From 80afa8e082e75494ff7d318a1042e09f77d615c5 Mon Sep 17 00:00:00 2001
From: Tambet Ingo <tambet@gmail.com>
Date: Wed, 3 Dec 2008 12:16:58 +0200
Subject: [PATCH] nm-pkcs11


Index: NetworkManager-0.7.0/libnm-util/libnm-util.ver
===================================================================
--- NetworkManager-0.7.0.orig/libnm-util/libnm-util.ver
+++ NetworkManager-0.7.0/libnm-util/libnm-util.ver
@@ -55,6 +55,10 @@ global:
 	nm_setting_802_1x_get_phase2_private_key_password;
 	nm_setting_802_1x_get_phase2_private_key_type;
 	nm_setting_802_1x_get_pin;
+	nm_setting_802_1x_get_pkcs11_engine_path;
+	nm_setting_802_1x_get_pkcs11_module_path;
+	nm_setting_802_1x_get_pkcs11_module_init_args;
+	nm_setting_802_1x_get_pkcs11_slot;
 	nm_setting_802_1x_get_private_key;
 	nm_setting_802_1x_set_private_key_from_file;
 	nm_setting_802_1x_get_private_key_password;
Index: NetworkManager-0.7.0/libnm-util/nm-setting-8021x.c
===================================================================
--- NetworkManager-0.7.0.orig/libnm-util/nm-setting-8021x.c
+++ NetworkManager-0.7.0/libnm-util/nm-setting-8021x.c
@@ -94,6 +94,10 @@ typedef struct {
 	GByteArray *phase2_private_key;
 	char *phase2_private_key_password;
 	gboolean system_ca_certs;
+	char *pkcs11_engine_path;
+	char *pkcs11_module_path;
+	char *pkcs11_module_init_args;
+	guint pkcs11_slot;
 } NMSetting8021xPrivate;
 
 enum {
@@ -120,6 +124,10 @@ enum {
 	PROP_PIN,
 	PROP_PSK,
 	PROP_SYSTEM_CA_CERTS,
+	PROP_PKCS11_ENGINE_PATH,
+	PROP_PKCS11_MODULE_PATH,
+	PROP_PKCS11_MODULE_INIT_ARGS,
+	PROP_PKCS11_SLOT,
 
 	LAST_PROP
 };
@@ -689,6 +697,38 @@ nm_setting_802_1x_get_phase2_private_key
 	return NM_SETTING_802_1X_CK_TYPE_X509;
 }
 
