added SSL support for POP using OpenSSL
authorChristoph Hohmann <reboot@gmx.ch>
Tue, 10 Jul 2001 15:21:51 +0000 (15:21 +0000)
committerChristoph Hohmann <reboot@gmx.ch>
Tue, 10 Jul 2001 15:21:51 +0000 (15:21 +0000)
fixed a bug in compose button

13 files changed:
ChangeLog.claws
acconfig.h
configure.in
src/inc.c
src/main.c
src/main.h
src/mainwindow.c
src/md5.c
src/md5.h
src/prefs_account.c
src/prefs_account.h
src/socket.c
src/socket.h

index a407796..742f0da 100644 (file)
@@ -1,3 +1,20 @@
+2001-07-10 [christoph]
+
+       * acconfig.h
+       * configure.in
+               added --enable-ssl
+       * src/md5.[ch]
+               renamed MD5_CTX to MD5_CTX_syl
+               conflicts with a struct in openssl
+       * src/inc.c
+       * src/main.[ch]
+       * src/prefs_account.[ch]
+       * src/socket.[ch]
+               SSL support for POP
+       * src/mainwindow.c
+               fixed compose with current account
+               broken by new compose button stuff
+
 2001-07-09 [hoa]
 
        * AUTHORS
index 898a120..a70cfa1 100644 (file)
@@ -24,6 +24,9 @@
 /* Define if we use GPGME to support OpenPGP */
 #undef USE_GPGME
 
+/* Define if we use GPGME to support OpenPGP */
+#undef USE_SSL
+
 /* Define to `unsigned int' if <stddef.h> or <wchar.h> doesn't define.  */
 #undef wint_t
 
index 073755c..4ee9aeb 100644 (file)
@@ -100,6 +100,29 @@ if test $ac_cv_enable_gpgme = yes; then
        AM_PATH_GPGME(0.2.1, AC_DEFINE(USE_GPGME), [use_gpgme=no])
 fi
 
+dnl Use OpenSSL for SSL connections 
+AC_MSG_CHECKING([whether to use ssl])
+AC_ARG_ENABLE(ssl,
+       [  --enable-ssl            Enable SSL support using OpenSSL [default=no]],
+       [ac_cv_enable_ssl=$enableval], [ac_cv_enable_ssl=no])
+if test $ac_cv_enable_ssl = yes; then
+       AC_MSG_RESULT(yes)
+else
+       AC_MSG_RESULT(no)
+fi
+
+if test $ac_cv_enable_ssl = yes; then
+       AC_MSG_CHECKING([whether to openssl is available])
+       LIBS="$LIBS -lssl"
+       AC_TRY_LINK([
+#include <openssl/opensslv.h>
+],     [ return(OPENSSL_VERSION_NUMBER); ],
+       [ AC_MSG_RESULT(yes)
+         AC_DEFINE(USE_SSL) ],
+       [ AC_MSG_RESULT(no) 
+         LIBS="$ac_save_LIBS" ])
+fi
+         
 dnl Check for X-Face support
 AC_ARG_ENABLE(compface,
        [  --disable-compface      Do not use compface (X-Face)],
index aac1acd..8fe0b65 100644 (file)
--- a/src/inc.c
+++ b/src/inc.c
@@ -262,7 +262,10 @@ static IncProgressDialog *inc_progress_dialog_create(void)
                           GTK_SIGNAL_FUNC(inc_cancel), dialog);
        gtk_signal_connect(GTK_OBJECT(progress->window), "delete_event",
                           GTK_SIGNAL_FUNC(gtk_true), NULL);
-       manage_window_set_transient(GTK_WINDOW(progress->window));
+       if((prefs_common.receive_dialog == RECVDIALOG_ALWAYS) ||
+           ((prefs_common.receive_dialog == RECVDIALOG_WINDOW_ACTIVE) && focus_window)) {
+               manage_window_set_transient(GTK_WINDOW(progress->window));
+       }
 
        progress_dialog_set_value(progress, 0.0);
 
@@ -401,8 +404,11 @@ static void inc_start(IncProgressDialog *inc_dialog)
                        pass = input_dialog_with_invisible(_("Input password"),
                                                           message, NULL);
                        g_free(message);
