vici: Add support to load certificates from tokens

This commit is contained in:
Tobias Brunner
2017-02-16 19:24:08 +01:00
parent d2e3ff8e0c
commit 00bf6a2a49
2 changed files with 163 additions and 12 deletions
+115 -12
View File
@@ -246,6 +246,26 @@ typedef struct {
vici_message_t *reply; vici_message_t *reply;
} request_data_t; } 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 * Auth config data
*/ */
@@ -1160,28 +1180,37 @@ CALLBACK(parse_cert_policy, bool,
return TRUE; return TRUE;
} }
/**
* Add a certificate as auth rule to config
*/
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 * Parse a certificate; add as auth rule to config
*/ */
static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v) 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; certificate_t *cert;
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_PEM, v, BUILD_END); BUILD_BLOB_PEM, v, BUILD_END);
if (cert) if (cert)
{ {
if (rule == AUTH_RULE_SUBJECT_CERT) return add_cert(auth, rule, 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 FALSE; return FALSE;
} }
@@ -1366,6 +1395,19 @@ CALLBACK(parse_hosts, bool,
return TRUE; 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, CALLBACK(child_li, bool,
child_data_t *child, vici_message_t *message, char *name, chunk_t value) child_data_t *child, vici_message_t *message, char *name, chunk_t value)
{ {
@@ -1492,6 +1534,67 @@ CALLBACK(peer_kv, bool,
&peer->request->reply); &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 * Check and update lifetimes
*/ */
@@ -1654,7 +1757,7 @@ CALLBACK(peer_sn, bool,
.cfg = auth_cfg_create(), .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); free_auth_data(auth);
return FALSE; return FALSE;
+48
View File
@@ -292,6 +292,22 @@ connections.<conn>.local<suffix>.certs =
certificate request payloads. If no appropriate CA can be located, the certificate request payloads. If no appropriate CA can be located, the
first certificate is used. 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 = 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.
@@ -419,6 +435,22 @@ connections.<conn>.remote<suffix>.certs =
The certificates may use a relative path from the **swanctl** _x509_ 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>.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 = 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.
@@ -426,6 +458,22 @@ connections.<conn>.remote<suffix>.cacerts =
The certificates may use a relative path from the **swanctl** _x509ca_ 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>.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 = 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.