summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2009-11-16 18:00:11 -0800
committerDan Williams <dcbw@redhat.com>2009-11-16 18:02:53 -0800
commite54a79b1acdea6ae882295524af38a5dbe2ba7b1 (patch)
tree078f293f28ac7bed9f865d68119fec9a9fe6fde5
parent5e04155d2f46e0bc5be4ae50ad903245e8de72e4 (diff)
downloadnetwork-manager-applet-e54a79b1acdea6ae882295524af38a5dbe2ba7b1.tar.gz
tls: require password-protected private keys
We already required this, but unencrypted private keys got by the cert chooser dialog's filter. Fix that by alerting the user that the key appears to be unencrypted and that they'll need to encrypt it to use it. Usually caused by outdated NM 0.6.x-era instructions for connecting to eduroam, for example: http://imt.uni-paderborn.de/unser-angebot/dienste-a-z/dienste-nach-themen/wlan/netzwerk-eduroam/netzwerkzertifikate/linux-gui/
-rw-r--r--src/wireless-security/eap-method-tls.c23
-rw-r--r--src/wireless-security/eap-method.c34
-rw-r--r--src/wireless-security/eap-method.h2
3 files changed, 55 insertions, 4 deletions
diff --git a/src/wireless-security/eap-method-tls.c b/src/wireless-security/eap-method-tls.c
index db0d7c4d..01f29e9f 100644
--- a/src/wireless-security/eap-method-tls.c
+++ b/src/wireless-security/eap-method-tls.c
@@ -254,6 +254,29 @@ private_key_picker_helper (EAPMethod *parent, const char *filename, gboolean cha
gtk_widget_set_sensitive (widget, FALSE);
} else if (changed)
gtk_widget_set_sensitive (widget, TRUE);
+
+ /* Warn the user if the private key is unencrypted */
+ if (!eap_method_is_encrypted_private_key (filename)) {
+ GtkWidget *dialog;
+ GtkWidget *toplevel;
+ GtkWindow *parent_window = NULL;
+
+ toplevel = gtk_widget_get_toplevel (parent->ui_widget);
+ if (GTK_WIDGET_TOPLEVEL (toplevel))
+ parent_window = GTK_WINDOW (toplevel);
+
+ dialog = gtk_message_dialog_new (parent_window,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ "%s",
+ _("Unencrypted private keys are insecure"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s",
+ _("The selected private key does not appear to be protected by a password. This could allow your security credentials to be compromised. Please select a password-protected private key.\n\n(You can password-protect your private key with openssl)"));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ }
}
static void
diff --git a/src/wireless-security/eap-method.c b/src/wireless-security/eap-method.c
index f382bf7e..6ab01ec9 100644
--- a/src/wireless-security/eap-method.c
+++ b/src/wireless-security/eap-method.c
@@ -324,6 +324,8 @@ find_tag (const char *tag, const char *buf, gsize len)
static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----";
static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
+static const char *proc_type_tag = "Proc-Type: 4,ENCRYPTED";
+static const char *dek_info_tag = "DEK-Info:";
static gboolean
file_has_extension (const char *filename, const char *extensions[])
@@ -351,13 +353,16 @@ file_has_extension (const char *filename, const char *extensions[])
}
static gboolean
-file_is_der_or_pem (const char *filename, gboolean privkey)
+file_is_der_or_pem (const char *filename,
+ gboolean privkey,
+ gboolean *out_privkey_encrypted)
{
int fd;
unsigned char buffer[8192];
ssize_t bytes_read;
guint16 der_tag = 0x8230;
gboolean success = FALSE;
+ gboolean encrypted = FALSE;
fd = open (filename, O_RDONLY);
if (fd < 0)
@@ -385,6 +390,17 @@ file_is_der_or_pem (const char *filename, gboolean privkey)
success = TRUE;
goto out;
}
+
+ /* Check if the private key is encrypted or not by looking for the
+ * old OpenSSL-style proc-type and dec-info tags.
+ */
+ if (out_privkey_encrypted) {
+ if (find_tag (proc_type_tag, (const char *) buffer, bytes_read)) {
+ if (find_tag (dek_info_tag, (const char *) buffer, bytes_read))
+ encrypted = TRUE;
+ }
+ *out_privkey_encrypted = encrypted;
+ }
} else {
if (find_tag (pem_cert_begin, (const char *) buffer, bytes_read)) {
success = TRUE;
@@ -401,6 +417,8 @@ static gboolean
default_filter_privkey (const GtkFileFilterInfo *filter_info, gpointer user_data)
{
const char *extensions[] = { ".der", ".pem", ".p12", NULL };
+ gboolean require_encrypted = !!user_data;
+ gboolean is_encrypted = TRUE;
if (!filter_info->filename)
return FALSE;
@@ -408,10 +426,10 @@ default_filter_privkey (const GtkFileFilterInfo *filter_info, gpointer user_data
if (!file_has_extension (filter_info->filename, extensions))
return FALSE;
- if (!file_is_der_or_pem (filter_info->filename, TRUE))
+ if (!file_is_der_or_pem (filter_info->filename, TRUE, &is_encrypted))
return FALSE;
- return TRUE;
+ return require_encrypted ? is_encrypted : TRUE;
}
static gboolean
@@ -425,7 +443,7 @@ default_filter_cert (const GtkFileFilterInfo *filter_info, gpointer user_data)
if (!file_has_extension (filter_info->filename, extensions))
return FALSE;
- if (!file_is_der_or_pem (filter_info->filename, FALSE))
+ if (!file_is_der_or_pem (filter_info->filename, FALSE, NULL))
return FALSE;
return TRUE;
@@ -447,3 +465,11 @@ eap_method_default_file_chooser_filter_new (gboolean privkey)
return filter;
}
+gboolean
+eap_method_is_encrypted_private_key (const char *path)
+{
+ GtkFileFilterInfo info = { .filename = path };
+
+ return default_filter_privkey (&info, (gpointer) TRUE);
+}
+
diff --git a/src/wireless-security/eap-method.h b/src/wireless-security/eap-method.h
index 2d517b00..d2d03cd7 100644
--- a/src/wireless-security/eap-method.h
+++ b/src/wireless-security/eap-method.h
@@ -92,6 +92,8 @@ void eap_method_init (EAPMethod *method,
GtkFileFilter * eap_method_default_file_chooser_filter_new (gboolean privkey);
+gboolean eap_method_is_encrypted_private_key (const char *path);
+
#define TYPE_CLIENT_CERT 0
#define TYPE_CA_CERT 1
#define TYPE_PRIVATE_KEY 2