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*a90cf9f2SGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw #include <sys/types.h> 2712b65585SGordon Ross #include <sys/sockio.h> 2812b65585SGordon Ross #include <sys/socket.h> 2912b65585SGordon Ross #include <sys/utsname.h> 3012b65585SGordon Ross 31da6c28aaSamw #include <stdarg.h> 32da6c28aaSamw #include <unistd.h> 33da6c28aaSamw #include <stdlib.h> 34da6c28aaSamw #include <time.h> 35da6c28aaSamw #include <synch.h> 36da6c28aaSamw #include <syslog.h> 37da6c28aaSamw #include <string.h> 38da6c28aaSamw #include <strings.h> 39da6c28aaSamw #include <errno.h> 40da6c28aaSamw #include <net/if.h> 41da6c28aaSamw #include <netdb.h> 42dc20a302Sas200622 #include <netinet/in.h> 43dc20a302Sas200622 #include <arpa/nameser.h> 44dc20a302Sas200622 #include <resolv.h> 4512b65585SGordon Ross 46da6c28aaSamw #include <smbsrv/smbinfo.h> 47da6c28aaSamw #include <smbsrv/netbios.h> 48da6c28aaSamw #include <smbsrv/libsmb.h> 4912b65585SGordon Ross #include <assert.h> 50da6c28aaSamw 51faa1795aSjb150015 static mutex_t seqnum_mtx; 52da6c28aaSamw 53eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States /* 54a0aa776eSAlan Wright * IPC connection information that may be passed to the SMB Redirector. 55a0aa776eSAlan Wright */ 56a0aa776eSAlan Wright typedef struct { 57a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN]; 58a0aa776eSAlan Wright uint8_t passwd[SMBAUTH_HASH_SZ]; 59a0aa776eSAlan Wright } smb_ipc_t; 60a0aa776eSAlan Wright 61a0aa776eSAlan Wright static smb_ipc_t ipc_info; 62a0aa776eSAlan Wright static smb_ipc_t ipc_orig_info; 63a0aa776eSAlan Wright static rwlock_t smb_ipc_lock; 64a0aa776eSAlan Wright 65a0aa776eSAlan Wright /* 66*a90cf9f2SGordon Ross * These three parameters are all related: 67*a90cf9f2SGordon Ross * skc_initial_credits 68*a90cf9f2SGordon Ross * skc_maximum_credits 69*a90cf9f2SGordon Ross * skc_maxworkers (max worker threads) 70*a90cf9f2SGordon Ross * They must be in non-decreasing order. Get the values in order: 71*a90cf9f2SGordon Ross * maxworkers, maximum_credits, initial_credits 72*a90cf9f2SGordon Ross * enforcing maximum values and relations as we go. Then in the 73*a90cf9f2SGordon Ross * opposite order check minimum values and relations. 74*a90cf9f2SGordon Ross * 75*a90cf9f2SGordon Ross * smb_config_getnum puts a zero in the &citem if it fails getting 76*a90cf9f2SGordon Ross * the parameter value. When fetch parameters for which zero is OK, 77*a90cf9f2SGordon Ross * the return code is intentionally ignored. 78eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States */ 79da6c28aaSamw void 80da6c28aaSamw smb_load_kconfig(smb_kmod_cfg_t *kcfg) 81da6c28aaSamw { 8212b65585SGordon Ross struct utsname uts; 83dc20a302Sas200622 int64_t citem; 84*a90cf9f2SGordon Ross int rc; 85dc20a302Sas200622 86da6c28aaSamw bzero(kcfg, sizeof (smb_kmod_cfg_t)); 87da6c28aaSamw 88*a90cf9f2SGordon Ross /* 89*a90cf9f2SGordon Ross * skc_maxworkers (max. no. of taskq worker threads) 90*a90cf9f2SGordon Ross */ 91*a90cf9f2SGordon Ross rc = smb_config_getnum(SMB_CI_MAX_WORKERS, &citem); 92*a90cf9f2SGordon Ross if (rc != SMBD_SMF_OK) 93*a90cf9f2SGordon Ross citem = SMB_PI_MAX_WORKERS_DEF; 94*a90cf9f2SGordon Ross if (citem > SMB_PI_MAX_WORKERS_MAX) 95*a90cf9f2SGordon Ross citem = SMB_PI_MAX_WORKERS_MAX; 96dc20a302Sas200622 kcfg->skc_maxworkers = (uint32_t)citem; 97*a90cf9f2SGordon Ross 98*a90cf9f2SGordon Ross /* 99*a90cf9f2SGordon Ross * The largest number of credits we let a single client have. 100*a90cf9f2SGordon Ross * It never makes sense for this to be > max_workers 101*a90cf9f2SGordon Ross */ 102*a90cf9f2SGordon Ross rc = smb_config_getnum(SMB_CI_MAXIMUM_CREDITS, &citem); 103*a90cf9f2SGordon Ross if (rc != SMBD_SMF_OK) 104*a90cf9f2SGordon Ross citem = SMB_PI_MAXIMUM_CREDITS_DEF; 105*a90cf9f2SGordon Ross if (citem > SMB_PI_MAXIMUM_CREDITS_MAX) 106*a90cf9f2SGordon Ross citem = SMB_PI_MAXIMUM_CREDITS_MAX; 107*a90cf9f2SGordon Ross kcfg->skc_maximum_credits = (uint16_t)citem; 108*a90cf9f2SGordon Ross if (kcfg->skc_maximum_credits > kcfg->skc_maxworkers) 109*a90cf9f2SGordon Ross kcfg->skc_maximum_credits = (uint16_t)kcfg->skc_maxworkers; 110*a90cf9f2SGordon Ross 111*a90cf9f2SGordon Ross /* 112*a90cf9f2SGordon Ross * The number of credits we give a client initially. 113*a90cf9f2SGordon Ross * Should be enough for a "light" workload, as the 114*a90cf9f2SGordon Ross * client will request additional credits when the 115*a90cf9f2SGordon Ross * workload increases. Must be <= maximum_credits. 116*a90cf9f2SGordon Ross */ 117*a90cf9f2SGordon Ross rc = smb_config_getnum(SMB_CI_INITIAL_CREDITS, &citem); 118*a90cf9f2SGordon Ross if (rc != SMBD_SMF_OK) 119*a90cf9f2SGordon Ross citem = SMB_PI_INITIAL_CREDITS_DEF; 120*a90cf9f2SGordon Ross if (citem > SMB_PI_INITIAL_CREDITS_MAX) 121*a90cf9f2SGordon Ross citem = SMB_PI_INITIAL_CREDITS_MAX; 122*a90cf9f2SGordon Ross kcfg->skc_initial_credits = (uint16_t)citem; 123*a90cf9f2SGordon Ross if (kcfg->skc_initial_credits > kcfg->skc_maximum_credits) 124*a90cf9f2SGordon Ross kcfg->skc_initial_credits = kcfg->skc_maximum_credits; 125*a90cf9f2SGordon Ross 126*a90cf9f2SGordon Ross /* 127*a90cf9f2SGordon Ross * Now enforce minimums, smaller to larger. 128*a90cf9f2SGordon Ross */ 129*a90cf9f2SGordon Ross if (kcfg->skc_initial_credits < SMB_PI_INITIAL_CREDITS_MIN) 130*a90cf9f2SGordon Ross kcfg->skc_initial_credits = SMB_PI_INITIAL_CREDITS_MIN; 131*a90cf9f2SGordon Ross 132*a90cf9f2SGordon Ross if (kcfg->skc_maximum_credits < SMB_PI_MAXIMUM_CREDITS_MIN) 133*a90cf9f2SGordon Ross kcfg->skc_maximum_credits = SMB_PI_MAXIMUM_CREDITS_MIN; 134*a90cf9f2SGordon Ross if (kcfg->skc_maximum_credits < kcfg->skc_initial_credits) 135*a90cf9f2SGordon Ross kcfg->skc_maximum_credits = kcfg->skc_initial_credits; 136*a90cf9f2SGordon Ross 137*a90cf9f2SGordon Ross if (kcfg->skc_maxworkers < SMB_PI_MAX_WORKERS_MIN) 138*a90cf9f2SGordon Ross kcfg->skc_maxworkers = SMB_PI_MAX_WORKERS_MIN; 139*a90cf9f2SGordon Ross if (kcfg->skc_maxworkers < kcfg->skc_maximum_credits) 140*a90cf9f2SGordon Ross kcfg->skc_maxworkers = kcfg->skc_maximum_credits; 141eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 142dc20a302Sas200622 (void) smb_config_getnum(SMB_CI_KEEPALIVE, &citem); 143dc20a302Sas200622 kcfg->skc_keepalive = (uint32_t)citem; 144da6c28aaSamw if ((kcfg->skc_keepalive != 0) && 145da6c28aaSamw (kcfg->skc_keepalive < SMB_PI_KEEP_ALIVE_MIN)) 146da6c28aaSamw kcfg->skc_keepalive = SMB_PI_KEEP_ALIVE_MIN; 147da6c28aaSamw 148dc20a302Sas200622 (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &citem); 149dc20a302Sas200622 kcfg->skc_maxconnections = (uint32_t)citem; 150dc20a302Sas200622 kcfg->skc_restrict_anon = smb_config_getbool(SMB_CI_RESTRICT_ANON); 151dc20a302Sas200622 kcfg->skc_signing_enable = smb_config_getbool(SMB_CI_SIGNING_ENABLE); 152dc20a302Sas200622 kcfg->skc_signing_required = smb_config_getbool(SMB_CI_SIGNING_REQD); 15383d2dfe6SGordon Ross kcfg->skc_netbios_enable = smb_config_getbool(SMB_CI_NETBIOS_ENABLE); 1547f667e74Sjose borrego kcfg->skc_ipv6_enable = smb_config_getbool(SMB_CI_IPV6_ENABLE); 155cb174861Sjoyce mcintosh kcfg->skc_print_enable = smb_config_getbool(SMB_CI_PRINT_ENABLE); 156dc20a302Sas200622 kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE); 157dc20a302Sas200622 kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE); 1585f1ef25cSAram Hăvărneanu kcfg->skc_traverse_mounts = smb_config_getbool(SMB_CI_TRAVERSE_MOUNTS); 159*a90cf9f2SGordon Ross kcfg->skc_max_protocol = smb_config_get_max_protocol(); 160da6c28aaSamw kcfg->skc_secmode = smb_config_get_secmode(); 161*a90cf9f2SGordon Ross 162b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getdomainname(kcfg->skc_nbdomain, 163b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_nbdomain)); 164b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getfqdomainname(kcfg->skc_fqdn, 165b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_fqdn)); 166b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getnetbiosname(kcfg->skc_hostname, 167b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_hostname)); 168dc20a302Sas200622 (void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment, 169da6c28aaSamw sizeof (kcfg->skc_system_comment)); 1709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_config_get_version(&kcfg->skc_version); 171148c5f43SAlan Wright kcfg->skc_execflags = smb_config_get_execinfo(NULL, NULL, 0); 17212b65585SGordon Ross if (smb_config_get_localuuid(kcfg->skc_machine_uuid) < 0) { 17312b65585SGordon Ross syslog(LOG_ERR, "smb_load_kconfig: no machine_uuid"); 17412b65585SGordon Ross uuid_generate_time(kcfg->skc_machine_uuid); 17512b65585SGordon Ross } 17612b65585SGordon Ross /* skc_negtok, skc_negtok_len: see smbd_authsvc.c */ 17712b65585SGordon Ross 17812b65585SGordon Ross (void) uname(&uts); 17912b65585SGordon Ross (void) snprintf(kcfg->skc_native_os, sizeof (kcfg->skc_native_os), 18012b65585SGordon Ross "%s %s %s", uts.sysname, uts.release, uts.version); 18112b65585SGordon Ross 18212b65585SGordon Ross (void) strlcpy(kcfg->skc_native_lm, "Native SMB service", 18312b65585SGordon Ross sizeof (kcfg->skc_native_lm)); 184da6c28aaSamw } 185da6c28aaSamw 186da6c28aaSamw /* 187da6c28aaSamw * Get the current system NetBIOS name. The hostname is truncated at 188da6c28aaSamw * the first `.` or 15 bytes, whichever occurs first, and converted 189da6c28aaSamw * to uppercase (by smb_gethostname). Text that appears after the 190da6c28aaSamw * first '.' is considered to be part of the NetBIOS scope. 191da6c28aaSamw * 192da6c28aaSamw * Returns 0 on success, otherwise -1 to indicate an error. 193da6c28aaSamw */ 194da6c28aaSamw int 195da6c28aaSamw smb_getnetbiosname(char *buf, size_t buflen) 196da6c28aaSamw { 1979fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(buf, buflen, SMB_CASE_UPPER) != 0) 198da6c28aaSamw return (-1); 199da6c28aaSamw 200da6c28aaSamw if (buflen >= NETBIOS_NAME_SZ) 201da6c28aaSamw buf[NETBIOS_NAME_SZ - 1] = '\0'; 202da6c28aaSamw 203da6c28aaSamw return (0); 204da6c28aaSamw } 205da6c28aaSamw 206da6c28aaSamw /* 207b89a8333Snatalie li - Sun Microsystems - Irvine United States * Get the SAM account of the current system. 208b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns 0 on success, otherwise, -1 to indicate an error. 209b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 210b89a8333Snatalie li - Sun Microsystems - Irvine United States int 211b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_getsamaccount(char *buf, size_t buflen) 212b89a8333Snatalie li - Sun Microsystems - Irvine United States { 213b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getnetbiosname(buf, buflen - 1) != 0) 214b89a8333Snatalie li - Sun Microsystems - Irvine United States return (-1); 215b89a8333Snatalie li - Sun Microsystems - Irvine United States 216b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcat(buf, "$", buflen); 217b89a8333Snatalie li - Sun Microsystems - Irvine United States return (0); 218b89a8333Snatalie li - Sun Microsystems - Irvine United States } 219b89a8333Snatalie li - Sun Microsystems - Irvine United States 220b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 221da6c28aaSamw * Get the current system node name. The returned name is guaranteed 222da6c28aaSamw * to be null-terminated (gethostname may not null terminate the name). 223da6c28aaSamw * If the hostname has been fully-qualified for some reason, the domain 2249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * part will be removed. The returned hostname is converted to the 2259fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * specified case (lower, upper, or preserved). 226da6c28aaSamw * 227da6c28aaSamw * If gethostname fails, the returned buffer will contain an empty 228da6c28aaSamw * string. 229da6c28aaSamw */ 230da6c28aaSamw int 2319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_gethostname(char *buf, size_t buflen, smb_caseconv_t which) 232da6c28aaSamw { 233da6c28aaSamw char *p; 234da6c28aaSamw 235da6c28aaSamw if (buf == NULL || buflen == 0) 236da6c28aaSamw return (-1); 237da6c28aaSamw 238da6c28aaSamw if (gethostname(buf, buflen) != 0) { 239da6c28aaSamw *buf = '\0'; 240da6c28aaSamw return (-1); 241da6c28aaSamw } 242da6c28aaSamw 243da6c28aaSamw buf[buflen - 1] = '\0'; 244da6c28aaSamw 245da6c28aaSamw if ((p = strchr(buf, '.')) != NULL) 246da6c28aaSamw *p = '\0'; 247da6c28aaSamw 2489fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States switch (which) { 2499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_LOWER: 2509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_strlwr(buf); 2519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 2529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_UPPER: 254bbf6f00cSJordan Brown (void) smb_strupr(buf); 2559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 2569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_PRESERVE: 2589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States default: 2599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 2609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 261da6c28aaSamw 262da6c28aaSamw return (0); 263da6c28aaSamw } 264da6c28aaSamw 265da6c28aaSamw /* 2669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Obtain the fully-qualified name for this machine in lower case. If 2679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * the hostname is fully-qualified, accept it. Otherwise, try to find an 2689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * appropriate domain name to append to the hostname. 269da6c28aaSamw */ 270da6c28aaSamw int 271da6c28aaSamw smb_getfqhostname(char *buf, size_t buflen) 272da6c28aaSamw { 273da6c28aaSamw char hostname[MAXHOSTNAMELEN]; 274da6c28aaSamw char domain[MAXHOSTNAMELEN]; 275da6c28aaSamw 276da6c28aaSamw hostname[0] = '\0'; 277da6c28aaSamw domain[0] = '\0'; 278da6c28aaSamw 2799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(hostname, MAXHOSTNAMELEN, 2809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_CASE_LOWER) != 0) 281da6c28aaSamw return (-1); 282da6c28aaSamw 283dc20a302Sas200622 if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) 284da6c28aaSamw return (-1); 285da6c28aaSamw 286da6c28aaSamw if (hostname[0] == '\0') 287da6c28aaSamw return (-1); 288da6c28aaSamw 289da6c28aaSamw if (domain[0] == '\0') { 290da6c28aaSamw (void) strlcpy(buf, hostname, buflen); 291da6c28aaSamw return (0); 292da6c28aaSamw } 293da6c28aaSamw 294da6c28aaSamw (void) snprintf(buf, buflen, "%s.%s", hostname, domain); 295da6c28aaSamw return (0); 296da6c28aaSamw } 297da6c28aaSamw 298da6c28aaSamw /* 299dc20a302Sas200622 * smb_getdomainname 300dc20a302Sas200622 * 301dc20a302Sas200622 * Returns NETBIOS name of the domain if the system is in domain 302dc20a302Sas200622 * mode. Or returns workgroup name if the system is in workgroup 303dc20a302Sas200622 * mode. 304dc20a302Sas200622 */ 305dc20a302Sas200622 int 306dc20a302Sas200622 smb_getdomainname(char *buf, size_t buflen) 307dc20a302Sas200622 { 308dc20a302Sas200622 int rc; 309dc20a302Sas200622 310dc20a302Sas200622 if (buf == NULL || buflen == 0) 311dc20a302Sas200622 return (-1); 312dc20a302Sas200622 313dc20a302Sas200622 *buf = '\0'; 3148d7e4166Sjose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, buf, buflen); 315dc20a302Sas200622 3168d7e4166Sjose borrego if ((rc != SMBD_SMF_OK) || (*buf == '\0')) 317dc20a302Sas200622 return (-1); 318dc20a302Sas200622 319dc20a302Sas200622 return (0); 320dc20a302Sas200622 } 321dc20a302Sas200622 322dc20a302Sas200622 /* 323dc20a302Sas200622 * smb_getfqdomainname 324dc20a302Sas200622 * 3258d7e4166Sjose borrego * In the system is in domain mode, the dns_domain property value 3268d7e4166Sjose borrego * is returned. Otherwise, it returns the local domain obtained via 3278d7e4166Sjose borrego * resolver. 328dc20a302Sas200622 * 329dc20a302Sas200622 * Returns 0 upon success. Otherwise, returns -1. 330dc20a302Sas200622 */ 331dc20a302Sas200622 int 332dc20a302Sas200622 smb_getfqdomainname(char *buf, size_t buflen) 333dc20a302Sas200622 { 3348d7e4166Sjose borrego struct __res_state res_state; 3358d7e4166Sjose borrego int rc; 336dc20a302Sas200622 337dc20a302Sas200622 if (buf == NULL || buflen == 0) 338dc20a302Sas200622 return (-1); 339dc20a302Sas200622 340dc20a302Sas200622 *buf = '\0'; 341dc20a302Sas200622 if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { 3428d7e4166Sjose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_FQDN, buf, buflen); 343dc20a302Sas200622 3448d7e4166Sjose borrego if ((rc != SMBD_SMF_OK) || (*buf == '\0')) 3458d7e4166Sjose borrego return (-1); 3468d7e4166Sjose borrego } else { 3478d7e4166Sjose borrego bzero(&res_state, sizeof (struct __res_state)); 3488d7e4166Sjose borrego if (res_ninit(&res_state)) 349dc20a302Sas200622 return (-1); 350dc20a302Sas200622 3518d7e4166Sjose borrego if (*res_state.defdname == '\0') { 3528d7e4166Sjose borrego res_ndestroy(&res_state); 3538d7e4166Sjose borrego return (-1); 354dc20a302Sas200622 } 3558d7e4166Sjose borrego 3568d7e4166Sjose borrego (void) strlcpy(buf, res_state.defdname, buflen); 3578d7e4166Sjose borrego res_ndestroy(&res_state); 3588d7e4166Sjose borrego rc = 0; 359dc20a302Sas200622 } 360dc20a302Sas200622 361dc20a302Sas200622 return (rc); 362dc20a302Sas200622 } 363dc20a302Sas200622 364dc20a302Sas200622 365faa1795aSjb150015 /* 366faa1795aSjb150015 * smb_set_machine_passwd 367faa1795aSjb150015 * 368faa1795aSjb150015 * This function should be used when setting the machine password property. 369faa1795aSjb150015 * The associated sequence number is incremented. 370faa1795aSjb150015 */ 371faa1795aSjb150015 static int 372faa1795aSjb150015 smb_set_machine_passwd(char *passwd) 373faa1795aSjb150015 { 374faa1795aSjb150015 int64_t num; 375faa1795aSjb150015 int rc = -1; 376faa1795aSjb150015 377faa1795aSjb150015 if (smb_config_set(SMB_CI_MACHINE_PASSWD, passwd) != SMBD_SMF_OK) 378faa1795aSjb150015 return (-1); 379faa1795aSjb150015 380faa1795aSjb150015 (void) mutex_lock(&seqnum_mtx); 381faa1795aSjb150015 (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num); 382faa1795aSjb150015 if (smb_config_setnum(SMB_CI_KPASSWD_SEQNUM, ++num) 383faa1795aSjb150015 == SMBD_SMF_OK) 384faa1795aSjb150015 rc = 0; 385faa1795aSjb150015 (void) mutex_unlock(&seqnum_mtx); 386faa1795aSjb150015 return (rc); 387faa1795aSjb150015 } 388faa1795aSjb150015 389a0aa776eSAlan Wright static int 390a0aa776eSAlan Wright smb_get_machine_passwd(uint8_t *buf, size_t buflen) 391a0aa776eSAlan Wright { 392a0aa776eSAlan Wright char pwd[SMB_PASSWD_MAXLEN + 1]; 393a0aa776eSAlan Wright int rc; 394a0aa776eSAlan Wright 395a0aa776eSAlan Wright if (buflen < SMBAUTH_HASH_SZ) 396a0aa776eSAlan Wright return (-1); 397a0aa776eSAlan Wright 398a0aa776eSAlan Wright rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd)); 399a0aa776eSAlan Wright if ((rc != SMBD_SMF_OK) || *pwd == '\0') 400a0aa776eSAlan Wright return (-1); 401a0aa776eSAlan Wright 402a0aa776eSAlan Wright if (smb_auth_ntlm_hash(pwd, buf) != 0) 403a0aa776eSAlan Wright return (-1); 404a0aa776eSAlan Wright 405a0aa776eSAlan Wright return (rc); 406a0aa776eSAlan Wright } 407a0aa776eSAlan Wright 408a0aa776eSAlan Wright /* 409a0aa776eSAlan Wright * Set up IPC connection credentials. 410a0aa776eSAlan Wright */ 411a0aa776eSAlan Wright void 412a0aa776eSAlan Wright smb_ipc_init(void) 413a0aa776eSAlan Wright { 414a0aa776eSAlan Wright int rc; 415a0aa776eSAlan Wright 416a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 417a0aa776eSAlan Wright bzero(&ipc_info, sizeof (smb_ipc_t)); 418a0aa776eSAlan Wright bzero(&ipc_orig_info, sizeof (smb_ipc_t)); 419a0aa776eSAlan Wright 420a0aa776eSAlan Wright (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); 421a0aa776eSAlan Wright rc = smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ); 422a0aa776eSAlan Wright if (rc != 0) 423a0aa776eSAlan Wright *ipc_info.passwd = 0; 424a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 425a0aa776eSAlan Wright 426a0aa776eSAlan Wright } 427a0aa776eSAlan Wright 428a0aa776eSAlan Wright /* 429a0aa776eSAlan Wright * Set the IPC username and password hash in memory. If the domain 430a0aa776eSAlan Wright * join succeeds, the credentials will be committed for use with 431a0aa776eSAlan Wright * authenticated IPC. Otherwise, they should be rolled back. 432a0aa776eSAlan Wright */ 433a0aa776eSAlan Wright void 434a0aa776eSAlan Wright smb_ipc_set(char *plain_user, uint8_t *passwd_hash) 435a0aa776eSAlan Wright { 436a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 437a0aa776eSAlan Wright (void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user)); 438a0aa776eSAlan Wright (void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ); 439a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 440a0aa776eSAlan Wright 441a0aa776eSAlan Wright } 442a0aa776eSAlan Wright 443a0aa776eSAlan Wright /* 444a0aa776eSAlan Wright * Save the host credentials to be used for authenticated IPC. 445a0aa776eSAlan Wright * The credentials are also saved to the original IPC info as 446a0aa776eSAlan Wright * rollback data in case the join domain process fails later. 447a0aa776eSAlan Wright */ 448a0aa776eSAlan Wright void 449a0aa776eSAlan Wright smb_ipc_commit(void) 450a0aa776eSAlan Wright { 451a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 452a0aa776eSAlan Wright (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); 453a0aa776eSAlan Wright (void) smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ); 454a0aa776eSAlan Wright (void) memcpy(&ipc_orig_info, &ipc_info, sizeof (smb_ipc_t)); 455a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 456a0aa776eSAlan Wright } 457a0aa776eSAlan Wright 458a0aa776eSAlan Wright /* 459a0aa776eSAlan Wright * Restore the original credentials 460a0aa776eSAlan Wright */ 461a0aa776eSAlan Wright void 462a0aa776eSAlan Wright smb_ipc_rollback(void) 463a0aa776eSAlan Wright { 464a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 465a0aa776eSAlan Wright (void) strlcpy(ipc_info.user, ipc_orig_info.user, 466a0aa776eSAlan Wright sizeof (ipc_info.user)); 467a0aa776eSAlan Wright (void) memcpy(ipc_info.passwd, ipc_orig_info.passwd, 468a0aa776eSAlan Wright sizeof (ipc_info.passwd)); 469a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 470a0aa776eSAlan Wright } 471a0aa776eSAlan Wright 472a0aa776eSAlan Wright void 473a0aa776eSAlan Wright smb_ipc_get_user(char *buf, size_t buflen) 474a0aa776eSAlan Wright { 475a0aa776eSAlan Wright (void) rw_rdlock(&smb_ipc_lock); 476a0aa776eSAlan Wright (void) strlcpy(buf, ipc_info.user, buflen); 477a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 478a0aa776eSAlan Wright } 479a0aa776eSAlan Wright 480a0aa776eSAlan Wright void 481a0aa776eSAlan Wright smb_ipc_get_passwd(uint8_t *buf, size_t buflen) 482a0aa776eSAlan Wright { 483a0aa776eSAlan Wright if (buflen < SMBAUTH_HASH_SZ) 484a0aa776eSAlan Wright return; 485a0aa776eSAlan Wright 486a0aa776eSAlan Wright (void) rw_rdlock(&smb_ipc_lock); 487a0aa776eSAlan Wright (void) memcpy(buf, ipc_info.passwd, SMBAUTH_HASH_SZ); 488a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 489a0aa776eSAlan Wright } 490a0aa776eSAlan Wright 491faa1795aSjb150015 /* 492faa1795aSjb150015 * smb_match_netlogon_seqnum 493faa1795aSjb150015 * 494faa1795aSjb150015 * A sequence number is associated with each machine password property 495faa1795aSjb150015 * update and the netlogon credential chain setup. If the 496faa1795aSjb150015 * sequence numbers don't match, a NETLOGON credential chain 497faa1795aSjb150015 * establishment is required. 498faa1795aSjb150015 * 499faa1795aSjb150015 * Returns 0 if kpasswd_seqnum equals to netlogon_seqnum. Otherwise, 500faa1795aSjb150015 * returns -1. 501faa1795aSjb150015 */ 502faa1795aSjb150015 boolean_t 503faa1795aSjb150015 smb_match_netlogon_seqnum(void) 504faa1795aSjb150015 { 505faa1795aSjb150015 int64_t setpasswd_seqnum; 506faa1795aSjb150015 int64_t netlogon_seqnum; 507faa1795aSjb150015 508faa1795aSjb150015 (void) mutex_lock(&seqnum_mtx); 509faa1795aSjb150015 (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &setpasswd_seqnum); 510faa1795aSjb150015 (void) smb_config_getnum(SMB_CI_NETLOGON_SEQNUM, &netlogon_seqnum); 511faa1795aSjb150015 (void) mutex_unlock(&seqnum_mtx); 512faa1795aSjb150015 return (setpasswd_seqnum == netlogon_seqnum); 513faa1795aSjb150015 } 514faa1795aSjb150015 515faa1795aSjb150015 /* 516faa1795aSjb150015 * smb_setdomainprops 517faa1795aSjb150015 * 518faa1795aSjb150015 * This function should be called after joining an AD to 519faa1795aSjb150015 * set all the domain related SMF properties. 520faa1795aSjb150015 * 521faa1795aSjb150015 * The kpasswd_domain property is the AD domain to which the system 522faa1795aSjb150015 * is joined via kclient. If this function is invoked by the SMB 523faa1795aSjb150015 * daemon, fqdn should be set to NULL. 524faa1795aSjb150015 */ 525faa1795aSjb150015 int 526faa1795aSjb150015 smb_setdomainprops(char *fqdn, char *server, char *passwd) 527faa1795aSjb150015 { 528faa1795aSjb150015 if (server == NULL || passwd == NULL) 529faa1795aSjb150015 return (-1); 530faa1795aSjb150015 531faa1795aSjb150015 if ((*server == '\0') || (*passwd == '\0')) 532faa1795aSjb150015 return (-1); 533faa1795aSjb150015 534faa1795aSjb150015 if (fqdn && (smb_config_set(SMB_CI_KPASSWD_DOMAIN, fqdn) != 0)) 535faa1795aSjb150015 return (-1); 536faa1795aSjb150015 537faa1795aSjb150015 if (smb_config_set(SMB_CI_KPASSWD_SRV, server) != 0) 538faa1795aSjb150015 return (-1); 539faa1795aSjb150015 540faa1795aSjb150015 if (smb_set_machine_passwd(passwd) != 0) { 541faa1795aSjb150015 syslog(LOG_ERR, "smb_setdomainprops: failed to set" 542faa1795aSjb150015 " machine account password"); 543faa1795aSjb150015 return (-1); 544faa1795aSjb150015 } 545faa1795aSjb150015 546faa1795aSjb150015 /* 547faa1795aSjb150015 * If we successfully create a trust account, we mark 548faa1795aSjb150015 * ourselves as a domain member in the environment so 549faa1795aSjb150015 * that we use the SAMLOGON version of the NETLOGON 550faa1795aSjb150015 * PDC location protocol. 551faa1795aSjb150015 */ 552faa1795aSjb150015 (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_TRUE); 553faa1795aSjb150015 554faa1795aSjb150015 return (0); 555faa1795aSjb150015 } 556faa1795aSjb150015 557faa1795aSjb150015 /* 558faa1795aSjb150015 * smb_update_netlogon_seqnum 559faa1795aSjb150015 * 560faa1795aSjb150015 * This function should only be called upon a successful netlogon 561faa1795aSjb150015 * credential chain establishment to set the sequence number of the 562faa1795aSjb150015 * netlogon to match with that of the kpasswd. 563faa1795aSjb150015 */ 564faa1795aSjb150015 void 565faa1795aSjb150015 smb_update_netlogon_seqnum(void) 566faa1795aSjb150015 { 567faa1795aSjb150015 int64_t num; 568faa1795aSjb150015 569faa1795aSjb150015 (void) mutex_lock(&seqnum_mtx); 570faa1795aSjb150015 (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num); 571faa1795aSjb150015 (void) smb_config_setnum(SMB_CI_NETLOGON_SEQNUM, num); 572faa1795aSjb150015 (void) mutex_unlock(&seqnum_mtx); 573faa1795aSjb150015 } 574faa1795aSjb150015 575dc20a302Sas200622 576dc20a302Sas200622 /* 577da6c28aaSamw * Temporary fbt for dtrace until user space sdt enabled. 578da6c28aaSamw */ 579da6c28aaSamw void 580da6c28aaSamw smb_tracef(const char *fmt, ...) 581da6c28aaSamw { 582da6c28aaSamw va_list ap; 583da6c28aaSamw char buf[128]; 584da6c28aaSamw 585da6c28aaSamw va_start(ap, fmt); 586da6c28aaSamw (void) vsnprintf(buf, 128, fmt, ap); 587da6c28aaSamw va_end(ap); 588da6c28aaSamw 589da6c28aaSamw smb_trace(buf); 590da6c28aaSamw } 591da6c28aaSamw 592da6c28aaSamw /* 593da6c28aaSamw * Temporary fbt for dtrace until user space sdt enabled. 594b819cea2SGordon Ross * 595b819cea2SGordon Ross * This function is designed to be used with dtrace, i.e. see: 596b819cea2SGordon Ross * usr/src/cmd/smbsrv/dtrace/smbd-all.d 597b819cea2SGordon Ross * 598b819cea2SGordon Ross * Outside of dtrace, the messages passed to this function usually 599b819cea2SGordon Ross * lack sufficient context to be useful, so we don't log them. 600da6c28aaSamw */ 601b819cea2SGordon Ross /* ARGSUSED */ 602da6c28aaSamw void 603da6c28aaSamw smb_trace(const char *s) 604da6c28aaSamw { 605da6c28aaSamw } 6067b59d02dSjb150015 6077b59d02dSjb150015 /* 6087b59d02dSjb150015 * smb_tonetbiosname 6097b59d02dSjb150015 * 6107b59d02dSjb150015 * Creates a NetBIOS name based on the given name and suffix. 6117b59d02dSjb150015 * NetBIOS name is 15 capital characters, padded with space if needed 6127b59d02dSjb150015 * and the 16th byte is the suffix. 6137b59d02dSjb150015 */ 6147b59d02dSjb150015 void 6157b59d02dSjb150015 smb_tonetbiosname(char *name, char *nb_name, char suffix) 6167b59d02dSjb150015 { 6177b59d02dSjb150015 char tmp_name[NETBIOS_NAME_SZ]; 618bbf6f00cSJordan Brown smb_wchar_t wtmp_name[NETBIOS_NAME_SZ]; 6197b59d02dSjb150015 int len; 6207b59d02dSjb150015 size_t rc; 6217b59d02dSjb150015 6227b59d02dSjb150015 len = 0; 623bbf6f00cSJordan Brown rc = smb_mbstowcs(wtmp_name, (const char *)name, NETBIOS_NAME_SZ); 6247b59d02dSjb150015 6257b59d02dSjb150015 if (rc != (size_t)-1) { 6267b59d02dSjb150015 wtmp_name[NETBIOS_NAME_SZ - 1] = 0; 627bbf6f00cSJordan Brown rc = ucstooem(tmp_name, wtmp_name, NETBIOS_NAME_SZ, 628bbf6f00cSJordan Brown OEM_CPG_850); 6297b59d02dSjb150015 if (rc > 0) 6307b59d02dSjb150015 len = strlen(tmp_name); 6317b59d02dSjb150015 } 6327b59d02dSjb150015 6337b59d02dSjb150015 (void) memset(nb_name, ' ', NETBIOS_NAME_SZ - 1); 6347b59d02dSjb150015 if (len) { 635bbf6f00cSJordan Brown (void) smb_strupr(tmp_name); 6367b59d02dSjb150015 (void) memcpy(nb_name, tmp_name, len); 6377b59d02dSjb150015 } 6387b59d02dSjb150015 nb_name[NETBIOS_NAME_SZ - 1] = suffix; 6397b59d02dSjb150015 } 6407b59d02dSjb150015 6417b59d02dSjb150015 int 6427f667e74Sjose borrego smb_get_nameservers(smb_inaddr_t *ips, int sz) 6437b59d02dSjb150015 { 6447b59d02dSjb150015 union res_sockaddr_union set[MAXNS]; 6457b59d02dSjb150015 int i, cnt; 6467b59d02dSjb150015 struct __res_state res_state; 6477f667e74Sjose borrego char ipstr[INET6_ADDRSTRLEN]; 6487b59d02dSjb150015 6497b59d02dSjb150015 if (ips == NULL) 6507b59d02dSjb150015 return (0); 6517b59d02dSjb150015 6527b59d02dSjb150015 bzero(&res_state, sizeof (struct __res_state)); 6537b59d02dSjb150015 if (res_ninit(&res_state) < 0) 6547b59d02dSjb150015 return (0); 6557b59d02dSjb150015 6567b59d02dSjb150015 cnt = res_getservers(&res_state, set, MAXNS); 6577b59d02dSjb150015 for (i = 0; i < cnt; i++) { 6587b59d02dSjb150015 if (i >= sz) 6597b59d02dSjb150015 break; 6607f667e74Sjose borrego ips[i].a_family = AF_INET; 661b819cea2SGordon Ross bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv4, NS_INADDRSZ); 6627f667e74Sjose borrego if (inet_ntop(AF_INET, &ips[i].a_ipv4, ipstr, 6637f667e74Sjose borrego INET_ADDRSTRLEN)) { 6647f667e74Sjose borrego syslog(LOG_DEBUG, "Found %s name server\n", ipstr); 6657f667e74Sjose borrego continue; 6667b59d02dSjb150015 } 6677f667e74Sjose borrego ips[i].a_family = AF_INET6; 668b819cea2SGordon Ross bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv6, NS_IN6ADDRSZ); 6697f667e74Sjose borrego if (inet_ntop(AF_INET6, &ips[i].a_ipv6, ipstr, 6707f667e74Sjose borrego INET6_ADDRSTRLEN)) { 6717f667e74Sjose borrego syslog(LOG_DEBUG, "Found %s name server\n", ipstr); 6727f667e74Sjose borrego } 6737f667e74Sjose borrego } 6747b59d02dSjb150015 res_ndestroy(&res_state); 6757b59d02dSjb150015 return (i); 6767b59d02dSjb150015 } 67729bd2886SAlan Wright 6788d7e4166Sjose borrego /* 6798d7e4166Sjose borrego * smb_gethostbyname 6808d7e4166Sjose borrego * 6818d7e4166Sjose borrego * Looks up a host by the given name. The host entry can come 6828d7e4166Sjose borrego * from any of the sources for hosts specified in the 6838d7e4166Sjose borrego * /etc/nsswitch.conf and the NetBIOS cache. 6848d7e4166Sjose borrego * 6858d7e4166Sjose borrego * XXX Invokes nbt_name_resolve API once the NBTD is integrated 6868d7e4166Sjose borrego * to look in the NetBIOS cache if getipnodebyname fails. 6878d7e4166Sjose borrego * 6888d7e4166Sjose borrego * Caller should invoke freehostent to free the returned hostent. 6898d7e4166Sjose borrego */ 6908d7e4166Sjose borrego struct hostent * 6918d7e4166Sjose borrego smb_gethostbyname(const char *name, int *err_num) 6928d7e4166Sjose borrego { 6938d7e4166Sjose borrego struct hostent *h; 6948d7e4166Sjose borrego 6958d7e4166Sjose borrego h = getipnodebyname(name, AF_INET, 0, err_num); 6967f667e74Sjose borrego if ((h == NULL) || h->h_length != INADDRSZ) 6977f667e74Sjose borrego h = getipnodebyname(name, AF_INET6, AI_DEFAULT, err_num); 6988d7e4166Sjose borrego return (h); 6998d7e4166Sjose borrego } 7008d7e4166Sjose borrego 7018d7e4166Sjose borrego /* 7028d7e4166Sjose borrego * smb_gethostbyaddr 7038d7e4166Sjose borrego * 7048d7e4166Sjose borrego * Looks up a host by the given IP address. The host entry can come 7058d7e4166Sjose borrego * from any of the sources for hosts specified in the 7068d7e4166Sjose borrego * /etc/nsswitch.conf and the NetBIOS cache. 7078d7e4166Sjose borrego * 7088d7e4166Sjose borrego * XXX Invokes nbt API to resolve name by IP once the NBTD is integrated 7098d7e4166Sjose borrego * to look in the NetBIOS cache if getipnodebyaddr fails. 7108d7e4166Sjose borrego * 7118d7e4166Sjose borrego * Caller should invoke freehostent to free the returned hostent. 7128d7e4166Sjose borrego */ 7138d7e4166Sjose borrego struct hostent * 7148d7e4166Sjose borrego smb_gethostbyaddr(const char *addr, int len, int type, int *err_num) 7158d7e4166Sjose borrego { 7168d7e4166Sjose borrego struct hostent *h; 7178d7e4166Sjose borrego 7188d7e4166Sjose borrego h = getipnodebyaddr(addr, len, type, err_num); 7198d7e4166Sjose borrego 7208d7e4166Sjose borrego return (h); 7218d7e4166Sjose borrego } 722