aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2015-12-03 11:20:04 +0100
committerAndreas Steffen <andreas.steffen@strongswan.org>2015-12-11 18:26:54 +0100
commitfad851e2d34dd5c9c0f5feec5b93e020b97406f1 (patch)
tree861ee0166866067692aa8eb8dc4735439cc0d134
parent5d909303d80f9016e9cb1701f3ebaeee4c2f6dd1 (diff)
downloadstrongswan-fad851e2d34dd5c9c0f5feec5b93e020b97406f1.tar.bz2
strongswan-fad851e2d34dd5c9c0f5feec5b93e020b97406f1.tar.xz
Use VICI 2.0 protocol version for certificate queries
-rw-r--r--src/libcharon/plugins/vici/Makefile.am2
-rw-r--r--src/libcharon/plugins/vici/vici_cert_info.c50
-rw-r--r--src/libcharon/plugins/vici/vici_cert_info.h64
-rw-r--r--src/libcharon/plugins/vici/vici_query.c95
-rw-r--r--src/swanctl/commands/list_certs.c183
-rw-r--r--src/swanctl/commands/version.c21
-rw-r--r--testing/tests/swanctl/ocsp-multi-level/evaltest.dat10
7 files changed, 288 insertions, 137 deletions
diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am
index f152482a4..9540c2063 100644
--- a/src/libcharon/plugins/vici/Makefile.am
+++ b/src/libcharon/plugins/vici/Makefile.am
@@ -19,6 +19,7 @@ libstrongswan_vici_la_SOURCES = \
vici_message.h vici_message.c \
vici_builder.h vici_builder.c \
vici_dispatcher.h vici_dispatcher.c \
+ vici_cert_info.c vici_cert_info.h \
vici_query.h vici_query.c \
vici_control.h vici_control.c \
vici_config.h vici_config.c \
@@ -40,6 +41,7 @@ libvici_la_SOURCES = \
vici_message.c vici_message.h \
vici_builder.c vici_builder.h \
vici_version.c vici_version.h \
+ vici_cert_info.c vici_cert_info.h \
libvici.c libvici.h
libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
diff --git a/src/libcharon/plugins/vici/vici_cert_info.c b/src/libcharon/plugins/vici/vici_cert_info.c
new file mode 100644
index 000000000..ce079603b
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_cert_info.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "vici_cert_info.h"
+
+static vici_cert_info_t vici_cert_infos[] = {
+ { "any", "", CERT_ANY,
+ X509_NONE },
+ { "x509", "X.509 End Entity Certificate", CERT_X509,
+ X509_NONE },
+ { "x509ca", "X.509 CA Certificate", CERT_X509,
+ X509_CA },
+ { "x509aa", "X.509 AA Certificate", CERT_X509,
+ X509_AA },
+ { "x509ocsp", "X.509 OCSP Signer Certificate", CERT_X509,
+ X509_OCSP_SIGNER },
+ { "x509ac", "X.509 Attribute Certificate", CERT_X509_AC,
+ X509_NONE },
+ { "x509crl", "X.509 CRL", CERT_X509_CRL,
+ X509_NONE },
+ { "ocsp", "OCSP Response", CERT_X509_OCSP_RESPONSE,
+ X509_NONE }
+};
+
+/* See header. */
+vici_cert_info_t* vici_cert_info_retrieve(char *type_str)
+{
+ int i;
+
+ for (i = 0; i < countof(vici_cert_infos); i++)
+ {
+ if (strcaseeq(type_str, vici_cert_infos[i].type_str))
+ {
+ return &vici_cert_infos[i];
+ }
+ }
+ return NULL;
+}
diff --git a/src/libcharon/plugins/vici/vici_cert_info.h b/src/libcharon/plugins/vici/vici_cert_info.h
new file mode 100644
index 000000000..31d4b466f
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_cert_info.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup vici_cert_info vici_cert_info
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_CERT_INFO_H_
+#define VICI_CERT_INFO_H_
+
+typedef struct vici_cert_info_t vici_cert_info_t;
+
+#include <credentials/certificates/certificate.h>
+#include <credentials/certificates/x509.h>
+
+/**
+ * Information on vici certificate types
+ */
+struct vici_cert_info_t {
+
+ /**
+ * Certificate type string used in vici messages
+ */
+ char *type_str;
+
+ /**
+ * Caption describing the certificate type
+ */
+ char *caption;
+
+ /**
+ * Base certificate type
+ */
+ certificate_type_t type;
+
+ /**
+ * X.509 flag
+ */
+ x509_flag_t flag;
+
+};
+
+/**
+ * Retrieve information on a given certificate type
+ *
+ * @param type_str Vici certificate type string
+ * @return Information record or NULL if not found
+ */
+vici_cert_info_t* vici_cert_info_retrieve(char *type_str);
+
+#endif /** VICI_CERT_INFO_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
index bec9d565a..d5d973f6b 100644
--- a/src/libcharon/plugins/vici/vici_query.c
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -41,8 +41,7 @@
#include "vici_query.h"
#include "vici_builder.h"
#include "vici_version.h"
-
-#include <credentials/certificates/x509.h>
+#include "vici_cert_info.h"
#include <inttypes.h>
#include <time.h>
@@ -821,7 +820,7 @@ typedef struct {
*/
static void enum_x509(private_vici_query_t *this, u_int id,
linked_list_t *certs, cert_filter_t *filter,
- x509_flag_t flag)
+ x509_flag_t flag, char *cert_type)
{
enumerator_t *enumerator;
certificate_t *cert;
@@ -830,7 +829,7 @@ static void enum_x509(private_vici_query_t *this, u_int id,
x509_flag_t mask;
x509_t *x509;
- if (filter->type != CERT_ANY && filter->version == VICI_2_0 &&
+ if (filter->type != CERT_ANY && filter->version != VICI_1_0 &&
filter->flag != flag)
{
return;
@@ -849,8 +848,16 @@ static void enum_x509(private_vici_query_t *this, u_int id,
if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
{
b = vici_builder_create();
- b->add_kv(b, "type", "%N",
- certificate_type_names, cert->get_type(cert));
+ if (filter->version == VICI_1_0)
+ {
+ b->add_kv(b, "type", "%N", certificate_type_names,
+ cert->get_type(cert));
+ }
+ else
+ {
+ b->add_kv(b, "vici", "%N", vici_version_names, VICI_VERSION);
+ b->add_kv(b, "type", "%s", cert_type);
+ }
if (has_privkey(cert))
{
b->add_kv(b, "has_privkey", "yes");
@@ -869,7 +876,8 @@ static void enum_x509(private_vici_query_t *this, u_int id,
* Enumerate all non-X.509 certificate types
*/
static void enum_others(private_vici_query_t *this, u_int id,
- linked_list_t *certs, cert_filter_t *filter)
+ linked_list_t *certs, cert_filter_t *filter,
+ char *cert_type)
{
enumerator_t *enumerator;
certificate_t *cert;
@@ -882,8 +890,16 @@ static void enum_others(private_vici_query_t *this, u_int id,
if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
{
b = vici_builder_create();
- b->add_kv(b, "type", "%N",
- certificate_type_names, cert->get_type(cert));
+ if (filter->version == VICI_1_0)
+ {
+ b->add_kv(b, "type", "%N", certificate_type_names,
+ cert->get_type(cert));
+ }
+ else
+ {
+ b->add_kv(b, "vici", "%N", vici_version_names, VICI_VERSION);
+ b->add_kv(b, "type", "%s", cert_type);
+ }
b->add(b, VICI_KEY_VALUE, "data", encoding);
free(encoding.ptr);
@@ -898,7 +914,8 @@ static void enum_others(private_vici_query_t *this, u_int id,
* Enumerate all certificates of a given type
*/
static void enum_certs(private_vici_query_t *this, u_int id,
- cert_filter_t *filter, certificate_type_t type)
+ cert_filter_t *filter, certificate_type_t type,
+ char *cert_type)
{
enumerator_t *e1, *e2;
certificate_t *cert, *current;
@@ -937,14 +954,14 @@ static void enum_certs(private_vici_query_t *this, u_int id,
if (type == CERT_X509)
{
- enum_x509(this, id, certs, filter, X509_NONE);
- enum_x509(this, id, certs, filter, X509_CA);
- enum_x509(this, id, certs, filter, X509_AA);
- enum_x509(this, id, certs, filter, X509_OCSP_SIGNER);
+ enum_x509(this, id, certs, filter, X509_NONE, "x509");
+ enum_x509(this, id, certs, filter, X509_CA, "x509ca");
+ enum_x509(this, id, certs, filter, X509_AA, "x509ac");
+ enum_x509(this, id, certs, filter, X509_OCSP_SIGNER, "x509ocsp");
}
else
{
- enum_others(this, id, certs, filter);
+ enum_others(this, id, certs, filter, cert_type);
}
certs->destroy_offset(certs, offsetof(certificate_t, destroy));
}
@@ -979,40 +996,13 @@ CALLBACK(list_certs, vici_message_t*,
}
else /* VICI 2.0 */
{
- if (strcaseeq(str, "any"))
- {
- filter.type = CERT_ANY;
- }
- else if (strcaseeq(str, "x509"))
- {
- filter.type = CERT_X509;
- }
- else if (strcaseeq(str, "x509ca"))
- {
- filter.type = CERT_X509;
- filter.flag = X509_CA;
- }
- else if (strcaseeq(str, "x509aa"))
- {
- filter.type = CERT_X509;
- filter.flag = X509_AA;
- }
- else if (strcaseeq(str, "x509ocsp"))
- {
- filter.type = CERT_X509;
- filter.flag = X509_OCSP_SIGNER;
- }
- else if (strcaseeq(str, "x509crl"))
- {
- filter.type = CERT_X509_CRL;
- }
- else if (strcaseeq(str, "x509ac"))
- {
- filter.type = CERT_X509_AC;
- }
- else if (strcaseeq(str, "ocsp"))
+ vici_cert_info_t *cert_info;
+
+ cert_info = vici_cert_info_retrieve(str);
+ if (cert_info)
{
- filter.type = CERT_X509_OCSP_RESPONSE;
+ filter.type = cert_info->type;
+ filter.flag = cert_info->flag;
}
else
{
@@ -1026,10 +1016,10 @@ CALLBACK(list_certs, vici_message_t*,
{
filter.subject = identification_create_from_string(str);
}
- enum_certs(this, id, &filter, CERT_X509);
- enum_certs(this, id, &filter, CERT_X509_AC);
- enum_certs(this, id, &filter, CERT_X509_CRL);
- enum_certs(this, id, &filter, CERT_X509_OCSP_RESPONSE);
+ enum_certs(this, id, &filter, CERT_X509, "x509");
+ enum_certs(this, id, &filter, CERT_X509_AC, "x509ac");
+ enum_certs(this, id, &filter, CERT_X509_CRL, "x509crl");
+ enum_certs(this, id, &filter, CERT_X509_OCSP_RESPONSE, "ocsp");
DESTROY_IF(filter.subject);
finalize:
@@ -1146,6 +1136,7 @@ CALLBACK(version, vici_message_t*,
b = vici_builder_create();
+ b->add_kv(b, "vici", "%N", vici_version_names, VICI_VERSION);
b->add_kv(b, "daemon", "%s", lib->ns);
b->add_kv(b, "version", "%s", VERSION);
diff --git a/src/swanctl/commands/list_certs.c b/src/swanctl/commands/list_certs.c
index 167f8d848..bb08649c8 100644
--- a/src/swanctl/commands/list_certs.c
+++ b/src/swanctl/commands/list_certs.c
@@ -29,9 +29,17 @@
#include <credentials/certificates/ac.h>
#include <selectors/traffic_selector.h>
+#include <vici_version.h>
+#include <vici_cert_info.h>
+
#include "command.h"
/**
+ * Current certificate type info
+ */
+static vici_cert_info_t *current_cert_info = NULL;
+
+/**
* Print PEM encoding of a certificate
*/
static void print_pem(certificate_t *cert)
@@ -115,44 +123,43 @@ static void print_x509(x509_t *x509)
enumerator->destroy(enumerator);
flags = x509->get_flags(x509);
- printf("flags: ");
- if (flags & X509_CA)
- {
- printf("CA ");
- }
- if (flags & X509_CRL_SIGN)
- {
- printf("CRLSign ");
- }
- if (flags & X509_AA)
- {
- printf("AA ");
- }
- if (flags & X509_OCSP_SIGNER)
+ if (flags != X509_NONE)
{
- printf("OCSP ");
- }
- if (flags & X509_AA)
- {
- printf("AA ");
- }
- if (flags & X509_SERVER_AUTH)
- {
- printf("serverAuth ");
- }
- if (flags & X509_CLIENT_AUTH)
- {
- printf("clientAuth ");
- }
- if (flags & X509_IKE_INTERMEDIATE)
- {
- printf("iKEIntermediate ");
- }
- if (flags & X509_SELF_SIGNED)
- {
- printf("self-signed ");
+ printf("flags: ");
+ if (flags & X509_CA)
+ {
+ printf("CA ");
+ }
+ if (flags & X509_CRL_SIGN)
+ {
+ printf("CRLSign ");
+ }
+ if (flags & X509_OCSP_SIGNER)
+ {
+ printf("ocspSigning ");
+ }
+ if (flags & X509_SERVER_AUTH)
+ {
+ printf("serverAuth ");
+ }
+ if (flags & X509_CLIENT_AUTH)
+ {
+ printf("clientAuth ");
+ }
+ if (flags & X509_IKE_INTERMEDIATE)
+ {
+ printf("ikeIntermediate ");
+ }
+ if (flags & X509_MS_SMARTCARD_LOGON)
+ {
+ printf("msSmartcardLogon");
+ }
+ if (flags & X509_SELF_SIGNED)
+ {
+ printf("self-signed ");
+ }
+ printf("\n");
}
- printf("\n");
first = TRUE;
enumerator = x509->create_crl_uri_enumerator(x509);
@@ -486,8 +493,8 @@ static void print_cert(certificate_t *cert, bool has_privkey)
now = time(NULL);
- printf("cert: %N\n", certificate_type_names, cert->get_type(cert));
- if (cert->get_type(cert) != CERT_X509_CRL)
+ if (cert->get_type(cert) != CERT_X509_CRL &&
+ cert->get_type(cert) != CERT_X509_OCSP_RESPONSE)
{
printf("subject: \"%Y\"\n", cert->get_subject(cert));
}
@@ -541,49 +548,75 @@ static void print_cert(certificate_t *cert, bool has_privkey)
CALLBACK(list_cb, void,
command_format_options_t *format, char *name, vici_res_t *res)
{
+ certificate_t *cert;
+ vici_version_t version;
+ vici_cert_info_t *cert_info;
+ bool has_privkey, first = FALSE;
+ char *version_str, *type_str;
+ void *buf;
+ int len;
+
if (*format & COMMAND_FORMAT_RAW)
{
vici_dump(res, "list-cert event", *format & COMMAND_FORMAT_PRETTY,
stdout);
+ return;
}
- else
+
+ version_str = vici_find_str(res, "1.0", "vici");
+ if (!enum_from_name(vici_version_names, version_str, &version) ||
+ version == VICI_1_0)
{
- certificate_type_t type;
- certificate_t *cert;
- void *buf;
- int len;
- bool has_privkey;
-
- buf = vici_find(res, &len, "data");
- has_privkey = streq(vici_find_str(res, "no", "has_privkey"), "yes");
- if (enum_from_name(certificate_type_names,
- vici_find_str(res, "ANY", "type"), &type) &&
- type != CERT_ANY && buf)
- {
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, type,
- BUILD_BLOB_ASN1_DER, chunk_create(buf, len),
- BUILD_END);
- if (cert)
- {
- if (*format & COMMAND_FORMAT_PEM)
- {
- print_pem(cert);
- }
- else
- {
- print_cert(cert, has_privkey);
- }
- cert->destroy(cert);
- }
- else
- {
- fprintf(stderr, "parsing certificate failed\n");
- }
+ fprintf(stderr, "unsupported vici version '%s'\n", version_str);
+ return;
+ }
+
+ buf = vici_find(res, &len, "data");
+ if (!buf)
+ {
+ fprintf(stderr, "received incomplete certificate data\n");
+ return;
+ }
+ has_privkey = streq(vici_find_str(res, "no", "has_privkey"), "yes");
+
+ type_str = vici_find_str(res, "any", "type");
+ cert_info = vici_cert_info_retrieve(type_str);
+ if (!cert_info || cert_info->type == CERT_ANY)
+ {
+ fprintf(stderr, "unsupported certificate type '%s'\n", type_str);
+ return;
+ }
+
+ /* Detect change of certificate type */
+ if (cert_info != current_cert_info)
+ {
+ first = TRUE;
+ current_cert_info = cert_info;
+ }
+
+ /* Parse certificate data blob */
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, cert_info->type,
+ BUILD_BLOB_ASN1_DER, chunk_create(buf, len),
+ BUILD_END);
+ if (cert)
+ {
+ if (*format & COMMAND_FORMAT_PEM)
+ {
+ print_pem(cert);
}
else
{
- fprintf(stderr, "received incomplete certificate data\n");
+ if (first)
+ {
+ printf("List of %ss:\n\n", cert_info->caption);
+ }
+ print_cert(cert, has_privkey);
}
+ cert->destroy(cert);
+ }
+ else
+ {
+ fprintf(stderr, "parsing certificate failed\n");
}
}
@@ -631,6 +664,8 @@ static int list_certs(vici_conn_t *conn)
return ret;
}
req = vici_begin("list-certs");
+ vici_add_version(req, VICI_VERSION);
+
if (type)
{
vici_add_key_valuef(req, "type", "%s", type);
@@ -639,6 +674,7 @@ static int list_certs(vici_conn_t *conn)
{
vici_add_key_valuef(req, "subject", "%s", subject);
}
+
res = vici_submit(req, conn);
if (!res)
{
@@ -662,8 +698,9 @@ static void __attribute__ ((constructor))reg()
{
command_register((command_t) {
list_certs, 'x', "list-certs", "list stored certificates",
- {"[--subject <dn/san>] [--type X509|X509_AC|X509_CRL] [--pem] "
- "[--raw|--pretty]"},
+ {"[--subject <dn/san>] "
+ "[--type x509|x509ca|x509aa|x509ac|x509crl|x509ocsp|ocsp] "
+ "[--pem] [--raw|--pretty]"},
{
{"help", 'h', 0, "show usage information"},
{"subject", 's', 1, "filter by certificate subject"},
diff --git a/src/swanctl/commands/version.c b/src/swanctl/commands/version.c
index 0c499e4cc..32dd77e31 100644
--- a/src/swanctl/commands/version.c
+++ b/src/swanctl/commands/version.c
@@ -2,6 +2,9 @@
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -15,6 +18,8 @@
#include "command.h"
+#include <vici_version.h>
+
#include <errno.h>
static int version(vici_conn_t *conn)
@@ -51,7 +56,8 @@ static int version(vici_conn_t *conn)
if (!daemon)
{
- printf("strongSwan swanctl %s\n", VERSION);
+ printf("strongSwan swanctl %s vici %N\n", VERSION,
+ vici_version_names, VICI_VERSION);
return 0;
}
@@ -69,12 +75,13 @@ static int version(vici_conn_t *conn)
}
else
{
- printf("strongSwan %s %s (%s, %s, %s)\n",
- vici_find_str(res, "", "version"),
- vici_find_str(res, "", "daemon"),
- vici_find_str(res, "", "sysname"),
- vici_find_str(res, "", "release"),
- vici_find_str(res, "", "machine"));
+ printf("strongSwan %s vici %s %s (%s, %s, %s)\n",
+ vici_find_str(res, "" , "version"),
+ vici_find_str(res, "1.0", "vici"),
+ vici_find_str(res, "" , "daemon"),
+ vici_find_str(res, "" , "sysname"),
+ vici_find_str(res, "" , "release"),
+ vici_find_str(res, "" , "machine"));
}
vici_free_res(res);
return 0;
diff --git a/testing/tests/swanctl/ocsp-multi-level/evaltest.dat b/testing/tests/swanctl/ocsp-multi-level/evaltest.dat
index 48776c47c..db10ac184 100644
--- a/testing/tests/swanctl/ocsp-multi-level/evaltest.dat
+++ b/testing/tests/swanctl/ocsp-multi-level/evaltest.dat
@@ -1,8 +1,8 @@
-moon:: swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.research.strongswan.org::YES
-moon:: swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.sales.strongswan.org::YES
-moon:: swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.strongswan.org::YES
-carol::swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.strongswan.org::YES
-dave:: swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.strongswan.org::YES
+moon:: swanctl --list-certs --type ocsp 2> /dev/null::issuer.*ocsp.research.strongswan.org::YES
+moon:: swanctl --list-certs --type ocsp 2> /dev/null::issuer.*ocsp.sales.strongswan.org::YES
+moon:: swanctl --list-certs --type ocsp 2> /dev/null::issuer.*ocsp.strongswan.org::YES
+carol::swanctl --list-certs --type ocsp 2> /dev/null::issuer.*ocsp.strongswan.org::YES
+dave:: swanctl --list-certs --type ocsp 2> /dev/null::issuer.*ocsp.strongswan.org::YES
moon:: cat /var/log/daemon.log::ocsp response correctly signed by.*ocsp.research.strongswan.org::YES
moon:: cat /var/log/daemon.log::ocsp response correctly signed by.*ocsp.sales.strongswan.org::YES
moon:: cat /var/log/daemon.log::ocsp response correctly signed by.*ocsp.strongswan.org::YES