[balsa/oauth2-support: 28/30] libnetclient improvements for OAuth2 preparation




commit 215e204cf10b448bc0f09cbb4a95c10d4d01cd2f
Author: Albrecht Dreß <albrecht dress arcor de>
Date:   Wed Sep 9 19:42:25 2020 +0200

    libnetclient improvements for OAuth2 preparation
    
    - in libnetclient:
      - net-client.h: rename ANONYMOUS auth method to NONE_ANON, update docs
      - net-client-pop.[ch]: rework auth code, add ANONYMOUS auth
      - net-client-smtp.[ch]: rework auth code
      - net-client-utils.[ch]: add helper for ANONYMOUS auth token
    calculation
    - in libbalsa/imap:
      - auth-cram.c, auth-gssapi.c, imap-auth.c, imap-handle.c: use new auth
    signal signature and auth method naming
      - imap-auth.c: improve ANONYMOUS auth
      - fix meson error (thanks @peterb)
    - in libbalsa:
      - server-config.c: add ANONYMOUS auth for POP3 and IMAP, use new auth
    method naming, add log domain
      - server.[ch]: implement new auth signal handler, add log domain
      - smtp-server.c: add log domain
    
    Signed-off-by: Albrecht Dreß <albrecht dress arcor de>

 libbalsa/imap/auth-cram.c       |   2 +-
 libbalsa/imap/auth-gssapi.c     |   2 +-
 libbalsa/imap/imap-auth.c       |  24 ++-----
 libbalsa/imap/imap-handle.c     |   2 +-
 libbalsa/imap/imap_tst.c        |   2 +-
 libbalsa/server-config.c        |  16 +++--
 libbalsa/server.c               |  40 +++++++----
 libbalsa/server.h               |   6 +-
 libbalsa/smtp-server.c          |   7 ++
 libnetclient/net-client-pop.c   | 150 ++++++++++++++++++++++++++--------------
 libnetclient/net-client-pop.h   |  15 ++--
 libnetclient/net-client-smtp.c  |  86 +++++++++++++----------
 libnetclient/net-client-smtp.h  |   4 +-
 libnetclient/net-client-utils.c |  19 +++++
 libnetclient/net-client-utils.h |  17 ++++-
 libnetclient/net-client.h       |  13 ++--
 16 files changed, 258 insertions(+), 147 deletions(-)
---
diff --git a/libbalsa/imap/auth-cram.c b/libbalsa/imap/auth-cram.c
index 6b11f72a2..18b9a18d3 100644
--- a/libbalsa/imap/auth-cram.c
+++ b/libbalsa/imap/auth-cram.c
@@ -42,7 +42,7 @@ imap_auth_cram(ImapMboxHandle* handle)
   if (!imap_mbox_handle_can_do(handle, IMCAP_ACRAM_MD5))
     return IMAP_AUTH_UNAVAIL;
 
-  g_signal_emit_by_name(handle->sio, "auth", TRUE, &auth_data);
+  g_signal_emit_by_name(handle->sio, "auth", NET_CLIENT_AUTH_USER_PASS, &auth_data);
   if((auth_data == NULL) || (auth_data[0] == NULL) || (auth_data[1] == NULL)) {
     imap_mbox_handle_set_msg(handle, _("Authentication cancelled"));
        g_strfreev(auth_data);
diff --git a/libbalsa/imap/auth-gssapi.c b/libbalsa/imap/auth-gssapi.c
index e5bcd6973..0a6323f9c 100644
--- a/libbalsa/imap/auth-gssapi.c
+++ b/libbalsa/imap/auth-gssapi.c
@@ -125,7 +125,7 @@ imap_auth_gssapi(ImapMboxHandle* handle)
         return IMAP_AUTH_UNAVAIL;
     }
 
-    g_signal_emit_by_name(handle->sio, "auth", FALSE, &auth_data);
+    g_signal_emit_by_name(handle->sio, "auth", NET_CLIENT_AUTH_KERBEROS, &auth_data);
     if((auth_data == NULL) || (auth_data[0] == NULL)) {
        imap_mbox_handle_set_msg(handle, _("User name required, authentication cancelled"));
        g_strfreev(auth_data);
diff --git a/libbalsa/imap/imap-auth.c b/libbalsa/imap/imap-auth.c
index 94258a5d4..b3091f9a2 100644
--- a/libbalsa/imap/imap-auth.c
+++ b/libbalsa/imap/imap-auth.c
@@ -64,7 +64,7 @@ imap_authenticate(ImapMboxHandle* handle)
          r = imap_auth_gssapi(handle);
   }
 
