1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <strings.h> 29 #include <smbsrv/libsmb.h> 30 31 static idmap_handle_t *idmap_clnt_hdl = NULL; 32 static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib); 33 34 /* 35 * smb_idmap_start 36 * 37 * This function initializes the idmap client handle. It should be called 38 * at startup. 39 */ 40 int 41 smb_idmap_start(void) 42 { 43 idmap_stat stat; 44 45 if (idmap_clnt_hdl) 46 return (0); 47 48 stat = idmap_init(&idmap_clnt_hdl); 49 if (stat < 0) { 50 syslog(LOG_ERR, "smb_idmap_start: idmap_init failed (%s)", 51 idmap_stat2string(NULL, stat)); 52 return (-1); 53 } 54 55 return (0); 56 } 57 58 /* 59 * smb_idmap_stop 60 * 61 * This function destroys the idmap client handle. It should be called 62 * prior to exiting the SMB daemon. 63 */ 64 void 65 smb_idmap_stop(void) 66 { 67 if (idmap_clnt_hdl) { 68 (void) idmap_fini(idmap_clnt_hdl); 69 idmap_clnt_hdl = NULL; 70 } 71 } 72 73 /* 74 * smb_idmap_restart 75 * 76 * This function should be called when the idmap client handle 77 * becomes invalid. 78 */ 79 int 80 smb_idmap_restart(void) 81 { 82 smb_idmap_stop(); 83 if (smb_idmap_start() != 0) { 84 syslog(LOG_ERR, "smb_idmap_restart: smb_idmap_start failed"); 85 return (-1); 86 } 87 88 return (0); 89 } 90 91 /* 92 * smb_idmap_getsid 93 * 94 * Tries to get a mapping for the given uid/gid 95 */ 96 idmap_stat 97 smb_idmap_getsid(uid_t id, int idtype, nt_sid_t **sid) 98 { 99 smb_idmap_batch_t sib; 100 idmap_stat stat; 101 102 stat = smb_idmap_batch_create(&sib, 1, SMB_IDMAP_ID2SID); 103 if (stat != IDMAP_SUCCESS) 104 return (stat); 105 106 stat = smb_idmap_batch_getsid(sib.sib_idmaph, &sib.sib_maps[0], 107 id, idtype); 108 109 if (stat != IDMAP_SUCCESS) { 110 smb_idmap_batch_destroy(&sib); 111 return (stat); 112 } 113 114 stat = smb_idmap_batch_getmappings(&sib); 115 116 if (stat != IDMAP_SUCCESS) { 117 smb_idmap_batch_destroy(&sib); 118 return (stat); 119 } 120 121 *sid = nt_sid_dup(sib.sib_maps[0].sim_sid); 122 123 smb_idmap_batch_destroy(&sib); 124 125 return (IDMAP_SUCCESS); 126 } 127 128 /* 129 * smb_idmap_getid 130 * 131 * Tries to get a mapping for the given SID 132 */ 133 idmap_stat 134 smb_idmap_getid(nt_sid_t *sid, uid_t *id, int *id_type) 135 { 136 smb_idmap_batch_t sib; 137 smb_idmap_t *sim; 138 idmap_stat stat; 139 140 stat = smb_idmap_batch_create(&sib, 1, SMB_IDMAP_SID2ID); 141 if (stat != IDMAP_SUCCESS) 142 return (stat); 143 144 sim = &sib.sib_maps[0]; 145 sim->sim_id = id; 146 stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, sid, *id_type); 147 if (stat != IDMAP_SUCCESS) { 148 smb_idmap_batch_destroy(&sib); 149 return (stat); 150 } 151 152 stat = smb_idmap_batch_getmappings(&sib); 153 154 if (stat != IDMAP_SUCCESS) { 155 smb_idmap_batch_destroy(&sib); 156 return (stat); 157 } 158 159 *id_type = sim->sim_idtype; 160 smb_idmap_batch_destroy(&sib); 161 162 return (IDMAP_SUCCESS); 163 } 164 165 /* 166 * smb_idmap_batch_create 167 * 168 * Creates and initializes the context for batch ID mapping. 169 */ 170 idmap_stat 171 smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags) 172 { 173 idmap_stat stat; 174 175 if (!sib) 176 return (IDMAP_ERR_ARG); 177 178 bzero(sib, sizeof (smb_idmap_batch_t)); 179 stat = idmap_get_create(idmap_clnt_hdl, &sib->sib_idmaph); 180 if (stat != IDMAP_SUCCESS) 181 return (stat); 182 183 sib->sib_flags = flags; 184 sib->sib_nmap = nmap; 185 sib->sib_size = nmap * sizeof (smb_idmap_t); 186 sib->sib_maps = malloc(sib->sib_size); 187 if (!sib->sib_maps) 188 return (IDMAP_ERR_MEMORY); 189 190 bzero(sib->sib_maps, sib->sib_size); 191 return (IDMAP_SUCCESS); 192 } 193 194 /* 195 * smb_idmap_batch_destroy 196 * 197 * Frees the batch ID mapping context. 198 */ 199 void 200 smb_idmap_batch_destroy(smb_idmap_batch_t *sib) 201 { 202 nt_sid_t *sid; 203 int i; 204 205 if (!sib) 206 return; 207 208 if (sib->sib_idmaph) { 209 idmap_get_destroy(sib->sib_idmaph); 210 sib->sib_idmaph = NULL; 211 } 212 213 if (!sib->sib_maps) 214 return; 215 216 if (sib->sib_flags & SMB_IDMAP_ID2SID) { 217 /* 218 * SIDs are allocated only when mapping 219 * UID/GID to SIDs 220 */ 221 for (i = 0; i < sib->sib_nmap; i++) { 222 sid = sib->sib_maps[i].sim_sid; 223 if (sid) 224 free(sid); 225 } 226 } 227 228 if (sib->sib_size && sib->sib_maps) { 229 free(sib->sib_maps); 230 sib->sib_maps = NULL; 231 } 232 } 233 234 /* 235 * smb_idmap_batch_getid 236 * 237 * Queue a request to map the given SID to a UID or GID. 238 * 239 * sim->sim_id should point to variable that's supposed to 240 * hold the returned UID/GID. This needs to be setup by caller 241 * of this function. 242 * If requested ID type is known, it's passed as 'idtype', 243 * if it's unknown it'll be returned in sim->sim_idtype. 244 */ 245 idmap_stat 246 smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 247 nt_sid_t *sid, int idtype) 248 { 249 nt_sid_t *tmpsid; 250 idmap_stat stat; 251 int flag = 0; 252 253 if (!idmaph || !sim || !sid) 254 return (IDMAP_ERR_ARG); 255 256 tmpsid = nt_sid_dup(sid); 257 if (!tmpsid) 258 return (IDMAP_ERR_MEMORY); 259 260 if (nt_sid_split(tmpsid, &sim->sim_rid) != 0) { 261 free(tmpsid); 262 return (IDMAP_ERR_ARG); 263 } 264 265 sim->sim_domsid = nt_sid_format(tmpsid); 266 free(tmpsid); 267 268 switch (idtype) { 269 case SMB_IDMAP_USER: 270 stat = idmap_get_uidbysid(idmaph, sim->sim_domsid, 271 sim->sim_rid, flag, sim->sim_id, &sim->sim_stat); 272 break; 273 274 case SMB_IDMAP_GROUP: 275 stat = idmap_get_gidbysid(idmaph, sim->sim_domsid, 276 sim->sim_rid, flag, sim->sim_id, &sim->sim_stat); 277 break; 278 279 case SMB_IDMAP_UNKNOWN: 280 stat = idmap_get_pidbysid(idmaph, sim->sim_domsid, 281 sim->sim_rid, flag, sim->sim_id, &sim->sim_idtype, 282 &sim->sim_stat); 283 break; 284 285 default: 286 free(sim->sim_domsid); 287 return (IDMAP_ERR_ARG); 288 } 289 290 free(sim->sim_domsid); 291 return (stat); 292 } 293 294 /* 295 * smb_idmap_batch_getsid 296 * 297 * Queue a request to map the given UID/GID to a SID. 298 * 299 * sim->sim_domsid and sim->sim_rid will contain the mapping 300 * result upon successful process of the batched request. 301 */ 302 idmap_stat 303 smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 304 uid_t id, int idtype) 305 { 306 idmap_stat stat; 307 int flag = 0; 308 309 if (!idmaph || !sim) 310 return (IDMAP_ERR_ARG); 311 312 switch (idtype) { 313 case SMB_IDMAP_USER: 314 stat = idmap_get_sidbyuid(idmaph, id, flag, 315 &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat); 316 break; 317 318 case SMB_IDMAP_GROUP: 319 stat = idmap_get_sidbygid(idmaph, id, flag, 320 &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat); 321 break; 322 323 case SMB_IDMAP_EVERYONE: 324 /* Everyone S-1-1-0 */ 325 sim->sim_domsid = "S-1-1"; 326 sim->sim_rid = 0; 327 sim->sim_stat = IDMAP_SUCCESS; 328 stat = IDMAP_SUCCESS; 329 break; 330 331 default: 332 return (IDMAP_ERR_ARG); 333 } 334 335 return (stat); 336 } 337 338 /* 339 * smb_idmap_batch_getmappings 340 * 341 * trigger ID mapping service to get the mappings for queued 342 * requests. 343 * 344 * Checks the result of all the queued requests. 345 */ 346 idmap_stat 347 smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) 348 { 349 idmap_stat stat = IDMAP_SUCCESS; 350 int i; 351 352 stat = idmap_get_mappings(sib->sib_idmaph); 353 if (stat != IDMAP_SUCCESS) { 354 return (stat); 355 } 356 357 /* 358 * Check the status for all the queued requests 359 */ 360 for (i = 0; i < sib->sib_nmap; i++) { 361 if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS) { 362 return (sib->sib_maps[i].sim_stat); 363 } 364 } 365 366 if (smb_idmap_batch_binsid(sib) != 0) { 367 stat = IDMAP_ERR_OTHER; 368 } 369 370 return (stat); 371 } 372 373 /* 374 * smb_idmap_batch_binsid 375 * 376 * Convert sidrids to binary sids 377 * 378 * Returns 0 if successful and non-zero upon failure. 379 */ 380 static int 381 smb_idmap_batch_binsid(smb_idmap_batch_t *sib) 382 { 383 nt_sid_t *sid; 384 smb_idmap_t *sim; 385 int i; 386 387 if (sib->sib_flags & SMB_IDMAP_SID2ID) 388 /* This operation is not required */ 389 return (0); 390 391 sim = sib->sib_maps; 392 for (i = 0; i < sib->sib_nmap; sim++, i++) { 393 if (sim->sim_domsid == NULL) 394 return (-1); 395 396 sid = nt_sid_strtosid(sim->sim_domsid); 397 free(sim->sim_domsid); 398 if (sid == NULL) 399 return (-1); 400 401 sim->sim_sid = nt_sid_splice(sid, sim->sim_rid); 402 free(sid); 403 } 404 405 return (0); 406 } 407