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