summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/nm/nm_service.c
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2010-11-28 11:42:20 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2010-11-28 11:42:20 +0000
commitf73fba54dc8b30c6482e1e8abf15bbf455592fcd (patch)
treea449515607c5e51a5c703d7a9b1149c9e4a11560 /src/libcharon/plugins/nm/nm_service.c
parentb8064f4099997a9e2179f3ad4ace605f5ccac3a1 (diff)
downloadvyos-strongswan-f73fba54dc8b30c6482e1e8abf15bbf455592fcd.tar.gz
vyos-strongswan-f73fba54dc8b30c6482e1e8abf15bbf455592fcd.zip
[svn-upgrade] new version strongswan (4.5.0)
Diffstat (limited to 'src/libcharon/plugins/nm/nm_service.c')
-rw-r--r--src/libcharon/plugins/nm/nm_service.c108
1 files changed, 91 insertions, 17 deletions
diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c
index 07318bbbf..72c5bbbb5 100644
--- a/src/libcharon/plugins/nm/nm_service.c
+++ b/src/libcharon/plugins/nm/nm_service.c
@@ -204,6 +204,59 @@ static bool ike_rekey(listener_t *listener, ike_sa_t *old, ike_sa_t *new)
}
/**
+ * Find a certificate for which we have a private key on a smartcard
+ */
+static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv,
+ char *pin)
+{
+ enumerator_t *enumerator, *sans;
+ identification_t *id = NULL;
+ certificate_t *cert;
+ x509_t *x509;
+ private_key_t *key;
+ chunk_t keyid;
+
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ CERT_X509, KEY_ANY, NULL, FALSE);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ x509 = (x509_t*)cert;
+
+ /* there might be a lot of certificates, filter them by usage */
+ if ((x509->get_flags(x509) & X509_CLIENT_AUTH) &&
+ !(x509->get_flags(x509) & X509_CA))
+ {
+ keyid = x509->get_subjectKeyIdentifier(x509);
+ if (keyid.ptr)
+ {
+ /* try to find a private key by the certificate keyid */
+ priv->creds->set_pin(priv->creds, keyid, pin);
+ key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
+ KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_END);
+ if (key)
+ {
+ /* prefer a more convenient subjectAltName */
+ sans = x509->create_subjectAltName_enumerator(x509);
+ if (!sans->enumerate(sans, &id))
+ {
+ id = cert->get_subject(cert);
+ }
+ id = id->clone(id);
+ sans->destroy(sans);
+
+ DBG1(DBG_CFG, "using smartcard certificate '%Y'", id);
+ priv->creds->set_cert_and_key(priv->creds,
+ cert->get_ref(cert), key);
+ break;
+ }
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ return id;
+}
+
+/**
* Connect function called from NM via DBUS
*/
static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
@@ -224,7 +277,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
auth_class_t auth_class = AUTH_CLASS_EAP;
certificate_t *cert = NULL;
x509_t *x509;
- bool agent = FALSE;
+ bool agent = FALSE, smartcard = FALSE;
lifetime_cfg_t lifetime = {
.time = {
.life = 10800 /* 3h */,
@@ -279,6 +332,11 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
{
auth_class = AUTH_CLASS_PUBKEY;
}
+ else if (streq(str, "smartcard"))
+ {
+ auth_class = AUTH_CLASS_PUBKEY;
+ smartcard = TRUE;
+ }
}
/**
@@ -338,9 +396,26 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
if (auth_class == AUTH_CLASS_PUBKEY)
{
+ if (smartcard)
+ {
+ char *pin;
+
+ pin = (char*)nm_setting_vpn_get_secret(vpn, "password");
+ if (pin)
+ {
+ user = find_smartcard_key(priv, pin);
+ }
+ if (!user)
+ {
+ g_set_error(err, NM_VPN_PLUGIN_ERROR,
+ NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
+ "no usable smartcard certificate found.");
+ gateway->destroy(gateway);
+ return FALSE;
+ }
+ }
/* ... or certificate/private key authenitcation */
- str = nm_setting_vpn_get_data_item(vpn, "usercert");
- if (str)
+ else if ((str = nm_setting_vpn_get_data_item(vpn, "usercert")))
{
public_key_t *public;
private_key_t *private = NULL;
@@ -380,16 +455,15 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
str = nm_setting_vpn_get_data_item(vpn, "userkey");
if (!agent && str)
{
- chunk_t secret;
+ char *secret;
- secret.ptr = (char*)nm_setting_vpn_get_secret(vpn, "password");
- if (secret.ptr)
+ secret = (char*)nm_setting_vpn_get_secret(vpn, "password");
+ if (secret)
{
- secret.len = strlen(secret.ptr);
+ priv->creds->set_key_password(priv->creds, secret);
}
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
- KEY_RSA, BUILD_FROM_FILE, str,
- BUILD_PASSPHRASE, secret, BUILD_END);
+ KEY_RSA, BUILD_FROM_FILE, str, BUILD_END);
if (!private)
{
g_set_error(err, NM_VPN_PLUGIN_ERROR,
@@ -524,17 +598,10 @@ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
if (path)
{
private_key_t *key;
- chunk_t secret;
- secret.ptr = (char*)nm_setting_vpn_get_secret(settings, "password");
- if (secret.ptr)
- {
- secret.len = strlen(secret.ptr);
- }
/* try to load/decrypt the private key */
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
- KEY_RSA, BUILD_FROM_FILE, path,
- BUILD_PASSPHRASE, secret, BUILD_END);
+ KEY_RSA, BUILD_FROM_FILE, path, BUILD_END);
if (key)
{
key->destroy(key);
@@ -542,6 +609,13 @@ static gboolean need_secrets(NMVPNPlugin *plugin, NMConnection *connection,
}
}
}
+ else if streq(method, "smartcard")
+ {
+ if (nm_setting_vpn_get_secret(settings, "password"))
+ {
+ return FALSE;
+ }
+ }
}
*setting_name = NM_SETTING_VPN_SETTING_NAME;
return TRUE;