summaryrefslogtreecommitdiff
path: root/src/udb.c
diff options
context:
space:
mode:
authorAndreas Beckmann <debian@abeckmann.de>2012-10-01 19:58:38 +0200
committerAndreas Beckmann <debian@abeckmann.de>2012-10-01 19:58:38 +0200
commit6b71060b84a2d9111ec847e66cc5160aab8a45e8 (patch)
tree599eb55ae3e0ec0f95d829c185831f3027eec78b /src/udb.c
parent6c193ce1dd1d07ebdc1372e38bc4908ab1c37705 (diff)
downloadsendmail-6b71060b84a2d9111ec847e66cc5160aab8a45e8.tar.gz
Imported Upstream version 8.9.3upstream/8.9.3
Diffstat (limited to 'src/udb.c')
-rw-r--r--src/udb.c283
1 files changed, 229 insertions, 54 deletions
diff --git a/src/udb.c b/src/udb.c
index cf77bdc..96c6513 100644
--- a/src/udb.c
+++ b/src/udb.c
@@ -1,44 +1,22 @@
/*
- * Copyright (c) 1983, 1995-1997 Eric P. Allman
+ * Copyright (c) 1998 Sendmail, Inc. 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.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * 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.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
*/
#include "sendmail.h"
#ifndef lint
#if USERDB
-static char sccsid [] = "@(#)udb.c 8.51 (Berkeley) 5/29/97 (with USERDB)";
+static char sccsid [] = "@(#)udb.c 8.71 (Berkeley) 1/17/1999 (with USERDB)";
#else
-static char sccsid [] = "@(#)udb.c 8.51 (Berkeley) 5/29/97 (without USERDB)";
+static char sccsid [] = "@(#)udb.c 8.71 (Berkeley) 1/17/1999 (without USERDB)";
#endif
#endif
@@ -48,6 +26,9 @@ static char sccsid [] = "@(#)udb.c 8.51 (Berkeley) 5/29/97 (without USERDB)";
#ifdef NEWDB
# include <db.h>
+# ifndef DB_VERSION_MAJOR
+# define DB_VERSION_MAJOR 1
+# endif
#else
# define DBT struct _data_base_thang_
DBT
@@ -57,10 +38,6 @@ DBT
};
#endif
-#ifdef HESIOD
-# include <hesiod.h>
-#endif /* HESIOD */
-
/*
** UDB.C -- interface between sendmail and Berkeley User Data Base.
**
@@ -72,6 +49,7 @@ 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
{
@@ -114,12 +92,15 @@ struct udbent
#define MAXUDBENT 10 /* maximum number of UDB entries */
-struct option
+struct udb_option
{
char *name;
char *val;
};
+#ifdef HESIOD
+extern int hes_udb_get __P((DBT *, DBT *));
+#endif
extern int _udbx_init __P((ENVELOPE *));
/*
** UDBEXPAND -- look up user in database and expand
@@ -160,8 +141,12 @@ udbexpand(a, sendq, aliaslevel, e)
register struct udbent *up;
int keylen;
int naddrs;
+ char *user;
char keybuf[MAXKEY];
+ bzero(&key, sizeof key);
+ bzero(&info, sizeof info);
+
if (tTd(28, 1))
printf("udbexpand(%s)\n", a->q_paddr);
@@ -181,20 +166,24 @@ udbexpand(a, sendq, aliaslevel, e)
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 */
- if (a->q_user[0] == '\\')
+ /* (might want to treat this as unquoted instead) */
+ if (user[0] == '\\')
return EX_OK;
/* if name is too long, assume it won't match */
- if (strlen(a->q_user) > (SIZE_T) sizeof keybuf - 12)
+ if (strlen(user) > (SIZE_T) sizeof keybuf - 12)
return EX_OK;
/* if name begins with a colon, it indicates our metadata */
- if (a->q_user[0] == ':')
+ if (user[0] == ':')
return EX_OK;
/* build actual database key */
- (void) strcpy(keybuf, a->q_user);
+ (void) strcpy(keybuf, user);
(void) strcat(keybuf, ":maildrop");
keylen = strlen(keybuf);
@@ -208,6 +197,9 @@ udbexpand(a, sendq, aliaslevel, e)
#if defined(HESIOD) && defined(HES_GETMAILHOST)
char pobuf[MAXNAME];
#endif
+#if defined(NEWDB) && DB_VERSION_MAJOR > 1
+ DBC *dbc = NULL;
+#endif
user = userbuf;
userbuf[0] = '\0';
@@ -231,12 +223,36 @@ udbexpand(a, sendq, aliaslevel, e)
if (tTd(28, 80))
printf("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
+ 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
+ (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
+ NULL, &dbc)) != 0)
+# endif
+ i = -1;
+ if (i != 0 || dbc == NULL ||
+ (errno = dbc->c_get(dbc, &key,
+ &info, DB_SET)) != 0)
+ i = 1;
+#endif
if (i > 0 || info.size <= 0)
{
if (tTd(28, 2))
printf("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
break;
}
if (tTd(28, 80))
@@ -253,6 +269,13 @@ udbexpand(a, sendq, aliaslevel, e)
if (bitset(EF_VRFYONLY, e->e_flags))
{
a->q_flags |= QVERIFIED;
+#if DB_VERSION_MAJOR > 1
+ if (dbc != NULL)
+ {
+ (void) dbc->c_close(dbc);
+ dbc = NULL;
+ }
+#endif
return EX_OK;
}
@@ -284,9 +307,24 @@ udbexpand(a, sendq, aliaslevel, e)
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
+ i = 0;
+ if ((errno = dbc->c_get(dbc, &key,
+ &info, DB_NEXT)) != 0)
+ i = 1;
+#endif
}
+#if DB_VERSION_MAJOR > 1
+ if (dbc != NULL)
+ {
+ (void) dbc->c_close(dbc);
+ dbc = NULL;
+ }
+#endif
+
/* if nothing ever matched, try next database */
if (!breakout)
break;
@@ -296,7 +334,7 @@ udbexpand(a, sendq, aliaslevel, e)
sm_syslog(LOG_INFO, e->e_id,
"expand %.100s => %s",
e->e_to,
- shortenstring(user, 203));
+ shortenstring(user, MAXSHORTSTR));
naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
{
@@ -310,7 +348,7 @@ udbexpand(a, sendq, aliaslevel, e)
if (i < 0)
{
syserr("udbexpand: db-get %.*s stat %d",
- key.size, key.data, i);
+ (int) key.size, (char *) key.data, i);
return EX_TEMPFAIL;
}
@@ -319,12 +357,20 @@ udbexpand(a, sendq, aliaslevel, e)
** it into the envelope.
*/
+ bzero(&key, sizeof key);
+ bzero(&info, sizeof info);
(void) strcpy(keybuf, a->q_user);
(void) strcat(keybuf, ":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
+ i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
+ &key, &info, 0);
+#endif
if (i != 0 || info.size <= 0)
break;
a->q_owner = xalloc(info.size + 1);
@@ -355,7 +401,7 @@ udbexpand(a, sendq, aliaslevel, e)
if (i < 0)
{
syserr("udbexpand: hesiod-get %.*s stat %d",
- key.size, key.data, i);
+ (int) key.size, (char *) key.data, i);
return EX_TEMPFAIL;
}
else if (i > 0 || info.size <= 0)
@@ -366,7 +412,7 @@ udbexpand(a, sendq, aliaslevel, e)
if (tTd(28, 2))
printf("udbexpand: no match on %s (%d)\n",
- keybuf, keylen);
+ (char *) keybuf, (int) keylen);
#if HES_GETMAILHOST
if (tTd(28, 8))
printf(" ... trying hes_getmailhost(%s)\n",
@@ -405,7 +451,8 @@ udbexpand(a, sendq, aliaslevel, e)
}
if (tTd(28, 80))
printf("udbexpand: match %.*s: %.*s\n",
- key.size, key.data, info.size, info.data);
+ (int) key.size, (char *) key.data,
+ (int) info.size, (char *) info.data);
a->q_flags &= ~QSELFREF;
if (bitset(EF_VRFYONLY, e->e_flags))
@@ -425,7 +472,7 @@ udbexpand(a, sendq, aliaslevel, e)
sm_syslog(LOG_INFO, e->e_id,
"hesiod %.100s => %s",
e->e_to,
- shortenstring(user, 203));
+ shortenstring(user, MAXSHORTSTR));
naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
@@ -519,7 +566,7 @@ char *
udbsender(sender)
char *sender;
{
- extern char *udbmatch();
+ extern char *udbmatch __P((char *, char *));
return udbmatch(sender, "mailname");
}
@@ -581,9 +628,16 @@ udbmatch(user, field)
{
#ifdef NEWDB
case UDB_DBFETCH:
+ bzero(&key, sizeof key);
+ bzero(&info, 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
+ i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
+ &key, &info, 0);
+#endif
if (i != 0 || info.size <= 0)
{
if (tTd(28, 2))
@@ -598,7 +652,6 @@ udbmatch(user, field)
if (tTd(28, 1))
printf("udbmatch ==> %s\n", p);
return p;
- break;
#endif
#ifdef HESIOD
@@ -647,9 +700,18 @@ udbmatch(user, field)
/* get the default case for this database */
if (up->udb_default == NULL)
{
+ bzero(&key, sizeof key);
+ bzero(&info, sizeof info);
key.data = ":default:mailname";
key.size = strlen(key.data);
- i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
+#if DB_VERSION_MAJOR < 2
+ i = (*up->udb_dbp->get)(up->udb_dbp,
+ &key, &info, 0);
+#else
+ i = errno = (*up->udb_dbp->get)(up->udb_dbp,
+ NULL, &key,
+ &info, 0);
+#endif
if (i != 0 || info.size <= 0)
{
/* no default case */
@@ -666,9 +728,16 @@ udbmatch(user, field)
continue;
/* we have a default case -- verify user:maildrop */
+ bzero(&key, sizeof key);
+ bzero(&info, 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
+ i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
+ &key, &info, 0);
+#endif
if (i != 0 || info.size <= 0)
{
/* nope -- no aliasing for this user */
@@ -683,7 +752,6 @@ udbmatch(user, field)
if (tTd(28, 1))
printf("udbmatch ==> %s\n", p);
return p;
- break;
#endif
#ifdef HESIOD
@@ -750,6 +818,7 @@ udbmatch(user, field)
** The rewritten name otherwise.
*/
+/* ARGSUSED3 */
char *
udb_map_lookup(map, name, av, statp)
MAP *map;
@@ -809,6 +878,7 @@ int
_udbx_init(e)
ENVELOPE *e;
{
+ int ents = 0;
register char *p;
register struct udbent *up;
@@ -825,7 +895,6 @@ _udbx_init(e)
while (p != NULL)
{
char *spec;
- int nopts;
int l;
# if 0
auto int rcode;
@@ -834,8 +903,8 @@ _udbx_init(e)
register struct hostent *h;
char *mxhosts[MAXMXHOSTS + 1];
# endif
- struct option opts[MAXUDBOPTS + 1];
- extern int _udb_parsespec __P((char *, struct option [], int));
+ struct udb_option opts[MAXUDBOPTS + 1];
+ extern int _udb_parsespec __P((char *, struct udb_option [], int));
while (*p == ' ' || *p == '\t' || *p == ',')
p++;
@@ -846,8 +915,14 @@ _udbx_init(e)
if (p != NULL)
*p++ = '\0';
+ if (ents >= MAXUDBENT)
+ {
+ syserr("Maximum number of UDB entries exceeded");
+ break;
+ }
+
/* extract options */
- nopts = _udb_parsespec(spec, opts, MAXUDBOPTS);
+ (void) _udb_parsespec(spec, opts, MAXUDBOPTS);
/*
** Decode database specification.
@@ -908,12 +983,14 @@ _udbx_init(e)
if (h == NULL)
continue;
up->udb_type = UDB_REMOTE;
+ up->udb_pid = getpid();
up->udb_addr.sin_family = h->h_addrtype;
bcopy(h->h_addr_list[0],
(char *) &up->udb_addr.sin_addr,
INADDRSZ);
up->udb_addr.sin_port = UdbPort;
up->udb_timeout = UdbTimeout;
+ ents++;
up++;
}
@@ -928,7 +1005,9 @@ _udbx_init(e)
case '@': /* forward to remote host */
up->udb_type = UDB_FORWARD;
+ up->udb_pid = getpid();
up->udb_fwdhost = spec + 1;
+ ents++;
up++;
break;
@@ -938,6 +1017,8 @@ _udbx_init(e)
if (strcasecmp(spec, "hesiod") != 0)
goto badspec;
up->udb_type = UDB_HESIOD;
+ up->udb_pid = getpid();
+ ents++;
up++;
break;
#endif /* HESIOD */
@@ -956,15 +1037,25 @@ _udbx_init(e)
strcat(up->udb_dbname, ".db");
}
errno = 0;
+#if DB_VERSION_MAJOR < 2
up->udb_dbp = dbopen(up->udb_dbname, O_RDONLY,
0644, DB_BTREE, NULL);
+#else
+ up->udb_dbp = NULL;
+ errno = db_open(up->udb_dbname, DB_BTREE, DB_RDONLY,
+ 0644, NULL, NULL, &up->udb_dbp);
+#endif
if (up->udb_dbp == NULL)
{
if (tTd(28, 1))
{
int saveerrno = errno;
+#if DB_VERSION_MAJOR < 2
printf("dbopen(%s): %s\n",
+#else
+ printf("db_open(%s): %s\n",
+#endif
up->udb_dbname,
errstring(errno));
errno = saveerrno;
@@ -973,7 +1064,11 @@ _udbx_init(e)
{
if (LogLevel > 2)
sm_syslog(LOG_ERR, e->e_id,
+#if DB_VERSION_MAJOR < 2
"dbopen(%s): %s",
+#else
+ "db_open(%s): %s",
+#endif
up->udb_dbname,
errstring(errno));
up->udb_type = UDB_EOLIST;
@@ -985,7 +1080,18 @@ _udbx_init(e)
free(up->udb_dbname);
break;
}
+ if (tTd(28, 1))
+ {
+#if DB_VERSION_MAJOR < 2
+ printf("_udbx_init: dbopen(%s)\n",
+#else
+ printf("_udbx_init: db_open(%s)\n",
+#endif
+ up->udb_dbname);
+ }
up->udb_type = UDB_DBFETCH;
+ up->udb_pid = getpid();
+ ents++;
up++;
break;
#endif
@@ -1051,7 +1157,16 @@ badspec:
{
if (up->udb_type == UDB_DBFETCH)
{
+#if DB_VERSION_MAJOR < 2
(*up->udb_dbp->close)(up->udb_dbp);
+#else
+ errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
+#endif
+ if (tTd(28, 1))
+ {
+ printf("_udbx_init: db->close(%s)\n",
+ up->udb_dbname);
+ }
}
}
#endif
@@ -1061,7 +1176,7 @@ badspec:
int
_udb_parsespec(udbspec, opt, maxopts)
char *udbspec;
- struct option opt[];
+ struct udb_option opt[];
int maxopts;
{
register char *spec;
@@ -1087,6 +1202,48 @@ _udb_parsespec(udbspec, opt, maxopts)
}
return optnum;
}
+ /*
+** _UDBX_CLOSE -- close all file based UDB entries.
+**
+** Parameters:
+** none
+**
+** Returns:
+** none
+*/
+void
+_udbx_close()
+{
+ pid_t pid;
+ struct udbent *up;
+
+ if (!UdbInitialized)
+ return;
+
+ pid = getpid();
+
+ for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
+ {
+ if (up->udb_pid != pid)
+ continue;
+
+#ifdef NEWDB
+ if (up->udb_type == UDB_DBFETCH)
+ {
+#if DB_VERSION_MAJOR < 2
+ (*up->udb_dbp->close)(up->udb_dbp);
+#else
+ errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
+#endif
+ }
+ if (tTd(28, 1))
+ {
+ printf("_udbx_init: db->close(%s)\n",
+ up->udb_dbname);
+ }
+#endif
+ }
+}
#ifdef HESIOD
@@ -1096,7 +1253,7 @@ hes_udb_get(key, info)
DBT *info;
{
char *name, *type;
- char *p, **hp;
+ char **hp;
char kbuf[MAXKEY + 1];
if (strlen(key->data) >= (SIZE_T) sizeof kbuf)
@@ -1114,8 +1271,25 @@ hes_udb_get(key, info)
printf("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
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
if (hp == NULL || hp[0] == NULL)
{
/* network problem or timeout */
@@ -1124,6 +1298,7 @@ hes_udb_get(key, info)
return 1;
}
+#endif /* HESIOD_INIT */
else
{
/*