diff --git a/src/Makefile.in b/src/Makefile.in index d69f40d..ece7324 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -48,6 +48,9 @@ ln -sf libpiler.so.$(LIBPILER_VERSION) libpiler.so.$(PILER_VERSION) +pilerdecrypt: pilerdecrypt.c cfg.o misc.o tai.o store.o + $(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $^ $(LIBS) $(LIBDIR) + pilerconf: pilerconf.c cfg.o misc.o tai.o $(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $^ $(LIBS) $(LIBDIR) diff --git a/src/attachment.c b/src/attachment.c index 3d66193..a3d1b8a 100644 --- a/src/attachment.c +++ b/src/attachment.c @@ -27,7 +27,7 @@ found = 0; id = 0; - if(strlen(state->attachments[i].filename) > 4){ + if(strlen(state->attachments[i].filename) > 4 && state->attachments[i].size > 10){ snprintf(s, sizeof(s)-1, "SELECT `id` FROM `%s` WHERE `sig`='%s'", SQL_ATTACHMENT_TABLE, state->attachments[i].digest); @@ -57,11 +57,6 @@ if(mysql_real_query(&(sdata->mysql), s, strlen(s))){ syslog(LOG_PRIORITY, "%s attachment sql error: *%s*", sdata->ttmpfile, mysql_error(&(sdata->mysql))); - - if(found == 0){ - /* TODO: remove the previously stored attachment */ - } - return 1; } diff --git a/src/defs.h b/src/defs.h index 1805ebe..9ad279f 100644 --- a/src/defs.h +++ b/src/defs.h @@ -83,11 +83,11 @@ int line_num; int message_state; int is_header; + int is_1st_header; int textplain; int texthtml; int message_rfc822; int base64; - int has_base64; int utf8; int qp; int htmltag; @@ -109,6 +109,9 @@ unsigned long n_body_token; unsigned long n_chain_token; + char filename[TINYBUFSIZE]; + char type[TINYBUFSIZE]; + struct list *boundaries; int n_attachments; @@ -127,6 +130,7 @@ int need_scan; float __acquire, __parsed, __av, __store, __compress, __encrypt; char bodydigest[2*DIGEST_LENGTH+1]; + char digest[2*DIGEST_LENGTH+1]; time_t now, sent; #ifdef NEED_MYSQL MYSQL mysql; diff --git a/src/digest.c b/src/digest.c index 5785e83..5ab0f4f 100644 --- a/src/digest.c +++ b/src/digest.c @@ -15,12 +15,12 @@ int make_body_digest(struct session_data *sdata, struct __config *cfg){ - int i=0, n, fd; - char *p, *body=NULL; + int i=0, n, fd, hdr_len=0, offset=3; + char *body=NULL; unsigned char buf[MAXBUFSIZE], md[DIGEST_LENGTH]; SHA256_CTX context; - if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: digesting", sdata->ttmpfile); + //if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: digesting", sdata->ttmpfile); memset(sdata->bodydigest, 0, 2*DIGEST_LENGTH+1); SHA256_Init(&context); @@ -31,23 +31,30 @@ while((n = read(fd, buf, MAXBUFSIZE)) > 0){ body = (char *)&buf[0]; - i++; - if(i == 1){ - p = strstr((char*)buf, "\n\n"); - if(p){ - body = p+2; - n = strlen(body); - } else { - p = strstr((char*)buf, "\n\r\n"); - if(p){ - body = p+3; - n = strlen(body); - } + if(i == 0){ + + hdr_len = searchStringInBuffer(body, MAXBUFSIZE, "\n\r\n", 3); + if(hdr_len == 0){ + searchStringInBuffer(body, 2*MAXBUFSIZE+1, "\n\n", 2); + offset = 2; + } + + if(hdr_len > 0){ + hdr_len += offset; + + sdata->hdr_len = hdr_len; + + body += hdr_len; + n -= hdr_len; + + if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: hdr_len: %d, offset: %d", sdata->ttmpfile, hdr_len, offset); } } + SHA256_Update(&context, body, n); + i++; } close(fd); diff --git a/src/message.c b/src/message.c index 385112c..098eb9a 100644 --- a/src/message.c +++ b/src/message.c @@ -145,7 +145,7 @@ goto ENDE_META; } - snprintf(s, MAXBUFSIZE-1, "INSERT INTO %s (`from`,`to`,`subject`,`arrived`,`sent`,`size`,`hlen`,`piler_id`,`message_id`,`bodydigest`) VALUES(?,?,?,%ld,%ld,%d,%d,'%s',?,'%s')", SQL_METADATA_TABLE, sdata->now, sdata->sent, sdata->tot_len, sdata->hdr_len, sdata->ttmpfile, sdata->bodydigest); + snprintf(s, MAXBUFSIZE-1, "INSERT INTO %s (`from`,`to`,`subject`,`arrived`,`sent`,`size`,`hlen`,`attachments`,`piler_id`,`message_id`,`digest`,`bodydigest`) VALUES(?,?,?,%ld,%ld,%d,%d,%d,'%s',?,'%s','%s')", SQL_METADATA_TABLE, sdata->now, sdata->sent, sdata->tot_len, sdata->hdr_len, state->n_attachments, sdata->ttmpfile, sdata->digest, sdata->bodydigest); if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: meta sql: *%s*", sdata->ttmpfile, s); @@ -203,7 +203,6 @@ rc = mysql_stmt_execute(stmt); - //rc = mysql_real_query(&(sdata->mysql), s, strlen(s)); if(rc){ syslog(LOG_PRIORITY, "%s: meta sql error: *%s*", sdata->ttmpfile, mysql_error(&(sdata->mysql))); @@ -249,12 +248,13 @@ - if(store_attachments(sdata, state, cfg)) return ERR; + rc = store_attachments(sdata, state, cfg); - for(i=0; in_attachments; i++){ + for(i=1; i<=state->n_attachments; i++){ unlink(state->attachments[i].internalname); } + if(rc) return ERR; rc = store_file(sdata, sdata->tmpframe, 0, 0, cfg); if(rc == 0){ diff --git a/src/parser.c b/src/parser.c index 4279057..38357d4 100644 --- a/src/parser.c +++ b/src/parser.c @@ -49,9 +49,10 @@ free_list(state.boundaries); - for(i=0; iverbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: attachment list: i:%d, name=*%s*, type: *%s*, size: %d, int.name: %s, digest: %s\n", sdata->ttmpfile, i, state.attachments[i].filename, state.attachments[i].type, state.attachments[i].size, state.attachments[i].internalname, state.attachments[i].digest); + if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: attachment list: i:%d, name=*%s*, type: *%s*, size: %d, int.name: %s, digest: %s", sdata->ttmpfile, i, state.attachments[i].filename, state.attachments[i].type, state.attachments[i].size, state.attachments[i].internalname, state.attachments[i].digest); + //printf("attachment list: i:%d, name=*%s*, type: *%s*, size: %d, int.name: %s, digest: %s\n", i, state.attachments[i].filename, state.attachments[i].type, state.attachments[i].size, state.attachments[i].internalname, state.attachments[i].digest); } @@ -73,17 +74,20 @@ char *p, *r, puf[SMALLBUFSIZE]; int x, len, b64_len, boundary_line=0; - state->line_num++; len = strlen(buf); - if(state->message_state == MSG_BODY && state->has_to_dump == 1 && state->pushed_pointer == 0){ - snprintf(puf, sizeof(puf)-1, "ATTACHMENT_POINTER_%s.%d\n", sdata->ttmpfile, state->n_attachments); - write(state->mfd, puf, strlen(puf)); - state->pushed_pointer = 1; + //printf("buf: %s", buf); + + if(state->message_rfc822 == 0 && (buf[0] == '\r' || buf[0] == '\n') ){ + state->message_state = MSG_BODY; + + if(state->is_header == 1) state->is_header = 0; + state->is_1st_header = 0; } - if(state->message_state == MSG_BODY && state->has_to_dump == 1 && is_item_on_string(state->boundaries, buf) == 0){ + + if(state->message_state == MSG_BODY && state->fd != -1 && is_item_on_string(state->boundaries, buf) == 0){ //printf("dumping: %s", buf); write(state->fd, buf, len); state->attachments[state->n_attachments].size += len; @@ -95,6 +99,34 @@ } + if(state->message_state == MSG_BODY && state->has_to_dump == 1 && state->pushed_pointer == 0){ + //printf("####name: %s, type: %s, base64: %d\n", state->filename, state->type, state->base64); + + state->pushed_pointer = 1; + + + // this is a real attachment to dump + if(state->base64 == 1 && strlen(state->filename) > 5 && strlen(state->type) > 3 && state->n_attachments < MAX_ATTACHMENTS-1){ + state->n_attachments++; + + snprintf(state->attachments[state->n_attachments].filename, TINYBUFSIZE-1, "%s", state->filename); + snprintf(state->attachments[state->n_attachments].type, TINYBUFSIZE-1, "%s", state->type); + snprintf(state->attachments[state->n_attachments].internalname, TINYBUFSIZE-1, "%s.a%d", sdata->ttmpfile, state->n_attachments); + + //printf("DUMP FILE: %s\n", state->attachments[state->n_attachments].internalname); + state->fd = open(state->attachments[state->n_attachments].internalname, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); + + snprintf(puf, sizeof(puf)-1, "ATTACHMENT_POINTER_%s.a%d", sdata->ttmpfile, state->n_attachments); + write(state->mfd, puf, strlen(puf)); + //printf("%s", puf); + } + else { + state->has_to_dump = 0; + } + + } + + if(*buf == '.' && *(buf+1) == '.') buf++; @@ -104,10 +136,6 @@ /* skip empty lines */ if(state->message_rfc822 == 0 && (buf[0] == '\r' || buf[0] == '\n') ){ - state->message_state = MSG_BODY; - - if(state->is_header == 1) state->is_header = 0; - return 0; } @@ -168,9 +196,9 @@ if(p){ p++; if(*p == ' ' || *p == '\t') p++; - snprintf(state->attachments[state->n_attachments].type, TINYBUFSIZE-1, "%s", p); + snprintf(state->type, TINYBUFSIZE-1, "%s", p); state->content_type_is_set = 1; - p = strchr(state->attachments[state->n_attachments].type, ';'); + p = strchr(state->type, ';'); if(p) *p = '\0'; } @@ -202,34 +230,19 @@ } - if(state->message_state == MSG_CONTENT_TYPE || state->message_state == MSG_CONTENT_DISPOSITION){ - if(strlen(state->attachments[state->n_attachments].filename) < 5){ - extractNameFromHeaderLine(buf, "name", state->attachments[state->n_attachments].filename); - snprintf(state->attachments[state->n_attachments].internalname, TINYBUFSIZE-1, "%s.a%d", sdata->ttmpfile, state->n_attachments); - } - - if(strlen(state->attachments[state->n_attachments].filename) > 4 && state->has_to_dump == 0){ - state->has_to_dump = 1; - //printf("DUMP FILE: %s\n", state->attachments[state->n_attachments].internalname); - state->fd = open(state->attachments[state->n_attachments].internalname, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); - } - + if((state->message_state == MSG_CONTENT_TYPE || state->message_state == MSG_CONTENT_DISPOSITION) && strlen(state->filename) < 5){ + extractNameFromHeaderLine(buf, "name", state->filename); } if(state->message_state == MSG_CONTENT_TRANSFER_ENCODING){ - - if(strcasestr(buf, "base64")){ - state->base64 = 1; - state->has_base64 = 1; - } - + if(strcasestr(buf, "base64")) state->base64 = 1; if(strcasestr(buf, "quoted-printable")) state->qp = 1; } - /* skip the boundary itself */ + /* boundary check, and reset variables */ boundary_line = is_item_on_string(state->boundaries, buf); @@ -242,17 +255,7 @@ } - if(state->n_attachments < MAX_ATTACHMENTS-1) state->n_attachments++; - - /* - Use the previous attachment slot if there was not an attached file. - This is also the case if the filename field is empty. - */ - if(state->n_attachments > 0 && strlen(state->attachments[state->n_attachments-1].filename) < 5){ - state->n_attachments--; - } - - state->has_to_dump = 0; + state->has_to_dump = 1; state->base64 = 0; state->textplain = 0; state->texthtml = state->octetstream = 0; state->skip_html = 0; @@ -263,6 +266,11 @@ state->pushed_pointer = 0; + memset(state->filename, 0, TINYBUFSIZE); + memset(state->type, 0, TINYBUFSIZE); + + state->message_state = MSG_UNDEF; + return 0; } @@ -339,13 +347,13 @@ len = strlen(puf); - if(state->message_state == MSG_SUBJECT && strlen(state->b_subject) < MAXBUFSIZE-len-1) + if(state->message_state == MSG_SUBJECT && state->is_1st_header == 1 && strlen(state->b_subject) < MAXBUFSIZE-len-1) memcpy(&(state->b_subject[strlen(state->b_subject)]), puf, len); - else if(state->message_state == MSG_FROM && strchr(puf, '@') && strlen(state->b_from) < SMALLBUFSIZE-len-1) + else if(state->message_state == MSG_FROM && strchr(puf, '@') && state->is_1st_header == 1 && state->b_from[0] == '\0' && strlen(state->b_from) < SMALLBUFSIZE-len-1) memcpy(&(state->b_from[strlen(state->b_from)]), puf, len); - else if((state->message_state == MSG_TO || state->message_state == MSG_CC) && strchr(puf, '@') && strlen(state->b_to) < SMALLBUFSIZE-len-1) + else if((state->message_state == MSG_TO || state->message_state == MSG_CC) && state->is_1st_header == 1 && strchr(puf, '@') && strlen(state->b_to) < SMALLBUFSIZE-len-1) memcpy(&(state->b_to[strlen(state->b_to)]), puf, len); else if(state->message_state == MSG_BODY && strlen(state->b_body) < BIGBUFSIZE-len-1) diff --git a/src/parser_utils.c b/src/parser_utils.c index 3ba7bf4..3859084 100644 --- a/src/parser_utils.c +++ b/src/parser_utils.c @@ -27,6 +27,7 @@ state->line_num = 0; state->is_header = 1; + state->is_1st_header = 1; state->textplain = 1; /* by default we are a text/plain message */ state->texthtml = 0; @@ -47,18 +48,20 @@ memset(state->message_id, 0, SMALLBUFSIZE); memset(state->miscbuf, 0, MAX_TOKEN_LEN); + memset(state->filename, 0, TINYBUFSIZE); + memset(state->type, 0, TINYBUFSIZE); + state->has_to_dump = 0; state->fd = -1; state->mfd = -1; state->realbinary = 0; state->octetstream = 0; - state->pushed_pointer = 1; + state->pushed_pointer = 0; state->saved_size = 0; state->boundaries = NULL; state->n_attachments = 0; - state->has_base64 = 0; for(i=0; iattachments[i].size = 0; diff --git a/src/piler.c b/src/piler.c index 4b0b945..e906282 100644 --- a/src/piler.c +++ b/src/piler.c @@ -111,25 +111,6 @@ } -int read_key(struct __config *cfg){ - int fd, n; - - fd = open(KEYFILE, O_RDONLY); - if(fd == -1){ - syslog(LOG_PRIORITY, "cannot read keyfile: %s", KEYFILE); - return -1; - } - - n = read(fd, cfg->key, KEYLEN); - - close(fd); - - if(n > 5) return 0; - - return 1; -} - - int main(int argc, char **argv){ int i, new_sd, yes=1, pid, daemonise=0; unsigned int clen; diff --git a/src/piler.h b/src/piler.h index 57687a7..2eab6c4 100644 --- a/src/piler.h +++ b/src/piler.h @@ -26,6 +26,8 @@ #include "memc.h" #endif +int read_key(struct __config *cfg); + int do_av_check(struct session_data *sdata, char *rcpttoemail, char *fromemail, char *virusinfo, struct __data *data, struct __config *cfg); int make_body_digest(struct session_data *sdata, struct __config *cfg); diff --git a/src/pilerdecrypt.c b/src/pilerdecrypt.c new file mode 100644 index 0000000..65a560a --- /dev/null +++ b/src/pilerdecrypt.c @@ -0,0 +1,74 @@ +/* + * pilerdecrypt.c, SJ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +char *configfile = CONFIG_FILE; + + +int main(int argc, char **argv){ + int fd, n, olen, tlen; + unsigned char inbuf[BIGBUFSIZE], outbuf[BIGBUFSIZE+EVP_MAX_BLOCK_LENGTH]; + EVP_CIPHER_CTX ctx; + struct __config cfg; + + cfg = read_config(configfile); + + if(read_key(&cfg)){ + printf("%s\n", ERR_READING_KEY); + return 1; + } + + + EVP_CIPHER_CTX_init(&ctx); + EVP_DecryptInit_ex(&ctx, EVP_bf_cbc(), NULL, cfg.key, cfg.iv); + + if(argc != 2){ + printf("usage: $0 \n"); + return 1; + } + + fd = open(argv[1], O_RDONLY); + if(fd == -1){ + printf("error reading file: %s\n", argv[0]); + return 1; + } + + + while((n = read(fd, inbuf, sizeof(inbuf)))){ + bzero(&outbuf, sizeof(outbuf)); + + if(EVP_DecryptUpdate(&ctx, outbuf, &olen, inbuf, n) != 1){ + return 0; + } + + if(EVP_DecryptFinal(&ctx, outbuf + olen, &tlen) != 1){ + return 0; + } + + olen += tlen; + + write(1, outbuf, olen); + } + + EVP_CIPHER_CTX_cleanup(&ctx); + + close(fd); + + return 0; +} diff --git a/src/session.c b/src/session.c index a6e9c7b..58e90d9 100644 --- a/src/session.c +++ b/src/session.c @@ -85,10 +85,10 @@ memcpy(last2buf+prevlen, puf, MAXBUFSIZE); - if(sdata.hdr_len == 0){ + /*if(sdata.hdr_len == 0){ sdata.hdr_len = searchStringInBuffer(last2buf, 2*MAXBUFSIZE+1, "\n\r\n", 3); if(sdata.hdr_len == 0) searchStringInBuffer(last2buf, 2*MAXBUFSIZE+1, "\n\n", 2); - } + }*/ pos = searchStringInBuffer(last2buf, 2*MAXBUFSIZE+1, SMTP_CMD_PERIOD, 5); if(pos > 0){ @@ -106,7 +106,7 @@ /* fix posistion! */ pos += strlen(SMTP_CMD_PERIOD); - if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: got: (.), header length=%d", sdata.ttmpfile, sdata.hdr_len); + if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: got: (.)", sdata.ttmpfile); state = SMTP_STATE_PERIOD; @@ -146,6 +146,7 @@ sdata.need_scan = 1; + digest_file(sdata.ttmpfile, sdata.digest); make_body_digest(&sdata, cfg); #ifdef HAVE_ANTIVIRUS @@ -191,7 +192,7 @@ arule = check_againt_ruleset(data->rules, sstate.b_from, sstate.b_to, sstate.b_subject, sdata.tot_len); if(arule){ - syslog(LOG_PRIORITY, "%s: discard message by policy: *%s*", sdata.ttmpfile, arule); + syslog(LOG_PRIORITY, "%s: discarding message by policy: *%s*", sdata.ttmpfile, arule); inj = OK; } else { diff --git a/src/store.c b/src/store.c index 92bea7e..6108816 100644 --- a/src/store.c +++ b/src/store.c @@ -19,6 +19,25 @@ #include +int read_key(struct __config *cfg){ + int fd, n; + + fd = open(KEYFILE, O_RDONLY); + if(fd == -1){ + syslog(LOG_PRIORITY, "cannot read keyfile: %s", KEYFILE); + return -1; + } + + n = read(fd, cfg->key, KEYLEN); + + close(fd); + + if(n > 5) return 0; + + return 1; +} + + int store_file(struct session_data *sdata, char *filename, int startpos, int len, struct __config *cfg){ int ret=0, rc, fd, n; char *addr, *p, *p0, *p1, *p2, s[SMALLBUFSIZE]; @@ -35,11 +54,15 @@ fd = open(filename, O_RDONLY); - if(fd == -1) return ret; + if(fd == -1){ + syslog(LOG_PRIORITY, "%s: cannot open: %s", sdata->ttmpfile, filename); + return ret; + } if(len == 0){ if(fstat(fd, &st)) return ret; len = st.st_size; + if(len == 0) return 1; } gettimeofday(&tv1, &tz); @@ -55,6 +78,7 @@ if(z == NULL){ munmap(addr, len); + syslog(LOG_PRIORITY, "%s: cannot malloc for z buffer", sdata->ttmpfile); return ret; } @@ -116,13 +140,20 @@ *p0 = '/'; fd = open(s, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP); - if(fd == -1) goto ENDE; + if(fd == -1){ + syslog(LOG_PRIORITY, "%s: cannot open: %s", sdata->ttmpfile, s); + goto ENDE; + } + n = write(fd, outbuf, outlen); if(n == outlen){ ret = 1; } + else { + syslog(LOG_PRIORITY, "%s: cannot write %d bytes (only %d)", sdata->ttmpfile, outlen, n); + } fsync(fd); diff --git a/src/test.c b/src/test.c index 9f49baf..45ce124 100644 --- a/src/test.c +++ b/src/test.c @@ -16,7 +16,7 @@ int main(int argc, char **argv){ - int rc; + int i, rc; struct stat st; struct session_data sdata; struct _state state; @@ -49,7 +49,6 @@ data.rules = NULL; - load_archiving_rules(&sdata, &(data.rules)); rc = 0; @@ -62,6 +61,7 @@ snprintf(sdata.ttmpfile, SMALLBUFSIZE-1, "%s", argv[1]); snprintf(sdata.tmpframe, SMALLBUFSIZE-1, "%s.m", argv[1]); + state = parse_message(&sdata, &cfg); printf("message-id: %s\n", state.message_id); @@ -73,14 +73,18 @@ make_body_digest(&sdata, &cfg); rule = check_againt_ruleset(data.rules, state.b_from, state.b_to, state.b_subject, st.st_size); - printf("body digest: %s\n", sdata.bodydigest); + //printf("body digest: %s\n", sdata.bodydigest); - printf("rules check: %s\n", rule); + //printf("rules check: %s\n", rule); mysql_close(&(sdata.mysql)); free_rule(data.rules); + for(i=1; i<=state.n_attachments; i++){ + printf("i:%d, name=*%s*, type: *%s*, size: %d, int.name: %s, digest: %s\n", i, state.attachments[i].filename, state.attachments[i].type, state.attachments[i].size, state.attachments[i].internalname, state.attachments[i].digest); + } + printf("\n\n"); return 0; diff --git a/util/db-mysql.sql b/util/db-mysql.sql index 09d945e..9f04ee9 100644 --- a/util/db-mysql.sql +++ b/util/db-mysql.sql @@ -32,8 +32,10 @@ `deleted` int default 0, `size` int default 0, `hlen` int default 0, + `attachments` int default 0, `piler_id` char(36) not null, `message_id` char(128) character set 'latin1' not null, + `digest` char(64) not null, `bodydigest` char(64) not null, primary key (`id`), unique(`to`,`message_id`) ) Engine=InnoDB;