]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
vici: Add support to load CA certificates from tokens and paths in authority sections
authorTobias Brunner <tobias@strongswan.org>
Wed, 30 Nov 2016 14:41:18 +0000 (15:41 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 16 Feb 2017 18:24:08 +0000 (19:24 +0100)
src/libcharon/plugins/vici/vici_authority.c
src/swanctl/commands/load_authorities.c
src/swanctl/swanctl.opt

index 94a7f68f66c755f8dafa8297bbbf512e87d3beab..0fa158b32f0e562aed8dca0f9eec10214ccec4c7 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2016 Tobias Brunner
  * Copyright (C) 2015 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
@@ -199,8 +200,27 @@ typedef struct {
 typedef struct {
        request_data_t *request;
        authority_t *authority;
+       char *handle;
+       uint32_t slot;
+       char *module;
+       char *file;
 } load_data_t;
 
+/**
+ * Clean up data associated with an authority load
+ */
+static void free_load_data(load_data_t *data)
+{
+       if (data->authority)
+       {
+               authority_destroy(data->authority);
+       }
+       free(data->handle);
+       free(data->module);
+       free(data->file);
+       free(data);
+}
+
 /**
  * Parse a string
  */
@@ -216,6 +236,28 @@ CALLBACK(parse_string, bool,
        return TRUE;
 }
 
+/**
+ * Parse a uint32_t
+ */
+CALLBACK(parse_uint32, bool,
+       uint32_t *out, chunk_t v)
+{
+       char buf[16], *end;
+       u_long l;
+
+       if (!vici_stringify(v, buf, sizeof(buf)))
+       {
+               return FALSE;
+       }
+       l = strtoul(buf, &end, 0);
+       if (*end == 0)
+       {
+               *out = l;
+               return TRUE;
+       }
+       return FALSE;
+}
+
 /**
  * Parse list of URIs
  */
@@ -266,8 +308,12 @@ CALLBACK(authority_kv, bool,
        load_data_t *data, vici_message_t *message, char *name, chunk_t value)
 {
        parse_rule_t rules[] = {
-               { "cacert",                     parse_cacert, &data->authority->cert          },
-               { "cert_uri_base",      parse_string, &data->authority->cert_uri_base },
+               { "cacert",                     parse_cacert, &data->authority->cert                    },
+               { "file",                       parse_string, &data->file                                               },
+               { "handle",                     parse_string, &data->handle                                             },
+               { "slot",                       parse_uint32, &data->slot                                               },
+               { "module",                     parse_string, &data->module                                             },
+               { "cert_uri_base",      parse_string, &data->authority->cert_uri_base   },
        };
 
        return parse_rules(rules, countof(rules), name, value,
@@ -341,21 +387,60 @@ CALLBACK(authority_sn, bool,
        linked_list_t *authorities;
        authority_t *authority;
        vici_cred_t *cred;
+       load_data_t *data;
+       chunk_t handle;
 
-       load_data_t data = {
+       INIT(data,
                .request = request,
                .authority = authority_create(name),
-       };
+               .slot = -1,
+       );
 
        DBG2(DBG_CFG, " authority %s:", name);
 
-       if (!message->parse(message, ctx, NULL, authority_kv, authority_li, &data) ||
-               !data.authority->cert)
+       if (!message->parse(message, ctx, NULL, authority_kv, authority_li, data))
+       {
+               free_load_data(data);
+               return FALSE;
+       }
+       if (!data->authority->cert)
+       {
+               if (data->file)
+               {
+                       data->authority->cert = lib->creds->create(lib->creds,
+                                                                               CRED_CERTIFICATE, CERT_X509,
+                                                                               BUILD_FROM_FILE, data->file, BUILD_END);
+               }
+               else if (data->handle)
+               {
+                       handle = chunk_from_hex(chunk_from_str(data->handle), NULL);
+                       if (data->slot != -1)
+                       {
+                               data->authority->cert = lib->creds->create(lib->creds,
+                                                               CRED_CERTIFICATE, CERT_X509,
+                                                               BUILD_PKCS11_KEYID, handle,
+                                                               BUILD_PKCS11_SLOT, data->slot,
+                                                               data->module ? BUILD_PKCS11_MODULE : BUILD_END,
+                                                               data->module, BUILD_END);
+                       }
+                       else
+                       {
+                               data->authority->cert = lib->creds->create(lib->creds,
+                                                               CRED_CERTIFICATE, CERT_X509,
+                                                               BUILD_PKCS11_KEYID, handle,
+                                                               data->module ? BUILD_PKCS11_MODULE : BUILD_END,
+                                                               data->module, BUILD_END);
+                       }
+                       chunk_free(&handle);
+               }
+       }
+       if (!data->authority->cert)
        {
-               authority_destroy(data.authority);
+               request->reply = create_reply("CA certificate missing: %s", name);
+               free_load_data(data);
                return FALSE;
        }
-       log_authority_data(data.authority);
+       log_authority_data(data->authority);
 
        request->this->lock->write_lock(request->this->lock);
 
@@ -372,12 +457,14 @@ CALLBACK(authority_sn, bool,
                }
        }
        enumerator->destroy(enumerator);
-       authorities->insert_last(authorities, data.authority);
+       authorities->insert_last(authorities, data->authority);
 
        cred = request->this->cred;
-       data.authority->cert = cred->add_cert(cred, data.authority->cert);
+       data->authority->cert = cred->add_cert(cred, data->authority->cert);
+       data->authority = NULL;
 
        request->this->lock->unlock(request->this->lock);
+       free_load_data(data);
 
        return TRUE;
 }
index 352a185e8e366286338cd977a7b05357152fa416..8947866f58d1abc24ff6932964934c0f7b6d7f22 100644 (file)
@@ -86,18 +86,18 @@ static bool add_key_values(vici_req_t *req, settings_t *cfg, char *section)
        enumerator = cfg->create_key_value_enumerator(cfg, section);
        while (enumerator->enumerate(enumerator, &key, &value))
        {
-               /* pool subnet is encoded as key/value, all other attributes as list */
                if (streq(key, "cacert"))
                {
                        ret = add_file_key_value(req, key, value);
                }
-               else if (streq(key, "cert_uri_base"))
+               else if (streq(key, "crl_uris") ||
+                                streq(key, "ocsp_uris"))
                {
-                       vici_add_key_valuef(req, key, "%s", value);
+                       add_list_key(req, key, value);
                }
                else
                {
-                       add_list_key(req, key, value);
+                       vici_add_key_valuef(req, key, "%s", value);
                }
                if (!ret)
                {
index f749564ea4d64c3073923cccb66073bd726e48be..7eb0885c857c6e0040e8f243c644240bfd5130fe 100644 (file)
@@ -1054,18 +1054,40 @@ authorities.<name> { # }
 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.
+       CA certificate belonging to the certification authority. The certificates
+       may use a relative path from the **swanctl** _x509ca_ directory or an
+       absolute path.
+
+       Configure one of _cacert_, _file_, or _handle_ per section.
+
+authorities.<name>.file =
+       Absolute path to the certificate to load.
+
+       Absolute path to the certificate to load. Passed as-is to the daemon, so it
+       must be readable by it.
+
+       Configure one of _cacert_, _file_, or _handle_ per section.
+
+authorities.<name>.handle =
+       Hex-encoded CKA_ID of the CA certificate on a token.
+
+       Hex-encoded CKA_ID of the CA certificate on a token.
+
+       Configure one of _cacert_, _file_, or _handle_ per section.
+
+authorities.<name>.slot =
+       Optional slot number of the token that stores the CA certificate.
+
+authorities.<name>.module =
+       Optional PKCS#11 module name.
 
 authorities.<name>.crl_uris =
-       Comma-separated list of CRL distribution points
+       Comma-separated list of CRL distribution points.
 
-       Comma-separated list of CRL distribution points (ldap, http, or file URI)
+       Comma-separated list of CRL distribution points (ldap, http, or file URI).
 
 authorities.<name>.ocsp_uris =
-       Comma-separated list of OCSP URIs
-
-       Comma-separated list of OCSP URIs
+       Comma-separated list of OCSP URIs.
 
 authorities.<name>.cert_uri_base =
        Defines the base URI for the Hash and URL feature supported by IKEv2.