[network-manager-openswan/dcbw/cleanups: 17/17] auth-dialog: handle and parse hints
- From: Dan Williams <dcbw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-openswan/dcbw/cleanups: 17/17] auth-dialog: handle and parse hints
- Date: Thu, 28 Aug 2014 22:53:13 +0000 (UTC)
commit 004b5ee8b6c65dbc0f40389f917afe089cf4a79e
Author: Dan Williams <dcbw redhat com>
Date: Fri Aug 8 13:54:09 2014 -0500
auth-dialog: handle and parse hints
auth-dialog/main.c | 465 ++++++++++++++++++++++++++++---------------
configure.ac | 8 +-
nm-openswan-service.name.in | 1 +
3 files changed, 309 insertions(+), 165 deletions(-)
---
diff --git a/auth-dialog/main.c b/auth-dialog/main.c
index 24dd666..5c879dd 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,122 @@ 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_OPENSWAN_XAUTH_PASSWORD);
-
- /* Try the old name */
- if (upw == NULL)
- upw = keyring_lookup_secret (vpn_uuid, "password");
- }
+ 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_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_OPENSWAN_PSK_VALUE);
+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;
- /* Try the old name */
- if (gpw == NULL)
- gpw = keyring_lookup_secret (vpn_uuid, "group-password");
- }
+ keyfile = g_key_file_new ();
- 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;
- }
+ g_key_file_set_integer (keyfile, UI_KEYFILE_GROUP, "Version", 2);
+ g_key_file_set_string (keyfile, UI_KEYFILE_GROUP, "Description", prompt);
- 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;
- }
+ title = g_strdup_printf (_("Authenticate VPN %s"), vpn_name);
+ g_key_file_set_string (keyfile, UI_KEYFILE_GROUP, "Title", title);
+ g_free (title);
- if (!need_upw && !need_gpw)
- return TRUE;
- }
+ /* If we have an existing password, or we need the user to give us one,
+ * then tell the external UI about the password. An entry for the password
+ * (possibly pre-populated with the existing password) is only shown to the
+ * user when the password is needed or new secrets are required (retry).
+ * If the password isn't required and there's no existing password, then
+ * just ignore that password completely.
+ */
- prompt = g_strdup_printf (_("You need to authenticate to access the Virtual Private Network '%s'."),
vpn_name);
+ if (need_password || existing_password || retry) {
+ show = (need_password && !existing_password) || retry;
+ keyfile_add_entry_info (keyfile,
+ NM_OPENSWAN_XAUTH_PASSWORD,
+ existing_password ? existing_password : "",
+ _("Password:"),
+ TRUE,
+ show && allow_interaction);
+ }
- if (external_ui_mode) {
- GKeyFile *keyfile;
+ if (need_group_password || existing_group_password || retry) {
+ show = (need_group_password && !existing_group_password) || retry;
+ keyfile_add_entry_info (keyfile,
+ NM_OPENSWAN_PSK_VALUE,
+ existing_group_password ? existing_group_password : "",
+ _("Group Password:"),
+ TRUE,
+ show && allow_interaction);
+ }
- keyfile = g_key_file_new ();
+ 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"));
+/*****************************************************************/
- if (need_upw)
- keyfile_add_entry_info (keyfile, NM_OPENSWAN_XAUTH_PASSWORD, upw ? upw : "",
_("Password:"), TRUE, allow_interaction);
- if (need_gpw)
- keyfile_add_entry_info (keyfile, NM_OPENSWAN_PSK_VALUE, gpw ? gpw : "", _("Group
Password:"), TRUE, 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 ||
- ((upw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
- && (gpw_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED))) {
- /* If interaction isn't allowed, just return existing secrets
- * Also, don't ask if both passwords are unused */
-
- *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 */
+ nma_vpn_password_dialog_set_show_password (dialog, need_password);
+ if (need_password)
+ nma_vpn_password_dialog_set_password (dialog, existing_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_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);
+ nma_vpn_password_dialog_set_show_password_secondary (dialog, need_group_password);
+ if (need_group_password) {
+ nma_vpn_password_dialog_set_password_secondary_label (dialog, _("_Group Password:"));
+ nma_vpn_password_dialog_set_password_secondary (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)
+ *out_new_group_password = g_strdup (nma_vpn_password_dialog_get_password_secondary
(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 +286,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_OPENSWAN_XAUTH_PASSWORD, password);
+ if (group_password)
+ printf ("%s\n%s\n", NM_OPENSWAN_PSK_VALUE, 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 *mode_name)
{
@@ -320,16 +336,105 @@ get_pw_flags (GHashTable *hash, const char *secret_name, const char *mode_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);
+
+ if (need_password) {
+ upw_flags = get_pw_flags (existing_secrets, NM_OPENSWAN_XAUTH_PASSWORD,
NM_OPENSWAN_XAUTH_PASSWORD_INPUT_MODES);
+ if (!(upw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
+ *out_password = g_strdup (g_hash_table_lookup (existing_secrets,
NM_OPENSWAN_XAUTH_PASSWORD));
+ if (!*out_password)
+ *out_password = keyring_lookup_secret (vpn_uuid, NM_OPENSWAN_XAUTH_PASSWORD);
+ }
+ }
+
+ if (need_group_password) {
+ gpw_flags = get_pw_flags (existing_secrets, NM_OPENSWAN_PSK_VALUE,
NM_OPENSWAN_PSK_INPUT_MODES);
+ if (!(gpw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
+ *out_group_password = g_strdup (g_hash_table_lookup (existing_secrets,
NM_OPENSWAN_PSK_VALUE));
+ if (!*out_group_password)
+ *out_group_password = keyring_lookup_secret (vpn_uuid, NM_OPENSWAN_PSK_VALUE);
+ }
+ }
+}
+
+#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_OPENSWAN_XAUTH_PASSWORD) == 0)
+ *out_need_password = TRUE;
+ else if (strcmp (*iter, NM_OPENSWAN_PSK_VALUE) == 0)
+ *out_need_group_password = TRUE;
+ }
+ return prompt;
+ }
+
+ /* User password (XAuth password) */
+ flags = get_pw_flags (data, NM_OPENSWAN_XAUTH_PASSWORD, NM_OPENSWAN_XAUTH_PASSWORD_INPUT_MODES);
+ if (!(flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED))
+ *out_need_password = TRUE;
+
+ /* Group password (IPSec secret) */
+ flags = get_pw_flags (data, NM_OPENSWAN_PSK_VALUE, NM_OPENSWAN_PSK_INPUT_MODES);
+ 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;
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,6 +443,7 @@ 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 }
};
@@ -357,8 +463,8 @@ main (int argc, char *argv[])
g_option_context_free (context);
- if (vpn_uuid == NULL || vpn_service == NULL) {
- fprintf (stderr, "A connection UUID and VPN plugin service name are required.\n");
+ if (!vpn_uuid || !vpn_service || !vpn_name) {
+ fprintf (stderr, "A connection UUID, name, and VPN plugin service name are required.\n");
return 1;
}
@@ -373,40 +479,77 @@ main (int argc, char *argv[])
return 1;
}
- upw_flags = get_pw_flags (data, NM_OPENSWAN_XAUTH_PASSWORD, NM_OPENSWAN_XAUTH_PASSWORD_INPUT_MODES);
- gpw_flags = get_pw_flags (data, NM_OPENSWAN_PSK_VALUE, NM_OPENSWAN_PSK_INPUT_MODES);
-
- if (!get_secrets (vpn_uuid, vpn_name, retry,
- allow_interaction, external_ui_mode,
- g_hash_table_lookup (secrets, NM_OPENSWAN_XAUTH_PASSWORD),
- &password,
- upw_flags,
- g_hash_table_lookup (secrets, NM_OPENSWAN_PSK_VALUE),
- &group_password,
- gpw_flags))
- return 1;
-
- if (!external_ui_mode) {
- /* dump the passwords to stdout */
- if (password)
- printf ("%s\n%s\n", NM_OPENSWAN_XAUTH_PASSWORD, password);
- if (group_password)
- printf ("%s\n%s\n", NM_OPENSWAN_PSK_VALUE, 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;
}
+
diff --git a/configure.ac b/configure.ac
index 911b1ad..63f8c75 100644
--- a/configure.ac
+++ b/configure.ac
@@ -67,10 +67,10 @@ AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
PKG_CHECK_MODULES(NM,
- NetworkManager >= 0.9.8
- libnm-util >= 0.9.8
- libnm-glib >= 0.9.8
- libnm-glib-vpn >= 0.9.8)
+ NetworkManager >= 0.9.9
+ libnm-util >= 0.9.9
+ libnm-glib >= 0.9.9
+ libnm-glib-vpn >= 0.9.9)
AC_SUBST(NM_CFLAGS)
AC_SUBST(NM_LIBS)
diff --git a/nm-openswan-service.name.in b/nm-openswan-service.name.in
index 6dbf9ff..6607c12 100644
--- a/nm-openswan-service.name.in
+++ b/nm-openswan-service.name.in
@@ -7,3 +7,4 @@ program= LIBEXECDIR@/nm-openswan-service
auth-dialog= LIBEXECDIR@/nm-openswan-auth-dialog
properties= PLUGINDIR@/libnm-openswan-properties
supports-external-ui-mode=true
+supports-hints=true
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]