added SSL support to pilerimport

This commit is contained in:
SJ 2012-10-27 14:40:25 +02:00
parent 0f61106386
commit d7f860c15b
8 changed files with 256 additions and 70 deletions

100
configure vendored
View File

@ -3425,7 +3425,7 @@ unrtf="no"
have_static_build="no"
antispam_libs="-lz -lm -ldl -lcrypto"
antispam_libs="-lz -lm -ldl -lcrypto -lssl"
defs=""
objs=""
user_obj=""
@ -3684,7 +3684,103 @@ fi
fi
ac_cv_lib_crypto=ac_cv_lib_crypto_main
if test "$have_crypto" = "no"; then
for ac_header in openssl/ssl.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default"
if test "x$ac_cv_header_openssl_ssl_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_OPENSSL_SSL_H 1
_ACEOF
have_ssl=yes
else
have_ssl=no
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_write in -lssl" >&5
$as_echo_n "checking for SSL_write in -lssl... " >&6; }
if ${ac_cv_lib_ssl_SSL_write+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lssl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char SSL_write ();
int
main ()
{
return SSL_write ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_ssl_SSL_write=yes
else
ac_cv_lib_ssl_SSL_write=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_write" >&5
$as_echo "$ac_cv_lib_ssl_SSL_write" >&6; }
if test "x$ac_cv_lib_ssl_SSL_write" = xyes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_write in -lssl" >&5
$as_echo_n "checking for SSL_write in -lssl... " >&6; }
if ${ac_cv_lib_ssl_SSL_write+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lssl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char SSL_write ();
int
main ()
{
return SSL_write ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_ssl_SSL_write=yes
else
ac_cv_lib_ssl_SSL_write=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_write" >&5
$as_echo "$ac_cv_lib_ssl_SSL_write" >&6; }
if test "x$ac_cv_lib_ssl_SSL_write" = xyes; then :
have_ssl=yes
else
echo "libssl is not found"; have_ssl=no
fi
fi
ac_cv_lib_ssl=ac_cv_lib_ssl_main
if test "$have_crypto" = "no" || test "$have_ssl" = "no"; then
echo "please install openssl developer package"
exit 1
fi

View File

@ -51,7 +51,7 @@ unrtf="no"
have_static_build="no"
antispam_libs="-lz -lm -ldl -lcrypto"
antispam_libs="-lz -lm -ldl -lcrypto -lssl"
defs=""
objs=""
user_obj=""
@ -109,7 +109,10 @@ dnl openssl library
AC_CHECK_HEADERS(openssl/sha.h, have_crypto=yes, have_crypto=no)
AC_CHECK_LIB([crypto],[SHA256_Init],[AC_CHECK_LIB(crypto, SHA256_Init, have_crypto=yes, echo "libcrypto is not found"; have_crypto=no)],[],[])ac_cv_lib_crypto=ac_cv_lib_crypto_main
if test "$have_crypto" = "no"; then
AC_CHECK_HEADERS(openssl/ssl.h, have_ssl=yes, have_ssl=no)
AC_CHECK_LIB([ssl],[SSL_write],[AC_CHECK_LIB(ssl, SSL_write, have_ssl=yes, echo "libssl is not found"; have_ssl=no)],[],[])ac_cv_lib_ssl=ac_cv_lib_ssl_main
if test "$have_crypto" = "no" || test "$have_ssl" = "no"; then
echo "please install openssl developer package"
exit 1
fi

View File

@ -13,7 +13,7 @@
#define VERSION "0.1.21"
#define BUILD 717
#define BUILD 719
#define HOSTID "mailarchiver"

View File

@ -24,6 +24,7 @@
#endif
#include <openssl/sha.h>
#include <openssl/ssl.h>
#include "tai.h"
#include "config.h"
@ -247,6 +248,8 @@ struct __data {
struct memcached_server memc;
#endif
SSL_CTX *ctx;
SSL *ssl;
};

View File

@ -14,6 +14,7 @@
#include <netdb.h>
#include <sys/time.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <fcntl.h>
#include <ctype.h>
#include <syslog.h>
@ -22,6 +23,9 @@
#include <piler.h>
#define CHK_NULL(x, errmsg) if ((x)==NULL) { printf("error: %s\n", errmsg); return ERR; }
#define CHK_SSL(err, msg) if ((err)==-1) { printf("ssl error: %s\n", msg); return ERR; }
unsigned long resolve_host(char *host){
struct hostent *h;
@ -52,7 +56,8 @@ int get_message_length_from_imap_answer(char *s, int *_1st_line_bytes){
*p = '\0';
*_1st_line_bytes = strlen(s)+2;
//*_1st_line_bytes = strlen(s)+2;
*_1st_line_bytes = p-s+2;
if(*(p-1) == '}') *(p-1) = '\0';
@ -88,16 +93,16 @@ int is_last_complete_packet(char *s, int len, char *tagok, char *tagbad, int *po
}
int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sdata, struct __data *data, struct __config *cfg){
int rc=ERR, i, n, pos, endpos, messages=0, len, readlen, fd, lastpos, nreads, nwrites, processed_messages=0;
int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sdata, struct __data *data, int use_ssl, struct __config *cfg){
int rc=ERR, i, n, pos, endpos, messages=0, len, readlen, fd, lastpos, nreads, processed_messages=0;
char *p, tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], tagbad[SMALLBUFSIZE], buf[MAXBUFSIZE], filename[SMALLBUFSIZE];
char aggrbuf[3*MAXBUFSIZE];
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);
send(sd, buf, strlen(buf), 0);
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
n = write1(sd, buf, use_ssl, data->ssl);
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
if(!strstr(buf, tagok)){
trimBuffer(buf);
@ -139,20 +144,19 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
}
send(sd, buf, strlen(buf), 0);
n = write1(sd, buf, use_ssl, data->ssl);
readlen = 0;
pos = 0;
len = 0;
nreads = 0;
nwrites = 0;
endpos = 0;
memset(aggrbuf, 0, sizeof(aggrbuf));
lastpos = 0;
while((n = recvtimeout(sd, buf, sizeof(buf), 15)) > 0){
while((n = recvtimeoutssl(sd, buf, sizeof(buf), 15, use_ssl, data->ssl)) > 0){
nreads++;
readlen += n;
@ -165,45 +169,33 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
}
}
if(lastpos + n + sizeof(buf) > sizeof(aggrbuf)){
nwrites++;
if(lastpos + 1 + n < sizeof(aggrbuf)){
if(nwrites == 1)
write(fd, aggrbuf+pos, lastpos-pos);
else
write(fd, aggrbuf, lastpos);
memset(aggrbuf, 0, sizeof(aggrbuf));
lastpos = 0;
if(nreads == 1){
memcpy(aggrbuf+lastpos, buf+pos, n-pos);
lastpos += n-pos;
}
else {
memcpy(aggrbuf+lastpos, buf, n);
lastpos += n;
}
}
else {
write(fd, aggrbuf, sizeof(buf));
memmove(aggrbuf, aggrbuf+sizeof(buf), lastpos-sizeof(buf));
lastpos -= sizeof(buf);
memcpy(aggrbuf+lastpos, buf, n);
lastpos += n;
}
if(is_last_complete_packet(aggrbuf, lastpos, tagok, tagbad, &endpos) == 1){
nwrites++;
if(nwrites == 1)
write(fd, aggrbuf+pos, lastpos-(lastpos-endpos)-pos);
else
write(fd, aggrbuf, lastpos-(lastpos-endpos));
break;
}
else {
nwrites++;
if(nwrites == 1){
if(lastpos-n-pos > 0) write(fd, aggrbuf+pos, lastpos-n-pos); else nwrites--;
}
else {
write(fd, aggrbuf, lastpos-n);
}
memmove(aggrbuf, aggrbuf+lastpos-n, n);
lastpos = n;
memset(aggrbuf+lastpos, 0, sizeof(aggrbuf)-lastpos);
}
}
close(fd);
@ -218,29 +210,69 @@ int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sda
}
int connect_to_imap_server(int sd, int *seq, char *imapserver, char *username, char *password){
int connect_to_imap_server(int sd, int *seq, char *imapserver, char *username, char *password, int port, struct __data *data, int use_ssl){
int n, pos=0;
char tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], buf[MAXBUFSIZE];
char auth[2*SMALLBUFSIZE];
unsigned char tmp[SMALLBUFSIZE];
unsigned long host=0;
struct sockaddr_in remote_addr;
X509* server_cert;
SSL_METHOD *meth;
char *str;
host = resolve_host(imapserver);
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(143);
remote_addr.sin_port = htons(port);
remote_addr.sin_addr.s_addr = host;
bzero(&(remote_addr.sin_zero),8);
if(connect(sd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) == -1){
printf("connect()\n");
return ERR;
}
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
if(use_ssl == 1){
SSLeay_add_ssl_algorithms();
meth = SSLv3_client_method();
SSL_load_error_strings();
data->ctx = SSL_CTX_new(meth);
CHK_NULL(data->ctx, "internal SSL error");
data->ssl = SSL_new(data->ctx);
CHK_NULL(data->ssl, "internal ssl error");
SSL_set_fd(data->ssl, sd);
n = SSL_connect(data->ssl);
CHK_SSL(n, "internal ssl error");
//printf("Cipher: %s\n", SSL_get_cipher(data->ssl));
server_cert = SSL_get_peer_certificate(data->ssl);
CHK_NULL(server_cert, "server cert error");
//if(verbose){
str = X509_NAME_oneline(X509_get_subject_name(server_cert), 0, 0);
CHK_NULL(str, "error in server cert");
printf("server cert:\n\t subject: %s\n", str);
OPENSSL_free(str);
str = X509_NAME_oneline(X509_get_issuer_name(server_cert), 0, 0);
CHK_NULL(str, "error in server cert");
printf("\t issuer: %s\n\n", str);
OPENSSL_free(str);
//}
X509_free(server_cert);
}
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
/*
@ -262,8 +294,10 @@ int connect_to_imap_server(int sd, int *seq, char *imapserver, char *username, c
snprintf(tag, sizeof(tag)-1, "A%d", *seq); snprintf(tagok, sizeof(tagok)-1, "A%d OK", (*seq)++);
snprintf(buf, sizeof(buf)-1, "%s AUTHENTICATE PLAIN %s\r\n", tag, auth);
send(sd, buf, strlen(buf), 0);
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
write1(sd, buf, use_ssl, data->ssl);
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
if(strncmp(buf, tagok, strlen(tagok))){
printf("login failed, server reponse: %s\n", buf);
return ERR;
@ -273,7 +307,18 @@ int connect_to_imap_server(int sd, int *seq, char *imapserver, char *username, c
}
int list_folders(int sd, int *seq, char *folders, int foldersize){
void close_connection(int sd, struct __data *data, int use_ssl){
close(sd);
if(use_ssl == 1){
SSL_shutdown(data->ssl);
SSL_free(data->ssl);
SSL_CTX_free(data->ctx);
}
}
int list_folders(int sd, int *seq, char *folders, int foldersize, int use_ssl, struct __data *data){
int n;
char *p, *q, tag[SMALLBUFSIZE], tagok[SMALLBUFSIZE], buf[MAXBUFSIZE], puf[MAXBUFSIZE];
@ -281,9 +326,9 @@ int list_folders(int sd, int *seq, char *folders, int foldersize){
//snprintf(buf, sizeof(buf)-1, "%s LIST \"\" %%\r\n", tag);
snprintf(buf, sizeof(buf)-1, "%s LIST \"\" \"*\"\r\n", tag);
send(sd, buf, strlen(buf), 0);
write1(sd, buf, use_ssl, data->ssl);
n = recvtimeout(sd, buf, MAXBUFSIZE, 10);
n = recvtimeoutssl(sd, buf, sizeof(buf), 10, use_ssl, data->ssl);
p = &buf[0];
do {

View File

@ -18,6 +18,7 @@
#include <syslog.h>
#include <unistd.h>
#include <ctype.h>
#include <openssl/ssl.h>
#include "misc.h"
#include "smtpcodes.h"
#include "errmsg.h"
@ -293,7 +294,7 @@ int recvtimeout(int s, char *buf, int len, int timeout){
int n;
struct timeval tv;
memset(buf, 0, MAXBUFSIZE);
memset(buf, 0, len);
FD_ZERO(&fds);
FD_SET(s, &fds);
@ -309,6 +310,31 @@ int recvtimeout(int s, char *buf, int len, int timeout){
}
int write1(int sd, char *buf, int use_ssl, SSL *ssl){
int n;
if(use_ssl == 1)
n = SSL_write(ssl, buf, strlen(buf));
else
n = send(sd, buf, strlen(buf), 0);
return n;
}
int recvtimeoutssl(int s, char *buf, int len, int timeout, int use_ssl, SSL *ssl){
memset(buf, 0, len);
if(use_ssl == 1){
return SSL_read(ssl, buf, len-1);
}
else {
return recvtimeout(s, buf, len-1, timeout);
}
}
/*
* is it a valid dotted IPv4 address
*/

View File

@ -5,6 +5,7 @@
#ifndef _MISC_H
#define _MISC_H
#include <openssl/ssl.h>
#include <sys/time.h>
#include <pwd.h>
#include <cfg.h>
@ -24,6 +25,8 @@ void create_id(char *id);
int get_random_bytes(unsigned char *buf, int len);
int readFromEntropyPool(int fd, void *_s, size_t n);
int recvtimeout(int s, char *buf, int len, int timeout);
int write1(int sd, char *buf, 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);
int drop_privileges(struct passwd *pwd);

View File

@ -31,9 +31,10 @@ int quiet=0;
int remove_after_successful_import = 0;
int connect_to_imap_server(int sd, int *seq, char *imapserver, char *username, char *password);
int list_folders(int sd, int *seq, char *folders, int foldersize);
int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sdata, struct __data *data, struct __config *cfg);
int connect_to_imap_server(int sd, int *seq, char *imapserver, char *username, char *password, int port, struct __data *data, int use_ssl);
void close_connection(int sd, struct __data *data, int use_ssl);
int list_folders(int sd, int *seq, char *folders, int foldersize, int use_ssl, struct __data *data);
int process_imap_folder(int sd, int *seq, char *folder, struct session_data *sdata, struct __data *data, int use_ssl, struct __config *cfg);
int import_from_mailbox(char *mailbox, struct session_data *sdata, struct __data *data, struct __config *cfg){
@ -236,24 +237,28 @@ int import_from_maildir(char *directory, struct session_data *sdata, struct __da
}
int import_from_imap_server(char *imapserver, char *username, char *password, struct session_data *sdata, struct __data *data, char *skiplist, struct __config *cfg){
int rc=ERR, ret=OK, sd, seq=1, skipmatch;
int import_from_imap_server(char *imapserver, char *username, char *password, int port, struct session_data *sdata, struct __data *data, char *skiplist, struct __config *cfg){
int rc=ERR, ret=OK, sd, seq=1, skipmatch, use_ssl=0;
char *p, puf[SMALLBUFSIZE];
char *q, muf[SMALLBUFSIZE];
char folders[MAXBUFSIZE];
if(port == 993) use_ssl = 1;
if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
printf("cannot create socket\n");
return ERR;
}
if(connect_to_imap_server(sd, &seq, imapserver, username, password) == ERR){
if(connect_to_imap_server(sd, &seq, imapserver, username, password, port, data, use_ssl) == ERR){
close(sd);
return ERR;
}
list_folders(sd, &seq, &folders[0], sizeof(folders));
list_folders(sd, &seq, &folders[0], sizeof(folders), use_ssl, data);
p = &folders[0];
@ -284,26 +289,26 @@ int import_from_imap_server(char *imapserver, char *username, char *password, st
if(quiet == 0) printf("processing folder: %s... ", puf);
rc = process_imap_folder(sd, &seq, puf, sdata, data, cfg);
rc = process_imap_folder(sd, &seq, puf, sdata, data, use_ssl, cfg);
if(rc == ERR) ret = ERR;
} while(p);
close(sd);
close_connection(sd, data, use_ssl);
return ret;
}
void usage(){
printf("usage: pilerimport [-c <config file>] -e <eml file> | -m <mailbox file> | -d <directory> | -i <imap server> -u <imap username> -p <imap password> [-F <foldername>] [-R] [-r] [-q]\n");
printf("usage: pilerimport [-c <config file>] -e <eml file> | -m <mailbox file> | -d <directory> | -i <imap server> -u <imap username> -p <imap password> -P <imap port> [-F <foldername>] [-R] [-r] [-q]\n");
exit(0);
}
int main(int argc, char **argv){
int i, c, rc=0, n_mbox=0, tot_msgs=0;
int i, c, rc=0, n_mbox=0, tot_msgs=0, port=143;
char *configfile=CONFIG_FILE, *emlfile=NULL, *mboxdir=NULL, *mbox[MBOX_ARGS], *directory=NULL;
char *imapserver=NULL, *username=NULL, *password=NULL, *skiplist=SKIPLIST, *folder=NULL;
struct session_data sdata;
@ -330,6 +335,7 @@ int main(int argc, char **argv){
{"imapserver", required_argument, 0, 'i' },
{"username", required_argument, 0, 'u' },
{"password", required_argument, 0, 'p' },
{"port", required_argument, 0, 'P' },
{"skiplist", required_argument, 0, 'x' },
{"folder", required_argument, 0, 'F' },
{"quiet", required_argument, 0, 'q' },
@ -341,9 +347,9 @@ int main(int argc, char **argv){
int option_index = 0;
c = getopt_long(argc, argv, "c:m:M:e:d:i:u:p:x:F:Rrqh?", long_options, &option_index);
c = getopt_long(argc, argv, "c:m:M:e:d:i:u:p:P:x:F:Rrqh?", long_options, &option_index);
#else
c = getopt(argc, argv, "c:m:M:e:d:i:u:p:x:F:Rrqh?");
c = getopt(argc, argv, "c:m:M:e:d:i:u:p:P:x:F:Rrqh?");
#endif
if(c == -1) break;
@ -387,6 +393,10 @@ int main(int argc, char **argv){
password = optarg;
break;
case 'P' :
port = atoi(optarg);
break;
case 'x' :
skiplist = optarg;
break;
@ -470,7 +480,7 @@ int main(int argc, char **argv){
}
if(mboxdir) rc = import_mbox_from_dir(mboxdir, &sdata, &data, &tot_msgs, &cfg);
if(directory) rc = import_from_maildir(directory, &sdata, &data, &tot_msgs, &cfg);
if(imapserver && username && password) rc = import_from_imap_server(imapserver, username, password, &sdata, &data, skiplist, &cfg);
if(imapserver && username && password) rc = import_from_imap_server(imapserver, username, password, port, &sdata, &data, skiplist, &cfg);
free_rule(data.archiving_rules);