xref: /freebsd/contrib/sendmail/libsm/mbdb.c (revision 9bd497b8354567454e075076d40c996e21bd6095)
140266059SGregory Neil Shapiro /*
29bd497b8SGregory Neil Shapiro  * Copyright (c) 2001-2003,2009 Sendmail, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *      All rights reserved.
440266059SGregory Neil Shapiro  *
540266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro  * the sendmail distribution.
840266059SGregory Neil Shapiro  */
940266059SGregory Neil Shapiro 
1040266059SGregory Neil Shapiro #include <sm/gen.h>
119bd497b8SGregory Neil Shapiro SM_RCSID("@(#)$Id: mbdb.c,v 1.41 2009/06/19 22:02:26 guenther Exp $")
1240266059SGregory Neil Shapiro 
1340266059SGregory Neil Shapiro #include <sys/param.h>
1440266059SGregory Neil Shapiro 
1540266059SGregory Neil Shapiro #include <ctype.h>
1640266059SGregory Neil Shapiro #include <errno.h>
1740266059SGregory Neil Shapiro #include <pwd.h>
1840266059SGregory Neil Shapiro #include <stdlib.h>
1940266059SGregory Neil Shapiro #include <setjmp.h>
2013bd1963SGregory Neil Shapiro #include <unistd.h>
2140266059SGregory Neil Shapiro 
2240266059SGregory Neil Shapiro #include <sm/limits.h>
2340266059SGregory Neil Shapiro #include <sm/conf.h>
2440266059SGregory Neil Shapiro #include <sm/assert.h>
2540266059SGregory Neil Shapiro #include <sm/bitops.h>
2640266059SGregory Neil Shapiro #include <sm/errstring.h>
2740266059SGregory Neil Shapiro #include <sm/heap.h>
2840266059SGregory Neil Shapiro #include <sm/mbdb.h>
2940266059SGregory Neil Shapiro #include <sm/string.h>
30605302a5SGregory Neil Shapiro # ifdef EX_OK
31605302a5SGregory Neil Shapiro #  undef EX_OK			/* for SVr4.2 SMP */
32605302a5SGregory Neil Shapiro # endif /* EX_OK */
3340266059SGregory Neil Shapiro #include <sm/sysexits.h>
3440266059SGregory Neil Shapiro 
3540266059SGregory Neil Shapiro #if LDAPMAP
3640266059SGregory Neil Shapiro # if _LDAP_EXAMPLE_
3740266059SGregory Neil Shapiro #  include <sm/ldap.h>
3840266059SGregory Neil Shapiro # endif /* _LDAP_EXAMPLE_ */
3940266059SGregory Neil Shapiro #endif /* LDAPMAP */
4040266059SGregory Neil Shapiro 
4140266059SGregory Neil Shapiro typedef struct
4240266059SGregory Neil Shapiro {
4340266059SGregory Neil Shapiro 	char	*mbdb_typename;
4440266059SGregory Neil Shapiro 	int	(*mbdb_initialize) __P((char *));
4540266059SGregory Neil Shapiro 	int	(*mbdb_lookup) __P((char *name, SM_MBDB_T *user));
4640266059SGregory Neil Shapiro 	void	(*mbdb_terminate) __P((void));
4740266059SGregory Neil Shapiro } SM_MBDB_TYPE_T;
4840266059SGregory Neil Shapiro 
4940266059SGregory Neil Shapiro static int	mbdb_pw_initialize __P((char *));
5040266059SGregory Neil Shapiro static int	mbdb_pw_lookup __P((char *name, SM_MBDB_T *user));
5140266059SGregory Neil Shapiro static void	mbdb_pw_terminate __P((void));
5240266059SGregory Neil Shapiro 
5340266059SGregory Neil Shapiro #if LDAPMAP
5440266059SGregory Neil Shapiro # if _LDAP_EXAMPLE_
5540266059SGregory Neil Shapiro static struct sm_ldap_struct LDAPLMAP;
5640266059SGregory Neil Shapiro static int	mbdb_ldap_initialize __P((char *));
5740266059SGregory Neil Shapiro static int	mbdb_ldap_lookup __P((char *name, SM_MBDB_T *user));
5840266059SGregory Neil Shapiro static void	mbdb_ldap_terminate __P((void));
5940266059SGregory Neil Shapiro # endif /* _LDAP_EXAMPLE_ */
6040266059SGregory Neil Shapiro #endif /* LDAPMAP */
6140266059SGregory Neil Shapiro 
6240266059SGregory Neil Shapiro static SM_MBDB_TYPE_T SmMbdbTypes[] =
6340266059SGregory Neil Shapiro {
6440266059SGregory Neil Shapiro 	{ "pw", mbdb_pw_initialize, mbdb_pw_lookup, mbdb_pw_terminate },
6540266059SGregory Neil Shapiro #if LDAPMAP
6640266059SGregory Neil Shapiro # if _LDAP_EXAMPLE_
6740266059SGregory Neil Shapiro 	{ "ldap", mbdb_ldap_initialize, mbdb_ldap_lookup, mbdb_ldap_terminate },
6840266059SGregory Neil Shapiro # endif /* _LDAP_EXAMPLE_ */
6940266059SGregory Neil Shapiro #endif /* LDAPMAP */
7040266059SGregory Neil Shapiro 	{ NULL, NULL, NULL, NULL }
7140266059SGregory Neil Shapiro };
7240266059SGregory Neil Shapiro 
7340266059SGregory Neil Shapiro static SM_MBDB_TYPE_T *SmMbdbType = &SmMbdbTypes[0];
7440266059SGregory Neil Shapiro 
7540266059SGregory Neil Shapiro /*
7640266059SGregory Neil Shapiro **  SM_MBDB_INITIALIZE -- specify which mailbox database to use
7740266059SGregory Neil Shapiro **
7840266059SGregory Neil Shapiro **	If this function is not called, then the "pw" implementation
7940266059SGregory Neil Shapiro **	is used by default; this implementation uses getpwnam().
8040266059SGregory Neil Shapiro **
8140266059SGregory Neil Shapiro **	Parameters:
8240266059SGregory Neil Shapiro **		mbdb -- Which mailbox database to use.
8340266059SGregory Neil Shapiro **			The argument has the form "name" or "name.arg".
8440266059SGregory Neil Shapiro **			"pw" means use getpwnam().
8540266059SGregory Neil Shapiro **
8640266059SGregory Neil Shapiro **	Results:
8740266059SGregory Neil Shapiro **		EX_OK on success, or an EX_* code on failure.
8840266059SGregory Neil Shapiro */
8940266059SGregory Neil Shapiro 
9040266059SGregory Neil Shapiro int
9140266059SGregory Neil Shapiro sm_mbdb_initialize(mbdb)
9240266059SGregory Neil Shapiro 	char *mbdb;
9340266059SGregory Neil Shapiro {
9440266059SGregory Neil Shapiro 	size_t namelen;
9540266059SGregory Neil Shapiro 	int err;
9640266059SGregory Neil Shapiro 	char *name;
9740266059SGregory Neil Shapiro 	char *arg;
9840266059SGregory Neil Shapiro 	SM_MBDB_TYPE_T *t;
9940266059SGregory Neil Shapiro 
10040266059SGregory Neil Shapiro 	SM_REQUIRE(mbdb != NULL);
10140266059SGregory Neil Shapiro 
10240266059SGregory Neil Shapiro 	name = mbdb;
10340266059SGregory Neil Shapiro 	arg = strchr(mbdb, '.');
10440266059SGregory Neil Shapiro 	if (arg == NULL)
10540266059SGregory Neil Shapiro 		namelen = strlen(name);
10640266059SGregory Neil Shapiro 	else
10740266059SGregory Neil Shapiro 	{
10840266059SGregory Neil Shapiro 		namelen = arg - name;
10940266059SGregory Neil Shapiro 		++arg;
11040266059SGregory Neil Shapiro 	}
11140266059SGregory Neil Shapiro 
11240266059SGregory Neil Shapiro 	for (t = SmMbdbTypes; t->mbdb_typename != NULL; ++t)
11340266059SGregory Neil Shapiro 	{
11440266059SGregory Neil Shapiro 		if (strlen(t->mbdb_typename) == namelen &&
11540266059SGregory Neil Shapiro 		    strncmp(name, t->mbdb_typename, namelen) == 0)
11640266059SGregory Neil Shapiro 		{
11794c01205SGregory Neil Shapiro 			err = EX_OK;
11894c01205SGregory Neil Shapiro 			if (t->mbdb_initialize != NULL)
11940266059SGregory Neil Shapiro 				err = t->mbdb_initialize(arg);
12040266059SGregory Neil Shapiro 			if (err == EX_OK)
12140266059SGregory Neil Shapiro 				SmMbdbType = t;
12240266059SGregory Neil Shapiro 			return err;
12340266059SGregory Neil Shapiro 		}
12440266059SGregory Neil Shapiro 	}
12540266059SGregory Neil Shapiro 	return EX_UNAVAILABLE;
12640266059SGregory Neil Shapiro }
12740266059SGregory Neil Shapiro 
12840266059SGregory Neil Shapiro /*
12940266059SGregory Neil Shapiro **  SM_MBDB_TERMINATE -- terminate connection to the mailbox database
13040266059SGregory Neil Shapiro **
13140266059SGregory Neil Shapiro **	Because this function closes any cached file descriptors that
13240266059SGregory Neil Shapiro **	are being held open for the connection to the mailbox database,
13340266059SGregory Neil Shapiro **	it should be called for security reasons prior to dropping privileges
13440266059SGregory Neil Shapiro **	and execing another process.
13540266059SGregory Neil Shapiro **
13640266059SGregory Neil Shapiro **	Parameters:
13740266059SGregory Neil Shapiro **		none.
13840266059SGregory Neil Shapiro **
13940266059SGregory Neil Shapiro **	Results:
14040266059SGregory Neil Shapiro **		none.
14140266059SGregory Neil Shapiro */
14240266059SGregory Neil Shapiro 
14340266059SGregory Neil Shapiro void
14440266059SGregory Neil Shapiro sm_mbdb_terminate()
14540266059SGregory Neil Shapiro {
14694c01205SGregory Neil Shapiro 	if (SmMbdbType->mbdb_terminate != NULL)
14740266059SGregory Neil Shapiro 		SmMbdbType->mbdb_terminate();
14840266059SGregory Neil Shapiro }
14940266059SGregory Neil Shapiro 
15040266059SGregory Neil Shapiro /*
15140266059SGregory Neil Shapiro **  SM_MBDB_LOOKUP -- look up a local mail recipient, given name
15240266059SGregory Neil Shapiro **
15340266059SGregory Neil Shapiro **	Parameters:
15440266059SGregory Neil Shapiro **		name -- name of local mail recipient
15540266059SGregory Neil Shapiro **		user -- pointer to structure to fill in on success
15640266059SGregory Neil Shapiro **
15740266059SGregory Neil Shapiro **	Results:
15840266059SGregory Neil Shapiro **		On success, fill in *user and return EX_OK.
15940266059SGregory Neil Shapiro **		If the user does not exist, return EX_NOUSER.
16040266059SGregory Neil Shapiro **		If a temporary failure (eg, a network failure) occurred,
16140266059SGregory Neil Shapiro **		return EX_TEMPFAIL.  Otherwise return EX_OSERR.
16240266059SGregory Neil Shapiro */
16340266059SGregory Neil Shapiro 
16440266059SGregory Neil Shapiro int
16540266059SGregory Neil Shapiro sm_mbdb_lookup(name, user)
16640266059SGregory Neil Shapiro 	char *name;
16740266059SGregory Neil Shapiro 	SM_MBDB_T *user;
16840266059SGregory Neil Shapiro {
16994c01205SGregory Neil Shapiro 	int ret = EX_NOUSER;
17094c01205SGregory Neil Shapiro 
17194c01205SGregory Neil Shapiro 	if (SmMbdbType->mbdb_lookup != NULL)
17294c01205SGregory Neil Shapiro 		ret = SmMbdbType->mbdb_lookup(name, user);
17394c01205SGregory Neil Shapiro 	return ret;
17440266059SGregory Neil Shapiro }
17540266059SGregory Neil Shapiro 
17640266059SGregory Neil Shapiro /*
17740266059SGregory Neil Shapiro **  SM_MBDB_FROMPW -- copy from struct pw to SM_MBDB_T
17840266059SGregory Neil Shapiro **
17940266059SGregory Neil Shapiro **	Parameters:
18040266059SGregory Neil Shapiro **		user -- destination user information structure
18140266059SGregory Neil Shapiro **		pw -- source passwd structure
18240266059SGregory Neil Shapiro **
18340266059SGregory Neil Shapiro **	Results:
18440266059SGregory Neil Shapiro **		none.
18540266059SGregory Neil Shapiro */
18640266059SGregory Neil Shapiro 
18740266059SGregory Neil Shapiro void
18840266059SGregory Neil Shapiro sm_mbdb_frompw(user, pw)
18940266059SGregory Neil Shapiro 	SM_MBDB_T *user;
19040266059SGregory Neil Shapiro 	struct passwd *pw;
19140266059SGregory Neil Shapiro {
19240266059SGregory Neil Shapiro 	SM_REQUIRE(user != NULL);
19340266059SGregory Neil Shapiro 	(void) sm_strlcpy(user->mbdb_name, pw->pw_name,
19440266059SGregory Neil Shapiro 			  sizeof(user->mbdb_name));
19540266059SGregory Neil Shapiro 	user->mbdb_uid = pw->pw_uid;
19640266059SGregory Neil Shapiro 	user->mbdb_gid = pw->pw_gid;
19740266059SGregory Neil Shapiro 	sm_pwfullname(pw->pw_gecos, pw->pw_name, user->mbdb_fullname,
19840266059SGregory Neil Shapiro 		      sizeof(user->mbdb_fullname));
19940266059SGregory Neil Shapiro 	(void) sm_strlcpy(user->mbdb_homedir, pw->pw_dir,
20040266059SGregory Neil Shapiro 			  sizeof(user->mbdb_homedir));
20140266059SGregory Neil Shapiro 	(void) sm_strlcpy(user->mbdb_shell, pw->pw_shell,
20240266059SGregory Neil Shapiro 			  sizeof(user->mbdb_shell));
20340266059SGregory Neil Shapiro }
20440266059SGregory Neil Shapiro 
20540266059SGregory Neil Shapiro /*
20640266059SGregory Neil Shapiro **  SM_PWFULLNAME -- build full name of user from pw_gecos field.
20740266059SGregory Neil Shapiro **
20840266059SGregory Neil Shapiro **	This routine interprets the strange entry that would appear
20940266059SGregory Neil Shapiro **	in the GECOS field of the password file.
21040266059SGregory Neil Shapiro **
21140266059SGregory Neil Shapiro **	Parameters:
21240266059SGregory Neil Shapiro **		gecos -- name to build.
21340266059SGregory Neil Shapiro **		user -- the login name of this user (for &).
21440266059SGregory Neil Shapiro **		buf -- place to put the result.
21540266059SGregory Neil Shapiro **		buflen -- length of buf.
21640266059SGregory Neil Shapiro **
21740266059SGregory Neil Shapiro **	Returns:
21840266059SGregory Neil Shapiro **		none.
21940266059SGregory Neil Shapiro */
22040266059SGregory Neil Shapiro 
221605302a5SGregory Neil Shapiro #if _FFR_HANDLE_ISO8859_GECOS
222605302a5SGregory Neil Shapiro static char Latin1ToASCII[128] =
223605302a5SGregory Neil Shapiro {
224605302a5SGregory Neil Shapiro 	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
225605302a5SGregory Neil Shapiro 	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33,
226605302a5SGregory Neil Shapiro 	99, 80, 36, 89, 124, 36, 34, 99, 97, 60, 45, 45, 114, 45, 111, 42,
227605302a5SGregory Neil Shapiro 	50, 51, 39, 117, 80, 46, 44, 49, 111, 62, 42, 42, 42, 63, 65, 65,
228605302a5SGregory Neil Shapiro 	65, 65, 65, 65, 65, 67, 69, 69, 69, 69, 73, 73, 73, 73, 68, 78, 79,
229605302a5SGregory Neil Shapiro 	79, 79, 79, 79, 88, 79, 85, 85, 85, 85, 89, 80, 66, 97, 97, 97, 97,
230605302a5SGregory Neil Shapiro 	97, 97, 97, 99, 101, 101, 101, 101, 105, 105, 105, 105, 100, 110,
231605302a5SGregory Neil Shapiro 	111, 111, 111, 111, 111, 47, 111, 117, 117, 117, 117, 121, 112, 121
232605302a5SGregory Neil Shapiro };
233605302a5SGregory Neil Shapiro #endif /* _FFR_HANDLE_ISO8859_GECOS */
234605302a5SGregory Neil Shapiro 
23540266059SGregory Neil Shapiro void
23640266059SGregory Neil Shapiro sm_pwfullname(gecos, user, buf, buflen)
23740266059SGregory Neil Shapiro 	register char *gecos;
23840266059SGregory Neil Shapiro 	char *user;
23940266059SGregory Neil Shapiro 	char *buf;
24040266059SGregory Neil Shapiro 	size_t buflen;
24140266059SGregory Neil Shapiro {
24240266059SGregory Neil Shapiro 	register char *p;
24340266059SGregory Neil Shapiro 	register char *bp = buf;
24440266059SGregory Neil Shapiro 
24540266059SGregory Neil Shapiro 	if (*gecos == '*')
24640266059SGregory Neil Shapiro 		gecos++;
24740266059SGregory Neil Shapiro 
24840266059SGregory Neil Shapiro 	/* copy gecos, interpolating & to be full name */
24940266059SGregory Neil Shapiro 	for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
25040266059SGregory Neil Shapiro 	{
25140266059SGregory Neil Shapiro 		if (bp >= &buf[buflen - 1])
25240266059SGregory Neil Shapiro 		{
25340266059SGregory Neil Shapiro 			/* buffer overflow -- just use login name */
25440266059SGregory Neil Shapiro 			(void) sm_strlcpy(buf, user, buflen);
25540266059SGregory Neil Shapiro 			return;
25640266059SGregory Neil Shapiro 		}
25740266059SGregory Neil Shapiro 		if (*p == '&')
25840266059SGregory Neil Shapiro 		{
25940266059SGregory Neil Shapiro 			/* interpolate full name */
26040266059SGregory Neil Shapiro 			(void) sm_strlcpy(bp, user, buflen - (bp - buf));
26140266059SGregory Neil Shapiro 			*bp = toupper(*bp);
26240266059SGregory Neil Shapiro 			bp += strlen(bp);
26340266059SGregory Neil Shapiro 		}
26440266059SGregory Neil Shapiro 		else
265605302a5SGregory Neil Shapiro 		{
266605302a5SGregory Neil Shapiro #if _FFR_HANDLE_ISO8859_GECOS
267605302a5SGregory Neil Shapiro 			if ((unsigned char) *p >= 128)
268605302a5SGregory Neil Shapiro 				*bp++ = Latin1ToASCII[(unsigned char) *p - 128];
269605302a5SGregory Neil Shapiro 			else
270605302a5SGregory Neil Shapiro #endif /* _FFR_HANDLE_ISO8859_GECOS */
27140266059SGregory Neil Shapiro 				*bp++ = *p;
27240266059SGregory Neil Shapiro 		}
273605302a5SGregory Neil Shapiro 	}
27440266059SGregory Neil Shapiro 	*bp = '\0';
27540266059SGregory Neil Shapiro }
27640266059SGregory Neil Shapiro 
27740266059SGregory Neil Shapiro /*
27840266059SGregory Neil Shapiro **  /etc/passwd implementation.
27940266059SGregory Neil Shapiro */
28040266059SGregory Neil Shapiro 
28140266059SGregory Neil Shapiro /*
28240266059SGregory Neil Shapiro **  MBDB_PW_INITIALIZE -- initialize getpwnam() version
28340266059SGregory Neil Shapiro **
28440266059SGregory Neil Shapiro **	Parameters:
28540266059SGregory Neil Shapiro **		arg -- unused.
28640266059SGregory Neil Shapiro **
28740266059SGregory Neil Shapiro **	Results:
28840266059SGregory Neil Shapiro **		EX_OK.
28940266059SGregory Neil Shapiro */
29040266059SGregory Neil Shapiro 
29140266059SGregory Neil Shapiro /* ARGSUSED0 */
29240266059SGregory Neil Shapiro static int
29340266059SGregory Neil Shapiro mbdb_pw_initialize(arg)
29440266059SGregory Neil Shapiro 	char *arg;
29540266059SGregory Neil Shapiro {
29640266059SGregory Neil Shapiro 	return EX_OK;
29740266059SGregory Neil Shapiro }
29840266059SGregory Neil Shapiro 
29940266059SGregory Neil Shapiro /*
30040266059SGregory Neil Shapiro **  MBDB_PW_LOOKUP -- look up a local mail recipient, given name
30140266059SGregory Neil Shapiro **
30240266059SGregory Neil Shapiro **	Parameters:
30340266059SGregory Neil Shapiro **		name -- name of local mail recipient
30440266059SGregory Neil Shapiro **		user -- pointer to structure to fill in on success
30540266059SGregory Neil Shapiro **
30640266059SGregory Neil Shapiro **	Results:
30740266059SGregory Neil Shapiro **		On success, fill in *user and return EX_OK.
30840266059SGregory Neil Shapiro **		Failure: EX_NOUSER.
30940266059SGregory Neil Shapiro */
31040266059SGregory Neil Shapiro 
31140266059SGregory Neil Shapiro static int
31240266059SGregory Neil Shapiro mbdb_pw_lookup(name, user)
31340266059SGregory Neil Shapiro 	char *name;
31440266059SGregory Neil Shapiro 	SM_MBDB_T *user;
31540266059SGregory Neil Shapiro {
31640266059SGregory Neil Shapiro 	struct passwd *pw;
31740266059SGregory Neil Shapiro 
31840266059SGregory Neil Shapiro #ifdef HESIOD
31940266059SGregory Neil Shapiro 	/* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */
32040266059SGregory Neil Shapiro 	{
32140266059SGregory Neil Shapiro 		char *p;
32240266059SGregory Neil Shapiro 
32340266059SGregory Neil Shapiro 		for (p = name; *p != '\0'; p++)
32440266059SGregory Neil Shapiro 			if (!isascii(*p) || !isdigit(*p))
32540266059SGregory Neil Shapiro 				break;
32640266059SGregory Neil Shapiro 		if (*p == '\0')
32740266059SGregory Neil Shapiro 			return EX_NOUSER;
32840266059SGregory Neil Shapiro 	}
32940266059SGregory Neil Shapiro #endif /* HESIOD */
33040266059SGregory Neil Shapiro 
33140266059SGregory Neil Shapiro 	errno = 0;
33240266059SGregory Neil Shapiro 	pw = getpwnam(name);
33340266059SGregory Neil Shapiro 	if (pw == NULL)
33440266059SGregory Neil Shapiro 	{
33540266059SGregory Neil Shapiro #if 0
33640266059SGregory Neil Shapiro 		/*
33740266059SGregory Neil Shapiro 		**  getpwnam() isn't advertised as setting errno.
33840266059SGregory Neil Shapiro 		**  In fact, under FreeBSD, non-root getpwnam() on
33940266059SGregory Neil Shapiro 		**  non-existant users returns NULL with errno = EPERM.
34040266059SGregory Neil Shapiro 		**  This test won't work.
34140266059SGregory Neil Shapiro 		*/
34240266059SGregory Neil Shapiro 		switch (errno)
34340266059SGregory Neil Shapiro 		{
34440266059SGregory Neil Shapiro 		  case 0:
34540266059SGregory Neil Shapiro 			return EX_NOUSER;
34640266059SGregory Neil Shapiro 		  case EIO:
34740266059SGregory Neil Shapiro 			return EX_OSERR;
34840266059SGregory Neil Shapiro 		  default:
34940266059SGregory Neil Shapiro 			return EX_TEMPFAIL;
35040266059SGregory Neil Shapiro 		}
35140266059SGregory Neil Shapiro #endif /* 0 */
35240266059SGregory Neil Shapiro 		return EX_NOUSER;
35340266059SGregory Neil Shapiro 	}
35440266059SGregory Neil Shapiro 
35540266059SGregory Neil Shapiro 	sm_mbdb_frompw(user, pw);
35640266059SGregory Neil Shapiro 	return EX_OK;
35740266059SGregory Neil Shapiro }
35840266059SGregory Neil Shapiro 
35940266059SGregory Neil Shapiro /*
36040266059SGregory Neil Shapiro **  MBDB_PW_TERMINATE -- terminate connection to the mailbox database
36140266059SGregory Neil Shapiro **
36240266059SGregory Neil Shapiro **	Parameters:
36340266059SGregory Neil Shapiro **		none.
36440266059SGregory Neil Shapiro **
36540266059SGregory Neil Shapiro **	Results:
36640266059SGregory Neil Shapiro **		none.
36740266059SGregory Neil Shapiro */
36840266059SGregory Neil Shapiro 
36940266059SGregory Neil Shapiro static void
37040266059SGregory Neil Shapiro mbdb_pw_terminate()
37140266059SGregory Neil Shapiro {
37240266059SGregory Neil Shapiro 	endpwent();
37340266059SGregory Neil Shapiro }
37440266059SGregory Neil Shapiro 
37540266059SGregory Neil Shapiro #if LDAPMAP
37640266059SGregory Neil Shapiro # if _LDAP_EXAMPLE_
37740266059SGregory Neil Shapiro /*
37840266059SGregory Neil Shapiro **  LDAP example implementation based on RFC 2307, "An Approach for Using
37940266059SGregory Neil Shapiro **  LDAP as a Network Information Service":
38040266059SGregory Neil Shapiro **
38140266059SGregory Neil Shapiro **	( nisSchema.1.0 NAME 'uidNumber'
38240266059SGregory Neil Shapiro **	  DESC 'An integer uniquely identifying a user in an
38340266059SGregory Neil Shapiro **		administrative domain'
38440266059SGregory Neil Shapiro **	  EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE )
38540266059SGregory Neil Shapiro **
38640266059SGregory Neil Shapiro **	( nisSchema.1.1 NAME 'gidNumber'
38740266059SGregory Neil Shapiro **	  DESC 'An integer uniquely identifying a group in an
38840266059SGregory Neil Shapiro **		administrative domain'
38940266059SGregory Neil Shapiro **	  EQUALITY integerMatch SYNTAX 'INTEGER' SINGLE-VALUE )
39040266059SGregory Neil Shapiro **
39140266059SGregory Neil Shapiro **	( nisSchema.1.2 NAME 'gecos'
39240266059SGregory Neil Shapiro **	  DESC 'The GECOS field; the common name'
39340266059SGregory Neil Shapiro **	  EQUALITY caseIgnoreIA5Match
39440266059SGregory Neil Shapiro **	  SUBSTRINGS caseIgnoreIA5SubstringsMatch
39540266059SGregory Neil Shapiro **	  SYNTAX 'IA5String' SINGLE-VALUE )
39640266059SGregory Neil Shapiro **
39740266059SGregory Neil Shapiro **	( nisSchema.1.3 NAME 'homeDirectory'
39840266059SGregory Neil Shapiro **	  DESC 'The absolute path to the home directory'
39940266059SGregory Neil Shapiro **	  EQUALITY caseExactIA5Match
40040266059SGregory Neil Shapiro **	  SYNTAX 'IA5String' SINGLE-VALUE )
40140266059SGregory Neil Shapiro **
40240266059SGregory Neil Shapiro **	( nisSchema.1.4 NAME 'loginShell'
40340266059SGregory Neil Shapiro **	  DESC 'The path to the login shell'
40440266059SGregory Neil Shapiro **	  EQUALITY caseExactIA5Match
40540266059SGregory Neil Shapiro **	  SYNTAX 'IA5String' SINGLE-VALUE )
40640266059SGregory Neil Shapiro **
40740266059SGregory Neil Shapiro **	( nisSchema.2.0 NAME 'posixAccount' SUP top AUXILIARY
40840266059SGregory Neil Shapiro **	  DESC 'Abstraction of an account with POSIX attributes'
40940266059SGregory Neil Shapiro **	  MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
41040266059SGregory Neil Shapiro **	  MAY ( userPassword $ loginShell $ gecos $ description ) )
41140266059SGregory Neil Shapiro **
41240266059SGregory Neil Shapiro */
41340266059SGregory Neil Shapiro 
41440266059SGregory Neil Shapiro #  define MBDB_LDAP_LABEL		"MailboxDatabase"
41540266059SGregory Neil Shapiro 
41640266059SGregory Neil Shapiro #  ifndef MBDB_LDAP_FILTER
41740266059SGregory Neil Shapiro #   define MBDB_LDAP_FILTER		"(&(objectClass=posixAccount)(uid=%0))"
41840266059SGregory Neil Shapiro #  endif /* MBDB_LDAP_FILTER */
41940266059SGregory Neil Shapiro 
42040266059SGregory Neil Shapiro #  ifndef MBDB_DEFAULT_LDAP_BASEDN
42140266059SGregory Neil Shapiro #   define MBDB_DEFAULT_LDAP_BASEDN	NULL
42240266059SGregory Neil Shapiro #  endif /* MBDB_DEFAULT_LDAP_BASEDN */
42340266059SGregory Neil Shapiro 
42440266059SGregory Neil Shapiro #  ifndef MBDB_DEFAULT_LDAP_SERVER
42540266059SGregory Neil Shapiro #   define MBDB_DEFAULT_LDAP_SERVER	NULL
42640266059SGregory Neil Shapiro #  endif /* MBDB_DEFAULT_LDAP_SERVER */
42740266059SGregory Neil Shapiro 
42840266059SGregory Neil Shapiro /*
42940266059SGregory Neil Shapiro **  MBDB_LDAP_INITIALIZE -- initialize LDAP version
43040266059SGregory Neil Shapiro **
43140266059SGregory Neil Shapiro **	Parameters:
43240266059SGregory Neil Shapiro **		arg -- LDAP specification
43340266059SGregory Neil Shapiro **
43440266059SGregory Neil Shapiro **	Results:
43540266059SGregory Neil Shapiro **		EX_OK on success, or an EX_* code on failure.
43640266059SGregory Neil Shapiro */
43740266059SGregory Neil Shapiro 
43840266059SGregory Neil Shapiro static int
43940266059SGregory Neil Shapiro mbdb_ldap_initialize(arg)
44040266059SGregory Neil Shapiro 	char *arg;
44140266059SGregory Neil Shapiro {
44240266059SGregory Neil Shapiro 	sm_ldap_clear(&LDAPLMAP);
44340266059SGregory Neil Shapiro 	LDAPLMAP.ldap_base = MBDB_DEFAULT_LDAP_BASEDN;
444e92d3f3fSGregory Neil Shapiro 	LDAPLMAP.ldap_host = MBDB_DEFAULT_LDAP_SERVER;
44540266059SGregory Neil Shapiro 	LDAPLMAP.ldap_filter = MBDB_LDAP_FILTER;
44640266059SGregory Neil Shapiro 
44740266059SGregory Neil Shapiro 	/* Only want one match */
44840266059SGregory Neil Shapiro 	LDAPLMAP.ldap_sizelimit = 1;
44940266059SGregory Neil Shapiro 
450e92d3f3fSGregory Neil Shapiro 	/* interpolate new ldap_base and ldap_host from arg if given */
45140266059SGregory Neil Shapiro 	if (arg != NULL && *arg != '\0')
45240266059SGregory Neil Shapiro 	{
45340266059SGregory Neil Shapiro 		char *new;
45440266059SGregory Neil Shapiro 		char *sep;
45540266059SGregory Neil Shapiro 		size_t len;
45640266059SGregory Neil Shapiro 
45740266059SGregory Neil Shapiro 		len = strlen(arg) + 1;
45840266059SGregory Neil Shapiro 		new = sm_malloc(len);
45940266059SGregory Neil Shapiro 		if (new == NULL)
46040266059SGregory Neil Shapiro 			return EX_TEMPFAIL;
46140266059SGregory Neil Shapiro 		(void) sm_strlcpy(new, arg, len);
46240266059SGregory Neil Shapiro 		sep = strrchr(new, '@');
46340266059SGregory Neil Shapiro 		if (sep != NULL)
46440266059SGregory Neil Shapiro 		{
46540266059SGregory Neil Shapiro 			*sep++ = '\0';
466e92d3f3fSGregory Neil Shapiro 			LDAPLMAP.ldap_host = sep;
46740266059SGregory Neil Shapiro 		}
46840266059SGregory Neil Shapiro 		LDAPLMAP.ldap_base = new;
46940266059SGregory Neil Shapiro 	}
47040266059SGregory Neil Shapiro 	return EX_OK;
47140266059SGregory Neil Shapiro }
47240266059SGregory Neil Shapiro 
47340266059SGregory Neil Shapiro 
47440266059SGregory Neil Shapiro /*
47540266059SGregory Neil Shapiro **  MBDB_LDAP_LOOKUP -- look up a local mail recipient, given name
47640266059SGregory Neil Shapiro **
47740266059SGregory Neil Shapiro **	Parameters:
47840266059SGregory Neil Shapiro **		name -- name of local mail recipient
47940266059SGregory Neil Shapiro **		user -- pointer to structure to fill in on success
48040266059SGregory Neil Shapiro **
48140266059SGregory Neil Shapiro **	Results:
48240266059SGregory Neil Shapiro **		On success, fill in *user and return EX_OK.
48340266059SGregory Neil Shapiro **		Failure: EX_NOUSER.
48440266059SGregory Neil Shapiro */
48540266059SGregory Neil Shapiro 
48640266059SGregory Neil Shapiro #define NEED_FULLNAME	0x01
48740266059SGregory Neil Shapiro #define NEED_HOMEDIR	0x02
48840266059SGregory Neil Shapiro #define NEED_SHELL	0x04
48940266059SGregory Neil Shapiro #define NEED_UID	0x08
49040266059SGregory Neil Shapiro #define NEED_GID	0x10
49140266059SGregory Neil Shapiro 
49240266059SGregory Neil Shapiro static int
49340266059SGregory Neil Shapiro mbdb_ldap_lookup(name, user)
49440266059SGregory Neil Shapiro 	char *name;
49540266059SGregory Neil Shapiro 	SM_MBDB_T *user;
49640266059SGregory Neil Shapiro {
49740266059SGregory Neil Shapiro 	int msgid;
49840266059SGregory Neil Shapiro 	int need;
49940266059SGregory Neil Shapiro 	int ret;
50040266059SGregory Neil Shapiro 	int save_errno;
50140266059SGregory Neil Shapiro 	LDAPMessage *entry;
50240266059SGregory Neil Shapiro 	BerElement *ber;
50340266059SGregory Neil Shapiro 	char *attr = NULL;
50440266059SGregory Neil Shapiro 
50540266059SGregory Neil Shapiro 	if (strlen(name) >= sizeof(user->mbdb_name))
50640266059SGregory Neil Shapiro 	{
50740266059SGregory Neil Shapiro 		errno = EINVAL;
50840266059SGregory Neil Shapiro 		return EX_NOUSER;
50940266059SGregory Neil Shapiro 	}
51040266059SGregory Neil Shapiro 
51140266059SGregory Neil Shapiro 	if (LDAPLMAP.ldap_filter == NULL)
51240266059SGregory Neil Shapiro 	{
51340266059SGregory Neil Shapiro 		/* map not initialized, but don't have arg here */
51440266059SGregory Neil Shapiro 		errno = EFAULT;
51540266059SGregory Neil Shapiro 		return EX_TEMPFAIL;
51640266059SGregory Neil Shapiro 	}
51740266059SGregory Neil Shapiro 
51813bd1963SGregory Neil Shapiro 	if (LDAPLMAP.ldap_pid != getpid())
51913bd1963SGregory Neil Shapiro 	{
52013bd1963SGregory Neil Shapiro 		/* re-open map in this child process */
52113bd1963SGregory Neil Shapiro 		LDAPLMAP.ldap_ld = NULL;
52213bd1963SGregory Neil Shapiro 	}
52313bd1963SGregory Neil Shapiro 
52440266059SGregory Neil Shapiro 	if (LDAPLMAP.ldap_ld == NULL)
52540266059SGregory Neil Shapiro 	{
52640266059SGregory Neil Shapiro 		/* map not open, try to open now */
52740266059SGregory Neil Shapiro 		if (!sm_ldap_start(MBDB_LDAP_LABEL, &LDAPLMAP))
52840266059SGregory Neil Shapiro 			return EX_TEMPFAIL;
52940266059SGregory Neil Shapiro 	}
53040266059SGregory Neil Shapiro 
53140266059SGregory Neil Shapiro 	sm_ldap_setopts(LDAPLMAP.ldap_ld, &LDAPLMAP);
53240266059SGregory Neil Shapiro 	msgid = sm_ldap_search(&LDAPLMAP, name);
53340266059SGregory Neil Shapiro 	if (msgid == -1)
53440266059SGregory Neil Shapiro 	{
53540266059SGregory Neil Shapiro 		save_errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld) + E_LDAPBASE;
53640266059SGregory Neil Shapiro #  ifdef LDAP_SERVER_DOWN
53740266059SGregory Neil Shapiro 		if (errno == LDAP_SERVER_DOWN)
53840266059SGregory Neil Shapiro 		{
53940266059SGregory Neil Shapiro 			/* server disappeared, try reopen on next search */
54040266059SGregory Neil Shapiro 			sm_ldap_close(&LDAPLMAP);
54140266059SGregory Neil Shapiro 		}
54240266059SGregory Neil Shapiro #  endif /* LDAP_SERVER_DOWN */
54340266059SGregory Neil Shapiro 		errno = save_errno;
54440266059SGregory Neil Shapiro 		return EX_TEMPFAIL;
54540266059SGregory Neil Shapiro 	}
54640266059SGregory Neil Shapiro 
54740266059SGregory Neil Shapiro 	/* Get results */
54840266059SGregory Neil Shapiro 	ret = ldap_result(LDAPLMAP.ldap_ld, msgid, 1,
54940266059SGregory Neil Shapiro 			  (LDAPLMAP.ldap_timeout.tv_sec == 0 ? NULL :
55040266059SGregory Neil Shapiro 			   &(LDAPLMAP.ldap_timeout)),
55140266059SGregory Neil Shapiro 			  &(LDAPLMAP.ldap_res));
55240266059SGregory Neil Shapiro 
55340266059SGregory Neil Shapiro 	if (ret != LDAP_RES_SEARCH_RESULT &&
55440266059SGregory Neil Shapiro 	    ret != LDAP_RES_SEARCH_ENTRY)
55540266059SGregory Neil Shapiro 	{
55640266059SGregory Neil Shapiro 		if (ret == 0)
55740266059SGregory Neil Shapiro 			errno = ETIMEDOUT;
55840266059SGregory Neil Shapiro 		else
55940266059SGregory Neil Shapiro 			errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld);
56040266059SGregory Neil Shapiro 		ret = EX_TEMPFAIL;
56140266059SGregory Neil Shapiro 		goto abort;
56240266059SGregory Neil Shapiro 	}
56340266059SGregory Neil Shapiro 
56440266059SGregory Neil Shapiro 	entry = ldap_first_entry(LDAPLMAP.ldap_ld, LDAPLMAP.ldap_res);
56540266059SGregory Neil Shapiro 	if (entry == NULL)
56640266059SGregory Neil Shapiro 	{
5679bd497b8SGregory Neil Shapiro 		int rc;
5689bd497b8SGregory Neil Shapiro 
5699bd497b8SGregory Neil Shapiro 		/*
5709bd497b8SGregory Neil Shapiro 		**  We may have gotten an LDAP_RES_SEARCH_RESULT response
5719bd497b8SGregory Neil Shapiro 		**  with an error inside it, so we have to extract that
5729bd497b8SGregory Neil Shapiro 		**  with ldap_parse_result().  This can happen when talking
5739bd497b8SGregory Neil Shapiro 		**  to an LDAP proxy whose backend has gone down.
5749bd497b8SGregory Neil Shapiro 		*/
5759bd497b8SGregory Neil Shapiro 
5769bd497b8SGregory Neil Shapiro 		save_errno = ldap_parse_result(LDAPLMAP.ldap_ld,
5779bd497b8SGregory Neil Shapiro 					       LDAPLMAP.ldap_res, &rc, NULL,
5789bd497b8SGregory Neil Shapiro 					       NULL, NULL, NULL, 0);
5799bd497b8SGregory Neil Shapiro 		if (save_errno == LDAP_SUCCESS)
5809bd497b8SGregory Neil Shapiro 			save_errno = rc;
58140266059SGregory Neil Shapiro 		if (save_errno == LDAP_SUCCESS)
58240266059SGregory Neil Shapiro 		{
58340266059SGregory Neil Shapiro 			errno = ENOENT;
58440266059SGregory Neil Shapiro 			ret = EX_NOUSER;
58540266059SGregory Neil Shapiro 		}
58640266059SGregory Neil Shapiro 		else
58740266059SGregory Neil Shapiro 		{
58840266059SGregory Neil Shapiro 			errno = save_errno;
58940266059SGregory Neil Shapiro 			ret = EX_TEMPFAIL;
59040266059SGregory Neil Shapiro 		}
59140266059SGregory Neil Shapiro 		goto abort;
59240266059SGregory Neil Shapiro 	}
59340266059SGregory Neil Shapiro 
59440266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
59540266059SGregory Neil Shapiro 	/*
59640266059SGregory Neil Shapiro 	**  Reset value to prevent lingering
59740266059SGregory Neil Shapiro 	**  LDAP_DECODING_ERROR due to
59840266059SGregory Neil Shapiro 	**  OpenLDAP 1.X's hack (see below)
59940266059SGregory Neil Shapiro 	*/
60040266059SGregory Neil Shapiro 
60140266059SGregory Neil Shapiro 	LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS;
60240266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
60340266059SGregory Neil Shapiro 
60440266059SGregory Neil Shapiro 	ret = EX_OK;
60540266059SGregory Neil Shapiro 	need = NEED_FULLNAME|NEED_HOMEDIR|NEED_SHELL|NEED_UID|NEED_GID;
60640266059SGregory Neil Shapiro 	for (attr = ldap_first_attribute(LDAPLMAP.ldap_ld, entry, &ber);
60740266059SGregory Neil Shapiro 	     attr != NULL;
60840266059SGregory Neil Shapiro 	     attr = ldap_next_attribute(LDAPLMAP.ldap_ld, entry, ber))
60940266059SGregory Neil Shapiro 	{
61040266059SGregory Neil Shapiro 		char **vals;
61140266059SGregory Neil Shapiro 
61240266059SGregory Neil Shapiro 		vals = ldap_get_values(LDAPLMAP.ldap_ld, entry, attr);
61340266059SGregory Neil Shapiro 		if (vals == NULL)
61440266059SGregory Neil Shapiro 		{
61540266059SGregory Neil Shapiro 			errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld);
61640266059SGregory Neil Shapiro 			if (errno == LDAP_SUCCESS)
61740266059SGregory Neil Shapiro 			{
61840266059SGregory Neil Shapiro 				ldap_memfree(attr);
61940266059SGregory Neil Shapiro 				continue;
62040266059SGregory Neil Shapiro 			}
62140266059SGregory Neil Shapiro 
62240266059SGregory Neil Shapiro 			/* Must be an error */
62340266059SGregory Neil Shapiro 			errno += E_LDAPBASE;
62440266059SGregory Neil Shapiro 			ret = EX_TEMPFAIL;
62540266059SGregory Neil Shapiro 			goto abort;
62640266059SGregory Neil Shapiro 		}
62740266059SGregory Neil Shapiro 
62840266059SGregory Neil Shapiro # if !defined(LDAP_VERSION_MAX) && !defined(LDAP_OPT_SIZELIMIT)
62940266059SGregory Neil Shapiro 		/*
63040266059SGregory Neil Shapiro 		**  Reset value to prevent lingering
63140266059SGregory Neil Shapiro 		**  LDAP_DECODING_ERROR due to
63240266059SGregory Neil Shapiro 		**  OpenLDAP 1.X's hack (see below)
63340266059SGregory Neil Shapiro 		*/
63440266059SGregory Neil Shapiro 
63540266059SGregory Neil Shapiro 		LDAPLMAP.ldap_ld->ld_errno = LDAP_SUCCESS;
63640266059SGregory Neil Shapiro # endif /* !defined(LDAP_VERSION_MAX) !defined(LDAP_OPT_SIZELIMIT) */
63740266059SGregory Neil Shapiro 
63840266059SGregory Neil Shapiro 		if (vals[0] == NULL || vals[0][0] == '\0')
63940266059SGregory Neil Shapiro 			goto skip;
64040266059SGregory Neil Shapiro 
64140266059SGregory Neil Shapiro 		if (strcasecmp(attr, "gecos") == 0)
64240266059SGregory Neil Shapiro 		{
64340266059SGregory Neil Shapiro 			if (!bitset(NEED_FULLNAME, need) ||
64440266059SGregory Neil Shapiro 			    strlen(vals[0]) >= sizeof(user->mbdb_fullname))
64540266059SGregory Neil Shapiro 				goto skip;
64640266059SGregory Neil Shapiro 
64740266059SGregory Neil Shapiro 			sm_pwfullname(vals[0], name, user->mbdb_fullname,
64840266059SGregory Neil Shapiro 				      sizeof(user->mbdb_fullname));
64940266059SGregory Neil Shapiro 			need &= ~NEED_FULLNAME;
65040266059SGregory Neil Shapiro 		}
65140266059SGregory Neil Shapiro 		else if (strcasecmp(attr, "homeDirectory") == 0)
65240266059SGregory Neil Shapiro 		{
65340266059SGregory Neil Shapiro 			if (!bitset(NEED_HOMEDIR, need) ||
65440266059SGregory Neil Shapiro 			    strlen(vals[0]) >= sizeof(user->mbdb_homedir))
65540266059SGregory Neil Shapiro 				goto skip;
65640266059SGregory Neil Shapiro 
65740266059SGregory Neil Shapiro 			(void) sm_strlcpy(user->mbdb_homedir, vals[0],
65840266059SGregory Neil Shapiro 					  sizeof(user->mbdb_homedir));
65940266059SGregory Neil Shapiro 			need &= ~NEED_HOMEDIR;
66040266059SGregory Neil Shapiro 		}
66140266059SGregory Neil Shapiro 		else if (strcasecmp(attr, "loginShell") == 0)
66240266059SGregory Neil Shapiro 		{
66340266059SGregory Neil Shapiro 			if (!bitset(NEED_SHELL, need) ||
66440266059SGregory Neil Shapiro 			    strlen(vals[0]) >= sizeof(user->mbdb_shell))
66540266059SGregory Neil Shapiro 				goto skip;
66640266059SGregory Neil Shapiro 
66740266059SGregory Neil Shapiro 			(void) sm_strlcpy(user->mbdb_shell, vals[0],
66840266059SGregory Neil Shapiro 					  sizeof(user->mbdb_shell));
66940266059SGregory Neil Shapiro 			need &= ~NEED_SHELL;
67040266059SGregory Neil Shapiro 		}
67140266059SGregory Neil Shapiro 		else if (strcasecmp(attr, "uidNumber") == 0)
67240266059SGregory Neil Shapiro 		{
67340266059SGregory Neil Shapiro 			char *p;
67440266059SGregory Neil Shapiro 
67540266059SGregory Neil Shapiro 			if (!bitset(NEED_UID, need))
67640266059SGregory Neil Shapiro 				goto skip;
67740266059SGregory Neil Shapiro 
67840266059SGregory Neil Shapiro 			for (p = vals[0]; *p != '\0'; p++)
67940266059SGregory Neil Shapiro 			{
68040266059SGregory Neil Shapiro 				/* allow negative numbers */
68140266059SGregory Neil Shapiro 				if (p == vals[0] && *p == '-')
68240266059SGregory Neil Shapiro 				{
68340266059SGregory Neil Shapiro 					/* but not simply '-' */
68440266059SGregory Neil Shapiro 					if (*(p + 1) == '\0')
68540266059SGregory Neil Shapiro 						goto skip;
68640266059SGregory Neil Shapiro 				}
68740266059SGregory Neil Shapiro 				else if (!isascii(*p) || !isdigit(*p))
68840266059SGregory Neil Shapiro 					goto skip;
68940266059SGregory Neil Shapiro 			}
69040266059SGregory Neil Shapiro 			user->mbdb_uid = atoi(vals[0]);
69140266059SGregory Neil Shapiro 			need &= ~NEED_UID;
69240266059SGregory Neil Shapiro 		}
69340266059SGregory Neil Shapiro 		else if (strcasecmp(attr, "gidNumber") == 0)
69440266059SGregory Neil Shapiro 		{
69540266059SGregory Neil Shapiro 			char *p;
69640266059SGregory Neil Shapiro 
69740266059SGregory Neil Shapiro 			if (!bitset(NEED_GID, need))
69840266059SGregory Neil Shapiro 				goto skip;
69940266059SGregory Neil Shapiro 
70040266059SGregory Neil Shapiro 			for (p = vals[0]; *p != '\0'; p++)
70140266059SGregory Neil Shapiro 			{
70240266059SGregory Neil Shapiro 				/* allow negative numbers */
70340266059SGregory Neil Shapiro 				if (p == vals[0] && *p == '-')
70440266059SGregory Neil Shapiro 				{
70540266059SGregory Neil Shapiro 					/* but not simply '-' */
70640266059SGregory Neil Shapiro 					if (*(p + 1) == '\0')
70740266059SGregory Neil Shapiro 						goto skip;
70840266059SGregory Neil Shapiro 				}
70940266059SGregory Neil Shapiro 				else if (!isascii(*p) || !isdigit(*p))
71040266059SGregory Neil Shapiro 					goto skip;
71140266059SGregory Neil Shapiro 			}
71240266059SGregory Neil Shapiro 			user->mbdb_gid = atoi(vals[0]);
71340266059SGregory Neil Shapiro 			need &= ~NEED_GID;
71440266059SGregory Neil Shapiro 		}
71540266059SGregory Neil Shapiro 
71640266059SGregory Neil Shapiro skip:
71740266059SGregory Neil Shapiro 		ldap_value_free(vals);
71840266059SGregory Neil Shapiro 		ldap_memfree(attr);
71940266059SGregory Neil Shapiro 	}
72040266059SGregory Neil Shapiro 
72140266059SGregory Neil Shapiro 	errno = sm_ldap_geterrno(LDAPLMAP.ldap_ld);
72240266059SGregory Neil Shapiro 
72340266059SGregory Neil Shapiro 	/*
72440266059SGregory Neil Shapiro 	**  We check errno != LDAP_DECODING_ERROR since
72540266059SGregory Neil Shapiro 	**  OpenLDAP 1.X has a very ugly *undocumented*
72640266059SGregory Neil Shapiro 	**  hack of returning this error code from
72740266059SGregory Neil Shapiro 	**  ldap_next_attribute() if the library freed the
72840266059SGregory Neil Shapiro 	**  ber attribute.  See:
72940266059SGregory Neil Shapiro 	**  http://www.openldap.org/lists/openldap-devel/9901/msg00064.html
73040266059SGregory Neil Shapiro 	*/
73140266059SGregory Neil Shapiro 
73240266059SGregory Neil Shapiro 	if (errno != LDAP_SUCCESS &&
73340266059SGregory Neil Shapiro 	    errno != LDAP_DECODING_ERROR)
73440266059SGregory Neil Shapiro 	{
73540266059SGregory Neil Shapiro 		/* Must be an error */
73640266059SGregory Neil Shapiro 		errno += E_LDAPBASE;
73740266059SGregory Neil Shapiro 		ret = EX_TEMPFAIL;
73840266059SGregory Neil Shapiro 		goto abort;
73940266059SGregory Neil Shapiro 	}
74040266059SGregory Neil Shapiro 
74140266059SGregory Neil Shapiro  abort:
74240266059SGregory Neil Shapiro 	save_errno = errno;
74340266059SGregory Neil Shapiro 	if (attr != NULL)
74440266059SGregory Neil Shapiro 	{
74540266059SGregory Neil Shapiro 		ldap_memfree(attr);
74640266059SGregory Neil Shapiro 		attr = NULL;
74740266059SGregory Neil Shapiro 	}
74840266059SGregory Neil Shapiro 	if (LDAPLMAP.ldap_res != NULL)
74940266059SGregory Neil Shapiro 	{
75040266059SGregory Neil Shapiro 		ldap_msgfree(LDAPLMAP.ldap_res);
75140266059SGregory Neil Shapiro 		LDAPLMAP.ldap_res = NULL;
75240266059SGregory Neil Shapiro 	}
75340266059SGregory Neil Shapiro 	if (ret == EX_OK)
75440266059SGregory Neil Shapiro 	{
75540266059SGregory Neil Shapiro 		if (need == 0)
75640266059SGregory Neil Shapiro 		{
75740266059SGregory Neil Shapiro 			(void) sm_strlcpy(user->mbdb_name, name,
75840266059SGregory Neil Shapiro 					  sizeof(user->mbdb_name));
75940266059SGregory Neil Shapiro 			save_errno = 0;
76040266059SGregory Neil Shapiro 		}
76140266059SGregory Neil Shapiro 		else
76240266059SGregory Neil Shapiro 		{
76340266059SGregory Neil Shapiro 			ret = EX_NOUSER;
76440266059SGregory Neil Shapiro 			save_errno = EINVAL;
76540266059SGregory Neil Shapiro 		}
76640266059SGregory Neil Shapiro 	}
76740266059SGregory Neil Shapiro 	errno = save_errno;
76840266059SGregory Neil Shapiro 	return ret;
76940266059SGregory Neil Shapiro }
77040266059SGregory Neil Shapiro 
77140266059SGregory Neil Shapiro /*
77240266059SGregory Neil Shapiro **  MBDB_LDAP_TERMINATE -- terminate connection to the mailbox database
77340266059SGregory Neil Shapiro **
77440266059SGregory Neil Shapiro **	Parameters:
77540266059SGregory Neil Shapiro **		none.
77640266059SGregory Neil Shapiro **
77740266059SGregory Neil Shapiro **	Results:
77840266059SGregory Neil Shapiro **		none.
77940266059SGregory Neil Shapiro */
78040266059SGregory Neil Shapiro 
78140266059SGregory Neil Shapiro static void
78240266059SGregory Neil Shapiro mbdb_ldap_terminate()
78340266059SGregory Neil Shapiro {
78440266059SGregory Neil Shapiro 	sm_ldap_close(&LDAPLMAP);
78540266059SGregory Neil Shapiro }
78640266059SGregory Neil Shapiro # endif /* _LDAP_EXAMPLE_ */
78740266059SGregory Neil Shapiro #endif /* LDAPMAP */
788