diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2014-12-23 23:19:21 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2014-12-23 23:19:21 +0000 |
commit | af9034a8036f884fc06874c445d85ac9f416f4fe (patch) | |
tree | 01ceaeec83dcf7e2bab07cbf2db7f40b7fcb5622 /usr/src/cmd | |
parent | 8af96fbb6bb47d4566bcfef02a8e551164eb2208 (diff) | |
parent | 5422785d352a2bb398daceab3d1898a8aa64d006 (diff) | |
download | illumos-joyent-release-20141225.tar.gz |
[illumos-gate merge]20141225release-20141225
commit 5422785d352a2bb398daceab3d1898a8aa64d006
5481 CVE-2012-1750 mailx(1) tilde expansion vulnerability
5482 CVE-2014-7844, CVE-2004-2771 - more mailx(1) woes
commit 196c7f05d2deba7404e90ad67f3861185c78ca2d
5480 CVE-2012-3165 mailx(1) buffer overflow vulnerability
Diffstat (limited to 'usr/src/cmd')
-rw-r--r-- | usr/src/cmd/Makefile | 1 | ||||
-rw-r--r-- | usr/src/cmd/fmt/Makefile | 1 | ||||
-rw-r--r-- | usr/src/cmd/fmt/fmt.c | 6 | ||||
-rw-r--r-- | usr/src/cmd/mailx/Makefile | 4 | ||||
-rw-r--r-- | usr/src/cmd/mailx/cmd1.c | 34 | ||||
-rw-r--r-- | usr/src/cmd/mailx/fio.c | 10 | ||||
-rw-r--r-- | usr/src/cmd/mailx/hdr/def.h | 22 | ||||
-rw-r--r-- | usr/src/cmd/mailx/head.c | 242 | ||||
-rw-r--r-- | usr/src/cmd/mailx/main.c | 3 | ||||
-rw-r--r-- | usr/src/cmd/mailx/misc/mailx.rc | 4 | ||||
-rw-r--r-- | usr/src/cmd/mailx/names.c | 19 | ||||
-rw-r--r-- | usr/src/cmd/mailx/receipt.c | 26 |
12 files changed, 247 insertions, 125 deletions
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile index d16130bd8f..f78feac556 100644 --- a/usr/src/cmd/Makefile +++ b/usr/src/cmd/Makefile @@ -824,6 +824,7 @@ fs.d: fstyp ksh: shcomp isaexec mdb: terminfo print: lp +fmt: mailx $(FIRST_SUBDIRS) $(BWOSDIRS) $(SUBDIRS) $(AUDITSUBDIRS): FRC @if [ -f $@/Makefile ]; then \ diff --git a/usr/src/cmd/fmt/Makefile b/usr/src/cmd/fmt/Makefile index 21938536d6..cecd4e3c2a 100644 --- a/usr/src/cmd/fmt/Makefile +++ b/usr/src/cmd/fmt/Makefile @@ -33,6 +33,7 @@ SRCS= $(OBJS:%.o=%.c) include ../Makefile.cmd +LDLIBS += -lcmdutils CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-parentheses diff --git a/usr/src/cmd/fmt/fmt.c b/usr/src/cmd/fmt/fmt.c index 52d4676172..b5fbee6e13 100644 --- a/usr/src/cmd/fmt/fmt.c +++ b/usr/src/cmd/fmt/fmt.c @@ -86,7 +86,7 @@ int h_lines; /* index into lines of hdrbuf */ void (*(split))(wchar_t []); extern int scrwidth(wchar_t); -extern int ishead(char []); +extern boolean_t is_headline(const char *); static void fill_hdrbuf(wchar_t []); @@ -240,13 +240,13 @@ fmt(FILE *fi) } /* * Need to convert string from wchar_t to char, - * since this is what ishead() expects. Since we + * since this is what is_headline() expects. Since we * only want to make sure cp points to a "From" line * of the email, we don't have to alloc * BUFSIZ * MB_LEN_MAX to cbuf. */ wcstombs(cbuf, cp, (BUFSIZ - 1)); - if (ishead(cbuf)) { + if (is_headline(cbuf) == B_TRUE) { hdr_state = in_hdr; fill_hdrbuf(canonb); } else { diff --git a/usr/src/cmd/mailx/Makefile b/usr/src/cmd/mailx/Makefile index 93b527b72a..4fb19334f2 100644 --- a/usr/src/cmd/mailx/Makefile +++ b/usr/src/cmd/mailx/Makefile @@ -22,6 +22,8 @@ # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2014 Joyent, Inc. +# # cmd/mailx/Makefile PROG= mailx @@ -67,7 +69,7 @@ CERRWARN += -_gcc=-Wno-uninitialized CERRWARN += -_gcc=-Wno-unused-variable CERRWARN += -_gcc=-Wno-clobbered LINTFLAGS= -hb -LDLIBS += -lmail +LDLIBS += -lmail -lcmdutils LDFLAGS += $(MAPFILE.NGB:%=-M%) CLOBBERFILES += $(MAILXHELP) diff --git a/usr/src/cmd/mailx/cmd1.c b/usr/src/cmd/mailx/cmd1.c index 5cdb7ae465..38c9b7ab9b 100644 --- a/usr/src/cmd/mailx/cmd1.c +++ b/usr/src/cmd/mailx/cmd1.c @@ -19,6 +19,11 @@ * * CDDL HEADER END */ + +/* + * Copyright 2014 Joyent, Inc. + */ + /* * Copyright 2001 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -37,8 +42,7 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" - +#include <err.h> #include "rcv.h" #include <locale.h> @@ -213,10 +217,14 @@ printhead(int mesg) char *fromline; char pbuf[LINESIZE]; char name[LINESIZE]; - struct headline hl; + headline_t *hl; register char *cp; int showto; + if (headline_alloc(&hl) != 0) { + err(1, "could not allocate memory"); + } + mp = &message[mesg-1]; ibuf = setinput(mp); readline(ibuf, headline); @@ -248,9 +256,14 @@ printhead(int mesg) dispc = 'H'; if (mp->m_flag & MBOX) dispc = 'M'; - parse(headline, &hl, pbuf); - if (hl.l_date == NOSTR) - hl.l_date = "<Unknown date>"; + if (parse_headline(headline, hl) == -1) { + headline_reset(hl); + } + if (custr_len(hl->hl_date) == 0) { + if (custr_append(hl->hl_date, "<Unknown date>") != 0) { + err(1, "could not print header"); + } + } /* * Netnews interface? @@ -299,11 +312,14 @@ printhead(int mesg) } if (mp->m_text) { printf("%16.16s %4ld/%-5ld %-.25s\n", - hl.l_date, mp->m_lines, mp->m_size, subjline); - } else { - printf("%16.16s binary/%-5ld %-.25s\n", hl.l_date, mp->m_size, + custr_cstr(hl->hl_date), mp->m_lines, mp->m_size, subjline); + } else { + printf("%16.16s binary/%-5ld %-.25s\n", custr_cstr(hl->hl_date), + mp->m_size, subjline); } + + headline_free(hl); } /* diff --git a/usr/src/cmd/mailx/fio.c b/usr/src/cmd/mailx/fio.c index 818860d7ae..53907ca760 100644 --- a/usr/src/cmd/mailx/fio.c +++ b/usr/src/cmd/mailx/fio.c @@ -21,6 +21,10 @@ */ /* + * Copyright 2014 Joyent, Inc. + */ + +/* * Copyright 1999 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,8 +32,6 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "rcv.h" #include <locale.h> #include <wordexp.h> @@ -174,7 +176,7 @@ setptr(register FILE *ibuf) } /* Look for a From line that starts a new message */ - if (blankline && linebuf[0] == 'F' && ishead(linebuf)) { + if (blankline && linebuf[0] == 'F' && is_headline(linebuf)) { if (msgCount > 0 && !newmail) { message[msgCount-1].m_size = s; message[msgCount-1].m_lines = l; @@ -755,7 +757,7 @@ expand(char *name) if (debug) fprintf(stderr, "%s\n", name); return (name); } - if (wordexp(name, &wrdexp_buf, 0) != 0) { + if (wordexp(name, &wrdexp_buf, WRDE_NOCMD) != 0) { fprintf(stderr, gettext("Syntax error in \"%s\"\n"), name); fflush(stderr); return (NOSTR); diff --git a/usr/src/cmd/mailx/hdr/def.h b/usr/src/cmd/mailx/hdr/def.h index d0e48820ea..7453b24f97 100644 --- a/usr/src/cmd/mailx/hdr/def.h +++ b/usr/src/cmd/mailx/hdr/def.h @@ -20,6 +20,10 @@ */ /* + * Copyright 2014 Joyent, Inc. + */ + +/* * Copyright (c) 1985, 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -60,6 +64,7 @@ extern "C" { #include <stdlib.h> #include <ulimit.h> #include <wait.h> +#include <libcmdutils.h> #endif #ifdef VMUNIX #include <sys/wait.h> @@ -204,11 +209,11 @@ struct cmd { * line */ -struct headline { - char *l_from; /* The name of the sender */ - char *l_tty; /* His tty string (if any) */ - char *l_date; /* The entire date string */ -}; +typedef struct headline { + custr_t *hl_from; /* The name of the sender */ + custr_t *hl_tty; /* His tty string (if any) */ + custr_t *hl_date; /* The entire date string */ +} headline_t; #define GTO 1 /* Grab To: line */ #define GSUBJECT 2 /* Likewise, Subject: line */ @@ -486,6 +491,9 @@ extern int hash(char name[]); extern char *hcontents(char hfield[]); extern int headerp(register char *line); extern int headers(int *msgvec); +extern int headline_alloc(headline_t **); +extern void headline_free(headline_t *); +extern void headline_reset(headline_t *); extern int help(void); extern char *helppath(char *file); extern char *hfield(char field[], struct message *mp, @@ -497,7 +505,7 @@ extern int igfield(char *list[]); extern int inc(void); extern void inithost(void); extern int isdir(char name[]); -extern int ishead(char linebuf[]); +extern boolean_t is_headline(const char *); extern int ishfield(char linebuf[], char field[]); extern int ishost(char *sys, char *rest); extern int isign(char *field, int saving); @@ -533,7 +541,7 @@ extern int null(char *e); extern int outof(struct name *names, FILE *fo); extern struct name *outpre(struct name *to); extern void panic(char *str); -extern void parse(char line[], struct headline *hl, char pbuf[]); +extern int parse_headline(const char *, headline_t *); extern int pcmdlist(void); extern int pdot(void); extern int preserve(int *msgvec); diff --git a/usr/src/cmd/mailx/head.c b/usr/src/cmd/mailx/head.c index 3f833ab14e..b6d09f0767 100644 --- a/usr/src/cmd/mailx/head.c +++ b/usr/src/cmd/mailx/head.c @@ -19,6 +19,11 @@ * * CDDL HEADER END */ + +/* + * Copyright 2014 Joyent, Inc. + */ + /* * Copyright 1995 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -38,7 +43,7 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" +#include <err.h> #include "rcv.h" @@ -49,115 +54,188 @@ * Routines for processing and detecting headlines. */ -static char *copyin(char src[], char **space); -static char *nextword(char wp[], char wbuf[]); +static int nextword(const char *, custr_t *, const char **); /* * See if the passed line buffer is a mail header. * Return true if yes. */ - -int -ishead(char linebuf[]) +boolean_t +is_headline(const char *linebuf) { - register char *cp; - struct headline hl; - char parbuf[BUFSIZ]; - - cp = linebuf; - if (strncmp("From ", cp, 5) != 0) - return(0); - parse(cp, &hl, parbuf); - if (hl.l_from == NOSTR) { - return(0); + headline_t *hl; + boolean_t ret; + + if (strncmp("From ", linebuf, 5) != 0) { + return (B_FALSE); + } + + if (headline_alloc(&hl) != 0 || parse_headline(linebuf, hl) != 0) { + err(1, "could not parse headline"); } - return(1); + + ret = custr_len(hl->hl_from) > 0 ? B_TRUE : B_FALSE; + + headline_free(hl); + return (ret); } /* - * Split a headline into its useful components. - * Copy the line into dynamic string space, then set - * pointers into the copied line in the passed headline - * structure. Actually, it scans. + * Manage headline_t objects: */ -void -parse(char line[], struct headline *hl, char pbuf[]) +void +headline_free(headline_t *hl) +{ + custr_free(hl->hl_from); + custr_free(hl->hl_tty); + custr_free(hl->hl_date); + free(hl); +} + +int +headline_alloc(headline_t **hl) { - register char *cp, *dp; - char *sp; - char word[LINESIZE]; + int en; + headline_t *t; + + if ((t = calloc(1, sizeof (*t))) == NULL) { + return (-1); + } - hl->l_from = NOSTR; - hl->l_date = NOSTR; - cp = line; - sp = pbuf; + if (custr_alloc(&t->hl_from) != 0 || custr_alloc(&t->hl_tty) != 0 || + custr_alloc(&t->hl_date) != 0) { + en = errno; - /* - * Skip the first "word" of the line, which should be "From" - * anyway. - */ + headline_free(t); - cp = nextword(cp, word); - dp = nextword(cp, word); - if (!equal(word, "")) - hl->l_from = copyin(word, &sp); - if (dp != NOSTR) - hl->l_date = copyin(dp, &sp); + errno = en; + return (-1); + } + + *hl = t; + return (0); } /* - * Copy the string on the left into the string on the right - * and bump the right (reference) string pointer by the length. - * Thus, dynamically allocate space in the right string, copying - * the left string into it. + * Clear all of the strings in a headline_t: */ +void +headline_reset(headline_t *hl) +{ + custr_reset(hl->hl_from); + custr_reset(hl->hl_tty); + custr_reset(hl->hl_date); +} -static char * -copyin(char src[], char **space) +int +parse_headline(const char *line, headline_t *hl) { - register char *cp, *top; - register int s; - - s = strlen(src); - cp = *space; - top = cp; - strcpy(cp, src); - cp += s + 1; - *space = cp; - return(top); + const char *c = line; + + headline_reset(hl); + + /* + * Load the first word from the line and ensure that it is "From". + */ + if (nextword(c, hl->hl_from, &c) != 0) { + return (-1); + } + if (strcmp(custr_cstr(hl->hl_from), "From") != 0) { + errno = EINVAL; + return (-1); + } + custr_reset(hl->hl_from); + + /* + * The next word will be the From address. + */ + if (nextword(c, hl->hl_from, &c) != 0) { + return (-1); + } + + /* + * If there is a next word, the rest of the string is the Date. + */ + if (c != NULL) { + if (custr_append(hl->hl_date, c) != 0) { + return (-1); + } + } + + errno = 0; + return (0); } /* - * Collect a liberal (space, tab delimited) word into the word buffer - * passed. Also, return a pointer to the next word following that, - * or NOSTR if none follow. + * Collect a space- or tab-delimited word into the word buffer, if one is + * passed. The double quote character (") can be used to include whitespace + * within a word. Set "nextword" to the location of the first character of the + * _next_ word, or NULL if there were no more words. Returns 0 on success or + * -1 otherwise. */ - -static char * -nextword(char wp[], char wbuf[]) +static int +nextword(const char *input, custr_t *word, const char **nextword) { - register char *cp, *cp2; + boolean_t in_quotes = B_FALSE; + const char *c = input != NULL ? input : ""; + + /* + * Collect the first word into the word buffer, if one is provided. + */ + for (;;) { + if (*c == '\0') { + /* + * We have reached the end of the string. + */ + *nextword = NULL; + return (0); + } + + if (*c == '"') { + /* + * Either beginning or ending a quoted string. + */ + in_quotes = in_quotes ? B_FALSE : B_TRUE; + } + + if (!in_quotes && (*c == ' ' || *c == '\t')) { + /* + * We have reached a whitespace region. + */ + break; + } + + /* + * Copy this character into the word buffer. + */ + if (word != NULL) { + if (custr_appendc(word, *c) != 0) { + return (-1); + } + } + c++; + } + + /* + * Find the beginning of the next word, if there is one. + */ + for (;;) { + if (*c == '\0') { + /* + * We have reached the end of the string. + */ + *nextword = NULL; + return (0); - if ((cp = wp) == NOSTR) { - copy("", wbuf); - return(NOSTR); + } else if (*c != ' ' && *c != '\t') { + /* + * We have located the next word. + */ + *nextword = c; + return (0); + } + c++; } - cp2 = wbuf; - while (!any(*cp, " \t") && *cp != '\0') - if (*cp == '"') { - *cp2++ = *cp++; - while (*cp != '\0' && *cp != '"') - *cp2++ = *cp++; - if (*cp == '"') - *cp2++ = *cp++; - } else - *cp2++ = *cp++; - *cp2 = '\0'; - while (any(*cp, " \t")) - cp++; - if (*cp == '\0') - return(NOSTR); - return(cp); } /* diff --git a/usr/src/cmd/mailx/main.c b/usr/src/cmd/mailx/main.c index 35448ecf7c..0271552bea 100644 --- a/usr/src/cmd/mailx/main.c +++ b/usr/src/cmd/mailx/main.c @@ -37,8 +37,6 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "rcv.h" #ifndef preSVr4 #include <locale.h> @@ -104,7 +102,6 @@ main(int argc, char **argv) progname = argv[0]; if (progname[strlen(progname) - 1] != 'x') { assign("bsdcompat", ""); - assign("escapeok", ""); /* XXX */ } myegid = getegid(); myrgid = getgid(); diff --git a/usr/src/cmd/mailx/misc/mailx.rc b/usr/src/cmd/mailx/misc/mailx.rc index d10391f433..a6dfa46fb2 100644 --- a/usr/src/cmd/mailx/misc/mailx.rc +++ b/usr/src/cmd/mailx/misc/mailx.rc @@ -21,8 +21,6 @@ # Copyright 2000 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# # The following 3 settings produce the familiar Solaris behavior. set appenddeadletter unset pipeignore @@ -44,8 +42,6 @@ else set LISTER="ls -LF" # default is to allow editing of message windows set editmessagewindow - # have to allow ~ escapes even though not using tty - set escapeok endif # most mail headers are uninteresting to most people. here we ignore all diff --git a/usr/src/cmd/mailx/names.c b/usr/src/cmd/mailx/names.c index 7616630f79..886eb2dbc5 100644 --- a/usr/src/cmd/mailx/names.c +++ b/usr/src/cmd/mailx/names.c @@ -191,7 +191,7 @@ outpre(struct name *to) /* * For each recipient in the passed name list with a / * in the name, append the message to the end of the named file - * and remove him from the recipient list. + * and remove them from the recipient list. * * Recipients whose name begins with | are piped through the given * program and removed. @@ -212,6 +212,9 @@ outof(struct name *names, FILE *fo) char line[BUFSIZ]; #endif + if (value("expandaddr") == NOSTR) + return (nout); + for (np = names; np != NIL; np = np->n_flink) { if (!isfileaddr(np->n_name) && np->n_name[0] != '|') continue; @@ -599,14 +602,15 @@ unpack(struct name *np) panic("No names to unpack"); /* - * Compute the number of extra arguments we will need. - * We need at least 2 extra -- one for "mail" and one for - * the terminating 0 pointer. - * Additional spots may be needed to pass along -r and -f to - * the host mailer. + * Compute the number of extra arguments we will need. We need at least + * 3 extra -- one for "mail", one for a terminating -- to stop sendmail + * option processing, and one for the terminating 0 pointer. + * + * Additional spots may be needed to pass along -r and -f to the host + * mailer. */ - extra = 2; + extra = 3; if (rflag != NOSTR) extra += 2; @@ -636,6 +640,7 @@ unpack(struct name *np) snprintf(hbuf, sizeof (hbuf), "%d", hflag); *ap++ = savestr(hbuf); } + *ap++ = "--"; while (n != NIL) { if (n->n_type & GDEL) { n = n->n_flink; diff --git a/usr/src/cmd/mailx/receipt.c b/usr/src/cmd/mailx/receipt.c index 2a128d6a91..0b6b9296fc 100644 --- a/usr/src/cmd/mailx/receipt.c +++ b/usr/src/cmd/mailx/receipt.c @@ -19,6 +19,11 @@ * * CDDL HEADER END */ + +/* + * Copyright 2014 Joyent, Inc. + */ + /* * Copyright 1998 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. @@ -38,7 +43,7 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" +#include <err.h> #include "rcv.h" @@ -47,12 +52,12 @@ static int icsubstr(char *s1, char *s2); void receipt(struct message *mp) { - struct headline hl; char head[LINESIZE]; char buf[BUFSIZ]; FILE *pp, *fp; char *mail, *s; + if ((mail = value("sendmail")) == 0) #ifdef SENDMAIL mail = SENDMAIL; @@ -63,16 +68,27 @@ receipt(struct message *mp) || icsubstr(hfield(">to", mp, addto), "/receipt")) { snprintf(buf, sizeof (buf), "%s %s", mail, skin(nameof(mp))); if (pp = npopen(buf, "w")) { + headline_t *hl; + + if (headline_alloc(&hl) != 0) { + err(1, "could not allocate memory"); + } + fp = setinput(mp); readline(fp, head); - parse(head, &hl, buf); - if (hl.l_date != NOSTR) - fprintf(pp, "Original-Date: %s\n", hl.l_date); + if (parse_headline(head, hl) != 0) { + headline_reset(hl); + } + if (custr_len(hl->hl_date) > 0) { + fprintf(pp, "Original-Date: %s\n", + custr_cstr(hl->hl_date)); + } if (s = hfield("message-id", mp, addone)) fprintf(pp, "Original-Message-ID: %s\n", s); s = hfield("subject", mp, addone); fprintf(pp, "Subject: RR: %s\n", s ? s : "(none)"); npclose(pp); + headline_free(hl); } } } |