mirror of
https://bitbucket.org/jsuto/piler.git
synced 2024-12-25 09:20:11 +01:00
added pilergetd daemon
This commit is contained in:
parent
d5d6741748
commit
2a94804586
2
configure
vendored
2
configure
vendored
@ -4634,7 +4634,7 @@ echo; echo
|
|||||||
|
|
||||||
CFLAGS="$static -O2 -Wall -g"
|
CFLAGS="$static -O2 -Wall -g"
|
||||||
LIBS="$antispam_libs $sunos_libs "
|
LIBS="$antispam_libs $sunos_libs "
|
||||||
OBJS="dirs.o base64.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 import.o imap.o pop3.o extract.o mydomains.o mysql.o $objs"
|
OBJS="dirs.o base64.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 import.o imap.o pop3.o extract.o mydomains.o retr.o mysql.o $objs"
|
||||||
|
|
||||||
ac_config_files="$ac_config_files Makefile src/Makefile etc/Makefile util/Makefile init.d/Makefile test/Makefile contrib/imap/Makefile"
|
ac_config_files="$ac_config_files Makefile src/Makefile etc/Makefile util/Makefile init.d/Makefile test/Makefile contrib/imap/Makefile"
|
||||||
|
|
||||||
|
@ -405,7 +405,7 @@ echo; echo
|
|||||||
|
|
||||||
CFLAGS="$static -O2 -Wall -g"
|
CFLAGS="$static -O2 -Wall -g"
|
||||||
LIBS="$antispam_libs $sunos_libs "
|
LIBS="$antispam_libs $sunos_libs "
|
||||||
OBJS="dirs.o base64.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 import.o imap.o pop3.o extract.o mydomains.o mysql.o $objs"
|
OBJS="dirs.o base64.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 import.o imap.o pop3.o extract.o mydomains.o retr.o mysql.o $objs"
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile src/Makefile etc/Makefile util/Makefile init.d/Makefile test/Makefile contrib/imap/Makefile])
|
AC_CONFIG_FILES([Makefile src/Makefile etc/Makefile util/Makefile init.d/Makefile test/Makefile contrib/imap/Makefile])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
@ -33,13 +33,16 @@ MAKE = `which make`
|
|||||||
|
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
|
|
||||||
all: libpiler.a piler pilerconf pilerget pileraget pilerimport pilerexport pilerpurge reindex test
|
all: libpiler.a piler pilerconf pilerget pilergetd pileraget pilerimport pilerexport pilerpurge reindex test
|
||||||
install: install-piler
|
install: install-piler
|
||||||
|
|
||||||
|
|
||||||
piler: piler.c libpiler.a
|
piler: piler.c libpiler.a
|
||||||
$(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR) @LDFLAGS@ @libclamav_extra_libs@
|
$(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR) @LDFLAGS@ @libclamav_extra_libs@
|
||||||
|
|
||||||
|
pilergetd: pilergetd.c libpiler.a
|
||||||
|
$(CC) $(CFLAGS) $(INCDIR) $(DEFS) -o $@ $< -lpiler $(LIBS) $(LIBDIR) @LDFLAGS@ @libclamav_extra_libs@
|
||||||
|
|
||||||
libpiler.a: $(OBJS) $(MYSQL_OBJS)
|
libpiler.a: $(OBJS) $(MYSQL_OBJS)
|
||||||
ar cr libpiler.a $(OBJS) $(MYSQL_OBJS)
|
ar cr libpiler.a $(OBJS) $(MYSQL_OBJS)
|
||||||
ranlib libpiler.a
|
ranlib libpiler.a
|
||||||
@ -83,6 +86,7 @@ install-piler:
|
|||||||
(cd $(DESTDIR)$(libdir) && ln -sf libpiler.so.$(LIBPILER_VERSION) libpiler.so.$(PILER_VERSION))
|
(cd $(DESTDIR)$(libdir) && ln -sf libpiler.so.$(LIBPILER_VERSION) libpiler.so.$(PILER_VERSION))
|
||||||
|
|
||||||
$(INSTALL) -m 0755 piler $(DESTDIR)$(sbindir)
|
$(INSTALL) -m 0755 piler $(DESTDIR)$(sbindir)
|
||||||
|
$(INSTALL) -m 0755 pilergetd $(DESTDIR)$(sbindir)
|
||||||
$(INSTALL) -m 0755 pilerconf $(DESTDIR)$(sbindir)
|
$(INSTALL) -m 0755 pilerconf $(DESTDIR)$(sbindir)
|
||||||
$(INSTALL) -m 6755 -o $(RUNNING_USER) -g $(RUNNING_GROUP) pilerget $(DESTDIR)$(bindir)
|
$(INSTALL) -m 6755 -o $(RUNNING_USER) -g $(RUNNING_GROUP) pilerget $(DESTDIR)$(bindir)
|
||||||
$(INSTALL) -m 6755 -o $(RUNNING_USER) -g $(RUNNING_GROUP) pileraget $(DESTDIR)$(bindir)
|
$(INSTALL) -m 6755 -o $(RUNNING_USER) -g $(RUNNING_GROUP) pileraget $(DESTDIR)$(bindir)
|
||||||
@ -92,7 +96,7 @@ install-piler:
|
|||||||
$(INSTALL) -m 6755 -o $(RUNNING_USER) -g $(RUNNING_GROUP) reindex $(DESTDIR)$(bindir)
|
$(INSTALL) -m 6755 -o $(RUNNING_USER) -g $(RUNNING_GROUP) reindex $(DESTDIR)$(bindir)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.a libpiler.so* piler pilerconf pilerget pileraget pilerimport pilerexport pilerpurge pilertest reindex
|
rm -f *.o *.a libpiler.so* piler pilerconf pilerget pilergetd pileraget pilerimport pilerexport pilerpurge pilertest reindex
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f Makefile
|
rm -f Makefile
|
||||||
|
@ -209,6 +209,82 @@ CLEANUP:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int file_from_archive_to_network(char *filename, int sd, struct __data *data, struct __config *cfg){
|
||||||
|
int n, olen, tlen, len, fd=-1;
|
||||||
|
unsigned char *s=NULL, *addr=NULL, inbuf[REALLYBIGBUFSIZE];
|
||||||
|
struct stat st;
|
||||||
|
EVP_CIPHER_CTX ctx;
|
||||||
|
|
||||||
|
|
||||||
|
if(filename == NULL) return 1;
|
||||||
|
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if(fd == -1){
|
||||||
|
syslog(LOG_PRIORITY, "%s: cannot open()", filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(fstat(fd, &st)){
|
||||||
|
syslog(LOG_PRIORITY, "%s: cannot fstat()", filename);
|
||||||
|
close(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(cfg->encrypt_messages == 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){
|
||||||
|
syslog(LOG_PRIORITY, "error: malloc(), '%s'", filename);
|
||||||
|
goto CLEANUP2;
|
||||||
|
}
|
||||||
|
|
||||||
|
tlen = 0;
|
||||||
|
|
||||||
|
while((n = read(fd, inbuf, sizeof(inbuf)))){
|
||||||
|
|
||||||
|
if(!EVP_DecryptUpdate(&ctx, s+tlen, &olen, inbuf, n)){
|
||||||
|
syslog(LOG_PRIORITY, "%s: EVP_DecryptUpdate()", filename);
|
||||||
|
goto CLEANUP2;
|
||||||
|
}
|
||||||
|
|
||||||
|
tlen += olen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(EVP_DecryptFinal(&ctx, s + tlen, &olen) != 1){
|
||||||
|
syslog(LOG_PRIORITY, "%s: EVP_DecryptFinal()", filename);
|
||||||
|
goto CLEANUP2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tlen += olen;
|
||||||
|
write1(sd, s, tlen, 1, data->ssl);
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
write1(sd, addr, st.st_size, 1, data->ssl);
|
||||||
|
munmap(addr, st.st_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CLEANUP2:
|
||||||
|
if(fd != -1) close(fd);
|
||||||
|
if(s) free(s);
|
||||||
|
if(cfg->encrypt_messages == 1) EVP_CIPHER_CTX_cleanup(&ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int retrieve_email_from_archive(struct session_data *sdata, struct __data *data, FILE *dest, struct __config *cfg){
|
int retrieve_email_from_archive(struct session_data *sdata, struct __data *data, FILE *dest, struct __config *cfg){
|
||||||
int i, attachments;
|
int i, attachments;
|
||||||
char *buffer=NULL, *saved_buffer, *p, filename[SMALLBUFSIZE], pointer[SMALLBUFSIZE];
|
char *buffer=NULL, *saved_buffer, *p, filename[SMALLBUFSIZE], pointer[SMALLBUFSIZE];
|
||||||
|
@ -90,6 +90,9 @@ struct _parse_rule config_parse_rules[] =
|
|||||||
{ "pemfile", "string", (void*) string_parser, offsetof(struct __config, pemfile), "", MAXVAL-1},
|
{ "pemfile", "string", (void*) string_parser, offsetof(struct __config, pemfile), "", MAXVAL-1},
|
||||||
{ "pidfile", "string", (void*) string_parser, offsetof(struct __config, pidfile), PIDFILE, MAXVAL-1},
|
{ "pidfile", "string", (void*) string_parser, offsetof(struct __config, pidfile), PIDFILE, MAXVAL-1},
|
||||||
{ "piler_header_field", "string", (void*) string_parser, offsetof(struct __config, piler_header_field), "", MAXVAL-1},
|
{ "piler_header_field", "string", (void*) string_parser, offsetof(struct __config, piler_header_field), "", MAXVAL-1},
|
||||||
|
{ "pilergetd_listen_addr", "string", (void*) string_parser, offsetof(struct __config, pilergetd_listen_addr), "127.0.0.1", MAXVAL-1},
|
||||||
|
{ "pilergetd_listen_port", "integer", (void*) int_parser, offsetof(struct __config, pilergetd_listen_port), "10026", sizeof(int)},
|
||||||
|
{ "pilergetd_pidfile", "string", (void*) string_parser, offsetof(struct __config, pilergetd_pidfile), PILERGETD_PIDFILE, MAXVAL-1},
|
||||||
{ "queuedir", "string", (void*) string_parser, offsetof(struct __config, queuedir), QUEUE_DIR, MAXVAL-1},
|
{ "queuedir", "string", (void*) string_parser, offsetof(struct __config, queuedir), QUEUE_DIR, MAXVAL-1},
|
||||||
{ "server_id", "integer", (void*) int_parser, offsetof(struct __config, server_id), "0", sizeof(int)},
|
{ "server_id", "integer", (void*) int_parser, offsetof(struct __config, server_id), "0", sizeof(int)},
|
||||||
{ "session_timeout", "integer", (void*) int_parser, offsetof(struct __config, session_timeout), "420", sizeof(int)},
|
{ "session_timeout", "integer", (void*) int_parser, offsetof(struct __config, session_timeout), "420", sizeof(int)},
|
||||||
|
@ -13,10 +13,14 @@ struct __config {
|
|||||||
|
|
||||||
char hostid[MAXVAL];
|
char hostid[MAXVAL];
|
||||||
char pidfile[MAXVAL];
|
char pidfile[MAXVAL];
|
||||||
|
char pilergetd_pidfile[MAXVAL];
|
||||||
|
|
||||||
char listen_addr[MAXVAL];
|
char listen_addr[MAXVAL];
|
||||||
int listen_port;
|
int listen_port;
|
||||||
|
|
||||||
|
char pilergetd_listen_addr[MAXVAL];
|
||||||
|
int pilergetd_listen_port;
|
||||||
|
|
||||||
char clamd_addr[MAXVAL];
|
char clamd_addr[MAXVAL];
|
||||||
int clamd_port;
|
int clamd_port;
|
||||||
char clamd_socket[MAXVAL];
|
char clamd_socket[MAXVAL];
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
#define PROGNAME "piler"
|
#define PROGNAME "piler"
|
||||||
#define PILERGETD_PROGNAME "pilergetd"
|
#define PILERGETD_PROGNAME "pilergetd"
|
||||||
|
|
||||||
#define VERSION "0.1.23"
|
#define VERSION "0.1.24-master-branch"
|
||||||
|
|
||||||
#define BUILD 789
|
#define BUILD 791
|
||||||
|
|
||||||
#define HOSTID "mailarchiver"
|
#define HOSTID "mailarchiver"
|
||||||
|
|
||||||
|
10
src/imap.c
10
src/imap.c
@ -81,7 +81,7 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
|
|||||||
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "\r\nA%d OK", (*seq)++);
|
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "\r\nA%d OK", (*seq)++);
|
||||||
snprintf(buf, sizeof(buf)-1, "%s SELECT \"%s\"\r\n", tag, folder);
|
snprintf(buf, sizeof(buf)-1, "%s SELECT \"%s\"\r\n", tag, folder);
|
||||||
|
|
||||||
n = write1(sd, buf, use_ssl, data->ssl);
|
n = write1(sd, buf, strlen(buf), use_ssl, data->ssl);
|
||||||
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
||||||
|
|
||||||
if(!strstr(buf, tagok)){
|
if(!strstr(buf, tagok)){
|
||||||
@ -124,7 +124,7 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
n = write1(sd, buf, use_ssl, data->ssl);
|
n = write1(sd, buf, strlen(buf), use_ssl, data->ssl);
|
||||||
|
|
||||||
readlen = 0;
|
readlen = 0;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
@ -240,14 +240,14 @@ int connect_to_imap_server(int sd, int *seq, char *username, char *password, int
|
|||||||
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "A%d OK", (*seq)++);
|
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "A%d OK", (*seq)++);
|
||||||
snprintf(buf, sizeof(buf)-1, "%s CAPABILITY\r\n", tag);
|
snprintf(buf, sizeof(buf)-1, "%s CAPABILITY\r\n", tag);
|
||||||
|
|
||||||
write1(sd, buf, use_ssl, data->ssl);
|
write1(sd, buf, strlen(buf), use_ssl, data->ssl);
|
||||||
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
||||||
|
|
||||||
|
|
||||||
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "A%d OK", (*seq)++);
|
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "A%d OK", (*seq)++);
|
||||||
snprintf(buf, sizeof(buf)-1, "%s LOGIN %s \"%s\"\r\n", tag, username, password);
|
snprintf(buf, sizeof(buf)-1, "%s LOGIN %s \"%s\"\r\n", tag, username, password);
|
||||||
|
|
||||||
write1(sd, buf, use_ssl, data->ssl);
|
write1(sd, buf, strlen(buf), use_ssl, data->ssl);
|
||||||
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
||||||
|
|
||||||
if(strncmp(buf, tagok, strlen(tagok))){
|
if(strncmp(buf, tagok, strlen(tagok))){
|
||||||
@ -281,7 +281,7 @@ int list_folders(int sd, int *seq, char *folders, int foldersize, int use_ssl, s
|
|||||||
//snprintf(puf, sizeof(puf)-1, "%s LIST \"\" %%\r\n", tag);
|
//snprintf(puf, sizeof(puf)-1, "%s LIST \"\" %%\r\n", tag);
|
||||||
snprintf(puf, sizeof(puf)-1, "%s LIST \"\" \"*\"\r\n", tag);
|
snprintf(puf, sizeof(puf)-1, "%s LIST \"\" \"*\"\r\n", tag);
|
||||||
|
|
||||||
write1(sd, puf, use_ssl, data->ssl);
|
write1(sd, puf, strlen(puf), use_ssl, data->ssl);
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
n = recvtimeoutssl(sd, puf, sizeof(puf), 10, use_ssl, data->ssl);
|
n = recvtimeoutssl(sd, puf, sizeof(puf), 10, use_ssl, data->ssl);
|
||||||
|
12
src/misc.c
12
src/misc.c
@ -302,13 +302,13 @@ int recvtimeout(int s, char *buf, int len, int timeout){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int write1(int sd, char *buf, int use_ssl, SSL *ssl){
|
int write1(int sd, void *buf, int buflen, int use_ssl, SSL *ssl){
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if(use_ssl == 1)
|
if(use_ssl == 1)
|
||||||
n = SSL_write(ssl, buf, strlen(buf));
|
n = SSL_write(ssl, buf, buflen);
|
||||||
else
|
else
|
||||||
n = send(sd, buf, strlen(buf), 0);
|
n = send(sd, buf, buflen, 0);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@ -520,6 +520,12 @@ void strtolower(char *s){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *get_in_addr(struct sockaddr *sa){
|
||||||
|
if(sa->sa_family == AF_INET) return &(((struct sockaddr_in*)sa)->sin_addr);
|
||||||
|
return &(((struct sockaddr_in6*)sa)->sin6_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#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;
|
||||||
|
@ -28,7 +28,7 @@ void create_id(char *id, unsigned char server_id);
|
|||||||
int get_random_bytes(unsigned char *buf, int len, unsigned char server_id);
|
int get_random_bytes(unsigned char *buf, int len, unsigned char server_id);
|
||||||
int readFromEntropyPool(int fd, void *_s, size_t n);
|
int readFromEntropyPool(int fd, void *_s, size_t n);
|
||||||
int recvtimeout(int s, char *buf, int len, int timeout);
|
int recvtimeout(int s, char *buf, int len, int timeout);
|
||||||
int write1(int sd, char *buf, int use_ssl, SSL *ssl);
|
int write1(int sd, void *buf, int buflen, int use_ssl, SSL *ssl);
|
||||||
int recvtimeoutssl(int s, char *buf, int len, int timeout, int use_ssl, SSL *ssl);
|
int recvtimeoutssl(int s, char *buf, int len, int timeout, int use_ssl, SSL *ssl);
|
||||||
|
|
||||||
void write_pid_file(char *pidfile);
|
void write_pid_file(char *pidfile);
|
||||||
@ -39,6 +39,8 @@ void init_session_data(struct session_data *sdata, struct __config *cfg);
|
|||||||
int read_from_stdin(struct session_data *sdata);
|
int read_from_stdin(struct session_data *sdata);
|
||||||
void strtolower(char *s);
|
void strtolower(char *s);
|
||||||
|
|
||||||
|
void *get_in_addr(struct sockaddr *sa);
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
char *strcasestr(const char *s, const char *find);
|
char *strcasestr(const char *s, const char *find);
|
||||||
#endif
|
#endif
|
||||||
|
26
src/piler.c
26
src/piler.c
@ -41,7 +41,6 @@ struct passwd *pwd;
|
|||||||
struct child children[MAXCHILDREN];
|
struct child children[MAXCHILDREN];
|
||||||
|
|
||||||
|
|
||||||
signal_func *set_signal_handler(int signo, signal_func * func);
|
|
||||||
static void takesig(int sig);
|
static void takesig(int sig);
|
||||||
static void child_sighup_handler(int sig);
|
static void child_sighup_handler(int sig);
|
||||||
static void child_main(struct child *ptr);
|
static void child_main(struct child *ptr);
|
||||||
@ -55,23 +54,6 @@ void initialise_configuration();
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* most of the preforking code was taken from the tinyproxy project
|
|
||||||
*/
|
|
||||||
|
|
||||||
signal_func *set_signal_handler(int signo, signal_func * func){
|
|
||||||
struct sigaction act, oact;
|
|
||||||
|
|
||||||
act.sa_handler = func;
|
|
||||||
sigemptyset (&act.sa_mask);
|
|
||||||
act.sa_flags = 0;
|
|
||||||
|
|
||||||
if(sigaction(signo, &act, &oact) < 0) return SIG_ERR;
|
|
||||||
|
|
||||||
return oact.sa_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void takesig(int sig){
|
static void takesig(int sig){
|
||||||
int i, status;
|
int i, status;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
@ -118,12 +100,6 @@ static void child_sighup_handler(int sig){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *get_in_addr(struct sockaddr *sa){
|
|
||||||
if(sa->sa_family == AF_INET) return &(((struct sockaddr_in*)sa)->sin_addr);
|
|
||||||
return &(((struct sockaddr_in6*)sa)->sin6_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void child_main(struct child *ptr){
|
static void child_main(struct child *ptr){
|
||||||
int new_sd;
|
int new_sd;
|
||||||
char s[INET6_ADDRSTRLEN];
|
char s[INET6_ADDRSTRLEN];
|
||||||
@ -368,7 +344,7 @@ void initialise_configuration(){
|
|||||||
|
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
int i, rc, yes=1, daemonise=0;
|
int i, rc, yes=1, daemonise=0;
|
||||||
char port_string[6];
|
char port_string[8];
|
||||||
struct addrinfo hints, *res;
|
struct addrinfo hints, *res;
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ void digest_file(char *filename, char *digest);
|
|||||||
void digest_string(char *s, char *digest);
|
void digest_string(char *s, char *digest);
|
||||||
|
|
||||||
int handle_smtp_session(int new_sd, struct __data *data, struct __config *cfg);
|
int handle_smtp_session(int new_sd, struct __data *data, struct __config *cfg);
|
||||||
|
int handle_pilerget_request(int new_sd, struct __data *data, struct __config *cfg);
|
||||||
|
|
||||||
void remove_stripped_attachments(struct _state *state);
|
void remove_stripped_attachments(struct _state *state);
|
||||||
int process_message(struct session_data *sdata, struct _state *state, struct __data *data, struct __config *cfg);
|
int process_message(struct session_data *sdata, struct _state *state, struct __data *data, struct __config *cfg);
|
||||||
@ -50,6 +51,7 @@ void check_and_create_directories(struct __config *cfg, uid_t uid, gid_t gid);
|
|||||||
void update_counters(struct session_data *sdata, struct __data *data, struct __counters *counters, struct __config *cfg);
|
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, struct __data *data, FILE *dest, struct __config *cfg);
|
int retrieve_email_from_archive(struct session_data *sdata, struct __data *data, FILE *dest, struct __config *cfg);
|
||||||
|
int file_from_archive_to_network(char *filename, int sd, struct __data *data, struct __config *cfg);
|
||||||
|
|
||||||
int prepare_a_mysql_statement(struct session_data *sdata, MYSQL_STMT **stmt, char *s);
|
int prepare_a_mysql_statement(struct session_data *sdata, MYSQL_STMT **stmt, char *s);
|
||||||
|
|
||||||
|
399
src/pilergetd.c
Normal file
399
src/pilergetd.c
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
/*
|
||||||
|
* pilergetd.c, SJ
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <piler.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char *optarg;
|
||||||
|
extern int optind;
|
||||||
|
|
||||||
|
int sd;
|
||||||
|
int quit = 0;
|
||||||
|
int received_sighup = 0;
|
||||||
|
char *configfile = CONFIG_FILE;
|
||||||
|
struct __config cfg;
|
||||||
|
struct __data data;
|
||||||
|
struct passwd *pwd;
|
||||||
|
|
||||||
|
struct child children[MAXCHILDREN];
|
||||||
|
|
||||||
|
|
||||||
|
static void takesig(int sig);
|
||||||
|
static void child_sighup_handler(int sig);
|
||||||
|
static void child_main(struct child *ptr);
|
||||||
|
static pid_t child_make(struct child *ptr);
|
||||||
|
int search_slot_by_pid(pid_t pid);
|
||||||
|
void kill_children(int sig);
|
||||||
|
void p_clean_exit();
|
||||||
|
void fatal(char *s);
|
||||||
|
void initialise_configuration();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void takesig(int sig){
|
||||||
|
int i, status;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
switch(sig){
|
||||||
|
case SIGHUP:
|
||||||
|
initialise_configuration();
|
||||||
|
if(read_key(&cfg)) fatal(ERR_READING_KEY);
|
||||||
|
kill_children(SIGHUP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGTERM:
|
||||||
|
case SIGKILL:
|
||||||
|
quit = 1;
|
||||||
|
p_clean_exit();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIGCHLD:
|
||||||
|
while((pid = waitpid (-1, &status, WNOHANG)) > 0){
|
||||||
|
|
||||||
|
if(quit == 0){
|
||||||
|
i = search_slot_by_pid(pid);
|
||||||
|
if(i >= 0){
|
||||||
|
children[i].status = READY;
|
||||||
|
children[i].pid = child_make(&children[i]);
|
||||||
|
}
|
||||||
|
else syslog(LOG_PRIORITY, "error: couldn't find slot for pid %d", pid);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void child_sighup_handler(int sig){
|
||||||
|
if(sig == SIGHUP){
|
||||||
|
received_sighup = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void child_main(struct child *ptr){
|
||||||
|
int new_sd;
|
||||||
|
char s[INET6_ADDRSTRLEN];
|
||||||
|
struct sockaddr_storage client_addr;
|
||||||
|
socklen_t addr_size;
|
||||||
|
|
||||||
|
ptr->messages = 0;
|
||||||
|
|
||||||
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "child (pid: %d) started main()", getpid());
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
if(received_sighup == 1){
|
||||||
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "child (pid: %d) caught HUP signal", getpid());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr->status = READY;
|
||||||
|
|
||||||
|
addr_size = sizeof(client_addr);
|
||||||
|
new_sd = accept(sd, (struct sockaddr *)&client_addr, &addr_size);
|
||||||
|
|
||||||
|
if(new_sd == -1) continue;
|
||||||
|
|
||||||
|
ptr->status = BUSY;
|
||||||
|
|
||||||
|
inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof(s));
|
||||||
|
|
||||||
|
syslog(LOG_PRIORITY, "connection from %s", s);
|
||||||
|
|
||||||
|
|
||||||
|
sig_block(SIGHUP);
|
||||||
|
ptr->messages += handle_pilerget_request(new_sd, &data, &cfg);
|
||||||
|
sig_unblock(SIGHUP);
|
||||||
|
|
||||||
|
close(new_sd);
|
||||||
|
|
||||||
|
if(cfg.max_requests_per_child > 0 && ptr->messages >= cfg.max_requests_per_child){
|
||||||
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "child (pid: %d) served enough: %d", getpid(), ptr->messages);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr->status = UNDEF;
|
||||||
|
|
||||||
|
#ifdef HAVE_MEMCACHED
|
||||||
|
memcached_shutdown(&(data.memc));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "child decides to exit (pid: %d)", getpid());
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static pid_t child_make(struct child *ptr){
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if((pid = fork()) > 0) return pid;
|
||||||
|
|
||||||
|
if(pid == -1) return -1;
|
||||||
|
|
||||||
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "forked a child (pid: %d)", getpid());
|
||||||
|
|
||||||
|
/* reset signals */
|
||||||
|
|
||||||
|
set_signal_handler(SIGCHLD, SIG_DFL);
|
||||||
|
set_signal_handler(SIGTERM, SIG_DFL);
|
||||||
|
set_signal_handler(SIGHUP, child_sighup_handler);
|
||||||
|
|
||||||
|
child_main(ptr);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int child_pool_create(){
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<MAXCHILDREN; i++){
|
||||||
|
children[i].pid = 0;
|
||||||
|
children[i].messages = 0;
|
||||||
|
children[i].status = UNDEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<cfg.number_of_worker_processes; i++){
|
||||||
|
children[i].status = READY;
|
||||||
|
children[i].pid = child_make(&children[i]);
|
||||||
|
|
||||||
|
if(children[i].pid == -1){
|
||||||
|
syslog(LOG_PRIORITY, "error: failed to fork a child");
|
||||||
|
p_clean_exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int search_slot_by_pid(pid_t pid){
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<MAXCHILDREN; i++){
|
||||||
|
if(children[i].pid == pid) return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void kill_children(int sig){
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<MAXCHILDREN; i++){
|
||||||
|
if(children[i].status != UNDEF && children[i].pid > 1){
|
||||||
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "sending signal to child (pid: %d)", children[i].pid);
|
||||||
|
kill(children[i].pid, sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void p_clean_exit(){
|
||||||
|
if(sd != -1) close(sd);
|
||||||
|
|
||||||
|
kill_children(SIGTERM);
|
||||||
|
|
||||||
|
syslog(LOG_PRIORITY, "%s has been terminated", PILERGETD_PROGNAME);
|
||||||
|
|
||||||
|
unlink(cfg.pilergetd_pidfile);
|
||||||
|
|
||||||
|
if(data.ctx){
|
||||||
|
SSL_CTX_free(data.ctx);
|
||||||
|
ERR_free_strings();
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fatal(char *s){
|
||||||
|
syslog(LOG_PRIORITY, "%s\n", s);
|
||||||
|
p_clean_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int init_ssl(){
|
||||||
|
|
||||||
|
SSL_library_init();
|
||||||
|
SSL_load_error_strings();
|
||||||
|
|
||||||
|
data.ctx = SSL_CTX_new(SSLv23_server_method());
|
||||||
|
|
||||||
|
if(data.ctx == NULL){ syslog(LOG_PRIORITY, "SSL_CTX_new() failed"); return ERR; }
|
||||||
|
|
||||||
|
if(SSL_CTX_set_cipher_list(data.ctx, cfg.cipher_list) == 0){ syslog(LOG_PRIORITY, "failed to set cipher list: '%s'", cfg.cipher_list); return ERR; }
|
||||||
|
|
||||||
|
if(SSL_CTX_use_PrivateKey_file(data.ctx, cfg.pemfile, SSL_FILETYPE_PEM) != 1){ syslog(LOG_PRIORITY, "cannot load private key from %s", cfg.pemfile); return ERR; }
|
||||||
|
|
||||||
|
if(SSL_CTX_use_certificate_file(data.ctx, cfg.pemfile, SSL_FILETYPE_PEM) != 1){ syslog(LOG_PRIORITY, "cannot load certificate from %s", cfg.pemfile); return ERR; }
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void initialise_configuration(){
|
||||||
|
|
||||||
|
cfg = read_config(configfile);
|
||||||
|
|
||||||
|
if(cfg.number_of_worker_processes < 5) cfg.number_of_worker_processes = 5;
|
||||||
|
if(cfg.number_of_worker_processes > MAXCHILDREN) cfg.number_of_worker_processes = MAXCHILDREN;
|
||||||
|
|
||||||
|
if(strlen(cfg.username) > 1){
|
||||||
|
pwd = getpwnam(cfg.username);
|
||||||
|
if(!pwd) fatal(ERR_NON_EXISTENT_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(getuid() == 0 && pwd){
|
||||||
|
check_and_create_directories(&cfg, pwd->pw_uid, pwd->pw_gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(chdir(cfg.workdir)){
|
||||||
|
syslog(LOG_PRIORITY, "workdir: *%s*", cfg.workdir);
|
||||||
|
fatal(ERR_CHDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
setlocale(LC_MESSAGES, cfg.locale);
|
||||||
|
setlocale(LC_CTYPE, cfg.locale);
|
||||||
|
|
||||||
|
syslog(LOG_PRIORITY, "reloaded config: %s", configfile);
|
||||||
|
|
||||||
|
#ifdef HAVE_MEMCACHED
|
||||||
|
memcached_init(&(data.memc), cfg.memcached_servers, 11211);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
int i, rc, yes=1, daemonise=0;
|
||||||
|
char port_string[8];
|
||||||
|
struct addrinfo hints, *res;
|
||||||
|
|
||||||
|
|
||||||
|
while((i = getopt(argc, argv, "c:dvVh")) > 0){
|
||||||
|
switch(i){
|
||||||
|
|
||||||
|
case 'c' :
|
||||||
|
configfile = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd' :
|
||||||
|
daemonise = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v' :
|
||||||
|
case 'V' :
|
||||||
|
printf("%s %s, build %d, Janos SUTO <sj@acts.hu>\n\n%s\n\n", PILERGETD_PROGNAME, VERSION, get_build(), CONFIGURE_PARAMS);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 'h' :
|
||||||
|
default :
|
||||||
|
__fatal("usage: ...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) openlog(PILERGETD_PROGNAME, LOG_PID, LOG_MAIL);
|
||||||
|
|
||||||
|
data.ctx = NULL;
|
||||||
|
data.ssl = NULL;
|
||||||
|
|
||||||
|
initialise_configuration();
|
||||||
|
|
||||||
|
if(init_ssl() == ERR) fatal("cannot init ssl");
|
||||||
|
|
||||||
|
set_signal_handler (SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
|
|
||||||
|
if(read_key(&cfg)) fatal(ERR_READING_KEY);
|
||||||
|
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
snprintf(port_string, sizeof(port_string)-1, "%d", cfg.pilergetd_listen_port);
|
||||||
|
|
||||||
|
if((rc = getaddrinfo(cfg.pilergetd_listen_addr, port_string, &hints, &res)) != 0){
|
||||||
|
fprintf(stderr, "getaddrinfo for '%s': %s\n", cfg.pilergetd_listen_addr, gai_strerror(rc));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if((sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1)
|
||||||
|
fatal(ERR_OPEN_SOCKET);
|
||||||
|
|
||||||
|
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
|
||||||
|
fatal(ERR_SET_SOCK_OPT);
|
||||||
|
|
||||||
|
if(bind(sd, res->ai_addr, res->ai_addrlen) == -1)
|
||||||
|
fatal(ERR_BIND_TO_PORT);
|
||||||
|
|
||||||
|
if(listen(sd, cfg.backlog) == -1)
|
||||||
|
fatal(ERR_LISTEN);
|
||||||
|
|
||||||
|
|
||||||
|
freeaddrinfo(res);
|
||||||
|
|
||||||
|
|
||||||
|
if(drop_privileges(pwd)) fatal(ERR_SETUID);
|
||||||
|
|
||||||
|
|
||||||
|
syslog(LOG_PRIORITY, "%s %s, build %d starting", PILERGETD_PROGNAME, VERSION, get_build());
|
||||||
|
|
||||||
|
|
||||||
|
#if HAVE_DAEMON == 1
|
||||||
|
if(daemonise == 1) i = daemon(1, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_pid_file(cfg.pilergetd_pidfile);
|
||||||
|
|
||||||
|
|
||||||
|
child_pool_create();
|
||||||
|
|
||||||
|
set_signal_handler(SIGCHLD, takesig);
|
||||||
|
set_signal_handler(SIGTERM, takesig);
|
||||||
|
set_signal_handler(SIGKILL, takesig);
|
||||||
|
set_signal_handler(SIGHUP, takesig);
|
||||||
|
|
||||||
|
|
||||||
|
for(;;){ sleep(1); }
|
||||||
|
|
||||||
|
p_clean_exit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
10
src/pop3.c
10
src/pop3.c
@ -75,13 +75,13 @@ int connect_to_pop3_server(int sd, char *username, char *password, int port, str
|
|||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1, "USER %s\r\n", username);
|
snprintf(buf, sizeof(buf)-1, "USER %s\r\n", username);
|
||||||
|
|
||||||
write1(sd, buf, use_ssl, data->ssl);
|
write1(sd, buf, strlen(buf), use_ssl, data->ssl);
|
||||||
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
||||||
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1, "PASS %s\r\n", password);
|
snprintf(buf, sizeof(buf)-1, "PASS %s\r\n", password);
|
||||||
|
|
||||||
write1(sd, buf, use_ssl, data->ssl);
|
write1(sd, buf, strlen(buf), use_ssl, data->ssl);
|
||||||
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
||||||
|
|
||||||
if(strncmp(buf, "+OK", 3) == 0) return OK;
|
if(strncmp(buf, "+OK", 3) == 0) return OK;
|
||||||
@ -96,7 +96,7 @@ int process_pop3_emails(int sd, struct session_data *sdata, struct __data *data,
|
|||||||
char aggrbuf[3*MAXBUFSIZE];
|
char aggrbuf[3*MAXBUFSIZE];
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1, "STAT\r\n");
|
snprintf(buf, sizeof(buf)-1, "STAT\r\n");
|
||||||
n = write1(sd, buf, use_ssl, data->ssl);
|
n = write1(sd, buf, strlen(buf), use_ssl, data->ssl);
|
||||||
|
|
||||||
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ int process_pop3_emails(int sd, struct session_data *sdata, struct __data *data,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = write1(sd, buf, use_ssl, data->ssl);
|
n = write1(sd, buf, strlen(buf), use_ssl, data->ssl);
|
||||||
|
|
||||||
readlen = 0;
|
readlen = 0;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
@ -195,7 +195,7 @@ int process_pop3_emails(int sd, struct session_data *sdata, struct __data *data,
|
|||||||
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1, "QUIT\r\n");
|
snprintf(buf, sizeof(buf)-1, "QUIT\r\n");
|
||||||
n = write1(sd, buf, use_ssl, data->ssl);
|
n = write1(sd, buf, strlen(buf), use_ssl, data->ssl);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
251
src/retr.c
Normal file
251
src/retr.c
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/*
|
||||||
|
* retr.c, SJ
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <piler.h>
|
||||||
|
|
||||||
|
|
||||||
|
int stat_file(struct session_data *sdata, char *f, char **buf, int buflen, struct __config *cfg){
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
snprintf(*buf, buflen, "%s/%02x/%c%c%c/%c%c/%c%c/%s", cfg->queuedir, cfg->server_id, f[8], f[9], f[10], f[RND_STR_LEN-4], f[RND_STR_LEN-3], f[RND_STR_LEN-2], f[RND_STR_LEN-1], f);
|
||||||
|
if(!stat(*buf, &st)) return st.st_size;
|
||||||
|
|
||||||
|
snprintf(*buf, TINYBUFSIZE-1, "%s/%02x/%c%c/%c%c/%c%c/%s", cfg->queuedir, cfg->server_id, f[RND_STR_LEN-6], f[RND_STR_LEN-5], f[RND_STR_LEN-4], f[RND_STR_LEN-3], f[RND_STR_LEN-2], f[RND_STR_LEN-1], f);
|
||||||
|
if(!stat(*buf, &st)) return st.st_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int stat_message(struct session_data *sdata, struct __data *data, char **buf, int buflen, struct __config *cfg){
|
||||||
|
int i, attachments, len=0;
|
||||||
|
struct ptr_array ptr_arr[MAX_ATTACHMENTS];
|
||||||
|
char puf[TINYBUFSIZE];
|
||||||
|
|
||||||
|
if(strlen(sdata->ttmpfile) != RND_STR_LEN){
|
||||||
|
return ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(*buf, buflen-2, "%s.m", sdata->ttmpfile);
|
||||||
|
len = strlen(*buf);
|
||||||
|
|
||||||
|
attachments = query_attachments(sdata, data, &ptr_arr[0], cfg);
|
||||||
|
|
||||||
|
if(attachments == -1){
|
||||||
|
return ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=1; i<=attachments; i++){
|
||||||
|
if(len < buflen){
|
||||||
|
snprintf(puf, sizeof(puf)-1, " %s.a%d", ptr_arr[i].piler_id, ptr_arr[i].attachment_id);
|
||||||
|
strncat(*buf, puf, buflen);
|
||||||
|
len += strlen(puf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strncat(*buf, "\r\n", buflen-2);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int handle_pilerget_request(int new_sd, struct __data *data, struct __config *cfg){
|
||||||
|
int len, n, ssl_ok=0, n_files=0;
|
||||||
|
char *q, buf[MAXBUFSIZE], puf[MAXBUFSIZE], muf[TINYBUFSIZE], resp[MAXBUFSIZE];
|
||||||
|
char ssl_error[SMALLBUFSIZE];
|
||||||
|
struct session_data sdata;
|
||||||
|
int db_conn=0;
|
||||||
|
int rc;
|
||||||
|
struct __counters counters;
|
||||||
|
|
||||||
|
struct timezone tz;
|
||||||
|
struct timeval tv1, tv2;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBWRAP
|
||||||
|
struct request_info req;
|
||||||
|
|
||||||
|
request_init(&req, RQ_DAEMON, PILERGETD_PROGNAME, RQ_FILE, new_sd, 0);
|
||||||
|
fromhost(&req);
|
||||||
|
if(!hosts_access(&req)){
|
||||||
|
send(new_sd, SMTP_RESP_550_ERR_YOU_ARE_BANNED_BY_LOCAL_POLICY, strlen(SMTP_RESP_550_ERR_YOU_ARE_BANNED_BY_LOCAL_POLICY), 0);
|
||||||
|
syslog(LOG_PRIORITY, "denied connection from %s by tcp_wrappers", eval_client(&req));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
init_session_data(&sdata, cfg);
|
||||||
|
sdata.tls = 0;
|
||||||
|
|
||||||
|
bzero(&counters, sizeof(counters));
|
||||||
|
|
||||||
|
|
||||||
|
/* open database connection */
|
||||||
|
|
||||||
|
db_conn = 0;
|
||||||
|
|
||||||
|
#ifdef NEED_MYSQL
|
||||||
|
rc = 1;
|
||||||
|
mysql_init(&(sdata.mysql));
|
||||||
|
mysql_options(&(sdata.mysql), MYSQL_OPT_CONNECT_TIMEOUT, (const char*)&cfg->mysql_connect_timeout);
|
||||||
|
mysql_options(&(sdata.mysql), MYSQL_OPT_RECONNECT, (const char*)&rc);
|
||||||
|
|
||||||
|
if(mysql_real_connect(&(sdata.mysql), cfg->mysqlhost, cfg->mysqluser, cfg->mysqlpwd, cfg->mysqldb, cfg->mysqlport, cfg->mysqlsocket, 0)){
|
||||||
|
db_conn = 1;
|
||||||
|
mysql_real_query(&(sdata.mysql), "SET NAMES utf8", strlen("SET NAMES utf8"));
|
||||||
|
mysql_real_query(&(sdata.mysql), "SET CHARACTER SET utf8", strlen("SET CHARACTER SET utf8"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
syslog(LOG_PRIORITY, "%s", ERR_MYSQL_CONNECT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(db_conn == 1 && create_prepared_statements(&sdata, data) == ERR){
|
||||||
|
close_prepared_statements(data);
|
||||||
|
mysql_close(&(sdata.mysql));
|
||||||
|
db_conn = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(db_conn == 0){
|
||||||
|
send(new_sd, SMTP_RESP_421_ERR_TMP, strlen(SMTP_RESP_421_ERR_TMP), 0);
|
||||||
|
syslog(LOG_PRIORITY, "cannot make prepared statement");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gettimeofday(&tv1, &tz);
|
||||||
|
|
||||||
|
|
||||||
|
if(data->ctx){
|
||||||
|
data->ssl = SSL_new(data->ctx);
|
||||||
|
if(data->ssl){
|
||||||
|
if(SSL_set_fd(data->ssl, new_sd) == 1){
|
||||||
|
ssl_ok = 1;
|
||||||
|
} else syslog(LOG_PRIORITY, "SSL_set_fd() failed");
|
||||||
|
} else syslog(LOG_PRIORITY, "SSL_new() failed");
|
||||||
|
} else syslog(LOG_PRIORITY, "SSL ctx is null!");
|
||||||
|
|
||||||
|
|
||||||
|
if(ssl_ok == 0){
|
||||||
|
send(new_sd, SMTP_RESP_421_ERR_TMP, strlen(SMTP_RESP_421_ERR_TMP), 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rc = SSL_accept(data->ssl);
|
||||||
|
|
||||||
|
if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "SSL_accept() finished");
|
||||||
|
|
||||||
|
if(rc == 1){
|
||||||
|
sdata.tls = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ERR_error_string_n(ERR_get_error(), ssl_error, SMALLBUFSIZE);
|
||||||
|
syslog(LOG_PRIORITY, "SSL_accept() failed, rc=%d, errorcode: %d, error text: %s\n", rc, SSL_get_error(data->ssl, rc), ssl_error);
|
||||||
|
goto QUITTING;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
snprintf(buf, MAXBUFSIZE-1, SMTP_RESP_220_BANNER, cfg->hostid);
|
||||||
|
|
||||||
|
write1(new_sd, buf, strlen(buf), sdata.tls, data->ssl);
|
||||||
|
|
||||||
|
if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "sent: %s", buf);
|
||||||
|
|
||||||
|
while((n = recvtimeoutssl(new_sd, puf, MAXBUFSIZE, TIMEOUT, sdata.tls, data->ssl)) > 0){
|
||||||
|
|
||||||
|
if(strncasecmp(puf, "MESSAGE ", strlen("MESSAGE ")) == 0){
|
||||||
|
trimBuffer(puf);
|
||||||
|
q = &resp[0];
|
||||||
|
|
||||||
|
memset(resp, 0, sizeof(resp));
|
||||||
|
|
||||||
|
snprintf(sdata.ttmpfile, sizeof(sdata.ttmpfile)-1, "%s", &puf[8]);
|
||||||
|
stat_message(&sdata, data, &q, sizeof(resp)-2, cfg);
|
||||||
|
|
||||||
|
write1(new_sd, resp, strlen(resp), sdata.tls, data->ssl);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(strncasecmp(puf, "STAT ", strlen("STAT ")) == 0){
|
||||||
|
trimBuffer(puf);
|
||||||
|
q = &muf[0];
|
||||||
|
|
||||||
|
len = stat_file(&sdata, &puf[5], &q, sizeof(muf)-2, cfg);
|
||||||
|
|
||||||
|
snprintf(resp, sizeof(resp)-1, "SIZE %s %d\r\n", &puf[5], len);
|
||||||
|
|
||||||
|
write1(new_sd, resp, strlen(resp), sdata.tls, data->ssl);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(strncasecmp(puf, "RETR ", strlen("RETR ")) == 0){
|
||||||
|
|
||||||
|
trimBuffer(puf);
|
||||||
|
q = &muf[0];
|
||||||
|
|
||||||
|
if(strlen(&puf[5]) >= RND_STR_LEN){
|
||||||
|
len = stat_file(&sdata, &puf[5], &q, sizeof(muf)-2, cfg);
|
||||||
|
file_from_archive_to_network(muf, new_sd, data, cfg);
|
||||||
|
n_files++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snprintf(resp, sizeof(resp)-1, "ERR\r\n");
|
||||||
|
write1(new_sd, resp, strlen(resp), sdata.tls, data->ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(strncasecmp(puf, SMTP_CMD_QUIT, strlen(SMTP_CMD_QUIT)) == 0){
|
||||||
|
snprintf(resp, sizeof(resp)-1, SMTP_RESP_221_GOODBYE, cfg->hostid);
|
||||||
|
write1(new_sd, resp, strlen(resp), sdata.tls, data->ssl);
|
||||||
|
|
||||||
|
gettimeofday(&tv2, &tz);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(resp, sizeof(resp)-1, "ERR\r\n");
|
||||||
|
write1(new_sd, resp, strlen(resp), sdata.tls, data->ssl);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QUITTING:
|
||||||
|
|
||||||
|
#ifdef NEED_MYSQL
|
||||||
|
close_prepared_statements(data);
|
||||||
|
mysql_close(&(sdata.mysql));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SSL_shutdown(data->ssl);
|
||||||
|
SSL_free(data->ssl);
|
||||||
|
|
||||||
|
if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "served %d files", n_files);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -154,8 +154,7 @@ int handle_smtp_session(int new_sd, struct __data *data, struct __config *cfg){
|
|||||||
for(i=0; i<sdata.num_of_rcpt_to; i++){
|
for(i=0; i<sdata.num_of_rcpt_to; i++){
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//send(new_sd, SMTP_RESP_421_ERR_WRITE_FAILED, strlen(SMTP_RESP_421_ERR_WRITE_FAILED), 0);
|
write1(new_sd, SMTP_RESP_421_ERR_WRITE_FAILED, strlen(SMTP_RESP_421_ERR_WRITE_FAILED), sdata.tls, data->ssl);
|
||||||
write1(new_sd, SMTP_RESP_421_ERR_WRITE_FAILED, sdata.tls, data->ssl);
|
|
||||||
|
|
||||||
#ifdef HAVE_LMTP
|
#ifdef HAVE_LMTP
|
||||||
}
|
}
|
||||||
@ -250,8 +249,7 @@ int handle_smtp_session(int new_sd, struct __data *data, struct __config *cfg){
|
|||||||
|
|
||||||
if(inj == ERR) snprintf(sdata.acceptbuf, SMALLBUFSIZE-1, "451 %s <%s>\r\n", sdata.ttmpfile, rctptoemail);
|
if(inj == ERR) snprintf(sdata.acceptbuf, SMALLBUFSIZE-1, "451 %s <%s>\r\n", sdata.ttmpfile, rctptoemail);
|
||||||
|
|
||||||
//send(new_sd, sdata.acceptbuf, strlen(sdata.acceptbuf), 0);
|
write1(new_sd, sdata.acceptbuf, strlen(sdata.acceptbuf), sdata.tls, data->ssl);
|
||||||
write1(new_sd, sdata.acceptbuf, sdata.tls, data->ssl);
|
|
||||||
|
|
||||||
if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: sent: %s", sdata.ttmpfile, sdata.acceptbuf);
|
if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: sent: %s", sdata.ttmpfile, sdata.acceptbuf);
|
||||||
|
|
||||||
@ -506,8 +504,7 @@ AFTER_PERIOD:
|
|||||||
/* now we can send our buffered response */
|
/* now we can send our buffered response */
|
||||||
|
|
||||||
if(strlen(resp) > 0){
|
if(strlen(resp) > 0){
|
||||||
//send(new_sd, resp, strlen(resp), 0);
|
write1(new_sd, resp, strlen(resp), sdata.tls, data->ssl);
|
||||||
write1(new_sd, resp, sdata.tls, data->ssl);
|
|
||||||
|
|
||||||
if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: sent: %s", sdata.ttmpfile, resp);
|
if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: sent: %s", sdata.ttmpfile, resp);
|
||||||
memset(resp, 0, MAXBUFSIZE);
|
memset(resp, 0, MAXBUFSIZE);
|
||||||
@ -547,8 +544,7 @@ AFTER_PERIOD:
|
|||||||
|
|
||||||
if(state < SMTP_STATE_QUIT && inj == ERR){
|
if(state < SMTP_STATE_QUIT && inj == ERR){
|
||||||
snprintf(buf, MAXBUFSIZE-1, SMTP_RESP_421_ERR, cfg->hostid);
|
snprintf(buf, MAXBUFSIZE-1, SMTP_RESP_421_ERR, cfg->hostid);
|
||||||
//send(new_sd, buf, strlen(buf), 0);
|
write1(new_sd, buf, strlen(buf), sdata.tls, data->ssl);
|
||||||
write1(new_sd, buf, sdata.tls, data->ssl);
|
|
||||||
|
|
||||||
if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: sent: %s", sdata.ttmpfile, buf);
|
if(cfg->verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "%s: sent: %s", sdata.ttmpfile, buf);
|
||||||
|
|
||||||
|
14
src/sig.c
14
src/sig.c
@ -5,6 +5,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <piler.h>
|
||||||
|
|
||||||
|
|
||||||
void sig_block(int sig){
|
void sig_block(int sig){
|
||||||
sigset_t ss;
|
sigset_t ss;
|
||||||
@ -43,3 +45,15 @@ int wait_nohang(int *wstat){
|
|||||||
return waitpid(-1, wstat, WNOHANG);
|
return waitpid(-1, wstat, WNOHANG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal_func *set_signal_handler(int signo, signal_func * func){
|
||||||
|
struct sigaction act, oact;
|
||||||
|
|
||||||
|
act.sa_handler = func;
|
||||||
|
sigemptyset (&act.sa_mask);
|
||||||
|
act.sa_flags = 0;
|
||||||
|
|
||||||
|
if(sigaction(signo, &act, &oact) < 0) return SIG_ERR;
|
||||||
|
|
||||||
|
return oact.sa_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -11,5 +11,6 @@ void sig_catch(int sig, void (*f)());
|
|||||||
void sig_uncatch(int sig);
|
void sig_uncatch(int sig);
|
||||||
void sig_pause();
|
void sig_pause();
|
||||||
int wait_nohang(int *wstat);
|
int wait_nohang(int *wstat);
|
||||||
|
signal_func *set_signal_handler(int signo, signal_func * func);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user