diff options
Diffstat (limited to 'usr.sbin/sendmail/makemap/makemap.c')
| -rw-r--r-- | usr.sbin/sendmail/makemap/makemap.c | 303 |
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 +} |
