xref: /onnv-gate/usr/src/cmd/smbsrv/smbd/smbd_join.c (revision 13082:81ec56bf6147)
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  */
2112508Samw@Sun.COM 
225331Samw /*
2312508Samw@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
245331Samw  */
255331Samw 
265331Samw #include <syslog.h>
275331Samw #include <synch.h>
285331Samw #include <pthread.h>
295331Samw #include <unistd.h>
305331Samw #include <string.h>
315331Samw #include <strings.h>
325331Samw #include <sys/errno.h>
335331Samw 
345331Samw #include <smbsrv/libsmb.h>
355331Samw #include <smbsrv/libsmbns.h>
365331Samw #include <smbsrv/libmlsvc.h>
375331Samw #include <smbsrv/smbinfo.h>
388334SJose.Borrego@Sun.COM #include "smbd.h"
398334SJose.Borrego@Sun.COM 
4012914SJoyce.McIntosh@Sun.COM #define	SMBD_DC_MONITOR_ATTEMPTS		3
4112914SJoyce.McIntosh@Sun.COM #define	SMBD_DC_MONITOR_RETRY_INTERVAL		3	/* seconds */
4212914SJoyce.McIntosh@Sun.COM #define	SMBD_DC_MONITOR_INTERVAL		60	/* seconds */
435331Samw 
4412914SJoyce.McIntosh@Sun.COM extern smbd_t smbd;
458334SJose.Borrego@Sun.COM 
46*13082SJoyce.McIntosh@Sun.COM static mutex_t smbd_dc_mutex;
47*13082SJoyce.McIntosh@Sun.COM static cond_t smbd_dc_cv;
48*13082SJoyce.McIntosh@Sun.COM 
4912914SJoyce.McIntosh@Sun.COM static void *smbd_dc_monitor(void *);
5012914SJoyce.McIntosh@Sun.COM static void smbd_dc_update(void);
5112914SJoyce.McIntosh@Sun.COM static boolean_t smbd_set_netlogon_cred(void);
528334SJose.Borrego@Sun.COM static int smbd_get_kpasswd_srv(char *, size_t);
538334SJose.Borrego@Sun.COM static uint32_t smbd_join_workgroup(smb_joininfo_t *);
548334SJose.Borrego@Sun.COM static uint32_t smbd_join_domain(smb_joininfo_t *);
555331Samw 
565331Samw /*
5712914SJoyce.McIntosh@Sun.COM  * Launch the DC discovery and monitor thread.
5812914SJoyce.McIntosh@Sun.COM  */
5912914SJoyce.McIntosh@Sun.COM int
smbd_dc_monitor_init(void)6012914SJoyce.McIntosh@Sun.COM smbd_dc_monitor_init(void)
6112914SJoyce.McIntosh@Sun.COM {
6212914SJoyce.McIntosh@Sun.COM 	pthread_attr_t	attr;
6312914SJoyce.McIntosh@Sun.COM 	int		rc;
6412914SJoyce.McIntosh@Sun.COM 
65*13082SJoyce.McIntosh@Sun.COM 	(void) smb_config_getstr(SMB_CI_ADS_SITE, smbd.s_site,
66*13082SJoyce.McIntosh@Sun.COM 	    MAXHOSTNAMELEN);
67*13082SJoyce.McIntosh@Sun.COM 	(void) smb_config_getip(SMB_CI_DOMAIN_SRV, &smbd.s_pdc);
6812914SJoyce.McIntosh@Sun.COM 	smb_ads_init();
6912914SJoyce.McIntosh@Sun.COM 
7012914SJoyce.McIntosh@Sun.COM 	if (smbd.s_secmode != SMB_SECMODE_DOMAIN)
7112914SJoyce.McIntosh@Sun.COM 		return (0);
7212914SJoyce.McIntosh@Sun.COM 
7312914SJoyce.McIntosh@Sun.COM 	(void) pthread_attr_init(&attr);
7412914SJoyce.McIntosh@Sun.COM 	(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7512914SJoyce.McIntosh@Sun.COM 	rc = pthread_create(&smbd.s_dc_monitor_tid, &attr, smbd_dc_monitor,
7612914SJoyce.McIntosh@Sun.COM 	    NULL);
7712914SJoyce.McIntosh@Sun.COM 	(void) pthread_attr_destroy(&attr);
7812914SJoyce.McIntosh@Sun.COM 	return (rc);
7912914SJoyce.McIntosh@Sun.COM }
8012914SJoyce.McIntosh@Sun.COM 
81*13082SJoyce.McIntosh@Sun.COM void
smbd_dc_monitor_refresh(void)82*13082SJoyce.McIntosh@Sun.COM smbd_dc_monitor_refresh(void)
83*13082SJoyce.McIntosh@Sun.COM {
84*13082SJoyce.McIntosh@Sun.COM 	char		site[MAXHOSTNAMELEN];
85*13082SJoyce.McIntosh@Sun.COM 	smb_inaddr_t	pdc;
86*13082SJoyce.McIntosh@Sun.COM 
87*13082SJoyce.McIntosh@Sun.COM 	site[0] = '\0';
88*13082SJoyce.McIntosh@Sun.COM 	bzero(&pdc, sizeof (smb_inaddr_t));
89*13082SJoyce.McIntosh@Sun.COM 	(void) smb_config_getstr(SMB_CI_ADS_SITE, site, MAXHOSTNAMELEN);
90*13082SJoyce.McIntosh@Sun.COM 	(void) smb_config_getip(SMB_CI_DOMAIN_SRV, &pdc);
91*13082SJoyce.McIntosh@Sun.COM 
92*13082SJoyce.McIntosh@Sun.COM 	(void) mutex_lock(&smbd_dc_mutex);
93*13082SJoyce.McIntosh@Sun.COM 
94*13082SJoyce.McIntosh@Sun.COM 	if ((bcmp(&smbd.s_pdc, &pdc, sizeof (smb_inaddr_t)) != 0) ||
95*13082SJoyce.McIntosh@Sun.COM 	    (smb_strcasecmp(smbd.s_site, site, 0) != 0)) {
96*13082SJoyce.McIntosh@Sun.COM 		bcopy(&pdc, &smbd.s_pdc, sizeof (smb_inaddr_t));
97*13082SJoyce.McIntosh@Sun.COM 		(void) strlcpy(smbd.s_site, site, MAXHOSTNAMELEN);
98*13082SJoyce.McIntosh@Sun.COM 		smbd.s_pdc_changed = B_TRUE;
99*13082SJoyce.McIntosh@Sun.COM 		(void) cond_signal(&smbd_dc_cv);
100*13082SJoyce.McIntosh@Sun.COM 	}
101*13082SJoyce.McIntosh@Sun.COM 
102*13082SJoyce.McIntosh@Sun.COM 	(void) mutex_unlock(&smbd_dc_mutex);
103*13082SJoyce.McIntosh@Sun.COM }
104*13082SJoyce.McIntosh@Sun.COM 
10512914SJoyce.McIntosh@Sun.COM /*ARGSUSED*/
10612914SJoyce.McIntosh@Sun.COM static void *
smbd_dc_monitor(void * arg)10712914SJoyce.McIntosh@Sun.COM smbd_dc_monitor(void *arg)
10812914SJoyce.McIntosh@Sun.COM {
10912914SJoyce.McIntosh@Sun.COM 	boolean_t	ds_not_responding = B_FALSE;
110*13082SJoyce.McIntosh@Sun.COM 	boolean_t	ds_cfg_changed = B_FALSE;
111*13082SJoyce.McIntosh@Sun.COM 	timestruc_t	delay;
11212914SJoyce.McIntosh@Sun.COM 	int		i;
11312914SJoyce.McIntosh@Sun.COM 
11412914SJoyce.McIntosh@Sun.COM 	smbd_dc_update();
11512914SJoyce.McIntosh@Sun.COM 	smbd_online_wait("smbd_dc_monitor");
11612914SJoyce.McIntosh@Sun.COM 
11712914SJoyce.McIntosh@Sun.COM 	while (smbd_online()) {
118*13082SJoyce.McIntosh@Sun.COM 		delay.tv_sec = SMBD_DC_MONITOR_INTERVAL;
119*13082SJoyce.McIntosh@Sun.COM 		delay.tv_nsec = 0;
120*13082SJoyce.McIntosh@Sun.COM 
121*13082SJoyce.McIntosh@Sun.COM 		(void) mutex_lock(&smbd_dc_mutex);
122*13082SJoyce.McIntosh@Sun.COM 		(void) cond_reltimedwait(&smbd_dc_cv, &smbd_dc_mutex, &delay);
123*13082SJoyce.McIntosh@Sun.COM 
124*13082SJoyce.McIntosh@Sun.COM 		if (smbd.s_pdc_changed) {
125*13082SJoyce.McIntosh@Sun.COM 			smbd.s_pdc_changed = B_FALSE;
126*13082SJoyce.McIntosh@Sun.COM 			ds_cfg_changed = B_TRUE;
127*13082SJoyce.McIntosh@Sun.COM 		}
128*13082SJoyce.McIntosh@Sun.COM 
129*13082SJoyce.McIntosh@Sun.COM 		(void) mutex_unlock(&smbd_dc_mutex);
13012914SJoyce.McIntosh@Sun.COM 
13112914SJoyce.McIntosh@Sun.COM 		for (i = 0; i < SMBD_DC_MONITOR_ATTEMPTS; ++i) {
13212914SJoyce.McIntosh@Sun.COM 			if (dssetup_check_service() == 0) {
13312914SJoyce.McIntosh@Sun.COM 				ds_not_responding = B_FALSE;
13412914SJoyce.McIntosh@Sun.COM 				break;
13512914SJoyce.McIntosh@Sun.COM 			}
13612914SJoyce.McIntosh@Sun.COM 
13712914SJoyce.McIntosh@Sun.COM 			ds_not_responding = B_TRUE;
13812914SJoyce.McIntosh@Sun.COM 			(void) sleep(SMBD_DC_MONITOR_RETRY_INTERVAL);
13912914SJoyce.McIntosh@Sun.COM 		}
14012914SJoyce.McIntosh@Sun.COM 
141*13082SJoyce.McIntosh@Sun.COM 		if (ds_not_responding)
14212914SJoyce.McIntosh@Sun.COM 			smb_log(smbd.s_loghd, LOG_NOTICE,
14312914SJoyce.McIntosh@Sun.COM 			    "smbd_dc_monitor: domain service not responding");
14412914SJoyce.McIntosh@Sun.COM 
145*13082SJoyce.McIntosh@Sun.COM 		if (ds_not_responding || ds_cfg_changed) {
146*13082SJoyce.McIntosh@Sun.COM 			ds_cfg_changed = B_FALSE;
14712914SJoyce.McIntosh@Sun.COM 			smb_ads_refresh();
14812914SJoyce.McIntosh@Sun.COM 			smbd_dc_update();
14912914SJoyce.McIntosh@Sun.COM 		}
15012914SJoyce.McIntosh@Sun.COM 	}
15112914SJoyce.McIntosh@Sun.COM 
15212914SJoyce.McIntosh@Sun.COM 	smbd.s_dc_monitor_tid = 0;
15312914SJoyce.McIntosh@Sun.COM 	return (NULL);
15412914SJoyce.McIntosh@Sun.COM }
15512914SJoyce.McIntosh@Sun.COM 
15612914SJoyce.McIntosh@Sun.COM /*
15712914SJoyce.McIntosh@Sun.COM  * Locate a domain controller in the current resource domain and Update
15812914SJoyce.McIntosh@Sun.COM  * the Netlogon credential chain.
15912914SJoyce.McIntosh@Sun.COM  *
16012914SJoyce.McIntosh@Sun.COM  * The domain configuration will be updated upon successful DC discovery.
16112914SJoyce.McIntosh@Sun.COM  */
16212914SJoyce.McIntosh@Sun.COM static void
smbd_dc_update(void)16312914SJoyce.McIntosh@Sun.COM smbd_dc_update(void)
16412914SJoyce.McIntosh@Sun.COM {
16512914SJoyce.McIntosh@Sun.COM 	char		domain[MAXHOSTNAMELEN];
16612914SJoyce.McIntosh@Sun.COM 	smb_domainex_t	info;
16712914SJoyce.McIntosh@Sun.COM 	smb_domain_t	*primary;
16812914SJoyce.McIntosh@Sun.COM 
16912914SJoyce.McIntosh@Sun.COM 
17012914SJoyce.McIntosh@Sun.COM 	if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) {
17112914SJoyce.McIntosh@Sun.COM 		(void) smb_getdomainname(domain, MAXHOSTNAMELEN);
17212914SJoyce.McIntosh@Sun.COM 		(void) smb_strupr(domain);
17312914SJoyce.McIntosh@Sun.COM 	}
17412914SJoyce.McIntosh@Sun.COM 
17512914SJoyce.McIntosh@Sun.COM 	if (!smb_locate_dc(domain, "", &info)) {
17612914SJoyce.McIntosh@Sun.COM 		smb_log(smbd.s_loghd, LOG_NOTICE,
17712914SJoyce.McIntosh@Sun.COM 		    "smbd_dc_update: %s: locate failed", domain);
17812914SJoyce.McIntosh@Sun.COM 	} else {
17912914SJoyce.McIntosh@Sun.COM 		primary = &info.d_primary;
18012914SJoyce.McIntosh@Sun.COM 
18112914SJoyce.McIntosh@Sun.COM 		smb_config_setdomaininfo(primary->di_nbname,
18212914SJoyce.McIntosh@Sun.COM 		    primary->di_fqname,
18312914SJoyce.McIntosh@Sun.COM 		    primary->di_sid,
18412914SJoyce.McIntosh@Sun.COM 		    primary->di_u.di_dns.ddi_forest,
18512914SJoyce.McIntosh@Sun.COM 		    primary->di_u.di_dns.ddi_guid);
18612914SJoyce.McIntosh@Sun.COM 
18712914SJoyce.McIntosh@Sun.COM 		smb_log(smbd.s_loghd, LOG_NOTICE,
18812914SJoyce.McIntosh@Sun.COM 		    "smbd_dc_update: %s: located %s", domain, info.d_dc);
18912914SJoyce.McIntosh@Sun.COM 	}
19012914SJoyce.McIntosh@Sun.COM 
19112914SJoyce.McIntosh@Sun.COM 	if (smbd_set_netlogon_cred()) {
19212914SJoyce.McIntosh@Sun.COM 		/*
19312914SJoyce.McIntosh@Sun.COM 		 * Restart required because the domain changed
19412914SJoyce.McIntosh@Sun.COM 		 * or the credential chain setup failed.
19512914SJoyce.McIntosh@Sun.COM 		 */
19612914SJoyce.McIntosh@Sun.COM 		smb_log(smbd.s_loghd, LOG_NOTICE,
19712914SJoyce.McIntosh@Sun.COM 		    "smbd_dc_update: %s: smb/server restart required");
19812914SJoyce.McIntosh@Sun.COM 
19912914SJoyce.McIntosh@Sun.COM 		if (smb_smf_restart_service() != 0)
20012914SJoyce.McIntosh@Sun.COM 			smb_log(smbd.s_loghd, LOG_ERR,
20112914SJoyce.McIntosh@Sun.COM 			    "restart failed: run 'svcs -xv smb/server'"
20212914SJoyce.McIntosh@Sun.COM 			    " for more information");
20312914SJoyce.McIntosh@Sun.COM 	}
20412914SJoyce.McIntosh@Sun.COM }
20512914SJoyce.McIntosh@Sun.COM 
20612914SJoyce.McIntosh@Sun.COM /*
2078334SJose.Borrego@Sun.COM  * smbd_join
2088334SJose.Borrego@Sun.COM  *
2098334SJose.Borrego@Sun.COM  * Joins the specified domain/workgroup.
2108334SJose.Borrego@Sun.COM  *
2118334SJose.Borrego@Sun.COM  * If the security mode or domain name is being changed,
2128334SJose.Borrego@Sun.COM  * the caller must restart the service.
2135331Samw  */
2148334SJose.Borrego@Sun.COM uint32_t
smbd_join(smb_joininfo_t * info)2158334SJose.Borrego@Sun.COM smbd_join(smb_joininfo_t *info)
2168334SJose.Borrego@Sun.COM {
2178334SJose.Borrego@Sun.COM 	uint32_t status;
2186139Sjb150015 
2198334SJose.Borrego@Sun.COM 	dssetup_clear_domain_info();
2208334SJose.Borrego@Sun.COM 	if (info->mode == SMB_SECMODE_WORKGRP)
2218334SJose.Borrego@Sun.COM 		status = smbd_join_workgroup(info);
2228334SJose.Borrego@Sun.COM 	else
2238334SJose.Borrego@Sun.COM 		status = smbd_join_domain(info);
2245331Samw 
2258334SJose.Borrego@Sun.COM 	return (status);
2265331Samw }
2275331Samw 
2285331Samw /*
2298334SJose.Borrego@Sun.COM  * smbd_set_netlogon_cred
2308334SJose.Borrego@Sun.COM  *
2318334SJose.Borrego@Sun.COM  * If the system is joined to an AD domain via kclient, SMB daemon will need
2328334SJose.Borrego@Sun.COM  * to establish the NETLOGON credential chain.
2338334SJose.Borrego@Sun.COM  *
2348334SJose.Borrego@Sun.COM  * Since the kclient has updated the machine password stored in SMF
2358334SJose.Borrego@Sun.COM  * repository, the cached ipc_info must be updated accordingly by calling
23610717Samw@Sun.COM  * smb_ipc_commit.
2378334SJose.Borrego@Sun.COM  *
2388334SJose.Borrego@Sun.COM  * Due to potential replication delays in a multiple DC environment, the
2398334SJose.Borrego@Sun.COM  * NETLOGON rpc request must be sent to the DC, to which the KPASSWD request
2408334SJose.Borrego@Sun.COM  * is sent. If the DC discovered by the SMB daemon is different than the
2418334SJose.Borrego@Sun.COM  * kpasswd server, the current connection with the DC will be torn down
2428334SJose.Borrego@Sun.COM  * and a DC discovery process will be triggered to locate the kpasswd
2438334SJose.Borrego@Sun.COM  * server.
2448334SJose.Borrego@Sun.COM  *
2458334SJose.Borrego@Sun.COM  * If joining a new domain, the domain_name property must be set after a
2468334SJose.Borrego@Sun.COM  * successful credential chain setup.
2478334SJose.Borrego@Sun.COM  */
24812914SJoyce.McIntosh@Sun.COM static boolean_t
smbd_set_netlogon_cred(void)2498334SJose.Borrego@Sun.COM smbd_set_netlogon_cred(void)
2508334SJose.Borrego@Sun.COM {
2518334SJose.Borrego@Sun.COM 	char kpasswd_srv[MAXHOSTNAMELEN];
2528334SJose.Borrego@Sun.COM 	char kpasswd_domain[MAXHOSTNAMELEN];
2538334SJose.Borrego@Sun.COM 	char sam_acct[SMB_SAMACCT_MAXLEN];
25410717Samw@Sun.COM 	char ipc_usr[SMB_USERNAME_MAXLEN];
25510717Samw@Sun.COM 	char *dom;
2568334SJose.Borrego@Sun.COM 	boolean_t new_domain = B_FALSE;
25710717Samw@Sun.COM 	smb_domainex_t dxi;
25810717Samw@Sun.COM 	smb_domain_t *di;
2598334SJose.Borrego@Sun.COM 
2608334SJose.Borrego@Sun.COM 	if (smb_match_netlogon_seqnum())
2618334SJose.Borrego@Sun.COM 		return (B_FALSE);
2628334SJose.Borrego@Sun.COM 
2638334SJose.Borrego@Sun.COM 	(void) smb_config_getstr(SMB_CI_KPASSWD_SRV, kpasswd_srv,
2648334SJose.Borrego@Sun.COM 	    sizeof (kpasswd_srv));
2658334SJose.Borrego@Sun.COM 
2668334SJose.Borrego@Sun.COM 	if (*kpasswd_srv == '\0')
2678334SJose.Borrego@Sun.COM 		return (B_FALSE);
2688334SJose.Borrego@Sun.COM 
2698334SJose.Borrego@Sun.COM 	/*
2708334SJose.Borrego@Sun.COM 	 * If the domain join initiated by smbadm join CLI is in
2718334SJose.Borrego@Sun.COM 	 * progress, don't do anything.
2728334SJose.Borrego@Sun.COM 	 */
2738334SJose.Borrego@Sun.COM 	(void) smb_getsamaccount(sam_acct, sizeof (sam_acct));
27410717Samw@Sun.COM 	smb_ipc_get_user(ipc_usr, SMB_USERNAME_MAXLEN);
27510966SJordan.Brown@Sun.COM 	if (smb_strcasecmp(ipc_usr, sam_acct, 0))
2768334SJose.Borrego@Sun.COM 		return (B_FALSE);
2778334SJose.Borrego@Sun.COM 
27810717Samw@Sun.COM 	di = &dxi.d_primary;
27910717Samw@Sun.COM 	if (!smb_domain_getinfo(&dxi))
2809832Samw@Sun.COM 		(void) smb_getfqdomainname(di->di_fqname, MAXHOSTNAMELEN);
2818334SJose.Borrego@Sun.COM 
2828334SJose.Borrego@Sun.COM 	(void) smb_config_getstr(SMB_CI_KPASSWD_DOMAIN, kpasswd_domain,
2838334SJose.Borrego@Sun.COM 	    sizeof (kpasswd_domain));
2848334SJose.Borrego@Sun.COM 
2858334SJose.Borrego@Sun.COM 	if (*kpasswd_domain != '\0' &&
28610966SJordan.Brown@Sun.COM 	    smb_strcasecmp(kpasswd_domain, di->di_fqname, 0)) {
2878334SJose.Borrego@Sun.COM 		dom = kpasswd_domain;
2888334SJose.Borrego@Sun.COM 		new_domain = B_TRUE;
2898334SJose.Borrego@Sun.COM 	} else {
2909832Samw@Sun.COM 		dom = di->di_fqname;
2918334SJose.Borrego@Sun.COM 	}
2928334SJose.Borrego@Sun.COM 
2938334SJose.Borrego@Sun.COM 	/*
2948334SJose.Borrego@Sun.COM 	 * DC discovery will be triggered if the domain info is not
2958334SJose.Borrego@Sun.COM 	 * currently cached or the SMB daemon has previously discovered a DC
2968334SJose.Borrego@Sun.COM 	 * that is different than the kpasswd server.
2978334SJose.Borrego@Sun.COM 	 */
29810966SJordan.Brown@Sun.COM 	if (new_domain || smb_strcasecmp(dxi.d_dc, kpasswd_srv, 0) != 0) {
29910717Samw@Sun.COM 		if (*dxi.d_dc != '\0')
30010717Samw@Sun.COM 			mlsvc_disconnect(dxi.d_dc);
3018334SJose.Borrego@Sun.COM 
30210717Samw@Sun.COM 		if (!smb_locate_dc(dom, kpasswd_srv, &dxi)) {
30310717Samw@Sun.COM 			if (!smb_locate_dc(di->di_fqname, "", &dxi)) {
30410717Samw@Sun.COM 				smb_ipc_commit();
3058334SJose.Borrego@Sun.COM 				return (B_FALSE);
3068334SJose.Borrego@Sun.COM 			}
3078334SJose.Borrego@Sun.COM 		}
3088334SJose.Borrego@Sun.COM 	}
3098334SJose.Borrego@Sun.COM 
31010717Samw@Sun.COM 	smb_ipc_commit();
31110717Samw@Sun.COM 	if (mlsvc_netlogon(dxi.d_dc, di->di_nbname)) {
31212914SJoyce.McIntosh@Sun.COM 		syslog(LOG_NOTICE,
3138334SJose.Borrego@Sun.COM 		    "failed to establish NETLOGON credential chain");
3148334SJose.Borrego@Sun.COM 		return (B_TRUE);
3158334SJose.Borrego@Sun.COM 	} else {
3168334SJose.Borrego@Sun.COM 		if (new_domain) {
3179832Samw@Sun.COM 			smb_config_setdomaininfo(di->di_nbname, di->di_fqname,
3189832Samw@Sun.COM 			    di->di_sid,
3199832Samw@Sun.COM 			    di->di_u.di_dns.ddi_forest,
3209832Samw@Sun.COM 			    di->di_u.di_dns.ddi_guid);
3218334SJose.Borrego@Sun.COM 			(void) smb_config_setstr(SMB_CI_KPASSWD_DOMAIN, "");
3228334SJose.Borrego@Sun.COM 		}
3238334SJose.Borrego@Sun.COM 	}
3248334SJose.Borrego@Sun.COM 
3258334SJose.Borrego@Sun.COM 	return (new_domain);
3268334SJose.Borrego@Sun.COM }
3278334SJose.Borrego@Sun.COM 
3288334SJose.Borrego@Sun.COM /*
3296139Sjb150015  * Retrieve the kpasswd server from krb5.conf.
3308334SJose.Borrego@Sun.COM  *
3318334SJose.Borrego@Sun.COM  * Initialization of the locate dc thread.
3328334SJose.Borrego@Sun.COM  * Returns 0 on success, an error number if thread creation fails.
3336139Sjb150015  */
3346139Sjb150015 static int
smbd_get_kpasswd_srv(char * srv,size_t len)3356139Sjb150015 smbd_get_kpasswd_srv(char *srv, size_t len)
3366139Sjb150015 {
3376139Sjb150015 	FILE *fp;
3386139Sjb150015 	static char buf[512];
3396139Sjb150015 	char *p;
3406139Sjb150015 
3416139Sjb150015 	*srv = '\0';
3426139Sjb150015 	p = getenv("KRB5_CONFIG");
3436139Sjb150015 	if (p == NULL || *p == '\0')
3446139Sjb150015 		p = "/etc/krb5/krb5.conf";
3456139Sjb150015 
3466139Sjb150015 	if ((fp = fopen(p, "r")) == NULL)
3476139Sjb150015 		return (-1);
3486139Sjb150015 
3496139Sjb150015 	while (fgets(buf, sizeof (buf), fp)) {
3506139Sjb150015 
3516139Sjb150015 		/* Weed out any comment text */
3526139Sjb150015 		(void) trim_whitespace(buf);
3536139Sjb150015 		if (*buf == '#')
3546139Sjb150015 			continue;
3556139Sjb150015 
3566139Sjb150015 		if ((p = strstr(buf, "kpasswd_server")) != NULL) {
3576139Sjb150015 			if ((p = strchr(p, '=')) != NULL) {
3586139Sjb150015 				(void) trim_whitespace(++p);
3596139Sjb150015 				(void) strlcpy(srv, p, len);
3606139Sjb150015 			}
3616139Sjb150015 			break;
3626139Sjb150015 		}
3636139Sjb150015 	}
3646139Sjb150015 
3658334SJose.Borrego@Sun.COM 
3666139Sjb150015 	(void) fclose(fp);
3676139Sjb150015 	return ((*srv == '\0') ? -1 : 0);
3686139Sjb150015 }
3696139Sjb150015 
3708334SJose.Borrego@Sun.COM static uint32_t
smbd_join_workgroup(smb_joininfo_t * info)3718334SJose.Borrego@Sun.COM smbd_join_workgroup(smb_joininfo_t *info)
3725331Samw {
3738334SJose.Borrego@Sun.COM 	char nb_domain[SMB_PI_MAX_DOMAIN];
3748334SJose.Borrego@Sun.COM 
3758334SJose.Borrego@Sun.COM 	(void) smb_config_getstr(SMB_CI_DOMAIN_NAME, nb_domain,
3768334SJose.Borrego@Sun.COM 	    sizeof (nb_domain));
3778334SJose.Borrego@Sun.COM 
3788334SJose.Borrego@Sun.COM 	smbd_set_secmode(SMB_SECMODE_WORKGRP);
3799832Samw@Sun.COM 	smb_config_setdomaininfo(info->domain_name, "", "", "", "");
3808334SJose.Borrego@Sun.COM 
3818334SJose.Borrego@Sun.COM 	if (strcasecmp(nb_domain, info->domain_name))
3828334SJose.Borrego@Sun.COM 		smb_browser_reconfig();
3838334SJose.Borrego@Sun.COM 
3848334SJose.Borrego@Sun.COM 	return (NT_STATUS_SUCCESS);
3858334SJose.Borrego@Sun.COM }
3868334SJose.Borrego@Sun.COM 
3878334SJose.Borrego@Sun.COM static uint32_t
smbd_join_domain(smb_joininfo_t * info)3888334SJose.Borrego@Sun.COM smbd_join_domain(smb_joininfo_t *info)
3898334SJose.Borrego@Sun.COM {
3905331Samw 	uint32_t status;
3915331Samw 	unsigned char passwd_hash[SMBAUTH_HASH_SZ];
3926139Sjb150015 	char dc[MAXHOSTNAMELEN];
39310717Samw@Sun.COM 	smb_domainex_t dxi;
39410717Samw@Sun.COM 	smb_domain_t *di;
3955331Samw 
3965331Samw 	/*
3975331Samw 	 * Ensure that any previous membership of this domain has
3985331Samw 	 * been cleared from the environment before we start. This
3995331Samw 	 * will ensure that we don't attempt a NETLOGON_SAMLOGON
4005331Samw 	 * when attempting to find the PDC.
4015331Samw 	 */
4028334SJose.Borrego@Sun.COM 
4035772Sas200622 	(void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_FALSE);
4045772Sas200622 
4058334SJose.Borrego@Sun.COM 	if (smb_auth_ntlm_hash(info->domain_passwd, passwd_hash)
4068334SJose.Borrego@Sun.COM 	    != SMBAUTH_SUCCESS) {
4078334SJose.Borrego@Sun.COM 		syslog(LOG_ERR, "smbd: could not compute ntlm hash for '%s'",
4088334SJose.Borrego@Sun.COM 		    info->domain_username);
4095772Sas200622 		return (NT_STATUS_INTERNAL_ERROR);
4105772Sas200622 	}
4115331Samw 
41210717Samw@Sun.COM 	smb_ipc_set(info->domain_username, passwd_hash);
4135331Samw 
4146139Sjb150015 	(void) smbd_get_kpasswd_srv(dc, sizeof (dc));
4158334SJose.Borrego@Sun.COM 	/* info->domain_name could either be NetBIOS domain name or FQDN */
41610717Samw@Sun.COM 	if (smb_locate_dc(info->domain_name, dc, &dxi)) {
41710717Samw@Sun.COM 		status = mlsvc_join(&dxi, info->domain_username,
4188334SJose.Borrego@Sun.COM 		    info->domain_passwd);
4195331Samw 
4205331Samw 		if (status == NT_STATUS_SUCCESS) {
42110717Samw@Sun.COM 			di = &dxi.d_primary;
4228334SJose.Borrego@Sun.COM 			smbd_set_secmode(SMB_SECMODE_DOMAIN);
4239832Samw@Sun.COM 			smb_config_setdomaininfo(di->di_nbname, di->di_fqname,
4249832Samw@Sun.COM 			    di->di_sid,
4259832Samw@Sun.COM 			    di->di_u.di_dns.ddi_forest,
4269832Samw@Sun.COM 			    di->di_u.di_dns.ddi_guid);
42710717Samw@Sun.COM 			smb_ipc_commit();
4285331Samw 			return (status);
4295331Samw 		}
4305331Samw 
43110717Samw@Sun.COM 		smb_ipc_rollback();
4325331Samw 		syslog(LOG_ERR, "smbd: failed joining %s (%s)",
4335331Samw 		    info->domain_name, xlate_nt_status(status));
4345331Samw 		return (status);
4355331Samw 	}
4365331Samw 
43710717Samw@Sun.COM 	smb_ipc_rollback();
4385331Samw 	syslog(LOG_ERR, "smbd: failed locating domain controller for %s",
4395331Samw 	    info->domain_name);
4405331Samw 	return (NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND);
4415331Samw }
442