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 2008 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 file defines the NT domain environment values and the domain 30 * database interface. The database is a single linked list of 31 * structures containing domain type, name and SID information. 32 */ 33 34 #include <strings.h> 35 #include <unistd.h> 36 #include <netdb.h> 37 #include <syslog.h> 38 #include <synch.h> 39 40 #include <smbsrv/smbinfo.h> 41 #include <smbsrv/string.h> 42 #include <smbsrv/ntsid.h> 43 #include <smbsrv/alloc.h> 44 45 #include <smbsrv/libsmb.h> 46 47 48 static void nt_domain_unlist(nt_domain_t *); 49 50 /* 51 * Valid domain type identifiers as text. This table must be kept 52 * in step with the nt_domain_type_t enum in ntdomain.h. 53 */ 54 static char *nt_domain_type_name[NT_DOMAIN_NUM_TYPES] = { 55 "null", 56 "builtin", 57 "local", 58 "primary", 59 "account", 60 "trusted", 61 "untrusted" 62 }; 63 64 65 static rwlock_t nt_domain_lock; 66 static nt_domain_t *nt_domain_list; 67 68 /* 69 * nt_domain_init 70 * 71 * NT domain database one time initialization. This function should 72 * be called during module installation. 73 * 74 * Returns 0 on successful domain initialization. Less than zero otherwise. 75 */ 76 int 77 nt_domain_init(char *resource_domain, uint32_t secmode) 78 { 79 nt_domain_t *domain; 80 nt_sid_t *sid = NULL; 81 char sidstr[128]; 82 char *lsidstr; 83 char hostname[MAXHOSTNAMELEN]; 84 int rc; 85 86 if (rwlock_init(&nt_domain_lock, USYNC_THREAD, NULL)) 87 return (SMB_DOMAIN_NODOMAIN_SID); 88 89 if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0) { 90 (void) rwlock_destroy(&nt_domain_lock); 91 return (SMB_DOMAIN_NOMACHINE_SID); 92 } 93 94 lsidstr = smb_config_get_localsid(); 95 96 if (lsidstr) { 97 sid = nt_sid_strtosid(lsidstr); 98 99 if (sid) { 100 domain = nt_domain_new(NT_DOMAIN_LOCAL, hostname, sid); 101 (void) nt_domain_add(domain); 102 free(sid); 103 } 104 free(lsidstr); 105 } else { 106 (void) rwlock_destroy(&nt_domain_lock); 107 return (SMB_DOMAIN_NOMACHINE_SID); 108 } 109 110 if (secmode == SMB_SECMODE_DOMAIN) { 111 sid = nt_sid_strtosid(NT_BUILTIN_DOMAIN_SIDSTR); 112 domain = nt_domain_new(NT_DOMAIN_BUILTIN, "BUILTIN", sid); 113 (void) nt_domain_add(domain); 114 free(sid); 115 116 sid = NULL; 117 rc = smb_config_getstr(SMB_CI_DOMAIN_SID, sidstr, 118 sizeof (sidstr)); 119 if (rc == SMBD_SMF_OK) 120 sid = nt_sid_strtosid(sidstr); 121 if (nt_sid_is_valid(sid)) { 122 domain = nt_domain_new(NT_DOMAIN_PRIMARY, 123 resource_domain, sid); 124 (void) nt_domain_add(domain); 125 free(sid); 126 } else { 127 free(sid); 128 (void) rwlock_destroy(&nt_domain_lock); 129 return (SMB_DOMAIN_NODOMAIN_SID); 130 } 131 132 } 133 return (0); 134 } 135 136 /* 137 * nt_domain_new 138 * 139 * Allocate and initialize a new domain structure. On success, a pointer to 140 * the new domain structure is returned. Otherwise a null pointer is returned. 141 */ 142 nt_domain_t * 143 nt_domain_new(nt_domain_type_t type, char *name, nt_sid_t *sid) 144 { 145 nt_domain_t *new_domain; 146 147 if ((name == NULL) || (sid == NULL)) 148 return (NULL); 149 150 if (type == NT_DOMAIN_NULL || type >= NT_DOMAIN_NUM_TYPES) 151 return (NULL); 152 153 if ((new_domain = malloc(sizeof (nt_domain_t))) == NULL) 154 return (NULL); 155 156 bzero(new_domain, sizeof (nt_domain_t)); 157 new_domain->type = type; 158 new_domain->name = strdup(name); 159 new_domain->sid = nt_sid_dup(sid); 160 161 return (new_domain); 162 } 163 164 /* 165 * nt_domain_delete 166 * 167 * Free the memory used by the specified domain structure. 168 */ 169 void 170 nt_domain_delete(nt_domain_t *domain) 171 { 172 if (domain) { 173 free(domain->name); 174 free(domain->sid); 175 free(domain); 176 } 177 } 178 179 180 /* 181 * nt_domain_add 182 * 183 * Add a domain structure to the global list. There is no checking 184 * for duplicates. If it's the primary domain, we save the SID in the 185 * environment. Returns a pointer to the new domain entry on success. 186 * Otherwise a null pointer is returned. 187 */ 188 nt_domain_t * 189 nt_domain_add(nt_domain_t *new_domain) 190 { 191 char *sidstr; 192 193 if (new_domain == NULL) 194 return (NULL); 195 196 (void) rw_wrlock(&nt_domain_lock); 197 198 new_domain->next = nt_domain_list; 199 nt_domain_list = new_domain; 200 201 if (new_domain->type == NT_DOMAIN_PRIMARY) { 202 sidstr = nt_sid_format(new_domain->sid); 203 (void) smb_config_setstr(SMB_CI_DOMAIN_SID, sidstr); 204 free(sidstr); 205 } 206 (void) rw_unlock(&nt_domain_lock); 207 208 return (new_domain); 209 } 210 211 212 /* 213 * nt_domain_remove 214 * 215 * Remove a domain from the global list. The memory 216 * used by the structure is not freed. 217 */ 218 void 219 nt_domain_remove(nt_domain_t *domain) 220 { 221 (void) rw_wrlock(&nt_domain_lock); 222 nt_domain_unlist(domain); 223 (void) rw_unlock(&nt_domain_lock); 224 } 225 226 227 /* 228 * nt_domain_flush 229 * 230 * Flush all domains of the specified type from the list. This is 231 * useful for things like updating the list of trusted domains. 232 */ 233 void 234 nt_domain_flush(nt_domain_type_t domain_type) 235 { 236 nt_domain_t *domain = nt_domain_list; 237 238 (void) rw_wrlock(&nt_domain_lock); 239 while (domain) { 240 if (domain->type == domain_type) { 241 nt_domain_unlist(domain); 242 nt_domain_delete(domain); 243 domain = nt_domain_list; 244 continue; 245 } 246 domain = domain->next; 247 } 248 (void) rw_unlock(&nt_domain_lock); 249 } 250 251 /* 252 * nt_domain_xlat_type 253 * 254 * Translate a domain type into a text string. 255 */ 256 char * 257 nt_domain_xlat_type(nt_domain_type_t domain_type) 258 { 259 if (domain_type < NT_DOMAIN_NUM_TYPES) 260 return (nt_domain_type_name[domain_type]); 261 else 262 return ("unknown"); 263 } 264 265 266 /* 267 * nt_domain_xlat_type_name 268 * 269 * Translate a domain type test string into a domain type. 270 */ 271 nt_domain_type_t 272 nt_domain_xlat_type_name(char *type_name) 273 { 274 int i; 275 276 for (i = 0; i < NT_DOMAIN_NUM_TYPES; ++i) 277 if (utf8_strcasecmp(nt_domain_type_name[i], type_name) == 0) 278 return (i); 279 280 return (NT_DOMAIN_NUM_TYPES); 281 } 282 283 284 /* 285 * nt_domain_lookup_name 286 * 287 * Lookup a domain by its domain name. If the domain is in the list, 288 * a pointer to it is returned. Otherwise a null pointer is returned. 289 */ 290 nt_domain_t * 291 nt_domain_lookup_name(char *domain_name) 292 { 293 nt_domain_t *domain = nt_domain_list; 294 295 (void) rw_rdlock(&nt_domain_lock); 296 while (domain) { 297 if (utf8_strcasecmp(domain->name, domain_name) == 0) 298 break; 299 300 domain = domain->next; 301 } 302 (void) rw_unlock(&nt_domain_lock); 303 304 return (domain); 305 } 306 307 308 /* 309 * nt_domain_lookup_sid 310 * 311 * Lookup a domain by its domain SID. If the domain is in the list, 312 * a pointer to it is returned. Otherwise a null pointer is returned. 313 */ 314 nt_domain_t * 315 nt_domain_lookup_sid(nt_sid_t *domain_sid) 316 { 317 nt_domain_t *domain = nt_domain_list; 318 319 (void) rw_rdlock(&nt_domain_lock); 320 while (domain) { 321 if (nt_sid_is_equal(domain->sid, domain_sid)) 322 break; 323 324 domain = domain->next; 325 } 326 (void) rw_unlock(&nt_domain_lock); 327 328 return (domain); 329 } 330 331 332 /* 333 * nt_domain_lookupbytype 334 * 335 * Lookup a domain by its type. The first matching entry in the list 336 * is returned. Otherwise a null pointer is returned. 337 */ 338 nt_domain_t * 339 nt_domain_lookupbytype(nt_domain_type_t type) 340 { 341 nt_domain_t *domain = nt_domain_list; 342 343 (void) rw_rdlock(&nt_domain_lock); 344 while (domain) { 345 if (domain->type == type) 346 break; 347 348 domain = domain->next; 349 } 350 (void) rw_unlock(&nt_domain_lock); 351 352 return (domain); 353 } 354 355 356 /* 357 * nt_domain_local_sid 358 * 359 * Return a pointer to the local domain SID. Each system has a SID that 360 * represents the local domain, which is named after the local hostname. 361 * The local domain SID must exist. 362 */ 363 nt_sid_t * 364 nt_domain_local_sid(void) 365 { 366 nt_domain_t *domain = nt_domain_list; 367 368 (void) rw_rdlock(&nt_domain_lock); 369 while (domain) { 370 if (domain->type == NT_DOMAIN_LOCAL) 371 break; 372 373 domain = domain->next; 374 } 375 (void) rw_unlock(&nt_domain_lock); 376 377 return (domain->sid); 378 } 379 380 381 static void 382 nt_domain_unlist(nt_domain_t *domain) 383 { 384 nt_domain_t **ppdomain = &nt_domain_list; 385 386 while (*ppdomain) { 387 if (*ppdomain == domain) { 388 *ppdomain = domain->next; 389 domain->next = NULL; 390 return; 391 } 392 ppdomain = &(*ppdomain)->next; 393 } 394 } 395