xref: /onnv-gate/usr/src/lib/nsswitch/ad/common/ad_common.c (revision 8040:42abce45ef67)
1*8040SBaban.Kenkre@Sun.COM /*
2*8040SBaban.Kenkre@Sun.COM  * CDDL HEADER START
3*8040SBaban.Kenkre@Sun.COM  *
4*8040SBaban.Kenkre@Sun.COM  * The contents of this file are subject to the terms of the
5*8040SBaban.Kenkre@Sun.COM  * Common Development and Distribution License (the "License").
6*8040SBaban.Kenkre@Sun.COM  * You may not use this file except in compliance with the License.
7*8040SBaban.Kenkre@Sun.COM  *
8*8040SBaban.Kenkre@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8040SBaban.Kenkre@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*8040SBaban.Kenkre@Sun.COM  * See the License for the specific language governing permissions
11*8040SBaban.Kenkre@Sun.COM  * and limitations under the License.
12*8040SBaban.Kenkre@Sun.COM  *
13*8040SBaban.Kenkre@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*8040SBaban.Kenkre@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8040SBaban.Kenkre@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*8040SBaban.Kenkre@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*8040SBaban.Kenkre@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*8040SBaban.Kenkre@Sun.COM  *
19*8040SBaban.Kenkre@Sun.COM  * CDDL HEADER END
20*8040SBaban.Kenkre@Sun.COM  */
21*8040SBaban.Kenkre@Sun.COM /*
22*8040SBaban.Kenkre@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*8040SBaban.Kenkre@Sun.COM  * Use is subject to license terms.
24*8040SBaban.Kenkre@Sun.COM  */
25*8040SBaban.Kenkre@Sun.COM 
26*8040SBaban.Kenkre@Sun.COM #include <malloc.h>
27*8040SBaban.Kenkre@Sun.COM #include <synch.h>
28*8040SBaban.Kenkre@Sun.COM #include <syslog.h>
29*8040SBaban.Kenkre@Sun.COM #include <rpcsvc/ypclnt.h>
30*8040SBaban.Kenkre@Sun.COM #include <rpcsvc/yp_prot.h>
31*8040SBaban.Kenkre@Sun.COM #include <pthread.h>
32*8040SBaban.Kenkre@Sun.COM #include <ctype.h>
33*8040SBaban.Kenkre@Sun.COM #include <stdlib.h>
34*8040SBaban.Kenkre@Sun.COM #include <stdio.h>
35*8040SBaban.Kenkre@Sun.COM #include <signal.h>
36*8040SBaban.Kenkre@Sun.COM #include <sys/stat.h>
37*8040SBaban.Kenkre@Sun.COM #include <assert.h>
38*8040SBaban.Kenkre@Sun.COM #include "ad_common.h"
39*8040SBaban.Kenkre@Sun.COM 
40*8040SBaban.Kenkre@Sun.COM static pthread_mutex_t	statelock = PTHREAD_MUTEX_INITIALIZER;
41*8040SBaban.Kenkre@Sun.COM static nssad_state_t	state = {0};
42*8040SBaban.Kenkre@Sun.COM 
43*8040SBaban.Kenkre@Sun.COM static void
44*8040SBaban.Kenkre@Sun.COM nssad_cfg_free_props(nssad_prop_t *props)
45*8040SBaban.Kenkre@Sun.COM {
46*8040SBaban.Kenkre@Sun.COM 	if (props->domain_name != NULL) {
47*8040SBaban.Kenkre@Sun.COM 		free(props->domain_name);
48*8040SBaban.Kenkre@Sun.COM 		props->domain_name = NULL;
49*8040SBaban.Kenkre@Sun.COM 	}
50*8040SBaban.Kenkre@Sun.COM 	if (props->domain_controller != NULL) {
51*8040SBaban.Kenkre@Sun.COM 		free(props->domain_controller);
52*8040SBaban.Kenkre@Sun.COM 		props->domain_controller = NULL;
53*8040SBaban.Kenkre@Sun.COM 	}
54*8040SBaban.Kenkre@Sun.COM }
55*8040SBaban.Kenkre@Sun.COM 
56*8040SBaban.Kenkre@Sun.COM static int
57*8040SBaban.Kenkre@Sun.COM nssad_cfg_discover_props(const char *domain, ad_disc_t ad_ctx,
58*8040SBaban.Kenkre@Sun.COM 	nssad_prop_t *props)
59*8040SBaban.Kenkre@Sun.COM {
60*8040SBaban.Kenkre@Sun.COM 	ad_disc_refresh(ad_ctx);
61*8040SBaban.Kenkre@Sun.COM 	if (ad_disc_set_DomainName(ad_ctx, domain) != 0)
62*8040SBaban.Kenkre@Sun.COM 		return (-1);
63*8040SBaban.Kenkre@Sun.COM 	if (props->domain_controller == NULL)
64*8040SBaban.Kenkre@Sun.COM 		props->domain_controller =
65*8040SBaban.Kenkre@Sun.COM 		    ad_disc_get_DomainController(ad_ctx, AD_DISC_PREFER_SITE);
66*8040SBaban.Kenkre@Sun.COM 	return (0);
67*8040SBaban.Kenkre@Sun.COM }
68*8040SBaban.Kenkre@Sun.COM 
69*8040SBaban.Kenkre@Sun.COM static int
70*8040SBaban.Kenkre@Sun.COM nssad_cfg_reload_ad(nssad_prop_t *props, adutils_ad_t **ad)
71*8040SBaban.Kenkre@Sun.COM {
72*8040SBaban.Kenkre@Sun.COM 	int		i;
73*8040SBaban.Kenkre@Sun.COM 	adutils_ad_t	*new;
74*8040SBaban.Kenkre@Sun.COM 
75*8040SBaban.Kenkre@Sun.COM 	if (props->domain_controller == NULL ||
76*8040SBaban.Kenkre@Sun.COM 	    props->domain_controller[0].host[0] == '\0')
77*8040SBaban.Kenkre@Sun.COM 		return (0);
78*8040SBaban.Kenkre@Sun.COM 	if (adutils_ad_alloc(&new, props->domain_name,
79*8040SBaban.Kenkre@Sun.COM 	    ADUTILS_AD_DATA) != ADUTILS_SUCCESS)
80*8040SBaban.Kenkre@Sun.COM 		return (-1);
81*8040SBaban.Kenkre@Sun.COM 	for (i = 0; props->domain_controller[i].host[0] != '\0'; i++) {
82*8040SBaban.Kenkre@Sun.COM 		if (adutils_add_ds(new,
83*8040SBaban.Kenkre@Sun.COM 		    props->domain_controller[i].host,
84*8040SBaban.Kenkre@Sun.COM 		    props->domain_controller[i].port) != ADUTILS_SUCCESS) {
85*8040SBaban.Kenkre@Sun.COM 			adutils_ad_free(&new);
86*8040SBaban.Kenkre@Sun.COM 			return (-1);
87*8040SBaban.Kenkre@Sun.COM 		}
88*8040SBaban.Kenkre@Sun.COM 	}
89*8040SBaban.Kenkre@Sun.COM 
90*8040SBaban.Kenkre@Sun.COM 	if (*ad != NULL)
91*8040SBaban.Kenkre@Sun.COM 		adutils_ad_free(ad);
92*8040SBaban.Kenkre@Sun.COM 	*ad = new;
93*8040SBaban.Kenkre@Sun.COM 	return (0);
94*8040SBaban.Kenkre@Sun.COM }
95*8040SBaban.Kenkre@Sun.COM 
96*8040SBaban.Kenkre@Sun.COM static
97*8040SBaban.Kenkre@Sun.COM int
98*8040SBaban.Kenkre@Sun.COM update_dirs(idmap_ad_disc_ds_t **value, idmap_ad_disc_ds_t **new)
99*8040SBaban.Kenkre@Sun.COM {
100*8040SBaban.Kenkre@Sun.COM 	if (*value == *new)
101*8040SBaban.Kenkre@Sun.COM 		return (0);
102*8040SBaban.Kenkre@Sun.COM 
103*8040SBaban.Kenkre@Sun.COM 	if (*value != NULL && *new != NULL &&
104*8040SBaban.Kenkre@Sun.COM 	    ad_disc_compare_ds(*value, *new) == 0) {
105*8040SBaban.Kenkre@Sun.COM 		free(*new);
106*8040SBaban.Kenkre@Sun.COM 		*new = NULL;
107*8040SBaban.Kenkre@Sun.COM 		return (0);
108*8040SBaban.Kenkre@Sun.COM 	}
109*8040SBaban.Kenkre@Sun.COM 
110*8040SBaban.Kenkre@Sun.COM 	if (*value)
111*8040SBaban.Kenkre@Sun.COM 		free(*value);
112*8040SBaban.Kenkre@Sun.COM 	*value = *new;
113*8040SBaban.Kenkre@Sun.COM 	*new = NULL;
114*8040SBaban.Kenkre@Sun.COM 	return (1);
115*8040SBaban.Kenkre@Sun.COM }
116*8040SBaban.Kenkre@Sun.COM 
117*8040SBaban.Kenkre@Sun.COM static
118*8040SBaban.Kenkre@Sun.COM int
119*8040SBaban.Kenkre@Sun.COM nssad_cfg_refresh(nssad_cfg_t *cp)
120*8040SBaban.Kenkre@Sun.COM {
121*8040SBaban.Kenkre@Sun.COM 	nssad_prop_t	props;
122*8040SBaban.Kenkre@Sun.COM 
123*8040SBaban.Kenkre@Sun.COM 	(void) ad_disc_SubnetChanged(cp->ad_ctx);
124*8040SBaban.Kenkre@Sun.COM 	(void) memset(&props, 0, sizeof (props));
125*8040SBaban.Kenkre@Sun.COM 	if (nssad_cfg_discover_props(cp->props.domain_name, cp->ad_ctx,
126*8040SBaban.Kenkre@Sun.COM 	    &props) < 0)
127*8040SBaban.Kenkre@Sun.COM 		return (-1);
128*8040SBaban.Kenkre@Sun.COM 	if (update_dirs(&cp->props.domain_controller,
129*8040SBaban.Kenkre@Sun.COM 	    &props.domain_controller)) {
130*8040SBaban.Kenkre@Sun.COM 		if (cp->props.domain_controller != NULL &&
131*8040SBaban.Kenkre@Sun.COM 		    cp->props.domain_controller[0].host[0] != '\0')
132*8040SBaban.Kenkre@Sun.COM 			(void) nssad_cfg_reload_ad(&cp->props, &cp->ad);
133*8040SBaban.Kenkre@Sun.COM 	}
134*8040SBaban.Kenkre@Sun.COM 	return (0);
135*8040SBaban.Kenkre@Sun.COM }
136*8040SBaban.Kenkre@Sun.COM 
137*8040SBaban.Kenkre@Sun.COM static void
138*8040SBaban.Kenkre@Sun.COM nssad_cfg_destroy(nssad_cfg_t *cp)
139*8040SBaban.Kenkre@Sun.COM {
140*8040SBaban.Kenkre@Sun.COM 	if (cp != NULL) {
141*8040SBaban.Kenkre@Sun.COM 		(void) pthread_rwlock_destroy(&cp->lock);
142*8040SBaban.Kenkre@Sun.COM 		ad_disc_fini(cp->ad_ctx);
143*8040SBaban.Kenkre@Sun.COM 		nssad_cfg_free_props(&cp->props);
144*8040SBaban.Kenkre@Sun.COM 		adutils_ad_free(&cp->ad);
145*8040SBaban.Kenkre@Sun.COM 		free(cp);
146*8040SBaban.Kenkre@Sun.COM 	}
147*8040SBaban.Kenkre@Sun.COM }
148*8040SBaban.Kenkre@Sun.COM 
149*8040SBaban.Kenkre@Sun.COM static nssad_cfg_t *
150*8040SBaban.Kenkre@Sun.COM nssad_cfg_create(const char *domain)
151*8040SBaban.Kenkre@Sun.COM {
152*8040SBaban.Kenkre@Sun.COM 	nssad_cfg_t	*cp;
153*8040SBaban.Kenkre@Sun.COM 
154*8040SBaban.Kenkre@Sun.COM 	if ((cp = calloc(1, sizeof (*cp))) == NULL)
155*8040SBaban.Kenkre@Sun.COM 		return (NULL);
156*8040SBaban.Kenkre@Sun.COM 	if (pthread_rwlock_init(&cp->lock, NULL) != 0) {
157*8040SBaban.Kenkre@Sun.COM 		free(cp);
158*8040SBaban.Kenkre@Sun.COM 		return (NULL);
159*8040SBaban.Kenkre@Sun.COM 	}
160*8040SBaban.Kenkre@Sun.COM 	adutils_set_log(-1, TRUE, FALSE);
161*8040SBaban.Kenkre@Sun.COM 	if ((cp->ad_ctx = ad_disc_init()) == NULL)
162*8040SBaban.Kenkre@Sun.COM 		goto errout;
163*8040SBaban.Kenkre@Sun.COM 	if ((cp->props.domain_name = strdup(domain)) == NULL)
164*8040SBaban.Kenkre@Sun.COM 		goto errout;
165*8040SBaban.Kenkre@Sun.COM 	if (nssad_cfg_discover_props(domain, cp->ad_ctx, &cp->props) < 0)
166*8040SBaban.Kenkre@Sun.COM 		goto errout;
167*8040SBaban.Kenkre@Sun.COM 	if (nssad_cfg_reload_ad(&cp->props, &cp->ad) < 0)
168*8040SBaban.Kenkre@Sun.COM 		goto errout;
169*8040SBaban.Kenkre@Sun.COM 	return (cp);
170*8040SBaban.Kenkre@Sun.COM errout:
171*8040SBaban.Kenkre@Sun.COM 	nssad_cfg_destroy(cp);
172*8040SBaban.Kenkre@Sun.COM 	return (NULL);
173*8040SBaban.Kenkre@Sun.COM }
174*8040SBaban.Kenkre@Sun.COM 
175*8040SBaban.Kenkre@Sun.COM #define	hex_char(n)	"0123456789abcdef"[n & 0xf]
176*8040SBaban.Kenkre@Sun.COM 
177*8040SBaban.Kenkre@Sun.COM int
178*8040SBaban.Kenkre@Sun.COM _ldap_filter_name(char *filter_name, const char *name, int filter_name_size)
179*8040SBaban.Kenkre@Sun.COM {
180*8040SBaban.Kenkre@Sun.COM 	char *end = filter_name + filter_name_size;
181*8040SBaban.Kenkre@Sun.COM 	char c;
182*8040SBaban.Kenkre@Sun.COM 
183*8040SBaban.Kenkre@Sun.COM 	for (; *name; name++) {
184*8040SBaban.Kenkre@Sun.COM 		c = *name;
185*8040SBaban.Kenkre@Sun.COM 		switch (c) {
186*8040SBaban.Kenkre@Sun.COM 			case '*':
187*8040SBaban.Kenkre@Sun.COM 			case '(':
188*8040SBaban.Kenkre@Sun.COM 			case ')':
189*8040SBaban.Kenkre@Sun.COM 			case '\\':
190*8040SBaban.Kenkre@Sun.COM 				if (end <= filter_name + 3)
191*8040SBaban.Kenkre@Sun.COM 					return (-1);
192*8040SBaban.Kenkre@Sun.COM 				*filter_name++ = '\\';
193*8040SBaban.Kenkre@Sun.COM 				*filter_name++ = hex_char(c >> 4);
194*8040SBaban.Kenkre@Sun.COM 				*filter_name++ = hex_char(c & 0xf);
195*8040SBaban.Kenkre@Sun.COM 				break;
196*8040SBaban.Kenkre@Sun.COM 			default:
197*8040SBaban.Kenkre@Sun.COM 				if (end <= filter_name + 1)
198*8040SBaban.Kenkre@Sun.COM 					return (-1);
199*8040SBaban.Kenkre@Sun.COM 				*filter_name++ = c;
200*8040SBaban.Kenkre@Sun.COM 				break;
201*8040SBaban.Kenkre@Sun.COM 		}
202*8040SBaban.Kenkre@Sun.COM 	}
203*8040SBaban.Kenkre@Sun.COM 	if (end <= filter_name)
204*8040SBaban.Kenkre@Sun.COM 		return (-1);
205*8040SBaban.Kenkre@Sun.COM 	*filter_name = '\0';
206*8040SBaban.Kenkre@Sun.COM 	return (0);
207*8040SBaban.Kenkre@Sun.COM }
208*8040SBaban.Kenkre@Sun.COM 
209*8040SBaban.Kenkre@Sun.COM static
210*8040SBaban.Kenkre@Sun.COM nss_status_t
211*8040SBaban.Kenkre@Sun.COM map_adrc2nssrc(adutils_rc adrc)
212*8040SBaban.Kenkre@Sun.COM {
213*8040SBaban.Kenkre@Sun.COM 	if (adrc == ADUTILS_SUCCESS)
214*8040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_SUCCESS);
215*8040SBaban.Kenkre@Sun.COM 	if (adrc == ADUTILS_ERR_NOTFOUND)
216*8040SBaban.Kenkre@Sun.COM 		errno = 0;
217*8040SBaban.Kenkre@Sun.COM 	return ((nss_status_t)NSS_NOTFOUND);
218*8040SBaban.Kenkre@Sun.COM }
219*8040SBaban.Kenkre@Sun.COM 
220*8040SBaban.Kenkre@Sun.COM /* ARGSUSED */
221*8040SBaban.Kenkre@Sun.COM nss_status_t
222*8040SBaban.Kenkre@Sun.COM _nss_ad_marshall_data(ad_backend_ptr be, nss_XbyY_args_t *argp)
223*8040SBaban.Kenkre@Sun.COM {
224*8040SBaban.Kenkre@Sun.COM 	int	stat;
225*8040SBaban.Kenkre@Sun.COM 
226*8040SBaban.Kenkre@Sun.COM 	if (argp->buf.result == NULL) {
227*8040SBaban.Kenkre@Sun.COM 		/*
228*8040SBaban.Kenkre@Sun.COM 		 * This suggests that the process (e.g. nscd) expects
229*8040SBaban.Kenkre@Sun.COM 		 * nssad to return the data in native file format in
230*8040SBaban.Kenkre@Sun.COM 		 * argp->buf.buffer i.e. no need to marshall the data.
231*8040SBaban.Kenkre@Sun.COM 		 */
232*8040SBaban.Kenkre@Sun.COM 		argp->returnval = argp->buf.buffer;
233*8040SBaban.Kenkre@Sun.COM 		argp->returnlen = strlen(argp->buf.buffer);
234*8040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_STR_PARSE_SUCCESS);
235*8040SBaban.Kenkre@Sun.COM 	}
236*8040SBaban.Kenkre@Sun.COM 
237*8040SBaban.Kenkre@Sun.COM 	if (argp->str2ent == NULL)
238*8040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_STR_PARSE_PARSE);
239*8040SBaban.Kenkre@Sun.COM 
240*8040SBaban.Kenkre@Sun.COM 	stat = (*argp->str2ent)(be->buffer, be->buflen,
241*8040SBaban.Kenkre@Sun.COM 	    argp->buf.result, argp->buf.buffer, argp->buf.buflen);
242*8040SBaban.Kenkre@Sun.COM 
243*8040SBaban.Kenkre@Sun.COM 	if (stat == NSS_STR_PARSE_SUCCESS) {
244*8040SBaban.Kenkre@Sun.COM 		argp->returnval = argp->buf.result;
245*8040SBaban.Kenkre@Sun.COM 		argp->returnlen = 1; /* irrelevant */
246*8040SBaban.Kenkre@Sun.COM 	}
247*8040SBaban.Kenkre@Sun.COM 	return ((nss_status_t)stat);
248*8040SBaban.Kenkre@Sun.COM }
249*8040SBaban.Kenkre@Sun.COM 
250*8040SBaban.Kenkre@Sun.COM nss_status_t
251*8040SBaban.Kenkre@Sun.COM _nss_ad_sanitize_status(ad_backend_ptr be, nss_XbyY_args_t *argp,
252*8040SBaban.Kenkre@Sun.COM 		nss_status_t stat)
253*8040SBaban.Kenkre@Sun.COM {
254*8040SBaban.Kenkre@Sun.COM 	if (be->buffer != NULL) {
255*8040SBaban.Kenkre@Sun.COM 		free(be->buffer);
256*8040SBaban.Kenkre@Sun.COM 		be->buffer = NULL;
257*8040SBaban.Kenkre@Sun.COM 		be->buflen = 0;
258*8040SBaban.Kenkre@Sun.COM 		be->db_type = NSS_AD_DB_NONE;
259*8040SBaban.Kenkre@Sun.COM 	}
260*8040SBaban.Kenkre@Sun.COM 
261*8040SBaban.Kenkre@Sun.COM 	if (stat == NSS_STR_PARSE_SUCCESS) {
262*8040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_SUCCESS);
263*8040SBaban.Kenkre@Sun.COM 	} else if (stat == NSS_STR_PARSE_PARSE) {
264*8040SBaban.Kenkre@Sun.COM 		argp->returnval = 0;
265*8040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
266*8040SBaban.Kenkre@Sun.COM 	} else if (stat == NSS_STR_PARSE_ERANGE) {
267*8040SBaban.Kenkre@Sun.COM 		argp->erange = 1;
268*8040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
269*8040SBaban.Kenkre@Sun.COM 	}
270*8040SBaban.Kenkre@Sun.COM 	return ((nss_status_t)NSS_UNAVAIL);
271*8040SBaban.Kenkre@Sun.COM }
272*8040SBaban.Kenkre@Sun.COM 
273*8040SBaban.Kenkre@Sun.COM /* ARGSUSED */
274*8040SBaban.Kenkre@Sun.COM static
275*8040SBaban.Kenkre@Sun.COM nssad_cfg_t *
276*8040SBaban.Kenkre@Sun.COM get_cfg(const char *domain)
277*8040SBaban.Kenkre@Sun.COM {
278*8040SBaban.Kenkre@Sun.COM 	nssad_cfg_t	*cp, *lru, *prev;
279*8040SBaban.Kenkre@Sun.COM 
280*8040SBaban.Kenkre@Sun.COM 	/*
281*8040SBaban.Kenkre@Sun.COM 	 * Note about the queue:
282*8040SBaban.Kenkre@Sun.COM 	 *
283*8040SBaban.Kenkre@Sun.COM 	 * The queue is used to hold our per domain
284*8040SBaban.Kenkre@Sun.COM 	 * configs. The queue is limited to CFG_QUEUE_MAX_SIZE.
285*8040SBaban.Kenkre@Sun.COM 	 * If the queue increases beyond that point we toss
286*8040SBaban.Kenkre@Sun.COM 	 * out the LRU entry. The entries are inserted into
287*8040SBaban.Kenkre@Sun.COM 	 * the queue at state.qtail and the LRU entry is
288*8040SBaban.Kenkre@Sun.COM 	 * removed from state.qhead. state.qnext points
289*8040SBaban.Kenkre@Sun.COM 	 * from the qtail to the qhead. Everytime a config
290*8040SBaban.Kenkre@Sun.COM 	 * is accessed it is moved to qtail.
291*8040SBaban.Kenkre@Sun.COM 	 */
292*8040SBaban.Kenkre@Sun.COM 
293*8040SBaban.Kenkre@Sun.COM 	(void) pthread_mutex_lock(&statelock);
294*8040SBaban.Kenkre@Sun.COM 
295*8040SBaban.Kenkre@Sun.COM 	for (cp = state.qtail, prev = NULL; cp != NULL;
296*8040SBaban.Kenkre@Sun.COM 	    prev = cp, cp = cp->qnext) {
297*8040SBaban.Kenkre@Sun.COM 		if (cp->props.domain_name == NULL ||
298*8040SBaban.Kenkre@Sun.COM 		    strcasecmp(cp->props.domain_name, domain) != 0)
299*8040SBaban.Kenkre@Sun.COM 			continue;
300*8040SBaban.Kenkre@Sun.COM 
301*8040SBaban.Kenkre@Sun.COM 		/* Found config for the given domain. */
302*8040SBaban.Kenkre@Sun.COM 
303*8040SBaban.Kenkre@Sun.COM 		if (state.qtail != cp) {
304*8040SBaban.Kenkre@Sun.COM 			/*
305*8040SBaban.Kenkre@Sun.COM 			 * Move the entry to the tail of the queue.
306*8040SBaban.Kenkre@Sun.COM 			 * This way the LRU entry can be found at
307*8040SBaban.Kenkre@Sun.COM 			 * the head of the queue.
308*8040SBaban.Kenkre@Sun.COM 			 */
309*8040SBaban.Kenkre@Sun.COM 			prev->qnext = cp->qnext;
310*8040SBaban.Kenkre@Sun.COM 			if (state.qhead == cp)
311*8040SBaban.Kenkre@Sun.COM 				state.qhead = prev;
312*8040SBaban.Kenkre@Sun.COM 			cp->qnext = state.qtail;
313*8040SBaban.Kenkre@Sun.COM 			state.qtail = cp;
314*8040SBaban.Kenkre@Sun.COM 		}
315*8040SBaban.Kenkre@Sun.COM 
316*8040SBaban.Kenkre@Sun.COM 		if (ad_disc_get_TTL(cp->ad_ctx) == 0) {
317*8040SBaban.Kenkre@Sun.COM 			/*
318*8040SBaban.Kenkre@Sun.COM 			 * If there are expired items in the
319*8040SBaban.Kenkre@Sun.COM 			 * config, grab the write lock and
320*8040SBaban.Kenkre@Sun.COM 			 * refresh the config.
321*8040SBaban.Kenkre@Sun.COM 			 */
322*8040SBaban.Kenkre@Sun.COM 			(void) pthread_rwlock_wrlock(&cp->lock);
323*8040SBaban.Kenkre@Sun.COM 			if (nssad_cfg_refresh(cp) < 0) {
324*8040SBaban.Kenkre@Sun.COM 				(void) pthread_rwlock_unlock(&cp->lock);
325*8040SBaban.Kenkre@Sun.COM 				(void) pthread_mutex_unlock(&statelock);
326*8040SBaban.Kenkre@Sun.COM 				return (NULL);
327*8040SBaban.Kenkre@Sun.COM 			}
328*8040SBaban.Kenkre@Sun.COM 			(void) pthread_rwlock_unlock(&cp->lock);
329*8040SBaban.Kenkre@Sun.COM 		}
330*8040SBaban.Kenkre@Sun.COM 
331*8040SBaban.Kenkre@Sun.COM 		/* Return the config found */
332*8040SBaban.Kenkre@Sun.COM 		(void) pthread_rwlock_rdlock(&cp->lock);
333*8040SBaban.Kenkre@Sun.COM 		(void) pthread_mutex_unlock(&statelock);
334*8040SBaban.Kenkre@Sun.COM 		return (cp);
335*8040SBaban.Kenkre@Sun.COM 	}
336*8040SBaban.Kenkre@Sun.COM 
337*8040SBaban.Kenkre@Sun.COM 	/* Create new config entry for the domain */
338*8040SBaban.Kenkre@Sun.COM 	if ((cp = nssad_cfg_create(domain)) == NULL) {
339*8040SBaban.Kenkre@Sun.COM 		(void) pthread_mutex_unlock(&statelock);
340*8040SBaban.Kenkre@Sun.COM 		return (NULL);
341*8040SBaban.Kenkre@Sun.COM 	}
342*8040SBaban.Kenkre@Sun.COM 
343*8040SBaban.Kenkre@Sun.COM 	/* Add it to the queue */
344*8040SBaban.Kenkre@Sun.COM 	state.qcount++;
345*8040SBaban.Kenkre@Sun.COM 	if (state.qtail == NULL) {
346*8040SBaban.Kenkre@Sun.COM 		state.qtail = state.qhead = cp;
347*8040SBaban.Kenkre@Sun.COM 		(void) pthread_rwlock_rdlock(&cp->lock);
348*8040SBaban.Kenkre@Sun.COM 		(void) pthread_mutex_unlock(&statelock);
349*8040SBaban.Kenkre@Sun.COM 		return (cp);
350*8040SBaban.Kenkre@Sun.COM 	}
351*8040SBaban.Kenkre@Sun.COM 	cp->qnext = state.qtail;
352*8040SBaban.Kenkre@Sun.COM 	state.qtail = cp;
353*8040SBaban.Kenkre@Sun.COM 
354*8040SBaban.Kenkre@Sun.COM 	/* If the queue has exceeded its size, remove the LRU entry */
355*8040SBaban.Kenkre@Sun.COM 	if (state.qcount >= CFG_QUEUE_MAX_SIZE) {
356*8040SBaban.Kenkre@Sun.COM 		/* Detach the lru entry and destroy */
357*8040SBaban.Kenkre@Sun.COM 		lru = state.qhead;
358*8040SBaban.Kenkre@Sun.COM 		if (pthread_rwlock_trywrlock(&lru->lock) == 0) {
359*8040SBaban.Kenkre@Sun.COM 			for (prev = state.qtail; prev != NULL;
360*8040SBaban.Kenkre@Sun.COM 			    prev = prev->qnext) {
361*8040SBaban.Kenkre@Sun.COM 				if (prev->qnext != lru)
362*8040SBaban.Kenkre@Sun.COM 					continue;
363*8040SBaban.Kenkre@Sun.COM 				state.qhead = prev;
364*8040SBaban.Kenkre@Sun.COM 				prev->qnext = NULL;
365*8040SBaban.Kenkre@Sun.COM 				state.qcount--;
366*8040SBaban.Kenkre@Sun.COM 				(void) pthread_rwlock_unlock(&lru->lock);
367*8040SBaban.Kenkre@Sun.COM 				nssad_cfg_destroy(lru);
368*8040SBaban.Kenkre@Sun.COM 				break;
369*8040SBaban.Kenkre@Sun.COM 			}
370*8040SBaban.Kenkre@Sun.COM 			(void) assert(prev != NULL);
371*8040SBaban.Kenkre@Sun.COM 		}
372*8040SBaban.Kenkre@Sun.COM 	}
373*8040SBaban.Kenkre@Sun.COM 
374*8040SBaban.Kenkre@Sun.COM 	(void) pthread_rwlock_rdlock(&cp->lock);
375*8040SBaban.Kenkre@Sun.COM 	(void) pthread_mutex_unlock(&statelock);
376*8040SBaban.Kenkre@Sun.COM 	return (cp);
377*8040SBaban.Kenkre@Sun.COM }
378*8040SBaban.Kenkre@Sun.COM 
379*8040SBaban.Kenkre@Sun.COM 
380*8040SBaban.Kenkre@Sun.COM /* ARGSUSED */
381*8040SBaban.Kenkre@Sun.COM static
382*8040SBaban.Kenkre@Sun.COM nss_status_t
383*8040SBaban.Kenkre@Sun.COM ad_lookup(const char *filter, const char **attrs,
384*8040SBaban.Kenkre@Sun.COM 	const char *domain, adutils_result_t **result)
385*8040SBaban.Kenkre@Sun.COM {
386*8040SBaban.Kenkre@Sun.COM 	int			retries = 0;
387*8040SBaban.Kenkre@Sun.COM 	adutils_rc		rc, brc;
388*8040SBaban.Kenkre@Sun.COM 	adutils_query_state_t	*qs;
389*8040SBaban.Kenkre@Sun.COM 	nssad_cfg_t		*cp;
390*8040SBaban.Kenkre@Sun.COM 
391*8040SBaban.Kenkre@Sun.COM retry:
392*8040SBaban.Kenkre@Sun.COM 	if ((cp = get_cfg(domain)) == NULL)
393*8040SBaban.Kenkre@Sun.COM 		return ((nss_status_t)NSS_NOTFOUND);
394*8040SBaban.Kenkre@Sun.COM 
395*8040SBaban.Kenkre@Sun.COM 	rc = adutils_lookup_batch_start(cp->ad, 1, NULL, NULL, &qs);
396*8040SBaban.Kenkre@Sun.COM 	(void) pthread_rwlock_unlock(&cp->lock);
397*8040SBaban.Kenkre@Sun.COM 	if (rc != ADUTILS_SUCCESS)
398*8040SBaban.Kenkre@Sun.COM 		goto out;
399*8040SBaban.Kenkre@Sun.COM 
400*8040SBaban.Kenkre@Sun.COM 	rc = adutils_lookup_batch_add(qs, filter, attrs, domain, result, &brc);
401*8040SBaban.Kenkre@Sun.COM 	if (rc != ADUTILS_SUCCESS) {
402*8040SBaban.Kenkre@Sun.COM 		adutils_lookup_batch_release(&qs);
403*8040SBaban.Kenkre@Sun.COM 		goto out;
404*8040SBaban.Kenkre@Sun.COM 	}
405*8040SBaban.Kenkre@Sun.COM 
406*8040SBaban.Kenkre@Sun.COM 	rc = adutils_lookup_batch_end(&qs);
407*8040SBaban.Kenkre@Sun.COM 	if (rc != ADUTILS_SUCCESS)
408*8040SBaban.Kenkre@Sun.COM 		goto out;
409*8040SBaban.Kenkre@Sun.COM 	rc = brc;
410*8040SBaban.Kenkre@Sun.COM 
411*8040SBaban.Kenkre@Sun.COM out:
412*8040SBaban.Kenkre@Sun.COM 	if (rc == ADUTILS_ERR_RETRIABLE_NET_ERR &&
413*8040SBaban.Kenkre@Sun.COM 	    retries++ < ADUTILS_DEF_NUM_RETRIES)
414*8040SBaban.Kenkre@Sun.COM 		goto retry;
415*8040SBaban.Kenkre@Sun.COM 	return (map_adrc2nssrc(rc));
416*8040SBaban.Kenkre@Sun.COM }
417*8040SBaban.Kenkre@Sun.COM 
418*8040SBaban.Kenkre@Sun.COM 
419*8040SBaban.Kenkre@Sun.COM /* ARGSUSED */
420*8040SBaban.Kenkre@Sun.COM nss_status_t
421*8040SBaban.Kenkre@Sun.COM _nss_ad_lookup(ad_backend_ptr be, nss_XbyY_args_t *argp,
422*8040SBaban.Kenkre@Sun.COM 		const char *database, const char *searchfilter,
423*8040SBaban.Kenkre@Sun.COM 		const char *dname, int *try_idmap)
424*8040SBaban.Kenkre@Sun.COM {
425*8040SBaban.Kenkre@Sun.COM 	nss_status_t	stat;
426*8040SBaban.Kenkre@Sun.COM 
427*8040SBaban.Kenkre@Sun.COM 	*try_idmap = 0;
428*8040SBaban.Kenkre@Sun.COM 
429*8040SBaban.Kenkre@Sun.COM 	/* Clear up results if any */
430*8040SBaban.Kenkre@Sun.COM 	(void) adutils_freeresult(&be->result);
431*8040SBaban.Kenkre@Sun.COM 
432*8040SBaban.Kenkre@Sun.COM 	/* Lookup AD */
433*8040SBaban.Kenkre@Sun.COM 	stat = ad_lookup(searchfilter, be->attrs, dname, &be->result);
434*8040SBaban.Kenkre@Sun.COM 	if (stat != NSS_SUCCESS) {
435*8040SBaban.Kenkre@Sun.COM 		argp->returnval = 0;
436*8040SBaban.Kenkre@Sun.COM 		*try_idmap = 1;
437*8040SBaban.Kenkre@Sun.COM 		return (stat);
438*8040SBaban.Kenkre@Sun.COM 	}
439*8040SBaban.Kenkre@Sun.COM 
440*8040SBaban.Kenkre@Sun.COM 	/* Map AD object(s) to string in native file format */
441*8040SBaban.Kenkre@Sun.COM 	stat = be->adobj2str(be, argp);
442*8040SBaban.Kenkre@Sun.COM 	if (stat == NSS_STR_PARSE_SUCCESS)
443*8040SBaban.Kenkre@Sun.COM 		stat = _nss_ad_marshall_data(be, argp);
444*8040SBaban.Kenkre@Sun.COM 	return (_nss_ad_sanitize_status(be, argp, stat));
445*8040SBaban.Kenkre@Sun.COM }
446*8040SBaban.Kenkre@Sun.COM 
447*8040SBaban.Kenkre@Sun.COM static
448*8040SBaban.Kenkre@Sun.COM void
449*8040SBaban.Kenkre@Sun.COM clean_state()
450*8040SBaban.Kenkre@Sun.COM {
451*8040SBaban.Kenkre@Sun.COM 	nssad_cfg_t	*cp, *curr;
452*8040SBaban.Kenkre@Sun.COM 
453*8040SBaban.Kenkre@Sun.COM 	(void) pthread_mutex_lock(&statelock);
454*8040SBaban.Kenkre@Sun.COM 	for (cp = state.qtail; cp != NULL; ) {
455*8040SBaban.Kenkre@Sun.COM 		curr = cp;
456*8040SBaban.Kenkre@Sun.COM 		cp = cp->qnext;
457*8040SBaban.Kenkre@Sun.COM 		nssad_cfg_destroy(curr);
458*8040SBaban.Kenkre@Sun.COM 	}
459*8040SBaban.Kenkre@Sun.COM 	(void) memset(&state, 0, sizeof (state));
460*8040SBaban.Kenkre@Sun.COM 	(void) pthread_mutex_unlock(&statelock);
461*8040SBaban.Kenkre@Sun.COM }
462*8040SBaban.Kenkre@Sun.COM 
463*8040SBaban.Kenkre@Sun.COM static
464*8040SBaban.Kenkre@Sun.COM void
465*8040SBaban.Kenkre@Sun.COM _clean_ad_backend(ad_backend_ptr be)
466*8040SBaban.Kenkre@Sun.COM {
467*8040SBaban.Kenkre@Sun.COM 	if (be->tablename != NULL)
468*8040SBaban.Kenkre@Sun.COM 		free(be->tablename);
469*8040SBaban.Kenkre@Sun.COM 	if (be->buffer != NULL) {
470*8040SBaban.Kenkre@Sun.COM 		free(be->buffer);
471*8040SBaban.Kenkre@Sun.COM 		be->buffer = NULL;
472*8040SBaban.Kenkre@Sun.COM 	}
473*8040SBaban.Kenkre@Sun.COM 	free(be);
474*8040SBaban.Kenkre@Sun.COM }
475*8040SBaban.Kenkre@Sun.COM 
476*8040SBaban.Kenkre@Sun.COM 
477*8040SBaban.Kenkre@Sun.COM /*
478*8040SBaban.Kenkre@Sun.COM  * _nss_ad_destr frees allocated memory before exiting this nsswitch shared
479*8040SBaban.Kenkre@Sun.COM  * backend library. This function is called before returning control back to
480*8040SBaban.Kenkre@Sun.COM  * nsswitch.
481*8040SBaban.Kenkre@Sun.COM  */
482*8040SBaban.Kenkre@Sun.COM /*ARGSUSED*/
483*8040SBaban.Kenkre@Sun.COM nss_status_t
484*8040SBaban.Kenkre@Sun.COM _nss_ad_destr(ad_backend_ptr be, void *a)
485*8040SBaban.Kenkre@Sun.COM {
486*8040SBaban.Kenkre@Sun.COM 	(void) _clean_ad_backend(be);
487*8040SBaban.Kenkre@Sun.COM 	clean_state();
488*8040SBaban.Kenkre@Sun.COM 	return ((nss_status_t)NSS_SUCCESS);
489*8040SBaban.Kenkre@Sun.COM }
490*8040SBaban.Kenkre@Sun.COM 
491*8040SBaban.Kenkre@Sun.COM 
492*8040SBaban.Kenkre@Sun.COM /*ARGSUSED*/
493*8040SBaban.Kenkre@Sun.COM nss_status_t
494*8040SBaban.Kenkre@Sun.COM _nss_ad_setent(ad_backend_ptr be, void *a)
495*8040SBaban.Kenkre@Sun.COM {
496*8040SBaban.Kenkre@Sun.COM 	return ((nss_status_t)NSS_UNAVAIL);
497*8040SBaban.Kenkre@Sun.COM }
498*8040SBaban.Kenkre@Sun.COM 
499*8040SBaban.Kenkre@Sun.COM 
500*8040SBaban.Kenkre@Sun.COM /*ARGSUSED*/
501*8040SBaban.Kenkre@Sun.COM nss_status_t
502*8040SBaban.Kenkre@Sun.COM _nss_ad_endent(ad_backend_ptr be, void *a)
503*8040SBaban.Kenkre@Sun.COM {
504*8040SBaban.Kenkre@Sun.COM 	return ((nss_status_t)NSS_UNAVAIL);
505*8040SBaban.Kenkre@Sun.COM }
506*8040SBaban.Kenkre@Sun.COM 
507*8040SBaban.Kenkre@Sun.COM 
508*8040SBaban.Kenkre@Sun.COM /*ARGSUSED*/
509*8040SBaban.Kenkre@Sun.COM nss_status_t
510*8040SBaban.Kenkre@Sun.COM _nss_ad_getent(ad_backend_ptr be, void *a)
511*8040SBaban.Kenkre@Sun.COM {
512*8040SBaban.Kenkre@Sun.COM 	return ((nss_status_t)NSS_UNAVAIL);
513*8040SBaban.Kenkre@Sun.COM }
514*8040SBaban.Kenkre@Sun.COM 
515*8040SBaban.Kenkre@Sun.COM 
516*8040SBaban.Kenkre@Sun.COM nss_backend_t *
517*8040SBaban.Kenkre@Sun.COM _nss_ad_constr(ad_backend_op_t ops[], int nops, char *tablename,
518*8040SBaban.Kenkre@Sun.COM 		const char **attrs, fnf adobj2str)
519*8040SBaban.Kenkre@Sun.COM {
520*8040SBaban.Kenkre@Sun.COM 	ad_backend_ptr	be;
521*8040SBaban.Kenkre@Sun.COM 
522*8040SBaban.Kenkre@Sun.COM 	if ((be = (ad_backend_ptr) calloc(1, sizeof (*be))) == NULL)
523*8040SBaban.Kenkre@Sun.COM 		return (NULL);
524*8040SBaban.Kenkre@Sun.COM 	if ((be->tablename = (char *)strdup(tablename)) == NULL) {
525*8040SBaban.Kenkre@Sun.COM 		free(be);
526*8040SBaban.Kenkre@Sun.COM 		return (NULL);
527*8040SBaban.Kenkre@Sun.COM 	}
528*8040SBaban.Kenkre@Sun.COM 	be->ops = ops;
529*8040SBaban.Kenkre@Sun.COM 	be->nops = (nss_dbop_t)nops;
530*8040SBaban.Kenkre@Sun.COM 	be->attrs = attrs;
531*8040SBaban.Kenkre@Sun.COM 	be->adobj2str = adobj2str;
532*8040SBaban.Kenkre@Sun.COM 	(void) memset(&state, 0, sizeof (state));
533*8040SBaban.Kenkre@Sun.COM 	return ((nss_backend_t *)be);
534*8040SBaban.Kenkre@Sun.COM }
535