xref: /onnv-gate/usr/src/lib/smbsrv/libsmb/common/smb_info.c (revision 12890:16985853e3aa)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
2212508Samw@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw  */
245331Samw 
258334SJose.Borrego@Sun.COM #include <assert.h>
265331Samw #include <sys/types.h>
275331Samw #include <stdarg.h>
285331Samw #include <unistd.h>
295331Samw #include <stdlib.h>
305331Samw #include <time.h>
315331Samw #include <synch.h>
325331Samw #include <syslog.h>
335331Samw #include <string.h>
345331Samw #include <strings.h>
355331Samw #include <errno.h>
365331Samw #include <net/if.h>
375331Samw #include <netdb.h>
385772Sas200622 #include <netinet/in.h>
395772Sas200622 #include <arpa/nameser.h>
405772Sas200622 #include <resolv.h>
415331Samw #include <sys/sockio.h>
428334SJose.Borrego@Sun.COM #include <sys/socket.h>
435331Samw #include <smbsrv/smbinfo.h>
445331Samw #include <smbsrv/netbios.h>
455331Samw #include <smbsrv/libsmb.h>
465331Samw 
476139Sjb150015 static mutex_t seqnum_mtx;
485331Samw 
499343SAfshin.Ardakani@Sun.COM /*
5010717Samw@Sun.COM  * IPC connection information that may be passed to the SMB Redirector.
5110717Samw@Sun.COM  */
5210717Samw@Sun.COM typedef struct {
5310717Samw@Sun.COM 	char	user[SMB_USERNAME_MAXLEN];
5410717Samw@Sun.COM 	uint8_t	passwd[SMBAUTH_HASH_SZ];
5510717Samw@Sun.COM } smb_ipc_t;
5610717Samw@Sun.COM 
5710717Samw@Sun.COM static smb_ipc_t	ipc_info;
5810717Samw@Sun.COM static smb_ipc_t	ipc_orig_info;
5910717Samw@Sun.COM static rwlock_t		smb_ipc_lock;
6010717Samw@Sun.COM 
6110717Samw@Sun.COM /*
629343SAfshin.Ardakani@Sun.COM  * Some older clients (Windows 98) only handle the low byte
639343SAfshin.Ardakani@Sun.COM  * of the max workers value. If the low byte is less than
649343SAfshin.Ardakani@Sun.COM  * SMB_PI_MAX_WORKERS_MIN set it to SMB_PI_MAX_WORKERS_MIN.
659343SAfshin.Ardakani@Sun.COM  */
665331Samw void
smb_load_kconfig(smb_kmod_cfg_t * kcfg)675331Samw smb_load_kconfig(smb_kmod_cfg_t *kcfg)
685331Samw {
695772Sas200622 	int64_t citem;
705772Sas200622 
715331Samw 	bzero(kcfg, sizeof (smb_kmod_cfg_t));
725331Samw 
735772Sas200622 	(void) smb_config_getnum(SMB_CI_MAX_WORKERS, &citem);
745772Sas200622 	kcfg->skc_maxworkers = (uint32_t)citem;
759343SAfshin.Ardakani@Sun.COM 	if ((kcfg->skc_maxworkers & 0xFF) < SMB_PI_MAX_WORKERS_MIN) {
769343SAfshin.Ardakani@Sun.COM 		kcfg->skc_maxworkers &= ~0xFF;
779343SAfshin.Ardakani@Sun.COM 		kcfg->skc_maxworkers += SMB_PI_MAX_WORKERS_MIN;
789343SAfshin.Ardakani@Sun.COM 	}
799343SAfshin.Ardakani@Sun.COM 
805772Sas200622 	(void) smb_config_getnum(SMB_CI_KEEPALIVE, &citem);
815772Sas200622 	kcfg->skc_keepalive = (uint32_t)citem;
825331Samw 	if ((kcfg->skc_keepalive != 0) &&
835331Samw 	    (kcfg->skc_keepalive < SMB_PI_KEEP_ALIVE_MIN))
845331Samw 		kcfg->skc_keepalive = SMB_PI_KEEP_ALIVE_MIN;
855331Samw 
865772Sas200622 	(void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &citem);
875772Sas200622 	kcfg->skc_maxconnections = (uint32_t)citem;
885772Sas200622 	kcfg->skc_restrict_anon = smb_config_getbool(SMB_CI_RESTRICT_ANON);
895772Sas200622 	kcfg->skc_signing_enable = smb_config_getbool(SMB_CI_SIGNING_ENABLE);
905772Sas200622 	kcfg->skc_signing_required = smb_config_getbool(SMB_CI_SIGNING_REQD);
918670SJose.Borrego@Sun.COM 	kcfg->skc_ipv6_enable = smb_config_getbool(SMB_CI_IPV6_ENABLE);
92*12890SJoyce.McIntosh@Sun.COM 	kcfg->skc_print_enable = smb_config_getbool(SMB_CI_PRINT_ENABLE);
935772Sas200622 	kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE);
945772Sas200622 	kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE);
955331Samw 	kcfg->skc_secmode = smb_config_get_secmode();
967961SNatalie.Li@Sun.COM 	(void) smb_getdomainname(kcfg->skc_nbdomain,
977961SNatalie.Li@Sun.COM 	    sizeof (kcfg->skc_nbdomain));
987961SNatalie.Li@Sun.COM 	(void) smb_getfqdomainname(kcfg->skc_fqdn,
997961SNatalie.Li@Sun.COM 	    sizeof (kcfg->skc_fqdn));
1007961SNatalie.Li@Sun.COM 	(void) smb_getnetbiosname(kcfg->skc_hostname,
1017961SNatalie.Li@Sun.COM 	    sizeof (kcfg->skc_hostname));
1025772Sas200622 	(void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment,
1035331Samw 	    sizeof (kcfg->skc_system_comment));
10411963SAfshin.Ardakani@Sun.COM 	smb_config_get_version(&kcfg->skc_version);
10512508Samw@Sun.COM 	kcfg->skc_execflags = smb_config_get_execinfo(NULL, NULL, 0);
1065331Samw }
1075331Samw 
1085331Samw /*
1095331Samw  * Get the current system NetBIOS name.  The hostname is truncated at
1105331Samw  * the first `.` or 15 bytes, whichever occurs first, and converted
1115331Samw  * to uppercase (by smb_gethostname).  Text that appears after the
1125331Samw  * first '.' is considered to be part of the NetBIOS scope.
1135331Samw  *
1145331Samw  * Returns 0 on success, otherwise -1 to indicate an error.
1155331Samw  */
1165331Samw int
smb_getnetbiosname(char * buf,size_t buflen)1175331Samw smb_getnetbiosname(char *buf, size_t buflen)
1185331Samw {
11911963SAfshin.Ardakani@Sun.COM 	if (smb_gethostname(buf, buflen, SMB_CASE_UPPER) != 0)
1205331Samw 		return (-1);
1215331Samw 
1225331Samw 	if (buflen >= NETBIOS_NAME_SZ)
1235331Samw 		buf[NETBIOS_NAME_SZ - 1] = '\0';
1245331Samw 
1255331Samw 	return (0);
1265331Samw }
1275331Samw 
1285331Samw /*
1297961SNatalie.Li@Sun.COM  * Get the SAM account of the current system.
1307961SNatalie.Li@Sun.COM  * Returns 0 on success, otherwise, -1 to indicate an error.
1317961SNatalie.Li@Sun.COM  */
1327961SNatalie.Li@Sun.COM int
smb_getsamaccount(char * buf,size_t buflen)1337961SNatalie.Li@Sun.COM smb_getsamaccount(char *buf, size_t buflen)
1347961SNatalie.Li@Sun.COM {
1357961SNatalie.Li@Sun.COM 	if (smb_getnetbiosname(buf, buflen - 1) != 0)
1367961SNatalie.Li@Sun.COM 		return (-1);
1377961SNatalie.Li@Sun.COM 
1387961SNatalie.Li@Sun.COM 	(void) strlcat(buf, "$", buflen);
1397961SNatalie.Li@Sun.COM 	return (0);
1407961SNatalie.Li@Sun.COM }
1417961SNatalie.Li@Sun.COM 
1427961SNatalie.Li@Sun.COM /*
1435331Samw  * Get the current system node name.  The returned name is guaranteed
1445331Samw  * to be null-terminated (gethostname may not null terminate the name).
1455331Samw  * If the hostname has been fully-qualified for some reason, the domain
14611963SAfshin.Ardakani@Sun.COM  * part will be removed.  The returned hostname is converted to the
14711963SAfshin.Ardakani@Sun.COM  * specified case (lower, upper, or preserved).
1485331Samw  *
1495331Samw  * If gethostname fails, the returned buffer will contain an empty
1505331Samw  * string.
1515331Samw  */
1525331Samw int
smb_gethostname(char * buf,size_t buflen,smb_caseconv_t which)15311963SAfshin.Ardakani@Sun.COM smb_gethostname(char *buf, size_t buflen, smb_caseconv_t which)
1545331Samw {
1555331Samw 	char *p;
1565331Samw 
1575331Samw 	if (buf == NULL || buflen == 0)
1585331Samw 		return (-1);
1595331Samw 
1605331Samw 	if (gethostname(buf, buflen) != 0) {
1615331Samw 		*buf = '\0';
1625331Samw 		return (-1);
1635331Samw 	}
1645331Samw 
1655331Samw 	buf[buflen - 1] = '\0';
1665331Samw 
1675331Samw 	if ((p = strchr(buf, '.')) != NULL)
1685331Samw 		*p = '\0';
1695331Samw 
17011963SAfshin.Ardakani@Sun.COM 	switch (which) {
17111963SAfshin.Ardakani@Sun.COM 	case SMB_CASE_LOWER:
17211963SAfshin.Ardakani@Sun.COM 		(void) smb_strlwr(buf);
17311963SAfshin.Ardakani@Sun.COM 		break;
17411963SAfshin.Ardakani@Sun.COM 
17511963SAfshin.Ardakani@Sun.COM 	case SMB_CASE_UPPER:
17610966SJordan.Brown@Sun.COM 		(void) smb_strupr(buf);
17711963SAfshin.Ardakani@Sun.COM 		break;
17811963SAfshin.Ardakani@Sun.COM 
17911963SAfshin.Ardakani@Sun.COM 	case SMB_CASE_PRESERVE:
18011963SAfshin.Ardakani@Sun.COM 	default:
18111963SAfshin.Ardakani@Sun.COM 		break;
18211963SAfshin.Ardakani@Sun.COM 	}
1835331Samw 
1845331Samw 	return (0);
1855331Samw }
1865331Samw 
1875331Samw /*
18811963SAfshin.Ardakani@Sun.COM  * Obtain the fully-qualified name for this machine in lower case.  If
18911963SAfshin.Ardakani@Sun.COM  * the hostname is fully-qualified, accept it.  Otherwise, try to find an
19011963SAfshin.Ardakani@Sun.COM  * appropriate domain name to append to the hostname.
1915331Samw  */
1925331Samw int
smb_getfqhostname(char * buf,size_t buflen)1935331Samw smb_getfqhostname(char *buf, size_t buflen)
1945331Samw {
1955331Samw 	char hostname[MAXHOSTNAMELEN];
1965331Samw 	char domain[MAXHOSTNAMELEN];
1975331Samw 
1985331Samw 	hostname[0] = '\0';
1995331Samw 	domain[0] = '\0';
2005331Samw 
20111963SAfshin.Ardakani@Sun.COM 	if (smb_gethostname(hostname, MAXHOSTNAMELEN,
20211963SAfshin.Ardakani@Sun.COM 	    SMB_CASE_LOWER) != 0)
2035331Samw 		return (-1);
2045331Samw 
2055772Sas200622 	if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0)
2065331Samw 		return (-1);
2075331Samw 
2085331Samw 	if (hostname[0] == '\0')
2095331Samw 		return (-1);
2105331Samw 
2115331Samw 	if (domain[0] == '\0') {
2125331Samw 		(void) strlcpy(buf, hostname, buflen);
2135331Samw 		return (0);
2145331Samw 	}
2155331Samw 
2165331Samw 	(void) snprintf(buf, buflen, "%s.%s", hostname, domain);
2175331Samw 	return (0);
2185331Samw }
2195331Samw 
2205331Samw /*
2215772Sas200622  * smb_getdomainname
2225772Sas200622  *
2235772Sas200622  * Returns NETBIOS name of the domain if the system is in domain
2245772Sas200622  * mode. Or returns workgroup name if the system is in workgroup
2255772Sas200622  * mode.
2265772Sas200622  */
2275772Sas200622 int
smb_getdomainname(char * buf,size_t buflen)2285772Sas200622 smb_getdomainname(char *buf, size_t buflen)
2295772Sas200622 {
2305772Sas200622 	int rc;
2315772Sas200622 
2325772Sas200622 	if (buf == NULL || buflen == 0)
2335772Sas200622 		return (-1);
2345772Sas200622 
2355772Sas200622 	*buf = '\0';
2368334SJose.Borrego@Sun.COM 	rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, buf, buflen);
2375772Sas200622 
2388334SJose.Borrego@Sun.COM 	if ((rc != SMBD_SMF_OK) || (*buf == '\0'))
2395772Sas200622 		return (-1);
2405772Sas200622 
2415772Sas200622 	return (0);
2425772Sas200622 }
2435772Sas200622 
2445772Sas200622 /*
2455772Sas200622  * smb_getfqdomainname
2465772Sas200622  *
2478334SJose.Borrego@Sun.COM  * In the system is in domain mode, the dns_domain property value
2488334SJose.Borrego@Sun.COM  * is returned. Otherwise, it returns the local domain obtained via
2498334SJose.Borrego@Sun.COM  * resolver.
2505772Sas200622  *
2515772Sas200622  * Returns 0 upon success.  Otherwise, returns -1.
2525772Sas200622  */
2535772Sas200622 int
smb_getfqdomainname(char * buf,size_t buflen)2545772Sas200622 smb_getfqdomainname(char *buf, size_t buflen)
2555772Sas200622 {
2568334SJose.Borrego@Sun.COM 	struct __res_state res_state;
2578334SJose.Borrego@Sun.COM 	int rc;
2585772Sas200622 
2595772Sas200622 	if (buf == NULL || buflen == 0)
2605772Sas200622 		return (-1);
2615772Sas200622 
2625772Sas200622 	*buf = '\0';
2635772Sas200622 	if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) {
2648334SJose.Borrego@Sun.COM 		rc = smb_config_getstr(SMB_CI_DOMAIN_FQDN, buf, buflen);
2655772Sas200622 
2668334SJose.Borrego@Sun.COM 		if ((rc != SMBD_SMF_OK) || (*buf == '\0'))
2678334SJose.Borrego@Sun.COM 			return (-1);
2688334SJose.Borrego@Sun.COM 	} else {
2698334SJose.Borrego@Sun.COM 		bzero(&res_state, sizeof (struct __res_state));
2708334SJose.Borrego@Sun.COM 		if (res_ninit(&res_state))
2715772Sas200622 			return (-1);
2725772Sas200622 
2738334SJose.Borrego@Sun.COM 		if (*res_state.defdname == '\0') {
2748334SJose.Borrego@Sun.COM 			res_ndestroy(&res_state);
2758334SJose.Borrego@Sun.COM 			return (-1);
2765772Sas200622 		}
2778334SJose.Borrego@Sun.COM 
2788334SJose.Borrego@Sun.COM 		(void) strlcpy(buf, res_state.defdname, buflen);
2798334SJose.Borrego@Sun.COM 		res_ndestroy(&res_state);
2808334SJose.Borrego@Sun.COM 		rc = 0;
2815772Sas200622 	}
2825772Sas200622 
2835772Sas200622 	return (rc);
2845772Sas200622 }
2855772Sas200622 
2865772Sas200622 
2876139Sjb150015 /*
2886139Sjb150015  * smb_set_machine_passwd
2896139Sjb150015  *
2906139Sjb150015  * This function should be used when setting the machine password property.
2916139Sjb150015  * The associated sequence number is incremented.
2926139Sjb150015  */
2936139Sjb150015 static int
smb_set_machine_passwd(char * passwd)2946139Sjb150015 smb_set_machine_passwd(char *passwd)
2956139Sjb150015 {
2966139Sjb150015 	int64_t num;
2976139Sjb150015 	int rc = -1;
2986139Sjb150015 
2996139Sjb150015 	if (smb_config_set(SMB_CI_MACHINE_PASSWD, passwd) != SMBD_SMF_OK)
3006139Sjb150015 		return (-1);
3016139Sjb150015 
3026139Sjb150015 	(void) mutex_lock(&seqnum_mtx);
3036139Sjb150015 	(void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num);
3046139Sjb150015 	if (smb_config_setnum(SMB_CI_KPASSWD_SEQNUM, ++num)
3056139Sjb150015 	    == SMBD_SMF_OK)
3066139Sjb150015 		rc = 0;
3076139Sjb150015 	(void) mutex_unlock(&seqnum_mtx);
3086139Sjb150015 	return (rc);
3096139Sjb150015 }
3106139Sjb150015 
31110717Samw@Sun.COM static int
smb_get_machine_passwd(uint8_t * buf,size_t buflen)31210717Samw@Sun.COM smb_get_machine_passwd(uint8_t *buf, size_t buflen)
31310717Samw@Sun.COM {
31410717Samw@Sun.COM 	char pwd[SMB_PASSWD_MAXLEN + 1];
31510717Samw@Sun.COM 	int rc;
31610717Samw@Sun.COM 
31710717Samw@Sun.COM 	if (buflen < SMBAUTH_HASH_SZ)
31810717Samw@Sun.COM 		return (-1);
31910717Samw@Sun.COM 
32010717Samw@Sun.COM 	rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd));
32110717Samw@Sun.COM 	if ((rc != SMBD_SMF_OK) || *pwd == '\0')
32210717Samw@Sun.COM 		return (-1);
32310717Samw@Sun.COM 
32410717Samw@Sun.COM 	if (smb_auth_ntlm_hash(pwd, buf) != 0)
32510717Samw@Sun.COM 		return (-1);
32610717Samw@Sun.COM 
32710717Samw@Sun.COM 	return (rc);
32810717Samw@Sun.COM }
32910717Samw@Sun.COM 
33010717Samw@Sun.COM /*
33110717Samw@Sun.COM  * Set up IPC connection credentials.
33210717Samw@Sun.COM  */
33310717Samw@Sun.COM void
smb_ipc_init(void)33410717Samw@Sun.COM smb_ipc_init(void)
33510717Samw@Sun.COM {
33610717Samw@Sun.COM 	int rc;
33710717Samw@Sun.COM 
33810717Samw@Sun.COM 	(void) rw_wrlock(&smb_ipc_lock);
33910717Samw@Sun.COM 	bzero(&ipc_info, sizeof (smb_ipc_t));
34010717Samw@Sun.COM 	bzero(&ipc_orig_info, sizeof (smb_ipc_t));
34110717Samw@Sun.COM 
34210717Samw@Sun.COM 	(void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
34310717Samw@Sun.COM 	rc = smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ);
34410717Samw@Sun.COM 	if (rc != 0)
34510717Samw@Sun.COM 		*ipc_info.passwd = 0;
34610717Samw@Sun.COM 	(void) rw_unlock(&smb_ipc_lock);
34710717Samw@Sun.COM 
34810717Samw@Sun.COM }
34910717Samw@Sun.COM 
35010717Samw@Sun.COM /*
35110717Samw@Sun.COM  * Set the IPC username and password hash in memory.  If the domain
35210717Samw@Sun.COM  * join succeeds, the credentials will be committed for use with
35310717Samw@Sun.COM  * authenticated IPC.  Otherwise, they should be rolled back.
35410717Samw@Sun.COM  */
35510717Samw@Sun.COM void
smb_ipc_set(char * plain_user,uint8_t * passwd_hash)35610717Samw@Sun.COM smb_ipc_set(char *plain_user, uint8_t *passwd_hash)
35710717Samw@Sun.COM {
35810717Samw@Sun.COM 	(void) rw_wrlock(&smb_ipc_lock);
35910717Samw@Sun.COM 	(void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user));
36010717Samw@Sun.COM 	(void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ);
36110717Samw@Sun.COM 	(void) rw_unlock(&smb_ipc_lock);
36210717Samw@Sun.COM 
36310717Samw@Sun.COM }
36410717Samw@Sun.COM 
36510717Samw@Sun.COM /*
36610717Samw@Sun.COM  * Save the host credentials to be used for authenticated IPC.
36710717Samw@Sun.COM  * The credentials are also saved to the original IPC info as
36810717Samw@Sun.COM  * rollback data in case the join domain process fails later.
36910717Samw@Sun.COM  */
37010717Samw@Sun.COM void
smb_ipc_commit(void)37110717Samw@Sun.COM smb_ipc_commit(void)
37210717Samw@Sun.COM {
37310717Samw@Sun.COM 	(void) rw_wrlock(&smb_ipc_lock);
37410717Samw@Sun.COM 	(void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
37510717Samw@Sun.COM 	(void) smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ);
37610717Samw@Sun.COM 	(void) memcpy(&ipc_orig_info, &ipc_info, sizeof (smb_ipc_t));
37710717Samw@Sun.COM 	(void) rw_unlock(&smb_ipc_lock);
37810717Samw@Sun.COM }
37910717Samw@Sun.COM 
38010717Samw@Sun.COM /*
38110717Samw@Sun.COM  * Restore the original credentials
38210717Samw@Sun.COM  */
38310717Samw@Sun.COM void
smb_ipc_rollback(void)38410717Samw@Sun.COM smb_ipc_rollback(void)
38510717Samw@Sun.COM {
38610717Samw@Sun.COM 	(void) rw_wrlock(&smb_ipc_lock);
38710717Samw@Sun.COM 	(void) strlcpy(ipc_info.user, ipc_orig_info.user,
38810717Samw@Sun.COM 	    sizeof (ipc_info.user));
38910717Samw@Sun.COM 	(void) memcpy(ipc_info.passwd, ipc_orig_info.passwd,
39010717Samw@Sun.COM 	    sizeof (ipc_info.passwd));
39110717Samw@Sun.COM 	(void) rw_unlock(&smb_ipc_lock);
39210717Samw@Sun.COM }
39310717Samw@Sun.COM 
39410717Samw@Sun.COM void
smb_ipc_get_user(char * buf,size_t buflen)39510717Samw@Sun.COM smb_ipc_get_user(char *buf, size_t buflen)
39610717Samw@Sun.COM {
39710717Samw@Sun.COM 	(void) rw_rdlock(&smb_ipc_lock);
39810717Samw@Sun.COM 	(void) strlcpy(buf, ipc_info.user, buflen);
39910717Samw@Sun.COM 	(void) rw_unlock(&smb_ipc_lock);
40010717Samw@Sun.COM }
40110717Samw@Sun.COM 
40210717Samw@Sun.COM void
smb_ipc_get_passwd(uint8_t * buf,size_t buflen)40310717Samw@Sun.COM smb_ipc_get_passwd(uint8_t *buf, size_t buflen)
40410717Samw@Sun.COM {
40510717Samw@Sun.COM 	if (buflen < SMBAUTH_HASH_SZ)
40610717Samw@Sun.COM 		return;
40710717Samw@Sun.COM 
40810717Samw@Sun.COM 	(void) rw_rdlock(&smb_ipc_lock);
40910717Samw@Sun.COM 	(void) memcpy(buf, ipc_info.passwd, SMBAUTH_HASH_SZ);
41010717Samw@Sun.COM 	(void) rw_unlock(&smb_ipc_lock);
41110717Samw@Sun.COM }
41210717Samw@Sun.COM 
4136139Sjb150015 /*
4146139Sjb150015  * smb_match_netlogon_seqnum
4156139Sjb150015  *
4166139Sjb150015  * A sequence number is associated with each machine password property
4176139Sjb150015  * update and the netlogon credential chain setup. If the
4186139Sjb150015  * sequence numbers don't match, a NETLOGON credential chain
4196139Sjb150015  * establishment is required.
4206139Sjb150015  *
4216139Sjb150015  * Returns 0 if kpasswd_seqnum equals to netlogon_seqnum. Otherwise,
4226139Sjb150015  * returns -1.
4236139Sjb150015  */
4246139Sjb150015 boolean_t
smb_match_netlogon_seqnum(void)4256139Sjb150015 smb_match_netlogon_seqnum(void)
4266139Sjb150015 {
4276139Sjb150015 	int64_t setpasswd_seqnum;
4286139Sjb150015 	int64_t netlogon_seqnum;
4296139Sjb150015 
4306139Sjb150015 	(void) mutex_lock(&seqnum_mtx);
4316139Sjb150015 	(void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &setpasswd_seqnum);
4326139Sjb150015 	(void) smb_config_getnum(SMB_CI_NETLOGON_SEQNUM, &netlogon_seqnum);
4336139Sjb150015 	(void) mutex_unlock(&seqnum_mtx);
4346139Sjb150015 	return (setpasswd_seqnum == netlogon_seqnum);
4356139Sjb150015 }
4366139Sjb150015 
4376139Sjb150015 /*
4386139Sjb150015  * smb_setdomainprops
4396139Sjb150015  *
4406139Sjb150015  * This function should be called after joining an AD to
4416139Sjb150015  * set all the domain related SMF properties.
4426139Sjb150015  *
4436139Sjb150015  * The kpasswd_domain property is the AD domain to which the system
4446139Sjb150015  * is joined via kclient. If this function is invoked by the SMB
4456139Sjb150015  * daemon, fqdn should be set to NULL.
4466139Sjb150015  */
4476139Sjb150015 int
smb_setdomainprops(char * fqdn,char * server,char * passwd)4486139Sjb150015 smb_setdomainprops(char *fqdn, char *server, char *passwd)
4496139Sjb150015 {
4506139Sjb150015 	if (server == NULL || passwd == NULL)
4516139Sjb150015 		return (-1);
4526139Sjb150015 
4536139Sjb150015 	if ((*server == '\0') || (*passwd == '\0'))
4546139Sjb150015 		return (-1);
4556139Sjb150015 
4566139Sjb150015 	if (fqdn && (smb_config_set(SMB_CI_KPASSWD_DOMAIN, fqdn) != 0))
4576139Sjb150015 		return (-1);
4586139Sjb150015 
4596139Sjb150015 	if (smb_config_set(SMB_CI_KPASSWD_SRV, server) != 0)
4606139Sjb150015 		return (-1);
4616139Sjb150015 
4626139Sjb150015 	if (smb_set_machine_passwd(passwd) != 0) {
4636139Sjb150015 		syslog(LOG_ERR, "smb_setdomainprops: failed to set"
4646139Sjb150015 		    " machine account password");
4656139Sjb150015 		return (-1);
4666139Sjb150015 	}
4676139Sjb150015 
4686139Sjb150015 	/*
4696139Sjb150015 	 * If we successfully create a trust account, we mark
4706139Sjb150015 	 * ourselves as a domain member in the environment so
4716139Sjb150015 	 * that we use the SAMLOGON version of the NETLOGON
4726139Sjb150015 	 * PDC location protocol.
4736139Sjb150015 	 */
4746139Sjb150015 	(void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_TRUE);
4756139Sjb150015 
4766139Sjb150015 	return (0);
4776139Sjb150015 }
4786139Sjb150015 
4796139Sjb150015 /*
4806139Sjb150015  * smb_update_netlogon_seqnum
4816139Sjb150015  *
4826139Sjb150015  * This function should only be called upon a successful netlogon
4836139Sjb150015  * credential chain establishment to set the sequence number of the
4846139Sjb150015  * netlogon to match with that of the kpasswd.
4856139Sjb150015  */
4866139Sjb150015 void
smb_update_netlogon_seqnum(void)4876139Sjb150015 smb_update_netlogon_seqnum(void)
4886139Sjb150015 {
4896139Sjb150015 	int64_t num;
4906139Sjb150015 
4916139Sjb150015 	(void) mutex_lock(&seqnum_mtx);
4926139Sjb150015 	(void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num);
4936139Sjb150015 	(void) smb_config_setnum(SMB_CI_NETLOGON_SEQNUM, num);
4946139Sjb150015 	(void) mutex_unlock(&seqnum_mtx);
4956139Sjb150015 }
4966139Sjb150015 
4975772Sas200622 
4985772Sas200622 /*
4995331Samw  * Temporary fbt for dtrace until user space sdt enabled.
5005331Samw  */
5015331Samw void
smb_tracef(const char * fmt,...)5025331Samw smb_tracef(const char *fmt, ...)
5035331Samw {
5045331Samw 	va_list ap;
5055331Samw 	char buf[128];
5065331Samw 
5075331Samw 	va_start(ap, fmt);
5085331Samw 	(void) vsnprintf(buf, 128, fmt, ap);
5095331Samw 	va_end(ap);
5105331Samw 
5115331Samw 	smb_trace(buf);
5125331Samw }
5135331Samw 
5145331Samw /*
5155331Samw  * Temporary fbt for dtrace until user space sdt enabled.
5165331Samw  */
5175331Samw void
smb_trace(const char * s)5185331Samw smb_trace(const char *s)
5195331Samw {
5205331Samw 	syslog(LOG_DEBUG, "%s", s);
5215331Samw }
5226030Sjb150015 
5236030Sjb150015 /*
5246030Sjb150015  * smb_tonetbiosname
5256030Sjb150015  *
5266030Sjb150015  * Creates a NetBIOS name based on the given name and suffix.
5276030Sjb150015  * NetBIOS name is 15 capital characters, padded with space if needed
5286030Sjb150015  * and the 16th byte is the suffix.
5296030Sjb150015  */
5306030Sjb150015 void
smb_tonetbiosname(char * name,char * nb_name,char suffix)5316030Sjb150015 smb_tonetbiosname(char *name, char *nb_name, char suffix)
5326030Sjb150015 {
5336030Sjb150015 	char tmp_name[NETBIOS_NAME_SZ];
53410966SJordan.Brown@Sun.COM 	smb_wchar_t wtmp_name[NETBIOS_NAME_SZ];
5356030Sjb150015 	int len;
5366030Sjb150015 	size_t rc;
5376030Sjb150015 
5386030Sjb150015 	len = 0;
53910966SJordan.Brown@Sun.COM 	rc = smb_mbstowcs(wtmp_name, (const char *)name, NETBIOS_NAME_SZ);
5406030Sjb150015 
5416030Sjb150015 	if (rc != (size_t)-1) {
5426030Sjb150015 		wtmp_name[NETBIOS_NAME_SZ - 1] = 0;
54310966SJordan.Brown@Sun.COM 		rc = ucstooem(tmp_name, wtmp_name, NETBIOS_NAME_SZ,
54410966SJordan.Brown@Sun.COM 		    OEM_CPG_850);
5456030Sjb150015 		if (rc > 0)
5466030Sjb150015 			len = strlen(tmp_name);
5476030Sjb150015 	}
5486030Sjb150015 
5496030Sjb150015 	(void) memset(nb_name, ' ', NETBIOS_NAME_SZ - 1);
5506030Sjb150015 	if (len) {
55110966SJordan.Brown@Sun.COM 		(void) smb_strupr(tmp_name);
5526030Sjb150015 		(void) memcpy(nb_name, tmp_name, len);
5536030Sjb150015 	}
5546030Sjb150015 	nb_name[NETBIOS_NAME_SZ - 1] = suffix;
5556030Sjb150015 }
5566030Sjb150015 
5576030Sjb150015 int
smb_get_nameservers(smb_inaddr_t * ips,int sz)5588670SJose.Borrego@Sun.COM smb_get_nameservers(smb_inaddr_t *ips, int sz)
5596030Sjb150015 {
5606030Sjb150015 	union res_sockaddr_union set[MAXNS];
5616030Sjb150015 	int i, cnt;
5626030Sjb150015 	struct __res_state res_state;
5638670SJose.Borrego@Sun.COM 	char ipstr[INET6_ADDRSTRLEN];
5646030Sjb150015 
5656030Sjb150015 	if (ips == NULL)
5666030Sjb150015 		return (0);
5676030Sjb150015 
5686030Sjb150015 	bzero(&res_state, sizeof (struct __res_state));
5696030Sjb150015 	if (res_ninit(&res_state) < 0)
5706030Sjb150015 		return (0);
5716030Sjb150015 
5726030Sjb150015 	cnt = res_getservers(&res_state, set, MAXNS);
5736030Sjb150015 	for (i = 0; i < cnt; i++) {
5746030Sjb150015 		if (i >= sz)
5756030Sjb150015 			break;
5768670SJose.Borrego@Sun.COM 		ips[i].a_family = AF_INET;
5778670SJose.Borrego@Sun.COM 		bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv4, INADDRSZ);
5788670SJose.Borrego@Sun.COM 		if (inet_ntop(AF_INET, &ips[i].a_ipv4, ipstr,
5798670SJose.Borrego@Sun.COM 		    INET_ADDRSTRLEN)) {
5808670SJose.Borrego@Sun.COM 			syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
5818670SJose.Borrego@Sun.COM 			continue;
5828670SJose.Borrego@Sun.COM 		}
5838670SJose.Borrego@Sun.COM 		ips[i].a_family = AF_INET6;
5848670SJose.Borrego@Sun.COM 		bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv6, IPV6_ADDR_LEN);
5858670SJose.Borrego@Sun.COM 		if (inet_ntop(AF_INET6, &ips[i].a_ipv6, ipstr,
5868670SJose.Borrego@Sun.COM 		    INET6_ADDRSTRLEN)) {
5878670SJose.Borrego@Sun.COM 			syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
5888670SJose.Borrego@Sun.COM 		}
5896030Sjb150015 	}
5906030Sjb150015 	res_ndestroy(&res_state);
5916030Sjb150015 	return (i);
5926030Sjb150015 }
5939832Samw@Sun.COM 
5948334SJose.Borrego@Sun.COM /*
5958334SJose.Borrego@Sun.COM  * smb_gethostbyname
5968334SJose.Borrego@Sun.COM  *
5978334SJose.Borrego@Sun.COM  * Looks up a host by the given name. The host entry can come
5988334SJose.Borrego@Sun.COM  * from any of the sources for hosts specified in the
5998334SJose.Borrego@Sun.COM  * /etc/nsswitch.conf and the NetBIOS cache.
6008334SJose.Borrego@Sun.COM  *
6018334SJose.Borrego@Sun.COM  * XXX Invokes nbt_name_resolve API once the NBTD is integrated
6028334SJose.Borrego@Sun.COM  * to look in the NetBIOS cache if getipnodebyname fails.
6038334SJose.Borrego@Sun.COM  *
6048334SJose.Borrego@Sun.COM  * Caller should invoke freehostent to free the returned hostent.
6058334SJose.Borrego@Sun.COM  */
6068334SJose.Borrego@Sun.COM struct hostent *
smb_gethostbyname(const char * name,int * err_num)6078334SJose.Borrego@Sun.COM smb_gethostbyname(const char *name, int *err_num)
6088334SJose.Borrego@Sun.COM {
6098334SJose.Borrego@Sun.COM 	struct hostent *h;
6108334SJose.Borrego@Sun.COM 
6118334SJose.Borrego@Sun.COM 	h = getipnodebyname(name, AF_INET, 0, err_num);
6128670SJose.Borrego@Sun.COM 	if ((h == NULL) || h->h_length != INADDRSZ)
6138670SJose.Borrego@Sun.COM 		h = getipnodebyname(name, AF_INET6, AI_DEFAULT, err_num);
6148334SJose.Borrego@Sun.COM 	return (h);
6158334SJose.Borrego@Sun.COM }
6168334SJose.Borrego@Sun.COM 
6178334SJose.Borrego@Sun.COM /*
6188334SJose.Borrego@Sun.COM  * smb_gethostbyaddr
6198334SJose.Borrego@Sun.COM  *
6208334SJose.Borrego@Sun.COM  * Looks up a host by the given IP address. The host entry can come
6218334SJose.Borrego@Sun.COM  * from any of the sources for hosts specified in the
6228334SJose.Borrego@Sun.COM  * /etc/nsswitch.conf and the NetBIOS cache.
6238334SJose.Borrego@Sun.COM  *
6248334SJose.Borrego@Sun.COM  * XXX Invokes nbt API to resolve name by IP once the NBTD is integrated
6258334SJose.Borrego@Sun.COM  * to look in the NetBIOS cache if getipnodebyaddr fails.
6268334SJose.Borrego@Sun.COM  *
6278334SJose.Borrego@Sun.COM  * Caller should invoke freehostent to free the returned hostent.
6288334SJose.Borrego@Sun.COM  */
6298334SJose.Borrego@Sun.COM struct hostent *
smb_gethostbyaddr(const char * addr,int len,int type,int * err_num)6308334SJose.Borrego@Sun.COM smb_gethostbyaddr(const char *addr, int len, int type, int *err_num)
6318334SJose.Borrego@Sun.COM {
6328334SJose.Borrego@Sun.COM 	struct hostent *h;
6338334SJose.Borrego@Sun.COM 
6348334SJose.Borrego@Sun.COM 	h = getipnodebyaddr(addr, len, type, err_num);
6358334SJose.Borrego@Sun.COM 
6368334SJose.Borrego@Sun.COM 	return (h);
6378334SJose.Borrego@Sun.COM }
638