+const char *
+nm_setting_802_1x_get_pkcs11_engine_path (NMSetting8021x *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->pkcs11_engine_path;
+}
+
+const char *
+nm_setting_802_1x_get_pkcs11_module_path (NMSetting8021x *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->pkcs11_module_path;
+}
+
+const char *
+nm_setting_802_1x_get_pkcs11_module_init_args (NMSetting8021x *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->pkcs11_module_init_args;
+}
+
+guint
+nm_setting_802_1x_get_pkcs11_slot (NMSetting8021x *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0);
+
+	return NM_SETTING_802_1X_GET_PRIVATE (setting)->pkcs11_slot;
+}
+
 static void
 need_secrets_password (NMSetting8021x *self,
                        GPtrArray *secrets,
@@ -745,6 +785,10 @@ need_secrets_tls (NMSetting8021x *self,
 {
 	NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
 
+	if (priv->pkcs11_module_path && (!priv->pin || !strlen (priv->pin)) &&
+		(priv->private_key || priv->phase2_private_key))
+		g_ptr_array_add (secrets, NM_SETTING_802_1X_PIN);
+
 	if (phase2) {
 		if (!priv->phase2_private_key || !priv->phase2_private_key->len)
 			g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
@@ -1145,6 +1189,10 @@ finalize (GObject *object)
 	g_free (priv->phase2_autheap);
 	g_free (priv->phase2_ca_path);
 	g_free (priv->password);
+	g_free (priv->pin);
+	g_free (priv->pkcs11_engine_path);
+	g_free (priv->pkcs11_module_path);
+	g_free (priv->pkcs11_module_init_args);
 
 	nm_utils_slist_free (priv->eap, g_free);
 
@@ -1238,6 +1286,10 @@ set_property (GObject *object, guint pro
 		g_free (priv->password);
 		priv->password = g_value_dup_string (value);
 		break;
+	case PROP_PIN:
+		g_free (priv->pin);
+		priv->pin = g_value_dup_string (value);
+		break;
 	case PROP_PRIVATE_KEY:
 		if (priv->private_key)
 			g_byte_array_free (priv->private_key, TRUE);
@@ -1259,6 +1311,20 @@ set_property (GObject *object, guint pro
 	case PROP_SYSTEM_CA_CERTS:
 		priv->system_ca_certs = g_value_get_boolean (value);
 		break;
+	case PROP_PKCS11_ENGINE_PATH:
+		g_free (priv->pkcs11_engine_path);
+		priv->pkcs11_engine_path = g_value_dup_string (value);
+		break;
+	case PROP_PKCS11_MODULE_PATH:
+		g_free (priv->pkcs11_module_path);
+		priv->pkcs11_module_path = g_value_dup_string (value);
+		break;
+	case PROP_PKCS11_MODULE_INIT_ARGS:
+		g_free (priv->pkcs11_module_init_args);
+		priv->pkcs11_module_init_args = g_value_dup_string (value);
+	case PROP_PKCS11_SLOT:
+		priv->pkcs11_slot = g_value_get_uint (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1318,6 +1384,9 @@ get_property (GObject *object, guint pro
 	case PROP_PASSWORD:
 		g_value_set_string (value, priv->password);
 		break;
+	case PROP_PIN:
+		g_value_set_string (value, priv->pin);
+		break;
 	case PROP_PRIVATE_KEY:
 		g_value_set_boxed (value, priv->private_key);
 		break;
@@ -1333,6 +1402,18 @@ get_property (GObject *object, guint pro
 	case PROP_SYSTEM_CA_CERTS:
 		g_value_set_boolean (value, priv->system_ca_certs);
 		break;
+	case PROP_PKCS11_ENGINE_PATH:
+		g_value_set_string (value, priv->pkcs11_engine_path);
+		break;
+	case PROP_PKCS11_MODULE_PATH:
+		g_value_set_string (value, priv->pkcs11_module_path);
+		break;
+	case PROP_PKCS11_MODULE_INIT_ARGS:
+		g_value_set_string (value, priv->pkcs11_module_init_args);
+		break;
+	case PROP_PKCS11_SLOT:
+		g_value_set_uint (value, priv->pkcs11_slot);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1478,6 +1559,14 @@ nm_setting_802_1x_class_init (NMSetting8
 						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
 
 	g_object_class_install_property
+		(object_class, PROP_PIN,
+		 g_param_spec_string (NM_SETTING_802_1X_PIN,
+							  "PIN",
+							  "PIN",
+							  NULL,
+							  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+
+	g_object_class_install_property
 		(object_class, PROP_PRIVATE_KEY,
 		 _nm_param_spec_specialized (NM_SETTING_802_1X_PRIVATE_KEY,
 							   "Private key",
@@ -1517,6 +1606,38 @@ nm_setting_802_1x_class_init (NMSetting8
 							   FALSE,
 							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
 
+	g_object_class_install_property
+		(object_class, PROP_PKCS11_ENGINE_PATH,
+		 g_param_spec_string (NM_SETTING_802_1X_PKCS11_ENGINE_PATH,
+						  "OpenSSL pkcs11 engine path",
+						  "OpenSSL pkcs11 engine path",
+						  NULL,
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	g_object_class_install_property
+		(object_class, PROP_PKCS11_MODULE_PATH,
+		 g_param_spec_string (NM_SETTING_802_1X_PKCS11_MODULE_PATH,
+						  "PKCS11 smartcard library module path",
+						  "PKCS11 smartcard library module path",
+						  NULL,
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	g_object_class_install_property
+		(object_class, PROP_PKCS11_MODULE_INIT_ARGS,
+		 g_param_spec_string (NM_SETTING_802_1X_PKCS11_MODULE_INIT_ARGS,
+						  "PKCS11 smartcard library initialization arguments",
+						  "PKCS11 smartcard library initialization arguments",
+						  NULL,
+						  G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
+	g_object_class_install_property
+		(object_class, PROP_PKCS11_SLOT,
+		 g_param_spec_uint (NM_SETTING_802_1X_PKCS11_SLOT,
+						"PKCS11 slot",
+						"PKCS11 slot",
+						0, 1000, 0,
+						G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+
 	/* Initialize crypto lbrary. */
 	if (!nm_utils_init (&error)) {
 		g_warning ("Couldn't initilize nm-utils/crypto system: %d %s",
Index: NetworkManager-0.7.0/libnm-util/nm-setting-8021x.h
===================================================================
--- NetworkManager-0.7.0.orig/libnm-util/nm-setting-8021x.h
+++ NetworkManager-0.7.0/libnm-util/nm-setting-8021x.h
@@ -82,6 +82,10 @@ GQuark nm_setting_802_1x_error_quark (vo
 #define NM_SETTING_802_1X_PIN "pin"
 #define NM_SETTING_802_1X_PSK "psk"
 #define NM_SETTING_802_1X_SYSTEM_CA_CERTS "system-ca-certs"
+#define NM_SETTING_802_1X_PKCS11_ENGINE_PATH "pkcs11-engine-path"
+#define NM_SETTING_802_1X_PKCS11_MODULE_PATH "pkcs11-module-path"
+#define NM_SETTING_802_1X_PKCS11_MODULE_INIT_ARGS "pkcs11-module-init-args"
+#define NM_SETTING_802_1X_PKCS11_SLOT "pkcs11-slot"
 
 #define NM_SETTING_802_1X_CK_FORMAT_ID   "id:"
 #define NM_SETTING_802_1X_CK_FORMAT_FILE "file:"
@@ -185,6 +189,11 @@ gboolean          nm_setting_802_1x_set_
                                                                       GError **err);
 NMSetting8021xCKType nm_setting_802_1x_get_phase2_private_key_type   (NMSetting8021x *setting);
 
+const char *      nm_setting_802_1x_get_pkcs11_engine_path           (NMSetting8021x *setting);
+const char *      nm_setting_802_1x_get_pkcs11_module_path           (NMSetting8021x *setting);
+const char *      nm_setting_802_1x_get_pkcs11_module_init_args      (NMSetting8021x *setting);
+guint             nm_setting_802_1x_get_pkcs11_slot                  (NMSetting8021x *setting);
+
 G_END_DECLS
 
 #endif /* NM_SETTING_8021X_H */
Index: NetworkManager-0.7.0/src/supplicant-manager/nm-supplicant-config.c
===================================================================
--- NetworkManager-0.7.0.orig/src/supplicant-manager/nm-supplicant-config.c
+++ NetworkManager-0.7.0/src/supplicant-manager/nm-supplicant-config.c
@@ -53,6 +53,9 @@ typedef struct
 	GHashTable *blobs;
 	guint32    ap_scan;
 	gboolean   dispose_has_run;
+	char       *pkcs11_engine_path;
+	char       *pkcs11_module_path;
+	char       *pkcs11_module_init_args;
 } NMSupplicantConfigPrivate;
 
 NMSupplicantConfig *
@@ -88,6 +91,8 @@ nm_supplicant_config_init (NMSupplicantC
 	                                     (GDestroyNotify) blob_free);
 
 	priv->ap_scan = 1;
+	priv->pkcs11_engine_path = g_strdup ("/usr/lib/engines/engine_pkcs11.so");
+
 	priv->dispose_has_run = FALSE;
 }
 
@@ -224,9 +229,14 @@ nm_info ("Config: added '%s' value '%s'"
 static void
 nm_supplicant_config_finalize (GObject *object)
 {
+	NMSupplicantConfigPrivate *priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (object);
+
 	/* Complete object destruction */
-	g_hash_table_destroy (NM_SUPPLICANT_CONFIG_GET_PRIVATE (object)->config);
-	g_hash_table_destroy (NM_SUPPLICANT_CONFIG_GET_PRIVATE (object)->blobs);
+	g_hash_table_destroy (priv->config);
+	g_hash_table_destroy (priv->blobs);
+	g_free (priv->pkcs11_engine_path);
+	g_free (priv->pkcs11_module_path);
+	g_free (priv->pkcs11_module_init_args);
 
 	/* Chain up to the parent class */
 	G_OBJECT_CLASS (nm_supplicant_config_parent_class)->finalize (object);
@@ -261,6 +271,69 @@ nm_supplicant_config_set_ap_scan (NMSupp
 	NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->ap_scan = ap_scan;
 }
 
+const char *
+nm_supplicant_config_get_pkcs11_engine_path (NMSupplicantConfig * self)
+{
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), NULL);
+
+	return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->pkcs11_engine_path;
+}
+
+void
+nm_supplicant_config_set_pkcs11_engine_path (NMSupplicantConfig * self,
+                                             const char *pkcs11_engine_path)
+{
+	NMSupplicantConfigPrivate *priv;
+
+	g_return_if_fail (NM_IS_SUPPLICANT_CONFIG (self));
+
+	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
+	g_free (priv->pkcs11_engine_path);
+	priv->pkcs11_engine_path = g_strdup (pkcs11_engine_path);
+}
+
+const char *
+nm_supplicant_config_get_pkcs11_module_path (NMSupplicantConfig * self)
+{
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), NULL);
+
+	return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->pkcs11_module_path;
+}
+
+void
+nm_supplicant_config_set_pkcs11_module_path (NMSupplicantConfig * self,
+                                             const char *pkcs11_module_path)
+{
+	NMSupplicantConfigPrivate *priv;
+
+	g_return_if_fail (NM_IS_SUPPLICANT_CONFIG (self));
+
+	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
+	g_free (priv->pkcs11_module_path);
+	priv->pkcs11_module_path = g_strdup (pkcs11_module_path);
+}
+
+const char *
+nm_supplicant_config_get_pkcs11_module_init_args (NMSupplicantConfig * self)
+{
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), NULL);
+
+	return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->pkcs11_module_init_args;
+}
+
+void
+nm_supplicant_config_set_pkcs11_module_init_args (NMSupplicantConfig * self,
+                                                  const char *pkcs11_module_init_args)
+{
+	NMSupplicantConfigPrivate *priv;
+
+	g_return_if_fail (NM_IS_SUPPLICANT_CONFIG (self));
+
+	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
+	g_free (priv->pkcs11_module_init_args);
+	priv->pkcs11_module_init_args = g_strdup (pkcs11_module_init_args);
+}
+
 static void
 get_hash_cb (gpointer key, gpointer value, gpointer user_data)
 {
@@ -569,7 +642,7 @@ add_certificates (NMSupplicantConfig *se
 	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;
+	use_system_ca = nm_setting_802_1x_get_system_ca_certs (setting);
 
 	if (use_system_ca) {
 		ADD_STRING_VAL (SYSTEM_CA_PATH, "ca_path", FALSE, FALSE, FALSE);
@@ -736,6 +809,8 @@ nm_supplicant_config_add_setting_8021x (
 	char *value, *tmp;
 	gboolean success;
 	GString *phase1, *phase2;
+	const char *pkcs11_engine_path;
+	const char *pkcs11_module_path;
 
 	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
 	g_return_val_if_fail (setting != NULL, FALSE);
@@ -796,6 +871,19 @@ nm_supplicant_config_add_setting_8021x (
 
 	add_certificates (self, setting, connection_uid);
 
+	pkcs11_engine_path = nm_setting_802_1x_get_pkcs11_engine_path (setting);
+	pkcs11_module_path = nm_setting_802_1x_get_pkcs11_module_path (setting);
+
+	if (pkcs11_engine_path && pkcs11_module_path) {
+		nm_supplicant_config_set_pkcs11_engine_path (self, pkcs11_engine_path);
+		nm_supplicant_config_set_pkcs11_module_path (self, pkcs11_module_path);
+		nm_supplicant_config_set_pkcs11_module_init_args (self,
+														  nm_setting_802_1x_get_pkcs11_module_init_args (setting));
+
+		ADD_STRING_VAL ("1", "engine", FALSE, FALSE, FALSE);
+		ADD_STRING_VAL ("pkcs11", "engine_id", FALSE, FALSE, FALSE);
+	}
+
 	return TRUE;
 }
 
Index: NetworkManager-0.7.0/src/supplicant-manager/nm-supplicant-config.h
===================================================================
--- NetworkManager-0.7.0.orig/src/supplicant-manager/nm-supplicant-config.h
+++ NetworkManager-0.7.0/src/supplicant-manager/nm-supplicant-config.h
@@ -57,6 +57,21 @@ guint32 nm_supplicant_config_get_ap_scan
 void nm_supplicant_config_set_ap_scan (NMSupplicantConfig * self,
                                        guint32 ap_scan);
 
+const char *nm_supplicant_config_get_pkcs11_engine_path (NMSupplicantConfig * self);
+
+void nm_supplicant_config_set_pkcs11_engine_path (NMSupplicantConfig * self,
+                                                  const char *pkcs11_engine_path);
+
+const char *nm_supplicant_config_get_pkcs11_module_path (NMSupplicantConfig * self);
+
+void nm_supplicant_config_set_pkcs11_module_path (NMSupplicantConfig * self,
+                                                  const char *pkcs11_module_path);
+
+const char *nm_supplicant_config_get_pkcs11_module_init_args (NMSupplicantConfig * self);
+
+void nm_supplicant_config_set_pkcs11_module_init_args (NMSupplicantConfig * self,
+													   const char *pkcs11_module_init_args);
+
 gboolean nm_supplicant_config_add_option (NMSupplicantConfig *self,
                                           const char * key,
                                           const char * value,
Index: NetworkManager-0.7.0/src/supplicant-manager/nm-supplicant-interface.c
===================================================================
--- NetworkManager-0.7.0.orig/src/supplicant-manager/nm-supplicant-interface.c
+++ NetworkManager-0.7.0/src/supplicant-manager/nm-supplicant-interface.c
@@ -1038,7 +1038,7 @@ byte_array_to_gvalue (const GByteArray *
 }
 
 static void
-blob_free (GValue *val)
+gvalue_free (GValue *val)
 {
 	g_value_unset (val);
 	g_slice_free (GValue, val);
@@ -1062,7 +1062,7 @@ call_set_blobs (NMSupplicantInfo *info,
 
 	blobs = g_hash_table_new_full (g_str_hash, g_str_equal,
 	                               (GDestroyNotify) g_free,
-	                               (GDestroyNotify) blob_free);
+	                               (GDestroyNotify) gvalue_free);
 	if (!blobs) {
 		const char *msg = "Not enough memory to create blob table.";
 		nm_warning ("%s", msg);
@@ -1157,13 +1157,15 @@ nm_supplicant_interface_set_config (NMSu
 	NMSupplicantInfo *info;
 	DBusGProxyCall *call;
 	guint32 ap_scan;
+	const char *pkcs11_engine_path;
+	const char *pkcs11_module_path;
 
 	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
 
 	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
 
 	nm_supplicant_interface_disconnect (self);
-	
+
 	if (priv->cfg)
 		g_object_unref (priv->cfg);
 	priv->cfg = cfg;
@@ -1182,6 +1184,40 @@ nm_supplicant_interface_set_config (NMSu
 									G_TYPE_INVALID);
 	nm_supplicant_info_set_call (info, call);
 
+	if (!call)
+		return FALSE;
+
+	pkcs11_engine_path = nm_supplicant_config_get_pkcs11_engine_path (priv->cfg);
+	pkcs11_module_path = nm_supplicant_config_get_pkcs11_module_path (priv->cfg);
+
+	if (pkcs11_engine_path && pkcs11_module_path) {
+		GHashTable *pkcs11_config_hash;
+		GValue *val;
+
+		pkcs11_config_hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gvalue_free);
+
+		val = g_slice_new0 (GValue);
+		g_value_init (val, G_TYPE_STRING);
+		g_value_set_string (val, pkcs11_engine_path);
+		g_hash_table_insert (pkcs11_config_hash, "pkcs11_engine_path", val);
+
+		val = g_slice_new0 (GValue);
+		g_value_init (val, G_TYPE_STRING);
+		g_value_set_string (val, pkcs11_module_path);
+		g_hash_table_insert (pkcs11_config_hash, "pkcs11_module_path", val);
+
+		val = g_slice_new0 (GValue);
+		g_value_init (val, G_TYPE_STRING);
+		g_value_set_string (val, nm_supplicant_config_get_pkcs11_module_init_args (priv->cfg));
+		g_hash_table_insert (pkcs11_config_hash, "pkcs11_module_init_args", val);
+
+		dbus_g_proxy_call_no_reply (priv->iface_proxy, "setSmartcardModules",
+									DBUS_TYPE_G_MAP_OF_VARIANT,
+									pkcs11_config_hash,
+									G_TYPE_INVALID);
+		g_hash_table_destroy (pkcs11_config_hash);
+	}
+
 	return call != NULL;
 }
 
