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_message.h vici_message.c \
vici_builder.h vici_builder.c \ vici_builder.h vici_builder.c \
vici_dispatcher.h vici_dispatcher.c \ vici_dispatcher.h vici_dispatcher.c \
vici_cert_info.c vici_cert_info.h \
vici_query.h vici_query.c \ vici_query.h vici_query.c \
vici_control.h vici_control.c \ vici_control.h vici_control.c \
vici_config.h vici_config.c \ vici_config.h vici_config.c \
@ -40,6 +41,7 @@ libvici_la_SOURCES = \
vici_message.c vici_message.h \ vici_message.c vici_message.h \
vici_builder.c vici_builder.h \ vici_builder.c vici_builder.h \
vici_version.c vici_version.h \ vici_version.c vici_version.h \
vici_cert_info.c vici_cert_info.h \
libvici.c libvici.h libvici.c libvici.h
libvici_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la 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_query.h"
#include "vici_builder.h" #include "vici_builder.h"
#include "vici_version.h" #include "vici_version.h"
#include "vici_cert_info.h"
#include <credentials/certificates/x509.h>
#include <inttypes.h> #include <inttypes.h>
#include <time.h> #include <time.h>
@ -821,7 +820,7 @@ typedef struct {
*/ */
static void enum_x509(private_vici_query_t *this, u_int id, static void enum_x509(private_vici_query_t *this, u_int id,
linked_list_t *certs, cert_filter_t *filter, linked_list_t *certs, cert_filter_t *filter,
x509_flag_t flag) x509_flag_t flag, char *cert_type)
{ {
enumerator_t *enumerator; enumerator_t *enumerator;
certificate_t *cert; certificate_t *cert;
@ -830,7 +829,7 @@ static void enum_x509(private_vici_query_t *this, u_int id,
x509_flag_t mask; x509_flag_t mask;
x509_t *x509; 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) filter->flag != flag)
{ {
return; 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)) if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
{ {
b = vici_builder_create(); b = vici_builder_create();
b->add_kv(b, "type", "%N", if (filter->version == VICI_1_0)
certificate_type_names, cert->get_type(cert)); {
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)) if (has_privkey(cert))
{ {
b->add_kv(b, "has_privkey", "yes"); 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 * Enumerate all non-X.509 certificate types
*/ */
static void enum_others(private_vici_query_t *this, u_int id, 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; enumerator_t *enumerator;
certificate_t *cert; 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)) if (cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
{ {
b = vici_builder_create(); b = vici_builder_create();
b->add_kv(b, "type", "%N", if (filter->version == VICI_1_0)
certificate_type_names, cert->get_type(cert)); {
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); b->add(b, VICI_KEY_VALUE, "data", encoding);
free(encoding.ptr); 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 * Enumerate all certificates of a given type
*/ */
static void enum_certs(private_vici_query_t *this, u_int id, 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; enumerator_t *e1, *e2;
certificate_t *cert, *current; certificate_t *cert, *current;
@ -937,14 +954,14 @@ static void enum_certs(private_vici_query_t *this, u_int id,
if (type == CERT_X509) if (type == CERT_X509)
{ {
enum_x509(this, id, certs, filter, X509_NONE); enum_x509(this, id, certs, filter, X509_NONE, "x509");
enum_x509(this, id, certs, filter, X509_CA); enum_x509(this, id, certs, filter, X509_CA, "x509ca");
enum_x509(this, id, certs, filter, X509_AA); enum_x509(this, id, certs, filter, X509_AA, "x509ac");
enum_x509(this, id, certs, filter, X509_OCSP_SIGNER); enum_x509(this, id, certs, filter, X509_OCSP_SIGNER, "x509ocsp");
} }
else else
{ {
enum_others(this, id, certs, filter); enum_others(this, id, certs, filter, cert_type);
} }
certs->destroy_offset(certs, offsetof(certificate_t, destroy)); certs->destroy_offset(certs, offsetof(certificate_t, destroy));
} }
@ -979,40 +996,13 @@ CALLBACK(list_certs, vici_message_t*,
} }
else /* VICI 2.0 */ 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; filter.type = cert_info->type;
} filter.flag = cert_info->flag;
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;
} }
else else
{ {
@ -1026,10 +1016,10 @@ CALLBACK(list_certs, vici_message_t*,
{ {
filter.subject = identification_create_from_string(str); filter.subject = identification_create_from_string(str);
} }
enum_certs(this, id, &filter, CERT_X509); enum_certs(this, id, &filter, CERT_X509, "x509");
enum_certs(this, id, &filter, CERT_X509_AC); enum_certs(this, id, &filter, CERT_X509_AC, "x509ac");
enum_certs(this, id, &filter, CERT_X509_CRL); enum_certs(this, id, &filter, CERT_X509_CRL, "x509crl");
enum_certs(this, id, &filter, CERT_X509_OCSP_RESPONSE); enum_certs(this, id, &filter, CERT_X509_OCSP_RESPONSE, "ocsp");
DESTROY_IF(filter.subject); DESTROY_IF(filter.subject);
finalize: finalize:
@ -1146,6 +1136,7 @@ CALLBACK(version, vici_message_t*,
b = vici_builder_create(); 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, "daemon", "%s", lib->ns);
b->add_kv(b, "version", "%s", VERSION); b->add_kv(b, "version", "%s", VERSION);

View File

@ -29,8 +29,16 @@
#include <credentials/certificates/ac.h> #include <credentials/certificates/ac.h>
#include <selectors/traffic_selector.h> #include <selectors/traffic_selector.h>
#include <vici_version.h>
#include <vici_cert_info.h>
#include "command.h" #include "command.h"
/**
* Current certificate type info
*/
static vici_cert_info_t *current_cert_info = NULL;
/** /**
* Print PEM encoding of a certificate * Print PEM encoding of a certificate
*/ */
@ -115,44 +123,43 @@ static void print_x509(x509_t *x509)
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
flags = x509->get_flags(x509); flags = x509->get_flags(x509);
printf("flags: "); if (flags != X509_NONE)
if (flags & X509_CA)
{ {
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; first = TRUE;
enumerator = x509->create_crl_uri_enumerator(x509); enumerator = x509->create_crl_uri_enumerator(x509);
@ -486,8 +493,8 @@ static void print_cert(certificate_t *cert, bool has_privkey)
now = time(NULL); 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)); 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, CALLBACK(list_cb, void,
command_format_options_t *format, char *name, vici_res_t *res) 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) if (*format & COMMAND_FORMAT_RAW)
{ {
vici_dump(res, "list-cert event", *format & COMMAND_FORMAT_PRETTY, vici_dump(res, "list-cert event", *format & COMMAND_FORMAT_PRETTY,
stdout); stdout);
return;
} }
else
{
certificate_type_t type;
certificate_t *cert;
void *buf;
int len;
bool has_privkey;
buf = vici_find(res, &len, "data"); version_str = vici_find_str(res, "1.0", "vici");
has_privkey = streq(vici_find_str(res, "no", "has_privkey"), "yes"); if (!enum_from_name(vici_version_names, version_str, &version) ||
if (enum_from_name(certificate_type_names, version == VICI_1_0)
vici_find_str(res, "ANY", "type"), &type) && {
type != CERT_ANY && buf) 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, print_pem(cert);
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");
}
} }
else 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; return ret;
} }
req = vici_begin("list-certs"); req = vici_begin("list-certs");
vici_add_version(req, VICI_VERSION);
if (type) if (type)
{ {
vici_add_key_valuef(req, "type", "%s", 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); vici_add_key_valuef(req, "subject", "%s", subject);
} }
res = vici_submit(req, conn); res = vici_submit(req, conn);
if (!res) if (!res)
{ {
@ -662,8 +698,9 @@ static void __attribute__ ((constructor))reg()
{ {
command_register((command_t) { command_register((command_t) {
list_certs, 'x', "list-certs", "list stored certificates", list_certs, 'x', "list-certs", "list stored certificates",
{"[--subject <dn/san>] [--type X509|X509_AC|X509_CRL] [--pem] " {"[--subject <dn/san>] "
"[--raw|--pretty]"}, "[--type x509|x509ca|x509aa|x509ac|x509crl|x509ocsp|ocsp] "
"[--pem] [--raw|--pretty]"},
{ {
{"help", 'h', 0, "show usage information"}, {"help", 'h', 0, "show usage information"},
{"subject", 's', 1, "filter by certificate subject"}, {"subject", 's', 1, "filter by certificate subject"},

View File

@ -2,6 +2,9 @@
* Copyright (C) 2014 Martin Willi * Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG * 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 * 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 * 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 * Free Software Foundation; either version 2 of the License, or (at your
@ -15,6 +18,8 @@
#include "command.h" #include "command.h"
#include <vici_version.h>
#include <errno.h> #include <errno.h>
static int version(vici_conn_t *conn) static int version(vici_conn_t *conn)
@ -51,7 +56,8 @@ static int version(vici_conn_t *conn)
if (!daemon) if (!daemon)
{ {
printf("strongSwan swanctl %s\n", VERSION); printf("strongSwan swanctl %s vici %N\n", VERSION,
vici_version_names, VICI_VERSION);
return 0; return 0;
} }
@ -69,12 +75,13 @@ static int version(vici_conn_t *conn)
} }
else else
{ {
printf("strongSwan %s %s (%s, %s, %s)\n", printf("strongSwan %s vici %s %s (%s, %s, %s)\n",
vici_find_str(res, "", "version"), vici_find_str(res, "" , "version"),
vici_find_str(res, "", "daemon"), vici_find_str(res, "1.0", "vici"),
vici_find_str(res, "", "sysname"), vici_find_str(res, "" , "daemon"),
vici_find_str(res, "", "release"), vici_find_str(res, "" , "sysname"),
vici_find_str(res, "", "machine")); vici_find_str(res, "" , "release"),
vici_find_str(res, "" , "machine"));
} }
vici_free_res(res); vici_free_res(res);
return 0; 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 ocsp 2> /dev/null::issuer.*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 ocsp 2> /dev/null::issuer.*ocsp.sales.strongswan.org::YES
moon:: 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.strongswan.org::YES
carol::swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*ocsp.strongswan.org::YES carol::swanctl --list-certs --type ocsp 2> /dev/null::issuer.*ocsp.strongswan.org::YES
dave:: swanctl --list-certs --type X509_OCSP_RESPONSE 2> /dev/null::subject.*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.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.sales.strongswan.org::YES
moon:: cat /var/log/daemon.log::ocsp response correctly signed by.*ocsp.strongswan.org::YES moon:: cat /var/log/daemon.log::ocsp response correctly signed by.*ocsp.strongswan.org::YES