-  if ((r != IMAP_SUCCESS) && (handle->auth_mode & NET_CLIENT_AUTH_ANONYMOUS) != 0U) {
+  if ((r != IMAP_SUCCESS) && (handle->auth_mode & NET_CLIENT_AUTH_NONE_ANON) != 0U) {
          r = imap_auth_anonymous(handle);
   }
 
@@ -94,7 +94,7 @@ imap_auth_login(ImapMboxHandle* handle)
   if (imap_mbox_handle_can_do(handle, IMCAP_LOGINDISABLED))
     return IMAP_AUTH_UNAVAIL;
   
-  g_signal_emit_by_name(handle->sio, "auth", TRUE, &auth_data);
+  g_signal_emit_by_name(handle->sio, "auth", NET_CLIENT_AUTH_USER_PASS, &auth_data);
   if((auth_data == NULL) || (auth_data[0] == NULL) || (auth_data[1] == NULL)) {
     imap_mbox_handle_set_msg(handle, _("Authentication cancelled"));
        g_strfreev(auth_data);
@@ -184,7 +184,7 @@ getmsg_plain(ImapMboxHandle *h, char **retmsg, int *retmsglen)
        gchar **auth_data;
        gboolean result;
 
-       g_signal_emit_by_name(h->sio, "auth", TRUE, &auth_data);
+       g_signal_emit_by_name(h->sio, "auth", NET_CLIENT_AUTH_USER_PASS, &auth_data);
        if ((auth_data == NULL) || (auth_data[0] == NULL) || (auth_data[1] == NULL)) {
                result = FALSE;
        } else {
@@ -209,24 +209,14 @@ imap_auth_plain(ImapMboxHandle* handle)
 
 
 /* =================================================================== */
-/* SASL ANONYMOUS RFC-2245                                             */
+/* SASL ANONYMOUS RFC-4505                                             */
 /* =================================================================== */
 static gboolean
 getmsg_anonymous(ImapMboxHandle *h, char **retmsg, int *retmsglen)
 {
-       gchar **auth_data;
-       gboolean result;
-
-       g_signal_emit_by_name(h->sio, "auth", FALSE, &auth_data);
-       if((auth_data == NULL) || (auth_data[0] == NULL)) {
-               result = FALSE;
-       } else {
-               *retmsg = g_base64_encode((const guchar *) auth_data[0], strlen(auth_data[0]));
-               *retmsglen = strlen(*retmsg);
-               result = TRUE;
-       }
-       g_strfreev(auth_data);
-       return result;
+       *retmsg = net_client_auth_anonymous_token();
+       *retmsglen = strlen(*retmsg);
+       return TRUE;
 }
 
 static ImapResult
diff --git a/libbalsa/imap/imap-handle.c b/libbalsa/imap/imap-handle.c
index 1ae777482..b8e5643aa 100644
--- a/libbalsa/imap/imap-handle.c
+++ b/libbalsa/imap/imap-handle.c
@@ -4480,7 +4480,7 @@ imap_server_probe(const gchar *host, guint timeout_secs, NetClientProbeResult *r
 
                                result->auth_mode = 0U;
                                if (imap_mbox_handle_can_do(handle, IMCAP_AANONYMOUS) != 0) {
-                                       result->auth_mode |= NET_CLIENT_AUTH_ANONYMOUS;
+                                       result->auth_mode |= NET_CLIENT_AUTH_NONE_ANON;
                                }
                                if ((imap_mbox_handle_can_do(handle, IMCAP_ACRAM_MD5) != 0) ||
                                        (imap_mbox_handle_can_do(handle, IMCAP_APLAIN) != 0)) {
diff --git a/libbalsa/imap/imap_tst.c b/libbalsa/imap/imap_tst.c
index 7174f066f..01997f031 100644
--- a/libbalsa/imap/imap_tst.c
+++ b/libbalsa/imap/imap_tst.c
@@ -124,7 +124,7 @@ get_handle(const char *host)
 
   imap_handle_set_tls_mode(h, TestContext.tls_mode);
   if(TestContext.anonymous)
-         imap_handle_set_auth_mode(h, NET_CLIENT_AUTH_ANONYMOUS);
+         imap_handle_set_auth_mode(h, NET_CLIENT_AUTH_NONE_ANON);
 
   if(TestContext.compress)
     imap_handle_set_option(h, IMAP_OPT_COMPRESS, TRUE);
diff --git a/libbalsa/server-config.c b/libbalsa/server-config.c
index 1bf2f3659..5ac74dc97 100644
--- a/libbalsa/server-config.c
+++ b/libbalsa/server-config.c
@@ -30,6 +30,12 @@
 #include "server-config.h"
 
 
+#ifdef G_LOG_DOMAIN
+#  undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "libbalsa-server"
+
+
 struct _LibBalsaServerCfg {
         GtkNotebook parent;
 
@@ -416,7 +422,9 @@ server_cfg_auth_widget(LibBalsaServer *server)
     gchar id_buf[8];
 
     protocol = libbalsa_server_get_protocol(server);
-    if ((strcmp(protocol, "smtp") == 0) || (strcmp(protocol, "imap") == 0)) {
+    if ((strcmp(protocol, "pop3") == 0) || (strcmp(protocol, "imap") == 0)) {
+       gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box), "1", _("anonymous access"));           /* 
RFC 4505 */
+    } else {
        gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box), "1", _("none required"));
     }
     gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo_box), "2", _("user name and pass phrase"));
@@ -455,12 +463,12 @@ on_server_cfg_changed(GtkWidget *widget, LibBalsaServerCfg *server_cfg)
        } else {
                auth_mode = 0;
        }
-       gtk_widget_set_sensitive(server_cfg->username, auth_mode != NET_CLIENT_AUTH_ANONYMOUS);
+       gtk_widget_set_sensitive(server_cfg->username, auth_mode != NET_CLIENT_AUTH_NONE_ANON);
        gtk_widget_set_sensitive(server_cfg->password, auth_mode == NET_CLIENT_AUTH_USER_PASS);
        gtk_widget_set_sensitive(server_cfg->remember_pass, auth_mode == NET_CLIENT_AUTH_USER_PASS);
 
        /* invalid configuration if authentication is required, but no user name given */
