diff options
Diffstat (limited to 'contrib/sendmail/src/util.c')
-rw-r--r-- | contrib/sendmail/src/util.c | 304 |
1 files changed, 132 insertions, 172 deletions
diff --git a/contrib/sendmail/src/util.c b/contrib/sendmail/src/util.c index c27cd90..af781ef 100644 --- a/contrib/sendmail/src/util.c +++ b/contrib/sendmail/src/util.c @@ -13,8 +13,9 @@ #include <sendmail.h> -SM_RCSID("@(#)$Id: util.c,v 8.394 2006/05/03 23:55:29 ca Exp $") +SM_RCSID("@(#)$Id: util.c,v 8.410 2006/12/18 18:36:44 ca Exp $") +#include <sm/sendmail.h> #include <sysexits.h> #include <sm/xtrap.h> @@ -180,6 +181,7 @@ rfc822_string(s) /* unbalanced '"' or '(' */ return !quoted && commentlev == 0; } + /* ** SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string ** @@ -288,6 +290,7 @@ increment: } return modified; } + /* ** FIND_CHARACTER -- find an unquoted character in an RFC822 string ** @@ -383,7 +386,6 @@ check_bodytype(bodytype) return BODYTYPE_ILLEGAL; } -#if _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI /* ** TRUNCATE_AT_DELIM -- truncate string at a delimiter and append "..." ** @@ -426,7 +428,7 @@ truncate_at_delim(str, len, delim) else str[0] = '\0'; } -#endif /* _FFR_BESTMX_BETTER_TRUNCATION || _FFR_DNSMAP_MULTI */ + /* ** XALLOC -- Allocate memory, raise an exception on error ** @@ -472,6 +474,7 @@ xalloc(sz) } return p; } + /* ** COPYPLIST -- copy list of pointers. ** @@ -504,8 +507,8 @@ copyplist(list, copycont, rpool) vp++; - newvp = (char **) sm_rpool_malloc_x(rpool, (vp - list) * sizeof *vp); - memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof *vp); + newvp = (char **) sm_rpool_malloc_x(rpool, (vp - list) * sizeof(*vp)); + memmove((char *) newvp, (char *) list, (int) (vp - list) * sizeof(*vp)); if (copycont) { @@ -515,6 +518,7 @@ copyplist(list, copycont, rpool) return newvp; } + /* ** COPYQUEUE -- copy address queue. ** @@ -543,7 +547,7 @@ copyqueue(addr, rpool) if (!QS_IS_DEAD(addr->q_state)) { newaddr = (ADDRESS *) sm_rpool_malloc_x(rpool, - sizeof *newaddr); + sizeof(*newaddr)); STRUCTCOPY(*addr, *newaddr); *tail = newaddr; tail = &newaddr->q_next; @@ -554,6 +558,7 @@ copyqueue(addr, rpool) return ret; } + /* ** LOG_SENDMAIL_PID -- record sendmail pid and command line. ** @@ -582,7 +587,7 @@ log_sendmail_pid(e) sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT|SFF_NBLOCK; if (TrustedUid != 0 && RealUid == TrustedUid) sff |= SFF_OPENASROOT; - expand(PidFile, pidpath, sizeof pidpath, e); + expand(PidFile, pidpath, sizeof(pidpath), e); Pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, FileMode, sff); if (Pidf == NULL) { @@ -666,6 +671,7 @@ set_delivery_mode(mode, e) buf[1] = '\0'; macdefine(&e->e_macro, A_TEMP, macid("{deliveryMode}"), buf); } + /* ** SET_OP_MODE -- set and record the op mode ** @@ -692,6 +698,7 @@ set_op_mode(mode) buf[1] = '\0'; macdefine(&BlankEnvelope.e_macro, A_TEMP, MID_OPMODE, buf); } + /* ** PRINTAV -- print argument vector. ** @@ -709,7 +716,7 @@ set_op_mode(mode) void printav(fp, av) SM_FILE_T *fp; - register char **av; + char **av; { while (*av != NULL) { @@ -717,10 +724,14 @@ printav(fp, av) sm_dprintf("\n\t%08lx=", (unsigned long) *av); else (void) sm_io_putc(fp, SM_TIME_DEFAULT, ' '); - xputs(fp, *av++); + if (tTd(0, 99)) + sm_dprintf("%s", str2prt(*av++)); + else + xputs(fp, *av++); } (void) sm_io_putc(fp, SM_TIME_DEFAULT, '\n'); } + /* ** XPUTS -- put string doing control escapes. ** @@ -738,10 +749,10 @@ printav(fp, av) void xputs(fp, s) SM_FILE_T *fp; - register const char *s; + const char *s; { - register int c; - register struct metamac *mp; + int c; + struct metamac *mp; bool shiftout = false; extern struct metamac MetaMacros[]; static SM_DEBUG_T DebugANSI = SM_DEBUG_INITIALIZER("ANSI", @@ -758,19 +769,19 @@ xputs(fp, s) if (sm_debug_active(&DebugANSI, 1)) { TermEscape.te_rv_on = "\033[7m"; - TermEscape.te_rv_off = "\033[0m"; + TermEscape.te_normal = "\033[0m"; } else { TermEscape.te_rv_on = ""; - TermEscape.te_rv_off = ""; + TermEscape.te_normal = ""; } } if (s == NULL) { (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s<null>%s", - TermEscape.te_rv_on, TermEscape.te_rv_off); + TermEscape.te_rv_on, TermEscape.te_normal); return; } while ((c = (*s++ & 0377)) != '\0') @@ -778,10 +789,10 @@ xputs(fp, s) if (shiftout) { (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", - TermEscape.te_rv_off); + TermEscape.te_normal); shiftout = false; } - if (!isascii(c)) + if (!isascii(c) && !tTd(84, 1)) { if (c == MATCHREPL) { @@ -889,7 +900,11 @@ xputs(fp, s) (void) sm_io_putc(fp, SM_TIME_DEFAULT, '\\'); (void) sm_io_putc(fp, SM_TIME_DEFAULT, c); } - else + else if (tTd(84, 2)) + (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " %o ", c); + else if (tTd(84, 1)) + (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, " %#x ", c); + else if (!isascii(c) && !tTd(84, 1)) { (void) sm_io_putc(fp, SM_TIME_DEFAULT, '^'); (void) sm_io_putc(fp, SM_TIME_DEFAULT, c ^ 0100); @@ -897,9 +912,10 @@ xputs(fp, s) } if (shiftout) (void) sm_io_fprintf(fp, SM_TIME_DEFAULT, "%s", - TermEscape.te_rv_off); + TermEscape.te_normal); (void) sm_io_flush(fp, SM_TIME_DEFAULT); } + /* ** MAKELOWER -- Translate a line into lower case ** @@ -926,6 +942,7 @@ makelower(p) if (isascii(c) && isupper(c)) *p = tolower(c); } + /* ** FIXCRLF -- fix <CR><LF> in line. ** @@ -961,6 +978,7 @@ fixcrlf(line, stripnl) *p++ = '\n'; *p = '\0'; } + /* ** PUTLINE -- put a line like fputs obeying SMTP conventions ** @@ -985,6 +1003,7 @@ putline(l, mci) { return putxline(l, strlen(l), mci, PXLF_MAPFROM); } + /* ** PUTXLINE -- putline with flags bits. ** @@ -1000,6 +1019,7 @@ putline(l, mci) ** PXLF_STRIP8BIT -- strip 8th bit. ** PXLF_HEADER -- map bare newline in header to newline space. ** PXLF_NOADDEOL -- don't add an EOL if one wasn't present. +** PXLF_STRIPMQUOTE -- strip METAQUOTE bytes. ** ** Returns: ** true iff line was written successfully @@ -1008,6 +1028,37 @@ putline(l, mci) ** output of l to mci->mci_out. */ + +#define PUTX(limit) \ + do \ + { \ + quotenext = false; \ + while (l < limit) \ + { \ + unsigned char c = (unsigned char) *l++; \ + \ + if (bitset(PXLF_STRIPMQUOTE, pxflags) && \ + !quotenext && c == METAQUOTE) \ + { \ + quotenext = true; \ + continue; \ + } \ + quotenext = false; \ + if (strip8bit) \ + c &= 0177; \ + if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, \ + c) == SM_IO_EOF) \ + { \ + dead = true; \ + break; \ + } \ + if (TrafficLogFile != NULL) \ + (void) sm_io_putc(TrafficLogFile, \ + SM_TIME_DEFAULT, \ + c); \ + } \ + } while (0) + bool putxline(l, len, mci, pxflags) register char *l; @@ -1015,20 +1066,15 @@ putxline(l, len, mci, pxflags) register MCI *mci; int pxflags; { - bool dead = false; register char *p, *end; - int slop = 0; + int slop; + bool dead, quotenext, strip8bit; /* strip out 0200 bits -- these can look like TELNET protocol */ - if (bitset(MCIF_7BIT, mci->mci_flags) || - bitset(PXLF_STRIP8BIT, pxflags)) - { - register char svchar; - - for (p = l; (svchar = *p) != '\0'; ++p) - if (bitset(0200, svchar)) - *p = svchar &~ 0200; - } + strip8bit = bitset(MCIF_7BIT, mci->mci_flags) || + bitset(PXLF_STRIP8BIT, pxflags); + dead = false; + slop = 0; end = l + len; do @@ -1051,7 +1097,6 @@ putxline(l, len, mci, pxflags) while (mci->mci_mailer->m_linelimit > 0 && (p - l + slop) > mci->mci_mailer->m_linelimit) { - char *l_base = l; register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1]; if (l[0] == '.' && slop == 0 && @@ -1080,35 +1125,22 @@ putxline(l, len, mci, pxflags) if (dead) break; - while (l < q) - { - if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, - (unsigned char) *l++) == SM_IO_EOF) - { - dead = true; - break; - } - } + PUTX(q); if (dead) break; - if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, '!') == - SM_IO_EOF || + if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, + '!') == SM_IO_EOF || sm_io_fputs(mci->mci_out, SM_TIME_DEFAULT, - mci->mci_mailer->m_eol) == - SM_IO_EOF || - sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, ' ') == - SM_IO_EOF) + mci->mci_mailer->m_eol) == SM_IO_EOF || + sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, + ' ') == SM_IO_EOF) { dead = true; break; } if (TrafficLogFile != NULL) { - for (l = l_base; l < q; l++) - (void) sm_io_putc(TrafficLogFile, - SM_TIME_DEFAULT, - (unsigned char)*l); (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, "!\n%05d >>> ", @@ -1149,19 +1181,7 @@ putxline(l, len, mci, pxflags) (void) sm_io_putc(TrafficLogFile, SM_TIME_DEFAULT, '>'); } - for ( ; l < p; ++l) - { - if (TrafficLogFile != NULL) - (void) sm_io_putc(TrafficLogFile, - SM_TIME_DEFAULT, - (unsigned char)*l); - if (sm_io_putc(mci->mci_out, SM_TIME_DEFAULT, - (unsigned char) *l) == SM_IO_EOF) - { - dead = true; - break; - } - } + PUTX(p); if (dead) break; @@ -1230,6 +1250,7 @@ xunlink(f) errno = save_errno; return i; } + /* ** SFGETS -- "safe" fgets -- times out and ignores random interrupts. ** @@ -1338,12 +1359,15 @@ sfgets(buf, siz, fp, timeout, during) } return buf; } + /* ** FGETFOLDED -- like fgets, but knows about folded lines. ** ** Parameters: ** buf -- place to put result. -** n -- bytes available. +** np -- pointer to bytes available; will be updated with +** the actual buffer size (not number of bytes filled) +** on return. ** f -- file to read from. ** ** Returns: @@ -1358,15 +1382,18 @@ sfgets(buf, siz, fp, timeout, during) */ char * -fgetfolded(buf, n, f) +fgetfolded(buf, np, f) char *buf; - register int n; + int *np; SM_FILE_T *f; { register char *p = buf; char *bp = buf; register int i; + int n; + SM_REQUIRE(np != NULL); + n = *np; SM_REQUIRE(n > 0); SM_REQUIRE(buf != NULL); if (f == NULL) @@ -1408,6 +1435,7 @@ fgetfolded(buf, n, f) sm_free(bp); bp = nbp; n = nn - (p - bp); + *np = nn; } *p++ = i; if (i == '\n') @@ -1427,6 +1455,7 @@ fgetfolded(buf, n, f) *p = '\0'; return bp; } + /* ** CURTIME -- return current time. ** @@ -1445,6 +1474,7 @@ curtime() (void) time(&t); return t; } + /* ** ATOBOOL -- convert a string representation to boolean. ** @@ -1466,6 +1496,7 @@ atobool(s) return true; return false; } + /* ** ATOOCT -- convert a string representation to octal. ** @@ -1487,6 +1518,7 @@ atooct(s) i = (i << 3) | (*s++ - '0'); return i; } + /* ** BITINTERSECT -- tell if two bitmaps intersect ** @@ -1505,13 +1537,14 @@ bitintersect(a, b) { int i; - for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) + for (i = BITMAPBYTES / sizeof(int); --i >= 0; ) { if ((a[i] & b[i]) != 0) return true; } return false; } + /* ** BITZEROP -- tell if a bitmap is all zero ** @@ -1529,13 +1562,14 @@ bitzerop(map) { int i; - for (i = BITMAPBYTES / sizeof (int); --i >= 0; ) + for (i = BITMAPBYTES / sizeof(int); --i >= 0; ) { if (map[i] != 0) return false; } return true; } + /* ** STRCONTAINEDIN -- tell if one string is contained in another ** @@ -1584,6 +1618,7 @@ strcontainedin(icase, a, b) } return false; } + /* ** CHECKFD012 -- check low numbered file descriptors ** @@ -1608,6 +1643,7 @@ checkfd012(where) fill_fd(i, where); #endif /* XDEBUG */ } + /* ** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging ** @@ -1634,6 +1670,7 @@ checkfdopen(fd, where) } #endif /* XDEBUG */ } + /* ** CHECKFDS -- check for new or missing file descriptors ** @@ -1694,6 +1731,7 @@ checkfds(where) } errno = save_errno; } + /* ** PRINTOPENFDS -- print the open file descriptors (for debugging) ** @@ -1719,6 +1757,7 @@ printopenfds(logit) for (fd = 0; fd < DtableSize; fd++) dumpfd(fd, false, logit); } + /* ** DUMPFD -- dump a file descriptor ** @@ -1795,8 +1834,8 @@ dumpfd(fd, printclosed, logit) case S_IFSOCK: (void) sm_snprintf(p, SPACELEFT(buf, p), "SOCK "); p += strlen(p); - memset(&sa, '\0', sizeof sa); - slen = sizeof sa; + memset(&sa, '\0', sizeof(sa)); + slen = sizeof(sa); if (getsockname(fd, &sa.sa, &slen) < 0) (void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)", sm_errstring(errno)); @@ -1825,7 +1864,7 @@ dumpfd(fd, printclosed, logit) p += strlen(p); (void) sm_snprintf(p, SPACELEFT(buf, p), "->"); p += strlen(p); - slen = sizeof sa; + slen = sizeof(sa); if (getpeername(fd, &sa.sa, &slen) < 0) (void) sm_snprintf(p, SPACELEFT(buf, p), "(%s)", sm_errstring(errno)); @@ -1908,6 +1947,7 @@ printit: else sm_dprintf("%s\n", buf); } + /* ** SHORTEN_HOSTNAME -- strip local domain information off of hostname. ** @@ -1955,6 +1995,7 @@ shorten_hostname(host) } return NULL; } + /* ** PROG_OPEN -- open a program for reading ** @@ -2057,7 +2098,7 @@ prog_open(argv, pfd, e) /* chroot to the program mailer directory, if defined */ if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL) { - expand(ProgMailer->m_rootdir, buf, sizeof buf, e); + expand(ProgMailer->m_rootdir, buf, sizeof(buf), e); if (chroot(buf) < 0) { syserr("prog_open: cannot chroot(%s)", buf); @@ -2097,7 +2138,7 @@ prog_open(argv, pfd, e) q = strchr(p, ':'); if (q != NULL) *q = '\0'; - expand(p, buf, sizeof buf, e); + expand(p, buf, sizeof(buf), e); if (q != NULL) *q++ = ':'; if (buf[0] != '\0' && chdir(buf) >= 0) @@ -2138,6 +2179,7 @@ prog_open(argv, pfd, e) _exit(EX_CONFIG); return -1; /* avoid compiler warning on IRIX */ } + /* ** GET_COLUMN -- look up a Column in a line buffer ** @@ -2168,7 +2210,7 @@ get_column(line, col, delim, buf, buflen) char delimbuf[4]; if ((char) delim == '\0') - (void) sm_strlcpy(delimbuf, "\n\t ", sizeof delimbuf); + (void) sm_strlcpy(delimbuf, "\n\t ", sizeof(delimbuf)); else { delimbuf[0] = (char) delim; @@ -2211,6 +2253,7 @@ get_column(line, col, delim, buf, buflen) (void) sm_strlcpy(buf, begin, i + 1); return buf; } + /* ** CLEANSTRCPY -- copy string keeping out bogus characters ** @@ -2248,6 +2291,7 @@ cleanstrcpy(t, f, l) } *t = '\0'; } + /* ** DENLSTRING -- convert newlines in a string to spaces ** @@ -2296,7 +2340,7 @@ denlstring(s, strict, logattacks) if (logattacks) { - sm_syslog(LOG_NOTICE, CurEnv->e_id, + sm_syslog(LOG_NOTICE, CurEnv ? CurEnv->e_id : NULL, "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", RealHostName == NULL ? "[UNKNOWN]" : RealHostName, shortenstring(bp, MAXSHORTSTR)); @@ -2339,101 +2383,6 @@ strreplnonprt(s, c) } /* -** STR2PRT -- convert "unprintable" characters in a string to \oct -** -** Parameters: -** s -- string to convert -** -** Returns: -** converted string. -** This is a static local buffer, string must be copied -** before this function is called again! -*/ - -char * -str2prt(s) - char *s; -{ - int l; - char c, *h; - bool ok; - static int len = 0; - static char *buf = NULL; - - if (s == NULL) - return NULL; - ok = true; - for (h = s, l = 1; *h != '\0'; h++, l++) - { - if (*h == '\\') - { - ++l; - ok = false; - } - else if (!(isascii(*h) && isprint(*h))) - { - l += 3; - ok = false; - } - } - if (ok) - return s; - if (l > len) - { - char *nbuf = sm_pmalloc_x(l); - - if (buf != NULL) - sm_free(buf); - len = l; - buf = nbuf; - } - for (h = buf; *s != '\0' && l > 0; s++, l--) - { - c = *s; - if (isascii(c) && isprint(c) && c != '\\') - { - *h++ = c; - } - else - { - *h++ = '\\'; - --l; - switch (c) - { - case '\\': - *h++ = '\\'; - break; - case '\t': - *h++ = 't'; - break; - case '\n': - *h++ = 'n'; - break; - case '\r': - *h++ = 'r'; - break; - default: - SM_ASSERT(l >= 2); - (void) sm_snprintf(h, l, "%03o", - (unsigned int)((unsigned char) c)); - - /* - ** XXX since l is unsigned this may - ** wrap around if the calculation is screwed - ** up... - */ - - l -= 2; - h += 3; - break; - } - } - } - *h = '\0'; - buf[len - 1] = '\0'; - return buf; -} -/* ** PATH_IS_DIR -- check to see if file exists and is a directory. ** ** There are some additional checks for security violations in @@ -2482,6 +2431,7 @@ path_is_dir(pathname, createflag) } return true; } + /* ** PROC_LIST_ADD -- add process id to list of our children ** @@ -2545,15 +2495,19 @@ proc_list_add(pid, task, type, count, other, hostaddr) if (i >= ProcListSize) { /* grow process list */ + int chldwasblocked; PROCS_T *npv; SM_ASSERT(ProcListSize < INT_MAX - PROC_LIST_SEG); - npv = (PROCS_T *) sm_pmalloc_x((sizeof *npv) * + npv = (PROCS_T *) sm_pmalloc_x((sizeof(*npv)) * (ProcListSize + PROC_LIST_SEG)); + + /* Block SIGCHLD so reapchild() doesn't mess with us */ + chldwasblocked = sm_blocksignal(SIGCHLD); if (ProcListSize > 0) { memmove(npv, ProcListVec, - ProcListSize * sizeof (PROCS_T)); + ProcListSize * sizeof(PROCS_T)); sm_free(ProcListVec); } @@ -2567,6 +2521,8 @@ proc_list_add(pid, task, type, count, other, hostaddr) i = ProcListSize; ProcListSize += PROC_LIST_SEG; ProcListVec = npv; + if (chldwasblocked == 0) + (void) sm_releasesignal(SIGCHLD); } ProcListVec[i].proc_pid = pid; PSTRSET(ProcListVec[i].proc_task, task); @@ -2586,6 +2542,7 @@ proc_list_add(pid, task, type, count, other, hostaddr) CurChildren++; } } + /* ** PROC_LIST_SET -- set pid task in process list ** @@ -2613,6 +2570,7 @@ proc_list_set(pid, task) } } } + /* ** PROC_LIST_DROP -- drop pid from process list ** @@ -2674,6 +2632,7 @@ proc_list_drop(pid, st, other) else if (type == PROC_QUEUE) CurRunners -= ProcListVec[i].proc_count; } + /* ** PROC_LIST_CLEAR -- clear the process list ** @@ -2697,6 +2656,7 @@ proc_list_clear() ProcListVec[i].proc_pid = NO_PID; CurChildren = 0; } + /* ** PROC_LIST_PROBE -- probe processes in the list to see if they still exist ** |