15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 228474SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw /* 275331Samw * This file defines the NT domain environment values and the domain 285331Samw * database interface. The database is a single linked list of 295331Samw * structures containing domain type, name and SID information. 305331Samw */ 315331Samw 328474SJose.Borrego@Sun.COM #include <sys/types.h> 338474SJose.Borrego@Sun.COM #include <sys/stat.h> 348474SJose.Borrego@Sun.COM #include <stdio.h> 355331Samw #include <strings.h> 368474SJose.Borrego@Sun.COM #include <string.h> 375331Samw #include <unistd.h> 388474SJose.Borrego@Sun.COM #include <stdlib.h> 395331Samw #include <netdb.h> 405331Samw #include <syslog.h> 415331Samw #include <synch.h> 428474SJose.Borrego@Sun.COM #include <pwd.h> 438474SJose.Borrego@Sun.COM #include <grp.h> 445331Samw 455331Samw #include <smbsrv/smbinfo.h> 465331Samw #include <smbsrv/string.h> 476432Sas200622 #include <smbsrv/smb_sid.h> 485331Samw #include <smbsrv/libsmb.h> 495331Samw 508474SJose.Borrego@Sun.COM #define SMB_DOMAINS_FILE "domains" 515331Samw 525331Samw static void nt_domain_unlist(nt_domain_t *); 535331Samw 545331Samw /* 555331Samw * Valid domain type identifiers as text. This table must be kept 565331Samw * in step with the nt_domain_type_t enum in ntdomain.h. 575331Samw */ 585331Samw static char *nt_domain_type_name[NT_DOMAIN_NUM_TYPES] = { 595331Samw "null", 605331Samw "builtin", 615331Samw "local", 625331Samw "primary", 635331Samw "account", 645331Samw "trusted", 655331Samw "untrusted" 665331Samw }; 675331Samw 685331Samw 695331Samw static rwlock_t nt_domain_lock; 705331Samw static nt_domain_t *nt_domain_list; 715331Samw 725331Samw /* 735331Samw * nt_domain_init 745331Samw * 755331Samw * NT domain database one time initialization. This function should 765331Samw * be called during module installation. 775331Samw * 785331Samw * Returns 0 on successful domain initialization. Less than zero otherwise. 795331Samw */ 805331Samw int 815331Samw nt_domain_init(char *resource_domain, uint32_t secmode) 825331Samw { 835331Samw nt_domain_t *domain; 846432Sas200622 smb_sid_t *sid = NULL; 855772Sas200622 char sidstr[128]; 865331Samw char *lsidstr; 877961SNatalie.Li@Sun.COM char hostname[NETBIOS_NAME_SZ]; 885772Sas200622 int rc; 895331Samw 905331Samw if (rwlock_init(&nt_domain_lock, USYNC_THREAD, NULL)) 915331Samw return (SMB_DOMAIN_NODOMAIN_SID); 925331Samw 937961SNatalie.Li@Sun.COM if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0) { 945331Samw (void) rwlock_destroy(&nt_domain_lock); 955331Samw return (SMB_DOMAIN_NOMACHINE_SID); 965331Samw } 975331Samw 985331Samw lsidstr = smb_config_get_localsid(); 995331Samw 1005331Samw if (lsidstr) { 1016432Sas200622 sid = smb_sid_fromstr(lsidstr); 1025331Samw 1035331Samw if (sid) { 1045331Samw domain = nt_domain_new(NT_DOMAIN_LOCAL, hostname, sid); 1055331Samw (void) nt_domain_add(domain); 1065331Samw free(sid); 1075331Samw } 1085331Samw free(lsidstr); 1095331Samw } else { 1105331Samw (void) rwlock_destroy(&nt_domain_lock); 1115331Samw return (SMB_DOMAIN_NOMACHINE_SID); 1125331Samw } 1135331Samw 1146432Sas200622 if ((sid = smb_sid_fromstr(NT_BUILTIN_DOMAIN_SIDSTR)) != NULL) { 1155331Samw domain = nt_domain_new(NT_DOMAIN_BUILTIN, "BUILTIN", sid); 1165331Samw (void) nt_domain_add(domain); 1175331Samw free(sid); 1186139Sjb150015 } 1195331Samw 1206139Sjb150015 if (secmode == SMB_SECMODE_DOMAIN) { 1215772Sas200622 rc = smb_config_getstr(SMB_CI_DOMAIN_SID, sidstr, 1225772Sas200622 sizeof (sidstr)); 1236432Sas200622 sid = (rc == SMBD_SMF_OK) ? smb_sid_fromstr(sidstr) : NULL; 1246432Sas200622 if (smb_sid_isvalid(sid)) { 1255331Samw domain = nt_domain_new(NT_DOMAIN_PRIMARY, 1265331Samw resource_domain, sid); 1275331Samw (void) nt_domain_add(domain); 1285331Samw free(sid); 1295331Samw } else { 1305772Sas200622 free(sid); 1315331Samw (void) rwlock_destroy(&nt_domain_lock); 1325331Samw return (SMB_DOMAIN_NODOMAIN_SID); 1335331Samw } 1345331Samw 1355331Samw } 1366139Sjb150015 1375331Samw return (0); 1385331Samw } 1395331Samw 1405331Samw /* 1415331Samw * nt_domain_new 1425331Samw * 1435331Samw * Allocate and initialize a new domain structure. On success, a pointer to 1445331Samw * the new domain structure is returned. Otherwise a null pointer is returned. 1455331Samw */ 1465331Samw nt_domain_t * 1476432Sas200622 nt_domain_new(nt_domain_type_t type, char *name, smb_sid_t *sid) 1485331Samw { 1495331Samw nt_domain_t *new_domain; 1505331Samw 1515331Samw if ((name == NULL) || (sid == NULL)) 1525331Samw return (NULL); 1535331Samw 1545331Samw if (type == NT_DOMAIN_NULL || type >= NT_DOMAIN_NUM_TYPES) 1555331Samw return (NULL); 1565331Samw 1575331Samw if ((new_domain = malloc(sizeof (nt_domain_t))) == NULL) 1585331Samw return (NULL); 1595331Samw 1605331Samw bzero(new_domain, sizeof (nt_domain_t)); 1615331Samw new_domain->type = type; 1625331Samw new_domain->name = strdup(name); 1636432Sas200622 new_domain->sid = smb_sid_dup(sid); 1645331Samw 1655331Samw return (new_domain); 1665331Samw } 1675331Samw 1685331Samw /* 1695331Samw * nt_domain_delete 1705331Samw * 1715331Samw * Free the memory used by the specified domain structure. 1725331Samw */ 1735331Samw void 1745331Samw nt_domain_delete(nt_domain_t *domain) 1755331Samw { 1765331Samw if (domain) { 1775331Samw free(domain->name); 1785331Samw free(domain->sid); 1795331Samw free(domain); 1805331Samw } 1815331Samw } 1825331Samw 1835331Samw 1845331Samw /* 1855331Samw * nt_domain_add 1865331Samw * 1875331Samw * Add a domain structure to the global list. There is no checking 1885331Samw * for duplicates. If it's the primary domain, we save the SID in the 1895331Samw * environment. Returns a pointer to the new domain entry on success. 1905331Samw * Otherwise a null pointer is returned. 1915331Samw */ 1925331Samw nt_domain_t * 1935331Samw nt_domain_add(nt_domain_t *new_domain) 1945331Samw { 1956432Sas200622 char sidstr[SMB_SID_STRSZ]; 1965331Samw 1975331Samw if (new_domain == NULL) 1985331Samw return (NULL); 1995331Samw 2005331Samw (void) rw_wrlock(&nt_domain_lock); 2015331Samw 2025331Samw new_domain->next = nt_domain_list; 2035331Samw nt_domain_list = new_domain; 2045331Samw 2055331Samw if (new_domain->type == NT_DOMAIN_PRIMARY) { 2066432Sas200622 smb_sid_tostr(new_domain->sid, sidstr); 2075772Sas200622 (void) smb_config_setstr(SMB_CI_DOMAIN_SID, sidstr); 2085331Samw } 2095331Samw (void) rw_unlock(&nt_domain_lock); 2105331Samw 2115331Samw return (new_domain); 2125331Samw } 2135331Samw 2145331Samw 2155331Samw /* 2165331Samw * nt_domain_remove 2175331Samw * 2185331Samw * Remove a domain from the global list. The memory 2195331Samw * used by the structure is not freed. 2205331Samw */ 2215331Samw void 2225331Samw nt_domain_remove(nt_domain_t *domain) 2235331Samw { 2245331Samw (void) rw_wrlock(&nt_domain_lock); 2255331Samw nt_domain_unlist(domain); 2265331Samw (void) rw_unlock(&nt_domain_lock); 2275331Samw } 2285331Samw 2295331Samw 2305331Samw /* 2315331Samw * nt_domain_flush 2325331Samw * 2335331Samw * Flush all domains of the specified type from the list. This is 2345331Samw * useful for things like updating the list of trusted domains. 2355331Samw */ 2365331Samw void 2375331Samw nt_domain_flush(nt_domain_type_t domain_type) 2385331Samw { 2395331Samw nt_domain_t *domain = nt_domain_list; 2405331Samw 2415331Samw (void) rw_wrlock(&nt_domain_lock); 2425331Samw while (domain) { 2435331Samw if (domain->type == domain_type) { 2445331Samw nt_domain_unlist(domain); 2455331Samw nt_domain_delete(domain); 2465331Samw domain = nt_domain_list; 2475331Samw continue; 2485331Samw } 2495331Samw domain = domain->next; 2505331Samw } 2515331Samw (void) rw_unlock(&nt_domain_lock); 2525331Samw } 2535331Samw 2545331Samw /* 2555331Samw * nt_domain_xlat_type 2565331Samw * 2575331Samw * Translate a domain type into a text string. 2585331Samw */ 2595331Samw char * 2605331Samw nt_domain_xlat_type(nt_domain_type_t domain_type) 2615331Samw { 2625331Samw if (domain_type < NT_DOMAIN_NUM_TYPES) 2635331Samw return (nt_domain_type_name[domain_type]); 2645331Samw else 2655331Samw return ("unknown"); 2665331Samw } 2675331Samw 2685331Samw 2695331Samw /* 2705331Samw * nt_domain_xlat_type_name 2715331Samw * 2725331Samw * Translate a domain type test string into a domain type. 2735331Samw */ 2745331Samw nt_domain_type_t 2755331Samw nt_domain_xlat_type_name(char *type_name) 2765331Samw { 2775331Samw int i; 2785331Samw 2795331Samw for (i = 0; i < NT_DOMAIN_NUM_TYPES; ++i) 2805331Samw if (utf8_strcasecmp(nt_domain_type_name[i], type_name) == 0) 2815331Samw return (i); 2825331Samw 2835331Samw return (NT_DOMAIN_NUM_TYPES); 2845331Samw } 2855331Samw 2865331Samw 2875331Samw /* 2885331Samw * nt_domain_lookup_name 2895331Samw * 2905331Samw * Lookup a domain by its domain name. If the domain is in the list, 2915331Samw * a pointer to it is returned. Otherwise a null pointer is returned. 2925331Samw */ 2935331Samw nt_domain_t * 2945331Samw nt_domain_lookup_name(char *domain_name) 2955331Samw { 296*8670SJose.Borrego@Sun.COM char nbname[MAXHOSTNAMELEN]; 2975331Samw nt_domain_t *domain = nt_domain_list; 298*8670SJose.Borrego@Sun.COM char *p; 299*8670SJose.Borrego@Sun.COM 300*8670SJose.Borrego@Sun.COM if (domain_name == NULL || *domain_name == '\0') 301*8670SJose.Borrego@Sun.COM return (NULL); 302*8670SJose.Borrego@Sun.COM 303*8670SJose.Borrego@Sun.COM (void) strlcpy(nbname, domain_name, sizeof (nbname)); 304*8670SJose.Borrego@Sun.COM if ((p = strchr(nbname, '.')) != NULL) 305*8670SJose.Borrego@Sun.COM *p = '\0'; 3065331Samw 3075331Samw (void) rw_rdlock(&nt_domain_lock); 3085331Samw while (domain) { 309*8670SJose.Borrego@Sun.COM if (utf8_strcasecmp(domain->name, nbname) == 0) 3105331Samw break; 3115331Samw 3125331Samw domain = domain->next; 3135331Samw } 3145331Samw (void) rw_unlock(&nt_domain_lock); 3155331Samw 3165331Samw return (domain); 3175331Samw } 3185331Samw 3195331Samw 3205331Samw /* 3215331Samw * nt_domain_lookup_sid 3225331Samw * 3235331Samw * Lookup a domain by its domain SID. If the domain is in the list, 3245331Samw * a pointer to it is returned. Otherwise a null pointer is returned. 3255331Samw */ 3265331Samw nt_domain_t * 3276432Sas200622 nt_domain_lookup_sid(smb_sid_t *domain_sid) 3285331Samw { 3295331Samw nt_domain_t *domain = nt_domain_list; 3305331Samw 3315331Samw (void) rw_rdlock(&nt_domain_lock); 3325331Samw while (domain) { 3336432Sas200622 if (smb_sid_cmp(domain->sid, domain_sid)) 3345331Samw break; 3355331Samw 3365331Samw domain = domain->next; 3375331Samw } 3385331Samw (void) rw_unlock(&nt_domain_lock); 3395331Samw 3405331Samw return (domain); 3415331Samw } 3425331Samw 3435331Samw 3445331Samw /* 3455331Samw * nt_domain_lookupbytype 3465331Samw * 3475331Samw * Lookup a domain by its type. The first matching entry in the list 3485331Samw * is returned. Otherwise a null pointer is returned. 3495331Samw */ 3505331Samw nt_domain_t * 3515331Samw nt_domain_lookupbytype(nt_domain_type_t type) 3525331Samw { 3535331Samw nt_domain_t *domain = nt_domain_list; 3545331Samw 3555331Samw (void) rw_rdlock(&nt_domain_lock); 3565331Samw while (domain) { 3575331Samw if (domain->type == type) 3585331Samw break; 3595331Samw 3605331Samw domain = domain->next; 3615331Samw } 3625331Samw (void) rw_unlock(&nt_domain_lock); 3635331Samw 3645331Samw return (domain); 3655331Samw } 3665331Samw 3675331Samw 3685331Samw /* 3695331Samw * nt_domain_local_sid 3705331Samw * 3715331Samw * Return a pointer to the local domain SID. Each system has a SID that 3725331Samw * represents the local domain, which is named after the local hostname. 3735331Samw * The local domain SID must exist. 3745331Samw */ 3756432Sas200622 smb_sid_t * 3765331Samw nt_domain_local_sid(void) 3775331Samw { 3785331Samw nt_domain_t *domain = nt_domain_list; 3795331Samw 3805331Samw (void) rw_rdlock(&nt_domain_lock); 3815331Samw while (domain) { 3825331Samw if (domain->type == NT_DOMAIN_LOCAL) 3835331Samw break; 3845331Samw 3855331Samw domain = domain->next; 3865331Samw } 3875331Samw (void) rw_unlock(&nt_domain_lock); 3885331Samw 3895331Samw return (domain->sid); 3905331Samw } 3915331Samw 3925331Samw 3935331Samw static void 3945331Samw nt_domain_unlist(nt_domain_t *domain) 3955331Samw { 3965331Samw nt_domain_t **ppdomain = &nt_domain_list; 3975331Samw 3985331Samw while (*ppdomain) { 3995331Samw if (*ppdomain == domain) { 4005331Samw *ppdomain = domain->next; 4015331Samw domain->next = NULL; 4025331Samw return; 4035331Samw } 4045331Samw ppdomain = &(*ppdomain)->next; 4055331Samw } 4065331Samw } 4078474SJose.Borrego@Sun.COM 4088474SJose.Borrego@Sun.COM /* 4098474SJose.Borrego@Sun.COM * Write the list of domains to /var/run/smb/domains. 4108474SJose.Borrego@Sun.COM */ 4118474SJose.Borrego@Sun.COM void 4128474SJose.Borrego@Sun.COM nt_domain_save(void) 4138474SJose.Borrego@Sun.COM { 4148474SJose.Borrego@Sun.COM char fname[MAXPATHLEN]; 4158474SJose.Borrego@Sun.COM char sidstr[SMB_SID_STRSZ]; 4168474SJose.Borrego@Sun.COM char tag; 4178474SJose.Borrego@Sun.COM nt_domain_t *domain; 4188474SJose.Borrego@Sun.COM FILE *fp; 4198474SJose.Borrego@Sun.COM struct passwd *pwd; 4208474SJose.Borrego@Sun.COM struct group *grp; 4218474SJose.Borrego@Sun.COM uid_t uid; 4228474SJose.Borrego@Sun.COM gid_t gid; 4238474SJose.Borrego@Sun.COM 4248474SJose.Borrego@Sun.COM (void) snprintf(fname, MAXPATHLEN, "%s/%s", 4258474SJose.Borrego@Sun.COM SMB_VARRUN_DIR, SMB_DOMAINS_FILE); 4268474SJose.Borrego@Sun.COM 4278474SJose.Borrego@Sun.COM if ((fp = fopen(fname, "w")) == NULL) 4288474SJose.Borrego@Sun.COM return; 4298474SJose.Borrego@Sun.COM 4308474SJose.Borrego@Sun.COM pwd = getpwnam("root"); 4318474SJose.Borrego@Sun.COM grp = getgrnam("sys"); 4328474SJose.Borrego@Sun.COM uid = (pwd == NULL) ? 0 : pwd->pw_uid; 4338474SJose.Borrego@Sun.COM gid = (grp == NULL) ? 3 : grp->gr_gid; 4348474SJose.Borrego@Sun.COM 4358474SJose.Borrego@Sun.COM (void) lockf(fileno(fp), F_LOCK, 0); 4368474SJose.Borrego@Sun.COM (void) fchmod(fileno(fp), 0600); 4378474SJose.Borrego@Sun.COM (void) fchown(fileno(fp), uid, gid); 4388474SJose.Borrego@Sun.COM 4398474SJose.Borrego@Sun.COM (void) rw_rdlock(&nt_domain_lock); 4408474SJose.Borrego@Sun.COM 4418474SJose.Borrego@Sun.COM domain = nt_domain_list; 4428474SJose.Borrego@Sun.COM while (domain) { 4438474SJose.Borrego@Sun.COM smb_sid_tostr(domain->sid, sidstr); 4448474SJose.Borrego@Sun.COM switch (domain->type) { 4458474SJose.Borrego@Sun.COM case NT_DOMAIN_PRIMARY: 4468474SJose.Borrego@Sun.COM tag = '*'; 4478474SJose.Borrego@Sun.COM break; 4488474SJose.Borrego@Sun.COM 4498474SJose.Borrego@Sun.COM case NT_DOMAIN_TRUSTED: 4508474SJose.Borrego@Sun.COM case NT_DOMAIN_UNTRUSTED: 4518474SJose.Borrego@Sun.COM tag = '-'; 4528474SJose.Borrego@Sun.COM break; 4538474SJose.Borrego@Sun.COM 4548474SJose.Borrego@Sun.COM case NT_DOMAIN_LOCAL: 4558474SJose.Borrego@Sun.COM tag = '.'; 4568474SJose.Borrego@Sun.COM break; 4578474SJose.Borrego@Sun.COM default: 4588474SJose.Borrego@Sun.COM domain = domain->next; 4598474SJose.Borrego@Sun.COM continue; 4608474SJose.Borrego@Sun.COM } 4618474SJose.Borrego@Sun.COM 4628474SJose.Borrego@Sun.COM (void) fprintf(fp, "[%c] [%s] [%s]\n", 4638474SJose.Borrego@Sun.COM tag, domain->name, sidstr); 4648474SJose.Borrego@Sun.COM 4658474SJose.Borrego@Sun.COM domain = domain->next; 4668474SJose.Borrego@Sun.COM } 4678474SJose.Borrego@Sun.COM 4688474SJose.Borrego@Sun.COM (void) rw_unlock(&nt_domain_lock); 4698474SJose.Borrego@Sun.COM (void) lockf(fileno(fp), F_ULOCK, 0); 4708474SJose.Borrego@Sun.COM (void) fclose(fp); 4718474SJose.Borrego@Sun.COM } 4728474SJose.Borrego@Sun.COM 4738474SJose.Borrego@Sun.COM /* 4748474SJose.Borrego@Sun.COM * List the domains in /var/run/smb/domains. 4758474SJose.Borrego@Sun.COM */ 4768474SJose.Borrego@Sun.COM void 4778474SJose.Borrego@Sun.COM nt_domain_show(void) 4788474SJose.Borrego@Sun.COM { 4798474SJose.Borrego@Sun.COM char buf[MAXPATHLEN]; 4808474SJose.Borrego@Sun.COM char *p; 4818474SJose.Borrego@Sun.COM FILE *fp; 4828474SJose.Borrego@Sun.COM 4838474SJose.Borrego@Sun.COM (void) snprintf(buf, MAXPATHLEN, "%s/%s", 4848474SJose.Borrego@Sun.COM SMB_VARRUN_DIR, SMB_DOMAINS_FILE); 4858474SJose.Borrego@Sun.COM 4868474SJose.Borrego@Sun.COM if ((fp = fopen(buf, "r")) != NULL) { 4878474SJose.Borrego@Sun.COM (void) lockf(fileno(fp), F_LOCK, 0); 4888474SJose.Borrego@Sun.COM 4898474SJose.Borrego@Sun.COM while (fgets(buf, MAXPATHLEN, fp) != NULL) { 4908474SJose.Borrego@Sun.COM if ((p = strchr(buf, '\n')) != NULL) 4918474SJose.Borrego@Sun.COM *p = '\0'; 4928474SJose.Borrego@Sun.COM (void) printf("%s\n", buf); 4938474SJose.Borrego@Sun.COM } 4948474SJose.Borrego@Sun.COM 4958474SJose.Borrego@Sun.COM (void) lockf(fileno(fp), F_ULOCK, 0); 4968474SJose.Borrego@Sun.COM (void) fclose(fp); 4978474SJose.Borrego@Sun.COM } 4988474SJose.Borrego@Sun.COM } 4998474SJose.Borrego@Sun.COM 5008474SJose.Borrego@Sun.COM /* 5018474SJose.Borrego@Sun.COM * Remove the /var/run/smb/domains file. 5028474SJose.Borrego@Sun.COM */ 5038474SJose.Borrego@Sun.COM void 5048474SJose.Borrego@Sun.COM nt_domain_unlink(void) 5058474SJose.Borrego@Sun.COM { 5068474SJose.Borrego@Sun.COM char fname[MAXPATHLEN]; 5078474SJose.Borrego@Sun.COM 5088474SJose.Borrego@Sun.COM (void) snprintf(fname, MAXPATHLEN, "%s/%s", 5098474SJose.Borrego@Sun.COM SMB_VARRUN_DIR, SMB_DOMAINS_FILE); 5108474SJose.Borrego@Sun.COM (void) unlink(fname); 5118474SJose.Borrego@Sun.COM } 512