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