diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/smtppass.c | 68 | ||||
-rw-r--r-- | common/stringx.c | 26 | ||||
-rw-r--r-- | common/stringx.h | 4 |
3 files changed, 84 insertions, 14 deletions
diff --git a/common/smtppass.c b/common/smtppass.c index b682e83..0a20777 100644 --- a/common/smtppass.c +++ b/common/smtppass.c @@ -91,7 +91,13 @@ clamsmtp_thread_t; #define SMTP_DATA "DATA" CRLF #define SMTP_BANNER "220 clamsmtp" CRLF -#define SMTP_DELIMS "\r\n\t :" +#define SMTP_DELIMS "\r\n\t :-" + +#define ESMTP_PIPELINE "PIPELINING" +#define ESMTP_TLS "STARTTLS" +#define ESMTP_CHUNK "CHUNKING" +#define ESMTP_BINARY "BINARYMIME" +#define ESMTP_CHECK "CHECKPOINT" #define HELO_CMD "HELO" #define EHLO_CMD "EHLO" @@ -99,6 +105,8 @@ clamsmtp_thread_t; #define TO_CMD "RCPT TO" #define DATA_CMD "DATA" #define RSET_CMD "RSET" +#define STARTTLS_CMD "STARTTLS" +#define BDAT_CMD "BDAT" #define DATA_END_SIG CRLF "." CRLF @@ -668,6 +676,7 @@ static int smtp_passthru(clamsmtp_context_t* ctx) char logline[LINE_LENGTH]; int r, ret = 0; int first_rsp = 1; + int filter_ehlo = 0; fd_set mask; int neterror = 0; @@ -738,13 +747,24 @@ static int smtp_passthru(clamsmtp_context_t* ctx) } /* - * We don't support EHLO (ESMTP) because pipelining - * and other nuances aren't implemented here. In order - * to keep things reliable we just disable it all. + * We filter out features that we can't support in + * the EHLO response (ESMTP). See below */ else if(is_first_word(ctx->line, EHLO_CMD, KL(EHLO_CMD))) { - messagex(ctx, LOG_DEBUG, "ESMTP not implemented"); + messagex(ctx, LOG_DEBUG, "filtering EHLO response"); + filter_ehlo = 1; + } + + /* + * We don't like these commands. Filter them out. We should have + * filtered out their service extensions earlier in the EHLO response. + * This is just for errant clients. + */ + else if(is_first_word(ctx->line, STARTTLS_CMD, KL(STARTTLS_CMD)) || + is_first_word(ctx->line, BDAT_CMD, KL(BDAT_CMD))) + { + messagex(ctx, LOG_DEBUG, "ESMTP feature not supported"); if(write_data(ctx, &(ctx->client), SMTP_NOTSUPP) == -1) RETURN(-1); @@ -812,6 +832,32 @@ static int smtp_passthru(clamsmtp_context_t* ctx) } } + /* + * Filter out any EHLO responses that we can't or don't want + * to support. For example pipelining or TLS. + */ + if(filter_ehlo) + { + if((r = check_first_word(ctx->line, OK_RSP, KL(OK_RSP), SMTP_DELIMS)) > 0) + { + char* p = ctx->line + r; + if(is_first_word(p, ESMTP_PIPELINE, KL(ESMTP_PIPELINE)) || + is_first_word(p, ESMTP_TLS, KL(ESMTP_TLS)) || + is_first_word(p, ESMTP_CHUNK, KL(ESMTP_CHUNK)) || + is_first_word(p, ESMTP_BINARY, KL(ESMTP_BINARY)) || + is_first_word(p, ESMTP_CHECK, KL(ESMTP_CHECK))) + { + messagex(ctx, LOG_DEBUG, "filtered ESMTP feature: %s", p); + continue; + } + } + else + { + filter_ehlo = 0; + messagex(ctx, LOG_DEBUG, "done filtering ESMTP response"); + } + } + if(write_data(ctx, &(ctx->client), ctx->line) == -1) RETURN(-1); @@ -844,15 +890,12 @@ static void add_to_logline(char* logline, char* prefix, char* line) strlcat(logline, prefix, l); /* Skip initial white space */ - while(*line && isspace(*line)) - *line++; + line = trim_start(line); strlcat(logline, line, l); - t = logline + strlen(logline); /* Skip later white space */ - while(t > logline && isspace(*(t - 1))) - *(--t) = 0; + trim_end(logline); } static int avcheck_data(clamsmtp_context_t* ctx, char* logline) @@ -1380,10 +1423,7 @@ static void read_junk(clamsmtp_context_t* ctx, int fd) break; buf[l] = 0; - t = buf; - - while(*t && isspace(*t)) - t++; + t = trim_start(buf); if(!said && *t) { diff --git a/common/stringx.c b/common/stringx.c index f4d9910..a2bc90d 100644 --- a/common/stringx.c +++ b/common/stringx.c @@ -261,6 +261,32 @@ int is_blank_line(const char* line) return *line == 0; } +char* trim_start(const char* data) +{ + while(*data && isspace(*data)) + ++data; + return (char*)data; +} + +char* trim_end(char* data) +{ + char* t = data + strlen(data); + + while(t > data && isspace(*(t - 1))) + { + t--; + *t = 0; + } + + return data; +} + +char* trim_space(char* data) +{ + data = (char*)trim_start(data); + return trim_end(data); +} + /* ----------------------------------------------------------------------- * Locking */ diff --git a/common/stringx.h b/common/stringx.h index 8a39c7e..8e6f2f4 100644 --- a/common/stringx.h +++ b/common/stringx.h @@ -50,6 +50,10 @@ int is_first_word(const char* line, const char* word, int len); int is_last_word(const char* line, const char* word, int len); int is_blank_line(const char* line); +char* trim_start(const char* data); +char* trim_end(char* data); +char* trim_space(char* data); + void plock(); void punlock(); |