sendmail: from Vladimir:
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 30 Jun 2008 13:30:21 +0000 (13:30 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 30 Jun 2008 13:30:21 +0000 (13:30 -0000)
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
libbb/safe_gethostname.c
miscutils/crond.c
networking/sendmail.c

index 7bc0dca2f24edc017f5a414370fad64bcea356ae..54601f87b4b09d24eed78784d1e56b1160b675d5 100644 (file)
@@ -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;
index 1f8b2a8fd32c5e46f5a93431c9d70eacf95e7b8f..7407fb78299c59aa8db1756b76f9ac710c6c0ade 100644 (file)
@@ -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));
 }
index 27f24dd8570748dd7607dd9e2f03d2089d278715..51b09ece03770efb49ca850b7b6e3ce412e3ea69 100644 (file)
@@ -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 {
index b81c8525f675ce0544c16d6d9ef1b05e106fffba..1c23ca290f758c9733136a2317443e6365f7a1ee 100644 (file)
@@ -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");