sendmail: update by Vladimir
function old new delta sendmail_main 897 939 +42 rcptto 17 40 +23 Signed-off-by: Vladimir Dronnikov <dronnikov@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
f5a295d5a8
commit
944d275175
@ -9,6 +9,10 @@
|
|||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
|
|
||||||
|
// limit maximum allowed number of headers to prevent overflows.
|
||||||
|
// set to 0 to not limit
|
||||||
|
#define MAX_HEADERS 256
|
||||||
|
|
||||||
static int smtp_checkp(const char *fmt, const char *param, int code)
|
static int smtp_checkp(const char *fmt, const char *param, int code)
|
||||||
{
|
{
|
||||||
char *answer;
|
char *answer;
|
||||||
@ -55,7 +59,9 @@ static char *sane_address(char *str)
|
|||||||
|
|
||||||
static void rcptto(const char *s)
|
static void rcptto(const char *s)
|
||||||
{
|
{
|
||||||
smtp_checkp("RCPT TO:<%s>", s, 250);
|
// N.B. we don't die if recipient is rejected, for the other recipients may be accepted
|
||||||
|
if (250 != smtp_checkp("RCPT TO:<%s>", s, -1))
|
||||||
|
bb_error_msg("Bad recipient: <%s>", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sendmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
int sendmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
@ -66,6 +72,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
char *s;
|
char *s;
|
||||||
llist_t *list = NULL;
|
llist_t *list = NULL;
|
||||||
char *domain = sane_address(safe_getdomainname());
|
char *domain = sane_address(safe_getdomainname());
|
||||||
|
unsigned nheaders = 0;
|
||||||
int code;
|
int code;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -197,6 +204,7 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
// and then use the rest of stdin as message body
|
// and then use the rest of stdin as message body
|
||||||
code = 0; // set "analyze headers" mode
|
code = 0; // set "analyze headers" mode
|
||||||
while ((s = xmalloc_fgetline(G.fp0)) != NULL) {
|
while ((s = xmalloc_fgetline(G.fp0)) != NULL) {
|
||||||
|
dump:
|
||||||
// put message lines doubling leading dots
|
// put message lines doubling leading dots
|
||||||
if (code) {
|
if (code) {
|
||||||
// escape leading dots
|
// escape leading dots
|
||||||
@ -215,41 +223,62 @@ int sendmail_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
// To: or Cc: headers add recipients
|
// To: or Cc: headers add recipients
|
||||||
if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Bcc: " + 1, s, 4)) {
|
if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Bcc: " + 1, s, 4)) {
|
||||||
rcptto(sane_address(s+4));
|
rcptto(sane_address(s+4));
|
||||||
// goto addh;
|
goto addheader;
|
||||||
llist_add_to_end(&list, s);
|
|
||||||
// Bcc: header adds blind copy (hidden) recipient
|
// Bcc: header adds blind copy (hidden) recipient
|
||||||
} else if (0 == strncasecmp("Bcc: ", s, 5)) {
|
} else if (0 == strncasecmp("Bcc: ", s, 5)) {
|
||||||
rcptto(sane_address(s+5));
|
rcptto(sane_address(s+5));
|
||||||
free(s);
|
free(s);
|
||||||
// N.B. Bcc: vanishes from headers!
|
// N.B. Bcc: vanishes from headers!
|
||||||
// other headers go verbatim
|
// other headers go verbatim
|
||||||
} else if (s[0]) {
|
// N.B. we allow MAX_HEADERS generic headers at most to prevent attacks
|
||||||
// addh:
|
} else if (strchr(s, ':')) {
|
||||||
|
addheader:
|
||||||
|
if (MAX_HEADERS && ++nheaders >= MAX_HEADERS)
|
||||||
|
goto bail;
|
||||||
llist_add_to_end(&list, s);
|
llist_add_to_end(&list, s);
|
||||||
// the empty line stops analyzing headers
|
// a line without ":" (an empty line too, by definition) doesn't look like a valid header
|
||||||
|
// so stop "analyze headers" mode
|
||||||
} else {
|
} else {
|
||||||
free(s);
|
reenter:
|
||||||
// put recipients specified on cmdline
|
// put recipients specified on cmdline
|
||||||
while (*argv) {
|
while (*argv) {
|
||||||
s = sane_address(*argv);
|
char *t = sane_address(*argv);
|
||||||
rcptto(s);
|
rcptto(t);
|
||||||
llist_add_to_end(&list, xasprintf("To: %s", s));
|
//if (MAX_HEADERS && ++nheaders >= MAX_HEADERS)
|
||||||
|
// goto bail;
|
||||||
|
llist_add_to_end(&list, xasprintf("To: %s", t));
|
||||||
argv++;
|
argv++;
|
||||||
}
|
}
|
||||||
// enter "put message" mode
|
// enter "put message" mode
|
||||||
smtp_check("DATA", 354);
|
// N.B. DATA fails iff no recipients were accepted (or even provided)
|
||||||
|
// in this case just bail out gracefully
|
||||||
|
if (354 != smtp_check("DATA", -1))
|
||||||
|
goto bail;
|
||||||
// dump the headers
|
// dump the headers
|
||||||
while (list) {
|
while (list) {
|
||||||
printf("%s\r\n", (char *) llist_pop(&list));
|
printf("%s\r\n", (char *) llist_pop(&list));
|
||||||
}
|
}
|
||||||
printf("%s\r\n" + 2); // quirk for format string to be reused
|
|
||||||
// stop analyzing headers
|
// stop analyzing headers
|
||||||
code++;
|
code++;
|
||||||
|
// N.B. !s means: we read nothing, and nothing to be read in the future.
|
||||||
|
// just dump empty line and break the loop
|
||||||
|
if (!s) {
|
||||||
|
puts("\r");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// go dump message body
|
||||||
|
// N.B. "s" already contains the first non-header line, so pretend we read it from input
|
||||||
|
goto dump;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// odd case: we didn't stop "analyze headers" mode -> message body is empty. Reenter the loop
|
||||||
|
// N.B. after reenter code will be > 0
|
||||||
|
if (!code)
|
||||||
|
goto reenter;
|
||||||
|
|
||||||
// finalize the message
|
// finalize the message
|
||||||
smtp_check(".", 250);
|
smtp_check(".", 250);
|
||||||
|
bail:
|
||||||
// ... and say goodbye
|
// ... and say goodbye
|
||||||
smtp_check("QUIT", 221);
|
smtp_check("QUIT", 221);
|
||||||
// cleanup
|
// cleanup
|
||||||
|
Loading…
Reference in New Issue
Block a user