network-manager-applet r1018 - in trunk: . src/connection-editor src/gconf-helpers src/utils src/wireless-security
- From: dcbw svn gnome org
- To: svn-commits-list gnome org
- Subject: network-manager-applet r1018 - in trunk: . src/connection-editor src/gconf-helpers src/utils src/wireless-security
- Date: Thu, 13 Nov 2008 21:30:30 +0000 (UTC)
Author: dcbw
Date: Thu Nov 13 21:30:30 2008
New Revision: 1018
URL: http://svn.gnome.org/viewvc/network-manager-applet?rev=1018&view=rev
Log:
2008-11-13 Dan Williams <dcbw redhat com>
Add support for PKCS#12 private keys (bgo #558982)
* src/utils/utils.c
- (utils_fill_connection_certs): report errors
* src/connection-editor/nm-connection-editor.c
- (nm_connection_editor_set_connection): run initial validation from
and idle handler to allow file choosers time to asynchronously
find their files
* src/gconf-helpers/gconf-helpers.c
- (get_one_private_key): add private key passwords to the secrets hash
if the private key is a pkcs#12 private key
- (nm_gconf_get_keyring_items): move force-included private key passwords
functionality into get_one_private_key()
* src/wireless-security/eap-method.c
src/wireless-security/eap-method.h
- (eap_method_default_file_chooser_filter_new): use differnet filters
for private keys versus certificates, since private keys can be
pkcs#12 and certificates cannot
- (default_filter): split up into file_has_extension(),
file_is_der_or_pem(), default_filter_cert(), and
default_filter_privkey(); fix a bug where only the first 1K of a
candidate file would be read, missing some certificates with long
text descriptions
- (eap_method_validate_filepicker): take the private key password for
validation purposes; return the certificate/key type
* src/wireless-security/eap-method-peap.c
src/wireless-security/eap-method-ttls.c
- Update for eap_method_validate_filepicker() changes
* src/wireless-security/eap-method-tls.c
- (eap_method_tls_new): handle phase2 secrets too; and do initial
validation from and idle handler to allow file choosers time to
asynchronously find their file
- (setup_filepicker): connect a special handler to the private key
chooser so that the client certificate chooser can be disabled when
the user picks a pkcs#12 private key; additionally, work around a
GTK+ issue where GTK would clear the choosers filter
- (private_key_picker_helper): disable the client certificate chooser
button when the private key is pkcs#12
- (fill_connection): if the private key is pkcs#12, set the client
certificate to the the same file as the private key, as NM requires
- (validate): ignore the client certificate if the private key is
pkcs#12
Modified:
trunk/ChangeLog
trunk/src/connection-editor/nm-connection-editor.c
trunk/src/gconf-helpers/gconf-helpers.c
trunk/src/utils/utils.c
trunk/src/wireless-security/eap-method-peap.c
trunk/src/wireless-security/eap-method-tls.c
trunk/src/wireless-security/eap-method-ttls.c
trunk/src/wireless-security/eap-method.c
trunk/src/wireless-security/eap-method.h
Modified: trunk/src/connection-editor/nm-connection-editor.c
==============================================================================
--- trunk/src/connection-editor/nm-connection-editor.c (original)
+++ trunk/src/connection-editor/nm-connection-editor.c Thu Nov 13 21:30:30 2008
@@ -482,6 +482,13 @@
editor->pages = g_slist_append (editor->pages, page);
}
+static gboolean
+idle_validate (gpointer user_data)
+{
+ connection_editor_validate (NM_CONNECTION_EDITOR (user_data));
+ return FALSE;
+}
+
static void
nm_connection_editor_set_connection (NMConnectionEditor *editor, NMConnection *connection)
{
@@ -529,7 +536,10 @@
/* set the UI */
populate_connection_ui (editor);
- connection_editor_validate (editor);
+ /* Validate the connection from an idle handler to ensure that stuff like
+ * GtkFileChoosers have had a chance to asynchronously find their files.
+ */
+ g_idle_add (idle_validate, editor);
}
void
Modified: trunk/src/gconf-helpers/gconf-helpers.c
==============================================================================
--- trunk/src/gconf-helpers/gconf-helpers.c (original)
+++ trunk/src/gconf-helpers/gconf-helpers.c Thu Nov 13 21:30:30 2008
@@ -1616,6 +1616,7 @@
const char *setting_name,
const char *tag,
const char *password,
+ gboolean include_password,
GHashTable *secrets,
GError **error)
{
@@ -1623,7 +1624,9 @@
GByteArray *array = NULL;
const char *filename = NULL;
const char *secret_name;
+ const char *real_password_secret_name = NULL;
gboolean success = FALSE;
+ gboolean add_password = FALSE;
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (tag != NULL, FALSE);
@@ -1636,9 +1639,11 @@
if (!strcmp (tag, NMA_PRIVATE_KEY_PASSWORD_TAG)) {
filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_PRIVATE_KEY_TAG);
secret_name = NM_SETTING_802_1X_PRIVATE_KEY;
+ real_password_secret_name = NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD;
} else if (!strcmp (tag, NMA_PHASE2_PRIVATE_KEY_PASSWORD_TAG)) {
filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_PHASE2_PRIVATE_KEY_TAG);
secret_name = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY;
+ real_password_secret_name = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD;
} else {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE,
"%s.%d - %s/%s Unknown private key password type '%s'.",
@@ -1648,15 +1653,23 @@
if (filename) {
NMSetting8021x *setting;
- const GByteArray *tmp;
+ const GByteArray *tmp = NULL;
+ NMSetting8021xCKType ck_type = NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
setting = (NMSetting8021x *) nm_setting_802_1x_new ();
- nm_setting_802_1x_set_private_key_from_file (setting, filename, password, error);
+ if (nm_setting_802_1x_set_private_key_from_file (setting, filename, password, &ck_type, error)) {
+ /* For PKCS#12 files, which don't get decrypted, add the private key
+ * password to the secrets hash.
+ */
+ if (ck_type == NM_SETTING_802_1X_CK_TYPE_PKCS12)
+ add_password = TRUE;
- /* Steal the private key */
- tmp = nm_setting_802_1x_get_private_key (setting);
- array = g_byte_array_sized_new (tmp->len);
- g_byte_array_append (array, tmp->data, tmp->len);
+ /* Steal the private key */
+ tmp = nm_setting_802_1x_get_private_key (setting);
+ g_assert (tmp);
+ array = g_byte_array_sized_new (tmp->len);
+ g_byte_array_append (array, tmp->data, tmp->len);
+ }
g_object_unref (setting);
}
@@ -1669,9 +1682,11 @@
goto out;
}
- g_hash_table_insert (secrets,
- g_strdup (secret_name),
- byte_array_to_gvalue (array));
+ g_hash_table_insert (secrets, g_strdup (secret_name), byte_array_to_gvalue (array));
+
+ if (include_password || add_password)
+ g_hash_table_insert (secrets, g_strdup (real_password_secret_name), string_to_gvalue (password));
+
success = TRUE;
out:
@@ -1750,25 +1765,17 @@
if ( !strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME)
&& ( !strcmp (key_name, NMA_PRIVATE_KEY_PASSWORD_TAG)
|| !strcmp (key_name, NMA_PHASE2_PRIVATE_KEY_PASSWORD_TAG))) {
- /* Private key passwords aren't passed to NM, they are used
- * to decrypt the private key and send _that_ to NM.
+ /* Private key passwords aren't passed to NM for "traditional"
+ * OpenSSL private keys, but are passed to NM for PKCS#12 keys.
*/
if (!get_one_private_key (connection, setting_name, key_name,
- found->secret, secrets, error)) {
+ found->secret, include_private_passwords, secrets, error)) {
if (!*error) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE,
"%s.%d - %s/%s unknown error from get_one_private_key().",
__FILE__, __LINE__, connection_name, setting_name);
}
break;
- } else if (include_private_passwords) {
- /* If asked, include the actual private key passwords and such
- * too. NOT to be used in response to a GetSecrets call, but
- * for displaying the passwords in the UI if required.
- */
- g_hash_table_insert (secrets,
- g_strdup (key_name),
- string_to_gvalue (found->secret));
}
} else {
/* Ignore older obsolete keyring keys that we don't want to leak
Modified: trunk/src/utils/utils.c
==============================================================================
--- trunk/src/utils/utils.c (original)
+++ trunk/src/utils/utils.c Thu Nov 13 21:30:30 2008
@@ -219,6 +219,7 @@
{
NMSetting8021x *s_8021x;
const char *filename;
+ GError *error = NULL;
g_return_if_fail (connection != NULL);
@@ -227,20 +228,32 @@
return;
filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_CA_CERT_TAG);
- if (filename)
- nm_setting_802_1x_set_ca_cert_from_file (s_8021x, filename, NULL);
+ if (filename) {
+ if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, filename, NULL, &error))
+ g_warning ("%s: couldn't read CA certificate: %d %s", __func__, error->code, error->message);
+ g_clear_error (&error);
+ }
filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_CLIENT_CERT_TAG);
- if (filename)
- nm_setting_802_1x_set_client_cert_from_file (s_8021x, filename, NULL);
+ if (filename) {
+ if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, filename, NULL, &error))
+ g_warning ("%s: couldn't read client certificate: %d %s", __func__, error->code, error->message);
+ g_clear_error (&error);
+ }
filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_PHASE2_CA_CERT_TAG);
- if (filename)
- nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, filename, NULL);
+ if (filename) {
+ if (!nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, filename, NULL, &error))
+ g_warning ("%s: couldn't read phase2 CA certificate: %d %s", __func__, error->code, error->message);
+ g_clear_error (&error);
+ }
filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_PHASE2_CLIENT_CERT_TAG);
- if (filename)
- nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, filename, NULL);
+ if (filename) {
+ if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, filename, NULL, &error))
+ g_warning ("%s: couldn't read phase2 client certificate: %d %s", __func__, error->code, error->message);
+ g_clear_error (&error);
+ }
}
void
Modified: trunk/src/wireless-security/eap-method-peap.c
==============================================================================
--- trunk/src/wireless-security/eap-method-peap.c (original)
+++ trunk/src/wireless-security/eap-method-peap.c Thu Nov 13 21:30:30 2008
@@ -52,7 +52,7 @@
EAPMethod *eap = NULL;
gboolean valid = FALSE;
- if (!eap_method_validate_filepicker (parent->xml, "eap_peap_ca_cert_button", TRUE, FALSE, NULL))
+ if (!eap_method_validate_filepicker (parent->xml, "eap_peap_ca_cert_button", TYPE_CA_CERT, NULL, NULL))
return FALSE;
widget = glade_xml_get_widget (parent->xml, "eap_peap_inner_auth_combo");
@@ -392,10 +392,10 @@
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
_("Choose a Certificate Authority certificate..."));
- g_signal_connect (G_OBJECT (widget), "selection-changed",
+ g_signal_connect (G_OBJECT (widget), "file-set",
(GCallback) wireless_security_changed_cb,
parent);
- filter = eap_method_default_file_chooser_filter_new ();
+ filter = eap_method_default_file_chooser_filter_new (FALSE);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
if (connection) {
filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_CA_CERT_TAG);
Modified: trunk/src/wireless-security/eap-method-tls.c
==============================================================================
--- trunk/src/wireless-security/eap-method-tls.c (original)
+++ trunk/src/wireless-security/eap-method-tls.c Thu Nov 13 21:30:30 2008
@@ -57,34 +57,36 @@
static gboolean
validate (EAPMethod *parent)
{
+ NMSetting8021xCKType ck_type = NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
GtkWidget *widget;
- const char *text;
+ const char *password, *identity;
widget = glade_xml_get_widget (parent->xml, "eap_tls_identity_entry");
g_assert (widget);
- text = gtk_entry_get_text (GTK_ENTRY (widget));
- if (!text || !strlen (text))
+ identity = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (!identity || !strlen (identity))
return FALSE;
- if (!eap_method_validate_filepicker (parent->xml, "eap_tls_user_cert_button", FALSE, FALSE, NULL))
+ if (!eap_method_validate_filepicker (parent->xml, "eap_tls_ca_cert_button", TYPE_CA_CERT, NULL, NULL))
return FALSE;
- if (!eap_method_validate_filepicker (parent->xml, "eap_tls_ca_cert_button", TRUE, FALSE, NULL))
+ widget = glade_xml_get_widget (parent->xml, "eap_tls_private_key_password_entry");
+ g_assert (widget);
+ password = gtk_entry_get_text (GTK_ENTRY (widget));
+ if (!password || !strlen (password))
return FALSE;
if (!eap_method_validate_filepicker (parent->xml,
"eap_tls_private_key_button",
- FALSE,
- TRUE,
- "eap_tls_private_key_password_entry"))
+ TYPE_PRIVATE_KEY,
+ password,
+ &ck_type))
return FALSE;
- widget = glade_xml_get_widget (parent->xml, "eap_tls_private_key_password_entry");
- g_assert (widget);
- // FIXME: require encrypted private keys for now
- text = gtk_entry_get_text (GTK_ENTRY (widget));
- if (!text || !strlen (text))
- return FALSE;
+ if (ck_type != NM_SETTING_802_1X_CK_TYPE_PKCS12) {
+ if (!eap_method_validate_filepicker (parent->xml, "eap_tls_user_cert_button", TYPE_CLIENT_CERT, NULL, NULL))
+ return FALSE;
+ }
return TRUE;
}
@@ -129,9 +131,10 @@
fill_connection (EAPMethod *parent, NMConnection *connection)
{
EAPMethodTLS *method = (EAPMethodTLS *) parent;
+ NMSetting8021xCKType key_type = NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
NMSetting8021x *s_8021x;
GtkWidget *widget;
- char *filename;
+ char *filename, *pk_filename, *cc_filename;
char *password = NULL;
GError *error = NULL;
@@ -147,31 +150,6 @@
g_assert (widget);
g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, gtk_entry_get_text (GTK_ENTRY (widget)), NULL);
- widget = glade_xml_get_widget (parent->xml, "eap_tls_user_cert_button");
- g_assert (widget);
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
- g_assert (filename);
- g_object_set_data_full (G_OBJECT (connection),
- method->phase2 ? NMA_PATH_PHASE2_CLIENT_CERT_TAG : NMA_PATH_CLIENT_CERT_TAG,
- g_strdup (filename),
- (GDestroyNotify) g_free);
- g_free (filename);
-
- widget = glade_xml_get_widget (parent->xml, "eap_tls_ca_cert_button");
- g_assert (widget);
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
- if (filename) {
- g_object_set_data_full (G_OBJECT (connection),
- method->phase2 ? NMA_PATH_PHASE2_CA_CERT_TAG : NMA_PATH_CA_CERT_TAG,
- g_strdup (filename),
- (GDestroyNotify) g_free);
- g_free (filename);
- } else {
- g_object_set_data (G_OBJECT (connection),
- method->phase2 ? NMA_PATH_PHASE2_CA_CERT_TAG : NMA_PATH_CA_CERT_TAG,
- NULL);
- }
-
widget = glade_xml_get_widget (parent->xml, "eap_tls_private_key_password_entry");
g_assert (widget);
password = g_strdup (gtk_entry_get_text (GTK_ENTRY (widget)));
@@ -187,29 +165,60 @@
(GDestroyNotify) free_password);
}
+ /* TLS private key */
widget = glade_xml_get_widget (parent->xml, "eap_tls_private_key_button");
g_assert (widget);
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
- g_assert (filename);
+ pk_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ g_assert (pk_filename);
g_object_set_data_full (G_OBJECT (connection),
method->phase2 ? NMA_PATH_PHASE2_PRIVATE_KEY_TAG : NMA_PATH_PRIVATE_KEY_TAG,
- g_strdup (filename),
+ g_strdup (pk_filename),
(GDestroyNotify) g_free);
if (method->phase2) {
- nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, filename, password, &error);
- if (error) {
- g_warning ("Couldn't read phase2 private key: %s", error->message);
+ if (!nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, pk_filename, password, &key_type, &error)) {
+ g_warning ("Couldn't read phase2 private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
g_clear_error (&error);
}
} else {
- nm_setting_802_1x_set_private_key_from_file (s_8021x, filename, password, &error);
- if (error) {
- g_warning ("Couldn't read private key: %s", error->message);
+ if (!nm_setting_802_1x_set_private_key_from_file (s_8021x, pk_filename, password, &key_type, &error)) {
+ g_warning ("Couldn't read private key '%s': %s", pk_filename, error ? error->message : "(unknown)");
g_clear_error (&error);
}
}
- g_free (filename);
+ /* TLS client certificate */
+ if (key_type == NM_SETTING_802_1X_CK_TYPE_PKCS12) {
+ /* if the key is pkcs#12, the cert is filled with the same data */
+ cc_filename = g_strdup (pk_filename);
+ } else {
+ widget = glade_xml_get_widget (parent->xml, "eap_tls_user_cert_button");
+ g_assert (widget);
+ cc_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ }
+
+ g_assert (cc_filename);
+ g_object_set_data_full (G_OBJECT (connection),
+ method->phase2 ? NMA_PATH_PHASE2_CLIENT_CERT_TAG : NMA_PATH_CLIENT_CERT_TAG,
+ g_strdup (cc_filename),
+ (GDestroyNotify) g_free);
+ g_free (cc_filename);
+ g_free (pk_filename);
+
+ /* TLS CA certificate */
+ widget = glade_xml_get_widget (parent->xml, "eap_tls_ca_cert_button");
+ g_assert (widget);
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
+ if (filename) {
+ g_object_set_data_full (G_OBJECT (connection),
+ method->phase2 ? NMA_PATH_PHASE2_CA_CERT_TAG : NMA_PATH_CA_CERT_TAG,
+ g_strdup (filename),
+ (GDestroyNotify) g_free);
+ g_free (filename);
+ } else {
+ g_object_set_data (G_OBJECT (connection),
+ method->phase2 ? NMA_PATH_PHASE2_CA_CERT_TAG : NMA_PATH_CA_CERT_TAG,
+ NULL);
+ }
if (method->ignore_ca_cert) {
g_object_set_data (G_OBJECT (connection),
@@ -301,32 +310,113 @@
}
static void
+private_key_picker_helper (EAPMethod *parent, const char *filename, gboolean changed)
+{
+ NMSetting8021x *setting;
+ NMSetting8021xCKType cert_type = NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
+ const char *password;
+ GtkWidget *widget;
+
+ widget = glade_xml_get_widget (parent->xml, "eap_tls_private_key_password_entry");
+ g_assert (widget);
+ password = gtk_entry_get_text (GTK_ENTRY (widget));
+
+ setting = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_setting_802_1x_set_private_key_from_file (setting, filename, password, &cert_type, NULL);
+ g_object_unref (setting);
+
+ /* With PKCS#12, the client cert must be the same as the private key */
+ widget = glade_xml_get_widget (parent->xml, "eap_tls_user_cert_button");
+ if (cert_type == NM_SETTING_802_1X_CK_TYPE_PKCS12) {
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (widget));
+ gtk_widget_set_sensitive (widget, FALSE);
+ } else if (changed)
+ gtk_widget_set_sensitive (widget, TRUE);
+}
+
+static void
+private_key_picker_file_set_cb (GtkWidget *chooser, gpointer user_data)
+{
+ EAPMethod *parent = (EAPMethod *) user_data;
+ char *filename;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+ if (filename)
+ private_key_picker_helper (parent, filename, TRUE);
+ g_free (filename);
+}
+
+static void reset_filter (GtkWidget *widget, GParamSpec *spec, gpointer user_data)
+{
+ if (!gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (widget))) {
+ g_signal_handlers_block_by_func (widget, reset_filter, user_data);
+ gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (widget), GTK_FILE_FILTER (user_data));
+ g_signal_handlers_unblock_by_func (widget, reset_filter, user_data);
+ }
+}
+
+static void
setup_filepicker (GladeXML *xml,
const char *name,
const char *title,
WirelessSecurity *parent,
+ EAPMethodTLS *method,
NMConnection *connection,
const char *tag)
{
GtkWidget *widget;
GtkFileFilter *filter;
- const char *filename;
+ const char *filename = NULL;
+ gboolean privkey = FALSE, client_cert = FALSE;
+
+ if (!strcmp (tag, NMA_PATH_PHASE2_PRIVATE_KEY_TAG) || !strcmp (tag, NMA_PATH_PRIVATE_KEY_TAG))
+ privkey = TRUE;
+ if (!strcmp (tag, NMA_PATH_PHASE2_CLIENT_CERT_TAG) || !strcmp (tag, NMA_PATH_CLIENT_CERT_TAG))
+ client_cert = TRUE;
widget = glade_xml_get_widget (xml, name);
g_assert (widget);
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget), title);
- g_signal_connect (G_OBJECT (widget), "selection-changed",
- (GCallback) wireless_security_changed_cb,
- parent);
+
if (connection && tag) {
filename = g_object_get_data (G_OBJECT (connection), tag);
if (filename)
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), filename);
}
- filter = eap_method_default_file_chooser_filter_new ();
+ /* Connect a special handler for private keys to intercept PKCS#12 key types
+ * and desensitize the user cert button.
+ */
+ if (privkey) {
+ g_signal_connect (G_OBJECT (widget), "file-set",
+ (GCallback) private_key_picker_file_set_cb,
+ method);
+ if (filename)
+ private_key_picker_helper ((EAPMethod *) method, filename, FALSE);
+ }
+
+ g_signal_connect (G_OBJECT (widget), "file-set",
+ (GCallback) wireless_security_changed_cb,
+ parent);
+
+ filter = eap_method_default_file_chooser_filter_new (privkey);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
+
+ /* For some reason, GTK+ calls set_current_filter (..., NULL) from
+ * gtkfilechooserdefault.c::show_and_select_files_finished_loading() on our
+ * dialog; so force-reset the filter to what we want it to be whenever
+ * it gets cleared.
+ */
+ if (client_cert)
+ g_signal_connect (G_OBJECT (widget), "notify::filter", (GCallback) reset_filter, filter);
+}
+
+static gboolean
+revalidate (gpointer user_data)
+{
+ wireless_security_changed_cb (NULL, (WirelessSecurity *) user_data);
+ return FALSE;
}
EAPMethodTLS *
@@ -395,41 +485,43 @@
gtk_entry_set_text (GTK_ENTRY (widget), nm_setting_802_1x_get_identity (s_8021x));
widget = glade_xml_get_widget (xml, "eap_tls_private_key_password_entry");
- g_assert (widget);
- g_signal_connect (G_OBJECT (widget), "changed",
- (GCallback) wireless_security_changed_cb,
- parent);
/* Fill secrets, if any */
if (connection) {
GHashTable *secrets;
GError *error = NULL;
GValue *value;
+ const char *pw_secret_name = phase2 ? NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD :
+ NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD;
secrets = nm_gconf_get_keyring_items (connection,
NM_SETTING_802_1X_SETTING_NAME,
TRUE,
&error);
if (secrets) {
- value = g_hash_table_lookup (secrets, NMA_PRIVATE_KEY_PASSWORD_TAG);
+ value = g_hash_table_lookup (secrets, pw_secret_name);
if (value)
gtk_entry_set_text (GTK_ENTRY (widget), g_value_get_string (value));
g_hash_table_destroy (secrets);
- } else if (error)
- g_error_free (error);
+ }
+ g_clear_error (&error);
}
+ g_assert (widget);
+ g_signal_connect (G_OBJECT (widget), "changed",
+ (GCallback) wireless_security_changed_cb,
+ parent);
setup_filepicker (xml, "eap_tls_user_cert_button",
_("Choose your personal certificate..."),
- parent, connection,
+ parent, method, connection,
phase2 ? NMA_PATH_PHASE2_CLIENT_CERT_TAG : NMA_PATH_CLIENT_CERT_TAG);
setup_filepicker (xml, "eap_tls_ca_cert_button",
_("Choose a Certificate Authority certificate..."),
- parent, connection,
+ parent, method, connection,
phase2 ? NMA_PATH_PHASE2_CA_CERT_TAG : NMA_PATH_CA_CERT_TAG);
setup_filepicker (xml,
"eap_tls_private_key_button",
_("Choose your private key..."),
- parent, connection,
+ parent, method, connection,
phase2 ? NMA_PATH_PHASE2_PRIVATE_KEY_TAG : NMA_PATH_PRIVATE_KEY_TAG);
widget = glade_xml_get_widget (xml, "show_checkbutton");
@@ -438,6 +530,11 @@
(GCallback) show_toggled_cb,
method);
+ /* Re-validate from an idle-handler becuase file chooser widgets set their
+ * file asynchronously, not when gtk_file_chooser_set_filename() is called.
+ */
+ g_idle_add (revalidate, parent);
+
return method;
}
Modified: trunk/src/wireless-security/eap-method-ttls.c
==============================================================================
--- trunk/src/wireless-security/eap-method-ttls.c (original)
+++ trunk/src/wireless-security/eap-method-ttls.c Thu Nov 13 21:30:30 2008
@@ -52,7 +52,7 @@
EAPMethod *eap = NULL;
gboolean valid = FALSE;
- if (!eap_method_validate_filepicker (parent->xml, "eap_ttls_ca_cert_button", TRUE, FALSE, NULL))
+ if (!eap_method_validate_filepicker (parent->xml, "eap_ttls_ca_cert_button", TYPE_CA_CERT, NULL, NULL))
return FALSE;
widget = glade_xml_get_widget (parent->xml, "eap_ttls_inner_auth_combo");
@@ -429,10 +429,10 @@
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (widget),
_("Choose a Certificate Authority certificate..."));
- g_signal_connect (G_OBJECT (widget), "selection-changed",
+ g_signal_connect (G_OBJECT (widget), "file-set",
(GCallback) wireless_security_changed_cb,
parent);
- filter = eap_method_default_file_chooser_filter_new ();
+ filter = eap_method_default_file_chooser_filter_new (FALSE);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (widget), filter);
if (connection) {
filename = g_object_get_data (G_OBJECT (connection), NMA_PATH_CA_CERT_TAG);
Modified: trunk/src/wireless-security/eap-method.c
==============================================================================
--- trunk/src/wireless-security/eap-method.c (original)
+++ trunk/src/wireless-security/eap-method.c Thu Nov 13 21:30:30 2008
@@ -146,9 +146,9 @@
gboolean
eap_method_validate_filepicker (GladeXML *xml,
const char *name,
- gboolean ignore_blank,
- gboolean is_private_key,
- const char *pw_entry_name)
+ guint32 item_type,
+ const char *password,
+ NMSetting8021xCKType *out_ck_type)
{
GtkWidget *widget;
char *filename;
@@ -156,42 +156,45 @@
gboolean success = FALSE;
GError *error = NULL;
- if (is_private_key)
- g_return_val_if_fail (pw_entry_name != NULL, FALSE);
+ if (item_type == TYPE_PRIVATE_KEY) {
+ g_return_val_if_fail (password != NULL, NM_SETTING_802_1X_CK_TYPE_UNKNOWN);
+ g_return_val_if_fail (strlen (password), NM_SETTING_802_1X_CK_TYPE_UNKNOWN);
+ }
widget = glade_xml_get_widget (xml, name);
g_assert (widget);
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (widget));
if (!filename)
- return ignore_blank ? TRUE : FALSE;
+ return (item_type == TYPE_CA_CERT) ? NM_SETTING_802_1X_CK_TYPE_X509 : NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
if (!g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
goto out;
setting = (NMSetting8021x *) nm_setting_802_1x_new ();
- if (is_private_key) {
- const char *pw;
-
- if (!pw_entry_name)
- goto out;
-
- /* Need the private key password to decrypt the private key */
- widget = glade_xml_get_widget (xml, pw_entry_name);
- g_assert (widget);
- pw = gtk_entry_get_text (GTK_ENTRY (widget));
- if (!pw || !strlen (pw))
- goto out;
-
- success = nm_setting_802_1x_set_private_key_from_file (setting, filename, pw, NULL);
- } else {
- success = nm_setting_802_1x_set_ca_cert_from_file (setting, filename, &error);
- if (error) {
- g_warning ("Error: couldn't verify certificate: %d %s",
- error->code, error->message);
+ if (item_type == TYPE_PRIVATE_KEY) {
+ if (!nm_setting_802_1x_set_private_key_from_file (setting, filename, password, out_ck_type, &error)) {
+ g_warning ("Error: couldn't verify private key: %d %s",
+ error ? error->code : -1, error ? error->message : "(none)");
g_clear_error (&error);
- }
- }
+ } else
+ success = TRUE;
+ } else if (item_type == TYPE_CLIENT_CERT) {
+ if (!nm_setting_802_1x_set_client_cert_from_file (setting, filename, out_ck_type, &error)) {
+ g_warning ("Error: couldn't verify client certificate: %d %s",
+ error ? error->code : -1, error ? error->message : "(none)");
+ g_clear_error (&error);
+ } else
+ success = TRUE;
+ } else if (item_type == TYPE_CA_CERT) {
+ if (!nm_setting_802_1x_set_ca_cert_from_file (setting, filename, out_ck_type, &error)) {
+ g_warning ("Error: couldn't verify CA certificate: %d %s",
+ error ? error->code : -1, error ? error->message : "(none)");
+ g_clear_error (&error);
+ } else
+ success = TRUE;
+ } else
+ g_warning ("%s: invalid item type %d.", __func__, item_type);
g_object_unref (setting);
@@ -221,33 +224,40 @@
static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
static gboolean
-default_filter (const GtkFileFilterInfo *filter_info, gpointer data)
+file_has_extension (const char *filename, const char *extensions[])
{
- int fd;
- unsigned char buffer[1024];
- ssize_t bytes_read;
- gboolean show = FALSE;
- guint16 der_tag = 0x8230;
- char *p;
- char *ext;
+ char *p, *ext;
+ int i = 0;
+ gboolean found = FALSE;
- if (!filter_info->filename)
- return FALSE;
-
- p = strrchr (filter_info->filename, '.');
+ p = strrchr (filename, '.');
if (!p)
return FALSE;
ext = g_ascii_strdown (p, -1);
- if (!ext)
- return FALSE;
- if (strcmp (ext, ".der") && strcmp (ext, ".pem") && strcmp (ext, ".crt") && strcmp (ext, ".cer")) {
- g_free (ext);
- return FALSE;
+ if (ext) {
+ while (extensions[i]) {
+ if (!strcmp (ext, extensions[i++])) {
+ found = TRUE;
+ break;
+ }
+ }
}
g_free (ext);
- fd = open (filter_info->filename, O_RDONLY);
+ return found;
+}
+
+static gboolean
+file_is_der_or_pem (const char *filename, gboolean privkey)
+{
+ int fd;
+ unsigned char buffer[8192];
+ ssize_t bytes_read;
+ guint16 der_tag = 0x8230;
+ gboolean success = FALSE;
+
+ fd = open (filename, O_RDONLY);
if (fd < 0)
return FALSE;
@@ -258,39 +268,80 @@
/* Check for DER signature */
if (!memcmp (buffer, &der_tag, 2)) {
- show = TRUE;
+ success = TRUE;
goto out;
}
/* Check for PEM signatures */
- if (find_tag (pem_rsa_key_begin, (const char *) buffer, bytes_read)) {
- show = TRUE;
- goto out;
- }
-
- if (find_tag (pem_dsa_key_begin, (const char *) buffer, bytes_read)) {
- show = TRUE;
- goto out;
- }
+ if (privkey) {
+ if (find_tag (pem_rsa_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ goto out;
+ }
- if (find_tag (pem_cert_begin, (const char *) buffer, bytes_read)) {
- show = TRUE;
- goto out;
+ if (find_tag (pem_dsa_key_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ goto out;
+ }
+ } else {
+ if (find_tag (pem_cert_begin, (const char *) buffer, bytes_read)) {
+ success = TRUE;
+ goto out;
+ }
}
out:
close (fd);
- return show;
+ return success;
+}
+
+static gboolean
+default_filter_privkey (const GtkFileFilterInfo *filter_info, gpointer user_data)
+{
+ const char *extensions[] = { ".der", ".pem", ".p12", NULL };
+
+ if (!filter_info->filename)
+ return FALSE;
+
+ if (!file_has_extension (filter_info->filename, extensions))
+ return FALSE;
+
+ if (!file_is_der_or_pem (filter_info->filename, TRUE))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+default_filter_cert (const GtkFileFilterInfo *filter_info, gpointer user_data)
+{
+ const char *extensions[] = { ".der", ".pem", ".crt", ".cer", NULL };
+
+ if (!filter_info->filename)
+ return FALSE;
+
+ if (!file_has_extension (filter_info->filename, extensions))
+ return FALSE;
+
+ if (!file_is_der_or_pem (filter_info->filename, FALSE))
+ return FALSE;
+
+ return TRUE;
}
GtkFileFilter *
-eap_method_default_file_chooser_filter_new (void)
+eap_method_default_file_chooser_filter_new (gboolean privkey)
{
GtkFileFilter *filter;
filter = gtk_file_filter_new ();
- gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, default_filter, NULL, NULL);
- gtk_file_filter_set_name (filter, _("DER or PEM certificates (*.der, *.pem, *.crt, *.cer)"));
+ if (privkey) {
+ gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, default_filter_privkey, NULL, NULL);
+ gtk_file_filter_set_name (filter, _("DER, PEM, or PKCS#12 private keys (*.der, *.pem, *.p12)"));
+ } else {
+ gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, default_filter_cert, NULL, NULL);
+ gtk_file_filter_set_name (filter, _("DER or PEM certificates (*.der, *.pem, *.crt, *.cer)"));
+ }
return filter;
}
Modified: trunk/src/wireless-security/eap-method.h
==============================================================================
--- trunk/src/wireless-security/eap-method.h (original)
+++ trunk/src/wireless-security/eap-method.h Thu Nov 13 21:30:30 2008
@@ -29,6 +29,7 @@
#include <gtk/gtkwidget.h>
#include <nm-connection.h>
+#include <nm-setting-8021x.h>
typedef struct _EAPMethod EAPMethod;
@@ -85,13 +86,17 @@
GladeXML *xml,
GtkWidget *ui_widget);
-GtkFileFilter * eap_method_default_file_chooser_filter_new (void);
+GtkFileFilter * eap_method_default_file_chooser_filter_new (gboolean privkey);
+
+#define TYPE_CLIENT_CERT 0
+#define TYPE_CA_CERT 1
+#define TYPE_PRIVATE_KEY 2
gboolean eap_method_validate_filepicker (GladeXML *xml,
const char *name,
- gboolean ignore_blank,
- gboolean is_private_key,
- const char *pw_entry_name);
+ guint32 item_type,
+ const char *password,
+ NMSetting8021xCKType *out_ck_type);
#endif /* EAP_METHOD_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]