--- gnubiff-2.2.9.orig/src/gnubiff_options.cc 2007-09-08 17:57:56 +0300
+++ gnubiff-2.2.9.orig/src/gnubiff_options.cc 2008-02-09 15:37:44 +0200
@@ -427,9 +427,9 @@
"address_entry"));
// AUTHENTICATION
const static guint i4[] = {AUTH_AUTODETECT, AUTH_USER_PASS, AUTH_APOP,
- AUTH_SSL, AUTH_CERTIFICATE, AUTH_NONE, 0};
+ AUTH_SSL, AUTH_CERTIFICATE, AUTH_TLS, AUTH_NONE, 0};
const static gchar *s4[] = {"autodetect", "user_pass", "apop", "ssl",
- "certificate", "-", NULL};
+ "certificate", "tls", "-", NULL};
add_option (new Option_UInt ("authentication", OPTGRP_MAILBOX,
"Authentication to be used when connecting to the server via the "
"internet.\n"
--- gnubiff-2.2.9.orig/src/gnubiff_options.h 2007-09-08 21:06:30 +0300
+++ gnubiff-2.2.9.orig/src/gnubiff_options.h 2008-02-09 15:37:59 +0200
@@ -63,6 +63,7 @@
const guint AUTH_APOP = 2;
const guint AUTH_SSL = 3;
const guint AUTH_CERTIFICATE = 4;
+const guint AUTH_TLS = 5;
const guint AUTH_NONE = (guint)-1;
const guint MAILBOX_ERROR = 0;
--- gnubiff-2.2.9.orig/src/imap4.cc 2008-01-06 22:12:48 +0200
+++ gnubiff-2.2.9.orig/src/imap4.cc 2008-02-09 15:40:30 +0200
@@ -263,6 +263,22 @@
// CAPABILITY
command_capability (true);
+
+#ifdef HAVE_LIBSSL
+ // Negotiate TLS encryption
+ if (authentication() == AUTH_TLS) {
+ if (can_starttls_) {
+ sendline ("STARTTLS");
+ readline (line);
+ if (!socket_->starttls (certificate())) {
+ throw imap_command_err();
+ }
+ } else {
+ command_logout();
+ throw imap_nologin_err();
+ }
+ }
+#endif
// LOGIN
command_login();
@@ -369,6 +385,7 @@
* The command "CAPABILITY" is sent to the server to get the supported
* capabilities. Currently gnubiff recognizes the following capabilities:
* \begin{itemize}
+ * \item STARTTLS: Server supports TLS encryption.
* \item IDLE: If the server has the IDLE capability, gnubiff uses the
* IDLE command instead of polling.
* \item LOGINDISABLED: The server wants us not to login.
@@ -418,7 +435,8 @@
// Looking for supported capabilities
idleable_ = use_idle () && (line.find (" IDLE ") != std::string::npos);
- if (line.find (" LOGINDISABLED ") != std::string::npos) {
+ // Some sites advertise LOGINDISABLED until STARTTLS is used
+ if (line.find (" LOGINDISABLED ") != std::string::npos && line.find (" STARTTLS ") == std::string::npos) {
command_logout();
throw imap_nologin_err();
}
@@ -428,6 +446,9 @@
// CAPABILITY command, maybe the server sends additional capabilities
if (((idleable_ == false) && use_idle()) && check_rc && !command_sent)
command_capability (false);
+
+ // Check for STARTTLS support
+ can_starttls_ = (line.find (" STARTTLS ") != std::string::npos);
}
/**
--- gnubiff-2.2.9.orig/src/imap4.h 2007-09-08 21:06:30 +0300
+++ gnubiff-2.2.9.orig/src/imap4.h 2008-02-09 15:41:00 +0200
@@ -47,6 +47,9 @@
/// Does the server support the IDLE capability?
gboolean idleable_;
+ /// Does the server support STARTTLS?
+ gboolean can_starttls_;
+
/// Is the server currently idled?
gboolean idled_;
--- gnubiff-2.2.9.orig/src/mailbox.cc 2007-09-08 17:57:57 +0300
+++ gnubiff-2.2.9.orig/src/mailbox.cc 2008-02-09 15:41:25 +0200
@@ -231,6 +231,7 @@
return 993;
return ((protocol == PROTOCOL_POP3) ? 995 : 0);
case AUTH_USER_PASS:
+ case AUTH_TLS:
if (protocol == PROTOCOL_IMAP4)
return 143;
return ((protocol == PROTOCOL_POP3) ? 110 : 0);
--- gnubiff-2.2.9.orig/src/socket.cc 2007-09-08 17:57:58 +0300
+++ gnubiff-2.2.9.orig/src/socket.cc 2008-02-09 15:46:04 +0200
@@ -267,6 +267,72 @@
return 1;
}
+gint
+Socket::starttls (std::string certificate)
+{
+#ifdef HAVE_LIBSSL
+ char *err_buf;
+
+ err_buf = (char*) malloc (120);
+
+ context_ = SSL_CTX_new (TLSv1_client_method());
+
+ if (certificate_.size() > 0) {
+ const gchar *capath = mailbox_->biff()->value_gchar ("dir_certificates");
+ if (*capath == '\0')
+ capath = NULL;
+ if (!SSL_CTX_load_verify_locations (context_, certificate_.c_str(),
+ capath)) {
+ g_warning(_("[%d] Failed to load certificate (%s) for %s"),
+ uin_, certificate_.c_str(), hostname_.c_str());
+ ::close (sd_);
+ sd_ = SD_CLOSE;
+ return 0;
+ }
+ SSL_CTX_set_verify (context_, SSL_VERIFY_PEER, NULL);
+ }
+ else
+ SSL_CTX_set_verify (context_, SSL_VERIFY_NONE, NULL);
+
+ ssl_ = SSL_new (context_);
+ if ((!ssl_) || (SSL_set_fd (ssl_, sd_) == 0)) {
+ ::close (sd_);
+ sd_ = SD_CLOSE;
+ g_warning (_("[%d] Unable to set file descriptor: %s"), uin_,
+ hostname_.c_str());
+ return 0;
+ }
+
+ if (SSL_connect (ssl_) != 1) {
+ ERR_error_string(ERR_get_error(), err_buf);
+ SSL_free (ssl_);
+ ssl_ = NULL;
+ ::close (sd_);
+ sd_ = SD_CLOSE;
+ g_warning (_("[%d] Unable to negotiate TLS connection: %s"), uin_, err_buf);
+ return 0;
+ }
+
+ if ((certificate_.size() > 0) && (SSL_get_verify_result(ssl_) != X509_V_OK)) {
+ g_static_mutex_lock (&ui_cert_mutex_);
+ ui_cert_->select (this);
+ g_static_mutex_unlock (&ui_cert_mutex_);
+ if (!bypass_certificate_) {
+ SSL_free (ssl_);
+ ssl_ = NULL;
+ ::close (sd_);
+ sd_ = SD_CLOSE;
+ g_warning (_("[%d] Cannot identify remote host (%s on port %d)"), uin_, hostname_.c_str(), port_);
+ }
+ }
+
+ use_ssl_ = true;
+
+#endif
+ status_ = SOCKET_STATUS_OK;
+ return 1;
+}
+
/**
* Close the socket.
*/
--- gnubiff-2.2.9.orig/src/socket.h 2007-09-08 21:06:30 +0300
+++ gnubiff-2.2.9.orig/src/socket.h 2008-02-09 15:46:23 +0200
@@ -91,6 +91,7 @@
guint authentication = AUTH_SSL,
std::string certificate = "",
guint timeout = 5);
+ gint starttls (std::string certificate = "");
void close (void);
gint write (std::string line, gboolean print = true);
gint read (std::string &line,
--- gnubiff-2.2.9.orig/src/ui-properties.cc 2007-09-08 17:57:59 +0300
+++ gnubiff-2.2.9.orig/src/ui-properties.cc 2008-02-09 15:49:15 +0200
@@ -156,6 +156,8 @@
{ "SSL", GTK_STOCK_DIALOG_AUTHENTICATION, "SSL",
0, 0, G_CALLBACK(PROPERTIES_on_auth_changed)},
{ "Certificate", GTK_STOCK_DIALOG_AUTHENTICATION, _("SSL with certificate"),
+ 0, 0, G_CALLBACK(PROPERTIES_on_auth_changed)},
+ { "TLS", GTK_STOCK_DIALOG_AUTHENTICATION, "TLS",
0, 0, G_CALLBACK(PROPERTIES_on_auth_changed)}
};
static const char *auth_ui_description =
@@ -166,6 +168,7 @@
" "
" "
" "
+ " "
" "
"";
action_group = gtk_action_group_new ("actions");
@@ -302,6 +305,10 @@
selected_auth_ = AUTH_CERTIFICATE;
certificate_view (true);
}
+ else if (auth == "TLS") {
+ selected_auth_ = AUTH_TLS;
+ certificate_view (false);
+ }
else {
selected_auth_ = AUTH_AUTODETECT;
certificate_view (false);