source: trunk/third/sendmail/libsm/mbdb.c @ 19204

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