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