[NetworkManager-openvpn/bg/ask-username: 1/7] auth-dialog: generalize secrets handling
- From: Beniamino Galvani <bgalvani src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [NetworkManager-openvpn/bg/ask-username: 1/7] auth-dialog: generalize secrets handling
- Date: Tue, 16 Oct 2018 20:20:47 +0000 (UTC)
commit 8b179d7b36c297bc18888fe1c6aef8609335959d
Author: Beniamino Galvani <bgalvani redhat com>
Date: Wed Oct 10 11:41:17 2018 +0200
auth-dialog: generalize secrets handling
auth-dialog/main.c | 363 ++++++++++++++++++++++++-----------------------------
1 file changed, 161 insertions(+), 202 deletions(-)
---
diff --git a/auth-dialog/main.c b/auth-dialog/main.c
index 41b6384..94f4aad 100644
--- a/auth-dialog/main.c
+++ b/auth-dialog/main.c
@@ -52,6 +52,22 @@ static const SecretSchema network_manager_secret_schema = {
#define UI_KEYFILE_GROUP "VPN Plugin UI"
+typedef struct {
+ const char *key;
+ const char *label;
+ const char *label_acc;
+ char *existing;
+ char *new;
+ gboolean needed;
+} Field;
+
+typedef enum {
+ FIELD_TYPE_PASSWORD,
+ FIELD_TYPE_CERT_PASSWORD,
+ FIELD_TYPE_PROXY_PASSWORD,
+ _FIELD_TYPE_NUM,
+} FieldType;
+
static char *
keyring_lookup_secret (const char *uuid, const char *secret_name)
{
@@ -90,25 +106,12 @@ typedef void (*NoSecretsRequiredFunc) (void);
/* Returns TRUE on success, FALSE on cancel */
typedef gboolean (*AskUserFunc) (const char *vpn_name,
const char *prompt,
- gboolean need_password,
- const char *existing_password,
- char **out_new_password,
- gboolean need_certpass,
- const char *existing_certpass,
- char **out_new_certpass,
- gboolean need_proxypass,
- const char *existing_proxypass,
- char **out_new_proxypass);
+ Field *fields);
typedef void (*FinishFunc) (const char *vpn_name,
const char *prompt,
gboolean allow_interaction,
- gboolean need_password,
- const char *password,
- gboolean need_certpass,
- const char *certpass,
- gboolean need_proxypass,
- const char *proxypass);
+ Field *fields);
/*****************************************************************/
/* External UI mode stuff */
@@ -157,15 +160,12 @@ static void
eui_finish (const char *vpn_name,
const char *prompt,
gboolean allow_interaction,
- gboolean need_password,
- const char *existing_password,
- gboolean need_certpass,
- const char *existing_certpass,
- gboolean need_proxypass,
- const char *existing_proxypass)
+ Field *fields)
{
+ Field *field;
GKeyFile *keyfile;
char *title;
+ guint i;
keyfile = g_key_file_new ();
@@ -176,26 +176,15 @@ eui_finish (const char *vpn_name,
g_key_file_set_string (keyfile, UI_KEYFILE_GROUP, "Title", title);
g_free (title);
- keyfile_add_entry_info (keyfile,
- NM_OPENVPN_KEY_PASSWORD,
- existing_password ? existing_password : "",
- _("Password:"),
- TRUE,
- need_password && allow_interaction);
-
- keyfile_add_entry_info (keyfile,
- NM_OPENVPN_KEY_CERTPASS,
- existing_certpass ? existing_certpass : "",
- _("Certificate password:"),
- TRUE,
- need_certpass && allow_interaction);
-
- keyfile_add_entry_info (keyfile,
- NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD,
- existing_proxypass ? existing_proxypass : "",
- _("HTTP proxy password:"),
- TRUE,
- need_proxypass && allow_interaction);
+ for (i = 0; i < _FIELD_TYPE_NUM; i++) {
+ field = &fields[i];
+ keyfile_add_entry_info (keyfile,
+ field->key,
+ field->existing ?: "",
+ _(field->label),
+ TRUE,
+ field->needed && allow_interaction);
+ }
keyfile_print_stdout (keyfile);
g_key_file_unref (keyfile);
@@ -210,54 +199,47 @@ std_no_secrets_required (void)
}
static gboolean
-std_ask_user (const char *vpn_name,
- const char *prompt,
- gboolean need_password,
- const char *existing_password,
- char **out_new_password,
- gboolean need_certpass,
- const char *existing_certpass,
- char **out_new_certpass,
- gboolean need_proxypass,
- const char *existing_proxypass,
- char **out_new_proxypass)
+std_ask_user (const char *vpn_name, const char *prompt, Field *fields)
{
+ Field *field;
NMAVpnPasswordDialog *dialog;
gboolean success = FALSE;
- 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_certpass != NULL, FALSE);
- g_return_val_if_fail (out_new_proxypass != NULL, FALSE);
+ g_return_val_if_fail (vpn_name, FALSE);
+ g_return_val_if_fail (prompt, FALSE);
dialog = NMA_VPN_PASSWORD_DIALOG (nma_vpn_password_dialog_new (_("Authenticate VPN"), prompt, NULL));
/* 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);
-
- nma_vpn_password_dialog_set_show_password_secondary (dialog, need_certpass);
- if (need_certpass) {
- nma_vpn_password_dialog_set_password_secondary_label (dialog, _("Certificate pass_word:") );
- nma_vpn_password_dialog_set_password_secondary (dialog, existing_certpass);
+ field = &fields[FIELD_TYPE_PASSWORD];
+ nma_vpn_password_dialog_set_show_password (dialog, field->needed);
+ if (field->needed) {
+ nma_vpn_password_dialog_set_password_label (dialog, _(field->label_acc));
+ nma_vpn_password_dialog_set_password (dialog, field->existing);
+ }
+
+ field = &fields[FIELD_TYPE_CERT_PASSWORD];
+ nma_vpn_password_dialog_set_show_password_secondary (dialog, field->needed);
+ if (field->needed) {
+ nma_vpn_password_dialog_set_password_secondary_label (dialog, _(field->label_acc) );
+ nma_vpn_password_dialog_set_password_secondary (dialog, field->existing);
}
- nma_vpn_password_dialog_set_show_password_ternary (dialog, need_proxypass);
- if (need_proxypass) {
- nma_vpn_password_dialog_set_password_ternary_label (dialog, _("_HTTP proxy password:"));
- nma_vpn_password_dialog_set_password_ternary (dialog, existing_proxypass);
+ field = &fields[FIELD_TYPE_PROXY_PASSWORD];
+ nma_vpn_password_dialog_set_show_password_ternary (dialog, field->needed);
+ if (field->needed) {
+ nma_vpn_password_dialog_set_password_ternary_label (dialog, _(field->label_acc));
+ nma_vpn_password_dialog_set_password_ternary (dialog, field->existing);
}
gtk_widget_show (GTK_WIDGET (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_certpass)
- *out_new_certpass = g_strdup (nma_vpn_password_dialog_get_password_secondary
(dialog));
- if (need_proxypass)
- *out_new_proxypass = g_strdup (nma_vpn_password_dialog_get_password_ternary (dialog));
+ if (fields[FIELD_TYPE_PASSWORD].needed)
+ fields[FIELD_TYPE_PASSWORD].new = g_strdup (nma_vpn_password_dialog_get_password
(dialog));
+ if (fields[FIELD_TYPE_CERT_PASSWORD].needed)
+ fields[FIELD_TYPE_CERT_PASSWORD].new = g_strdup
(nma_vpn_password_dialog_get_password_secondary (dialog));
+ if (fields[FIELD_TYPE_PROXY_PASSWORD].needed)
+ fields[FIELD_TYPE_PROXY_PASSWORD].new = g_strdup
(nma_vpn_password_dialog_get_password_ternary (dialog));
success = TRUE;
}
@@ -295,20 +277,16 @@ static void
std_finish (const char *vpn_name,
const char *prompt,
gboolean allow_interaction,
- gboolean need_password,
- const char *password,
- gboolean need_certpass,
- const char *certpass,
- gboolean need_proxypass,
- const char *proxypass)
+ Field *fields)
{
+ guint i;
+
/* Send the passwords back to our parent */
- if (password)
- printf ("%s\n%s\n", NM_OPENVPN_KEY_PASSWORD, password);
- if (certpass)
- printf ("%s\n%s\n", NM_OPENVPN_KEY_CERTPASS, certpass);
- if (proxypass)
- printf ("%s\n%s\n", NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD, proxypass);
+ for (i = 0; i < _FIELD_TYPE_NUM; i++) {
+ if (fields[i].new || fields[i].existing)
+ printf ("%s\n%s\n", fields[i].key, fields[i].new ?: fields[i].existing);
+ }
+
printf ("\n\n");
/* for good measure, flush stdout since Kansas is going Bye-Bye */
@@ -320,106 +298,87 @@ std_finish (const char *vpn_name,
/*****************************************************************/
-static void
+static gboolean
get_existing_passwords (GHashTable *vpn_data,
GHashTable *existing_secrets,
const char *vpn_uuid,
- gboolean need_password,
- gboolean need_certpass,
- gboolean need_proxypass,
- char **out_password,
- char **out_certpass,
- char **out_proxypass)
+ Field *fields)
{
- NMSettingSecretFlags pw_flags = NM_SETTING_SECRET_FLAG_NONE;
- NMSettingSecretFlags cp_flags = NM_SETTING_SECRET_FLAG_NONE;
- NMSettingSecretFlags proxy_flags = NM_SETTING_SECRET_FLAG_NONE;
-
- g_return_if_fail (out_password != NULL);
- g_return_if_fail (out_certpass != NULL);
- g_return_if_fail (out_proxypass != NULL);
-
- nm_vpn_service_plugin_get_secret_flags (vpn_data, NM_OPENVPN_KEY_PASSWORD, &pw_flags);
- if (need_password) {
- if (!(pw_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
- *out_password = g_strdup (g_hash_table_lookup (existing_secrets,
NM_OPENVPN_KEY_PASSWORD));
- if (!*out_password)
- *out_password = keyring_lookup_secret (vpn_uuid, NM_OPENVPN_KEY_PASSWORD);
- }
- }
+ gboolean ret = FALSE;
+ guint i;
- nm_vpn_service_plugin_get_secret_flags (vpn_data, NM_OPENVPN_KEY_CERTPASS, &cp_flags);
- if (need_certpass) {
- if (!(cp_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
- *out_certpass = g_strdup (g_hash_table_lookup (existing_secrets,
NM_OPENVPN_KEY_CERTPASS));
- if (!*out_certpass)
- *out_certpass = keyring_lookup_secret (vpn_uuid, NM_OPENVPN_KEY_CERTPASS);
- }
- }
+ for (i = 0; i < _FIELD_TYPE_NUM; i++) {
+ NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ if (!fields[i].needed)
+ continue;
- nm_vpn_service_plugin_get_secret_flags (vpn_data, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD, &proxy_flags);
- if (need_proxypass) {
- if (!(proxy_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)) {
- *out_proxypass = g_strdup (g_hash_table_lookup (existing_secrets,
NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD));
- if (!*out_proxypass)
- *out_proxypass = keyring_lookup_secret (vpn_uuid,
NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD);
+ nm_vpn_service_plugin_get_secret_flags (vpn_data, fields[i].key, &flags);
+ if (flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) {
+ ret = TRUE;
+ continue;
}
+
+ fields[i].existing = g_strdup (g_hash_table_lookup (existing_secrets, fields[i].key));
+ if (!fields[i].existing)
+ fields[i].existing = keyring_lookup_secret (vpn_uuid, fields[i].key);
+ if (!fields[i].existing)
+ ret = TRUE;
}
+
+ return ret;
}
#define VPN_MSG_TAG "x-vpn-message:"
-static char *
+static gboolean
get_passwords_required (GHashTable *data,
- const char *const*hints,
- gboolean *out_need_password,
- gboolean *out_need_certpass,
- gboolean *out_need_proxypass)
+ const char *const *hints,
+ char **prompt,
+ Field *fields)
{
const char *ctype, *val;
NMSettingSecretFlags flags;
- char *prompt = NULL;
- const char *const*iter;
-
- *out_need_password = FALSE;
- *out_need_certpass = FALSE;
- *out_need_proxypass = FALSE;
+ const char *const *iter;
+ guint i;
/* If hints are given, then always ask for what the hints require */
- if (hints && hints[0]) {
+ if (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_OPENVPN_KEY_PASSWORD) == 0)
- *out_need_password = TRUE;
- else if (strcmp (*iter, NM_OPENVPN_KEY_CERTPASS) == 0)
- *out_need_certpass = TRUE;
- else if (strcmp (*iter, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD) == 0)
- *out_need_proxypass = TRUE;
+ if (!*prompt && g_str_has_prefix (*iter, VPN_MSG_TAG))
+ *prompt = g_strdup (*iter + strlen (VPN_MSG_TAG));
+ else {
+ for (i = 0; i < _FIELD_TYPE_NUM; i++) {
+ if (nm_streq (*iter, fields[i].key))
+ fields[i].needed = TRUE;
+ }
+ }
}
- return prompt;
+ goto done;
}
ctype = g_hash_table_lookup (data, NM_OPENVPN_KEY_CONNECTION_TYPE);
- g_return_val_if_fail (ctype != NULL, NULL);
+ g_return_val_if_fail (ctype, FALSE);
- if (!strcmp (ctype, NM_OPENVPN_CONTYPE_TLS) || !strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
+ if (NM_IN_STRSET (ctype,
+ NM_OPENVPN_CONTYPE_TLS,
+ NM_OPENVPN_CONTYPE_PASSWORD_TLS)) {
/* Normal user password */
flags = NM_SETTING_SECRET_FLAG_NONE;
nm_vpn_service_plugin_get_secret_flags (data, NM_OPENVPN_KEY_PASSWORD, &flags);
- if ( !strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
+ if ( nm_streq (ctype, NM_OPENVPN_CONTYPE_PASSWORD_TLS)
&& !(flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED))
- *out_need_password = TRUE;
+ fields[FIELD_TYPE_PASSWORD].needed = TRUE;
/* Encrypted private key password */
val = g_hash_table_lookup (data, NM_OPENVPN_KEY_KEY);
if (val)
- *out_need_certpass = is_encrypted (val);
- } else if (!strcmp (ctype, NM_OPENVPN_CONTYPE_PASSWORD)) {
+ fields[FIELD_TYPE_CERT_PASSWORD].needed = is_encrypted (val);
+ } else if (nm_streq (ctype, NM_OPENVPN_CONTYPE_PASSWORD)) {
flags = NM_SETTING_SECRET_FLAG_NONE;
nm_vpn_service_plugin_get_secret_flags (data, NM_OPENVPN_KEY_PASSWORD, &flags);
if (!(flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED))
- *out_need_password = TRUE;
+ fields[FIELD_TYPE_PASSWORD].needed = TRUE;
}
val = g_hash_table_lookup (data, NM_OPENVPN_KEY_PROXY_SERVER);
@@ -427,10 +386,27 @@ get_passwords_required (GHashTable *data,
flags = NM_SETTING_SECRET_FLAG_NONE;
nm_vpn_service_plugin_get_secret_flags (data, NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD, &flags);
if (!(flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED))
- *out_need_proxypass = TRUE;
+ fields[FIELD_TYPE_PROXY_PASSWORD].needed = TRUE;
+ }
+
+done:
+ for (i = 0; i < _FIELD_TYPE_NUM; i++) {
+ if (fields[i].needed)
+ return TRUE;
}
- return NULL;
+ return FALSE;
+}
+
+static void
+clear_secrets (Field **fields)
+{
+ guint i;
+
+ for (i = 0; i < _FIELD_TYPE_NUM; i++) {
+ nm_free_secret ((*fields)[i].existing);
+ nm_free_secret ((*fields)[i].new);
+ }
}
int
@@ -440,24 +416,34 @@ main (int argc, char *argv[])
gchar *vpn_name = NULL;
gchar *vpn_uuid = NULL;
gchar *vpn_service = NULL;
- gs_unref_hashtable GHashTable *data = NULL;
- gs_unref_hashtable GHashTable *secrets = NULL;
- gboolean need_password = FALSE;
- gboolean need_certpass = FALSE;
- gboolean need_proxypass = FALSE;
+ gs_unref_hashtable GHashTable *data_hash = NULL;
+ gs_unref_hashtable GHashTable *secrets_hash = NULL;
gs_strfreev char **hints = NULL;
gs_free char *prompt = NULL;
- nm_auto_free_secret char *new_password = NULL;
- nm_auto_free_secret char *new_certpass = NULL;
- nm_auto_free_secret char *new_proxypass = NULL;
- nm_auto_free_secret char *existing_password = NULL;
- nm_auto_free_secret char *existing_certpass = NULL;
- nm_auto_free_secret char *existing_proxypass = NULL;
+ gboolean needed = FALSE;
gboolean external_ui_mode = FALSE;
gboolean ask_user;
NoSecretsRequiredFunc no_secrets_required_func;
AskUserFunc ask_user_func;
FinishFunc finish_func;
+ Field fields[] = {
+ [FIELD_TYPE_PASSWORD] = {
+ .key = NM_OPENVPN_KEY_PASSWORD,
+ .label = N_("Password:"),
+ .label_acc = N_("_Password:"),
+ },
+ [FIELD_TYPE_CERT_PASSWORD] = {
+ .key = NM_OPENVPN_KEY_CERTPASS,
+ .label = N_("Certificate password:"),
+ .label_acc = N_("Certificate pass_word:"),
+ },
+ [FIELD_TYPE_PROXY_PASSWORD] = {
+ .key = NM_OPENVPN_KEY_HTTP_PROXY_PASSWORD,
+ .label = N_("HTTP proxy password"),
+ .label_acc = N_("_HTTP proxy password:"),
+ },
+ };
+ nm_auto(clear_secrets) Field *_fields = fields;
GOptionContext *context;
GOptionEntry entries[] = {
@@ -492,7 +478,7 @@ main (int argc, char *argv[])
return EXIT_FAILURE;
}
- if (!nm_vpn_service_plugin_read_vpn_details (0, &data, &secrets)) {
+ if (!nm_vpn_service_plugin_read_vpn_details (0, &data_hash, &secrets_hash)) {
fprintf (stderr, "Failed to read '%s' (%s) data and secrets from stdin.\n",
vpn_name, vpn_uuid);
return EXIT_FAILURE;
@@ -511,33 +497,20 @@ main (int argc, char *argv[])
/* Determine which passwords are actually required, either from hints or
* from looking at the VPN configuration.
*/
- prompt = get_passwords_required (data, (const char *const*) hints, &need_password, &need_certpass,
&need_proxypass);
+ needed = get_passwords_required (data_hash, (const char *const*) hints, &prompt, fields);
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_certpass && !need_proxypass) {
+ if (!needed) {
no_secrets_required_func ();
return EXIT_SUCCESS;
}
- get_existing_passwords (data,
- secrets,
- vpn_uuid,
- need_password,
- need_certpass,
- need_proxypass,
- &existing_password,
- &existing_certpass,
- &existing_proxypass);
- if (need_password && !existing_password)
- ask_user = TRUE;
- else if (need_certpass && !existing_certpass)
- ask_user = TRUE;
- else if (need_proxypass && !existing_proxypass)
- ask_user = TRUE;
- else
- ask_user = FALSE;
+ ask_user = get_existing_passwords (data_hash,
+ secrets_hash,
+ vpn_uuid,
+ fields);
/* If interaction is allowed then ask the user, otherwise pass back
* whatever existing secrets we can find.
@@ -545,28 +518,14 @@ main (int argc, char *argv[])
if ( ask_user_func
&& allow_interaction
&& (ask_user || retry)) {
- if (!ask_user_func (vpn_name,
- prompt,
- need_password,
- existing_password,
- &new_password,
- need_certpass,
- existing_certpass,
- &new_certpass,
- need_proxypass,
- existing_proxypass,
- &new_proxypass))
+ if (!ask_user_func (vpn_name, prompt, fields))
return EXIT_FAILURE;
}
finish_func (vpn_name,
prompt,
allow_interaction,
- need_password,
- new_password ? new_password : existing_password,
- need_certpass,
- new_certpass ? new_certpass : existing_certpass,
- need_proxypass,
- new_proxypass ? new_proxypass : existing_proxypass);
+ fields);
+
return EXIT_SUCCESS;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]