[PATCH v2 13/13] ublox: check which auth methods are supported

Aleksander Morgado aleksander at aleksander.es
Fri Sep 15 05:01:09 UTC 2017


Don't assume the 'auto' auth method is supported for APN
authentication, query the modem first:

    checking supported authentication methods...
    (ttyACM2): --> 'AT+UAUTHREQ=?<CR>'
    (ttyACM2): <-- '<CR><LF>+UAUTHREQ: (1-4),(0-2),,<CR><LF>'
    (ttyACM2): <-- '<CR><LF>OK<CR><LF>'

    Using automatic authentication method

    setting up authentication preferences in PDP context #2...
    (ttyACM2): --> 'AT+UAUTHREQ=2,1,"vodafone","vodafone"<CR>'
    (ttyACM2): <-- '<CR><LF>OK<CR><LF>'
---
 plugins/ublox/mm-broadband-bearer-ublox.c | 169 +++++++++++++++++++++++-------
 1 file changed, 130 insertions(+), 39 deletions(-)

diff --git a/plugins/ublox/mm-broadband-bearer-ublox.c b/plugins/ublox/mm-broadband-bearer-ublox.c
index 866b2e7f..3cb17336 100644
--- a/plugins/ublox/mm-broadband-bearer-ublox.c
+++ b/plugins/ublox/mm-broadband-bearer-ublox.c
@@ -51,9 +51,10 @@ typedef enum {
 } FeatureSupport;

 struct _MMBroadbandBearerUbloxPrivate {
-    MMUbloxUsbProfile     profile;
-    MMUbloxNetworkingMode mode;
-    FeatureSupport        statistics;
+    MMUbloxUsbProfile        profile;
+    MMUbloxNetworkingMode    mode;
+    MMUbloxBearerAllowedAuth allowed_auths;
+    FeatureSupport           statistics;
 };

 /*****************************************************************************/
@@ -393,59 +394,76 @@ uauthreq_ready (MMBaseModem  *modem,
 static void
 authenticate_3gpp (GTask *task)
 {
-    const gchar          *user;
-    const gchar          *password;
-    MMBearerAllowedAuth   allowed_auth;
-    CommonConnectContext *ctx;
-    gchar                *cmd;
+    MMBroadbandBearerUblox *self;
+    CommonConnectContext   *ctx;
+    gchar                  *cmd = NULL;
+    MMBearerAllowedAuth     allowed_auth;
+    gint                    ublox_auth = -1;

+    self = g_task_get_source_object (task);
     ctx = (CommonConnectContext *) g_task_get_task_data (task);

-    user         = mm_bearer_properties_get_user         (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
-    password     = mm_bearer_properties_get_password     (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
     allowed_auth = mm_bearer_properties_get_allowed_auth (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));

-    /* Flag whether authentication is required. If it isn't, we won't fail
-     * connection attempt if the +UAUTHREQ command fails */
-    ctx->auth_required = (user && password && allowed_auth != MM_BEARER_ALLOWED_AUTH_NONE);
     if (!ctx->auth_required) {
         mm_dbg ("Not using authentication");
-        cmd = g_strdup_printf ("+UAUTHREQ=%u,0", ctx->cid);
-    } else {
-        gchar *quoted_user;
-        gchar *quoted_password;
-        guint  ublox_auth;
+        ublox_auth = 0;
+        goto out;
+    }

-        if (allowed_auth == MM_BEARER_ALLOWED_AUTH_UNKNOWN || allowed_auth == (MM_BEARER_ALLOWED_AUTH_PAP | MM_BEARER_ALLOWED_AUTH_CHAP)) {
-            mm_dbg ("Using automatic authentication method");
+    if (allowed_auth == MM_BEARER_ALLOWED_AUTH_UNKNOWN || allowed_auth == (MM_BEARER_ALLOWED_AUTH_PAP | MM_BEARER_ALLOWED_AUTH_CHAP)) {
+        mm_dbg ("Using automatic authentication method");
+        if (self->priv->allowed_auths & MM_UBLOX_BEARER_ALLOWED_AUTH_AUTO)
             ublox_auth = 3;
-        } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_PAP) {
-            mm_dbg ("Using PAP authentication method");
+        else if (self->priv->allowed_auths & MM_UBLOX_BEARER_ALLOWED_AUTH_PAP)
             ublox_auth = 1;
-        } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_CHAP) {
-            mm_dbg ("Using CHAP authentication method");
+        else if (self->priv->allowed_auths & MM_UBLOX_BEARER_ALLOWED_AUTH_CHAP)
             ublox_auth = 2;
-        } else {
-            gchar *str;
+        else if (self->priv->allowed_auths & MM_UBLOX_BEARER_ALLOWED_AUTH_NONE)
+            ublox_auth = 0;
+    } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_PAP) {
+        mm_dbg ("Using PAP authentication method");
+        ublox_auth = 1;
+    } else if (allowed_auth & MM_BEARER_ALLOWED_AUTH_CHAP) {
+        mm_dbg ("Using CHAP authentication method");
+        ublox_auth = 2;
+    }

-            str = mm_bearer_allowed_auth_build_string_from_mask (allowed_auth);
-            g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
-                                     "Cannot use any of the specified authentication methods (%s)", str);
-            g_object_unref (task);
-            g_free (str);
-            return;
-        }
+out:
+
+    if (ublox_auth < 0) {
+        gchar *str;
+
+        str = mm_bearer_allowed_auth_build_string_from_mask (allowed_auth);
+        g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+                                 "Cannot use any of the specified authentication methods (%s)", str);
+        g_object_unref (task);
+        g_free (str);
+        return;
+    }
+
+    if (ublox_auth > 0) {
+        const gchar *user;
+        const gchar *password;
+        gchar       *quoted_user;
+        gchar       *quoted_password;

-        quoted_user = mm_port_serial_at_quote_string (user);
+        user     = mm_bearer_properties_get_user     (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
+        password = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
+
+        quoted_user     = mm_port_serial_at_quote_string (user);
         quoted_password = mm_port_serial_at_quote_string (password);
+
         cmd = g_strdup_printf ("+UAUTHREQ=%u,%u,%s,%s",
                                ctx->cid,
                                ublox_auth,
                                quoted_password,
                                quoted_user);
+
         g_free (quoted_user);
         g_free (quoted_password);
-    }
+    } else
+        cmd = g_strdup_printf ("+UAUTHREQ=%u,0", ctx->cid);

     mm_dbg ("setting up authentication preferences in PDP context #%u...", ctx->cid);
     mm_base_modem_at_command (MM_BASE_MODEM (ctx->modem),
@@ -457,6 +475,78 @@ authenticate_3gpp (GTask *task)
     g_free (cmd);
 }

