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