17c478bd9Sstevel@tonic-gate /*
2*058561cbSjbeck * Copyright (c) 1998-2003, 2006 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate * All rights reserved.
47c478bd9Sstevel@tonic-gate * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
57c478bd9Sstevel@tonic-gate * Copyright (c) 1988, 1993
67c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set
97c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of
107c478bd9Sstevel@tonic-gate * the sendmail distribution.
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate */
137c478bd9Sstevel@tonic-gate
147c478bd9Sstevel@tonic-gate #include <sendmail.h>
15*058561cbSjbeck #include "map.h"
167c478bd9Sstevel@tonic-gate
177c478bd9Sstevel@tonic-gate #if USERDB
18*058561cbSjbeck SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (with USERDB)")
197c478bd9Sstevel@tonic-gate #else /* USERDB */
20*058561cbSjbeck SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (without USERDB)")
217c478bd9Sstevel@tonic-gate #endif /* USERDB */
227c478bd9Sstevel@tonic-gate
237c478bd9Sstevel@tonic-gate #if USERDB
247c478bd9Sstevel@tonic-gate
25*058561cbSjbeck #include <sm/sendmail.h>
267c478bd9Sstevel@tonic-gate # if NEWDB
277c478bd9Sstevel@tonic-gate # include "sm/bdb.h"
287c478bd9Sstevel@tonic-gate # else /* NEWDB */
297c478bd9Sstevel@tonic-gate # define DBT struct _data_base_thang_
307c478bd9Sstevel@tonic-gate DBT
317c478bd9Sstevel@tonic-gate {
327c478bd9Sstevel@tonic-gate void *data; /* pointer to data */
337c478bd9Sstevel@tonic-gate size_t size; /* length of data */
347c478bd9Sstevel@tonic-gate };
357c478bd9Sstevel@tonic-gate # endif /* NEWDB */
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate ** UDB.C -- interface between sendmail and Berkeley User Data Base.
397c478bd9Sstevel@tonic-gate **
407c478bd9Sstevel@tonic-gate ** This depends on the 4.4BSD db package.
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate struct udbent
457c478bd9Sstevel@tonic-gate {
467c478bd9Sstevel@tonic-gate char *udb_spec; /* string version of spec */
477c478bd9Sstevel@tonic-gate int udb_type; /* type of entry */
487c478bd9Sstevel@tonic-gate pid_t udb_pid; /* PID of process which opened db */
497c478bd9Sstevel@tonic-gate char *udb_default; /* default host for outgoing mail */
507c478bd9Sstevel@tonic-gate union
517c478bd9Sstevel@tonic-gate {
527c478bd9Sstevel@tonic-gate # if NETINET || NETINET6
537c478bd9Sstevel@tonic-gate /* type UE_REMOTE -- do remote call for lookup */
547c478bd9Sstevel@tonic-gate struct
557c478bd9Sstevel@tonic-gate {
567c478bd9Sstevel@tonic-gate SOCKADDR _udb_addr; /* address */
577c478bd9Sstevel@tonic-gate int _udb_timeout; /* timeout */
587c478bd9Sstevel@tonic-gate } udb_remote;
597c478bd9Sstevel@tonic-gate # define udb_addr udb_u.udb_remote._udb_addr
607c478bd9Sstevel@tonic-gate # define udb_timeout udb_u.udb_remote._udb_timeout
617c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate /* type UE_FORWARD -- forward message to remote */
647c478bd9Sstevel@tonic-gate struct
657c478bd9Sstevel@tonic-gate {
667c478bd9Sstevel@tonic-gate char *_udb_fwdhost; /* name of forward host */
677c478bd9Sstevel@tonic-gate } udb_forward;
687c478bd9Sstevel@tonic-gate # define udb_fwdhost udb_u.udb_forward._udb_fwdhost
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate # if NEWDB
717c478bd9Sstevel@tonic-gate /* type UE_FETCH -- lookup in local database */
727c478bd9Sstevel@tonic-gate struct
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate char *_udb_dbname; /* pathname of database */
757c478bd9Sstevel@tonic-gate DB *_udb_dbp; /* open database ptr */
767c478bd9Sstevel@tonic-gate } udb_lookup;
777c478bd9Sstevel@tonic-gate # define udb_dbname udb_u.udb_lookup._udb_dbname
787c478bd9Sstevel@tonic-gate # define udb_dbp udb_u.udb_lookup._udb_dbp
797c478bd9Sstevel@tonic-gate # endif /* NEWDB */
807c478bd9Sstevel@tonic-gate } udb_u;
817c478bd9Sstevel@tonic-gate };
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate # define UDB_EOLIST 0 /* end of list */
847c478bd9Sstevel@tonic-gate # define UDB_SKIP 1 /* skip this entry */
857c478bd9Sstevel@tonic-gate # define UDB_REMOTE 2 /* look up in remote database */
867c478bd9Sstevel@tonic-gate # define UDB_DBFETCH 3 /* look up in local database */
877c478bd9Sstevel@tonic-gate # define UDB_FORWARD 4 /* forward to remote host */
887c478bd9Sstevel@tonic-gate # define UDB_HESIOD 5 /* look up via hesiod */
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate # define MAXUDBENT 10 /* maximum number of UDB entries */
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate struct udb_option
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate char *udbo_name;
967c478bd9Sstevel@tonic-gate char *udbo_val;
977c478bd9Sstevel@tonic-gate };
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate # if HESIOD
1007c478bd9Sstevel@tonic-gate static int hes_udb_get __P((DBT *, DBT *));
1017c478bd9Sstevel@tonic-gate # endif /* HESIOD */
1027c478bd9Sstevel@tonic-gate static char *udbmatch __P((char *, char *, SM_RPOOL_T *));
1037c478bd9Sstevel@tonic-gate static int _udbx_init __P((ENVELOPE *));
1047c478bd9Sstevel@tonic-gate static int _udb_parsespec __P((char *, struct udb_option [], int));
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate ** UDBEXPAND -- look up user in database and expand
1087c478bd9Sstevel@tonic-gate **
1097c478bd9Sstevel@tonic-gate ** Parameters:
1107c478bd9Sstevel@tonic-gate ** a -- address to expand.
1117c478bd9Sstevel@tonic-gate ** sendq -- pointer to head of sendq to put the expansions in.
1127c478bd9Sstevel@tonic-gate ** aliaslevel -- the current alias nesting depth.
1137c478bd9Sstevel@tonic-gate ** e -- the current envelope.
1147c478bd9Sstevel@tonic-gate **
1157c478bd9Sstevel@tonic-gate ** Returns:
1167c478bd9Sstevel@tonic-gate ** EX_TEMPFAIL -- if something "odd" happened -- probably due
1177c478bd9Sstevel@tonic-gate ** to accessing a file on an NFS server that is down.
1187c478bd9Sstevel@tonic-gate ** EX_OK -- otherwise.
1197c478bd9Sstevel@tonic-gate **
1207c478bd9Sstevel@tonic-gate ** Side Effects:
1217c478bd9Sstevel@tonic-gate ** Modifies sendq.
1227c478bd9Sstevel@tonic-gate */
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate static struct udbent UdbEnts[MAXUDBENT + 1];
1257c478bd9Sstevel@tonic-gate static bool UdbInitialized = false;
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate int
udbexpand(a,sendq,aliaslevel,e)1287c478bd9Sstevel@tonic-gate udbexpand(a, sendq, aliaslevel, e)
1297c478bd9Sstevel@tonic-gate register ADDRESS *a;
1307c478bd9Sstevel@tonic-gate ADDRESS **sendq;
1317c478bd9Sstevel@tonic-gate int aliaslevel;
1327c478bd9Sstevel@tonic-gate register ENVELOPE *e;
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate int i;
1357c478bd9Sstevel@tonic-gate DBT key;
1367c478bd9Sstevel@tonic-gate DBT info;
1377c478bd9Sstevel@tonic-gate bool breakout;
1387c478bd9Sstevel@tonic-gate register struct udbent *up;
1397c478bd9Sstevel@tonic-gate int keylen;
1407c478bd9Sstevel@tonic-gate int naddrs;
1417c478bd9Sstevel@tonic-gate char *user;
14249218d4fSjbeck char keybuf[MAXUDBKEY];
1437c478bd9Sstevel@tonic-gate
144*058561cbSjbeck memset(&key, '\0', sizeof(key));
145*058561cbSjbeck memset(&info, '\0', sizeof(info));
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate if (tTd(28, 1))
1487c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand(%s)\n", a->q_paddr);
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate /* make certain we are supposed to send to this address */
1517c478bd9Sstevel@tonic-gate if (!QS_IS_SENDABLE(a->q_state))
1527c478bd9Sstevel@tonic-gate return EX_OK;
1537c478bd9Sstevel@tonic-gate e->e_to = a->q_paddr;
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate /* on first call, locate the database */
1567c478bd9Sstevel@tonic-gate if (!UdbInitialized)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate if (_udbx_init(e) == EX_TEMPFAIL)
1597c478bd9Sstevel@tonic-gate return EX_TEMPFAIL;
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate /* short circuit the process if no chance of a match */
1637c478bd9Sstevel@tonic-gate if (UdbSpec == NULL || UdbSpec[0] == '\0')
1647c478bd9Sstevel@tonic-gate return EX_OK;
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate /* extract user to do userdb matching on */
1677c478bd9Sstevel@tonic-gate user = a->q_user;
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate /* short circuit name begins with '\\' since it can't possibly match */
1707c478bd9Sstevel@tonic-gate /* (might want to treat this as unquoted instead) */
1717c478bd9Sstevel@tonic-gate if (user[0] == '\\')
1727c478bd9Sstevel@tonic-gate return EX_OK;
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate /* if name begins with a colon, it indicates our metadata */
1757c478bd9Sstevel@tonic-gate if (user[0] == ':')
1767c478bd9Sstevel@tonic-gate return EX_OK;
1777c478bd9Sstevel@tonic-gate
178*058561cbSjbeck keylen = sm_strlcpyn(keybuf, sizeof(keybuf), 2, user, ":maildrop");
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /* if name is too long, assume it won't match */
181*058561cbSjbeck if (keylen >= sizeof(keybuf))
1827c478bd9Sstevel@tonic-gate return EX_OK;
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate /* build actual database key */
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate breakout = false;
1877c478bd9Sstevel@tonic-gate for (up = UdbEnts; !breakout; up++)
1887c478bd9Sstevel@tonic-gate {
1897c478bd9Sstevel@tonic-gate int usersize;
1907c478bd9Sstevel@tonic-gate int userleft;
1917c478bd9Sstevel@tonic-gate char userbuf[MEMCHUNKSIZE];
1927c478bd9Sstevel@tonic-gate # if HESIOD && HES_GETMAILHOST
1937c478bd9Sstevel@tonic-gate char pobuf[MAXNAME];
1947c478bd9Sstevel@tonic-gate # endif /* HESIOD && HES_GETMAILHOST */
1957c478bd9Sstevel@tonic-gate # if defined(NEWDB) && DB_VERSION_MAJOR > 1
1967c478bd9Sstevel@tonic-gate DBC *dbc = NULL;
1977c478bd9Sstevel@tonic-gate # endif /* defined(NEWDB) && DB_VERSION_MAJOR > 1 */
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate user = userbuf;
2007c478bd9Sstevel@tonic-gate userbuf[0] = '\0';
201*058561cbSjbeck usersize = sizeof(userbuf);
202*058561cbSjbeck userleft = sizeof(userbuf) - 1;
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate /*
2057c478bd9Sstevel@tonic-gate ** Select action based on entry type.
2067c478bd9Sstevel@tonic-gate **
2077c478bd9Sstevel@tonic-gate ** On dropping out of this switch, "class" should
2087c478bd9Sstevel@tonic-gate ** explain the type of the data, and "user" should
2097c478bd9Sstevel@tonic-gate ** contain the user information.
2107c478bd9Sstevel@tonic-gate */
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate switch (up->udb_type)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate # if NEWDB
2157c478bd9Sstevel@tonic-gate case UDB_DBFETCH:
2167c478bd9Sstevel@tonic-gate key.data = keybuf;
2177c478bd9Sstevel@tonic-gate key.size = keylen;
2187c478bd9Sstevel@tonic-gate if (tTd(28, 80))
2197c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand: trying %s (%d) via db\n",
2207c478bd9Sstevel@tonic-gate keybuf, keylen);
2217c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
2227c478bd9Sstevel@tonic-gate i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR);
2237c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
2247c478bd9Sstevel@tonic-gate i = 0;
2257c478bd9Sstevel@tonic-gate if (dbc == NULL &&
2267c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
2277c478bd9Sstevel@tonic-gate (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
2287c478bd9Sstevel@tonic-gate NULL, &dbc, 0)) != 0)
2297c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
2307c478bd9Sstevel@tonic-gate (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
2317c478bd9Sstevel@tonic-gate NULL, &dbc)) != 0)
2327c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
2337c478bd9Sstevel@tonic-gate i = -1;
2347c478bd9Sstevel@tonic-gate if (i != 0 || dbc == NULL ||
2357c478bd9Sstevel@tonic-gate (errno = dbc->c_get(dbc, &key,
2367c478bd9Sstevel@tonic-gate &info, DB_SET)) != 0)
2377c478bd9Sstevel@tonic-gate i = 1;
2387c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
2397c478bd9Sstevel@tonic-gate if (i > 0 || info.size <= 0)
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate if (tTd(28, 2))
2427c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand: no match on %s (%d)\n",
2437c478bd9Sstevel@tonic-gate keybuf, keylen);
2447c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 1
2457c478bd9Sstevel@tonic-gate if (dbc != NULL)
2467c478bd9Sstevel@tonic-gate {
2477c478bd9Sstevel@tonic-gate (void) dbc->c_close(dbc);
2487c478bd9Sstevel@tonic-gate dbc = NULL;
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 1 */
2517c478bd9Sstevel@tonic-gate break;
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate if (tTd(28, 80))
2547c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand: match %.*s: %.*s\n",
2557c478bd9Sstevel@tonic-gate (int) key.size, (char *) key.data,
2567c478bd9Sstevel@tonic-gate (int) info.size, (char *) info.data);
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate a->q_flags &= ~QSELFREF;
2597c478bd9Sstevel@tonic-gate while (i == 0 && key.size == keylen &&
2607c478bd9Sstevel@tonic-gate memcmp(key.data, keybuf, keylen) == 0)
2617c478bd9Sstevel@tonic-gate {
2627c478bd9Sstevel@tonic-gate char *p;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate if (bitset(EF_VRFYONLY, e->e_flags))
2657c478bd9Sstevel@tonic-gate {
2667c478bd9Sstevel@tonic-gate a->q_state = QS_VERIFIED;
2677c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 1
2687c478bd9Sstevel@tonic-gate if (dbc != NULL)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate (void) dbc->c_close(dbc);
2717c478bd9Sstevel@tonic-gate dbc = NULL;
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 1 */
2747c478bd9Sstevel@tonic-gate return EX_OK;
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate breakout = true;
2787c478bd9Sstevel@tonic-gate if (info.size >= userleft - 1)
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate char *nuser;
2817c478bd9Sstevel@tonic-gate int size = MEMCHUNKSIZE;
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate if (info.size > MEMCHUNKSIZE)
2847c478bd9Sstevel@tonic-gate size = info.size;
2857c478bd9Sstevel@tonic-gate nuser = sm_malloc_x(usersize + size);
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate memmove(nuser, user, usersize);
2887c478bd9Sstevel@tonic-gate if (user != userbuf)
2897c478bd9Sstevel@tonic-gate sm_free(user); /* XXX */
2907c478bd9Sstevel@tonic-gate user = nuser;
2917c478bd9Sstevel@tonic-gate usersize += size;
2927c478bd9Sstevel@tonic-gate userleft += size;
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate p = &user[strlen(user)];
2957c478bd9Sstevel@tonic-gate if (p != user)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate *p++ = ',';
2987c478bd9Sstevel@tonic-gate userleft--;
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate memmove(p, info.data, info.size);
3017c478bd9Sstevel@tonic-gate p[info.size] = '\0';
3027c478bd9Sstevel@tonic-gate userleft -= info.size;
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate /* get the next record */
3057c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
3067c478bd9Sstevel@tonic-gate i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT);
3077c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
3087c478bd9Sstevel@tonic-gate i = 0;
3097c478bd9Sstevel@tonic-gate if ((errno = dbc->c_get(dbc, &key,
3107c478bd9Sstevel@tonic-gate &info, DB_NEXT)) != 0)
3117c478bd9Sstevel@tonic-gate i = 1;
3127c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 1
3167c478bd9Sstevel@tonic-gate if (dbc != NULL)
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate (void) dbc->c_close(dbc);
3197c478bd9Sstevel@tonic-gate dbc = NULL;
3207c478bd9Sstevel@tonic-gate }
3217c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 1 */
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate /* if nothing ever matched, try next database */
3247c478bd9Sstevel@tonic-gate if (!breakout)
3257c478bd9Sstevel@tonic-gate break;
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate message("expanded to %s", user);
3287c478bd9Sstevel@tonic-gate if (LogLevel > 10)
3297c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id,
3307c478bd9Sstevel@tonic-gate "expand %.100s => %s",
3317c478bd9Sstevel@tonic-gate e->e_to,
3327c478bd9Sstevel@tonic-gate shortenstring(user, MAXSHORTSTR));
3337c478bd9Sstevel@tonic-gate naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
3347c478bd9Sstevel@tonic-gate if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
3357c478bd9Sstevel@tonic-gate {
3367c478bd9Sstevel@tonic-gate if (tTd(28, 5))
3377c478bd9Sstevel@tonic-gate {
3387c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand: QS_EXPANDED ");
3397c478bd9Sstevel@tonic-gate printaddr(sm_debug_file(), a, false);
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate a->q_state = QS_EXPANDED;
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate if (i < 0)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate syserr("udbexpand: db-get %.*s stat %d",
3467c478bd9Sstevel@tonic-gate (int) key.size, (char *) key.data, i);
3477c478bd9Sstevel@tonic-gate return EX_TEMPFAIL;
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate /*
3517c478bd9Sstevel@tonic-gate ** If this address has a -request address, reflect
3527c478bd9Sstevel@tonic-gate ** it into the envelope.
3537c478bd9Sstevel@tonic-gate */
3547c478bd9Sstevel@tonic-gate
355*058561cbSjbeck memset(&key, '\0', sizeof(key));
356*058561cbSjbeck memset(&info, '\0', sizeof(info));
357*058561cbSjbeck (void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, a->q_user,
3587c478bd9Sstevel@tonic-gate ":mailsender");
3597c478bd9Sstevel@tonic-gate keylen = strlen(keybuf);
3607c478bd9Sstevel@tonic-gate key.data = keybuf;
3617c478bd9Sstevel@tonic-gate key.size = keylen;
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
3647c478bd9Sstevel@tonic-gate i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
3657c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
3667c478bd9Sstevel@tonic-gate i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
3677c478bd9Sstevel@tonic-gate &key, &info, 0);
3687c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
3697c478bd9Sstevel@tonic-gate if (i != 0 || info.size <= 0)
3707c478bd9Sstevel@tonic-gate break;
3717c478bd9Sstevel@tonic-gate a->q_owner = sm_rpool_malloc_x(e->e_rpool,
3727c478bd9Sstevel@tonic-gate info.size + 1);
3737c478bd9Sstevel@tonic-gate memmove(a->q_owner, info.data, info.size);
3747c478bd9Sstevel@tonic-gate a->q_owner[info.size] = '\0';
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate /* announce delivery; NORECEIPT bit set later */
3777c478bd9Sstevel@tonic-gate if (e->e_xfp != NULL)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
3807c478bd9Sstevel@tonic-gate "Message delivered to mailing list %s\n",
3817c478bd9Sstevel@tonic-gate a->q_paddr);
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate e->e_flags |= EF_SENDRECEIPT;
3847c478bd9Sstevel@tonic-gate a->q_flags |= QDELIVERED|QEXPANDED;
3857c478bd9Sstevel@tonic-gate break;
3867c478bd9Sstevel@tonic-gate # endif /* NEWDB */
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate # if HESIOD
3897c478bd9Sstevel@tonic-gate case UDB_HESIOD:
3907c478bd9Sstevel@tonic-gate key.data = keybuf;
3917c478bd9Sstevel@tonic-gate key.size = keylen;
3927c478bd9Sstevel@tonic-gate if (tTd(28, 80))
3937c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand: trying %s (%d) via hesiod\n",
3947c478bd9Sstevel@tonic-gate keybuf, keylen);
3957c478bd9Sstevel@tonic-gate /* look up the key via hesiod */
3967c478bd9Sstevel@tonic-gate i = hes_udb_get(&key, &info);
3977c478bd9Sstevel@tonic-gate if (i < 0)
3987c478bd9Sstevel@tonic-gate {
3997c478bd9Sstevel@tonic-gate syserr("udbexpand: hesiod-get %.*s stat %d",
4007c478bd9Sstevel@tonic-gate (int) key.size, (char *) key.data, i);
4017c478bd9Sstevel@tonic-gate return EX_TEMPFAIL;
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate else if (i > 0 || info.size <= 0)
4047c478bd9Sstevel@tonic-gate {
4057c478bd9Sstevel@tonic-gate # if HES_GETMAILHOST
4067c478bd9Sstevel@tonic-gate struct hes_postoffice *hp;
4077c478bd9Sstevel@tonic-gate # endif /* HES_GETMAILHOST */
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate if (tTd(28, 2))
4107c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand: no match on %s (%d)\n",
4117c478bd9Sstevel@tonic-gate (char *) keybuf, (int) keylen);
4127c478bd9Sstevel@tonic-gate # if HES_GETMAILHOST
4137c478bd9Sstevel@tonic-gate if (tTd(28, 8))
4147c478bd9Sstevel@tonic-gate sm_dprintf(" ... trying hes_getmailhost(%s)\n",
4157c478bd9Sstevel@tonic-gate a->q_user);
4167c478bd9Sstevel@tonic-gate hp = hes_getmailhost(a->q_user);
4177c478bd9Sstevel@tonic-gate if (hp == NULL)
4187c478bd9Sstevel@tonic-gate {
4197c478bd9Sstevel@tonic-gate if (hes_error() == HES_ER_NET)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate syserr("udbexpand: hesiod-getmail %s stat %d",
4227c478bd9Sstevel@tonic-gate a->q_user, hes_error());
4237c478bd9Sstevel@tonic-gate return EX_TEMPFAIL;
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate if (tTd(28, 2))
4267c478bd9Sstevel@tonic-gate sm_dprintf("hes_getmailhost(%s): %d\n",
4277c478bd9Sstevel@tonic-gate a->q_user, hes_error());
4287c478bd9Sstevel@tonic-gate break;
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate if (strlen(hp->po_name) + strlen(hp->po_host) >
431*058561cbSjbeck sizeof(pobuf) - 2)
4327c478bd9Sstevel@tonic-gate {
4337c478bd9Sstevel@tonic-gate if (tTd(28, 2))
4347c478bd9Sstevel@tonic-gate sm_dprintf("hes_getmailhost(%s): expansion too long: %.30s@%.30s\n",
4357c478bd9Sstevel@tonic-gate a->q_user,
4367c478bd9Sstevel@tonic-gate hp->po_name,
4377c478bd9Sstevel@tonic-gate hp->po_host);
4387c478bd9Sstevel@tonic-gate break;
4397c478bd9Sstevel@tonic-gate }
4407c478bd9Sstevel@tonic-gate info.data = pobuf;
441*058561cbSjbeck (void) sm_snprintf(pobuf, sizeof(pobuf),
4427c478bd9Sstevel@tonic-gate "%s@%s", hp->po_name, hp->po_host);
4437c478bd9Sstevel@tonic-gate info.size = strlen(info.data);
4447c478bd9Sstevel@tonic-gate # else /* HES_GETMAILHOST */
4457c478bd9Sstevel@tonic-gate break;
4467c478bd9Sstevel@tonic-gate # endif /* HES_GETMAILHOST */
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate if (tTd(28, 80))
4497c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand: match %.*s: %.*s\n",
4507c478bd9Sstevel@tonic-gate (int) key.size, (char *) key.data,
4517c478bd9Sstevel@tonic-gate (int) info.size, (char *) info.data);
4527c478bd9Sstevel@tonic-gate a->q_flags &= ~QSELFREF;
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate if (bitset(EF_VRFYONLY, e->e_flags))
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate a->q_state = QS_VERIFIED;
4577c478bd9Sstevel@tonic-gate return EX_OK;
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate breakout = true;
4617c478bd9Sstevel@tonic-gate if (info.size >= usersize)
4627c478bd9Sstevel@tonic-gate user = sm_malloc_x(info.size + 1);
4637c478bd9Sstevel@tonic-gate memmove(user, info.data, info.size);
4647c478bd9Sstevel@tonic-gate user[info.size] = '\0';
4657c478bd9Sstevel@tonic-gate
4667c478bd9Sstevel@tonic-gate message("hesioded to %s", user);
4677c478bd9Sstevel@tonic-gate if (LogLevel > 10)
4687c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id,
4697c478bd9Sstevel@tonic-gate "hesiod %.100s => %s",
4707c478bd9Sstevel@tonic-gate e->e_to,
4717c478bd9Sstevel@tonic-gate shortenstring(user, MAXSHORTSTR));
4727c478bd9Sstevel@tonic-gate naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
4737c478bd9Sstevel@tonic-gate
4747c478bd9Sstevel@tonic-gate if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
4757c478bd9Sstevel@tonic-gate {
4767c478bd9Sstevel@tonic-gate if (tTd(28, 5))
4777c478bd9Sstevel@tonic-gate {
4787c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand: QS_EXPANDED ");
4797c478bd9Sstevel@tonic-gate printaddr(sm_debug_file(), a, false);
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate a->q_state = QS_EXPANDED;
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate /*
4857c478bd9Sstevel@tonic-gate ** If this address has a -request address, reflect
4867c478bd9Sstevel@tonic-gate ** it into the envelope.
4877c478bd9Sstevel@tonic-gate */
4887c478bd9Sstevel@tonic-gate
489*058561cbSjbeck (void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, a->q_user,
4907c478bd9Sstevel@tonic-gate ":mailsender");
4917c478bd9Sstevel@tonic-gate keylen = strlen(keybuf);
4927c478bd9Sstevel@tonic-gate key.data = keybuf;
4937c478bd9Sstevel@tonic-gate key.size = keylen;
4947c478bd9Sstevel@tonic-gate i = hes_udb_get(&key, &info);
4957c478bd9Sstevel@tonic-gate if (i != 0 || info.size <= 0)
4967c478bd9Sstevel@tonic-gate break;
4977c478bd9Sstevel@tonic-gate a->q_owner = sm_rpool_malloc_x(e->e_rpool,
4987c478bd9Sstevel@tonic-gate info.size + 1);
4997c478bd9Sstevel@tonic-gate memmove(a->q_owner, info.data, info.size);
5007c478bd9Sstevel@tonic-gate a->q_owner[info.size] = '\0';
5017c478bd9Sstevel@tonic-gate break;
5027c478bd9Sstevel@tonic-gate # endif /* HESIOD */
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate case UDB_REMOTE:
5057c478bd9Sstevel@tonic-gate /* not yet implemented */
5067c478bd9Sstevel@tonic-gate break;
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate case UDB_FORWARD:
5097c478bd9Sstevel@tonic-gate if (bitset(EF_VRFYONLY, e->e_flags))
5107c478bd9Sstevel@tonic-gate {
5117c478bd9Sstevel@tonic-gate a->q_state = QS_VERIFIED;
5127c478bd9Sstevel@tonic-gate return EX_OK;
5137c478bd9Sstevel@tonic-gate }
5147c478bd9Sstevel@tonic-gate i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
5157c478bd9Sstevel@tonic-gate if (i >= usersize)
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate usersize = i + 1;
5187c478bd9Sstevel@tonic-gate user = sm_malloc_x(usersize);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(user, usersize, 3,
5217c478bd9Sstevel@tonic-gate a->q_user, "@", up->udb_fwdhost);
5227c478bd9Sstevel@tonic-gate message("expanded to %s", user);
5237c478bd9Sstevel@tonic-gate a->q_flags &= ~QSELFREF;
5247c478bd9Sstevel@tonic-gate naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
5257c478bd9Sstevel@tonic-gate if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
5267c478bd9Sstevel@tonic-gate {
5277c478bd9Sstevel@tonic-gate if (tTd(28, 5))
5287c478bd9Sstevel@tonic-gate {
5297c478bd9Sstevel@tonic-gate sm_dprintf("udbexpand: QS_EXPANDED ");
5307c478bd9Sstevel@tonic-gate printaddr(sm_debug_file(), a, false);
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate a->q_state = QS_EXPANDED;
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate breakout = true;
5357c478bd9Sstevel@tonic-gate break;
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate case UDB_EOLIST:
5387c478bd9Sstevel@tonic-gate breakout = true;
5397c478bd9Sstevel@tonic-gate break;
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate default:
5427c478bd9Sstevel@tonic-gate /* unknown entry type */
5437c478bd9Sstevel@tonic-gate break;
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate /* XXX if an exception occurs, there is a storage leak */
5467c478bd9Sstevel@tonic-gate if (user != userbuf)
5477c478bd9Sstevel@tonic-gate sm_free(user); /* XXX */
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate return EX_OK;
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate /*
5527c478bd9Sstevel@tonic-gate ** UDBSENDER -- return canonical external name of sender, given local name
5537c478bd9Sstevel@tonic-gate **
5547c478bd9Sstevel@tonic-gate ** Parameters:
5557c478bd9Sstevel@tonic-gate ** sender -- the name of the sender on the local machine.
5567c478bd9Sstevel@tonic-gate ** rpool -- resource pool from which to allocate result
5577c478bd9Sstevel@tonic-gate **
5587c478bd9Sstevel@tonic-gate ** Returns:
5597c478bd9Sstevel@tonic-gate ** The external name for this sender, if derivable from the
5607c478bd9Sstevel@tonic-gate ** database. Storage allocated from rpool.
5617c478bd9Sstevel@tonic-gate ** NULL -- if nothing is changed from the database.
5627c478bd9Sstevel@tonic-gate **
5637c478bd9Sstevel@tonic-gate ** Side Effects:
5647c478bd9Sstevel@tonic-gate ** none.
5657c478bd9Sstevel@tonic-gate */
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate char *
udbsender(sender,rpool)5687c478bd9Sstevel@tonic-gate udbsender(sender, rpool)
5697c478bd9Sstevel@tonic-gate char *sender;
5707c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool;
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate return udbmatch(sender, "mailname", rpool);
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate /*
5757c478bd9Sstevel@tonic-gate ** UDBMATCH -- match user in field, return result of lookup.
5767c478bd9Sstevel@tonic-gate **
5777c478bd9Sstevel@tonic-gate ** Parameters:
5787c478bd9Sstevel@tonic-gate ** user -- the name of the user.
5797c478bd9Sstevel@tonic-gate ** field -- the field to lookup.
5807c478bd9Sstevel@tonic-gate ** rpool -- resource pool from which to allocate result
5817c478bd9Sstevel@tonic-gate **
5827c478bd9Sstevel@tonic-gate ** Returns:
5837c478bd9Sstevel@tonic-gate ** The external name for this sender, if derivable from the
5847c478bd9Sstevel@tonic-gate ** database. Storage allocated from rpool.
5857c478bd9Sstevel@tonic-gate ** NULL -- if nothing is changed from the database.
5867c478bd9Sstevel@tonic-gate **
5877c478bd9Sstevel@tonic-gate ** Side Effects:
5887c478bd9Sstevel@tonic-gate ** none.
5897c478bd9Sstevel@tonic-gate */
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate static char *
udbmatch(user,field,rpool)5927c478bd9Sstevel@tonic-gate udbmatch(user, field, rpool)
5937c478bd9Sstevel@tonic-gate char *user;
5947c478bd9Sstevel@tonic-gate char *field;
5957c478bd9Sstevel@tonic-gate SM_RPOOL_T *rpool;
5967c478bd9Sstevel@tonic-gate {
5977c478bd9Sstevel@tonic-gate register char *p;
5987c478bd9Sstevel@tonic-gate register struct udbent *up;
5997c478bd9Sstevel@tonic-gate int i;
6007c478bd9Sstevel@tonic-gate int keylen;
6017c478bd9Sstevel@tonic-gate DBT key, info;
60249218d4fSjbeck char keybuf[MAXUDBKEY];
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate if (tTd(28, 1))
6057c478bd9Sstevel@tonic-gate sm_dprintf("udbmatch(%s, %s)\n", user, field);
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate if (!UdbInitialized)
6087c478bd9Sstevel@tonic-gate {
6097c478bd9Sstevel@tonic-gate if (_udbx_init(CurEnv) == EX_TEMPFAIL)
6107c478bd9Sstevel@tonic-gate return NULL;
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate
6137c478bd9Sstevel@tonic-gate /* short circuit if no spec */
6147c478bd9Sstevel@tonic-gate if (UdbSpec == NULL || UdbSpec[0] == '\0')
6157c478bd9Sstevel@tonic-gate return NULL;
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate /* short circuit name begins with '\\' since it can't possibly match */
6187c478bd9Sstevel@tonic-gate if (user[0] == '\\')
6197c478bd9Sstevel@tonic-gate return NULL;
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate /* long names can never match and are a pain to deal with */
6227c478bd9Sstevel@tonic-gate i = strlen(field);
623*058561cbSjbeck if (i < sizeof("maildrop"))
624*058561cbSjbeck i = sizeof("maildrop");
625*058561cbSjbeck if ((strlen(user) + i) > sizeof(keybuf) - 4)
6267c478bd9Sstevel@tonic-gate return NULL;
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate /* names beginning with colons indicate metadata */
6297c478bd9Sstevel@tonic-gate if (user[0] == ':')
6307c478bd9Sstevel@tonic-gate return NULL;
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate /* build database key */
633*058561cbSjbeck (void) sm_strlcpyn(keybuf, sizeof(keybuf), 3, user, ":", field);
6347c478bd9Sstevel@tonic-gate keylen = strlen(keybuf);
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
6377c478bd9Sstevel@tonic-gate {
6387c478bd9Sstevel@tonic-gate /*
6397c478bd9Sstevel@tonic-gate ** Select action based on entry type.
6407c478bd9Sstevel@tonic-gate */
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate switch (up->udb_type)
6437c478bd9Sstevel@tonic-gate {
6447c478bd9Sstevel@tonic-gate # if NEWDB
6457c478bd9Sstevel@tonic-gate case UDB_DBFETCH:
646*058561cbSjbeck memset(&key, '\0', sizeof(key));
647*058561cbSjbeck memset(&info, '\0', sizeof(info));
6487c478bd9Sstevel@tonic-gate key.data = keybuf;
6497c478bd9Sstevel@tonic-gate key.size = keylen;
6507c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
6517c478bd9Sstevel@tonic-gate i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
6527c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
6537c478bd9Sstevel@tonic-gate i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
6547c478bd9Sstevel@tonic-gate &key, &info, 0);
6557c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
6567c478bd9Sstevel@tonic-gate if (i != 0 || info.size <= 0)
6577c478bd9Sstevel@tonic-gate {
6587c478bd9Sstevel@tonic-gate if (tTd(28, 2))
6597c478bd9Sstevel@tonic-gate sm_dprintf("udbmatch: no match on %s (%d) via db\n",
6607c478bd9Sstevel@tonic-gate keybuf, keylen);
6617c478bd9Sstevel@tonic-gate continue;
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate p = sm_rpool_malloc_x(rpool, info.size + 1);
6657c478bd9Sstevel@tonic-gate memmove(p, info.data, info.size);
6667c478bd9Sstevel@tonic-gate p[info.size] = '\0';
6677c478bd9Sstevel@tonic-gate if (tTd(28, 1))
6687c478bd9Sstevel@tonic-gate sm_dprintf("udbmatch ==> %s\n", p);
6697c478bd9Sstevel@tonic-gate return p;
6707c478bd9Sstevel@tonic-gate # endif /* NEWDB */
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate # if HESIOD
6737c478bd9Sstevel@tonic-gate case UDB_HESIOD:
6747c478bd9Sstevel@tonic-gate key.data = keybuf;
6757c478bd9Sstevel@tonic-gate key.size = keylen;
6767c478bd9Sstevel@tonic-gate i = hes_udb_get(&key, &info);
6777c478bd9Sstevel@tonic-gate if (i != 0 || info.size <= 0)
6787c478bd9Sstevel@tonic-gate {
6797c478bd9Sstevel@tonic-gate if (tTd(28, 2))
6807c478bd9Sstevel@tonic-gate sm_dprintf("udbmatch: no match on %s (%d) via hesiod\n",
6817c478bd9Sstevel@tonic-gate keybuf, keylen);
6827c478bd9Sstevel@tonic-gate continue;
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate p = sm_rpool_malloc_x(rpool, info.size + 1);
6867c478bd9Sstevel@tonic-gate memmove(p, info.data, info.size);
6877c478bd9Sstevel@tonic-gate p[info.size] = '\0';
6887c478bd9Sstevel@tonic-gate if (tTd(28, 1))
6897c478bd9Sstevel@tonic-gate sm_dprintf("udbmatch ==> %s\n", p);
6907c478bd9Sstevel@tonic-gate return p;
6917c478bd9Sstevel@tonic-gate # endif /* HESIOD */
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate if (strcmp(field, "mailname") != 0)
6967c478bd9Sstevel@tonic-gate return NULL;
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate /*
6997c478bd9Sstevel@tonic-gate ** Nothing yet. Search again for a default case. But only
7007c478bd9Sstevel@tonic-gate ** use it if we also have a forward (:maildrop) pointer already
7017c478bd9Sstevel@tonic-gate ** in the database.
7027c478bd9Sstevel@tonic-gate */
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate /* build database key */
705*058561cbSjbeck (void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, user, ":maildrop");
7067c478bd9Sstevel@tonic-gate keylen = strlen(keybuf);
7077c478bd9Sstevel@tonic-gate
7087c478bd9Sstevel@tonic-gate for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
7097c478bd9Sstevel@tonic-gate {
7107c478bd9Sstevel@tonic-gate switch (up->udb_type)
7117c478bd9Sstevel@tonic-gate {
7127c478bd9Sstevel@tonic-gate # if NEWDB
7137c478bd9Sstevel@tonic-gate case UDB_DBFETCH:
7147c478bd9Sstevel@tonic-gate /* get the default case for this database */
7157c478bd9Sstevel@tonic-gate if (up->udb_default == NULL)
7167c478bd9Sstevel@tonic-gate {
717*058561cbSjbeck memset(&key, '\0', sizeof(key));
718*058561cbSjbeck memset(&info, '\0', sizeof(info));
7197c478bd9Sstevel@tonic-gate key.data = ":default:mailname";
7207c478bd9Sstevel@tonic-gate key.size = strlen(key.data);
7217c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
7227c478bd9Sstevel@tonic-gate i = (*up->udb_dbp->get)(up->udb_dbp,
7237c478bd9Sstevel@tonic-gate &key, &info, 0);
7247c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
7257c478bd9Sstevel@tonic-gate i = errno = (*up->udb_dbp->get)(up->udb_dbp,
7267c478bd9Sstevel@tonic-gate NULL, &key,
7277c478bd9Sstevel@tonic-gate &info, 0);
7287c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
7297c478bd9Sstevel@tonic-gate if (i != 0 || info.size <= 0)
7307c478bd9Sstevel@tonic-gate {
7317c478bd9Sstevel@tonic-gate /* no default case */
7327c478bd9Sstevel@tonic-gate up->udb_default = "";
7337c478bd9Sstevel@tonic-gate continue;
7347c478bd9Sstevel@tonic-gate }
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate /* save the default case */
7377c478bd9Sstevel@tonic-gate up->udb_default = sm_pmalloc_x(info.size + 1);
7387c478bd9Sstevel@tonic-gate memmove(up->udb_default, info.data, info.size);
7397c478bd9Sstevel@tonic-gate up->udb_default[info.size] = '\0';
7407c478bd9Sstevel@tonic-gate }
7417c478bd9Sstevel@tonic-gate else if (up->udb_default[0] == '\0')
7427c478bd9Sstevel@tonic-gate continue;
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate /* we have a default case -- verify user:maildrop */
745*058561cbSjbeck memset(&key, '\0', sizeof(key));
746*058561cbSjbeck memset(&info, '\0', sizeof(info));
7477c478bd9Sstevel@tonic-gate key.data = keybuf;
7487c478bd9Sstevel@tonic-gate key.size = keylen;
7497c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
7507c478bd9Sstevel@tonic-gate i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
7517c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
7527c478bd9Sstevel@tonic-gate i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
7537c478bd9Sstevel@tonic-gate &key, &info, 0);
7547c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
7557c478bd9Sstevel@tonic-gate if (i != 0 || info.size <= 0)
7567c478bd9Sstevel@tonic-gate {
7577c478bd9Sstevel@tonic-gate /* nope -- no aliasing for this user */
7587c478bd9Sstevel@tonic-gate continue;
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate /* they exist -- build the actual address */
7627c478bd9Sstevel@tonic-gate i = strlen(user) + strlen(up->udb_default) + 2;
7637c478bd9Sstevel@tonic-gate p = sm_rpool_malloc_x(rpool, i);
7647c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(p, i, 3, user, "@", up->udb_default);
7657c478bd9Sstevel@tonic-gate if (tTd(28, 1))
7667c478bd9Sstevel@tonic-gate sm_dprintf("udbmatch ==> %s\n", p);
7677c478bd9Sstevel@tonic-gate return p;
7687c478bd9Sstevel@tonic-gate # endif /* NEWDB */
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate # if HESIOD
7717c478bd9Sstevel@tonic-gate case UDB_HESIOD:
7727c478bd9Sstevel@tonic-gate /* get the default case for this database */
7737c478bd9Sstevel@tonic-gate if (up->udb_default == NULL)
7747c478bd9Sstevel@tonic-gate {
7757c478bd9Sstevel@tonic-gate key.data = ":default:mailname";
7767c478bd9Sstevel@tonic-gate key.size = strlen(key.data);
7777c478bd9Sstevel@tonic-gate i = hes_udb_get(&key, &info);
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate if (i != 0 || info.size <= 0)
7807c478bd9Sstevel@tonic-gate {
7817c478bd9Sstevel@tonic-gate /* no default case */
7827c478bd9Sstevel@tonic-gate up->udb_default = "";
7837c478bd9Sstevel@tonic-gate continue;
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate /* save the default case */
7877c478bd9Sstevel@tonic-gate up->udb_default = sm_pmalloc_x(info.size + 1);
7887c478bd9Sstevel@tonic-gate memmove(up->udb_default, info.data, info.size);
7897c478bd9Sstevel@tonic-gate up->udb_default[info.size] = '\0';
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate else if (up->udb_default[0] == '\0')
7927c478bd9Sstevel@tonic-gate continue;
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate /* we have a default case -- verify user:maildrop */
7957c478bd9Sstevel@tonic-gate key.data = keybuf;
7967c478bd9Sstevel@tonic-gate key.size = keylen;
7977c478bd9Sstevel@tonic-gate i = hes_udb_get(&key, &info);
7987c478bd9Sstevel@tonic-gate if (i != 0 || info.size <= 0)
7997c478bd9Sstevel@tonic-gate {
8007c478bd9Sstevel@tonic-gate /* nope -- no aliasing for this user */
8017c478bd9Sstevel@tonic-gate continue;
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate /* they exist -- build the actual address */
8057c478bd9Sstevel@tonic-gate i = strlen(user) + strlen(up->udb_default) + 2;
8067c478bd9Sstevel@tonic-gate p = sm_rpool_malloc_x(rpool, i);
8077c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(p, i, 3, user, "@", up->udb_default);
8087c478bd9Sstevel@tonic-gate if (tTd(28, 1))
8097c478bd9Sstevel@tonic-gate sm_dprintf("udbmatch ==> %s\n", p);
8107c478bd9Sstevel@tonic-gate return p;
8117c478bd9Sstevel@tonic-gate break;
8127c478bd9Sstevel@tonic-gate # endif /* HESIOD */
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate /* still nothing.... too bad */
8177c478bd9Sstevel@tonic-gate return NULL;
8187c478bd9Sstevel@tonic-gate }
8197c478bd9Sstevel@tonic-gate /*
8207c478bd9Sstevel@tonic-gate ** UDB_MAP_LOOKUP -- look up arbitrary entry in user database map
8217c478bd9Sstevel@tonic-gate **
8227c478bd9Sstevel@tonic-gate ** Parameters:
8237c478bd9Sstevel@tonic-gate ** map -- the map being queried.
8247c478bd9Sstevel@tonic-gate ** name -- the name to look up.
8257c478bd9Sstevel@tonic-gate ** av -- arguments to the map lookup.
8267c478bd9Sstevel@tonic-gate ** statp -- to get any error status.
8277c478bd9Sstevel@tonic-gate **
8287c478bd9Sstevel@tonic-gate ** Returns:
8297c478bd9Sstevel@tonic-gate ** NULL if name not found in map.
8307c478bd9Sstevel@tonic-gate ** The rewritten name otherwise.
8317c478bd9Sstevel@tonic-gate */
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
8347c478bd9Sstevel@tonic-gate char *
udb_map_lookup(map,name,av,statp)8357c478bd9Sstevel@tonic-gate udb_map_lookup(map, name, av, statp)
8367c478bd9Sstevel@tonic-gate MAP *map;
8377c478bd9Sstevel@tonic-gate char *name;
8387c478bd9Sstevel@tonic-gate char **av;
8397c478bd9Sstevel@tonic-gate int *statp;
8407c478bd9Sstevel@tonic-gate {
8417c478bd9Sstevel@tonic-gate char *val;
8427c478bd9Sstevel@tonic-gate char *key;
8437c478bd9Sstevel@tonic-gate char *SM_NONVOLATILE result = NULL;
8447c478bd9Sstevel@tonic-gate char keybuf[MAXNAME + 1];
8457c478bd9Sstevel@tonic-gate
8467c478bd9Sstevel@tonic-gate if (tTd(28, 20) || tTd(38, 20))
8477c478bd9Sstevel@tonic-gate sm_dprintf("udb_map_lookup(%s, %s)\n", map->map_mname, name);
8487c478bd9Sstevel@tonic-gate
8497c478bd9Sstevel@tonic-gate if (bitset(MF_NOFOLDCASE, map->map_mflags))
8507c478bd9Sstevel@tonic-gate {
8517c478bd9Sstevel@tonic-gate key = name;
8527c478bd9Sstevel@tonic-gate }
8537c478bd9Sstevel@tonic-gate else
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate int keysize = strlen(name);
8567c478bd9Sstevel@tonic-gate
857*058561cbSjbeck if (keysize > sizeof(keybuf) - 1)
858*058561cbSjbeck keysize = sizeof(keybuf) - 1;
8597c478bd9Sstevel@tonic-gate memmove(keybuf, name, keysize);
8607c478bd9Sstevel@tonic-gate keybuf[keysize] = '\0';
8617c478bd9Sstevel@tonic-gate makelower(keybuf);
8627c478bd9Sstevel@tonic-gate key = keybuf;
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate val = udbmatch(key, map->map_file, NULL);
8657c478bd9Sstevel@tonic-gate if (val == NULL)
8667c478bd9Sstevel@tonic-gate return NULL;
8677c478bd9Sstevel@tonic-gate SM_TRY
8687c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags))
8697c478bd9Sstevel@tonic-gate result = map_rewrite(map, name, strlen(name), NULL);
8707c478bd9Sstevel@tonic-gate else
8717c478bd9Sstevel@tonic-gate result = map_rewrite(map, val, strlen(val), av);
8727c478bd9Sstevel@tonic-gate SM_FINALLY
8737c478bd9Sstevel@tonic-gate sm_free(val);
8747c478bd9Sstevel@tonic-gate SM_END_TRY
8757c478bd9Sstevel@tonic-gate return result;
8767c478bd9Sstevel@tonic-gate }
8777c478bd9Sstevel@tonic-gate /*
8787c478bd9Sstevel@tonic-gate ** _UDBX_INIT -- parse the UDB specification, opening any valid entries.
8797c478bd9Sstevel@tonic-gate **
8807c478bd9Sstevel@tonic-gate ** Parameters:
8817c478bd9Sstevel@tonic-gate ** e -- the current envelope.
8827c478bd9Sstevel@tonic-gate **
8837c478bd9Sstevel@tonic-gate ** Returns:
8847c478bd9Sstevel@tonic-gate ** EX_TEMPFAIL -- if it appeared it couldn't get hold of a
8857c478bd9Sstevel@tonic-gate ** database due to a host being down or some similar
8867c478bd9Sstevel@tonic-gate ** (recoverable) situation.
8877c478bd9Sstevel@tonic-gate ** EX_OK -- otherwise.
8887c478bd9Sstevel@tonic-gate **
8897c478bd9Sstevel@tonic-gate ** Side Effects:
8907c478bd9Sstevel@tonic-gate ** Fills in the UdbEnts structure from UdbSpec.
8917c478bd9Sstevel@tonic-gate */
8927c478bd9Sstevel@tonic-gate
8937c478bd9Sstevel@tonic-gate # define MAXUDBOPTS 27
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate static int
_udbx_init(e)8967c478bd9Sstevel@tonic-gate _udbx_init(e)
8977c478bd9Sstevel@tonic-gate ENVELOPE *e;
8987c478bd9Sstevel@tonic-gate {
8997c478bd9Sstevel@tonic-gate int ents = 0;
9007c478bd9Sstevel@tonic-gate register char *p;
9017c478bd9Sstevel@tonic-gate register struct udbent *up;
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate if (UdbInitialized)
9047c478bd9Sstevel@tonic-gate return EX_OK;
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate # ifdef UDB_DEFAULT_SPEC
9077c478bd9Sstevel@tonic-gate if (UdbSpec == NULL)
9087c478bd9Sstevel@tonic-gate UdbSpec = UDB_DEFAULT_SPEC;
9097c478bd9Sstevel@tonic-gate # endif /* UDB_DEFAULT_SPEC */
9107c478bd9Sstevel@tonic-gate
9117c478bd9Sstevel@tonic-gate p = UdbSpec;
9127c478bd9Sstevel@tonic-gate up = UdbEnts;
9137c478bd9Sstevel@tonic-gate while (p != NULL)
9147c478bd9Sstevel@tonic-gate {
9157c478bd9Sstevel@tonic-gate char *spec;
9167c478bd9Sstevel@tonic-gate int l;
9177c478bd9Sstevel@tonic-gate struct udb_option opts[MAXUDBOPTS + 1];
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate while (*p == ' ' || *p == '\t' || *p == ',')
9207c478bd9Sstevel@tonic-gate p++;
9217c478bd9Sstevel@tonic-gate if (*p == '\0')
9227c478bd9Sstevel@tonic-gate break;
9237c478bd9Sstevel@tonic-gate spec = p;
9247c478bd9Sstevel@tonic-gate p = strchr(p, ',');
9257c478bd9Sstevel@tonic-gate if (p != NULL)
9267c478bd9Sstevel@tonic-gate *p++ = '\0';
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate if (ents >= MAXUDBENT)
9297c478bd9Sstevel@tonic-gate {
9307c478bd9Sstevel@tonic-gate syserr("Maximum number of UDB entries exceeded");
9317c478bd9Sstevel@tonic-gate break;
9327c478bd9Sstevel@tonic-gate }
9337c478bd9Sstevel@tonic-gate
9347c478bd9Sstevel@tonic-gate /* extract options */
9357c478bd9Sstevel@tonic-gate (void) _udb_parsespec(spec, opts, MAXUDBOPTS);
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate /*
9387c478bd9Sstevel@tonic-gate ** Decode database specification.
9397c478bd9Sstevel@tonic-gate **
9407c478bd9Sstevel@tonic-gate ** In the sendmail tradition, the leading character
9417c478bd9Sstevel@tonic-gate ** defines the semantics of the rest of the entry.
9427c478bd9Sstevel@tonic-gate **
9437c478bd9Sstevel@tonic-gate ** @hostname -- forward email to the indicated host.
9447c478bd9Sstevel@tonic-gate ** This should be the last in the list,
9457c478bd9Sstevel@tonic-gate ** since it always matches the input.
9467c478bd9Sstevel@tonic-gate ** /dbname -- search the named database on the local
9477c478bd9Sstevel@tonic-gate ** host using the Berkeley db package.
9487c478bd9Sstevel@tonic-gate ** Hesiod -- search the named database with BIND
9497c478bd9Sstevel@tonic-gate ** using the MIT Hesiod package.
9507c478bd9Sstevel@tonic-gate */
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate switch (*spec)
9537c478bd9Sstevel@tonic-gate {
9547c478bd9Sstevel@tonic-gate case '@': /* forward to remote host */
9557c478bd9Sstevel@tonic-gate up->udb_type = UDB_FORWARD;
9567c478bd9Sstevel@tonic-gate up->udb_pid = CurrentPid;
9577c478bd9Sstevel@tonic-gate up->udb_fwdhost = spec + 1;
9587c478bd9Sstevel@tonic-gate ents++;
9597c478bd9Sstevel@tonic-gate up++;
9607c478bd9Sstevel@tonic-gate break;
9617c478bd9Sstevel@tonic-gate
9627c478bd9Sstevel@tonic-gate # if HESIOD
9637c478bd9Sstevel@tonic-gate case 'h': /* use hesiod */
9647c478bd9Sstevel@tonic-gate case 'H':
9657c478bd9Sstevel@tonic-gate if (sm_strcasecmp(spec, "hesiod") != 0)
9667c478bd9Sstevel@tonic-gate goto badspec;
9677c478bd9Sstevel@tonic-gate up->udb_type = UDB_HESIOD;
9687c478bd9Sstevel@tonic-gate up->udb_pid = CurrentPid;
9697c478bd9Sstevel@tonic-gate ents++;
9707c478bd9Sstevel@tonic-gate up++;
9717c478bd9Sstevel@tonic-gate break;
9727c478bd9Sstevel@tonic-gate # endif /* HESIOD */
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate # if NEWDB
9757c478bd9Sstevel@tonic-gate case '/': /* look up remote name */
9767c478bd9Sstevel@tonic-gate l = strlen(spec);
9777c478bd9Sstevel@tonic-gate if (l > 3 && strcmp(&spec[l - 3], ".db") == 0)
9787c478bd9Sstevel@tonic-gate {
9797c478bd9Sstevel@tonic-gate up->udb_dbname = spec;
9807c478bd9Sstevel@tonic-gate }
9817c478bd9Sstevel@tonic-gate else
9827c478bd9Sstevel@tonic-gate {
9837c478bd9Sstevel@tonic-gate up->udb_dbname = sm_pmalloc_x(l + 4);
9847c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(up->udb_dbname, l + 4, 2,
9857c478bd9Sstevel@tonic-gate spec, ".db");
9867c478bd9Sstevel@tonic-gate }
9877c478bd9Sstevel@tonic-gate errno = 0;
9887c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
9897c478bd9Sstevel@tonic-gate up->udb_dbp = dbopen(up->udb_dbname, O_RDONLY,
9907c478bd9Sstevel@tonic-gate 0644, DB_BTREE, NULL);
9917c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
9927c478bd9Sstevel@tonic-gate {
9937c478bd9Sstevel@tonic-gate int flags = DB_RDONLY;
9947c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2
9957c478bd9Sstevel@tonic-gate int ret;
9967c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate SM_DB_FLAG_ADD(flags);
9997c478bd9Sstevel@tonic-gate up->udb_dbp = NULL;
10007c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2
10017c478bd9Sstevel@tonic-gate ret = db_create(&up->udb_dbp, NULL, 0);
10027c478bd9Sstevel@tonic-gate if (ret != 0)
10037c478bd9Sstevel@tonic-gate {
10047c478bd9Sstevel@tonic-gate (void) up->udb_dbp->close(up->udb_dbp,
10057c478bd9Sstevel@tonic-gate 0);
10067c478bd9Sstevel@tonic-gate up->udb_dbp = NULL;
10077c478bd9Sstevel@tonic-gate }
10087c478bd9Sstevel@tonic-gate else
10097c478bd9Sstevel@tonic-gate {
10107c478bd9Sstevel@tonic-gate ret = up->udb_dbp->open(up->udb_dbp,
10117c478bd9Sstevel@tonic-gate DBTXN
10127c478bd9Sstevel@tonic-gate up->udb_dbname,
10137c478bd9Sstevel@tonic-gate NULL,
10147c478bd9Sstevel@tonic-gate DB_BTREE,
10157c478bd9Sstevel@tonic-gate flags,
10167c478bd9Sstevel@tonic-gate 0644);
10177c478bd9Sstevel@tonic-gate if (ret != 0)
10187c478bd9Sstevel@tonic-gate {
10197c478bd9Sstevel@tonic-gate #ifdef DB_OLD_VERSION
10207c478bd9Sstevel@tonic-gate if (ret == DB_OLD_VERSION)
10217c478bd9Sstevel@tonic-gate ret = EINVAL;
10227c478bd9Sstevel@tonic-gate #endif /* DB_OLD_VERSION */
10237c478bd9Sstevel@tonic-gate (void) up->udb_dbp->close(up->udb_dbp, 0);
10247c478bd9Sstevel@tonic-gate up->udb_dbp = NULL;
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate errno = ret;
10287c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR > 2 */
10297c478bd9Sstevel@tonic-gate errno = db_open(up->udb_dbname, DB_BTREE,
10307c478bd9Sstevel@tonic-gate flags, 0644, NULL,
10317c478bd9Sstevel@tonic-gate NULL, &up->udb_dbp);
10327c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */
10337c478bd9Sstevel@tonic-gate }
10347c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
10357c478bd9Sstevel@tonic-gate if (up->udb_dbp == NULL)
10367c478bd9Sstevel@tonic-gate {
10377c478bd9Sstevel@tonic-gate if (tTd(28, 1))
10387c478bd9Sstevel@tonic-gate {
10397c478bd9Sstevel@tonic-gate int save_errno = errno;
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
10427c478bd9Sstevel@tonic-gate sm_dprintf("dbopen(%s): %s\n",
10437c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
10447c478bd9Sstevel@tonic-gate sm_dprintf("db_open(%s): %s\n",
10457c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
10467c478bd9Sstevel@tonic-gate up->udb_dbname,
10477c478bd9Sstevel@tonic-gate sm_errstring(errno));
10487c478bd9Sstevel@tonic-gate errno = save_errno;
10497c478bd9Sstevel@tonic-gate }
10507c478bd9Sstevel@tonic-gate if (errno != ENOENT && errno != EACCES)
10517c478bd9Sstevel@tonic-gate {
10527c478bd9Sstevel@tonic-gate if (LogLevel > 2)
10537c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, e->e_id,
10547c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
10557c478bd9Sstevel@tonic-gate "dbopen(%s): %s",
10567c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
10577c478bd9Sstevel@tonic-gate "db_open(%s): %s",
10587c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
10597c478bd9Sstevel@tonic-gate up->udb_dbname,
10607c478bd9Sstevel@tonic-gate sm_errstring(errno));
10617c478bd9Sstevel@tonic-gate up->udb_type = UDB_EOLIST;
10627c478bd9Sstevel@tonic-gate if (up->udb_dbname != spec)
10637c478bd9Sstevel@tonic-gate sm_free(up->udb_dbname); /* XXX */
10647c478bd9Sstevel@tonic-gate goto tempfail;
10657c478bd9Sstevel@tonic-gate }
10667c478bd9Sstevel@tonic-gate if (up->udb_dbname != spec)
10677c478bd9Sstevel@tonic-gate sm_free(up->udb_dbname); /* XXX */
10687c478bd9Sstevel@tonic-gate break;
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate if (tTd(28, 1))
10717c478bd9Sstevel@tonic-gate {
10727c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
10737c478bd9Sstevel@tonic-gate sm_dprintf("_udbx_init: dbopen(%s)\n",
10747c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
10757c478bd9Sstevel@tonic-gate sm_dprintf("_udbx_init: db_open(%s)\n",
10767c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
10777c478bd9Sstevel@tonic-gate up->udb_dbname);
10787c478bd9Sstevel@tonic-gate }
10797c478bd9Sstevel@tonic-gate up->udb_type = UDB_DBFETCH;
10807c478bd9Sstevel@tonic-gate up->udb_pid = CurrentPid;
10817c478bd9Sstevel@tonic-gate ents++;
10827c478bd9Sstevel@tonic-gate up++;
10837c478bd9Sstevel@tonic-gate break;
10847c478bd9Sstevel@tonic-gate # endif /* NEWDB */
10857c478bd9Sstevel@tonic-gate
10867c478bd9Sstevel@tonic-gate default:
10877c478bd9Sstevel@tonic-gate # if HESIOD
10887c478bd9Sstevel@tonic-gate badspec:
10897c478bd9Sstevel@tonic-gate # endif /* HESIOD */
10907c478bd9Sstevel@tonic-gate syserr("Unknown UDB spec %s", spec);
10917c478bd9Sstevel@tonic-gate break;
10927c478bd9Sstevel@tonic-gate }
10937c478bd9Sstevel@tonic-gate }
10947c478bd9Sstevel@tonic-gate up->udb_type = UDB_EOLIST;
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate if (tTd(28, 4))
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
10997c478bd9Sstevel@tonic-gate {
11007c478bd9Sstevel@tonic-gate switch (up->udb_type)
11017c478bd9Sstevel@tonic-gate {
11027c478bd9Sstevel@tonic-gate case UDB_REMOTE:
11037c478bd9Sstevel@tonic-gate sm_dprintf("REMOTE: addr %s, timeo %d\n",
11047c478bd9Sstevel@tonic-gate anynet_ntoa((SOCKADDR *) &up->udb_addr),
11057c478bd9Sstevel@tonic-gate up->udb_timeout);
11067c478bd9Sstevel@tonic-gate break;
11077c478bd9Sstevel@tonic-gate
11087c478bd9Sstevel@tonic-gate case UDB_DBFETCH:
11097c478bd9Sstevel@tonic-gate # if NEWDB
11107c478bd9Sstevel@tonic-gate sm_dprintf("FETCH: file %s\n",
11117c478bd9Sstevel@tonic-gate up->udb_dbname);
11127c478bd9Sstevel@tonic-gate # else /* NEWDB */
11137c478bd9Sstevel@tonic-gate sm_dprintf("FETCH\n");
11147c478bd9Sstevel@tonic-gate # endif /* NEWDB */
11157c478bd9Sstevel@tonic-gate break;
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate case UDB_FORWARD:
11187c478bd9Sstevel@tonic-gate sm_dprintf("FORWARD: host %s\n",
11197c478bd9Sstevel@tonic-gate up->udb_fwdhost);
11207c478bd9Sstevel@tonic-gate break;
11217c478bd9Sstevel@tonic-gate
11227c478bd9Sstevel@tonic-gate case UDB_HESIOD:
11237c478bd9Sstevel@tonic-gate sm_dprintf("HESIOD\n");
11247c478bd9Sstevel@tonic-gate break;
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate default:
11277c478bd9Sstevel@tonic-gate sm_dprintf("UNKNOWN\n");
11287c478bd9Sstevel@tonic-gate break;
11297c478bd9Sstevel@tonic-gate }
11307c478bd9Sstevel@tonic-gate }
11317c478bd9Sstevel@tonic-gate }
11327c478bd9Sstevel@tonic-gate
11337c478bd9Sstevel@tonic-gate UdbInitialized = true;
11347c478bd9Sstevel@tonic-gate errno = 0;
11357c478bd9Sstevel@tonic-gate return EX_OK;
11367c478bd9Sstevel@tonic-gate
11377c478bd9Sstevel@tonic-gate /*
11387c478bd9Sstevel@tonic-gate ** On temporary failure, back out anything we've already done
11397c478bd9Sstevel@tonic-gate */
11407c478bd9Sstevel@tonic-gate
11417c478bd9Sstevel@tonic-gate tempfail:
11427c478bd9Sstevel@tonic-gate # if NEWDB
11437c478bd9Sstevel@tonic-gate for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
11447c478bd9Sstevel@tonic-gate {
11457c478bd9Sstevel@tonic-gate if (up->udb_type == UDB_DBFETCH)
11467c478bd9Sstevel@tonic-gate {
11477c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
11487c478bd9Sstevel@tonic-gate (*up->udb_dbp->close)(up->udb_dbp);
11497c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
11507c478bd9Sstevel@tonic-gate errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
11517c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
11527c478bd9Sstevel@tonic-gate if (tTd(28, 1))
11537c478bd9Sstevel@tonic-gate sm_dprintf("_udbx_init: db->close(%s)\n",
11547c478bd9Sstevel@tonic-gate up->udb_dbname);
11557c478bd9Sstevel@tonic-gate }
11567c478bd9Sstevel@tonic-gate }
11577c478bd9Sstevel@tonic-gate # endif /* NEWDB */
11587c478bd9Sstevel@tonic-gate return EX_TEMPFAIL;
11597c478bd9Sstevel@tonic-gate }
11607c478bd9Sstevel@tonic-gate
11617c478bd9Sstevel@tonic-gate static int
_udb_parsespec(udbspec,opt,maxopts)11627c478bd9Sstevel@tonic-gate _udb_parsespec(udbspec, opt, maxopts)
11637c478bd9Sstevel@tonic-gate char *udbspec;
11647c478bd9Sstevel@tonic-gate struct udb_option opt[];
11657c478bd9Sstevel@tonic-gate int maxopts;
11667c478bd9Sstevel@tonic-gate {
11677c478bd9Sstevel@tonic-gate register char *spec;
11687c478bd9Sstevel@tonic-gate register char *spec_end;
11697c478bd9Sstevel@tonic-gate register int optnum;
11707c478bd9Sstevel@tonic-gate
11717c478bd9Sstevel@tonic-gate spec_end = strchr(udbspec, ':');
11727c478bd9Sstevel@tonic-gate for (optnum = 0; optnum < maxopts && (spec = spec_end) != NULL; optnum++)
11737c478bd9Sstevel@tonic-gate {
11747c478bd9Sstevel@tonic-gate register char *p;
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate while (isascii(*spec) && isspace(*spec))
11777c478bd9Sstevel@tonic-gate spec++;
11787c478bd9Sstevel@tonic-gate spec_end = strchr(spec, ':');
11797c478bd9Sstevel@tonic-gate if (spec_end != NULL)
11807c478bd9Sstevel@tonic-gate *spec_end++ = '\0';
11817c478bd9Sstevel@tonic-gate
11827c478bd9Sstevel@tonic-gate opt[optnum].udbo_name = spec;
11837c478bd9Sstevel@tonic-gate opt[optnum].udbo_val = NULL;
11847c478bd9Sstevel@tonic-gate p = strchr(spec, '=');
11857c478bd9Sstevel@tonic-gate if (p != NULL)
11867c478bd9Sstevel@tonic-gate opt[optnum].udbo_val = ++p;
11877c478bd9Sstevel@tonic-gate }
11887c478bd9Sstevel@tonic-gate return optnum;
11897c478bd9Sstevel@tonic-gate }
11907c478bd9Sstevel@tonic-gate /*
11917c478bd9Sstevel@tonic-gate ** _UDBX_CLOSE -- close all file based UDB entries.
11927c478bd9Sstevel@tonic-gate **
11937c478bd9Sstevel@tonic-gate ** Parameters:
11947c478bd9Sstevel@tonic-gate ** none
11957c478bd9Sstevel@tonic-gate **
11967c478bd9Sstevel@tonic-gate ** Returns:
11977c478bd9Sstevel@tonic-gate ** none
11987c478bd9Sstevel@tonic-gate */
11997c478bd9Sstevel@tonic-gate void
_udbx_close()12007c478bd9Sstevel@tonic-gate _udbx_close()
12017c478bd9Sstevel@tonic-gate {
12027c478bd9Sstevel@tonic-gate struct udbent *up;
12037c478bd9Sstevel@tonic-gate
12047c478bd9Sstevel@tonic-gate if (!UdbInitialized)
12057c478bd9Sstevel@tonic-gate return;
12067c478bd9Sstevel@tonic-gate
12077c478bd9Sstevel@tonic-gate for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
12087c478bd9Sstevel@tonic-gate {
12097c478bd9Sstevel@tonic-gate if (up->udb_pid != CurrentPid)
12107c478bd9Sstevel@tonic-gate continue;
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate # if NEWDB
12137c478bd9Sstevel@tonic-gate if (up->udb_type == UDB_DBFETCH)
12147c478bd9Sstevel@tonic-gate {
12157c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
12167c478bd9Sstevel@tonic-gate (*up->udb_dbp->close)(up->udb_dbp);
12177c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
12187c478bd9Sstevel@tonic-gate errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
12197c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
12207c478bd9Sstevel@tonic-gate }
12217c478bd9Sstevel@tonic-gate if (tTd(28, 1))
12227c478bd9Sstevel@tonic-gate sm_dprintf("_udbx_init: db->close(%s)\n",
12237c478bd9Sstevel@tonic-gate up->udb_dbname);
12247c478bd9Sstevel@tonic-gate # endif /* NEWDB */
12257c478bd9Sstevel@tonic-gate }
12267c478bd9Sstevel@tonic-gate }
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate # if HESIOD
12297c478bd9Sstevel@tonic-gate
12307c478bd9Sstevel@tonic-gate static int
hes_udb_get(key,info)12317c478bd9Sstevel@tonic-gate hes_udb_get(key, info)
12327c478bd9Sstevel@tonic-gate DBT *key;
12337c478bd9Sstevel@tonic-gate DBT *info;
12347c478bd9Sstevel@tonic-gate {
12357c478bd9Sstevel@tonic-gate char *name, *type;
12367c478bd9Sstevel@tonic-gate char **hp;
123749218d4fSjbeck char kbuf[MAXUDBKEY + 1];
12387c478bd9Sstevel@tonic-gate
1239*058561cbSjbeck if (sm_strlcpy(kbuf, key->data, sizeof(kbuf)) >= sizeof(kbuf))
12407c478bd9Sstevel@tonic-gate return 0;
12417c478bd9Sstevel@tonic-gate name = kbuf;
12427c478bd9Sstevel@tonic-gate type = strrchr(name, ':');
12437c478bd9Sstevel@tonic-gate if (type == NULL)
12447c478bd9Sstevel@tonic-gate return 1;
12457c478bd9Sstevel@tonic-gate *type++ = '\0';
12467c478bd9Sstevel@tonic-gate if (strchr(name, '@') != NULL)
12477c478bd9Sstevel@tonic-gate return 1;
12487c478bd9Sstevel@tonic-gate
12497c478bd9Sstevel@tonic-gate if (tTd(28, 1))
12507c478bd9Sstevel@tonic-gate sm_dprintf("hes_udb_get(%s, %s)\n", name, type);
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate /* make the hesiod query */
12537c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT
12547c478bd9Sstevel@tonic-gate if (HesiodContext == NULL && hesiod_init(&HesiodContext) != 0)
12557c478bd9Sstevel@tonic-gate return -1;
12567c478bd9Sstevel@tonic-gate hp = hesiod_resolve(HesiodContext, name, type);
12577c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */
12587c478bd9Sstevel@tonic-gate hp = hes_resolve(name, type);
12597c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */
12607c478bd9Sstevel@tonic-gate *--type = ':';
12617c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT
12627c478bd9Sstevel@tonic-gate if (hp == NULL)
12637c478bd9Sstevel@tonic-gate return 1;
12647c478bd9Sstevel@tonic-gate if (*hp == NULL)
12657c478bd9Sstevel@tonic-gate {
12667c478bd9Sstevel@tonic-gate hesiod_free_list(HesiodContext, hp);
12677c478bd9Sstevel@tonic-gate if (errno == ECONNREFUSED || errno == EMSGSIZE)
12687c478bd9Sstevel@tonic-gate return -1;
12697c478bd9Sstevel@tonic-gate return 1;
12707c478bd9Sstevel@tonic-gate }
12717c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */
12727c478bd9Sstevel@tonic-gate if (hp == NULL || hp[0] == NULL)
12737c478bd9Sstevel@tonic-gate {
12747c478bd9Sstevel@tonic-gate /* network problem or timeout */
12757c478bd9Sstevel@tonic-gate if (hes_error() == HES_ER_NET)
12767c478bd9Sstevel@tonic-gate return -1;
12777c478bd9Sstevel@tonic-gate
12787c478bd9Sstevel@tonic-gate return 1;
12797c478bd9Sstevel@tonic-gate }
12807c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */
12817c478bd9Sstevel@tonic-gate else
12827c478bd9Sstevel@tonic-gate {
12837c478bd9Sstevel@tonic-gate /*
12847c478bd9Sstevel@tonic-gate ** If there are multiple matches, just return the
12857c478bd9Sstevel@tonic-gate ** first one.
12867c478bd9Sstevel@tonic-gate **
12877c478bd9Sstevel@tonic-gate ** XXX These should really be returned; for example,
12887c478bd9Sstevel@tonic-gate ** XXX it is legal for :maildrop to be multi-valued.
12897c478bd9Sstevel@tonic-gate */
12907c478bd9Sstevel@tonic-gate
12917c478bd9Sstevel@tonic-gate info->data = hp[0];
12927c478bd9Sstevel@tonic-gate info->size = (size_t) strlen(info->data);
12937c478bd9Sstevel@tonic-gate }
12947c478bd9Sstevel@tonic-gate
12957c478bd9Sstevel@tonic-gate if (tTd(28, 80))
12967c478bd9Sstevel@tonic-gate sm_dprintf("hes_udb_get => %s\n", *hp);
12977c478bd9Sstevel@tonic-gate
12987c478bd9Sstevel@tonic-gate return 0;
12997c478bd9Sstevel@tonic-gate }
13007c478bd9Sstevel@tonic-gate # endif /* HESIOD */
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate #else /* USERDB */
13037c478bd9Sstevel@tonic-gate
13047c478bd9Sstevel@tonic-gate int
13057c478bd9Sstevel@tonic-gate udbexpand(a, sendq, aliaslevel, e)
13067c478bd9Sstevel@tonic-gate ADDRESS *a;
13077c478bd9Sstevel@tonic-gate ADDRESS **sendq;
13087c478bd9Sstevel@tonic-gate int aliaslevel;
13097c478bd9Sstevel@tonic-gate ENVELOPE *e;
13107c478bd9Sstevel@tonic-gate {
13117c478bd9Sstevel@tonic-gate return EX_OK;
13127c478bd9Sstevel@tonic-gate }
13137c478bd9Sstevel@tonic-gate
13147c478bd9Sstevel@tonic-gate #endif /* USERDB */
1315