summaryrefslogtreecommitdiffstats
path: root/usr.sbin/sendmail/src/udb.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src/udb.c')
-rw-r--r--usr.sbin/sendmail/src/udb.c236
1 files changed, 177 insertions, 59 deletions
diff --git a/usr.sbin/sendmail/src/udb.c b/usr.sbin/sendmail/src/udb.c
index 4739a08..bb83bef 100644
--- a/usr.sbin/sendmail/src/udb.c
+++ b/usr.sbin/sendmail/src/udb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -35,21 +35,30 @@
#include "sendmail.h"
#ifndef lint
-#ifdef USERDB
-static char sccsid [] = "@(#)udb.c 8.8 (Berkeley) 4/14/94 (with USERDB)";
+#if USERDB
+static char sccsid [] = "@(#)udb.c 8.32 (Berkeley) 11/18/95 (with USERDB)";
#else
-static char sccsid [] = "@(#)udb.c 8.8 (Berkeley) 4/14/94 (without USERDB)";
+static char sccsid [] = "@(#)udb.c 8.32 (Berkeley) 11/18/95 (without USERDB)";
#endif
#endif
-#ifdef USERDB
+#if USERDB
#include <errno.h>
-#include <netdb.h>
-#include <db.h>
+
+#ifdef NEWDB
+# include <db.h>
+#else
+# define DBT struct _data_base_thang_
+DBT
+{
+ void *data; /* pointer to data */
+ size_t size; /* length of data */
+};
+#endif
#ifdef HESIOD
-#include <hesiod.h>
+# include <hesiod.h>
#endif /* HESIOD */
/*
@@ -82,6 +91,7 @@ struct udbent
} udb_forward;
#define udb_fwdhost udb_u.udb_forward._udb_fwdhost
+#ifdef NEWDB
/* type UE_FETCH -- lookup in local database */
struct
{
@@ -90,6 +100,7 @@ struct udbent
} udb_lookup;
#define udb_dbname udb_u.udb_lookup._udb_dbname
#define udb_dbp udb_u.udb_lookup._udb_dbp
+#endif
} udb_u;
};
@@ -114,6 +125,8 @@ struct option
** 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
@@ -132,13 +145,13 @@ int UdbSock = -1;
bool UdbInitialized = FALSE;
int
-udbexpand(a, sendq, e)
+udbexpand(a, sendq, aliaslevel, e)
register ADDRESS *a;
ADDRESS **sendq;
+ int aliaslevel;
register ENVELOPE *e;
{
int i;
- register char *p;
DBT key;
DBT info;
bool breakout;
@@ -201,6 +214,7 @@ udbexpand(a, sendq, e)
switch (up->udb_type)
{
+#ifdef NEWDB
case UDB_DBFETCH:
key.data = keybuf;
key.size = keylen;
@@ -227,7 +241,6 @@ udbexpand(a, sendq, e)
if (bitset(EF_VRFYONLY, e->e_flags))
{
a->q_flags |= QVERIFIED;
- e->e_nrcpts++;
return EX_OK;
}
@@ -242,12 +255,11 @@ udbexpand(a, sendq, e)
message("expanded to %s", user);
#ifdef LOG
if (LogLevel >= 10)
- syslog(LOG_INFO, "%s: expand %s => %s",
- e->e_id, e->e_to, user);
+ syslog(LOG_INFO, "%s: expand %.100s => %s",
+ e->e_id, e->e_to,
+ shortenstring(user, 203));
#endif
- AliasLevel++;
- naddrs += sendtolist(user, a, sendq, e);
- AliasLevel--;
+ naddrs += sendtolist(user, a, sendq, aliaslevel + 1, e);
if (user != buf)
free(user);
@@ -299,9 +311,11 @@ udbexpand(a, sendq, e)
fprintf(e->e_xfp,
"Message delivered to mailing list %s\n",
a->q_paddr);
- e->e_flags |= EF_SENDRECEIPT;
}
+ e->e_flags |= EF_SENDRECEIPT;
+ a->q_flags |= QDELIVERED|QEXPANDED;
break;
+#endif
#ifdef HESIOD
case UDB_HESIOD:
@@ -312,12 +326,45 @@ udbexpand(a, sendq, e)
keybuf, keylen);
/* look up the key via hesiod */
i = hes_udb_get(&key, &info);
- if (i > 0 || info.size <= 0)
+ if (i < 0)
{
+ syserr("udbexpand: hesiod-get %.*s stat %d",
+ key.size, key.data, i);
+ return EX_TEMPFAIL;
+ }
+ else if (i > 0 || info.size <= 0)
+ {
+#if HES_GETMAILHOST
+ struct hes_postoffice *hp;
+#endif
+
if (tTd(28, 2))
- printf("udbexpand: no match on %s (%d)\n",
- keybuf, keylen);
+ printf("udbexpand: no match on %s (%d)\n",
+ keybuf, keylen);
+#if HES_GETMAILHOST
+ if (tTd(28, 8))
+ printf(" ... 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))
+ printf("hes_getmailhost(%s): %d\n",
+ a->q_user, hes_error();
+ continue;
+ }
+ sprintf(info.data, "%s@%s",
+ hp->po_name, hp->po_host);
+ info.size = strlen(info.data);
+#else
continue;
+#endif
}
if (tTd(28, 80))
printf("udbexpand: match %.*s: %.*s\n",
@@ -327,8 +374,6 @@ udbexpand(a, sendq, e)
if (bitset(EF_VRFYONLY, e->e_flags))
{
a->q_flags |= QVERIFIED;
- e->e_nrcpts++;
- free(info.data);
return EX_OK;
}
@@ -339,17 +384,15 @@ udbexpand(a, sendq, e)
user = xalloc(info.size + 1);
bcopy(info.data, user, info.size);
user[info.size] = '\0';
- free(info.data);
message("hesioded to %s", user);
#ifdef LOG
if (LogLevel >= 10)
- syslog(LOG_INFO, "%s: hesiod %s => %s",
- e->e_id, e->e_to, user);
+ syslog(LOG_INFO, "%s: hesiod %.100s => %s",
+ e->e_id, e->e_to,
+ shortenstring(user, 203));
#endif
- AliasLevel++;
- naddrs = sendtolist(user, a, sendq, e);
- AliasLevel--;
+ naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (user != buf)
free(user);
@@ -363,12 +406,6 @@ udbexpand(a, sendq, e)
}
a->q_flags |= QDONTSEND;
}
- if (i < 0)
- {
- syserr("udbexpand: hesiod-get %.*s stat %d",
- key.size, key.data, i);
- return EX_TEMPFAIL;
- }
/*
** If this address has a -request address, reflect
@@ -386,7 +423,6 @@ udbexpand(a, sendq, e)
a->q_owner = xalloc(info.size + 1);
bcopy(info.data, a->q_owner, info.size);
a->q_owner[info.size] = '\0';
- free(info.data);
break;
#endif /* HESIOD */
@@ -405,9 +441,7 @@ udbexpand(a, sendq, e)
(void) sprintf(user, "%s@%s", a->q_user, up->udb_fwdhost);
message("expanded to %s", user);
a->q_flags &= ~QSELFREF;
- AliasLevel++;
- naddrs = sendtolist(user, a, sendq, e);
- AliasLevel--;
+ naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
{
if (tTd(28, 5))
@@ -509,6 +543,7 @@ udbmatch(user, field)
switch (up->udb_type)
{
+#ifdef NEWDB
case UDB_DBFETCH:
key.data = keybuf;
key.size = keylen;
@@ -528,6 +563,7 @@ udbmatch(user, field)
printf("udbmatch ==> %s\n", p);
return p;
break;
+#endif
#ifdef HESIOD
case UDB_HESIOD:
@@ -545,11 +581,9 @@ udbmatch(user, field)
p = xalloc(info.size + 1);
bcopy(info.data, p, info.size);
p[info.size] = '\0';
- free(info.data);
if (tTd(28, 1))
printf("udbmatch ==> %s\n", p);
return p;
- break;
#endif /* HESIOD */
}
}
@@ -572,6 +606,7 @@ udbmatch(user, field)
{
switch (up->udb_type)
{
+#ifdef NEWDB
case UDB_DBFETCH:
/* get the default case for this database */
if (up->udb_default == NULL)
@@ -613,6 +648,7 @@ udbmatch(user, field)
printf("udbmatch ==> %s\n", p);
return p;
break;
+#endif
#ifdef HESIOD
case UDB_HESIOD:
@@ -634,7 +670,6 @@ udbmatch(user, field)
up->udb_default = xalloc(info.size + 1);
bcopy(info.data, up->udb_default, info.size);
up->udb_default[info.size] = '\0';
- free(info.data);
}
else if (up->udb_default[0] == '\0')
continue;
@@ -649,7 +684,6 @@ udbmatch(user, field)
continue;
}
- free(info.data);
/* they exist -- build the actual address */
p = xalloc(strlen(user) + strlen(up->udb_default) + 2);
(void) strcpy(p, user);
@@ -667,6 +701,57 @@ udbmatch(user, field)
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.
+*/
+
+char *
+udb_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ char *val;
+ char *key;
+ char keybuf[MAXNAME + 1];
+
+ if (tTd(28, 20) || tTd(38, 20))
+ printf("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;
+ bcopy(name, keybuf, keysize);
+ keybuf[keysize] = '\0';
+ makelower(keybuf);
+ key = keybuf;
+ }
+ val = udbmatch(key, map->map_file);
+ if (val == NULL)
+ return NULL;
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ return map_rewrite(map, name, strlen(name), NULL);
+ else
+ return map_rewrite(map, val, strlen(val), av);
+}
+ /*
** _UDBX_INIT -- parse the UDB specification, opening any valid entries.
**
** Parameters:
@@ -688,9 +773,7 @@ int
_udbx_init()
{
register char *p;
- int i;
register struct udbent *up;
- char buf[BUFSIZ];
if (UdbInitialized)
return EX_OK;
@@ -705,11 +788,14 @@ _udbx_init()
while (p != NULL)
{
char *spec;
- auto int rcode;
int nopts;
+# if 0
+ auto int rcode;
int nmx;
+ int i;
register struct hostent *h;
char *mxhosts[MAXMXHOSTS + 1];
+# endif
struct option opts[MAXUDBOPTS + 1];
while (*p == ' ' || *p == '\t' || *p == ',')
@@ -743,10 +829,13 @@ _udbx_init()
** 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)
{
+#if 0
case '+': /* search remote database */
case '*': /* search remote database (expand MX) */
if (*spec == '*')
@@ -776,14 +865,14 @@ _udbx_init()
for (i = 0; i < nmx; i++)
{
- h = gethostbyname(mxhosts[i]);
+ h = sm_gethostbyname(mxhosts[i]);
if (h == NULL)
continue;
up->udb_type = UDB_REMOTE;
up->udb_addr.sin_family = h->h_addrtype;
bcopy(h->h_addr_list[0],
(char *) &up->udb_addr.sin_addr,
- sizeof up->udb_addr.sin_addr);
+ INADDRSZ);
up->udb_addr.sin_port = UdbPort;
up->udb_timeout = UdbTimeout;
up++;
@@ -796,6 +885,7 @@ _udbx_init()
(void) fcntl(UdbSock, F_SETFD, 1);
}
break;
+#endif
case '@': /* forward to remote host */
up->udb_type = UDB_FORWARD;
@@ -803,22 +893,31 @@ _udbx_init()
up++;
break;
+#ifdef HESIOD
case 'h': /* use hesiod */
case 'H':
-#ifdef HESIOD
if (strcasecmp(spec, "hesiod") != 0)
- break;
+ goto badspec;
up->udb_type = UDB_HESIOD;
up++;
-#endif /* HESIOD */
break;
+#endif /* HESIOD */
+#ifdef NEWDB
case '/': /* look up remote name */
up->udb_dbname = spec;
errno = 0;
up->udb_dbp = dbopen(spec, O_RDONLY, 0644, DB_BTREE, NULL);
if (up->udb_dbp == NULL)
{
+ if (tTd(28, 1))
+ {
+ int saveerrno = errno;
+
+ printf("dbopen(%s): %s",
+ spec, errstring(errno));
+ errno = saveerrno;
+ }
if (errno != ENOENT && errno != EACCES)
{
#ifdef LOG
@@ -834,6 +933,12 @@ _udbx_init()
up->udb_type = UDB_DBFETCH;
up++;
break;
+#endif
+
+ default:
+badspec:
+ syserr("Unknown UDB spec %s", spec);
+ break;
}
}
up->udb_type = UDB_EOLIST;
@@ -844,15 +949,21 @@ _udbx_init()
{
switch (up->udb_type)
{
+#ifdef DAEMON
case UDB_REMOTE:
printf("REMOTE: addr %s, timeo %d\n",
anynet_ntoa((SOCKADDR *) &up->udb_addr),
up->udb_timeout);
break;
+#endif
case UDB_DBFETCH:
+#ifdef NEWDB
printf("FETCH: file %s\n",
up->udb_dbname);
+#else
+ printf("FETCH\n");
+#endif
break;
case UDB_FORWARD:
@@ -880,6 +991,7 @@ _udbx_init()
*/
tempfail:
+#ifdef NEWDB
for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
{
if (up->udb_type == UDB_DBFETCH)
@@ -887,6 +999,7 @@ _udbx_init()
(*up->udb_dbp->close)(up->udb_dbp);
}
}
+#endif
return EX_TEMPFAIL;
}
@@ -929,20 +1042,24 @@ hes_udb_get(key, info)
{
char *name, *type;
char *p, **hp;
+ char kbuf[MAXKEY + 1];
- name = key->data;
- type = strchr(name, ':');
+ strcpy(kbuf, key->data);
+ name = kbuf;
+ type = strrchr(name, ':');
if (type == NULL)
return 1;
-
*type++ = '\0';
+ if (strchr(name, '@') != NULL)
+ return 1;
if (tTd(28, 1))
printf("hes_udb_get(%s, %s)\n", name, type);
/* make the hesiod query */
hp = hes_resolve(name, type);
- if (hp == NULL)
+ *--type = ':';
+ if (hp == NULL || hp[0] == NULL)
{
/* network problem or timeout */
if (hes_error() == HES_ER_NET)
@@ -954,19 +1071,19 @@ hes_udb_get(key, info)
{
/*
** If there are multiple matches, just return the
- ** first one and free the others.
+ ** first one.
**
** XXX These should really be returned; for example,
** XXX it is legal for :maildrop to be multi-valued.
*/
- for (p = hp[1]; p; p++)
- free(p);
-
info->data = hp[0];
info->size = (size_t) strlen(info->data);
}
+ if (tTd(28, 80))
+ printf("hes_udb_get => %s\n", *hp);
+
return 0;
}
#endif /* HESIOD */
@@ -974,9 +1091,10 @@ hes_udb_get(key, info)
#else /* not USERDB */
int
-udbexpand(a, sendq, e)
+udbexpand(a, sendq, aliaslevel, e)
ADDRESS *a;
ADDRESS **sendq;
+ int aliaslevel;
ENVELOPE *e;
{
return EX_OK;
OpenPOWER on IntegriCloud