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