xref: /onnv-gate/usr/src/cmd/fs.d/autofs/ns_ldap.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  *	ns_ldap.c
24*0Sstevel@tonic-gate  *
25*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
26*0Sstevel@tonic-gate  * Use is subject to license terms.
27*0Sstevel@tonic-gate  */
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
30*0Sstevel@tonic-gate 
31*0Sstevel@tonic-gate #include <stdio.h>
32*0Sstevel@tonic-gate #include <stdlib.h>
33*0Sstevel@tonic-gate #include <syslog.h>
34*0Sstevel@tonic-gate #include <string.h>
35*0Sstevel@tonic-gate #include <ctype.h>
36*0Sstevel@tonic-gate #include <nsswitch.h>
37*0Sstevel@tonic-gate #include <sys/param.h>
38*0Sstevel@tonic-gate #include <sys/types.h>
39*0Sstevel@tonic-gate #include <rpc/rpc.h>
40*0Sstevel@tonic-gate #include <rpcsvc/nfs_prot.h>
41*0Sstevel@tonic-gate #include <sys/errno.h>
42*0Sstevel@tonic-gate #include <libintl.h>
43*0Sstevel@tonic-gate #include "automount.h"
44*0Sstevel@tonic-gate #include "../../../lib/libsldap/common/ns_sldap.h"
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*
47*0Sstevel@tonic-gate  * LDAP schema used for automounter:
48*0Sstevel@tonic-gate  *
49*0Sstevel@tonic-gate  * automountMapName: mapname i.e. auto_home, etc.
50*0Sstevel@tonic-gate  * automountKey: contains the key i.e. the mount point
51*0Sstevel@tonic-gate  * automountInformation: contains the mount options and remote mount location
52*0Sstevel@tonic-gate  * description: an optional description (not used by automounter)
53*0Sstevel@tonic-gate  *
54*0Sstevel@tonic-gate  * For example, if auto_direct has the following line of data:
55*0Sstevel@tonic-gate  *
56*0Sstevel@tonic-gate  * 		/work -rw,intr,nosuid,noquota hosta:/export/work
57*0Sstevel@tonic-gate  *
58*0Sstevel@tonic-gate  * Then this would map to the the following LDAP entry:
59*0Sstevel@tonic-gate  *
60*0Sstevel@tonic-gate  *	dn: automountKey=/work,automountMapName=auto_direct,...
61*0Sstevel@tonic-gate  * 	automountKey: /work
62*0Sstevel@tonic-gate  * 	automountInformation: -rw,intr,nosuid,noquota hosta:/export/work
63*0Sstevel@tonic-gate  *	objectclass: top
64*0Sstevel@tonic-gate  *	objectclass: automount
65*0Sstevel@tonic-gate  *
66*0Sstevel@tonic-gate  * In this container:
67*0Sstevel@tonic-gate  *
68*0Sstevel@tonic-gate  *	dn: automountMapName=auto_direct,...
69*0Sstevel@tonic-gate  *	automountMapName: auto_direct
70*0Sstevel@tonic-gate  *	objectClass: top
71*0Sstevel@tonic-gate  *	objectClass: automountMap
72*0Sstevel@tonic-gate  *
73*0Sstevel@tonic-gate  * Note that the schema can be mapped and SSD's can be used to relocate
74*0Sstevel@tonic-gate  * the default location of these entries.
75*0Sstevel@tonic-gate  *
76*0Sstevel@tonic-gate  */
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate #define	CAPCHAR '%'
79*0Sstevel@tonic-gate #define	MAXERROR 4000
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate static char *automountKey = NULL;
82*0Sstevel@tonic-gate static char *automountInformation = NULL;
83*0Sstevel@tonic-gate static char *defaultFilter = NULL;
84*0Sstevel@tonic-gate static int encode = 0;
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate static int mastermap_callback_ldap();
87*0Sstevel@tonic-gate static int directmap_callback();
88*0Sstevel@tonic-gate static int ldap_err(int);
89*0Sstevel@tonic-gate static int ldap_match();
90*0Sstevel@tonic-gate static int readdir_callback();
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate struct loadmaster_cbdata {
93*0Sstevel@tonic-gate 	char *ptr1;
94*0Sstevel@tonic-gate 	char **ptr2;
95*0Sstevel@tonic-gate 	char ***ptr3;
96*0Sstevel@tonic-gate };
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate struct loaddirect_cbdata {
99*0Sstevel@tonic-gate 	char *ptr1;
100*0Sstevel@tonic-gate 	char *ptr2;
101*0Sstevel@tonic-gate 	char **ptr3;
102*0Sstevel@tonic-gate 	char ***ptr4;
103*0Sstevel@tonic-gate };
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate struct dir_cbdata {
106*0Sstevel@tonic-gate 	struct dir_entry **list;
107*0Sstevel@tonic-gate 	struct dir_entry *last;
108*0Sstevel@tonic-gate 	int error;
109*0Sstevel@tonic-gate };
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate static char *tosunds_str(char *);
112*0Sstevel@tonic-gate static char *tounix_str(char *);
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate static int
115*0Sstevel@tonic-gate isAttrMapped(char *orig, char *mapped)
116*0Sstevel@tonic-gate {
117*0Sstevel@tonic-gate 	char **s;
118*0Sstevel@tonic-gate 	char **mappedschema = NULL;
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 	mappedschema = __ns_ldap_getMappedAttributes("automount", orig);
121*0Sstevel@tonic-gate 	if (mappedschema == NULL)
122*0Sstevel@tonic-gate 		return (0);
123*0Sstevel@tonic-gate 	if (strcasecmp(mappedschema[0], mapped) != 0) {
124*0Sstevel@tonic-gate 		for (s = mappedschema; *s != NULL; s++)
125*0Sstevel@tonic-gate 			free(*s);
126*0Sstevel@tonic-gate 		free(mappedschema);
127*0Sstevel@tonic-gate 		return (0);
128*0Sstevel@tonic-gate 	}
129*0Sstevel@tonic-gate 	for (s = mappedschema; *s != NULL; s++)
130*0Sstevel@tonic-gate 		free(*s);
131*0Sstevel@tonic-gate 	free(mappedschema);
132*0Sstevel@tonic-gate 	return (1);
133*0Sstevel@tonic-gate }
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate static int
136*0Sstevel@tonic-gate isObjectMapped(char *orig, char *mapped)
137*0Sstevel@tonic-gate {
138*0Sstevel@tonic-gate 	char **s;
139*0Sstevel@tonic-gate 	char **mappedschema = NULL;
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate 	mappedschema = __ns_ldap_getMappedObjectClass("automount", orig);
142*0Sstevel@tonic-gate 	if (mappedschema == NULL)
143*0Sstevel@tonic-gate 		return (0);
144*0Sstevel@tonic-gate 	if (strcasecmp(mappedschema[0], mapped) != 0) {
145*0Sstevel@tonic-gate 		for (s = mappedschema; *s != NULL; s++)
146*0Sstevel@tonic-gate 			free(*s);
147*0Sstevel@tonic-gate 		free(mappedschema);
148*0Sstevel@tonic-gate 		return (0);
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 	for (s = mappedschema; *s != NULL; s++)
151*0Sstevel@tonic-gate 		free(*s);
152*0Sstevel@tonic-gate 	free(mappedschema);
153*0Sstevel@tonic-gate 	return (1);
154*0Sstevel@tonic-gate }
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate void
157*0Sstevel@tonic-gate init_ldap(char **stack, char ***stkptr)
158*0Sstevel@tonic-gate {
159*0Sstevel@tonic-gate 	/*
160*0Sstevel@tonic-gate 	 * Check for version of the profile the client is using
161*0Sstevel@tonic-gate 	 *
162*0Sstevel@tonic-gate 	 * For version 1 profiles we do encoding of attributes
163*0Sstevel@tonic-gate 	 * and use nisMap and nisObject schema for backward compatibility.
164*0Sstevel@tonic-gate 	 *
165*0Sstevel@tonic-gate 	 * For version 2 profiles we don't do encoding and use
166*0Sstevel@tonic-gate 	 * automountMap and automount as default attributes (which can
167*0Sstevel@tonic-gate 	 * then be overridden in libsldap if schema mapping is configured
168*0Sstevel@tonic-gate 	 * in the profile).
169*0Sstevel@tonic-gate 	 *
170*0Sstevel@tonic-gate 	 * If profile version is not available, use version 2 as default
171*0Sstevel@tonic-gate 	 * and syslog message.
172*0Sstevel@tonic-gate 	 */
173*0Sstevel@tonic-gate 	int rc, v2 = 1;
174*0Sstevel@tonic-gate 	void **paramVal = NULL;
175*0Sstevel@tonic-gate 	ns_ldap_error_t *errorp = NULL;
176*0Sstevel@tonic-gate 	struct __nsw_switchconfig *conf = NULL;
177*0Sstevel@tonic-gate 	struct __nsw_lookup *lkp = NULL;
178*0Sstevel@tonic-gate 	enum __nsw_parse_err pserr;
179*0Sstevel@tonic-gate 	int	ldap_configured = 0;
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate #ifdef lint
182*0Sstevel@tonic-gate 	stack = stack;
183*0Sstevel@tonic-gate 	stkptr = stkptr;
184*0Sstevel@tonic-gate #endif /* lint */
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate 	/* get nsswitch info of "automount */
187*0Sstevel@tonic-gate 	conf = __nsw_getconfig("automount", &pserr);
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 	/* find out if LDAP backend is configured */
190*0Sstevel@tonic-gate 	if (conf != NULL) {
191*0Sstevel@tonic-gate 		for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) {
192*0Sstevel@tonic-gate 			if (strcmp(lkp->service_name, "ldap") == 0) {
193*0Sstevel@tonic-gate 				ldap_configured = 1;
194*0Sstevel@tonic-gate 				break;
195*0Sstevel@tonic-gate 			}
196*0Sstevel@tonic-gate 		}
197*0Sstevel@tonic-gate 		/* free conf at the end of "if"  bracket */
198*0Sstevel@tonic-gate 		(void) __nsw_freeconfig(conf);
199*0Sstevel@tonic-gate 	}
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 	/* if ldap is not configured, init_ldap is a no op */
202*0Sstevel@tonic-gate 	if (!ldap_configured)
203*0Sstevel@tonic-gate 		return;
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 	rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal, &errorp);
206*0Sstevel@tonic-gate 	if (rc != NS_LDAP_SUCCESS || !paramVal || !*paramVal) {
207*0Sstevel@tonic-gate 		syslog(LOG_ERR, "Can not determine version of LDAP profile"
208*0Sstevel@tonic-gate 			" that is used (%d, %s).  Using version 2 profile"
209*0Sstevel@tonic-gate 			" defaults", rc, (errorp && errorp->message ?
210*0Sstevel@tonic-gate 			errorp->message : ""));
211*0Sstevel@tonic-gate 		(void) __ns_ldap_freeError(&errorp);
212*0Sstevel@tonic-gate 	} else {
213*0Sstevel@tonic-gate 		if (strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
214*0Sstevel@tonic-gate 			v2 = 0;
215*0Sstevel@tonic-gate 		(void) __ns_ldap_freeParam(&paramVal);
216*0Sstevel@tonic-gate 	}
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 	if (v2) {
219*0Sstevel@tonic-gate 		if (trace > 1)
220*0Sstevel@tonic-gate 			trace_prt(1, "init_ldap: setting up for version 2\n");
221*0Sstevel@tonic-gate 		automountKey = "automountKey";
222*0Sstevel@tonic-gate 		automountInformation = "automountInformation";
223*0Sstevel@tonic-gate 		defaultFilter = "(&(objectClass=automount)(automountKey=%s))";
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 		/* check for automountMapName mapped to nisMapName */
226*0Sstevel@tonic-gate 		if (!isAttrMapped("automountMapName", "nisMapName"))
227*0Sstevel@tonic-gate 			return;
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 		/* check for automountKey mapped to cn */
230*0Sstevel@tonic-gate 		if (!isAttrMapped("automountKey", "cn"))
231*0Sstevel@tonic-gate 			return;
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate 		/* check for automountInformation mapped to nisMapEntry */
234*0Sstevel@tonic-gate 		if (!isAttrMapped("automountInformation", "nisMapEntry"))
235*0Sstevel@tonic-gate 			return;
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 		/* check for automountMap mapped to nisMap */
238*0Sstevel@tonic-gate 		if (!isObjectMapped("automountMap", "nisMap"))
239*0Sstevel@tonic-gate 			return;
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate 		/* check for automount mapped to nisObject */
242*0Sstevel@tonic-gate 		if (!isObjectMapped("automount", "nisObject"))
243*0Sstevel@tonic-gate 			return;
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate 		if (trace > 1)
246*0Sstevel@tonic-gate 			trace_prt(1, "init_ldap: encode = TRUE\n");
247*0Sstevel@tonic-gate 		encode = 1;
248*0Sstevel@tonic-gate 	} else {
249*0Sstevel@tonic-gate 		if (trace > 1) {
250*0Sstevel@tonic-gate 			trace_prt(1, "init_ldap: setting up for version 1\n");
251*0Sstevel@tonic-gate 			trace_prt(1, "init_ldap: encode = TRUE\n");
252*0Sstevel@tonic-gate 		}
253*0Sstevel@tonic-gate 		encode = 1;
254*0Sstevel@tonic-gate 		automountKey = "cn";
255*0Sstevel@tonic-gate 		automountInformation = "nisMapEntry";
256*0Sstevel@tonic-gate 		defaultFilter = "(&(objectClass=nisObject)(cn=%s))";
257*0Sstevel@tonic-gate 	}
258*0Sstevel@tonic-gate }
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate /*ARGSUSED*/
261*0Sstevel@tonic-gate int
262*0Sstevel@tonic-gate getmapent_ldap(char *key, char *map, struct mapline *ml,
263*0Sstevel@tonic-gate char **stack, char ***stkptr, bool_t *iswildcard, bool_t isrestricted)
264*0Sstevel@tonic-gate {
265*0Sstevel@tonic-gate 	char *ldap_line = NULL;
266*0Sstevel@tonic-gate 	char *lp;
267*0Sstevel@tonic-gate 	int ldap_len, len;
268*0Sstevel@tonic-gate 	int nserr;
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	if (trace > 1)
271*0Sstevel@tonic-gate 		trace_prt(1, "getmapent_ldap called\n");
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate 	if (trace > 1) {
274*0Sstevel@tonic-gate 		trace_prt(1, "getmapent_ldap: key=[ %s ]\n", key);
275*0Sstevel@tonic-gate 	}
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate 	if (iswildcard)
278*0Sstevel@tonic-gate 		*iswildcard = FALSE;
279*0Sstevel@tonic-gate 	nserr = ldap_match(map, key, &ldap_line, &ldap_len);
280*0Sstevel@tonic-gate 	if (nserr) {
281*0Sstevel@tonic-gate 		if (nserr == __NSW_NOTFOUND) {
282*0Sstevel@tonic-gate 			/* Try the default entry "*" */
283*0Sstevel@tonic-gate 			if ((nserr = ldap_match(map, "\\2a", &ldap_line,
284*0Sstevel@tonic-gate 			    &ldap_len)))
285*0Sstevel@tonic-gate 				goto done;
286*0Sstevel@tonic-gate 			else {
287*0Sstevel@tonic-gate 				if (iswildcard)
288*0Sstevel@tonic-gate 					*iswildcard = TRUE;
289*0Sstevel@tonic-gate 			}
290*0Sstevel@tonic-gate 		} else
291*0Sstevel@tonic-gate 			goto done;
292*0Sstevel@tonic-gate 	}
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 	/*
295*0Sstevel@tonic-gate 	 * at this point we are sure that ldap_match
296*0Sstevel@tonic-gate 	 * succeeded so massage the entry by
297*0Sstevel@tonic-gate 	 * 1. ignoring # and beyond
298*0Sstevel@tonic-gate 	 * 2. trim the trailing whitespace
299*0Sstevel@tonic-gate 	 */
300*0Sstevel@tonic-gate 	if (lp = strchr(ldap_line, '#'))
301*0Sstevel@tonic-gate 		*lp = '\0';
302*0Sstevel@tonic-gate 	len = strlen(ldap_line);
303*0Sstevel@tonic-gate 	if (len == 0) {
304*0Sstevel@tonic-gate 		nserr = __NSW_NOTFOUND;
305*0Sstevel@tonic-gate 		goto done;
306*0Sstevel@tonic-gate 	}
307*0Sstevel@tonic-gate 	lp = &ldap_line[len - 1];
308*0Sstevel@tonic-gate 	while (lp > ldap_line && isspace(*lp))
309*0Sstevel@tonic-gate 		*lp-- = '\0';
310*0Sstevel@tonic-gate 	if (lp == ldap_line) {
311*0Sstevel@tonic-gate 		nserr = __NSW_NOTFOUND;
312*0Sstevel@tonic-gate 		goto done;
313*0Sstevel@tonic-gate 	}
314*0Sstevel@tonic-gate 	(void) strncpy(ml->linebuf, ldap_line, LINESZ);
315*0Sstevel@tonic-gate 	unquote(ml->linebuf, ml->lineqbuf);
316*0Sstevel@tonic-gate 	nserr = __NSW_SUCCESS;
317*0Sstevel@tonic-gate done:
318*0Sstevel@tonic-gate 	if (ldap_line)
319*0Sstevel@tonic-gate 		free((char *)ldap_line);
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate 	if (trace > 1)
322*0Sstevel@tonic-gate 		trace_prt(1, "getmapent_ldap: exiting ...\n");
323*0Sstevel@tonic-gate 
324*0Sstevel@tonic-gate 	return (nserr);
325*0Sstevel@tonic-gate }
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate static int
328*0Sstevel@tonic-gate ldap_match(char *map, char *key, char **ldap_line, int *ldap_len)
329*0Sstevel@tonic-gate {
330*0Sstevel@tonic-gate 	char searchfilter[LDAP_FILT_MAXSIZ];
331*0Sstevel@tonic-gate 	int res, attr_found;
332*0Sstevel@tonic-gate 	ns_ldap_result_t *result = NULL;
333*0Sstevel@tonic-gate 	ns_ldap_error_t *errp = NULL;
334*0Sstevel@tonic-gate 	ns_ldap_entry_t *entry = NULL;
335*0Sstevel@tonic-gate 	char *ldapkey;
336*0Sstevel@tonic-gate 	int i;
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	if (trace > 1) {
339*0Sstevel@tonic-gate 		trace_prt(1, "ldap_match called\n");
340*0Sstevel@tonic-gate 		trace_prt(1, "ldap_match: key =[ %s ]\n", key);
341*0Sstevel@tonic-gate 	}
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	/*
344*0Sstevel@tonic-gate 	 * need to handle uppercase characters in the key because LDAP
345*0Sstevel@tonic-gate 	 * searches are case insensitive.  Note, key = attribute automountKey.
346*0Sstevel@tonic-gate 	 */
347*0Sstevel@tonic-gate 	if (encode)
348*0Sstevel@tonic-gate 		ldapkey = tosunds_str(key);
349*0Sstevel@tonic-gate 	else
350*0Sstevel@tonic-gate 		ldapkey = key;
351*0Sstevel@tonic-gate 
352*0Sstevel@tonic-gate 	if (trace > 1) {
353*0Sstevel@tonic-gate 		trace_prt(1, "ldap_match: ldapkey =[ %s ]\n", ldapkey);
354*0Sstevel@tonic-gate 	}
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 	(void) sprintf(searchfilter, defaultFilter, ldapkey);
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate 	if (trace > 1)
359*0Sstevel@tonic-gate 		trace_prt(1, "  ldap_match: Requesting list for %s in %s\n",
360*0Sstevel@tonic-gate 		    searchfilter, map);
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 	res = __ns_ldap_list(map, searchfilter, NULL,
363*0Sstevel@tonic-gate 	    NULL, NULL, 0, &result, &errp, NULL, NULL);
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	if (trace > 1) {
366*0Sstevel@tonic-gate 		if (res != NS_LDAP_SUCCESS)
367*0Sstevel@tonic-gate 			trace_prt(1,
368*0Sstevel@tonic-gate 			    "  ldap_match: __ns_ldap_list FAILED (%d)\n", res);
369*0Sstevel@tonic-gate 		else
370*0Sstevel@tonic-gate 			trace_prt(1, "  ldap_match: __ns_ldap_list OK\n");
371*0Sstevel@tonic-gate 	}
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	if (res != NS_LDAP_SUCCESS && res != NS_LDAP_NOTFOUND) {
374*0Sstevel@tonic-gate 		if (errp) {
375*0Sstevel@tonic-gate 			if (verbose) {
376*0Sstevel@tonic-gate 				char errstr[MAXERROR];
377*0Sstevel@tonic-gate 				(void) sprintf(errstr,
378*0Sstevel@tonic-gate 					gettext("ldap server can't list map,"
379*0Sstevel@tonic-gate 					" '%s': '%s' - '%d'."),
380*0Sstevel@tonic-gate 					map, errp->message, errp->status);
381*0Sstevel@tonic-gate 				syslog(LOG_ERR, errstr);
382*0Sstevel@tonic-gate 			}
383*0Sstevel@tonic-gate 			__ns_ldap_freeError(&errp);
384*0Sstevel@tonic-gate 		} else {
385*0Sstevel@tonic-gate 			if (verbose) {
386*0Sstevel@tonic-gate 				char *errmsg;
387*0Sstevel@tonic-gate 				__ns_ldap_err2str(res, &errmsg);
388*0Sstevel@tonic-gate 				syslog(LOG_ERR, errmsg);
389*0Sstevel@tonic-gate 			}
390*0Sstevel@tonic-gate 		}
391*0Sstevel@tonic-gate 		if (result)
392*0Sstevel@tonic-gate 			__ns_ldap_freeResult(&result);
393*0Sstevel@tonic-gate 		return (ldap_err(res));
394*0Sstevel@tonic-gate 	}
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate 	if (res == NS_LDAP_NOTFOUND || result == NULL ||
397*0Sstevel@tonic-gate 	    result->entries_count == 0 || result->entry->attr_count == 0) {
398*0Sstevel@tonic-gate 		if (trace > 1)
399*0Sstevel@tonic-gate 			trace_prt(1, "  ldap_match: no entries found\n");
400*0Sstevel@tonic-gate 		if (errp)
401*0Sstevel@tonic-gate 			__ns_ldap_freeError(&errp);
402*0Sstevel@tonic-gate 		if (result)
403*0Sstevel@tonic-gate 			__ns_ldap_freeResult(&result);
404*0Sstevel@tonic-gate 		return (__NSW_NOTFOUND);
405*0Sstevel@tonic-gate 	}
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate 	/*
408*0Sstevel@tonic-gate 	 * get value of attribute nisMapEntry.  This attribute contains a
409*0Sstevel@tonic-gate 	 * list of mount options AND mount location for a particular mount
410*0Sstevel@tonic-gate 	 * point (key).
411*0Sstevel@tonic-gate 	 * For example:
412*0Sstevel@tonic-gate 	 *
413*0Sstevel@tonic-gate 	 * key: /work
414*0Sstevel@tonic-gate 	 *	^^^^^
415*0Sstevel@tonic-gate 	 *	(mount point)
416*0Sstevel@tonic-gate 	 *
417*0Sstevel@tonic-gate 	 * nisMapEntry: -rw,intr,nosuid,noquota hosta:/export/work
418*0Sstevel@tonic-gate 	 *		^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
419*0Sstevel@tonic-gate 	 *		(    mount options    ) (remote mount location)
420*0Sstevel@tonic-gate 	 *
421*0Sstevel@tonic-gate 	 */
422*0Sstevel@tonic-gate 	attr_found = 0;
423*0Sstevel@tonic-gate 	entry = result->entry;
424*0Sstevel@tonic-gate 	for (i = 0; i < entry->attr_count; i++) {
425*0Sstevel@tonic-gate 		ns_ldap_attr_t *attr;
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate 		attr = entry->attr_pair[i];
428*0Sstevel@tonic-gate 		if (strcasecmp(attr->attrname, automountInformation) == 0) {
429*0Sstevel@tonic-gate 			char *attrval;
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate 			attr_found = 1;
432*0Sstevel@tonic-gate 			if (encode)
433*0Sstevel@tonic-gate 				attrval = tounix_str(attr->attrvalue[0]);
434*0Sstevel@tonic-gate 			else
435*0Sstevel@tonic-gate 				attrval = attr->attrvalue[0];
436*0Sstevel@tonic-gate 			*ldap_len = strlen(key) + strlen(attrval);
437*0Sstevel@tonic-gate 
438*0Sstevel@tonic-gate 			/*
439*0Sstevel@tonic-gate 			 * so check for the length; it should be less than
440*0Sstevel@tonic-gate 			 * LINESZ
441*0Sstevel@tonic-gate 			 */
442*0Sstevel@tonic-gate 			if ((*ldap_len + 2) > LINESZ) {
443*0Sstevel@tonic-gate 				syslog(LOG_ERR,
444*0Sstevel@tonic-gate 				    "ldap server map %s, entry for %s"
445*0Sstevel@tonic-gate 				    " is too long %d chars (max %d)",
446*0Sstevel@tonic-gate 				    map, key, (*ldap_len + 2), LINESZ);
447*0Sstevel@tonic-gate 				__ns_ldap_freeResult(&result);
448*0Sstevel@tonic-gate 				return (__NSW_UNAVAIL);
449*0Sstevel@tonic-gate 			}
450*0Sstevel@tonic-gate 			*ldap_line = (char *)malloc(*ldap_len + 2);
451*0Sstevel@tonic-gate 			if (*ldap_line == NULL) {
452*0Sstevel@tonic-gate 				syslog(LOG_ERR, "ldap_match: malloc failed");
453*0Sstevel@tonic-gate 				__ns_ldap_freeResult(&result);
454*0Sstevel@tonic-gate 				return (__NSW_UNAVAIL);
455*0Sstevel@tonic-gate 			}
456*0Sstevel@tonic-gate 
457*0Sstevel@tonic-gate 			(void) sprintf(*ldap_line, "%s", attrval);
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 			break;
460*0Sstevel@tonic-gate 		}
461*0Sstevel@tonic-gate 	}
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate 	__ns_ldap_freeError(&errp);
464*0Sstevel@tonic-gate 	__ns_ldap_freeResult(&result);
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate 	if (!attr_found)
467*0Sstevel@tonic-gate 		return (__NSW_NOTFOUND);
468*0Sstevel@tonic-gate 
469*0Sstevel@tonic-gate 	if (trace > 1)
470*0Sstevel@tonic-gate 		trace_prt(1, "  ldap_match: found: %s\n", *ldap_line);
471*0Sstevel@tonic-gate 
472*0Sstevel@tonic-gate 	return (__NSW_SUCCESS);
473*0Sstevel@tonic-gate }
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate loadmaster_ldap(char *mapname, char *defopts, char **stack, char ***stkptr)
476*0Sstevel@tonic-gate {
477*0Sstevel@tonic-gate 	char searchfilter[LDAP_FILT_MAXSIZ];
478*0Sstevel@tonic-gate 	int res;
479*0Sstevel@tonic-gate 	ns_ldap_result_t *result = NULL;
480*0Sstevel@tonic-gate 	ns_ldap_error_t *errp = NULL;
481*0Sstevel@tonic-gate 	struct loadmaster_cbdata master_cbdata;
482*0Sstevel@tonic-gate 
483*0Sstevel@tonic-gate 	if (trace > 1)
484*0Sstevel@tonic-gate 		trace_prt(1, "loadmaster_ldap called\n");
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate 	master_cbdata.ptr1 = defopts;
487*0Sstevel@tonic-gate 	master_cbdata.ptr2 = stack;
488*0Sstevel@tonic-gate 	master_cbdata.ptr3 = stkptr;
489*0Sstevel@tonic-gate 
490*0Sstevel@tonic-gate 	/* filter gets all the entries for the specified mapname */
491*0Sstevel@tonic-gate 	(void) sprintf(searchfilter, defaultFilter, "*");
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 	if (trace > 1)
494*0Sstevel@tonic-gate 		trace_prt(1, "loadmaster_ldap: Requesting list for %s in %s\n",
495*0Sstevel@tonic-gate 		    searchfilter, mapname);
496*0Sstevel@tonic-gate 
497*0Sstevel@tonic-gate 	res = __ns_ldap_list(mapname, searchfilter, NULL, NULL, NULL,
498*0Sstevel@tonic-gate 		0, &result, &errp, mastermap_callback_ldap,
499*0Sstevel@tonic-gate 		(void *) &master_cbdata);
500*0Sstevel@tonic-gate 
501*0Sstevel@tonic-gate 	if (trace > 1)
502*0Sstevel@tonic-gate 		trace_prt(1,
503*0Sstevel@tonic-gate 			"loadmaster_ldap: __ns_ldap_list just returned: %d\n",
504*0Sstevel@tonic-gate 			res);
505*0Sstevel@tonic-gate 
506*0Sstevel@tonic-gate 	if (res != NS_LDAP_SUCCESS) {
507*0Sstevel@tonic-gate 		if (errp) {
508*0Sstevel@tonic-gate 			char errstr[MAXERROR];
509*0Sstevel@tonic-gate 			if (verbose) {
510*0Sstevel@tonic-gate 				(void) sprintf(errstr, gettext(
511*0Sstevel@tonic-gate 					"ldap server can't list map,"
512*0Sstevel@tonic-gate 					"'%s': '%s' - '%d'."),
513*0Sstevel@tonic-gate 					mapname, errp->message, errp->status);
514*0Sstevel@tonic-gate 				syslog(LOG_ERR, errstr);
515*0Sstevel@tonic-gate 			}
516*0Sstevel@tonic-gate 			__ns_ldap_freeError(&errp);
517*0Sstevel@tonic-gate 		} else {
518*0Sstevel@tonic-gate 			if (verbose) {
519*0Sstevel@tonic-gate 				char *errmsg;
520*0Sstevel@tonic-gate 				__ns_ldap_err2str(res, &errmsg);
521*0Sstevel@tonic-gate 				syslog(LOG_ERR, errmsg);
522*0Sstevel@tonic-gate 			}
523*0Sstevel@tonic-gate 		}
524*0Sstevel@tonic-gate 		if (result)
525*0Sstevel@tonic-gate 			__ns_ldap_freeResult(&result);
526*0Sstevel@tonic-gate 		return (ldap_err(res));
527*0Sstevel@tonic-gate 	}
528*0Sstevel@tonic-gate 
529*0Sstevel@tonic-gate 	if (trace > 1)
530*0Sstevel@tonic-gate 		trace_prt(1,
531*0Sstevel@tonic-gate 			"loadmaster_ldap: calling __ns_ldap_freeResult...\n");
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate 	__ns_ldap_freeResult(&result);
534*0Sstevel@tonic-gate 
535*0Sstevel@tonic-gate 	if (trace > 1)
536*0Sstevel@tonic-gate 		trace_prt(1,
537*0Sstevel@tonic-gate 			"loadmaster_ldap: about to return __NSW_SUCCESS...\n");
538*0Sstevel@tonic-gate 
539*0Sstevel@tonic-gate 	return (__NSW_SUCCESS);
540*0Sstevel@tonic-gate }
541*0Sstevel@tonic-gate 
542*0Sstevel@tonic-gate loaddirect_ldap(char *nsmap, char *localmap, char *opts,
543*0Sstevel@tonic-gate char **stack, char ***stkptr)
544*0Sstevel@tonic-gate {
545*0Sstevel@tonic-gate 	char searchfilter[LDAP_FILT_MAXSIZ];
546*0Sstevel@tonic-gate 	int res;
547*0Sstevel@tonic-gate 	ns_ldap_result_t *result = NULL;
548*0Sstevel@tonic-gate 	ns_ldap_error_t *errp = NULL;
549*0Sstevel@tonic-gate 	struct loaddirect_cbdata direct_cbdata;
550*0Sstevel@tonic-gate 
551*0Sstevel@tonic-gate 	if (trace > 1) {
552*0Sstevel@tonic-gate 		trace_prt(1, "loaddirect_ldap called\n");
553*0Sstevel@tonic-gate 	}
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 	direct_cbdata.ptr1 = opts;
556*0Sstevel@tonic-gate 	direct_cbdata.ptr2 = localmap;
557*0Sstevel@tonic-gate 	direct_cbdata.ptr3 = stack;
558*0Sstevel@tonic-gate 	direct_cbdata.ptr4 = stkptr;
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate 	/* filter gets all the entries for the specified mapname */
561*0Sstevel@tonic-gate 	(void) sprintf(searchfilter, defaultFilter, "*");
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 	if (trace > 1)
564*0Sstevel@tonic-gate 		trace_prt(1, "loaddirect_ldap: Requesting list for %s in %s\n",
565*0Sstevel@tonic-gate 		    searchfilter, nsmap);
566*0Sstevel@tonic-gate 
567*0Sstevel@tonic-gate 	res = __ns_ldap_list(nsmap, searchfilter, NULL, NULL,
568*0Sstevel@tonic-gate 	    NULL, 0, &result, &errp,
569*0Sstevel@tonic-gate 	    directmap_callback, (void *) &direct_cbdata);
570*0Sstevel@tonic-gate 
571*0Sstevel@tonic-gate 
572*0Sstevel@tonic-gate 	if (res != NS_LDAP_SUCCESS) {
573*0Sstevel@tonic-gate 		if (errp) {
574*0Sstevel@tonic-gate 			char errstr[MAXERROR];
575*0Sstevel@tonic-gate 			if (verbose) {
576*0Sstevel@tonic-gate 				(void) sprintf(errstr,
577*0Sstevel@tonic-gate 					gettext("ldap server can't list map,"
578*0Sstevel@tonic-gate 					" '%s': '%s' - '%d'."),
579*0Sstevel@tonic-gate 					nsmap, errp->message, errp->status);
580*0Sstevel@tonic-gate 				syslog(LOG_ERR, errstr);
581*0Sstevel@tonic-gate 			}
582*0Sstevel@tonic-gate 			__ns_ldap_freeError(&errp);
583*0Sstevel@tonic-gate 		} else {
584*0Sstevel@tonic-gate 			if (verbose) {
585*0Sstevel@tonic-gate 				char *errmsg;
586*0Sstevel@tonic-gate 				__ns_ldap_err2str(res, &errmsg);
587*0Sstevel@tonic-gate 				syslog(LOG_ERR, errmsg);
588*0Sstevel@tonic-gate 			}
589*0Sstevel@tonic-gate 		}
590*0Sstevel@tonic-gate 		if (result)
591*0Sstevel@tonic-gate 			__ns_ldap_freeResult(&result);
592*0Sstevel@tonic-gate 		return (ldap_err(res));
593*0Sstevel@tonic-gate 	}
594*0Sstevel@tonic-gate 
595*0Sstevel@tonic-gate 	__ns_ldap_freeResult(&result);
596*0Sstevel@tonic-gate 	return (__NSW_SUCCESS);
597*0Sstevel@tonic-gate }
598*0Sstevel@tonic-gate 
599*0Sstevel@tonic-gate static int
600*0Sstevel@tonic-gate ldap_err(int err)
601*0Sstevel@tonic-gate {
602*0Sstevel@tonic-gate 	if (trace > 1)
603*0Sstevel@tonic-gate 		trace_prt(1, "ldap_err called\n");
604*0Sstevel@tonic-gate 
605*0Sstevel@tonic-gate 	switch (err) {
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate 	case NS_LDAP_SUCCESS:
608*0Sstevel@tonic-gate 		return (__NSW_SUCCESS);
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate 	case NS_LDAP_NOTFOUND:
611*0Sstevel@tonic-gate 		return (__NSW_NOTFOUND);
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate 	case NS_LDAP_PARTIAL:
614*0Sstevel@tonic-gate 		return (__NSW_TRYAGAIN);
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate 	default:
617*0Sstevel@tonic-gate 		return (__NSW_UNAVAIL);
618*0Sstevel@tonic-gate 	}
619*0Sstevel@tonic-gate }
620*0Sstevel@tonic-gate 
621*0Sstevel@tonic-gate static int
622*0Sstevel@tonic-gate mastermap_callback_ldap(ns_ldap_entry_t *entry, void *udata)
623*0Sstevel@tonic-gate {
624*0Sstevel@tonic-gate 	char *key, *contents, *pmap, *opts;
625*0Sstevel@tonic-gate 	char dir[LINESZ], map[LINESZ], qbuff[LINESZ];
626*0Sstevel@tonic-gate 	char cont_temp[LINESZ], key_temp[LINESZ];
627*0Sstevel@tonic-gate 	int  key_len, contents_len;
628*0Sstevel@tonic-gate 	struct loadmaster_cbdata *temp = (struct loadmaster_cbdata *)udata;
629*0Sstevel@tonic-gate 	char *defopts = temp->ptr1;
630*0Sstevel@tonic-gate 	char **stack = temp->ptr2;
631*0Sstevel@tonic-gate 	char ***stkptr = temp->ptr3;
632*0Sstevel@tonic-gate 	int i;
633*0Sstevel@tonic-gate 
634*0Sstevel@tonic-gate 	if (trace > 1) {
635*0Sstevel@tonic-gate 		trace_prt(1, "mastermap_callback_ldap called\n");
636*0Sstevel@tonic-gate 		trace_prt(1, "mastermap_callback_ldap: entry=%x\n", entry);
637*0Sstevel@tonic-gate 		if (entry) {
638*0Sstevel@tonic-gate 			trace_prt(1,
639*0Sstevel@tonic-gate 			"mastermap_callback_ldap: entry->attr_count=[ %d ]\n",
640*0Sstevel@tonic-gate 			    entry->attr_count);
641*0Sstevel@tonic-gate 		}
642*0Sstevel@tonic-gate 	}
643*0Sstevel@tonic-gate 
644*0Sstevel@tonic-gate 	/*
645*0Sstevel@tonic-gate 	 * For the current entry, obtain the values of the cn and the
646*0Sstevel@tonic-gate 	 * nisMapEntry attributes and the length of each value (cn=key,
647*0Sstevel@tonic-gate 	 * nisMapEntry=contents).
648*0Sstevel@tonic-gate 	 * We skip the description.  Even though LDAP allows for multiple
649*0Sstevel@tonic-gate 	 * values per attribute, we take only the 1st value for each
650*0Sstevel@tonic-gate 	 * attribute because the automount data is organized as such
651*0Sstevel@tonic-gate 	 * (same as NIS+).
652*0Sstevel@tonic-gate 	 */
653*0Sstevel@tonic-gate 	key_len = 0;
654*0Sstevel@tonic-gate 	contents_len = 0;
655*0Sstevel@tonic-gate 	key = NULL;
656*0Sstevel@tonic-gate 	contents = NULL;
657*0Sstevel@tonic-gate 	for (i = 0; i < entry->attr_count; i++) {
658*0Sstevel@tonic-gate 		ns_ldap_attr_t *attr;
659*0Sstevel@tonic-gate 
660*0Sstevel@tonic-gate 		attr = entry->attr_pair[i];
661*0Sstevel@tonic-gate 		if (trace > 1) {
662*0Sstevel@tonic-gate 			trace_prt(1,
663*0Sstevel@tonic-gate 			"mastermap_callback_ldap: attr[%d]: %s=%s\n",
664*0Sstevel@tonic-gate 			    i, attr->attrname, attr->attrvalue[0]);
665*0Sstevel@tonic-gate 		}
666*0Sstevel@tonic-gate 		if (strcasecmp(attr->attrname, automountInformation) == 0) {
667*0Sstevel@tonic-gate 			if (encode)
668*0Sstevel@tonic-gate 				(void) strncpy(cont_temp,
669*0Sstevel@tonic-gate 					tounix_str(attr->attrvalue[0]), LINESZ);
670*0Sstevel@tonic-gate 			else
671*0Sstevel@tonic-gate 				(void) strncpy(cont_temp, attr->attrvalue[0],
672*0Sstevel@tonic-gate 					LINESZ);
673*0Sstevel@tonic-gate 			contents = cont_temp;
674*0Sstevel@tonic-gate 			contents_len = strlen(contents);
675*0Sstevel@tonic-gate 			if (trace > 1) {
676*0Sstevel@tonic-gate 				trace_prt(1,
677*0Sstevel@tonic-gate 	"mastermap_callback_ldap: contents=[ %s ], contents_len=[ %d ]\n",
678*0Sstevel@tonic-gate 				contents, contents_len);
679*0Sstevel@tonic-gate 			}
680*0Sstevel@tonic-gate 		}
681*0Sstevel@tonic-gate 		if (strcasecmp(attr->attrname, automountKey) == 0) {
682*0Sstevel@tonic-gate 			if (encode)
683*0Sstevel@tonic-gate 				(void) strncpy(key_temp,
684*0Sstevel@tonic-gate 					tounix_str(attr->attrvalue[0]), LINESZ);
685*0Sstevel@tonic-gate 			else
686*0Sstevel@tonic-gate 				(void) strncpy(key_temp, attr->attrvalue[0],
687*0Sstevel@tonic-gate 					LINESZ);
688*0Sstevel@tonic-gate 			key = key_temp;
689*0Sstevel@tonic-gate 			key_len = strlen(key);
690*0Sstevel@tonic-gate 			if (trace > 1) {
691*0Sstevel@tonic-gate 				trace_prt(1,
692*0Sstevel@tonic-gate 			"mastermap_callback_ldap: key=[ %s ], key_len=[ %d ]\n",
693*0Sstevel@tonic-gate 				key, key_len);
694*0Sstevel@tonic-gate 			}
695*0Sstevel@tonic-gate 		}
696*0Sstevel@tonic-gate 	}
697*0Sstevel@tonic-gate 
698*0Sstevel@tonic-gate 	if (key_len >= LINESZ || contents_len >= LINESZ)
699*0Sstevel@tonic-gate 		return (0);
700*0Sstevel@tonic-gate 	if (key_len < 2 || contents_len < 2)
701*0Sstevel@tonic-gate 		return (0);
702*0Sstevel@tonic-gate 
703*0Sstevel@tonic-gate 	while (isspace(*contents))
704*0Sstevel@tonic-gate 		contents++;
705*0Sstevel@tonic-gate 	if (contents == NULL)
706*0Sstevel@tonic-gate 		return (0);
707*0Sstevel@tonic-gate 	if (isspace(*key) || *key == '#')
708*0Sstevel@tonic-gate 		return (0);
709*0Sstevel@tonic-gate 
710*0Sstevel@tonic-gate 	(void) strncpy(dir, key, key_len);
711*0Sstevel@tonic-gate 	dir[key_len] = '\0';
712*0Sstevel@tonic-gate 	if (trace > 1)
713*0Sstevel@tonic-gate 		trace_prt(1, "mastermap_callback_ldap: dir= [ %s ]\n", dir);
714*0Sstevel@tonic-gate 	for (i = 0; i < LINESZ; i++)
715*0Sstevel@tonic-gate 		qbuff[i] = ' ';
716*0Sstevel@tonic-gate 	if (macro_expand("", dir, qbuff, sizeof (dir))) {
717*0Sstevel@tonic-gate 		syslog(LOG_ERR,
718*0Sstevel@tonic-gate 		    "%s in ldap server map: entry too long (max %d chars)",
719*0Sstevel@tonic-gate 		    dir, sizeof (dir) - 1);
720*0Sstevel@tonic-gate 		return (0);
721*0Sstevel@tonic-gate 	}
722*0Sstevel@tonic-gate 	(void) strncpy(map, contents, contents_len);
723*0Sstevel@tonic-gate 	map[contents_len] = '\0';
724*0Sstevel@tonic-gate 	if (trace > 1)
725*0Sstevel@tonic-gate 		trace_prt(1, "mastermap_callback_ldap: map= [ %s ]\n", map);
726*0Sstevel@tonic-gate 	if (macro_expand("", map, qbuff, sizeof (map))) {
727*0Sstevel@tonic-gate 		syslog(LOG_ERR,
728*0Sstevel@tonic-gate 		    "%s in ldap server map: entry too long (max %d chars)",
729*0Sstevel@tonic-gate 		    map, sizeof (map) - 1);
730*0Sstevel@tonic-gate 		return (0);
731*0Sstevel@tonic-gate 	}
732*0Sstevel@tonic-gate 	pmap = map;
733*0Sstevel@tonic-gate 	while (*pmap && isspace(*pmap))
734*0Sstevel@tonic-gate 		pmap++;		/* skip blanks in front of map */
735*0Sstevel@tonic-gate 	opts = pmap;
736*0Sstevel@tonic-gate 	while (*opts && !isspace(*opts))
737*0Sstevel@tonic-gate 		opts++;
738*0Sstevel@tonic-gate 	if (*opts) {
739*0Sstevel@tonic-gate 		*opts++ = '\0';
740*0Sstevel@tonic-gate 		while (*opts && isspace(*opts))
741*0Sstevel@tonic-gate 			opts++;
742*0Sstevel@tonic-gate 		if (*opts == '-')
743*0Sstevel@tonic-gate 			opts++;
744*0Sstevel@tonic-gate 			else
745*0Sstevel@tonic-gate 			opts = defopts;
746*0Sstevel@tonic-gate 	}
747*0Sstevel@tonic-gate 	/*
748*0Sstevel@tonic-gate 	 * Check for no embedded blanks.
749*0Sstevel@tonic-gate 	 */
750*0Sstevel@tonic-gate 	if (strcspn(opts, " 	") == strlen(opts)) {
751*0Sstevel@tonic-gate 		if (trace > 1)
752*0Sstevel@tonic-gate 			trace_prt(1,
753*0Sstevel@tonic-gate 			"mastermap_callback_ldap: dir=[ %s ], pmap=[ %s ]\n",
754*0Sstevel@tonic-gate 			    dir, pmap);
755*0Sstevel@tonic-gate 		dirinit(dir, pmap, opts, 0, stack, stkptr);
756*0Sstevel@tonic-gate 	} else {
757*0Sstevel@tonic-gate 		char *dn = NULL;
758*0Sstevel@tonic-gate 
759*0Sstevel@tonic-gate 		/* get the value for the dn */
760*0Sstevel@tonic-gate 		for (i = 0; i < entry->attr_count; i++) {
761*0Sstevel@tonic-gate 			ns_ldap_attr_t *attr;
762*0Sstevel@tonic-gate 
763*0Sstevel@tonic-gate 			attr = entry->attr_pair[i];
764*0Sstevel@tonic-gate 			if (strcasecmp(attr->attrname, "dn")
765*0Sstevel@tonic-gate 								== 0) {
766*0Sstevel@tonic-gate 				dn = attr->attrvalue[0];
767*0Sstevel@tonic-gate 				break;
768*0Sstevel@tonic-gate 			}
769*0Sstevel@tonic-gate 		}
770*0Sstevel@tonic-gate 		pr_msg(
771*0Sstevel@tonic-gate 	"Warning: invalid entry for %s in ldap server dn: %s ignored.\n",
772*0Sstevel@tonic-gate 		    dir, dn);
773*0Sstevel@tonic-gate 	}
774*0Sstevel@tonic-gate 	if (trace > 1)
775*0Sstevel@tonic-gate 		trace_prt(1, "mastermap_callback_ldap exiting...\n");
776*0Sstevel@tonic-gate 	return (0);
777*0Sstevel@tonic-gate }
778*0Sstevel@tonic-gate 
779*0Sstevel@tonic-gate static int
780*0Sstevel@tonic-gate directmap_callback(ns_ldap_entry_t *entry, void *udata)
781*0Sstevel@tonic-gate {
782*0Sstevel@tonic-gate 	char *key;
783*0Sstevel@tonic-gate 	char dir[256];
784*0Sstevel@tonic-gate 	int  key_len;
785*0Sstevel@tonic-gate 	struct loaddirect_cbdata *temp = (struct loaddirect_cbdata *)udata;
786*0Sstevel@tonic-gate 	char *opts = temp->ptr1;
787*0Sstevel@tonic-gate 	char *localmap = temp->ptr2;
788*0Sstevel@tonic-gate 	char **stack = temp->ptr3;
789*0Sstevel@tonic-gate 	char ***stkptr = temp->ptr4;
790*0Sstevel@tonic-gate 	int i;
791*0Sstevel@tonic-gate 
792*0Sstevel@tonic-gate 	/*
793*0Sstevel@tonic-gate 	 * For the current entry, obtain the value and length of the cn i.e.
794*0Sstevel@tonic-gate 	 * the contents of key and its key length.
795*0Sstevel@tonic-gate 	 */
796*0Sstevel@tonic-gate 	key_len = 0;
797*0Sstevel@tonic-gate 	key = NULL;
798*0Sstevel@tonic-gate 	for (i = 0; i < entry->attr_count; i++) {
799*0Sstevel@tonic-gate 		ns_ldap_attr_t *attr;
800*0Sstevel@tonic-gate 
801*0Sstevel@tonic-gate 		attr = entry->attr_pair[i];
802*0Sstevel@tonic-gate 		if (strcasecmp(attr->attrname, automountKey) == 0) {
803*0Sstevel@tonic-gate 			if (encode)
804*0Sstevel@tonic-gate 				key = tounix_str(attr->attrvalue[0]);
805*0Sstevel@tonic-gate 			else
806*0Sstevel@tonic-gate 				key = attr->attrvalue[0];
807*0Sstevel@tonic-gate 			key_len = strlen(key);
808*0Sstevel@tonic-gate 			break;
809*0Sstevel@tonic-gate 		}
810*0Sstevel@tonic-gate 	}
811*0Sstevel@tonic-gate 
812*0Sstevel@tonic-gate 	if (key_len >= 100 || key_len < 2)
813*0Sstevel@tonic-gate 		return (0);
814*0Sstevel@tonic-gate 
815*0Sstevel@tonic-gate 	if (isspace(*key) || *key == '#')
816*0Sstevel@tonic-gate 		return (0);
817*0Sstevel@tonic-gate 	(void) strncpy(dir, key, key_len);
818*0Sstevel@tonic-gate 	dir[key_len] = '\0';
819*0Sstevel@tonic-gate 
820*0Sstevel@tonic-gate 	dirinit(dir, localmap, opts, 1, stack, stkptr);
821*0Sstevel@tonic-gate 
822*0Sstevel@tonic-gate 	return (0);
823*0Sstevel@tonic-gate }
824*0Sstevel@tonic-gate 
825*0Sstevel@tonic-gate int
826*0Sstevel@tonic-gate getmapkeys_ldap(char *nsmap, struct dir_entry **list, int *error,
827*0Sstevel@tonic-gate int *cache_time, char **stack, char ***stkptr)
828*0Sstevel@tonic-gate {
829*0Sstevel@tonic-gate 	char searchfilter[LDAP_FILT_MAXSIZ];
830*0Sstevel@tonic-gate 	int res;
831*0Sstevel@tonic-gate 	ns_ldap_result_t *result = NULL;
832*0Sstevel@tonic-gate 	ns_ldap_error_t *errp = NULL;
833*0Sstevel@tonic-gate 	struct dir_cbdata readdir_cbdata;
834*0Sstevel@tonic-gate 
835*0Sstevel@tonic-gate #ifdef lint
836*0Sstevel@tonic-gate 	stack = stack;
837*0Sstevel@tonic-gate 	stkptr = stkptr;
838*0Sstevel@tonic-gate #endif /* lint */
839*0Sstevel@tonic-gate 
840*0Sstevel@tonic-gate 	if (trace > 1)
841*0Sstevel@tonic-gate 		trace_prt(1, "getmapkeys_ldap called\n");
842*0Sstevel@tonic-gate 
843*0Sstevel@tonic-gate 	*cache_time = RDDIR_CACHE_TIME;
844*0Sstevel@tonic-gate 	*error = 0;
845*0Sstevel@tonic-gate 	readdir_cbdata.list = list;
846*0Sstevel@tonic-gate 	readdir_cbdata.last = NULL;
847*0Sstevel@tonic-gate 
848*0Sstevel@tonic-gate 	/* filter gets all the entries for the specified mapname */
849*0Sstevel@tonic-gate 	(void) sprintf(searchfilter, defaultFilter, "*");
850*0Sstevel@tonic-gate 
851*0Sstevel@tonic-gate 	if (trace > 1)
852*0Sstevel@tonic-gate 		trace_prt(1, "getmapkeys_ldap: Requesting list for %s in %s\n",
853*0Sstevel@tonic-gate 		    searchfilter, nsmap);
854*0Sstevel@tonic-gate 
855*0Sstevel@tonic-gate 	res = __ns_ldap_list(nsmap, searchfilter, NULL, NULL, NULL, 0,
856*0Sstevel@tonic-gate 		&result, &errp, readdir_callback, (void *) &readdir_cbdata);
857*0Sstevel@tonic-gate 
858*0Sstevel@tonic-gate 	if (trace > 1)
859*0Sstevel@tonic-gate 		trace_prt(1, "  getmapkeys_ldap: __ns_ldap_list returned %d\n",
860*0Sstevel@tonic-gate 			res);
861*0Sstevel@tonic-gate 
862*0Sstevel@tonic-gate 	if (readdir_cbdata.error)
863*0Sstevel@tonic-gate 		*error = readdir_cbdata.error;
864*0Sstevel@tonic-gate 
865*0Sstevel@tonic-gate 	if (res != NS_LDAP_SUCCESS && res != NS_LDAP_NOTFOUND) {
866*0Sstevel@tonic-gate 		if (errp) {
867*0Sstevel@tonic-gate 			if (verbose) {
868*0Sstevel@tonic-gate 				char errstr[MAXERROR];
869*0Sstevel@tonic-gate 				(void) sprintf(errstr, gettext(
870*0Sstevel@tonic-gate 					"ldap server can't list map,"
871*0Sstevel@tonic-gate 					" '%s': '%s' - '%d'."),
872*0Sstevel@tonic-gate 					nsmap, errp->message, errp->status);
873*0Sstevel@tonic-gate 				syslog(LOG_ERR, errstr);
874*0Sstevel@tonic-gate 			}
875*0Sstevel@tonic-gate 			__ns_ldap_freeError(&errp);
876*0Sstevel@tonic-gate 		} else {
877*0Sstevel@tonic-gate 			if (verbose) {
878*0Sstevel@tonic-gate 				char *errmsg;
879*0Sstevel@tonic-gate 				__ns_ldap_err2str(res, &errmsg);
880*0Sstevel@tonic-gate 				syslog(LOG_ERR, errmsg);
881*0Sstevel@tonic-gate 			}
882*0Sstevel@tonic-gate 		}
883*0Sstevel@tonic-gate 		if (result)
884*0Sstevel@tonic-gate 			__ns_ldap_freeResult(&result);
885*0Sstevel@tonic-gate 		if (*error == 0)
886*0Sstevel@tonic-gate 			*error = ECOMM;
887*0Sstevel@tonic-gate 		return (ldap_err(res));
888*0Sstevel@tonic-gate 	}
889*0Sstevel@tonic-gate 	if (result)
890*0Sstevel@tonic-gate 		__ns_ldap_freeResult(&result);
891*0Sstevel@tonic-gate 
892*0Sstevel@tonic-gate 	return (__NSW_SUCCESS);
893*0Sstevel@tonic-gate }
894*0Sstevel@tonic-gate 
895*0Sstevel@tonic-gate static int
896*0Sstevel@tonic-gate readdir_callback(const ns_ldap_entry_t *entry, const void *udata)
897*0Sstevel@tonic-gate {
898*0Sstevel@tonic-gate 	char *key;
899*0Sstevel@tonic-gate 	int  key_len;
900*0Sstevel@tonic-gate 	struct dir_cbdata *temp = (struct dir_cbdata *)udata;
901*0Sstevel@tonic-gate 	struct dir_entry **list = temp->list;
902*0Sstevel@tonic-gate 	struct dir_entry *last = temp->last;
903*0Sstevel@tonic-gate 	int i;
904*0Sstevel@tonic-gate 
905*0Sstevel@tonic-gate 	if (trace > 1)
906*0Sstevel@tonic-gate 		trace_prt(1, "readdir_callback called\n");
907*0Sstevel@tonic-gate 	/*
908*0Sstevel@tonic-gate 	 * For the current entry, obtain the value and length of the cn i.e. the
909*0Sstevel@tonic-gate 	 * contents of key and its key length.
910*0Sstevel@tonic-gate 	 */
911*0Sstevel@tonic-gate 	key_len = 0;
912*0Sstevel@tonic-gate 	key = NULL;
913*0Sstevel@tonic-gate 
914*0Sstevel@tonic-gate 	if (trace > 1)
915*0Sstevel@tonic-gate 		trace_prt(1, "readdir_callback: entry->attr_count=[ %d ]\n",
916*0Sstevel@tonic-gate 		    entry->attr_count);
917*0Sstevel@tonic-gate 
918*0Sstevel@tonic-gate 	for (i = 0; i < entry->attr_count; i++) {
919*0Sstevel@tonic-gate 		ns_ldap_attr_t *attr;
920*0Sstevel@tonic-gate 
921*0Sstevel@tonic-gate 		attr = entry->attr_pair[i];
922*0Sstevel@tonic-gate 
923*0Sstevel@tonic-gate 		if (trace > 1)
924*0Sstevel@tonic-gate 			trace_prt(1,
925*0Sstevel@tonic-gate 			"readdir_callback: attr->attrname=[ %s ]\n",
926*0Sstevel@tonic-gate 			    attr->attrname);
927*0Sstevel@tonic-gate 
928*0Sstevel@tonic-gate 		if (strcasecmp(attr->attrname, automountKey) == 0) {
929*0Sstevel@tonic-gate 			if (encode)
930*0Sstevel@tonic-gate 				key = tounix_str(attr->attrvalue[0]);
931*0Sstevel@tonic-gate 			else
932*0Sstevel@tonic-gate 				key = attr->attrvalue[0];
933*0Sstevel@tonic-gate 			key_len = strlen(key);
934*0Sstevel@tonic-gate 
935*0Sstevel@tonic-gate 			if (trace > 1)
936*0Sstevel@tonic-gate 				trace_prt(1,
937*0Sstevel@tonic-gate 			"readdir_callback: key=[ %s ], key_len=[ %d ]\n",
938*0Sstevel@tonic-gate 				    key, key_len);
939*0Sstevel@tonic-gate 
940*0Sstevel@tonic-gate 			break;
941*0Sstevel@tonic-gate 		}
942*0Sstevel@tonic-gate 	}
943*0Sstevel@tonic-gate 
944*0Sstevel@tonic-gate 	if (key_len >= 100 || key_len < 2)
945*0Sstevel@tonic-gate 		return (0);
946*0Sstevel@tonic-gate 
947*0Sstevel@tonic-gate 	if (isspace(*key) || *key == '#')
948*0Sstevel@tonic-gate 		return (0);
949*0Sstevel@tonic-gate 
950*0Sstevel@tonic-gate 	/*
951*0Sstevel@tonic-gate 	 * Wildcard entry should be ignored - following entries should continue
952*0Sstevel@tonic-gate 	 * to be read to corroborate with the way we search for entries in
953*0Sstevel@tonic-gate 	 * LDAP, i.e., first for an exact key match and then a wildcard
954*0Sstevel@tonic-gate 	 * if there's no exact key match.
955*0Sstevel@tonic-gate 	 */
956*0Sstevel@tonic-gate 	if (key[0] == '*' && key[1] == '\0')
957*0Sstevel@tonic-gate 		return (0);
958*0Sstevel@tonic-gate 
959*0Sstevel@tonic-gate 	if (add_dir_entry(key, list, &last)) {
960*0Sstevel@tonic-gate 		temp->error = ENOMEM;
961*0Sstevel@tonic-gate 		return (1);
962*0Sstevel@tonic-gate 	}
963*0Sstevel@tonic-gate 
964*0Sstevel@tonic-gate 	temp->last = last;
965*0Sstevel@tonic-gate 	temp->error = 0;
966*0Sstevel@tonic-gate 
967*0Sstevel@tonic-gate 	if (trace > 1)
968*0Sstevel@tonic-gate 		trace_prt(1, "readdir_callback returning 0...\n");
969*0Sstevel@tonic-gate 
970*0Sstevel@tonic-gate 	return (0);
971*0Sstevel@tonic-gate }
972*0Sstevel@tonic-gate 
973*0Sstevel@tonic-gate /*
974*0Sstevel@tonic-gate  * Puts CAPCHAR in front of uppercase characters or surrounds a set of
975*0Sstevel@tonic-gate  * contiguous uppercase characters with CAPCHARS and square brackets.
976*0Sstevel@tonic-gate  *
977*0Sstevel@tonic-gate  * For example (assuming CAPCHAR = '%'):
978*0Sstevel@tonic-gate  *
979*0Sstevel@tonic-gate  * if str = Abc, it returns %Abc
980*0Sstevel@tonic-gate  * if str = ABc, it returns %[AB]c
981*0Sstevel@tonic-gate  * if str = AbC, it returns %Ab%C
982*0Sstevel@tonic-gate  *
983*0Sstevel@tonic-gate  */
984*0Sstevel@tonic-gate static char *
985*0Sstevel@tonic-gate tosunds_str(char *str)
986*0Sstevel@tonic-gate {
987*0Sstevel@tonic-gate 	static char buf[BUFSIZ];
988*0Sstevel@tonic-gate 	int i, j, er = FALSE;
989*0Sstevel@tonic-gate #ifdef NEWCAP
990*0Sstevel@tonic-gate 	int openBracket = FALSE, closeBracket = FALSE;
991*0Sstevel@tonic-gate #endif
992*0Sstevel@tonic-gate 
993*0Sstevel@tonic-gate 	(void) memset(buf, 0, BUFSIZ);
994*0Sstevel@tonic-gate 
995*0Sstevel@tonic-gate 	j = 0;
996*0Sstevel@tonic-gate 	for (i = 0; i < strlen(str); i++) {
997*0Sstevel@tonic-gate 		/* Check the current element */
998*0Sstevel@tonic-gate 		if (isupper(str[i])) {
999*0Sstevel@tonic-gate #ifdef NEWCAP
1000*0Sstevel@tonic-gate 			/* check the next element */
1001*0Sstevel@tonic-gate 			if (isupper(str[i+1])) {
1002*0Sstevel@tonic-gate 				if (openBracket == FALSE) {
1003*0Sstevel@tonic-gate 					openBracket = TRUE;
1004*0Sstevel@tonic-gate 					buf[j] = CAPCHAR;
1005*0Sstevel@tonic-gate 					buf[j+1] = '[';
1006*0Sstevel@tonic-gate 					j += 2;
1007*0Sstevel@tonic-gate 				}
1008*0Sstevel@tonic-gate 			} else {
1009*0Sstevel@tonic-gate 				if (openBracket == FALSE) {
1010*0Sstevel@tonic-gate 					buf[j] = CAPCHAR;
1011*0Sstevel@tonic-gate 					j++;
1012*0Sstevel@tonic-gate 				} else {
1013*0Sstevel@tonic-gate 					openBracket = FALSE;
1014*0Sstevel@tonic-gate 					closeBracket = TRUE;
1015*0Sstevel@tonic-gate 				}
1016*0Sstevel@tonic-gate 			}
1017*0Sstevel@tonic-gate #else
1018*0Sstevel@tonic-gate 			buf[j++] = CAPCHAR;
1019*0Sstevel@tonic-gate #endif
1020*0Sstevel@tonic-gate 		}
1021*0Sstevel@tonic-gate 		buf[j] = str[i];
1022*0Sstevel@tonic-gate 		j++;
1023*0Sstevel@tonic-gate 
1024*0Sstevel@tonic-gate #ifdef NEWCAP
1025*0Sstevel@tonic-gate 		if (closeBracket == TRUE) {
1026*0Sstevel@tonic-gate 			closeBracket = FALSE;
1027*0Sstevel@tonic-gate 			buf[j] = ']';
1028*0Sstevel@tonic-gate 			j++;
1029*0Sstevel@tonic-gate 		}
1030*0Sstevel@tonic-gate #endif
1031*0Sstevel@tonic-gate 		if (j >= BUFSIZ) {
1032*0Sstevel@tonic-gate 			er = TRUE;
1033*0Sstevel@tonic-gate 			break;
1034*0Sstevel@tonic-gate 		}
1035*0Sstevel@tonic-gate 	}
1036*0Sstevel@tonic-gate 
1037*0Sstevel@tonic-gate 	if (er) {
1038*0Sstevel@tonic-gate 		syslog(LOG_ERR, "Buffer size exceeded.");
1039*0Sstevel@tonic-gate 		(void) memset(buf, 0, BUFSIZ);
1040*0Sstevel@tonic-gate 	} else
1041*0Sstevel@tonic-gate 		buf[j] = '\0';
1042*0Sstevel@tonic-gate 
1043*0Sstevel@tonic-gate 	return (buf);
1044*0Sstevel@tonic-gate 
1045*0Sstevel@tonic-gate }
1046*0Sstevel@tonic-gate 
1047*0Sstevel@tonic-gate /*
1048*0Sstevel@tonic-gate  * Reverses what tosunds_str() did
1049*0Sstevel@tonic-gate  */
1050*0Sstevel@tonic-gate static char *
1051*0Sstevel@tonic-gate tounix_str(char *str)
1052*0Sstevel@tonic-gate {
1053*0Sstevel@tonic-gate 	static char buf[BUFSIZ];
1054*0Sstevel@tonic-gate 	int i, j;
1055*0Sstevel@tonic-gate 	int openBracket = FALSE;
1056*0Sstevel@tonic-gate 
1057*0Sstevel@tonic-gate 	(void) memset(buf, 0, BUFSIZ);
1058*0Sstevel@tonic-gate 	j = 0;
1059*0Sstevel@tonic-gate 
1060*0Sstevel@tonic-gate 	for (i = 0; i < strlen(str); i++) {
1061*0Sstevel@tonic-gate 		if (str[i] == '%') {
1062*0Sstevel@tonic-gate 			if (isupper(str[i+1])) {
1063*0Sstevel@tonic-gate 				i += 1;
1064*0Sstevel@tonic-gate 			} else if ((str[i+1] == '[') && (isupper(str[i+2]))) {
1065*0Sstevel@tonic-gate 				i += 2;
1066*0Sstevel@tonic-gate 				openBracket = TRUE;
1067*0Sstevel@tonic-gate 			}
1068*0Sstevel@tonic-gate 		} else if (str[i] == ']') {
1069*0Sstevel@tonic-gate 			if ((isupper(str[i-1])) && (openBracket == TRUE))
1070*0Sstevel@tonic-gate 				i += 1;
1071*0Sstevel@tonic-gate 			openBracket = FALSE;
1072*0Sstevel@tonic-gate 		}
1073*0Sstevel@tonic-gate 		buf[j] = str[i];
1074*0Sstevel@tonic-gate 		j++;
1075*0Sstevel@tonic-gate 	}
1076*0Sstevel@tonic-gate 	return (buf);
1077*0Sstevel@tonic-gate }
1078