-                       manage_window_focus_in(inc_dialog->mainwin->window,
-                                              NULL, NULL);
+                       if((prefs_common.receive_dialog == RECVDIALOG_ALWAYS) ||
+                           ((prefs_common.receive_dialog == RECVDIALOG_WINDOW_ACTIVE) && focus_window)) {
+                               manage_window_focus_in(inc_dialog->mainwin->window,
+                                                      NULL, NULL);
+                       }
                        if (pass) {
                                pop3_state->ac_prefs->tmp_pass = g_strdup(pass);
                                pop3_state->pass = pass;
@@ -430,7 +436,10 @@ static void inc_start(IncProgressDialog *inc_dialog)
 
                if (pop3_state->error_val == PS_AUTHFAIL) {
                        if(!prefs_common.noerrorpanel) {
-                               manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
+                               if((prefs_common.receive_dialog == RECVDIALOG_ALWAYS) ||
+                                   ((prefs_common.receive_dialog == RECVDIALOG_WINDOW_ACTIVE) && focus_window)) {
+                                       manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
+                               }
                                alertpanel_error
                                        (_("Authorization for %s on %s failed"),
                                         pop3_state->user,
@@ -439,8 +448,11 @@ static void inc_start(IncProgressDialog *inc_dialog)
                }
 
                statusbar_pop_all();
-               manage_window_focus_in(inc_dialog->mainwin->window, NULL, NULL);
-
+               if((prefs_common.receive_dialog == RECVDIALOG_ALWAYS) ||
+                   ((prefs_common.receive_dialog == RECVDIALOG_WINDOW_ACTIVE) && focus_window)) {
+                       manage_window_focus_in(inc_dialog->mainwin->window, NULL, NULL);
+               }
+               
                folder_item_scan_foreach(pop3_state->folder_table);
                folderview_update_item_foreach(pop3_state->folder_table);
 
@@ -525,8 +537,13 @@ static IncState inc_pop3_session_do(IncSession *session)
        atm->num = POP3_GREETING_RECV;
 
        server = pop3_state->ac_prefs->recv_server;
+#if USE_SSL
+       port = pop3_state->ac_prefs->set_popport ?
+               pop3_state->ac_prefs->popport : (pop3_state->ac_prefs->pop_ssl ? 995 : 110);
+#else
        port = pop3_state->ac_prefs->set_popport ?
                pop3_state->ac_prefs->popport : 110;
+#endif
 
        buf = g_strdup_printf(_("Connecting to POP3 server: %s ..."), server);
        log_message("%s\n", buf);
@@ -542,7 +559,10 @@ static IncState inc_pop3_session_do(IncSession *session)
                log_warning(_("Can't connect to POP3 server: %s:%d\n"),
                            server, port);
                if(!prefs_common.noerrorpanel) {
-                       manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
+                       if((prefs_common.receive_dialog == RECVDIALOG_ALWAYS) ||
+                           ((prefs_common.receive_dialog == RECVDIALOG_WINDOW_ACTIVE) && focus_window)) {
+                               manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
+                       }
                        alertpanel_error(_("Can't connect to POP3 server: %s:%d"),
                                         server, port);
                        manage_window_focus_out(inc_dialog->dialog->window, NULL, NULL);
@@ -558,6 +578,66 @@ static IncState inc_pop3_session_do(IncSession *session)
        pop3_state->sockinfo = sockinfo;
        atm->help_sock = sockinfo;
 
+#ifdef USE_SSL
+       if(pop3_state->ac_prefs->pop_ssl) {
+               X509 *server_cert;
+
+               if(ssl_ctx == NULL) {
+                       log_warning(_("SSL not available\n"));
+
+                       pop3_automaton_terminate(NULL, atm);
+                       automaton_destroy(atm);
+
+                       return INC_ERROR;
+               }
+
+               sockinfo->ssl = SSL_new(ssl_ctx);
+               if(sockinfo->ssl == NULL) {
+                       log_warning(_("Error creating ssl context\n"));
+
+                       pop3_automaton_terminate(NULL, atm);
+                       automaton_destroy(atm);
+
+                       return INC_ERROR;
+               }
+               SSL_set_fd(sockinfo->ssl, sockinfo->sock);
+               if(SSL_connect(sockinfo->ssl) == -1) {
+                       log_warning(_("SSL connect failed\n"));
+
+                       pop3_automaton_terminate(NULL, atm);
+                       automaton_destroy(atm);
+
+                       return INC_ERROR;
+               }
+               
+               /* Get the cipher */
+
+               log_print(_("SSL connection using %s\n"), SSL_get_cipher(sockinfo->ssl));
+  
+               /* Get server's certificate (note: beware of dynamic allocation) */
+
+               if((server_cert = SSL_get_peer_certificate(sockinfo->ssl)) != NULL) {
+                       char *str;
+                       
+                       log_print(_("Server certificate:\n"));
+  
+                       if((str = X509_NAME_oneline(X509_get_subject_name (server_cert),0,0)) != NULL) {
+                               log_print(_("  Subject: %s\n"), str);
+                               free(str);
+                       }
+                       
+                       if((str = X509_NAME_oneline(X509_get_issuer_name  (server_cert),0,0)) != NULL) {
+                               log_print(_("  Issuer: %s\n"), str);
+                               free(str);
+                       }
+
+                       X509_free(server_cert);
+               }
+       } else {
+               sockinfo->ssl = NULL;
+       }
+#endif
+
        recv_set_ui_func(inc_pop3_recv_func, session);
 
 #if USE_THREADS
@@ -578,6 +658,13 @@ static IncState inc_pop3_session_do(IncSession *session)
        pthread_join(sockinfo->connect_thr, NULL);
 */     
 #endif
+
+#if USE_SSL
+       if(sockinfo->ssl) {
+               SSL_free(sockinfo->ssl);
+       }
+#endif
+
        automaton_destroy(atm);
 
        return pop3_state->inc_state;
@@ -679,7 +766,10 @@ static gint connection_check_cb(Automaton *atm)
                log_warning(_("Can't connect to POP3 server: %s:%d\n"),
                            sockinfo->hostname, sockinfo->port);
                if(!prefs_common.noerrorpanel) {
-                       manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
+                       if((prefs_common.receive_dialog == RECVDIALOG_ALWAYS) ||
+                           ((prefs_common.receive_dialog == RECVDIALOG_WINDOW_ACTIVE) && focus_window)) {
+                               manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
+                       }
                        alertpanel_error(_("Can't connect to POP3 server: %s:%d"),
                                         sockinfo->hostname, sockinfo->port);
                        manage_window_focus_out(inc_dialog->dialog->window, NULL, NULL);
index b7bac27..61f4419 100644 (file)
@@ -83,6 +83,10 @@ gboolean debug_mode = FALSE;
 static gint lock_socket = -1;
 static gint lock_socket_tag = 0;
 
+#if USE_SSL
+SSL_CTX *ssl_ctx;
+#endif
+
 static struct Cmd {
        gboolean receive;
        gboolean receive_all;
@@ -233,6 +237,22 @@ int main(int argc, char *argv[])
        gpgme_register_idle(idle_function_for_gpgme);
 #endif
 
+#if USE_SSL
+       {
+               SSL_METHOD *meth;
+               
+               SSLeay_add_ssl_algorithms();
+               meth = SSLv2_client_method();
+               SSL_load_error_strings();
+               ssl_ctx = SSL_CTX_new(meth);
+               if(ssl_ctx == NULL) {
+                       debug_print(_("SSL disabled\n"));
+               } else {
+                       debug_print(_("SSL loaded: \n"));
+               }
+       }
+#endif
+
        prefs_common_save_config();
        prefs_filter_read_config();
        prefs_filter_write_config();
@@ -278,6 +298,12 @@ int main(int argc, char *argv[])
 
        gtk_main();
 
+#if USE_SSL
+       if(ssl_ctx) {
+               SSL_CTX_free(ssl_ctx);
+       }
+#endif
+
        return 0;
 }
 
index 0fb8c56..dffb291 100644 (file)
 #include <glib.h>
 #include <gtk/gtkwidget.h>
 
+#ifdef USE_SSL
+#include <openssl/crypto.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif
+
 extern gchar *prog_version;
 extern gchar *startup_dir;
 extern gboolean debug_mode;
 
+#ifdef USE_SSL
+extern SSL_CTX *ssl_ctx;
+#endif
+
 void app_will_exit     (GtkWidget *widget, gpointer data);
 
 #endif /* __MAIN_H__ */
index 1d48030..a1939ad 100644 (file)
@@ -2179,6 +2179,11 @@ static void compose_mail_cb(MainWindow *mainwin, guint action,
                }
        }
 
+       if(cur_account && (cur_account->protocol != A_NNTP)) {
+               compose_new(cur_account);
+               return;
+       }
+
        list = account_get_list();
        for(cur = list ; cur != NULL ; cur = g_list_next(cur)) {
                ac = (PrefsAccount *) cur->data;
index fb999ff..fcc8f96 100644 (file)
--- a/src/md5.c
+++ b/src/md5.c
@@ -333,7 +333,7 @@ void
 md5_hex_digest(char *hexdigest, const unsigned char *s)
 {
        int i;
-       MD5_CTX context;
+       MD5_CTX_syl context;
        unsigned char digest[16];
 
        md5_init(&context);
@@ -355,7 +355,7 @@ md5_hmac(unsigned char *digest,
         const unsigned char* text, int text_len,
         const unsigned char* key, int key_len)
 {
-       MD5_CTX context;
+       MD5_CTX_syl context;
        unsigned char k_ipad[64];    /* inner padding -
                                      * key XORd with ipad
                                      */
@@ -370,7 +370,7 @@ md5_hmac(unsigned char *digest,
        memset(k_opad, 0, sizeof k_opad);
        if (key_len > 64) {
                /* if key is longer than 64 bytes reset it to key=MD5(key) */
-               MD5_CTX tctx;
+               MD5_CTX_syl tctx;
 
                md5_init(&tctx);
                md5_update(&tctx, key, key_len);
index 013a305..a3783da 100644 (file)
--- a/src/md5.h
+++ b/src/md5.h
@@ -32,7 +32,7 @@ typedef struct {  /* Hmm, should be private */
     int  finalized;
 } MD5_CONTEXT;
 
-typedef MD5_CONTEXT MD5_CTX;
+typedef MD5_CONTEXT MD5_CTX_syl;
 
 void md5_init(MD5_CONTEXT *ctx);
 void md5_update(MD5_CONTEXT *hd, const unsigned char *inbuf, size_t inlen);
index 2b8e622..0ec0365 100644 (file)
@@ -130,6 +130,9 @@ static struct Advanced {
        GtkWidget *popport_hbox;
        GtkWidget *popport_chkbtn;
        GtkWidget *popport_entry;
+#if USE_SSL
+       GtkWidget *popssl_chkbtn;
+#endif
        GtkWidget *imapport_hbox;
        GtkWidget *imapport_chkbtn;
        GtkWidget *imapport_entry;
@@ -307,6 +310,12 @@ static PrefParam param[] = {
         &advanced.popport_entry,
         prefs_set_data_from_entry, prefs_set_entry},
 
+#if USE_SSL
+       {"pop_ssl", "FALSE", &tmp_ac_prefs.pop_ssl, P_BOOL,
+        &advanced.popssl_chkbtn,
+        prefs_set_data_from_toggle, prefs_set_toggle},
+#endif
+
        {"set_imapport", "FALSE", &tmp_ac_prefs.set_imapport, P_BOOL,
         &advanced.imapport_chkbtn,
         prefs_set_data_from_toggle, prefs_set_toggle},
@@ -1205,6 +1214,9 @@ static void prefs_account_advanced_create(void)
        GtkWidget *hbox_popport;
        GtkWidget *checkbtn_popport;
        GtkWidget *entry_popport;
+#ifdef USE_SSL
+       GtkWidget *checkbtn_popssl;
+#endif
        GtkWidget *hbox_imapport;
        GtkWidget *checkbtn_imapport;
        GtkWidget *entry_imapport;
@@ -1249,6 +1261,10 @@ static void prefs_account_advanced_create(void)
        PACK_PORT_ENTRY (hbox_popport, entry_popport);
        SET_TOGGLE_SENSITIVITY (checkbtn_popport, entry_popport);
 
+#ifdef USE_SSL
+       PACK_CHECK_BUTTON (vbox2, checkbtn_popssl, _("Use SSL to connect to POP server"));
+#endif
+
        PACK_HBOX (hbox_imapport);
        PACK_CHECK_BUTTON (hbox_imapport, checkbtn_imapport,
                           _("Specify IMAP4 port"));
@@ -1277,6 +1293,9 @@ static void prefs_account_advanced_create(void)
        advanced.popport_hbox           = hbox_popport;
        advanced.popport_chkbtn         = checkbtn_popport;
        advanced.popport_entry          = entry_popport;
+#ifdef USE_SSL
+       advanced.popssl_chkbtn           = checkbtn_popssl;
+#endif
        advanced.imapport_hbox          = hbox_imapport;
        advanced.imapport_chkbtn        = checkbtn_imapport;
        advanced.imapport_entry         = entry_imapport;
index edcfaad..45ca638 100644 (file)
@@ -110,6 +110,9 @@ struct _PrefsAccount
        gushort   smtpport;
        gboolean  set_popport;
        gushort   popport;
+#if USE_SSL
+       gboolean  pop_ssl;
+#endif
        gboolean  set_imapport;
        gushort   imapport;
        gboolean  set_nntpport;
index 1d8f95e..4a8f73f 100644 (file)
@@ -397,6 +397,11 @@ gint sock_read(SockInfo *sock, gchar *buf, gint len)
 {
        g_return_val_if_fail(sock != NULL, -1);
 
+#if USE_SSL
+       if(sock->ssl) {
+               return ssl_read(sock->ssl, buf, len);
+       }
+#endif
        return fd_read(sock->sock, buf, len);
 }
 
@@ -405,10 +410,22 @@ gint fd_read(gint fd, gchar *buf, gint len)
        return read(fd, buf, len);
 }
 
+#ifdef USE_SSL
+gint ssl_read(SSL *ssl, gchar *buf, gint len)
+{
+       return SSL_read(ssl, buf, len);
+}
+#endif
+
 gint sock_write(SockInfo *sock, const gchar *buf, gint len)
 {
        g_return_val_if_fail(sock != NULL, -1);
 
+#if USE_SSL
+       if(sock->ssl) {
+               return ssl_write(sock->ssl, buf, len);
+       }
+#endif
        return fd_write(sock->sock, buf, len);
 }
 
@@ -428,6 +445,24 @@ gint fd_write(gint fd, const gchar *buf, gint len)
        return wrlen;
 }
 
+#ifdef USE_SSL
+gint ssl_write(SSL *ssl, const gchar *buf, gint len)
+{
+       gint n, wrlen = 0;
+
+       while (len) {
+               n = SSL_write(ssl, buf, len);
+               if (n <= 0)
+                       return -1;
+               len -= n;
+               wrlen += n;
+               buf += n;
+       }
+
+       return wrlen;
+}
+#endif
+
 gint fd_gets(gint fd, gchar *buf, gint len)
 {
        gchar *newline, *bp = buf;
@@ -450,10 +485,39 @@ gint fd_gets(gint fd, gchar *buf, gint len)
        return bp - buf;
 }
 
+#if USE_SSL
+gint ssl_gets(SSL *ssl, gchar *buf, gint len)
+{
+       gchar *buf2 = buf;
+       gboolean newline = FALSE;
+       gint n, count = 0;
+
+       if (--len < 1)
+               return -1;
+       while(len > 0 && !newline) {
+               *buf2 = '\0';
+               if((n = SSL_read(ssl, buf2, 1)) < 0)
+                       return -1;
+               if(*buf2 == '\n')
+                       newline = TRUE;
+               buf2 += n;
+               count += n;
+       }
+
+       *buf2 = '\0';
+       return n;
+}
+#endif
+
 gint sock_gets(SockInfo *sock, gchar *buf, gint len)
 {
        g_return_val_if_fail(sock != NULL, -1);
 
+#if USE_SSL
+       if(sock->ssl) {
+               return ssl_gets(sock->ssl, buf, len);
+       }
+#endif
        return fd_gets(sock->sock, buf, len);
 }
 
@@ -479,10 +543,39 @@ gchar *fd_getline(gint fd)
        return str;
 }
 
+#if USE_SSL
+gchar *ssl_getline(SSL *ssl)
+{
+       gchar buf[BUFFSIZE];
+       gchar *str = NULL;
+       gint len;
+       gulong size = 1;
+
+       while ((len = ssl_gets(ssl, buf, sizeof(buf))) > 0) {
+               size += len;
+               if (!str)
+                       str = g_strdup(buf);
+               else {
+                       str = g_realloc(str, size);
+                       strcat(str, buf);
+               }
+               if (buf[len - 1] == '\n')
+                       break;
+       }
+
+       return str;
+}
+#endif
+
 gchar *sock_getline(SockInfo *sock)
 {
        g_return_val_if_fail(sock != NULL, NULL);
 
+#if USE_SSL
+       if(sock->ssl) {
+               return ssl_getline(sock->ssl);
+       }
+#endif
        return fd_getline(sock->sock);
 }
 
index 93eaa36..a3a99f3 100644 (file)
 #  include <pthread.h>
 #endif
 
+#if USE_SSL
+#  include <openssl/crypto.h>
+#  include <openssl/x509.h>
+#  include <openssl/pem.h>
+#  include <openssl/ssl.h>
+#  include <openssl/err.h>
+#endif
+
 typedef struct _SockInfo       SockInfo;
 
 typedef enum
@@ -59,6 +67,9 @@ struct _SockInfo
        pthread_t connect_thr;
        pthread_mutex_t mutex;
 #endif
+#if USE_SSL
+       SSL *ssl;
+#endif
 };
 
 gint sock_set_nonblocking_mode         (SockInfo *sock, gboolean nonblock);