acert: Implement a plugin finding, validating and evaluating attribute certs

This validator checks for any attribute certificate it can find for validated
end entity certificates and tries to extract group membership information
used for connection authorization rules.
This commit is contained in:
Martin Willi 2014-02-05 16:59:55 +01:00
parent b06283f1e3
commit 5ac0e66879
7 changed files with 367 additions and 0 deletions

View File

@ -165,6 +165,7 @@ ARG_ENABL_SET([mysql], [enable MySQL database support. Requires libmysq
ARG_ENABL_SET([sqlite], [enable SQLite database support. Requires libsqlite3.])
# authentication/credential plugins
ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.])
ARG_ENABL_SET([acert], [enable X509 attribute certificate checking plugin.])
ARG_ENABL_SET([agent], [enables the ssh-agent signing plugin.])
ARG_DISBL_SET([constraints], [disable advanced X509 constraint checking plugin.])
ARG_ENABL_SET([coupling], [enable IKEv2 plugin to couple peer certificates permanently to authentication.])
@ -1090,6 +1091,7 @@ ADD_PLUGIN([nonce], [s charon nm cmd])
ADD_PLUGIN([x509], [s charon openac scepclient pki scripts attest nm cmd])
ADD_PLUGIN([revocation], [s charon nm cmd])
ADD_PLUGIN([constraints], [s charon nm cmd])
ADD_PLUGIN([acert], [s charon])
ADD_PLUGIN([pubkey], [s charon cmd])
ADD_PLUGIN([pkcs1], [s charon openac scepclient pki scripts manager medsrv attest nm cmd])
ADD_PLUGIN([pkcs7], [s charon scepclient pki scripts nm cmd])
@ -1229,6 +1231,7 @@ AM_CONDITIONAL(USE_NONCE, test x$nonce = xtrue)
AM_CONDITIONAL(USE_X509, test x$x509 = xtrue)
AM_CONDITIONAL(USE_REVOCATION, test x$revocation = xtrue)
AM_CONDITIONAL(USE_CONSTRAINTS, test x$constraints = xtrue)
AM_CONDITIONAL(USE_ACERT, test x$acert = xtrue)
AM_CONDITIONAL(USE_PUBKEY, test x$pubkey = xtrue)
AM_CONDITIONAL(USE_PKCS1, test x$pkcs1 = xtrue)
AM_CONDITIONAL(USE_PKCS7, test x$pkcs7 = xtrue)
@ -1454,6 +1457,7 @@ AC_CONFIG_FILES([
src/libstrongswan/plugins/x509/Makefile
src/libstrongswan/plugins/revocation/Makefile
src/libstrongswan/plugins/constraints/Makefile
src/libstrongswan/plugins/acert/Makefile
src/libstrongswan/plugins/pubkey/Makefile
src/libstrongswan/plugins/pkcs1/Makefile
src/libstrongswan/plugins/pkcs7/Makefile

View File

@ -307,6 +307,13 @@ if MONOLITHIC
endif
endif
if USE_ACERT
SUBDIRS += plugins/acert
if MONOLITHIC
libstrongswan_la_LIBADD += plugins/acert/libstrongswan-acert.la
endif
endif
if USE_PUBKEY
SUBDIRS += plugins/pubkey
if MONOLITHIC

View File

@ -0,0 +1,17 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = \
-rdynamic
if MONOLITHIC
noinst_LTLIBRARIES = libstrongswan-acert.la
else
plugin_LTLIBRARIES = libstrongswan-acert.la
endif
libstrongswan_acert_la_SOURCES = \
acert_validator.h acert_validator.c \
acert_plugin.h acert_plugin.c
libstrongswan_acert_la_LDFLAGS = -module -avoid-version

View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
* 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 "acert_plugin.h"
#include "acert_validator.h"
#include <library.h>
typedef struct private_acert_plugin_t private_acert_plugin_t;
/**
* private data of acert_plugin
*/
struct private_acert_plugin_t {
/**
* public functions
*/
acert_plugin_t public;
/**
* Validator implementation instance.
*/
acert_validator_t *validator;
};
METHOD(plugin_t, get_name, char*,
private_acert_plugin_t *this)
{
return "acert";
}
/**
* Register validator
*/
static bool plugin_cb(private_acert_plugin_t *this,
plugin_feature_t *feature, bool reg, void *cb_data)
{
if (reg)
{
lib->credmgr->add_validator(lib->credmgr, &this->validator->validator);
}
else
{
lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator);
}
return TRUE;
}
METHOD(plugin_t, get_features, int,
private_acert_plugin_t *this, plugin_feature_t *features[])
{
static plugin_feature_t f[] = {
PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
PLUGIN_PROVIDE(CUSTOM, "acert"),
};
*features = f;
return countof(f);
}
METHOD(plugin_t, destroy, void,
private_acert_plugin_t *this)
{
this->validator->destroy(this->validator);
free(this);
}
/*
* see header file
*/
plugin_t *acert_plugin_create()
{
private_acert_plugin_t *this;
INIT(this,
.public = {
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
.destroy = _destroy,
},
},
.validator = acert_validator_create(),
);
return &this->public.plugin;
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
* 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 acert acert
* @ingroup plugins
*
* @defgroup acert_plugin acert_plugin
* @{ @ingroup acert
*/
#ifndef ACERT_PLUGIN_H_
#define ACERT_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct acert_plugin_t acert_plugin_t;
/**
* X.509 attribute certificate group membership checking.
*/
struct acert_plugin_t {
/**
* Implements plugin_t. interface.
*/
plugin_t plugin;
};
#endif /** ACERT_PLUGIN_H_ @}*/

View File

@ -0,0 +1,149 @@
/*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
* 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.
*/
#define _GNU_SOURCE
#include <library.h>
#include "acert_validator.h"
#include <credentials/certificates/x509.h>
#include <credentials/certificates/ac.h>
typedef struct private_acert_validator_t private_acert_validator_t;
/**
* Private data of an acert_validator_t object.
*/
struct private_acert_validator_t {
/**
* Public acert_validator_t interface.
*/
acert_validator_t public;
};
/**
* Check if an AC can be trusted
*/
static bool verify(private_acert_validator_t *this, certificate_t *ac)
{
certificate_t *issuer;
enumerator_t *enumerator;
bool verified = FALSE;
if (!ac->get_validity(ac, NULL, NULL, NULL))
{
return FALSE;
}
DBG1(DBG_CFG, "verifying attribute certificate issued by \"%Y\"",
ac->get_issuer(ac));
enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr, KEY_ANY,
ac->get_issuer(ac), TRUE);
while (enumerator->enumerate(enumerator, &issuer, NULL))
{
if (issuer->get_validity(issuer, NULL, NULL, NULL))
{
if (lib->credmgr->issued_by(lib->credmgr, ac, issuer, NULL))
{
verified = TRUE;
break;
}
}
}
enumerator->destroy(enumerator);
return verified;
}
/**
* Apply AC group membership to auth config
*/
static void apply(private_acert_validator_t *this, ac_t *ac, auth_cfg_t *auth)
{
enumerator_t *enumerator;
ac_group_type_t type;
chunk_t chunk;
enumerator = ac->create_group_enumerator(ac);
while (enumerator->enumerate(enumerator, &type, &chunk))
{
if (type == AC_GROUP_TYPE_STRING)
{
auth->add(auth, AUTH_RULE_GROUP,
identification_create_from_data(chunk));
}
}
enumerator->destroy(enumerator);
}
METHOD(cert_validator_t, validate, bool,
private_acert_validator_t *this, certificate_t *subject,
certificate_t *issuer, bool online, u_int pathlen, bool anchor,
auth_cfg_t *auth)
{
/* for X.509 end entity certs only */
if (pathlen == 0 && subject->get_type(subject) == CERT_X509)
{
x509_t *x509 = (x509_t*)subject;
enumerator_t *enumerator;
identification_t *id, *serial;
ac_t *ac;
/* find attribute certificates by serial and issuer. A lookup by
* the holder DN would work as well, but RFC 5755 recommends the use
* of baseCertificateID. */
serial = identification_create_from_encoding(ID_KEY_ID,
x509->get_serial(x509));
enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
CERT_X509_AC, KEY_ANY, serial, FALSE);
while (enumerator->enumerate(enumerator, &ac))
{
id = ac->get_holderIssuer(ac);
if (id && id->equals(id, subject->get_issuer(subject)))
{
if (verify(this, &ac->certificate))
{
apply(this, ac, auth);
}
}
}
enumerator->destroy(enumerator);
serial->destroy(serial);
}
return TRUE;
}
METHOD(acert_validator_t, destroy, void,
private_acert_validator_t *this)
{
free(this);
}
/**
* See header
*/
acert_validator_t *acert_validator_create()
{
private_acert_validator_t *this;
INIT(this,
.public = {
.validator.validate = _validate,
.destroy = _destroy,
},
);
return &this->public;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
* 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 acert_validator acert_validator
* @{ @ingroup acert
*/
#ifndef ACERT_VALIDATOR_H_
#define ACERT_VALIDATOR_H_
#include <credentials/cert_validator.h>
typedef struct acert_validator_t acert_validator_t;
/**
* Attribute certificate group membership checking
*/
struct acert_validator_t {
/**
* Implements cert_validator_t interface.
*/
cert_validator_t validator;
/**
* Destroy a acert_validator_t.
*/
void (*destroy)(acert_validator_t *this);
};
/**
* Create a acert_validator instance.
*/
acert_validator_t *acert_validator_create();
#endif /** ACERT_VALIDATOR_H_ @}*/