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