xref: /titanic_44/usr/src/cmd/smbsrv/smbd/smbd_join.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
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  */
21148c5f43SAlan Wright 
22da6c28aaSamw /*
23148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
241ed6b69aSGordon Ross  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
25da6c28aaSamw  */
26da6c28aaSamw 
27da6c28aaSamw #include <syslog.h>
28da6c28aaSamw #include <synch.h>
29da6c28aaSamw #include <pthread.h>
30da6c28aaSamw #include <unistd.h>
31da6c28aaSamw #include <string.h>
32da6c28aaSamw #include <strings.h>
33da6c28aaSamw #include <sys/errno.h>
34da6c28aaSamw 
35da6c28aaSamw #include <smbsrv/libsmb.h>
36da6c28aaSamw #include <smbsrv/libsmbns.h>
37da6c28aaSamw #include <smbsrv/libmlsvc.h>
38da6c28aaSamw #include <smbsrv/smbinfo.h>
398d7e4166Sjose borrego #include "smbd.h"
408d7e4166Sjose borrego 
411fdeec65Sjoyce mcintosh #define	SMBD_DC_MONITOR_ATTEMPTS		3
421fdeec65Sjoyce mcintosh #define	SMBD_DC_MONITOR_RETRY_INTERVAL		3	/* seconds */
431fdeec65Sjoyce mcintosh #define	SMBD_DC_MONITOR_INTERVAL		60	/* seconds */
44da6c28aaSamw 
451fdeec65Sjoyce mcintosh extern smbd_t smbd;
468d7e4166Sjose borrego 
47fd9ee8b5Sjoyce mcintosh static mutex_t smbd_dc_mutex;
48fd9ee8b5Sjoyce mcintosh static cond_t smbd_dc_cv;
49fd9ee8b5Sjoyce mcintosh 
501fdeec65Sjoyce mcintosh static void *smbd_dc_monitor(void *);
511fdeec65Sjoyce mcintosh static void smbd_dc_update(void);
521ed6b69aSGordon Ross /* Todo: static boolean_t smbd_set_netlogon_cred(void); */
538d7e4166Sjose borrego static uint32_t smbd_join_workgroup(smb_joininfo_t *);
548d7e4166Sjose borrego static uint32_t smbd_join_domain(smb_joininfo_t *);
55da6c28aaSamw 
56da6c28aaSamw /*
571fdeec65Sjoyce mcintosh  * Launch the DC discovery and monitor thread.
581fdeec65Sjoyce mcintosh  */
591fdeec65Sjoyce mcintosh int
smbd_dc_monitor_init(void)601fdeec65Sjoyce mcintosh smbd_dc_monitor_init(void)
611fdeec65Sjoyce mcintosh {
621fdeec65Sjoyce mcintosh 	pthread_attr_t	attr;
631fdeec65Sjoyce mcintosh 	int		rc;
641fdeec65Sjoyce mcintosh 
65fd9ee8b5Sjoyce mcintosh 	(void) smb_config_getstr(SMB_CI_ADS_SITE, smbd.s_site,
66fd9ee8b5Sjoyce mcintosh 	    MAXHOSTNAMELEN);
67fd9ee8b5Sjoyce mcintosh 	(void) smb_config_getip(SMB_CI_DOMAIN_SRV, &smbd.s_pdc);
681fdeec65Sjoyce mcintosh 	smb_ads_init();
691fdeec65Sjoyce mcintosh 
701fdeec65Sjoyce mcintosh 	if (smbd.s_secmode != SMB_SECMODE_DOMAIN)
711fdeec65Sjoyce mcintosh 		return (0);
721fdeec65Sjoyce mcintosh 
731fdeec65Sjoyce mcintosh 	(void) pthread_attr_init(&attr);
741fdeec65Sjoyce mcintosh 	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
751fdeec65Sjoyce mcintosh 	rc = pthread_create(&smbd.s_dc_monitor_tid, &attr, smbd_dc_monitor,
761fdeec65Sjoyce mcintosh 	    NULL);
771fdeec65Sjoyce mcintosh 	(void) pthread_attr_destroy(&attr);
781fdeec65Sjoyce mcintosh 	return (rc);
791fdeec65Sjoyce mcintosh }
801fdeec65Sjoyce mcintosh 
81fd9ee8b5Sjoyce mcintosh void
smbd_dc_monitor_refresh(void)82fd9ee8b5Sjoyce mcintosh smbd_dc_monitor_refresh(void)
83fd9ee8b5Sjoyce mcintosh {
84fd9ee8b5Sjoyce mcintosh 	char		site[MAXHOSTNAMELEN];
85fd9ee8b5Sjoyce mcintosh 	smb_inaddr_t	pdc;
86fd9ee8b5Sjoyce mcintosh 
87fd9ee8b5Sjoyce mcintosh 	site[0] = '\0';
88fd9ee8b5Sjoyce mcintosh 	bzero(&pdc, sizeof (smb_inaddr_t));
89fd9ee8b5Sjoyce mcintosh 	(void) smb_config_getstr(SMB_CI_ADS_SITE, site, MAXHOSTNAMELEN);
90fd9ee8b5Sjoyce mcintosh 	(void) smb_config_getip(SMB_CI_DOMAIN_SRV, &pdc);
91fd9ee8b5Sjoyce mcintosh 
92fd9ee8b5Sjoyce mcintosh 	(void) mutex_lock(&smbd_dc_mutex);
93fd9ee8b5Sjoyce mcintosh 
94fd9ee8b5Sjoyce mcintosh 	if ((bcmp(&smbd.s_pdc, &pdc, sizeof (smb_inaddr_t)) != 0) ||
95fd9ee8b5Sjoyce mcintosh 	    (smb_strcasecmp(smbd.s_site, site, 0) != 0)) {
96fd9ee8b5Sjoyce mcintosh 		bcopy(&pdc, &smbd.s_pdc, sizeof (smb_inaddr_t));
97fd9ee8b5Sjoyce mcintosh 		(void) strlcpy(smbd.s_site, site, MAXHOSTNAMELEN);
98fd9ee8b5Sjoyce mcintosh 		smbd.s_pdc_changed = B_TRUE;
99fd9ee8b5Sjoyce mcintosh 		(void) cond_signal(&smbd_dc_cv);
100fd9ee8b5Sjoyce mcintosh 	}
101fd9ee8b5Sjoyce mcintosh 
102fd9ee8b5Sjoyce mcintosh 	(void) mutex_unlock(&smbd_dc_mutex);
103fd9ee8b5Sjoyce mcintosh }
104fd9ee8b5Sjoyce mcintosh 
1051fdeec65Sjoyce mcintosh /*ARGSUSED*/
1061fdeec65Sjoyce mcintosh static void *
smbd_dc_monitor(void * arg)1071fdeec65Sjoyce mcintosh smbd_dc_monitor(void *arg)
1081fdeec65Sjoyce mcintosh {
1091fdeec65Sjoyce mcintosh 	boolean_t	ds_not_responding = B_FALSE;
110fd9ee8b5Sjoyce mcintosh 	boolean_t	ds_cfg_changed = B_FALSE;
111fd9ee8b5Sjoyce mcintosh 	timestruc_t	delay;
1121fdeec65Sjoyce mcintosh 	int		i;
1131fdeec65Sjoyce mcintosh 
1141fdeec65Sjoyce mcintosh 	smbd_dc_update();
1151fdeec65Sjoyce mcintosh 	smbd_online_wait("smbd_dc_monitor");
1161fdeec65Sjoyce mcintosh 
1171fdeec65Sjoyce mcintosh 	while (smbd_online()) {
118fd9ee8b5Sjoyce mcintosh 		delay.tv_sec = SMBD_DC_MONITOR_INTERVAL;
119fd9ee8b5Sjoyce mcintosh 		delay.tv_nsec = 0;
120fd9ee8b5Sjoyce mcintosh 
121fd9ee8b5Sjoyce mcintosh 		(void) mutex_lock(&smbd_dc_mutex);
122fd9ee8b5Sjoyce mcintosh 		(void) cond_reltimedwait(&smbd_dc_cv, &smbd_dc_mutex, &delay);
123fd9ee8b5Sjoyce mcintosh 
124fd9ee8b5Sjoyce mcintosh 		if (smbd.s_pdc_changed) {
125fd9ee8b5Sjoyce mcintosh 			smbd.s_pdc_changed = B_FALSE;
126fd9ee8b5Sjoyce mcintosh 			ds_cfg_changed = B_TRUE;
127fd9ee8b5Sjoyce mcintosh 		}
128fd9ee8b5Sjoyce mcintosh 
129fd9ee8b5Sjoyce mcintosh 		(void) mutex_unlock(&smbd_dc_mutex);
1301fdeec65Sjoyce mcintosh 
1311fdeec65Sjoyce mcintosh 		for (i = 0; i < SMBD_DC_MONITOR_ATTEMPTS; ++i) {
1321fdeec65Sjoyce mcintosh 			if (dssetup_check_service() == 0) {
1331fdeec65Sjoyce mcintosh 				ds_not_responding = B_FALSE;
1341fdeec65Sjoyce mcintosh 				break;
1351fdeec65Sjoyce mcintosh 			}
1361fdeec65Sjoyce mcintosh 
1371fdeec65Sjoyce mcintosh 			ds_not_responding = B_TRUE;
1381fdeec65Sjoyce mcintosh 			(void) sleep(SMBD_DC_MONITOR_RETRY_INTERVAL);
1391fdeec65Sjoyce mcintosh 		}
1401fdeec65Sjoyce mcintosh 
141fd9ee8b5Sjoyce mcintosh 		if (ds_not_responding)
142*b819cea2SGordon Ross 			syslog(LOG_NOTICE,
1431fdeec65Sjoyce mcintosh 			    "smbd_dc_monitor: domain service not responding");
1441fdeec65Sjoyce mcintosh 
145fd9ee8b5Sjoyce mcintosh 		if (ds_not_responding || ds_cfg_changed) {
146fd9ee8b5Sjoyce mcintosh 			ds_cfg_changed = B_FALSE;
1471fdeec65Sjoyce mcintosh 			smb_ads_refresh();
1481fdeec65Sjoyce mcintosh 			smbd_dc_update();
1491fdeec65Sjoyce mcintosh 		}
1501fdeec65Sjoyce mcintosh 	}
1511fdeec65Sjoyce mcintosh 
1521fdeec65Sjoyce mcintosh 	smbd.s_dc_monitor_tid = 0;
1531fdeec65Sjoyce mcintosh 	return (NULL);
1541fdeec65Sjoyce mcintosh }
1551fdeec65Sjoyce mcintosh 
1561fdeec65Sjoyce mcintosh /*
1571fdeec65Sjoyce mcintosh  * Locate a domain controller in the current resource domain and Update
1581fdeec65Sjoyce mcintosh  * the Netlogon credential chain.
1591fdeec65Sjoyce mcintosh  *
1601fdeec65Sjoyce mcintosh  * The domain configuration will be updated upon successful DC discovery.
1611fdeec65Sjoyce mcintosh  */
1621fdeec65Sjoyce mcintosh static void
smbd_dc_update(void)1631fdeec65Sjoyce mcintosh smbd_dc_update(void)
1641fdeec65Sjoyce mcintosh {
1651fdeec65Sjoyce mcintosh 	char		domain[MAXHOSTNAMELEN];
1661fdeec65Sjoyce mcintosh 	smb_domainex_t	info;
1671ed6b69aSGordon Ross 	smb_domain_t	*di;
1681ed6b69aSGordon Ross 	DWORD		status;
1691fdeec65Sjoyce mcintosh 
1701fdeec65Sjoyce mcintosh 	if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) {
1711fdeec65Sjoyce mcintosh 		(void) smb_getdomainname(domain, MAXHOSTNAMELEN);
1721fdeec65Sjoyce mcintosh 		(void) smb_strupr(domain);
1731fdeec65Sjoyce mcintosh 	}
1741fdeec65Sjoyce mcintosh 
1751fdeec65Sjoyce mcintosh 	if (!smb_locate_dc(domain, "", &info)) {
176*b819cea2SGordon Ross 		syslog(LOG_NOTICE,
1771fdeec65Sjoyce mcintosh 		    "smbd_dc_update: %s: locate failed", domain);
1781ed6b69aSGordon Ross 		return;
1791fdeec65Sjoyce mcintosh 	}
1801fdeec65Sjoyce mcintosh 
1811ed6b69aSGordon Ross 	di = &info.d_primary;
182*b819cea2SGordon Ross 	syslog(LOG_INFO,
1831ed6b69aSGordon Ross 	    "smbd_dc_update: %s: located %s", domain, info.d_dc);
1841ed6b69aSGordon Ross 
1851ed6b69aSGordon Ross 	status = mlsvc_netlogon(info.d_dc, di->di_nbname);
1861ed6b69aSGordon Ross 	if (status != NT_STATUS_SUCCESS) {
1871ed6b69aSGordon Ross 		syslog(LOG_NOTICE,
1881ed6b69aSGordon Ross 		    "failed to establish NETLOGON credential chain");
1891ed6b69aSGordon Ross 
1901fdeec65Sjoyce mcintosh 		/*
1911fdeec65Sjoyce mcintosh 		 * Restart required because the domain changed
1921fdeec65Sjoyce mcintosh 		 * or the credential chain setup failed.
1931fdeec65Sjoyce mcintosh 		 */
194*b819cea2SGordon Ross 		syslog(LOG_NOTICE,
1951ed6b69aSGordon Ross 		    "smbd_dc_update: smb/server restart required");
1961fdeec65Sjoyce mcintosh 
1971fdeec65Sjoyce mcintosh 		if (smb_smf_restart_service() != 0)
198*b819cea2SGordon Ross 			syslog(LOG_ERR,
1991fdeec65Sjoyce mcintosh 			    "restart failed: run 'svcs -xv smb/server'"
2001fdeec65Sjoyce mcintosh 			    " for more information");
2011fdeec65Sjoyce mcintosh 	}
2021fdeec65Sjoyce mcintosh }
2031fdeec65Sjoyce mcintosh 
2041fdeec65Sjoyce mcintosh /*
2058d7e4166Sjose borrego  * smbd_join
2068d7e4166Sjose borrego  *
2078d7e4166Sjose borrego  * Joins the specified domain/workgroup.
2088d7e4166Sjose borrego  *
2098d7e4166Sjose borrego  * If the security mode or domain name is being changed,
2108d7e4166Sjose borrego  * the caller must restart the service.
211da6c28aaSamw  */
2128d7e4166Sjose borrego uint32_t
smbd_join(smb_joininfo_t * info)2138d7e4166Sjose borrego smbd_join(smb_joininfo_t *info)
214da6c28aaSamw {
2158d7e4166Sjose borrego 	uint32_t status;
216da6c28aaSamw 
2178d7e4166Sjose borrego 	dssetup_clear_domain_info();
2188d7e4166Sjose borrego 	if (info->mode == SMB_SECMODE_WORKGRP)
2198d7e4166Sjose borrego 		status = smbd_join_workgroup(info);
2208d7e4166Sjose borrego 	else
2218d7e4166Sjose borrego 		status = smbd_join_domain(info);
2228d7e4166Sjose borrego 
2238d7e4166Sjose borrego 	return (status);
224da6c28aaSamw }
225da6c28aaSamw 
2268d7e4166Sjose borrego static uint32_t
smbd_join_workgroup(smb_joininfo_t * info)2278d7e4166Sjose borrego smbd_join_workgroup(smb_joininfo_t *info)
228da6c28aaSamw {
2298d7e4166Sjose borrego 	char nb_domain[SMB_PI_MAX_DOMAIN];
230faa1795aSjb150015 
2318d7e4166Sjose borrego 	(void) smb_config_getstr(SMB_CI_DOMAIN_NAME, nb_domain,
2328d7e4166Sjose borrego 	    sizeof (nb_domain));
233da6c28aaSamw 
2348d7e4166Sjose borrego 	smbd_set_secmode(SMB_SECMODE_WORKGRP);
23529bd2886SAlan Wright 	smb_config_setdomaininfo(info->domain_name, "", "", "", "");
2367b59d02dSjb150015 
2378d7e4166Sjose borrego 	if (strcasecmp(nb_domain, info->domain_name))
2387b59d02dSjb150015 		smb_browser_reconfig();
2397b59d02dSjb150015 
240da6c28aaSamw 	return (NT_STATUS_SUCCESS);
241da6c28aaSamw }
242da6c28aaSamw 
2438d7e4166Sjose borrego static uint32_t
smbd_join_domain(smb_joininfo_t * info)2448d7e4166Sjose borrego smbd_join_domain(smb_joininfo_t *info)
2458d7e4166Sjose borrego {
2461ed6b69aSGordon Ross 	static unsigned char zero_hash[SMBAUTH_HASH_SZ];
247a0aa776eSAlan Wright 	smb_domainex_t dxi;
248a0aa776eSAlan Wright 	smb_domain_t *di;
2491ed6b69aSGordon Ross 	uint32_t status;
2508d7e4166Sjose borrego 
251da6c28aaSamw 	/*
252da6c28aaSamw 	 * Ensure that any previous membership of this domain has
253da6c28aaSamw 	 * been cleared from the environment before we start. This
254da6c28aaSamw 	 * will ensure that we don't attempt a NETLOGON_SAMLOGON
255da6c28aaSamw 	 * when attempting to find the PDC.
256da6c28aaSamw 	 */
257dc20a302Sas200622 	(void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_FALSE);
258da6c28aaSamw 
2591ed6b69aSGordon Ross 	/* Clear DNS local (ADS) lookup cache too. */
2601ed6b69aSGordon Ross 	smb_ads_refresh();
2611ed6b69aSGordon Ross 
2621ed6b69aSGordon Ross 	/*
2631ed6b69aSGordon Ross 	 * Use a NULL session while searching for a DC, and
2641ed6b69aSGordon Ross 	 * while getting information about the domain.
2651ed6b69aSGordon Ross 	 */
2661ed6b69aSGordon Ross 	smb_ipc_set(MLSVC_ANON_USER, zero_hash);
2671ed6b69aSGordon Ross 
2681ed6b69aSGordon Ross 	if (!smb_locate_dc(info->domain_name, "", &dxi)) {
2691ed6b69aSGordon Ross 		syslog(LOG_ERR, "smbd: failed locating "
2701ed6b69aSGordon Ross 		    "domain controller for %s",
2711ed6b69aSGordon Ross 		    info->domain_name);
2721ed6b69aSGordon Ross 		status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
2731ed6b69aSGordon Ross 		goto errout;
274dc20a302Sas200622 	}
275da6c28aaSamw 
2768d7e4166Sjose borrego 	/* info->domain_name could either be NetBIOS domain name or FQDN */
2771ed6b69aSGordon Ross 	status = mlsvc_join(&dxi, info->domain_username, info->domain_passwd);
2781ed6b69aSGordon Ross 	if (status != NT_STATUS_SUCCESS) {
2791ed6b69aSGordon Ross 		syslog(LOG_ERR, "smbd: failed joining %s (%s)",
2801ed6b69aSGordon Ross 		    info->domain_name, xlate_nt_status(status));
2811ed6b69aSGordon Ross 		goto errout;
2821ed6b69aSGordon Ross 	}
283da6c28aaSamw 
2841ed6b69aSGordon Ross 	/*
2851ed6b69aSGordon Ross 	 * Success!
2861ed6b69aSGordon Ross 	 *
2871ed6b69aSGordon Ross 	 * Strange, mlsvc_join does some of the work to
2881ed6b69aSGordon Ross 	 * save the config, then the rest happens here.
2891ed6b69aSGordon Ross 	 * Todo: Do the config update all in one place.
2901ed6b69aSGordon Ross 	 */
291a0aa776eSAlan Wright 	di = &dxi.d_primary;
2928d7e4166Sjose borrego 	smbd_set_secmode(SMB_SECMODE_DOMAIN);
29329bd2886SAlan Wright 	smb_config_setdomaininfo(di->di_nbname, di->di_fqname,
29429bd2886SAlan Wright 	    di->di_sid,
29529bd2886SAlan Wright 	    di->di_u.di_dns.ddi_forest,
29629bd2886SAlan Wright 	    di->di_u.di_dns.ddi_guid);
297a0aa776eSAlan Wright 	smb_ipc_commit();
298da6c28aaSamw 	return (status);
299da6c28aaSamw 
3001ed6b69aSGordon Ross errout:
301a0aa776eSAlan Wright 	smb_ipc_rollback();
302da6c28aaSamw 	return (status);
303da6c28aaSamw }
304