[network-manager-vpnc/dcbw/auth-refactor: 1/2] auth-dialog: refactor standard vs. external-ui-mode logic (bgo #728681)
- From: Dan Williams <dcbw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-vpnc/dcbw/auth-refactor: 1/2] auth-dialog: refactor standard vs. external-ui-mode logic (bgo #728681)
- Date: Mon, 28 Apr 2014 16:11:31 +0000 (UTC)
commit 19de1759fceb2b43a37671a08075ddd175a24f05
Author: Dan Williams <dcbw redhat com>
Date: Tue Apr 22 16:50:22 2014 -0500
auth-dialog: refactor standard vs. external-ui-mode logic (bgo #728681)
Give each method a much clearer path and make sure they aren't
tangled together.
This should also fix a bug with external-ui-mode where if no
secrets were required, or both secrets were saved, that external
UI mode would exit early without writing a keyfile to stdout.
This caused a traceback in GNOME Shell 3.12.
https://bugzilla.gnome.org/show_bug.cgi?id=728681
Based off NM-openvpn commit 440671733a3e38c63a9b5882482c4cc710c71a39
auth-dialog/main.c | 483 ++++++++++++++++++++++++++++++++++------------------
1 files changed, 319 insertions(+), 164 deletions(-)
---
diff --git a/auth-dialog/main.c b/auth-dialog/main.c
index 62ae146..ade3570 100644
--- a/auth-dialog/main.c
+++ b/auth-dialog/main.c
@@ -88,6 +88,33 @@ keyring_lookup_secret (const char *uuid, const char *secret_name)
return secret;
}
+/*****************************************************************/
+
+typedef void (*NoSecretsRequiredFunc) (void);
+
+/* Returns TRUE on success, FALSE on cancel */
+typedef gboolean (*AskUserFunc) (const char *vpn_name,
+ const char *prompt,
+ gboolean retry,
+ gboolean need_password,
+ const char *existing_password,
+ char **out_new_password,
+ gboolean need_certpass,
+ const char *existing_certpass,
+ char **out_new_certpass);
+
+typedef void (*FinishFunc) (const char *vpn_name,
+ const char *prompt,
+ gboolean allow_interaction,
+ gboolean retry,
+ gboolean need_password,
+ const char *password,
+ gboolean need_certpass,
+ const char *certpass);
+
+/*****************************************************************/
+/* External UI mode stuff */
+
static void
keyfile_add_entry_info (GKeyFile *keyfile,
const gchar *key,
@@ -115,159 +142,126 @@ keyfile_print_stdout (GKeyFile *keyfile)
g_free (data);
}
-static gboolean
-get_secrets (const char *vpn_uuid,
- const char *vpn_name,
- gboolean retry,
- gboolean allow_interaction,
- gboolean external_ui_mode,
- const char *in_upw,
- char **out_upw,
- NMSettingSecretFlags upw_flags,
- const char *in_gpw,
- char **out_gpw,
- NMSettingSecretFlags gpw_flags)
+static void
+eui_no_secrets_required (void)
{
- NMAVpnPasswordDialog *dialog;
- char *upw = NULL, *gpw = NULL;
- char *prompt;
- gboolean success = FALSE;
- gboolean need_upw = TRUE, need_gpw = TRUE;
+ GKeyFile *keyfile;
- g_return_val_if_fail (vpn_uuid != NULL, FALSE);
- g_return_val_if_fail (vpn_name != NULL, FALSE);
- g_return_val_if_fail (out_upw != NULL, FALSE);
- g_return_val_if_fail (*out_upw == NULL, FALSE);
- g_return_val_if_fail (out_gpw != NULL, FALSE);
- g_return_val_if_fail (*out_gpw == NULL, FALSE);
-
- if ( !(upw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
- && !(upw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) {
- if (in_upw)
- upw = g_strdup (in_upw);
- else
- upw = keyring_lookup_secret (vpn_uuid, NM_VPNC_KEY_XAUTH_PASSWORD);
-
- /* Try the old name */
- if (upw == NULL)
- upw = keyring_lookup_secret (vpn_uuid, "password");
- }
-
- if ( !(gpw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
- && !(gpw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) {
- if (in_gpw)
- gpw = g_strdup (in_gpw);
- else
- gpw = keyring_lookup_secret (vpn_uuid, NM_VPNC_KEY_SECRET);
-
- /* Try the old name */
- if (gpw == NULL)
- gpw = keyring_lookup_secret (vpn_uuid, "group-password");
- }
-
- if (!retry) {
- /* Don't ask if both passwords are either saved and present, or unused */
- if (upw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
- need_upw = FALSE;
- else if (upw && !(upw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
- *out_upw = upw;
- need_upw = FALSE;
- }
+ keyfile = g_key_file_new ();
+ g_key_file_set_integer (keyfile, UI_KEYFILE_GROUP, "Version", 2);
+ keyfile_print_stdout (keyfile);
+ g_key_file_unref (keyfile);
+}
- if (gpw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
- need_gpw = FALSE;
- else if (gpw && !(gpw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
- *out_gpw = gpw;
- need_gpw = FALSE;
- }
+static void
+eui_finish (const char *vpn_name,
+ const char *prompt,
+ gboolean allow_interaction,
+ gboolean retry,
+ gboolean need_password,
+ const char *existing_password,
+ gboolean need_group_password,
+ const char *existing_group_password)
+{
+ GKeyFile *keyfile;
+ char *title;
+ gboolean show;
- if (!need_upw && !need_gpw)
- return TRUE;
- } else {
- need_upw = !(upw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED);
- need_gpw = !(gpw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED);
+ keyfile = g_key_file_new ();
- /* Don't ask if both passwords are unused */
- if (!need_upw && !need_gpw)
- return TRUE;
- }
+ g_key_file_set_integer (keyfile, UI_KEYFILE_GROUP, "Version", 2);
+ g_key_file_set_string (keyfile, UI_KEYFILE_GROUP, "Description", prompt);
- prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network '%s'."),
vpn_name);
+ title = g_strdup_printf (_("Authenticate VPN %s"), vpn_name);
+ g_key_file_set_string (keyfile, UI_KEYFILE_GROUP, "Title", title);
+ g_free (title);
- if (external_ui_mode) {
- GKeyFile *keyfile;
+ /* Only show an entry for a password if (a) we don't have it, and it's
+ * required, or (b) we're retrying authentication. Obviously don't show
+ * anything if interaction is not allowed.
+ */
- keyfile = g_key_file_new ();
+ show = (need_password && !existing_password) || retry;
+ keyfile_add_entry_info (keyfile,
+ NM_VPNC_KEY_XAUTH_PASSWORD,
+ existing_password ? existing_password : "",
+ _("Password:"),
+ TRUE,
+ show && allow_interaction);
+
+ show = (need_group_password && !existing_group_password) || retry;
+ keyfile_add_entry_info (keyfile,
+ NM_VPNC_KEY_SECRET,
+ existing_group_password ? existing_group_password : "",
+ _("Group Password:"),
+ TRUE,
+ show && allow_interaction);
+
+ keyfile_print_stdout (keyfile);
+ g_key_file_unref (keyfile);
+}
- g_key_file_set_integer (keyfile, UI_KEYFILE_GROUP, "Version", 2);
- g_key_file_set_string (keyfile, UI_KEYFILE_GROUP, "Description", prompt);
- g_key_file_set_string (keyfile, UI_KEYFILE_GROUP, "Title", _("Authenticate VPN"));
+/*****************************************************************/
- keyfile_add_entry_info (keyfile, NM_VPNC_KEY_XAUTH_PASSWORD, upw ? upw : "", _("Password:"),
TRUE, need_upw && allow_interaction);
- keyfile_add_entry_info (keyfile, NM_VPNC_KEY_SECRET, gpw ? gpw : "", _("Group Password:"),
TRUE, need_gpw && allow_interaction);
+static void
+std_no_secrets_required (void)
+{
+ printf ("\n\n");
+}
- keyfile_print_stdout (keyfile);
- g_key_file_unref (keyfile);
+static gboolean
+std_ask_user (const char *vpn_name,
+ const char *prompt,
+ gboolean retry,
+ gboolean need_password,
+ const char *existing_password,
+ char **out_new_password,
+ gboolean need_group_password,
+ const char *existing_group_password,
+ char **out_new_group_password)
+{
+ NMAVpnPasswordDialog *dialog;
+ gboolean success = FALSE;
- success = TRUE;
- goto out;
- } else if (allow_interaction == FALSE) {
- /* If interaction isn't allowed, just return existing secrets */
- *out_upw = upw;
- *out_gpw = gpw;
- g_free (prompt);
- return TRUE;
- }
+ g_return_val_if_fail (vpn_name != NULL, FALSE);
+ g_return_val_if_fail (prompt != NULL, FALSE);
+ g_return_val_if_fail (out_new_password != NULL, FALSE);
+ g_return_val_if_fail (out_new_group_password != NULL, FALSE);
dialog = NMA_VPN_PASSWORD_DIALOG (nma_vpn_password_dialog_new (_("Authenticate VPN"), prompt, NULL));
- nma_vpn_password_dialog_set_password_secondary_label (dialog, _("_Group Password:"));
+ /* pre-fill dialog with existing passwords */
+ if (need_password && need_group_password) {
+ nma_vpn_password_dialog_set_show_password_secondary (dialog, TRUE);
+ nma_vpn_password_dialog_set_password_secondary_label (dialog, _("_Group Password:"));
- /* Don't show the user password entry if the user password isn't required,
- * or if we don't need new secrets and the user password is saved.
- */
- if (upw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
- nma_vpn_password_dialog_set_show_password (dialog, FALSE);
- else if (!retry && upw && !(upw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
- nma_vpn_password_dialog_set_show_password (dialog, FALSE);
-
- if (gpw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
- nma_vpn_password_dialog_set_show_password_secondary (dialog, FALSE);
- else if (!retry && gpw && !(gpw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
+ nma_vpn_password_dialog_set_password (dialog, existing_password);
+ nma_vpn_password_dialog_set_password_secondary (dialog, existing_group_password);
+ } else {
nma_vpn_password_dialog_set_show_password_secondary (dialog, FALSE);
-
- /* On reprompt the first entry of type 'ask' gets the focus */
- if (retry) {
- if (upw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
- nma_vpn_password_dialog_focus_password (dialog);
- else if (gpw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
- nma_vpn_password_dialog_focus_password_secondary (dialog);
+ if (need_password)
+ nma_vpn_password_dialog_set_password (dialog, existing_password);
+ else if (need_group_password) {
+ nma_vpn_password_dialog_set_password_label (dialog, _("_Group Password:"));
+ nma_vpn_password_dialog_set_password (dialog, existing_group_password);
+ }
}
- /* if retrying, pre-fill dialog with the password */
- if (upw)
- nma_vpn_password_dialog_set_password (dialog, upw);
-
- if (gpw)
- nma_vpn_password_dialog_set_password_secondary (dialog, gpw);
-
gtk_widget_show (GTK_WIDGET (dialog));
-
- /* Show the dialog */
- success = nma_vpn_password_dialog_run_and_block (dialog);
- if (success) {
- *out_upw = g_strdup (nma_vpn_password_dialog_get_password (dialog));
- *out_gpw = g_strdup (nma_vpn_password_dialog_get_password_secondary (dialog));
+ if (nma_vpn_password_dialog_run_and_block (dialog)) {
+ if (need_password)
+ *out_new_password = g_strdup (nma_vpn_password_dialog_get_password (dialog));
+
+ if (need_group_password) {
+ if (need_password)
+ *out_new_group_password = g_strdup
(nma_vpn_password_dialog_get_password_secondary (dialog));
+ else
+ *out_new_group_password = g_strdup (nma_vpn_password_dialog_get_password
(dialog));
+ }
+ success = TRUE;
}
- gtk_widget_hide (GTK_WIDGET (dialog));
gtk_widget_destroy (GTK_WIDGET (dialog));
-
- out:
- g_free (prompt);
- g_free (upw);
- g_free (gpw);
-
return success;
}
@@ -296,6 +290,32 @@ wait_for_quit (void)
g_string_free (str, TRUE);
}
+static void
+std_finish (const char *vpn_name,
+ const char *prompt,
+ gboolean allow_interaction,
+ gboolean finish,
+ gboolean need_password,
+ const char *password,
+ gboolean need_group_password,
+ const char *group_password)
+{
+ /* Send the passwords back to our parent */
+ if (password)
+ printf ("%s\n%s\n", NM_VPNC_KEY_XAUTH_PASSWORD, password);
+ if (group_password)
+ printf ("%s\n%s\n", NM_VPNC_KEY_SECRET, group_password);
+ printf ("\n\n");
+
+ /* for good measure, flush stdout since Kansas is going Bye-Bye */
+ fflush (stdout);
+
+ /* Wait for quit signal */
+ wait_for_quit ();
+}
+
+/*****************************************************************/
+
static NMSettingSecretFlags
get_pw_flags (GHashTable *hash, const char *secret_name, const char *type_name)
{
@@ -320,16 +340,115 @@ get_pw_flags (GHashTable *hash, const char *secret_name, const char *type_name)
return NM_SETTING_SECRET_FLAG_NONE;
}
+static void
+get_existing_passwords (GHashTable *vpn_data,
+ GHashTable *existing_secrets,
+ const char *vpn_uuid,
+ gboolean need_password,
+ gboolean need_group_password,
+ char **out_password,
+ char **out_group_password)
+{
+ NMSettingSecretFlags upw_flags = NM_SETTING_SECRET_FLAG_NONE;
+ NMSettingSecretFlags gpw_flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ g_return_if_fail (out_password != NULL);
+ g_return_if_fail (out_group_password != NULL);
+
+ upw_flags = get_pw_flags (existing_secrets, NM_VPNC_KEY_XAUTH_PASSWORD,
NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+ if (need_password) {
+ if (!(upw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
+ *out_password = g_strdup (g_hash_table_lookup (existing_secrets,
NM_VPNC_KEY_XAUTH_PASSWORD));
+ if (!*out_password)
+ *out_password = keyring_lookup_secret (vpn_uuid, NM_VPNC_KEY_XAUTH_PASSWORD);
+
+ /* Try the old name */
+ if (!*out_password)
+ *out_password = keyring_lookup_secret (vpn_uuid, "password");
+ }
+ }
+
+ gpw_flags = get_pw_flags (existing_secrets, NM_VPNC_KEY_SECRET, NM_VPNC_KEY_SECRET_TYPE);
+ if (need_group_password) {
+ if (!(gpw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
+ *out_group_password = g_strdup (g_hash_table_lookup (existing_secrets,
NM_VPNC_KEY_SECRET));
+ if (!*out_group_password)
+ *out_group_password = keyring_lookup_secret (vpn_uuid, NM_VPNC_KEY_SECRET);
+
+ /* Try the old name */
+ if (!*out_group_password)
+ *out_group_password = keyring_lookup_secret (vpn_uuid, "group-password");
+ }
+ }
+}
+
+#define VPN_MSG_TAG "x-vpn-message:"
+
+static char *
+get_passwords_required (GHashTable *data,
+ char **hints,
+ gboolean *out_need_password,
+ gboolean *out_need_group_password)
+{
+ NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+ char *prompt = NULL;
+ char **iter;
+
+ /* If hints are given, then always ask for what the hints require */
+ if (hints && g_strv_length (hints)) {
+ for (iter = hints; iter && *iter; iter++) {
+ if (!prompt && g_str_has_prefix (*iter, VPN_MSG_TAG))
+ prompt = g_strdup (*iter + strlen (VPN_MSG_TAG));
+ else if (strcmp (*iter, NM_VPNC_KEY_XAUTH_PASSWORD) == 0)
+ *out_need_password = TRUE;
+ else if (strcmp (*iter, NM_VPNC_KEY_SECRET) == 0)
+ *out_need_group_password = TRUE;
+ }
+ return prompt;
+ }
+
+ /* User password (XAuth password) */
+ flags = get_pw_flags (data, NM_VPNC_KEY_XAUTH_PASSWORD, NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
+ if (!(flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED))
+ *out_need_password = TRUE;
+
+ /* Group password (IPSec secret) */
+ flags = get_pw_flags (data, NM_VPNC_KEY_SECRET, NM_VPNC_KEY_SECRET_TYPE);
+ if (!(flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED))
+ *out_need_group_password = TRUE;
+
+ return NULL;
+}
+
+static void
+free_secret (char *p)
+{
+ if (p) {
+ memset (p, 0, strlen (p));
+ g_free (p);
+ }
+}
+
int
main (int argc, char *argv[])
{
gboolean retry = FALSE, allow_interaction = FALSE, external_ui_mode = FALSE;
- char *vpn_name = NULL, *vpn_uuid = NULL, *vpn_service = NULL;
+ char *vpn_name = NULL;
+ char *vpn_uuid = NULL;
+ char *vpn_service = NULL;
GHashTable *data = NULL, *secrets = NULL;
- char *password = NULL, *group_password = NULL;
- NMSettingSecretFlags upw_flags = NM_SETTING_SECRET_FLAG_NONE;
- NMSettingSecretFlags gpw_flags = NM_SETTING_SECRET_FLAG_NONE;
+ gboolean need_password = FALSE, need_group_password = FALSE;
+ char *existing_password = NULL, *existing_group_password = NULL;
+ char *new_password = NULL, *new_group_password = NULL;
GError *error = NULL;
+ char **hints = NULL;
+ char *prompt = NULL;
+ gboolean canceled = FALSE, ask_user = FALSE;
+
+ NoSecretsRequiredFunc no_secrets_required_func = NULL;
+ AskUserFunc ask_user_func = NULL;
+ FinishFunc finish_func = NULL;
+
GOptionContext *context;
GOptionEntry entries[] = {
{ "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL},
@@ -338,23 +457,23 @@ main (int argc, char *argv[])
{ "service", 's', 0, G_OPTION_ARG_STRING, &vpn_service, "VPN service type", NULL},
{ "allow-interaction", 'i', 0, G_OPTION_ARG_NONE, &allow_interaction, "Allow user
interaction", NULL},
{ "external-ui-mode", 0, 0, G_OPTION_ARG_NONE, &external_ui_mode, "External UI mode",
NULL},
+ { "hint", 't', 0, G_OPTION_ARG_STRING_ARRAY, &hints, "Hints from the VPN plugin",
NULL},
{ NULL }
};
bindtextdomain (GETTEXT_PACKAGE, NULL);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- gtk_init (&argc, &argv);
textdomain (GETTEXT_PACKAGE);
+ gtk_init (&argc, &argv);
+
context = g_option_context_new ("- vpnc auth dialog");
g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
-
if (!g_option_context_parse (context, &argc, &argv, &error)) {
fprintf (stderr, "Error parsing options: %s\n", error->message);
g_error_free (error);
return 1;
}
-
g_option_context_free (context);
if (!vpn_uuid || !vpn_service || !vpn_name) {
@@ -373,40 +492,76 @@ main (int argc, char *argv[])
return 1;
}
- upw_flags = get_pw_flags (data, NM_VPNC_KEY_XAUTH_PASSWORD, NM_VPNC_KEY_XAUTH_PASSWORD_TYPE);
- gpw_flags = get_pw_flags (data, NM_VPNC_KEY_SECRET, NM_VPNC_KEY_SECRET_TYPE);
-
- if (!get_secrets (vpn_uuid, vpn_name,
- retry, allow_interaction, external_ui_mode,
- g_hash_table_lookup (secrets, NM_VPNC_KEY_XAUTH_PASSWORD),
- &password,
- upw_flags,
- g_hash_table_lookup (secrets, NM_VPNC_KEY_SECRET),
- &group_password,
- gpw_flags))
- return 1;
-
- if (!external_ui_mode) {
- /* dump the passwords to stdout */
- if (password)
- printf ("%s\n%s\n", NM_VPNC_KEY_XAUTH_PASSWORD, password);
- if (group_password)
- printf ("%s\n%s\n", NM_VPNC_KEY_SECRET, group_password);
- printf ("\n\n");
+ if (external_ui_mode) {
+ no_secrets_required_func = eui_no_secrets_required;
+ finish_func = eui_finish;
+ } else {
+ no_secrets_required_func = std_no_secrets_required;
+ ask_user_func = std_ask_user;
+ finish_func = std_finish;
+ }
- g_free (password);
- g_free (group_password);
+ /* Determine which passwords are actually required, either from hints or
+ * from looking at the VPN configuration.
+ */
+ prompt = get_passwords_required (data, hints, &need_password, &need_group_password);
+ if (!prompt)
+ prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network
'%s'."), vpn_name);
+
+ /* Exit early if we don't need any passwords */
+ if (!need_password && !need_group_password)
+ no_secrets_required_func ();
+ else {
+ get_existing_passwords (data,
+ secrets,
+ vpn_uuid,
+ need_password,
+ need_group_password,
+ &existing_password,
+ &existing_group_password);
+ if (need_password && !existing_password)
+ ask_user = TRUE;
+ if (need_group_password && !existing_group_password)
+ ask_user = TRUE;
+
+ /* If interaction is allowed then ask the user, otherwise pass back
+ * whatever existing secrets we can find.
+ */
+ if (ask_user_func && allow_interaction && (ask_user || retry)) {
+ canceled = !ask_user_func (vpn_name,
+ prompt,
+ retry,
+ need_password,
+ existing_password,
+ &new_password,
+ need_group_password,
+ existing_group_password,
+ &new_group_password);
+ }
- /* for good measure, flush stdout since Kansas is going Bye-Bye */
- fflush (stdout);
+ if (!canceled) {
+ finish_func (vpn_name,
+ prompt,
+ allow_interaction,
+ retry,
+ need_password,
+ new_password ? new_password : existing_password,
+ need_group_password,
+ new_group_password ? new_group_password : existing_group_password);
+ }
- /* Wait for quit signal */
- wait_for_quit ();
+ free_secret (existing_password);
+ free_secret (existing_group_password);
+ free_secret (new_password);
+ free_secret (new_group_password);
}
if (data)
g_hash_table_unref (data);
if (secrets)
g_hash_table_unref (secrets);
- return 0;
+ if (hints)
+ g_strfreev (hints);
+ g_free (prompt);
+ return canceled ? 1 : 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]