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