]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
vici: Add support to load certificates from tokens
authorTobias Brunner <tobias@strongswan.org>
Wed, 30 Nov 2016 11:44:51 +0000 (12:44 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 16 Feb 2017 18:24:08 +0000 (19:24 +0100)
src/libcharon/plugins/vici/vici_config.c
src/swanctl/swanctl.opt

index 3b27bf7c347565164e670b9782aa2ae8dfc0cf5c..0a8fc29056af1d1b366d9bec2fad5b758699010e 100644 (file)
@@ -246,6 +246,26 @@ typedef struct {
        vici_message_t *reply;
 } request_data_t;
 
+/**
+ * Certificate data
+ */
+typedef struct {
+       request_data_t *request;
+       char *handle;
+       uint32_t slot;
+       char *module;
+} cert_data_t;
+
+/**
+ * Clean up certificate data
+ */
+static void free_cert_data(cert_data_t *data)
+{
+       free(data->handle);
+       free(data->module);
+       free(data);
+}
+
 /**
  * Auth config data
  */
@@ -1161,27 +1181,36 @@ CALLBACK(parse_cert_policy, bool,
 }
 
 /**
- * Parse a certificate; add as auth rule to config
+ * Add a certificate as auth rule to config
  */
-static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
+static bool add_cert(auth_data_t *auth, auth_rule_t rule, certificate_t *cert)
 {
        vici_authority_t *authority;
        vici_cred_t *cred;
+
+       if (rule == AUTH_RULE_SUBJECT_CERT)
+       {
+               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;
+}
+
+/**
+ * Parse a certificate; add as auth rule to config
+ */
+static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
+{
        certificate_t *cert;
 
        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                                                          BUILD_BLOB_PEM, v, BUILD_END);
        if (cert)
        {
-               if (rule == AUTH_RULE_SUBJECT_CERT)
-               {
-                       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;
+               return add_cert(auth, rule, cert);
        }
        return FALSE;
 }
@@ -1366,6 +1395,19 @@ CALLBACK(parse_hosts, bool,
        return TRUE;
 }
 
+CALLBACK(cert_kv, bool,
+       cert_data_t *cert, vici_message_t *message, char *name, chunk_t value)
+{
+       parse_rule_t rules[] = {
+               { "handle",                     parse_string,           &cert->handle                           },
+               { "slot",                       parse_uint32,           &cert->slot                                     },
+               { "module",                     parse_string,           &cert->module                           },
+       };
+
+       return parse_rules(rules, countof(rules), name, value,
+                                          &cert->request->reply);
+}
+
 CALLBACK(child_li, bool,
        child_data_t *child, vici_message_t *message, char *name, chunk_t value)
 {
@@ -1492,6 +1534,67 @@ CALLBACK(peer_kv, bool,
                                           &peer->request->reply);
 }
 
+CALLBACK(auth_sn, bool,
+       auth_data_t *auth, vici_message_t *message, vici_parse_context_t *ctx,
+       char *name)
+{
+       if (strcasepfx(name, "cert") ||
+               strcasepfx(name, "cacert"))
+       {
+               cert_data_t *data;
+               auth_rule_t rule;
+               certificate_t *cert;
+               chunk_t handle;
+
+               INIT(data,
+                       .request = auth->request,
+                       .slot = -1,
+               );
+
+               if (!message->parse(message, ctx, NULL, cert_kv, NULL, data))
+               {
+                       free_cert_data(data);
+                       return FALSE;
+               }
+               if  (!data->handle)
+               {
+                       auth->request->reply = create_reply("CKA_ID missing: %s", name);
+                       free_cert_data(data);
+                       return FALSE;
+               }
+
+               handle = chunk_from_hex(chunk_from_str(data->handle), NULL);
+               if (data->slot != -1)
+               {
+                       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
+               {
+                       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);
+               free_cert_data(data);
+               if (!cert)
+               {
+                       auth->request->reply = create_reply("unable to load certificate: "
+                                                                                               "%s", name);
+                       return FALSE;
+               }
+               rule = strcasepfx(name, "cert") ? AUTH_RULE_SUBJECT_CERT
+                                                                               : AUTH_RULE_CA_CERT;
+               return add_cert(auth, rule, cert);
+       }
+       auth->request->reply = create_reply("invalid section: %s", name);
+       return FALSE;
+}
+
 /**
  * Check and update lifetimes
  */
@@ -1654,7 +1757,7 @@ CALLBACK(peer_sn, bool,
                        .cfg = auth_cfg_create(),
                );
 
-               if (!message->parse(message, ctx, NULL, auth_kv, auth_li, auth))
+               if (!message->parse(message, ctx, auth_sn, auth_kv, auth_li, auth))
                {
                        free_auth_data(auth);
                        return FALSE;
index caae41e88715adac8630e2ccb0060cdaa4d33089..0bf1243d0ccac82003290e36aee83c97ac73da8c 100644 (file)
@@ -292,6 +292,22 @@ connections.<conn>.local<suffix>.certs =
        certificate request payloads. If no appropriate CA can be located, the
        first certificate is used.
 
+connections.<conn>.local<suffix>.cert<suffix> =
+       Section for a certificate candidate to use for authentication.
+
+       Section for a certificate candidate to use for authentication. Certificates
+       in _certs_ are transmitted as binary blobs, these sections offer more
+       flexibility.
+
+connections.<conn>.local<suffix>.cert<suffix>.handle =
+       Hex-encoded CKA_ID of the certificate on a token.
+
+connections.<conn>.local<suffix>.cert<suffix>.slot =
+       Optional slot number of the token that stores the certificate.
+
+connections.<conn>.local<suffix>.cert<suffix>.module =
+       Optional PKCS#11 module name.
+
 connections.<conn>.local<suffix>.pubkeys =
        Comma separated list of raw public key candidates to use for authentication.
 
@@ -419,6 +435,22 @@ connections.<conn>.remote<suffix>.certs =
        The certificates may use a relative path from the **swanctl** _x509_
        directory or an absolute path.
 
+connections.<conn>.remote<suffix>.cert<suffix> =
+       Section for a certificate to accept for authentication.
+
+       Section for a certificate to accept for authentication. Certificates
+       in _certs_ are transmitted as binary blobs, these sections offer more
+       flexibility.
+
+connections.<conn>.remote<suffix>.cert<suffix>.handle =
+       Hex-encoded CKA_ID of the certificate on a token.
+
+connections.<conn>.remote<suffix>.cert<suffix>.slot =
+       Optional slot number of the token that stores the certificate.
+
+connections.<conn>.remote<suffix>.cert<suffix>.module =
+       Optional PKCS#11 module name.
+
 connections.<conn>.remote<suffix>.cacerts =
        Comma separated list of CA certificates to accept for authentication.
 
@@ -426,6 +458,22 @@ connections.<conn>.remote<suffix>.cacerts =
        The certificates may use a relative path from the **swanctl** _x509ca_
        directory or an absolute path.
 
+connections.<conn>.remote<suffix>.cacert<suffix> =
+       Section for a CA certificate to accept for authentication.
+
+       Section for a CA certificate to accept for authentication. Certificates
+       in _cacerts_ are transmitted as binary blobs, these sections offer more
+       flexibility.
+
+connections.<conn>.remote<suffix>.cacert<suffix>.handle =
+       Hex-encoded CKA_ID of the CA certificate on a token.
+
+connections.<conn>.remote<suffix>.cacert<suffix>.slot =
+       Optional slot number of the token that stores the CA certificate.
+
+connections.<conn>.remote<suffix>.cacert<suffix>.module =
+       Optional PKCS#11 module name.
+
 connections.<conn>.remote<suffix>.pubkeys =
        Comma separated list of raw public keys to accept for authentication.