From e18ec3a7019ebcf631d1fe67459964ffbc442315 Mon Sep 17 00:00:00 2001 From: Janos SUTO Date: Fri, 2 Mar 2018 22:46:48 +0100 Subject: [PATCH] revised smtp protocol handling Signed-off-by: Janos SUTO --- src/config.h | 4 +- src/defs.h | 2 +- src/misc.c | 66 +++++++++++++------------------ src/misc.h | 3 +- src/session.c | 88 ++++++++++++++++++++--------------------- src/smtp.c | 62 +++++------------------------ src/smtp.h | 2 +- unit_tests/check_misc.c | 46 --------------------- 8 files changed, 86 insertions(+), 187 deletions(-) diff --git a/src/config.h b/src/config.h index e022a47e..b67b3e12 100644 --- a/src/config.h +++ b/src/config.h @@ -9,9 +9,9 @@ #include "piler-config.h" #include "params.h" -#define VERSION "1.3.3" +#define VERSION "1.3.4" -#define BUILD 990 +#define BUILD 991 #define HOSTID "mailarchiver" diff --git a/src/defs.h b/src/defs.h index 75911f57..129c56b7 100644 --- a/src/defs.h +++ b/src/defs.h @@ -383,7 +383,7 @@ struct smtp_session { char ttmpfile[SMALLBUFSIZE]; char mailfrom[SMALLBUFSIZE]; char rcptto[MAX_RCPT_TO][SMALLBUFSIZE]; - char buf[SMALLBUFSIZE]; + char buf[MAXBUFSIZE]; char remote_host[INET6_ADDRSTRLEN]; time_t lasttime; int protocol_state; diff --git a/src/misc.c b/src/misc.c index 9643acdc..37191c62 100644 --- a/src/misc.c +++ b/src/misc.c @@ -84,44 +84,6 @@ long tvdiff(struct timeval a, struct timeval b){ } -/* - * search something in a buffer - */ - -int searchStringInBuffer(char *s, int len1, char *what, int len2){ - int i, k, r; - - for(i=0; inum_of_rcpt_to = 0; for(i=0; ircptto[i], 0, SMALLBUFSIZE); - memset(session->buf, 0, SMALLBUFSIZE); + memset(session->buf, 0, MAXBUFSIZE); memset(session->remote_host, 0, INET6_ADDRSTRLEN); reset_bdat_counters(session); @@ -169,64 +169,64 @@ void tear_down_session(struct smtp_session **sessions, int slot, int *num_connec void handle_data(struct smtp_session *session, char *readbuf, int readlen, struct config *cfg){ - char *p, puf[MAXBUFSIZE]; - int result; + int puflen, rc, lines=0; + char *p, copybuf[BIGBUFSIZE+MAXBUFSIZE], puf[MAXBUFSIZE]; - // process BDAT stuff + // if there's something in the saved buffer, then let's merge them - if(session->protocol_state == SMTP_STATE_BDAT){ - if(session->bad == 1){ - // something bad happened in the BDAT processing - return; - } + if(session->buflen > 0){ + memset(copybuf, 0, sizeof(copybuf)); - process_bdat(session, readbuf, readlen, cfg); + memcpy(copybuf, session->buf, session->buflen); + memcpy(©buf[session->buflen], readbuf, readlen); + + session->buflen = 0; + memset(session->buf, 0, MAXBUFSIZE); + + p = ©buf[0]; } - - // process DATA - - else if(session->protocol_state == SMTP_STATE_DATA){ - process_data(session, readbuf, readlen); - } - - // process other SMTP commands - else { - - if(session->buflen > 0){ - snprintf(puf, sizeof(puf)-1, "%s%s", session->buf, readbuf); - snprintf(readbuf, BIGBUFSIZE-1, "%s", puf); - - session->buflen = 0; - memset(session->buf, 0, SMALLBUFSIZE); - } - p = readbuf; + } - do { - memset(puf, 0, sizeof(puf)); - p = split(p, '\n', puf, sizeof(puf)-1, &result); - if(puf[0] == '\0') continue; + do { + puflen = read_one_line(p, '\n', puf, sizeof(puf)-1, &rc); + p += puflen; - if(result == 1){ - process_smtp_command(session, puf, cfg); + lines++; - // if chunking is enabled and we have data after BDAT - // then process the rest - - if(session->cfg->enable_chunking == 1 && p && session->protocol_state == SMTP_STATE_BDAT){ - process_bdat(session, p, strlen(p), cfg); - break; + if(rc == OK){ + if(session->protocol_state == SMTP_STATE_BDAT){ + if(session->bad == 1){ + // something bad happened in the BDAT processing + return; } + + process_bdat(session, puf, puflen, cfg); + } + + else if(session->protocol_state == SMTP_STATE_DATA){ + process_data(session, puf, puflen); + } + + else { + process_smtp_command(session, puf, cfg); + } + } + else if(puflen > 0){ + // if it's BDAT state, then don't buffer, rather give it to + // the BDAT processing function + if(session->protocol_state == SMTP_STATE_BDAT){ + process_bdat(session, puf, puflen, cfg); } else { - snprintf(session->buf, SMALLBUFSIZE-1, "%s", puf); - session->buflen = strlen(puf); + snprintf(session->buf, MAXBUFSIZE-1, "%s", puf); + session->buflen = puflen; } - } while(p); + } - } + } while(puflen > 0); } diff --git a/src/smtp.c b/src/smtp.c index 850fe65d..171e789e 100644 --- a/src/smtp.c +++ b/src/smtp.c @@ -70,61 +70,17 @@ void process_smtp_command(struct smtp_session *session, char *buf, struct config } -void process_data(struct smtp_session *session, char *readbuf, int readlen){ - char puf[SMALLBUFSIZE+BIGBUFSIZE]; - int n, pos, len, writelen; - - memset(puf, 0, sizeof(puf)); - len = readlen; - - if(session->buflen > 0){ - memcpy(&puf[0], session->buf, session->buflen); - memcpy(&puf[session->buflen], readbuf, readlen); - - len += session->buflen; - } - else { - memcpy(&puf[0], readbuf, readlen); - } - - pos = searchStringInBuffer(&puf[0], len, SMTP_CMD_PERIOD, 5); - - if(pos > 0){ - if(write(session->fd, puf, pos) != -1){ - session->tot_len += pos; - process_command_period(session); - } - else syslog(LOG_PRIORITY, "ERROR (line: %d): process_data(): failed to write %d bytes", __LINE__, pos); - } - else if(pos < 0){ - n = search_char_backward(&puf[0], len, '\r'); - - if(n == -1 || len - n > 4){ - - if(n == -1) writelen = len; - else writelen = n-1; - - if(writelen > 0){ - if(write(session->fd, puf, writelen) != -1){ - session->tot_len += writelen; - } - else syslog(LOG_PRIORITY, "ERROR (line: %d): process_data(): failed to write %d bytes", __LINE__, writelen); - } - } - else { - if(write(session->fd, puf, n) != -1){ - session->tot_len += n; - } - else syslog(LOG_PRIORITY, "ERROR (line: %d) process_data(): failed to write %d bytes", __LINE__, n); - - snprintf(session->buf, SMALLBUFSIZE-1, "%s", &puf[n]); - session->buflen = len - n; - } - } - else { - // The buffer contains only the CR-LF-DOT-CR-LF sequence +void process_data(struct smtp_session *session, char *buf, int buflen){ + if(strcmp(buf, ".\r\n") == 0){ process_command_period(session); } + else { + // write line to file + if(write(session->fd, buf, buflen) != -1){ + session->tot_len += buflen; + } + else syslog(LOG_PRIORITY, "ERROR (line: %d) process_data(): failed to write %d bytes", __LINE__, buflen); + } } diff --git a/src/smtp.h b/src/smtp.h index 5a429ff6..f4b0cb39 100644 --- a/src/smtp.h +++ b/src/smtp.h @@ -8,7 +8,7 @@ #include void process_smtp_command(struct smtp_session *session, char *buf, struct config *cfg); -void process_data(struct smtp_session *session, char *readbuf, int readlen); +void process_data(struct smtp_session *session, char *buf, int buflen); void send_smtp_response(struct smtp_session *session, char *buf); void process_command_helo(struct smtp_session *session, char *buf, int buflen); diff --git a/unit_tests/check_misc.c b/unit_tests/check_misc.c index b1f4a7f1..96a5bb03 100644 --- a/unit_tests/check_misc.c +++ b/unit_tests/check_misc.c @@ -89,50 +89,6 @@ static void test_trim_buffer(){ } -static void test_search_string_in_buffer(){ - unsigned int i; - int pos; - struct test_data_s_s_i test_data_s_s_i[] = { - { "ajaja\r\n.\r\n", SMTP_CMD_PERIOD, 5 }, - { "ajaja\r\n.\r\ndhdjdhj", SMTP_CMD_PERIOD, 5 }, - { "ajajadjdhj", "a", 0 }, - { "ajajadjdhj", "aja", 0 }, - { "ajajadjdhj", "jaja", 1 }, - { "ajajadjdhj", "qqq", -1 }, - }; - - TEST_HEADER(); - - for(i=0; i