[network-manager-applet/NETWORKMANAGER_APPLET_0_7] tls: require password-protected private keys



commit e54a79b1acdea6ae882295524af38a5dbe2ba7b1
Author: Dan Williams <dcbw redhat com>
Date:   Mon Nov 16 18:00:11 2009 -0800

    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/

 src/wireless-security/eap-method-tls.c |   23 +++++++++++++++++++++
 src/wireless-security/eap-method.c     |   34 ++++++++++++++++++++++++++++---
 src/wireless-security/eap-method.h     |    2 +
 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 db0d7c4..01f29e9 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 f382bf7..6ab01ec 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 2d517b0..d2d03cd 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]