diff --git a/src/defs.h b/src/defs.h index ba5995e0..50b22e37 100644 --- a/src/defs.h +++ b/src/defs.h @@ -402,6 +402,7 @@ struct smtp_session { char rcptto[MAX_RCPT_TO][SMALLBUFSIZE]; char buf[MAXBUFSIZE]; char remote_host[INET6_ADDRSTRLEN+1]; + char nullbyte; time_t lasttime; int protocol_state; int slot; diff --git a/src/import_pilerexport.c b/src/import_pilerexport.c index 8514a593..eb40692e 100644 --- a/src/import_pilerexport.c +++ b/src/import_pilerexport.c @@ -58,7 +58,7 @@ void process_buffer(char *buf, int buflen, uint64 *count, struct session_data *s void import_from_pilerexport(struct session_data *sdata, struct data *data, struct config *cfg){ - int n, rc, savedlen=0, puflen; + int n, rc, nullbyte, savedlen=0, puflen; uint64 count=0; char *p, copybuf[2*BIGBUFSIZE+1], buf[BIGBUFSIZE], savedbuf[BIGBUFSIZE], puf[BIGBUFSIZE]; @@ -70,12 +70,16 @@ void import_from_pilerexport(struct session_data *sdata, struct data *data, stru memset(buf, 0, sizeof(buf)); n = fread(buf, 1, sizeof(buf)-1, stdin); + int remaininglen = n; + if(savedlen > 0){ memset(copybuf, 0, sizeof(copybuf)); memcpy(copybuf, savedbuf, savedlen); memcpy(©buf[savedlen], buf, n); + remaininglen += savedlen; + savedlen = 0; memset(savedbuf, 0, sizeof(savedbuf)); @@ -86,8 +90,9 @@ void import_from_pilerexport(struct session_data *sdata, struct data *data, stru } do { - puflen = read_one_line(p, '\n', puf, sizeof(puf), &rc); + puflen = read_one_line(p, remaininglen, '\n', puf, sizeof(puf), &rc, &nullbyte); p += puflen; + remaininglen -= puflen; if(puflen > 0){ if(rc == OK){ diff --git a/src/misc.c b/src/misc.c index 703b21d0..5ac2dc54 100644 --- a/src/misc.c +++ b/src/misc.c @@ -652,34 +652,42 @@ void move_email(struct smtp_session *session){ snprintf(buf, sizeof(buf)-1, "%d/%s", session->ttmpfile[0] % session->cfg->number_of_worker_processes, session->ttmpfile); + if(session->nullbyte){ + snprintf(buf, sizeof(buf)-1, "%s/%s", ERROR_DIR, session->ttmpfile); + syslog(LOG_PRIORITY, "ERROR: %s contains an invalid NUL-byte, moving it to %s", session->ttmpfile, ERROR_DIR); + } + if(rename(session->ttmpfile, buf)){ syslog(LOG_PRIORITY, "ERROR: couldn't rename %s to %s (reason: %s)", session->ttmpfile, buf, strerror(errno)); } } -int read_one_line(char *s, int c, char *buf, int buflen, int *rc){ +int read_one_line(char *s, int slen, int c, char *buf, int buflen, int *rc, int *nullbyte){ int i=0; *rc = ERR; + *nullbyte = 0; memset(buf, 0, buflen); - if(s == NULL){ - return i; - } - - for(; *s; s++){ + for(int j=0; jnet, buf, sizeof(buf))) > 0){ + int remaininglen = n; + if(savedlen){ memset(copybuf, 0, sizeof(copybuf)); memcpy(copybuf, savedbuf, savedlen); memcpy(©buf[savedlen], buf, n); + remaininglen += savedlen; + savedlen = 0; memset(savedbuf, 0, sizeof(savedbuf)); @@ -115,10 +119,13 @@ int pop3_download_email(struct data *data, int i){ int puflen=0; int rc=OK; + int nullbyte=0; + do { char puf[MAXBUFSIZE]; - puflen = read_one_line(p, '\n', puf, sizeof(puf)-1, &rc); + puflen = read_one_line(p, remaininglen, '\n', puf, sizeof(puf)-1, &rc, &nullbyte); + remaininglen -= puflen; nlines++; if(nlines == 1){ diff --git a/src/session.c b/src/session.c index a17b89f9..b8b9ce76 100644 --- a/src/session.c +++ b/src/session.c @@ -99,6 +99,7 @@ void init_smtp_session(struct smtp_session *session, int slot, int sd, char *cli session->net.ctx = NULL; session->net.ssl = NULL; + session->nullbyte = 0; session->last_data_char = 0; session->fd = -1; @@ -160,11 +161,13 @@ 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){ - int puflen, rc; + int puflen, rc, nullbyte; char *p, copybuf[BIGBUFSIZE+MAXBUFSIZE], puf[MAXBUFSIZE]; // if there's something in the saved buffer, then let's merge them + int remaininglen = readlen + session->buflen; + if(session->buflen > 0){ memset(copybuf, 0, sizeof(copybuf)); @@ -183,8 +186,13 @@ void handle_data(struct smtp_session *session, char *readbuf, int readlen, struc do { - puflen = read_one_line(p, '\n', puf, sizeof(puf)-1, &rc); + puflen = read_one_line(p, remaininglen, '\n', puf, sizeof(puf)-1, &rc, &nullbyte); p += puflen; + remaininglen -= puflen; + + if(nullbyte){ + session->nullbyte = 1; + } // complete line: rc == OK and puflen > 0 // incomplete line with something in the buffer: rc == ERR and puflen > 0 @@ -195,7 +203,7 @@ void handle_data(struct smtp_session *session, char *readbuf, int readlen, struc // Save incomplete line to buffer if(rc == ERR){ - snprintf(session->buf, sizeof(session->buf)-1, "%s", puf); + memcpy(session->buf, puf, puflen); session->buflen = puflen; }