xref: /titanic_51/usr/src/cmd/sendmail/libsm/mbdb.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *      All rights reserved.
4*7c478bd9Sstevel@tonic-gate  *
5*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
6*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
7*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
8*7c478bd9Sstevel@tonic-gate  */
9*7c478bd9Sstevel@tonic-gate 
10*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
11*7c478bd9Sstevel@tonic-gate 
12*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
13*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: mbdb.c,v 1.40 2003/12/10 03:19:07 gshapiro Exp $")
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate #include <ctype.h>
18*7c478bd9Sstevel@tonic-gate #include <errno.h>
19*7c478bd9Sstevel@tonic-gate #include <pwd.h>
20*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
21*7c478bd9Sstevel@tonic-gate #include <setjmp.h>
22*7c478bd9Sstevel@tonic-gate #include <unistd.h>
23*7c478bd9Sstevel@tonic-gate 
24*7c478bd9Sstevel@tonic-gate #include <sm/limits.h>
25*7c478bd9Sstevel@tonic-gate #include <sm/conf.h>
26*7c478bd9Sstevel@tonic-gate #include <sm/assert.h>
27*7c478bd9Sstevel@tonic-gate #include <sm/bitops.h>
28*7c478bd9Sstevel@tonic-gate #include <sm/errstring.h>
29*7c478bd9Sstevel@tonic-gate #include <sm/heap.h>
30*7c478bd9Sstevel@tonic-gate #include <sm/mbdb.h>
31*7c478bd9Sstevel@tonic-gate #include <sm/string.h>
32*7c478bd9Sstevel@tonic-gate # ifdef EX_OK
33*7c478bd9Sstevel@tonic-gate #  undef EX_OK			/* for SVr4.2 SMP */
34*7c478bd9Sstevel@tonic-gate # endif /* EX_OK */
35*7c478bd9Sstevel@tonic-gate #include <sm/sysexits.h>
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #if LDAPMAP
38*7c478bd9Sstevel@tonic-gate # if _LDAP_EXAMPLE_
39*7c478bd9Sstevel@tonic-gate #  include <sm/ldap.h>
40*7c478bd9Sstevel@tonic-gate # endif /* _LDAP_EXAMPLE_ */
41*7c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate typedef struct
44*7c478bd9Sstevel@tonic-gate {
45*7c478bd9Sstevel@tonic-gate 	char	*mbdb_typename;
46*7c478bd9Sstevel@tonic-gate 	int	(*mbdb_initialize) __P((char *));
47*7c478bd9Sstevel@tonic-gate 	int	(*mbdb_lookup) __P((char *name, SM_MBDB_T *user));
48*7c478bd9Sstevel@tonic-gate 	void	(*mbdb_terminate) __P((void));
49*7c478bd9Sstevel@tonic-gate } SM_MBDB_TYPE_T;
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate static int	mbdb_pw_initialize __P((char *));
52*7c478bd9Sstevel@tonic-gate static int	mbdb_pw_lookup __P((char *name, SM_MBDB_T *user));
53*7c478bd9Sstevel@tonic-gate static void	mbdb_pw_terminate __P((void));
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate #if LDAPMAP
56*7c478bd9Sstevel@tonic-gate # if _LDAP_EXAMPLE_
57*7c478bd9Sstevel@tonic-gate static struct sm_ldap_struct LDAPLMAP;
58*7c478bd9Sstevel@tonic-gate static int	mbdb_ldap_initialize __P((char *));
59*7c478bd9Sstevel@tonic-gate static int	mbdb_ldap_lookup __P((char *name, SM_MBDB_T *user));
60*7c478bd9Sstevel@tonic-gate static void	mbdb_ldap_terminate __P((void));
61*7c478bd9Sstevel@tonic-gate # endif /* _LDAP_EXAMPLE_ */
62*7c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate static SM_MBDB_TYPE_T SmMbdbTypes[] =
65*7c478bd9Sstevel@tonic-gate {
66*7c478bd9Sstevel@tonic-gate 	{ "pw", mbdb_pw_initialize, mbdb_pw_lookup, mbdb_pw_terminate },
67*7c478bd9Sstevel@tonic-gate #if LDAPMAP
68*7c478bd9Sstevel@tonic-gate # if _LDAP_EXAMPLE_
69*7c478bd9Sstevel@tonic-gate 	{ "ldap", mbdb_ldap_initialize, mbdb_ldap_lookup, mbdb_ldap_terminate },
70*7c478bd9Sstevel@tonic-gate # endif /* _LDAP_EXAMPLE_ */
71*7c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */
72*7c478bd9Sstevel@tonic-gate 	{ NULL, NULL, NULL, NULL }
73*7c478bd9Sstevel@tonic-gate };
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate static SM_MBDB_TYPE_T *SmMbdbType = &SmMbdbTypes[0];
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate /*
78*7c478bd9Sstevel@tonic-gate **  SM_MBDB_INITIALIZE -- specify which mailbox database to use
79*7c478bd9Sstevel@tonic-gate **
80*7c478bd9Sstevel@tonic-gate **	If this function is not called, then the "pw" implementation
81*7c478bd9Sstevel@tonic-gate **	is used by default; this implementation uses getpwnam().
82*7c478bd9Sstevel@tonic-gate **
83*7c478bd9Sstevel@tonic-gate **	Parameters:
84*7c478bd9Sstevel@tonic-gate **		mbdb -- Which mailbox database to use.
85*7c478bd9Sstevel@tonic-gate **			The argument has the form "name" or "name.arg".
86*7c478bd9Sstevel@tonic-gate **			"pw" means use getpwnam().
87*7c478bd9Sstevel@tonic-gate **
88*7c478bd9Sstevel@tonic-gate **	Results:
89*7c478bd9Sstevel@tonic-gate **		EX_OK on success, or an EX_* code on failure.
90*7c478bd9Sstevel@tonic-gate */
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate int
93*7c478bd9Sstevel@tonic-gate sm_mbdb_initialize(mbdb)
94*7c478bd9Sstevel@tonic-gate 	char *mbdb;
95*7c478bd9Sstevel@tonic-gate {
96*7c478bd9Sstevel@tonic-gate 	size_t namelen;
97*7c478bd9Sstevel@tonic-gate 	int err;
98*7c478bd9Sstevel@tonic-gate 	char *name;
99*7c478bd9Sstevel@tonic-gate 	char *arg;
100*7c478bd9Sstevel@tonic-gate 	SM_MBDB_TYPE_T *t;
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate 	SM_REQUIRE(mbdb != NULL);
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	name = mbdb;
105*7c478bd9Sstevel@tonic-gate 	arg = strchr(mbdb, '.');
106*7c478bd9Sstevel@tonic-gate 	if (arg == NULL)
107*7c478bd9Sstevel@tonic-gate 		namelen = strlen(name);
108*7c478bd9Sstevel@tonic-gate 	else
109*7c478bd9Sstevel@tonic-gate 	{
110*7c478bd9Sstevel@tonic-gate 		namelen = arg - name;
111*7c478bd9Sstevel@tonic-gate 		++arg;
112*7c478bd9Sstevel@tonic-gate 	}
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	for (t = SmMbdbTypes; t->mbdb_typename != NULL; ++t)
115*7c478bd9Sstevel@tonic-gate 	{
116*7c478bd9Sstevel@tonic-gate 		if (strlen(t->mbdb_typename) == namelen &&
117*7c478bd9Sstevel@tonic-gate 		    strncmp(name, t->mbdb_typename, namelen) == 0)
118*7c478bd9Sstevel@tonic-gate 		{
119*7c478bd9Sstevel@tonic-gate 			err = EX_OK;
120*7c478bd9Sstevel@tonic-gate 			if (t->mbdb_initialize != NULL)
121*7c478bd9Sstevel@tonic-gate 				err = t->mbdb_initialize(arg);
122*7c478bd9Sstevel@tonic-gate 			if (err == EX_OK)
123*7c478bd9Sstevel@tonic-gate 				SmMbdbType = t;
124*7c478bd9Sstevel@tonic-gate 			return err;
125*7c478bd9Sstevel@tonic-gate 		}
126*7c478bd9Sstevel@tonic-gate 	}
127*7c478bd9Sstevel@tonic-gate 	return EX_UNAVAILABLE;
128*7c478bd9Sstevel@tonic-gate }
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate /*
131*7c478bd9Sstevel@tonic-gate **  SM_MBDB_TERMINATE -- terminate connection to the mailbox database
132*7c478bd9Sstevel@tonic-gate **
133*7c478bd9Sstevel@tonic-gate **	Because this function closes any cached file descriptors that
134*7c478bd9Sstevel@tonic-gate **	are being held open for the connection to the mailbox database,
135*7c478bd9Sstevel@tonic-gate **	it should be called for security reasons prior to dropping privileges
136*7c478bd9Sstevel@tonic-gate **	and execing another process.
137*7c478bd9Sstevel@tonic-gate **
138*7c478bd9Sstevel@tonic-gate **	Parameters:
139*7c478bd9Sstevel@tonic-gate **		none.
140*7c478bd9Sstevel@tonic-gate **
141*7c478bd9Sstevel@tonic-gate **	Results:
142*7c478bd9Sstevel@tonic-gate **		none.
143*7c478bd9Sstevel@tonic-gate */
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate void
146*7c478bd9Sstevel@tonic-gate sm_mbdb_terminate()
147*7c478bd9Sstevel@tonic-gate {
148*7c478bd9Sstevel@tonic-gate 	if (SmMbdbType->mbdb_terminate != NULL)
149*7c478bd9Sstevel@tonic-gate 		SmMbdbType->mbdb_terminate();
150*7c478bd9Sstevel@tonic-gate }
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate /*
153*7c478bd9Sstevel@tonic-gate **  SM_MBDB_LOOKUP -- look up a local mail recipient, given name
154*7c478bd9Sstevel@tonic-gate **
155*7c478bd9Sstevel@tonic-gate **	Parameters:
156*7c478bd9Sstevel@tonic-gate **		name -- name of local mail recipient
157*7c478bd9Sstevel@tonic-gate **		user -- pointer to structure to fill in on success
158*7c478bd9Sstevel@tonic-gate **
159*7c478bd9Sstevel@tonic-gate **	Results:
160*7c478bd9Sstevel@tonic-gate **		On success, fill in *user and return EX_OK.
161*7c478bd9Sstevel@tonic-gate **		If the user does not exist, return EX_NOUSER.
162*7c478bd9Sstevel@tonic-gate **		If a temporary failure (eg, a network failure) occurred,
163*7c478bd9Sstevel@tonic-gate **		return EX_TEMPFAIL.  Otherwise return EX_OSERR.
164*7c478bd9Sstevel@tonic-gate */
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate int
167*7c478bd9Sstevel@tonic-gate sm_mbdb_lookup(name, user)
168*7c478bd9Sstevel@tonic-gate 	char *name;
169*7c478bd9Sstevel@tonic-gate 	SM_MBDB_T *user;
170*7c478bd9Sstevel@tonic-gate {
171*7c478bd9Sstevel@tonic-gate 	int ret = EX_NOUSER;
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	if (SmMbdbType->mbdb_lookup != NULL)
174*7c478bd9Sstevel@tonic-gate 		ret = SmMbdbType->mbdb_lookup(name, user);
175*7c478bd9Sstevel@tonic-gate 	return ret;
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate /*
179*7c478bd9Sstevel@tonic-gate **  SM_MBDB_FROMPW -- copy from struct pw to SM_MBDB_T
180*7c478bd9Sstevel@tonic-gate **
181*7c478bd9Sstevel@tonic-gate **	Parameters:
182*7c478bd9Sstevel@tonic-gate **		user -- destination user information structure
183*7c478bd9Sstevel@tonic-gate **		pw -- source passwd structure
184*7c478bd9Sstevel@tonic-gate **
185*7c478bd9Sstevel@tonic-gate **	Results:
186*7c478bd9Sstevel@tonic-gate **		none.
187*7c478bd9Sstevel@tonic-gate */
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate void
190*7c478bd9Sstevel@tonic-gate sm_mbdb_frompw(user, pw)
191*7c478bd9Sstevel@tonic-gate 	SM_MBDB_T *user;
192*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
193*7c478bd9Sstevel@tonic-gate {
194*7c478bd9Sstevel@tonic-gate 	SM_REQUIRE(user != NULL);
195*7c478bd9Sstevel@tonic-gate 	(void) sm_strlcpy(user->mbdb_name, pw->pw_name,
196*7c478bd9Sstevel@tonic-gate 			  sizeof(user->mbdb_name));
197*7c478bd9Sstevel@tonic-gate 	user->mbdb_uid = pw->pw_uid;
198*7c478bd9Sstevel@tonic-gate 	user->mbdb_gid = pw->pw_gid;
199*7c478bd9Sstevel@tonic-gate 	sm_pwfullname(pw->pw_gecos, pw->pw_name, user->mbdb_fullname,
200*7c478bd9Sstevel@tonic-gate 		      sizeof(user->mbdb_fullname));
201*7c478bd9Sstevel@tonic-gate 	(void) sm_strlcpy(user->mbdb_homedir, pw->pw_dir,
202*7c478bd9Sstevel@tonic-gate 			  sizeof(user->mbdb_homedir));
203*7c478bd9Sstevel@tonic-gate 	(void) sm_strlcpy(user->mbdb_shell, pw->pw_shell,
204*7c478bd9Sstevel@tonic-gate 			  sizeof(user->mbdb_shell));
205*7c478bd9Sstevel@tonic-gate }
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate /*
208*7c478bd9Sstevel@tonic-gate **  SM_PWFULLNAME -- build full name of user from pw_gecos field.
209*7c478bd9Sstevel@tonic-gate **
210*7c478bd9Sstevel@tonic-gate **	This routine interprets the strange entry that would appear
211*7c478bd9Sstevel@tonic-gate **	in the GECOS field of the password file.
212*7c478bd9Sstevel@tonic-gate **
213*7c478bd9Sstevel@tonic-gate **	Parameters:
214*7c478bd9Sstevel@tonic-gate **		gecos -- name to build.
215*7c478bd9Sstevel@tonic-gate **		user -- the login name of this user (for &).
216*7c478bd9Sstevel@tonic-gate **		buf -- place to put the result.
217*7c478bd9Sstevel@tonic-gate **		buflen -- length of buf.
218*7c478bd9Sstevel@tonic-gate **
219*7c478bd9Sstevel@tonic-gate **	Returns:
220*7c478bd9Sstevel@tonic-gate **		none.
221*7c478bd9Sstevel@tonic-gate */
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate #if _FFR_HANDLE_ISO8859_GECOS
224*7c478bd9Sstevel@tonic-gate static char Latin1ToASCII[128] =
225*7c478bd9Sstevel@tonic-gate {
226*7c478bd9Sstevel@tonic-gate 	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
227*7c478bd9Sstevel@tonic-gate 	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33,
228*7c478bd9Sstevel@tonic-gate 	99, 80, 36, 89, 124, 36, 34, 99, 97, 60, 45, 45, 114, 45, 111, 42,
229*7c478bd9Sstevel@tonic-gate 	50, 51, 39, 117, 80, 46, 44, 49, 111, 62, 42, 42, 42, 63, 65, 65,
230*7c478bd9Sstevel@tonic-gate 	65, 65, 65, 65, 65, 67, 69, 69, 69, 69, 73, 73, 73, 73, 68, 78, 79,
231*7c478bd9Sstevel@tonic-gate 	79, 79, 79, 79, 88, 79, 85, 85, 85, 85, 89, 80, 66, 97, 97, 97, 97,
232*7c478bd9Sstevel@tonic-gate 	97, 97, 97, 99, 101, 101, 101, 101, 105, 105, 105, 105, 100, 110,
233*7c478bd9Sstevel@tonic-gate 	111, 111, 111, 111, 111, 47, 111, 117, 117, 117, 117, 121, 112, 121
234*7c478bd9Sstevel@tonic-gate };
235*7c478bd9Sstevel@tonic-gate #endif /* _FFR_HANDLE_ISO8859_GECOS */
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate void
238*7c478bd9Sstevel@tonic-gate sm_pwfullname(gecos, user, buf, buflen)
239*7c478bd9Sstevel@tonic-gate 	register char *gecos;
240*7c478bd9Sstevel@tonic-gate 	char *user;
241*7c478bd9Sstevel@tonic-gate 	char *buf;
242*7c478bd9Sstevel@tonic-gate 	size_t buflen;
243*7c478bd9Sstevel@tonic-gate {
244*7c478bd9Sstevel@tonic-gate 	register char *p;
245*7c478bd9Sstevel@tonic-gate 	register char *bp = buf;
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 	if (*gecos == '*')
248*7c478bd9Sstevel@tonic-gate 		gecos++;
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	/* copy gecos, interpolating & to be full name */
251*7c478bd9Sstevel@tonic-gate 	for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
252*7c478bd9Sstevel@tonic-gate 	{
253*7c478bd9Sstevel@tonic-gate 		if (bp >= &buf[buflen - 1])
254*7c478bd9Sstevel@tonic-gate 		{
255*7c478bd9Sstevel@tonic-gate 			/* buffer overflow -- just use login name */
256*7c478bd9Sstevel@tonic-gate 			(void) sm_strlcpy(buf, user, buflen);
257*7c478bd9Sstevel@tonic-gate 			return;
258*7c478bd9Sstevel@tonic-gate 		}
259*7c478bd9Sstevel@tonic-gate 		if (*p == '&')
260*7c478bd9Sstevel@tonic-gate 		{
261*7c478bd9Sstevel@tonic-gate 			/* interpolate full name */
262*7c478bd9Sstevel@tonic-gate 			(void) sm_strlcpy(bp, user, buflen - (bp - buf));
263*7c478bd9Sstevel@tonic-gate 			*bp = toupper(*bp);
264*7c478bd9Sstevel@tonic-gate 			bp += strlen(bp);
265*7c478bd9Sstevel@tonic-gate 		}
266*7c478bd9Sstevel@tonic-gate 		else
267*7c478bd9Sstevel@tonic-gate 		{
268*7c478bd9Sstevel@tonic-gate #if _FFR_HANDLE_ISO8859_GECOS
269*7c478bd9Sstevel@tonic-gate 			if ((unsigned char) *p >= 128)
270*7c478bd9Sstevel@tonic-gate 				*bp++ = Latin1ToASCII[(unsigned char) *p - 128];
271*7c478bd9Sstevel@tonic-gate 			else
272*7c478bd9Sstevel@tonic-gate #endif /* _FFR_HANDLE_ISO8859_GECOS */
273*7c478bd9Sstevel@tonic-gate 				*bp++ = *p;
274*7c478bd9Sstevel@tonic-gate 		}
275*7c478bd9Sstevel@tonic-gate 	}
276*7c478bd9Sstevel@tonic-gate 	*bp = '\0';
277*7c478bd9Sstevel@tonic-gate }
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate /*
280*7c478bd9Sstevel@tonic-gate **  /etc/passwd implementation.
281*7c478bd9Sstevel@tonic-gate */
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate /*
284*7c478bd9Sstevel@tonic-gate **  MBDB_PW_INITIALIZE -- initialize getpwnam() version
285*7c478bd9Sstevel@tonic-gate **
286*7c478bd9Sstevel@tonic-gate **	Parameters:
287*7c478bd9Sstevel@tonic-gate **		arg -- unused.
288*7c478bd9Sstevel@tonic-gate **
289*7c478bd9Sstevel@tonic-gate **	Results:
290*7c478bd9Sstevel@tonic-gate **		EX_OK.
291*7c478bd9Sstevel@tonic-gate */
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate /* ARGSUSED0 */
294*7c478bd9Sstevel@tonic-gate static int
295*7c478bd9Sstevel@tonic-gate mbdb_pw_initialize(arg)
296*7c478bd9Sstevel@tonic-gate 	char *arg;
297*7c478bd9Sstevel@tonic-gate {
298*7c478bd9Sstevel@tonic-gate 	return EX_OK;
299*7c478bd9Sstevel@tonic-gate }
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate /*
302*7c478bd9Sstevel@tonic-gate **  MBDB_PW_LOOKUP -- look up a local mail recipient, given name
303*7c478bd9Sstevel@tonic-gate **
304*7c478bd9Sstevel@tonic-gate **	Parameters:
305*7c478bd9Sstevel@tonic-gate **		name -- name of local mail recipient
306*7c478bd9Sstevel@tonic-gate **		user -- pointer to structure to fill in on success
307*7c478bd9Sstevel@tonic-gate **
308*7c478bd9Sstevel@tonic-gate **	Results:
309*7c478bd9Sstevel@tonic-gate **		On success, fill in *user and return EX_OK.
310*7c478bd9Sstevel@tonic-gate **		Failure: EX_NOUSER.
311*7c478bd9Sstevel@tonic-gate */
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate static int
314*7c478bd9Sstevel@tonic-gate mbdb_pw_lookup(name, user)
315*7c478bd9Sstevel@tonic-gate 	char *name;
316*7c478bd9Sstevel@tonic-gate 	SM_MBDB_T *user;
317*7c478bd9Sstevel@tonic-gate {
318*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate #ifdef HESIOD
321*7c478bd9Sstevel@tonic-gate 	/* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */
322*7c478bd9Sstevel@tonic-gate 	{
323*7c478bd9Sstevel@tonic-gate 		char *p;
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 		for (p = name; *p != '\0'; p++)
326*7c478bd9Sstevel@tonic-gate 			if (!isascii(*p) || !isdigit(*p))
327*7c478bd9Sstevel@tonic-gate 				break;
328*7c478bd9Sstevel@tonic-gate 		if (*p == '\0')
329*7c478bd9Sstevel@tonic-gate 			return EX_NOUSER;
330*7c478bd9Sstevel@tonic-gate 	}
331*7c478bd9Sstevel@tonic-gate #endif /* HESIOD */
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 	errno = 0;
334*7c478bd9Sstevel@tonic-gate 	pw = getpwnam(name);
335*7c478bd9Sstevel@tonic-gate 	if (pw == NULL)
336*7c478bd9Sstevel@tonic-gate 	{
337*7c478bd9Sstevel@tonic-gate #if 0
338*7c478bd9Sstevel@tonic-gate 		/*
339*7c478bd9Sstevel@tonic-gate 		**  getpwnam() isn't advertised as setting errno.
340*7c478bd9Sstevel@tonic-gate 		**  In fact, under FreeBSD, non-root getpwnam() on
341*7c478bd9Sstevel@tonic-gate 		**  non-existant users returns NULL with errno = EPERM.
342*7c478bd9Sstevel@tonic-gate 		**  This test won't work.
343*7c478bd9Sstevel@tonic-gate 		*/
344*7c478bd9Sstevel@tonic-gate 		switch (errno)
345*7c478bd9Sstevel@tonic-gate 		{
346*7c478bd9Sstevel@tonic-gate 		  case 0:
347*7c478bd9Sstevel@tonic-gate 			return EX_NOUSER;
348*7c478bd9Sstevel@tonic-gate 		  case EIO:
349*7c478bd9Sstevel@tonic-gate 			return EX_OSERR;
350*7c478bd9Sstevel@tonic-gate 		  default:
351*7c478bd9Sstevel@tonic-gate 			return EX_TEMPFAIL;
352*7c478bd9Sstevel@tonic-gate 		}
353*7c478bd9Sstevel@tonic-gate #endif /* 0 */
354*7c478bd9Sstevel@tonic-gate 		return EX_NOUSER;
355*7c478bd9Sstevel@tonic-gate 	}
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 	sm_mbdb_frompw(user, pw);
358*7c478bd9Sstevel@tonic-gate 	return EX_OK;
359*7c478bd9Sstevel@tonic-gate }
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate /*
362*7c478bd9Sstevel@tonic-gate **  MBDB_PW_TERMINATE -- terminate connection to the mailbox database
363*7c478bd9Sstevel@tonic-gate **
364*7c478bd9Sstevel@tonic-gate **	Parameters:
365*7c478bd9Sstevel@tonic-gate **		none.
366*7c478bd9Sstevel@tonic-gate **
367*7c478bd9Sstevel@tonic-gate **	Results:
368*7c478bd9Sstevel@tonic-gate **		none.
369*7c478bd9Sstevel@tonic-gate */
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate static void
372*7c478bd9Sstevel@tonic-gate mbdb_pw_terminate()
373*7c478bd9Sstevel@tonic-gate {
374*7c478bd9Sstevel@tonic-gate 	endpwent();
375*7c478bd9Sstevel@tonic-gate }
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate #if LDAPMAP
378*7c478bd9Sstevel@tonic-gate # if _LDAP_EXAMPLE_
379*7c478bd9Sstevel@tonic-gate /*
380*7c478bd9Sstevel@tonic-gate **  LDAP example implementation based on RFC 2307, "An Approach for Using
381*7c478bd9Sstevel@tonic-gate **  LDAP as a Network Information Service":
382*7c478bd9Sstevel@tonic-gate **
383*7c478bd9Sstevel@tonic-gate **	( nisSchema.1.0 NAME 'uidNumber'
384*7c478bd9Sstevel@tonic-gate **	  DESC 'An integer uniquely identifying a user in an
385*7c478bd9Sstevel@tonic-gate **		administrative domain'
386*7c478bd9Sstevel@tonic-gate **	  EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE )
387*7c478bd9Sstevel@tonic-gate **
388*7c478bd9Sstevel@tonic-gate **	( nisSchema.1.1 NAME 'gidNumber'
389*7c478bd9Sstevel@tonic-gate **	  DESC 'An integer uniquely identifying a group in an
390*7c478bd9Sstevel@tonic-gate **		administrative domain'
391*7c478bd9Sstevel@tonic-gate **	  EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE )
392*7c478bd9Sstevel@tonic-gate **
393*7c478bd9Sstevel@tonic-gate **	( nisSchema.1.2 NAME 'gecos'
394*7c478bd9Sstevel@tonic-gate **	  DESC 'The GECOS field; the common name'
395*7c478bd9Sstevel@tonic-gate **	  EQUALITY caseIgnoreIA5Match
396*7c478bd9Sstevel@tonic-gate **	  SUBSTRINGS caseIgnoreIA5SubstringsMatch
397*7c478bd9Sstevel@tonic-gate **	  SYNTAX 'IA5String' SINGLE-VALUE )
398*7c478bd9Sstevel@tonic-gate **
399*7c478bd9Sstevel@tonic-gate **	( nisSchema.1.3 NAME 'homeDirectory'
400*7c478bd9Sstevel@tonic-gate **	  DESC 'The absolute path to the home directory'
401*7c478bd9Sstevel@tonic-gate **	  EQUALITY caseExactIA5Match
402*7c478bd9Sstevel@tonic-gate **	  SYNTAX 'IA5String' SINGLE-VALUE )
403*7c478bd9Sstevel@tonic-gate **
404*7c478bd9Sstevel@tonic-gate **	( nisSchema.1.4 NAME 'loginShell'
405*7c478bd9Sstevel@tonic-gate **	  DESC 'The path to the login shell'
406*7c478bd9Sstevel@tonic-gate **	  EQUALITY caseExactIA5Match
407*7c478bd9Sstevel@tonic-gate **	  SYNTAX 'IA5String' SINGLE-VALUE )
408*7c478bd9Sstevel@tonic-gate **
409*7c478bd9Sstevel@tonic-gate **	( nisSchema.2.0 NAME 'posixAccount' SUP top AUXILIARY
410*7c478bd9Sstevel@tonic-gate **	  DESC 'Abstraction of an account with POSIX attributes'
411*7c478bd9Sstevel@tonic-gate **	  MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
412*7c478bd9Sstevel@tonic-gate **	  MAY ( userPassword $ loginShell $ gecos $ description ) )
413*7c478bd9Sstevel@tonic-gate **
414*7c478bd9Sstevel@tonic-gate */
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate #  define MBDB_LDAP_LABEL		"MailboxDatabase"
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate #  ifndef MBDB_LDAP_FILTER
419*7c478bd9Sstevel@tonic-gate #   define MBDB_LDAP_FILTER		"(&(objectClass=posixAccount)(uid=%0))"
420*7c478bd9Sstevel@tonic-gate #  endif /* MBDB_LDAP_FILTER */
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate #  ifndef MBDB_DEFAULT_LDAP_BASEDN
423*7c478bd9Sstevel@tonic-gate #   define MBDB_DEFAULT_LDAP_BASEDN	NULL
424*7c478bd9Sstevel@tonic-gate #  endif /* MBDB_DEFAULT_LDAP_BASEDN */
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate #  ifndef MBDB_DEFAULT_LDAP_SERVER
427*7c478bd9Sstevel@tonic-gate #   define MBDB_DEFAULT_LDAP_SERVER	NULL
428*7c478bd9Sstevel@tonic-gate #  endif /* MBDB_DEFAULT_LDAP_SERVER */
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate /*
431*7c478bd9Sstevel@tonic-gate **  MBDB_LDAP_INITIALIZE -- initialize LDAP version
432*7c478bd9Sstevel@tonic-gate **
433*7c478bd9Sstevel@tonic-gate **	Parameters:
434*7c478bd9Sstevel@tonic-gate **		arg -- LDAP specification
435*7c478bd9Sstevel@tonic-gate **
436*7c478bd9Sstevel@tonic-gate **	Results:
437*7c478bd9Sstevel@tonic-gate **		EX_OK on success, or an EX_* code on failure.
438*7c478bd9Sstevel@tonic-gate */
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate static int
441*7c478bd9Sstevel@tonic-gate mbdb_ldap_initialize(arg)
442*7c478bd9Sstevel@tonic-gate 	char *arg;
443*7c478bd9Sstevel@tonic-gate {
444*7c478bd9Sstevel@tonic-gate 	sm_ldap_clear(&LDAPLMAP);
445*7c478bd9Sstevel@tonic-gate 	LDAPLMAP.ldap_base = MBDB_DEFAULT_LDAP_BASEDN;
446*7c478bd9Sstevel@tonic-gate 	LDAPLMAP.ldap_host = MBDB_DEFAULT_LDAP_SERVER;
447*7c478bd9Sstevel@tonic-gate 	LDAPLMAP.ldap_filter = MBDB_LDAP_FILTER;
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	/* Only want one match */
450*7c478bd9Sstevel@tonic-gate 	LDAPLMAP.ldap_sizelimit = 1;
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	/* interpolate new ldap_base and ldap_host from arg if given */
453*7c478bd9Sstevel@tonic-gate 	if (arg != NULL && *arg != '\0')
454*7c478bd9Sstevel@tonic-gate 	{
455*7c478bd9Sstevel@tonic-gate 		char *new;
456*7c478bd9Sstevel@tonic-gate 		char *sep;
457*7c478bd9Sstevel@tonic-gate 		size_t len;
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 		len = strlen(arg) + 1;
460*7c478bd9Sstevel@tonic-gate 		new = sm_malloc(len);
461*7c478bd9Sstevel@tonic-gate 		if (new == NULL)
462*7c478bd9Sstevel@tonic-gate 			return EX_TEMPFAIL;
463*7c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(new, arg, len);
464*7c478bd9Sstevel@tonic-gate 		sep = strrchr(new, '@');
465*7c478bd9Sstevel@tonic-gate 		if (sep != NULL)
466*7c478bd9Sstevel@tonic-gate 		{
467*7c478bd9Sstevel@tonic-gate 			*sep++ = '\0';
468*7c478bd9Sstevel@tonic-gate 			LDAPLMAP.ldap_host = sep;
469*7c478bd9Sstevel@tonic-gate 		}
470*7c478bd9Sstevel@tonic-gate 		LDAPLMAP.ldap_base = new;
471*7c478bd9Sstevel@tonic-gate 	}
472*7c478bd9Sstevel@tonic-gate 	return EX_OK;
473*7c478bd9Sstevel@tonic-gate }
474*7c478bd9Sstevel@tonic-gate 
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate /*
477*7c478bd9Sstevel@tonic-gate **  MBDB_LDAP_LOOKUP -- look up a local mail recipient, given name
478*7c478bd9Sstevel@tonic-gate **
479*7c478bd9Sstevel@tonic-gate **	Parameters:
480*7c478bd9Sstevel@tonic-gate **		name -- name of local mail recipient
481*7c478bd9Sstevel@tonic-gate **		user -- pointer to structure to fill in on success
482*7c478bd9Sstevel@tonic-gate **
483*7c478bd9Sstevel@tonic-gate **	Results:
484*7c478bd9Sstevel@tonic-gate **		On success, fill in *user and return EX_OK.
485*7c478bd9Sstevel@tonic-gate **		Failure: EX_NOUSER.
486*7c478bd9Sstevel@tonic-gate */
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate #define NEED_FULLNAME	0x01
489*7c478bd9Sstevel@tonic-gate #define NEED_HOMEDIR	0x02
490*7c478bd9Sstevel@tonic-gate #define NEED_SHELL	0x04
491*7c478bd9Sstevel@tonic-gate #define NEED_UID	0x08
492*7c478bd9Sstevel@tonic-gate #define NEED_GID	0x10
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate static int
495*7c478bd9Sstevel@tonic-gate mbdb_ldap_lookup(name, user)
496*7c478bd9Sstevel@tonic-gate 	char *name;
497*7c478bd9Sstevel@tonic-gate 	SM_MBDB_T *user;
498*7c478bd9Sstevel@tonic-gate {
499*7c478bd9Sstevel@tonic-gate 	int msgid;
500*7c478bd9Sstevel@tonic-gate 	int need;
501*7c478bd9Sstevel@tonic-gate 	int ret;
502*7c478bd9Sstevel@tonic-gate 	int save_errno;
503*7c478bd9Sstevel@tonic-gate 	LDAPMessage *entry;
504*7c478bd9Sstevel@tonic-gate 	BerElement *ber;
505*7c478bd9Sstevel@tonic-gate 	char *attr = NULL;
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	if (strlen(name) >= sizeof(user->mbdb_name))
508*7c478bd9Sstevel@tonic-gate 	{
509*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
510*7c478bd9Sstevel@tonic-gate 		return EX_NOUSER;
511*7c478bd9Sstevel@tonic-gate 	}
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 	if (LDAPLMAP.ldap_filter == NULL)
514*7c478bd9Sstevel@tonic-gate 	{
515*7c478bd9Sstevel@tonic-gate 		/* map not initialized, but don't have arg here */
516*7c478bd9Sstevel@tonic-gate 		errno = EFAULT;
517*7c478bd9Sstevel@tonic-gate 		return EX_TEMPFAIL;
518*7c478bd9Sstevel@tonic-gate 	}
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate 	if (LDAPLMAP.ldap_pid != getpid())
521*7c478bd9Sstevel@tonic-gate 	{
522*7c478bd9Sstevel@tonic-gate 		/* re-open map in this child process */
523*7c478bd9Sstevel@tonic-gate 		LDAPLMAP.ldap_ld = NULL;
524*7c478bd9Sstevel@tonic-gate 	}
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 	if (LDAPLMAP.ldap_ld == NULL)
527*7c478bd9Sstevel@tonic-gate 	{
528*7c478bd9Sstevel@tonic-gate 		/* map not open, try to open now */
529*7c478bd9Sstevel@tonic-gate 		if (!sm_ldap_start(MBDB_LDAP_LABEL, &LDAPLMAP))
530*7c478bd9Sstevel@tonic-gate 			return EX_TEMPFAIL;
531*7c478bd9Sstevel@tonic-gate 	}
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 	sm_ldap_setopts(LDAPLMAP.ldap_ld, &LDAPLMAP);
534*7c478bd9Sstevel@tonic-gate 	msgid = sm_ldap_search(&LDAPLMAP, name);
535*7c478bd9Sstevel@tonic-gate 	if (msgid == -1)
536*7c478bd9Sstevel@tonic-gate 	{
537*7c478bd9Sstevel@tonic-gate 		save_errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld) + E_LDAPBASE;
538*7c478bd9Sstevel@tonic-gate #  ifdef LDAP_SERVER_DOWN
539*7c478bd9Sstevel@tonic-gate 		if (errno == LDAP_SERVER_DOWN)
540*7c478bd9Sstevel@tonic-gate 		{
541*7c478bd9Sstevel@tonic-gate 			/* server disappeared, try reopen on next search */
542*7c478bd9Sstevel@tonic-gate 			sm_ldap_close(&LDAPLMAP);
543*7c478bd9Sstevel@tonic-gate 		}
544*7c478bd9Sstevel@tonic-gate #  endif /* LDAP_SERVER_DOWN */
545*7c478bd9Sstevel@tonic-gate 		errno = save_errno;
546*7c478bd9Sstevel@tonic-gate 		return EX_TEMPFAIL;
547*7c478bd9Sstevel@tonic-gate 	}
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	/* Get results */
550*7c478bd9Sstevel@tonic-gate 	ret = ldap_result(LDAPLMAP.ldap_ld, msgid, 1,
551*7c478bd9Sstevel@tonic-gate 			  (LDAPLMAP.ldap_timeout.tv_sec == 0 ? NULL :
552*7c478bd9Sstevel@tonic-gate 			   &(LDAPLMAP.ldap_timeout)),
553*7c478bd9Sstevel@tonic-gate 			  &(LDAPLMAP.ldap_res));
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 	if (ret != LDAP_RES_SEARCH_RESULT &&
556*7c478bd9Sstevel@tonic-gate 	    ret != LDAP_RES_SEARCH_ENTRY)
557*7c478bd9Sstevel@tonic-gate 	{
558*7c478bd9Sstevel@tonic-gate 		if (ret == 0)
559*7c478bd9Sstevel@tonic-gate 			errno = ETIMEDOUT;
560*7c478bd9Sstevel@tonic-gate 		else
561*7c478bd9Sstevel@tonic-gate 			errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld);
562*7c478bd9Sstevel@tonic-gate 		ret = EX_TEMPFAIL;
563*7c478bd9Sstevel@tonic-gate 		goto abort;
564*7c478bd9Sstevel@tonic-gate 	}
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	entry = ldap_first_entry(LDAPLMAP.ldap_ld, LDAPLMAP.ldap_res);
567*7c478bd9Sstevel@tonic-gate 	if (entry == NULL)
568*7c478bd9Sstevel@tonic-gate 	{
569*7c478bd9Sstevel@tonic-gate 		save_errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld);
570*7c478bd9Sstevel@tonic-gate 		if (save_errno == LDAP_SUCCESS)
571*7c478bd9Sstevel@tonic-gate 		{
572*7c478bd9Sstevel@tonic-gate 			errno = ENOENT;
573*7c478bd9Sstevel@tonic-gate 			ret = EX_NOUSER;
574*7c478bd9Sstevel@tonic-gate 		}
575*7c478bd9Sstevel@tonic-gate 		else
576*7c478bd9Sstevel@tonic-gate 		{
577*7c478bd9Sstevel@tonic-gate 			errno = save_errno;
578*7c478bd9Sstevel@tonic-gate 			ret = EX_TEMPFAIL;
579*7c478bd9Sstevel@tonic-gate 		}
580*7c478bd9Sstevel@tonic-gate 		goto abort;
581*7c478bd9Sstevel@tonic-gate 	}
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
584*7c478bd9Sstevel@tonic-gate 	/*
585*7c478bd9Sstevel@tonic-gate 	**  Reset value to prevent lingering
586*7c478bd9Sstevel@tonic-gate 	**  LDAP_DECODING_ERROR due to
587*7c478bd9Sstevel@tonic-gate 	**  OpenLDAP 1.X's hack (see below)
588*7c478bd9Sstevel@tonic-gate 	*/
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate 	LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS;
591*7c478bd9Sstevel@tonic-gate # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 	ret = EX_OK;
594*7c478bd9Sstevel@tonic-gate 	need = NEED_FULLNAME|NEED_HOMEDIR|NEED_SHELL|NEED_UID|NEED_GID;
595*7c478bd9Sstevel@tonic-gate 	for (attr = ldap_first_attribute(LDAPLMAP.ldap_ld, entry, &ber);
596*7c478bd9Sstevel@tonic-gate 	     attr != NULL;
597*7c478bd9Sstevel@tonic-gate 	     attr = ldap_next_attribute(LDAPLMAP.ldap_ld, entry, ber))
598*7c478bd9Sstevel@tonic-gate 	{
599*7c478bd9Sstevel@tonic-gate 		char **vals;
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 		vals = ldap_get_values(LDAPLMAP.ldap_ld, entry, attr);
602*7c478bd9Sstevel@tonic-gate 		if (vals == NULL)
603*7c478bd9Sstevel@tonic-gate 		{
604*7c478bd9Sstevel@tonic-gate 			errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld);
605*7c478bd9Sstevel@tonic-gate 			if (errno == LDAP_SUCCESS)
606*7c478bd9Sstevel@tonic-gate 			{
607*7c478bd9Sstevel@tonic-gate 				ldap_memfree(attr);
608*7c478bd9Sstevel@tonic-gate 				continue;
609*7c478bd9Sstevel@tonic-gate 			}
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate 			/* Must be an error */
612*7c478bd9Sstevel@tonic-gate 			errno += E_LDAPBASE;
613*7c478bd9Sstevel@tonic-gate 			ret = EX_TEMPFAIL;
614*7c478bd9Sstevel@tonic-gate 			goto abort;
615*7c478bd9Sstevel@tonic-gate 		}
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
618*7c478bd9Sstevel@tonic-gate 		/*
619*7c478bd9Sstevel@tonic-gate 		**  Reset value to prevent lingering
620*7c478bd9Sstevel@tonic-gate 		**  LDAP_DECODING_ERROR due to
621*7c478bd9Sstevel@tonic-gate 		**  OpenLDAP 1.X's hack (see below)
622*7c478bd9Sstevel@tonic-gate 		*/
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 		LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS;
625*7c478bd9Sstevel@tonic-gate # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate 		if (vals[0] == NULL || vals[0][0] == '\0')
628*7c478bd9Sstevel@tonic-gate 			goto skip;
629*7c478bd9Sstevel@tonic-gate 
630*7c478bd9Sstevel@tonic-gate 		if (strcasecmp(attr, "gecos") == 0)
631*7c478bd9Sstevel@tonic-gate 		{
632*7c478bd9Sstevel@tonic-gate 			if (!bitset(NEED_FULLNAME, need) ||
633*7c478bd9Sstevel@tonic-gate 			    strlen(vals[0]) >= sizeof(user->mbdb_fullname))
634*7c478bd9Sstevel@tonic-gate 				goto skip;
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 			sm_pwfullname(vals[0], name, user->mbdb_fullname,
637*7c478bd9Sstevel@tonic-gate 				      sizeof(user->mbdb_fullname));
638*7c478bd9Sstevel@tonic-gate 			need &= ~NEED_FULLNAME;
639*7c478bd9Sstevel@tonic-gate 		}
640*7c478bd9Sstevel@tonic-gate 		else if (strcasecmp(attr, "homeDirectory") == 0)
641*7c478bd9Sstevel@tonic-gate 		{
642*7c478bd9Sstevel@tonic-gate 			if (!bitset(NEED_HOMEDIR, need) ||
643*7c478bd9Sstevel@tonic-gate 			    strlen(vals[0]) >= sizeof(user->mbdb_homedir))
644*7c478bd9Sstevel@tonic-gate 				goto skip;
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 			(void) sm_strlcpy(user->mbdb_homedir, vals[0],
647*7c478bd9Sstevel@tonic-gate 					  sizeof(user->mbdb_homedir));
648*7c478bd9Sstevel@tonic-gate 			need &= ~NEED_HOMEDIR;
649*7c478bd9Sstevel@tonic-gate 		}
650*7c478bd9Sstevel@tonic-gate 		else if (strcasecmp(attr, "loginShell") == 0)
651*7c478bd9Sstevel@tonic-gate 		{
652*7c478bd9Sstevel@tonic-gate 			if (!bitset(NEED_SHELL, need) ||
653*7c478bd9Sstevel@tonic-gate 			    strlen(vals[0]) >= sizeof(user->mbdb_shell))
654*7c478bd9Sstevel@tonic-gate 				goto skip;
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 			(void) sm_strlcpy(user->mbdb_shell, vals[0],
657*7c478bd9Sstevel@tonic-gate 					  sizeof(user->mbdb_shell));
658*7c478bd9Sstevel@tonic-gate 			need &= ~NEED_SHELL;
659*7c478bd9Sstevel@tonic-gate 		}
660*7c478bd9Sstevel@tonic-gate 		else if (strcasecmp(attr, "uidNumber") == 0)
661*7c478bd9Sstevel@tonic-gate 		{
662*7c478bd9Sstevel@tonic-gate 			char *p;
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate 			if (!bitset(NEED_UID, need))
665*7c478bd9Sstevel@tonic-gate 				goto skip;
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 			for (p = vals[0]; *p != '\0'; p++)
668*7c478bd9Sstevel@tonic-gate 			{
669*7c478bd9Sstevel@tonic-gate 				/* allow negative numbers */
670*7c478bd9Sstevel@tonic-gate 				if (p == vals[0] && *p == '-')
671*7c478bd9Sstevel@tonic-gate 				{
672*7c478bd9Sstevel@tonic-gate 					/* but not simply '-' */
673*7c478bd9Sstevel@tonic-gate 					if (*(p + 1) == '\0')
674*7c478bd9Sstevel@tonic-gate 						goto skip;
675*7c478bd9Sstevel@tonic-gate 				}
676*7c478bd9Sstevel@tonic-gate 				else if (!isascii(*p) || !isdigit(*p))
677*7c478bd9Sstevel@tonic-gate 					goto skip;
678*7c478bd9Sstevel@tonic-gate 			}
679*7c478bd9Sstevel@tonic-gate 			user->mbdb_uid = atoi(vals[0]);
680*7c478bd9Sstevel@tonic-gate 			need &= ~NEED_UID;
681*7c478bd9Sstevel@tonic-gate 		}
682*7c478bd9Sstevel@tonic-gate 		else if (strcasecmp(attr, "gidNumber") == 0)
683*7c478bd9Sstevel@tonic-gate 		{
684*7c478bd9Sstevel@tonic-gate 			char *p;
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 			if (!bitset(NEED_GID, need))
687*7c478bd9Sstevel@tonic-gate 				goto skip;
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 			for (p = vals[0]; *p != '\0'; p++)
690*7c478bd9Sstevel@tonic-gate 			{
691*7c478bd9Sstevel@tonic-gate 				/* allow negative numbers */
692*7c478bd9Sstevel@tonic-gate 				if (p == vals[0] && *p == '-')
693*7c478bd9Sstevel@tonic-gate 				{
694*7c478bd9Sstevel@tonic-gate 					/* but not simply '-' */
695*7c478bd9Sstevel@tonic-gate 					if (*(p + 1) == '\0')
696*7c478bd9Sstevel@tonic-gate 						goto skip;
697*7c478bd9Sstevel@tonic-gate 				}
698*7c478bd9Sstevel@tonic-gate 				else if (!isascii(*p) || !isdigit(*p))
699*7c478bd9Sstevel@tonic-gate 					goto skip;
700*7c478bd9Sstevel@tonic-gate 			}
701*7c478bd9Sstevel@tonic-gate 			user->mbdb_gid = atoi(vals[0]);
702*7c478bd9Sstevel@tonic-gate 			need &= ~NEED_GID;
703*7c478bd9Sstevel@tonic-gate 		}
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate skip:
706*7c478bd9Sstevel@tonic-gate 		ldap_value_free(vals);
707*7c478bd9Sstevel@tonic-gate 		ldap_memfree(attr);
708*7c478bd9Sstevel@tonic-gate 	}
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate 	errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld);
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 	/*
713*7c478bd9Sstevel@tonic-gate 	**  We check errno != LDAP_DECODING_ERROR since
714*7c478bd9Sstevel@tonic-gate 	**  OpenLDAP 1.X has a very ugly *undocumented*
715*7c478bd9Sstevel@tonic-gate 	**  hack of returning this error code from
716*7c478bd9Sstevel@tonic-gate 	**  ldap_next_attribute() if the library freed the
717*7c478bd9Sstevel@tonic-gate 	**  ber attribute.  See:
718*7c478bd9Sstevel@tonic-gate 	**  http://www.openldap.org/lists/openldap-devel/9901/msg00064.html
719*7c478bd9Sstevel@tonic-gate 	*/
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 	if (errno != LDAP_SUCCESS &&
722*7c478bd9Sstevel@tonic-gate 	    errno != LDAP_DECODING_ERROR)
723*7c478bd9Sstevel@tonic-gate 	{
724*7c478bd9Sstevel@tonic-gate 		/* Must be an error */
725*7c478bd9Sstevel@tonic-gate 		errno += E_LDAPBASE;
726*7c478bd9Sstevel@tonic-gate 		ret = EX_TEMPFAIL;
727*7c478bd9Sstevel@tonic-gate 		goto abort;
728*7c478bd9Sstevel@tonic-gate 	}
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate  abort:
731*7c478bd9Sstevel@tonic-gate 	save_errno = errno;
732*7c478bd9Sstevel@tonic-gate 	if (attr != NULL)
733*7c478bd9Sstevel@tonic-gate 	{
734*7c478bd9Sstevel@tonic-gate 		ldap_memfree(attr);
735*7c478bd9Sstevel@tonic-gate 		attr = NULL;
736*7c478bd9Sstevel@tonic-gate 	}
737*7c478bd9Sstevel@tonic-gate 	if (LDAPLMAP.ldap_res != NULL)
738*7c478bd9Sstevel@tonic-gate 	{
739*7c478bd9Sstevel@tonic-gate 		ldap_msgfree(LDAPLMAP.ldap_res);
740*7c478bd9Sstevel@tonic-gate 		LDAPLMAP.ldap_res = NULL;
741*7c478bd9Sstevel@tonic-gate 	}
742*7c478bd9Sstevel@tonic-gate 	if (ret == EX_OK)
743*7c478bd9Sstevel@tonic-gate 	{
744*7c478bd9Sstevel@tonic-gate 		if (need == 0)
745*7c478bd9Sstevel@tonic-gate 		{
746*7c478bd9Sstevel@tonic-gate 			(void) sm_strlcpy(user->mbdb_name, name,
747*7c478bd9Sstevel@tonic-gate 					  sizeof(user->mbdb_name));
748*7c478bd9Sstevel@tonic-gate 			save_errno = 0;
749*7c478bd9Sstevel@tonic-gate 		}
750*7c478bd9Sstevel@tonic-gate 		else
751*7c478bd9Sstevel@tonic-gate 		{
752*7c478bd9Sstevel@tonic-gate 			ret = EX_NOUSER;
753*7c478bd9Sstevel@tonic-gate 			save_errno = EINVAL;
754*7c478bd9Sstevel@tonic-gate 		}
755*7c478bd9Sstevel@tonic-gate 	}
756*7c478bd9Sstevel@tonic-gate 	errno = save_errno;
757*7c478bd9Sstevel@tonic-gate 	return ret;
758*7c478bd9Sstevel@tonic-gate }
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate /*
761*7c478bd9Sstevel@tonic-gate **  MBDB_LDAP_TERMINATE -- terminate connection to the mailbox database
762*7c478bd9Sstevel@tonic-gate **
763*7c478bd9Sstevel@tonic-gate **	Parameters:
764*7c478bd9Sstevel@tonic-gate **		none.
765*7c478bd9Sstevel@tonic-gate **
766*7c478bd9Sstevel@tonic-gate **	Results:
767*7c478bd9Sstevel@tonic-gate **		none.
768*7c478bd9Sstevel@tonic-gate */
769*7c478bd9Sstevel@tonic-gate 
770*7c478bd9Sstevel@tonic-gate static void
771*7c478bd9Sstevel@tonic-gate mbdb_ldap_terminate()
772*7c478bd9Sstevel@tonic-gate {
773*7c478bd9Sstevel@tonic-gate 	sm_ldap_close(&LDAPLMAP);
774*7c478bd9Sstevel@tonic-gate }
775*7c478bd9Sstevel@tonic-gate # endif /* _LDAP_EXAMPLE_ */
776*7c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */
777