[balsa] Clear passwords if authentication fails



commit 2ead0558aba5d0aa32462eba69574334a7fea994
Author: Albrecht Dreß <albrecht dress arcor de>
Date:   Tue Nov 27 14:33:42 2018 -0500

    Clear passwords if authentication fails
    
    * libbalsa/mailbox_pop3.c, libbalsa/send.c: clear appropriate
      password when libnetclient reports an authentication failure
      (SMTP, POP), or could not decrypt a user certificate's private key
    * libnetclient/net-client-pop.[ch]: report auth failure if the
      server reports any error in the authentication phase (AUTH,
      APOP, USER/PASS); fix nagging by Flexelint
    * libnetclient/net-client-smtp.[ch]: report auth failure if
      the server replies with status codes 534 or 535; fix nagging
      by Flexelint
    * libnetclient/net-client.[ch]: report a certificate key
      decryption error if the passphrase is wrong
    
    Signed-off-by: Peter Bloomfield <PeterBloomfield bellsouth net>

 ChangeLog                      | 17 +++++++++++++++++
 libbalsa/mailbox_pop3.c        |  8 ++++++++
 libbalsa/send.c                | 10 +++++++++-
 libnetclient/net-client-pop.c  |  8 +++++++-
 libnetclient/net-client-pop.h  |  3 ++-
 libnetclient/net-client-smtp.c | 11 ++++++++---
 libnetclient/net-client-smtp.h |  6 ++++--
 libnetclient/net-client.c      |  4 ++--
 libnetclient/net-client.h      |  3 ++-
 9 files changed, 59 insertions(+), 11 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index ac833e360..f326d0d1b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2018-11-27  Albrecht Dreß  <albrecht dress arcor de>
+
+       Clear passwords if authentication fails
+
+       * libbalsa/mailbox_pop3.c, libbalsa/send.c: clear appropriate
+       password when libnetclient reports an authentication failure
+       (SMTP, POP), or could not decrypt a user certificate's private key
+       * libnetclient/net-client-pop.[ch]: report auth failure if the
+       server reports any error in the authentication phase (AUTH,
+       APOP, USER/PASS); fix nagging by Flexelint
+       * libnetclient/net-client-smtp.[ch]: report auth failure if
+       the server replies with status codes 534 or 535; fix nagging
+       by Flexelint
+       * libnetclient/net-client.[ch]: report a certificate key
+       decryption error if the passphrase is wrong
+
+
 2018-11-27  Albrecht Dreß  <albrecht dress arcor de>
 
        Fix broken IMAP special folders & other migration issues
