diff --git a/include/detect.h b/include/detect.h index bdb9a88..4d25556 100644 --- a/include/detect.h +++ b/include/detect.h @@ -19,7 +19,9 @@ #define DETECT_H #include +#include bool detect_pgp(const char* message); - +char* detect_start_of_body(char* message); +char* detect_end_of_body(char* message); #endif /* DETECT_H */ diff --git a/src/detect.c b/src/detect.c index 9b659d1..59c585a 100644 --- a/src/detect.c +++ b/src/detect.c @@ -16,9 +16,55 @@ */ #include "detect.h" +#include +#define _GNU_SOURCE +#include bool detect_pgp(const char* message){ return false; } +/* If body hasn't started yet, it returns NULL, if it has started, it returns + * the pointer to the beginning of the newline. + */ +char* detect_start_of_body(char* message){ + + const char* data = "DATA"; + + char* data_cmd = strcasestr(message, data); + for(;data_cmd != NULL; data_cmd = strcasestr(data_cmd+1, data)){ + + if(data_cmd == NULL){ + return NULL; + } + + if(data_cmd == message){ + /* You don't start an smtp conversation with data eh? */ + return NULL; + } + + char before = data_cmd[-1]; + char after = data_cmd[strlen(data)+1]; + if(before == '\n' || after == '\r'){ + /* Find the end of that line, otherwise fail... */ + for(size_t i = 0; data_cmd[i] != '\0'; i++){ + if(data_cmd[i] == '\n'){ + return data_cmd+i+1; + } + } + } + + + } + return NULL; + +} + +char* detect_end_of_body(char* message){ + + const char* data = "\r\n.\r\n"; + + return strstr(message, data); + +} diff --git a/src/main.c b/src/main.c index e4b3e1b..6a46357 100644 --- a/src/main.c +++ b/src/main.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #include "version.h" #include "config.h" #include "attach.h" +#include "detect.h" /* * error - wrapper for perror @@ -63,7 +65,7 @@ void* client_handle_async(void* params){ } int n; /* message byte size */ - char buf[1024]; + char buf[10]; struct pollfd fds[2]; memset(fds, 0 , sizeof(fds)); fds[0].fd = cli->fd; @@ -73,6 +75,13 @@ void* client_handle_async(void* params){ int timeout = (10 * 1000); /* 10 seconds */ + char * input_buffer = malloc(1); + input_buffer[0]=0; + size_t in_len = 1; + bool in_body = false, after_body = false; + char* body_p = NULL; + size_t body_offs = 0; + while(poll(fds, 2, timeout) > 0){ for(size_t i = 0; i < 2; i++){ if(!(fds[i].revents & POLLIN)){ @@ -84,18 +93,75 @@ void* client_handle_async(void* params){ if (n <= 0) { goto closeup; } - printf("%lu: %s\n", i, buf); - write((fds[!i].fd), buf, n); + + + if(i==0 && !in_body){ + /* As long as we are outside the real mail body + * we can basically passthrough the commands + */ + in_len += n; + input_buffer = realloc(input_buffer, in_len); + strncat(input_buffer,buf, n); + body_p = detect_start_of_body(input_buffer); + if(body_p != NULL){ + /* We reached the beginning of the body + * now! */ + body_offs = body_p - input_buffer; + in_body = true; + write((fds[!i].fd), + input_buffer+(in_len-n), + body_offs-(in_len-n)); + printf("Beginning of body found! " + "Awaiting end...\n"); + + }else{ + write((fds[!i].fd), buf, n); + + } + } else if(i==0 && !after_body){ + /* We keep the body until we have it completetly + */ + in_len += n; + input_buffer = realloc(input_buffer, in_len); + strncat(input_buffer,buf, n); + body_p = detect_end_of_body(input_buffer+ + body_offs); + + if(body_p != NULL){ + + printf("We found the body:\n%.*s\n", + body_p-(input_buffer+body_offs), + input_buffer+body_offs); + + size_t body_len = body_p- + (input_buffer+body_offs); + + write((fds[!i].fd), + input_buffer+body_offs, + body_len); + write((fds[!i].fd), + input_buffer+body_offs+body_len, + in_len-(body_offs+body_len)); + + after_body = true; + + } + + }else{ + write((fds[!i].fd), buf, n); + + } } } closeup: - printf("Disconnecting clients"); + printf("Disconnecting clients\n"); close(cli->fd); close(remote_fd); free(cli); + free(input_buffer); return NULL; }