summaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/makemap/makemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/makemap/makemap.c')
-rw-r--r--usr.sbin/sendmail/makemap/makemap.c303
1 files changed, 272 insertions, 31 deletions
diff --git a/usr.sbin/sendmail/makemap/makemap.c b/usr.sbin/sendmail/makemap/makemap.c
index 2e289a81641eb..027d208c5d89b 100644
--- a/usr.sbin/sendmail/makemap/makemap.c
+++ b/usr.sbin/sendmail/makemap/makemap.c
@@ -33,21 +33,15 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)makemap.c 8.19 (Berkeley) 11/18/96";
+static char sccsid[] = "@(#)makemap.c 8.35 (Berkeley) 6/10/97";
#endif /* not lint */
-#include <stdio.h>
-#include <sysexits.h>
#include <sys/types.h>
-#include <ctype.h>
-#include <string.h>
#include <sys/errno.h>
#ifndef ISC_UNIX
# include <sys/file.h>
#endif
-#define NOT_SENDMAIL
-#include "useful.h"
-#include "conf.h"
+#include "sendmail.h"
#ifdef NDBM
#include <ndbm.h>
@@ -74,6 +68,17 @@ union dbent
} xx;
};
+uid_t RealUid;
+gid_t RealGid;
+char *RealUserName;
+uid_t RunAsUid;
+uid_t RunAsGid;
+char *RunAsUserName;
+int Verbose = 2;
+bool DontInitGroups = TRUE;
+bool UnsafeGroupWrites = FALSE;
+u_char tTdvect[100];
+
#define BUFSIZE 1024
main(argc, argv)
@@ -87,12 +92,12 @@ main(argc, argv)
bool allowdups = FALSE;
bool verbose = FALSE;
bool foldcase = TRUE;
+ bool ignoresafeties = FALSE;
int exitstat;
int opt;
char *typename;
char *mapname;
char *ext;
- char *lext;
int lineno;
int st;
int mode;
@@ -117,15 +122,33 @@ main(argc, argv)
#endif
char ibuf[BUFSIZE];
char fbuf[MAXNAME];
- char lbuf[MAXNAME];
+ char dbuf[MAXNAME];
+ char pbuf[MAXNAME];
+ static char rnamebuf[MAXNAME]; /* holds RealUserName */
+ struct passwd *pw;
+ int sff = SFF_ROOTOK|SFF_REGONLY|SFF_NOLINK|SFF_NOWLINK;
+ struct stat std, stp;
extern char *optarg;
extern int optind;
extern bool lockfile();
progname = argv[0];
-#ifdef FFR_CFLAG
-#define OPTIONS "Nc:dforv"
+ RunAsUid = RealUid = getuid();
+ RunAsGid = RealGid = getgid();
+ pw = getpwuid(RealUid);
+ if (pw != NULL)
+ {
+ if (strlen(pw->pw_name) > MAXNAME - 1)
+ pw->pw_name[MAXNAME] = 0;
+ sprintf(rnamebuf, "%s", pw->pw_name);
+ }
+ else
+ sprintf(rnamebuf, "Unknown UID %d", RealUid);
+ RunAsUserName = RealUserName = rnamebuf;
+
+#if _FFR_NEW_MAKEMAP_FLAGS
+#define OPTIONS "Nc:dforsv"
#else
#define OPTIONS "Ndforv"
#endif
@@ -137,7 +160,7 @@ main(argc, argv)
inclnull = TRUE;
break;
-#ifdef FFR_CFLAG
+#if _FFR_NEW_MAKEMAP_FLAGS
case 'c':
dbcachesize = atol(optarg);
break;
@@ -159,6 +182,12 @@ main(argc, argv)
allowreplace = TRUE;
break;
+#if _FFR_NEW_MAKEMAP_FLAGS
+ case 's':
+ ignoresafeties = TRUE;
+ break;
+#endif
+
case 'v':
verbose = TRUE;
break;
@@ -178,12 +207,10 @@ main(argc, argv)
typename = argv[0];
mapname = argv[1];
ext = NULL;
- lext = NULL;
if (strcmp(typename, "dbm") == 0)
{
type = T_DBM;
- lext = ".dir";
}
else if (strcmp(typename, "btree") == 0)
{
@@ -202,8 +229,10 @@ main(argc, argv)
switch (type)
{
case T_ERR:
-#ifdef FFR_CFLAG
- fprintf(stderr, "Usage: %s [-N] [-c cachesize] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname);
+#if _FFR_NEW_MAKEMAP_FLAGS
+ fprintf(stderr,
+ "Usage: %s [-N] [-c cachesize] [-d] [-f] [-o] [-r] [-s] [-v] type mapname\n",
+ progname);
#else
fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname);
#endif
@@ -270,6 +299,11 @@ main(argc, argv)
el = strlen(ext);
fl = strlen(mapname);
+ if (el + fl + 1 >= sizeof fbuf)
+ {
+ fprintf(stderr, "%s: file name too long", mapname);
+ exit(EX_USAGE);
+ }
if (fl < el || strcmp(&mapname[fl - el], ext) != 0)
{
strcpy(fbuf, mapname);
@@ -278,9 +312,68 @@ main(argc, argv)
}
}
- strcpy(lbuf, mapname);
- if (lext != NULL)
- strcat(lbuf, lext);
+ if (!notrunc)
+ sff |= SFF_CREAT;
+ switch (type)
+ {
+#ifdef NEWDB
+ case T_BTREE:
+ case T_HASH:
+ if (strlen(mapname) >= sizeof dbuf)
+ {
+ fprintf(stderr,
+ "%s: map name too long\n", mapname);
+ exit(EX_USAGE);
+ }
+ strcpy(dbuf, mapname);
+ if (!ignoresafeties &&
+ (st = safefile(dbuf, RealUid, RealGid, RealUserName,
+ sff, S_IWUSR, &std)) != 0)
+ {
+ fprintf(stderr,
+ "%s: could not create: %s\n",
+ dbuf, errstring(st));
+ exit(EX_CANTCREAT);
+ }
+ break;
+#endif
+#ifdef NDBM
+ case T_DBM:
+ if (strlen(mapname) + 5 > sizeof dbuf)
+ {
+ fprintf(stderr,
+ "%s: map name too long\n", mapname);
+ exit(EX_USAGE);
+ }
+ sprintf(dbuf, "%s.dir", mapname);
+ if (!ignoresafeties &&
+ (st = safefile(dbuf, RealUid, RealGid, RealUserName,
+ sff, S_IWUSR, &std)) != 0)
+ {
+ fprintf(stderr,
+ "%s: could not create: %s\n",
+ dbuf, errstring(st));
+ exit(EX_CANTCREAT);
+ }
+ sprintf(pbuf, "%s.pag", mapname);
+ if (!ignoresafeties &&
+ (st = safefile(pbuf, RealUid, RealGid, RealUserName,
+ sff, S_IWUSR, &stp)) != 0)
+ {
+ fprintf(stderr,
+ "%s: could not create: %s\n",
+ pbuf, errstring(st));
+ exit(EX_CANTCREAT);
+ }
+ break;
+#endif
+ default:
+ fprintf(stderr,
+ "%s: internal error: type %d\n",
+ progname,
+ type);
+ exit(EX_SOFTWARE);
+ }
/*
** Create the database.
@@ -289,24 +382,36 @@ main(argc, argv)
mode = O_RDWR;
if (!notrunc)
mode |= O_CREAT|O_TRUNC;
-#ifdef O_EXLOCK
+#if O_EXLOCK
mode |= O_EXLOCK;
#else
/* pre-lock the database */
- fd = open(lbuf, mode & ~O_TRUNC, 0644);
+ if (ignoresafeties)
+ fd = dfopen(dbuf, mode & ~O_TRUNC, 0644, sff);
+ else
+ fd = safeopen(dbuf, mode & ~O_TRUNC, 0644, sff);
if (fd < 0)
{
fprintf(stderr, "%s: cannot create type %s map %s\n",
progname, typename, mapname);
exit(EX_CANTCREAT);
}
- (void) lockfile(fd);
#endif
switch (type)
{
#ifdef NDBM
case T_DBM:
dbp.dbm = dbm_open(mapname, mode, 0644);
+ if (!ignoresafeties && dbp.dbm != NULL &&
+ (filechanged(dbuf, dbm_dirfno(dbp.dbm), &std, sff) ||
+ filechanged(pbuf, dbm_pagfno(dbp.dbm), &stp, sff)))
+ {
+ fprintf(stderr,
+ "dbm map %s: file changed after open\n",
+ mapname);
+ dbm_close(dbp.dbm);
+ exit(EX_CANTCREAT);
+ }
break;
#endif
@@ -315,10 +420,19 @@ main(argc, argv)
/* tweak some parameters for performance */
hinfo.nelem = 4096;
hinfo.cachesize = dbcachesize;
-
+
dbp.db = dbopen(mapname, mode, 0644, DB_HASH, &hinfo);
if (dbp.db != NULL)
{
+ if (!ignoresafeties &&
+ filechanged(dbuf, dbp.db->fd(dbp.db), &std, sff))
+ {
+ fprintf(stderr,
+ "db map %s: file changed after open\n",
+ mapname);
+ dbp.db->close(dbp.db);
+ exit(EX_CANTCREAT);
+ }
# if OLD_NEWDB
(void) (*dbp.db->sync)(dbp.db);
# else
@@ -334,6 +448,15 @@ main(argc, argv)
dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti);
if (dbp.db != NULL)
{
+ if (!ignoresafeties &&
+ filechanged(dbuf, dbp.db->fd(dbp.db), &std, sff))
+ {
+ fprintf(stderr,
+ "db map %s: file changed after open\n",
+ mapname);
+ dbp.db->close(dbp.db);
+ exit(EX_CANTCREAT);
+ }
# if OLD_NEWDB
(void) (*dbp.db->sync)(dbp.db);
# else
@@ -344,7 +467,8 @@ main(argc, argv)
#endif
default:
- fprintf(stderr, "%s: internal error: type %d\n", progname, type);
+ fprintf(stderr, "%s: internal error: type %d\n",
+ progname, type);
exit(EX_SOFTWARE);
}
@@ -447,7 +571,8 @@ main(argc, argv)
}
else if (st > 0)
{
- fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n",
+ fprintf(stderr,
+ "%s: %s: line %d: key %s: duplicate key\n",
progname, mapname, lineno, key.xx.data);
}
}
@@ -477,7 +602,7 @@ main(argc, argv)
#endif
}
-#ifndef O_EXLOCK
+#if !O_EXLOCK
/* release locks */
close(fd);
#endif
@@ -489,6 +614,11 @@ main(argc, argv)
**
** Parameters:
** fd -- the file descriptor of the file.
+** filename -- the file name (for error messages).
+** ext -- the filename extension.
+** type -- type of the lock. Bits can be:
+** LOCK_EX -- exclusive lock.
+** LOCK_NB -- non-blocking.
**
** Returns:
** TRUE if the lock was acquired.
@@ -496,8 +626,11 @@ main(argc, argv)
*/
bool
-lockfile(fd)
+lockfile(fd, filename, ext, type)
int fd;
+ char *filename;
+ char *ext;
+ int type;
{
# if !HASFLOCK
int action;
@@ -505,8 +638,16 @@ lockfile(fd)
extern int errno;
bzero(&lfd, sizeof lfd);
- lfd.l_type = F_WRLCK;
- action = F_SETLKW;
+ if (bitset(LOCK_UN, type))
+ lfd.l_type = F_UNLCK;
+ else if (bitset(LOCK_EX, type))
+ lfd.l_type = F_WRLCK;
+ else
+ lfd.l_type = F_RDLCK;
+ if (bitset(LOCK_NB, type))
+ action = F_SETLK;
+ else
+ action = F_SETLKW;
if (fcntl(fd, action, &lfd) >= 0)
return TRUE;
@@ -525,10 +666,110 @@ lockfile(fd)
# else /* HASFLOCK */
- if (flock(fd, LOCK_EX) >= 0)
+ if (flock(fd, type) >= 0)
return TRUE;
# endif
return FALSE;
}
+
+/*VARARGS2*/
+void
+#ifdef __STDC__
+message(const char *msg, ...)
+#else
+message(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif
+{
+ const char *m;
+ VA_LOCAL_DECL
+
+ m = msg;
+ if (isdigit(m[0]) && isdigit(m[1]) && isdigit(m[2]) && m[3] == ' ')
+ m += 4;
+ VA_START(msg);
+ vfprintf(stderr, m, ap);
+ VA_END;
+ fprintf(stderr, "\n");
+}
+
+/*VARARGS2*/
+void
+#ifdef __STDC__
+syserr(const char *msg, ...)
+#else
+syserr(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif
+{
+ const char *m;
+ VA_LOCAL_DECL
+
+ m = msg;
+ if (isdigit(m[0]) && isdigit(m[1]) && isdigit(m[2]) && m[3] == ' ')
+ m += 4;
+ VA_START(msg);
+ vfprintf(stderr, m, ap);
+ VA_END;
+ fprintf(stderr, "\n");
+}
+
+const char *
+errstring(err)
+ int err;
+{
+ static char errstr[64];
+#if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+#endif
+
+ /* handle pseudo-errors internal to sendmail */
+ switch (err)
+ {
+ case E_SM_OPENTIMEOUT:
+ return "Timeout on file open";
+
+ case E_SM_NOSLINK:
+ return "Symbolic links not allowed";
+
+ case E_SM_NOHLINK:
+ return "Hard links not allowed";
+
+ case E_SM_REGONLY:
+ return "Regular files only";
+
+ case E_SM_ISEXEC:
+ return "Executable files not allowed";
+
+ case E_SM_WWDIR:
+ return "World writable directory";
+
+ case E_SM_GWDIR:
+ return "Group writable directory";
+
+ case E_SM_FILECHANGE:
+ return "File changed after open";
+
+ case E_SM_WWFILE:
+ return "World writable file";
+
+ case E_SM_GWFILE:
+ return "Group writable file";
+ }
+
+#if HASSTRERROR
+ return strerror(err);
+#else
+ if (err < 0 || err > sys_nerr)
+ {
+ sprintf(errstr, "Error %d", err);
+ return errstr;
+ }
+ return sys_errlist[err];
+#endif
+}