summaryrefslogtreecommitdiff
path: root/src/map.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map.c')
-rw-r--r--src/map.c1142
1 files changed, 976 insertions, 166 deletions
diff --git a/src/map.c b/src/map.c
index e889736..8fc3387 100644
--- a/src/map.c
+++ b/src/map.c
@@ -1,39 +1,17 @@
/*
- * Copyright (c) 1992, 1995-1997 Eric P. Allman.
+ * Copyright (c) 1998 Sendmail, Inc. All rights reserved.
+ * Copyright (c) 1992, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1992, 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.
*/
#ifndef lint
-static char sccsid[] = "@(#)map.c 8.186 (Berkeley) 10/21/97";
+static char sccsid[] = "@(#)map.c 8.261 (Berkeley) 2/2/1999";
#endif /* not lint */
#include "sendmail.h"
@@ -42,13 +20,16 @@ static char sccsid[] = "@(#)map.c 8.186 (Berkeley) 10/21/97";
# include <ndbm.h>
# ifdef R_FIRST
ERROR README: You are running the Berkeley DB version of ndbm.h. See
- ERROR README: the READ_ME file about tweaking Berkeley DB so it can
+ ERROR README: the README file about tweaking Berkeley DB so it can
ERROR README: coexist with NDBM, or delete -DNDBM from the Makefile
ERROR README: and use -DNEWDB instead.
# endif
#endif
#ifdef NEWDB
# include <db.h>
+# ifndef DB_VERSION_MAJOR
+# define DB_VERSION_MAJOR 1
+# endif
#endif
#ifdef NIS
struct dom_binding; /* forward reference needed on IRIX */
@@ -182,6 +163,10 @@ map_parseargs(map, ap)
map->map_app = ++p;
break;
+ case 'T':
+ map->map_tapp = ++p;
+ break;
+
case 'k':
while (isascii(*++p) && isspace(*p))
continue;
@@ -236,6 +221,8 @@ map_parseargs(map, ap)
}
if (map->map_app != NULL)
map->map_app = newstr(map->map_app);
+ if (map->map_tapp != NULL)
+ map->map_tapp = newstr(map->map_tapp);
if (map->map_keycolnm != NULL)
map->map_keycolnm = newstr(map->map_keycolnm);
if (map->map_valcolnm != NULL)
@@ -289,21 +276,21 @@ char *
map_rewrite(map, s, slen, av)
register MAP *map;
register const char *s;
- int slen;
+ size_t slen;
char **av;
{
register char *bp;
register char c;
char **avp;
register char *ap;
- int i;
- int len;
- static int buflen = -1;
+ size_t l;
+ size_t len;
+ static size_t buflen = 0;
static char *buf = NULL;
if (tTd(39, 1))
{
- printf("map_rewrite(%.*s), av =", slen, s);
+ printf("map_rewrite(%.*s), av =", (int)slen, s);
if (av == NULL)
printf(" (nullv)");
else
@@ -315,16 +302,16 @@ map_rewrite(map, s, slen, av)
}
/* count expected size of output (can safely overestimate) */
- i = len = slen;
+ l = len = slen;
if (av != NULL)
{
const char *sp = s;
- for (i = slen; --i >= 0 && (c = *sp++) != 0; )
+ while (l-- > 0 && (c = *sp++) != '\0')
{
if (c != '%')
continue;
- if (--i < 0)
+ if (l-- <= 0)
break;
c = *sp++;
if (!(isascii(c) && isdigit(c)))
@@ -355,7 +342,7 @@ map_rewrite(map, s, slen, av)
}
else
{
- while (--slen >= 0 && (c = *s++) != '\0')
+ while (slen-- > 0 && (c = *s++) != '\0')
{
if (c != '%')
{
@@ -363,7 +350,7 @@ map_rewrite(map, s, slen, av)
*bp++ = c;
continue;
}
- if (--slen < 0 || (c = *s++) == '\0')
+ if (slen-- <= 0 || (c = *s++) == '\0')
c = '%';
if (c == '%')
goto pushc;
@@ -411,7 +398,7 @@ initmaps(rebuild, e)
bool rebuild;
register ENVELOPE *e;
{
- extern void map_init();
+ extern void map_init __P((STAB *, int));
#if XDEBUG
checkfd012("entering initmaps");
@@ -450,9 +437,9 @@ map_init(s, pass)
pass);
/*
- ** Pass 0 opens all non-rebuildable maps.
- ** Pass 1 opens all rebuildable maps for read.
- ** Pass 2 rebuilds all rebuildable maps.
+ ** Pass 0 opens all non-rebuildable maps.
+ ** Pass 1 opens all rebuildable maps for read.
+ ** Pass 2 rebuilds all rebuildable maps.
*/
rebuildable = (bitset(MF_ALIAS, map->map_mflags) &&
@@ -473,10 +460,10 @@ map_init(s, pass)
map->map_class->map_close(map);
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
}
-
+
if (pass == 2)
{
- rebuildaliases(map, FALSE);
+ (void) rebuildaliases(map, FALSE);
return;
}
@@ -491,6 +478,7 @@ map_init(s, pass)
map->map_file == NULL ? "NULL" :
map->map_file);
map->map_mflags |= MF_OPEN;
+ map->map_pid = getpid();
}
else
{
@@ -509,10 +497,55 @@ map_init(s, pass)
map->map_class = &BogusMapClass;
map->map_mflags |= MF_OPEN;
+ map->map_pid = getpid();
}
}
}
/*
+** CLOSEMAPS -- close all open maps opened by the current pid.
+**
+** Parameters:
+** none
+**
+** Returns:
+** none.
+*/
+
+void
+closemaps()
+{
+ extern void map_close __P((STAB *, int));
+
+ stabapply(map_close, 0);
+}
+
+/* ARGSUSED1 */
+void
+map_close(s, unused)
+ register STAB *s;
+ int unused;
+{
+ MAP *map;
+
+ if (s->s_type != ST_MAP)
+ return;
+
+ map = &s->s_map;
+
+ if (!bitset(MF_VALID, map->map_mflags) ||
+ !bitset(MF_OPEN, map->map_mflags) ||
+ map->map_pid != getpid())
+ return;
+
+ if (tTd(38, 5))
+ printf("closemaps: closing %s (%s)\n",
+ map->map_mname == NULL ? "NULL" : map->map_mname,
+ map->map_file == NULL ? "NULL" : map->map_file);
+
+ map->map_class->map_close(map);
+ map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
+}
+ /*
** GETCANONNAME -- look up name using service switch
**
** Parameters:
@@ -760,26 +793,55 @@ ndbm_map_open(map, mode)
sff = SFF_ROOTOK|SFF_REGONLY;
if (mode == O_RDWR)
{
- sff |= SFF_NOLINK|SFF_CREAT;
+ sff |= SFF_CREAT;
+ if (!bitset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
+ sff |= SFF_NOSLINK;
+ if (!bitset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
+ sff |= SFF_NOHLINK;
smode = S_IWRITE;
}
else
{
- sff |= SFF_NOWLINK;
+ if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
+ sff |= SFF_NOWLINK;
}
- if (FatalWritableDirs)
+ if (!bitset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
sff |= SFF_SAFEDIRPATH;
- if ((ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName,
- sff, smode, &std)) != 0 ||
- (ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName,
- sff, smode, &stp)) != 0)
+ ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName,
+ sff, smode, &std);
+ if (ret == 0)
+ ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName,
+ sff, smode, &stp);
+ if (ret == ENOENT && AutoRebuild &&
+ bitset(MCF_REBUILDABLE, map->map_class->map_cflags) &&
+ (bitset(MF_IMPL_NDBM, map->map_mflags) ||
+ bitset(MF_ALIAS, map->map_mflags)) &&
+ mode == O_RDONLY)
+ {
+ bool impl = bitset(MF_IMPL_NDBM, map->map_mflags);
+ extern bool impl_map_open __P((MAP *, int));
+
+ /* may be able to rebuild */
+ map->map_mflags &= ~MF_IMPL_NDBM;
+ if (!rebuildaliases(map, TRUE))
+ return FALSE;
+ if (impl)
+ return impl_map_open(map, O_RDONLY);
+ else
+ return ndbm_map_open(map, O_RDONLY);
+ }
+ if (ret != 0)
{
+ char *prob = "unsafe";
+
/* cannot open this map */
+ if (ret == ENOENT)
+ prob = "missing";
if (tTd(38, 2))
- printf("\tunsafe map file: %d\n", ret);
+ printf("\t%s map file: %d\n", prob, ret);
if (!bitset(MF_OPTIONAL, map->map_mflags))
- syserr("dbm map \"%s\": unsafe map file %s",
- map->map_mname, map->map_file);
+ syserr("dbm map \"%s\": %s map file %s",
+ map->map_mname, prob, map->map_file);
return FALSE;
}
if (std.st_mode == ST_MODE_NOFILE)
@@ -811,11 +873,15 @@ ndbm_map_open(map, mode)
int dirfd;
int pagfd;
+ int sff = SFF_CREAT|SFF_OPENASROOT;
- dirfd = safeopen(dirfile, mode, DBMMODE,
- SFF_NOLINK|SFF_CREAT|SFF_OPENASROOT);
- pagfd = safeopen(pagfile, mode, DBMMODE,
- SFF_NOLINK|SFF_CREAT|SFF_OPENASROOT);
+ if (!bitset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
+ sff |= SFF_NOSLINK;
+ if (!bitset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
+ sff |= SFF_NOHLINK;
+
+ dirfd = safeopen(dirfile, mode, DBMMODE, sff);
+ pagfd = safeopen(pagfile, mode, DBMMODE, sff);
if (dirfd < 0 || pagfd < 0)
{
@@ -901,8 +967,8 @@ ndbm_map_open(map, mode)
return FALSE;
}
- if (filechanged(dirfile, dfd, &std, sff) ||
- filechanged(pagfile, pfd, &stp, sff))
+ if (filechanged(dirfile, dfd, &std) ||
+ filechanged(pagfile, pfd, &stp))
{
int save_errno = errno;
@@ -933,6 +999,22 @@ ndbm_map_open(map, mode)
else
{
map->map_mflags |= MF_LOCKED;
+#if _FFR_TRUSTED_USER
+ if (geteuid() == 0 && TrustedUid != 0)
+ {
+ if (fchown(dfd, TrustedUid, -1) < 0 ||
+ fchown(pfd, TrustedUid, -1) < 0)
+ {
+ int err = errno;
+
+ sm_syslog(LOG_ALERT, NOQID,
+ "ownership change on %s failed: %s",
+ map->map_file, errstring(err));
+ message("050 ownership change on %s failed: %s",
+ map->map_file, errstring(err));
+ }
+ }
+#endif
}
if (fstat(dfd, &st) >= 0)
map->map_mtime = st.st_mtime;
@@ -975,7 +1057,7 @@ lockdbm:
fd = dbm_dirfno((DBM *) map->map_db1);
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
- if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
+ if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
{
/* Reopen the database to sync the cache */
int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
@@ -983,22 +1065,24 @@ lockdbm:
map->map_class->map_close(map);
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
- if (map->map_class->map_open(map, omode))
+ if (map->map_class->map_open(map, omode))
{
map->map_mflags |= MF_OPEN;
+ map->map_pid = getpid();
if ((omode && O_ACCMODE) == O_RDWR)
map->map_mflags |= MF_WRITABLE;
goto lockdbm;
}
else
{
- if (!bitset(MF_OPTIONAL, map->map_mflags))
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
{
extern MAPCLASS BogusMapClass;
*statp = EX_TEMPFAIL;
map->map_class = &BogusMapClass;
map->map_mflags |= MF_OPEN;
+ map->map_pid = getpid();
syserr("Cannot reopen NDBM database %s",
map->map_file);
}
@@ -1082,7 +1166,8 @@ ndbm_map_store(map, lhs, rhs)
auto int xstat;
datum old;
- old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat);
+ old.dptr = ndbm_map_lookup(map, key.dptr,
+ (char **)NULL, &xstat);
if (old.dptr != NULL && *(char *) old.dptr != '\0')
{
old.dsize = strlen(old.dptr);
@@ -1117,14 +1202,14 @@ ndbm_map_close(map)
register MAP *map;
{
if (tTd(38, 9))
- printf("ndbm_map_close(%s, %s, %x)\n",
+ printf("ndbm_map_close(%s, %s, %lx)\n",
map->map_mname, map->map_file, map->map_mflags);
if (bitset(MF_WRITABLE, map->map_mflags))
{
#ifdef NDBM_YP_COMPAT
bool inclnull;
- char buf[200];
+ char buf[MAXHOSTNAMELEN];
inclnull = bitset(MF_INCLNULL, map->map_mflags);
map->map_mflags &= ~MF_INCLNULL;
@@ -1179,14 +1264,22 @@ ndbm_map_close(map)
** be pokey about it. That's hard to do.
*/
+#if DB_VERSION_MAJOR < 2
extern bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *));
+#else
+extern bool db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *));
+#endif
/* these should be K line arguments */
-#ifndef DB_CACHE_SIZE
-# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */
-#endif
-#ifndef DB_HASH_NELEM
-# define DB_HASH_NELEM 4096 /* (starting) size of hash table */
+#if DB_VERSION_MAJOR < 2
+# define db_cachesize cachesize
+# define h_nelem nelem
+# ifndef DB_CACHE_SIZE
+# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */
+# endif
+# ifndef DB_HASH_NELEM
+# define DB_HASH_NELEM 4096 /* (starting) size of hash table */
+# endif
#endif
bool
@@ -1194,14 +1287,20 @@ bt_map_open(map, mode)
MAP *map;
int mode;
{
+#if DB_VERSION_MAJOR < 2
BTREEINFO btinfo;
+#else
+ DB_INFO btinfo;
+#endif
if (tTd(38, 2))
printf("bt_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
bzero(&btinfo, sizeof btinfo);
- btinfo.cachesize = DB_CACHE_SIZE;
+#ifdef DB_CACHE_SIZE
+ btinfo.db_cachesize = DB_CACHE_SIZE;
+#endif
return db_map_open(map, mode, "btree", DB_BTREE, &btinfo);
}
@@ -1210,15 +1309,23 @@ hash_map_open(map, mode)
MAP *map;
int mode;
{
+#if DB_VERSION_MAJOR < 2
HASHINFO hinfo;
+#else
+ DB_INFO hinfo;
+#endif
if (tTd(38, 2))
printf("hash_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
bzero(&hinfo, sizeof hinfo);
- hinfo.nelem = DB_HASH_NELEM;
- hinfo.cachesize = DB_CACHE_SIZE;
+#ifdef DB_HASH_NELEM
+ hinfo.h_nelem = DB_HASH_NELEM;
+#endif
+#ifdef DB_CACHE_SIZE
+ hinfo.db_cachesize = DB_CACHE_SIZE;
+#endif
return db_map_open(map, mode, "hash", DB_HASH, &hinfo);
}
@@ -1228,9 +1335,13 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
int mode;
char *mapclassname;
DBTYPE dbtype;
+#if DB_VERSION_MAJOR < 2
const void *openinfo;
+#else
+ DB_INFO *openinfo;
+#endif
{
- DB *db;
+ DB *db = NULL;
int i;
int omode;
int smode = S_IREAD;
@@ -1252,25 +1363,54 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
sff = SFF_ROOTOK|SFF_REGONLY;
if (mode == O_RDWR)
{
- sff |= SFF_NOLINK|SFF_CREAT;
+ sff |= SFF_CREAT;
+ if (!bitset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
+ sff |= SFF_NOSLINK;
+ if (!bitset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
+ sff |= SFF_NOHLINK;
smode = S_IWRITE;
}
else
{
- sff |= SFF_NOWLINK;
+ if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
+ sff |= SFF_NOWLINK;
}
- if (FatalWritableDirs)
+ if (!bitset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
sff |= SFF_SAFEDIRPATH;
- if ((i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName,
- sff, smode, &st)) != 0)
+ i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st);
+ if (i == ENOENT && AutoRebuild &&
+ bitset(MCF_REBUILDABLE, map->map_class->map_cflags) &&
+ (bitset(MF_IMPL_HASH, map->map_mflags) ||
+ bitset(MF_ALIAS, map->map_mflags)) &&
+ mode == O_RDONLY)
{
+ bool impl = bitset(MF_IMPL_HASH, map->map_mflags);
+ extern bool impl_map_open __P((MAP *, int));
+
+ /* may be able to rebuild */
+ map->map_mflags &= ~MF_IMPL_HASH;
+ if (!rebuildaliases(map, TRUE))
+ return FALSE;
+ if (impl)
+ return impl_map_open(map, O_RDONLY);
+ else
+ return db_map_open(map, O_RDONLY, mapclassname,
+ dbtype, openinfo);
+ }
+
+ if (i != 0)
+ {
+ char *prob = "unsafe";
+
/* cannot open this map */
+ if (i == ENOENT)
+ prob = "missing";
if (tTd(38, 2))
- printf("\tunsafe map file: %s\n", errstring(i));
+ printf("\t%s map file: %s\n", prob, errstring(i));
errno = i;
if (!bitset(MF_OPTIONAL, map->map_mflags))
- syserr("%s map \"%s\": unsafe map file %s",
- mapclassname, map->map_mname, map->map_file);
+ syserr("%s map \"%s\": %s map file %s",
+ mapclassname, map->map_mname, prob, buf);
return FALSE;
}
if (st.st_mode == ST_MODE_NOFILE)
@@ -1281,10 +1421,8 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
#if LOCK_ON_OPEN
if (mode == O_RDWR)
omode |= O_TRUNC|O_EXLOCK;
-# if !OLD_NEWDB
else
omode |= O_SHLOCK;
-# endif
#else
/*
** Pre-lock the file to avoid race conditions. In particular,
@@ -1301,7 +1439,7 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
}
/* make sure no baddies slipped in just before the open... */
- if (filechanged(buf, fd, &st, sff))
+ if (filechanged(buf, fd, &st))
{
int save_errno = errno;
@@ -1333,7 +1471,23 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
omode &= ~(O_EXCL|O_CREAT);
#endif
+#if DB_VERSION_MAJOR < 2
db = dbopen(buf, omode, DBMMODE, dbtype, openinfo);
+#else
+ {
+ int flags = 0;
+
+ if (mode == O_RDONLY)
+ flags |= DB_RDONLY;
+ if (bitset(O_CREAT, omode))
+ flags |= DB_CREATE;
+ if (bitset(O_TRUNC, omode))
+ flags |= DB_TRUNCATE;
+
+ errno = db_open(buf, dbtype, flags, DBMMODE,
+ NULL, openinfo, &db);
+ }
+#endif
saveerrno = errno;
#if !LOCK_ON_OPEN
@@ -1355,15 +1509,25 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
errno = saveerrno;
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("Cannot open %s database %s",
- mapclassname, map->map_file);
+ mapclassname, buf);
return FALSE;
}
- if (filechanged(buf, db->fd(db), &st, sff))
+#if DB_VERSION_MAJOR < 2
+ fd = db->fd(db);
+#else
+ fd = -1;
+ errno = db->fd(db, &fd);
+#endif
+ if (filechanged(buf, fd, &st))
{
int save_errno = errno;
+#if DB_VERSION_MAJOR < 2
db->close(db);
+#else
+ errno = db->close(db, 0);
+#endif
#if !LOCK_ON_OPEN
if (map->map_lockfd >= 0)
close(map->map_lockfd);
@@ -1375,26 +1539,36 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
if (mode == O_RDWR)
map->map_mflags |= MF_LOCKED;
-#if !OLD_NEWDB
- fd = db->fd(db);
-# if LOCK_ON_OPEN
+#if LOCK_ON_OPEN
if (fd >= 0 && mode == O_RDONLY)
{
(void) lockfile(fd, buf, NULL, LOCK_UN);
}
-# endif
#endif
/* try to make sure that at least the database header is on disk */
if (mode == O_RDWR)
-#if OLD_NEWDB
- (void) db->sync(db);
-#else
+ {
(void) db->sync(db, 0);
+#if _FFR_TRUSTED_USER
+ if (geteuid() == 0 && TrustedUid != 0)
+ {
+ if (fchown(fd, TrustedUid, -1) < 0)
+ {
+ int err = errno;
+
+ sm_syslog(LOG_ALERT, NOQID,
+ "ownership change on %s failed: %s",
+ buf, errstring(err));
+ message("050 ownership change on %s failed: %s",
+ buf, errstring(err));
+ }
+ }
+#endif
+ }
if (fd >= 0 && fstat(fd, &st) >= 0)
map->map_mtime = st.st_mtime;
-#endif
map->map_db2 = (ARBPTR_T) db;
if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
@@ -1425,6 +1599,9 @@ db_map_lookup(map, name, av, statp)
char keybuf[MAXNAME + 1];
char buf[MAXNAME + 1];
+ bzero(&key, sizeof key);
+ bzero(&val, sizeof val);
+
if (tTd(38, 20))
printf("db_map_lookup(%s, %s)\n",
map->map_mname, name);
@@ -1445,12 +1622,16 @@ db_map_lookup(map, name, av, statp)
keybuf[key.size] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(keybuf);
-#if !OLD_NEWDB
lockdb:
+#if DB_VERSION_MAJOR < 2
fd = db->fd(db);
+#else
+ fd = -1;
+ errno = db->fd(db, &fd);
+#endif
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, buf, ".db", LOCK_SH);
- if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
+ if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
{
/* Reopen the database to sync the cache */
int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
@@ -1458,9 +1639,10 @@ db_map_lookup(map, name, av, statp)
map->map_class->map_close(map);
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
- if (map->map_class->map_open(map, omode))
+ if (map->map_class->map_open(map, omode))
{
map->map_mflags |= MF_OPEN;
+ map->map_pid = getpid();
if ((omode && O_ACCMODE) == O_RDWR)
map->map_mflags |= MF_WRITABLE;
db = (DB *) map->map_db2;
@@ -1468,40 +1650,76 @@ db_map_lookup(map, name, av, statp)
}
else
{
- if (!bitset(MF_OPTIONAL, map->map_mflags))
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
{
extern MAPCLASS BogusMapClass;
*statp = EX_TEMPFAIL;
map->map_class = &BogusMapClass;
map->map_mflags |= MF_OPEN;
+ map->map_pid = getpid();
syserr("Cannot reopen DB database %s",
map->map_file);
}
return NULL;
}
}
-#endif
-
+
st = 1;
if (bitset(MF_TRY0NULL, map->map_mflags))
{
+#if DB_VERSION_MAJOR < 2
st = db->get(db, &key, &val, 0);
+#else
+ errno = db->get(db, NULL, &key, &val, 0);
+ switch (errno)
+ {
+ case DB_NOTFOUND:
+ case DB_KEYEMPTY:
+ st = 1;
+ break;
+
+ case 0:
+ st = 0;
+ break;
+
+ default:
+ st = -1;
+ break;
+ }
+#endif
if (st == 0)
map->map_mflags &= ~MF_TRY1NULL;
}
if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
{
key.size++;
+#if DB_VERSION_MAJOR < 2
st = db->get(db, &key, &val, 0);
+#else
+ errno = db->get(db, NULL, &key, &val, 0);
+ switch (errno)
+ {
+ case DB_NOTFOUND:
+ case DB_KEYEMPTY:
+ st = 1;
+ break;
+
+ case 0:
+ st = 0;
+ break;
+
+ default:
+ st = -1;
+ break;
+ }
+#endif
if (st == 0)
map->map_mflags &= ~MF_TRY0NULL;
}
saveerrno = errno;
-#if !OLD_NEWDB
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, buf, ".db", LOCK_UN);
-#endif
if (st != 0)
{
errno = saveerrno;
@@ -1532,6 +1750,9 @@ db_map_store(map, lhs, rhs)
register DB *db = map->map_db2;
char keybuf[MAXNAME + 1];
+ bzero(&key, sizeof key);
+ bzero(&data, sizeof data);
+
if (tTd(38, 12))
printf("db_map_store(%s, %s, %s)\n",
map->map_mname, lhs, rhs);
@@ -1557,7 +1778,25 @@ db_map_store(map, lhs, rhs)
data.size++;
}
+#if DB_VERSION_MAJOR < 2
stat = db->put(db, &key, &data, R_NOOVERWRITE);
+#else
+ errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE);
+ switch (errno)
+ {
+ case DB_KEYEXIST:
+ stat = 1;
+ break;
+
+ case 0:
+ stat = 0;
+ break;
+
+ default:
+ stat = -1;
+ break;
+ }
+#endif
if (stat > 0)
{
if (!bitset(MF_APPEND, map->map_mflags))
@@ -1568,7 +1807,10 @@ db_map_store(map, lhs, rhs)
static int bufsiz = 0;
DBT old;
- old.data = db_map_lookup(map, key.data, NULL, &stat);
+ bzero(&old, sizeof old);
+
+ old.data = db_map_lookup(map, key.data,
+ (char **)NULL, &stat);
if (old.data != NULL)
{
old.size = strlen(old.data);
@@ -1580,7 +1822,7 @@ db_map_store(map, lhs, rhs)
buf = xalloc(bufsiz);
}
snprintf(buf, bufsiz, "%s,%s",
- data.data, old.data);
+ (char *) data.data, (char *) old.data);
data.size = data.size + old.size + 1;
data.data = buf;
if (tTd(38, 9))
@@ -1588,7 +1830,11 @@ db_map_store(map, lhs, rhs)
(char *) data.data);
}
}
+#if DB_VERSION_MAJOR < 2
stat = db->put(db, &key, &data, 0);
+#else
+ stat = errno = db->put(db, NULL, &key, &data, 0);
+#endif
}
if (stat != 0)
syserr("readaliases: db put (%s)", lhs);
@@ -1615,19 +1861,43 @@ db_map_close(map)
db_map_store(map, "@", "@");
}
-#if OLD_NEWDB
- (void) db->sync(db);
-#else
(void) db->sync(db, 0);
-#endif
#if !LOCK_ON_OPEN
if (map->map_lockfd >= 0)
(void) close(map->map_lockfd);
#endif
+#if DB_VERSION_MAJOR < 2
if (db->close(db) != 0)
- syserr("readaliases: db close failure");
+#else
+ /*
+ ** Berkeley DB can use internal shared memory
+ ** locking for its memory pool. Closing a map
+ ** opened by another process will interfere
+ ** with the shared memory and locks of the parent
+ ** process leaving things in a bad state.
+ */
+
+ /*
+ ** If this map was not opened by the current
+ ** process, do not close the map but recover
+ ** the file descriptor.
+ */
+ if (map->map_pid != getpid())
+ {
+ int fd = -1;
+
+ errno = db->fd(db, &fd);
+ if (fd >= 0)
+ (void) close(fd);
+ return;
+ }
+
+ if ((errno = db->close(db, 0)) != 0)
+#endif
+ syserr("db_map_close(%s, %s, %lx): db close failure",
+ map->map_mname, map->map_file, map->map_mflags);
}
#endif
@@ -1734,6 +2004,7 @@ nis_map_open(map, mode)
** NIS_MAP_LOOKUP -- look up a datum in a NIS map
*/
+/* ARGSUSED3 */
char *
nis_map_lookup(map, name, av, statp)
MAP *map;
@@ -1910,7 +2181,7 @@ nisplus_map_open(map, mode)
mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
- errno = ENODEV;
+ errno = EPERM;
return FALSE;
}
@@ -1920,7 +2191,7 @@ nisplus_map_open(map, mode)
if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
{
/* set default NISPLUS Domain to $m */
- extern char *nisplus_default_domain();
+ extern char *nisplus_default_domain __P((void));
map->map_domain = newstr(nisplus_default_domain());
if (tTd(38, 2))
@@ -1953,7 +2224,7 @@ nisplus_map_open(map, mode)
case NIS_NAMEUNREACHABLE:
if (retry_cnt++ > 4)
{
- errno = EBADR;
+ errno = EAGAIN;
return FALSE;
}
/* try not to overwhelm hosed server */
@@ -1967,7 +2238,7 @@ nisplus_map_open(map, mode)
map->map_file, map->map_domain,
nis_sperrno(res->status));
#endif
- errno = EBADR;
+ errno = EAGAIN;
return FALSE;
}
}
@@ -1983,7 +2254,7 @@ nisplus_map_open(map, mode)
map->map_file, map->map_domain,
nis_sperrno(res->status));
#endif
- errno = EBADR;
+ errno = EBADF;
return FALSE;
}
/* default key column is column 0 */
@@ -1991,7 +2262,7 @@ nisplus_map_open(map, mode)
map->map_keycolnm = newstr(COL_NAME(res,0));
max_col = COL_MAX(res);
-
+
/* verify the key column exist */
for (i=0; i< max_col; i++)
{
@@ -2003,7 +2274,7 @@ nisplus_map_open(map, mode)
if (tTd(38, 2))
printf("nisplus_map_open(%s): can not find key column %s\n",
map->map_file, map->map_keycolnm);
- errno = EBADR;
+ errno = ENOENT;
return FALSE;
}
@@ -2026,7 +2297,7 @@ nisplus_map_open(map, mode)
if (tTd(38, 2))
printf("nisplus_map_open(%s): can not find column %s\n",
map->map_file, map->map_keycolnm);
- errno = EBADR;
+ errno = ENOENT;
return FALSE;
}
@@ -2057,14 +2328,17 @@ nisplus_map_lookup(map, name, av, statp)
if (!bitset(MF_OPEN, map->map_mflags))
{
if (nisplus_map_open(map, O_RDONLY))
+ {
map->map_mflags |= MF_OPEN;
+ map->map_pid = getpid();
+ }
else
{
*statp = EX_UNAVAILABLE;
return NULL;
}
}
-
+
/*
** Copy the name to the key buffer, escaping double quote characters
** by doubling them and quoting "]" and "," to avoid having the
@@ -2295,7 +2569,7 @@ nisplus_default_domain()
if (default_domain[0] != '\0')
return(default_domain);
-
+
p = nis_local_directory();
snprintf(default_domain, sizeof default_domain, "%s", p);
return default_domain;
@@ -2357,12 +2631,22 @@ ldap_map_open(map, mode)
** Caching should be investigated.
*/
+static jmp_buf LDAPTimeout;
+
+static void
+ldaptimeout(sig_no)
+ int sig_no;
+{
+ longjmp(LDAPTimeout, 1);
+}
+
bool
ldap_map_start(map)
MAP *map;
{
LDAP_MAP_STRUCT *lmap;
LDAP *ld;
+ register EVENT *ev = NULL;
if (tTd(38, 2))
printf("ldap_map_start(%s)\n", map->map_mname);
@@ -2372,21 +2656,63 @@ ldap_map_start(map)
if (tTd(38,9))
printf("ldap_open(%s, %d)\n", lmap->ldaphost, lmap->ldapport);
- if ((ld = ldap_open(lmap->ldaphost,lmap->ldapport)) == NULL)
+ /* Need to set an alarm here, ldap_open is hopelessly broken. */
+
+ /* set the timeout */
+ if (lmap->timeout.tv_sec != 0)
+ {
+ if (setjmp(LDAPTimeout) != 0)
+ {
+ if (LogLevel > 1)
+ sm_syslog(LOG_NOTICE, CurEnv->e_id,
+ "timeout waiting for ldap_open to %.100s",
+ lmap->ldaphost);
+ return (FALSE);
+ }
+ ev = setevent(lmap->timeout.tv_sec, ldaptimeout, 0);
+ }
+
+#ifdef USE_LDAP_INIT
+ ld = ldap_init(lmap->ldaphost,lmap->ldapport);
+#else
+ ld = ldap_open(lmap->ldaphost,lmap->ldapport);
+#endif
+
+ /* clear the event if it has not sprung */
+ if (lmap->timeout.tv_sec != 0)
+ clrevent(ev);
+
+ if (ld == NULL)
{
if (!bitset(MF_OPTIONAL, map->map_mflags))
{
- syserr("ldapopen failed to %s in map %s",
+ syserr("%sldapopen failed to %s in map %s",
+ bitset(MF_NODEFER, map->map_mflags) ? "" : "421 ",
lmap->ldaphost, map->map_mname);
}
return FALSE;
}
+#ifdef USE_LDAP_SET_OPTION
+ ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->deref);
+ ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->timelimit);
+ ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->sizelimit);
+ ldap_set_option(ld, LDAP_OPT_REFERRALS,
+ bitset(LDAP_OPT_REFERRALS, lmap->ldap_options) ?
+ LDAP_OPT_ON : LDAP_OPT_OFF);
+#else
+ /* From here on in we can use ldap internal timelimits */
ld->ld_deref = lmap->deref;
ld->ld_timelimit = lmap->timelimit;
ld->ld_sizelimit = lmap->sizelimit;
ld->ld_options = lmap->ldap_options;
+#endif
+#ifdef USE_LDAP_INIT
+ /* ld needs to be cast into the map struct */
+ lmap->ld = ld;
+ return TRUE;
+#else
if (ldap_bind_s(ld, lmap->binddn,lmap->passwd,lmap->method) != LDAP_SUCCESS)
{
if (!bitset(MF_OPTIONAL, map->map_mflags))
@@ -2403,28 +2729,43 @@ ldap_map_start(map)
}
return FALSE;
+#endif
}
/*
-** LDAP_MAP_CLOSE -- close ldap map
+** LDAP_MAP_STOP -- close the ldap connection
*/
void
-ldap_map_close(map)
+ldap_map_stop(map)
MAP *map;
{
- LDAP_MAP_STRUCT *lmap ;
+ LDAP_MAP_STRUCT *lmap;
+
lmap = (LDAP_MAP_STRUCT *) map->map_db1;
if (lmap->ld != NULL)
+ {
ldap_unbind(lmap->ld);
+ lmap->ld = NULL;
+ }
}
+/*
+** LDAP_MAP_CLOSE -- close ldap map
+*/
+
+void
+ldap_map_close(map)
+ MAP *map;
+{
+ ldap_map_stop(map);
+}
#ifdef SUNET_ID
/*
-** SUNET_ID_HASH -- Convert a string to it's Sunet_id canonical form
-** This only makes sense at Stanford University.
+** SUNET_ID_HASH -- Convert a string to it's Sunet_id canonical form
+** This only makes sense at Stanford University.
*/
char *
@@ -2458,7 +2799,7 @@ sunet_id_hash(str)
#endif /* SUNET_ID */
/*
-** LDAP_MAP_LOOKUP -- look up a datum in a LDAP map
+** LDAP_MAP_LOOKUP -- look up a datum in a LDAP map
*/
char *
@@ -2477,6 +2818,7 @@ ldap_map_lookup(map, name, av, statp)
char **attr_values = NULL;
char *result;
int name_len;
+ char *fp, *p, *q;
if (tTd(38, 20))
printf("ldap_map_lookup(%s, %s)\n", map->map_mname, name);
@@ -2505,15 +2847,35 @@ ldap_map_lookup(map, name, av, statp)
makelower(keybuf);
#endif /*SUNET_ID */
- /* sprintf keybuf into filter */
- snprintf(filter, sizeof filter, lmap->filter, keybuf);
+ /* substitute keybuf into filter, perhaps multiple times */
+ fp = filter;
+ p = lmap->filter;
+ while ((q = strchr(p, '%')) != NULL)
+ {
+ if (q[1] == 's')
+ {
+ snprintf(fp, SPACELEFT(filter, fp), "%.*s%s",
+ q - p, p, keybuf);
+ p = q + 2;
+ }
+ else
+ {
+ snprintf(fp, SPACELEFT(filter, fp), "%.*s",
+ q - p + 1, p);
+ p = q + (q[1] == '%' ? 2 : 1);
+ }
+ fp += strlen(fp);
+ }
+ snprintf(fp, SPACELEFT(filter, fp), "%s", p);
+ if (tTd(38, 20))
+ printf("ldap search filter=%s\n", filter);
if (ldap_search_st(lmap->ld, lmap->base,lmap->scope,filter,
lmap->attr, lmap->attrsonly, &(lmap->timeout),
&(lmap->res)) != LDAP_SUCCESS)
{
- /* try close/opening map */
- ldap_map_close(map);
+ /* try stopping/starting map */
+ ldap_map_stop(map);
if (!ldap_map_start(map))
{
result = NULL;
@@ -2527,7 +2889,8 @@ ldap_map_lookup(map, name, av, statp)
{
if (!bitset(MF_OPTIONAL, map->map_mflags))
{
- syserr("Error in ldap_search_st using %s in map %s",
+ syserr("%sError in ldap_search_st using %s in map %s",
+ bitset(MF_NODEFER, map->map_mflags) ? "" : "421 ",
filter, map->map_mname);
}
result = NULL;
@@ -2574,13 +2937,13 @@ ldap_map_lookup(map, name, av, statp)
ldap_value_free(attr_values);
if (lmap != NULL)
ldap_msgfree(lmap->res);
- ldap_map_close(map);
+ ldap_map_stop(map);
return result ;
}
/*
-** LDAP_MAP_DEQUOTE - helper routine for ldap_map_parseargs
+** LDAP_MAP_DEQUOTE - helper routine for ldap_map_parseargs
*/
char *
@@ -2610,7 +2973,7 @@ ldap_map_dequote(str)
}
/*
-** LDAP_MAP_PARSEARGS -- parse ldap map definition args.
+** LDAP_MAP_PARSEARGS -- parse ldap map definition args.
*/
bool
@@ -2642,6 +3005,11 @@ ldap_map_parseargs(map,args)
lmap->passwd = NULL;
lmap->base = NULL;
lmap->ldaphost = NULL;
+
+ /* Default general ptrs to NULL */
+ lmap->ld = NULL;
+ lmap->res = NULL;
+
map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
for (;;)
{
@@ -2688,6 +3056,10 @@ ldap_map_parseargs(map,args)
map->map_app = ++p;
break;
+ case 'T':
+ map->map_tapp = ++p;
+ break;
+
/* Start of ldap_map specific args */
case 'k': /* search field */
while (isascii(*++p) && isspace(*p))
@@ -2716,7 +3088,7 @@ ldap_map_parseargs(map,args)
break;
case 's': /* search scope */
- if (strncasecmp(p, "base", 4) == 0)
+ if (strncasecmp(++p, "base", 4) == 0)
{
lmap->scope = LDAP_SCOPE_BASE;
}
@@ -2732,8 +3104,14 @@ ldap_map_parseargs(map,args)
{ /* bad config line */
if (!bitset(MCF_OPTFILE, map->map_class->map_cflags))
{
+ char *ptr;
+
+ if ((ptr = strchr(p, ' ')) != NULL)
+ *ptr = '\0';
syserr("Scope must be [base|one|sub] not %s in map %s",
p, map->map_mname);
+ if (ptr != NULL)
+ *ptr = ' ';
return FALSE;
}
}
@@ -2762,6 +3140,7 @@ ldap_map_parseargs(map,args)
while (isascii(*++p) && isspace(*p))
continue;
lmap->timelimit = atoi(p);
+ lmap->timeout.tv_sec = lmap->timelimit;
break;
}
@@ -2792,13 +3171,14 @@ ldap_map_parseargs(map,args)
if (map->map_app != NULL)
map->map_app = newstr(ldap_map_dequote(map->map_app));
-
+ if (map->map_tapp != NULL)
+ map->map_tapp = newstr(ldap_map_dequote(map->map_tapp));
if (map->map_domain != NULL)
map->map_domain = newstr(ldap_map_dequote(map->map_domain));
/*
- ** We need to swallow up all the stuff into a struct
- ** and dump it into map->map_dbptr1
+ ** We need to swallow up all the stuff into a struct
+ ** and dump it into map->map_dbptr1
*/
if (lmap->ldaphost != NULL)
@@ -2856,15 +3236,15 @@ ldap_map_parseargs(map,args)
#endif /* LDAP Modules */
/*
-** syslog map
+** syslog map
*/
-#if _FFR_SYSLOG_MAP
+#if _FFR_MAP_SYSLOG
#define map_prio map_lockfd /* overload field */
/*
-** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages.
+** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages.
*/
bool
@@ -2895,7 +3275,7 @@ syslog_map_parseargs(map, args)
{
if (strncasecmp("LOG_", priority, 4) == 0)
priority += 4;
-
+
#ifdef LOG_EMERG
if (strcasecmp("EMERG", priority) == 0)
map->map_prio = LOG_EMERG;
@@ -2946,7 +3326,7 @@ syslog_map_parseargs(map, args)
}
/*
-** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string
+** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string
*/
char *
@@ -2966,20 +3346,18 @@ syslog_map_lookup(map, string, args, statp)
sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr);
}
-
+
*statp = EX_OK;
return "";
}
-#endif /* _FFR_SYSLOG_MAP */
+#endif /* _FFR_MAP_SYSLOG */
/*
** HESIOD Modules
*/
#ifdef HESIOD
-#include <hesiod.h>
-
bool
hes_map_open(map, mode)
MAP *map;
@@ -3004,6 +3382,15 @@ hes_map_open(map, mode)
return FALSE;
}
+#ifdef HESIOD_INIT
+ if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0)
+ return TRUE;
+
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("421 cannot initialize Hesiod map (%s)",
+ errstring(errno));
+ return FALSE;
+#else
if (hes_error() == HES_ER_UNINIT)
hes_init();
switch (hes_error())
@@ -3017,6 +3404,7 @@ hes_map_open(map, mode)
syserr("421 cannot initialize Hesiod map (%d)", hes_error());
return FALSE;
+#endif /* HESIOD_INIT */
}
char *
@@ -3044,14 +3432,45 @@ hes_map_lookup(map, name, av, statp)
np = xalloc(strlen(name) + 2);
np[0] = '\\';
strcpy(&np[1], name);
+#ifdef HESIOD_INIT
+ hp = hesiod_resolve(HesiodContext, np, map->map_file);
+#else
hp = hes_resolve(np, map->map_file);
+#endif /* HESIOD_INIT */
if (np != nbuf)
free(np);
}
else
{
+#ifdef HESIOD_INIT
+ hp = hesiod_resolve(HesiodContext, name, map->map_file);
+#else
hp = hes_resolve(name, map->map_file);
+#endif /* HESIOD_INIT */
}
+#ifdef HESIOD_INIT
+ if (hp == NULL)
+ return NULL;
+ if (*hp == NULL)
+ {
+ hesiod_free_list(HesiodContext, hp);
+ switch (errno)
+ {
+ case ENOENT:
+ *statp = EX_NOTFOUND;
+ break;
+ case ECONNREFUSED:
+ case EMSGSIZE:
+ *statp = EX_TEMPFAIL;
+ break;
+ case ENOMEM:
+ default:
+ *statp = EX_UNAVAILABLE;
+ break;
+ }
+ return NULL;
+ }
+#else
if (hp == NULL || hp[0] == NULL)
{
switch (hes_error())
@@ -3074,7 +3493,8 @@ hes_map_lookup(map, name, av, statp)
}
return NULL;
}
-
+#endif /* HESIOD_INIT */
+
if (bitset(MF_MATCHONLY, map->map_mflags))
return map_rewrite(map, name, strlen(name), NULL);
else
@@ -3103,8 +3523,6 @@ ni_map_open(map, mode)
MAP *map;
int mode;
{
- char *p;
-
if (tTd(38, 2))
printf("ni_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
@@ -3162,6 +3580,7 @@ ni_getcanonname(name, hbsize, statp)
int *statp;
{
char *vptr;
+ char *ptr;
char nbuf[MAXNAME + 1];
if (tTd(38, 20))
@@ -3183,7 +3602,7 @@ ni_getcanonname(name, hbsize, statp)
}
/* Do the search */
- vptr = ni_propval("/machines", NULL, nbuf, "name", '\0');
+ vptr = ni_propval("/machines", NULL, nbuf, "name", '\n');
if (vptr == NULL)
{
@@ -3191,6 +3610,10 @@ ni_getcanonname(name, hbsize, statp)
return FALSE;
}
+ /* Only want the first machine name */
+ if ((ptr = strchr(vptr, '\n')) != NULL)
+ *ptr = '\0';
+
if (hbsize >= strlen(vptr))
{
strcpy(name, vptr);
@@ -3382,7 +3805,7 @@ ni_propval(keydir, keyprop, keyval, valprop, sepchar)
return propval;
}
-#endif
+#endif /* NETINFO */
/*
** TEXT (unindexed text file) Modules
**
@@ -3411,7 +3834,7 @@ text_map_open(map, mode)
mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
- errno = ENODEV;
+ errno = EPERM;
return FALSE;
}
@@ -3429,8 +3852,10 @@ text_map_open(map, mode)
return FALSE;
}
- sff = SFF_ROOTOK|SFF_REGONLY|SFF_NOWLINK;
- if (FatalWritableDirs)
+ sff = SFF_ROOTOK|SFF_REGONLY;
+ if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
+ sff |= SFF_NOWLINK;
+ if (!bitset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
sff |= SFF_SAFEDIRPATH;
if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName,
sff, S_IRUSR, NULL)) != 0)
@@ -3448,7 +3873,7 @@ text_map_open(map, mode)
map->map_keycolno = 0;
else
{
- if (!isdigit(*map->map_keycolnm))
+ if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm)))
{
syserr("text map \"%s\", file %s: -k should specify a number, not %s",
map->map_mname, map->map_file,
@@ -3462,7 +3887,7 @@ text_map_open(map, mode)
map->map_valcolno = 0;
else
{
- if (!isdigit(*map->map_valcolnm))
+ if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm)))
{
syserr("text map \"%s\", file %s: -v should specify a number, not %s",
map->map_mname, map->map_file,
@@ -3556,6 +3981,11 @@ text_map_lookup(map, name, av, statp)
return NULL;
}
vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf);
+ if (vp == NULL)
+ {
+ *statp = EX_NOTFOUND;
+ return NULL;
+ }
vsize = strlen(vp);
*statp = EX_OK;
if (bitset(MF_MATCHONLY, map->map_mflags))
@@ -3633,6 +4063,7 @@ text_getcanonname(name, hbsize, statp)
** STAB_MAP_LOOKUP -- look up alias in symbol table
*/
+/* ARGSUSED2 */
char *
stab_map_lookup(map, name, av, pstat)
register MAP *map;
@@ -3695,12 +4126,14 @@ stab_map_open(map, mode)
mode &= O_ACCMODE;
if (mode != O_RDONLY)
{
- errno = ENODEV;
+ errno = EPERM;
return FALSE;
}
- sff = SFF_ROOTOK|SFF_REGONLY|SFF_NOWLINK;
- if (FatalWritableDirs)
+ sff = SFF_ROOTOK|SFF_REGONLY;
+ if (!bitset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
+ sff |= SFF_NOWLINK;
+ if (!bitset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
sff |= SFF_SAFEDIRPATH;
af = safefopen(map->map_file, O_RDONLY, 0444, sff);
if (af == NULL)
@@ -3808,13 +4241,18 @@ impl_map_open(map, mode)
#if defined(NEWDB) || defined(NDBM)
if (Verbose)
- message("WARNING: cannot open alias database %s", map->map_file);
+ message("WARNING: cannot open alias database %s%s",
+ map->map_file,
+ mode == O_RDONLY ? "; reading text version" : "");
#else
if (mode != O_RDONLY)
usrerr("Cannot rebuild aliases: no database format defined");
#endif
- return stab_map_open(map, mode);
+ if (mode == O_RDONLY)
+ return stab_map_open(map, mode);
+ else
+ return FALSE;
}
@@ -3911,6 +4349,7 @@ user_map_open(map, mode)
** USER_MAP_LOOKUP -- look up a user in the passwd file.
*/
+/* ARGSUSED3 */
char *
user_map_lookup(map, key, av, statp)
MAP *map;
@@ -4340,6 +4779,7 @@ seq_map_store(map, key, val)
** NULL stubs
*/
+/* ARGSUSED */
bool
null_map_open(map, mode)
MAP *map;
@@ -4348,6 +4788,7 @@ null_map_open(map, mode)
return TRUE;
}
+/* ARGSUSED */
void
null_map_close(map)
MAP *map;
@@ -4366,6 +4807,7 @@ null_map_lookup(map, key, args, pstat)
return NULL;
}
+/* ARGSUSED */
void
null_map_store(map, key, val)
MAP *map;
@@ -4397,3 +4839,371 @@ MAPCLASS BogusMapClass =
NULL, bogus_map_lookup, null_map_store,
null_map_open, null_map_close,
};
+ /*
+** REGEX modules
+*/
+
+#ifdef MAP_REGEX
+
+# include <regex.h>
+
+# define DEFAULT_DELIM CONDELSE
+
+# define END_OF_FIELDS -1
+
+# define ERRBUF_SIZE 80
+# define MAX_MATCH 32
+
+# define xnalloc(s) memset(xalloc(s), 0, s);
+
+struct regex_map
+{
+ regex_t pattern_buf; /* xalloc it */
+ int *regex_subfields; /* move to type MAP */
+ char *delim; /* move to type MAP */
+};
+
+static int
+parse_fields(s, ibuf, blen, nr_substrings)
+ char *s;
+ int *ibuf; /* array */
+ int blen; /* number of elements in ibuf */
+ int nr_substrings; /* number of substrings in the pattern */
+{
+ register char *cp;
+ int i = 0;
+ bool lastone = FALSE;
+
+ blen--; /* for terminating END_OF_FIELDS */
+ cp = s;
+ do
+ {
+ for (;; cp++)
+ {
+ if (*cp == ',')
+ {
+ *cp = '\0';
+ break;
+ }
+ if (*cp == '\0')
+ {
+ lastone = TRUE;
+ break;
+ }
+ }
+ if (i < blen)
+ {
+ int val = atoi(s);
+
+ if (val < 0 || val >= nr_substrings)
+ {
+ syserr("field (%d) out of range, only %d substrings in pattern",
+ val, nr_substrings);
+ return -1;
+ }
+ ibuf[i++] = val;
+ }
+ else
+ {
+ syserr("too many fields, %d max\n", blen);
+ return -1;
+ }
+ s = ++cp;
+ } while (!lastone);
+ ibuf[i] = END_OF_FIELDS;
+ return i;
+}
+
+bool
+regex_map_init(map, ap)
+ MAP *map;
+ char *ap;
+{
+ int regerr;
+ struct regex_map *map_p;
+ register char *p;
+ char *sub_param = NULL;
+ int pflags;
+ static char defdstr[] = { (char)DEFAULT_DELIM, '\0' };
+
+ if (tTd(38, 2))
+ printf("regex_map_init: mapname '%s', args '%s'\n",
+ map->map_mname, ap);
+
+ pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB;
+
+ p = ap;
+
+ map_p = (struct regex_map *) xnalloc(sizeof(struct regex_map));
+
+ for (;;)
+ {
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p != '-')
+ break;
+ switch (*++p)
+ {
+ case 'n': /* not */
+ map->map_mflags |= MF_REGEX_NOT;
+ break;
+
+ case 'f': /* case sensitive */
+ map->map_mflags |= MF_NOFOLDCASE;
+ pflags &= ~REG_ICASE;
+ break;
+
+ case 'b': /* basic regular expressions */
+ pflags &= ~REG_EXTENDED;
+ break;
+
+ case 's': /* substring match () syntax */
+ sub_param = ++p;
+ pflags &= ~REG_NOSUB;
+ break;
+
+ case 'd': /* delimiter */
+ map_p->delim = ++p;
+ break;
+
+ case 'a': /* map append */
+ map->map_app = ++p;
+ break;
+
+ case 'm': /* matchonly */
+ map->map_mflags |= MF_MATCHONLY;
+ break;
+
+ }
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+ }
+ if (tTd(38, 3))
+ printf("regex_map_init: compile '%s' 0x%x\n", p, pflags);
+
+ if ((regerr = regcomp(&(map_p->pattern_buf), p, pflags)) != 0)
+ {
+ /* Errorhandling */
+ char errbuf[ERRBUF_SIZE];
+
+ regerror(regerr, &(map_p->pattern_buf), errbuf, ERRBUF_SIZE);
+ syserr("pattern-compile-error: %s\n", errbuf);
+ free(map_p);
+ return FALSE;
+ }
+
+ if (map->map_app != NULL)
+ map->map_app = newstr(map->map_app);
+ if (map_p->delim != NULL)
+ map_p->delim = newstr(map_p->delim);
+ else
+ map_p->delim = defdstr;
+
+ if (!bitset(REG_NOSUB, pflags))
+ {
+ /* substring matching */
+ int substrings;
+ int *fields = (int *)xalloc(sizeof(int) * (MAX_MATCH + 1));
+
+ substrings = map_p->pattern_buf.re_nsub + 1;
+
+ if (tTd(38, 3))
+ printf("regex_map_init: nr of substrings %d\n", substrings);
+
+ if (substrings >= MAX_MATCH)
+ {
+ syserr("too many substrings, %d max\n", MAX_MATCH);
+ free(map_p);
+ return FALSE;
+ }
+ if (sub_param != NULL && sub_param[0] != '\0')
+ {
+ /* optional parameter -sfields */
+ if (parse_fields(sub_param, fields,
+ MAX_MATCH + 1, substrings) == -1)
+ return FALSE;
+ }
+ else
+ {
+ /* set default fields */
+ int i;
+
+ for (i = 0; i < substrings; i++)
+ fields[i] = i;
+ fields[i] = END_OF_FIELDS;
+ }
+ map_p->regex_subfields = fields;
+ if (tTd(38, 3))
+ {
+ int *ip;
+
+ printf("regex_map_init: subfields");
+ for (ip = fields; *ip != END_OF_FIELDS; ip++)
+ printf(" %d", *ip);
+ printf("\n");
+ }
+ }
+ map->map_db1 = (ARBPTR_T)map_p; /* dirty hack */
+
+ return TRUE;
+}
+
+static char *
+regex_map_rewrite(map, s, slen, av)
+ MAP *map;
+ const char *s;
+ size_t slen;
+ char **av;
+{
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ return map_rewrite(map, av[0], strlen(av[0]), NULL);
+ else
+ return map_rewrite(map, s, slen, NULL);
+}
+
+char *
+regex_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ int reg_res;
+ struct regex_map *map_p;
+ regmatch_t pmatch[MAX_MATCH];
+
+ if (tTd(38, 20))
+ {
+ char **cpp;
+
+ printf("regex_map_lookup: key '%s'\n", name);
+ for (cpp = av; cpp && *cpp; cpp++)
+ printf("regex_map_lookup: arg '%s'\n", *cpp);
+ }
+
+ map_p = (struct regex_map *)(map->map_db1);
+ reg_res = regexec(&(map_p->pattern_buf), name, MAX_MATCH, pmatch, 0);
+
+ if (bitset(MF_REGEX_NOT, map->map_mflags))
+ {
+ /* option -n */
+ if (reg_res == REG_NOMATCH)
+ return regex_map_rewrite(map, "", (size_t)0, av);
+ else
+ return NULL;
+ }
+ if (reg_res == REG_NOMATCH)
+ return NULL;
+
+ if (map_p->regex_subfields != NULL)
+ {
+ /* option -s */
+ static char retbuf[MAXNAME];
+ int fields[MAX_MATCH + 1];
+ bool first = TRUE;
+ int anglecnt = 0, cmntcnt = 0, spacecnt = 0;
+ bool quotemode = FALSE, bslashmode = FALSE;
+ register char *dp, *sp;
+ char *endp, *ldp;
+ int *ip;
+
+ dp = retbuf;
+ ldp = retbuf + sizeof(retbuf) - 1;
+
+ if (av[1] != NULL)
+ {
+ if (parse_fields(av[1], fields, MAX_MATCH + 1,
+ (int) map_p->pattern_buf.re_nsub + 1) == -1)
+ {
+ *statp = EX_CONFIG;
+ return NULL;
+ }
+ ip = fields;
+ }
+ else
+ ip = map_p->regex_subfields;
+
+ for ( ; *ip != END_OF_FIELDS; ip++)
+ {
+ if (!first)
+ {
+ for (sp = map_p->delim; *sp; sp++)
+ {
+ if (dp < ldp)
+ *dp++ = *sp;
+ }
+ }
+ else
+ first = FALSE;
+
+
+ if (pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0)
+ continue;
+
+ sp = name + pmatch[*ip].rm_so;
+ endp = name + pmatch[*ip].rm_eo;
+ for (; endp > sp; sp++)
+ {
+ if (dp < ldp)
+ {
+ if(bslashmode)
+ {
+ *dp++ = *sp;
+ bslashmode = FALSE;
+ }
+ else if(quotemode && *sp != '"' &&
+ *sp != '\\')
+ {
+ *dp++ = *sp;
+ }
+ else switch(*dp++ = *sp)
+ {
+ case '\\':
+ bslashmode = TRUE;
+ break;
+
+ case '(':
+ cmntcnt++;
+ break;
+
+ case ')':
+ cmntcnt--;
+ break;
+
+ case '<':
+ anglecnt++;
+ break;
+
+ case '>':
+ anglecnt--;
+ break;
+
+ case ' ':
+ spacecnt++;
+ break;
+
+ case '"':
+ quotemode = !quotemode;
+ break;
+ }
+ }
+ }
+ }
+ if (anglecnt != 0 || cmntcnt != 0 || quotemode ||
+ bslashmode || spacecnt != 0)
+ {
+ sm_syslog(LOG_WARNING, NOQID,
+ "Warning: regex may cause prescan() failure map=%s lookup=%s",
+ map->map_mname, name);
+ return NULL;
+ }
+
+ *dp = '\0';
+
+ return regex_map_rewrite(map, retbuf, strlen(retbuf), av);
+ }
+ return regex_map_rewrite(map, "", (size_t)0, av);
+}
+#endif /* MAP_REGEX */