about summary refs log tree commit diff
path: root/libnm-core/nm-setting-macsec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-setting-macsec.c')
-rw-r--r--libnm-core/nm-setting-macsec.c159
1 files changed, 97 insertions, 62 deletions
diff --git a/libnm-core/nm-setting-macsec.c b/libnm-core/nm-setting-macsec.c
index 2c7cff23..3d93ac5a 100644
--- a/libnm-core/nm-setting-macsec.c
+++ b/libnm-core/nm-setting-macsec.c
@@ -25,6 +25,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "nm-utils/nm-secret-utils.h"
+
 #include "nm-utils.h"
 #include "nm-core-types-internal.h"
 #include "nm-setting-connection.h"
@@ -40,9 +42,19 @@
  * necessary for connection to MACsec (IEEE 802.1AE) interfaces.
  **/
 
-G_DEFINE_TYPE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING)
+/*****************************************************************************/
 
-#define NM_SETTING_MACSEC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACSEC, NMSettingMacsecPrivate))
+NM_GOBJECT_PROPERTIES_DEFINE_BASE (
+	PROP_PARENT,
+	PROP_MODE,
+	PROP_ENCRYPT,
+	PROP_MKA_CAK,
+	PROP_MKA_CAK_FLAGS,
+	PROP_MKA_CKN,
+	PROP_PORT,
+	PROP_VALIDATION,
+	PROP_SEND_SCI,
+);
 
 typedef struct {
 	char *parent;
@@ -56,32 +68,11 @@ typedef struct {
 	NMSettingMacsecValidation validation;
 } NMSettingMacsecPrivate;
 
-NM_GOBJECT_PROPERTIES_DEFINE_BASE (
-	PROP_PARENT,
-	PROP_MODE,
-	PROP_ENCRYPT,
-	PROP_MKA_CAK,
-	PROP_MKA_CAK_FLAGS,
-	PROP_MKA_CKN,
-	PROP_PORT,
-	PROP_VALIDATION,
-	PROP_SEND_SCI,
-);
+G_DEFINE_TYPE (NMSettingMacsec, nm_setting_macsec, NM_TYPE_SETTING)
 
-/**
- * nm_setting_macsec_new:
- *
- * Creates a new #NMSettingMacsec object with default values.
- *
- * Returns: (transfer full): the new empty #NMSettingMacsec object
- *
- * Since: 1.6
- **/
-NMSetting *
-nm_setting_macsec_new (void)
-{
-	return (NMSetting *) g_object_new (NM_TYPE_SETTING_MACSEC, NULL);
-}
+#define NM_SETTING_MACSEC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_MACSEC, NMSettingMacsecPrivate))
+
+/*****************************************************************************/
 
 /**
  * nm_setting_macsec_get_parent:
@@ -243,6 +234,12 @@ verify_macsec_key (const char *key, gboolean cak, GError **error)
 {
 	int req_len;
 
+	/* CAK is a connection secret and can be NULL for various
+	 * reasons (agent-owned, no permissions to get secrets, etc.)
+	 */
+	if (cak && !key)
+		return TRUE;
+
 	if (!key || !key[0]) {
 		g_set_error_literal (error,
 		                     NM_CONNECTION_ERROR,
@@ -254,7 +251,7 @@ verify_macsec_key (const char *key, gboolean cak, GError **error)
 	req_len = cak ?
 	    NM_SETTING_MACSEC_MKA_CAK_LENGTH :
 	    NM_SETTING_MACSEC_MKA_CKN_LENGTH;
-	if (strlen (key) != req_len) {
+	if (strlen (key) != (gsize) req_len) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -340,6 +337,10 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 			g_prefix_error (error, "%s.%s: ", NM_SETTING_MACSEC_SETTING_NAME, NM_SETTING_MACSEC_MKA_CKN);
 			return FALSE;
 		}
+		if (!verify_macsec_key (priv->mka_cak, TRUE, error)) {
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_MACSEC_SETTING_NAME, NM_SETTING_MACSEC_MKA_CAK);
+			return FALSE;
+		}
 	} else if (priv->mode == NM_SETTING_MACSEC_MODE_EAP) {
 		if (!s_8021x) {
 			g_set_error (error,
@@ -350,6 +351,13 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 			g_prefix_error (error, "%s: ", NM_SETTING_MACSEC_SETTING_NAME);
 			return FALSE;
 		}
+	} else {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("must be either psk (0) or eap (1)"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_MACSEC_SETTING_NAME, NM_SETTING_MACSEC_MODE);
+		return FALSE;
 	}
 
 	if (priv->port <= 0 || priv->port > 65534) {
@@ -362,51 +370,56 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
+	if (   priv->mode != NM_SETTING_MACSEC_MODE_PSK
+	    && (priv->mka_cak || priv->mka_ckn)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("only valid for psk mode"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_MACSEC_SETTING_NAME,
+		                priv->mka_cak ? NM_SETTING_MACSEC_MKA_CAK : NM_SETTING_MACSEC_MKA_CKN);
+		return NM_SETTING_VERIFY_NORMALIZABLE;
+	}
+
 	return TRUE;
 }
 
-static void
-nm_setting_macsec_init (NMSettingMacsec *setting)
-{
-}
+/*****************************************************************************/
 
 static void
-set_property (GObject *object, guint prop_id,
-              const GValue *value, GParamSpec *pspec)
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
 {
 	NMSettingMacsec *setting = NM_SETTING_MACSEC (object);
 	NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE (setting);
 
 	switch (prop_id) {
 	case PROP_PARENT:
-		g_free (priv->parent);
-		priv->parent = g_value_dup_string (value);
+		g_value_set_string (value, priv->parent);
 		break;
 	case PROP_MODE:
-		priv->mode = g_value_get_int (value);
+		g_value_set_int (value, priv->mode);
 		break;
 	case PROP_ENCRYPT:
-		priv->encrypt = g_value_get_boolean (value);
+		g_value_set_boolean (value, priv->encrypt);
 		break;
 	case PROP_MKA_CAK:
-		g_free (priv->mka_cak);
-		priv->mka_cak = g_value_dup_string (value);
+		g_value_set_string (value, priv->mka_cak);
 		break;
 	case PROP_MKA_CAK_FLAGS:
-		priv->mka_cak_flags = g_value_get_flags (value);
+		g_value_set_flags (value, priv->mka_cak_flags);
 		break;
 	case PROP_MKA_CKN:
-		g_free (priv->mka_ckn);
-		priv->mka_ckn = g_value_dup_string (value);
+		g_value_set_string (value, priv->mka_ckn);
 		break;
 	case PROP_PORT:
-		priv->port = g_value_get_int (value);
+		g_value_set_int (value, priv->port);
 		break;
 	case PROP_VALIDATION:
-		priv->validation = g_value_get_int (value);
+		g_value_set_int (value, priv->validation);
 		break;
 	case PROP_SEND_SCI:
-		priv->send_sci = g_value_get_boolean (value);
+		g_value_set_boolean (value, priv->send_sci);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -415,39 +428,42 @@ set_property (GObject *object, guint prop_id,
 }
 
 static void
-get_property (GObject *object, guint prop_id,
-              GValue *value, GParamSpec *pspec)
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
 {
 	NMSettingMacsec *setting = NM_SETTING_MACSEC (object);
 	NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE (setting);
 
 	switch (prop_id) {
 	case PROP_PARENT:
-		g_value_set_string (value, priv->parent);
+		g_free (priv->parent);
+		priv->parent = g_value_dup_string (value);
 		break;
 	case PROP_MODE:
-		g_value_set_int (value, priv->mode);
+		priv->mode = g_value_get_int (value);
 		break;
 	case PROP_ENCRYPT:
-		g_value_set_boolean (value, priv->encrypt);
+		priv->encrypt = g_value_get_boolean (value);
 		break;
 	case PROP_MKA_CAK:
-		g_value_set_string (value, priv->mka_cak);
+		nm_free_secret (priv->mka_cak);
+		priv->mka_cak = g_value_dup_string (value);
 		break;
 	case PROP_MKA_CAK_FLAGS:
-		g_value_set_flags (value, priv->mka_cak_flags);
+		priv->mka_cak_flags = g_value_get_flags (value);
 		break;
 	case PROP_MKA_CKN:
-		g_value_set_string (value, priv->mka_ckn);
+		g_free (priv->mka_ckn);
+		priv->mka_ckn = g_value_dup_string (value);
 		break;
 	case PROP_PORT:
-		g_value_set_int (value, priv->port);
+		priv->port = g_value_get_int (value);
 		break;
 	case PROP_VALIDATION:
-		g_value_set_int (value, priv->validation);
+		priv->validation = g_value_get_int (value);
 		break;
 	case PROP_SEND_SCI:
-		g_value_set_boolean (value, priv->send_sci);
+		priv->send_sci = g_value_get_boolean (value);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -455,6 +471,28 @@ get_property (GObject *object, guint prop_id,
 	}
 }
 
+/*****************************************************************************/
+
+static void
+nm_setting_macsec_init (NMSettingMacsec *setting)
+{
+}
+
+/**
+ * nm_setting_macsec_new:
+ *
+ * Creates a new #NMSettingMacsec object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingMacsec object
+ *
+ * Since: 1.6
+ **/
+NMSetting *
+nm_setting_macsec_new (void)
+{
+	return (NMSetting *) g_object_new (NM_TYPE_SETTING_MACSEC, NULL);
+}
+
 static void
 finalize (GObject *object)
 {
@@ -462,10 +500,7 @@ finalize (GObject *object)
 	NMSettingMacsecPrivate *priv = NM_SETTING_MACSEC_GET_PRIVATE (setting);
 
 	g_free (priv->parent);
-	if (priv->mka_cak) {
-		memset (priv->mka_cak, 0, strlen (priv->mka_cak));
-		g_free (priv->mka_cak);
-	}
+	nm_free_secret (priv->mka_cak);
 	g_free (priv->mka_ckn);
 
 	G_OBJECT_CLASS (nm_setting_macsec_parent_class)->finalize (object);
@@ -479,8 +514,8 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *klass)
 
 	g_type_class_add_private (klass, sizeof (NMSettingMacsecPrivate));
 
-	object_class->set_property = set_property;
 	object_class->get_property = get_property;
+	object_class->set_property = set_property;
 	object_class->finalize     = finalize;
 
 	setting_class->verify       = verify;