-       if ((auth_mode != NET_CLIENT_AUTH_ANONYMOUS) && (*gtk_entry_get_text(GTK_ENTRY(server_cfg->username)) 
== '\0')) {
+       if ((auth_mode != NET_CLIENT_AUTH_NONE_ANON) && (*gtk_entry_get_text(GTK_ENTRY(server_cfg->username)) 
== '\0')) {
                server_cfg->cfg_valid = FALSE;
        }
 
@@ -528,7 +536,7 @@ on_server_probe(GtkWidget *widget, LibBalsaServerCfg *server_cfg)
                        probe_res.auth_mode = NET_CLIENT_AUTH_USER_PASS;
                } else {
                        auth_str = _("none");
-                       probe_res.auth_mode = NET_CLIENT_AUTH_ANONYMOUS;
+                       probe_res.auth_mode = NET_CLIENT_AUTH_NONE_ANON;
                }
                msgdlg = gtk_message_dialog_new(NULL,
                        GTK_DIALOG_DESTROY_WITH_PARENT | libbalsa_dialog_flags(),
diff --git a/libbalsa/server.c b/libbalsa/server.c
index c49cd2d0d..f1ffe6bd8 100644
--- a/libbalsa/server.c
+++ b/libbalsa/server.c
@@ -36,6 +36,13 @@
 #include "net-client-utils.h"
 #include <glib/gi18n.h>
 
+
+#ifdef G_LOG_DOMAIN
+#  undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "libbalsa-server"
+
+
 #if defined(HAVE_LIBSECRET)
 static const SecretSchema server_schema = {
     "org.gnome.Balsa.NetworkPassword", SECRET_SCHEMA_NONE,
@@ -448,7 +455,7 @@ libbalsa_server_load_config(LibBalsaServer * server)
        priv->auth_mode = libbalsa_conf_get_int("AuthMode=2");  /* default NET_CLIENT_AUTH_USER_PASS */
     if (libbalsa_conf_has_key("Anonymous")) {
        if (libbalsa_conf_get_bool("Anonymous")) {
-               priv->auth_mode = NET_CLIENT_AUTH_ANONYMOUS;
+               priv->auth_mode = NET_CLIENT_AUTH_NONE_ANON;
        }
        libbalsa_conf_clean_key("Anonymous");
     }
@@ -553,25 +560,32 @@ libbalsa_server_connect_signals(LibBalsaServer * server, GCallback cb,
 
 
 gchar **
-libbalsa_server_get_auth(NetClient *client,
-                                                gboolean   need_passwd,
-                                gpointer   user_data)
+libbalsa_server_get_auth(NetClient         *client,
+                                                NetClientAuthMode  mode,
+                                                gpointer           user_data)
 {
     LibBalsaServer *server = LIBBALSA_SERVER(user_data);
     LibBalsaServerPrivate *priv = libbalsa_server_get_instance_private(server);
     gchar **result = NULL;
 
-    g_debug("%s: %p %p: encrypted = %d", __func__, client, user_data,
-            net_client_is_encrypted(client));
-    if (priv->auth_mode != NET_CLIENT_AUTH_ANONYMOUS) {
+    g_debug("%s: %p %d %p: encrypted = %d", __func__, client, mode, user_data, 
net_client_is_encrypted(client));
+    if (priv->auth_mode != NET_CLIENT_AUTH_NONE_ANON) {
         result = g_new0(gchar *, 3U);
         result[0] = g_strdup(priv->user);
-        if (need_passwd) {
-        if ((priv->passwd != NULL) && (priv->passwd[0] != '\0')) {
-               result[1] = g_strdup(priv->passwd);
-        } else {
-               result[1] = lbs_get_password(server, NULL);
-        }
+        switch (mode) {
+        case NET_CLIENT_AUTH_USER_PASS:
+            if ((priv->passwd != NULL) && (priv->passwd[0] != '\0')) {
+               result[1] = g_strdup(priv->passwd);
+            } else {
+               result[1] = lbs_get_password(server, NULL);
+            }
+            break;
+        case NET_CLIENT_AUTH_KERBEROS:
+               break;                  /* only user name required */
+        case NET_CLIENT_AUTH_OAUTH2:
+               break;                  // FIXME!! get the OAuth2 token in result[1]
+        default:
+               g_assert_not_reached();
         }
     }
     return result;
diff --git a/libbalsa/server.h b/libbalsa/server.h
index 34584ef31..5dc4cc5c5 100644
--- a/libbalsa/server.h
+++ b/libbalsa/server.h
@@ -64,9 +64,9 @@ void libbalsa_server_save_config(LibBalsaServer * server);
 
 
 /* NetClient related signal handlers */
-gchar **libbalsa_server_get_auth(NetClient *client,
-                                                                gboolean   need_passwd,
-                                                                gpointer   user_data);
+gchar **libbalsa_server_get_auth(NetClient         *client,
+                                                                NetClientAuthMode  mode,
+                                                                gpointer           user_data);
 gboolean libbalsa_server_check_cert(NetClient           *client,
                                                            GTlsCertificate     *peer_cert,
                                                                        GTlsCertificateFlags errors,
diff --git a/libbalsa/smtp-server.c b/libbalsa/smtp-server.c
index a0ca8dd7c..22e3ec695 100644
--- a/libbalsa/smtp-server.c
+++ b/libbalsa/smtp-server.c
@@ -35,6 +35,13 @@
 #  include "macosx-helpers.h"
 #endif
 
+
+#ifdef G_LOG_DOMAIN
+#  undef G_LOG_DOMAIN
+#endif
+#define G_LOG_DOMAIN "libbalsa-server"
+
+
 struct _LibBalsaSmtpServer {
     LibBalsaServer server;
 
diff --git a/libnetclient/net-client-pop.c b/libnetclient/net-client-pop.c
index 2f6456948..883e8bee9 100644
--- a/libnetclient/net-client-pop.c
+++ b/libnetclient/net-client-pop.c
@@ -39,21 +39,24 @@ struct _NetClientPop {
  * @{
  */
 /** RFC 1939 "USER" and "PASS" authentication method. */
-#define NET_CLIENT_POP_AUTH_USER_PASS          0x01U
+#define NET_CLIENT_POP_AUTH_USER_PASS          0x001U
 /** RFC 1939 "APOP" authentication method. */
-#define NET_CLIENT_POP_AUTH_APOP                       0x02U
+#define NET_CLIENT_POP_AUTH_APOP                       0x002U
 /** RFC 5034 SASL "LOGIN" authentication method. */
-#define NET_CLIENT_POP_AUTH_LOGIN                      0x04U
+#define NET_CLIENT_POP_AUTH_LOGIN                      0x004U
 /** RFC 5034 SASL "PLAIN" authentication method. */
-#define NET_CLIENT_POP_AUTH_PLAIN                      0x08U
+#define NET_CLIENT_POP_AUTH_PLAIN                      0x008U
 /** RFC 5034 SASL "CRAM-MD5" authentication method. */
-#define NET_CLIENT_POP_AUTH_CRAM_MD5           0x10U
+#define NET_CLIENT_POP_AUTH_CRAM_MD5           0x010U
 /** RFC 5034 SASL "CRAM-SHA1" authentication method. */
-#define NET_CLIENT_POP_AUTH_CRAM_SHA1          0x20U
+#define NET_CLIENT_POP_AUTH_CRAM_SHA1          0x020U
 /** RFC 4752 "GSSAPI" authentication method. */
-#define NET_CLIENT_POP_AUTH_GSSAPI                     0x40U
+#define NET_CLIENT_POP_AUTH_GSSAPI                     0x040U
 /** RFC 6749 "XOAUTH2" authentication method. */
-#define NET_CLIENT_POP_AUTH_OAUTH2                     0x80U
+#define NET_CLIENT_POP_AUTH_OAUTH2                     0x080U
+/** RFC 4505 "ANONYMOUS" authentication method. */
+#define NET_CLIENT_POP_AUTH_ANONYMOUS          0x100U
+
 
 /** Mask of all authentication methods requiring user name and password. */
 #define NET_CLIENT_POP_AUTH_PASSWORD           \
@@ -62,9 +65,7 @@ struct _NetClientPop {
 
 /** Mask of all authentication methods. */
 #define NET_CLIENT_POP_AUTH_ALL                                \
-       (NET_CLIENT_POP_AUTH_PASSWORD + NET_CLIENT_POP_AUTH_GSSAPI + NET_CLIENT_POP_AUTH_OAUTH2)
-/** Mask of all authentication methods which do not require a password (Note: OAuth2 requires the 
authentication token). */
-#define NET_CLIENT_POP_AUTH_NO_PWD                     NET_CLIENT_POP_AUTH_GSSAPI
+       (NET_CLIENT_POP_AUTH_PASSWORD + NET_CLIENT_POP_AUTH_GSSAPI + NET_CLIENT_POP_AUTH_OAUTH2 + 
NET_CLIENT_POP_AUTH_ANONYMOUS)
 /** @} */
 
 
@@ -95,10 +96,10 @@ static gboolean net_client_pop_starttls(NetClientPop *client, GError **error);
 static gboolean net_client_pop_execute(NetClientPop *client, const gchar *request_fmt, gchar **last_reply, 
GError **error, ...)
        G_GNUC_PRINTF(2, 5);
 static gboolean net_client_pop_execute_sasl(NetClientPop *client, const gchar *request_fmt, gchar 
**challenge, GError **error, ...);
-static gboolean net_client_pop_auth(NetClientPop *client, const gchar *user, const gchar *passwd, guint 
auth_supported,
-                                                                       GError **error);
+static gboolean net_client_pop_auth(NetClientPop *client, guint auth_supported, GError **error);
 static gboolean net_client_pop_auth_plain(NetClientPop *client, const gchar* user, const gchar* passwd, 
GError** error);
 static gboolean net_client_pop_auth_login(NetClientPop *client, const gchar *user, const gchar *passwd, 
GError **error);
+static gboolean net_client_pop_auth_anonymous(NetClientPop *client, GError **error);
 static gboolean net_client_pop_auth_user_pass(NetClientPop *client, const gchar* user, const gchar* passwd, 
GError** error);
 static gboolean net_client_pop_auth_apop(NetClientPop *client, const gchar* user, const gchar* passwd, 
GError** error);
 static gboolean net_client_pop_auth_cram(NetClientPop *client, GChecksumType chksum_type, const gchar *user, 
const gchar *passwd,
@@ -237,6 +238,9 @@ net_client_pop_set_auth_mode(NetClientPop *client, NetClientAuthMode auth_mode,
        g_return_val_if_fail(NET_IS_CLIENT_POP(client), FALSE);
 
        client->auth_enabled = 0U;
+       if ((auth_mode & NET_CLIENT_AUTH_NONE_ANON) != 0U) {
+               client->auth_enabled |= NET_CLIENT_POP_AUTH_ANONYMOUS;
+       }
        if ((auth_mode & NET_CLIENT_AUTH_USER_PASS) != 0U) {
                client->auth_enabled |= NET_CLIENT_POP_AUTH_PASSWORD;
                if (disable_apop) {
@@ -319,19 +323,7 @@ net_client_pop_connect(NetClientPop *client, gchar **greeting, GError **error)
 
        /* authenticate if we were successful so far */
        if (result) {
-               gchar **auth_data;
-               gboolean need_pwd;
-
-               auth_data = NULL;
-               need_pwd = (auth_supported & NET_CLIENT_POP_AUTH_NO_PWD) == 0U;
-               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]);
-               }
-               g_free(auth_data);
+               result = net_client_pop_auth(client, auth_supported, error);
        }
 
        return result;
@@ -626,46 +618,78 @@ net_client_pop_starttls(NetClientPop *client, GError **error)
 
 
 static gboolean
-net_client_pop_auth(NetClientPop *client, const gchar *user, const gchar *passwd, guint auth_supported, 
GError **error)
+net_client_pop_auth(NetClientPop *client, guint auth_supported, GError **error)
 {
        gboolean result = FALSE;
        guint auth_mask;
+       gchar **auth_data = NULL;
 
        /* calculate the possible authentication methods */
        auth_mask = client->auth_enabled & auth_supported;
 
+       /* try, in this order, enabled modes: anonymous; GSSAPI/Kerberos; OAuth2; user name and password */
        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 if ((auth_mask & NET_CLIENT_POP_AUTH_ANONYMOUS) != 0U) {
+               /* Anonymous authentication - nothing required */
+               result = net_client_pop_auth_anonymous(client, error);
+       } else if ((auth_mask & NET_CLIENT_POP_AUTH_GSSAPI) != 0U) {
+               /* GSSAPI aka Kerberos authentication - user name required */
+               g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_KERBEROS, &auth_data);
+               if ((auth_data == NULL) || (auth_data[0] == NULL)) {
+                       g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH, 
_("user name required"));
+               } else {
+                       result = net_client_pop_auth_gssapi(client, auth_data[0], error);
+               }
+       } else if ((auth_mask & NET_CLIENT_POP_AUTH_OAUTH2) != 0U) {
+               /* OAuth2 authentication - user name and access token required */
+               g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_OAUTH2, &auth_data);
+               if ((auth_data == NULL) || (auth_data[0] == NULL) || (auth_data[1] == NULL)) {
+                       g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH,
+                               _("user name and access token required"));
+               } else {
+                       result = net_client_pop_auth_oauth2(client, auth_data[0], auth_data[1], error);
+               }
        } else {
-               /* first try authentication methods w/o password, then safe ones, and finally the plain-text 
methods */
-               if ((auth_mask & NET_CLIENT_POP_AUTH_OAUTH2) != 0U) {
-                       result = net_client_pop_auth_oauth2(client, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_POP_AUTH_GSSAPI) != 0U) {
-                       result = net_client_pop_auth_gssapi(client, user, error);
-               } else if ((auth_mask & NET_CLIENT_POP_AUTH_CRAM_SHA1) != 0U) {
-                       result = net_client_pop_auth_cram(client, G_CHECKSUM_SHA1, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_POP_AUTH_CRAM_MD5) != 0U) {
-                       result = net_client_pop_auth_cram(client, G_CHECKSUM_MD5, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_POP_AUTH_APOP) != 0U) {
-                       result = net_client_pop_auth_apop(client, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_POP_AUTH_PLAIN) != 0U) {
-                       result = net_client_pop_auth_plain(client, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_POP_AUTH_USER_PASS) != 0U) {
-                       result = net_client_pop_auth_user_pass(client, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_POP_AUTH_LOGIN) != 0U) {
-                       result = net_client_pop_auth_login(client, user, passwd, error);
+               /* user name and password authentication methods */
+               g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_USER_PASS, &auth_data);
+               if ((auth_data == NULL) || (auth_data[0] == NULL) || (auth_data[1] == NULL)) {
+                       g_set_error(error, NET_CLIENT_POP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_POP_NO_AUTH,
+                               _("user name and password required"));
                } else {
-                       g_assert_not_reached();
+                       /* first check for safe (hashed) authentication methods, used plain-text ones if they 
are not supported */
+                       if ((auth_mask & NET_CLIENT_POP_AUTH_CRAM_SHA1) != 0U) {
+                               result = net_client_pop_auth_cram(client, G_CHECKSUM_SHA1, auth_data[0], 
auth_data[1], error);
+                       } else if ((auth_mask & NET_CLIENT_POP_AUTH_CRAM_MD5) != 0U) {
+                               result = net_client_pop_auth_cram(client, G_CHECKSUM_MD5, auth_data[0], 
auth_data[1], error);
+                       } else if ((auth_mask & NET_CLIENT_POP_AUTH_APOP) != 0U) {
+                               result = net_client_pop_auth_apop(client, auth_data[0], auth_data[1], error);
+                       } else if ((auth_mask & NET_CLIENT_POP_AUTH_PLAIN) != 0U) {
+                               result = net_client_pop_auth_plain(client, auth_data[0], auth_data[1], error);
+                       } else if ((auth_mask & NET_CLIENT_POP_AUTH_LOGIN) != 0U) {
+                               result = net_client_pop_auth_login(client, auth_data[0], auth_data[1], error);
+                       } else if ((auth_mask & NET_CLIENT_POP_AUTH_USER_PASS) != 0U) {
+                               result = net_client_pop_auth_user_pass(client, auth_data[0], auth_data[1], 
error);
+                       } else {
+                               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 == (gint) 
NET_CLIENT_ERROR_POP_SERVER_ERR)) {
-                       (*error)->code = (gint) NET_CLIENT_ERROR_POP_AUTHFAIL;
+       /* 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 != NULL) && ((*error)->code == (gint) 
NET_CLIENT_ERROR_POP_SERVER_ERR)) {
+               (*error)->code = (gint) NET_CLIENT_ERROR_POP_AUTHFAIL;
+       }
+
+       /* clean up any auth data */
+       if (auth_data != NULL) {
+               if (auth_data[0] != NULL) {
+                       net_client_free_authstr(auth_data[0]);
+                       net_client_free_authstr(auth_data[1]);
                }
+               free(auth_data);
        }
 
        return result;
@@ -716,6 +740,24 @@ net_client_pop_auth_login(NetClientPop *client, const gchar *user, const gchar *
 }
 
 
+static gboolean
+net_client_pop_auth_anonymous(NetClientPop *client, GError **error)
+{
+       gboolean result;
+
+       result = net_client_pop_execute_sasl(client, "AUTH ANONYMOUS", NULL, error);
+       if (result) {
+               gchar *base64_buf;
+
+               base64_buf = net_client_auth_anonymous_token();
+               result = net_client_pop_execute(client, "%s", NULL, error, base64_buf);
+               net_client_free_authstr(base64_buf);
+       }
+
+       return result;
+}
+
+
 static gboolean
 net_client_pop_auth_user_pass(NetClientPop *client, const gchar *user, const gchar *passwd, GError **error)
 {
@@ -856,7 +898,7 @@ net_client_pop_auth_oauth2(NetClientPop *client, const gchar *user, const gchar
 
 static gboolean
 net_client_pop_auth_oauth2(NetClientPop G_GNUC_UNUSED *client, const gchar G_GNUC_UNUSED *user,
-       const gcharG_GNUC_UNUSED *access_token, GError G_GNUC_UNUSED **error)
+       const gchar G_GNUC_UNUSED *access_token, GError G_GNUC_UNUSED **error)
 {
        g_assert_not_reached();                 /* this should never happen! */
        return FALSE;                                   /* never reached, make gcc happy */
@@ -932,6 +974,8 @@ net_client_pop_get_capa(NetClientPop *client, guint *auth_supported)
                                                *auth_supported |= NET_CLIENT_POP_AUTH_CRAM_MD5;
                                        } else if (strcmp(auth[n], "CRAM-SHA1") == 0) {
                                                *auth_supported |= NET_CLIENT_POP_AUTH_CRAM_SHA1;
+                                       } else if (strcmp(auth[n], "ANONYMOUS") == 0) {
+                                               *auth_supported |= NET_CLIENT_POP_AUTH_ANONYMOUS;
 #if defined(HAVE_GSSAPI)
                                        } else if (strcmp(auth[n], "GSSAPI") == 0) {
                                                *auth_supported |= NET_CLIENT_POP_AUTH_GSSAPI;
@@ -941,7 +985,7 @@ net_client_pop_get_capa(NetClientPop *client, guint *auth_supported)
                                                *auth_supported |= NET_CLIENT_POP_AUTH_OAUTH2;
 #endif
                                        } else {
-                                               /* other auth methods are ignored for the time being */
+                                               /* other auth methods are ignored for the time being (see 
MISRA C:2012, Rule 15.7) */
                                        }
                                }
                                g_strfreev(auth);
diff --git a/libnetclient/net-client-pop.h b/libnetclient/net-client-pop.h
index 58faeff60..8b94c9ed3 100644
--- a/libnetclient/net-client-pop.h
+++ b/libnetclient/net-client-pop.h
@@ -138,9 +138,9 @@ gboolean net_client_pop_set_auth_mode(NetClientPop *client, NetClientAuthMode au
  * information.  Simply ignore the signal for an unauthenticated connection.
  *
  * The function will try only @em one authentication method which is both supported by the server and 
enabled by calling
- * net_client_pop_set_auth_mode().  The default is to try all methods, from highest to lowest, OAuth2 (if 
configured), GSSAPI (if
- * configured), CRAM-SHA1, CRAM-MD5, APOP, PLAIN, USER/PASS or LOGIN.  It is up to the caller to ensure 
encryption or a connection
- * to @c localhost if one of the plain text methods shall be used.
+ * net_client_pop_set_auth_mode().  The precedence is: ANONYMOUS, GSSAPI (Kerberos), OAuth2, user name and 
password.  For the
+ * latter, the order is CRAM-SHA1, CRAM-MD5, APOP, PLAIN, LOGIN or USER/PASS.  It is up to the caller to 
ensure encryption or a
+ * connection to @c localhost if one of the plain text methods shall be used.
  *
  * In order to shut down a successfully established connection, just call <tt>g_object_unref()</tt> on the 
POP network client
  * object.
@@ -227,10 +227,11 @@ void net_client_pop_msg_info_free(NetClientPopMessageInfo *info);
  * - the <i>STAT</i>, <i>LIST</i>, <i>RETR</i> and <i>DELE</i> commands as defined in RFC 1939;
  * - support for <i>PIPELINING</i> and <i>UIDL</i> as defined by <a 
href="https://tools.ietf.org/html/rfc2449";>RFC 2449</a>;
  * - <i>STLS</i> encryption as defined by <a href="https://tools.ietf.org/html/rfc2595";>RFC 2595</a>;
- * - authentication using <i>APOP</i>, <i>USER/PASS</i> (both RFC 1939) or the SASL methods <i>PLAIN</i>, 
<i>LOGIN</i>,
- *   <i>CRAM-MD5</i>, <i>CRAM-SHA1</i> or <i>GSSAPI</i> (see <a 
href="https://tools.ietf.org/html/rfc4752";>RFC 4752</a> and
- *   <a href="https://tools.ietf.org/html/rfc5034";>RFC 5034</a>), depending upon the capabilities reported 
by the server.  Note the
- *   <i>GSSAPI</i> is available only if configured with gssapi support.
+ * - authentication using <i>APOP</i>, <i>USER/PASS</i> (both RFC 1939) or the SASL methods 
<i>ANONYMOUS</i>, <i>PLAIN</i>,
+ *   <i>LOGIN</i>, <i>CRAM-MD5</i>, <i>CRAM-SHA1</i>, <i>GSSAPI</i> (see <a 
href="https://tools.ietf.org/html/rfc4752";>RFC
+ *   4752</a> and <a href="https://tools.ietf.org/html/rfc5034";>RFC 5034</a>) or <i>XOAUTH2</i> (<a
+ *   href="https://tools.ietf.org/html/rfc6749";>RFC 6749</a>) depending upon the capabilities reported by 
the server.  Note that
+ *   <i>GSSAPI</i> and <i>XOAUTH2</i> are available only if configured with the respective support.
  */
 
 
diff --git a/libnetclient/net-client-smtp.c b/libnetclient/net-client-smtp.c
index be0d41332..925803749 100644
--- a/libnetclient/net-client-smtp.c
+++ b/libnetclient/net-client-smtp.c
@@ -71,8 +71,6 @@ typedef struct {
 /** Mask of all authentication methods. */
 #define NET_CLIENT_SMTP_AUTH_ALL                       \
        (NET_CLIENT_SMTP_AUTH_NONE | NET_CLIENT_SMTP_AUTH_PASSWORD | NET_CLIENT_SMTP_AUTH_GSSAPI | 
NET_CLIENT_SMTP_AUTH_OAUTH2)
-/** Mask of all authentication methods which do not require a password (Note: OAuth2 requires the 
authentication token). */
-#define NET_CLIENT_SMTP_AUTH_NO_PWD                    NET_CLIENT_SMTP_AUTH_GSSAPI
 /** @} */
 
 
@@ -91,8 +89,7 @@ static gboolean net_client_smtp_ehlo(NetClientSmtp *client, guint *auth_supporte
 static gboolean net_client_smtp_starttls(NetClientSmtp *client, GError **error);
 static gboolean net_client_smtp_execute(NetClientSmtp *client, const gchar *request_fmt, gchar **last_reply, 
GError **error, ...)
        G_GNUC_PRINTF(2, 5);
-static gboolean net_client_smtp_auth(NetClientSmtp *client, const gchar *user, const gchar *passwd, guint 
auth_supported,
-                                                                        GError **error);
+static gboolean net_client_smtp_auth(NetClientSmtp *client, guint auth_supported, GError **error);
 static gboolean net_client_smtp_auth_plain(NetClientSmtp *client, const gchar *user, const gchar *passwd, 
GError **error);
 static gboolean net_client_smtp_auth_login(NetClientSmtp *client, const gchar *user, const gchar *passwd, 
GError **error);
 static gboolean net_client_smtp_auth_cram(NetClientSmtp *client, GChecksumType chksum_type, const gchar 
*user, const gchar *passwd,
@@ -133,7 +130,7 @@ net_client_smtp_set_auth_mode(NetClientSmtp *client, NetClientAuthMode auth_mode
        g_return_val_if_fail(NET_IS_CLIENT_SMTP(client), FALSE);
 
        client->auth_enabled = 0U;
-       if ((auth_mode & NET_CLIENT_AUTH_ANONYMOUS) != 0U) {
+       if ((auth_mode & NET_CLIENT_AUTH_NONE_ANON) != 0U) {
                client->auth_enabled |= NET_CLIENT_SMTP_AUTH_NONE;
        }
        if ((auth_mode & NET_CLIENT_AUTH_USER_PASS) != 0U) {
@@ -300,20 +297,8 @@ net_client_smtp_connect(NetClientSmtp *client, gchar **greeting, GError **error)
        }
 
        /* authenticate if we were successful so far, unless anonymous access is configured */
-       if (result && (client->auth_enabled != NET_CLIENT_SMTP_AUTH_NONE)) {
-               gchar **auth_data;
-               gboolean need_pwd;
-
-               auth_data = NULL;
-               need_pwd = (auth_supported & NET_CLIENT_SMTP_AUTH_NO_PWD) == 0U;
-               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]);
-               }
-               g_free(auth_data);
+       if (result && ((client->auth_enabled & NET_CLIENT_SMTP_AUTH_NONE) == 0U)) {
+               result = net_client_smtp_auth(client, auth_supported, error);
        }
 
        return result;
@@ -526,36 +511,65 @@ net_client_smtp_starttls(NetClientSmtp *client, GError **error)
 
 
 static gboolean
-net_client_smtp_auth(NetClientSmtp *client, const gchar *user, const gchar *passwd, guint auth_supported, 
GError **error)
+net_client_smtp_auth(NetClientSmtp *client, guint auth_supported, GError **error)
 {
        gboolean result = FALSE;
        guint auth_mask;
+       gchar **auth_data = NULL;
 
        /* calculate the possible authentication methods */
        auth_mask = client->auth_enabled & auth_supported;
 
+       /* try, in this order, enabled modes: GSSAPI/Kerberos; OAuth2; user name and password */
        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 if ((auth_mask & NET_CLIENT_SMTP_AUTH_GSSAPI) != 0U) {
+               /* GSSAPI aka Kerberos authentication - user name required */
+               g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_KERBEROS, &auth_data);
+               if ((auth_data == NULL) || (auth_data[0] == NULL)) {
+                       g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_AUTH, 
_("user name required"));
+               } else {
+                       result = net_client_smtp_auth_gssapi(client, auth_data[0], error);
+               }
+       } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_OAUTH2) != 0U) {
+               /* OAuth2 authentication - user name and access token required */
+               g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_OAUTH2, &auth_data);
+               if ((auth_data == NULL) || (auth_data[0] == NULL) || (auth_data[1] == NULL)) {
+                       g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_AUTH,
+                               _("user name and access token required"));
+               } else {
+                       result = net_client_smtp_auth_oauth2(client, auth_data[0], auth_data[1], error);
+               }
        } else {
-               /* first try authentication methods w/o password, then safe ones, and finally the plain-text 
methods */
-               if ((auth_mask & NET_CLIENT_SMTP_AUTH_OAUTH2) != 0U) {
-                       result = net_client_smtp_auth_oauth2(client, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_GSSAPI) != 0U) {
-                       result = net_client_smtp_auth_gssapi(client, user, error);
-               } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_CRAM_SHA1) != 0U) {
-                       result = net_client_smtp_auth_cram(client, G_CHECKSUM_SHA1, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_CRAM_MD5) != 0U) {
-                       result = net_client_smtp_auth_cram(client, G_CHECKSUM_MD5, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_PLAIN) != 0U) {
-                       result = net_client_smtp_auth_plain(client, user, passwd, error);
-               } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_LOGIN) != 0U) {
-                       result = net_client_smtp_auth_login(client, user, passwd, error);
+               /* user name and password authentication methods */
+               g_signal_emit_by_name(client, "auth", NET_CLIENT_AUTH_USER_PASS, &auth_data);
+               if ((auth_data == NULL) || (auth_data[0] == NULL) || (auth_data[1] == NULL)) {
+                       g_set_error(error, NET_CLIENT_SMTP_ERROR_QUARK, (gint) NET_CLIENT_ERROR_SMTP_NO_AUTH,
+                               _("user name and password required"));
                } else {
-                       g_assert_not_reached();
+                       /* first check for safe (hashed) authentication methods, used plain-text ones if they 
are not supported */
+                       if ((auth_mask & NET_CLIENT_SMTP_AUTH_CRAM_SHA1) != 0U) {
+                               result = net_client_smtp_auth_cram(client, G_CHECKSUM_SHA1, auth_data[0], 
auth_data[1], error);
+                       } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_CRAM_MD5) != 0U) {
+                               result = net_client_smtp_auth_cram(client, G_CHECKSUM_MD5, auth_data[0], 
auth_data[1], error);
+                       } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_PLAIN) != 0U) {
+                               result = net_client_smtp_auth_plain(client, auth_data[0], auth_data[1], 
error);
+                       } else if ((auth_mask & NET_CLIENT_SMTP_AUTH_LOGIN) != 0U) {
+                               result = net_client_smtp_auth_login(client, auth_data[0], auth_data[1], 
error);
+                       } else {
+                               g_assert_not_reached();
+                       }
+               }
+       }
+
+       /* clean up any auth data */
+       if (auth_data != NULL) {
+               if (auth_data[0] != NULL) {
+                       net_client_free_authstr(auth_data[0]);
+                       net_client_free_authstr(auth_data[1]);
                }
+               free(auth_data);
        }
 
        return result;
diff --git a/libnetclient/net-client-smtp.h b/libnetclient/net-client-smtp.h
index c26d61c1a..373eb8916 100644
--- a/libnetclient/net-client-smtp.h
+++ b/libnetclient/net-client-smtp.h
@@ -125,8 +125,8 @@ gboolean net_client_smtp_set_auth_mode(NetClientSmtp *client, NetClientAuthMode
  * information unless anonymous access has been configured by calling net_client_smtp_set_auth_mode().
  *
  * The function will try only @em one authentication method which is both supported by the server and 
enabled by calling
- * net_client_smtp_set_auth_mode().  The default is to try all methods, from highest to lowest, OAuth2 (if 
configured), GSSAPI (if
- * configured), CRAM-SHA1, CRAM-MD5, PLAIN, LOGIN or anonymous.  It is up to the caller to ensure encryption 
or a connection to
+ * net_client_smtp_set_auth_mode().  The precedence is: no authentication, GSSAPI (Kerberos), OAuth2, user 
name and password.  For
+ * the latter, the order is CRAM-SHA1, CRAM-MD5, PLAIN, or LOGIN.  It is up to the caller to ensure 
encryption or a connection to
  * @c localhost if one of the plain text methods shall be used.
  *
  * In order to shut down a successfully established connection, just call <tt>g_object_unref()</tt> on the 
SMTP network client
diff --git a/libnetclient/net-client-utils.c b/libnetclient/net-client-utils.c
index 04b8c422a..0781956f0 100644
--- a/libnetclient/net-client-utils.c
+++ b/libnetclient/net-client-utils.c
@@ -129,6 +129,25 @@ net_client_auth_plain_calc(const gchar *user, const gchar *passwd)
 }
 
 
+gchar *
+net_client_auth_anonymous_token(void)
+{
+       gchar *buffer;
+       GChecksum *hash;
+       const gchar *hash_str;
+
+       buffer = g_strdup_printf("%s@%s:%ld", g_get_user_name(), g_get_host_name(), (long) time(NULL));
+       hash = g_checksum_new(G_CHECKSUM_SHA256);
+       g_checksum_update(hash, (const guchar *) buffer, strlen(buffer));
+       g_free(buffer);
+
+       hash_str = g_checksum_get_string(hash);
+       buffer = g_base64_encode((const guchar *) hash_str, strlen(hash_str));
+       g_checksum_free(hash);
+       return buffer;
+}
+
+
 void
 net_client_free_authstr(gchar *str)
 {
diff --git a/libnetclient/net-client-utils.h b/libnetclient/net-client-utils.h
index b521d4c62..4ca69f461 100644
--- a/libnetclient/net-client-utils.h
+++ b/libnetclient/net-client-utils.h
@@ -83,7 +83,7 @@ const gchar *net_client_chksum_to_str(GChecksumType chksum_type);
  * @param passwd password
  * @return a newly allocated string containing the base64-encoded authentication
  *
- * This helper function calculates the the base64-encoded SASL AUTH PLAIN authentication string from the 
user name and the password
+ * This helper function calculates the base64-encoded SASL AUTH PLAIN authentication string from the user 
name and the password
  * according to <a href="https://tools.ietf.org/html/rfc4616";>RFC 4616</a>.  The caller shall free the 
returned string when it is
  * not needed any more.
  */
@@ -101,6 +101,21 @@ gchar *net_client_auth_plain_calc(const gchar *user, const gchar *passwd)
 void net_client_free_authstr(gchar *str);
 
 
+/** @brief Create a token for anonymous authentication
+ *
+ * @return a newly allocated string containing the base64-encoded authentication
+ *
+ * This helper function calculates a base64-encoded SASL AUTH ANONYMOUS authentication token which is used 
as trace information by
+ * the server.  As recommended by RFC 4505, the token does not contain personal data.  The returned value is 
the encoded SHA256 hex
+ * hash of the string <c>user-name@host-name:time<c> (time is the creation time stamp as returned by 
time()).  This token will be
+ * unique, but makes it impossible for the server to extract user and host.  However, the client @em may 
store to token if linking
+ * server to client operations is required, e.g. for debugging purposes.
+ *
+ * The caller shall free the returned string when it is not needed any more.
+ */
+gchar *net_client_auth_anonymous_token(void);
+
+
 #if defined(HAVE_GSSAPI)
 
 /** @brief Create a GSSAPI authentication context
diff --git a/libnetclient/net-client.h b/libnetclient/net-client.h
index ab6102264..68392aaa8 100644
--- a/libnetclient/net-client.h
+++ b/libnetclient/net-client.h
@@ -52,7 +52,7 @@ enum _NetClientCryptMode {
 
 /** @brief Authentication mode */
 enum _NetClientAuthMode {
-       NET_CLIENT_AUTH_ANONYMOUS = 1,                  /**< No authentication required (e.g. local service, 
user cert authentication). */
+       NET_CLIENT_AUTH_NONE_ANON = 1,                  /**< No authentication (SMTP); anonymous 
authentication (RFC 4505 for POP3, IMAP). */
        NET_CLIENT_AUTH_USER_PASS = 2,                  /**< Authenticate with user name and password. */
        NET_CLIENT_AUTH_KERBEROS = 4,                   /**< Authenticate with user name and Kerberos ticket. 
*/
        NET_CLIENT_AUTH_OAUTH2 = 8                              /**< OAuth2 authentication (RFC 6749). */
@@ -343,12 +343,11 @@ gboolean net_client_can_read(NetClient *client);
  *   @endcode The server certificate is not trusted.  The received certificate and the errors which occurred 
during the check are
  *   passed to the signal handler.  The handler shall return TRUE to accept the certificate, or FALSE to 
reject it.
  * - @anchor auth auth
- *   @code gchar **get_auth(NetClient *client, gboolean need_passwd, gpointer user_data) @endcode 
Authentication is required by the
- *   remote server.  The signal handler shall return a NULL-terminated array of strings, containing the user 
name in the first and
- *   the password in the second element.  If the parameter @em need_passwd is FALSE, no password is required 
(e.g. for kerberos
- *   ticket-based or for OAuth2 authentication).  In this case, the password element must be present in the 
reply, but it is ignored
- *   an may be NULL.  The strings are wiped and freed when they are not needed any more.  Return NULL if no 
authentication is
- *   required.
+ *   @code gchar **get_auth(NetClient *client, NetClientAuthMode mode, gpointer user_data) @endcode 
Authentication is required by
+ *   the remote server.  The signal handler shall return a NULL-terminated array of strings, containing the 
user name in the first
+ *   and the password (mode @ref NET_CLIENT_AUTH_USER_PASS) or the OAuth2 access token (@ref 
NET_CLIENT_AUTH_OAUTH2) in the second
+ *   element.  For @ref NET_CLIENT_AUTH_KERBEROS, no password is required.  In this case, the second element 
must be present in the
+ *   reply, but it is ignored and should be NULL.  The strings are wiped and freed when they are not needed 
any more.
  */
 
 



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