NetworkManager/libnm-util/nm-setting-8021x.c
Dan Williams f30fba23ee 2008-11-21 Dan Williams <dcbw@redhat.com>
Patch from Tambet Ingo  <tambet@gmail.com>

	* configure.in
	  libnm-util/libnm-util.ver
	  libnm-util/nm-setting-8021x.c
	  libnm-util/nm-setting-8021x.h
		- Add configure-time option for the system CA path
		- Add 'system-ca-certs' option to 802.1x setting, which directs
			NetworkManager to use system CA certificates instead of any
			connection-defined CA certificates

	* src/supplicant-manager/nm-supplicant-config.c
	  src/supplicant-manager/nm-supplicant-settings-verify.c
		- Use system CA certificates if the connection says to do so



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4326 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-11-21 18:59:37 +00:00

1525 lines
46 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* Dan Williams <dcbw@redhat.com>
* Tambet Ingo <tambet@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2007 - 2008 Red Hat, Inc.
* (C) Copyright 2007 - 2008 Novell, Inc.
*/
#include <string.h>
#include <ctype.h>
#include <dbus/dbus-glib.h>
#include "nm-setting-8021x.h"
#include "nm-param-spec-specialized.h"
#include "nm-utils.h"
#include "nm-dbus-glib-types.h"
#include "crypto.h"
#include "nm-utils-private.h"
GQuark
nm_setting_802_1x_error_quark (void)
{
static GQuark quark;
if (G_UNLIKELY (!quark))
quark = g_quark_from_static_string ("nm-setting-802-1x-error-quark");
return quark;
}
/* This should really be standard. */
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
GType
nm_setting_802_1x_error_get_type (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] = {
/* Unknown error. */
ENUM_ENTRY (NM_SETTING_802_1X_ERROR_UNKNOWN, "UnknownError"),
/* The specified property was invalid. */
ENUM_ENTRY (NM_SETTING_802_1X_ERROR_INVALID_PROPERTY, "InvalidProperty"),
/* The specified property was missing and is required. */
ENUM_ENTRY (NM_SETTING_802_1X_ERROR_MISSING_PROPERTY, "MissingProperty"),
{ 0, 0, 0 }
};
etype = g_enum_register_static ("NMSetting8021xError", values);
}
return etype;
}
G_DEFINE_TYPE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING)
#define NM_SETTING_802_1X_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_802_1X, NMSetting8021xPrivate))
typedef struct {
GSList *eap; /* GSList of strings */
char *identity;
char *anonymous_identity;
GByteArray *ca_cert;
char *ca_path;
GByteArray *client_cert;
char *phase1_peapver;
char *phase1_peaplabel;
char *phase1_fast_provisioning;
char *phase2_auth;
char *phase2_autheap;
GByteArray *phase2_ca_cert;
char *phase2_ca_path;
GByteArray *phase2_client_cert;
char *password;
char *pin;
char *psk;
GByteArray *private_key;
char *private_key_password;
GByteArray *phase2_private_key;
char *phase2_private_key_password;
gboolean system_ca_certs;
} NMSetting8021xPrivate;
enum {
PROP_0,
PROP_EAP,
PROP_IDENTITY,
PROP_ANONYMOUS_IDENTITY,
PROP_CA_CERT,
PROP_CA_PATH,
PROP_CLIENT_CERT,
PROP_PHASE1_PEAPVER,
PROP_PHASE1_PEAPLABEL,
PROP_PHASE1_FAST_PROVISIONING,
PROP_PHASE2_AUTH,
PROP_PHASE2_AUTHEAP,
PROP_PHASE2_CA_CERT,
PROP_PHASE2_CA_PATH,
PROP_PHASE2_CLIENT_CERT,
PROP_PASSWORD,
PROP_PRIVATE_KEY,
PROP_PRIVATE_KEY_PASSWORD,
PROP_PHASE2_PRIVATE_KEY,
PROP_PHASE2_PRIVATE_KEY_PASSWORD,
PROP_PIN,
PROP_PSK,
PROP_SYSTEM_CA_CERTS,
LAST_PROP
};
NMSetting *
nm_setting_802_1x_new (void)
{
return (NMSetting *) g_object_new (NM_TYPE_SETTING_802_1X, NULL);
}
guint32
nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0);
return g_slist_length (NM_SETTING_802_1X_GET_PRIVATE (setting)->eap);
}
const char *
nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i)
{
NMSetting8021xPrivate *priv;
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
g_return_val_if_fail (i <= g_slist_length (priv->eap), NULL);
return (const char *) g_slist_nth_data (priv->eap, i);
}
gboolean
nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap)
{
NMSetting8021xPrivate *priv;
GSList *iter;
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
g_return_val_if_fail (eap != NULL, FALSE);
priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
for (iter = priv->eap; iter; iter = g_slist_next (iter)) {
if (!strcmp (eap, (char *) iter->data))
return FALSE;
}
priv->eap = g_slist_append (priv->eap, g_ascii_strdown (eap, -1));
return TRUE;
}
void
nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i)
{
NMSetting8021xPrivate *priv;
GSList *elt;
g_return_if_fail (NM_IS_SETTING_802_1X (setting));
priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
elt = g_slist_nth (priv->eap, i);
g_return_if_fail (elt != NULL);
g_free (elt->data);
priv->eap = g_slist_delete_link (priv->eap, elt);
}
void
nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting)
{
NMSetting8021xPrivate *priv;
g_return_if_fail (NM_IS_SETTING_802_1X (setting));
priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
nm_utils_slist_free (priv->eap, g_free);
priv->eap = NULL;
}
const char *
nm_setting_802_1x_get_identity (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->identity;
}
const char *
nm_setting_802_1x_get_anonymous_identity (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->anonymous_identity;
}
const GByteArray *
nm_setting_802_1x_get_ca_cert (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_cert;
}
const char *
nm_setting_802_1x_get_ca_path (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_path;
}
gboolean
nm_setting_802_1x_set_ca_cert_from_file (NMSetting8021x *self,
const char *filename,
NMSetting8021xCKType *out_ck_type,
GError **err)
{
NMSetting8021xPrivate *priv;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
if (out_ck_type)
g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE);
priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (priv->ca_cert)
g_byte_array_free (priv->ca_cert, TRUE);
priv->ca_cert = crypto_load_and_verify_certificate (filename, &format, err);
if (priv->ca_cert) {
/* wpa_supplicant can only use raw x509 CA certs */
switch (format) {
case NM_CRYPTO_FILE_FORMAT_X509:
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_X509;
break;
default:
g_byte_array_free (priv->ca_cert, TRUE);
priv->ca_cert = NULL;
g_set_error (err,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_CA_CERT);
break;
}
}
return priv->ca_cert != NULL;
}
gboolean
nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->system_ca_certs;
}
const GByteArray *
nm_setting_802_1x_get_client_cert (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->client_cert;
}
gboolean
nm_setting_802_1x_set_client_cert_from_file (NMSetting8021x *self,
const char *filename,
NMSetting8021xCKType *out_ck_type,
GError **err)
{
NMSetting8021xPrivate *priv;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
if (out_ck_type)
g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE);
priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (priv->client_cert)
g_byte_array_free (priv->client_cert, TRUE);
priv->client_cert = crypto_load_and_verify_certificate (filename, &format, err);
if (priv->client_cert) {
switch (format) {
case NM_CRYPTO_FILE_FORMAT_X509:
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_X509;
break;
case NM_CRYPTO_FILE_FORMAT_PKCS12:
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12;
break;
default:
g_byte_array_free (priv->client_cert, TRUE);
priv->client_cert = NULL;
g_set_error (err,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_CLIENT_CERT);
break;
}
}
return priv->client_cert != NULL;
}
const char *
nm_setting_802_1x_get_phase1_peapver (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peapver;
}
const char *
nm_setting_802_1x_get_phase1_peaplabel (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peaplabel;
}
const char *
nm_setting_802_1x_get_phase1_fast_provisioning (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_fast_provisioning;
}
const char *
nm_setting_802_1x_get_phase2_auth (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_auth;
}
const char *
nm_setting_802_1x_get_phase2_autheap (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_autheap;
}
const GByteArray *
nm_setting_802_1x_get_phase2_ca_cert (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_cert;
}
const char *
nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_path;
}
gboolean
nm_setting_802_1x_set_phase2_ca_cert_from_file (NMSetting8021x *self,
const char *filename,
NMSetting8021xCKType *out_ck_type,
GError **err)
{
NMSetting8021xPrivate *priv;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
if (out_ck_type)
g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE);
priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (priv->phase2_ca_cert)
g_byte_array_free (priv->phase2_ca_cert, TRUE);
priv->phase2_ca_cert = crypto_load_and_verify_certificate (filename, &format, err);
if (priv->phase2_ca_cert) {
/* wpa_supplicant can only use X509 CA certs */
switch (format) {
case NM_CRYPTO_FILE_FORMAT_X509:
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_X509;
break;
default:
g_byte_array_free (priv->phase2_ca_cert, TRUE);
priv->phase2_ca_cert = NULL;
g_set_error (err,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE2_CA_CERT);
break;
}
}
return priv->phase2_ca_cert != NULL;
}
const GByteArray *
nm_setting_802_1x_get_phase2_client_cert (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_client_cert;
}
gboolean
nm_setting_802_1x_set_phase2_client_cert_from_file (NMSetting8021x *self,
const char *filename,
NMSetting8021xCKType *out_ck_type,
GError **err)
{
NMSetting8021xPrivate *priv;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
if (out_ck_type)
g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE);
priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (priv->phase2_client_cert)
g_byte_array_free (priv->phase2_client_cert, TRUE);
priv->phase2_client_cert = crypto_load_and_verify_certificate (filename, &format, err);
if (priv->phase2_client_cert) {
/* Only X509 client certs should be used; not pkcs#12 */
switch (format) {
case NM_CRYPTO_FILE_FORMAT_X509:
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_X509;
break;
case NM_CRYPTO_FILE_FORMAT_PKCS12:
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12;
break;
default:
g_byte_array_free (priv->phase2_client_cert, TRUE);
priv->phase2_client_cert = NULL;
g_set_error (err,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_CLIENT_CERT);
break;
}
}
return priv->phase2_client_cert != NULL;
}
const char *
nm_setting_802_1x_get_password (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->password;
}
const char *
nm_setting_802_1x_get_pin (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->pin;
}
const char *
nm_setting_802_1x_get_psk (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->psk;
}
const GByteArray *
nm_setting_802_1x_get_private_key (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key;
}
const char *
nm_setting_802_1x_get_private_key_password (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key_password;
}
gboolean
nm_setting_802_1x_set_private_key_from_file (NMSetting8021x *self,
const char *filename,
const char *password,
NMSetting8021xCKType *out_ck_type,
GError **err)
{
NMSetting8021xPrivate *priv;
NMCryptoKeyType ignore = NM_CRYPTO_KEY_TYPE_UNKNOWN;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
if (out_ck_type)
g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE);
priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (priv->private_key) {
/* Try not to leave the decrypted private key around in memory */
memset (priv->private_key, 0, priv->private_key->len);
g_byte_array_free (priv->private_key, TRUE);
}
g_free (priv->private_key_password);
priv->private_key_password = NULL;
priv->private_key = crypto_get_private_key (filename, password, &ignore, &format, err);
if (priv->private_key) {
switch (format) {
case NM_CRYPTO_FILE_FORMAT_RAW_KEY:
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_RAW_KEY;
break;
case NM_CRYPTO_FILE_FORMAT_PKCS12:
// FIXME: use secure memory
priv->private_key_password = g_strdup (password);
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12;
break;
default:
g_assert_not_reached ();
break;
}
/* As required by NM, set the client-cert property to the same PKCS#12 data */
if (priv->client_cert)
g_byte_array_free (priv->client_cert, TRUE);
priv->client_cert = g_byte_array_sized_new (priv->private_key->len);
g_byte_array_append (priv->client_cert, priv->private_key->data, priv->private_key->len);
} else {
/* As a special case for private keys, even if the decrypt fails,
* return the key's file type.
*/
if (out_ck_type && crypto_is_pkcs12_file (filename))
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12;
}
return priv->private_key != NULL;
}
NMSetting8021xCKType
nm_setting_802_1x_get_private_key_type (NMSetting8021x *setting)
{
NMSetting8021xPrivate *priv;
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_TYPE_UNKNOWN);
priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
if (!priv->private_key)
return NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
if (crypto_is_pkcs12_data (priv->private_key))
return NM_SETTING_802_1X_CK_TYPE_PKCS12;
return NM_SETTING_802_1X_CK_TYPE_X509;
}
const GByteArray *
nm_setting_802_1x_get_phase2_private_key (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key;
}
const char *
nm_setting_802_1x_get_phase2_private_key_password (NMSetting8021x *setting)
{
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key_password;
}
gboolean
nm_setting_802_1x_set_phase2_private_key_from_file (NMSetting8021x *self,
const char *filename,
const char *password,
NMSetting8021xCKType *out_ck_type,
GError **err)
{
NMSetting8021xPrivate *priv;
NMCryptoKeyType ignore = NM_CRYPTO_KEY_TYPE_UNKNOWN;
NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
g_return_val_if_fail (NM_IS_SETTING_802_1X (self), FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
if (out_ck_type)
g_return_val_if_fail (*out_ck_type == NM_SETTING_802_1X_CK_TYPE_UNKNOWN, FALSE);
priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (priv->phase2_private_key) {
/* Try not to leave the decrypted private key around in memory */
memset (priv->phase2_private_key, 0, priv->phase2_private_key->len);
g_byte_array_free (priv->phase2_private_key, TRUE);
}
g_free (priv->phase2_private_key_password);
priv->phase2_private_key_password = NULL;
priv->phase2_private_key = crypto_get_private_key (filename, password, &ignore, &format, err);
if (priv->phase2_private_key) {
switch (format) {
case NM_CRYPTO_FILE_FORMAT_RAW_KEY:
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_RAW_KEY;
break;
case NM_CRYPTO_FILE_FORMAT_PKCS12:
// FIXME: use secure memory
priv->phase2_private_key_password = g_strdup (password);
if (out_ck_type)
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12;
break;
default:
g_assert_not_reached ();
break;
}
/* As required by NM, set the client-cert property to the same PKCS#12 data */
if (priv->phase2_client_cert)
g_byte_array_free (priv->phase2_client_cert, TRUE);
priv->phase2_client_cert = g_byte_array_sized_new (priv->phase2_private_key->len);
g_byte_array_append (priv->phase2_client_cert, priv->phase2_private_key->data, priv->phase2_private_key->len);
} else {
/* As a special case for private keys, even if the decrypt fails,
* return the key's file type.
*/
if (out_ck_type && crypto_is_pkcs12_file (filename))
*out_ck_type = NM_SETTING_802_1X_CK_TYPE_PKCS12;
}
return priv->phase2_private_key != NULL;
}
NMSetting8021xCKType
nm_setting_802_1x_get_phase2_private_key_type (NMSetting8021x *setting)
{
NMSetting8021xPrivate *priv;
g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_802_1X_CK_TYPE_UNKNOWN);
priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
if (!priv->phase2_private_key)
return NM_SETTING_802_1X_CK_TYPE_UNKNOWN;
if (crypto_is_pkcs12_data (priv->phase2_private_key))
return NM_SETTING_802_1X_CK_TYPE_PKCS12;
return NM_SETTING_802_1X_CK_TYPE_X509;
}
static void
need_secrets_password (NMSetting8021x *self,
GPtrArray *secrets,
gboolean phase2)
{
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (!priv->password || !strlen (priv->password))
g_ptr_array_add (secrets, NM_SETTING_802_1X_PASSWORD);
}
static void
need_secrets_sim (NMSetting8021x *self,
GPtrArray *secrets,
gboolean phase2)
{
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (!priv->pin || !strlen (priv->pin))
g_ptr_array_add (secrets, NM_SETTING_802_1X_PIN);
}
static gboolean
need_private_key_password (GByteArray *key, const char *password)
{
GError *error = NULL;
gboolean needed = TRUE;
/* 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.
*/
if (!crypto_is_pkcs12_data (key))
return FALSE;
if (crypto_verify_pkcs12 (key, password, &error))
return FALSE; /* pkcs#12 validation successful */
/* If the error was a decryption error then a password is needed */
if (!error || g_error_matches (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERR_CIPHER_DECRYPT_FAILED))
needed = TRUE;
g_clear_error (&error);
return needed;
}
static void
need_secrets_tls (NMSetting8021x *self,
GPtrArray *secrets,
gboolean phase2)
{
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (phase2) {
if (!priv->phase2_private_key || !priv->phase2_private_key->len)
g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
else if (need_private_key_password (priv->phase2_private_key, priv->phase2_private_key_password))
g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
} else {
if (!priv->private_key || !priv->private_key->len)
g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY);
else if (need_private_key_password (priv->private_key, priv->private_key_password))
g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
}
}
static gboolean
verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
{
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (phase2) {
if (!priv->phase2_client_cert) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
return FALSE;
} else if (!priv->phase2_client_cert->len) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
return FALSE;
}
/* If the private key is PKCS#12, check that it matches the client cert */
if (priv->phase2_private_key && crypto_is_pkcs12_data (priv->phase2_private_key)) {
if (priv->phase2_private_key->len != priv->phase2_client_cert->len) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
return FALSE;
}
if (memcmp (priv->phase2_private_key->data,
priv->phase2_client_cert->data,
priv->phase2_private_key->len)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
return FALSE;
}
}
} else {
if (!priv->client_cert) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
NM_SETTING_802_1X_CLIENT_CERT);
return FALSE;
} else if (!priv->client_cert->len) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_CLIENT_CERT);
return FALSE;
}
/* If the private key is PKCS#12, check that it matches the client cert */
if (priv->private_key && crypto_is_pkcs12_data (priv->private_key)) {
if (priv->private_key->len != priv->client_cert->len) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_CLIENT_CERT);
return FALSE;
}
if (memcmp (priv->private_key->data,
priv->client_cert->data,
priv->private_key->len)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_CLIENT_CERT);
return FALSE;
}
}
}
return TRUE;
}
static gboolean
verify_ttls (NMSetting8021x *self, gboolean phase2, GError **error)
{
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if ( (!priv->identity || !strlen (priv->identity))
&& (!priv->anonymous_identity || !strlen (priv->anonymous_identity))) {
if (!priv->identity) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
NM_SETTING_802_1X_IDENTITY);
} else if (!strlen (priv->identity)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_IDENTITY);
} else if (!priv->anonymous_identity) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
} else {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
}
return FALSE;
}
if ( (!priv->phase2_auth || !strlen (priv->phase2_auth))
&& (!priv->phase2_autheap || !strlen (priv->phase2_autheap))) {
if (!priv->phase2_auth) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
NM_SETTING_802_1X_PHASE2_AUTH);
} else if (!strlen (priv->phase2_auth)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE2_AUTH);
} else if (!priv->phase2_autheap) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
NM_SETTING_802_1X_PHASE2_AUTHEAP);
} else {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE2_AUTHEAP);
}
return FALSE;
}
return TRUE;
}
static gboolean
verify_identity (NMSetting8021x *self, gboolean phase2, GError **error)
{
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
if (!priv->identity) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
NM_SETTING_802_1X_IDENTITY);
} else if (!strlen (priv->identity)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_IDENTITY);
}
return TRUE;
}
/* Implemented below... */
static void need_secrets_phase2 (NMSetting8021x *self,
GPtrArray *secrets,
gboolean phase2);
typedef void (*EAPMethodNeedSecretsFunc) (NMSetting8021x *self,
GPtrArray *secrets,
gboolean phase2);
typedef gboolean (*EAPMethodValidateFunc)(NMSetting8021x *self,
gboolean phase2,
GError **error);
typedef struct {
const char *method;
EAPMethodNeedSecretsFunc ns_func;
EAPMethodValidateFunc v_func;
} EAPMethodsTable;
static EAPMethodsTable eap_methods_table[] = {
{ "leap", need_secrets_password, verify_identity },
{ "md5", need_secrets_password, verify_identity },
{ "pap", need_secrets_password, verify_identity },
{ "chap", need_secrets_password, verify_identity },
{ "mschap", need_secrets_password, verify_identity },
{ "mschapv2", need_secrets_password, verify_identity },
{ "fast", need_secrets_password, verify_identity },
{ "tls", need_secrets_tls, verify_tls },
{ "peap", need_secrets_phase2, verify_ttls },
{ "ttls", need_secrets_phase2, verify_ttls },
{ "sim", need_secrets_sim, NULL },
{ "gtc", NULL, NULL }, // FIXME: implement
{ "otp", NULL, NULL }, // FIXME: implement
{ NULL, NULL, NULL }
};
static void
need_secrets_phase2 (NMSetting8021x *self,
GPtrArray *secrets,
gboolean phase2)
{
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
char *method = NULL;
int i;
g_return_if_fail (phase2 == FALSE);
/* Check phase2_auth and phase2_autheap */
method = priv->phase2_auth;
if (!method && priv->phase2_autheap)
method = priv->phase2_autheap;
if (!method) {
g_warning ("Couldn't find EAP method.");
g_assert_not_reached();
return;
}
/* Ask the configured phase2 method if it needs secrets */
for (i = 0; eap_methods_table[i].method; i++) {
if (eap_methods_table[i].ns_func == NULL)
continue;
if (strcmp (eap_methods_table[i].method, method)) {
(*eap_methods_table[i].ns_func) (self, secrets, TRUE);
break;
}
}
}
static GPtrArray *
need_secrets (NMSetting *setting)
{
NMSetting8021x *self = NM_SETTING_802_1X (setting);
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
GSList *iter;
GPtrArray *secrets;
gboolean eap_method_found = FALSE;
secrets = g_ptr_array_sized_new (4);
/* Ask each configured EAP method if it needs secrets */
for (iter = priv->eap; iter && !eap_method_found; iter = g_slist_next (iter)) {
const char *method = (const char *) iter->data;
int i;
for (i = 0; eap_methods_table[i].method; i++) {
if (eap_methods_table[i].ns_func == NULL)
continue;
if (!strcmp (eap_methods_table[i].method, method)) {
(*eap_methods_table[i].ns_func) (self, secrets, FALSE);
/* Only break out of the outer loop if this EAP method
* needed secrets.
*/
if (secrets->len > 0)
eap_method_found = TRUE;
break;
}
}
}
if (secrets->len == 0) {
g_ptr_array_free (secrets, TRUE);
secrets = NULL;
}
return secrets;
}
static gboolean
verify (NMSetting *setting, GSList *all_settings, GError **error)
{
NMSetting8021x *self = NM_SETTING_802_1X (setting);
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
const char *valid_eap[] = { "leap", "md5", "tls", "peap", "ttls", "sim", "fast", NULL };
const char *valid_phase1_peapver[] = { "0", "1", NULL };
const char *valid_phase1_peaplabel[] = { "0", "1", NULL };
const char *valid_phase2_auth[] = { "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", "tls", NULL };
const char *valid_phase2_autheap[] = { "md5", "mschapv2", "otp", "gtc", "tls", NULL };
GSList *iter;
if (error)
g_return_val_if_fail (*error == NULL, FALSE);
if (!priv->eap) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_MISSING_PROPERTY,
NM_SETTING_802_1X_EAP);
return FALSE;
}
if (!_nm_utils_string_slist_validate (priv->eap, valid_eap)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_EAP);
return FALSE;
}
/* Ask each configured EAP method if its valid */
for (iter = priv->eap; iter; iter = g_slist_next (iter)) {
const char *method = (const char *) iter->data;
int i;
for (i = 0; eap_methods_table[i].method; i++) {
if (eap_methods_table[i].v_func == NULL)
continue;
if (!strcmp (eap_methods_table[i].method, method)) {
if (!(*eap_methods_table[i].v_func) (self, FALSE, error))
return FALSE;
break;
}
}
}
if (priv->phase1_peapver && !_nm_utils_string_in_list (priv->phase1_peapver, valid_phase1_peapver)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE1_PEAPVER);
return FALSE;
}
if (priv->phase1_peaplabel && !_nm_utils_string_in_list (priv->phase1_peaplabel, valid_phase1_peaplabel)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE1_PEAPLABEL);
return FALSE;
}
if (priv->phase1_fast_provisioning && strcmp (priv->phase1_fast_provisioning, "1")) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING);
return FALSE;
}
if (priv->phase2_auth && !_nm_utils_string_in_list (priv->phase2_auth, valid_phase2_auth)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE2_AUTH);
return FALSE;
}
if (priv->phase2_autheap && !_nm_utils_string_in_list (priv->phase2_autheap, valid_phase2_autheap)) {
g_set_error (error,
NM_SETTING_802_1X_ERROR,
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
NM_SETTING_802_1X_PHASE2_AUTHEAP);
return FALSE;
}
/* FIXME: finish */
return TRUE;
}
static void
nm_setting_802_1x_init (NMSetting8021x *setting)
{
g_object_set (setting, NM_SETTING_NAME, NM_SETTING_802_1X_SETTING_NAME, NULL);
}
static void
finalize (GObject *object)
{
NMSetting8021x *self = NM_SETTING_802_1X (object);
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
/* Strings first. g_free() already checks for NULLs so we don't have to */
g_free (priv->identity);
g_free (priv->anonymous_identity);
g_free (priv->ca_path);
g_free (priv->phase1_peapver);
g_free (priv->phase1_peaplabel);
g_free (priv->phase1_fast_provisioning);
g_free (priv->phase2_auth);
g_free (priv->phase2_autheap);
g_free (priv->phase2_ca_path);
g_free (priv->password);
nm_utils_slist_free (priv->eap, g_free);
if (priv->ca_cert)
g_byte_array_free (priv->ca_cert, TRUE);
if (priv->client_cert)
g_byte_array_free (priv->client_cert, TRUE);
if (priv->private_key)
g_byte_array_free (priv->private_key, TRUE);
g_free (priv->private_key_password);
if (priv->phase2_ca_cert)
g_byte_array_free (priv->phase2_ca_cert, TRUE);
if (priv->phase2_client_cert)
g_byte_array_free (priv->phase2_client_cert, TRUE);
if (priv->phase2_private_key)
g_byte_array_free (priv->phase2_private_key, TRUE);
g_free (priv->phase2_private_key_password);
G_OBJECT_CLASS (nm_setting_802_1x_parent_class)->finalize (object);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMSetting8021x *setting = NM_SETTING_802_1X (object);
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
switch (prop_id) {
case PROP_EAP:
nm_utils_slist_free (priv->eap, g_free);
priv->eap = g_value_dup_boxed (value);
break;
case PROP_IDENTITY:
g_free (priv->identity);
priv->identity = g_value_dup_string (value);
break;
case PROP_ANONYMOUS_IDENTITY:
g_free (priv->anonymous_identity);
priv->anonymous_identity = g_value_dup_string (value);
break;
case PROP_CA_CERT:
if (priv->ca_cert)
g_byte_array_free (priv->ca_cert, TRUE);
priv->ca_cert = g_value_dup_boxed (value);
break;
case PROP_CA_PATH:
g_free (priv->ca_path);
priv->ca_path = g_value_dup_string (value);
break;
case PROP_CLIENT_CERT:
if (priv->client_cert)
g_byte_array_free (priv->client_cert, TRUE);
priv->client_cert = g_value_dup_boxed (value);
break;
case PROP_PHASE1_PEAPVER:
g_free (priv->phase1_peapver);
priv->phase1_peapver = g_value_dup_string (value);
break;
case PROP_PHASE1_PEAPLABEL:
g_free (priv->phase1_peaplabel);
priv->phase1_peaplabel = g_value_dup_string (value);
break;
case PROP_PHASE1_FAST_PROVISIONING:
g_free (priv->phase1_fast_provisioning);
priv->phase1_fast_provisioning = g_value_dup_string (value);
break;
case PROP_PHASE2_AUTH:
g_free (priv->phase2_auth);
priv->phase2_auth = g_value_dup_string (value);
break;
case PROP_PHASE2_AUTHEAP:
g_free (priv->phase2_autheap);
priv->phase2_autheap = g_value_dup_string (value);
break;
case PROP_PHASE2_CA_CERT:
if (priv->phase2_ca_cert)
g_byte_array_free (priv->phase2_ca_cert, TRUE);
priv->phase2_ca_cert = g_value_dup_boxed (value);
break;
case PROP_PHASE2_CA_PATH:
g_free (priv->phase2_ca_path);
priv->phase2_ca_path = g_value_dup_string (value);
break;
case PROP_PHASE2_CLIENT_CERT:
if (priv->phase2_client_cert)
g_byte_array_free (priv->phase2_client_cert, TRUE);
priv->phase2_client_cert = g_value_dup_boxed (value);
break;
case PROP_PASSWORD:
g_free (priv->password);
priv->password = g_value_dup_string (value);
break;
case PROP_PRIVATE_KEY:
if (priv->private_key)
g_byte_array_free (priv->private_key, TRUE);
priv->private_key = g_value_dup_boxed (value);
break;
case PROP_PRIVATE_KEY_PASSWORD:
g_free (priv->private_key_password);
priv->private_key_password = g_value_dup_string (value);
break;
case PROP_PHASE2_PRIVATE_KEY:
if (priv->phase2_private_key)
g_byte_array_free (priv->phase2_private_key, TRUE);
priv->phase2_private_key = g_value_dup_boxed (value);
break;
case PROP_PHASE2_PRIVATE_KEY_PASSWORD:
g_free (priv->phase2_private_key_password);
priv->phase2_private_key_password = g_value_dup_string (value);
break;
case PROP_SYSTEM_CA_CERTS:
priv->system_ca_certs = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMSetting8021x *setting = NM_SETTING_802_1X (object);
NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
switch (prop_id) {
case PROP_EAP:
g_value_set_boxed (value, priv->eap);
break;
case PROP_IDENTITY:
g_value_set_string (value, priv->identity);
break;
case PROP_ANONYMOUS_IDENTITY:
g_value_set_string (value, priv->anonymous_identity);
break;
case PROP_CA_CERT:
g_value_set_boxed (value, priv->ca_cert);
break;
case PROP_CA_PATH:
g_value_set_string (value, priv->ca_path);
break;
case PROP_CLIENT_CERT:
g_value_set_boxed (value, priv->client_cert);
break;
case PROP_PHASE1_PEAPVER:
g_value_set_string (value, priv->phase1_peapver);
break;
case PROP_PHASE1_PEAPLABEL:
g_value_set_string (value, priv->phase1_peaplabel);
break;
case PROP_PHASE1_FAST_PROVISIONING:
g_value_set_string (value, priv->phase1_fast_provisioning);
break;
case PROP_PHASE2_AUTH:
g_value_set_string (value, priv->phase2_auth);
break;
case PROP_PHASE2_AUTHEAP:
g_value_set_string (value, priv->phase2_autheap);
break;
case PROP_PHASE2_CA_CERT:
g_value_set_boxed (value, priv->phase2_ca_cert);
break;
case PROP_PHASE2_CA_PATH:
g_value_set_string (value, priv->phase2_ca_path);
break;
case PROP_PHASE2_CLIENT_CERT:
g_value_set_boxed (value, priv->phase2_client_cert);
break;
case PROP_PASSWORD:
g_value_set_string (value, priv->password);
break;
case PROP_PRIVATE_KEY:
g_value_set_boxed (value, priv->private_key);
break;
case PROP_PRIVATE_KEY_PASSWORD:
g_value_set_string (value, priv->private_key_password);
break;
case PROP_PHASE2_PRIVATE_KEY:
g_value_set_boxed (value, priv->phase2_private_key);
break;
case PROP_PHASE2_PRIVATE_KEY_PASSWORD:
g_value_set_string (value, priv->phase2_private_key_password);
break;
case PROP_SYSTEM_CA_CERTS:
g_value_set_boolean (value, priv->system_ca_certs);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
GError *error = NULL;
g_type_class_add_private (setting_class, sizeof (NMSetting8021xPrivate));
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->finalize = finalize;
parent_class->verify = verify;
parent_class->need_secrets = need_secrets;
/* Properties */
g_object_class_install_property
(object_class, PROP_EAP,
_nm_param_spec_specialized (NM_SETTING_802_1X_EAP,
"EAP",
"EAP",
DBUS_TYPE_G_LIST_OF_STRING,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_IDENTITY,
g_param_spec_string (NM_SETTING_802_1X_IDENTITY,
"Identity",
"Identity",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_ANONYMOUS_IDENTITY,
g_param_spec_string (NM_SETTING_802_1X_ANONYMOUS_IDENTITY,
"Anonymous identity",
"Anonymous identity",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_CA_CERT,
_nm_param_spec_specialized (NM_SETTING_802_1X_CA_CERT,
"CA certificate",
"CA certificate",
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_CA_PATH,
g_param_spec_string (NM_SETTING_802_1X_CA_PATH,
"CA path",
"CA path",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_CLIENT_CERT,
_nm_param_spec_specialized (NM_SETTING_802_1X_CLIENT_CERT,
"Client certificate",
"Client certificate",
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_PHASE1_PEAPVER,
g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPVER,
"Phase1 PEAPVER",
"Phase1 PEAPVER",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_PHASE1_PEAPLABEL,
g_param_spec_string (NM_SETTING_802_1X_PHASE1_PEAPLABEL,
"Phase1 PEAP label",
"Phase1 PEAP label",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_PHASE1_FAST_PROVISIONING,
g_param_spec_string (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING,
"Phase1 fast provisioning",
"Phase1 fast provisioning",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_PHASE2_AUTH,
g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTH,
"Phase2 auth",
"Phase2 auth",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_PHASE2_AUTHEAP,
g_param_spec_string (NM_SETTING_802_1X_PHASE2_AUTHEAP,
"Phase2 autheap",
"Phase2 autheap",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_PHASE2_CA_CERT,
_nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_CA_CERT,
"Phase2 CA certificate",
"Phase2 CA certificate",
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_PHASE2_CA_PATH,
g_param_spec_string (NM_SETTING_802_1X_PHASE2_CA_PATH,
"Phase2 auth CA path",
"Phase2 auth CA path",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_PHASE2_CLIENT_CERT,
_nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
"Phase2 client certificate",
"Phase2 client certificate",
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
g_object_class_install_property
(object_class, PROP_PASSWORD,
g_param_spec_string (NM_SETTING_802_1X_PASSWORD,
"Password",
"Password",
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",
"Private key",
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
g_object_class_install_property
(object_class, PROP_PRIVATE_KEY_PASSWORD,
g_param_spec_string (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
"Private key password",
"Private key password",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
g_object_class_install_property
(object_class, PROP_PHASE2_PRIVATE_KEY,
_nm_param_spec_specialized (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
"Phase2 private key",
"Phase2 private key",
DBUS_TYPE_G_UCHAR_ARRAY,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
g_object_class_install_property
(object_class, PROP_PHASE2_PRIVATE_KEY_PASSWORD,
g_param_spec_string (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD,
"Phase2 private key password",
"Phase2 private key password",
NULL,
G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
g_object_class_install_property
(object_class, PROP_SYSTEM_CA_CERTS,
g_param_spec_boolean (NM_SETTING_802_1X_SYSTEM_CA_CERTS,
"Use system CA certificates",
"Use system CA certificates",
FALSE,
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",
error->code, error->message);
g_error_free (error);
}
}