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, smb_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 = smb_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(smb_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 int i; 203 204 if (sib == NULL) 205 return; 206 207 if (sib->sib_idmaph) { 208 idmap_get_destroy(sib->sib_idmaph); 209 sib->sib_idmaph = NULL; 210 } 211 212 if (sib->sib_maps == NULL) 213 return; 214 215 if (sib->sib_flags & SMB_IDMAP_ID2SID) { 216 /* 217 * SIDs are allocated only when mapping 218 * UID/GID to SIDs 219 */ 220 for (i = 0; i < sib->sib_nmap; i++) 221 smb_sid_free(sib->sib_maps[i].sim_sid); 222 } 223 224 if (sib->sib_size && sib->sib_maps) { 225 free(sib->sib_maps); 226 sib->sib_maps = NULL; 227 } 228 } 229 230 /* 231 * smb_idmap_batch_getid 232 * 233 * Queue a request to map the given SID to a UID or GID. 234 * 235 * sim->sim_id should point to variable that's supposed to 236 * hold the returned UID/GID. This needs to be setup by caller 237 * of this function. 238 * If requested ID type is known, it's passed as 'idtype', 239 * if it's unknown it'll be returned in sim->sim_idtype. 240 */ 241 idmap_stat 242 smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 243 smb_sid_t *sid, int idtype) 244 { 245 char sidstr[SMB_SID_STRSZ]; 246 smb_sid_t *tmpsid; 247 idmap_stat stat; 248 int flag = 0; 249 250 if (!idmaph || !sim || !sid) 251 return (IDMAP_ERR_ARG); 252 253 tmpsid = smb_sid_dup(sid); 254 if (!tmpsid) 255 return (IDMAP_ERR_MEMORY); 256 257 if (smb_sid_split(tmpsid, &sim->sim_rid) != 0) { 258 smb_sid_free(tmpsid); 259 return (IDMAP_ERR_ARG); 260 } 261 262 smb_sid_tostr(tmpsid, sidstr); 263 sim->sim_domsid = sidstr; 264 smb_sid_free(tmpsid); 265 266 switch (idtype) { 267 case SMB_IDMAP_USER: 268 stat = idmap_get_uidbysid(idmaph, sim->sim_domsid, 269 sim->sim_rid, flag, sim->sim_id, &sim->sim_stat); 270 break; 271 272 case SMB_IDMAP_GROUP: 273 stat = idmap_get_gidbysid(idmaph, sim->sim_domsid, 274 sim->sim_rid, flag, sim->sim_id, &sim->sim_stat); 275 break; 276 277 case SMB_IDMAP_UNKNOWN: 278 stat = idmap_get_pidbysid(idmaph, sim->sim_domsid, 279 sim->sim_rid, flag, sim->sim_id, &sim->sim_idtype, 280 &sim->sim_stat); 281 break; 282 283 default: 284 return (IDMAP_ERR_ARG); 285 } 286 287 return (stat); 288 } 289 290 /* 291 * smb_idmap_batch_getsid 292 * 293 * Queue a request to map the given UID/GID to a SID. 294 * 295 * sim->sim_domsid and sim->sim_rid will contain the mapping 296 * result upon successful process of the batched request. 297 */ 298 idmap_stat 299 smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 300 uid_t id, int idtype) 301 { 302 idmap_stat stat; 303 int flag = 0; 304 305 if (!idmaph || !sim) 306 return (IDMAP_ERR_ARG); 307 308 switch (idtype) { 309 case SMB_IDMAP_USER: 310 stat = idmap_get_sidbyuid(idmaph, id, flag, 311 &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat); 312 break; 313 314 case SMB_IDMAP_GROUP: 315 stat = idmap_get_sidbygid(idmaph, id, flag, 316 &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat); 317 break; 318 319 case SMB_IDMAP_EVERYONE: 320 /* Everyone S-1-1-0 */ 321 sim->sim_domsid = "S-1-1"; 322 sim->sim_rid = 0; 323 sim->sim_stat = IDMAP_SUCCESS; 324 stat = IDMAP_SUCCESS; 325 break; 326 327 default: 328 return (IDMAP_ERR_ARG); 329 } 330 331 return (stat); 332 } 333 334 /* 335 * smb_idmap_batch_getmappings 336 * 337 * trigger ID mapping service to get the mappings for queued 338 * requests. 339 * 340 * Checks the result of all the queued requests. 341 */ 342 idmap_stat 343 smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) 344 { 345 idmap_stat stat = IDMAP_SUCCESS; 346 int i; 347 348 stat = idmap_get_mappings(sib->sib_idmaph); 349 if (stat != IDMAP_SUCCESS) { 350 return (stat); 351 } 352 353 /* 354 * Check the status for all the queued requests 355 */ 356 for (i = 0; i < sib->sib_nmap; i++) { 357 if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS) { 358 return (sib->sib_maps[i].sim_stat); 359 } 360 } 361 362 if (smb_idmap_batch_binsid(sib) != 0) { 363 stat = IDMAP_ERR_OTHER; 364 } 365 366 return (stat); 367 } 368 369 /* 370 * smb_idmap_batch_binsid 371 * 372 * Convert sidrids to binary sids 373 * 374 * Returns 0 if successful and non-zero upon failure. 375 */ 376 static int 377 smb_idmap_batch_binsid(smb_idmap_batch_t *sib) 378 { 379 smb_sid_t *sid; 380 smb_idmap_t *sim; 381 int i; 382 383 if (sib->sib_flags & SMB_IDMAP_SID2ID) 384 /* This operation is not required */ 385 return (0); 386 387 sim = sib->sib_maps; 388 for (i = 0; i < sib->sib_nmap; sim++, i++) { 389 if (sim->sim_domsid == NULL) 390 return (-1); 391 392 sid = smb_sid_fromstr(sim->sim_domsid); 393 free(sim->sim_domsid); 394 if (sid == NULL) 395 return (-1); 396 397 sim->sim_sid = smb_sid_splice(sid, sim->sim_rid); 398 free(sid); 399 } 400 401 return (0); 402 } 403