diff --git a/libbalsa/mailbox_pop3.c b/libbalsa/mailbox_pop3.c
index f72016574..e8561e3c0 100644
--- a/libbalsa/mailbox_pop3.c
+++ b/libbalsa/mailbox_pop3.c
@@ -494,6 +494,10 @@ libbalsa_mailbox_pop3_startup(LibBalsaServer            *server,
                if (!net_client_set_cert_from_file(NET_CLIENT(pop), server->cert_file, &error)) {
                        libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("Cannot load certificate file %s: 
%s"), server->cert_file,
                                error->message);
+                       /* bad certificate private key password: clear it */
+                       if (error->code == NET_CLIENT_ERROR_CERT_KEY_PASS) {
+                               libbalsa_server_set_password(server, NULL, TRUE);
+                       }
                        g_error_free(error);
                        g_object_unref(G_OBJECT(pop));
                        return NULL;
@@ -509,6 +513,10 @@ libbalsa_mailbox_pop3_startup(LibBalsaServer            *server,
        if (!net_client_pop_connect(pop, NULL, &error)) {
                libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("POP3 mailbox %s: cannot connect %s: %s"), 
name, server->host,
                        error->message);
+               /* authentication failed: clear password */
+               if (error->code == NET_CLIENT_ERROR_POP_AUTHFAIL) {
+                       libbalsa_server_set_password(server, NULL, FALSE);
+               }
                g_error_free(error);
                net_client_shutdown(NET_CLIENT(pop));
                g_object_unref(G_OBJECT(pop));
diff --git a/libbalsa/send.c b/libbalsa/send.c
index ff80d5d52..f4e747ada 100644
--- a/libbalsa/send.c
+++ b/libbalsa/send.c
@@ -796,6 +796,10 @@ lbs_process_queue_init_session(LibBalsaServer* server)
                if (!net_client_set_cert_from_file(NET_CLIENT(session), server->cert_file, &error)) {
                        libbalsa_information(LIBBALSA_INFORMATION_ERROR, _("Cannot load certificate file %s: 
%s"), server->cert_file,
                                error->message);
+                       /* bad certificate private key password: clear it */
+                       if (error->code == NET_CLIENT_ERROR_CERT_KEY_PASS) {
+                               libbalsa_server_set_password(server, NULL, TRUE);
+                       }
                        g_error_free(error);
                        g_object_unref(session);
                        session = NULL;
@@ -1048,7 +1052,7 @@ balsa_send_message_real(SendMessageInfo *info)
             g_mutex_unlock(&send_messages_lock);
         }
     } else {
-        if (ERROR_IS_TRANSIENT(error)) {
+        if (ERROR_IS_TRANSIENT(error) || (error->code == NET_CLIENT_ERROR_SMTP_AUTHFAIL)) {
             GList *this_msg;
 
             /* Mark all messages as neither flagged nor deleted, so they can be resent later
@@ -1063,6 +1067,10 @@ balsa_send_message_real(SendMessageInfo *info)
                                                   LIBBALSA_MESSAGE_FLAG_DELETED);
                 }
             }
+               if (error->code == NET_CLIENT_ERROR_SMTP_AUTHFAIL) {
+                       /* authentication failed: clear password */
+                       libbalsa_server_set_password(LIBBALSA_SERVER(info->smtp_server), NULL, FALSE);
+               }
         }
         libbalsa_information(LIBBALSA_INFORMATION_ERROR,
                              _("Connecting SMTP server %s (%s) failed: %s"),
diff --git a/libnetclient/net-client-pop.c b/libnetclient/net-client-pop.c
index ee26648ab..3a757c0d0 100644
--- a/libnetclient/net-client-pop.c
+++ b/libnetclient/net-client-pop.c
@@ -380,7 +380,7 @@ net_client_pop_class_init(NetClientPopClass *klass)
 static void
 net_client_pop_init(NetClientPop *self)
 {
-       self->priv = net_client_pop_get_instance_private(self);
+       self->priv = net_client_pop_get_instance_private(self);         /*lint !e9079 (MISRA C:2012 Rule 
11.5) intended use */
        self->priv->auth_allowed[0] = NET_CLIENT_POP_AUTH_ALL;
        self->priv->auth_allowed[1] = NET_CLIENT_POP_AUTH_SAFE;
 }
@@ -504,6 +504,12 @@ net_client_pop_auth(NetClientPop *client, const gchar *user, const gchar *passwd
                        g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH,
                                _("no suitable authentication mechanism"));
                }
+
+               /* POP3 does not define a mechanism to indicate that the authentication failed due to a too 
weak mechanism or wrong
+                * credentials, so we treat all server -ERR responses as authentication failures */
+               if (!result && (*error != NULL) && ((*error)->code == NET_CLIENT_ERROR_POP_SERVER_ERR)) {
+                       (*error)->code = NET_CLIENT_ERROR_POP_AUTHFAIL;
+               }
        }
 
        return result;
diff --git a/libnetclient/net-client-pop.h b/libnetclient/net-client-pop.h
index c999a31bb..e94743c2b 100644
--- a/libnetclient/net-client-pop.h
+++ b/libnetclient/net-client-pop.h
@@ -44,7 +44,8 @@ enum _NetClientPopError {
        NET_CLIENT_ERROR_POP_PROTOCOL = 1,              /**< A bad server reply has been received. */
        NET_CLIENT_ERROR_POP_SERVER_ERR,                /**< The server replied with an error. */
        NET_CLIENT_ERROR_POP_NO_AUTH,                   /**< The server offers no suitable authentication 
mechanism. */
-       NET_CLIENT_ERROR_POP_NO_STARTTLS                /**< The server does not support STARTTLS. */
+       NET_CLIENT_ERROR_POP_NO_STARTTLS,               /**< The server does not support STARTTLS. */
+       NET_CLIENT_ERROR_POP_AUTHFAIL                   /**< Authentication failure. */
 };
 
 
diff --git a/libnetclient/net-client-smtp.c b/libnetclient/net-client-smtp.c
index 9b830d432..bc7597031 100644
--- a/libnetclient/net-client-smtp.c
+++ b/libnetclient/net-client-smtp.c
@@ -342,7 +342,7 @@ net_client_smtp_class_init(NetClientSmtpClass *klass)
 static void
 net_client_smtp_init(NetClientSmtp *self)
 {
-       self->priv = net_client_smtp_get_instance_private(self);
+       self->priv = net_client_smtp_get_instance_private(self);        /*lint !e9079 (MISRA C:2012 Rule 
11.5) intended use */
        self->priv->auth_allowed[0] = NET_CLIENT_SMTP_AUTH_ALL;
        self->priv->auth_allowed[1] = NET_CLIENT_SMTP_AUTH_SAFE;
 }
@@ -685,8 +685,13 @@ net_client_smtp_eval_rescode(gint res_code, const gchar *reply, GError **error)
                result = FALSE;
                break;
        case 5:
-               g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_PERMANENT,
-                       _("permanent error %d: %s"), res_code, reply);
+               if ((res_code == 534) || (res_code == 535)) {
+                       g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_AUTHFAIL,
+                               _("authentication failure %d: %s"), res_code, reply);
+               } else {
+                       g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) 
NET_CLIENT_ERROR_SMTP_PERMANENT,
+                               _("permanent error %d: %s"), res_code, reply);
+               }
                result = FALSE;
                break;
        default:
