[NetworkManager-openvpn/bg/ask-username: 7/7] auth-dialog: support dynamic challenge
- From: Beniamino Galvani <bgalvani src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [NetworkManager-openvpn/bg/ask-username: 7/7] auth-dialog: support dynamic challenge
- Date: Tue, 16 Oct 2018 20:21:17 +0000 (UTC)
commit 22ba8e3d11e68688c53c70e0b72c53a72fbd5d9f
Author: Beniamino Galvani <bgalvani redhat com>
Date: Mon Oct 15 14:15:17 2018 +0200
auth-dialog: support dynamic challenge
Add support for asking a dynamic challenge.
auth-dialog/main.c | 17 +++++++++-
shared/nm-service-defines.h | 2 ++
src/nm-openvpn-service.c | 79 ++++++++++++++++++++++++++++++---------------
3 files changed, 71 insertions(+), 27 deletions(-)
---
diff --git a/auth-dialog/main.c b/auth-dialog/main.c
index 262ff3f..9ad841c 100644
--- a/auth-dialog/main.c
+++ b/auth-dialog/main.c
@@ -67,6 +67,7 @@ typedef enum {
FIELD_TYPE_PASSWORD,
FIELD_TYPE_CERT_PASSWORD,
FIELD_TYPE_PROXY_PASSWORD,
+ FIELD_TYPE_DYNAMIC_CHALLENGE,
_FIELD_TYPE_NUM,
} FieldType;
@@ -329,6 +330,7 @@ get_passwords_required (GHashTable *data,
const char *ctype, *val;
NMSettingSecretFlags flags;
const char *const *iter;
+ gboolean ask_from_setting = TRUE;
guint i;
/* If hints are given, then always ask for what the hints require */
@@ -337,12 +339,18 @@ get_passwords_required (GHashTable *data,
*prompt = g_strdup (*iter + strlen (VPN_MSG_TAG));
else {
for (i = 0; i < _FIELD_TYPE_NUM; i++) {
- if (nm_streq (*iter, fields[i].key))
+ if (nm_streq (*iter, fields[i].key)) {
fields[i].needed = TRUE;
+ if (i != FIELD_TYPE_USER_NAME)
+ ask_from_setting = FALSE;
+ }
}
}
}
+ if (!ask_from_setting)
+ goto done;
+
ctype = g_hash_table_lookup (data, NM_OPENVPN_KEY_CONNECTION_TYPE);
g_return_val_if_fail (ctype, FALSE);
@@ -375,6 +383,7 @@ get_passwords_required (GHashTable *data,
fields[FIELD_TYPE_PROXY_PASSWORD].needed = TRUE;
}
+done:
for (i = 0; i < _FIELD_TYPE_NUM; i++) {
if (fields[i].needed)
return TRUE;
@@ -436,6 +445,12 @@ main (int argc, char *argv[])
.label_acc = N_("_HTTP proxy password:"),
.is_password = TRUE,
},
+ [FIELD_TYPE_DYNAMIC_CHALLENGE] = {
+ .key = "x-vpn-interactive-dynamic-challenge",
+ .label = N_("Answer:"),
+ .label_acc = N_("_Answer:"),
+ .is_password = FALSE,
+ },
};
nm_auto(clear_secrets) Field *_fields = fields;
diff --git a/shared/nm-service-defines.h b/shared/nm-service-defines.h
index 340d8d0..8539920 100644
--- a/shared/nm-service-defines.h
+++ b/shared/nm-service-defines.h
@@ -90,6 +90,8 @@
*/
#define NM_OPENVPN_KEY_NOSECRET "no-secret"
+/* Hint indicating that a dynamic challenge is required */
+#define NM_OPENVPN_KEY_DYNAMIC_CHALLENGE "x-vpn-interactive-dynamic-challenge"
#define NM_OPENVPN_AUTH_MD5 "MD5"
#define NM_OPENVPN_AUTH_NONE "none"
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index b0c3ff6..e2bc6d3 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -109,8 +109,12 @@ typedef struct {
char *proxy_username;
char *proxy_password;
char *pending_auth;
- char *challenge_state_id;
- char *challenge_text;
+ struct {
+ char *state_id;
+ char *text;
+ char *user;
+ char *response;
+ } challenge;
GIOChannel *socket_channel;
guint socket_channel_eventid;
} NMOpenvpnPluginIOData;
@@ -769,8 +773,11 @@ nm_openvpn_disconnect_management_socket (NMOpenvpnPlugin *plugin)
if (io_data->proxy_password)
memset (io_data->proxy_password, 0, strlen (io_data->proxy_password));
g_free (io_data->proxy_password);
- g_free (io_data->challenge_state_id);
- g_free (io_data->challenge_text);
+
+ g_free (io_data->challenge.state_id);
+ g_free (io_data->challenge.text);
+ g_free (io_data->challenge.user);
+ g_free (io_data->challenge.response);
g_free (priv->io_data);
priv->io_data = NULL;
@@ -818,9 +825,13 @@ get_detail (const char *input, const char *prefix)
* CRV1:flags:state_id:username:text
*/
static gboolean
-parse_challenge (const char *failure_reason, char **challenge_state_id, char **challenge_text)
+parse_challenge (const char *failure_reason,
+ char **challenge_state_id,
+ char **challenge_text,
+ char **challenge_user)
{
const char *colon[4];
+ gsize out_len;
if ( !failure_reason
|| !g_str_has_prefix (failure_reason, "CRV1:"))
@@ -844,6 +855,10 @@ parse_challenge (const char *failure_reason, char **challenge_state_id, char **c
*challenge_state_id = g_strndup (colon[1] + 1, colon[2] - colon[1] - 1);
*challenge_text = g_strdup (colon[3] + 1);
+ *challenge_user = g_strndup (colon[2] + 1, colon[3] - colon[2] - 1);
+ g_base64_decode_inplace (*challenge_user, &out_len);
+ (*challenge_user)[out_len] = 0;
+
return TRUE;
}
@@ -898,18 +913,23 @@ handle_auth (NMOpenvpnPluginIOData *io_data,
return FALSE;
}
- if (io_data->password && io_data->challenge_state_id) {
- gs_free char *response = NULL;
+ if (io_data->challenge.response) {
+ gs_free char *password = NULL;
+
+ password = g_strdup_printf ("CRV1::%s::%s",
+ io_data->challenge.state_id,
+ io_data->challenge.response);
+
+ _LOGW (" ---------- sending answer for user '%s': %s", io_data->challenge.user,
password);
- response = g_strdup_printf ("CRV1::%s::%s",
- io_data->challenge_state_id,
- io_data->password);
write_user_pass (io_data->socket_channel,
requested_auth,
- io_data->username,
- response);
- nm_clear_g_free (&io_data->challenge_state_id);
- nm_clear_g_free (&io_data->challenge_text);
+ io_data->challenge.user,
+ password);
+ nm_clear_g_free (&io_data->challenge.state_id);
+ nm_clear_g_free (&io_data->challenge.text);
+ nm_clear_g_free (&io_data->challenge.user);
+ nm_clear_g_free (&io_data->challenge.response);
} else if (io_data->password) {
write_user_pass (io_data->socket_channel,
requested_auth,
@@ -918,14 +938,14 @@ handle_auth (NMOpenvpnPluginIOData *io_data,
} else {
hints = g_new0 (const char *, 3);
- hints[i++] = "x-vpn-interactive-username";
- hints[i++] = NM_OPENVPN_KEY_PASSWORD;
- *out_message = _("Credentials are required.");
-
- /* FIXME: this is wrong, we can't reuse the password
- * hint for the challenge. */
- if (io_data->challenge_text)
- *out_message = io_data->challenge_text;
+ if (io_data->challenge.text) {
+ hints[i++] = NM_OPENVPN_KEY_DYNAMIC_CHALLENGE;
+ *out_message = io_data->challenge.text;
+ } else {
+ hints[i++] = "x-vpn-interactive-username";
+ hints[i++] = NM_OPENVPN_KEY_PASSWORD;
+ *out_message = _("Credentials are required.");
+ }
}
handled = TRUE;
} else if (nm_streq (requested_auth, "Private Key")) {
@@ -1052,10 +1072,14 @@ handle_management_socket (NMOpenvpnPlugin *plugin,
gs_free char *failure_reason = NULL;
failure_reason = get_detail (str, ">PASSWORD:Verification Failed: 'Auth' ['");
- if (parse_challenge (failure_reason, &priv->io_data->challenge_state_id,
&priv->io_data->challenge_text)) {
- _LOGD ("Received challenge '%s' for state '%s'",
- priv->io_data->challenge_state_id,
- priv->io_data->challenge_text);
+ if (parse_challenge (failure_reason,
+ &priv->io_data->challenge.state_id,
+ &priv->io_data->challenge.text,
+ &priv->io_data->challenge.user)) {
+ _LOGD ("Received challenge '%s' for user '%s' and state '%s'",
+ priv->io_data->challenge.state_id,
+ priv->io_data->challenge.user,
+ priv->io_data->challenge.text);
} else
_LOGW ("Password verification failed");
@@ -1226,6 +1250,9 @@ update_io_data_from_vpn_setting (NMOpenvpnPluginIOData *io_data,
g_free (io_data->proxy_password);
}
io_data->proxy_password = g_strdup (nm_setting_vpn_get_secret (s_vpn,
NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD));
+
+ g_free (io_data->challenge.response);
+ io_data->challenge.response = g_strdup (nm_setting_vpn_get_secret (s_vpn,
NM_OPENVPN_KEY_DYNAMIC_CHALLENGE));
}
static char *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]