summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/udb.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/udb.c')
-rw-r--r--contrib/sendmail/src/udb.c1314
1 files changed, 0 insertions, 1314 deletions
diff --git a/contrib/sendmail/src/udb.c b/contrib/sendmail/src/udb.c
deleted file mode 100644
index 29470e7..0000000
--- a/contrib/sendmail/src/udb.c
+++ /dev/null
@@ -1,1314 +0,0 @@
-/*
- * Copyright (c) 1998-2003, 2006 Sendmail, Inc. and its suppliers.
- * All rights reserved.
- * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * By using this file, you agree to the terms and conditions set
- * forth in the LICENSE file which can be found at the top level of
- * the sendmail distribution.
- *
- */
-
-#include <sendmail.h>
-#include "map.h"
-
-#if USERDB
-SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (with USERDB)")
-#else /* USERDB */
-SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (without USERDB)")
-#endif /* USERDB */
-
-#if USERDB
-
-#include <sm/sendmail.h>
-# if NEWDB
-# include "sm/bdb.h"
-# else /* NEWDB */
-# define DBT struct _data_base_thang_
-DBT
-{
- void *data; /* pointer to data */
- size_t size; /* length of data */
-};
-# endif /* NEWDB */
-
-/*
-** UDB.C -- interface between sendmail and Berkeley User Data Base.
-**
-** This depends on the 4.4BSD db package.
-*/
-
-
-struct udbent
-{
- char *udb_spec; /* string version of spec */
- int udb_type; /* type of entry */
- pid_t udb_pid; /* PID of process which opened db */
- char *udb_default; /* default host for outgoing mail */
- union
- {
-# if NETINET || NETINET6
- /* type UE_REMOTE -- do remote call for lookup */
- struct
- {
- SOCKADDR _udb_addr; /* address */
- int _udb_timeout; /* timeout */
- } udb_remote;
-# define udb_addr udb_u.udb_remote._udb_addr
-# define udb_timeout udb_u.udb_remote._udb_timeout
-# endif /* NETINET || NETINET6 */
-
- /* type UE_FORWARD -- forward message to remote */
- struct
- {
- char *_udb_fwdhost; /* name of forward host */
- } udb_forward;
-# define udb_fwdhost udb_u.udb_forward._udb_fwdhost
-
-# if NEWDB
- /* type UE_FETCH -- lookup in local database */
- struct
- {
- char *_udb_dbname; /* pathname of database */
- DB *_udb_dbp; /* open database ptr */
- } udb_lookup;
-# define udb_dbname udb_u.udb_lookup._udb_dbname
-# define udb_dbp udb_u.udb_lookup._udb_dbp
-# endif /* NEWDB */
- } udb_u;
-};
-
-# define UDB_EOLIST 0 /* end of list */
-# define UDB_SKIP 1 /* skip this entry */
-# define UDB_REMOTE 2 /* look up in remote database */
-# define UDB_DBFETCH 3 /* look up in local database */
-# define UDB_FORWARD 4 /* forward to remote host */
-# define UDB_HESIOD 5 /* look up via hesiod */
-
-# define MAXUDBENT 10 /* maximum number of UDB entries */
-
-
-struct udb_option
-{
- char *udbo_name;
- char *udbo_val;
-};
-
-# if HESIOD
-static int hes_udb_get __P((DBT *, DBT *));
-# endif /* HESIOD */
-static char *udbmatch __P((char *, char *, SM_RPOOL_T *));
-static int _udbx_init __P((ENVELOPE *));
-static int _udb_parsespec __P((char *, struct udb_option [], int));
-
-/*
-** UDBEXPAND -- look up user in database and expand
-**
-** Parameters:
-** a -- address to expand.
-** sendq -- pointer to head of sendq to put the expansions in.
-** aliaslevel -- the current alias nesting depth.
-** e -- the current envelope.
-**
-** Returns:
-** EX_TEMPFAIL -- if something "odd" happened -- probably due
-** to accessing a file on an NFS server that is down.
-** EX_OK -- otherwise.
-**
-** Side Effects:
-** Modifies sendq.
-*/
-
-static struct udbent UdbEnts[MAXUDBENT + 1];
-static bool UdbInitialized = false;
-
-int
-udbexpand(a, sendq, aliaslevel, e)
- register ADDRESS *a;
- ADDRESS **sendq;
- int aliaslevel;
- register ENVELOPE *e;
-{
- int i;
- DBT key;
- DBT info;
- bool breakout;
- register struct udbent *up;
- int keylen;
- int naddrs;
- char *user;
- char keybuf[MAXUDBKEY];
-
- memset(&key, '\0', sizeof(key));
- memset(&info, '\0', sizeof(info));
-
- if (tTd(28, 1))
- sm_dprintf("udbexpand(%s)\n", a->q_paddr);
-
- /* make certain we are supposed to send to this address */
- if (!QS_IS_SENDABLE(a->q_state))
- return EX_OK;
- e->e_to = a->q_paddr;
-
- /* on first call, locate the database */
- if (!UdbInitialized)
- {
- if (_udbx_init(e) == EX_TEMPFAIL)
- return EX_TEMPFAIL;
- }
-
- /* short circuit the process if no chance of a match */
- if (UdbSpec == NULL || UdbSpec[0] == '\0')
- return EX_OK;
-
- /* extract user to do userdb matching on */
- user = a->q_user;
-
- /* short circuit name begins with '\\' since it can't possibly match */
- /* (might want to treat this as unquoted instead) */
- if (user[0] == '\\')
- return EX_OK;
-
- /* if name begins with a colon, it indicates our metadata */
- if (user[0] == ':')
- return EX_OK;
-
- keylen = sm_strlcpyn(keybuf, sizeof(keybuf), 2, user, ":maildrop");
-
- /* if name is too long, assume it won't match */
- if (keylen >= sizeof(keybuf))
- return EX_OK;
-
- /* build actual database key */
-
- breakout = false;
- for (up = UdbEnts; !breakout; up++)
- {
- int usersize;
- int userleft;
- char userbuf[MEMCHUNKSIZE];
-# if HESIOD && HES_GETMAILHOST
- char pobuf[MAXNAME];
-# endif /* HESIOD && HES_GETMAILHOST */
-# if defined(NEWDB) && DB_VERSION_MAJOR > 1
- DBC *dbc = NULL;
-# endif /* defined(NEWDB) && DB_VERSION_MAJOR > 1 */
-
- user = userbuf;
- userbuf[0] = '\0';
- usersize = sizeof(userbuf);
- userleft = sizeof(userbuf) - 1;
-
- /*
- ** Select action based on entry type.
- **
- ** On dropping out of this switch, "class" should
- ** explain the type of the data, and "user" should
- ** contain the user information.
- */
-
- switch (up->udb_type)
- {
-# if NEWDB
- case UDB_DBFETCH:
- key.data = keybuf;
- key.size = keylen;
- if (tTd(28, 80))
- sm_dprintf("udbexpand: trying %s (%d) via db\n",
- keybuf, keylen);
-# if DB_VERSION_MAJOR < 2
- i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR);
-# else /* DB_VERSION_MAJOR < 2 */
- i = 0;
- if (dbc == NULL &&
-# if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
- (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
- NULL, &dbc, 0)) != 0)
-# else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
- (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
- NULL, &dbc)) != 0)
-# endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
- i = -1;
- if (i != 0 || dbc == NULL ||
- (errno = dbc->c_get(dbc, &key,
- &info, DB_SET)) != 0)
- i = 1;
-# endif /* DB_VERSION_MAJOR < 2 */
- if (i > 0 || info.size <= 0)
- {
- if (tTd(28, 2))
- sm_dprintf("udbexpand: no match on %s (%d)\n",
- keybuf, keylen);
-# if DB_VERSION_MAJOR > 1
- if (dbc != NULL)
- {
- (void) dbc->c_close(dbc);
- dbc = NULL;
- }
-# endif /* DB_VERSION_MAJOR > 1 */
- break;
- }
- if (tTd(28, 80))
- sm_dprintf("udbexpand: match %.*s: %.*s\n",
- (int) key.size, (char *) key.data,
- (int) info.size, (char *) info.data);
-
- a->q_flags &= ~QSELFREF;
- while (i == 0 && key.size == keylen &&
- memcmp(key.data, keybuf, keylen) == 0)
- {
- char *p;
-
- if (bitset(EF_VRFYONLY, e->e_flags))
- {
- a->q_state = QS_VERIFIED;
-# if DB_VERSION_MAJOR > 1
- if (dbc != NULL)
- {
- (void) dbc->c_close(dbc);
- dbc = NULL;
- }
-# endif /* DB_VERSION_MAJOR > 1 */
- return EX_OK;
- }
-
- breakout = true;
- if (info.size >= userleft - 1)
- {
- char *nuser;
- int size = MEMCHUNKSIZE;
-
- if (info.size > MEMCHUNKSIZE)
- size = info.size;
- nuser = sm_malloc_x(usersize + size);
-
- memmove(nuser, user, usersize);
- if (user != userbuf)
- sm_free(user); /* XXX */
- user = nuser;
- usersize += size;
- userleft += size;
- }
- p = &user[strlen(user)];
- if (p != user)
- {
- *p++ = ',';
- userleft--;
- }
- memmove(p, info.data, info.size);
- p[info.size] = '\0';
- userleft -= info.size;
-
- /* get the next record */
-# if DB_VERSION_MAJOR < 2
- i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT);
-# else /* DB_VERSION_MAJOR < 2 */
- i = 0;
- if ((errno = dbc->c_get(dbc, &key,
- &info, DB_NEXT)) != 0)
- i = 1;
-# endif /* DB_VERSION_MAJOR < 2 */
- }
-
-# if DB_VERSION_MAJOR > 1
- if (dbc != NULL)
- {
- (void) dbc->c_close(dbc);
- dbc = NULL;
- }
-# endif /* DB_VERSION_MAJOR > 1 */
-
- /* if nothing ever matched, try next database */
- if (!breakout)
- break;
-
- message("expanded to %s", user);
- if (LogLevel > 10)
- sm_syslog(LOG_INFO, e->e_id,
- "expand %.100s => %s",
- e->e_to,
- shortenstring(user, MAXSHORTSTR));
- naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
- if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
- {
- if (tTd(28, 5))
- {
- sm_dprintf("udbexpand: QS_EXPANDED ");
- printaddr(sm_debug_file(), a, false);
- }
- a->q_state = QS_EXPANDED;
- }
- if (i < 0)
- {
- syserr("udbexpand: db-get %.*s stat %d",
- (int) key.size, (char *) key.data, i);
- return EX_TEMPFAIL;
- }
-
- /*
- ** If this address has a -request address, reflect
- ** it into the envelope.
- */
-
- memset(&key, '\0', sizeof(key));
- memset(&info, '\0', sizeof(info));
- (void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, a->q_user,
- ":mailsender");
- keylen = strlen(keybuf);
- key.data = keybuf;
- key.size = keylen;
-
-# if DB_VERSION_MAJOR < 2
- i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
-# else /* DB_VERSION_MAJOR < 2 */
- i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
- &key, &info, 0);
-# endif /* DB_VERSION_MAJOR < 2 */
- if (i != 0 || info.size <= 0)
- break;
- a->q_owner = sm_rpool_malloc_x(e->e_rpool,
- info.size + 1);
- memmove(a->q_owner, info.data, info.size);
- a->q_owner[info.size] = '\0';
-
- /* announce delivery; NORECEIPT bit set later */
- if (e->e_xfp != NULL)
- {
- (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
- "Message delivered to mailing list %s\n",
- a->q_paddr);
- }
- e->e_flags |= EF_SENDRECEIPT;
- a->q_flags |= QDELIVERED|QEXPANDED;
- break;
-# endif /* NEWDB */
-
-# if HESIOD
- case UDB_HESIOD:
- key.data = keybuf;
- key.size = keylen;
- if (tTd(28, 80))
- sm_dprintf("udbexpand: trying %s (%d) via hesiod\n",
- keybuf, keylen);
- /* look up the key via hesiod */
- i = hes_udb_get(&key, &info);
- if (i < 0)
- {
- syserr("udbexpand: hesiod-get %.*s stat %d",
- (int) key.size, (char *) key.data, i);
- return EX_TEMPFAIL;
- }
- else if (i > 0 || info.size <= 0)
- {
-# if HES_GETMAILHOST
- struct hes_postoffice *hp;
-# endif /* HES_GETMAILHOST */
-
- if (tTd(28, 2))
- sm_dprintf("udbexpand: no match on %s (%d)\n",
- (char *) keybuf, (int) keylen);
-# if HES_GETMAILHOST
- if (tTd(28, 8))
- sm_dprintf(" ... trying hes_getmailhost(%s)\n",
- a->q_user);
- hp = hes_getmailhost(a->q_user);
- if (hp == NULL)
- {
- if (hes_error() == HES_ER_NET)
- {
- syserr("udbexpand: hesiod-getmail %s stat %d",
- a->q_user, hes_error());
- return EX_TEMPFAIL;
- }
- if (tTd(28, 2))
- sm_dprintf("hes_getmailhost(%s): %d\n",
- a->q_user, hes_error());
- break;
- }
- if (strlen(hp->po_name) + strlen(hp->po_host) >
- sizeof(pobuf) - 2)
- {
- if (tTd(28, 2))
- sm_dprintf("hes_getmailhost(%s): expansion too long: %.30s@%.30s\n",
- a->q_user,
- hp->po_name,
- hp->po_host);
- break;
- }
- info.data = pobuf;
- (void) sm_snprintf(pobuf, sizeof(pobuf),
- "%s@%s", hp->po_name, hp->po_host);
- info.size = strlen(info.data);
-# else /* HES_GETMAILHOST */
- break;
-# endif /* HES_GETMAILHOST */
- }
- if (tTd(28, 80))
- sm_dprintf("udbexpand: match %.*s: %.*s\n",
- (int) key.size, (char *) key.data,
- (int) info.size, (char *) info.data);
- a->q_flags &= ~QSELFREF;
-
- if (bitset(EF_VRFYONLY, e->e_flags))
- {
- a->q_state = QS_VERIFIED;
- return EX_OK;
- }
-
- breakout = true;
- if (info.size >= usersize)
- user = sm_malloc_x(info.size + 1);
- memmove(user, info.data, info.size);
- user[info.size] = '\0';
-
- message("hesioded to %s", user);
- if (LogLevel > 10)
- sm_syslog(LOG_INFO, e->e_id,
- "hesiod %.100s => %s",
- e->e_to,
- shortenstring(user, MAXSHORTSTR));
- naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
-
- if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
- {
- if (tTd(28, 5))
- {
- sm_dprintf("udbexpand: QS_EXPANDED ");
- printaddr(sm_debug_file(), a, false);
- }
- a->q_state = QS_EXPANDED;
- }
-
- /*
- ** If this address has a -request address, reflect
- ** it into the envelope.
- */
-
- (void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, a->q_user,
- ":mailsender");
- keylen = strlen(keybuf);
- key.data = keybuf;
- key.size = keylen;
- i = hes_udb_get(&key, &info);
- if (i != 0 || info.size <= 0)
- break;
- a->q_owner = sm_rpool_malloc_x(e->e_rpool,
- info.size + 1);
- memmove(a->q_owner, info.data, info.size);
- a->q_owner[info.size] = '\0';
- break;
-# endif /* HESIOD */
-
- case UDB_REMOTE:
- /* not yet implemented */
- break;
-
- case UDB_FORWARD:
- if (bitset(EF_VRFYONLY, e->e_flags))
- {
- a->q_state = QS_VERIFIED;
- return EX_OK;
- }
- i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
- if (i >= usersize)
- {
- usersize = i + 1;
- user = sm_malloc_x(usersize);
- }
- (void) sm_strlcpyn(user, usersize, 3,
- a->q_user, "@", up->udb_fwdhost);
- message("expanded to %s", user);
- a->q_flags &= ~QSELFREF;
- naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
- if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
- {
- if (tTd(28, 5))
- {
- sm_dprintf("udbexpand: QS_EXPANDED ");
- printaddr(sm_debug_file(), a, false);
- }
- a->q_state = QS_EXPANDED;
- }
- breakout = true;
- break;
-
- case UDB_EOLIST:
- breakout = true;
- break;
-
- default:
- /* unknown entry type */
- break;
- }
- /* XXX if an exception occurs, there is a storage leak */
- if (user != userbuf)
- sm_free(user); /* XXX */
- }
- return EX_OK;
-}
-/*
-** UDBSENDER -- return canonical external name of sender, given local name
-**
-** Parameters:
-** sender -- the name of the sender on the local machine.
-** rpool -- resource pool from which to allocate result
-**
-** Returns:
-** The external name for this sender, if derivable from the
-** database. Storage allocated from rpool.
-** NULL -- if nothing is changed from the database.
-**
-** Side Effects:
-** none.
-*/
-
-char *
-udbsender(sender, rpool)
- char *sender;
- SM_RPOOL_T *rpool;
-{
- return udbmatch(sender, "mailname", rpool);
-}
-/*
-** UDBMATCH -- match user in field, return result of lookup.
-**
-** Parameters:
-** user -- the name of the user.
-** field -- the field to lookup.
-** rpool -- resource pool from which to allocate result
-**
-** Returns:
-** The external name for this sender, if derivable from the
-** database. Storage allocated from rpool.
-** NULL -- if nothing is changed from the database.
-**
-** Side Effects:
-** none.
-*/
-
-static char *
-udbmatch(user, field, rpool)
- char *user;
- char *field;
- SM_RPOOL_T *rpool;
-{
- register char *p;
- register struct udbent *up;
- int i;
- int keylen;
- DBT key, info;
- char keybuf[MAXUDBKEY];
-
- if (tTd(28, 1))
- sm_dprintf("udbmatch(%s, %s)\n", user, field);
-
- if (!UdbInitialized)
- {
- if (_udbx_init(CurEnv) == EX_TEMPFAIL)
- return NULL;
- }
-
- /* short circuit if no spec */
- if (UdbSpec == NULL || UdbSpec[0] == '\0')
- return NULL;
-
- /* short circuit name begins with '\\' since it can't possibly match */
- if (user[0] == '\\')
- return NULL;
-
- /* long names can never match and are a pain to deal with */
- i = strlen(field);
- if (i < sizeof("maildrop"))
- i = sizeof("maildrop");
- if ((strlen(user) + i) > sizeof(keybuf) - 4)
- return NULL;
-
- /* names beginning with colons indicate metadata */
- if (user[0] == ':')
- return NULL;
-
- /* build database key */
- (void) sm_strlcpyn(keybuf, sizeof(keybuf), 3, user, ":", field);
- keylen = strlen(keybuf);
-
- for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
- {
- /*
- ** Select action based on entry type.
- */
-
- switch (up->udb_type)
- {
-# if NEWDB
- case UDB_DBFETCH:
- memset(&key, '\0', sizeof(key));
- memset(&info, '\0', sizeof(info));
- key.data = keybuf;
- key.size = keylen;
-# if DB_VERSION_MAJOR < 2
- i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
-# else /* DB_VERSION_MAJOR < 2 */
- i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
- &key, &info, 0);
-# endif /* DB_VERSION_MAJOR < 2 */
- if (i != 0 || info.size <= 0)
- {
- if (tTd(28, 2))
- sm_dprintf("udbmatch: no match on %s (%d) via db\n",
- keybuf, keylen);
- continue;
- }
-
- p = sm_rpool_malloc_x(rpool, info.size + 1);
- memmove(p, info.data, info.size);
- p[info.size] = '\0';
- if (tTd(28, 1))
- sm_dprintf("udbmatch ==> %s\n", p);
- return p;
-# endif /* NEWDB */
-
-# if HESIOD
- case UDB_HESIOD:
- key.data = keybuf;
- key.size = keylen;
- i = hes_udb_get(&key, &info);
- if (i != 0 || info.size <= 0)
- {
- if (tTd(28, 2))
- sm_dprintf("udbmatch: no match on %s (%d) via hesiod\n",
- keybuf, keylen);
- continue;
- }
-
- p = sm_rpool_malloc_x(rpool, info.size + 1);
- memmove(p, info.data, info.size);
- p[info.size] = '\0';
- if (tTd(28, 1))
- sm_dprintf("udbmatch ==> %s\n", p);
- return p;
-# endif /* HESIOD */
- }
- }
-
- if (strcmp(field, "mailname") != 0)
- return NULL;
-
- /*
- ** Nothing yet. Search again for a default case. But only
- ** use it if we also have a forward (:maildrop) pointer already
- ** in the database.
- */
-
- /* build database key */
- (void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, user, ":maildrop");
- keylen = strlen(keybuf);
-
- for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
- {
- switch (up->udb_type)
- {
-# if NEWDB
- case UDB_DBFETCH:
- /* get the default case for this database */
- if (up->udb_default == NULL)
- {
- memset(&key, '\0', sizeof(key));
- memset(&info, '\0', sizeof(info));
- key.data = ":default:mailname";
- key.size = strlen(key.data);
-# if DB_VERSION_MAJOR < 2
- i = (*up->udb_dbp->get)(up->udb_dbp,
- &key, &info, 0);
-# else /* DB_VERSION_MAJOR < 2 */
- i = errno = (*up->udb_dbp->get)(up->udb_dbp,
- NULL, &key,
- &info, 0);
-# endif /* DB_VERSION_MAJOR < 2 */
- if (i != 0 || info.size <= 0)
- {
- /* no default case */
- up->udb_default = "";
- continue;
- }
-
- /* save the default case */
- up->udb_default = sm_pmalloc_x(info.size + 1);
- memmove(up->udb_default, info.data, info.size);
- up->udb_default[info.size] = '\0';
- }
- else if (up->udb_default[0] == '\0')
- continue;
-
- /* we have a default case -- verify user:maildrop */
- memset(&key, '\0', sizeof(key));
- memset(&info, '\0', sizeof(info));
- key.data = keybuf;
- key.size = keylen;
-# if DB_VERSION_MAJOR < 2
- i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
-# else /* DB_VERSION_MAJOR < 2 */
- i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
- &key, &info, 0);
-# endif /* DB_VERSION_MAJOR < 2 */
- if (i != 0 || info.size <= 0)
- {
- /* nope -- no aliasing for this user */
- continue;
- }
-
- /* they exist -- build the actual address */
- i = strlen(user) + strlen(up->udb_default) + 2;
- p = sm_rpool_malloc_x(rpool, i);
- (void) sm_strlcpyn(p, i, 3, user, "@", up->udb_default);
- if (tTd(28, 1))
- sm_dprintf("udbmatch ==> %s\n", p);
- return p;
-# endif /* NEWDB */
-
-# if HESIOD
- case UDB_HESIOD:
- /* get the default case for this database */
- if (up->udb_default == NULL)
- {
- key.data = ":default:mailname";
- key.size = strlen(key.data);
- i = hes_udb_get(&key, &info);
-
- if (i != 0 || info.size <= 0)
- {
- /* no default case */
- up->udb_default = "";
- continue;
- }
-
- /* save the default case */
- up->udb_default = sm_pmalloc_x(info.size + 1);
- memmove(up->udb_default, info.data, info.size);
- up->udb_default[info.size] = '\0';
- }
- else if (up->udb_default[0] == '\0')
- continue;
-
- /* we have a default case -- verify user:maildrop */
- key.data = keybuf;
- key.size = keylen;
- i = hes_udb_get(&key, &info);
- if (i != 0 || info.size <= 0)
- {
- /* nope -- no aliasing for this user */
- continue;
- }
-
- /* they exist -- build the actual address */
- i = strlen(user) + strlen(up->udb_default) + 2;
- p = sm_rpool_malloc_x(rpool, i);
- (void) sm_strlcpyn(p, i, 3, user, "@", up->udb_default);
- if (tTd(28, 1))
- sm_dprintf("udbmatch ==> %s\n", p);
- return p;
- break;
-# endif /* HESIOD */
- }
- }
-
- /* still nothing.... too bad */
- return NULL;
-}
-/*
-** UDB_MAP_LOOKUP -- look up arbitrary entry in user database map
-**
-** Parameters:
-** map -- the map being queried.
-** name -- the name to look up.
-** av -- arguments to the map lookup.
-** statp -- to get any error status.
-**
-** Returns:
-** NULL if name not found in map.
-** The rewritten name otherwise.
-*/
-
-/* ARGSUSED3 */
-char *
-udb_map_lookup(map, name, av, statp)
- MAP *map;
- char *name;
- char **av;
- int *statp;
-{
- char *val;
- char *key;
- char *SM_NONVOLATILE result = NULL;
- char keybuf[MAXNAME + 1];
-
- if (tTd(28, 20) || tTd(38, 20))
- sm_dprintf("udb_map_lookup(%s, %s)\n", map->map_mname, name);
-
- if (bitset(MF_NOFOLDCASE, map->map_mflags))
- {
- key = name;
- }
- else
- {
- int keysize = strlen(name);
-
- if (keysize > sizeof(keybuf) - 1)
- keysize = sizeof(keybuf) - 1;
- memmove(keybuf, name, keysize);
- keybuf[keysize] = '\0';
- makelower(keybuf);
- key = keybuf;
- }
- val = udbmatch(key, map->map_file, NULL);
- if (val == NULL)
- return NULL;
- SM_TRY
- if (bitset(MF_MATCHONLY, map->map_mflags))
- result = map_rewrite(map, name, strlen(name), NULL);
- else
- result = map_rewrite(map, val, strlen(val), av);
- SM_FINALLY
- sm_free(val);
- SM_END_TRY
- return result;
-}
-/*
-** _UDBX_INIT -- parse the UDB specification, opening any valid entries.
-**
-** Parameters:
-** e -- the current envelope.
-**
-** Returns:
-** EX_TEMPFAIL -- if it appeared it couldn't get hold of a
-** database due to a host being down or some similar
-** (recoverable) situation.
-** EX_OK -- otherwise.
-**
-** Side Effects:
-** Fills in the UdbEnts structure from UdbSpec.
-*/
-
-# define MAXUDBOPTS 27
-
-static int
-_udbx_init(e)
- ENVELOPE *e;
-{
- int ents = 0;
- register char *p;
- register struct udbent *up;
-
- if (UdbInitialized)
- return EX_OK;
-
-# ifdef UDB_DEFAULT_SPEC
- if (UdbSpec == NULL)
- UdbSpec = UDB_DEFAULT_SPEC;
-# endif /* UDB_DEFAULT_SPEC */
-
- p = UdbSpec;
- up = UdbEnts;
- while (p != NULL)
- {
- char *spec;
- int l;
- struct udb_option opts[MAXUDBOPTS + 1];
-
- while (*p == ' ' || *p == '\t' || *p == ',')
- p++;
- if (*p == '\0')
- break;
- spec = p;
- p = strchr(p, ',');
- if (p != NULL)
- *p++ = '\0';
-
- if (ents >= MAXUDBENT)
- {
- syserr("Maximum number of UDB entries exceeded");
- break;
- }
-
- /* extract options */
- (void) _udb_parsespec(spec, opts, MAXUDBOPTS);
-
- /*
- ** Decode database specification.
- **
- ** In the sendmail tradition, the leading character
- ** defines the semantics of the rest of the entry.
- **
- ** @hostname -- forward email to the indicated host.
- ** This should be the last in the list,
- ** since it always matches the input.
- ** /dbname -- search the named database on the local
- ** host using the Berkeley db package.
- ** Hesiod -- search the named database with BIND
- ** using the MIT Hesiod package.
- */
-
- switch (*spec)
- {
- case '@': /* forward to remote host */
- up->udb_type = UDB_FORWARD;
- up->udb_pid = CurrentPid;
- up->udb_fwdhost = spec + 1;
- ents++;
- up++;
- break;
-
-# if HESIOD
- case 'h': /* use hesiod */
- case 'H':
- if (sm_strcasecmp(spec, "hesiod") != 0)
- goto badspec;
- up->udb_type = UDB_HESIOD;
- up->udb_pid = CurrentPid;
- ents++;
- up++;
- break;
-# endif /* HESIOD */
-
-# if NEWDB
- case '/': /* look up remote name */
- l = strlen(spec);
- if (l > 3 && strcmp(&spec[l - 3], ".db") == 0)
- {
- up->udb_dbname = spec;
- }
- else
- {
- up->udb_dbname = sm_pmalloc_x(l + 4);
- (void) sm_strlcpyn(up->udb_dbname, l + 4, 2,
- spec, ".db");
- }
- errno = 0;
-# if DB_VERSION_MAJOR < 2
- up->udb_dbp = dbopen(up->udb_dbname, O_RDONLY,
- 0644, DB_BTREE, NULL);
-# else /* DB_VERSION_MAJOR < 2 */
- {
- int flags = DB_RDONLY;
-# if DB_VERSION_MAJOR > 2
- int ret;
-# endif /* DB_VERSION_MAJOR > 2 */
-
- SM_DB_FLAG_ADD(flags);
- up->udb_dbp = NULL;
-# if DB_VERSION_MAJOR > 2
- ret = db_create(&up->udb_dbp, NULL, 0);
- if (ret != 0)
- {
- (void) up->udb_dbp->close(up->udb_dbp,
- 0);
- up->udb_dbp = NULL;
- }
- else
- {
- ret = up->udb_dbp->open(up->udb_dbp,
- DBTXN
- up->udb_dbname,
- NULL,
- DB_BTREE,
- flags,
- 0644);
- if (ret != 0)
- {
-#ifdef DB_OLD_VERSION
- if (ret == DB_OLD_VERSION)
- ret = EINVAL;
-#endif /* DB_OLD_VERSION */
- (void) up->udb_dbp->close(up->udb_dbp, 0);
- up->udb_dbp = NULL;
- }
- }
- errno = ret;
-# else /* DB_VERSION_MAJOR > 2 */
- errno = db_open(up->udb_dbname, DB_BTREE,
- flags, 0644, NULL,
- NULL, &up->udb_dbp);
-# endif /* DB_VERSION_MAJOR > 2 */
- }
-# endif /* DB_VERSION_MAJOR < 2 */
- if (up->udb_dbp == NULL)
- {
- if (tTd(28, 1))
- {
- int save_errno = errno;
-
-# if DB_VERSION_MAJOR < 2
- sm_dprintf("dbopen(%s): %s\n",
-# else /* DB_VERSION_MAJOR < 2 */
- sm_dprintf("db_open(%s): %s\n",
-# endif /* DB_VERSION_MAJOR < 2 */
- up->udb_dbname,
- sm_errstring(errno));
- errno = save_errno;
- }
- if (errno != ENOENT && errno != EACCES)
- {
- if (LogLevel > 2)
- sm_syslog(LOG_ERR, e->e_id,
-# if DB_VERSION_MAJOR < 2
- "dbopen(%s): %s",
-# else /* DB_VERSION_MAJOR < 2 */
- "db_open(%s): %s",
-# endif /* DB_VERSION_MAJOR < 2 */
- up->udb_dbname,
- sm_errstring(errno));
- up->udb_type = UDB_EOLIST;
- if (up->udb_dbname != spec)
- sm_free(up->udb_dbname); /* XXX */
- goto tempfail;
- }
- if (up->udb_dbname != spec)
- sm_free(up->udb_dbname); /* XXX */
- break;
- }
- if (tTd(28, 1))
- {
-# if DB_VERSION_MAJOR < 2
- sm_dprintf("_udbx_init: dbopen(%s)\n",
-# else /* DB_VERSION_MAJOR < 2 */
- sm_dprintf("_udbx_init: db_open(%s)\n",
-# endif /* DB_VERSION_MAJOR < 2 */
- up->udb_dbname);
- }
- up->udb_type = UDB_DBFETCH;
- up->udb_pid = CurrentPid;
- ents++;
- up++;
- break;
-# endif /* NEWDB */
-
- default:
-# if HESIOD
-badspec:
-# endif /* HESIOD */
- syserr("Unknown UDB spec %s", spec);
- break;
- }
- }
- up->udb_type = UDB_EOLIST;
-
- if (tTd(28, 4))
- {
- for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
- {
- switch (up->udb_type)
- {
- case UDB_REMOTE:
- sm_dprintf("REMOTE: addr %s, timeo %d\n",
- anynet_ntoa((SOCKADDR *) &up->udb_addr),
- up->udb_timeout);
- break;
-
- case UDB_DBFETCH:
-# if NEWDB
- sm_dprintf("FETCH: file %s\n",
- up->udb_dbname);
-# else /* NEWDB */
- sm_dprintf("FETCH\n");
-# endif /* NEWDB */
- break;
-
- case UDB_FORWARD:
- sm_dprintf("FORWARD: host %s\n",
- up->udb_fwdhost);
- break;
-
- case UDB_HESIOD:
- sm_dprintf("HESIOD\n");
- break;
-
- default:
- sm_dprintf("UNKNOWN\n");
- break;
- }
- }
- }
-
- UdbInitialized = true;
- errno = 0;
- return EX_OK;
-
- /*
- ** On temporary failure, back out anything we've already done
- */
-
- tempfail:
-# if NEWDB
- for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
- {
- if (up->udb_type == UDB_DBFETCH)
- {
-# if DB_VERSION_MAJOR < 2
- (*up->udb_dbp->close)(up->udb_dbp);
-# else /* DB_VERSION_MAJOR < 2 */
- errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
-# endif /* DB_VERSION_MAJOR < 2 */
- if (tTd(28, 1))
- sm_dprintf("_udbx_init: db->close(%s)\n",
- up->udb_dbname);
- }
- }
-# endif /* NEWDB */
- return EX_TEMPFAIL;
-}
-
-static int
-_udb_parsespec(udbspec, opt, maxopts)
- char *udbspec;
- struct udb_option opt[];
- int maxopts;
-{
- register char *spec;
- register char *spec_end;
- register int optnum;
-
- spec_end = strchr(udbspec, ':');
- for (optnum = 0; optnum < maxopts && (spec = spec_end) != NULL; optnum++)
- {
- register char *p;
-
- while (isascii(*spec) && isspace(*spec))
- spec++;
- spec_end = strchr(spec, ':');
- if (spec_end != NULL)
- *spec_end++ = '\0';
-
- opt[optnum].udbo_name = spec;
- opt[optnum].udbo_val = NULL;
- p = strchr(spec, '=');
- if (p != NULL)
- opt[optnum].udbo_val = ++p;
- }
- return optnum;
-}
-/*
-** _UDBX_CLOSE -- close all file based UDB entries.
-**
-** Parameters:
-** none
-**
-** Returns:
-** none
-*/
-void
-_udbx_close()
-{
- struct udbent *up;
-
- if (!UdbInitialized)
- return;
-
- for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
- {
- if (up->udb_pid != CurrentPid)
- continue;
-
-# if NEWDB
- if (up->udb_type == UDB_DBFETCH)
- {
-# if DB_VERSION_MAJOR < 2
- (*up->udb_dbp->close)(up->udb_dbp);
-# else /* DB_VERSION_MAJOR < 2 */
- errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
-# endif /* DB_VERSION_MAJOR < 2 */
- }
- if (tTd(28, 1))
- sm_dprintf("_udbx_init: db->close(%s)\n",
- up->udb_dbname);
-# endif /* NEWDB */
- }
-}
-
-# if HESIOD
-
-static int
-hes_udb_get(key, info)
- DBT *key;
- DBT *info;
-{
- char *name, *type;
- char **hp;
- char kbuf[MAXUDBKEY + 1];
-
- if (sm_strlcpy(kbuf, key->data, sizeof(kbuf)) >= sizeof(kbuf))
- return 0;
- name = kbuf;
- type = strrchr(name, ':');
- if (type == NULL)
- return 1;
- *type++ = '\0';
- if (strchr(name, '@') != NULL)
- return 1;
-
- if (tTd(28, 1))
- sm_dprintf("hes_udb_get(%s, %s)\n", name, type);
-
- /* make the hesiod query */
-# ifdef HESIOD_INIT
- if (HesiodContext == NULL && hesiod_init(&HesiodContext) != 0)
- return -1;
- hp = hesiod_resolve(HesiodContext, name, type);
-# else /* HESIOD_INIT */
- hp = hes_resolve(name, type);
-# endif /* HESIOD_INIT */
- *--type = ':';
-# ifdef HESIOD_INIT
- if (hp == NULL)
- return 1;
- if (*hp == NULL)
- {
- hesiod_free_list(HesiodContext, hp);
- if (errno == ECONNREFUSED || errno == EMSGSIZE)
- return -1;
- return 1;
- }
-# else /* HESIOD_INIT */
- if (hp == NULL || hp[0] == NULL)
- {
- /* network problem or timeout */
- if (hes_error() == HES_ER_NET)
- return -1;
-
- return 1;
- }
-# endif /* HESIOD_INIT */
- else
- {
- /*
- ** If there are multiple matches, just return the
- ** first one.
- **
- ** XXX These should really be returned; for example,
- ** XXX it is legal for :maildrop to be multi-valued.
- */
-
- info->data = hp[0];
- info->size = (size_t) strlen(info->data);
- }
-
- if (tTd(28, 80))
- sm_dprintf("hes_udb_get => %s\n", *hp);
-
- return 0;
-}
-# endif /* HESIOD */
-
-#else /* USERDB */
-
-int
-udbexpand(a, sendq, aliaslevel, e)
- ADDRESS *a;
- ADDRESS **sendq;
- int aliaslevel;
- ENVELOPE *e;
-{
- return EX_OK;
-}
-
-#endif /* USERDB */
OpenPOWER on IntegriCloud