1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22148c5f43SAlan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23da6c28aaSamw */ 24da6c28aaSamw 258d7e4166Sjose borrego #include <assert.h> 26da6c28aaSamw #include <sys/types.h> 27da6c28aaSamw #include <stdarg.h> 28da6c28aaSamw #include <unistd.h> 29da6c28aaSamw #include <stdlib.h> 30da6c28aaSamw #include <time.h> 31da6c28aaSamw #include <synch.h> 32da6c28aaSamw #include <syslog.h> 33da6c28aaSamw #include <string.h> 34da6c28aaSamw #include <strings.h> 35da6c28aaSamw #include <errno.h> 36da6c28aaSamw #include <net/if.h> 37da6c28aaSamw #include <netdb.h> 38dc20a302Sas #include <netinet/in.h> 39dc20a302Sas #include <arpa/nameser.h> 40dc20a302Sas #include <resolv.h> 41da6c28aaSamw #include <sys/sockio.h> 428d7e4166Sjose borrego #include <sys/socket.h> 43da6c28aaSamw #include <smbsrv/smbinfo.h> 44da6c28aaSamw #include <smbsrv/netbios.h> 45da6c28aaSamw #include <smbsrv/libsmb.h> 46da6c28aaSamw 47faa1795aSjb static mutex_t seqnum_mtx; 48da6c28aaSamw 49a0aa776eSAlan Wright /* 50a0aa776eSAlan Wright * IPC connection information that may be passed to the SMB Redirector. 51a0aa776eSAlan Wright */ 52a0aa776eSAlan Wright typedef struct { 53a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN]; 54a0aa776eSAlan Wright uint8_t passwd[SMBAUTH_HASH_SZ]; 55a0aa776eSAlan Wright } smb_ipc_t; 56a0aa776eSAlan Wright 57a0aa776eSAlan Wright static smb_ipc_t ipc_info; 58a0aa776eSAlan Wright static smb_ipc_t ipc_orig_info; 59a0aa776eSAlan Wright static rwlock_t smb_ipc_lock; 60a0aa776eSAlan Wright 61eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States /* 62eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * Some older clients (Windows 98) only handle the low byte 63eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * of the max workers value. If the low byte is less than 64eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * SMB_PI_MAX_WORKERS_MIN set it to SMB_PI_MAX_WORKERS_MIN. 65eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States */ 66da6c28aaSamw void 67da6c28aaSamw smb_load_kconfig(smb_kmod_cfg_t *kcfg) 68da6c28aaSamw { 69dc20a302Sas int64_t citem; 70dc20a302Sas 71da6c28aaSamw bzero(kcfg, sizeof (smb_kmod_cfg_t)); 72da6c28aaSamw 73dc20a302Sas (void) smb_config_getnum(SMB_CI_MAX_WORKERS, &citem); 74dc20a302Sas kcfg->skc_maxworkers = (uint32_t)citem; 75eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States if ((kcfg->skc_maxworkers & 0xFF) < SMB_PI_MAX_WORKERS_MIN) { 76eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States kcfg->skc_maxworkers &= ~0xFF; 77eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States kcfg->skc_maxworkers += SMB_PI_MAX_WORKERS_MIN; 78eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States } 79eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 80dc20a302Sas (void) smb_config_getnum(SMB_CI_KEEPALIVE, &citem); 81dc20a302Sas kcfg->skc_keepalive = (uint32_t)citem; 82da6c28aaSamw if ((kcfg->skc_keepalive != 0) && 83da6c28aaSamw (kcfg->skc_keepalive < SMB_PI_KEEP_ALIVE_MIN)) 84da6c28aaSamw kcfg->skc_keepalive = SMB_PI_KEEP_ALIVE_MIN; 85da6c28aaSamw 86dc20a302Sas (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &citem); 87dc20a302Sas kcfg->skc_maxconnections = (uint32_t)citem; 88dc20a302Sas kcfg->skc_restrict_anon = smb_config_getbool(SMB_CI_RESTRICT_ANON); 89dc20a302Sas kcfg->skc_signing_enable = smb_config_getbool(SMB_CI_SIGNING_ENABLE); 90dc20a302Sas kcfg->skc_signing_required = smb_config_getbool(SMB_CI_SIGNING_REQD); 917f667e74Sjose borrego kcfg->skc_ipv6_enable = smb_config_getbool(SMB_CI_IPV6_ENABLE); 92*cb174861Sjoyce mcintosh kcfg->skc_print_enable = smb_config_getbool(SMB_CI_PRINT_ENABLE); 93dc20a302Sas kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE); 94dc20a302Sas kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE); 95da6c28aaSamw kcfg->skc_secmode = smb_config_get_secmode(); 96b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getdomainname(kcfg->skc_nbdomain, 97b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_nbdomain)); 98b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getfqdomainname(kcfg->skc_fqdn, 99b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_fqdn)); 100b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getnetbiosname(kcfg->skc_hostname, 101b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_hostname)); 102dc20a302Sas (void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment, 103da6c28aaSamw sizeof (kcfg->skc_system_comment)); 1049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_config_get_version(&kcfg->skc_version); 105148c5f43SAlan Wright kcfg->skc_execflags = smb_config_get_execinfo(NULL, NULL, 0); 106da6c28aaSamw } 107da6c28aaSamw 108da6c28aaSamw /* 109da6c28aaSamw * Get the current system NetBIOS name. The hostname is truncated at 110da6c28aaSamw * the first `.` or 15 bytes, whichever occurs first, and converted 111da6c28aaSamw * to uppercase (by smb_gethostname). Text that appears after the 112da6c28aaSamw * first '.' is considered to be part of the NetBIOS scope. 113da6c28aaSamw * 114da6c28aaSamw * Returns 0 on success, otherwise -1 to indicate an error. 115da6c28aaSamw */ 116da6c28aaSamw int 117da6c28aaSamw smb_getnetbiosname(char *buf, size_t buflen) 118da6c28aaSamw { 1199fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(buf, buflen, SMB_CASE_UPPER) != 0) 120da6c28aaSamw return (-1); 121da6c28aaSamw 122da6c28aaSamw if (buflen >= NETBIOS_NAME_SZ) 123da6c28aaSamw buf[NETBIOS_NAME_SZ - 1] = '\0'; 124da6c28aaSamw 125da6c28aaSamw return (0); 126da6c28aaSamw } 127da6c28aaSamw 128b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 129b89a8333Snatalie li - Sun Microsystems - Irvine United States * Get the SAM account of the current system. 130b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns 0 on success, otherwise, -1 to indicate an error. 131b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 132b89a8333Snatalie li - Sun Microsystems - Irvine United States int 133b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_getsamaccount(char *buf, size_t buflen) 134b89a8333Snatalie li - Sun Microsystems - Irvine United States { 135b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getnetbiosname(buf, buflen - 1) != 0) 136b89a8333Snatalie li - Sun Microsystems - Irvine United States return (-1); 137b89a8333Snatalie li - Sun Microsystems - Irvine United States 138b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcat(buf, "$", buflen); 139b89a8333Snatalie li - Sun Microsystems - Irvine United States return (0); 140b89a8333Snatalie li - Sun Microsystems - Irvine United States } 141b89a8333Snatalie li - Sun Microsystems - Irvine United States 142da6c28aaSamw /* 143da6c28aaSamw * Get the current system node name. The returned name is guaranteed 144da6c28aaSamw * to be null-terminated (gethostname may not null terminate the name). 145da6c28aaSamw * If the hostname has been fully-qualified for some reason, the domain 1469fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * part will be removed. The returned hostname is converted to the 1479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * specified case (lower, upper, or preserved). 148da6c28aaSamw * 149da6c28aaSamw * If gethostname fails, the returned buffer will contain an empty 150da6c28aaSamw * string. 151da6c28aaSamw */ 152da6c28aaSamw int 1539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_gethostname(char *buf, size_t buflen, smb_caseconv_t which) 154da6c28aaSamw { 155da6c28aaSamw char *p; 156da6c28aaSamw 157da6c28aaSamw if (buf == NULL || buflen == 0) 158da6c28aaSamw return (-1); 159da6c28aaSamw 160da6c28aaSamw if (gethostname(buf, buflen) != 0) { 161da6c28aaSamw *buf = '\0'; 162da6c28aaSamw return (-1); 163da6c28aaSamw } 164da6c28aaSamw 165da6c28aaSamw buf[buflen - 1] = '\0'; 166da6c28aaSamw 167da6c28aaSamw if ((p = strchr(buf, '.')) != NULL) 168da6c28aaSamw *p = '\0'; 169da6c28aaSamw 1709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States switch (which) { 1719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_LOWER: 1729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_strlwr(buf); 1739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 1749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_UPPER: 176bbf6f00cSJordan Brown (void) smb_strupr(buf); 1779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 1789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 1799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_PRESERVE: 1809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States default: 1819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 1829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 183da6c28aaSamw 184da6c28aaSamw return (0); 185da6c28aaSamw } 186da6c28aaSamw 187da6c28aaSamw /* 1889fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Obtain the fully-qualified name for this machine in lower case. If 1899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * the hostname is fully-qualified, accept it. Otherwise, try to find an 1909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * appropriate domain name to append to the hostname. 191da6c28aaSamw */ 192da6c28aaSamw int 193dc20a302Sas smb_getfqhostname(char *buf, size_t buflen) 194da6c28aaSamw { 195dc20a302Sas char hostname[MAXHOSTNAMELEN]; 196dc20a302Sas char domain[MAXHOSTNAMELEN]; 197da6c28aaSamw 198dc20a302Sas hostname[0] = '\0'; 199dc20a302Sas domain[0] = '\0'; 200dc20a302Sas 2019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(hostname, MAXHOSTNAMELEN, 2029fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_CASE_LOWER) != 0) 203da6c28aaSamw return (-1); 204da6c28aaSamw 205dc20a302Sas if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) 206dc20a302Sas return (-1); 207dc20a302Sas 208dc20a302Sas if (hostname[0] == '\0') 209dc20a302Sas return (-1); 210da6c28aaSamw 211dc20a302Sas if (domain[0] == '\0') { 212dc20a302Sas (void) strlcpy(buf, hostname, buflen); 213da6c28aaSamw return (0); 214da6c28aaSamw } 215da6c28aaSamw 216dc20a302Sas (void) snprintf(buf, buflen, "%s.%s", hostname, domain); 217dc20a302Sas return (0); 218dc20a302Sas } 219da6c28aaSamw 220da6c28aaSamw /* 221dc20a302Sas * smb_getdomainname 222dc20a302Sas * 223dc20a302Sas * Returns NETBIOS name of the domain if the system is in domain 224dc20a302Sas * mode. Or returns workgroup name if the system is in workgroup 225dc20a302Sas * mode. 226da6c28aaSamw */ 227da6c28aaSamw int 228dc20a302Sas smb_getdomainname(char *buf, size_t buflen) 229da6c28aaSamw { 230dc20a302Sas int rc; 231da6c28aaSamw 232dc20a302Sas if (buf == NULL || buflen == 0) 233dc20a302Sas return (-1); 234da6c28aaSamw 235dc20a302Sas *buf = '\0'; 2368d7e4166Sjose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, buf, buflen); 237dc20a302Sas 2388d7e4166Sjose borrego if ((rc != SMBD_SMF_OK) || (*buf == '\0')) 239da6c28aaSamw return (-1); 240da6c28aaSamw 241dc20a302Sas return (0); 242dc20a302Sas } 243dc20a302Sas 244dc20a302Sas /* 245dc20a302Sas * smb_getfqdomainname 246dc20a302Sas * 2478d7e4166Sjose borrego * In the system is in domain mode, the dns_domain property value 2488d7e4166Sjose borrego * is returned. Otherwise, it returns the local domain obtained via 2498d7e4166Sjose borrego * resolver. 250dc20a302Sas * 251dc20a302Sas * Returns 0 upon success. Otherwise, returns -1. 252dc20a302Sas */ 253dc20a302Sas int 254dc20a302Sas smb_getfqdomainname(char *buf, size_t buflen) 255dc20a302Sas { 2568d7e4166Sjose borrego struct __res_state res_state; 2578d7e4166Sjose borrego int rc; 258dc20a302Sas 259dc20a302Sas if (buf == NULL || buflen == 0) 260dc20a302Sas return (-1); 261dc20a302Sas 262dc20a302Sas *buf = '\0'; 263dc20a302Sas if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { 2648d7e4166Sjose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_FQDN, buf, buflen); 265dc20a302Sas 2668d7e4166Sjose borrego if ((rc != SMBD_SMF_OK) || (*buf == '\0')) 2678d7e4166Sjose borrego return (-1); 2688d7e4166Sjose borrego } else { 2698d7e4166Sjose borrego bzero(&res_state, sizeof (struct __res_state)); 2708d7e4166Sjose borrego if (res_ninit(&res_state)) 271dc20a302Sas return (-1); 272dc20a302Sas 2738d7e4166Sjose borrego if (*res_state.defdname == '\0') { 2748d7e4166Sjose borrego res_ndestroy(&res_state); 2758d7e4166Sjose borrego return (-1); 276dc20a302Sas } 2778d7e4166Sjose borrego 2788d7e4166Sjose borrego (void) strlcpy(buf, res_state.defdname, buflen); 2798d7e4166Sjose borrego res_ndestroy(&res_state); 2808d7e4166Sjose borrego rc = 0; 281dc20a302Sas } 282dc20a302Sas 283dc20a302Sas return (rc); 284da6c28aaSamw } 285da6c28aaSamw 286dc20a302Sas 287faa1795aSjb /* 288faa1795aSjb * smb_set_machine_passwd 289faa1795aSjb * 290faa1795aSjb * This function should be used when setting the machine password property. 291faa1795aSjb * The associated sequence number is incremented. 292faa1795aSjb */ 293faa1795aSjb static int 294faa1795aSjb smb_set_machine_passwd(char *passwd) 295faa1795aSjb { 296faa1795aSjb int64_t num; 297faa1795aSjb int rc = -1; 298faa1795aSjb 299faa1795aSjb if (smb_config_set(SMB_CI_MACHINE_PASSWD, passwd) != SMBD_SMF_OK) 300faa1795aSjb return (-1); 301faa1795aSjb 302faa1795aSjb (void) mutex_lock(&seqnum_mtx); 303faa1795aSjb (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num); 304faa1795aSjb if (smb_config_setnum(SMB_CI_KPASSWD_SEQNUM, ++num) 305faa1795aSjb == SMBD_SMF_OK) 306faa1795aSjb rc = 0; 307faa1795aSjb (void) mutex_unlock(&seqnum_mtx); 308faa1795aSjb return (rc); 309faa1795aSjb } 310faa1795aSjb 311a0aa776eSAlan Wright static int 312a0aa776eSAlan Wright smb_get_machine_passwd(uint8_t *buf, size_t buflen) 313a0aa776eSAlan Wright { 314a0aa776eSAlan Wright char pwd[SMB_PASSWD_MAXLEN + 1]; 315a0aa776eSAlan Wright int rc; 316a0aa776eSAlan Wright 317a0aa776eSAlan Wright if (buflen < SMBAUTH_HASH_SZ) 318a0aa776eSAlan Wright return (-1); 319a0aa776eSAlan Wright 320a0aa776eSAlan Wright rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd)); 321a0aa776eSAlan Wright if ((rc != SMBD_SMF_OK) || *pwd == '\0') 322a0aa776eSAlan Wright return (-1); 323a0aa776eSAlan Wright 324a0aa776eSAlan Wright if (smb_auth_ntlm_hash(pwd, buf) != 0) 325a0aa776eSAlan Wright return (-1); 326a0aa776eSAlan Wright 327a0aa776eSAlan Wright return (rc); 328a0aa776eSAlan Wright } 329a0aa776eSAlan Wright 330a0aa776eSAlan Wright /* 331a0aa776eSAlan Wright * Set up IPC connection credentials. 332a0aa776eSAlan Wright */ 333a0aa776eSAlan Wright void 334a0aa776eSAlan Wright smb_ipc_init(void) 335a0aa776eSAlan Wright { 336a0aa776eSAlan Wright int rc; 337a0aa776eSAlan Wright 338a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 339a0aa776eSAlan Wright bzero(&ipc_info, sizeof (smb_ipc_t)); 340a0aa776eSAlan Wright bzero(&ipc_orig_info, sizeof (smb_ipc_t)); 341a0aa776eSAlan Wright 342a0aa776eSAlan Wright (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); 343a0aa776eSAlan Wright rc = smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ); 344a0aa776eSAlan Wright if (rc != 0) 345a0aa776eSAlan Wright *ipc_info.passwd = 0; 346a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 347a0aa776eSAlan Wright 348a0aa776eSAlan Wright } 349a0aa776eSAlan Wright 350a0aa776eSAlan Wright /* 351a0aa776eSAlan Wright * Set the IPC username and password hash in memory. If the domain 352a0aa776eSAlan Wright * join succeeds, the credentials will be committed for use with 353a0aa776eSAlan Wright * authenticated IPC. Otherwise, they should be rolled back. 354a0aa776eSAlan Wright */ 355a0aa776eSAlan Wright void 356a0aa776eSAlan Wright smb_ipc_set(char *plain_user, uint8_t *passwd_hash) 357a0aa776eSAlan Wright { 358a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 359a0aa776eSAlan Wright (void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user)); 360a0aa776eSAlan Wright (void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ); 361a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 362a0aa776eSAlan Wright 363a0aa776eSAlan Wright } 364a0aa776eSAlan Wright 365a0aa776eSAlan Wright /* 366a0aa776eSAlan Wright * Save the host credentials to be used for authenticated IPC. 367a0aa776eSAlan Wright * The credentials are also saved to the original IPC info as 368a0aa776eSAlan Wright * rollback data in case the join domain process fails later. 369a0aa776eSAlan Wright */ 370a0aa776eSAlan Wright void 371a0aa776eSAlan Wright smb_ipc_commit(void) 372a0aa776eSAlan Wright { 373a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 374a0aa776eSAlan Wright (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); 375a0aa776eSAlan Wright (void) smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ); 376a0aa776eSAlan Wright (void) memcpy(&ipc_orig_info, &ipc_info, sizeof (smb_ipc_t)); 377a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 378a0aa776eSAlan Wright } 379a0aa776eSAlan Wright 380a0aa776eSAlan Wright /* 381a0aa776eSAlan Wright * Restore the original credentials 382a0aa776eSAlan Wright */ 383a0aa776eSAlan Wright void 384a0aa776eSAlan Wright smb_ipc_rollback(void) 385a0aa776eSAlan Wright { 386a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 387a0aa776eSAlan Wright (void) strlcpy(ipc_info.user, ipc_orig_info.user, 388a0aa776eSAlan Wright sizeof (ipc_info.user)); 389a0aa776eSAlan Wright (void) memcpy(ipc_info.passwd, ipc_orig_info.passwd, 390a0aa776eSAlan Wright sizeof (ipc_info.passwd)); 391a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 392a0aa776eSAlan Wright } 393a0aa776eSAlan Wright 394a0aa776eSAlan Wright void 395a0aa776eSAlan Wright smb_ipc_get_user(char *buf, size_t buflen) 396a0aa776eSAlan Wright { 397a0aa776eSAlan Wright (void) rw_rdlock(&smb_ipc_lock); 398a0aa776eSAlan Wright (void) strlcpy(buf, ipc_info.user, buflen); 399a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 400a0aa776eSAlan Wright } 401a0aa776eSAlan Wright 402a0aa776eSAlan Wright void 403a0aa776eSAlan Wright smb_ipc_get_passwd(uint8_t *buf, size_t buflen) 404a0aa776eSAlan Wright { 405a0aa776eSAlan Wright if (buflen < SMBAUTH_HASH_SZ) 406a0aa776eSAlan Wright return; 407a0aa776eSAlan Wright 408a0aa776eSAlan Wright (void) rw_rdlock(&smb_ipc_lock); 409a0aa776eSAlan Wright (void) memcpy(buf, ipc_info.passwd, SMBAUTH_HASH_SZ); 410a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 411a0aa776eSAlan Wright } 412a0aa776eSAlan Wright 413faa1795aSjb /* 414faa1795aSjb * smb_match_netlogon_seqnum 415faa1795aSjb * 416faa1795aSjb * A sequence number is associated with each machine password property 417faa1795aSjb * update and the netlogon credential chain setup. If the 418faa1795aSjb * sequence numbers don't match, a NETLOGON credential chain 419faa1795aSjb * establishment is required. 420faa1795aSjb * 421faa1795aSjb * Returns 0 if kpasswd_seqnum equals to netlogon_seqnum. Otherwise, 422faa1795aSjb * returns -1. 423faa1795aSjb */ 424faa1795aSjb boolean_t 425faa1795aSjb smb_match_netlogon_seqnum(void) 426faa1795aSjb { 427faa1795aSjb int64_t setpasswd_seqnum; 428faa1795aSjb int64_t netlogon_seqnum; 429faa1795aSjb 430faa1795aSjb (void) mutex_lock(&seqnum_mtx); 431faa1795aSjb (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &setpasswd_seqnum); 432faa1795aSjb (void) smb_config_getnum(SMB_CI_NETLOGON_SEQNUM, &netlogon_seqnum); 433faa1795aSjb (void) mutex_unlock(&seqnum_mtx); 434faa1795aSjb return (setpasswd_seqnum == netlogon_seqnum); 435faa1795aSjb } 436faa1795aSjb 437faa1795aSjb /* 438faa1795aSjb * smb_setdomainprops 439faa1795aSjb * 440faa1795aSjb * This function should be called after joining an AD to 441faa1795aSjb * set all the domain related SMF properties. 442faa1795aSjb * 443faa1795aSjb * The kpasswd_domain property is the AD domain to which the system 444faa1795aSjb * is joined via kclient. If this function is invoked by the SMB 445faa1795aSjb * daemon, fqdn should be set to NULL. 446faa1795aSjb */ 447faa1795aSjb int 448faa1795aSjb smb_setdomainprops(char *fqdn, char *server, char *passwd) 449faa1795aSjb { 450faa1795aSjb if (server == NULL || passwd == NULL) 451faa1795aSjb return (-1); 452faa1795aSjb 453faa1795aSjb if ((*server == '\0') || (*passwd == '\0')) 454faa1795aSjb return (-1); 455faa1795aSjb 456faa1795aSjb if (fqdn && (smb_config_set(SMB_CI_KPASSWD_DOMAIN, fqdn) != 0)) 457faa1795aSjb return (-1); 458faa1795aSjb 459faa1795aSjb if (smb_config_set(SMB_CI_KPASSWD_SRV, server) != 0) 460faa1795aSjb return (-1); 461faa1795aSjb 462faa1795aSjb if (smb_set_machine_passwd(passwd) != 0) { 463faa1795aSjb syslog(LOG_ERR, "smb_setdomainprops: failed to set" 464faa1795aSjb " machine account password"); 465faa1795aSjb return (-1); 466faa1795aSjb } 467faa1795aSjb 468faa1795aSjb /* 469faa1795aSjb * If we successfully create a trust account, we mark 470faa1795aSjb * ourselves as a domain member in the environment so 471faa1795aSjb * that we use the SAMLOGON version of the NETLOGON 472faa1795aSjb * PDC location protocol. 473faa1795aSjb */ 474faa1795aSjb (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_TRUE); 475faa1795aSjb 476faa1795aSjb return (0); 477faa1795aSjb } 478faa1795aSjb 479faa1795aSjb /* 480faa1795aSjb * smb_update_netlogon_seqnum 481faa1795aSjb * 482faa1795aSjb * This function should only be called upon a successful netlogon 483faa1795aSjb * credential chain establishment to set the sequence number of the 484faa1795aSjb * netlogon to match with that of the kpasswd. 485faa1795aSjb */ 486faa1795aSjb void 487faa1795aSjb smb_update_netlogon_seqnum(void) 488faa1795aSjb { 489faa1795aSjb int64_t num; 490faa1795aSjb 491faa1795aSjb (void) mutex_lock(&seqnum_mtx); 492faa1795aSjb (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num); 493faa1795aSjb (void) smb_config_setnum(SMB_CI_NETLOGON_SEQNUM, num); 494faa1795aSjb (void) mutex_unlock(&seqnum_mtx); 495faa1795aSjb } 496faa1795aSjb 497dc20a302Sas 498da6c28aaSamw /* 499da6c28aaSamw * Temporary fbt for dtrace until user space sdt enabled. 500da6c28aaSamw */ 501da6c28aaSamw void 502da6c28aaSamw smb_tracef(const char *fmt, ...) 503da6c28aaSamw { 504da6c28aaSamw va_list ap; 505da6c28aaSamw char buf[128]; 506da6c28aaSamw 507da6c28aaSamw va_start(ap, fmt); 508da6c28aaSamw (void) vsnprintf(buf, 128, fmt, ap); 509da6c28aaSamw va_end(ap); 510da6c28aaSamw 511da6c28aaSamw smb_trace(buf); 512da6c28aaSamw } 513da6c28aaSamw 514da6c28aaSamw /* 515da6c28aaSamw * Temporary fbt for dtrace until user space sdt enabled. 516da6c28aaSamw */ 517da6c28aaSamw void 518da6c28aaSamw smb_trace(const char *s) 519da6c28aaSamw { 520da6c28aaSamw syslog(LOG_DEBUG, "%s", s); 521da6c28aaSamw } 5227b59d02dSjb 5237b59d02dSjb /* 5247b59d02dSjb * smb_tonetbiosname 5257b59d02dSjb * 5267b59d02dSjb * Creates a NetBIOS name based on the given name and suffix. 5277b59d02dSjb * NetBIOS name is 15 capital characters, padded with space if needed 5287b59d02dSjb * and the 16th byte is the suffix. 5297b59d02dSjb */ 5307b59d02dSjb void 5317b59d02dSjb smb_tonetbiosname(char *name, char *nb_name, char suffix) 5327b59d02dSjb { 5337b59d02dSjb char tmp_name[NETBIOS_NAME_SZ]; 534bbf6f00cSJordan Brown smb_wchar_t wtmp_name[NETBIOS_NAME_SZ]; 5357b59d02dSjb int len; 5367b59d02dSjb size_t rc; 5377b59d02dSjb 5387b59d02dSjb len = 0; 539bbf6f00cSJordan Brown rc = smb_mbstowcs(wtmp_name, (const char *)name, NETBIOS_NAME_SZ); 5407b59d02dSjb 5417b59d02dSjb if (rc != (size_t)-1) { 5427b59d02dSjb wtmp_name[NETBIOS_NAME_SZ - 1] = 0; 543bbf6f00cSJordan Brown rc = ucstooem(tmp_name, wtmp_name, NETBIOS_NAME_SZ, 544bbf6f00cSJordan Brown OEM_CPG_850); 5457b59d02dSjb if (rc > 0) 5467b59d02dSjb len = strlen(tmp_name); 5477b59d02dSjb } 5487b59d02dSjb 5497b59d02dSjb (void) memset(nb_name, ' ', NETBIOS_NAME_SZ - 1); 5507b59d02dSjb if (len) { 551bbf6f00cSJordan Brown (void) smb_strupr(tmp_name); 5527b59d02dSjb (void) memcpy(nb_name, tmp_name, len); 5537b59d02dSjb } 5547b59d02dSjb nb_name[NETBIOS_NAME_SZ - 1] = suffix; 5557b59d02dSjb } 5567b59d02dSjb 5577b59d02dSjb int 5587f667e74Sjose borrego smb_get_nameservers(smb_inaddr_t *ips, int sz) 5597b59d02dSjb { 5607b59d02dSjb union res_sockaddr_union set[MAXNS]; 5617b59d02dSjb int i, cnt; 5627b59d02dSjb struct __res_state res_state; 5637f667e74Sjose borrego char ipstr[INET6_ADDRSTRLEN]; 5647b59d02dSjb 5657b59d02dSjb if (ips == NULL) 5667b59d02dSjb return (0); 5677b59d02dSjb 5687b59d02dSjb bzero(&res_state, sizeof (struct __res_state)); 5697b59d02dSjb if (res_ninit(&res_state) < 0) 5707b59d02dSjb return (0); 5717b59d02dSjb 5727b59d02dSjb cnt = res_getservers(&res_state, set, MAXNS); 5737b59d02dSjb for (i = 0; i < cnt; i++) { 5747b59d02dSjb if (i >= sz) 5757b59d02dSjb break; 5767f667e74Sjose borrego ips[i].a_family = AF_INET; 5777f667e74Sjose borrego bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv4, INADDRSZ); 5787f667e74Sjose borrego if (inet_ntop(AF_INET, &ips[i].a_ipv4, ipstr, 5797f667e74Sjose borrego INET_ADDRSTRLEN)) { 5807f667e74Sjose borrego syslog(LOG_DEBUG, "Found %s name server\n", ipstr); 5817f667e74Sjose borrego continue; 5827f667e74Sjose borrego } 5837f667e74Sjose borrego ips[i].a_family = AF_INET6; 5847f667e74Sjose borrego bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv6, IPV6_ADDR_LEN); 5857f667e74Sjose borrego if (inet_ntop(AF_INET6, &ips[i].a_ipv6, ipstr, 5867f667e74Sjose borrego INET6_ADDRSTRLEN)) { 5877f667e74Sjose borrego syslog(LOG_DEBUG, "Found %s name server\n", ipstr); 5887f667e74Sjose borrego } 5897b59d02dSjb } 5907b59d02dSjb res_ndestroy(&res_state); 5917b59d02dSjb return (i); 5927b59d02dSjb } 59329bd2886SAlan Wright 5948d7e4166Sjose borrego /* 5958d7e4166Sjose borrego * smb_gethostbyname 5968d7e4166Sjose borrego * 5978d7e4166Sjose borrego * Looks up a host by the given name. The host entry can come 5988d7e4166Sjose borrego * from any of the sources for hosts specified in the 5998d7e4166Sjose borrego * /etc/nsswitch.conf and the NetBIOS cache. 6008d7e4166Sjose borrego * 6018d7e4166Sjose borrego * XXX Invokes nbt_name_resolve API once the NBTD is integrated 6028d7e4166Sjose borrego * to look in the NetBIOS cache if getipnodebyname fails. 6038d7e4166Sjose borrego * 6048d7e4166Sjose borrego * Caller should invoke freehostent to free the returned hostent. 6058d7e4166Sjose borrego */ 6068d7e4166Sjose borrego struct hostent * 6078d7e4166Sjose borrego smb_gethostbyname(const char *name, int *err_num) 6088d7e4166Sjose borrego { 6098d7e4166Sjose borrego struct hostent *h; 6108d7e4166Sjose borrego 6118d7e4166Sjose borrego h = getipnodebyname(name, AF_INET, 0, err_num); 6127f667e74Sjose borrego if ((h == NULL) || h->h_length != INADDRSZ) 6137f667e74Sjose borrego h = getipnodebyname(name, AF_INET6, AI_DEFAULT, err_num); 6148d7e4166Sjose borrego return (h); 6158d7e4166Sjose borrego } 6168d7e4166Sjose borrego 6178d7e4166Sjose borrego /* 6188d7e4166Sjose borrego * smb_gethostbyaddr 6198d7e4166Sjose borrego * 6208d7e4166Sjose borrego * Looks up a host by the given IP address. The host entry can come 6218d7e4166Sjose borrego * from any of the sources for hosts specified in the 6228d7e4166Sjose borrego * /etc/nsswitch.conf and the NetBIOS cache. 6238d7e4166Sjose borrego * 6248d7e4166Sjose borrego * XXX Invokes nbt API to resolve name by IP once the NBTD is integrated 6258d7e4166Sjose borrego * to look in the NetBIOS cache if getipnodebyaddr fails. 6268d7e4166Sjose borrego * 6278d7e4166Sjose borrego * Caller should invoke freehostent to free the returned hostent. 6288d7e4166Sjose borrego */ 6298d7e4166Sjose borrego struct hostent * 6308d7e4166Sjose borrego smb_gethostbyaddr(const char *addr, int len, int type, int *err_num) 6318d7e4166Sjose borrego { 6328d7e4166Sjose borrego struct hostent *h; 6338d7e4166Sjose borrego 6348d7e4166Sjose borrego h = getipnodebyaddr(addr, len, type, err_num); 6358d7e4166Sjose borrego 6368d7e4166Sjose borrego return (h); 6378d7e4166Sjose borrego } 638