[balsa] SMTP, POP: fall back to auth w/ password



commit a0065aa672da97a21d91cb7e0f4d7e0720edac7b
Author: Albrecht Dreß <albrecht dress arcor de>
Date:   Tue Dec 18 19:23:10 2018 -0500

    SMTP, POP: fall back to auth w/ password
    
    SMTP, POP: fall back to auth w/ password if GSS failed
    
    * libnetclient/net-client-pop.c, libnetclient/net-client-smtp.c:
      retry auth with password if GSS auth failed; small performance
      improvement checking the various auth methods
    * libnetclient/net-client-utils.c: print more (internal) debug
      info about failed GSS operations, fix nit-picks
    
    Signed-off-by: Peter Bloomfield <PeterBloomfield bellsouth net>

 ChangeLog                       | 10 ++++++++++
 libnetclient/net-client-pop.c   | 28 ++++++++++++++++++++++------
 libnetclient/net-client-smtp.c  | 24 ++++++++++++++++++++----
 libnetclient/net-client-utils.c |  8 ++++++--
 4 files changed, 58 insertions(+), 12 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 6bf1134bb..4f08ef2b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2018-12-18  Albrecht Dreß  <albrecht dress arcor de>
+
+       SMTP, POP: fall back to auth w/ password if GSS failed
+
+       * libnetclient/net-client-pop.c, libnetclient/net-client-smtp.c:
+         retry auth with password if GSS auth failed; small performance
+         improvement checking the various auth methods
+       * libnetclient/net-client-utils.c: print more (internal) debug
+         info about failed GSS operations, fix nit-picks
+
 2018-12-14  Peter Bloomfield  <pbloomfield bellsouth net>
 
        Stop using GSlice; it may go away
diff --git a/libnetclient/net-client-pop.c b/libnetclient/net-client-pop.c
index 3a757c0d0..5967fdbff 100644
--- a/libnetclient/net-client-pop.c
+++ b/libnetclient/net-client-pop.c
@@ -171,12 +171,26 @@ net_client_pop_connect(NetClientPop *client, gchar **greeting, GError **error)
 
                auth_data = NULL;
                need_pwd = (auth_supported & NET_CLIENT_POP_AUTH_NO_PWD) == 0U;
-               g_debug("emit 'auth' signal for client %p", client);
+               g_debug("emit 'auth' signal for client %p, need pwd %d", client, need_pwd);
                g_signal_emit_by_name(client, "auth", need_pwd, &auth_data);
                if ((auth_data != NULL) && (auth_data[0] != NULL)) {
                        result = net_client_pop_auth(client, auth_data[0], auth_data[1], auth_supported, 
error);
                        net_client_free_authstr(auth_data[0]);
                        net_client_free_authstr(auth_data[1]);
+
+                       /* if passwordless authentication failed, try again with password */
+                       if (!result && !need_pwd) {
+                               g_debug("passwordless authentication failed, retry w/ password: emit 'auth' 
signal for client %p", client);
+                               g_clear_error(error);
+                               g_free(auth_data);
+                               g_signal_emit_by_name(client, "auth", TRUE, &auth_data);
+                               if ((auth_data != NULL) && (auth_data[0] != NULL)) {
+                                       result = net_client_pop_auth(client, auth_data[0], auth_data[1],
+                                               auth_supported & ~NET_CLIENT_POP_AUTH_NO_PWD, error);
+                                       net_client_free_authstr(auth_data[0]);
+                                       net_client_free_authstr(auth_data[1]);
+                               }
+                       }
                }
                g_free(auth_data);
        }
@@ -482,7 +496,10 @@ net_client_pop_auth(NetClientPop *client, const gchar *user, const gchar *passwd
                auth_mask = client->priv->auth_allowed[1] & auth_supported;
        }
 
-       if (((auth_mask & NET_CLIENT_POP_AUTH_NO_PWD) == 0U) && (passwd == NULL)) {
+       if (auth_mask == 0U) {
+               g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH,
+                       _("no suitable authentication mechanism"));
+       } else if (((auth_mask & NET_CLIENT_POP_AUTH_NO_PWD) == 0U) && (passwd == NULL)) {
                g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH, 
_("password required"));
        } else {
                /* first try authentication methods w/o password, then safe ones, and finally the plain-text 
methods */
@@ -501,14 +518,13 @@ net_client_pop_auth(NetClientPop *client, const gchar *user, const gchar *passwd
                } else if ((auth_mask & NET_CLIENT_POP_AUTH_LOGIN) != 0U) {
                        result = net_client_pop_auth_login(client, user, passwd, error);
                } else {
-                       g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH,
-                               _("no suitable authentication mechanism"));
+                       g_assert_not_reached();
                }
 
                /* 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;
+               if (!result && (*error != NULL) && ((*error)->code == (gint) 
NET_CLIENT_ERROR_POP_SERVER_ERR)) {
+                       (*error)->code = (gint) NET_CLIENT_ERROR_POP_AUTHFAIL;
                }
        }
 
diff --git a/libnetclient/net-client-smtp.c b/libnetclient/net-client-smtp.c
index bc7597031..63c59fa3c 100644
--- a/libnetclient/net-client-smtp.c
+++ b/libnetclient/net-client-smtp.c
@@ -157,12 +157,26 @@ net_client_smtp_connect(NetClientSmtp *client, gchar **greeting, GError **error)
 
                auth_data = NULL;
                need_pwd = (auth_supported & NET_CLIENT_SMTP_AUTH_NO_PWD) == 0U;
-               g_debug("emit 'auth' signal for client %p", client);
+               g_debug("emit 'auth' signal for client %p, need pwd %d", client, need_pwd);
                g_signal_emit_by_name(client, "auth", need_pwd, &auth_data);
                if ((auth_data != NULL) && (auth_data[0] != NULL)) {
                        result = net_client_smtp_auth(client, auth_data[0], auth_data[1], auth_supported, 
error);
                        net_client_free_authstr(auth_data[0]);
                        net_client_free_authstr(auth_data[1]);
+
+                       /* if passwordless authentication failed, try again with password */
+                       if (!result && !need_pwd) {
+                               g_debug("passwordless authentication failed, retry w/ password: emit 'auth' 
signal for client %p", client);
+                               g_clear_error(error);
+                               g_free(auth_data);
+                               g_signal_emit_by_name(client, "auth", TRUE, &auth_data);
+                               if ((auth_data != NULL) && (auth_data[0] != NULL)) {
+                                       result = net_client_smtp_auth(client, auth_data[0], auth_data[1],
+                                               auth_supported & ~NET_CLIENT_SMTP_AUTH_NO_PWD, error);
+                                       net_client_free_authstr(auth_data[0]);
+                                       net_client_free_authstr(auth_data[1]);
+                               }
+                       }
                }
                g_free(auth_data);
        }
