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*ce8560eeSMatt Barden * Copyright 2020 Tintri by DDN, Inc. All rights reserved. 244e065a9fSAlexander Stetsenko * Copyright 2020 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); 160a90cf9f2SGordon Ross kcfg->skc_max_protocol = smb_config_get_max_protocol(); 1613e2c0c09SMatt Barden kcfg->skc_min_protocol = smb_config_get_min_protocol(); 162da6c28aaSamw kcfg->skc_secmode = smb_config_get_secmode(); 1631160dcf7SMatt Barden kcfg->skc_encrypt = smb_config_get_require(SMB_CI_ENCRYPT); 1644e065a9fSAlexander Stetsenko kcfg->skc_encrypt_cipher = smb31_config_get_encrypt_cipher(); 165a90cf9f2SGordon Ross 166b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getdomainname(kcfg->skc_nbdomain, 167b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_nbdomain)); 168b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getfqdomainname(kcfg->skc_fqdn, 169b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_fqdn)); 170b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getnetbiosname(kcfg->skc_hostname, 171b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_hostname)); 172dc20a302Sas (void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment, 173da6c28aaSamw sizeof (kcfg->skc_system_comment)); 1749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_config_get_version(&kcfg->skc_version); 175148c5f43SAlan Wright kcfg->skc_execflags = smb_config_get_execinfo(NULL, NULL, 0); 17612b65585SGordon Ross if (smb_config_get_localuuid(kcfg->skc_machine_uuid) < 0) { 17712b65585SGordon Ross syslog(LOG_ERR, "smb_load_kconfig: no machine_uuid"); 17812b65585SGordon Ross uuid_generate_time(kcfg->skc_machine_uuid); 17912b65585SGordon Ross } 18012b65585SGordon Ross /* skc_negtok, skc_negtok_len: see smbd_authsvc.c */ 18112b65585SGordon Ross 18212b65585SGordon Ross (void) uname(&uts); 18312b65585SGordon Ross (void) snprintf(kcfg->skc_native_os, sizeof (kcfg->skc_native_os), 18412b65585SGordon Ross "%s %s %s", uts.sysname, uts.release, uts.version); 18512b65585SGordon Ross 18612b65585SGordon Ross (void) strlcpy(kcfg->skc_native_lm, "Native SMB service", 18712b65585SGordon Ross sizeof (kcfg->skc_native_lm)); 188da6c28aaSamw } 189da6c28aaSamw 190da6c28aaSamw /* 191da6c28aaSamw * Get the current system NetBIOS name. The hostname is truncated at 192da6c28aaSamw * the first `.` or 15 bytes, whichever occurs first, and converted 193da6c28aaSamw * to uppercase (by smb_gethostname). Text that appears after the 194da6c28aaSamw * first '.' is considered to be part of the NetBIOS scope. 195da6c28aaSamw * 196da6c28aaSamw * Returns 0 on success, otherwise -1 to indicate an error. 197da6c28aaSamw */ 198da6c28aaSamw int 199da6c28aaSamw smb_getnetbiosname(char *buf, size_t buflen) 200da6c28aaSamw { 2019fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(buf, buflen, SMB_CASE_UPPER) != 0) 202da6c28aaSamw return (-1); 203da6c28aaSamw 204da6c28aaSamw if (buflen >= NETBIOS_NAME_SZ) 205da6c28aaSamw buf[NETBIOS_NAME_SZ - 1] = '\0'; 206da6c28aaSamw 207da6c28aaSamw return (0); 208da6c28aaSamw } 209da6c28aaSamw 210b89a8333Snatalie li - Sun Microsystems - Irvine United States /* 211b89a8333Snatalie li - Sun Microsystems - Irvine United States * Get the SAM account of the current system. 212b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns 0 on success, otherwise, -1 to indicate an error. 213b89a8333Snatalie li - Sun Microsystems - Irvine United States */ 214b89a8333Snatalie li - Sun Microsystems - Irvine United States int 215b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_getsamaccount(char *buf, size_t buflen) 216b89a8333Snatalie li - Sun Microsystems - Irvine United States { 217b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getnetbiosname(buf, buflen - 1) != 0) 218b89a8333Snatalie li - Sun Microsystems - Irvine United States return (-1); 219b89a8333Snatalie li - Sun Microsystems - Irvine United States 220b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcat(buf, "$", buflen); 221b89a8333Snatalie li - Sun Microsystems - Irvine United States return (0); 222b89a8333Snatalie li - Sun Microsystems - Irvine United States } 223b89a8333Snatalie li - Sun Microsystems - Irvine United States 224da6c28aaSamw /* 225da6c28aaSamw * Get the current system node name. The returned name is guaranteed 226da6c28aaSamw * to be null-terminated (gethostname may not null terminate the name). 227da6c28aaSamw * If the hostname has been fully-qualified for some reason, the domain 2289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * part will be removed. The returned hostname is converted to the 2299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * specified case (lower, upper, or preserved). 230da6c28aaSamw * 231da6c28aaSamw * If gethostname fails, the returned buffer will contain an empty 232da6c28aaSamw * string. 233da6c28aaSamw */ 234da6c28aaSamw int 2359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_gethostname(char *buf, size_t buflen, smb_caseconv_t which) 236da6c28aaSamw { 237da6c28aaSamw char *p; 238da6c28aaSamw 239da6c28aaSamw if (buf == NULL || buflen == 0) 240da6c28aaSamw return (-1); 241da6c28aaSamw 242da6c28aaSamw if (gethostname(buf, buflen) != 0) { 243da6c28aaSamw *buf = '\0'; 244da6c28aaSamw return (-1); 245da6c28aaSamw } 246da6c28aaSamw 247da6c28aaSamw buf[buflen - 1] = '\0'; 248da6c28aaSamw 249da6c28aaSamw if ((p = strchr(buf, '.')) != NULL) 250da6c28aaSamw *p = '\0'; 251da6c28aaSamw 2529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States switch (which) { 2539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_LOWER: 2549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_strlwr(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_UPPER: 258bbf6f00cSJordan Brown (void) smb_strupr(buf); 2599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 2609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 2619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_PRESERVE: 2629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States default: 2639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break; 2649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States } 265da6c28aaSamw 266da6c28aaSamw return (0); 267da6c28aaSamw } 268da6c28aaSamw 269da6c28aaSamw /* 2709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Obtain the fully-qualified name for this machine in lower case. If 2719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * the hostname is fully-qualified, accept it. Otherwise, try to find an 2729fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * appropriate domain name to append to the hostname. 273da6c28aaSamw */ 274da6c28aaSamw int 275dc20a302Sas smb_getfqhostname(char *buf, size_t buflen) 276da6c28aaSamw { 277dc20a302Sas char hostname[MAXHOSTNAMELEN]; 278dc20a302Sas char domain[MAXHOSTNAMELEN]; 279da6c28aaSamw 280dc20a302Sas hostname[0] = '\0'; 281dc20a302Sas domain[0] = '\0'; 282dc20a302Sas 2839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(hostname, MAXHOSTNAMELEN, 2849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_CASE_LOWER) != 0) 285da6c28aaSamw return (-1); 286da6c28aaSamw 287dc20a302Sas if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) 288dc20a302Sas return (-1); 289dc20a302Sas 290dc20a302Sas if (hostname[0] == '\0') 291dc20a302Sas return (-1); 292da6c28aaSamw 293dc20a302Sas if (domain[0] == '\0') { 294dc20a302Sas (void) strlcpy(buf, hostname, buflen); 295da6c28aaSamw return (0); 296da6c28aaSamw } 297da6c28aaSamw 298dc20a302Sas (void) snprintf(buf, buflen, "%s.%s", hostname, domain); 299dc20a302Sas return (0); 300dc20a302Sas } 301da6c28aaSamw 302da6c28aaSamw /* 303dc20a302Sas * smb_getdomainname 304dc20a302Sas * 305dc20a302Sas * Returns NETBIOS name of the domain if the system is in domain 306dc20a302Sas * mode. Or returns workgroup name if the system is in workgroup 307dc20a302Sas * mode. 308da6c28aaSamw */ 309da6c28aaSamw int 310dc20a302Sas smb_getdomainname(char *buf, size_t buflen) 311da6c28aaSamw { 312dc20a302Sas int rc; 313da6c28aaSamw 314dc20a302Sas if (buf == NULL || buflen == 0) 315dc20a302Sas return (-1); 316da6c28aaSamw 317dc20a302Sas *buf = '\0'; 3188d7e4166Sjose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, buf, buflen); 319dc20a302Sas 3208d7e4166Sjose borrego if ((rc != SMBD_SMF_OK) || (*buf == '\0')) 321da6c28aaSamw return (-1); 322da6c28aaSamw 323dc20a302Sas return (0); 324dc20a302Sas } 325dc20a302Sas 326dc20a302Sas /* 327dc20a302Sas * smb_getfqdomainname 328dc20a302Sas * 3298d7e4166Sjose borrego * In the system is in domain mode, the dns_domain property value 3308d7e4166Sjose borrego * is returned. Otherwise, it returns the local domain obtained via 3318d7e4166Sjose borrego * resolver. 332dc20a302Sas * 333dc20a302Sas * Returns 0 upon success. Otherwise, returns -1. 334dc20a302Sas */ 335dc20a302Sas int 336dc20a302Sas smb_getfqdomainname(char *buf, size_t buflen) 337dc20a302Sas { 3388d7e4166Sjose borrego struct __res_state res_state; 3398d7e4166Sjose borrego int rc; 340dc20a302Sas 341dc20a302Sas if (buf == NULL || buflen == 0) 342dc20a302Sas return (-1); 343dc20a302Sas 344dc20a302Sas *buf = '\0'; 345dc20a302Sas if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { 3468d7e4166Sjose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_FQDN, buf, buflen); 347dc20a302Sas 3488d7e4166Sjose borrego if ((rc != SMBD_SMF_OK) || (*buf == '\0')) 3498d7e4166Sjose borrego return (-1); 3508d7e4166Sjose borrego } else { 3518d7e4166Sjose borrego bzero(&res_state, sizeof (struct __res_state)); 3528d7e4166Sjose borrego if (res_ninit(&res_state)) 353dc20a302Sas return (-1); 354dc20a302Sas 3558d7e4166Sjose borrego if (*res_state.defdname == '\0') { 3568d7e4166Sjose borrego res_ndestroy(&res_state); 3578d7e4166Sjose borrego return (-1); 358dc20a302Sas } 3598d7e4166Sjose borrego 3608d7e4166Sjose borrego (void) strlcpy(buf, res_state.defdname, buflen); 3618d7e4166Sjose borrego res_ndestroy(&res_state); 3628d7e4166Sjose borrego rc = 0; 363dc20a302Sas } 364dc20a302Sas 365dc20a302Sas return (rc); 366da6c28aaSamw } 367da6c28aaSamw 368dc20a302Sas 369faa1795aSjb /* 370faa1795aSjb * smb_set_machine_passwd 371faa1795aSjb * 372faa1795aSjb * This function should be used when setting the machine password property. 373faa1795aSjb * The associated sequence number is incremented. 374faa1795aSjb */ 375faa1795aSjb static int 376faa1795aSjb smb_set_machine_passwd(char *passwd) 377faa1795aSjb { 378faa1795aSjb int64_t num; 379faa1795aSjb int rc = -1; 380faa1795aSjb 381faa1795aSjb if (smb_config_set(SMB_CI_MACHINE_PASSWD, passwd) != SMBD_SMF_OK) 382faa1795aSjb return (-1); 383faa1795aSjb 384faa1795aSjb (void) mutex_lock(&seqnum_mtx); 385faa1795aSjb (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num); 386faa1795aSjb if (smb_config_setnum(SMB_CI_KPASSWD_SEQNUM, ++num) 387faa1795aSjb == SMBD_SMF_OK) 388faa1795aSjb rc = 0; 389faa1795aSjb (void) mutex_unlock(&seqnum_mtx); 390faa1795aSjb return (rc); 391faa1795aSjb } 392faa1795aSjb 393a0aa776eSAlan Wright static int 394a0aa776eSAlan Wright smb_get_machine_passwd(uint8_t *buf, size_t buflen) 395a0aa776eSAlan Wright { 396a0aa776eSAlan Wright char pwd[SMB_PASSWD_MAXLEN + 1]; 397a0aa776eSAlan Wright int rc; 398a0aa776eSAlan Wright 399a0aa776eSAlan Wright if (buflen < SMBAUTH_HASH_SZ) 400a0aa776eSAlan Wright return (-1); 401a0aa776eSAlan Wright 402a0aa776eSAlan Wright rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd)); 403a0aa776eSAlan Wright if ((rc != SMBD_SMF_OK) || *pwd == '\0') 404a0aa776eSAlan Wright return (-1); 405a0aa776eSAlan Wright 406a0aa776eSAlan Wright if (smb_auth_ntlm_hash(pwd, buf) != 0) 407a0aa776eSAlan Wright return (-1); 408a0aa776eSAlan Wright 409a0aa776eSAlan Wright return (rc); 410a0aa776eSAlan Wright } 411a0aa776eSAlan Wright 412a0aa776eSAlan Wright /* 413a0aa776eSAlan Wright * Set up IPC connection credentials. 414a0aa776eSAlan Wright */ 415a0aa776eSAlan Wright void 416a0aa776eSAlan Wright smb_ipc_init(void) 417a0aa776eSAlan Wright { 418a0aa776eSAlan Wright int rc; 419a0aa776eSAlan Wright 420a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 421a0aa776eSAlan Wright bzero(&ipc_info, sizeof (smb_ipc_t)); 422a0aa776eSAlan Wright bzero(&ipc_orig_info, sizeof (smb_ipc_t)); 423a0aa776eSAlan Wright 424a0aa776eSAlan Wright (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); 425a0aa776eSAlan Wright rc = smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ); 426a0aa776eSAlan Wright if (rc != 0) 427a0aa776eSAlan Wright *ipc_info.passwd = 0; 428a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 429a0aa776eSAlan Wright 430a0aa776eSAlan Wright } 431a0aa776eSAlan Wright 432a0aa776eSAlan Wright /* 433a0aa776eSAlan Wright * Set the IPC username and password hash in memory. If the domain 434a0aa776eSAlan Wright * join succeeds, the credentials will be committed for use with 435a0aa776eSAlan Wright * authenticated IPC. Otherwise, they should be rolled back. 436a0aa776eSAlan Wright */ 437a0aa776eSAlan Wright void 438a0aa776eSAlan Wright smb_ipc_set(char *plain_user, uint8_t *passwd_hash) 439a0aa776eSAlan Wright { 440a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 441a0aa776eSAlan Wright (void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user)); 442a0aa776eSAlan Wright (void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ); 443a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 444a0aa776eSAlan Wright 445a0aa776eSAlan Wright } 446a0aa776eSAlan Wright 447a0aa776eSAlan Wright /* 448a0aa776eSAlan Wright * Save the host credentials to be used for authenticated IPC. 449a0aa776eSAlan Wright * The credentials are also saved to the original IPC info as 450a0aa776eSAlan Wright * rollback data in case the join domain process fails later. 451a0aa776eSAlan Wright */ 452a0aa776eSAlan Wright void 453a0aa776eSAlan Wright smb_ipc_commit(void) 454a0aa776eSAlan Wright { 455a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 456a0aa776eSAlan Wright (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); 457a0aa776eSAlan Wright (void) smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ); 458a0aa776eSAlan Wright (void) memcpy(&ipc_orig_info, &ipc_info, sizeof (smb_ipc_t)); 459a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 460a0aa776eSAlan Wright } 461a0aa776eSAlan Wright 462a0aa776eSAlan Wright /* 463a0aa776eSAlan Wright * Restore the original credentials 464a0aa776eSAlan Wright */ 465a0aa776eSAlan Wright void 466a0aa776eSAlan Wright smb_ipc_rollback(void) 467a0aa776eSAlan Wright { 468a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock); 469a0aa776eSAlan Wright (void) strlcpy(ipc_info.user, ipc_orig_info.user, 470a0aa776eSAlan Wright sizeof (ipc_info.user)); 471a0aa776eSAlan Wright (void) memcpy(ipc_info.passwd, ipc_orig_info.passwd, 472a0aa776eSAlan Wright sizeof (ipc_info.passwd)); 473a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 474a0aa776eSAlan Wright } 475a0aa776eSAlan Wright 476a0aa776eSAlan Wright void 477a0aa776eSAlan Wright smb_ipc_get_user(char *buf, size_t buflen) 478a0aa776eSAlan Wright { 479a0aa776eSAlan Wright (void) rw_rdlock(&smb_ipc_lock); 480a0aa776eSAlan Wright (void) strlcpy(buf, ipc_info.user, buflen); 481a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 482a0aa776eSAlan Wright } 483a0aa776eSAlan Wright 484a0aa776eSAlan Wright void 485a0aa776eSAlan Wright smb_ipc_get_passwd(uint8_t *buf, size_t buflen) 486a0aa776eSAlan Wright { 487a0aa776eSAlan Wright if (buflen < SMBAUTH_HASH_SZ) 488a0aa776eSAlan Wright return; 489a0aa776eSAlan Wright 490a0aa776eSAlan Wright (void) rw_rdlock(&smb_ipc_lock); 491a0aa776eSAlan Wright (void) memcpy(buf, ipc_info.passwd, SMBAUTH_HASH_SZ); 492a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock); 493a0aa776eSAlan Wright } 494a0aa776eSAlan Wright 495faa1795aSjb /* 496faa1795aSjb * smb_match_netlogon_seqnum 497faa1795aSjb * 498faa1795aSjb * A sequence number is associated with each machine password property 499faa1795aSjb * update and the netlogon credential chain setup. If the 500faa1795aSjb * sequence numbers don't match, a NETLOGON credential chain 501faa1795aSjb * establishment is required. 502faa1795aSjb * 503faa1795aSjb * Returns 0 if kpasswd_seqnum equals to netlogon_seqnum. Otherwise, 504faa1795aSjb * returns -1. 505faa1795aSjb */ 506faa1795aSjb boolean_t 507faa1795aSjb smb_match_netlogon_seqnum(void) 508faa1795aSjb { 509faa1795aSjb int64_t setpasswd_seqnum; 510faa1795aSjb int64_t netlogon_seqnum; 511faa1795aSjb 512faa1795aSjb (void) mutex_lock(&seqnum_mtx); 513faa1795aSjb (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &setpasswd_seqnum); 514faa1795aSjb (void) smb_config_getnum(SMB_CI_NETLOGON_SEQNUM, &netlogon_seqnum); 515faa1795aSjb (void) mutex_unlock(&seqnum_mtx); 516faa1795aSjb return (setpasswd_seqnum == netlogon_seqnum); 517faa1795aSjb } 518faa1795aSjb 519faa1795aSjb /* 520faa1795aSjb * smb_setdomainprops 521faa1795aSjb * 522faa1795aSjb * This function should be called after joining an AD to 523faa1795aSjb * set all the domain related SMF properties. 524faa1795aSjb * 525faa1795aSjb * The kpasswd_domain property is the AD domain to which the system 526faa1795aSjb * is joined via kclient. If this function is invoked by the SMB 527faa1795aSjb * daemon, fqdn should be set to NULL. 528faa1795aSjb */ 529faa1795aSjb int 530faa1795aSjb smb_setdomainprops(char *fqdn, char *server, char *passwd) 531faa1795aSjb { 532faa1795aSjb if (server == NULL || passwd == NULL) 533faa1795aSjb return (-1); 534faa1795aSjb 535faa1795aSjb if ((*server == '\0') || (*passwd == '\0')) 536faa1795aSjb return (-1); 537faa1795aSjb 538faa1795aSjb if (fqdn && (smb_config_set(SMB_CI_KPASSWD_DOMAIN, fqdn) != 0)) 539faa1795aSjb return (-1); 540faa1795aSjb 541faa1795aSjb if (smb_config_set(SMB_CI_KPASSWD_SRV, server) != 0) 542faa1795aSjb return (-1); 543faa1795aSjb 544faa1795aSjb if (smb_set_machine_passwd(passwd) != 0) { 545faa1795aSjb syslog(LOG_ERR, "smb_setdomainprops: failed to set" 546faa1795aSjb " machine account password"); 547faa1795aSjb return (-1); 548faa1795aSjb } 549faa1795aSjb 550faa1795aSjb /* 551faa1795aSjb * If we successfully create a trust account, we mark 552faa1795aSjb * ourselves as a domain member in the environment so 553faa1795aSjb * that we use the SAMLOGON version of the NETLOGON 554faa1795aSjb * PDC location protocol. 555faa1795aSjb */ 556faa1795aSjb (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_TRUE); 557faa1795aSjb 558faa1795aSjb return (0); 559faa1795aSjb } 560faa1795aSjb 561faa1795aSjb /* 562faa1795aSjb * smb_update_netlogon_seqnum 563faa1795aSjb * 564faa1795aSjb * This function should only be called upon a successful netlogon 565faa1795aSjb * credential chain establishment to set the sequence number of the 566faa1795aSjb * netlogon to match with that of the kpasswd. 567faa1795aSjb */ 568faa1795aSjb void 569faa1795aSjb smb_update_netlogon_seqnum(void) 570faa1795aSjb { 571faa1795aSjb int64_t num; 572faa1795aSjb 573faa1795aSjb (void) mutex_lock(&seqnum_mtx); 574faa1795aSjb (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num); 575faa1795aSjb (void) smb_config_setnum(SMB_CI_NETLOGON_SEQNUM, num); 576faa1795aSjb (void) mutex_unlock(&seqnum_mtx); 577faa1795aSjb } 578faa1795aSjb 579dc20a302Sas 580da6c28aaSamw /* 581da6c28aaSamw * Temporary fbt for dtrace until user space sdt enabled. 582da6c28aaSamw */ 583da6c28aaSamw void 584da6c28aaSamw smb_tracef(const char *fmt, ...) 585da6c28aaSamw { 586da6c28aaSamw va_list ap; 587da6c28aaSamw char buf[128]; 588da6c28aaSamw 589da6c28aaSamw va_start(ap, fmt); 590da6c28aaSamw (void) vsnprintf(buf, 128, fmt, ap); 591da6c28aaSamw va_end(ap); 592da6c28aaSamw 593da6c28aaSamw smb_trace(buf); 594da6c28aaSamw } 595da6c28aaSamw 596da6c28aaSamw /* 597da6c28aaSamw * Temporary fbt for dtrace until user space sdt enabled. 598b819cea2SGordon Ross * 599b819cea2SGordon Ross * This function is designed to be used with dtrace, i.e. see: 600b819cea2SGordon Ross * usr/src/cmd/smbsrv/dtrace/smbd-all.d 601b819cea2SGordon Ross * 602b819cea2SGordon Ross * Outside of dtrace, the messages passed to this function usually 603b819cea2SGordon Ross * lack sufficient context to be useful, so we don't log them. 604da6c28aaSamw */ 605b819cea2SGordon Ross /* ARGSUSED */ 606da6c28aaSamw void 607da6c28aaSamw smb_trace(const char *s) 608da6c28aaSamw { 609da6c28aaSamw } 6107b59d02dSjb 6117b59d02dSjb /* 6127b59d02dSjb * smb_tonetbiosname 6137b59d02dSjb * 6147b59d02dSjb * Creates a NetBIOS name based on the given name and suffix. 6157b59d02dSjb * NetBIOS name is 15 capital characters, padded with space if needed 6167b59d02dSjb * and the 16th byte is the suffix. 6177b59d02dSjb */ 6187b59d02dSjb void 6197b59d02dSjb smb_tonetbiosname(char *name, char *nb_name, char suffix) 6207b59d02dSjb { 6217b59d02dSjb char tmp_name[NETBIOS_NAME_SZ]; 622bbf6f00cSJordan Brown smb_wchar_t wtmp_name[NETBIOS_NAME_SZ]; 6237b59d02dSjb int len; 6247b59d02dSjb size_t rc; 6257b59d02dSjb 6267b59d02dSjb len = 0; 627bbf6f00cSJordan Brown rc = smb_mbstowcs(wtmp_name, (const char *)name, NETBIOS_NAME_SZ); 6287b59d02dSjb 6297b59d02dSjb if (rc != (size_t)-1) { 6307b59d02dSjb wtmp_name[NETBIOS_NAME_SZ - 1] = 0; 631bbf6f00cSJordan Brown rc = ucstooem(tmp_name, wtmp_name, NETBIOS_NAME_SZ, 632bbf6f00cSJordan Brown OEM_CPG_850); 6337b59d02dSjb if (rc > 0) 6347b59d02dSjb len = strlen(tmp_name); 6357b59d02dSjb } 6367b59d02dSjb 6377b59d02dSjb (void) memset(nb_name, ' ', NETBIOS_NAME_SZ - 1); 6387b59d02dSjb if (len) { 639bbf6f00cSJordan Brown (void) smb_strupr(tmp_name); 6407b59d02dSjb (void) memcpy(nb_name, tmp_name, len); 6417b59d02dSjb } 6427b59d02dSjb nb_name[NETBIOS_NAME_SZ - 1] = suffix; 6437b59d02dSjb } 6447b59d02dSjb 6457b59d02dSjb int 6467f667e74Sjose borrego smb_get_nameservers(smb_inaddr_t *ips, int sz) 6477b59d02dSjb { 6487b59d02dSjb union res_sockaddr_union set[MAXNS]; 6497b59d02dSjb int i, cnt; 6507b59d02dSjb struct __res_state res_state; 6517f667e74Sjose borrego char ipstr[INET6_ADDRSTRLEN]; 6527b59d02dSjb 6537b59d02dSjb if (ips == NULL) 6547b59d02dSjb return (0); 6557b59d02dSjb 6567b59d02dSjb bzero(&res_state, sizeof (struct __res_state)); 6577b59d02dSjb if (res_ninit(&res_state) < 0) 6587b59d02dSjb return (0); 6597b59d02dSjb 6607b59d02dSjb cnt = res_getservers(&res_state, set, MAXNS); 6617b59d02dSjb for (i = 0; i < cnt; i++) { 6627b59d02dSjb if (i >= sz) 6637b59d02dSjb break; 6647f667e74Sjose borrego ips[i].a_family = AF_INET; 665b819cea2SGordon Ross bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv4, NS_INADDRSZ); 6667f667e74Sjose borrego if (inet_ntop(AF_INET, &ips[i].a_ipv4, ipstr, 6677f667e74Sjose borrego INET_ADDRSTRLEN)) { 6687f667e74Sjose borrego syslog(LOG_DEBUG, "Found %s name server\n", ipstr); 6697f667e74Sjose borrego continue; 6707f667e74Sjose borrego } 6717f667e74Sjose borrego ips[i].a_family = AF_INET6; 672b819cea2SGordon Ross bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv6, NS_IN6ADDRSZ); 6737f667e74Sjose borrego if (inet_ntop(AF_INET6, &ips[i].a_ipv6, ipstr, 6747f667e74Sjose borrego INET6_ADDRSTRLEN)) { 6757f667e74Sjose borrego syslog(LOG_DEBUG, "Found %s name server\n", ipstr); 6767f667e74Sjose borrego } 6777b59d02dSjb } 6787b59d02dSjb res_ndestroy(&res_state); 6797b59d02dSjb return (i); 6807b59d02dSjb } 68129bd2886SAlan Wright 6828d7e4166Sjose borrego /* 6838d7e4166Sjose borrego * smb_gethostbyname 6848d7e4166Sjose borrego * 6858d7e4166Sjose borrego * Looks up a host by the given name. The host entry can come 6868d7e4166Sjose borrego * from any of the sources for hosts specified in the 6878d7e4166Sjose borrego * /etc/nsswitch.conf and the NetBIOS cache. 6888d7e4166Sjose borrego * 6898d7e4166Sjose borrego * XXX Invokes nbt_name_resolve API once the NBTD is integrated 6908d7e4166Sjose borrego * to look in the NetBIOS cache if getipnodebyname fails. 6918d7e4166Sjose borrego * 6928d7e4166Sjose borrego * Caller should invoke freehostent to free the returned hostent. 6938d7e4166Sjose borrego */ 6948d7e4166Sjose borrego struct hostent * 6958d7e4166Sjose borrego smb_gethostbyname(const char *name, int *err_num) 6968d7e4166Sjose borrego { 6978d7e4166Sjose borrego struct hostent *h; 6988d7e4166Sjose borrego 6998d7e4166Sjose borrego h = getipnodebyname(name, AF_INET, 0, err_num); 7007f667e74Sjose borrego if ((h == NULL) || h->h_length != INADDRSZ) 7017f667e74Sjose borrego h = getipnodebyname(name, AF_INET6, AI_DEFAULT, err_num); 7028d7e4166Sjose borrego return (h); 7038d7e4166Sjose borrego } 7048d7e4166Sjose borrego 7058d7e4166Sjose borrego /* 7068d7e4166Sjose borrego * smb_gethostbyaddr 7078d7e4166Sjose borrego * 7088d7e4166Sjose borrego * Looks up a host by the given IP address. The host entry can come 7098d7e4166Sjose borrego * from any of the sources for hosts specified in the 7108d7e4166Sjose borrego * /etc/nsswitch.conf and the NetBIOS cache. 7118d7e4166Sjose borrego * 7128d7e4166Sjose borrego * XXX Invokes nbt API to resolve name by IP once the NBTD is integrated 7138d7e4166Sjose borrego * to look in the NetBIOS cache if getipnodebyaddr fails. 7148d7e4166Sjose borrego * 7158d7e4166Sjose borrego * Caller should invoke freehostent to free the returned hostent. 7168d7e4166Sjose borrego */ 7178d7e4166Sjose borrego struct hostent * 7188d7e4166Sjose borrego smb_gethostbyaddr(const char *addr, int len, int type, int *err_num) 7198d7e4166Sjose borrego { 7208d7e4166Sjose borrego struct hostent *h; 7218d7e4166Sjose borrego 7228d7e4166Sjose borrego h = getipnodebyaddr(addr, len, type, err_num); 7238d7e4166Sjose borrego 7248d7e4166Sjose borrego return (h); 7258d7e4166Sjose borrego } 726*ce8560eeSMatt Barden 727*ce8560eeSMatt Barden uint32_t 728*ce8560eeSMatt Barden smb_get_netlogon_flags(void) 729*ce8560eeSMatt Barden { 730*ce8560eeSMatt Barden int64_t val; 731*ce8560eeSMatt Barden 732*ce8560eeSMatt Barden if (smb_config_getnum(SMB_CI_NETLOGON_FLAGS, &val) != SMBD_SMF_OK) 733*ce8560eeSMatt Barden return (SMB_PI_NETLOGON_FLAGS_DEFAULT); 734*ce8560eeSMatt Barden 735*ce8560eeSMatt Barden /* These are flags, and we only use the lowest 32 bits */ 736*ce8560eeSMatt Barden return ((uint32_t)val); 737*ce8560eeSMatt Barden } 738