Use VICI 2.0 protocol version for certificate queries

This commit is contained in:
Andreas Steffen 2015-12-03 11:20:04 +01:00
parent 5d909303d8
commit fad851e2d3
7 changed files with 287 additions and 136 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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_ @}*/

View File

@ -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"))
vici_cert_info_t *cert_info;
cert_info = vici_cert_info_retrieve(str);
if (cert_info)
{
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"))
{
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);

View File

@ -29,8 +29,16 @@
#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
*/
@ -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)
if (flags != X509_NONE)
{
printf("CA ");
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");
}
if (flags & X509_CRL_SIGN)
{
printf("CRLSign ");
}
if (flags & X509_AA)
{
printf("AA ");
}
if (flags & X509_OCSP_SIGNER)
{
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("\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
{
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)
version_str = vici_find_str(res, "1.0", "vici");
if (!enum_from_name(vici_version_names, version_str, &version) ||
version == VICI_1_0)
{
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)
{
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");
}
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"},

View File

@ -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;

View File

@ -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