@@ -391,7 +405,10 @@ net_client_smtp_auth(NetClientSmtp *client, const gchar *user, const gchar *pass
                auth_mask = client->priv->auth_allowed[1] & auth_supported;
        }
 
-       if (((auth_mask & NET_CLIENT_SMTP_AUTH_NO_PWD) == 0U) && (passwd == NULL)) {
+       if (auth_mask == 0U) {
+               g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_AUTH,
+                       _("no suitable authentication mechanism"));
+       } else if (((auth_mask & NET_CLIENT_SMTP_AUTH_NO_PWD) == 0U) && (passwd == NULL)) {
                g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_AUTH, 
_("password required"));
        } else {
                /* first try authentication methods w/o password, then safe ones, and finally the plain-text 
methods */
@@ -406,8 +423,7 @@ net_client_smtp_auth(NetClientSmtp *client, const gchar *user, const gchar *pass
                } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_LOGIN) != 0U) {
                        result = net_client_smtp_auth_login(client, user, passwd, error);
                } else {
-                       g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_AUTH,
-                               _("no suitable authentication mechanism"));
+                       g_assert_not_reached();
                }
        }
 
diff --git a/libnetclient/net-client-utils.c b/libnetclient/net-client-utils.c
index 83c9641ad..141dc70bc 100644
--- a/libnetclient/net-client-utils.c
+++ b/libnetclient/net-client-utils.c
@@ -70,7 +70,7 @@ net_client_cram_calc(const gchar *base64_challenge, GChecksumType chksum_type, c
 const gchar *
 net_client_chksum_to_str(GChecksumType chksum_type)
 {
-       /*lint -e{904} -e{9077} -e{9090}        (MISRA C:2012 Rules 15.5, 16.1, 16.3) */
+       /*lint -e{904} -e{9077} -e{9090} -e{788}        (MISRA C:2012 Rules 15.5, 16.1, 16.3) */
        switch (chksum_type) {
        case G_CHECKSUM_MD5:
                return "MD5";
@@ -118,7 +118,7 @@ net_client_free_authstr(gchar *str)
                guint n;
 
                for (n = 0; str[n] != '\0'; n++) {
-                       str[n] = g_random_int_range(32, 128);
+                       str[n] = (gchar) g_random_int_range(32, 128);
                }
                g_free(str);
        }
@@ -151,6 +151,7 @@ net_client_gss_ctx_new(const gchar *service, const gchar *host, const gchar *use
     if (GSS_ERROR(maj_stat) != 0U) {
        gchar *gss_err = gss_error_string(maj_stat, min_stat);
 
+       g_debug("gss_import_name: %x:%x: %s", maj_stat, min_stat, gss_err);
        g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GSSAPI, _("importing GSS service 
name %s failed: %s"),
                service_str, gss_err);
        g_free(gss_err);
@@ -194,6 +195,7 @@ net_client_gss_auth_step(NetClientGssCtx *gss_ctx, const gchar *in_token, gchar
        if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) {
        gchar *gss_err = gss_error_string(maj_stat, min_stat);
 
+       g_debug("gss_init_sec_context: %x:%x: %s", maj_stat, min_stat, gss_err);
        g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GSSAPI, _("cannot initialize GSS 
security context: %s"),
                gss_err);
        g_free(gss_err);
@@ -233,6 +235,7 @@ net_client_gss_auth_finish(const NetClientGssCtx *gss_ctx, const gchar *in_token
        if (maj_stat != GSS_S_COMPLETE) {
        gchar *gss_err = gss_error_string(maj_stat, min_stat);
 
+       g_debug("gss_unwrap: %x:%x: %s", maj_stat, min_stat, gss_err);
        g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GSSAPI, _("malformed GSS security 
token: %s"), gss_err);
        g_free(gss_err);
        } else {
@@ -258,6 +261,7 @@ net_client_gss_auth_finish(const NetClientGssCtx *gss_ctx, const gchar *in_token
                        if (maj_stat != GSS_S_COMPLETE) {
                                gchar *gss_err = gss_error_string(maj_stat, min_stat);
 
+                       g_debug("gss_wrap: %x:%x: %s", maj_stat, min_stat, gss_err);
                                g_set_error(error, NET_CLIENT_ERROR_QUARK, (gint) NET_CLIENT_ERROR_GSSAPI, 
_("cannot create GSS login request: %s"),
                                        gss_err);
                                g_free(gss_err);


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