xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c (revision 10966:37e5dcdf36d3)
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/libsmbns.h>
428334SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h>
438334SJose.Borrego@Sun.COM 
448334SJose.Borrego@Sun.COM #include <smbsrv/smbinfo.h>
458334SJose.Borrego@Sun.COM #include <smbsrv/ntstatus.h>
468334SJose.Borrego@Sun.COM #include <lsalib.h>
478334SJose.Borrego@Sun.COM 
488334SJose.Borrego@Sun.COM /*
498334SJose.Borrego@Sun.COM  * DC Locator
508334SJose.Borrego@Sun.COM  */
5110717Samw@Sun.COM #define	SMB_DCLOCATOR_TIMEOUT	45	/* seconds */
528334SJose.Borrego@Sun.COM #define	SMB_IS_FQDN(domain)	(strchr(domain, '.') != NULL)
538334SJose.Borrego@Sun.COM 
548334SJose.Borrego@Sun.COM typedef struct smb_dclocator {
559832Samw@Sun.COM 	char		sdl_domain[SMB_PI_MAX_DOMAIN];
569832Samw@Sun.COM 	char		sdl_dc[MAXHOSTNAMELEN];
579832Samw@Sun.COM 	boolean_t	sdl_locate;
589832Samw@Sun.COM 	mutex_t		sdl_mtx;
599832Samw@Sun.COM 	cond_t		sdl_cv;
609832Samw@Sun.COM 	uint32_t	sdl_status;
618334SJose.Borrego@Sun.COM } smb_dclocator_t;
628334SJose.Borrego@Sun.COM 
638334SJose.Borrego@Sun.COM static smb_dclocator_t smb_dclocator;
648334SJose.Borrego@Sun.COM static pthread_t smb_dclocator_thr;
658334SJose.Borrego@Sun.COM 
6610717Samw@Sun.COM static void *smb_ddiscover_service(void *);
6710717Samw@Sun.COM static void smb_ddiscover_main(char *, char *);
6810717Samw@Sun.COM static boolean_t smb_ddiscover_dns(char *, char *, smb_domainex_t *);
6910717Samw@Sun.COM static boolean_t smb_ddiscover_nbt(char *, char *, smb_domainex_t *);
7010717Samw@Sun.COM static boolean_t smb_ddiscover_domain_match(char *, char *, uint32_t);
7110717Samw@Sun.COM static uint32_t smb_ddiscover_qinfo(char *, char *, smb_domainex_t *);
7210717Samw@Sun.COM static void smb_ddiscover_enum_trusted(char *, char *, smb_domainex_t *);
7310717Samw@Sun.COM static uint32_t smb_ddiscover_use_config(char *, smb_domainex_t *);
7410717Samw@Sun.COM static void smb_domainex_free(smb_domainex_t *);
758334SJose.Borrego@Sun.COM 
768334SJose.Borrego@Sun.COM /*
778334SJose.Borrego@Sun.COM  * ===================================================================
788334SJose.Borrego@Sun.COM  * API to initialize DC locator thread, trigger DC discovery, and
798334SJose.Borrego@Sun.COM  * get the discovered DC and/or domain information.
808334SJose.Borrego@Sun.COM  * ===================================================================
818334SJose.Borrego@Sun.COM  */
828334SJose.Borrego@Sun.COM 
838334SJose.Borrego@Sun.COM /*
848334SJose.Borrego@Sun.COM  * Initialization of the DC locator thread.
858334SJose.Borrego@Sun.COM  * Returns 0 on success, an error number if thread creation fails.
868334SJose.Borrego@Sun.COM  */
878334SJose.Borrego@Sun.COM int
888334SJose.Borrego@Sun.COM smb_dclocator_init(void)
898334SJose.Borrego@Sun.COM {
908334SJose.Borrego@Sun.COM 	pthread_attr_t tattr;
918334SJose.Borrego@Sun.COM 	int rc;
928334SJose.Borrego@Sun.COM 
938334SJose.Borrego@Sun.COM 	(void) pthread_attr_init(&tattr);
948334SJose.Borrego@Sun.COM 	(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
958334SJose.Borrego@Sun.COM 	rc = pthread_create(&smb_dclocator_thr, &tattr,
9610717Samw@Sun.COM 	    smb_ddiscover_service, 0);
978334SJose.Borrego@Sun.COM 	(void) pthread_attr_destroy(&tattr);
988334SJose.Borrego@Sun.COM 	return (rc);
998334SJose.Borrego@Sun.COM }
1008334SJose.Borrego@Sun.COM 
1018334SJose.Borrego@Sun.COM /*
1028334SJose.Borrego@Sun.COM  * This is the entry point for discovering a domain controller for the
1038334SJose.Borrego@Sun.COM  * specified domain.
1048334SJose.Borrego@Sun.COM  *
1058334SJose.Borrego@Sun.COM  * The actual work of discovering a DC is handled by DC locator thread.
1068334SJose.Borrego@Sun.COM  * All we do here is signal the request and wait for a DC or a timeout.
1078334SJose.Borrego@Sun.COM  *
1088334SJose.Borrego@Sun.COM  * Input parameters:
1098334SJose.Borrego@Sun.COM  *  domain - domain to be discovered (can either be NetBIOS or DNS domain)
1108334SJose.Borrego@Sun.COM  *  dc - preferred DC. If the preferred DC is set to empty string, it
1118334SJose.Borrego@Sun.COM  *       will attempt to discover any DC in the specified domain.
1128334SJose.Borrego@Sun.COM  *
1138334SJose.Borrego@Sun.COM  * Output parameter:
1148334SJose.Borrego@Sun.COM  *  dp - on success, dp will be filled with the discovered DC and domain
1158334SJose.Borrego@Sun.COM  *       information.
1168334SJose.Borrego@Sun.COM  * Returns B_TRUE if the DC/domain info is available.
1178334SJose.Borrego@Sun.COM  */
1188334SJose.Borrego@Sun.COM boolean_t
11910717Samw@Sun.COM smb_locate_dc(char *domain, char *dc, smb_domainex_t *dp)
1208334SJose.Borrego@Sun.COM {
1218334SJose.Borrego@Sun.COM 	int rc;
1228334SJose.Borrego@Sun.COM 	timestruc_t to;
12310717Samw@Sun.COM 	smb_domainex_t domain_info;
1248334SJose.Borrego@Sun.COM 
1258334SJose.Borrego@Sun.COM 	if (domain == NULL || *domain == '\0')
1268334SJose.Borrego@Sun.COM 		return (B_FALSE);
1278334SJose.Borrego@Sun.COM 
1288334SJose.Borrego@Sun.COM 	(void) mutex_lock(&smb_dclocator.sdl_mtx);
1298334SJose.Borrego@Sun.COM 
1308334SJose.Borrego@Sun.COM 	if (!smb_dclocator.sdl_locate) {
1318334SJose.Borrego@Sun.COM 		smb_dclocator.sdl_locate = B_TRUE;
1328334SJose.Borrego@Sun.COM 		(void) strlcpy(smb_dclocator.sdl_domain, domain,
1338334SJose.Borrego@Sun.COM 		    SMB_PI_MAX_DOMAIN);
1349832Samw@Sun.COM 		(void) strlcpy(smb_dclocator.sdl_dc, dc, MAXHOSTNAMELEN);
1358334SJose.Borrego@Sun.COM 		(void) cond_broadcast(&smb_dclocator.sdl_cv);
1368334SJose.Borrego@Sun.COM 	}
1378334SJose.Borrego@Sun.COM 
1388334SJose.Borrego@Sun.COM 	while (smb_dclocator.sdl_locate) {
1398334SJose.Borrego@Sun.COM 		to.tv_sec = SMB_DCLOCATOR_TIMEOUT;
1408334SJose.Borrego@Sun.COM 		to.tv_nsec = 0;
1418334SJose.Borrego@Sun.COM 		rc = cond_reltimedwait(&smb_dclocator.sdl_cv,
1428334SJose.Borrego@Sun.COM 		    &smb_dclocator.sdl_mtx, &to);
1438334SJose.Borrego@Sun.COM 
1448334SJose.Borrego@Sun.COM 		if (rc == ETIME)
1458334SJose.Borrego@Sun.COM 			break;
1468334SJose.Borrego@Sun.COM 	}
1478334SJose.Borrego@Sun.COM 
1488334SJose.Borrego@Sun.COM 	if (dp == NULL)
1498334SJose.Borrego@Sun.COM 		dp = &domain_info;
1508334SJose.Borrego@Sun.COM 	rc = smb_domain_getinfo(dp);
1519832Samw@Sun.COM 
1528334SJose.Borrego@Sun.COM 	(void) mutex_unlock(&smb_dclocator.sdl_mtx);
1538334SJose.Borrego@Sun.COM 
1548334SJose.Borrego@Sun.COM 	return (rc);
1558334SJose.Borrego@Sun.COM }
1568334SJose.Borrego@Sun.COM 
1578334SJose.Borrego@Sun.COM /*
1588334SJose.Borrego@Sun.COM  * ==========================================================
1598334SJose.Borrego@Sun.COM  * DC discovery functions
1608334SJose.Borrego@Sun.COM  * ==========================================================
1618334SJose.Borrego@Sun.COM  */
1628334SJose.Borrego@Sun.COM 
1638334SJose.Borrego@Sun.COM /*
16410717Samw@Sun.COM  * This is the domain and DC discovery service: it gets woken up whenever
16510717Samw@Sun.COM  * there is need to locate a domain controller.
1668334SJose.Borrego@Sun.COM  *
1679832Samw@Sun.COM  * Upon success, the SMB domain cache will be populated with the discovered
1689832Samw@Sun.COM  * DC and domain info.
1698334SJose.Borrego@Sun.COM  */
1708334SJose.Borrego@Sun.COM /*ARGSUSED*/
1718334SJose.Borrego@Sun.COM static void *
17210717Samw@Sun.COM smb_ddiscover_service(void *arg)
1738334SJose.Borrego@Sun.COM {
1748334SJose.Borrego@Sun.COM 	char domain[SMB_PI_MAX_DOMAIN];
1758334SJose.Borrego@Sun.COM 	char sought_dc[MAXHOSTNAMELEN];
1768334SJose.Borrego@Sun.COM 
1778334SJose.Borrego@Sun.COM 	for (;;) {
1788334SJose.Borrego@Sun.COM 		(void) mutex_lock(&smb_dclocator.sdl_mtx);
1798334SJose.Borrego@Sun.COM 
1808334SJose.Borrego@Sun.COM 		while (!smb_dclocator.sdl_locate)
1818334SJose.Borrego@Sun.COM 			(void) cond_wait(&smb_dclocator.sdl_cv,
1828334SJose.Borrego@Sun.COM 			    &smb_dclocator.sdl_mtx);
1838334SJose.Borrego@Sun.COM 
1848334SJose.Borrego@Sun.COM 		(void) strlcpy(domain, smb_dclocator.sdl_domain,
1858334SJose.Borrego@Sun.COM 		    SMB_PI_MAX_DOMAIN);
1868334SJose.Borrego@Sun.COM 		(void) strlcpy(sought_dc, smb_dclocator.sdl_dc, MAXHOSTNAMELEN);
1878334SJose.Borrego@Sun.COM 		(void) mutex_unlock(&smb_dclocator.sdl_mtx);
1888334SJose.Borrego@Sun.COM 
18910717Samw@Sun.COM 		smb_ddiscover_main(domain, sought_dc);
1908334SJose.Borrego@Sun.COM 
1918334SJose.Borrego@Sun.COM 		(void) mutex_lock(&smb_dclocator.sdl_mtx);
1928334SJose.Borrego@Sun.COM 		smb_dclocator.sdl_locate = B_FALSE;
1938334SJose.Borrego@Sun.COM 		(void) cond_broadcast(&smb_dclocator.sdl_cv);
1948334SJose.Borrego@Sun.COM 		(void) mutex_unlock(&smb_dclocator.sdl_mtx);
1958334SJose.Borrego@Sun.COM 	}
1968334SJose.Borrego@Sun.COM 
1978334SJose.Borrego@Sun.COM 	/*NOTREACHED*/
1988334SJose.Borrego@Sun.COM 	return (NULL);
1998334SJose.Borrego@Sun.COM }
2008334SJose.Borrego@Sun.COM 
2018334SJose.Borrego@Sun.COM /*
2029832Samw@Sun.COM  * Discovers a domain controller for the specified domain either via
2039832Samw@Sun.COM  * DNS or NetBIOS. After the domain controller is discovered successfully
2049832Samw@Sun.COM  * primary and trusted domain infromation will be queried using RPC queries.
2059832Samw@Sun.COM  * If the RPC queries fail, the domain information stored in SMF might be used
2069832Samw@Sun.COM  * if the the discovered domain is the same as the previously joined domain.
2079832Samw@Sun.COM  * If everything is successful domain cache will be updated with all the
2089832Samw@Sun.COM  * obtained information.
2099832Samw@Sun.COM  */
2109832Samw@Sun.COM static void
21110717Samw@Sun.COM smb_ddiscover_main(char *domain, char *server)
2129832Samw@Sun.COM {
21310717Samw@Sun.COM 	smb_domainex_t dxi;
21410717Samw@Sun.COM 	boolean_t discovered;
2159832Samw@Sun.COM 
21610717Samw@Sun.COM 	bzero(&dxi, sizeof (smb_domainex_t));
2179832Samw@Sun.COM 
21810717Samw@Sun.COM 	if (smb_domain_start_update() != SMB_DOMAIN_SUCCESS)
21910717Samw@Sun.COM 		return;
2209832Samw@Sun.COM 
2219832Samw@Sun.COM 	if (SMB_IS_FQDN(domain))
22210717Samw@Sun.COM 		discovered = smb_ddiscover_dns(domain, server, &dxi);
2239832Samw@Sun.COM 	else
22410717Samw@Sun.COM 		discovered = smb_ddiscover_nbt(domain, server, &dxi);
2259832Samw@Sun.COM 
22610717Samw@Sun.COM 	if (discovered)
22710717Samw@Sun.COM 		smb_domain_update(&dxi);
2289832Samw@Sun.COM 
22910717Samw@Sun.COM 	smb_domain_end_update();
2309832Samw@Sun.COM 
23110717Samw@Sun.COM 	smb_domainex_free(&dxi);
2329832Samw@Sun.COM 
23310717Samw@Sun.COM 	if (discovered)
23410717Samw@Sun.COM 		smb_domain_save();
2359832Samw@Sun.COM }
2369832Samw@Sun.COM 
2379832Samw@Sun.COM /*
2389832Samw@Sun.COM  * Discovers a DC for the specified domain via DNS. If a DC is found
2399832Samw@Sun.COM  * primary and trusted domains information will be queried.
2409832Samw@Sun.COM  */
2419832Samw@Sun.COM static boolean_t
24210717Samw@Sun.COM smb_ddiscover_dns(char *domain, char *server, smb_domainex_t *dxi)
2439832Samw@Sun.COM {
2449832Samw@Sun.COM 	uint32_t status;
24510717Samw@Sun.COM 
24610717Samw@Sun.COM 	if (!smb_ads_lookup_msdcs(domain, server, dxi->d_dc, MAXHOSTNAMELEN))
2479832Samw@Sun.COM 		return (B_FALSE);
2489832Samw@Sun.COM 
24910717Samw@Sun.COM 	status = smb_ddiscover_qinfo(domain, dxi->d_dc, dxi);
2509832Samw@Sun.COM 	return (status == NT_STATUS_SUCCESS);
2519832Samw@Sun.COM }
2529832Samw@Sun.COM 
2539832Samw@Sun.COM /*
2549832Samw@Sun.COM  * Discovers a DC for the specified domain using NETLOGON protocol.
2559832Samw@Sun.COM  * If a DC cannot be found using NETLOGON then it will
2568334SJose.Borrego@Sun.COM  * try to resolve it via DNS, i.e. find out if it is the first label
2578334SJose.Borrego@Sun.COM  * of a DNS domain name. If the corresponding DNS name is found, DC
2588334SJose.Borrego@Sun.COM  * discovery will be done via DNS query.
2598334SJose.Borrego@Sun.COM  *
2608334SJose.Borrego@Sun.COM  * If the fully-qualified domain name is derived from the DNS config
2618334SJose.Borrego@Sun.COM  * file, the NetBIOS domain name specified by the user will be compared
2628334SJose.Borrego@Sun.COM  * against the NetBIOS domain name obtained via LSA query.  If there is
2638334SJose.Borrego@Sun.COM  * a mismatch, the DC discovery will fail since the discovered DC is
2648334SJose.Borrego@Sun.COM  * actually for another domain, whose first label of its FQDN somehow
2658334SJose.Borrego@Sun.COM  * matches with the NetBIOS name of the domain we're interested in.
2668334SJose.Borrego@Sun.COM  */
2678334SJose.Borrego@Sun.COM static boolean_t
26810717Samw@Sun.COM smb_ddiscover_nbt(char *domain, char *server, smb_domainex_t *dxi)
2698334SJose.Borrego@Sun.COM {
2709832Samw@Sun.COM 	char dnsdomain[MAXHOSTNAMELEN];
2719832Samw@Sun.COM 	uint32_t status;
2728334SJose.Borrego@Sun.COM 
2739832Samw@Sun.COM 	*dnsdomain = '\0';
2749832Samw@Sun.COM 
27510717Samw@Sun.COM 	if (!smb_browser_netlogon(domain, dxi->d_dc, MAXHOSTNAMELEN)) {
27610717Samw@Sun.COM 		if (!smb_ddiscover_domain_match(domain, dnsdomain,
27710717Samw@Sun.COM 		    MAXHOSTNAMELEN))
2789832Samw@Sun.COM 			return (B_FALSE);
2799832Samw@Sun.COM 
28010717Samw@Sun.COM 		if (!smb_ads_lookup_msdcs(dnsdomain, server, dxi->d_dc,
2818334SJose.Borrego@Sun.COM 		    MAXHOSTNAMELEN))
2828334SJose.Borrego@Sun.COM 			return (B_FALSE);
2838334SJose.Borrego@Sun.COM 	}
2848334SJose.Borrego@Sun.COM 
28510717Samw@Sun.COM 	status = smb_ddiscover_qinfo(domain, dxi->d_dc, dxi);
2869832Samw@Sun.COM 	if (status != NT_STATUS_SUCCESS)
2878334SJose.Borrego@Sun.COM 		return (B_FALSE);
2888334SJose.Borrego@Sun.COM 
2899832Samw@Sun.COM 	if ((*dnsdomain != '\0') &&
290*10966SJordan.Brown@Sun.COM 	    smb_strcasecmp(domain, dxi->d_primary.di_nbname, 0))
2918334SJose.Borrego@Sun.COM 		return (B_FALSE);
2928334SJose.Borrego@Sun.COM 
2938334SJose.Borrego@Sun.COM 	/*
2948334SJose.Borrego@Sun.COM 	 * Now that we get the fully-qualified DNS name of the
2958334SJose.Borrego@Sun.COM 	 * domain via LSA query. Verifies ADS configuration
2968334SJose.Borrego@Sun.COM 	 * if we previously locate a DC via NetBIOS. On success,
2978334SJose.Borrego@Sun.COM 	 * ADS cache will be populated.
2988334SJose.Borrego@Sun.COM 	 */
29910717Samw@Sun.COM 	if (smb_ads_lookup_msdcs(dxi->d_primary.di_fqname, server,
30010717Samw@Sun.COM 	    dxi->d_dc, MAXHOSTNAMELEN) == 0)
3019832Samw@Sun.COM 		return (B_FALSE);
3028334SJose.Borrego@Sun.COM 
3038334SJose.Borrego@Sun.COM 	return (B_TRUE);
3048334SJose.Borrego@Sun.COM }
3058334SJose.Borrego@Sun.COM 
3068334SJose.Borrego@Sun.COM /*
3078334SJose.Borrego@Sun.COM  * Tries to find a matching DNS domain for the given NetBIOS domain
3088334SJose.Borrego@Sun.COM  * name by checking the first label of system's configured DNS domains.
3098334SJose.Borrego@Sun.COM  * If a match is found, it'll be returned in the passed buffer.
3108334SJose.Borrego@Sun.COM  */
3118334SJose.Borrego@Sun.COM static boolean_t
31210717Samw@Sun.COM smb_ddiscover_domain_match(char *nb_domain, char *buf, uint32_t len)
3138334SJose.Borrego@Sun.COM {
3148334SJose.Borrego@Sun.COM 	struct __res_state res_state;
3158334SJose.Borrego@Sun.COM 	int i;
3168334SJose.Borrego@Sun.COM 	char *entry, *p;
3178334SJose.Borrego@Sun.COM 	char first_label[MAXHOSTNAMELEN];
3188334SJose.Borrego@Sun.COM 	boolean_t found;
3198334SJose.Borrego@Sun.COM 
3208334SJose.Borrego@Sun.COM 	if (!nb_domain || !buf)
3218334SJose.Borrego@Sun.COM 		return (B_FALSE);
3228334SJose.Borrego@Sun.COM 
3238334SJose.Borrego@Sun.COM 	*buf = '\0';
3248334SJose.Borrego@Sun.COM 	bzero(&res_state, sizeof (struct __res_state));
3258334SJose.Borrego@Sun.COM 	if (res_ninit(&res_state))
3268334SJose.Borrego@Sun.COM 		return (B_FALSE);
3278334SJose.Borrego@Sun.COM 
3288334SJose.Borrego@Sun.COM 	found = B_FALSE;
3298334SJose.Borrego@Sun.COM 	entry = res_state.defdname;
3308334SJose.Borrego@Sun.COM 	for (i = 0; entry != NULL; i++) {
3318334SJose.Borrego@Sun.COM 		(void) strlcpy(first_label, entry, MAXHOSTNAMELEN);
3328334SJose.Borrego@Sun.COM 		if ((p = strchr(first_label, '.')) != NULL) {
3338334SJose.Borrego@Sun.COM 			*p = '\0';
3348334SJose.Borrego@Sun.COM 			if (strlen(first_label) > 15)
3358334SJose.Borrego@Sun.COM 				first_label[15] = '\0';
3368334SJose.Borrego@Sun.COM 		}
3378334SJose.Borrego@Sun.COM 
338*10966SJordan.Brown@Sun.COM 		if (smb_strcasecmp(nb_domain, first_label, 0) == 0) {
3398334SJose.Borrego@Sun.COM 			found = B_TRUE;
3408334SJose.Borrego@Sun.COM 			(void) strlcpy(buf, entry, len);
3418334SJose.Borrego@Sun.COM 			break;
3428334SJose.Borrego@Sun.COM 		}
3438334SJose.Borrego@Sun.COM 
3448334SJose.Borrego@Sun.COM 		entry = res_state.dnsrch[i];
3458334SJose.Borrego@Sun.COM 	}
3468334SJose.Borrego@Sun.COM 
3478334SJose.Borrego@Sun.COM 
3488334SJose.Borrego@Sun.COM 	res_ndestroy(&res_state);
3498334SJose.Borrego@Sun.COM 	return (found);
3508334SJose.Borrego@Sun.COM }
3518334SJose.Borrego@Sun.COM 
3528334SJose.Borrego@Sun.COM /*
3539832Samw@Sun.COM  * Obtain primary and trusted domain information using LSA queries.
3548334SJose.Borrego@Sun.COM  *
3559832Samw@Sun.COM  * Disconnect any existing connection with the domain controller.
3569832Samw@Sun.COM  * This will ensure that no stale connection will be used, it will
3579832Samw@Sun.COM  * also pickup any configuration changes in either side by trying
3589832Samw@Sun.COM  * to establish a new connection.
3598334SJose.Borrego@Sun.COM  *
3608334SJose.Borrego@Sun.COM  * domain - either NetBIOS or fully-qualified domain name
3618334SJose.Borrego@Sun.COM  */
3628334SJose.Borrego@Sun.COM static uint32_t
36310717Samw@Sun.COM smb_ddiscover_qinfo(char *domain, char *server, smb_domainex_t *dxi)
3648334SJose.Borrego@Sun.COM {
3659832Samw@Sun.COM 	uint32_t status;
3669832Samw@Sun.COM 
3679832Samw@Sun.COM 	mlsvc_disconnect(server);
3688334SJose.Borrego@Sun.COM 
36910717Samw@Sun.COM 	status = lsa_query_dns_domain_info(server, domain, &dxi->d_primary);
3709832Samw@Sun.COM 	if (status != NT_STATUS_SUCCESS) {
37110717Samw@Sun.COM 		status = smb_ddiscover_use_config(domain, dxi);
3729832Samw@Sun.COM 		if (status != NT_STATUS_SUCCESS)
3739832Samw@Sun.COM 			status = lsa_query_primary_domain_info(server, domain,
37410717Samw@Sun.COM 			    &dxi->d_primary);
3758334SJose.Borrego@Sun.COM 	}
3768334SJose.Borrego@Sun.COM 
3779832Samw@Sun.COM 	if (status == NT_STATUS_SUCCESS)
37810717Samw@Sun.COM 		smb_ddiscover_enum_trusted(domain, server, dxi);
3799832Samw@Sun.COM 
3809832Samw@Sun.COM 	return (status);
3818334SJose.Borrego@Sun.COM }
3828334SJose.Borrego@Sun.COM 
3838334SJose.Borrego@Sun.COM /*
3849832Samw@Sun.COM  * Obtain trusted domains information using LSA queries.
3858334SJose.Borrego@Sun.COM  *
3868334SJose.Borrego@Sun.COM  * domain - either NetBIOS or fully-qualified domain name.
3878334SJose.Borrego@Sun.COM  */
3888334SJose.Borrego@Sun.COM static void
38910717Samw@Sun.COM smb_ddiscover_enum_trusted(char *domain, char *server, smb_domainex_t *dxi)
3908334SJose.Borrego@Sun.COM {
39110717Samw@Sun.COM 	smb_trusted_domains_t *list;
3929832Samw@Sun.COM 	uint32_t status;
3938334SJose.Borrego@Sun.COM 
39410717Samw@Sun.COM 	list = &dxi->d_trusted;
3959832Samw@Sun.COM 	status = lsa_enum_trusted_domains_ex(server, domain, list);
3969832Samw@Sun.COM 	if (status != NT_STATUS_SUCCESS)
3979832Samw@Sun.COM 		(void) lsa_enum_trusted_domains(server, domain, list);
3988334SJose.Borrego@Sun.COM }
3998334SJose.Borrego@Sun.COM 
4008334SJose.Borrego@Sun.COM /*
4018334SJose.Borrego@Sun.COM  * If the domain to be discovered matches the current domain (i.e the
40210717Samw@Sun.COM  * value of either domain or fqdn configuration), then get the primary
40310717Samw@Sun.COM  * domain information from SMF.
4048334SJose.Borrego@Sun.COM  */
4059832Samw@Sun.COM static uint32_t
40610717Samw@Sun.COM smb_ddiscover_use_config(char *domain, smb_domainex_t *dxi)
4078334SJose.Borrego@Sun.COM {
4088334SJose.Borrego@Sun.COM 	boolean_t use;
40910717Samw@Sun.COM 	smb_domain_t *dinfo;
4108334SJose.Borrego@Sun.COM 
41110717Samw@Sun.COM 	dinfo = &dxi->d_primary;
41210717Samw@Sun.COM 	bzero(dinfo, sizeof (smb_domain_t));
4139832Samw@Sun.COM 
4148334SJose.Borrego@Sun.COM 	if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
4159832Samw@Sun.COM 		return (NT_STATUS_UNSUCCESSFUL);
4168334SJose.Borrego@Sun.COM 
4179832Samw@Sun.COM 	smb_config_getdomaininfo(dinfo->di_nbname, dinfo->di_fqname,
4189832Samw@Sun.COM 	    NULL, NULL, NULL);
4198334SJose.Borrego@Sun.COM 
4209832Samw@Sun.COM 	if (SMB_IS_FQDN(domain))
421*10966SJordan.Brown@Sun.COM 		use = (smb_strcasecmp(dinfo->di_fqname, domain, 0) == 0);
4229832Samw@Sun.COM 	else
423*10966SJordan.Brown@Sun.COM 		use = (smb_strcasecmp(dinfo->di_nbname, domain, 0) == 0);
4248334SJose.Borrego@Sun.COM 
4259832Samw@Sun.COM 	if (use)
4269832Samw@Sun.COM 		smb_config_getdomaininfo(NULL, NULL, dinfo->di_sid,
4279832Samw@Sun.COM 		    dinfo->di_u.di_dns.ddi_forest,
4289832Samw@Sun.COM 		    dinfo->di_u.di_dns.ddi_guid);
4298334SJose.Borrego@Sun.COM 
4309832Samw@Sun.COM 	return ((use) ? NT_STATUS_SUCCESS : NT_STATUS_UNSUCCESSFUL);
4318334SJose.Borrego@Sun.COM }
4329832Samw@Sun.COM 
4339832Samw@Sun.COM static void
43410717Samw@Sun.COM smb_domainex_free(smb_domainex_t *dxi)
4359832Samw@Sun.COM {
43610717Samw@Sun.COM 	free(dxi->d_trusted.td_domains);
4379832Samw@Sun.COM }
438