vici: Support of raw public keys
authorAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 4 Jan 2016 09:34:21 +0000 (10:34 +0100)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 9 Jan 2016 06:23:29 +0000 (07:23 +0100)
src/libcharon/plugins/vici/Makefile.am
src/libcharon/plugins/vici/vici_config.c
src/libcharon/plugins/vici/vici_config.h
src/libcharon/plugins/vici/vici_cred.c
src/libcharon/plugins/vici/vici_plugin.c
src/libstrongswan/plugins/pubkey/pubkey_cert.c
src/libstrongswan/plugins/pubkey/pubkey_cert.h
src/swanctl/commands/load_conns.c
src/swanctl/swanctl.opt

index f51670d..5521283 100644 (file)
@@ -1,5 +1,6 @@
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/libstrongswan \
+       -I$(top_srcdir)/src/libstrongswan/plugins/pubkey \
        -I$(top_srcdir)/src/libhydra \
        -I$(top_srcdir)/src/libcharon \
        -DIPSEC_PIDDIR=\"${piddir}\"
index 52e4a92..b0615df 100644 (file)
@@ -48,6 +48,8 @@
 #include <collections/array.h>
 #include <collections/linked_list.h>
 
+#include <pubkey_cert.h>
+
 #include <stdio.h>
 
 /**
@@ -98,6 +100,11 @@ struct private_vici_config_t {
        rwlock_t *lock;
 
        /**
+        * Credential backend managed by VICI used for our certificates
+        */
+       vici_cred_t *cred;
+
+       /**
         * Auxiliary certification authority information
         */
        vici_authority_t *authority;
@@ -1057,6 +1064,7 @@ CALLBACK(parse_group, bool,
 static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
 {
        vici_authority_t *authority;
+       vici_cred_t *cred;
        certificate_t *cert;
 
        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
@@ -1068,6 +1076,8 @@ static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
                        authority = auth->request->this->authority;
                        authority->check_for_hash_and_url(authority, cert);
                }
+               cred = auth->request->this->cred;
+               cert = cred->add_cert(cred, cert);
                auth->cfg->add(auth->cfg, rule, cert);
                return TRUE;
        }
