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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Some helper routines for directory lookup. These offer functions that 29 * you could implement yourself on top of the generic routines, but since 30 * they're a common request we implement them here. (Well, OK, we cheat a bit 31 * and call an internal routine to do the dirty work to reduce code 32 * duplication, but you could still implement them using the generic routines.) 33 */ 34 35 #include <stdio.h> 36 #include <string.h> 37 #include <libadutils.h> 38 #include <rpcsvc/idmap_prot.h> 39 #include "directory.h" 40 #include "directory_private.h" 41 #include "directory_library_impl.h" 42 #include "miscutils.h" 43 #include "sidutil.h" 44 45 /* 46 * Given a username, return a text-form SID. 47 * 48 * The SID must be free()ed by the caller. 49 * 50 * d, if non-NULL, specifies an existing directory-search context. 51 * If NULL, a temporary one will be created. 52 */ 53 directory_error_t 54 directory_sid_from_name_common( 55 directory_t d, 56 char *name, 57 char *type, 58 char **sid, 59 uint64_t *classes) 60 { 61 directory_t d1 = NULL; 62 static char *attrs[] = { 63 "objectSid", 64 "objectClass", 65 NULL, 66 }; 67 directory_entry_t *ret_list = NULL; 68 directory_error_t de; 69 struct ret_sid { 70 sid_t **objectSid; 71 char **objectClass; 72 } *ret_sid; 73 74 /* Prep for error cases. */ 75 *sid = NULL; 76 if (classes != NULL) 77 *classes = 0; 78 79 if (d == NULL) { 80 de = directory_open(&d1); 81 if (de != NULL) 82 goto out; 83 } else { 84 d1 = d; 85 } 86 87 de = directory_get_v(d1, &ret_list, &name, 1, type, attrs); 88 if (de != NULL) 89 goto out; 90 if (ret_list[0].err != NULL) { 91 de = ret_list[0].err; 92 ret_list[0].err = NULL; 93 goto out; 94 } 95 96 ret_sid = (struct ret_sid *)ret_list[0].attrs; 97 if (ret_sid == NULL) 98 goto out; 99 100 if (ret_sid->objectSid != NULL && 101 ret_sid->objectSid[0] != NULL) { 102 char text_sid[SID_STRSZ+1]; 103 sid_from_le(ret_sid->objectSid[0]); 104 sid_tostr(ret_sid->objectSid[0], text_sid); 105 *sid = strdup(text_sid); 106 if (*sid == NULL) 107 goto nomem; 108 } 109 110 if (ret_sid->objectClass != NULL && 111 classes != NULL) 112 *classes = class_bitmap(ret_sid->objectClass); 113 114 goto out; 115 116 nomem: 117 de = directory_error("ENOMEM.directory_sid_from_name_common", 118 "Insufficient memory retrieving data about SID", NULL); 119 120 out: 121 directory_free(ret_list); 122 if (d == NULL) 123 directory_close(d1); 124 return (de); 125 } 126 127 directory_error_t 128 directory_sid_from_name( 129 directory_t d, 130 char *name, 131 char **sid, 132 uint64_t *classes) 133 { 134 return (directory_sid_from_name_common(d, name, DIRECTORY_ID_NAME, sid, 135 classes)); 136 } 137 138 directory_error_t 139 directory_sid_from_user_name(directory_t d, char *name, char **sid) 140 { 141 return (directory_sid_from_name_common(d, name, DIRECTORY_ID_USER, sid, 142 NULL)); 143 } 144 145 directory_error_t 146 directory_sid_from_group_name(directory_t d, char *name, char **sid) 147 { 148 return (directory_sid_from_name_common(d, name, DIRECTORY_ID_GROUP, sid, 149 NULL)); 150 } 151 152 /* 153 * Given a name or text-format SID, return a user@domain. 154 * 155 * The user@domain returned must be free()ed by the caller. 156 * 157 * Returns NULL and sets *name to NULL if no error occurred but the specified 158 * entity does not exist. 159 * 160 * d, if non-NULL, specifies an existing directory-search context. 161 * If NULL, a temporary one will be created. 162 */ 163 static 164 directory_error_t 165 directory_canon_common( 166 directory_t d, 167 char *id, 168 char *id_type, 169 char **canon, 170 uint64_t *classes) 171 { 172 directory_t d1 = NULL; 173 directory_entry_t *ret_list = NULL; 174 directory_error_t de; 175 /* 176 * Attributes required to generate a canonical name, in named-list and 177 * structure form. 178 */ 179 static char *attrs[] = { 180 "x-sun-canonicalName", 181 "objectClass", 182 NULL, 183 }; 184 185 struct canon_name_ret { 186 char **x_sun_canonicalName; 187 char **objectClass; 188 } *ret_name; 189 190 /* Prep for error cases. */ 191 *canon = NULL; 192 if (classes != NULL) 193 *classes = 0; 194 195 if (d == NULL) { 196 de = directory_open(&d1); 197 if (de != NULL) 198 goto out; 199 } else { 200 d1 = d; 201 } 202 203 de = directory_get_v(d1, &ret_list, &id, 1, id_type, attrs); 204 if (de != NULL) 205 goto out; 206 if (ret_list[0].err != NULL) { 207 de = ret_list[0].err; 208 ret_list[0].err = NULL; 209 goto out; 210 } 211 212 ret_name = (struct canon_name_ret *)ret_list[0].attrs; 213 if (ret_name == NULL) 214 goto out; 215 216 if (ret_name->x_sun_canonicalName != NULL && 217 ret_name->x_sun_canonicalName[0] != NULL) { 218 *canon = strdup(ret_name->x_sun_canonicalName[0]); 219 if (*canon == NULL) 220 goto nomem; 221 } 222 223 if (ret_name->objectClass != NULL && 224 classes != NULL) 225 *classes = class_bitmap(ret_name->objectClass); 226 227 goto out; 228 229 nomem: 230 de = directory_error("ENOMEM.directory_canon_common", 231 "Insufficient memory retrieving data about name", NULL); 232 233 out: 234 directory_free(ret_list); 235 if (d == NULL) 236 directory_close(d1); 237 return (de); 238 } 239 240 directory_error_t 241 directory_name_from_sid( 242 directory_t d, 243 char *sid, 244 char **canon, 245 uint64_t *classes) 246 { 247 return (directory_canon_common(d, sid, DIRECTORY_ID_SID, canon, 248 classes)); 249 } 250 251 directory_error_t 252 directory_canon_from_name( 253 directory_t d, 254 char *name, 255 char **canon, 256 uint64_t *classes) 257 { 258 return (directory_canon_common(d, name, DIRECTORY_ID_NAME, canon, 259 classes)); 260 } 261 262 directory_error_t 263 directory_canon_from_user_name(directory_t d, char *name, char **canon) 264 { 265 return ( 266 directory_canon_common(d, name, DIRECTORY_ID_USER, canon, NULL)); 267 } 268 269 directory_error_t 270 directory_canon_from_group_name(directory_t d, char *name, char **canon) 271 { 272 return ( 273 directory_canon_common(d, name, DIRECTORY_ID_GROUP, canon, NULL)); 274 } 275 276 boolean_t 277 is_in_list(char **list, char *val) 278 { 279 for (; *list != NULL; list++) { 280 if (strcaseeq(*list, val)) 281 return (B_TRUE); 282 } 283 return (B_FALSE); 284 } 285 286 uint64_t 287 class_bitmap(char **objectClass) 288 { 289 uint64_t ret = 0; 290 291 for (; *objectClass != NULL; objectClass++) { 292 if (strcaseeq(*objectClass, "user") || 293 strcaseeq(*objectClass, "posixAccount")) 294 ret |= DIRECTORY_CLASS_USER; 295 296 if (strcaseeq(*objectClass, "group") || 297 strcaseeq(*objectClass, "posixGroup")) 298 ret |= DIRECTORY_CLASS_GROUP; 299 } 300 301 return (ret); 302 } 303