diff --git a/libnetclient/net-client-smtp.h b/libnetclient/net-client-smtp.h
index 5634c8199..194fc68c4 100644
--- a/libnetclient/net-client-smtp.h
+++ b/libnetclient/net-client-smtp.h
@@ -43,9 +43,11 @@ typedef enum _NetClientSmtpDsnMode NetClientSmtpDsnMode;
 enum _NetClientSmtpError {
        NET_CLIENT_ERROR_SMTP_PROTOCOL = 1,             /**< A bad server reply has been received. */
        NET_CLIENT_ERROR_SMTP_TRANSIENT,                /**< The server replied with a transient error code 
(code 4yz). */
-       NET_CLIENT_ERROR_SMTP_PERMANENT,                /**< The server replied with a permanent error code 
(code 5yz). */
+       NET_CLIENT_ERROR_SMTP_PERMANENT,                /**< The server replied with a permanent error code 
(code 5yz, except 534 or 535). */
        NET_CLIENT_ERROR_SMTP_NO_AUTH,          /**< The server offers no suitable authentication mechanism. 
*/
-       NET_CLIENT_ERROR_SMTP_NO_STARTTLS               /**< The server does not support STARTTLS. */
+       NET_CLIENT_ERROR_SMTP_NO_STARTTLS,              /**< The server does not support STARTTLS. */
+       NET_CLIENT_ERROR_SMTP_AUTHFAIL                  /**< Authentication failure (see RFC 4954, section 
6): mechanism is too weak (534) or
+                                                                                        * credentials 
invalid (535). */
 };
 
 
diff --git a/libnetclient/net-client.c b/libnetclient/net-client.c
index 39b4d17f6..f9e023351 100644
--- a/libnetclient/net-client.c
+++ b/libnetclient/net-client.c
@@ -450,7 +450,7 @@ net_client_set_cert_from_pem(NetClient *client, const gchar *pem_data, GError **
                                gnutls_x509_privkey_deinit(key);
 
                                if (res != GNUTLS_E_SUCCESS) {
-                                       g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) 
NET_CLIENT_ERROR_GNUTLS, _("error loading key: %s"),
+                                       g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) 
NET_CLIENT_ERROR_CERT_KEY_PASS, _("error loading key: %s"),
                                                gnutls_strerror(res));
                                }
                        }
@@ -606,7 +606,7 @@ net_client_class_init(NetClientClass *klass)
 static void
 net_client_init(NetClient *self)
 {
-       self->priv = net_client_get_instance_private(self);
+       self->priv = net_client_get_instance_private(self);             /*lint !e9079 (MISRA C:2012 Rule 
11.5) intended use of this function */
        self->priv->sock = g_socket_client_new();
        if (self->priv->sock != NULL) {
                g_socket_client_set_timeout(self->priv->sock, 180U);
diff --git a/libnetclient/net-client.h b/libnetclient/net-client.h
index d0a394e23..ad553e440 100644
--- a/libnetclient/net-client.h
+++ b/libnetclient/net-client.h
@@ -69,7 +69,8 @@ enum _NetClientError {
        NET_CLIENT_ERROR_TLS_ACTIVE,                    /**< TLS is already active for the connection. */
        NET_CLIENT_ERROR_COMP_ACTIVE,                   /**< Compression is already active for the 
connection. */
        NET_CLIENT_ERROR_LINE_TOO_LONG,                 /**< The line is too long. */
-       NET_CLIENT_ERROR_GNUTLS,                                /**< A GnuTLS error occurred. */
+       NET_CLIENT_ERROR_GNUTLS,                                /**< A GnuTLS error occurred (bad certificate 
or key data, or internal error). */
+       NET_CLIENT_ERROR_CERT_KEY_PASS,                 /**< GnuTLS could not decrypt the user certificate's 
private key. */
        NET_CLIENT_ERROR_GSSAPI                                 /**< A GSSAPI error occurred. */
 };
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]