From c94d3564c2b0584804fd4bab0a03f9160aa39720 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 30 Jun 2008 13:30:21 +0000 Subject: [PATCH] sendmail: from Vladimir: Here comes the third part of compatibility patch for sendmail. * Introduced new safe_getdomainname() -- will it be useful? * Fixed SEGV if sender address is missed. Should snoop for sender address in mail headers? * More compat: use HOSTNAME instead of HOST when no server is explicitly specified. * crond: fixed mail recipient address. function old new delta safe_getdomainname - 56 +56 sendgetmail_main 1937 1946 +9 grep_file 846 850 +4 crond_main 1423 1425 +2 xstrtoull_range_sfx 295 296 +1 utoa_to_buf 110 108 -2 passwd_main 1053 1049 -4 sv_main 1234 1228 -6 parse_expr 841 833 -8 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/4 up/down: 72/-20) Total: 52 bytes --- include/libbb.h | 1 + libbb/safe_gethostname.c | 15 +++++++++++- miscutils/crond.c | 2 +- networking/sendmail.c | 53 +++++++++++++++++++++++----------------- 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 7bc0dca2f..54601f87b 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -630,6 +630,7 @@ void qsort_string_vector(char **sv, unsigned count) FAST_FUNC; int safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout_ms) FAST_FUNC; char *safe_gethostname(void) FAST_FUNC; +char *safe_getdomainname(void) FAST_FUNC; /* Convert each alpha char in str to lower-case */ char* str_tolower(char *str) FAST_FUNC; diff --git a/libbb/safe_gethostname.c b/libbb/safe_gethostname.c index 1f8b2a8fd..7407fb782 100644 --- a/libbb/safe_gethostname.c +++ b/libbb/safe_gethostname.c @@ -48,6 +48,19 @@ char* FAST_FUNC safe_gethostname(void) /* Uname can fail only if you pass a bad pointer to it. */ uname(&uts); + return xstrndup(!uts.nodename[0] ? "?" : uts.nodename, sizeof(uts.nodename)); +} - return xstrndup(!*(uts.nodename) ? "?" : uts.nodename, sizeof(uts.nodename)); +/* + * On success return the current malloced and NUL terminated domainname. + * On error return malloced and NUL terminated string "?". + * This is an illegal first character for a domainname. + * The returned malloced string must be freed by the caller. + */ +char* FAST_FUNC safe_getdomainname(void) +{ + struct utsname uts; + + uname(&uts); + return xstrndup(!uts.domainname[0] ? "?" : uts.domainname, sizeof(uts.domainname)); } diff --git a/miscutils/crond.c b/miscutils/crond.c index 27f24dd85..51b09ece0 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -839,7 +839,7 @@ static void RunJob(const char *user, CronLine *line) if (mailFd >= 0) { line->cl_MailFlag = 1; - fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", user, + fdprintf(mailFd, "To: %s\nSubject: cron: %s\n\n", line->cl_MailTo, line->cl_Shell); line->cl_MailPos = lseek(mailFd, 0, SEEK_CUR); } else { diff --git a/networking/sendmail.c b/networking/sendmail.c index b81c8525f..1c23ca290 100644 --- a/networking/sendmail.c +++ b/networking/sendmail.c @@ -305,6 +305,7 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) OPTS_i = 1 << 7, // sendmail: ignore lone dots in message body (implied) OPTS_N = 1 << 8, // sendmail: request notification + OPTS_f = 1 << 9, // sendmail: sender address }; const char *options; int opts; @@ -317,7 +318,7 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) // and is NOT NULL if we are called as sendmail if (!ENABLE_FETCHMAIL || 's' == applet_name[0]) { // SENDMAIL - // save initial stdin (body or attachements can be piped!) + // save initial stdin since body is piped! xdup2(STDIN_FILENO, INITIAL_STDIN_FILENO); opt_complementary = "w+:a::"; options = "w:H:St" "s:c:a:iN:f:"; @@ -337,9 +338,9 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) argv += optind; // connect to server - // host[:port] not specified ? -> use $HOST. no $HOST ? -> use localhost + // host[:port] not specified ? -> use $HOSTNAME. no $HOSTNAME ? -> use localhost if (!(opts & OPT_H)) { - opt_connect = getenv("HOST"); + opt_connect = getenv("HOSTNAME"); if (!opt_connect) opt_connect = "127.0.0.1"; } @@ -349,6 +350,12 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) opt_connect = parse_url((char*)opt_connect, &opt_user, &opt_pass); // bb_error_msg("H[%s] U[%s] P[%s]", opt_connect, opt_user, opt_pass); + // username must be defined! + if (!opt_user) { + // N.B. IMHO getenv("USER") can be way easily spoofed! + opt_user = bb_getpwuid(NULL, -1, getuid()); + } + // SSL ordered? -> if (opts & OPT_S) { // ... use openssl helper @@ -384,12 +391,6 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) argv++; } - // we didn't use SSL helper? -> - if (!(opts & OPT_S)) { - // ... wait for initial server OK - smtp_check(NULL, 220); - } - // if -t specified or no recipients specified -> enter all-included mode // i.e. scan stdin for To: and Subject: lines ... // ... and then use the rest of stdin as message body @@ -402,7 +403,10 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) while ((s = xmalloc_reads(INITIAL_STDIN_FILENO, NULL, NULL)) != NULL) { if (0 == strncmp("To: ", s, 4)) { llist_add_to_end(&opt_recipients, s+4); - } else if (0 == strncmp("Subject: ", s, 9)) { +/* } else if (0 == strncmp("From: ", s, 6)) { + opt_from = s+6; + opts |= OPTS_f; +*/ } else if (0 == strncmp("Subject: ", s, 9)) { opt_subject = s+9; opts |= OPTS_s; } else { @@ -414,7 +418,21 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) } } + // got no sender address? -> use username as a resort + if (!(opts & OPTS_f)) { + char *domain = safe_getdomainname(); + opt_from = xasprintf("%s@%s", opt_user, domain); + free(domain); + } + // introduce to server + + // we didn't use SSL helper? -> + if (!(opts & OPT_S)) { + // ... wait for initial server OK + smtp_check(NULL, 220); + } + // we should start with modern EHLO if (250 != smtp_checkp("EHLO %s", sane(opt_from), -1)) { smtp_checkp("HELO %s", opt_from, 250); @@ -427,16 +445,8 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) // first try softly without authentication while (250 != smtp_checkp("MAIL FROM:<%s>", opt_from, code)) { // MAIL FROM failed -> authentication needed - // have we got username? - if (!opt_user) { - // no! fetch it from "from" option - opt_user = xstrdup(opt_from); - *strchrnul(opt_user, '@') = '\0'; - } - // now we've got username - // so try to authenticate if (334 == smtp_check("AUTH LOGIN", -1)) { - uuencode(NULL, opt_user); + uuencode(NULL, opt_user); // opt_user != NULL smtp_check("", 334); uuencode(NULL, opt_pass); smtp_check("", 235); @@ -552,10 +562,7 @@ int sendgetmail_main(int argc ATTRIBUTE_UNUSED, char **argv) *fargs = *argv; // authenticate - if (!opt_user) { - // N.B. IMHO getenv("USER") can be way easily spoofed! - opt_user = bb_getpwuid(NULL, -1, getuid()); - } + // password is mandatory if (!opt_pass) { bb_error_msg_and_die("no password"); -- 2.25.1