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