mirror of
https://bitbucket.org/jsuto/piler.git
synced 2024-12-25 06:00:13 +01:00
revised smtp protocol handling
Signed-off-by: Janos SUTO <sj@acts.hu>
This commit is contained in:
parent
52d44ddee1
commit
e18ec3a701
@ -9,9 +9,9 @@
|
|||||||
#include "piler-config.h"
|
#include "piler-config.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
|
||||||
#define VERSION "1.3.3"
|
#define VERSION "1.3.4"
|
||||||
|
|
||||||
#define BUILD 990
|
#define BUILD 991
|
||||||
|
|
||||||
#define HOSTID "mailarchiver"
|
#define HOSTID "mailarchiver"
|
||||||
|
|
||||||
|
@ -383,7 +383,7 @@ struct smtp_session {
|
|||||||
char ttmpfile[SMALLBUFSIZE];
|
char ttmpfile[SMALLBUFSIZE];
|
||||||
char mailfrom[SMALLBUFSIZE];
|
char mailfrom[SMALLBUFSIZE];
|
||||||
char rcptto[MAX_RCPT_TO][SMALLBUFSIZE];
|
char rcptto[MAX_RCPT_TO][SMALLBUFSIZE];
|
||||||
char buf[SMALLBUFSIZE];
|
char buf[MAXBUFSIZE];
|
||||||
char remote_host[INET6_ADDRSTRLEN];
|
char remote_host[INET6_ADDRSTRLEN];
|
||||||
time_t lasttime;
|
time_t lasttime;
|
||||||
int protocol_state;
|
int protocol_state;
|
||||||
|
66
src/misc.c
66
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; i<len1; i++){
|
|
||||||
r = 0;
|
|
||||||
|
|
||||||
for(k=0; k<len2; k++){
|
|
||||||
if(*(s+i+k) == *(what+k))
|
|
||||||
r++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(r == len2)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int search_char_backward(char *buf, int buflen, char c){
|
|
||||||
int n, m;
|
|
||||||
|
|
||||||
m = buflen - 1 - 5;
|
|
||||||
if(m < 0) m = 0;
|
|
||||||
|
|
||||||
for(n=m; n<buflen; n++){
|
|
||||||
if(*(buf + n) == c){
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* count a character in buffer
|
* count a character in buffer
|
||||||
*/
|
*/
|
||||||
@ -739,6 +701,34 @@ void move_email(struct smtp_session *session){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int read_one_line(char *s, int c, char *buf, int buflen, int *rc){
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
*rc = ERR;
|
||||||
|
|
||||||
|
memset(buf, 0, buflen);
|
||||||
|
|
||||||
|
if(s == NULL){
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(; *s; s++){
|
||||||
|
if(i<buflen-2){
|
||||||
|
buf[i] = *s;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if(*s == c){
|
||||||
|
*rc = OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
char *strcasestr(const char *s, const char *find){
|
char *strcasestr(const char *s, const char *find){
|
||||||
char c, sc;
|
char c, sc;
|
||||||
|
@ -19,8 +19,6 @@ int get_build();
|
|||||||
void get_extractor_list();
|
void get_extractor_list();
|
||||||
void __fatal(char *s);
|
void __fatal(char *s);
|
||||||
long tvdiff(struct timeval a, struct timeval b);
|
long tvdiff(struct timeval a, struct timeval b);
|
||||||
int searchStringInBuffer(char *s, int len1, char *what, int len2);
|
|
||||||
int search_char_backward(char *buf, int buflen, char c);
|
|
||||||
int countCharacterInBuffer(char *p, char c);
|
int countCharacterInBuffer(char *p, char c);
|
||||||
void replaceCharacterInBuffer(char *p, char from, char to);
|
void replaceCharacterInBuffer(char *p, char from, char to);
|
||||||
char *split(char *str, int ch, char *buf, int buflen, int *result);
|
char *split(char *str, int ch, char *buf, int buflen, int *result);
|
||||||
@ -51,6 +49,7 @@ int create_and_bind(char *listen_addr, int listen_port);
|
|||||||
int can_i_write_directory(char *dir);
|
int can_i_write_directory(char *dir);
|
||||||
|
|
||||||
void move_email(struct smtp_session *session);
|
void move_email(struct smtp_session *session);
|
||||||
|
int read_one_line(char *s, int c, char *buf, int buflen, int *rc);
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
char *strcasestr(const char *s, const char *find);
|
char *strcasestr(const char *s, const char *find);
|
||||||
|
@ -126,7 +126,7 @@ void init_smtp_session(struct smtp_session *session, int slot, int sd, struct co
|
|||||||
session->num_of_rcpt_to = 0;
|
session->num_of_rcpt_to = 0;
|
||||||
for(i=0; i<MAX_RCPT_TO; i++) memset(session->rcptto[i], 0, SMALLBUFSIZE);
|
for(i=0; i<MAX_RCPT_TO; i++) memset(session->rcptto[i], 0, SMALLBUFSIZE);
|
||||||
|
|
||||||
memset(session->buf, 0, SMALLBUFSIZE);
|
memset(session->buf, 0, MAXBUFSIZE);
|
||||||
memset(session->remote_host, 0, INET6_ADDRSTRLEN);
|
memset(session->remote_host, 0, INET6_ADDRSTRLEN);
|
||||||
|
|
||||||
reset_bdat_counters(session);
|
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){
|
void handle_data(struct smtp_session *session, char *readbuf, int readlen, struct config *cfg){
|
||||||
char *p, puf[MAXBUFSIZE];
|
int puflen, rc, lines=0;
|
||||||
int result;
|
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->buflen > 0){
|
||||||
|
memset(copybuf, 0, sizeof(copybuf));
|
||||||
|
|
||||||
|
memcpy(copybuf, session->buf, session->buflen);
|
||||||
|
memcpy(©buf[session->buflen], readbuf, readlen);
|
||||||
|
|
||||||
|
session->buflen = 0;
|
||||||
|
memset(session->buf, 0, MAXBUFSIZE);
|
||||||
|
|
||||||
|
p = ©buf[0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p = readbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
do {
|
||||||
|
puflen = read_one_line(p, '\n', puf, sizeof(puf)-1, &rc);
|
||||||
|
p += puflen;
|
||||||
|
|
||||||
|
lines++;
|
||||||
|
|
||||||
|
if(rc == OK){
|
||||||
if(session->protocol_state == SMTP_STATE_BDAT){
|
if(session->protocol_state == SMTP_STATE_BDAT){
|
||||||
if(session->bad == 1){
|
if(session->bad == 1){
|
||||||
// something bad happened in the BDAT processing
|
// something bad happened in the BDAT processing
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_bdat(session, readbuf, readlen, cfg);
|
process_bdat(session, puf, puflen, cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process DATA
|
|
||||||
|
|
||||||
else if(session->protocol_state == SMTP_STATE_DATA){
|
else if(session->protocol_state == SMTP_STATE_DATA){
|
||||||
process_data(session, readbuf, readlen);
|
process_data(session, puf, puflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process other SMTP commands
|
|
||||||
|
|
||||||
else {
|
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;
|
|
||||||
|
|
||||||
if(result == 1){
|
|
||||||
process_smtp_command(session, puf, cfg);
|
process_smtp_command(session, puf, cfg);
|
||||||
|
|
||||||
// if chunking is enabled and we have data after BDAT <len>
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 {
|
else {
|
||||||
snprintf(session->buf, SMALLBUFSIZE-1, "%s", puf);
|
snprintf(session->buf, MAXBUFSIZE-1, "%s", puf);
|
||||||
session->buflen = strlen(puf);
|
session->buflen = puflen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while(p);
|
|
||||||
|
|
||||||
}
|
} while(puflen > 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
56
src/smtp.c
56
src/smtp.c
@ -70,60 +70,16 @@ void process_smtp_command(struct smtp_session *session, char *buf, struct config
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void process_data(struct smtp_session *session, char *readbuf, int readlen){
|
void process_data(struct smtp_session *session, char *buf, int buflen){
|
||||||
char puf[SMALLBUFSIZE+BIGBUFSIZE];
|
if(strcmp(buf, ".\r\n") == 0){
|
||||||
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);
|
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 {
|
else {
|
||||||
if(write(session->fd, puf, n) != -1){
|
// write line to file
|
||||||
session->tot_len += n;
|
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__, n);
|
else syslog(LOG_PRIORITY, "ERROR (line: %d) process_data(): failed to write %d bytes", __LINE__, buflen);
|
||||||
|
|
||||||
snprintf(session->buf, SMALLBUFSIZE-1, "%s", &puf[n]);
|
|
||||||
session->buflen = len - n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The buffer contains only the CR-LF-DOT-CR-LF sequence
|
|
||||||
process_command_period(session);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <piler.h>
|
#include <piler.h>
|
||||||
|
|
||||||
void process_smtp_command(struct smtp_session *session, char *buf, struct config *cfg);
|
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 send_smtp_response(struct smtp_session *session, char *buf);
|
||||||
void process_command_helo(struct smtp_session *session, char *buf, int buflen);
|
void process_command_helo(struct smtp_session *session, char *buf, int buflen);
|
||||||
|
@ -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<sizeof(test_data_s_s_i)/sizeof(struct test_data_s_s_i); i++){
|
|
||||||
pos = searchStringInBuffer(test_data_s_s_i[i].s1, strlen(test_data_s_s_i[i].s1), test_data_s_s_i[i].s2, strlen(test_data_s_s_i[i].s2));
|
|
||||||
//printf("%s %s %d, %d\n", test_data_s_s_i[i].s1, test_data_s_s_i[i].s2, pos, test_data_s_s_i[i].result);
|
|
||||||
ASSERT(pos == test_data_s_s_i[i].result, test_data_s_s_i[i].s1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_FOOTER();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void test_search_char_backward(){
|
|
||||||
unsigned int i;
|
|
||||||
int pos;
|
|
||||||
struct test_data_s_s_i test_data_s_s_i[] = {
|
|
||||||
{ "abcdefghij\r\n.\r\n", "\r", 10 },
|
|
||||||
{ "abcdefghij\n\n.\r\n", "\r", 13 },
|
|
||||||
{ "abcdefghij\n\n.\n\n", "\r", -1 },
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_HEADER();
|
|
||||||
|
|
||||||
for(i=0; i<sizeof(test_data_s_s_i)/sizeof(struct test_data_s_s_i); i++){
|
|
||||||
pos = search_char_backward(test_data_s_s_i[i].s1, strlen(test_data_s_s_i[i].s1), test_data_s_s_i[i].s2[0]);
|
|
||||||
ASSERT(pos == test_data_s_s_i[i].result, test_data_s_s_i[i].s1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_FOOTER();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void test_make_random_string(){
|
static void test_make_random_string(){
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
char buf[SMALLBUFSIZE];
|
char buf[SMALLBUFSIZE];
|
||||||
@ -229,8 +185,6 @@ int main(){
|
|||||||
test_extract_verp_address();
|
test_extract_verp_address();
|
||||||
test_extract_email();
|
test_extract_email();
|
||||||
test_trim_buffer();
|
test_trim_buffer();
|
||||||
test_search_string_in_buffer();
|
|
||||||
test_search_char_backward();
|
|
||||||
test_make_random_string();
|
test_make_random_string();
|
||||||
test_create_id();
|
test_create_id();
|
||||||
test_split();
|
test_split();
|
||||||
|
Loading…
Reference in New Issue
Block a user