xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c (revision 9832:3569b6c7f56c)
18334SJose.Borrego@Sun.COM /*
28334SJose.Borrego@Sun.COM  * CDDL HEADER START
38334SJose.Borrego@Sun.COM  *
48334SJose.Borrego@Sun.COM  * The contents of this file are subject to the terms of the
58334SJose.Borrego@Sun.COM  * Common Development and Distribution License (the "License").
68334SJose.Borrego@Sun.COM  * You may not use this file except in compliance with the License.
78334SJose.Borrego@Sun.COM  *
88334SJose.Borrego@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98334SJose.Borrego@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108334SJose.Borrego@Sun.COM  * See the License for the specific language governing permissions
118334SJose.Borrego@Sun.COM  * and limitations under the License.
128334SJose.Borrego@Sun.COM  *
138334SJose.Borrego@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148334SJose.Borrego@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158334SJose.Borrego@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168334SJose.Borrego@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178334SJose.Borrego@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188334SJose.Borrego@Sun.COM  *
198334SJose.Borrego@Sun.COM  * CDDL HEADER END
208334SJose.Borrego@Sun.COM  */
218334SJose.Borrego@Sun.COM /*
228474SJose.Borrego@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
238334SJose.Borrego@Sun.COM  * Use is subject to license terms.
248334SJose.Borrego@Sun.COM  */
258334SJose.Borrego@Sun.COM 
268334SJose.Borrego@Sun.COM #include <syslog.h>
278334SJose.Borrego@Sun.COM #include <synch.h>
288334SJose.Borrego@Sun.COM #include <pthread.h>
298334SJose.Borrego@Sun.COM #include <unistd.h>
308334SJose.Borrego@Sun.COM #include <string.h>
318334SJose.Borrego@Sun.COM #include <strings.h>
328334SJose.Borrego@Sun.COM #include <sys/errno.h>
338334SJose.Borrego@Sun.COM #include <sys/types.h>
348334SJose.Borrego@Sun.COM #include <netinet/in.h>
358334SJose.Borrego@Sun.COM #include <arpa/nameser.h>
368334SJose.Borrego@Sun.COM #include <resolv.h>
378334SJose.Borrego@Sun.COM #include <netdb.h>
388334SJose.Borrego@Sun.COM #include <assert.h>
398334SJose.Borrego@Sun.COM 
408334SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h>
418334SJose.Borrego@Sun.COM #include <smbsrv/libsmbrdr.h>
428334SJose.Borrego@Sun.COM #include <smbsrv/libsmbns.h>
438334SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h>
448334SJose.Borrego@Sun.COM 
458334SJose.Borrego@Sun.COM #include <smbsrv/smbinfo.h>
468334SJose.Borrego@Sun.COM #include <smbsrv/ntstatus.h>
478334SJose.Borrego@Sun.COM #include <lsalib.h>
488334SJose.Borrego@Sun.COM 
498334SJose.Borrego@Sun.COM /*
508334SJose.Borrego@Sun.COM  * DC Locator
518334SJose.Borrego@Sun.COM  */
528334SJose.Borrego@Sun.COM #define	SMB_DCLOCATOR_TIMEOUT	45
538334SJose.Borrego@Sun.COM #define	SMB_IS_FQDN(domain)	(strchr(domain, '.') != NULL)
548334SJose.Borrego@Sun.COM 
558334SJose.Borrego@Sun.COM typedef struct smb_dclocator {
56*9832Samw@Sun.COM 	char		sdl_domain[SMB_PI_MAX_DOMAIN];
57*9832Samw@Sun.COM 	char		sdl_dc[MAXHOSTNAMELEN];
58*9832Samw@Sun.COM 	boolean_t	sdl_locate;
59*9832Samw@Sun.COM 	mutex_t		sdl_mtx;
60*9832Samw@Sun.COM 	cond_t		sdl_cv;
61*9832Samw@Sun.COM 	uint32_t	sdl_status;
628334SJose.Borrego@Sun.COM } smb_dclocator_t;
638334SJose.Borrego@Sun.COM 
648334SJose.Borrego@Sun.COM static smb_dclocator_t smb_dclocator;
658334SJose.Borrego@Sun.COM static pthread_t smb_dclocator_thr;
668334SJose.Borrego@Sun.COM 
678334SJose.Borrego@Sun.COM static void *smb_dclocator_main(void *);
68*9832Samw@Sun.COM static void smb_domain_update(char *, char *);
69*9832Samw@Sun.COM static boolean_t smb_domain_query_dns(char *, char *, smb_domain_t *);
70*9832Samw@Sun.COM static boolean_t smb_domain_query_nbt(char *, char *, smb_domain_t *);
71*9832Samw@Sun.COM static boolean_t smb_domain_match(char *, char *, uint32_t);
728334SJose.Borrego@Sun.COM static uint32_t smb_domain_query(char *, char *, smb_domain_t *);
73*9832Samw@Sun.COM static void smb_domain_enum_trusted(char *, char *, smb_trusted_domains_t *);
74*9832Samw@Sun.COM static uint32_t smb_domain_use_config(char *, nt_domain_t *);
75*9832Samw@Sun.COM static void smb_domain_free(smb_domain_t *di);
768334SJose.Borrego@Sun.COM 
778334SJose.Borrego@Sun.COM /*
788334SJose.Borrego@Sun.COM  * ===================================================================
798334SJose.Borrego@Sun.COM  * API to initialize DC locator thread, trigger DC discovery, and
808334SJose.Borrego@Sun.COM  * get the discovered DC and/or domain information.
818334SJose.Borrego@Sun.COM  * ===================================================================
828334SJose.Borrego@Sun.COM  */
838334SJose.Borrego@Sun.COM 
848334SJose.Borrego@Sun.COM /*
858334SJose.Borrego@Sun.COM  * smb_dclocator_init
868334SJose.Borrego@Sun.COM  *
878334SJose.Borrego@Sun.COM  * Initialization of the DC locator thread.
888334SJose.Borrego@Sun.COM  * Returns 0 on success, an error number if thread creation fails.
898334SJose.Borrego@Sun.COM  */
908334SJose.Borrego@Sun.COM int
918334SJose.Borrego@Sun.COM smb_dclocator_init(void)
928334SJose.Borrego@Sun.COM {
938334SJose.Borrego@Sun.COM 	pthread_attr_t tattr;
948334SJose.Borrego@Sun.COM 	int rc;
958334SJose.Borrego@Sun.COM 
968334SJose.Borrego@Sun.COM 	(void) pthread_attr_init(&tattr);
978334SJose.Borrego@Sun.COM 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
988334SJose.Borrego@Sun.COM 	rc = pthread_create(&smb_dclocator_thr, &tattr,
998334SJose.Borrego@Sun.COM 	    smb_dclocator_main, 0);
1008334SJose.Borrego@Sun.COM 	(void) pthread_attr_destroy(&tattr);
1018334SJose.Borrego@Sun.COM 	return (rc);
1028334SJose.Borrego@Sun.COM }
1038334SJose.Borrego@Sun.COM 
1048334SJose.Borrego@Sun.COM /*
1058334SJose.Borrego@Sun.COM  * smb_locate_dc
1068334SJose.Borrego@Sun.COM  *
1078334SJose.Borrego@Sun.COM  * This is the entry point for discovering a domain controller for the
1088334SJose.Borrego@Sun.COM  * specified domain.
1098334SJose.Borrego@Sun.COM  *
1108334SJose.Borrego@Sun.COM  * The actual work of discovering a DC is handled by DC locator thread.
1118334SJose.Borrego@Sun.COM  * All we do here is signal the request and wait for a DC or a timeout.
1128334SJose.Borrego@Sun.COM  *
1138334SJose.Borrego@Sun.COM  * Input parameters:
1148334SJose.Borrego@Sun.COM  *  domain - domain to be discovered (can either be NetBIOS or DNS domain)
1158334SJose.Borrego@Sun.COM  *  dc - preferred DC. If the preferred DC is set to empty string, it
1168334SJose.Borrego@Sun.COM  *       will attempt to discover any DC in the specified domain.
1178334SJose.Borrego@Sun.COM  *
1188334SJose.Borrego@Sun.COM  * Output parameter:
1198334SJose.Borrego@Sun.COM  *  dp - on success, dp will be filled with the discovered DC and domain
1208334SJose.Borrego@Sun.COM  *       information.
1218334SJose.Borrego@Sun.COM  * Returns B_TRUE if the DC/domain info is available.
1228334SJose.Borrego@Sun.COM  */
1238334SJose.Borrego@Sun.COM boolean_t
1248334SJose.Borrego@Sun.COM smb_locate_dc(char *domain, char *dc, smb_domain_t *dp)
1258334SJose.Borrego@Sun.COM {
1268334SJose.Borrego@Sun.COM 	int rc;
1278334SJose.Borrego@Sun.COM 	timestruc_t to;
1288334SJose.Borrego@Sun.COM 	smb_domain_t domain_info;
1298334SJose.Borrego@Sun.COM 
1308334SJose.Borrego@Sun.COM 	if (domain == NULL || *domain == '\0')
1318334SJose.Borrego@Sun.COM 		return (B_FALSE);
1328334SJose.Borrego@Sun.COM 
1338334SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_dclocator.sdl_mtx);
1348334SJose.Borrego@Sun.COM 
1358334SJose.Borrego@Sun.COM 	if (!smb_dclocator.sdl_locate) {
1368334SJose.Borrego@Sun.COM 		smb_dclocator.sdl_locate = B_TRUE;
1378334SJose.Borrego@Sun.COM 		(void) strlcpy(smb_dclocator.sdl_domain, domain,
1388334SJose.Borrego@Sun.COM 		    SMB_PI_MAX_DOMAIN);
139*9832Samw@Sun.COM 		(void) strlcpy(smb_dclocator.sdl_dc, dc, MAXHOSTNAMELEN);
1408334SJose.Borrego@Sun.COM 		(void) cond_broadcast(&smb_dclocator.sdl_cv);
1418334SJose.Borrego@Sun.COM 	}
1428334SJose.Borrego@Sun.COM 
1438334SJose.Borrego@Sun.COM 	while (smb_dclocator.sdl_locate) {
1448334SJose.Borrego@Sun.COM 		to.tv_sec = SMB_DCLOCATOR_TIMEOUT;
1458334SJose.Borrego@Sun.COM 		to.tv_nsec = 0;
1468334SJose.Borrego@Sun.COM 		rc = cond_reltimedwait(&smb_dclocator.sdl_cv,
1478334SJose.Borrego@Sun.COM 		    &smb_dclocator.sdl_mtx, &to);
1488334SJose.Borrego@Sun.COM 
1498334SJose.Borrego@Sun.COM 		if (rc == ETIME)
1508334SJose.Borrego@Sun.COM 			break;
1518334SJose.Borrego@Sun.COM 	}
1528334SJose.Borrego@Sun.COM 
1538334SJose.Borrego@Sun.COM 	if (dp == NULL)
1548334SJose.Borrego@Sun.COM 		dp = &domain_info;
1558334SJose.Borrego@Sun.COM 	rc = smb_domain_getinfo(dp);
156*9832Samw@Sun.COM 
1578334SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_dclocator.sdl_mtx);
1588334SJose.Borrego@Sun.COM 
1598334SJose.Borrego@Sun.COM 	return (rc);
1608334SJose.Borrego@Sun.COM }
1618334SJose.Borrego@Sun.COM 
1628334SJose.Borrego@Sun.COM /*
163*9832Samw@Sun.COM  * Returns a copy of primary domain information plus
164*9832Samw@Sun.COM  * the selected domain controller
1658334SJose.Borrego@Sun.COM  */
1668334SJose.Borrego@Sun.COM boolean_t
1678334SJose.Borrego@Sun.COM smb_domain_getinfo(smb_domain_t *dp)
1688334SJose.Borrego@Sun.COM {
169*9832Samw@Sun.COM 	return (nt_domain_get_primary(dp));
1708334SJose.Borrego@Sun.COM }
1718334SJose.Borrego@Sun.COM 
1728334SJose.Borrego@Sun.COM /*
1738334SJose.Borrego@Sun.COM  * ==========================================================
1748334SJose.Borrego@Sun.COM  * DC discovery functions
1758334SJose.Borrego@Sun.COM  * ==========================================================
1768334SJose.Borrego@Sun.COM  */
1778334SJose.Borrego@Sun.COM 
1788334SJose.Borrego@Sun.COM /*
1798334SJose.Borrego@Sun.COM  * This is the DC discovery thread: it gets woken up whenever someone
1808334SJose.Borrego@Sun.COM  * wants to locate a domain controller.
1818334SJose.Borrego@Sun.COM  *
182*9832Samw@Sun.COM  * Upon success, the SMB domain cache will be populated with the discovered
183*9832Samw@Sun.COM  * DC and domain info.
1848334SJose.Borrego@Sun.COM  */
1858334SJose.Borrego@Sun.COM /*ARGSUSED*/
1868334SJose.Borrego@Sun.COM static void *
1878334SJose.Borrego@Sun.COM smb_dclocator_main(void *arg)
1888334SJose.Borrego@Sun.COM {
1898334SJose.Borrego@Sun.COM 	char domain[SMB_PI_MAX_DOMAIN];
1908334SJose.Borrego@Sun.COM 	char sought_dc[MAXHOSTNAMELEN];
1918334SJose.Borrego@Sun.COM 
1928334SJose.Borrego@Sun.COM 	for (;;) {
1938334SJose.Borrego@Sun.COM 		(void) mutex_lock(&smb_dclocator.sdl_mtx);
1948334SJose.Borrego@Sun.COM 
1958334SJose.Borrego@Sun.COM 		while (!smb_dclocator.sdl_locate)
1968334SJose.Borrego@Sun.COM 			(void) cond_wait(&smb_dclocator.sdl_cv,
1978334SJose.Borrego@Sun.COM 			    &smb_dclocator.sdl_mtx);
1988334SJose.Borrego@Sun.COM 
1998334SJose.Borrego@Sun.COM 		(void) strlcpy(domain, smb_dclocator.sdl_domain,
2008334SJose.Borrego@Sun.COM 		    SMB_PI_MAX_DOMAIN);
2018334SJose.Borrego@Sun.COM 		(void) strlcpy(sought_dc, smb_dclocator.sdl_dc, MAXHOSTNAMELEN);
2028334SJose.Borrego@Sun.COM 		(void) mutex_unlock(&smb_dclocator.sdl_mtx);
2038334SJose.Borrego@Sun.COM 
204*9832Samw@Sun.COM 		smb_domain_update(domain, sought_dc);
2058334SJose.Borrego@Sun.COM 
2068334SJose.Borrego@Sun.COM 		(void) mutex_lock(&smb_dclocator.sdl_mtx);
2078334SJose.Borrego@Sun.COM 		smb_dclocator.sdl_locate = B_FALSE;
2088334SJose.Borrego@Sun.COM 		(void) cond_broadcast(&smb_dclocator.sdl_cv);
2098334SJose.Borrego@Sun.COM 		(void) mutex_unlock(&smb_dclocator.sdl_mtx);
2108334SJose.Borrego@Sun.COM 	}
2118334SJose.Borrego@Sun.COM 
2128334SJose.Borrego@Sun.COM 	/*NOTREACHED*/
2138334SJose.Borrego@Sun.COM 	return (NULL);
2148334SJose.Borrego@Sun.COM }
2158334SJose.Borrego@Sun.COM 
2168334SJose.Borrego@Sun.COM /*
217*9832Samw@Sun.COM  * Discovers a domain controller for the specified domain either via
218*9832Samw@Sun.COM  * DNS or NetBIOS. After the domain controller is discovered successfully
219*9832Samw@Sun.COM  * primary and trusted domain infromation will be queried using RPC queries.
220*9832Samw@Sun.COM  * If the RPC queries fail, the domain information stored in SMF might be used
221*9832Samw@Sun.COM  * if the the discovered domain is the same as the previously joined domain.
222*9832Samw@Sun.COM  * If everything is successful domain cache will be updated with all the
223*9832Samw@Sun.COM  * obtained information.
224*9832Samw@Sun.COM  */
225*9832Samw@Sun.COM static void
226*9832Samw@Sun.COM smb_domain_update(char *domain, char *server)
227*9832Samw@Sun.COM {
228*9832Samw@Sun.COM 	smb_domain_t di;
229*9832Samw@Sun.COM 	boolean_t query_ok;
230*9832Samw@Sun.COM 
231*9832Samw@Sun.COM 	bzero(&di, sizeof (smb_domain_t));
232*9832Samw@Sun.COM 
233*9832Samw@Sun.COM 	nt_domain_start_update();
234*9832Samw@Sun.COM 
235*9832Samw@Sun.COM 	if (SMB_IS_FQDN(domain))
236*9832Samw@Sun.COM 		query_ok = smb_domain_query_dns(domain, server, &di);
237*9832Samw@Sun.COM 	else
238*9832Samw@Sun.COM 		query_ok = smb_domain_query_nbt(domain, server, &di);
239*9832Samw@Sun.COM 
240*9832Samw@Sun.COM 	if (query_ok)
241*9832Samw@Sun.COM 		nt_domain_update(&di);
242*9832Samw@Sun.COM 
243*9832Samw@Sun.COM 	nt_domain_end_update();
244*9832Samw@Sun.COM 
245*9832Samw@Sun.COM 	smb_domain_free(&di);
246*9832Samw@Sun.COM 
247*9832Samw@Sun.COM 	if (query_ok)
248*9832Samw@Sun.COM 		nt_domain_save();
249*9832Samw@Sun.COM }
250*9832Samw@Sun.COM 
251*9832Samw@Sun.COM /*
252*9832Samw@Sun.COM  * Discovers a DC for the specified domain via DNS. If a DC is found
253*9832Samw@Sun.COM  * primary and trusted domains information will be queried.
254*9832Samw@Sun.COM  */
255*9832Samw@Sun.COM static boolean_t
256*9832Samw@Sun.COM smb_domain_query_dns(char *domain, char *server, smb_domain_t *di)
257*9832Samw@Sun.COM {
258*9832Samw@Sun.COM 	uint32_t status;
259*9832Samw@Sun.COM 	if (!smb_ads_lookup_msdcs(domain, server, di->d_dc, MAXHOSTNAMELEN))
260*9832Samw@Sun.COM 		return (B_FALSE);
261*9832Samw@Sun.COM 
262*9832Samw@Sun.COM 	status = smb_domain_query(domain, di->d_dc, di);
263*9832Samw@Sun.COM 	return (status == NT_STATUS_SUCCESS);
264*9832Samw@Sun.COM }
265*9832Samw@Sun.COM 
266*9832Samw@Sun.COM /*
267*9832Samw@Sun.COM  * Discovers a DC for the specified domain using NETLOGON protocol.
268*9832Samw@Sun.COM  * If a DC cannot be found using NETLOGON then it will
2698334SJose.Borrego@Sun.COM  * try to resolve it via DNS, i.e. find out if it is the first label
2708334SJose.Borrego@Sun.COM  * of a DNS domain name. If the corresponding DNS name is found, DC
2718334SJose.Borrego@Sun.COM  * discovery will be done via DNS query.
2728334SJose.Borrego@Sun.COM  *
2738334SJose.Borrego@Sun.COM  * If the fully-qualified domain name is derived from the DNS config
2748334SJose.Borrego@Sun.COM  * file, the NetBIOS domain name specified by the user will be compared
2758334SJose.Borrego@Sun.COM  * against the NetBIOS domain name obtained via LSA query.  If there is
2768334SJose.Borrego@Sun.COM  * a mismatch, the DC discovery will fail since the discovered DC is
2778334SJose.Borrego@Sun.COM  * actually for another domain, whose first label of its FQDN somehow
2788334SJose.Borrego@Sun.COM  * matches with the NetBIOS name of the domain we're interested in.
2798334SJose.Borrego@Sun.COM  */
280*9832Samw@Sun.COM 
2818334SJose.Borrego@Sun.COM static boolean_t
282*9832Samw@Sun.COM smb_domain_query_nbt(char *domain, char *server, smb_domain_t *di)
2838334SJose.Borrego@Sun.COM {
284*9832Samw@Sun.COM 	char dnsdomain[MAXHOSTNAMELEN];
285*9832Samw@Sun.COM 	uint32_t status;
2868334SJose.Borrego@Sun.COM 
287*9832Samw@Sun.COM 	*dnsdomain = '\0';
288*9832Samw@Sun.COM 
289*9832Samw@Sun.COM 	if (!smb_browser_netlogon(domain, di->d_dc, MAXHOSTNAMELEN)) {
290*9832Samw@Sun.COM 		if (!smb_domain_match(domain, dnsdomain, MAXHOSTNAMELEN))
291*9832Samw@Sun.COM 			return (B_FALSE);
292*9832Samw@Sun.COM 
293*9832Samw@Sun.COM 		if (!smb_ads_lookup_msdcs(dnsdomain, server, di->d_dc,
2948334SJose.Borrego@Sun.COM 		    MAXHOSTNAMELEN))
2958334SJose.Borrego@Sun.COM 			return (B_FALSE);
2968334SJose.Borrego@Sun.COM 	}
2978334SJose.Borrego@Sun.COM 
298*9832Samw@Sun.COM 	status = smb_domain_query(domain, di->d_dc, di);
299*9832Samw@Sun.COM 	if (status != NT_STATUS_SUCCESS)
3008334SJose.Borrego@Sun.COM 		return (B_FALSE);
3018334SJose.Borrego@Sun.COM 
302*9832Samw@Sun.COM 	if ((*dnsdomain != '\0') &&
303*9832Samw@Sun.COM 	    utf8_strcasecmp(domain, di->d_info.di_nbname))
3048334SJose.Borrego@Sun.COM 		return (B_FALSE);
3058334SJose.Borrego@Sun.COM 
3068334SJose.Borrego@Sun.COM 	/*
3078334SJose.Borrego@Sun.COM 	 * Now that we get the fully-qualified DNS name of the
3088334SJose.Borrego@Sun.COM 	 * domain via LSA query. Verifies ADS configuration
3098334SJose.Borrego@Sun.COM 	 * if we previously locate a DC via NetBIOS. On success,
3108334SJose.Borrego@Sun.COM 	 * ADS cache will be populated.
3118334SJose.Borrego@Sun.COM 	 */
312*9832Samw@Sun.COM 	if (smb_ads_lookup_msdcs(di->d_info.di_fqname, server,
313*9832Samw@Sun.COM 	    di->d_dc, MAXHOSTNAMELEN) == 0)
314*9832Samw@Sun.COM 		return (B_FALSE);
3158334SJose.Borrego@Sun.COM 
3168334SJose.Borrego@Sun.COM 	return (B_TRUE);
3178334SJose.Borrego@Sun.COM }
3188334SJose.Borrego@Sun.COM 
3198334SJose.Borrego@Sun.COM /*
3208334SJose.Borrego@Sun.COM  * Tries to find a matching DNS domain for the given NetBIOS domain
3218334SJose.Borrego@Sun.COM  * name by checking the first label of system's configured DNS domains.
3228334SJose.Borrego@Sun.COM  * If a match is found, it'll be returned in the passed buffer.
3238334SJose.Borrego@Sun.COM  */
3248334SJose.Borrego@Sun.COM static boolean_t
325*9832Samw@Sun.COM smb_domain_match(char *nb_domain, char *buf, uint32_t len)
3268334SJose.Borrego@Sun.COM {
3278334SJose.Borrego@Sun.COM 	struct __res_state res_state;
3288334SJose.Borrego@Sun.COM 	int i;
3298334SJose.Borrego@Sun.COM 	char *entry, *p;
3308334SJose.Borrego@Sun.COM 	char first_label[MAXHOSTNAMELEN];
3318334SJose.Borrego@Sun.COM 	boolean_t found;
3328334SJose.Borrego@Sun.COM 
3338334SJose.Borrego@Sun.COM 	if (!nb_domain || !buf)
3348334SJose.Borrego@Sun.COM 		return (B_FALSE);
3358334SJose.Borrego@Sun.COM 
3368334SJose.Borrego@Sun.COM 	*buf = '\0';
3378334SJose.Borrego@Sun.COM 	bzero(&res_state, sizeof (struct __res_state));
3388334SJose.Borrego@Sun.COM 	if (res_ninit(&res_state))
3398334SJose.Borrego@Sun.COM 		return (B_FALSE);
3408334SJose.Borrego@Sun.COM 
3418334SJose.Borrego@Sun.COM 	found = B_FALSE;
3428334SJose.Borrego@Sun.COM 	entry = res_state.defdname;
3438334SJose.Borrego@Sun.COM 	for (i = 0; entry != NULL; i++) {
3448334SJose.Borrego@Sun.COM 		(void) strlcpy(first_label, entry, MAXHOSTNAMELEN);
3458334SJose.Borrego@Sun.COM 		if ((p = strchr(first_label, '.')) != NULL) {
3468334SJose.Borrego@Sun.COM 			*p = '\0';
3478334SJose.Borrego@Sun.COM 			if (strlen(first_label) > 15)
3488334SJose.Borrego@Sun.COM 				first_label[15] = '\0';
3498334SJose.Borrego@Sun.COM 		}
3508334SJose.Borrego@Sun.COM 
3518334SJose.Borrego@Sun.COM 		if (utf8_strcasecmp(nb_domain, first_label) == 0) {
3528334SJose.Borrego@Sun.COM 			found = B_TRUE;
3538334SJose.Borrego@Sun.COM 			(void) strlcpy(buf, entry, len);
3548334SJose.Borrego@Sun.COM 			break;
3558334SJose.Borrego@Sun.COM 		}
3568334SJose.Borrego@Sun.COM 
3578334SJose.Borrego@Sun.COM 		entry = res_state.dnsrch[i];
3588334SJose.Borrego@Sun.COM 	}
3598334SJose.Borrego@Sun.COM 
3608334SJose.Borrego@Sun.COM 
3618334SJose.Borrego@Sun.COM 	res_ndestroy(&res_state);
3628334SJose.Borrego@Sun.COM 	return (found);
3638334SJose.Borrego@Sun.COM }
3648334SJose.Borrego@Sun.COM 
3658334SJose.Borrego@Sun.COM /*
366*9832Samw@Sun.COM  * Obtain primary and trusted domain information using LSA queries.
3678334SJose.Borrego@Sun.COM  *
368*9832Samw@Sun.COM  * Disconnect any existing connection with the domain controller.
369*9832Samw@Sun.COM  * This will ensure that no stale connection will be used, it will
370*9832Samw@Sun.COM  * also pickup any configuration changes in either side by trying
371*9832Samw@Sun.COM  * to establish a new connection.
3728334SJose.Borrego@Sun.COM  *
3738334SJose.Borrego@Sun.COM  * domain - either NetBIOS or fully-qualified domain name
3748334SJose.Borrego@Sun.COM  */
3758334SJose.Borrego@Sun.COM static uint32_t
376*9832Samw@Sun.COM smb_domain_query(char *domain, char *server, smb_domain_t *di)
3778334SJose.Borrego@Sun.COM {
378*9832Samw@Sun.COM 	uint32_t status;
379*9832Samw@Sun.COM 
380*9832Samw@Sun.COM 	mlsvc_disconnect(server);
3818334SJose.Borrego@Sun.COM 
382*9832Samw@Sun.COM 	status = lsa_query_dns_domain_info(server, domain, &di->d_info);
383*9832Samw@Sun.COM 	if (status != NT_STATUS_SUCCESS) {
384*9832Samw@Sun.COM 		status = smb_domain_use_config(domain, &di->d_info);
385*9832Samw@Sun.COM 		if (status != NT_STATUS_SUCCESS)
386*9832Samw@Sun.COM 			status = lsa_query_primary_domain_info(server, domain,
387*9832Samw@Sun.COM 			    &di->d_info);
3888334SJose.Borrego@Sun.COM 	}
3898334SJose.Borrego@Sun.COM 
390*9832Samw@Sun.COM 	if (status == NT_STATUS_SUCCESS)
391*9832Samw@Sun.COM 		smb_domain_enum_trusted(domain, server, &di->d_trusted);
392*9832Samw@Sun.COM 
393*9832Samw@Sun.COM 	return (status);
3948334SJose.Borrego@Sun.COM }
3958334SJose.Borrego@Sun.COM 
3968334SJose.Borrego@Sun.COM /*
397*9832Samw@Sun.COM  * Obtain trusted domains information using LSA queries.
3988334SJose.Borrego@Sun.COM  *
3998334SJose.Borrego@Sun.COM  * domain - either NetBIOS or fully-qualified domain name.
4008334SJose.Borrego@Sun.COM  */
4018334SJose.Borrego@Sun.COM static void
402*9832Samw@Sun.COM smb_domain_enum_trusted(char *domain, char *server, smb_trusted_domains_t *list)
4038334SJose.Borrego@Sun.COM {
404*9832Samw@Sun.COM 	uint32_t status;
4058334SJose.Borrego@Sun.COM 
406*9832Samw@Sun.COM 	status = lsa_enum_trusted_domains_ex(server, domain, list);
407*9832Samw@Sun.COM 	if (status != NT_STATUS_SUCCESS)
408*9832Samw@Sun.COM 		(void) lsa_enum_trusted_domains(server, domain, list);
4098334SJose.Borrego@Sun.COM }
4108334SJose.Borrego@Sun.COM 
4118334SJose.Borrego@Sun.COM /*
4128334SJose.Borrego@Sun.COM  * If the domain to be discovered matches the current domain (i.e the
4138334SJose.Borrego@Sun.COM  * value of either domain or fqdn configuration), the output parameter
4148334SJose.Borrego@Sun.COM  * 'dinfo' will be set to the information stored in SMF.
4158334SJose.Borrego@Sun.COM  */
416*9832Samw@Sun.COM static uint32_t
417*9832Samw@Sun.COM smb_domain_use_config(char *domain, nt_domain_t *dinfo)
4188334SJose.Borrego@Sun.COM {
4198334SJose.Borrego@Sun.COM 	boolean_t use;
4208334SJose.Borrego@Sun.COM 
421*9832Samw@Sun.COM 	bzero(dinfo, sizeof (nt_domain_t));
422*9832Samw@Sun.COM 
4238334SJose.Borrego@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
424*9832Samw@Sun.COM 		return (NT_STATUS_UNSUCCESSFUL);
4258334SJose.Borrego@Sun.COM 
426*9832Samw@Sun.COM 	smb_config_getdomaininfo(dinfo->di_nbname, dinfo->di_fqname,
427*9832Samw@Sun.COM 	    NULL, NULL, NULL);
4288334SJose.Borrego@Sun.COM 
429*9832Samw@Sun.COM 	if (SMB_IS_FQDN(domain))
430*9832Samw@Sun.COM 		use = (utf8_strcasecmp(dinfo->di_fqname, domain) == 0);
431*9832Samw@Sun.COM 	else
432*9832Samw@Sun.COM 		use = (utf8_strcasecmp(dinfo->di_nbname, domain) == 0);
4338334SJose.Borrego@Sun.COM 
434*9832Samw@Sun.COM 	if (use)
435*9832Samw@Sun.COM 		smb_config_getdomaininfo(NULL, NULL, dinfo->di_sid,
436*9832Samw@Sun.COM 		    dinfo->di_u.di_dns.ddi_forest,
437*9832Samw@Sun.COM 		    dinfo->di_u.di_dns.ddi_guid);
4388334SJose.Borrego@Sun.COM 
439*9832Samw@Sun.COM 	return ((use) ? NT_STATUS_SUCCESS : NT_STATUS_UNSUCCESSFUL);
4408334SJose.Borrego@Sun.COM }
441*9832Samw@Sun.COM 
442*9832Samw@Sun.COM static void
443*9832Samw@Sun.COM smb_domain_free(smb_domain_t *di)
444*9832Samw@Sun.COM {
445*9832Samw@Sun.COM 	free(di->d_trusted.td_domains);
446*9832Samw@Sun.COM }
447