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 2007 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_batch_create 130 * 131 * Creates and initializes the context for batch ID mapping. 132 */ 133 idmap_stat 134 smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags) 135 { 136 idmap_stat stat; 137 138 if (!sib) 139 return (IDMAP_ERR_ARG); 140 141 bzero(sib, sizeof (smb_idmap_batch_t)); 142 stat = idmap_get_create(idmap_clnt_hdl, &sib->sib_idmaph); 143 if (stat != IDMAP_SUCCESS) 144 return (stat); 145 146 sib->sib_flags = flags; 147 sib->sib_nmap = nmap; 148 sib->sib_size = nmap * sizeof (smb_idmap_t); 149 sib->sib_maps = malloc(sib->sib_size); 150 if (!sib->sib_maps) 151 return (IDMAP_ERR_MEMORY); 152 153 bzero(sib->sib_maps, sib->sib_size); 154 return (IDMAP_SUCCESS); 155 } 156 157 /* 158 * smb_idmap_batch_destroy 159 * 160 * Frees the batch ID mapping context. 161 */ 162 void 163 smb_idmap_batch_destroy(smb_idmap_batch_t *sib) 164 { 165 nt_sid_t *sid; 166 char *domsid; 167 int i; 168 169 if (!sib) 170 return; 171 172 if (sib->sib_idmaph) { 173 idmap_get_destroy(sib->sib_idmaph); 174 sib->sib_idmaph = NULL; 175 } 176 177 if (!sib->sib_maps) 178 return; 179 180 switch (sib->sib_flags) { 181 case SMB_IDMAP_SID2ID: 182 /* 183 * SIDs are allocated only when mapping 184 * UID/GID to SIDs 185 */ 186 for (i = 0; i < sib->sib_nmap; i++) { 187 sid = sib->sib_maps[i].sim_sid; 188 if (sid) 189 free(sid); 190 } 191 break; 192 case SMB_IDMAP_ID2SID: 193 /* 194 * SID prefixes are allocated only when mapping 195 * SIDs to UID/GID 196 */ 197 for (i = 0; i < sib->sib_nmap; i++) { 198 domsid = sib->sib_maps[i].sim_domsid; 199 if (domsid) 200 free(domsid); 201 } 202 break; 203 default: 204 break; 205 } 206 207 if (sib->sib_size && sib->sib_maps) { 208 free(sib->sib_maps); 209 sib->sib_maps = NULL; 210 } 211 } 212 213 /* 214 * smb_idmap_batch_getid 215 * 216 * Queue a request to map the given SID to a UID or GID. 217 * 218 * sim->sim_id should point to variable that's supposed to 219 * hold the returned UID/GID. This needs to be setup by caller 220 * of this function. 221 * If requested ID type is known, it's passed as 'idtype', 222 * if it's unknown it'll be returned in sim->sim_idtype. 223 */ 224 idmap_stat 225 smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 226 nt_sid_t *sid, int idtype) 227 { 228 nt_sid_t *tmpsid; 229 idmap_stat stat; 230 int flag = 0; 231 232 if (!idmaph || !sim || !sid) 233 return (IDMAP_ERR_ARG); 234 235 tmpsid = nt_sid_dup(sid); 236 if (!tmpsid) 237 return (IDMAP_ERR_MEMORY); 238 239 if (nt_sid_split(tmpsid, &sim->sim_rid) != 0) { 240 free(tmpsid); 241 return (IDMAP_ERR_ARG); 242 } 243 244 sim->sim_domsid = nt_sid_format(tmpsid); 245 free(tmpsid); 246 247 switch (idtype) { 248 case SMB_IDMAP_USER: 249 stat = idmap_get_uidbysid(idmaph, sim->sim_domsid, 250 sim->sim_rid, flag, sim->sim_id, &sim->sim_stat); 251 break; 252 253 case SMB_IDMAP_GROUP: 254 stat = idmap_get_gidbysid(idmaph, sim->sim_domsid, 255 sim->sim_rid, flag, sim->sim_id, &sim->sim_stat); 256 break; 257 258 case SMB_IDMAP_UNKNOWN: 259 stat = idmap_get_pidbysid(idmaph, sim->sim_domsid, 260 sim->sim_rid, flag, sim->sim_id, &sim->sim_idtype, 261 &sim->sim_stat); 262 break; 263 264 default: 265 return (IDMAP_ERR_ARG); 266 } 267 268 return (stat); 269 } 270 271 /* 272 * smb_idmap_batch_getsid 273 * 274 * Queue a request to map the given UID/GID to a SID. 275 * 276 * sim->sim_domsid and sim->sim_rid will contain the mapping 277 * result upon successful process of the batched request. 278 */ 279 idmap_stat 280 smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 281 uid_t id, int idtype) 282 { 283 idmap_stat stat; 284 int flag = 0; 285 286 if (!idmaph || !sim) 287 return (IDMAP_ERR_ARG); 288 289 switch (idtype) { 290 case SMB_IDMAP_USER: 291 stat = idmap_get_sidbyuid(idmaph, id, flag, 292 &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat); 293 break; 294 295 case SMB_IDMAP_GROUP: 296 stat = idmap_get_sidbygid(idmaph, id, flag, 297 &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat); 298 break; 299 300 case SMB_IDMAP_EVERYONE: 301 /* Everyone S-1-1-0 */ 302 sim->sim_domsid = "S-1-1"; 303 sim->sim_rid = 0; 304 sim->sim_stat = IDMAP_SUCCESS; 305 stat = IDMAP_SUCCESS; 306 break; 307 308 default: 309 return (IDMAP_ERR_ARG); 310 } 311 312 return (stat); 313 } 314 315 /* 316 * smb_idmap_batch_getmappings 317 * 318 * trigger ID mapping service to get the mappings for queued 319 * requests. 320 * 321 * Checks the result of all the queued requests. 322 */ 323 idmap_stat 324 smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) 325 { 326 idmap_stat stat = IDMAP_SUCCESS; 327 int i; 328 329 stat = idmap_get_mappings(sib->sib_idmaph); 330 if (stat != IDMAP_SUCCESS) { 331 return (stat); 332 } 333 334 /* 335 * Check the status for all the queued requests 336 */ 337 for (i = 0; i < sib->sib_nmap; i++) { 338 if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS) { 339 return (sib->sib_maps[i].sim_stat); 340 } 341 } 342 343 if (smb_idmap_batch_binsid(sib) != 0) { 344 stat = IDMAP_ERR_OTHER; 345 } 346 347 return (stat); 348 } 349 350 /* 351 * smb_idmap_batch_binsid 352 * 353 * Convert sidrids to binary sids 354 * 355 * Returns 0 if successful and non-zero upon failure. 356 */ 357 static int 358 smb_idmap_batch_binsid(smb_idmap_batch_t *sib) 359 { 360 nt_sid_t *sid; 361 smb_idmap_t *sim; 362 int i; 363 364 if (sib->sib_flags & SMB_IDMAP_SID2ID) 365 /* This operation is not required */ 366 return (0); 367 368 sim = sib->sib_maps; 369 for (i = 0; i < sib->sib_nmap; sim++, i++) { 370 if (sim->sim_domsid == NULL) 371 return (-1); 372 373 sid = nt_sid_strtosid(sim->sim_domsid); 374 if (sid == NULL) 375 return (-1); 376 377 sim->sim_sid = nt_sid_splice(sid, sim->sim_rid); 378 free(sid); 379 } 380 381 return (0); 382 } 383