+static void
+uauthreq_test_ready (MMBaseModem  *modem,
+                     GAsyncResult *res,
+                     GTask        *task)
+{
+    MMBroadbandBearerUblox *self;
+    const gchar            *response;
+    GError                 *error = NULL;
+
+    self = g_task_get_source_object (task);
+
+    response = mm_base_modem_at_command_finish (modem, res, &error);
+    if (!response)
+        goto out;
+
+    self->priv->allowed_auths = mm_ublox_parse_uauthreq_test (response, &error);
+out:
+    if (error) {
+        CommonConnectContext *ctx;
+
+        ctx = (CommonConnectContext *) g_task_get_task_data (task);
+        /* If authentication required and the +UAUTHREQ test failed, abort */
+        if (ctx->auth_required) {
+            g_task_return_error (task, error);
+            g_object_unref (task);
+            return;
+        }
+        /* Otherwise, ignore and jump to activate_3gpp directly as no auth setup
+         * is needed */
+        g_error_free (error);
+        activate_3gpp (task);
+        return;
+    }
+
+    authenticate_3gpp (task);
+}
+
+static void
+check_supported_authentication_methods (GTask *task)
+{
+    MMBroadbandBearerUblox *self;
+    CommonConnectContext   *ctx;
+    const gchar            *user;
+    const gchar            *password;
+    MMBearerAllowedAuth     allowed_auth;
+
+    self = g_task_get_source_object (task);
+    ctx = (CommonConnectContext *) g_task_get_task_data (task);
+
+    user         = mm_bearer_properties_get_user         (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
+    password     = mm_bearer_properties_get_password     (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
+    allowed_auth = mm_bearer_properties_get_allowed_auth (mm_base_bearer_peek_config (MM_BASE_BEARER (ctx->self)));
+
+    /* Flag whether authentication is required. If it isn't, we won't fail
+     * connection attempt if the +UAUTHREQ command fails */
+    ctx->auth_required = (user && password && allowed_auth != MM_BEARER_ALLOWED_AUTH_NONE);
+
+    /* If we already cached the support, not do it again */
+    if (self->priv->allowed_auths != MM_UBLOX_BEARER_ALLOWED_AUTH_UNKNOWN) {
+        authenticate_3gpp (task);
+        return;
+    }
+
+    mm_dbg ("checking supported authentication methods...");
+    mm_base_modem_at_command (MM_BASE_MODEM (ctx->modem),
+                              "+UAUTHREQ=?",
+                              10,
+                              TRUE, /* allow cached */
+                              (GAsyncReadyCallback) uauthreq_test_ready,
+                              task);
+}
+
 static void
 dial_3gpp (MMBroadbandBearer   *self,
            MMBaseModem         *modem,
@@ -478,7 +568,7 @@ dial_3gpp (MMBroadbandBearer   *self,
                                           user_data)))
         return;

-    authenticate_3gpp (task);
+    check_supported_authentication_methods (task);
 }

 /*****************************************************************************/
@@ -785,9 +875,10 @@ mm_broadband_bearer_ublox_init (MMBroadbandBearerUblox *self)
                                               MMBroadbandBearerUbloxPrivate);

     /* Defaults */
-    self->priv->profile    = MM_UBLOX_USB_PROFILE_UNKNOWN;
-    self->priv->mode       = MM_UBLOX_NETWORKING_MODE_UNKNOWN;
-    self->priv->statistics = FEATURE_SUPPORT_UNKNOWN;
+    self->priv->profile       = MM_UBLOX_USB_PROFILE_UNKNOWN;
+    self->priv->mode          = MM_UBLOX_NETWORKING_MODE_UNKNOWN;
+    self->priv->allowed_auths = MM_UBLOX_BEARER_ALLOWED_AUTH_UNKNOWN;
+    self->priv->statistics    = FEATURE_SUPPORT_UNKNOWN;
 }

 static void
--
2.14.1


More information about the ModemManager-devel mailing list