@@ -1093,6 +1103,27 @@ CALLBACK(parse_cacerts, bool,
 }
 
 /**
+ * Parse raw public keys
+ */
+CALLBACK(parse_pubkeys, bool,
+       auth_data_t *auth, chunk_t v)
+{
+       vici_cred_t *cred;
+       certificate_t *cert;
+
+       cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY,
+                                                         BUILD_BLOB_PEM, v, BUILD_END);
+       if (cert)
+       {
+               cred = auth->request->this->cred;
+               cert = cred->add_cert(cred, cert);
+               auth->cfg->add(auth->cfg, AUTH_RULE_SUBJECT_CERT, cert);
+               return TRUE;
+       }
+       return FALSE;
+}
+
+/**
  * Parse revocation status
  */
 CALLBACK(parse_revocation, bool,
@@ -1287,6 +1318,7 @@ CALLBACK(auth_li, bool,
                { "groups",                     parse_group,            auth->cfg                                       },
                { "certs",                      parse_certs,            auth                                            },
                { "cacerts",            parse_cacerts,          auth                                            },
+               { "pubkeys",            parse_pubkeys,          auth                                            },
        };
 
        return parse_rules(rules, countof(rules), name, value,
@@ -1510,20 +1542,32 @@ CALLBACK(peer_sn, bool,
                        .request = peer->request,
                        .cfg = auth_cfg_create(),
                };
+               certificate_t *cert;
+               identification_t *id;
 
                if (!message->parse(message, ctx, NULL, auth_kv, auth_li, &auth))
                {
                        auth.cfg->destroy(auth.cfg);
                        return FALSE;
                }
+               cert = auth.cfg->get(auth.cfg, AUTH_RULE_SUBJECT_CERT);
+               id   = auth.cfg->get(auth.cfg, AUTH_RULE_IDENTITY);
 
-               if (!auth.cfg->get(auth.cfg, AUTH_RULE_IDENTITY))
+               if (cert)
                {
-                       identification_t *id;
-                       certificate_t *cert;
+                       if (id)
+                       {
+                               if (cert->get_type(cert) == CERT_TRUSTED_PUBKEY &&
+                                       id->get_type != ID_ANY)
+                               {
+                                       pubkey_cert_t *pubkey_cert;
 
-                       cert = auth.cfg->get(auth.cfg, AUTH_RULE_SUBJECT_CERT);
-                       if (cert)
+                                       /* the id is set for informational purposes, only */
+                                       pubkey_cert = (pubkey_cert_t*)cert;
+                                       pubkey_cert->set_subject(pubkey_cert, id);
+                               }
+                       }
+                       else
                        {
                                id = cert->get_subject(cert);
                                DBG1(DBG_CFG, "  id not specified, defaulting to cert id '%Y'",
@@ -2121,7 +2165,8 @@ METHOD(vici_config_t, destroy, void,
  * See header
  */
 vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
-                                                                 vici_authority_t *authority)
+                                                                 vici_authority_t *authority,
+                                                                 vici_cred_t *cred)
 {
        private_vici_config_t *this;
 
@@ -2138,6 +2183,7 @@ vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
                .conns = linked_list_create(),
                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                .authority = authority,
+               .cred = cred,
        );
 
        manage_commands(this, TRUE);
index c3245bf..0c237e7 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "vici_dispatcher.h"
 #include "vici_authority.h"
+#include "vici_cred.h"
 
 #include <config/backend.h>
 
@@ -51,9 +52,11 @@ struct vici_config_t {
  *
  * @param dispatcher           dispatcher to receive requests from
  * @param authority                    Auxiliary certification authority information
+ * @param cred                         in-memory credential backend managed by VICI
  * @return                                     config backend
  */
 vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
-                                                                 vici_authority_t *authority);
+                                                                 vici_authority_t *authority,
+                                                                 vici_cred_t *cred);
 
 #endif /** VICI_CONFIG_H_ @}*/
index fa3158f..3411b7d 100644 (file)
@@ -308,7 +308,7 @@ static void manage_commands(private_vici_cred_t *this, bool reg)
 METHOD(vici_cred_t, add_cert, certificate_t*,
        private_vici_cred_t *this, certificate_t *cert)
 {
-       return this->creds->get_cert_ref(this->creds, cert);
+       return this->creds->add_cert_ref(this->creds, TRUE, cert);
 }
 
 METHOD(vici_cred_t, destroy, void,
index 53ed8cd..ed7c743 100644 (file)
@@ -131,7 +131,8 @@ static bool register_vici(private_vici_plugin_t *this,
                        this->authority = vici_authority_create(this->dispatcher,
                                                                                                        this->cred);
                        lib->credmgr->add_set(lib->credmgr, &this->authority->set);
-                       this->config = vici_config_create(this->dispatcher, this->authority);
+                       this->config = vici_config_create(this->dispatcher, this->authority,
+                                                                                         this->cred);
                        this->attrs = vici_attribute_create(this->dispatcher);
                        this->logger = vici_logger_create(this->dispatcher);
 
index b7ba5ad..0631a68 100644 (file)
@@ -196,6 +196,13 @@ METHOD(certificate_t, destroy, void,
        }
 }
 
+METHOD(pubkey_cert_t, set_subject, void,
+       private_pubkey_cert_t *this, identification_t *subject)
+{
+       DESTROY_IF(this->subject);
+       this->subject = subject->clone(subject);
+}
+
 /*
  * see header file
  */
@@ -222,6 +229,7 @@ static pubkey_cert_t *pubkey_cert_create(public_key_t *key,
                                .get_ref = _get_ref,
                                .destroy = _destroy,
                        },
+                       .set_subject = _set_subject,
                },
                .ref = 1,
                .key = key,
index a2d7353..06e4e0f 100644 (file)
@@ -35,6 +35,13 @@ struct pubkey_cert_t {
         * Implements certificate_t.
         */
        certificate_t interface;
+
+       /**
+        * Set the subject of the trusted public key.
+        *
+        * @param subject       subject to be set
+        */
+       void (*set_subject)(pubkey_cert_t *this, identification_t *subject);
 };
 
 /**
index 6ee8b87..bbc700d 100644 (file)
@@ -59,6 +59,7 @@ static bool is_file_list_key(char *key)
        char *keys[] = {
                "certs",
                "cacerts",
+               "pubkeys"
        };
        int i;
 
@@ -112,12 +113,18 @@ static bool add_file_list_key(vici_req_t *req, char *key, char *value)
                                                 SWANCTL_X509DIR, DIRECTORY_SEPARATOR, token);
                                token = buf;
                        }
-                       if (streq(key, "cacerts"))
+                       else if (streq(key, "cacerts"))
                        {
                                snprintf(buf, sizeof(buf), "%s%s%s",
                                                 SWANCTL_X509CADIR, DIRECTORY_SEPARATOR, token);
                                token = buf;
                        }
+                       else if (streq(key, "pubkeys"))
+                       {
+                               snprintf(buf, sizeof(buf), "%s%s%s",
+                                                SWANCTL_PUBKEYDIR, DIRECTORY_SEPARATOR, token);
+                               token = buf;
+                       }
                }
 
                map = chunk_map(token, FALSE);
index 591204e..5f8a186 100644 (file)
@@ -273,12 +273,22 @@ connections.<conn>.local<suffix>.certs =
 
        Comma separated list of certificate candidates to use for authentication.
        The certificates may use a relative path from the **swanctl** _x509_
-       directory, or an absolute path.
+       directory or an absolute path.
 
        The certificate used for authentication is selected based on the received
        certificate request payloads. If no appropriate CA can be located, the
        first certificate is used.
 
+connections.<conn>.local<suffix>.pubkeys =
+       Comma separated list of raw public key candidates to use for authentication.
+
+       Comma separated list of raw public key candidates to use for authentication.
+       The public keys may use a relative path from the **swanctl** _pubkey_
+       directory or an absolute path.
+
+       Even though multiple local public keys could be defined in principle, only
+       the     first public key in the list is used for authentication.
+
 connections.<conn>.local<suffix>.auth = pubkey
        Authentication to perform locally (_pubkey_, _psk_, _xauth[-backend]_ or
        _eap[-method]_).
@@ -370,14 +380,21 @@ connections.<conn>.remote<suffix>.certs =
 
        Comma separated list of certificates to accept for authentication.
        The certificates may use a relative path from the **swanctl** _x509_
-       directory, or an absolute path.
+       directory or an absolute path.
 
 connections.<conn>.remote<suffix>.cacerts =
        Comma separated list of CA certificates to accept for authentication.
 
        Comma separated list of CA certificates to accept for authentication.
        The certificates may use a relative path from the **swanctl** _x509ca_
-       directory, or an absolute path.
+       directory or an absolute path.
+
+connections.<conn>.remote<suffix>.pubkeys =
+       Comma separated list of raw public keys to accept for authentication.
+
+       Comma separated list of raw public keys to accept for authentication.
+       The public keys may use a relative path from the **swanctl** _x509_
+       directory or an absolute path.
 
 connections.<conn>.remote<suffix>.revocation = relaxed
        Certificate revocation policy, (_strict_, _ifuri_ or _relaxed_).
@@ -587,8 +604,8 @@ connections.<conn>.children.<child>.mode = tunnel
        Both _transport_ and _beet_ modes are subject to mode negotiation; _tunnel_
        mode is negotiated if the preferred mode is not available.
 
-       _pass_ and _drop_ are used to install shunt policies, which explicitly
-       bypass the defined traffic from IPsec processing, or drop it, respectively.
+       _pass_ and _drop_ are used to install shunt policies which explicitly
+       bypass the defined traffic from IPsec processing or drop it, respectively.
 
 connections.<conn>.children.<child>.policies = yes
        Whether to install IPsec policies or not.
@@ -704,7 +721,7 @@ secrets { # }
 
        It is not recommended to define any private key decryption passphrases,
        as then there is no real security benefit in having encrypted keys. Either
-       store the key unencrypted, or enter the keys manually when loading
+       store the key unencrypted or enter the keys manually when loading
        credentials.
 
 secrets.eap<suffix> { # }
@@ -725,7 +742,7 @@ secrets.eap<suffix>.secret =
        Value of the EAP/XAuth secret.
 
        Value of the EAP/XAuth secret. It may either be an ASCII string, a hex
-       encoded string if it has a _0x_ prefix, or a Base64 encoded string if it
+       encoded string if it has a _0x_ prefix or a Base64 encoded string if it
        has a _0s_ prefix in its value.
 
 secrets.eap<suffix>.id<suffix> =
@@ -745,7 +762,7 @@ secrets.ike<suffix>.secret =
        Value of the IKE preshared secret.
 
        Value of the IKE preshared secret. It may either be an ASCII string,
-       a hex encoded string if it has a _0x_ prefix, or a Base64 encoded string if
+       a hex encoded string if it has a _0x_ prefix or a Base64 encoded string if
        it has a _0s_ prefix in its value.
 
 secrets.ike<suffix>.id<suffix> =
@@ -805,7 +822,7 @@ pools.<name>.addrs =
        Addresses allocated in pool.
 
        Subnet or range defining addresses allocated in pool. Accepts a single CIDR
-       subnet defining the pool to allocate addresses from, or an address range
+       subnet defining the pool to allocate addresses from or an address range
        (<from>-<to>).  Pools must be unique and non-overlapping.
 
 pools.<name>.<attr> =
@@ -828,7 +845,7 @@ authorities.<name>.cacert =
        CA certificate belonging to the certification authority.
 
        The certificates may use a relative path from the **swanctl** _x509ca_
-       directory, or an absolute path.
+       directory or an absolute path.
 
 authorities.<name>.crl_uris =
        Comma-separated list of CRL distribution points