diff --git a/configure b/configure index c69742c..f6b356d 100755 --- a/configure +++ b/configure @@ -4147,7 +4147,7 @@ CFLAGS="$static -O2 -Wall -g" LIBS="$antispam_libs $sunos_libs " -OBJS="dirs.o misc.o counters.o cfg.o sig.o decoder.o list.o parser.o parser_utils.o rules.o session.o message.o attachment.o digest.o store.o tai.o $objs" +OBJS="dirs.o misc.o counters.o cfg.o sig.o decoder.o list.o parser.o parser_utils.o rules.o session.o message.o attachment.o digest.o store.o archive.o tai.o $objs" ac_config_files="$ac_config_files Makefile src/Makefile etc/Makefile" diff --git a/configure.in b/configure.in index 07b6ce0..fa11593 100644 --- a/configure.in +++ b/configure.in @@ -271,7 +271,7 @@ CFLAGS="$static -O2 -Wall -g" LIBS="$antispam_libs $sunos_libs " -OBJS="dirs.o misc.o counters.o cfg.o sig.o decoder.o list.o parser.o parser_utils.o rules.o session.o message.o attachment.o digest.o store.o tai.o $objs" +OBJS="dirs.o misc.o counters.o cfg.o sig.o decoder.o list.o parser.o parser_utils.o rules.o session.o message.o attachment.o digest.o store.o archive.o tai.o $objs" AC_CONFIG_FILES([Makefile src/Makefile etc/Makefile]) AC_OUTPUT diff --git a/etc/Makefile b/etc/Makefile deleted file mode 100644 index e8db8c4..0000000 --- a/etc/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -SHELL = /bin/bash - -prefix = /usr/local -exec_prefix = ${prefix} -bindir = ${exec_prefix}/bin -sbindir = ${exec_prefix}/sbin -includedir = ${prefix}/include -libdir = ${exec_prefix}/lib -libexecdir = ${exec_prefix}/libexec -srcdir = . -sysconfdir = ${prefix}/etc -mandir = ${datarootdir}/man -datarootdir = ${prefix}/share -localstatedir = /var - -CC = gcc -CFLAGS = -O2 -Wall -g -DEFS = -DHAVE_MYSQL -D_GNU_SOURCE -DHAVE_ANTISPAM -DUSERS_IN_MYSQL -DHAVE_USERS -DNEED_MYSQL -INCDIR = -I. -I../.. -I../../src -I/usr/include/mysql -DBIG_JOINS=1 -fno-strict-aliasing -DUNIV_LINUX -DUNIV_LINUX -LIBDIR = -L. -L../../src -LIBS = -lm -ldl -rdynamic -L/usr/lib/mysql -lmysqlclient_r -LDAP_LIBS = -CLAPF_USER = clapf -CLAPF_GROUP = `id -gn $(CLAPF_USER)` - -INSTALL = /usr/bin/install -c - -all: - sed -e 's%pidfile=.*%pidfile=$(localstatedir)/run/clapf/clapf.pid%g' \ - -e 's%sqlite3=.*%sqlite3=$(localstatedir)/lib/clapf/data/tokens.sdb%g' \ - -e 's%workdir=.*%workdir=$(localstatedir)/spool/clapf/tmp%g' \ - -e 's%queuedir=.*%queuedir=$(localstatedir)/lib/clapf/queue%g' \ - -e 's%mydbfile=.*%mydbfile=$(localstatedir)/lib/clapf/tokens.mydb%g' < $(srcdir)/example.conf > $(srcdir)/clapf.conf - - sed -e 's%LOCALSTATEDIR%$(localstatedir)%g' \ - -e 's%LIBEXECDIR%$(libexecdir)%g' \ - -e 's%SYSCONFDIR%$(sysconfdir)%g' \ - -e 's%SBINDIR%$(sbindir)%g' \ - -e 's%DATAROOTDIR%$(datarootdir)%g' < $(srcdir)/cron.jobs.in > $(srcdir)/cron.jobs - -install: - if [ ! -f "$(DESTDIR)$(sysconfdir)/clapf.conf" ]; then $(INSTALL) -m 0640 $(srcdir)/clapf.conf $(DESTDIR)$(sysconfdir)/clapf.conf; chgrp $(CLAPF_GROUP) $(DESTDIR)$(sysconfdir)/clapf.conf; fi - -clean: - rm -f clapf.conf cron.jobs - -distclean: clean - rm -f Makefile diff --git a/src/Makefile.in b/src/Makefile.in index bee051f..d210b9f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -48,8 +48,8 @@ ln -sf libpiler.so.$(LIBPILER_VERSION) libpiler.so.$(PILER_VERSION) -pilerget: pilerget.c cfg.o misc.o tai.o store.o attachment.o digest.o - $(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $^ $(LIBS) $(LIBDIR) +pilerget: pilerget.c libpiler.a + $(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $^ -lpiler $(LIBS) $(LIBDIR) pilerimport: pilerimport.c libpiler.a $(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $^ -lpiler $(LIBS) $(LIBDIR) diff --git a/src/archive.c b/src/archive.c new file mode 100644 index 0000000..7dc6ed1 --- /dev/null +++ b/src/archive.c @@ -0,0 +1,263 @@ +/* + * archive.c, SJ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +void zerr(int ret){ + + fputs("zpipe: ", stderr); + + switch (ret) { + case Z_ERRNO: + fputs("I/O error\n", stderr); + break; + + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + + + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + break; + + } +} + + +int inf(unsigned char *in, int len, int mode, char **buffer, FILE *dest){ + int ret, pos=0; + unsigned have; + z_stream strm; + char *new_ptr; + unsigned char out[REALLYBIGBUFSIZE]; + + /* allocate inflate state */ + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + + + if(ret != Z_OK) return ret; + + strm.avail_in = len; + strm.next_in = in; + + if(mode == WRITE_TO_BUFFER){ + *buffer = malloc(REALLYBIGBUFSIZE); + if(!*buffer) return Z_MEM_ERROR; + memset(*buffer, 0, REALLYBIGBUFSIZE); + } + + + do { + strm.avail_out = REALLYBIGBUFSIZE; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return ret; + } + + have = REALLYBIGBUFSIZE - strm.avail_out; + + /* + * write the uncompressed result either to stdout + * or to the buffer + */ + + if(mode == WRITE_TO_STDOUT){ + if(fwrite(out, 1, have, dest) != have){ + (void)inflateEnd(&strm); + return Z_ERRNO; + } + } + else { + memcpy(*buffer+pos, out, have); + pos += have; + new_ptr = realloc(*buffer, pos+REALLYBIGBUFSIZE); + if(!new_ptr){ + (void)inflateEnd(&strm); + return Z_MEM_ERROR; + } + *buffer = new_ptr; + memset(*buffer+pos, 0, REALLYBIGBUFSIZE); + } + + + } while (strm.avail_out == 0); + + + (void)inflateEnd(&strm); + + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + + +int retrieve_file_from_archive(char *filename, int mode, char **buffer, FILE *dest, struct __config *cfg){ + int rc=0, n, olen, tlen, len, fd=-1; + unsigned char *s=NULL, inbuf[REALLYBIGBUFSIZE]; + struct stat st; + EVP_CIPHER_CTX ctx; + + + if(filename == NULL) return 1; + + + fd = open(filename, O_RDONLY); + if(fd == -1){ + printf("error reading file: %s\n", filename); + return 1; + } + + + if(fstat(fd, &st)){ + printf("cannot fstat() on %s\n", filename); + close(fd); + return 1; + } + + + EVP_CIPHER_CTX_init(&ctx); + EVP_DecryptInit_ex(&ctx, EVP_bf_cbc(), NULL, cfg->key, cfg->iv); + + len = st.st_size+EVP_MAX_BLOCK_LENGTH; + + s = malloc(len); + + if(!s){ + printf("malloc()\n"); + goto CLEANUP; + } + + + tlen = 0; + + while((n = read(fd, inbuf, sizeof(inbuf)))){ + + if(!EVP_DecryptUpdate(&ctx, s+tlen, &olen, inbuf, n)){ + printf("EVP_DecryptUpdate()\n"); + goto CLEANUP; + } + + tlen += olen; + } + + + if(EVP_DecryptFinal(&ctx, s + tlen, &olen) != 1){ + printf("EVP_DecryptFinal()\n"); + goto CLEANUP; + } + + + tlen += olen; + + + rc = inf(s, tlen, mode, buffer, dest); + if(rc != Z_OK) zerr(rc); + + +CLEANUP: + if(fd != -1) close(fd); + if(s) free(s); + EVP_CIPHER_CTX_cleanup(&ctx); + + return 0; +} + + +int retrieve_email_from_archive(struct session_data *sdata, FILE *dest, struct __config *cfg){ + int i, rc, attachments; + char *buffer=NULL, *saved_buffer, *p, filename[SMALLBUFSIZE], pointer[SMALLBUFSIZE]; + struct ptr_array ptr_arr[MAX_ATTACHMENTS]; + + if(strlen(sdata->ttmpfile) != RND_STR_LEN){ + printf("invalid piler-id: %s\n", sdata->ttmpfile); + return 1; + } + + attachments = query_attachments(sdata, &ptr_arr[0], cfg); + + if(attachments == -1){ + printf("problem querying the attachment of %s\n", sdata->ttmpfile); + return 1; + } + + snprintf(filename, sizeof(filename)-1, "%s/%c%c/%c%c/%c%c/%s.m", cfg->queuedir, *(sdata->ttmpfile+RND_STR_LEN-6), *(sdata->ttmpfile+RND_STR_LEN-5), *(sdata->ttmpfile+RND_STR_LEN-4), *(sdata->ttmpfile+RND_STR_LEN-3), *(sdata->ttmpfile+RND_STR_LEN-2), *(sdata->ttmpfile+RND_STR_LEN-1), sdata->ttmpfile); + + if(attachments == 0){ + rc = retrieve_file_from_archive(filename, WRITE_TO_STDOUT, &buffer, dest, cfg); + } + else { + rc = retrieve_file_from_archive(filename, WRITE_TO_BUFFER, &buffer, dest, cfg); + + if(buffer){ + saved_buffer = buffer; + + for(i=1; i<=attachments; i++){ + snprintf(pointer, sizeof(pointer)-1, "ATTACHMENT_POINTER_%s.a%d_XXX_PILER", sdata->ttmpfile, i); + + p = strstr(buffer, pointer); + if(p){ + *p = '\0'; + fwrite(buffer, 1, p - buffer, dest); + buffer = p + strlen(pointer); + + if(strlen(ptr_arr[i].piler_id) == RND_STR_LEN){ + snprintf(filename, sizeof(filename)-1, "%s/%c%c/%c%c/%c%c/%s.a%d", cfg->queuedir, ptr_arr[i].piler_id[RND_STR_LEN-6], ptr_arr[i].piler_id[RND_STR_LEN-5], ptr_arr[i].piler_id[RND_STR_LEN-4], ptr_arr[i].piler_id[RND_STR_LEN-3], ptr_arr[i].piler_id[RND_STR_LEN-2], ptr_arr[i].piler_id[RND_STR_LEN-1], ptr_arr[i].piler_id, ptr_arr[i].attachment_id); + + rc = retrieve_file_from_archive(filename, WRITE_TO_STDOUT, NULL, dest, cfg); + } + } + + } + + if(buffer){ + fwrite(buffer, 1, strlen(buffer), dest); + } + + buffer = saved_buffer; + free(buffer); + } + } + + return 0; +} + + diff --git a/src/config.h b/src/config.h index aeddeb6..a47352d 100644 --- a/src/config.h +++ b/src/config.h @@ -31,6 +31,7 @@ #define MAXBUFSIZE 8192 #define SMALLBUFSIZE 512 #define BIGBUFSIZE 65536 +#define REALLYBIGBUFSIZE 524288 #define TINYBUFSIZE 128 #define MAXVAL 256 #define RANDOM_POOL "/dev/urandom" @@ -99,5 +100,8 @@ #define DIRECTION_OUTGOING 2 #define DIRECTION_INTERNAL_AND_OUTGOING 3 +#define WRITE_TO_STDOUT 0 +#define WRITE_TO_BUFFER 1 + #endif /* _CONFIG_H */ diff --git a/src/piler.h b/src/piler.h index 5c14e7d..8b6ed55 100644 --- a/src/piler.h +++ b/src/piler.h @@ -45,5 +45,8 @@ void update_counters(struct session_data *sdata, struct __data *data, struct __counters *counters, struct __config *cfg); +int retrieve_email_from_archive(struct session_data *sdata, FILE *dest, struct __config *cfg); + + #endif /* _PILER_H */ diff --git a/src/pilerget.c b/src/pilerget.c index 8fc1968..bda8655 100644 --- a/src/pilerget.c +++ b/src/pilerget.c @@ -13,263 +13,9 @@ #include #include #include -#include -#include -#include -#include #include -#define WRITE_TO_STDOUT 0 -#define WRITE_TO_BUFFER 1 -#define REALLYBIGBUFSIZE 524288 - -int fd=-1; -EVP_CIPHER_CTX ctx; -unsigned char *s=NULL; - - -void clean_exit(){ - if(s) free(s); - - EVP_CIPHER_CTX_cleanup(&ctx); - - if(fd != -1) close(fd); - - exit(0); -} - - -void zerr(int ret){ - fputs("zpipe: ", stderr); - switch (ret) { - case Z_ERRNO: - if (ferror(stdin)) - fputs("error reading stdin\n", stderr); - if (ferror(stdout)) - fputs("error writing stdout\n", stderr); - break; - case Z_STREAM_ERROR: - fputs("invalid compression level\n", stderr); - break; - case Z_DATA_ERROR: - fputs("invalid or incomplete deflate data\n", stderr); - break; - case Z_MEM_ERROR: - fputs("out of memory\n", stderr); - break; - case Z_VERSION_ERROR: - fputs("zlib version mismatch!\n", stderr); - } -} - - -int inf(unsigned char *in, int len, int mode, char **buffer, FILE *dest){ - int ret, pos=0; - unsigned have; - z_stream strm; - char *new_ptr; - unsigned char out[REALLYBIGBUFSIZE]; - - /* allocate inflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - ret = inflateInit(&strm); - - - if(ret != Z_OK) return ret; - - strm.avail_in = len; - strm.next_in = in; - - if(mode == WRITE_TO_BUFFER){ - *buffer = malloc(REALLYBIGBUFSIZE); - if(!*buffer) return Z_MEM_ERROR; - memset(*buffer, 0, REALLYBIGBUFSIZE); - } - - - do { - strm.avail_out = REALLYBIGBUFSIZE; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - switch (ret) { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; /* and fall through */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - (void)inflateEnd(&strm); - return ret; - } - - have = REALLYBIGBUFSIZE - strm.avail_out; - - /* - * write the uncompressed result either to stdout - * or to the buffer - */ - - if(mode == WRITE_TO_STDOUT){ - if(fwrite(out, 1, have, dest) != have){ - (void)inflateEnd(&strm); - return Z_ERRNO; - } - } - else { - memcpy(*buffer+pos, out, have); - pos += have; - new_ptr = realloc(*buffer, pos+REALLYBIGBUFSIZE); - if(!new_ptr){ - (void)inflateEnd(&strm); - return Z_MEM_ERROR; - } - *buffer = new_ptr; - memset(*buffer+pos, 0, REALLYBIGBUFSIZE); - } - - - } while (strm.avail_out == 0); - - - (void)inflateEnd(&strm); - - return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; -} - - -int retrieve_file_from_archive(char *filename, int mode, char **buffer, FILE *dest, struct __config *cfg){ - int rc=0, n, olen, tlen, len; - unsigned char inbuf[REALLYBIGBUFSIZE]; - struct stat st; - - - if(filename == NULL) return 1; - - - fd = open(filename, O_RDONLY); - if(fd == -1){ - printf("error reading file: %s\n", filename); - return 1; - } - - - if(fstat(fd, &st)){ - perror("fstat()"); - close(fd); - return 1; - } - - - EVP_CIPHER_CTX_init(&ctx); - EVP_DecryptInit_ex(&ctx, EVP_bf_cbc(), NULL, cfg->key, cfg->iv); - - len = st.st_size+EVP_MAX_BLOCK_LENGTH; - - s = malloc(len); - - if(!s){ - perror("malloc"); - clean_exit(); - } - - - tlen = 0; - - while((n = read(fd, inbuf, sizeof(inbuf)))){ - - if(!EVP_DecryptUpdate(&ctx, s+tlen, &olen, inbuf, n)){ - printf("EVP_DecryptUpdate()\n"); - clean_exit(); - } - - tlen += olen; - } - - close(fd); - - if(EVP_DecryptFinal(&ctx, s + tlen, &olen) != 1){ - printf("EVP_DecryptFinal()\n"); - clean_exit(); - } - - EVP_CIPHER_CTX_cleanup(&ctx); - - tlen += olen; - - - rc = inf(s, tlen, mode, buffer, dest); - if(rc != Z_OK) zerr(rc); - - - if(s) free(s); - - return 0; -} - - -int retrieve_email_from_archive(struct session_data *sdata, FILE *dest, struct __config *cfg){ - int i, rc, attachments; - char *buffer=NULL, *saved_buffer, *p, filename[SMALLBUFSIZE], pointer[SMALLBUFSIZE]; - struct ptr_array ptr_arr[MAX_ATTACHMENTS]; - - if(strlen(sdata->ttmpfile) != RND_STR_LEN){ - printf("invalid piler-id: %s\n", sdata->ttmpfile); - return 1; - } - - attachments = query_attachments(sdata, &ptr_arr[0], cfg); - - if(attachments == -1){ - printf("problem querying the attachment of %s\n", sdata->ttmpfile); - return 1; - } - - snprintf(filename, sizeof(filename)-1, "%s/%c%c/%c%c/%c%c/%s.m", cfg->queuedir, *(sdata->ttmpfile+RND_STR_LEN-6), *(sdata->ttmpfile+RND_STR_LEN-5), *(sdata->ttmpfile+RND_STR_LEN-4), *(sdata->ttmpfile+RND_STR_LEN-3), *(sdata->ttmpfile+RND_STR_LEN-2), *(sdata->ttmpfile+RND_STR_LEN-1), sdata->ttmpfile); - - if(attachments == 0){ - rc = retrieve_file_from_archive(filename, WRITE_TO_STDOUT, &buffer, dest, cfg); - } - else { - rc = retrieve_file_from_archive(filename, WRITE_TO_BUFFER, &buffer, dest, cfg); - - if(buffer){ - saved_buffer = buffer; - - for(i=1; i<=attachments; i++){ - snprintf(pointer, sizeof(pointer)-1, "ATTACHMENT_POINTER_%s.a%d_XXX_PILER", sdata->ttmpfile, i); - - p = strstr(buffer, pointer); - if(p){ - *p = '\0'; - fwrite(buffer, 1, p - buffer, dest); - buffer = p + strlen(pointer); - - if(strlen(ptr_arr[i].piler_id) == RND_STR_LEN){ - snprintf(filename, sizeof(filename)-1, "%s/%c%c/%c%c/%c%c/%s.a%d", cfg->queuedir, ptr_arr[i].piler_id[RND_STR_LEN-6], ptr_arr[i].piler_id[RND_STR_LEN-5], ptr_arr[i].piler_id[RND_STR_LEN-4], ptr_arr[i].piler_id[RND_STR_LEN-3], ptr_arr[i].piler_id[RND_STR_LEN-2], ptr_arr[i].piler_id[RND_STR_LEN-1], ptr_arr[i].piler_id, ptr_arr[i].attachment_id); - - rc = retrieve_file_from_archive(filename, WRITE_TO_STDOUT, NULL, dest, cfg); - } - } - - } - - if(buffer){ - fwrite(buffer, 1, strlen(buffer), dest); - } - - buffer = saved_buffer; - free(buffer); - } - } - - return 0; -} - uint64 get_id_by_piler_id(struct session_data *sdata, char *digest, char *bodydigest, struct __config *cfg){ char s[SMALLBUFSIZE];