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.
2383d2dfe6SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
24da6c28aaSamw */
25da6c28aaSamw
268d7e4166Sjose borrego #include <assert.h>
27da6c28aaSamw #include <sys/types.h>
28da6c28aaSamw #include <stdarg.h>
29da6c28aaSamw #include <unistd.h>
30da6c28aaSamw #include <stdlib.h>
31da6c28aaSamw #include <time.h>
32da6c28aaSamw #include <synch.h>
33da6c28aaSamw #include <syslog.h>
34da6c28aaSamw #include <string.h>
35da6c28aaSamw #include <strings.h>
36da6c28aaSamw #include <errno.h>
37da6c28aaSamw #include <net/if.h>
38da6c28aaSamw #include <netdb.h>
39dc20a302Sas200622 #include <netinet/in.h>
40dc20a302Sas200622 #include <arpa/nameser.h>
41dc20a302Sas200622 #include <resolv.h>
42da6c28aaSamw #include <sys/sockio.h>
438d7e4166Sjose borrego #include <sys/socket.h>
44da6c28aaSamw #include <smbsrv/smbinfo.h>
45da6c28aaSamw #include <smbsrv/netbios.h>
46da6c28aaSamw #include <smbsrv/libsmb.h>
47da6c28aaSamw
48faa1795aSjb150015 static mutex_t seqnum_mtx;
49da6c28aaSamw
50eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States /*
51a0aa776eSAlan Wright * IPC connection information that may be passed to the SMB Redirector.
52a0aa776eSAlan Wright */
53a0aa776eSAlan Wright typedef struct {
54a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN];
55a0aa776eSAlan Wright uint8_t passwd[SMBAUTH_HASH_SZ];
56a0aa776eSAlan Wright } smb_ipc_t;
57a0aa776eSAlan Wright
58a0aa776eSAlan Wright static smb_ipc_t ipc_info;
59a0aa776eSAlan Wright static smb_ipc_t ipc_orig_info;
60a0aa776eSAlan Wright static rwlock_t smb_ipc_lock;
61a0aa776eSAlan Wright
62a0aa776eSAlan Wright /*
63eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * Some older clients (Windows 98) only handle the low byte
64eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * of the max workers value. If the low byte is less than
65eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States * SMB_PI_MAX_WORKERS_MIN set it to SMB_PI_MAX_WORKERS_MIN.
66eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States */
67da6c28aaSamw void
smb_load_kconfig(smb_kmod_cfg_t * kcfg)68da6c28aaSamw smb_load_kconfig(smb_kmod_cfg_t *kcfg)
69da6c28aaSamw {
70dc20a302Sas200622 int64_t citem;
71dc20a302Sas200622
72da6c28aaSamw bzero(kcfg, sizeof (smb_kmod_cfg_t));
73da6c28aaSamw
74dc20a302Sas200622 (void) smb_config_getnum(SMB_CI_MAX_WORKERS, &citem);
75dc20a302Sas200622 kcfg->skc_maxworkers = (uint32_t)citem;
76eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States if ((kcfg->skc_maxworkers & 0xFF) < SMB_PI_MAX_WORKERS_MIN) {
77eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States kcfg->skc_maxworkers &= ~0xFF;
78eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States kcfg->skc_maxworkers += SMB_PI_MAX_WORKERS_MIN;
79eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States }
80eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States
81dc20a302Sas200622 (void) smb_config_getnum(SMB_CI_KEEPALIVE, &citem);
82dc20a302Sas200622 kcfg->skc_keepalive = (uint32_t)citem;
83da6c28aaSamw if ((kcfg->skc_keepalive != 0) &&
84da6c28aaSamw (kcfg->skc_keepalive < SMB_PI_KEEP_ALIVE_MIN))
85da6c28aaSamw kcfg->skc_keepalive = SMB_PI_KEEP_ALIVE_MIN;
86da6c28aaSamw
87dc20a302Sas200622 (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &citem);
88dc20a302Sas200622 kcfg->skc_maxconnections = (uint32_t)citem;
89dc20a302Sas200622 kcfg->skc_restrict_anon = smb_config_getbool(SMB_CI_RESTRICT_ANON);
90dc20a302Sas200622 kcfg->skc_signing_enable = smb_config_getbool(SMB_CI_SIGNING_ENABLE);
91dc20a302Sas200622 kcfg->skc_signing_required = smb_config_getbool(SMB_CI_SIGNING_REQD);
9283d2dfe6SGordon Ross kcfg->skc_netbios_enable = smb_config_getbool(SMB_CI_NETBIOS_ENABLE);
937f667e74Sjose borrego kcfg->skc_ipv6_enable = smb_config_getbool(SMB_CI_IPV6_ENABLE);
94cb174861Sjoyce mcintosh kcfg->skc_print_enable = smb_config_getbool(SMB_CI_PRINT_ENABLE);
95dc20a302Sas200622 kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE);
96dc20a302Sas200622 kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE);
975f1ef25cSAram Hăvărneanu kcfg->skc_traverse_mounts = smb_config_getbool(SMB_CI_TRAVERSE_MOUNTS);
98da6c28aaSamw kcfg->skc_secmode = smb_config_get_secmode();
99b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getdomainname(kcfg->skc_nbdomain,
100b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_nbdomain));
101b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getfqdomainname(kcfg->skc_fqdn,
102b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_fqdn));
103b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) smb_getnetbiosname(kcfg->skc_hostname,
104b89a8333Snatalie li - Sun Microsystems - Irvine United States sizeof (kcfg->skc_hostname));
105dc20a302Sas200622 (void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment,
106da6c28aaSamw sizeof (kcfg->skc_system_comment));
1079fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_config_get_version(&kcfg->skc_version);
108148c5f43SAlan Wright kcfg->skc_execflags = smb_config_get_execinfo(NULL, NULL, 0);
109da6c28aaSamw }
110da6c28aaSamw
111da6c28aaSamw /*
112da6c28aaSamw * Get the current system NetBIOS name. The hostname is truncated at
113da6c28aaSamw * the first `.` or 15 bytes, whichever occurs first, and converted
114da6c28aaSamw * to uppercase (by smb_gethostname). Text that appears after the
115da6c28aaSamw * first '.' is considered to be part of the NetBIOS scope.
116da6c28aaSamw *
117da6c28aaSamw * Returns 0 on success, otherwise -1 to indicate an error.
118da6c28aaSamw */
119da6c28aaSamw int
smb_getnetbiosname(char * buf,size_t buflen)120da6c28aaSamw smb_getnetbiosname(char *buf, size_t buflen)
121da6c28aaSamw {
1229fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(buf, buflen, SMB_CASE_UPPER) != 0)
123da6c28aaSamw return (-1);
124da6c28aaSamw
125da6c28aaSamw if (buflen >= NETBIOS_NAME_SZ)
126da6c28aaSamw buf[NETBIOS_NAME_SZ - 1] = '\0';
127da6c28aaSamw
128da6c28aaSamw return (0);
129da6c28aaSamw }
130da6c28aaSamw
131da6c28aaSamw /*
132b89a8333Snatalie li - Sun Microsystems - Irvine United States * Get the SAM account of the current system.
133b89a8333Snatalie li - Sun Microsystems - Irvine United States * Returns 0 on success, otherwise, -1 to indicate an error.
134b89a8333Snatalie li - Sun Microsystems - Irvine United States */
135b89a8333Snatalie li - Sun Microsystems - Irvine United States int
smb_getsamaccount(char * buf,size_t buflen)136b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_getsamaccount(char *buf, size_t buflen)
137b89a8333Snatalie li - Sun Microsystems - Irvine United States {
138b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getnetbiosname(buf, buflen - 1) != 0)
139b89a8333Snatalie li - Sun Microsystems - Irvine United States return (-1);
140b89a8333Snatalie li - Sun Microsystems - Irvine United States
141b89a8333Snatalie li - Sun Microsystems - Irvine United States (void) strlcat(buf, "$", buflen);
142b89a8333Snatalie li - Sun Microsystems - Irvine United States return (0);
143b89a8333Snatalie li - Sun Microsystems - Irvine United States }
144b89a8333Snatalie li - Sun Microsystems - Irvine United States
145b89a8333Snatalie li - Sun Microsystems - Irvine United States /*
146da6c28aaSamw * Get the current system node name. The returned name is guaranteed
147da6c28aaSamw * to be null-terminated (gethostname may not null terminate the name).
148da6c28aaSamw * If the hostname has been fully-qualified for some reason, the domain
1499fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * part will be removed. The returned hostname is converted to the
1509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * specified case (lower, upper, or preserved).
151da6c28aaSamw *
152da6c28aaSamw * If gethostname fails, the returned buffer will contain an empty
153da6c28aaSamw * string.
154da6c28aaSamw */
155da6c28aaSamw int
smb_gethostname(char * buf,size_t buflen,smb_caseconv_t which)1569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_gethostname(char *buf, size_t buflen, smb_caseconv_t which)
157da6c28aaSamw {
158da6c28aaSamw char *p;
159da6c28aaSamw
160da6c28aaSamw if (buf == NULL || buflen == 0)
161da6c28aaSamw return (-1);
162da6c28aaSamw
163da6c28aaSamw if (gethostname(buf, buflen) != 0) {
164da6c28aaSamw *buf = '\0';
165da6c28aaSamw return (-1);
166da6c28aaSamw }
167da6c28aaSamw
168da6c28aaSamw buf[buflen - 1] = '\0';
169da6c28aaSamw
170da6c28aaSamw if ((p = strchr(buf, '.')) != NULL)
171da6c28aaSamw *p = '\0';
172da6c28aaSamw
1739fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States switch (which) {
1749fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_LOWER:
1759fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States (void) smb_strlwr(buf);
1769fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break;
1779fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
1789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_UPPER:
179bbf6f00cSJordan Brown (void) smb_strupr(buf);
1809fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break;
1819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
1829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case SMB_CASE_PRESERVE:
1839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States default:
1849fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break;
1859fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
186da6c28aaSamw
187da6c28aaSamw return (0);
188da6c28aaSamw }
189da6c28aaSamw
190da6c28aaSamw /*
1919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * Obtain the fully-qualified name for this machine in lower case. If
1929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * the hostname is fully-qualified, accept it. Otherwise, try to find an
1939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States * appropriate domain name to append to the hostname.
194da6c28aaSamw */
195da6c28aaSamw int
smb_getfqhostname(char * buf,size_t buflen)196da6c28aaSamw smb_getfqhostname(char *buf, size_t buflen)
197da6c28aaSamw {
198da6c28aaSamw char hostname[MAXHOSTNAMELEN];
199da6c28aaSamw char domain[MAXHOSTNAMELEN];
200da6c28aaSamw
201da6c28aaSamw hostname[0] = '\0';
202da6c28aaSamw domain[0] = '\0';
203da6c28aaSamw
2049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States if (smb_gethostname(hostname, MAXHOSTNAMELEN,
2059fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States SMB_CASE_LOWER) != 0)
206da6c28aaSamw return (-1);
207da6c28aaSamw
208dc20a302Sas200622 if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0)
209da6c28aaSamw return (-1);
210da6c28aaSamw
211da6c28aaSamw if (hostname[0] == '\0')
212da6c28aaSamw return (-1);
213da6c28aaSamw
214da6c28aaSamw if (domain[0] == '\0') {
215da6c28aaSamw (void) strlcpy(buf, hostname, buflen);
216da6c28aaSamw return (0);
217da6c28aaSamw }
218da6c28aaSamw
219da6c28aaSamw (void) snprintf(buf, buflen, "%s.%s", hostname, domain);
220da6c28aaSamw return (0);
221da6c28aaSamw }
222da6c28aaSamw
223da6c28aaSamw /*
224dc20a302Sas200622 * smb_getdomainname
225dc20a302Sas200622 *
226dc20a302Sas200622 * Returns NETBIOS name of the domain if the system is in domain
227dc20a302Sas200622 * mode. Or returns workgroup name if the system is in workgroup
228dc20a302Sas200622 * mode.
229dc20a302Sas200622 */
230dc20a302Sas200622 int
smb_getdomainname(char * buf,size_t buflen)231dc20a302Sas200622 smb_getdomainname(char *buf, size_t buflen)
232dc20a302Sas200622 {
233dc20a302Sas200622 int rc;
234dc20a302Sas200622
235dc20a302Sas200622 if (buf == NULL || buflen == 0)
236dc20a302Sas200622 return (-1);
237dc20a302Sas200622
238dc20a302Sas200622 *buf = '\0';
2398d7e4166Sjose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, buf, buflen);
240dc20a302Sas200622
2418d7e4166Sjose borrego if ((rc != SMBD_SMF_OK) || (*buf == '\0'))
242dc20a302Sas200622 return (-1);
243dc20a302Sas200622
244dc20a302Sas200622 return (0);
245dc20a302Sas200622 }
246dc20a302Sas200622
247dc20a302Sas200622 /*
248dc20a302Sas200622 * smb_getfqdomainname
249dc20a302Sas200622 *
2508d7e4166Sjose borrego * In the system is in domain mode, the dns_domain property value
2518d7e4166Sjose borrego * is returned. Otherwise, it returns the local domain obtained via
2528d7e4166Sjose borrego * resolver.
253dc20a302Sas200622 *
254dc20a302Sas200622 * Returns 0 upon success. Otherwise, returns -1.
255dc20a302Sas200622 */
256dc20a302Sas200622 int
smb_getfqdomainname(char * buf,size_t buflen)257dc20a302Sas200622 smb_getfqdomainname(char *buf, size_t buflen)
258dc20a302Sas200622 {
2598d7e4166Sjose borrego struct __res_state res_state;
2608d7e4166Sjose borrego int rc;
261dc20a302Sas200622
262dc20a302Sas200622 if (buf == NULL || buflen == 0)
263dc20a302Sas200622 return (-1);
264dc20a302Sas200622
265dc20a302Sas200622 *buf = '\0';
266dc20a302Sas200622 if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) {
2678d7e4166Sjose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_FQDN, buf, buflen);
268dc20a302Sas200622
2698d7e4166Sjose borrego if ((rc != SMBD_SMF_OK) || (*buf == '\0'))
2708d7e4166Sjose borrego return (-1);
2718d7e4166Sjose borrego } else {
2728d7e4166Sjose borrego bzero(&res_state, sizeof (struct __res_state));
2738d7e4166Sjose borrego if (res_ninit(&res_state))
274dc20a302Sas200622 return (-1);
275dc20a302Sas200622
2768d7e4166Sjose borrego if (*res_state.defdname == '\0') {
2778d7e4166Sjose borrego res_ndestroy(&res_state);
2788d7e4166Sjose borrego return (-1);
279dc20a302Sas200622 }
2808d7e4166Sjose borrego
2818d7e4166Sjose borrego (void) strlcpy(buf, res_state.defdname, buflen);
2828d7e4166Sjose borrego res_ndestroy(&res_state);
2838d7e4166Sjose borrego rc = 0;
284dc20a302Sas200622 }
285dc20a302Sas200622
286dc20a302Sas200622 return (rc);
287dc20a302Sas200622 }
288dc20a302Sas200622
289dc20a302Sas200622
290faa1795aSjb150015 /*
291faa1795aSjb150015 * smb_set_machine_passwd
292faa1795aSjb150015 *
293faa1795aSjb150015 * This function should be used when setting the machine password property.
294faa1795aSjb150015 * The associated sequence number is incremented.
295faa1795aSjb150015 */
296faa1795aSjb150015 static int
smb_set_machine_passwd(char * passwd)297faa1795aSjb150015 smb_set_machine_passwd(char *passwd)
298faa1795aSjb150015 {
299faa1795aSjb150015 int64_t num;
300faa1795aSjb150015 int rc = -1;
301faa1795aSjb150015
302faa1795aSjb150015 if (smb_config_set(SMB_CI_MACHINE_PASSWD, passwd) != SMBD_SMF_OK)
303faa1795aSjb150015 return (-1);
304faa1795aSjb150015
305faa1795aSjb150015 (void) mutex_lock(&seqnum_mtx);
306faa1795aSjb150015 (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num);
307faa1795aSjb150015 if (smb_config_setnum(SMB_CI_KPASSWD_SEQNUM, ++num)
308faa1795aSjb150015 == SMBD_SMF_OK)
309faa1795aSjb150015 rc = 0;
310faa1795aSjb150015 (void) mutex_unlock(&seqnum_mtx);
311faa1795aSjb150015 return (rc);
312faa1795aSjb150015 }
313faa1795aSjb150015
314a0aa776eSAlan Wright static int
smb_get_machine_passwd(uint8_t * buf,size_t buflen)315a0aa776eSAlan Wright smb_get_machine_passwd(uint8_t *buf, size_t buflen)
316a0aa776eSAlan Wright {
317a0aa776eSAlan Wright char pwd[SMB_PASSWD_MAXLEN + 1];
318a0aa776eSAlan Wright int rc;
319a0aa776eSAlan Wright
320a0aa776eSAlan Wright if (buflen < SMBAUTH_HASH_SZ)
321a0aa776eSAlan Wright return (-1);
322a0aa776eSAlan Wright
323a0aa776eSAlan Wright rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd));
324a0aa776eSAlan Wright if ((rc != SMBD_SMF_OK) || *pwd == '\0')
325a0aa776eSAlan Wright return (-1);
326a0aa776eSAlan Wright
327a0aa776eSAlan Wright if (smb_auth_ntlm_hash(pwd, buf) != 0)
328a0aa776eSAlan Wright return (-1);
329a0aa776eSAlan Wright
330a0aa776eSAlan Wright return (rc);
331a0aa776eSAlan Wright }
332a0aa776eSAlan Wright
333a0aa776eSAlan Wright /*
334a0aa776eSAlan Wright * Set up IPC connection credentials.
335a0aa776eSAlan Wright */
336a0aa776eSAlan Wright void
smb_ipc_init(void)337a0aa776eSAlan Wright smb_ipc_init(void)
338a0aa776eSAlan Wright {
339a0aa776eSAlan Wright int rc;
340a0aa776eSAlan Wright
341a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock);
342a0aa776eSAlan Wright bzero(&ipc_info, sizeof (smb_ipc_t));
343a0aa776eSAlan Wright bzero(&ipc_orig_info, sizeof (smb_ipc_t));
344a0aa776eSAlan Wright
345a0aa776eSAlan Wright (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
346a0aa776eSAlan Wright rc = smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ);
347a0aa776eSAlan Wright if (rc != 0)
348a0aa776eSAlan Wright *ipc_info.passwd = 0;
349a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock);
350a0aa776eSAlan Wright
351a0aa776eSAlan Wright }
352a0aa776eSAlan Wright
353a0aa776eSAlan Wright /*
354a0aa776eSAlan Wright * Set the IPC username and password hash in memory. If the domain
355a0aa776eSAlan Wright * join succeeds, the credentials will be committed for use with
356a0aa776eSAlan Wright * authenticated IPC. Otherwise, they should be rolled back.
357a0aa776eSAlan Wright */
358a0aa776eSAlan Wright void
smb_ipc_set(char * plain_user,uint8_t * passwd_hash)359a0aa776eSAlan Wright smb_ipc_set(char *plain_user, uint8_t *passwd_hash)
360a0aa776eSAlan Wright {
361a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock);
362a0aa776eSAlan Wright (void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user));
363a0aa776eSAlan Wright (void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ);
364a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock);
365a0aa776eSAlan Wright
366a0aa776eSAlan Wright }
367a0aa776eSAlan Wright
368a0aa776eSAlan Wright /*
369a0aa776eSAlan Wright * Save the host credentials to be used for authenticated IPC.
370a0aa776eSAlan Wright * The credentials are also saved to the original IPC info as
371a0aa776eSAlan Wright * rollback data in case the join domain process fails later.
372a0aa776eSAlan Wright */
373a0aa776eSAlan Wright void
smb_ipc_commit(void)374a0aa776eSAlan Wright smb_ipc_commit(void)
375a0aa776eSAlan Wright {
376a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock);
377a0aa776eSAlan Wright (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN);
378a0aa776eSAlan Wright (void) smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ);
379a0aa776eSAlan Wright (void) memcpy(&ipc_orig_info, &ipc_info, sizeof (smb_ipc_t));
380a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock);
381a0aa776eSAlan Wright }
382a0aa776eSAlan Wright
383a0aa776eSAlan Wright /*
384a0aa776eSAlan Wright * Restore the original credentials
385a0aa776eSAlan Wright */
386a0aa776eSAlan Wright void
smb_ipc_rollback(void)387a0aa776eSAlan Wright smb_ipc_rollback(void)
388a0aa776eSAlan Wright {
389a0aa776eSAlan Wright (void) rw_wrlock(&smb_ipc_lock);
390a0aa776eSAlan Wright (void) strlcpy(ipc_info.user, ipc_orig_info.user,
391a0aa776eSAlan Wright sizeof (ipc_info.user));
392a0aa776eSAlan Wright (void) memcpy(ipc_info.passwd, ipc_orig_info.passwd,
393a0aa776eSAlan Wright sizeof (ipc_info.passwd));
394a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock);
395a0aa776eSAlan Wright }
396a0aa776eSAlan Wright
397a0aa776eSAlan Wright void
smb_ipc_get_user(char * buf,size_t buflen)398a0aa776eSAlan Wright smb_ipc_get_user(char *buf, size_t buflen)
399a0aa776eSAlan Wright {
400a0aa776eSAlan Wright (void) rw_rdlock(&smb_ipc_lock);
401a0aa776eSAlan Wright (void) strlcpy(buf, ipc_info.user, buflen);
402a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock);
403a0aa776eSAlan Wright }
404a0aa776eSAlan Wright
405a0aa776eSAlan Wright void
smb_ipc_get_passwd(uint8_t * buf,size_t buflen)406a0aa776eSAlan Wright smb_ipc_get_passwd(uint8_t *buf, size_t buflen)
407a0aa776eSAlan Wright {
408a0aa776eSAlan Wright if (buflen < SMBAUTH_HASH_SZ)
409a0aa776eSAlan Wright return;
410a0aa776eSAlan Wright
411a0aa776eSAlan Wright (void) rw_rdlock(&smb_ipc_lock);
412a0aa776eSAlan Wright (void) memcpy(buf, ipc_info.passwd, SMBAUTH_HASH_SZ);
413a0aa776eSAlan Wright (void) rw_unlock(&smb_ipc_lock);
414a0aa776eSAlan Wright }
415a0aa776eSAlan Wright
416faa1795aSjb150015 /*
417faa1795aSjb150015 * smb_match_netlogon_seqnum
418faa1795aSjb150015 *
419faa1795aSjb150015 * A sequence number is associated with each machine password property
420faa1795aSjb150015 * update and the netlogon credential chain setup. If the
421faa1795aSjb150015 * sequence numbers don't match, a NETLOGON credential chain
422faa1795aSjb150015 * establishment is required.
423faa1795aSjb150015 *
424faa1795aSjb150015 * Returns 0 if kpasswd_seqnum equals to netlogon_seqnum. Otherwise,
425faa1795aSjb150015 * returns -1.
426faa1795aSjb150015 */
427faa1795aSjb150015 boolean_t
smb_match_netlogon_seqnum(void)428faa1795aSjb150015 smb_match_netlogon_seqnum(void)
429faa1795aSjb150015 {
430faa1795aSjb150015 int64_t setpasswd_seqnum;
431faa1795aSjb150015 int64_t netlogon_seqnum;
432faa1795aSjb150015
433faa1795aSjb150015 (void) mutex_lock(&seqnum_mtx);
434faa1795aSjb150015 (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &setpasswd_seqnum);
435faa1795aSjb150015 (void) smb_config_getnum(SMB_CI_NETLOGON_SEQNUM, &netlogon_seqnum);
436faa1795aSjb150015 (void) mutex_unlock(&seqnum_mtx);
437faa1795aSjb150015 return (setpasswd_seqnum == netlogon_seqnum);
438faa1795aSjb150015 }
439faa1795aSjb150015
440faa1795aSjb150015 /*
441faa1795aSjb150015 * smb_setdomainprops
442faa1795aSjb150015 *
443faa1795aSjb150015 * This function should be called after joining an AD to
444faa1795aSjb150015 * set all the domain related SMF properties.
445faa1795aSjb150015 *
446faa1795aSjb150015 * The kpasswd_domain property is the AD domain to which the system
447faa1795aSjb150015 * is joined via kclient. If this function is invoked by the SMB
448faa1795aSjb150015 * daemon, fqdn should be set to NULL.
449faa1795aSjb150015 */
450faa1795aSjb150015 int
smb_setdomainprops(char * fqdn,char * server,char * passwd)451faa1795aSjb150015 smb_setdomainprops(char *fqdn, char *server, char *passwd)
452faa1795aSjb150015 {
453faa1795aSjb150015 if (server == NULL || passwd == NULL)
454faa1795aSjb150015 return (-1);
455faa1795aSjb150015
456faa1795aSjb150015 if ((*server == '\0') || (*passwd == '\0'))
457faa1795aSjb150015 return (-1);
458faa1795aSjb150015
459faa1795aSjb150015 if (fqdn && (smb_config_set(SMB_CI_KPASSWD_DOMAIN, fqdn) != 0))
460faa1795aSjb150015 return (-1);
461faa1795aSjb150015
462faa1795aSjb150015 if (smb_config_set(SMB_CI_KPASSWD_SRV, server) != 0)
463faa1795aSjb150015 return (-1);
464faa1795aSjb150015
465faa1795aSjb150015 if (smb_set_machine_passwd(passwd) != 0) {
466faa1795aSjb150015 syslog(LOG_ERR, "smb_setdomainprops: failed to set"
467faa1795aSjb150015 " machine account password");
468faa1795aSjb150015 return (-1);
469faa1795aSjb150015 }
470faa1795aSjb150015
471faa1795aSjb150015 /*
472faa1795aSjb150015 * If we successfully create a trust account, we mark
473faa1795aSjb150015 * ourselves as a domain member in the environment so
474faa1795aSjb150015 * that we use the SAMLOGON version of the NETLOGON
475faa1795aSjb150015 * PDC location protocol.
476faa1795aSjb150015 */
477faa1795aSjb150015 (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_TRUE);
478faa1795aSjb150015
479faa1795aSjb150015 return (0);
480faa1795aSjb150015 }
481faa1795aSjb150015
482faa1795aSjb150015 /*
483faa1795aSjb150015 * smb_update_netlogon_seqnum
484faa1795aSjb150015 *
485faa1795aSjb150015 * This function should only be called upon a successful netlogon
486faa1795aSjb150015 * credential chain establishment to set the sequence number of the
487faa1795aSjb150015 * netlogon to match with that of the kpasswd.
488faa1795aSjb150015 */
489faa1795aSjb150015 void
smb_update_netlogon_seqnum(void)490faa1795aSjb150015 smb_update_netlogon_seqnum(void)
491faa1795aSjb150015 {
492faa1795aSjb150015 int64_t num;
493faa1795aSjb150015
494faa1795aSjb150015 (void) mutex_lock(&seqnum_mtx);
495faa1795aSjb150015 (void) smb_config_getnum(SMB_CI_KPASSWD_SEQNUM, &num);
496faa1795aSjb150015 (void) smb_config_setnum(SMB_CI_NETLOGON_SEQNUM, num);
497faa1795aSjb150015 (void) mutex_unlock(&seqnum_mtx);
498faa1795aSjb150015 }
499faa1795aSjb150015
500dc20a302Sas200622
501dc20a302Sas200622 /*
502da6c28aaSamw * Temporary fbt for dtrace until user space sdt enabled.
503da6c28aaSamw */
504da6c28aaSamw void
smb_tracef(const char * fmt,...)505da6c28aaSamw smb_tracef(const char *fmt, ...)
506da6c28aaSamw {
507da6c28aaSamw va_list ap;
508da6c28aaSamw char buf[128];
509da6c28aaSamw
510da6c28aaSamw va_start(ap, fmt);
511da6c28aaSamw (void) vsnprintf(buf, 128, fmt, ap);
512da6c28aaSamw va_end(ap);
513da6c28aaSamw
514da6c28aaSamw smb_trace(buf);
515da6c28aaSamw }
516da6c28aaSamw
517da6c28aaSamw /*
518da6c28aaSamw * Temporary fbt for dtrace until user space sdt enabled.
519*b819cea2SGordon Ross *
520*b819cea2SGordon Ross * This function is designed to be used with dtrace, i.e. see:
521*b819cea2SGordon Ross * usr/src/cmd/smbsrv/dtrace/smbd-all.d
522*b819cea2SGordon Ross *
523*b819cea2SGordon Ross * Outside of dtrace, the messages passed to this function usually
524*b819cea2SGordon Ross * lack sufficient context to be useful, so we don't log them.
525da6c28aaSamw */
526*b819cea2SGordon Ross /* ARGSUSED */
527da6c28aaSamw void
smb_trace(const char * s)528da6c28aaSamw smb_trace(const char *s)
529da6c28aaSamw {
530da6c28aaSamw }
5317b59d02dSjb150015
5327b59d02dSjb150015 /*
5337b59d02dSjb150015 * smb_tonetbiosname
5347b59d02dSjb150015 *
5357b59d02dSjb150015 * Creates a NetBIOS name based on the given name and suffix.
5367b59d02dSjb150015 * NetBIOS name is 15 capital characters, padded with space if needed
5377b59d02dSjb150015 * and the 16th byte is the suffix.
5387b59d02dSjb150015 */
5397b59d02dSjb150015 void
smb_tonetbiosname(char * name,char * nb_name,char suffix)5407b59d02dSjb150015 smb_tonetbiosname(char *name, char *nb_name, char suffix)
5417b59d02dSjb150015 {
5427b59d02dSjb150015 char tmp_name[NETBIOS_NAME_SZ];
543bbf6f00cSJordan Brown smb_wchar_t wtmp_name[NETBIOS_NAME_SZ];
5447b59d02dSjb150015 int len;
5457b59d02dSjb150015 size_t rc;
5467b59d02dSjb150015
5477b59d02dSjb150015 len = 0;
548bbf6f00cSJordan Brown rc = smb_mbstowcs(wtmp_name, (const char *)name, NETBIOS_NAME_SZ);
5497b59d02dSjb150015
5507b59d02dSjb150015 if (rc != (size_t)-1) {
5517b59d02dSjb150015 wtmp_name[NETBIOS_NAME_SZ - 1] = 0;
552bbf6f00cSJordan Brown rc = ucstooem(tmp_name, wtmp_name, NETBIOS_NAME_SZ,
553bbf6f00cSJordan Brown OEM_CPG_850);
5547b59d02dSjb150015 if (rc > 0)
5557b59d02dSjb150015 len = strlen(tmp_name);
5567b59d02dSjb150015 }
5577b59d02dSjb150015
5587b59d02dSjb150015 (void) memset(nb_name, ' ', NETBIOS_NAME_SZ - 1);
5597b59d02dSjb150015 if (len) {
560bbf6f00cSJordan Brown (void) smb_strupr(tmp_name);
5617b59d02dSjb150015 (void) memcpy(nb_name, tmp_name, len);
5627b59d02dSjb150015 }
5637b59d02dSjb150015 nb_name[NETBIOS_NAME_SZ - 1] = suffix;
5647b59d02dSjb150015 }
5657b59d02dSjb150015
5667b59d02dSjb150015 int
smb_get_nameservers(smb_inaddr_t * ips,int sz)5677f667e74Sjose borrego smb_get_nameservers(smb_inaddr_t *ips, int sz)
5687b59d02dSjb150015 {
5697b59d02dSjb150015 union res_sockaddr_union set[MAXNS];
5707b59d02dSjb150015 int i, cnt;
5717b59d02dSjb150015 struct __res_state res_state;
5727f667e74Sjose borrego char ipstr[INET6_ADDRSTRLEN];
5737b59d02dSjb150015
5747b59d02dSjb150015 if (ips == NULL)
5757b59d02dSjb150015 return (0);
5767b59d02dSjb150015
5777b59d02dSjb150015 bzero(&res_state, sizeof (struct __res_state));
5787b59d02dSjb150015 if (res_ninit(&res_state) < 0)
5797b59d02dSjb150015 return (0);
5807b59d02dSjb150015
5817b59d02dSjb150015 cnt = res_getservers(&res_state, set, MAXNS);
5827b59d02dSjb150015 for (i = 0; i < cnt; i++) {
5837b59d02dSjb150015 if (i >= sz)
5847b59d02dSjb150015 break;
5857f667e74Sjose borrego ips[i].a_family = AF_INET;
586*b819cea2SGordon Ross bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv4, NS_INADDRSZ);
5877f667e74Sjose borrego if (inet_ntop(AF_INET, &ips[i].a_ipv4, ipstr,
5887f667e74Sjose borrego INET_ADDRSTRLEN)) {
5897f667e74Sjose borrego syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
5907f667e74Sjose borrego continue;
5917b59d02dSjb150015 }
5927f667e74Sjose borrego ips[i].a_family = AF_INET6;
593*b819cea2SGordon Ross bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv6, NS_IN6ADDRSZ);
5947f667e74Sjose borrego if (inet_ntop(AF_INET6, &ips[i].a_ipv6, ipstr,
5957f667e74Sjose borrego INET6_ADDRSTRLEN)) {
5967f667e74Sjose borrego syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
5977f667e74Sjose borrego }
5987f667e74Sjose borrego }
5997b59d02dSjb150015 res_ndestroy(&res_state);
6007b59d02dSjb150015 return (i);
6017b59d02dSjb150015 }
60229bd2886SAlan Wright
6038d7e4166Sjose borrego /*
6048d7e4166Sjose borrego * smb_gethostbyname
6058d7e4166Sjose borrego *
6068d7e4166Sjose borrego * Looks up a host by the given name. The host entry can come
6078d7e4166Sjose borrego * from any of the sources for hosts specified in the
6088d7e4166Sjose borrego * /etc/nsswitch.conf and the NetBIOS cache.
6098d7e4166Sjose borrego *
6108d7e4166Sjose borrego * XXX Invokes nbt_name_resolve API once the NBTD is integrated
6118d7e4166Sjose borrego * to look in the NetBIOS cache if getipnodebyname fails.
6128d7e4166Sjose borrego *
6138d7e4166Sjose borrego * Caller should invoke freehostent to free the returned hostent.
6148d7e4166Sjose borrego */
6158d7e4166Sjose borrego struct hostent *
smb_gethostbyname(const char * name,int * err_num)6168d7e4166Sjose borrego smb_gethostbyname(const char *name, int *err_num)
6178d7e4166Sjose borrego {
6188d7e4166Sjose borrego struct hostent *h;
6198d7e4166Sjose borrego
6208d7e4166Sjose borrego h = getipnodebyname(name, AF_INET, 0, err_num);
6217f667e74Sjose borrego if ((h == NULL) || h->h_length != INADDRSZ)
6227f667e74Sjose borrego h = getipnodebyname(name, AF_INET6, AI_DEFAULT, err_num);
6238d7e4166Sjose borrego return (h);
6248d7e4166Sjose borrego }
6258d7e4166Sjose borrego
6268d7e4166Sjose borrego /*
6278d7e4166Sjose borrego * smb_gethostbyaddr
6288d7e4166Sjose borrego *
6298d7e4166Sjose borrego * Looks up a host by the given IP address. The host entry can come
6308d7e4166Sjose borrego * from any of the sources for hosts specified in the
6318d7e4166Sjose borrego * /etc/nsswitch.conf and the NetBIOS cache.
6328d7e4166Sjose borrego *
6338d7e4166Sjose borrego * XXX Invokes nbt API to resolve name by IP once the NBTD is integrated
6348d7e4166Sjose borrego * to look in the NetBIOS cache if getipnodebyaddr fails.
6358d7e4166Sjose borrego *
6368d7e4166Sjose borrego * Caller should invoke freehostent to free the returned hostent.
6378d7e4166Sjose borrego */
6388d7e4166Sjose borrego struct hostent *
smb_gethostbyaddr(const char * addr,int len,int type,int * err_num)6398d7e4166Sjose borrego smb_gethostbyaddr(const char *addr, int len, int type, int *err_num)
6408d7e4166Sjose borrego {
6418d7e4166Sjose borrego struct hostent *h;
6428d7e4166Sjose borrego
6438d7e4166Sjose borrego h = getipnodebyaddr(addr, len, type, err_num);
6448d7e4166Sjose borrego
6458d7e4166Sjose borrego return (h);
6468d7e4166Sjose borrego }
647