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 /* 29 * This module provides the interface to builtin domain information. 30 * These are the predefined groups and aliases in the NT AUTHORITY or 31 * BUILTIN domains, and some other miscellaneous bits. 32 */ 33 34 #include <string.h> 35 #include <synch.h> 36 #include <smbsrv/ntsid.h> 37 #include <smbsrv/string.h> 38 #include <smbsrv/alloc.h> 39 40 /* 41 * This table should contain all of the NT builtin domain names. 42 */ 43 static char *domain[] = { 44 "LOCAL", 45 "BUILTIN", 46 "NT AUTHORITY", 47 "UNKNOWN" 48 }; 49 50 static int wk_init = 0; 51 static rwlock_t wk_rwlock; 52 53 /* 54 * This table should contain all of the builtin domains, groups and 55 * aliases. The order is important because we do string compares on 56 * the SIDs. For each domain, ensure that the domain SID appears 57 * before any aliases in that domain. 58 */ 59 static well_known_account_t wkt[] = { 60 { SidTypeWellKnownGroup, 0, "S-1-0-0", "Null", 61 LGF_HIDDEN, 0, NULL}, 62 { SidTypeWellKnownGroup, 1, "S-1-1-0", "Everyone", 63 LGF_HIDDEN, 0, NULL}, 64 { SidTypeWellKnownGroup, 1, "S-1-2-0", "LOCAL", 65 LGF_HIDDEN, 0, NULL}, 66 { SidTypeWellKnownGroup, 1, "S-1-3-0", "CREATOR OWNER", 67 LGF_HIDDEN, 0, NULL}, 68 { SidTypeWellKnownGroup, 1, "S-1-3-1", "CREATOR GROUP", 69 LGF_HIDDEN, 0, NULL}, 70 { SidTypeWellKnownGroup, 1, "S-1-3-2", "CREATOR OWNER SERVER", 71 LGF_HIDDEN, 0, NULL}, 72 { SidTypeWellKnownGroup, 1, "S-1-3-3", "CREATOR GROUP SERVER", 73 LGF_HIDDEN, 0, NULL}, 74 { SidTypeDomain, 1, "S-1-4", "NON UNIQUE", 75 LGF_HIDDEN, 0, NULL}, 76 { SidTypeDomain, 2, "S-1-5", "NT AUTHORITY", 77 LGF_HIDDEN, 0, NULL}, 78 { SidTypeWellKnownGroup, 2, "S-1-5-1", "DIALUP", 79 LGF_HIDDEN, 0, NULL}, 80 { SidTypeWellKnownGroup, 2, "S-1-5-2", "NETWORK", 81 LGF_HIDDEN, 0, NULL}, 82 { SidTypeWellKnownGroup, 2, "S-1-5-3", "BATCH", 83 LGF_HIDDEN, 0, NULL}, 84 { SidTypeWellKnownGroup, 2, "S-1-5-4", "INTERACTIVE", 85 LGF_HIDDEN, 0, NULL}, 86 { SidTypeWellKnownGroup, 2, "S-1-5-6", "SERVICE", 87 LGF_HIDDEN, 0, NULL}, 88 { SidTypeWellKnownGroup, 2, "S-1-5-7", "ANONYMOUS", 89 LGF_HIDDEN, 0, NULL}, 90 { SidTypeWellKnownGroup, 2, "S-1-5-8", "PROXY", 91 LGF_HIDDEN, 0, NULL}, 92 { SidTypeWellKnownGroup, 2, "S-1-5-9", "SERVER", 93 LGF_HIDDEN, 0, NULL}, 94 { SidTypeWellKnownGroup, 2, "S-1-5-10", "SELF", 95 LGF_HIDDEN, 0, NULL}, 96 { SidTypeWellKnownGroup, 2, "S-1-5-11", "Authenticated Users", 97 LGF_HIDDEN, 0, NULL}, 98 { SidTypeWellKnownGroup, 2, "S-1-5-12", "RESTRICTED", 99 LGF_HIDDEN, 0, NULL}, 100 { SidTypeWellKnownGroup, 2, "S-1-5-18", "SYSTEM", 101 LGF_HIDDEN, 0, NULL}, 102 { SidTypeWellKnownGroup, 2, "S-1-5-21", "NON_UNIQUE", 103 LGF_HIDDEN, 0, NULL}, 104 { SidTypeDomain, 2, "S-1-5-32", "BUILTIN", 105 LGF_HIDDEN, 0, NULL}, 106 { SidTypeAlias, 1, "S-1-5-32-544", "Administrators", 107 0, "Members can fully administer the computer/domain", NULL }, 108 { SidTypeAlias, 1, "S-1-5-32-545", "Users", 109 LGF_HIDDEN, 0, NULL}, 110 { SidTypeAlias, 1, "S-1-5-32-546", "Guests", 111 LGF_HIDDEN, 0, NULL}, 112 { SidTypeAlias, 1, "S-1-5-32-547", "Power Users", 113 0, "Members can share directories", NULL }, 114 { SidTypeAlias, 1, "S-1-5-32-548", "Account Operators", 115 LGF_HIDDEN, 0, NULL}, 116 { SidTypeAlias, 1, "S-1-5-32-549", "Server Operators", 117 LGF_HIDDEN, 0, NULL}, 118 { SidTypeAlias, 1, "S-1-5-32-550", "Print Operators", 119 LGF_HIDDEN, 0, NULL}, 120 { SidTypeAlias, 1, "S-1-5-32-551", "Backup Operators", 121 0, "Members can bypass file security to back up files", NULL }, 122 { SidTypeAlias, 1, "S-1-5-32-552", "Replicator", 123 LGF_HIDDEN, 0, NULL} 124 }; 125 126 127 /* 128 * nt_builtin_lookup_sid 129 * 130 * Search the wkt looking for a match on the specified SID. If the 131 * SID matches a builtin entry, the associated name is returned. 132 * Otherwise a null pointer is returned. 133 */ 134 char * 135 nt_builtin_lookup_sid(nt_sid_t *sid, WORD *sid_name_use) 136 { 137 well_known_account_t *entry; 138 char *sidbuf; 139 int sidlen; 140 int i; 141 142 if ((sidbuf = nt_sid_format(sid)) == 0) { 143 return (0); 144 } 145 146 sidlen = strlen(sidbuf); 147 148 for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) { 149 entry = &wkt[i]; 150 151 if (strncmp(sidbuf, entry->sid, sidlen) == 0) { 152 if (sid_name_use) 153 *sid_name_use = entry->sid_name_use; 154 free(sidbuf); 155 return (entry->name); 156 } 157 } 158 159 free(sidbuf); 160 return (0); 161 } 162 163 164 /* 165 * nt_builtin_lookup_name 166 * 167 * Search the wkt looking for a match on the specified name. If the 168 * name matches a builtin entry, the associated SID (which is in 169 * malloc'd memory) is returned. Otherwise a null pointer is returned. 170 */ 171 nt_sid_t * 172 nt_builtin_lookup_name(char *name, WORD *sid_name_use) 173 { 174 well_known_account_t *entry; 175 int i; 176 177 for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) { 178 entry = &wkt[i]; 179 180 if (!utf8_strcasecmp(name, entry->name)) { 181 if (sid_name_use) 182 *sid_name_use = entry->sid_name_use; 183 return (nt_sid_strtosid(entry->sid)); 184 } 185 } 186 187 return (0); 188 } 189 190 /* 191 * nt_builtin_lookup 192 * 193 * Search the wkt looking for a match on the specified name. If the 194 * name matches a builtin entry then pointer to that entry will be 195 * returned. Otherwise 0 is returned. 196 */ 197 well_known_account_t * 198 nt_builtin_lookup(char *name) 199 { 200 well_known_account_t *entry; 201 int i; 202 203 (void) rw_rdlock(&wk_rwlock); 204 for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) { 205 entry = &wkt[i]; 206 207 if (!utf8_strcasecmp(name, entry->name)) { 208 (void) rw_unlock(&wk_rwlock); 209 return (entry); 210 } 211 } 212 213 (void) rw_unlock(&wk_rwlock); 214 return (0); 215 } 216 217 218 /* 219 * nt_builtin_is_wellknown 220 * 221 * Search the wkt looking for a match on the specified name. If the 222 * name matches a builtin entry returns 1. Otherwise returns 0. 223 */ 224 int 225 nt_builtin_is_wellknown(char *name) 226 { 227 well_known_account_t *entry; 228 int i; 229 230 for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) { 231 entry = &wkt[i]; 232 233 if (!utf8_strcasecmp(name, entry->name)) { 234 return (1); 235 } 236 } 237 238 return (0); 239 } 240 241 /* 242 * nt_builtin_lookup_domain 243 * 244 * Return the builtin domain name for the specified alias or group name. 245 */ 246 char * 247 nt_builtin_lookup_domain(char *name) 248 { 249 well_known_account_t *entry; 250 char *domain_name; 251 int i; 252 253 for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) { 254 entry = &wkt[i]; 255 256 if (!utf8_strcasecmp(name, entry->name)) { 257 domain_name = domain[entry->domain_ix]; 258 return (domain_name); 259 } 260 } 261 262 return (0); 263 } 264 265 /* 266 * nt_builtin_findfirst 267 * 268 * Returns pointer to the first entry of well known sids table. 269 */ 270 well_known_account_t * 271 nt_builtin_findfirst(DWORD *iterator) 272 { 273 *iterator = 1; 274 return (&wkt[0]); 275 } 276 277 /* 278 * nt_builtin_findnext 279 * 280 * Returns pointer to the entry of well known sids table specified 281 * by the iterator. Increments iterator to point to the next entry. 282 */ 283 well_known_account_t * 284 nt_builtin_findnext(DWORD *iterator) 285 { 286 if (*iterator < sizeof (wkt)/sizeof (wkt[0])) 287 return (&wkt[(*iterator)++]); 288 289 return (0); 290 } 291 292 /* 293 * nt_builtin_init 294 * 295 * Generate binary SIDs from the string SIDs in the table 296 * and set the proper field. 297 * 298 * Caller MUST not store the binary SID pointer anywhere that 299 * could lead to freeing it. 300 * 301 * This function should only be called once. 302 */ 303 int 304 nt_builtin_init() 305 { 306 well_known_account_t *entry; 307 int i; 308 309 (void) rw_wrlock(&wk_rwlock); 310 if (wk_init) { 311 (void) rw_unlock(&wk_rwlock); 312 return (1); 313 } 314 315 for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) { 316 entry = &wkt[i]; 317 entry->binsid = nt_sid_strtosid(entry->sid); 318 if (entry->binsid == NULL) { 319 (void) rw_unlock(&wk_rwlock); 320 nt_builtin_fini(); 321 return (0); 322 } 323 } 324 325 wk_init = 1; 326 (void) rw_unlock(&wk_rwlock); 327 return (1); 328 } 329 330 void 331 nt_builtin_fini() 332 { 333 int i; 334 335 (void) rw_wrlock(&wk_rwlock); 336 if (wk_init == 0) { 337 (void) rw_unlock(&wk_rwlock); 338 return; 339 } 340 341 for (i = 0; i < sizeof (wkt)/sizeof (wkt[0]); ++i) { 342 if (wkt[i].binsid) { 343 free(wkt[i].binsid); 344 wkt[i].binsid = NULL; 345 } 346 } 347 348 wk_init = 0; 349 (void) rw_unlock(&wk_rwlock); 350 } 351