]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
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 f51670de4bfafa5a2aed5996c81ee05bfa05ebd1..552128397666129582b5252251a1b3f9068b5132 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 52e4a92045534f85cc12fd2fc12c063bda6c0530..b0615df5ba3bb486601b58166c713096207aa75d 100644 (file)
@@ -48,6 +48,8 @@
 #include <collections/array.h>
 #include <collections/linked_list.h>
 
+#include <pubkey_cert.h>
+
 #include <stdio.h>
 
 /**
@@ -97,6 +99,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
         */
@@ -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;
        }
@@ -1092,6 +1102,27 @@ CALLBACK(parse_cacerts, bool,
        return parse_cert(auth, AUTH_RULE_CA_CERT, v);
 }
 
+/**
+ * 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
  */
@@ -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 c3245bf5ca47d35c7cf23a08c0a0b8da4396813f..0c237e7dedf14a4e8a7367b04408a2fcc320f783 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 fa3158fa9a2de699c68a2a2ed55995a1043c2aa1..3411b7d6cc51dc433a999e445e4b85584e8883c2 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 53ed8cdfb61ffc7347de6016b57f7c009b6960a2..ed7c743c7ade1a7d2cf19b1cb7a4794ecadcab87 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 b7ba5ad431dda6aeeefa720294a24fcfe76f2694..0631a68575e1e6669d598437b78bbebb06eea870 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 a2d73534290b006e91e367038df5629c1981dcb8..06e4e0fa348bc9ec85747daedbfb21ea494e1672 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 6ee8b8785bda3a728be37619ffcdbe92fcb4386e..bbc700d5cd8b5823f747d8ea3001478e157c2e72 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 591204ef884990b9dda903460792ddf3691c0164..5f8a1867b8bffddabf3d2315f470c098f552f927 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