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