? missing ? autom4te.cache ? install-sh ? mkinstalldirs ? pan-0.11.3.90-ssl.patch ? test ? test.c ? text.patch ? docs/temp ? gmime/temp ? libcamel/temp ? macros/temp ? pan/temp ? pan/filters/tasks.dtd ? pan/filters/~tasks.dtd ? pan/xpm/.xvpics ? po/temp ? tests/temp Index: configure.in =================================================================== RCS file: /cvs/gnome/pan/configure.in,v retrieving revision 1.172.2.4 diff -u -r1.172.2.4 configure.in --- configure.in 2002/05/07 21:30:10 1.172.2.4 +++ configure.in 2002/06/05 01:25:29 @@ -180,6 +180,27 @@ AC_SUBST(GNOME_XML_CFLAGS) AC_SUBST(GNOME_XML_LIBS) +dnl Check for OpenSSL +AC_ARG_ENABLE(ssl, + [ --enable-ssl Enable SSL with OpenSSL [default=no]], + [ac_cv_enable_ssl=$enableval], [ac_cv_enable_ssl=no]) +AC_MSG_CHECKING([whether to use OpenSSL]) +if test $ac_cv_enable_ssl = yes; then + AC_MSG_RESULT(yes) + AC_MSG_CHECKING([if openssl is available]) + LIBS="$LIBS -lssl -lcrypto" + AC_TRY_LINK([ +#include +], [ return OPENSSL_VERSION_NUMBER; ], + [ AC_MSG_RESULT(yes) + AC_DEFINE(USE_SSL) ], + [ AC_MSG_RESULT(no) + LIBS="$ac_save_LIBS" + ac_cv_enable_ssl=no ]) +else + AC_MSG_RESULT(no) +fi + dnl ****************************** dnl Makefiles Index: pan/prefs.c =================================================================== RCS file: /cvs/gnome/pan/pan/prefs.c,v retrieving revision 1.229.2.12 diff -u -r1.229.2.12 prefs.c --- pan/prefs.c 2002/05/15 20:26:39 1.229.2.12 +++ pan/prefs.c 2002/06/05 01:25:44 @@ -74,6 +74,10 @@ GtkWidget * server_password_label; GtkWidget * server_password; GtkWidget * msgid_cbutton; +#ifdef USE_SSL + GtkWidget * use_ssl_cbutton; + GtkWidget * server_ssl_port; +#endif GtkWidget * idle_secs_before_timeout; Server * server; } @@ -839,6 +843,10 @@ old->max_connections = new->max_connections; old->idle_secs_before_timeout = new->idle_secs_before_timeout; old->gen_msgid = new->gen_msgid; +#ifdef USE_SSL + old->use_ssl = new->use_ssl; + old->ssl_port = new -> ssl_port; +#endif } else { @@ -1155,6 +1163,10 @@ server->port = atoi((gtk_entry_get_text (GTK_ENTRY(sprof->server_port)))); server->need_auth = (!GTK_TOGGLE_BUTTON (sprof->auth_cbutton)->active) ? 0 : 1; server->gen_msgid = (!GTK_TOGGLE_BUTTON (sprof->msgid_cbutton)->active) ? 0 : 1; +#ifdef USE_SSL + server->use_ssl = (!GTK_TOGGLE_BUTTON (sprof->use_ssl_cbutton)->active) ? 0 : 1; + server->ssl_port = atoi((gtk_entry_get_text (GTK_ENTRY(sprof->server_ssl_port)))); +#endif server->username = gtk_editable_get_chars (GTK_EDITABLE (sprof->server_username), 0, -1); server->password = gtk_editable_get_chars (GTK_EDITABLE (sprof->server_password), 0, -1); server->idle_secs_before_timeout = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (sprof->idle_secs_before_timeout)); @@ -1418,6 +1430,33 @@ connect_signal_to_profile_changed (w, "toggled", dialog); gtk_box_pack_start (GTK_BOX(vbox), w, FALSE, FALSE, 0); sprof->msgid_cbutton = w; + +#ifdef USE_SSL + hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL); + + /* TOGGLE: Use SSL */ + w = gtk_check_button_new_with_label (_("Use SSL on port: ")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(w), server && server->use_ssl); + connect_signal_to_prefs_changed (w, "toggled"); + connect_signal_to_profile_changed (w, "toggled", dialog); + gtk_box_pack_start (GTK_BOX(hbox), w, FALSE, FALSE, 0); + sprof->use_ssl_cbutton = w; + + /* server ssl port */ + w = gtk_entry_new (); + if (1) { + int num = server && server->ssl_port ? server->ssl_port : 563; + char buf[32]; + g_snprintf (buf, sizeof(buf), "%d", num); + gtk_entry_set_text (GTK_ENTRY(w), buf); + } + connect_signal_to_prefs_changed (w, "changed"); + connect_signal_to_profile_changed (w, "changed", dialog); + gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); + sprof->server_ssl_port = w; + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + +#endif gtk_table_attach (GTK_TABLE(table), frame, 0, 2, 7, 9, Index: pan/queue.c =================================================================== RCS file: /cvs/gnome/pan/pan/queue.c,v retrieving revision 1.214.2.8 diff -u -r1.214.2.8 queue.c --- pan/queue.c 2002/05/07 22:28:43 1.214.2.8 +++ pan/queue.c 2002/06/05 01:25:46 @@ -861,7 +861,14 @@ debug1 (DEBUG_QUEUE, "making a new socket to %s", server->address); gui_set_connecting_flag (TRUE); +#ifndef USE_SSL sock = pan_socket_new (server->address, server->port); +#else + if (server->use_ssl) + sock = pan_socket_new_ssl (server->address, server->ssl_port); + else + sock = pan_socket_new (server->address, server->port); +#endif pan_socket_set_nntp_auth (sock, server->need_auth, server->username, server->password); debug1 (DEBUG_QUEUE, "new socket %p", sock); Index: pan/sockets.c =================================================================== RCS file: /cvs/gnome/pan/pan/sockets.c,v retrieving revision 1.96.2.1 diff -u -r1.96.2.1 sockets.c --- pan/sockets.c 2002/04/05 21:23:28 1.96.2.1 +++ pan/sockets.c 2002/06/05 01:25:47 @@ -45,6 +45,15 @@ #include +#ifdef USE_SSL +# include +# include +# include +# include +# include +#endif + + /********************* ********************** Defines / Enumerated types *********************/ @@ -55,6 +64,11 @@ ********************** Variables *********************/ +#ifdef USE_SSL +static SSL_CTX *ssl_ctx_SSLv23; +static SSL_CTX *ssl_ctx_TLSv1; +#endif + static gulong total_bytes = 0; /********************* @@ -78,6 +92,29 @@ return sock; } +#ifdef USE_SSL +PanSocket* +pan_socket_new_ssl (const gchar * address, + gint port) +{ + PanSocket * sock; + + if(ssl_ctx_SSLv23 == NULL) + ssl_init(); + + /* sanity clause */ + g_return_val_if_fail (is_nonempty_string (address), NULL); + g_return_val_if_fail (port>=0, NULL); + + /* create the socket */ + sock = g_new0 (PanSocket, 1); + debug1 (DEBUG_PAN_OBJECT, "pan_socket_new_ssl: %p", sock); + pan_socket_constructor (sock, pan_socket_destructor, address, port); + if(!ssl_init_socket(sock)) + fprintf(stderr,"ssl_init_socket failed\n"); + return sock; +} +#endif void pan_socket_constructor (PanSocket * sock, PanObjectDestructor destructor, @@ -123,7 +160,9 @@ sock->nntp_group_name = NULL; sock->nntp_username = NULL; sock->nntp_password = NULL; - +#ifdef USE_SSL + sock->ssl = NULL; +#endif /* set up the serv_addr struct */ memset ( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = AF_INET; @@ -227,28 +266,42 @@ FD_SET (ps->sockfd, &read_fds); /* wait 60 seconds for an OK to read */ - errno = 0; - tv.tv_sec = 60; - tv.tv_usec = 0; - retval = select (ps->sockfd+1, &read_fds, NULL, NULL, &tv); - my_errno = errno; + /* [Colin] I don't know why this doesn't work over ssl :-/ */ +#ifdef USE_SSL + if(!ps->ssl) { +#endif + errno = 0; + tv.tv_sec = 60; + tv.tv_usec = 0; + retval = select (ps->sockfd+1, &read_fds, NULL, NULL, &tv); + my_errno = errno; - /* did select fail? */ - if (!FD_ISSET(ps->sockfd, &read_fds)) - { - GString * str = g_string_new (NULL); - g_string_sprintf (str, _("Timed out waiting to read from the server.")); - if (my_errno != 0) - g_string_sprintfa (str, " %s", g_strerror(my_errno)); - log_add (LOG_ERROR, str->str); - ps->error = TRUE; - g_string_free (str, TRUE); - return -1; + /* did select fail? */ + if (!FD_ISSET(ps->sockfd, &read_fds)) + { + GString * str = g_string_new (NULL); + g_string_sprintf (str, _("Timed out waiting to read from the server.")); + if (my_errno != 0) + g_string_sprintfa (str, " %s", g_strerror(my_errno)); + log_add (LOG_ERROR, str->str); + ps->error = TRUE; + g_string_free (str, TRUE); + return -1; + } +#ifdef USE_SSL } +#endif /* try to read from the server... */ errno = 0; +#ifdef USE_SSL + if(ps->ssl) + read_count = ssl_read (ps->ssl, ps->inbuf, BUFSIZE); + else + read_count = read (ps->sockfd, ps->inbuf, BUFSIZE); +#else read_count = read (ps->sockfd, ps->inbuf, BUFSIZE); +#endif my_errno = errno; ps->endbuf = ps->inbuf + read_count; ps->inptr = ps->inbuf; @@ -387,7 +440,14 @@ } /* try to write to the server... */ +#ifdef USE_SSL + if(sock->ssl) + nwritten = ssl_write (sock->ssl, pch, nleft); + else + nwritten = write (sock->sockfd, pch, nleft); +#else nwritten = write (sock->sockfd, pch, nleft); +#endif sock->bytes_written += nwritten; if (nwritten == -1) { log_add (LOG_ERROR, _("An error occurred writing to the server.")); @@ -502,3 +562,155 @@ { return total_bytes / (gulong)1024; } + +#ifdef USE_SSL +/* the following SSL code adapted from Sylpheed-claws + http://sylpheed-claws.sourceforge.net/ */ + +void ssl_init(void) +{ + SSL_library_init(); + SSL_load_error_strings(); + + ssl_ctx_SSLv23 = SSL_CTX_new(SSLv23_client_method()); + if (ssl_ctx_SSLv23 == NULL) { + fprintf(stderr,"SSLv23 not available\n"); + } else { + fprintf(stderr,"SSLv23 available\n"); + } + + ssl_ctx_TLSv1 = SSL_CTX_new(TLSv1_client_method()); + if (ssl_ctx_TLSv1 == NULL) { + fprintf(stderr,"TLSv1 not available\n"); + } else { + fprintf(stderr,"TLSv1 available\n"); + } +} + +void ssl_done(void) +{ + if (ssl_ctx_SSLv23) { + SSL_CTX_free(ssl_ctx_SSLv23); + } + + if (ssl_ctx_TLSv1) { + SSL_CTX_free(ssl_ctx_TLSv1); + } +} + +gboolean ssl_init_socket(PanSocket *sockinfo) +{ + return ssl_init_socket_with_method(sockinfo, SSL_METHOD_SSLv23); +} + +gboolean ssl_init_socket_with_method(PanSocket *sockinfo, SSLMethod method) +{ + X509 *server_cert; + gint ret; + + switch (method) { + case SSL_METHOD_SSLv23: + if (!ssl_ctx_SSLv23) { + fprintf(stderr,"SSL method not available\n"); + return FALSE; + } + sockinfo->ssl = SSL_new(ssl_ctx_SSLv23); + break; + case SSL_METHOD_TLSv1: + if (!ssl_ctx_TLSv1) { + fprintf(stderr,"SSL method not available\n"); + return FALSE; + } + sockinfo->ssl = SSL_new(ssl_ctx_TLSv1); + break; + default: + fprintf(stderr,"Unknown SSL method *PROGRAM BUG*\n"); + return FALSE; + break; + } + + if (sockinfo->ssl == NULL) { + fprintf(stderr,"Error creating ssl context\n"); + return FALSE; + } + + SSL_set_fd(sockinfo->ssl, sockinfo->sockfd); + if ((ret = SSL_connect(sockinfo->ssl)) == -1) { + fprintf(stderr,"SSL connect failed (%s)\n", + ERR_error_string(ERR_get_error(), NULL)); + return FALSE; + } + + /* Get the cipher */ + + fprintf(stderr,"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) { + gchar *str; + + fprintf(stderr,"Server certificate:\n"); + + if ((str = X509_NAME_oneline(X509_get_subject_name(server_cert), 0, 0)) != NULL) { + fprintf(stderr," Subject: %s\n", str); + free(str); + } + + if ((str = X509_NAME_oneline(X509_get_issuer_name(server_cert), 0, 0)) != NULL) { + fprintf(stderr," Issuer: %s\n", str); + free(str); + } + + X509_free(server_cert); + } + + return TRUE; +} + +void ssl_done_socket(PanSocket *sockinfo) +{ + if (sockinfo->ssl) { + SSL_free(sockinfo->ssl); + } +} + +gint ssl_read(SSL *ssl, gchar *buf, gint len) +{ + gchar *newline, *bp = buf; + gint n; + + if (--len < 1) + return -1; + do { + if ((n = SSL_peek(ssl, bp, len)) <= 0) + return -1; + if ((newline = memchr(bp, '\n', n)) != NULL) + n = newline - bp + 1; + if ((n = SSL_read(ssl, bp, n)) < 0) + return -1; + bp += n; + len -= n; + } while (!newline && len); + + *bp = '\0'; + return bp - buf; +} + +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 /* USE_SSL */ Index: pan/sockets.h =================================================================== RCS file: /cvs/gnome/pan/pan/sockets.h,v retrieving revision 1.39.2.1 diff -u -r1.39.2.1 sockets.h --- pan/sockets.h 2002/04/05 21:23:29 1.39.2.1 +++ pan/sockets.h 2002/06/05 01:25:48 @@ -27,6 +27,14 @@ #define PAN_SOCKET(a) ((PanSocket *)a) +#ifdef USE_SSL +# include +# include +# include +# include +# include +#endif + typedef struct _PanSocket PanSocket; struct _PanSocket @@ -50,7 +58,9 @@ gchar * nntp_username; gchar * nntp_password; GArray * line_buffer; - +#ifdef USE_SSL + SSL *ssl; +#endif /* statistics */ gchar * host; unsigned int bytes_read; @@ -76,6 +86,11 @@ PanSocket* pan_socket_new (const gchar * address, int port); +#ifdef USE_SSL +PanSocket* pan_socket_new_ssl (const gchar * address, + int port); +#endif + void pan_socket_set_nntp_auth (PanSocket * socket, gboolean need_auth, const gchar * username, @@ -113,6 +128,23 @@ void pan_socket_reset_statistics (PanSocket * sock); gulong pan_socket_get_total_xfer_K (void); + +#ifdef USE_SSL +typedef enum { + SSL_METHOD_SSLv23, + SSL_METHOD_TLSv1 +} SSLMethod; + +void ssl_init (void); +void ssl_done (void); +gboolean ssl_init_socket (PanSocket *sockinfo); +gboolean ssl_init_socket_with_method (PanSocket *sockinfo, + SSLMethod method); +void ssl_done_socket (PanSocket *sockinfo); +gint ssl_read (SSL *ssl, gchar *buf, gint len); +gint ssl_write (SSL *ssl, const gchar *buf, gint len); + +#endif /* USE_SSL */ #endif /* __PAN_SOCKET_H__ */ Index: pan/base/server.c =================================================================== RCS file: /cvs/gnome/pan/pan/base/server.c,v retrieving revision 1.11.2.5 diff -u -r1.11.2.5 server.c --- pan/base/server.c 2002/05/06 16:03:37 1.11.2.5 +++ pan/base/server.c 2002/06/05 01:25:53 @@ -62,6 +62,10 @@ debug1 (DEBUG_PAN_OBJECT, "server_constructor: %p", server); server->posting = FALSE; server->gen_msgid = FALSE; +#ifdef USE_SSL + server->use_ssl = FALSE; + server->ssl_port = 563; +#endif USE_SSL server->need_auth = FALSE; server->reserve_connection_for_bodies = TRUE; server->address = NULL; Index: pan/base/server.h =================================================================== RCS file: /cvs/gnome/pan/pan/base/server.h,v retrieving revision 1.7.2.3 diff -u -r1.7.2.3 server.h --- pan/base/server.h 2002/05/06 16:03:37 1.7.2.3 +++ pan/base/server.h 2002/06/05 01:25:53 @@ -51,11 +51,17 @@ /*Fields*/ guint posting : 1; /* is posting allowed? */ guint gen_msgid : 1; +#ifdef USE_SSL + guint use_ssl : 1; /* connect via ssl? */ +#endif guint need_auth : 1; /* need authorization ? */ guint reserve_connection_for_bodies : 1; gint8 max_connections; /* max connections to server */ gint16 idle_secs_before_timeout; gint port; /* port number. This is usually 119 for NNTP. */ +#ifdef USE_SSL + gint ssl_port; /* ssl port. Usually 563 */ +#endif time_t last_newgroup_list_time; gchar * address; /* server net address */ gchar * name; /* pretty name, i.e. Erols */ Index: pan/base/serverlist.c =================================================================== RCS file: /cvs/gnome/pan/pan/base/serverlist.c,v retrieving revision 1.9.2.3 diff -u -r1.9.2.3 serverlist.c --- pan/base/serverlist.c 2002/05/06 04:12:12 1.9.2.3 +++ pan/base/serverlist.c 2002/06/05 01:25:54 @@ -145,6 +145,12 @@ g_strdup(name); server->gen_msgid = pan_config_get_int ("Generate_Msgid=0"); +#ifdef USE_SSL + server->use_ssl = + pan_config_get_int ("Use_SSL=0"); + server->ssl_port = + pan_config_get_int ("SSL_Port=563"); +#endif server->need_auth = pan_config_get_int ("Auth_Required=0"); server->username = @@ -410,7 +416,13 @@ g_snprintf (buf, sizeof(buf), "/Pan/%s/Generate_Msgid", sn); pan_config_set_int (buf, s->gen_msgid); - +#ifdef USE_SSL + g_snprintf (buf, sizeof(buf), "/Pan/%s/Use_SSL", sn); + pan_config_set_int (buf, s->use_ssl); + + g_snprintf (buf, sizeof(buf), "/Pan/%s/SSL_Port", sn); + pan_config_set_int (buf, s->ssl_port); +#endif g_snprintf (buf, sizeof(buf), "/Pan/%s/Username", sn); pan_config_set_string (buf, s->username);