diff options
author | peter <peter@FreeBSD.org> | 1995-12-02 18:17:40 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1995-12-02 18:17:40 +0000 |
commit | a531c1a15720076e696b7ecb296c53191cf906c6 (patch) | |
tree | a0e24bbe1b4263b12bb5a33862e1d9f0272e8ef8 /usr.sbin/sendmail/src/util.c | |
parent | 91b3d1fef5f70cc06d726f635e7a187744eb869d (diff) | |
download | FreeBSD-src-a531c1a15720076e696b7ecb296c53191cf906c6.zip FreeBSD-src-a531c1a15720076e696b7ecb296c53191cf906c6.tar.gz |
Initial round of conflict resolutions.. I need to do another
pass over this and check it more closely, but my initial concern was
to get it to all compile again. Some of the obsoleted files 'cvs rm'ed.
Diffstat (limited to 'usr.sbin/sendmail/src/util.c')
-rw-r--r-- | usr.sbin/sendmail/src/util.c | 740 |
1 files changed, 595 insertions, 145 deletions
diff --git a/usr.sbin/sendmail/src/util.c b/usr.sbin/sendmail/src/util.c index b7e1d14..eac336e 100644 --- a/usr.sbin/sendmail/src/util.c +++ b/usr.sbin/sendmail/src/util.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. * @@ -33,7 +33,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)util.c 8.39.1.5 (Berkeley) 3/5/95"; +static char sccsid[] = "@(#)util.c 8.84 (Berkeley) 11/18/95"; #endif /* not lint */ # include "sendmail.h" @@ -57,6 +57,7 @@ static char sccsid[] = "@(#)util.c 8.39.1.5 (Berkeley) 3/5/95"; ** deliver */ +void stripquotes(s) char *s; { @@ -107,8 +108,7 @@ xalloc(sz) p = malloc((unsigned) sz); if (p == NULL) { - syserr("Out of memory!!"); - abort(); + syserr("!Out of memory!!"); /* exit(EX_UNAVAILABLE); */ } return (p); @@ -208,6 +208,7 @@ copyqueue(addr) ** prints av. */ +void printav(av) register char **av; { @@ -253,8 +254,9 @@ lower(c) ** output to stdout */ +void xputs(s) - register char *s; + register const char *s; { register int c; register struct metamac *mp; @@ -269,11 +271,20 @@ xputs(s) { if (!isascii(c)) { - if (c == MATCHREPL || c == MACROEXPAND) + if (c == MATCHREPL) { putchar('$'); continue; } + if (c == MACROEXPAND) + { + putchar('$'); + if (strchr("=~&?", *s) != NULL) + putchar(*s++); + if (bitset(0200, *s)) + printf("{%s}", macname(*s++ & 0377)); + continue; + } for (mp = MetaMacros; mp->metaname != '\0'; mp++) { if ((mp->metaval & 0377) == c) @@ -282,6 +293,12 @@ xputs(s) break; } } + if (c == MATCHCLASS || c == MATCHNCLASS) + { + if (!bitset(0200, *s)) + continue; + printf("{%s}", macname(*s++ & 0377)); + } if (mp->metaname != '\0') continue; (void) putchar('\\'); @@ -296,9 +313,6 @@ xputs(s) /* wasn't a meta-macro -- find another way to print it */ switch (c) { - case '\0': - continue; - case '\n': c = 'n'; break; @@ -316,6 +330,8 @@ xputs(s) (void) putchar(c ^ 0100); continue; } + (void) putchar('\\'); + (void) putchar(c); } (void) fflush(stdout); } @@ -336,6 +352,7 @@ xputs(s) ** parse */ +void makelower(p) register char *p; { @@ -365,6 +382,7 @@ makelower(p) ** none. */ +void buildfname(gecos, login, buf) register char *gecos; char *login; @@ -415,6 +433,8 @@ buildfname(gecos, login, buf) ** SFF_MUSTOWN -- "uid" must own this file. ** SFF_NOSLINK -- file cannot be a symbolic link. ** mode -- mode bits that must match. +** st -- if set, points to a stat structure that will +** get the stat info for the file. ** ** Returns: ** 0 if fn exists, is owned by uid, and matches mode. @@ -438,104 +458,195 @@ buildfname(gecos, login, buf) # define S_IXUSR (S_IEXEC) #endif +#define ST_MODE_NOFILE 0171147 /* unlikely to occur */ + int -safefile(fn, uid, gid, uname, flags, mode) +safefile(fn, uid, gid, uname, flags, mode, st) char *fn; uid_t uid; gid_t gid; char *uname; int flags; int mode; + struct stat *st; { register char *p; register struct group *gr = NULL; + int file_errno = 0; struct stat stbuf; + struct stat fstbuf; - if (tTd(54, 4)) + if (tTd(44, 4)) printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n", fn, uid, gid, flags, mode); errno = 0; + if (st == NULL) + st = &fstbuf; - for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/') + /* first check to see if the file exists at all */ +#ifdef HASLSTAT + if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st) + : stat(fn, st)) < 0) +#else + if (stat(fn, st) < 0) +#endif { - *p = '\0'; - if (stat(fn, &stbuf) < 0) - break; - if (uid == 0 && !bitset(SFF_ROOTOK, flags)) + file_errno = errno; + } + else if (bitset(SFF_SETUIDOK, flags) && + !bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode) && + S_ISREG(st->st_mode)) + { + /* + ** If final file is setuid, run as the owner of that + ** file. Gotta be careful not to reveal anything too + ** soon here! + */ + +#ifdef SUID_ROOT_FILES_OK + if (bitset(S_ISUID, st->st_mode)) +#else + if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0) +#endif { - if (bitset(S_IXOTH, stbuf.st_mode)) - continue; - break; + uid = st->st_uid; + uname = NULL; } - if (stbuf.st_uid == uid && bitset(S_IXUSR, stbuf.st_mode)) - continue; - if (stbuf.st_gid == gid && bitset(S_IXGRP, stbuf.st_mode)) - continue; -#ifndef NO_GROUP_SET - if (uname != NULL && - ((gr != NULL && gr->gr_gid == stbuf.st_gid) || - (gr = getgrgid(stbuf.st_gid)) != NULL)) - { - register char **gp; +#ifdef SUID_ROOT_FILES_OK + if (bitset(S_ISGID, st->st_mode)) +#else + if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0) +#endif + gid = st->st_gid; + } - for (gp = gr->gr_mem; *gp != NULL; gp++) - if (strcmp(*gp, uname) == 0) - break; - if (*gp != NULL && bitset(S_IXGRP, stbuf.st_mode)) + if (!bitset(SFF_NOPATHCHECK, flags) || + (uid == 0 && !bitset(SFF_ROOTOK, flags))) + { + /* check the path to the file for acceptability */ + for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/') + { + *p = '\0'; + if (stat(fn, &stbuf) < 0) + break; + if (uid == 0 && bitset(S_IWGRP|S_IWOTH, stbuf.st_mode)) + message("051 WARNING: writable directory %s", + fn); + if (uid == 0 && !bitset(SFF_ROOTOK, flags)) + { + if (bitset(S_IXOTH, stbuf.st_mode)) + continue; + break; + } + if (stbuf.st_uid == uid && + bitset(S_IXUSR, stbuf.st_mode)) continue; - } + if (stbuf.st_gid == gid && + bitset(S_IXGRP, stbuf.st_mode)) + continue; +#ifndef NO_GROUP_SET + if (uname != NULL && + ((gr != NULL && gr->gr_gid == stbuf.st_gid) || + (gr = getgrgid(stbuf.st_gid)) != NULL)) + { + register char **gp; + + for (gp = gr->gr_mem; gp != NULL && *gp != NULL; gp++) + if (strcmp(*gp, uname) == 0) + break; + if (gp != NULL && *gp != NULL && + bitset(S_IXGRP, stbuf.st_mode)) + continue; + } #endif - if (!bitset(S_IXOTH, stbuf.st_mode)) - break; + if (!bitset(S_IXOTH, stbuf.st_mode)) + break; + } + if (p != NULL) + { + int ret = errno; + + if (ret == 0) + ret = EACCES; + if (tTd(44, 4)) + printf("\t[dir %s] %s\n", fn, errstring(ret)); + *p = '/'; + return ret; + } } - if (p != NULL) - { - int ret = errno; - if (ret == 0) - ret = EACCES; - if (tTd(54, 4)) - printf("\t[dir %s] %s\n", fn, errstring(ret)); - *p = '/'; - return ret; - } + /* + ** If the target file doesn't exist, check the directory to + ** ensure that it is writable by this user. + */ -#ifdef HASLSTAT - if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, &stbuf) - : stat(fn, &stbuf)) < 0) -#else - if (stat(fn, &stbuf) < 0) -#endif + if (file_errno != 0) { - int ret = errno; + int ret = file_errno; - if (tTd(54, 4)) + if (tTd(44, 4)) printf("\t%s\n", errstring(ret)); errno = 0; + if (!bitset(SFF_CREAT, flags)) + return ret; + + /* check to see if legal to create the file */ + p = strrchr(fn, '/'); + if (p == NULL) + return ENOTDIR; + *p = '\0'; + if (stat(fn, &stbuf) >= 0) + { + int md = S_IWRITE|S_IEXEC; + if (stbuf.st_uid != uid) + md >>= 6; + if ((stbuf.st_mode & md) != md) + errno = EACCES; + } + ret = errno; + if (tTd(44, 4)) + printf("\t[final dir %s uid %d mode %o] %s\n", + fn, stbuf.st_uid, stbuf.st_mode, + errstring(ret)); + *p = '/'; + st->st_mode = ST_MODE_NOFILE; return ret; } #ifdef S_ISLNK - if (bitset(SFF_NOSLINK, flags) && S_ISLNK(stbuf.st_mode)) + if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode)) { - if (tTd(54, 4)) - printf("\t[slink mode %o]\tEPERM\n", stbuf.st_mode); + if (tTd(44, 4)) + printf("\t[slink mode %o]\tEPERM\n", st->st_mode); return EPERM; } #endif + if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode)) + { + if (tTd(44, 4)) + printf("\t[non-reg mode %o]\tEPERM\n", st->st_mode); + return EPERM; + } + if (bitset(S_IWUSR|S_IWGRP|S_IWOTH, mode) && + bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode)) + { + if (tTd(44, 4)) + printf("\t[exec bits %o]\tEPERM]\n", st->st_mode); + return EPERM; + } if (uid == 0 && !bitset(SFF_ROOTOK, flags)) mode >>= 6; - else if (stbuf.st_uid != uid) + else if (st->st_uid != uid) { mode >>= 3; - if (stbuf.st_gid == gid) + if (st->st_gid == gid) ; #ifndef NO_GROUP_SET else if (uname != NULL && - ((gr != NULL && gr->gr_gid == stbuf.st_gid) || - (gr = getgrgid(stbuf.st_gid)) != NULL)) + ((gr != NULL && gr->gr_gid == st->st_gid) || + (gr = getgrgid(st->st_gid)) != NULL)) { register char **gp; @@ -549,22 +660,104 @@ safefile(fn, uid, gid, uname, flags, mode) else mode >>= 3; } - if (tTd(54, 4)) + if (tTd(44, 4)) printf("\t[uid %d, stat %o, mode %o] ", - stbuf.st_uid, stbuf.st_mode, mode); - if ((stbuf.st_uid == uid || stbuf.st_uid == 0 || + st->st_uid, st->st_mode, mode); + if ((st->st_uid == uid || st->st_uid == 0 || !bitset(SFF_MUSTOWN, flags)) && - (stbuf.st_mode & mode) == mode) + (st->st_mode & mode) == mode) { - if (tTd(54, 4)) + if (tTd(44, 4)) printf("\tOK\n"); return 0; } - if (tTd(54, 4)) + if (tTd(44, 4)) printf("\tEACCES\n"); return EACCES; } /* +** SAFEFOPEN -- do a file open with extra checking +** +** Parameters: +** fn -- the file name to open. +** omode -- the open-style mode flags. +** cmode -- the create-style mode flags. +** sff -- safefile flags. +** +** Returns: +** Same as fopen. +*/ + +#ifndef O_ACCMODE +# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif + +FILE * +safefopen(fn, omode, cmode, sff) + char *fn; + int omode; + int cmode; + int sff; +{ + int rval; + FILE *fp; + int smode; + struct stat stb, sta; + + if (bitset(O_CREAT, omode)) + sff |= SFF_CREAT; + smode = 0; + switch (omode & O_ACCMODE) + { + case O_RDONLY: + smode = S_IREAD; + break; + + case O_WRONLY: + smode = S_IWRITE; + break; + + case O_RDWR: + smode = S_IREAD|S_IWRITE; + break; + + default: + smode = 0; + break; + } + if (bitset(SFF_OPENASROOT, sff)) + rval = safefile(fn, 0, 0, NULL, sff, smode, &stb); + else + rval = safefile(fn, RealUid, RealGid, RealUserName, + sff, smode, &stb); + if (rval != 0) + { + errno = rval; + return NULL; + } + if (stb.st_mode == ST_MODE_NOFILE) + omode |= O_EXCL; + + fp = dfopen(fn, omode, cmode); + if (fp == NULL) + return NULL; + if (bitset(O_EXCL, omode)) + return fp; + if (fstat(fileno(fp), &sta) < 0 || + sta.st_nlink != stb.st_nlink || + sta.st_dev != stb.st_dev || + sta.st_ino != stb.st_ino || + sta.st_uid != stb.st_uid || + sta.st_gid != stb.st_gid) + { + syserr("554 cannot open: file %s changed after open", fn); + fclose(fp); + errno = EPERM; + return NULL; + } + return fp; +} +/* ** FIXCRLF -- fix <CR><LF> in line. ** ** Looks for the <CR><LF> combination and turns it into the @@ -583,6 +776,7 @@ safefile(fn, uid, gid, uname, flags, mode) ** line is changed in place. */ +void fixcrlf(line, stripnl) char *line; bool stripnl; @@ -607,10 +801,6 @@ fixcrlf(line, stripnl) ** whatever), so this tries to get around it. */ -#ifndef O_ACCMODE -# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) -#endif - struct omodes { int mask; @@ -693,16 +883,46 @@ dfopen(filename, omode, cmode) ** output of l to fp. */ +void putline(l, mci) register char *l; register MCI *mci; { + putxline(l, mci, PXLF_MAPFROM); +} +/* +** PUTXLINE -- putline with flags bits. +** +** This routine always guarantees outputing a newline (or CRLF, +** as appropriate) at the end of the string. +** +** Parameters: +** l -- line to put. +** mci -- the mailer connection information. +** pxflags -- flag bits: +** PXLF_MAPFROM -- map From_ to >From_. +** PXLF_STRIP8BIT -- strip 8th bit. +** +** Returns: +** none +** +** Side Effects: +** output of l to fp. +*/ + +void +putxline(l, mci, pxflags) + register char *l; + register MCI *mci; + int pxflags; +{ register char *p; register char svchar; int slop = 0; /* strip out 0200 bits -- these can look like TELNET protocol */ - if (bitset(MCIF_7BIT, mci->mci_flags)) + if (bitset(MCIF_7BIT, mci->mci_flags) || + bitset(PXLF_STRIP8BIT, pxflags)) { for (p = l; (svchar = *p) != '\0'; ++p) if (bitset(0200, svchar)) @@ -734,6 +954,15 @@ putline(l, mci) if (TrafficLogFile != NULL) (void) putc('.', TrafficLogFile); } + else if (l[0] == 'F' && slop == 0 && + bitset(PXLF_MAPFROM, pxflags) && + strncmp(l, "From ", 5) == 0 && + bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) + { + (void) putc('>', mci->mci_out); + if (TrafficLogFile != NULL) + (void) putc('>', TrafficLogFile); + } fputs(l, mci->mci_out); (void) putc('!', mci->mci_out); fputs(mci->mci_mailer->m_eol, mci->mci_out); @@ -776,6 +1005,7 @@ putline(l, mci) ** f is unlinked. */ +void xunlink(f) char *f; { @@ -806,13 +1036,14 @@ xunlink(f) ** fp is closed. */ +void xfclose(fp, a, b) FILE *fp; char *a, *b; { if (tTd(53, 99)) printf("xfclose(%x) %s %s\n", fp, a, b); -#ifdef XDEBUG +#if XDEBUG if (fileno(fp) == 1) syserr("xfclose(%s %s): fd = 1", a, b); #endif @@ -839,10 +1070,7 @@ xfclose(fp, a, b) */ static jmp_buf CtxReadTimeout; -static int readtimeout(); -static EVENT *GlobalTimeout = NULL; -static bool EnableTimeout = FALSE; -static int ReadProgress; +static void readtimeout(); char * sfgets(buf, siz, fp, timeout, during) @@ -868,22 +1096,19 @@ sfgets(buf, siz, fp, timeout, during) { # ifdef LOG syslog(LOG_NOTICE, - "timeout waiting for input from %s during %s\n", + "timeout waiting for input from %.100s during %s", CurHostName? CurHostName: "local", during); # endif errno = 0; usrerr("451 timeout waiting for input during %s", during); buf[0] = '\0'; -#ifdef XDEBUG +#if XDEBUG checkfd012(during); #endif return (NULL); } - if (GlobalTimeout == NULL) - ev = setevent(timeout, readtimeout, 0); - else - EnableTimeout = TRUE; + ev = setevent(timeout, readtimeout, 0); } /* try to read */ @@ -898,10 +1123,7 @@ sfgets(buf, siz, fp, timeout, during) } /* clear the event if it has not sprung */ - if (GlobalTimeout == NULL) - clrevent(ev); - else - EnableTimeout = FALSE; + clrevent(ev); /* clean up the books and exit */ LineNumber++; @@ -914,50 +1136,30 @@ sfgets(buf, siz, fp, timeout, during) } if (TrafficLogFile != NULL) fprintf(TrafficLogFile, "%05d <<< %s", getpid(), buf); - if (SevenBit) + if (SevenBitInput) + { for (p = buf; *p != '\0'; p++) *p &= ~0200; - return (buf); -} - -void -sfgetset(timeout) - time_t timeout; -{ - /* cancel pending timer */ - if (GlobalTimeout != NULL) - { - clrevent(GlobalTimeout); - GlobalTimeout = NULL; } - - /* schedule fresh one if so requested */ - if (timeout != 0) + else if (!HasEightBits) { - ReadProgress = LineNumber; - GlobalTimeout = setevent(timeout, readtimeout, timeout); + for (p = buf; *p != '\0'; p++) + { + if (bitset(0200, *p)) + { + HasEightBits = TRUE; + break; + } + } } + return (buf); } -static +static void readtimeout(timeout) time_t timeout; { - /* terminate if ordinary timeout */ - if (GlobalTimeout == NULL) - longjmp(CtxReadTimeout, 1); - - /* terminate if no progress was made -- reset state */ - if (EnableTimeout && (LineNumber <= ReadProgress)) - { - EnableTimeout = FALSE; - GlobalTimeout = NULL; - longjmp(CtxReadTimeout, 2); - } - - /* schedule a new timeout */ - GlobalTimeout = NULL; - sfgetset(timeout); + longjmp(CtxReadTimeout, 1); } /* ** FGETFOLDED -- like fgets, but know about folded lines. @@ -1033,7 +1235,9 @@ fgetfolded(buf, n, f) } if (p == bp) return (NULL); - *--p = '\0'; + if (p[-1] == '\n') + p--; + *p = '\0'; return (bp); } /* @@ -1095,6 +1299,7 @@ atobool(s) ** none. */ +int atooct(s) register char *s; { @@ -1241,10 +1446,11 @@ strcontainedin(a, b) ** none */ +void checkfd012(where) char *where; { -#ifdef XDEBUG +#if XDEBUG register int i; struct stat stbuf; @@ -1277,9 +1483,9 @@ checkfd012(where) ** none. */ -#include <netdb.h> #include <arpa/inet.h> +void printopenfds(logit) bool logit; { @@ -1299,18 +1505,22 @@ printopenfds(logit) ** logit -- if set, send output to syslog instead of stdout. */ +void dumpfd(fd, printclosed, logit) int fd; bool printclosed; bool logit; { - register struct hostent *hp; register char *p; + char *hp; char *fmtstr; - struct sockaddr_in sin; +#ifdef S_IFSOCK + SOCKADDR sa; +#endif auto int slen; struct stat st; char buf[200]; + extern char *hostnamebyanyaddr(); p = buf; sprintf(p, "%3d: ", fd); @@ -1341,26 +1551,30 @@ dumpfd(fd, printclosed, logit) case S_IFSOCK: sprintf(p, "SOCK "); p += strlen(p); - slen = sizeof sin; - if (getsockname(fd, (struct sockaddr *) &sin, &slen) < 0) - sprintf(p, "(badsock)"); + slen = sizeof sa; + if (getsockname(fd, &sa.sa, &slen) < 0) + sprintf(p, "(%s)", errstring(errno)); else { - hp = gethostbyaddr((char *) &sin.sin_addr, slen, AF_INET); - sprintf(p, "%s/%d", hp == NULL ? inet_ntoa(sin.sin_addr) - : hp->h_name, ntohs(sin.sin_port)); + hp = hostnamebyanyaddr(&sa); + if (sa.sa.sa_family == AF_INET) + sprintf(p, "%s/%d", hp, ntohs(sa.sin.sin_port)); + else + sprintf(p, "%s", hp); } p += strlen(p); sprintf(p, "->"); p += strlen(p); - slen = sizeof sin; - if (getpeername(fd, (struct sockaddr *) &sin, &slen) < 0) - sprintf(p, "(badsock)"); + slen = sizeof sa; + if (getpeername(fd, &sa.sa, &slen) < 0) + sprintf(p, "(%s)", errstring(errno)); else { - hp = gethostbyaddr((char *) &sin.sin_addr, slen, AF_INET); - sprintf(p, "%s/%d", hp == NULL ? inet_ntoa(sin.sin_addr) - : hp->h_name, ntohs(sin.sin_port)); + hp = hostnamebyanyaddr(&sa); + if (sa.sa.sa_family == AF_INET) + sprintf(p, "%s/%d", hp, ntohs(sa.sin.sin_port)); + else + sprintf(p, "%s", hp); } break; #endif @@ -1411,7 +1625,7 @@ defprint: printit: #ifdef LOG if (logit) - syslog(LOG_DEBUG, "%s", buf); + syslog(LOG_DEBUG, "%.800s", buf); else #endif printf("%s\n", buf); @@ -1436,7 +1650,7 @@ printit: char * shortenstring(s, m) - register char *s; + register const char *s; int m; { int l; @@ -1444,7 +1658,7 @@ shortenstring(s, m) l = strlen(s); if (l < m) - return s; + return (char *) s; if (m > MAXSHORTSTR) m = MAXSHORTSTR; else if (m < 10) @@ -1466,6 +1680,240 @@ shortenstring(s, m) return buf; } /* +** SHORTEN_HOSTNAME -- strip local domain information off of hostname. +** +** Parameters: +** host -- the host to shorten (stripped in place). +** +** Returns: +** none. +*/ + +void +shorten_hostname(host) + char host[]; +{ + register char *p; + char *mydom; + int i; + bool canon = FALSE; + + /* strip off final dot */ + p = &host[strlen(host) - 1]; + if (*p == '.') + { + *p = '\0'; + canon = TRUE; + } + + /* see if there is any domain at all -- if not, we are done */ + p = strchr(host, '.'); + if (p == NULL) + return; + + /* yes, we have a domain -- see if it looks like us */ + mydom = macvalue('m', CurEnv); + if (mydom == NULL) + mydom = ""; + i = strlen(++p); + if ((canon ? strcasecmp(p, mydom) : strncasecmp(p, mydom, i)) == 0 && + (mydom[i] == '.' || mydom[i] == '\0')) + *--p = '\0'; +} +/* +** PROG_OPEN -- open a program for reading +** +** Parameters: +** argv -- the argument list. +** pfd -- pointer to a place to store the file descriptor. +** e -- the current envelope. +** +** Returns: +** pid of the process -- -1 if it failed. +*/ + +int +prog_open(argv, pfd, e) + char **argv; + int *pfd; + ENVELOPE *e; +{ + int pid; + int i; + int saveerrno; + int fdv[2]; + char *p, *q; + char buf[MAXLINE + 1]; + extern int DtableSize; + + if (pipe(fdv) < 0) + { + syserr("%s: cannot create pipe for stdout", argv[0]); + return -1; + } + pid = fork(); + if (pid < 0) + { + syserr("%s: cannot fork", argv[0]); + close(fdv[0]); + close(fdv[1]); + return -1; + } + if (pid > 0) + { + /* parent */ + close(fdv[1]); + *pfd = fdv[0]; + return pid; + } + + /* child -- close stdin */ + close(0); + + /* stdout goes back to parent */ + close(fdv[0]); + if (dup2(fdv[1], 1) < 0) + { + syserr("%s: cannot dup2 for stdout", argv[0]); + _exit(EX_OSERR); + } + close(fdv[1]); + + /* stderr goes to transcript if available */ + if (e->e_xfp != NULL) + { + if (dup2(fileno(e->e_xfp), 2) < 0) + { + syserr("%s: cannot dup2 for stderr", argv[0]); + _exit(EX_OSERR); + } + } + + /* this process has no right to the queue file */ + if (e->e_lockfp != NULL) + close(fileno(e->e_lockfp)); + + /* run as default user */ + endpwent(); + setgid(DefGid); + setuid(DefUid); + + /* run in some directory */ + if (ProgMailer != NULL) + p = ProgMailer->m_execdir; + else + p = NULL; + for (; p != NULL; p = q) + { + q = strchr(p, ':'); + if (q != NULL) + *q = '\0'; + expand(p, buf, sizeof buf, e); + if (q != NULL) + *q++ = ':'; + if (buf[0] != '\0' && chdir(buf) >= 0) + break; + } + if (p == NULL) + { + /* backup directories */ + if (chdir("/tmp") < 0) + (void) chdir("/"); + } + + /* arrange for all the files to be closed */ + for (i = 3; i < DtableSize; i++) + { + register int j; + + if ((j = fcntl(i, F_GETFD, 0)) != -1) + (void) fcntl(i, F_SETFD, j | 1); + } + + /* now exec the process */ + execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); + + /* woops! failed */ + saveerrno = errno; + syserr("%s: cannot exec", argv[0]); + if (transienterror(saveerrno)) + _exit(EX_OSERR); + _exit(EX_CONFIG); +} +/* +** GET_COLUMN -- look up a Column in a line buffer +** +** Parameters: +** line -- the raw text line to search. +** col -- the column number to fetch. +** delim -- the delimiter between columns. If null, +** use white space. +** buf -- the output buffer. +** +** Returns: +** buf if successful. +** NULL otherwise. +*/ + +char * +get_column(line, col, delim, buf) + char line[]; + int col; + char delim; + char buf[]; +{ + char *p; + char *begin, *end; + int i; + char delimbuf[3]; + + if (delim == '\0') + strcpy(delimbuf, "\n\t "); + else + { + delimbuf[0] = delim; + delimbuf[1] = '\0'; + } + + p = line; + if (*p == '\0') + return NULL; /* line empty */ + if (*p == delim && col == 0) + return NULL; /* first column empty */ + + begin = line; + + if (col == 0 && delim == '\0') + { + while (*begin && isspace(*begin)) + begin++; + } + + for (i = 0; i < col; i++) + { + if ((begin = strpbrk(begin, delimbuf)) == NULL) + return NULL; /* no such column */ + begin++; + if (delim == '\0') + { + while (*begin && isspace(*begin)) + begin++; + } + } + + end = strpbrk(begin, delimbuf); + if (end == NULL) + { + strcpy(buf, begin); + } + else + { + strncpy(buf, begin, end - begin); + buf[end - begin] = '\0'; + } + return buf; +} +/* ** CLEANSTRCPY -- copy string keeping out bogus characters ** ** Parameters: @@ -1517,8 +1965,8 @@ cleanstrcpy(t, f, l) char * denlstring(s, strict, logattacks) char *s; - int strict; - int logattacks; + bool strict; + bool logattacks; { register char *p; int l; @@ -1545,14 +1993,16 @@ denlstring(s, strict, logattacks) for (p = bp; (p = strchr(p, '\n')) != NULL; ) *p++ = ' '; +/* #ifdef LOG if (logattacks) { - syslog(LOG_NOTICE, "POSSIBLE ATTACK from %s: newline in string \"%s\"", + syslog(LOG_NOTICE, "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", RealHostName == NULL ? "[UNKNOWN]" : RealHostName, - shortenstring(bp, 80)); + shortenstring(bp, 203)); } #endif +*/ return bp; } |