File nm-certificate-formats.patch of Package NetworkManager
From 7ae5c9af1dde0845271b76adeb4c383aa3c49359 Mon Sep 17 00:00:00 2001
From: Tambet Ingo <tambet@gmail.com>
Date: Wed, 3 Dec 2008 12:11:09 +0200
Subject: [PATCH] nm-certificate-formats
diff --git a/libnm-util/nm-setting-8021x.c b/libnm-util/nm-setting-8021x.c
index 062cb7a..cf11e2a 100644
--- a/libnm-util/nm-setting-8021x.c
+++ b/libnm-util/nm-setting-8021x.c
@@ -717,6 +717,9 @@ need_private_key_password (GByteArray *key, const char *password)
GError *error = NULL;
gboolean needed = TRUE;
+ if (key && key->data && g_str_has_prefix ((char *) key->data, NM_SETTING_802_1X_CK_FORMAT_FILE))
+ return FALSE;
+
/* See if a private key password is needed, which basically is whether
* or not the private key is a PKCS#12 file or not, since PKCS#1 files
* are decrypted by the settings service.
@@ -1384,7 +1387,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
"CA certificate",
"CA certificate",
DBUS_TYPE_G_UCHAR_ARRAY,
- G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_CERTIFICATE));
g_object_class_install_property
(object_class, PROP_CA_PATH,
@@ -1400,7 +1403,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
"Client certificate",
"Client certificate",
DBUS_TYPE_G_UCHAR_ARRAY,
- G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_CERTIFICATE));
g_object_class_install_property
(object_class, PROP_PHASE1_PEAPVER,
@@ -1448,7 +1451,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
"Phase2 CA certificate",
"Phase2 CA certificate",
DBUS_TYPE_G_UCHAR_ARRAY,
- G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_CERTIFICATE));
g_object_class_install_property
(object_class, PROP_PHASE2_CA_PATH,
@@ -1464,7 +1467,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
"Phase2 client certificate",
"Phase2 client certificate",
DBUS_TYPE_G_UCHAR_ARRAY,
- G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+ G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_CERTIFICATE));
g_object_class_install_property
(object_class, PROP_PASSWORD,
@@ -1480,7 +1483,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
"Private key",
"Private key",
DBUS_TYPE_G_UCHAR_ARRAY,
- G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+ G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET | NM_SETTING_PARAM_CERTIFICATE));
g_object_class_install_property
(object_class, PROP_PRIVATE_KEY_PASSWORD,
@@ -1496,7 +1499,7 @@ nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
"Phase2 private key",
"Phase2 private key",
DBUS_TYPE_G_UCHAR_ARRAY,
- G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+ G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET | NM_SETTING_PARAM_CERTIFICATE));
g_object_class_install_property
(object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD,
diff --git a/libnm-util/nm-setting-8021x.h b/libnm-util/nm-setting-8021x.h
index e956e68..d170e4e 100644
--- a/libnm-util/nm-setting-8021x.h
+++ b/libnm-util/nm-setting-8021x.h
@@ -83,6 +83,9 @@ GQuark nm_setting_802_1x_error_quark (void);
#define NM_SETTING_802_1X_PSK "psk"
#define NM_SETTING_802_1X_SYSTEM_CA_CERTS "system-ca-certs"
+#define NM_SETTING_802_1X_CK_FORMAT_ID "id:"
+#define NM_SETTING_802_1X_CK_FORMAT_FILE "file:"
+
typedef struct {
NMSetting parent;
} NMSetting8021x;
diff --git a/libnm-util/nm-setting.h b/libnm-util/nm-setting.h
index 474d3f6..84a9140 100644
--- a/libnm-util/nm-setting.h
+++ b/libnm-util/nm-setting.h
@@ -81,6 +81,8 @@ GQuark nm_setting_error_quark (void);
*/
#define NM_SETTING_PARAM_FUZZY_IGNORE (1 << (3 + G_PARAM_USER_SHIFT))
+#define NM_SETTING_PARAM_CERTIFICATE (1 << (4 + G_PARAM_USER_SHIFT))
+
#define NM_SETTING_NAME "name"
/**
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
index 2918504..da90f00 100644
--- a/src/supplicant-manager/nm-supplicant-config.c
+++ b/src/supplicant-manager/nm-supplicant-config.c
@@ -558,6 +558,174 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
return TRUE;
}
+static gboolean
+add_certificates (NMSupplicantConfig *self, NMSetting8021x *setting, const char *connection_uid)
+{
+ const GByteArray *array;
+ const char *str;
+ char *value;
+ gboolean use_system_ca;
+ gboolean send_private_key_passwd;
+ gboolean send_client_cert;
+ gboolean success;
+
+ use_system_ca = nm_setting_802_1x_get_system_ca_certs (setting) || nm_setting_802_1x_get_ca_cert (setting) == NULL;
+
+ if (use_system_ca) {
+ ADD_STRING_VAL (SYSTEM_CA_PATH, "ca_path", FALSE, FALSE, FALSE);
+ } else {
+ array = nm_setting_802_1x_get_ca_cert (setting);
+ if (array && array->data) {
+ str = (char *) array->data;
+
+ if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_ID))
+ nm_supplicant_config_add_option (self, "ca_cert_id",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_ID),
+ -1, FALSE);
+ else if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_FILE))
+ nm_supplicant_config_add_option (self, "ca_cert",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_FILE),
+ -1, FALSE);
+ else {
+ ADD_BLOB_VAL (array, "ca_cert", connection_uid);
+ }
+ }
+ }
+
+ array = nm_setting_802_1x_get_private_key (setting);
+ if (array && array->data) {
+ str = (char *) array->data;
+
+ if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_ID)) {
+ nm_supplicant_config_add_option (self, "key_id",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_ID),
+ -1, FALSE);
+
+ send_private_key_passwd = FALSE;
+ send_client_cert = TRUE;
+ } else if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_FILE)) {
+ nm_supplicant_config_add_option (self, "private_key",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_FILE),
+ -1, FALSE);
+
+ send_private_key_passwd = TRUE;
+ send_client_cert = TRUE;
+ } else {
+ ADD_BLOB_VAL (array, "private_key", connection_uid);
+
+ if (nm_setting_802_1x_get_private_key_type (setting) == NM_SETTING_802_1X_CK_TYPE_PKCS12) {
+ send_private_key_passwd = TRUE;
+ send_client_cert = FALSE;
+ } else {
+ send_private_key_passwd = FALSE;
+ send_client_cert = TRUE;
+ }
+ }
+ }
+
+ if (send_private_key_passwd) {
+ ADD_STRING_VAL (nm_setting_802_1x_get_private_key_password (setting),
+ "private_key_passwd", FALSE, FALSE, TRUE);
+ }
+
+ if (send_client_cert) {
+ array = nm_setting_802_1x_get_client_cert (setting);
+ if (array && array->data) {
+ str = (char *) array->data;
+
+ if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_ID))
+ nm_supplicant_config_add_option (self, "cert_id",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_ID),
+ -1, FALSE);
+ else if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_FILE))
+ nm_supplicant_config_add_option (self, "client_cert",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_FILE),
+ -1, FALSE);
+ else {
+ ADD_BLOB_VAL (array, "client_cert", connection_uid);
+ }
+ }
+ }
+
+ /* phase 2 */
+
+ if (!use_system_ca) {
+ array = nm_setting_802_1x_get_phase2_ca_cert (setting);
+ if (array && array->data) {
+ str = (char *) array->data;
+
+ if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_ID)) {
+ nm_supplicant_config_add_option (self, "ca_cert2_id",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_ID),
+ -1, FALSE);
+ } else if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_FILE)) {
+ nm_supplicant_config_add_option (self, "ca_cert2",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_FILE),
+ -1, FALSE);
+ } else {
+ ADD_BLOB_VAL (array, "ca_cert", connection_uid);
+ }
+ }
+ }
+
+ array = nm_setting_802_1x_get_phase2_private_key (setting);
+ if (array && array->data) {
+ str = (char *) array->data;
+
+ if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_ID)) {
+ nm_supplicant_config_add_option (self, "key2_id",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_ID),
+ -1, FALSE);
+
+ send_private_key_passwd = FALSE;
+ send_client_cert = TRUE;
+ } else if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_FILE)) {
+ nm_supplicant_config_add_option (self, "private_key2",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_FILE),
+ -1, FALSE);
+
+ send_private_key_passwd = TRUE;
+ send_client_cert = TRUE;
+ } else {
+ ADD_BLOB_VAL (array, "private_key2", connection_uid);
+
+ if (nm_setting_802_1x_get_phase2_private_key_type (setting) == NM_SETTING_802_1X_CK_TYPE_PKCS12) {
+ send_private_key_passwd = TRUE;
+ send_client_cert = FALSE;
+ } else {
+ send_private_key_passwd = FALSE;
+ send_client_cert = TRUE;
+ }
+ }
+ }
+
+ if (send_private_key_passwd) {
+ ADD_STRING_VAL (nm_setting_802_1x_get_phase2_private_key_password (setting),
+ "private_key2_passwd", FALSE, FALSE, TRUE);
+ }
+
+ if (send_client_cert) {
+ array = nm_setting_802_1x_get_phase2_client_cert (setting);
+ if (array && array->data) {
+ str = (char *) array->data;
+
+ if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_ID)) {
+ nm_supplicant_config_add_option (self, "cert2_id",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_ID),
+ -1, FALSE);
+ } else if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_FILE)) {
+ nm_supplicant_config_add_option (self, "client_cert2",
+ str + strlen (NM_SETTING_802_1X_CK_FORMAT_FILE),
+ -1, FALSE);
+ } else {
+ ADD_BLOB_VAL (array, "client_cert2", connection_uid);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
gboolean
nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
NMSetting8021x *setting,
@@ -568,7 +736,6 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
char *value, *tmp;
gboolean success;
GString *phase1, *phase2;
- const GByteArray *array;
g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
g_return_val_if_fail (setting != NULL, FALSE);
@@ -624,53 +791,11 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
ADD_STRING_VAL (phase2->str, "phase2", FALSE, FALSE, FALSE);
g_string_free (phase2, TRUE);
- if (nm_setting_802_1x_get_system_ca_certs (setting)) {
- ADD_STRING_VAL (SYSTEM_CA_PATH, "ca_path", FALSE, FALSE, FALSE);
- } else {
- ADD_BLOB_VAL (nm_setting_802_1x_get_ca_cert (setting), "ca_cert", connection_uid);
- }
-
- array = nm_setting_802_1x_get_private_key (setting);
- if (array) {
- ADD_BLOB_VAL (array, "private_key", connection_uid);
-
- switch (nm_setting_802_1x_get_private_key_type (setting)) {
- case NM_SETTING_802_1X_CK_TYPE_PKCS12:
- /* Only add the private key password for PKCS#12 keys */
- ADD_STRING_VAL (nm_setting_802_1x_get_private_key_password (setting), "private_key_passwd", FALSE, FALSE, TRUE);
- break;
- default:
- /* Only add the client cert if the private key is not PKCS#12 */
- ADD_BLOB_VAL (nm_setting_802_1x_get_client_cert (setting), "client_cert", connection_uid);
- break;
- }
- }
-
- if (nm_setting_802_1x_get_system_ca_certs (setting)) {
- ADD_STRING_VAL (SYSTEM_CA_PATH, "ca_path2", FALSE, FALSE, FALSE);
- } else {
- ADD_BLOB_VAL (nm_setting_802_1x_get_phase2_ca_cert (setting), "ca_cert2", connection_uid);
- }
-
- array = nm_setting_802_1x_get_phase2_private_key (setting);
- if (array) {
- ADD_BLOB_VAL (array, "private_key2", connection_uid);
-
- switch (nm_setting_802_1x_get_phase2_private_key_type (setting)) {
- case NM_SETTING_802_1X_CK_TYPE_PKCS12:
- /* Only add the private key password for PKCS#12 keys */
- ADD_STRING_VAL (nm_setting_802_1x_get_phase2_private_key_password (setting), "private_key2_passwd", FALSE, FALSE, TRUE);
- break;
- default:
- /* Only add the client cert if the private key is not PKCS#12 */
- ADD_BLOB_VAL (nm_setting_802_1x_get_phase2_client_cert (setting), "client_cert2", connection_uid);
- break;
- }
- }
-
ADD_STRING_VAL (nm_setting_802_1x_get_identity (setting), "identity", FALSE, FALSE, FALSE);
ADD_STRING_VAL (nm_setting_802_1x_get_anonymous_identity (setting), "anonymous_identity", FALSE, FALSE, FALSE);
+ add_certificates (self, setting, connection_uid);
+
return TRUE;
}
diff --git a/src/supplicant-manager/nm-supplicant-settings-verify.c b/src/supplicant-manager/nm-supplicant-settings-verify.c
index 5e30795..2c70d22 100644
--- a/src/supplicant-manager/nm-supplicant-settings-verify.c
+++ b/src/supplicant-manager/nm-supplicant-settings-verify.c
@@ -103,16 +103,22 @@ static const struct Opt opt_table[] = {
{ "password", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "ca_path", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "ca_cert", TYPE_BYTES, 0, 65536, FALSE, NULL },
+ { "ca_cert_id", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "client_cert", TYPE_BYTES, 0, 65536, FALSE, NULL },
+ { "cert_id", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "private_key", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "private_key_passwd", TYPE_BYTES, 0, 1024, FALSE, NULL },
+ { "key_id", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "phase1", TYPE_KEYWORD, 0, 0, TRUE, phase1_allowed },
{ "phase2", TYPE_KEYWORD, 0, 0, TRUE, phase2_allowed },
{ "anonymous_identity", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "ca_cert2", TYPE_BYTES, 0, 65536, FALSE, NULL },
+ { "ca_cert2_id", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "client_cert2", TYPE_BYTES, 0, 65536, FALSE, NULL },
+ { "cert2_id", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "private_key2", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "private_key2_passwd",TYPE_BYTES, 0, 1024, FALSE, NULL },
+ { "key2_id", TYPE_BYTES, 0, 65536, FALSE, NULL },
{ "pin", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "pcsc", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "nai", TYPE_BYTES, 0, 0, FALSE, NULL },
diff --git a/system-settings/plugins/keyfile/nm-keyfile-connection.c b/system-settings/plugins/keyfile/nm-keyfile-connection.c
index 0e4031b..2f4ded7 100644
--- a/system-settings/plugins/keyfile/nm-keyfile-connection.c
+++ b/system-settings/plugins/keyfile/nm-keyfile-connection.c
@@ -114,6 +114,18 @@ add_secrets (NMSetting *setting,
} else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_MAP_OF_STRING)) {
/* Flatten the string hash by pulling its keys/values out */
g_hash_table_foreach (g_value_get_boxed (value), copy_one_secret, secrets);
+ } else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY)) {
+ const GByteArray *array;
+
+ array = (GByteArray *) g_value_get_boxed (value);
+ if (array && array->len > 0) {
+ GValue *v;
+
+ v = g_slice_new0 (GValue);
+ g_value_init (v, DBUS_TYPE_G_UCHAR_ARRAY);
+ g_value_copy (value, v);
+ g_hash_table_insert (secrets, g_strdup (key), v);
+ }
} else
g_message ("%s: unhandled secret %s type %s", __func__, key, G_VALUE_TYPE_NAME (value));
}
diff --git a/system-settings/plugins/keyfile/reader.c b/system-settings/plugins/keyfile/reader.c
index 9efd130..b8c4099 100644
--- a/system-settings/plugins/keyfile/reader.c
+++ b/system-settings/plugins/keyfile/reader.c
@@ -29,6 +29,7 @@
#include <nm-setting-ip4-config.h>
#include <nm-setting-vpn.h>
#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
#include <arpa/inet.h>
#include <string.h>
@@ -337,6 +338,56 @@ read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key)
g_strfreev (keys);
}
+static void
+read_guchar_array (GKeyFile *file, NMSetting *setting, const char *key)
+{
+ gint *tmp;
+ GByteArray *array;
+ gsize length;
+ int i;
+
+ tmp = g_key_file_get_integer_list (file, nm_setting_get_name (setting), key, &length, NULL);
+ array = g_byte_array_sized_new (length);
+ for (i = 0; i < length; i++) {
+ int val = tmp[i];
+ unsigned char v = (unsigned char) (val & 0xFF);
+
+ if (val < 0 || val > 255)
+ g_warning ("Value out of range for a byte value");
+ else
+ g_byte_array_append (array, (const unsigned char *) &v, sizeof (v));
+ }
+
+ g_object_set (setting, key, array, NULL);
+ g_byte_array_free (array, TRUE);
+ g_free (tmp);
+}
+
+static void
+read_certificate (NMSetting *setting, GKeyFile *file, const char *key)
+{
+ char *value;
+
+ value = g_key_file_get_value (file, nm_setting_get_name (setting), key, NULL);
+ if (!value)
+ return;
+
+ if (g_str_has_prefix (value, NM_SETTING_802_1X_CK_FORMAT_ID) ||
+ g_str_has_prefix (value, NM_SETTING_802_1X_CK_FORMAT_FILE)) {
+ GByteArray *array;
+ gsize len;
+
+ len = strlen (value);
+ array = g_byte_array_sized_new (len);
+ g_byte_array_append (array, (guint8 *) value, len);
+ g_object_set (setting, key, array, NULL);
+ g_byte_array_free (array, TRUE);
+ } else
+ read_guchar_array (file, setting, key);
+
+ g_free (value);
+}
+
typedef struct {
GKeyFile *keyfile;
gboolean secrets;
@@ -390,6 +441,12 @@ read_one_setting_value (NMSetting *setting,
return;
}
+ /* Certificates are handled differently */
+ if (flags & NM_SETTING_PARAM_CERTIFICATE) {
+ read_certificate (setting, file, key);
+ return;
+ }
+
type = G_VALUE_TYPE (value);
if (type == G_TYPE_STRING) {
@@ -432,27 +489,7 @@ read_one_setting_value (NMSetting *setting,
g_free (tmp_str);
g_object_set (setting, key, uint_val, NULL);
} else if (type == DBUS_TYPE_G_UCHAR_ARRAY) {
- gint *tmp;
- GByteArray *array;
- gsize length;
- int i;
-
- tmp = g_key_file_get_integer_list (file, setting_name, key, &length, NULL);
-
- array = g_byte_array_sized_new (length);
- for (i = 0; i < length; i++) {
- int val = tmp[i];
- unsigned char v = (unsigned char) (val & 0xFF);
-
- if (val < 0 || val > 255)
- g_warning ("Value out of range for a byte value");
- else
- g_byte_array_append (array, (const unsigned char *) &v, sizeof (v));
- }
-
- g_object_set (setting, key, array, NULL);
- g_byte_array_free (array, TRUE);
- g_free (tmp);
+ read_guchar_array (file, setting, key);
} else if (type == DBUS_TYPE_G_LIST_OF_STRING) {
gchar **sa;
gsize length;
--
1.6.0.2