Merge branch 'acerts'
(Re-)Introduces X.509 Attribute Certificate support in IKE, and cleans up the x509 AC parser/generator. ACs may be stored locally or exchanged in IKEv2 CERT payloads, Attribute Authorities must be installed locally. pki --acert issues Attribute Certificates and replaces the removed openac utility.
This commit is contained in:
commit
1766ede330
13
NEWS
13
NEWS
|
@ -1,3 +1,16 @@
|
|||
strongswan-5.1.3
|
||||
----------------
|
||||
|
||||
- The acert plugin evaluates X.509 Attribute Certificates. Group membership
|
||||
information encoded as strings can be used to fulfill authorization checks
|
||||
defined with the rightgroups option. Attribute Certificates can be loaded
|
||||
locally or get exchanged in IKEv2 certificate payloads.
|
||||
|
||||
- The pki command gained support to generate X.509 Attribute Certificates
|
||||
using the --acert subcommand, while the --print command supports the ac type.
|
||||
The openac utility has been removed in favor of the new pki functionality.
|
||||
|
||||
|
||||
strongswan-5.1.2
|
||||
----------------
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
openac.load =
|
||||
Plugins to load in ipsec openac tool.
|
||||
|
||||
pki.load =
|
||||
Plugins to load in ipsec pki tool.
|
||||
|
||||
|
|
48
configure.ac
48
configure.ac
|
@ -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.])
|
||||
|
@ -264,7 +265,7 @@ ARG_ENABL_SET([medsrv], [enable mediation server web frontend and daemon
|
|||
ARG_ENABL_SET([nm], [enable NetworkManager backend.])
|
||||
ARG_DISBL_SET([scripts], [disable additional utilities (found in directory scripts).])
|
||||
ARG_ENABL_SET([tkm], [enable Trusted Key Manager support.])
|
||||
ARG_DISBL_SET([tools], [disable additional utilities (openac, scepclient and pki).])
|
||||
ARG_DISBL_SET([tools], [disable additional utilities (scepclient and pki).])
|
||||
# optional features
|
||||
ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.])
|
||||
ARG_DISBL_SET([ikev1], [disable IKEv1 protocol support in charon.])
|
||||
|
@ -1052,7 +1053,6 @@ charon_plugins=
|
|||
starter_plugins=
|
||||
pool_plugins=
|
||||
attest_plugins=
|
||||
openac_plugins=
|
||||
scepclient_plugins=
|
||||
pki_plugins=
|
||||
scripts_plugins=
|
||||
|
@ -1068,7 +1068,7 @@ h_plugins=
|
|||
s_plugins=
|
||||
t_plugins=
|
||||
|
||||
ADD_PLUGIN([test-vectors], [s charon openac scepclient pki])
|
||||
ADD_PLUGIN([test-vectors], [s charon scepclient pki])
|
||||
ADD_PLUGIN([curl], [s charon scepclient scripts nm cmd])
|
||||
ADD_PLUGIN([soup], [s charon scripts nm cmd])
|
||||
ADD_PLUGIN([unbound], [s charon scripts])
|
||||
|
@ -1076,37 +1076,38 @@ ADD_PLUGIN([ldap], [s charon scepclient scripts nm cmd])
|
|||
ADD_PLUGIN([mysql], [s charon pool manager medsrv attest])
|
||||
ADD_PLUGIN([sqlite], [s charon pool manager medsrv attest])
|
||||
ADD_PLUGIN([pkcs11], [s charon pki nm cmd])
|
||||
ADD_PLUGIN([aes], [s charon openac scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([des], [s charon openac scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([blowfish], [s charon openac scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([rc2], [s charon openac scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([sha1], [s charon openac scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([sha2], [s charon openac scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([md4], [s charon openac manager scepclient pki nm cmd])
|
||||
ADD_PLUGIN([md5], [s charon openac scepclient pki scripts attest nm cmd])
|
||||
ADD_PLUGIN([rdrand], [s charon openac scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([random], [s charon openac scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([aes], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([des], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([blowfish], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([rc2], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([sha1], [s charon scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([sha2], [s charon scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([md4], [s charon manager scepclient pki nm cmd])
|
||||
ADD_PLUGIN([md5], [s charon scepclient pki scripts attest nm cmd])
|
||||
ADD_PLUGIN([rdrand], [s charon scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([random], [s charon scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([nonce], [s charon nm cmd])
|
||||
ADD_PLUGIN([x509], [s charon openac scepclient pki scripts attest nm cmd])
|
||||
ADD_PLUGIN([x509], [s charon 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([pkcs1], [s charon scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([pkcs7], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([pkcs8], [s charon openac scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([pkcs8], [s charon scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([pkcs12], [s charon scepclient pki scripts cmd])
|
||||
ADD_PLUGIN([pgp], [s charon])
|
||||
ADD_PLUGIN([dnskey], [s charon pki])
|
||||
ADD_PLUGIN([sshkey], [s charon pki nm cmd])
|
||||
ADD_PLUGIN([dnscert], [c charon])
|
||||
ADD_PLUGIN([ipseckey], [c charon])
|
||||
ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([pem], [s charon scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([padlock], [s charon])
|
||||
ADD_PLUGIN([openssl], [s charon openac scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([gcrypt], [s charon openac scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([af-alg], [s charon openac scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([openssl], [s charon scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([gcrypt], [s charon scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([af-alg], [s charon scepclient pki scripts medsrv attest nm cmd])
|
||||
ADD_PLUGIN([fips-prf], [s charon nm cmd])
|
||||
ADD_PLUGIN([gmp], [s charon openac scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([gmp], [s charon scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([agent], [s charon nm cmd])
|
||||
ADD_PLUGIN([keychain], [s charon cmd])
|
||||
ADD_PLUGIN([xcbc], [s charon nm cmd])
|
||||
|
@ -1188,7 +1189,6 @@ AC_SUBST(charon_plugins)
|
|||
AC_SUBST(starter_plugins)
|
||||
AC_SUBST(pool_plugins)
|
||||
AC_SUBST(attest_plugins)
|
||||
AC_SUBST(openac_plugins)
|
||||
AC_SUBST(scepclient_plugins)
|
||||
AC_SUBST(pki_plugins)
|
||||
AC_SUBST(scripts_plugins)
|
||||
|
@ -1229,6 +1229,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 +1455,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
|
||||
|
@ -1582,7 +1584,6 @@ AC_CONFIG_FILES([
|
|||
src/_updown/Makefile
|
||||
src/_updown_espmark/Makefile
|
||||
src/_copyright/Makefile
|
||||
src/openac/Makefile
|
||||
src/scepclient/Makefile
|
||||
src/pki/Makefile
|
||||
src/pki/man/Makefile
|
||||
|
@ -1619,6 +1620,7 @@ AC_CONFIG_FILES([
|
|||
src/pki/man/pki---req.1
|
||||
src/pki/man/pki---self.1
|
||||
src/pki/man/pki---signcrl.1
|
||||
src/pki/man/pki---acert.1
|
||||
src/pki/man/pki---verify.1
|
||||
])
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
usr/lib/strongswan/scepclient usr/lib/strongswan/
|
||||
usr/lib/strongswan/openac usr/lib/strongswan/
|
||||
usr/lib/strongswan/pki usr/lib/strongswan/
|
||||
usr/share/man/man8/scepclient.8 usr/share/man/man8/
|
||||
usr/share/man/man8/openac.8 usr/share/man/man8/
|
||||
|
|
|
@ -73,7 +73,7 @@ if USE_UPDOWN
|
|||
endif
|
||||
|
||||
if USE_TOOLS
|
||||
SUBDIRS += openac scepclient pki
|
||||
SUBDIRS += scepclient pki
|
||||
endif
|
||||
|
||||
if USE_CONFTEST
|
||||
|
|
|
@ -100,7 +100,6 @@ if USE_CMD
|
|||
endif
|
||||
|
||||
if USE_TOOLS
|
||||
exes += $(DESTDIR)$(ipsecdir)/openac
|
||||
exes += $(DESTDIR)$(ipsecdir)/scepclient
|
||||
exes += $(DESTDIR)$(bindir)/pki
|
||||
endif
|
||||
|
|
|
@ -70,7 +70,6 @@ case "$1" in
|
|||
echo " rereadcacerts|rereadaacerts|rereadocspcerts"
|
||||
echo " rereadacerts|rereadcrls|rereadall"
|
||||
echo " purgeocsp|purgecrls|purgecerts|purgeike"
|
||||
echo " openac"
|
||||
echo " scepclient"
|
||||
echo " secrets"
|
||||
echo " starter"
|
||||
|
|
|
@ -224,6 +224,9 @@ METHOD(cert_payload_t, get_cert, certificate_t*,
|
|||
case ENC_X509_SIGNATURE:
|
||||
type = CERT_X509;
|
||||
break;
|
||||
case ENC_X509_ATTRIBUTE:
|
||||
type = CERT_X509_AC;
|
||||
break;
|
||||
case ENC_CRL:
|
||||
type = CERT_X509_CRL;
|
||||
break;
|
||||
|
@ -333,6 +336,9 @@ cert_payload_t *cert_payload_create_from_cert(payload_type_t type,
|
|||
case CERT_X509:
|
||||
this->encoding = ENC_X509_SIGNATURE;
|
||||
break;
|
||||
case CERT_X509_AC:
|
||||
this->encoding = ENC_X509_ATTRIBUTE;
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_ENC, "embedding %N certificate in payload failed",
|
||||
certificate_type_names, cert->get_type(cert));
|
||||
|
@ -380,4 +386,3 @@ cert_payload_t *cert_payload_create_custom(payload_type_t type,
|
|||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,9 @@
|
|||
#include <credentials/certificates/ac.h>
|
||||
#include <credentials/certificates/crl.h>
|
||||
#include <credentials/certificates/pgp_certificate.h>
|
||||
#include <credentials/ietf_attributes/ietf_attributes.h>
|
||||
#include <config/peer_cfg.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/oid.h>
|
||||
|
||||
/* warning intervals for list functions */
|
||||
#define CERT_WARNING_INTERVAL 30 /* days */
|
||||
|
@ -1027,16 +1028,19 @@ static void stroke_list_certs(linked_list_t *list, char *label,
|
|||
static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
|
||||
{
|
||||
bool first = TRUE;
|
||||
time_t thisUpdate, nextUpdate, now = time(NULL);
|
||||
enumerator_t *enumerator = list->create_enumerator(list);
|
||||
time_t notBefore, notAfter, now = time(NULL);
|
||||
enumerator_t *enumerator;
|
||||
certificate_t *cert;
|
||||
|
||||
while (enumerator->enumerate(enumerator, (void**)&cert))
|
||||
enumerator = list->create_enumerator(list);
|
||||
while (enumerator->enumerate(enumerator, &cert))
|
||||
{
|
||||
ac_t *ac = (ac_t*)cert;
|
||||
ac_group_type_t type;
|
||||
identification_t *id;
|
||||
ietf_attributes_t *groups;
|
||||
enumerator_t *groups;
|
||||
chunk_t chunk;
|
||||
bool firstgroup = TRUE;
|
||||
|
||||
if (first)
|
||||
{
|
||||
|
@ -1061,30 +1065,78 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
|
|||
{
|
||||
fprintf(out, " hserial: %#B\n", &chunk);
|
||||
}
|
||||
groups = ac->get_groups(ac);
|
||||
if (groups)
|
||||
groups = ac->create_group_enumerator(ac);
|
||||
while (groups->enumerate(groups, &type, &chunk))
|
||||
{
|
||||
fprintf(out, " groups: %s\n", groups->get_string(groups));
|
||||
groups->destroy(groups);
|
||||
int oid;
|
||||
char *str;
|
||||
|
||||
if (firstgroup)
|
||||
{
|
||||
fprintf(out, " groups: ");
|
||||
firstgroup = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(out, " ");
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case AC_GROUP_TYPE_STRING:
|
||||
fprintf(out, "%.*s", (int)chunk.len, chunk.ptr);
|
||||
break;
|
||||
case AC_GROUP_TYPE_OID:
|
||||
oid = asn1_known_oid(chunk);
|
||||
if (oid == OID_UNKNOWN)
|
||||
{
|
||||
str = asn1_oid_to_string(chunk);
|
||||
if (str)
|
||||
{
|
||||
fprintf(out, "%s", str);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(out, "OID:%#B", &chunk);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(out, "%s", oid_names[oid].name);
|
||||
}
|
||||
break;
|
||||
case AC_GROUP_TYPE_OCTETS:
|
||||
fprintf(out, "%#B", &chunk);
|
||||
break;
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
groups->destroy(groups);
|
||||
fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert));
|
||||
chunk = chunk_skip_zero(ac->get_serial(ac));
|
||||
fprintf(out, " serial: %#B\n", &chunk);
|
||||
|
||||
/* list validity */
|
||||
cert->get_validity(cert, &now, &thisUpdate, &nextUpdate);
|
||||
fprintf(out, " updates: this %T\n", &thisUpdate, utc);
|
||||
fprintf(out, " next %T, ", &nextUpdate, utc);
|
||||
if (now > nextUpdate)
|
||||
cert->get_validity(cert, &now, ¬Before, ¬After);
|
||||
fprintf(out, " validity: not before %T, ", ¬Before, utc);
|
||||
if (now < notBefore)
|
||||
{
|
||||
fprintf(out, "expired (%V ago)\n", &now, &nextUpdate);
|
||||
fprintf(out, "not valid yet (valid in %V)\n", &now, ¬Before);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(out, "ok\n");
|
||||
}
|
||||
fprintf(out, " not after %T, ", ¬After, utc);
|
||||
if (now > notAfter)
|
||||
{
|
||||
fprintf(out, "expired (%V ago)\n", &now, ¬After);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(out, "ok");
|
||||
if (now > nextUpdate - AC_WARNING_INTERVAL * 60 * 60 * 24)
|
||||
if (now > notAfter - AC_WARNING_INTERVAL * 60 * 60 * 24)
|
||||
{
|
||||
fprintf(out, " (expires in %V)", &now, &nextUpdate);
|
||||
fprintf(out, " (expires in %V)", &now, ¬After);
|
||||
}
|
||||
fprintf(out, " \n");
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <encoding/payloads/certreq_payload.h>
|
||||
#include <encoding/payloads/auth_payload.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
#include <credentials/certificates/ac.h>
|
||||
|
||||
|
||||
typedef struct private_ike_cert_post_t private_ike_cert_post_t;
|
||||
|
@ -104,6 +105,102 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this,
|
|||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subject certificate to message
|
||||
*/
|
||||
static bool add_subject_cert(private_ike_cert_post_t *this, auth_cfg_t *auth,
|
||||
message_t *message)
|
||||
{
|
||||
cert_payload_t *payload;
|
||||
certificate_t *cert;
|
||||
|
||||
cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
|
||||
if (!cert)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
payload = build_cert_payload(this, cert);
|
||||
if (!payload)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
DBG1(DBG_IKE, "sending end entity cert \"%Y\"", cert->get_subject(cert));
|
||||
message->add_payload(message, (payload_t*)payload);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add intermediate CA certificates to message
|
||||
*/
|
||||
static void add_im_certs(private_ike_cert_post_t *this, auth_cfg_t *auth,
|
||||
message_t *message)
|
||||
{
|
||||
cert_payload_t *payload;
|
||||
enumerator_t *enumerator;
|
||||
certificate_t *cert;
|
||||
auth_rule_t type;
|
||||
|
||||
enumerator = auth->create_enumerator(auth);
|
||||
while (enumerator->enumerate(enumerator, &type, &cert))
|
||||
{
|
||||
if (type == AUTH_RULE_IM_CERT)
|
||||
{
|
||||
payload = cert_payload_create_from_cert(CERTIFICATE, cert);
|
||||
if (payload)
|
||||
{
|
||||
DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
|
||||
cert->get_subject(cert));
|
||||
message->add_payload(message, (payload_t*)payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add any valid attribute certificates of subject to message
|
||||
*/
|
||||
static void add_attribute_certs(private_ike_cert_post_t *this,
|
||||
auth_cfg_t *auth, message_t *message)
|
||||
{
|
||||
certificate_t *subject, *cert;
|
||||
|
||||
subject = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
|
||||
if (subject && subject->get_type(subject) == CERT_X509)
|
||||
{
|
||||
x509_t *x509 = (x509_t*)subject;
|
||||
identification_t *id, *serial;
|
||||
enumerator_t *enumerator;
|
||||
cert_payload_t *payload;
|
||||
ac_t *ac;
|
||||
|
||||
/* we look for attribute certs having our serial and holder issuer,
|
||||
* which is recommended by RFC 5755 */
|
||||
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))
|
||||
{
|
||||
cert = &ac->certificate;
|
||||
id = ac->get_holderIssuer(ac);
|
||||
if (id && id->equals(id, subject->get_issuer(subject)) &&
|
||||
cert->get_validity(cert, NULL, NULL, NULL))
|
||||
{
|
||||
payload = cert_payload_create_from_cert(CERTIFICATE, cert);
|
||||
if (payload)
|
||||
{
|
||||
DBG1(DBG_IKE, "sending attribute certificate "
|
||||
"issued by \"%Y\"", cert->get_issuer(cert));
|
||||
message->add_payload(message, (payload_t*)payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
serial->destroy(serial);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add certificates to message
|
||||
*/
|
||||
|
@ -111,6 +208,7 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
|
|||
{
|
||||
peer_cfg_t *peer_cfg;
|
||||
auth_payload_t *payload;
|
||||
auth_cfg_t *auth;
|
||||
|
||||
payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION);
|
||||
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
|
||||
|
@ -130,46 +228,13 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message)
|
|||
}
|
||||
/* FALL */
|
||||
case CERT_ALWAYS_SEND:
|
||||
{
|
||||
cert_payload_t *payload;
|
||||
enumerator_t *enumerator;
|
||||
certificate_t *cert;
|
||||
auth_rule_t type;
|
||||
auth_cfg_t *auth;
|
||||
|
||||
auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
|
||||
|
||||
/* get subject cert first, then issuing certificates */
|
||||
cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
|
||||
if (!cert)
|
||||
if (add_subject_cert(this, auth, message))
|
||||
{
|
||||
break;
|
||||
add_im_certs(this, auth, message);
|
||||
add_attribute_certs(this, auth, message);
|
||||
}
|
||||
payload = build_cert_payload(this, cert);
|
||||
if (!payload)
|
||||
{
|
||||
break;
|
||||
}
|
||||
DBG1(DBG_IKE, "sending end entity cert \"%Y\"",
|
||||
cert->get_subject(cert));
|
||||
message->add_payload(message, (payload_t*)payload);
|
||||
|
||||
enumerator = auth->create_enumerator(auth);
|
||||
while (enumerator->enumerate(enumerator, &type, &cert))
|
||||
{
|
||||
if (type == AUTH_RULE_IM_CERT)
|
||||
{
|
||||
payload = cert_payload_create_from_cert(CERTIFICATE, cert);
|
||||
if (payload)
|
||||
{
|
||||
DBG1(DBG_IKE, "sending issuer cert \"%Y\"",
|
||||
cert->get_subject(cert));
|
||||
message->add_payload(message, (payload_t*)payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -259,6 +259,30 @@ static void process_crl(cert_payload_t *payload, auth_cfg_t *auth)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an attribute certificate payload
|
||||
*/
|
||||
static void process_ac(cert_payload_t *payload, auth_cfg_t *auth)
|
||||
{
|
||||
certificate_t *cert;
|
||||
|
||||
cert = payload->get_cert(payload);
|
||||
if (cert)
|
||||
{
|
||||
if (cert->get_issuer(cert))
|
||||
{
|
||||
DBG1(DBG_IKE, "received attribute certificate issued by \"%Y\"",
|
||||
cert->get_issuer(cert));
|
||||
}
|
||||
else if (cert->get_subject(cert))
|
||||
{
|
||||
DBG1(DBG_IKE, "received attribute certificate for \"%Y\"",
|
||||
cert->get_subject(cert));
|
||||
}
|
||||
auth->add(auth, AUTH_HELPER_AC_CERT, cert);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process certificate payloads
|
||||
*/
|
||||
|
@ -298,13 +322,15 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message)
|
|||
case ENC_CRL:
|
||||
process_crl(cert_payload, auth);
|
||||
break;
|
||||
case ENC_X509_ATTRIBUTE:
|
||||
process_ac(cert_payload, auth);
|
||||
break;
|
||||
case ENC_PKCS7_WRAPPED_X509:
|
||||
case ENC_PGP:
|
||||
case ENC_DNS_SIGNED_KEY:
|
||||
case ENC_KERBEROS_TOKEN:
|
||||
case ENC_ARL:
|
||||
case ENC_SPKI:
|
||||
case ENC_X509_ATTRIBUTE:
|
||||
case ENC_RAW_RSA_KEY:
|
||||
case ENC_X509_HASH_AND_URL_BUNDLE:
|
||||
case ENC_OCSP_CONTENT:
|
||||
|
|
|
@ -20,7 +20,7 @@ credentials/keys/public_key.c credentials/keys/shared_key.c \
|
|||
credentials/certificates/certificate.c credentials/certificates/crl.c \
|
||||
credentials/certificates/ocsp_response.c \
|
||||
credentials/containers/container.c credentials/containers/pkcs12.c \
|
||||
credentials/ietf_attributes/ietf_attributes.c credentials/credential_manager.c \
|
||||
credentials/credential_manager.c \
|
||||
credentials/sets/auth_cfg_wrapper.c credentials/sets/ocsp_response_wrapper.c \
|
||||
credentials/sets/cert_cache.c credentials/sets/mem_cred.c \
|
||||
credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \
|
||||
|
|
|
@ -18,7 +18,7 @@ credentials/keys/public_key.c credentials/keys/shared_key.c \
|
|||
credentials/certificates/certificate.c credentials/certificates/crl.c \
|
||||
credentials/certificates/ocsp_response.c \
|
||||
credentials/containers/container.c credentials/containers/pkcs12.c \
|
||||
credentials/ietf_attributes/ietf_attributes.c credentials/credential_manager.c \
|
||||
credentials/credential_manager.c \
|
||||
credentials/sets/auth_cfg_wrapper.c credentials/sets/ocsp_response_wrapper.c \
|
||||
credentials/sets/cert_cache.c credentials/sets/mem_cred.c \
|
||||
credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \
|
||||
|
@ -61,7 +61,6 @@ credentials/certificates/ocsp_response.h \
|
|||
credentials/certificates/pgp_certificate.h \
|
||||
credentials/containers/container.h credentials/containers/pkcs7.h \
|
||||
credentials/containers/pkcs12.h \
|
||||
credentials/ietf_attributes/ietf_attributes.h \
|
||||
credentials/credential_manager.h credentials/sets/auth_cfg_wrapper.h \
|
||||
credentials/sets/ocsp_response_wrapper.h credentials/sets/cert_cache.h \
|
||||
credentials/sets/mem_cred.h credentials/sets/callback_cred.h \
|
||||
|
@ -308,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
|
||||
|
|
|
@ -31,7 +31,7 @@ ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_XAUTH,
|
|||
"XAuth",
|
||||
);
|
||||
|
||||
ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT,
|
||||
ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_AC_CERT,
|
||||
"RULE_IDENTITY",
|
||||
"RULE_IDENTITY_LOOSE",
|
||||
"RULE_AUTH_CLASS",
|
||||
|
@ -56,6 +56,7 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT,
|
|||
"HELPER_IM_HASH_URL",
|
||||
"HELPER_SUBJECT_HASH_URL",
|
||||
"HELPER_REVOCATION_CERT",
|
||||
"HELPER_AC_CERT",
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -91,6 +92,7 @@ static inline bool is_multi_value_rule(auth_rule_t type)
|
|||
case AUTH_HELPER_IM_CERT:
|
||||
case AUTH_HELPER_IM_HASH_URL:
|
||||
case AUTH_HELPER_REVOCATION_CERT:
|
||||
case AUTH_HELPER_AC_CERT:
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
@ -224,6 +226,7 @@ static void init_entry(entry_t *this, auth_rule_t type, va_list args)
|
|||
case AUTH_HELPER_IM_HASH_URL:
|
||||
case AUTH_HELPER_SUBJECT_HASH_URL:
|
||||
case AUTH_HELPER_REVOCATION_CERT:
|
||||
case AUTH_HELPER_AC_CERT:
|
||||
/* pointer type */
|
||||
this->value = va_arg(args, void*);
|
||||
break;
|
||||
|
@ -262,6 +265,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2)
|
|||
case AUTH_HELPER_IM_CERT:
|
||||
case AUTH_HELPER_SUBJECT_CERT:
|
||||
case AUTH_HELPER_REVOCATION_CERT:
|
||||
case AUTH_HELPER_AC_CERT:
|
||||
{
|
||||
certificate_t *c1, *c2;
|
||||
|
||||
|
@ -319,6 +323,7 @@ static void destroy_entry_value(entry_t *entry)
|
|||
case AUTH_HELPER_IM_CERT:
|
||||
case AUTH_HELPER_SUBJECT_CERT:
|
||||
case AUTH_HELPER_REVOCATION_CERT:
|
||||
case AUTH_HELPER_AC_CERT:
|
||||
{
|
||||
certificate_t *cert = (certificate_t*)entry->value;
|
||||
cert->destroy(cert);
|
||||
|
@ -390,6 +395,7 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
|
|||
case AUTH_HELPER_IM_HASH_URL:
|
||||
case AUTH_HELPER_SUBJECT_HASH_URL:
|
||||
case AUTH_HELPER_REVOCATION_CERT:
|
||||
case AUTH_HELPER_AC_CERT:
|
||||
/* pointer type */
|
||||
entry->value = va_arg(args, void*);
|
||||
break;
|
||||
|
@ -467,6 +473,7 @@ METHOD(auth_cfg_t, get, void*,
|
|||
case AUTH_HELPER_IM_HASH_URL:
|
||||
case AUTH_HELPER_SUBJECT_HASH_URL:
|
||||
case AUTH_HELPER_REVOCATION_CERT:
|
||||
case AUTH_HELPER_AC_CERT:
|
||||
case AUTH_RULE_MAX:
|
||||
break;
|
||||
}
|
||||
|
@ -736,6 +743,7 @@ METHOD(auth_cfg_t, complies, bool,
|
|||
case AUTH_HELPER_IM_HASH_URL:
|
||||
case AUTH_HELPER_SUBJECT_HASH_URL:
|
||||
case AUTH_HELPER_REVOCATION_CERT:
|
||||
case AUTH_HELPER_AC_CERT:
|
||||
case AUTH_RULE_MAX:
|
||||
/* skip helpers */
|
||||
continue;
|
||||
|
@ -868,6 +876,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
|
|||
case AUTH_HELPER_IM_CERT:
|
||||
case AUTH_HELPER_SUBJECT_CERT:
|
||||
case AUTH_HELPER_REVOCATION_CERT:
|
||||
case AUTH_HELPER_AC_CERT:
|
||||
{
|
||||
certificate_t *cert = (certificate_t*)value;
|
||||
|
||||
|
@ -1029,6 +1038,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
|
|||
case AUTH_HELPER_IM_CERT:
|
||||
case AUTH_HELPER_SUBJECT_CERT:
|
||||
case AUTH_HELPER_REVOCATION_CERT:
|
||||
case AUTH_HELPER_AC_CERT:
|
||||
{
|
||||
certificate_t *cert = (certificate_t*)value;
|
||||
clone->add(clone, type, cert->get_ref(cert));
|
||||
|
|
|
@ -117,6 +117,8 @@ enum auth_rule_t {
|
|||
AUTH_HELPER_SUBJECT_HASH_URL,
|
||||
/** revocation certificate (CRL, OCSP), certificate_t* */
|
||||
AUTH_HELPER_REVOCATION_CERT,
|
||||
/** attribute certificate for authorization decisions, certificate_t */
|
||||
AUTH_HELPER_AC_CERT,
|
||||
|
||||
/** helper to determine the number of elements in this enum */
|
||||
AUTH_RULE_MAX,
|
||||
|
|
|
@ -38,7 +38,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
|
|||
"BUILD_SERIAL",
|
||||
"BUILD_DIGEST_ALG",
|
||||
"BUILD_ENCRYPTION_ALG",
|
||||
"BUILD_IETF_GROUP_ATTR",
|
||||
"BUILD_AC_GROUP_STRINGS",
|
||||
"BUILD_CA_CERT",
|
||||
"BUILD_CERT",
|
||||
"BUILD_CRL_DISTRIBUTION_POINTS",
|
||||
|
@ -72,4 +72,3 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
|
|||
"BUILD_THRESHOLD",
|
||||
"BUILD_END",
|
||||
);
|
||||
|
||||
|
|
|
@ -87,8 +87,8 @@ enum builder_part_t {
|
|||
BUILD_DIGEST_ALG,
|
||||
/** encryption algorithm to use, encryption_algorithm_t */
|
||||
BUILD_ENCRYPTION_ALG,
|
||||
/** a comma-separated list of ietf group attributes, char* */
|
||||
BUILD_IETF_GROUP_ATTR,
|
||||
/** list of AC group memberships, linked_list_t* with char* */
|
||||
BUILD_AC_GROUP_STRINGS,
|
||||
/** a ca certificate, certificate_t* */
|
||||
BUILD_CA_CERT,
|
||||
/** a certificate, certificate_t* */
|
||||
|
|
|
@ -24,9 +24,18 @@
|
|||
|
||||
#include <library.h>
|
||||
#include <credentials/certificates/certificate.h>
|
||||
#include <credentials/ietf_attributes/ietf_attributes.h>
|
||||
|
||||
typedef struct ac_t ac_t;
|
||||
typedef enum ac_group_type_t ac_group_type_t;
|
||||
|
||||
/**
|
||||
* Common group types, from IETF Attributes Syntax
|
||||
*/
|
||||
enum ac_group_type_t {
|
||||
AC_GROUP_TYPE_OCTETS,
|
||||
AC_GROUP_TYPE_STRING,
|
||||
AC_GROUP_TYPE_OID,
|
||||
};
|
||||
|
||||
/**
|
||||
* X.509 attribute certificate interface.
|
||||
|
@ -70,19 +79,11 @@ struct ac_t {
|
|||
chunk_t (*get_authKeyIdentifier)(ac_t *this);
|
||||
|
||||
/**
|
||||
* Get the group memberships as a list of IETF attributes
|
||||
* Create an enumerator of contained Group memberships.
|
||||
*
|
||||
* @return object containing a list of IETF attributes
|
||||
* @return enumerator over (ac_group_type_t, chunk_t)
|
||||
*/
|
||||
ietf_attributes_t* (*get_groups)(ac_t *this);
|
||||
|
||||
/**
|
||||
* @brief Checks if two attribute certificates belong to the same holder
|
||||
*
|
||||
* @param that other attribute certificate
|
||||
* @return TRUE if same holder
|
||||
*/
|
||||
bool (*equals_holder) (ac_t *this, ac_t *other);
|
||||
enumerator_t* (*create_group_enumerator)(ac_t *this);
|
||||
};
|
||||
|
||||
#endif /** AC_H_ @}*/
|
||||
|
|
|
@ -1,534 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 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 <asn1/oid.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/asn1_parser.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/lexparser.h>
|
||||
|
||||
#include "ietf_attributes.h"
|
||||
|
||||
/**
|
||||
* Private definition of IETF attribute types
|
||||
*/
|
||||
typedef enum {
|
||||
IETF_ATTRIBUTE_OCTETS = 0,
|
||||
IETF_ATTRIBUTE_OID = 1,
|
||||
IETF_ATTRIBUTE_STRING = 2
|
||||
} ietf_attribute_type_t;
|
||||
|
||||
typedef struct ietf_attr_t ietf_attr_t;
|
||||
|
||||
/**
|
||||
* Private definition of an IETF attribute
|
||||
*/
|
||||
struct ietf_attr_t {
|
||||
/**
|
||||
* IETF attribute type
|
||||
*/
|
||||
ietf_attribute_type_t type;
|
||||
|
||||
/**
|
||||
* IETF attribute value
|
||||
*/
|
||||
chunk_t value;
|
||||
|
||||
/**
|
||||
* Compares two IETF attributes
|
||||
*
|
||||
* return -1 if this is earlier in the alphabet than other
|
||||
* return 0 if this equals other
|
||||
* return +1 if this is later in the alphabet than other
|
||||
*
|
||||
* @param other other object
|
||||
*/
|
||||
int (*compare) (ietf_attr_t *this, ietf_attr_t *other);
|
||||
|
||||
/**
|
||||
* Destroys an ietf_attr_t object.
|
||||
*/
|
||||
void (*destroy) (ietf_attr_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements ietf_attr_t.compare.
|
||||
*/
|
||||
static int ietf_attr_compare(ietf_attr_t *this, ietf_attr_t *other)
|
||||
{
|
||||
int cmp_len, len, cmp_value;
|
||||
|
||||
/* OID attributes are appended after STRING and OCTETS attributes */
|
||||
if (this->type != IETF_ATTRIBUTE_OID && other->type == IETF_ATTRIBUTE_OID)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (this->type == IETF_ATTRIBUTE_OID && other->type != IETF_ATTRIBUTE_OID)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
cmp_len = this->value.len - other->value.len;
|
||||
len = (cmp_len < 0) ? this->value.len : other->value.len;
|
||||
cmp_value = memcmp(this->value.ptr, other->value.ptr, len);
|
||||
|
||||
return (cmp_value == 0) ? cmp_len : cmp_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements ietf_attr_t.destroy.
|
||||
*/
|
||||
static void ietf_attr_destroy(ietf_attr_t *this)
|
||||
{
|
||||
free(this->value.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ietf_attr_t object.
|
||||
*/
|
||||
static ietf_attr_t* ietf_attr_create(ietf_attribute_type_t type, chunk_t value)
|
||||
{
|
||||
ietf_attr_t *this;
|
||||
|
||||
INIT(this,
|
||||
.compare = ietf_attr_compare,
|
||||
.destroy = ietf_attr_destroy,
|
||||
.type = type,
|
||||
.value = chunk_clone(value),
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
typedef struct private_ietf_attributes_t private_ietf_attributes_t;
|
||||
|
||||
/**
|
||||
* Private data of an ietf_attributes_t object.
|
||||
*/
|
||||
struct private_ietf_attributes_t {
|
||||
/**
|
||||
* Public interface.
|
||||
*/
|
||||
ietf_attributes_t public;
|
||||
|
||||
/**
|
||||
* Printable representation of the IETF attributes
|
||||
*/
|
||||
char *string;
|
||||
|
||||
/**
|
||||
* Linked list of IETF attributes.
|
||||
*/
|
||||
linked_list_t *list;
|
||||
|
||||
/**
|
||||
* reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
METHOD(ietf_attributes_t, get_string, char*,
|
||||
private_ietf_attributes_t *this)
|
||||
{
|
||||
if (this->string == NULL)
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
char *pos = buf;
|
||||
int len = BUF_LEN;
|
||||
bool first = TRUE;
|
||||
ietf_attr_t *attr;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
int written;
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
written = snprintf(pos, len, ", ");
|
||||
if (written < 0 || written >= len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += written;
|
||||
len -= written;
|
||||
}
|
||||
|
||||
switch (attr->type)
|
||||
{
|
||||
case IETF_ATTRIBUTE_OCTETS:
|
||||
case IETF_ATTRIBUTE_STRING:
|
||||
written = snprintf(pos, len, "%.*s", (int)attr->value.len,
|
||||
attr->value.ptr);
|
||||
break;
|
||||
case IETF_ATTRIBUTE_OID:
|
||||
{
|
||||
int oid = asn1_known_oid(attr->value);
|
||||
|
||||
if (oid == OID_UNKNOWN)
|
||||
{
|
||||
written = snprintf(pos, len, "0x%#B", &attr->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
written = snprintf(pos, len, "%s", oid_names[oid].name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
written = 0;
|
||||
break;
|
||||
}
|
||||
if (written < 0 || written >= len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pos += written;
|
||||
len -= written;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
if (len < BUF_LEN)
|
||||
{
|
||||
this->string = strdup(buf);
|
||||
}
|
||||
}
|
||||
return this->string;
|
||||
}
|
||||
|
||||
METHOD(ietf_attributes_t, get_encoding, chunk_t,
|
||||
private_ietf_attributes_t *this)
|
||||
{
|
||||
chunk_t values;
|
||||
size_t size = 0;
|
||||
u_char *pos;
|
||||
ietf_attr_t *attr;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
/* precalculate the total size of all values */
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
size_t len = attr->value.len;
|
||||
|
||||
size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
pos = asn1_build_object(&values, ASN1_SEQUENCE, size);
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
chunk_t ietfAttribute;
|
||||
asn1_t type = ASN1_NULL;
|
||||
|
||||
switch (attr->type)
|
||||
{
|
||||
case IETF_ATTRIBUTE_OCTETS:
|
||||
type = ASN1_OCTET_STRING;
|
||||
break;
|
||||
case IETF_ATTRIBUTE_STRING:
|
||||
type = ASN1_UTF8STRING;
|
||||
break;
|
||||
case IETF_ATTRIBUTE_OID:
|
||||
type = ASN1_OID;
|
||||
break;
|
||||
}
|
||||
ietfAttribute = asn1_simple_object(type, attr->value);
|
||||
|
||||
/* copy ietfAttribute into values chunk */
|
||||
memcpy(pos, ietfAttribute.ptr, ietfAttribute.len);
|
||||
pos += ietfAttribute.len;
|
||||
free(ietfAttribute.ptr);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return asn1_wrap(ASN1_SEQUENCE, "m", values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ietf_attributes_t.equals.
|
||||
*/
|
||||
static bool equals(private_ietf_attributes_t *this,
|
||||
private_ietf_attributes_t *other)
|
||||
{
|
||||
bool result = TRUE;
|
||||
|
||||
/* lists must have the same number of attributes */
|
||||
if (other == NULL ||
|
||||
this->list->get_count(this->list) != other->list->get_count(other->list))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* compare two alphabetically-sorted lists */
|
||||
{
|
||||
ietf_attr_t *attr_a, *attr_b;
|
||||
enumerator_t *enum_a, *enum_b;
|
||||
|
||||
enum_a = this->list->create_enumerator(this->list);
|
||||
enum_b = other->list->create_enumerator(other->list);
|
||||
while (enum_a->enumerate(enum_a, &attr_a) &&
|
||||
enum_b->enumerate(enum_b, &attr_b))
|
||||
{
|
||||
if (attr_a->compare(attr_a, attr_b) != 0)
|
||||
{
|
||||
/* we have a mismatch */
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enum_a->destroy(enum_a);
|
||||
enum_b->destroy(enum_b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of ietf_attributes_t.matches.
|
||||
*/
|
||||
static bool matches(private_ietf_attributes_t *this,
|
||||
private_ietf_attributes_t *other)
|
||||
{
|
||||
bool result = FALSE;
|
||||
ietf_attr_t *attr_a, *attr_b;
|
||||
enumerator_t *enum_a, *enum_b;
|
||||
|
||||
/* always match if this->list does not contain any attributes */
|
||||
if (this->list->get_count(this->list) == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* never match if other->list does not contain any attributes */
|
||||
if (other == NULL || other->list->get_count(other->list) == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* get first attribute from both lists */
|
||||
enum_a = this->list->create_enumerator(this->list);
|
||||
enum_a->enumerate(enum_a, &attr_a);
|
||||
enum_b = other->list->create_enumerator(other->list);
|
||||
enum_b->enumerate(enum_b, &attr_b);
|
||||
|
||||
/* look for at least one common attribute */
|
||||
while (TRUE)
|
||||
{
|
||||
int cmp = attr_a->compare(attr_a, attr_b);
|
||||
|
||||
if (cmp == 0)
|
||||
{
|
||||
/* we have a match */
|
||||
result = TRUE;
|
||||
break;
|
||||
}
|
||||
if (cmp == -1)
|
||||
{
|
||||
/* attr_a is earlier in the alphabet, get next attr_a */
|
||||
if (!enum_a->enumerate(enum_a, &attr_a))
|
||||
{
|
||||
/* we have reached the end of enum_a */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* attr_a is later in the alphabet, get next attr_b */
|
||||
if (!enum_b->enumerate(enum_b, &attr_b))
|
||||
{
|
||||
/* we have reached the end of enum_b */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
enum_a->destroy(enum_a);
|
||||
enum_b->destroy(enum_b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(ietf_attributes_t, get_ref, ietf_attributes_t*,
|
||||
private_ietf_attributes_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
METHOD(ietf_attributes_t, destroy, void,
|
||||
private_ietf_attributes_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
this->list->destroy_offset(this->list, offsetof(ietf_attr_t, destroy));
|
||||
free(this->string);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
static private_ietf_attributes_t* create_empty(void)
|
||||
{
|
||||
private_ietf_attributes_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_string = _get_string,
|
||||
.get_encoding = _get_encoding,
|
||||
.equals = (bool (*)(ietf_attributes_t*,ietf_attributes_t*))equals,
|
||||
.matches = (bool (*)(ietf_attributes_t*,ietf_attributes_t*))matches,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.list = linked_list_create(),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an ietf_attr_t object to a sorted linked list
|
||||
*/
|
||||
static void ietf_attributes_add(private_ietf_attributes_t *this,
|
||||
ietf_attr_t *attr)
|
||||
{
|
||||
ietf_attr_t *current_attr;
|
||||
enumerator_t *enumerator;
|
||||
int cmp = -1;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, (void **)¤t_attr) &&
|
||||
(cmp = attr->compare(attr, current_attr)) > 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (cmp == 0)
|
||||
{
|
||||
attr->destroy(attr);
|
||||
}
|
||||
else
|
||||
{ /* the enumerator either points to the end or to the attribute > attr */
|
||||
this->list->insert_before(this->list, enumerator, attr);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
ietf_attributes_t *ietf_attributes_create_from_string(char *string)
|
||||
{
|
||||
private_ietf_attributes_t *this = create_empty();
|
||||
|
||||
chunk_t line = { string, strlen(string) };
|
||||
|
||||
while (eat_whitespace(&line))
|
||||
{
|
||||
chunk_t group;
|
||||
|
||||
/* extract the next comma-separated group attribute */
|
||||
if (!extract_token(&group, ',', &line))
|
||||
{
|
||||
group = line;
|
||||
line.len = 0;
|
||||
}
|
||||
|
||||
/* remove any trailing spaces */
|
||||
while (group.len > 0 && *(group.ptr + group.len - 1) == ' ')
|
||||
{
|
||||
group.len--;
|
||||
}
|
||||
|
||||
/* add the group attribute to the list */
|
||||
if (group.len > 0)
|
||||
{
|
||||
ietf_attr_t *attr = ietf_attr_create(IETF_ATTRIBUTE_STRING, group);
|
||||
|
||||
ietf_attributes_add(this, attr);
|
||||
}
|
||||
}
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
||||
/**
|
||||
* ASN.1 definition of ietfAttrSyntax
|
||||
*/
|
||||
static const asn1Object_t ietfAttrSyntaxObjects[] =
|
||||
{
|
||||
{ 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
|
||||
{ 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
|
||||
ASN1_BODY }, /* 1 */
|
||||
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
|
||||
{ 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */
|
||||
{ 2, "octets", ASN1_OCTET_STRING, ASN1_OPT |
|
||||
ASN1_BODY }, /* 4 */
|
||||
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
|
||||
{ 2, "oid", ASN1_OID, ASN1_OPT |
|
||||
ASN1_BODY }, /* 6 */
|
||||
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
|
||||
{ 2, "string", ASN1_UTF8STRING, ASN1_OPT |
|
||||
ASN1_BODY }, /* 8 */
|
||||
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
|
||||
{ 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
|
||||
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
||||
};
|
||||
#define IETF_ATTR_OCTETS 4
|
||||
#define IETF_ATTR_OID 6
|
||||
#define IETF_ATTR_STRING 8
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
ietf_attributes_t *ietf_attributes_create_from_encoding(chunk_t encoded)
|
||||
{
|
||||
private_ietf_attributes_t *this = create_empty();
|
||||
asn1_parser_t *parser;
|
||||
chunk_t object;
|
||||
int objectID;
|
||||
|
||||
parser = asn1_parser_create(ietfAttrSyntaxObjects, encoded);
|
||||
while (parser->iterate(parser, &objectID, &object))
|
||||
{
|
||||
switch (objectID)
|
||||
{
|
||||
case IETF_ATTR_OCTETS:
|
||||
case IETF_ATTR_OID:
|
||||
case IETF_ATTR_STRING:
|
||||
{
|
||||
ietf_attribute_type_t type;
|
||||
ietf_attr_t *attr;
|
||||
|
||||
type = (objectID - IETF_ATTR_OCTETS) / 2;
|
||||
attr = ietf_attr_create(type, object);
|
||||
ietf_attributes_add(this, attr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
parser->destroy(parser);
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2007-2009 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 ietf_attributes ietf_attributes
|
||||
* @{ @ingroup credentials
|
||||
*/
|
||||
|
||||
#ifndef IETF_ATTRIBUTES_H_
|
||||
#define IETF_ATTRIBUTES_H_
|
||||
|
||||
typedef struct ietf_attributes_t ietf_attributes_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
struct ietf_attributes_t {
|
||||
|
||||
/**
|
||||
* Get the an alphabetically sorted list of printable IETF attributes.
|
||||
*
|
||||
* Result points to internal data, do not free.
|
||||
*
|
||||
* @return a string containing printable attributes
|
||||
*/
|
||||
char* (*get_string) (ietf_attributes_t *this);
|
||||
|
||||
/**
|
||||
* Get the ASN.1 encoding of the IETF attributes.
|
||||
*
|
||||
* @return allocated chunk containing the encoded bytes
|
||||
*/
|
||||
chunk_t (*get_encoding) (ietf_attributes_t *this);
|
||||
|
||||
/**
|
||||
* Check for equality between two lists.
|
||||
*
|
||||
* @param other attribute list to be checked for equality
|
||||
* @return TRUE if equal
|
||||
*/
|
||||
bool (*equals) (ietf_attributes_t *this, ietf_attributes_t *other);
|
||||
|
||||
/**
|
||||
* Check for common attributes between two lists.
|
||||
*
|
||||
* @param other attribute list to be matched
|
||||
* @return TRUE if there is at least a common attribute
|
||||
*/
|
||||
bool (*matches) (ietf_attributes_t *this, ietf_attributes_t *other);
|
||||
|
||||
/**
|
||||
* Get a new reference to the IETF attributes.
|
||||
*
|
||||
* @return this, with an increased refcount
|
||||
*/
|
||||
ietf_attributes_t* (*get_ref)(ietf_attributes_t *this);
|
||||
|
||||
/**
|
||||
* Destroys an ietf_attributes_t object.
|
||||
*/
|
||||
void (*destroy) (ietf_attributes_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param string input string, which will be converted
|
||||
* @return ietf_attributes_t
|
||||
*/
|
||||
ietf_attributes_t *ietf_attributes_create_from_string(char *string);
|
||||
|
||||
/**
|
||||
* @param encoded ASN.1 encoded bytes, such as from ietf_attributes.get_encoding
|
||||
* @return ietf_attributes_t
|
||||
*/
|
||||
ietf_attributes_t *ietf_attributes_create_from_encoding(chunk_t encoded);
|
||||
|
||||
#endif /** IETF_ATTRIBUTES_H_ @}*/
|
||||
|
|
@ -133,7 +133,8 @@ static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
|
|||
}
|
||||
else if (rule != AUTH_HELPER_SUBJECT_CERT &&
|
||||
rule != AUTH_HELPER_IM_CERT &&
|
||||
rule != AUTH_HELPER_REVOCATION_CERT)
|
||||
rule != AUTH_HELPER_REVOCATION_CERT &&
|
||||
rule != AUTH_HELPER_AC_CERT)
|
||||
{ /* handle only HELPER certificates */
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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_ @}*/
|
|
@ -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;
|
||||
}
|
|
@ -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_ @}*/
|
|
@ -106,6 +106,12 @@ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
|
|||
label = "CERTIFICATE REQUEST";
|
||||
break;
|
||||
}
|
||||
if (cred_encoding_args(args, CRED_PART_X509_AC_ASN1_DER,
|
||||
&asn1, CRED_PART_END))
|
||||
{
|
||||
label = "ATTRIBUTE CERTIFICATE";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -154,4 +160,3 @@ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
|
|||
encoding->len = pos - encoding->ptr;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <utils/identification.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
#include <credentials/ietf_attributes/ietf_attributes.h>
|
||||
#include <credentials/keys/private_key.h>
|
||||
|
||||
extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob,
|
||||
|
@ -75,7 +74,7 @@ struct private_x509_ac_t {
|
|||
/**
|
||||
* Serial number of the holder certificate
|
||||
*/
|
||||
chunk_t holderSerial;
|
||||
identification_t *holderSerial;
|
||||
|
||||
/**
|
||||
* ID representing the holder
|
||||
|
@ -98,14 +97,9 @@ struct private_x509_ac_t {
|
|||
time_t notAfter;
|
||||
|
||||
/**
|
||||
* List of charging attributes
|
||||
* List of group attributes, as group_t
|
||||
*/
|
||||
ietf_attributes_t *charging;
|
||||
|
||||
/**
|
||||
* List of groub attributes
|
||||
*/
|
||||
ietf_attributes_t *groups;
|
||||
linked_list_t *groups;
|
||||
|
||||
/**
|
||||
* Authority Key Identifier
|
||||
|
@ -153,6 +147,25 @@ struct private_x509_ac_t {
|
|||
refcount_t ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* Group definition, an IETF attribute
|
||||
*/
|
||||
typedef struct {
|
||||
/** Attribute type */
|
||||
ac_group_type_t type;
|
||||
/* attribute value */
|
||||
chunk_t value;
|
||||
} group_t;
|
||||
|
||||
/**
|
||||
* Clean up a group entry
|
||||
*/
|
||||
static void group_destroy(group_t *group)
|
||||
{
|
||||
free(group->value.ptr);
|
||||
free(group);
|
||||
}
|
||||
|
||||
static chunk_t ASN1_noRevAvail_ext = chunk_from_chars(
|
||||
0x30, 0x09,
|
||||
0x06, 0x03,
|
||||
|
@ -169,42 +182,41 @@ extern void x509_parse_generalNames(chunk_t blob, int level0, bool implicit,
|
|||
/**
|
||||
* parses a directoryName
|
||||
*/
|
||||
static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name)
|
||||
static bool parse_directoryName(chunk_t blob, int level, bool implicit,
|
||||
identification_t **name)
|
||||
{
|
||||
bool has_directoryName;
|
||||
linked_list_t *list = linked_list_create();
|
||||
identification_t *directoryName;
|
||||
enumerator_t *enumerator;
|
||||
bool first = TRUE;
|
||||
linked_list_t *list;
|
||||
|
||||
list = linked_list_create();
|
||||
x509_parse_generalNames(blob, level, implicit, list);
|
||||
has_directoryName = list->get_count(list) > 0;
|
||||
|
||||
if (has_directoryName)
|
||||
enumerator = list->create_enumerator(list);
|
||||
while (enumerator->enumerate(enumerator, &directoryName))
|
||||
{
|
||||
enumerator_t *enumerator = list->create_enumerator(list);
|
||||
identification_t *directoryName;
|
||||
bool first = TRUE;
|
||||
|
||||
while (enumerator->enumerate(enumerator, (void**)&directoryName))
|
||||
if (first)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
*name = directoryName;
|
||||
first = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_ASN, "more than one directory name - first selected");
|
||||
directoryName->destroy(directoryName);
|
||||
}
|
||||
*name = directoryName;
|
||||
first = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_ASN, "more than one directory name - first selected");
|
||||
directoryName->destroy(directoryName);
|
||||
break;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
else
|
||||
enumerator->destroy(enumerator);
|
||||
list->destroy(list);
|
||||
|
||||
if (first)
|
||||
{
|
||||
DBG1(DBG_ASN, "no directoryName found");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
list->destroy(list);
|
||||
return has_directoryName;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -243,6 +255,74 @@ static void parse_roleSyntax(chunk_t blob, int level0)
|
|||
parser->destroy(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* ASN.1 definition of ietfAttrSyntax
|
||||
*/
|
||||
static const asn1Object_t ietfAttrSyntaxObjects[] =
|
||||
{
|
||||
{ 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
|
||||
{ 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
|
||||
ASN1_BODY }, /* 1 */
|
||||
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
|
||||
{ 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */
|
||||
{ 2, "octets", ASN1_OCTET_STRING, ASN1_OPT |
|
||||
ASN1_BODY }, /* 4 */
|
||||
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
|
||||
{ 2, "oid", ASN1_OID, ASN1_OPT |
|
||||
ASN1_BODY }, /* 6 */
|
||||
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
|
||||
{ 2, "string", ASN1_UTF8STRING, ASN1_OPT |
|
||||
ASN1_BODY }, /* 8 */
|
||||
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
|
||||
{ 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
|
||||
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
||||
};
|
||||
#define IETF_ATTR_OCTETS 4
|
||||
#define IETF_ATTR_OID 6
|
||||
#define IETF_ATTR_STRING 8
|
||||
|
||||
/**
|
||||
* Parse group memberships, IETF attributes
|
||||
*/
|
||||
static bool parse_groups(private_x509_ac_t *this, chunk_t encoded, int level0)
|
||||
{
|
||||
ac_group_type_t type;
|
||||
group_t *group;
|
||||
asn1_parser_t *parser;
|
||||
chunk_t object;
|
||||
int objectID;
|
||||
bool success;
|
||||
|
||||
parser = asn1_parser_create(ietfAttrSyntaxObjects, encoded);
|
||||
parser->set_top_level(parser, level0);
|
||||
while (parser->iterate(parser, &objectID, &object))
|
||||
{
|
||||
switch (objectID)
|
||||
{
|
||||
case IETF_ATTR_OCTETS:
|
||||
type = AC_GROUP_TYPE_OCTETS;
|
||||
break;
|
||||
case IETF_ATTR_OID:
|
||||
type = AC_GROUP_TYPE_OID;
|
||||
break;
|
||||
case IETF_ATTR_STRING:
|
||||
type = AC_GROUP_TYPE_STRING;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
INIT(group,
|
||||
.type = type,
|
||||
.value = chunk_clone(object),
|
||||
);
|
||||
this->groups->insert_last(this->groups, group);
|
||||
}
|
||||
success = parser->success(parser);
|
||||
parser->destroy(parser);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* ASN.1 definition of an X509 attribute certificate
|
||||
*/
|
||||
|
@ -250,57 +330,57 @@ static const asn1Object_t acObjects[] =
|
|||
{
|
||||
{ 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
|
||||
{ 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
|
||||
{ 2, "version", ASN1_INTEGER, ASN1_DEF |
|
||||
{ 2, "version", ASN1_INTEGER, ASN1_DEF |
|
||||
ASN1_BODY }, /* 2 */
|
||||
{ 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
|
||||
{ 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
|
||||
{ 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
|
||||
{ 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
|
||||
{ 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
|
||||
{ 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
|
||||
{ 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
|
||||
{ 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
|
||||
{ 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
|
||||
ASN1_BODY }, /* 7 */
|
||||
{ 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
|
||||
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
|
||||
{ 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
|
||||
{ 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
|
||||
ASN1_OBJ }, /* 10 */
|
||||
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
|
||||
{ 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
|
||||
{ 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */
|
||||
{ 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
|
||||
{ 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
|
||||
{ 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */
|
||||
{ 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
|
||||
ASN1_BODY }, /* 14 */
|
||||
{ 4, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
|
||||
{ 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */
|
||||
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
|
||||
{ 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
|
||||
{ 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
|
||||
{ 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
|
||||
{ 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
|
||||
ASN1_OBJ }, /* 19 */
|
||||
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
|
||||
{ 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
|
||||
{ 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
|
||||
{ 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
|
||||
{ 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
|
||||
{ 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
|
||||
{ 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
|
||||
{ 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
|
||||
{ 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
|
||||
{ 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
|
||||
ASN1_BODY }, /* 25 */
|
||||
{ 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
|
||||
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
|
||||
{ 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */
|
||||
{ 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
|
||||
{ 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
|
||||
{ 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
|
||||
{ 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
|
||||
{ 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
|
||||
{ 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
|
||||
ASN1_BODY }, /* 31 */
|
||||
{ 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */
|
||||
{ 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */
|
||||
{ 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */
|
||||
{ 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
|
||||
{ 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
|
||||
{ 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
|
||||
{ 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
|
||||
{ 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
|
||||
{ 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
|
||||
{ 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
|
||||
{ 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
|
||||
{ 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
|
||||
{ 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
|
||||
{ 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
|
||||
{ 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
|
||||
{ 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */
|
||||
{ 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */
|
||||
{ 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */
|
||||
{ 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */
|
||||
{ 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
|
||||
{ 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
|
||||
{ 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */
|
||||
{ 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */
|
||||
{ 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */
|
||||
|
@ -368,22 +448,26 @@ static bool parse_certificate(private_x509_ac_t *this)
|
|||
}
|
||||
break;
|
||||
case AC_OBJ_HOLDER_ISSUER:
|
||||
if (!parse_directoryName(object, level, FALSE, &this->holderIssuer))
|
||||
if (!parse_directoryName(object, level, FALSE,
|
||||
&this->holderIssuer))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
case AC_OBJ_HOLDER_SERIAL:
|
||||
this->holderSerial = object;
|
||||
this->holderSerial = identification_create_from_encoding(
|
||||
ID_KEY_ID, object);
|
||||
break;
|
||||
case AC_OBJ_ENTITY_NAME:
|
||||
if (!parse_directoryName(object, level, TRUE, &this->entityName))
|
||||
if (!parse_directoryName(object, level, TRUE,
|
||||
&this->entityName))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
case AC_OBJ_ISSUER_NAME:
|
||||
if (!parse_directoryName(object, level, FALSE, &this->issuerName))
|
||||
if (!parse_directoryName(object, level, FALSE,
|
||||
&this->issuerName))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
@ -414,13 +498,14 @@ static bool parse_certificate(private_x509_ac_t *this)
|
|||
DBG2(DBG_ASN, " need to parse accessIdentity");
|
||||
break;
|
||||
case OID_CHARGING_IDENTITY:
|
||||
DBG2(DBG_ASN, "-- > --");
|
||||
this->charging = ietf_attributes_create_from_encoding(object);
|
||||
DBG2(DBG_ASN, "-- < --");
|
||||
DBG2(DBG_ASN, " need to parse chargingIdentity");
|
||||
break;
|
||||
case OID_GROUP:
|
||||
DBG2(DBG_ASN, "-- > --");
|
||||
this->groups = ietf_attributes_create_from_encoding(object);
|
||||
if (!parse_groups(this, object, level))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
DBG2(DBG_ASN, "-- < --");
|
||||
break;
|
||||
case OID_ROLE:
|
||||
|
@ -446,8 +531,9 @@ static bool parse_certificate(private_x509_ac_t *this)
|
|||
DBG2(DBG_ASN, " need to parse crlDistributionPoints");
|
||||
break;
|
||||
case OID_AUTHORITY_KEY_ID:
|
||||
this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object,
|
||||
level, &this->authKeySerialNumber);
|
||||
this->authKeyIdentifier =
|
||||
x509_parse_authorityKeyIdentifier(object,
|
||||
level, &this->authKeySerialNumber);
|
||||
break;
|
||||
case OID_TARGET_INFORMATION:
|
||||
DBG2(DBG_ASN, " need to parse targetInformation");
|
||||
|
@ -490,7 +576,7 @@ end:
|
|||
static chunk_t build_directoryName(asn1_t tag, chunk_t name)
|
||||
{
|
||||
return asn1_wrap(tag, "m",
|
||||
asn1_simple_object(ASN1_CONTEXT_C_4, name));
|
||||
asn1_simple_object(ASN1_CONTEXT_C_4, name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -499,14 +585,15 @@ static chunk_t build_directoryName(asn1_t tag, chunk_t name)
|
|||
static chunk_t build_holder(private_x509_ac_t *this)
|
||||
{
|
||||
x509_t* x509 = (x509_t*)this->holderCert;
|
||||
identification_t *issuer = this->holderCert->get_issuer(this->holderCert);
|
||||
identification_t *subject = this->holderCert->get_subject(this->holderCert);
|
||||
identification_t *issuer, *subject;
|
||||
|
||||
issuer = this->holderCert->get_issuer(this->holderCert);
|
||||
subject = this->holderCert->get_subject(this->holderCert);
|
||||
|
||||
return asn1_wrap(ASN1_SEQUENCE, "mm",
|
||||
asn1_wrap(ASN1_CONTEXT_C_0, "mm",
|
||||
build_directoryName(ASN1_SEQUENCE, issuer->get_encoding(issuer)),
|
||||
asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509))
|
||||
),
|
||||
asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509))),
|
||||
build_directoryName(ASN1_CONTEXT_C_1, subject->get_encoding(subject)));
|
||||
}
|
||||
|
||||
|
@ -515,10 +602,12 @@ static chunk_t build_holder(private_x509_ac_t *this)
|
|||
*/
|
||||
static chunk_t build_v2_form(private_x509_ac_t *this)
|
||||
{
|
||||
identification_t *subject = this->signerCert->get_subject(this->signerCert);
|
||||
identification_t *subject;
|
||||
|
||||
subject = this->signerCert->get_subject(this->signerCert);
|
||||
return asn1_wrap(ASN1_CONTEXT_C_0, "m",
|
||||
build_directoryName(ASN1_SEQUENCE, subject->get_encoding(subject)));
|
||||
build_directoryName(ASN1_SEQUENCE,
|
||||
subject->get_encoding(subject)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -531,7 +620,6 @@ static chunk_t build_attr_cert_validity(private_x509_ac_t *this)
|
|||
asn1_from_time(&this->notAfter, ASN1_GENERALIZEDTIME));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* build attribute type
|
||||
*/
|
||||
|
@ -547,8 +635,55 @@ static chunk_t build_attribute_type(int type, chunk_t content)
|
|||
*/
|
||||
static chunk_t build_attributes(private_x509_ac_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
group_t *group;
|
||||
chunk_t values;
|
||||
size_t size = 0, len;
|
||||
u_char *pos;
|
||||
|
||||
/* precalculate the total size of all values */
|
||||
enumerator = this->groups->create_enumerator(this->groups);
|
||||
while (enumerator->enumerate(enumerator, &group))
|
||||
{
|
||||
len = group->value.len;
|
||||
size += 1 + (len > 0) + (len >= 128) +
|
||||
(len >= 256) + (len >= 65536) + len;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
pos = asn1_build_object(&values, ASN1_SEQUENCE, size);
|
||||
|
||||
enumerator = this->groups->create_enumerator(this->groups);
|
||||
while (enumerator->enumerate(enumerator, &group))
|
||||
{
|
||||
chunk_t attr;
|
||||
asn1_t type;
|
||||
|
||||
switch (group->type)
|
||||
{
|
||||
case AC_GROUP_TYPE_OCTETS:
|
||||
type = ASN1_OCTET_STRING;
|
||||
break;
|
||||
case AC_GROUP_TYPE_STRING:
|
||||
type = ASN1_UTF8STRING;
|
||||
break;
|
||||
case AC_GROUP_TYPE_OID:
|
||||
type = ASN1_OID;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
attr = asn1_simple_object(type, group->value);
|
||||
|
||||
memcpy(pos, attr.ptr, attr.len);
|
||||
pos += attr.len;
|
||||
free(attr.ptr);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return asn1_wrap(ASN1_SEQUENCE, "m",
|
||||
build_attribute_type(OID_GROUP, this->groups->get_encoding(this->groups)));
|
||||
build_attribute_type(OID_GROUP,
|
||||
asn1_wrap(ASN1_SEQUENCE, "m", values)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -621,14 +756,11 @@ static chunk_t build_attr_cert_info(private_x509_ac_t *this)
|
|||
*/
|
||||
static chunk_t build_ac(private_x509_ac_t *this)
|
||||
{
|
||||
chunk_t signatureValue;
|
||||
chunk_t attributeCertificateInfo;
|
||||
chunk_t signatureValue, attributeCertificateInfo;
|
||||
|
||||
attributeCertificateInfo = build_attr_cert_info(this);
|
||||
|
||||
this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1,
|
||||
attributeCertificateInfo, &signatureValue);
|
||||
|
||||
return asn1_wrap(ASN1_SEQUENCE, "mmm",
|
||||
attributeCertificateInfo,
|
||||
asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
|
||||
|
@ -644,7 +776,11 @@ METHOD(ac_t, get_serial, chunk_t,
|
|||
METHOD(ac_t, get_holderSerial, chunk_t,
|
||||
private_x509_ac_t *this)
|
||||
{
|
||||
return this->holderSerial;
|
||||
if (this->holderSerial)
|
||||
{
|
||||
return this->holderSerial->get_encoding(this->holderSerial);
|
||||
}
|
||||
return chunk_empty;
|
||||
}
|
||||
|
||||
METHOD(ac_t, get_holderIssuer, identification_t*,
|
||||
|
@ -659,10 +795,28 @@ METHOD(ac_t, get_authKeyIdentifier, chunk_t,
|
|||
return this->authKeyIdentifier;
|
||||
}
|
||||
|
||||
METHOD(ac_t, get_groups, ietf_attributes_t*,
|
||||
/**
|
||||
* Filter function for attribute enumeration
|
||||
*/
|
||||
static bool attr_filter(void *null, group_t **in, ac_group_type_t *type,
|
||||
void *in2, chunk_t *out)
|
||||
{
|
||||
if ((*in)->type == AC_GROUP_TYPE_STRING &&
|
||||
!chunk_printable((*in)->value, NULL, 0))
|
||||
{ /* skip non-printable strings */
|
||||
return FALSE;
|
||||
}
|
||||
*type = (*in)->type;
|
||||
*out = (*in)->value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(ac_t, create_group_enumerator, enumerator_t*,
|
||||
private_x509_ac_t *this)
|
||||
{
|
||||
return this->groups ? this->groups->get_ref(this->groups) : NULL;
|
||||
return enumerator_create_filter(
|
||||
this->groups->create_enumerator(this->groups),
|
||||
(void*)attr_filter, NULL, NULL);
|
||||
}
|
||||
|
||||
METHOD(certificate_t, get_type, certificate_type_t,
|
||||
|
@ -674,7 +828,11 @@ METHOD(certificate_t, get_type, certificate_type_t,
|
|||
METHOD(certificate_t, get_subject, identification_t*,
|
||||
private_x509_ac_t *this)
|
||||
{
|
||||
return this->entityName;
|
||||
if (this->entityName)
|
||||
{
|
||||
return this->entityName;
|
||||
}
|
||||
return this->holderSerial;
|
||||
}
|
||||
|
||||
METHOD(certificate_t, get_issuer, identification_t*,
|
||||
|
@ -686,13 +844,24 @@ METHOD(certificate_t, get_issuer, identification_t*,
|
|||
METHOD(certificate_t, has_subject, id_match_t,
|
||||
private_x509_ac_t *this, identification_t *subject)
|
||||
{
|
||||
return ID_MATCH_NONE;
|
||||
id_match_t entity = ID_MATCH_NONE, serial = ID_MATCH_NONE;
|
||||
|
||||
if (this->entityName)
|
||||
{
|
||||
entity = this->entityName->matches(this->entityName, subject);
|
||||
}
|
||||
if (this->holderSerial)
|
||||
{
|
||||
serial = this->holderSerial->matches(this->holderSerial, subject);
|
||||
}
|
||||
return max(entity, serial);
|
||||
}
|
||||
|
||||
METHOD(certificate_t, has_issuer, id_match_t,
|
||||
private_x509_ac_t *this, identification_t *issuer)
|
||||
{
|
||||
if (issuer->get_type(issuer) == ID_KEY_ID && this->authKeyIdentifier.ptr &&
|
||||
if (issuer->get_type(issuer) == ID_KEY_ID &&
|
||||
this->authKeyIdentifier.ptr &&
|
||||
chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer)))
|
||||
{
|
||||
return ID_MATCH_PERFECT;
|
||||
|
@ -808,9 +977,10 @@ METHOD(certificate_t, equals, bool,
|
|||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (other->equals == (void*)equals)
|
||||
if (other->equals == _equals)
|
||||
{ /* skip allocation if we have the same implementation */
|
||||
return chunk_equals(this->encoding, ((private_x509_ac_t*)other)->encoding);
|
||||
return chunk_equals(this->encoding,
|
||||
((private_x509_ac_t*)other)->encoding);
|
||||
}
|
||||
if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
|
||||
{
|
||||
|
@ -827,13 +997,13 @@ METHOD(certificate_t, destroy, void,
|
|||
if (ref_put(&this->ref))
|
||||
{
|
||||
DESTROY_IF(this->holderIssuer);
|
||||
DESTROY_IF(this->holderSerial);
|
||||
DESTROY_IF(this->entityName);
|
||||
DESTROY_IF(this->issuerName);
|
||||
DESTROY_IF(this->holderCert);
|
||||
DESTROY_IF(this->signerCert);
|
||||
DESTROY_IF(this->signerKey);
|
||||
DESTROY_IF(this->charging);
|
||||
DESTROY_IF(this->groups);
|
||||
this->groups->destroy_function(this->groups, (void*)group_destroy);
|
||||
free(this->serialNumber.ptr);
|
||||
free(this->authKeyIdentifier.ptr);
|
||||
free(this->encoding.ptr);
|
||||
|
@ -869,9 +1039,10 @@ static private_x509_ac_t *create_empty(void)
|
|||
.get_holderSerial = _get_holderSerial,
|
||||
.get_holderIssuer = _get_holderIssuer,
|
||||
.get_authKeyIdentifier = _get_authKeyIdentifier,
|
||||
.get_groups = _get_groups,
|
||||
.create_group_enumerator = _create_group_enumerator,
|
||||
},
|
||||
},
|
||||
.groups = linked_list_create(),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
|
@ -913,6 +1084,27 @@ x509_ac_t *x509_ac_load(certificate_type_t type, va_list args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add groups from a list into AC group memberships
|
||||
*/
|
||||
static void add_groups_from_list(private_x509_ac_t *this, linked_list_t *list)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
group_t *group;
|
||||
char *name;
|
||||
|
||||
enumerator = list->create_enumerator(list);
|
||||
while (enumerator->enumerate(enumerator, &name))
|
||||
{
|
||||
INIT(group,
|
||||
.type = AC_GROUP_TYPE_STRING,
|
||||
.value = chunk_clone(chunk_from_str(name)),
|
||||
);
|
||||
this->groups->insert_last(this->groups, group);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header.
|
||||
*/
|
||||
|
@ -934,8 +1126,8 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args)
|
|||
case BUILD_SERIAL:
|
||||
ac->serialNumber = chunk_clone(va_arg(args, chunk_t));
|
||||
continue;
|
||||
case BUILD_IETF_GROUP_ATTR:
|
||||
ac->groups = ietf_attributes_create_from_string(va_arg(args, char*));
|
||||
case BUILD_AC_GROUP_STRINGS:
|
||||
add_groups_from_list(ac, va_arg(args, linked_list_t*));
|
||||
continue;
|
||||
case BUILD_CERT:
|
||||
ac->holderCert = va_arg(args, certificate_t*);
|
||||
|
@ -968,4 +1160,3 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args)
|
|||
destroy(ac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
openac
|
|
@ -1,11 +0,0 @@
|
|||
ipsec_PROGRAMS = openac
|
||||
openac_SOURCES = openac.c
|
||||
dist_man_MANS = openac.8
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-DIPSEC_CONFDIR=\"${sysconfdir}\" \
|
||||
-DPLUGINS=\""${openac_plugins}\""
|
||||
|
||||
openac_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||
openac.o : $(top_builddir)/config.status
|
|
@ -1,165 +0,0 @@
|
|||
.TH IPSEC_OPENAC 8 "22 September 2007"
|
||||
.SH NAME
|
||||
ipsec openac \- Generation of X.509 attribute certificates
|
||||
.SH SYNOPSIS
|
||||
.B ipsec
|
||||
.B openac
|
||||
[
|
||||
.B \-\-help
|
||||
] [
|
||||
.B \-\-version
|
||||
] [
|
||||
.B \-\-optionsfrom
|
||||
\fIfilename\fP
|
||||
]
|
||||
.br
|
||||
\ \ \ [
|
||||
.B \-\-quiet
|
||||
] [
|
||||
.B \-\-debug
|
||||
\fIlevel\fP
|
||||
]
|
||||
.br
|
||||
\ \ \ [
|
||||
.B \-\-days
|
||||
\fIdays\fP
|
||||
] [
|
||||
.B \-\-hours
|
||||
\fIhours\fP
|
||||
]
|
||||
.br
|
||||
\ \ \ [
|
||||
.B \-\-startdate
|
||||
\fIYYYYMMDDHHMMSSZ\fP
|
||||
] [
|
||||
.B \-\-stopdate
|
||||
\fIYYYYMMDDHHMMSSZ\fP
|
||||
]
|
||||
.br
|
||||
.B \ \ \ \-\-cert
|
||||
\fIcertfile\fP
|
||||
.B \-\-key
|
||||
\fIkeyfile\fP
|
||||
[
|
||||
.B \-\-password
|
||||
\fIpassword\fP
|
||||
]
|
||||
.br
|
||||
.B \ \ \ \-\-usercert
|
||||
\fIcertfile\fP
|
||||
.B \-\-groups
|
||||
\fIattr1,attr2,...\fP
|
||||
.B \-\-out
|
||||
\fIfilename\fP
|
||||
.SH DESCRIPTION
|
||||
.BR openac
|
||||
is intended to be used by an Authorization Authority (AA) to generate and sign
|
||||
X.509 attribute certificates. Currently only the inclusion of one ore several group
|
||||
attributes is supported. An attribute certificate is linked to a holder by
|
||||
including the issuer and serial number of the holder's X.509 certificate.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-\-help\fP
|
||||
display the usage message.
|
||||
.TP
|
||||
\fB\-\-version\fP
|
||||
display the version of \fBopenac\fP.
|
||||
.TP
|
||||
\fB\-\-optionsfrom\fP\ \fIfilename\fP
|
||||
adds the contents of the file to the argument list.
|
||||
If \fIfilename\fP is a relative path then the file is searched in the directory
|
||||
\fI/etc/openac\fP.
|
||||
.TP
|
||||
\fB\-\-quiet\fP
|
||||
By default \fBopenac\fP logs all control output both to syslog and stderr.
|
||||
With the \fB\-\-quiet\fP option no output is written to stderr.
|
||||
.TP
|
||||
\fB\-\-days\fP\ \fIdays\fP
|
||||
Validity of the X.509 attribute certificate in days. If neiter the \fB\-\-days\fP\ nor
|
||||
the \fB\-\-hours\fP\ option is specified then a default validity interval of 1 day is assumed.
|
||||
The \fB\-\-days\fP\ option can be combined with the \fB\-\-hours\fP\ option.
|
||||
.TP
|
||||
\fB\-\-hours\fP\ \fIhours\fP
|
||||
Validity of the X.509 attribute certificate in hours. If neiter the \fB\-\-hours\fP\ nor
|
||||
the \fB\-\-days\fP\ option is specified then a default validity interval of 24 hours is assumed.
|
||||
The \fB\-\-hours\fP\ option can be combined with the \fB\-\-days\fP\ option.
|
||||
.TP
|
||||
\fB\-\-startdate\fP\ \fIYYYYMMDDHHMMSSZ\fP
|
||||
defines the \fBnotBefore\fP date when the X.509 attribute certificate becomes valid.
|
||||
The date \fIYYYYMMDDHHMMSS\fP must be specified in UTC (\fIZ\fPulu time).
|
||||
If the \fB\-\-startdate\fP option is not specified then the current date is taken as a default.
|
||||
|
||||
.TP
|
||||
\fB\-\-stopdate\fP\ \fIYYYYMMDDHHMMSSZ\fP
|
||||
defines the \fBnotAfter\fP date when the X.509 attribute certificate will expire.
|
||||
The date \fIYYYYMMDDHHMMSS\fP must be specified in UTC (\fIZ\fPulu time).
|
||||
If the \fB\-\-stopdate\fP option is not specified then the default \fBnotAfter\fP value is computed
|
||||
by adding the validity interval specified by the \fB\-\-days\fP\ and/or \fB\-\-days\fP\ options
|
||||
to the \fBnotBefore\fP date.
|
||||
.TP
|
||||
\fB\-\-cert\fP\ \fIcertfile\fP
|
||||
specifies the file containing the X.509 certificate of the Authorization Authority.
|
||||
The certificate is stored either in PEM or DER format.
|
||||
.TP
|
||||
\fB\-\-key\fP\ \fIkeyfile\fP
|
||||
specifies the encrypted file containing the private RSA key of the Authoritzation
|
||||
Authority. The private key is stored in PKCS#1 format.
|
||||
.TP
|
||||
\fB\-\-password\fP\ \fIpassword\fP
|
||||
specifies the password with which the private RSA keyfile defined by the
|
||||
\fB\-\-key\fP option has been protected. If the option is missing then the
|
||||
password is prompted for on the command line.
|
||||
.TP
|
||||
\fB\-\-usercert\fP\ \fIcertfile\fP
|
||||
specifies file containing the X.509 certificate of the user to which the generated attribute
|
||||
certificate will apply. The certificate file is stored either in PEM or DER format.
|
||||
.TP
|
||||
\fB\-\-groups\fP\ \fIattr1,attr2\fP
|
||||
specifies a comma-separated list of group attributes that will go into the
|
||||
X.509 attribute certificate.
|
||||
.TP
|
||||
\fB\-\-out\fP\ \fIfilename\fP
|
||||
specifies the file where the generated X.509 attribute certificate will be stored to.
|
||||
.SS Debugging
|
||||
.LP
|
||||
\fBopenac\fP produces a prodigious amount of debugging information. To do so,
|
||||
it must be compiled with \-DDEBUG. There are several classes of debugging output,
|
||||
and \fBopenac\fP may be directed to produce a selection of them. All lines of
|
||||
debugging output are prefixed with ``|\ '' to distinguish them from error messages.
|
||||
.LP
|
||||
When \fBopenac\fP is invoked, it may be given arguments to specify
|
||||
which classes to output. The current options are:
|
||||
.TP
|
||||
\fB\-\-debug\fP\ \fIlevel\fP
|
||||
sets the debug level to 0 (none), 1 (normal), 2 (more), 3 (raw), and 4 (private),
|
||||
the default level being 1.
|
||||
.SH EXIT STATUS
|
||||
.LP
|
||||
The execution of \fBopenac\fP terminates with one of the following two exit codes:
|
||||
.TP
|
||||
0
|
||||
means that the attribute certificate was successfully generated and stored.
|
||||
.TP
|
||||
1
|
||||
means that something went wrong.
|
||||
.SH FILES
|
||||
\fI/etc/openac/serial\fP\ \ \ serial number of latest attribute certificate
|
||||
.SH SEE ALSO
|
||||
.LP
|
||||
The X.509 attribute certificates generated with \fBopenac\fP can be used to
|
||||
enforce group policies defined by \fIipsec.conf\fP(5). Use \fIipsec_auto\fP(8)
|
||||
to load and list X.509 attribute certificates.
|
||||
.LP
|
||||
For more information on X.509 attribute certificates, refer to the following
|
||||
IETF RFC:
|
||||
.IP
|
||||
RFC 3281 An Internet Attribute Certificate Profile for Authorization
|
||||
.SH HISTORY
|
||||
The \fBopenac\fP program was originally written by Ariane Seiler and Ueli Galizzi.
|
||||
The software was recoded by Andreas Steffen using strongSwan's X.509 library and
|
||||
the ASN.1 code synthesis functions written by Christoph Gysin and Christoph Zwahlen.
|
||||
All authors were with the Zurich University of Applied Sciences in Winterthur,
|
||||
Switzerland.
|
||||
.LP
|
||||
.SH BUGS
|
||||
Bugs should be reported to the <users@lists.strongswan.org> mailing list.
|
|
@ -1,551 +0,0 @@
|
|||
/**
|
||||
* @file openac.c
|
||||
*
|
||||
* @brief Generation of X.509 attribute certificates.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
|
||||
* Copyright (C) 2004,2007 Andreas Steffen
|
||||
* Hochschule fuer Technik Rapperswil, Switzerland
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/debug.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
#include <credentials/certificates/ac.h>
|
||||
#include <credentials/keys/private_key.h>
|
||||
#include <credentials/sets/mem_cred.h>
|
||||
#include <utils/optionsfrom.h>
|
||||
|
||||
#define OPENAC_PATH IPSEC_CONFDIR "/openac"
|
||||
#define OPENAC_SERIAL IPSEC_CONFDIR "/openac/serial"
|
||||
|
||||
#define DEFAULT_VALIDITY 24*3600 /* seconds */
|
||||
|
||||
/**
|
||||
* @brief prints the usage of the program to the stderr
|
||||
*/
|
||||
static void usage(const char *message)
|
||||
{
|
||||
if (message != NULL && *message != '\0')
|
||||
{
|
||||
fprintf(stderr, "%s\n", message);
|
||||
}
|
||||
fprintf(stderr, "Usage: openac"
|
||||
" [--help]"
|
||||
" [--version]"
|
||||
" [--optionsfrom <filename>]"
|
||||
" [--quiet]"
|
||||
" \\\n\t"
|
||||
" [--debug <level 0..4>]"
|
||||
" \\\n\t"
|
||||
" [--days <days>]"
|
||||
" [--hours <hours>]"
|
||||
" \\\n\t"
|
||||
" [--startdate <YYYYMMDDHHMMSSZ>]"
|
||||
" [--enddate <YYYYMMDDHHMMSSZ>]"
|
||||
" \\\n\t"
|
||||
" --cert <certfile>"
|
||||
" --key <keyfile>"
|
||||
" [--password <password>]"
|
||||
" \\\n\t"
|
||||
" --usercert <certfile>"
|
||||
" --groups <attr1,attr2,..>"
|
||||
" --out <filename>"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* read the last serial number from file
|
||||
*/
|
||||
static chunk_t read_serial(void)
|
||||
{
|
||||
chunk_t hex, serial = chunk_empty;
|
||||
char one[] = {0x01};
|
||||
FILE *fd;
|
||||
|
||||
fd = fopen(OPENAC_SERIAL, "r");
|
||||
if (fd)
|
||||
{
|
||||
hex = chunk_alloca(64);
|
||||
hex.len = fread(hex.ptr, 1, hex.len, fd);
|
||||
if (hex.len)
|
||||
{
|
||||
/* remove any terminating newline character */
|
||||
if (hex.ptr[hex.len-1] == '\n')
|
||||
{
|
||||
hex.len--;
|
||||
}
|
||||
serial = chunk_alloca((hex.len / 2) + (hex.len % 2));
|
||||
serial = chunk_from_hex(hex, serial.ptr);
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_LIB, " file '%s' does not exist yet - serial number "
|
||||
"set to 01", OPENAC_SERIAL);
|
||||
}
|
||||
if (!serial.len)
|
||||
{
|
||||
return chunk_clone(chunk_create(one, 1));
|
||||
}
|
||||
if (chunk_increment(serial))
|
||||
{ /* overflow, prepend 0x01 */
|
||||
return chunk_cat("cc", chunk_create(one, 1), serial);
|
||||
}
|
||||
return chunk_clone(serial);
|
||||
}
|
||||
|
||||
/**
|
||||
* write back the last serial number to file
|
||||
*/
|
||||
static void write_serial(chunk_t serial)
|
||||
{
|
||||
FILE *fd = fopen(OPENAC_SERIAL, "w");
|
||||
|
||||
if (fd)
|
||||
{
|
||||
chunk_t hex_serial;
|
||||
|
||||
DBG1(DBG_LIB, " serial number is %#B", &serial);
|
||||
hex_serial = chunk_to_hex(serial, NULL, FALSE);
|
||||
fprintf(fd, "%.*s\n", (int)hex_serial.len, hex_serial.ptr);
|
||||
fclose(fd);
|
||||
free(hex_serial.ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_LIB, " could not open file '%s' for writing", OPENAC_SERIAL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* global variables accessible by both main() and build.c
|
||||
*/
|
||||
|
||||
static int debug_level = 1;
|
||||
static bool stderr_quiet = FALSE;
|
||||
|
||||
/**
|
||||
* openac dbg function
|
||||
*/
|
||||
static void openac_dbg(debug_t group, level_t level, char *fmt, ...)
|
||||
{
|
||||
int priority = LOG_INFO;
|
||||
char buffer[8192];
|
||||
char *current = buffer, *next;
|
||||
va_list args;
|
||||
|
||||
if (level <= debug_level)
|
||||
{
|
||||
if (!stderr_quiet)
|
||||
{
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/* write in memory buffer first */
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
/* do a syslog with every line */
|
||||
while (current)
|
||||
{
|
||||
next = strchr(current, '\n');
|
||||
if (next)
|
||||
{
|
||||
*(next++) = '\0';
|
||||
}
|
||||
syslog(priority, "%s\n", current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief openac main program
|
||||
*
|
||||
* @param argc number of arguments
|
||||
* @param argv pointer to the argument values
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
certificate_t *attr_cert = NULL;
|
||||
certificate_t *userCert = NULL;
|
||||
certificate_t *signerCert = NULL;
|
||||
private_key_t *signerKey = NULL;
|
||||
|
||||
time_t notBefore = UNDEFINED_TIME;
|
||||
time_t notAfter = UNDEFINED_TIME;
|
||||
time_t validity = 0;
|
||||
|
||||
char *keyfile = NULL;
|
||||
char *certfile = NULL;
|
||||
char *usercertfile = NULL;
|
||||
char *outfile = NULL;
|
||||
char *groups = "";
|
||||
char buf[BUF_LEN];
|
||||
|
||||
chunk_t passphrase = { buf, 0 };
|
||||
chunk_t serial = chunk_empty;
|
||||
chunk_t attr_chunk = chunk_empty;
|
||||
|
||||
int status = 1;
|
||||
|
||||
/* enable openac debugging hook */
|
||||
dbg = openac_dbg;
|
||||
|
||||
passphrase.ptr[0] = '\0';
|
||||
|
||||
openlog("openac", 0, LOG_AUTHPRIV);
|
||||
|
||||
/* initialize library */
|
||||
atexit(library_deinit);
|
||||
if (!library_init(NULL, "openac"))
|
||||
{
|
||||
exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
|
||||
}
|
||||
if (lib->integrity &&
|
||||
!lib->integrity->check_file(lib->integrity, "openac", argv[0]))
|
||||
{
|
||||
fprintf(stderr, "integrity check of openac failed\n");
|
||||
exit(SS_RC_DAEMON_INTEGRITY);
|
||||
}
|
||||
if (!lib->plugins->load(lib->plugins,
|
||||
lib->settings->get_str(lib->settings, "openac.load", PLUGINS)))
|
||||
{
|
||||
exit(SS_RC_INITIALIZATION_FAILED);
|
||||
}
|
||||
|
||||
/* initialize optionsfrom */
|
||||
options_t *options = options_create();
|
||||
|
||||
/* handle arguments */
|
||||
for (;;)
|
||||
{
|
||||
static const struct option long_opts[] = {
|
||||
/* name, has_arg, flag, val */
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'v' },
|
||||
{ "optionsfrom", required_argument, NULL, '+' },
|
||||
{ "quiet", no_argument, NULL, 'q' },
|
||||
{ "cert", required_argument, NULL, 'c' },
|
||||
{ "key", required_argument, NULL, 'k' },
|
||||
{ "password", required_argument, NULL, 'p' },
|
||||
{ "usercert", required_argument, NULL, 'u' },
|
||||
{ "groups", required_argument, NULL, 'g' },
|
||||
{ "days", required_argument, NULL, 'D' },
|
||||
{ "hours", required_argument, NULL, 'H' },
|
||||
{ "startdate", required_argument, NULL, 'S' },
|
||||
{ "enddate", required_argument, NULL, 'E' },
|
||||
{ "out", required_argument, NULL, 'o' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ 0,0,0,0 }
|
||||
};
|
||||
|
||||
int c = getopt_long(argc, argv, "hv+:qc:k:p;u:g:D:H:S:E:o:d:", long_opts, NULL);
|
||||
|
||||
/* Note: "breaking" from case terminates loop */
|
||||
switch (c)
|
||||
{
|
||||
case EOF: /* end of flags */
|
||||
break;
|
||||
|
||||
case 0: /* long option already handled */
|
||||
continue;
|
||||
|
||||
case ':': /* diagnostic already printed by getopt_long */
|
||||
case '?': /* diagnostic already printed by getopt_long */
|
||||
case 'h': /* --help */
|
||||
usage(NULL);
|
||||
status = 1;
|
||||
goto end;
|
||||
|
||||
case 'v': /* --version */
|
||||
printf("openac (strongSwan %s)\n", VERSION);
|
||||
status = 0;
|
||||
goto end;
|
||||
|
||||
case '+': /* --optionsfrom <filename> */
|
||||
{
|
||||
char path[BUF_LEN];
|
||||
|
||||
if (*optarg == '/') /* absolute pathname */
|
||||
{
|
||||
strncpy(path, optarg, BUF_LEN);
|
||||
path[BUF_LEN-1] = '\0';
|
||||
}
|
||||
else /* relative pathname */
|
||||
{
|
||||
snprintf(path, BUF_LEN, "%s/%s", OPENAC_PATH, optarg);
|
||||
}
|
||||
if (!options->from(options, path, &argc, &argv, optind))
|
||||
{
|
||||
status = 1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'q': /* --quiet */
|
||||
stderr_quiet = TRUE;
|
||||
continue;
|
||||
|
||||
case 'c': /* --cert */
|
||||
certfile = optarg;
|
||||
continue;
|
||||
|
||||
case 'k': /* --key */
|
||||
keyfile = optarg;
|
||||
continue;
|
||||
|
||||
case 'p': /* --key */
|
||||
if (strlen(optarg) >= BUF_LEN)
|
||||
{
|
||||
usage("passphrase too long");
|
||||
goto end;
|
||||
}
|
||||
strncpy(passphrase.ptr, optarg, BUF_LEN);
|
||||
passphrase.len = min(strlen(optarg), BUF_LEN);
|
||||
continue;
|
||||
|
||||
case 'u': /* --usercert */
|
||||
usercertfile = optarg;
|
||||
continue;
|
||||
|
||||
case 'g': /* --groups */
|
||||
groups = optarg;
|
||||
continue;
|
||||
|
||||
case 'D': /* --days */
|
||||
if (optarg == NULL || !isdigit(optarg[0]))
|
||||
{
|
||||
usage("missing number of days");
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *endptr;
|
||||
long days = strtol(optarg, &endptr, 0);
|
||||
|
||||
if (*endptr != '\0' || endptr == optarg || days <= 0)
|
||||
{
|
||||
usage("<days> must be a positive number");
|
||||
goto end;
|
||||
}
|
||||
validity += 24*3600*days;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'H': /* --hours */
|
||||
if (optarg == NULL || !isdigit(optarg[0]))
|
||||
{
|
||||
usage("missing number of hours");
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *endptr;
|
||||
long hours = strtol(optarg, &endptr, 0);
|
||||
|
||||
if (*endptr != '\0' || endptr == optarg || hours <= 0)
|
||||
{
|
||||
usage("<hours> must be a positive number");
|
||||
goto end;
|
||||
}
|
||||
validity += 3600*hours;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'S': /* --startdate */
|
||||
if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z')
|
||||
{
|
||||
usage("date format must be YYYYMMDDHHMMSSZ");
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk_t date = { optarg, 15 };
|
||||
|
||||
notBefore = asn1_to_time(&date, ASN1_GENERALIZEDTIME);
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'E': /* --enddate */
|
||||
if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z')
|
||||
{
|
||||
usage("date format must be YYYYMMDDHHMMSSZ");
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk_t date = { optarg, 15 };
|
||||
notAfter = asn1_to_time(&date, ASN1_GENERALIZEDTIME);
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'o': /* --out */
|
||||
outfile = optarg;
|
||||
continue;
|
||||
|
||||
case 'd': /* --debug */
|
||||
debug_level = atoi(optarg);
|
||||
continue;
|
||||
|
||||
default:
|
||||
usage("");
|
||||
status = 0;
|
||||
goto end;
|
||||
}
|
||||
/* break from loop */
|
||||
break;
|
||||
}
|
||||
|
||||
if (optind != argc)
|
||||
{
|
||||
usage("unexpected argument");
|
||||
goto end;
|
||||
}
|
||||
|
||||
DBG1(DBG_LIB, "starting openac (strongSwan Version %s)", VERSION);
|
||||
|
||||
/* load the signer's RSA private key */
|
||||
if (keyfile != NULL)
|
||||
{
|
||||
mem_cred_t *mem;
|
||||
shared_key_t *shared;
|
||||
|
||||
mem = mem_cred_create();
|
||||
lib->credmgr->add_set(lib->credmgr, &mem->set);
|
||||
shared = shared_key_create(SHARED_PRIVATE_KEY_PASS,
|
||||
chunk_clone(passphrase));
|
||||
mem->add_shared(mem, shared, NULL);
|
||||
signerKey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
|
||||
BUILD_FROM_FILE, keyfile,
|
||||
BUILD_END);
|
||||
lib->credmgr->remove_set(lib->credmgr, &mem->set);
|
||||
mem->destroy(mem);
|
||||
if (signerKey == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
DBG1(DBG_LIB, " loaded private key file '%s'", keyfile);
|
||||
}
|
||||
|
||||
/* load the signer's X.509 certificate */
|
||||
if (certfile != NULL)
|
||||
{
|
||||
signerCert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, certfile,
|
||||
BUILD_END);
|
||||
if (signerCert == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* load the users's X.509 certificate */
|
||||
if (usercertfile != NULL)
|
||||
{
|
||||
userCert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, usercertfile,
|
||||
BUILD_END);
|
||||
if (userCert == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute validity interval */
|
||||
validity = (validity)? validity : DEFAULT_VALIDITY;
|
||||
notBefore = (notBefore == UNDEFINED_TIME) ? time(NULL) : notBefore;
|
||||
notAfter = (notAfter == UNDEFINED_TIME) ? time(NULL) + validity : notAfter;
|
||||
|
||||
/* build and parse attribute certificate */
|
||||
if (userCert != NULL && signerCert != NULL && signerKey != NULL &&
|
||||
outfile != NULL)
|
||||
{
|
||||
/* read the serial number and increment it by one */
|
||||
serial = read_serial();
|
||||
|
||||
attr_cert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509_AC,
|
||||
BUILD_CERT, userCert,
|
||||
BUILD_NOT_BEFORE_TIME, notBefore,
|
||||
BUILD_NOT_AFTER_TIME, notAfter,
|
||||
BUILD_SERIAL, serial,
|
||||
BUILD_IETF_GROUP_ATTR, groups,
|
||||
BUILD_SIGNING_CERT, signerCert,
|
||||
BUILD_SIGNING_KEY, signerKey,
|
||||
BUILD_END);
|
||||
if (!attr_cert)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* write the attribute certificate to file */
|
||||
if (attr_cert->get_encoding(attr_cert, CERT_ASN1_DER, &attr_chunk))
|
||||
{
|
||||
if (chunk_write(attr_chunk, outfile, 0022, TRUE))
|
||||
{
|
||||
DBG1(DBG_APP, " written attribute cert file '%s' (%d bytes)",
|
||||
outfile, attr_chunk.len);
|
||||
write_serial(serial);
|
||||
status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_APP, " writing attribute cert file '%s' failed: %s",
|
||||
outfile, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
usage("some of the mandatory parameters --usercert --cert --key --out "
|
||||
"are missing");
|
||||
}
|
||||
|
||||
end:
|
||||
/* delete all dynamically allocated objects */
|
||||
DESTROY_IF(signerKey);
|
||||
DESTROY_IF(signerCert);
|
||||
DESTROY_IF(userCert);
|
||||
DESTROY_IF(attr_cert);
|
||||
free(attr_chunk.ptr);
|
||||
free(serial.ptr);
|
||||
closelog();
|
||||
dbg = dbg_default;
|
||||
options->destroy(options);
|
||||
exit(status);
|
||||
}
|
|
@ -11,6 +11,7 @@ pki_SOURCES = pki.c pki.h command.c command.h \
|
|||
commands/self.c \
|
||||
commands/print.c \
|
||||
commands/signcrl.c \
|
||||
commands/acert.c \
|
||||
commands/pkcs7.c \
|
||||
commands/verify.c
|
||||
|
||||
|
|
|
@ -24,12 +24,12 @@
|
|||
/**
|
||||
* Maximum number of commands (+1).
|
||||
*/
|
||||
#define MAX_COMMANDS 11
|
||||
#define MAX_COMMANDS 12
|
||||
|
||||
/**
|
||||
* Maximum number of options in a command (+3)
|
||||
*/
|
||||
#define MAX_OPTIONS 32
|
||||
#define MAX_OPTIONS 36
|
||||
|
||||
/**
|
||||
* Maximum number of usage summary lines (+1)
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Martin Willi
|
||||
* 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 <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "pki.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <credentials/certificates/certificate.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
#include <credentials/certificates/ac.h>
|
||||
|
||||
/**
|
||||
* Issue an attribute certificate
|
||||
*/
|
||||
static int acert()
|
||||
{
|
||||
cred_encoding_type_t form = CERT_ASN1_DER;
|
||||
hash_algorithm_t digest = HASH_SHA1;
|
||||
certificate_t *ac = NULL, *cert = NULL, *issuer =NULL;
|
||||
private_key_t *private = NULL;
|
||||
public_key_t *public = NULL;
|
||||
char *file = NULL, *hex = NULL, *issuercert = NULL, *issuerkey = NULL;
|
||||
char *error = NULL, *keyid = NULL;
|
||||
linked_list_t *groups;
|
||||
chunk_t serial = chunk_empty, encoding = chunk_empty;
|
||||
time_t not_before, not_after, lifetime = 24 * 60 * 60;
|
||||
char *datenb = NULL, *datena = NULL, *dateform = NULL;
|
||||
rng_t *rng;
|
||||
char *arg;
|
||||
|
||||
groups = linked_list_create();
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (command_getopt(&arg))
|
||||
{
|
||||
case 'h':
|
||||
goto usage;
|
||||
case 'g':
|
||||
digest = enum_from_name(hash_algorithm_short_names, arg);
|
||||
if (digest == -1)
|
||||
{
|
||||
error = "invalid --digest type";
|
||||
goto usage;
|
||||
}
|
||||
continue;
|
||||
case 'i':
|
||||
file = arg;
|
||||
continue;
|
||||
case 'm':
|
||||
groups->insert_last(groups, arg);
|
||||
continue;
|
||||
case 'c':
|
||||
issuercert = arg;
|
||||
continue;
|
||||
case 'k':
|
||||
issuerkey = arg;
|
||||
continue;
|
||||
case 'x':
|
||||
keyid = arg;
|
||||
continue;
|
||||
case 'l':
|
||||
lifetime = atoi(arg) * 60 * 60;
|
||||
if (!lifetime)
|
||||
{
|
||||
error = "invalid --lifetime value";
|
||||
goto usage;
|
||||
}
|
||||
continue;
|
||||
case 'D':
|
||||
dateform = arg;
|
||||
continue;
|
||||
case 'F':
|
||||
datenb = arg;
|
||||
continue;
|
||||
case 'T':
|
||||
datena = arg;
|
||||
continue;
|
||||
case 's':
|
||||
hex = arg;
|
||||
continue;
|
||||
case 'f':
|
||||
if (!get_form(arg, &form, CRED_CERTIFICATE))
|
||||
{
|
||||
error = "invalid output format";
|
||||
goto usage;
|
||||
}
|
||||
continue;
|
||||
case EOF:
|
||||
break;
|
||||
default:
|
||||
error = "invalid --acert option";
|
||||
goto usage;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!calculate_lifetime(dateform, datenb, datena, lifetime,
|
||||
¬_before, ¬_after))
|
||||
{
|
||||
error = "invalid --not-before/after datetime";
|
||||
goto usage;
|
||||
}
|
||||
|
||||
if (!issuercert)
|
||||
{
|
||||
error = "--issuercert is required";
|
||||
goto usage;
|
||||
}
|
||||
if (!issuerkey && !keyid)
|
||||
{
|
||||
error = "--issuerkey or --issuerkeyid is required";
|
||||
goto usage;
|
||||
}
|
||||
|
||||
issuer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, issuercert, BUILD_END);
|
||||
if (!issuer)
|
||||
{
|
||||
error = "parsing issuer certificate failed";
|
||||
goto end;
|
||||
}
|
||||
public = issuer->get_public_key(issuer);
|
||||
if (!public)
|
||||
{
|
||||
error = "extracting issuer certificate public key failed";
|
||||
goto end;
|
||||
}
|
||||
if (issuerkey)
|
||||
{
|
||||
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
|
||||
public->get_type(public),
|
||||
BUILD_FROM_FILE, issuerkey, BUILD_END);
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk_t chunk;
|
||||
|
||||
chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
|
||||
private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
|
||||
BUILD_PKCS11_KEYID, chunk, BUILD_END);
|
||||
free(chunk.ptr);
|
||||
}
|
||||
if (!private)
|
||||
{
|
||||
error = "loading issuer private key failed";
|
||||
goto end;
|
||||
}
|
||||
if (!private->belongs_to(private, public))
|
||||
{
|
||||
error = "issuer private key does not match issuer certificate";
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (hex)
|
||||
{
|
||||
serial = chunk_from_hex(chunk_create(hex, strlen(hex)), NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
|
||||
if (!rng)
|
||||
{
|
||||
error = "no random number generator found";
|
||||
goto end;
|
||||
}
|
||||
if (!rng_allocate_bytes_not_zero(rng, 8, &serial, FALSE))
|
||||
{
|
||||
error = "failed to generate serial number";
|
||||
rng->destroy(rng);
|
||||
goto end;
|
||||
}
|
||||
serial.ptr[0] &= 0x7F;
|
||||
rng->destroy(rng);
|
||||
}
|
||||
|
||||
if (file)
|
||||
{
|
||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, file, BUILD_END);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!chunk_from_fd(0, &encoding))
|
||||
{
|
||||
fprintf(stderr, "%s: ", strerror(errno));
|
||||
error = "reading public key failed";
|
||||
goto end;
|
||||
}
|
||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_BLOB, encoding, BUILD_END);
|
||||
chunk_free(&encoding);
|
||||
}
|
||||
if (!cert)
|
||||
{
|
||||
error = "parsing user certificate failed";
|
||||
goto end;
|
||||
}
|
||||
|
||||
ac = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509_AC,
|
||||
BUILD_CERT, cert,
|
||||
BUILD_NOT_BEFORE_TIME, not_before,
|
||||
BUILD_NOT_AFTER_TIME, not_after,
|
||||
BUILD_SERIAL, serial,
|
||||
BUILD_AC_GROUP_STRINGS, groups,
|
||||
BUILD_SIGNING_CERT, issuer,
|
||||
BUILD_SIGNING_KEY, private,
|
||||
BUILD_END);
|
||||
if (!ac)
|
||||
{
|
||||
error = "generating attribute certificate failed";
|
||||
goto end;
|
||||
}
|
||||
if (!ac->get_encoding(ac, form, &encoding))
|
||||
{
|
||||
error = "encoding attribute certificate failed";
|
||||
goto end;
|
||||
}
|
||||
if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1)
|
||||
{
|
||||
error = "writing attribute certificate key failed";
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
DESTROY_IF(ac);
|
||||
DESTROY_IF(cert);
|
||||
DESTROY_IF(issuer);
|
||||
DESTROY_IF(public);
|
||||
DESTROY_IF(private);
|
||||
groups->destroy(groups);
|
||||
free(encoding.ptr);
|
||||
free(serial.ptr);
|
||||
|
||||
if (error)
|
||||
{
|
||||
fprintf(stderr, "%s\n", error);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
groups->destroy(groups);
|
||||
return command_usage(error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the command.
|
||||
*/
|
||||
static void __attribute__ ((constructor))reg()
|
||||
{
|
||||
command_register((command_t) {
|
||||
acert, 'z', "acert",
|
||||
"issue an attribute certificate",
|
||||
{"[--in file] [--group name]* --issuerkey file|--issuerkeyid hex",
|
||||
" --issuercert file [--serial hex] [--lifetime hours]",
|
||||
" [--not-before datetime] [--not-after datetime] [--dateform form]",
|
||||
"[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"},
|
||||
{
|
||||
{"help", 'h', 0, "show usage information"},
|
||||
{"in", 'i', 1, "holder certificate, default: stdin"},
|
||||
{"group", 'm', 1, "group membership string to include"},
|
||||
{"issuercert", 'c', 1, "issuer certificate file"},
|
||||
{"issuerkey", 'k', 1, "issuer private key file"},
|
||||
{"issuerkeyid", 'x', 1, "keyid on smartcard of issuer private key"},
|
||||
{"serial", 's', 1, "serial number in hex, default: random"},
|
||||
{"lifetime", 'l', 1, "hours the acert is valid, default: 24"},
|
||||
{"not-before", 'F', 1, "date/time the validity of the AC starts"},
|
||||
{"not-after", 'T', 1, "date/time the validity of the AC ends"},
|
||||
{"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"},
|
||||
{"digest", 'g', 1, "digest for signature creation, default: sha1"},
|
||||
{"outform", 'f', 1, "encoding of generated cert, default: der"},
|
||||
}
|
||||
});
|
||||
}
|
|
@ -72,8 +72,8 @@ static int issue()
|
|||
int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT;
|
||||
chunk_t serial = chunk_empty;
|
||||
chunk_t encoding = chunk_empty;
|
||||
time_t lifetime = 1095;
|
||||
time_t not_before, not_after;
|
||||
time_t not_before, not_after, lifetime = 1095 * 24 * 60 * 60;
|
||||
char *datenb = NULL, *datena = NULL, *dateform = NULL;
|
||||
x509_flag_t flags = 0;
|
||||
x509_t *x509;
|
||||
x509_cdp_t *cdp = NULL;
|
||||
|
@ -132,13 +132,22 @@ static int issue()
|
|||
san->insert_last(san, identification_create_from_string(arg));
|
||||
continue;
|
||||
case 'l':
|
||||
lifetime = atoi(arg);
|
||||
lifetime = atoi(arg) * 24 * 60 * 60;
|
||||
if (!lifetime)
|
||||
{
|
||||
error = "invalid --lifetime value";
|
||||
goto usage;
|
||||
}
|
||||
continue;
|
||||
case 'D':
|
||||
dateform = arg;
|
||||
continue;
|
||||
case 'F':
|
||||
datenb = arg;
|
||||
continue;
|
||||
case 'T':
|
||||
datena = arg;
|
||||
continue;
|
||||
case 's':
|
||||
hex = arg;
|
||||
continue;
|
||||
|
@ -285,6 +294,12 @@ static int issue()
|
|||
error = "--cakey or --keyid is required";
|
||||
goto usage;
|
||||
}
|
||||
if (!calculate_lifetime(dateform, datenb, datena, lifetime,
|
||||
¬_before, ¬_after))
|
||||
{
|
||||
error = "invalid --not-before/after datetime";
|
||||
goto usage;
|
||||
}
|
||||
if (dn && *dn)
|
||||
{
|
||||
id = identification_create_from_string(dn);
|
||||
|
@ -363,6 +378,7 @@ static int issue()
|
|||
rng->destroy(rng);
|
||||
goto end;
|
||||
}
|
||||
serial.ptr[0] &= 0x7F;
|
||||
rng->destroy(rng);
|
||||
}
|
||||
|
||||
|
@ -454,9 +470,6 @@ static int issue()
|
|||
chunk_from_chars(ASN1_SEQUENCE, 0));
|
||||
}
|
||||
|
||||
not_before = time(NULL);
|
||||
not_after = not_before + lifetime * 24 * 60 * 60;
|
||||
|
||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_SIGNING_KEY, private, BUILD_SIGNING_CERT, ca,
|
||||
BUILD_PUBLIC_KEY, public, BUILD_SUBJECT, id,
|
||||
|
@ -552,6 +565,9 @@ static void __attribute__ ((constructor))reg()
|
|||
{"dn", 'd', 1, "distinguished name to include as subject"},
|
||||
{"san", 'a', 1, "subjectAltName to include in certificate"},
|
||||
{"lifetime", 'l', 1, "days the certificate is valid, default: 1095"},
|
||||
{"not-before", 'F', 1, "date/time the validity of the cert starts"},
|
||||
{"not-after", 'T', 1, "date/time the validity of the cert ends"},
|
||||
{"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"},
|
||||
{"serial", 's', 1, "serial number in hex, default: random"},
|
||||
{"ca", 'b', 0, "include CA basicConstraint, default: no"},
|
||||
{"pathlen", 'p', 1, "set path length constraint"},
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
#include "pki.h"
|
||||
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/oid.h>
|
||||
#include <credentials/certificates/certificate.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
#include <credentials/certificates/crl.h>
|
||||
#include <credentials/certificates/ac.h>
|
||||
#include <selectors/traffic_selector.h>
|
||||
|
||||
#include <time.h>
|
||||
|
@ -387,6 +389,84 @@ static void print_crl(crl_t *crl)
|
|||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print AC specific information
|
||||
*/
|
||||
static void print_ac(ac_t *ac)
|
||||
{
|
||||
ac_group_type_t type;
|
||||
identification_t *id;
|
||||
enumerator_t *groups;
|
||||
chunk_t chunk;
|
||||
bool first = TRUE;
|
||||
|
||||
chunk = chunk_skip_zero(ac->get_serial(ac));
|
||||
printf("serial: %#B\n", &chunk);
|
||||
|
||||
id = ac->get_holderIssuer(ac);
|
||||
if (id)
|
||||
{
|
||||
printf("hissuer: \"%Y\"\n", id);
|
||||
}
|
||||
chunk = chunk_skip_zero(ac->get_holderSerial(ac));
|
||||
if (chunk.ptr)
|
||||
{
|
||||
printf("hserial: %#B\n", &chunk);
|
||||
}
|
||||
groups = ac->create_group_enumerator(ac);
|
||||
while (groups->enumerate(groups, &type, &chunk))
|
||||
{
|
||||
int oid;
|
||||
char *str;
|
||||
|
||||
if (first)
|
||||
{
|
||||
printf("groups: ");
|
||||
first = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case AC_GROUP_TYPE_STRING:
|
||||
printf("%.*s", (int)chunk.len, chunk.ptr);
|
||||
break;
|
||||
case AC_GROUP_TYPE_OID:
|
||||
oid = asn1_known_oid(chunk);
|
||||
if (oid == OID_UNKNOWN)
|
||||
{
|
||||
str = asn1_oid_to_string(chunk);
|
||||
if (str)
|
||||
{
|
||||
printf("%s", str);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("OID:%#B", &chunk);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s", oid_names[oid].name);
|
||||
}
|
||||
break;
|
||||
case AC_GROUP_TYPE_OCTETS:
|
||||
printf("%#B", &chunk);
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
groups->destroy(groups);
|
||||
|
||||
chunk = ac->get_authKeyIdentifier(ac);
|
||||
if (chunk.ptr)
|
||||
{
|
||||
printf("authkey: %#B\n", &chunk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print certificate information
|
||||
*/
|
||||
|
@ -432,6 +512,9 @@ static void print_cert(certificate_t *cert)
|
|||
case CERT_X509_CRL:
|
||||
print_crl((crl_t*)cert);
|
||||
break;
|
||||
case CERT_X509_AC:
|
||||
print_ac((ac_t*)cert);
|
||||
break;
|
||||
default:
|
||||
printf("parsing certificate subtype %N not implemented\n",
|
||||
certificate_type_names, cert->get_type(cert));
|
||||
|
@ -472,6 +555,11 @@ static int print()
|
|||
type = CRED_CERTIFICATE;
|
||||
subtype = CERT_X509_CRL;
|
||||
}
|
||||
else if (streq(arg, "ac"))
|
||||
{
|
||||
type = CRED_CERTIFICATE;
|
||||
subtype = CERT_X509_AC;
|
||||
}
|
||||
else if (streq(arg, "pub"))
|
||||
{
|
||||
type = CRED_PUBLIC_KEY;
|
||||
|
@ -558,7 +646,7 @@ static void __attribute__ ((constructor))reg()
|
|||
command_register((command_t)
|
||||
{ print, 'a', "print",
|
||||
"print a credential in a human readable form",
|
||||
{"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509|crl]"},
|
||||
{"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509|crl|ac]"},
|
||||
{
|
||||
{"help", 'h', 0, "show usage information"},
|
||||
{"in", 'i', 1, "input file, default: stdin"},
|
||||
|
|
|
@ -60,8 +60,8 @@ static int self()
|
|||
int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT;
|
||||
chunk_t serial = chunk_empty;
|
||||
chunk_t encoding = chunk_empty;
|
||||
time_t lifetime = 1095;
|
||||
time_t not_before, not_after;
|
||||
time_t not_before, not_after, lifetime = 1095 * 24 * 60 * 60;
|
||||
char *datenb = NULL, *datena = NULL, *dateform = NULL;
|
||||
x509_flag_t flags = 0;
|
||||
x509_cert_policy_t *policy = NULL;
|
||||
char *arg;
|
||||
|
@ -114,14 +114,24 @@ static int self()
|
|||
case 'a':
|
||||
san->insert_last(san, identification_create_from_string(arg));
|
||||
continue;
|
||||
continue;
|
||||
case 'l':
|
||||
lifetime = atoi(arg);
|
||||
lifetime = atoi(arg) * 24 * 60 * 60;
|
||||
if (!lifetime)
|
||||
{
|
||||
error = "invalid --lifetime value";
|
||||
goto usage;
|
||||
}
|
||||
continue;
|
||||
case 'D':
|
||||
dateform = arg;
|
||||
continue;
|
||||
case 'F':
|
||||
datenb = arg;
|
||||
continue;
|
||||
case 'T':
|
||||
datena = arg;
|
||||
continue;
|
||||
case 's':
|
||||
hex = arg;
|
||||
continue;
|
||||
|
@ -250,6 +260,12 @@ static int self()
|
|||
error = "--dn is required";
|
||||
goto usage;
|
||||
}
|
||||
if (!calculate_lifetime(dateform, datenb, datena, lifetime,
|
||||
¬_before, ¬_after))
|
||||
{
|
||||
error = "invalid --not-before/after datetime";
|
||||
goto usage;
|
||||
}
|
||||
id = identification_create_from_string(dn);
|
||||
if (id->get_type(id) != ID_DER_ASN1_DN)
|
||||
{
|
||||
|
@ -314,10 +330,9 @@ static int self()
|
|||
rng->destroy(rng);
|
||||
goto end;
|
||||
}
|
||||
serial.ptr[0] &= 0x7F;
|
||||
rng->destroy(rng);
|
||||
}
|
||||
not_before = time(NULL);
|
||||
not_after = not_before + lifetime * 24 * 60 * 60;
|
||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_SIGNING_KEY, private, BUILD_PUBLIC_KEY, public,
|
||||
BUILD_SUBJECT, id, BUILD_NOT_BEFORE_TIME, not_before,
|
||||
|
@ -405,6 +420,9 @@ static void __attribute__ ((constructor))reg()
|
|||
{"dn", 'd', 1, "subject and issuer distinguished name"},
|
||||
{"san", 'a', 1, "subjectAltName to include in certificate"},
|
||||
{"lifetime", 'l', 1, "days the certificate is valid, default: 1095"},
|
||||
{"not-before", 'F', 1, "date/time the validity of the cert starts"},
|
||||
{"not-after", 'T', 1, "date/time the validity of the cert ends"},
|
||||
{"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"},
|
||||
{"serial", 's', 1, "serial number in hex, default: random"},
|
||||
{"ca", 'b', 0, "include CA basicConstraint, default: no"},
|
||||
{"pathlen", 'p', 1, "set path length constraint"},
|
||||
|
|
|
@ -124,7 +124,8 @@ static int sign_crl()
|
|||
int serial_len = 0;
|
||||
crl_reason_t reason = CRL_REASON_UNSPECIFIED;
|
||||
time_t thisUpdate, nextUpdate, date = time(NULL);
|
||||
time_t lifetime = 15;
|
||||
time_t lifetime = 15 * 24 * 60 * 60;
|
||||
char *datetu = NULL, *datenu = NULL, *dateform = NULL;
|
||||
linked_list_t *list, *cdps;
|
||||
enumerator_t *enumerator, *lastenum = NULL;
|
||||
x509_cdp_t *cdp;
|
||||
|
@ -161,13 +162,22 @@ static int sign_crl()
|
|||
lastupdate = arg;
|
||||
continue;
|
||||
case 'l':
|
||||
lifetime = atoi(arg);
|
||||
lifetime = atoi(arg) * 24 * 60 * 60;
|
||||
if (!lifetime)
|
||||
{
|
||||
error = "invalid lifetime";
|
||||
error = "invalid --lifetime value";
|
||||
goto usage;
|
||||
}
|
||||
continue;
|
||||
case 'D':
|
||||
dateform = arg;
|
||||
continue;
|
||||
case 'F':
|
||||
datetu = arg;
|
||||
continue;
|
||||
case 'T':
|
||||
datenu = arg;
|
||||
continue;
|
||||
case 'z':
|
||||
serial_len = read_serial(arg, serial, sizeof(serial));
|
||||
if (serial_len < 0)
|
||||
|
@ -275,6 +285,12 @@ static int sign_crl()
|
|||
error = "--cakey or --keyid is required";
|
||||
goto usage;
|
||||
}
|
||||
if (!calculate_lifetime(dateform, datetu, datenu, lifetime,
|
||||
&thisUpdate, &nextUpdate))
|
||||
{
|
||||
error = "invalid --this/next-update datetime";
|
||||
goto usage;
|
||||
}
|
||||
|
||||
ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, cacert, BUILD_END);
|
||||
|
@ -321,9 +337,6 @@ static int sign_crl()
|
|||
goto error;
|
||||
}
|
||||
|
||||
thisUpdate = time(NULL);
|
||||
nextUpdate = thisUpdate + lifetime * 24 * 60 * 60;
|
||||
|
||||
if (basecrl)
|
||||
{
|
||||
lastcrl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
|
||||
|
@ -442,6 +455,9 @@ static void __attribute__ ((constructor))reg()
|
|||
{"cakey", 'k', 1, "CA private key file"},
|
||||
{"cakeyid", 'x', 1, "keyid on smartcard of CA private key"},
|
||||
{"lifetime", 'l', 1, "days the CRL gets a nextUpdate, default: 15"},
|
||||
{"this-update", 'F', 1, "date/time the validity of the CRL starts"},
|
||||
{"next-update", 'T', 1, "date/time the validity of the CRL ends"},
|
||||
{"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"},
|
||||
{"lastcrl", 'a', 1, "CRL of lastUpdate to copy revocations from"},
|
||||
{"basecrl", 'b', 1, "base CRL to create a delta CRL for"},
|
||||
{"crluri", 'u', 1, "freshest delta CRL URI to include"},
|
||||
|
|
|
@ -4,6 +4,7 @@ man1_MANS = \
|
|||
pki---self.1 \
|
||||
pki---issue.1 \
|
||||
pki---signcrl.1 \
|
||||
pki---acert.1 \
|
||||
pki---req.1 \
|
||||
pki---pkcs7.1 \
|
||||
pki---keyid.1 \
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
.TH "PKI \-\-ACERT" 1 "2014-02-05" "@PACKAGE_VERSION@" "strongSwan"
|
||||
.
|
||||
.SH "NAME"
|
||||
.
|
||||
pki \-\-acert \- Issue an attribute certificate
|
||||
.
|
||||
.SH "SYNOPSIS"
|
||||
.
|
||||
.SY pki\ \-\-acert
|
||||
.OP \-\-in file
|
||||
.OP \-\-group membership
|
||||
.BI \-\-issuerkey\~ file |\-\-issuerkeyid\~ hex
|
||||
.BI \-\-issuercert\~ file
|
||||
.OP \-\-lifetime hours
|
||||
.OP \-\-not-before datetime
|
||||
.OP \-\-not-after datetime
|
||||
.OP \-\-serial hex
|
||||
.OP \-\-digest digest
|
||||
.OP \-\-outform encoding
|
||||
.OP \-\-debug level
|
||||
.YS
|
||||
.
|
||||
.SY pki\ \-\-acert
|
||||
.BI \-\-options\~ file
|
||||
.YS
|
||||
.
|
||||
.SY "pki \-\-acert"
|
||||
.B \-h
|
||||
|
|
||||
.B \-\-help
|
||||
.YS
|
||||
.
|
||||
.SH "DESCRIPTION"
|
||||
.
|
||||
This sub-command of
|
||||
.BR pki (1)
|
||||
is used to issue an attribute certificate using an issuer certificate with its
|
||||
private key and the holder certificate.
|
||||
.
|
||||
.SH "OPTIONS"
|
||||
.
|
||||
.TP
|
||||
.B "\-h, \-\-help"
|
||||
Print usage information with a summary of the available options.
|
||||
.TP
|
||||
.BI "\-v, \-\-debug " level
|
||||
Set debug level, default: 1.
|
||||
.TP
|
||||
.BI "\-+, \-\-options " file
|
||||
Read command line options from \fIfile\fR.
|
||||
.TP
|
||||
.BI "\-i, \-\-in " file
|
||||
Holder certificate to issue an attribute certificate for. If not given the
|
||||
certificate is read from \fISTDIN\fR.
|
||||
.TP
|
||||
.BI "\-m, \-\-group " membership
|
||||
Group membership the attribute certificate shall certify. The specified group
|
||||
is included as a string. To include multiple groups, the option can be repeated.
|
||||
.TP
|
||||
.BI "\-k, \-\-issuerkey " file
|
||||
Issuer private key file. Either this or
|
||||
.B \-\-issuerkeyid
|
||||
is required.
|
||||
.TP
|
||||
.BI "\-x, \-\-issuerkeyid " hex
|
||||
Key ID of a issuer private key on a smartcard. Either this or
|
||||
.B \-\-issuerkey
|
||||
is required.
|
||||
.TP
|
||||
.BI "\-c, \-\-issuercert " file
|
||||
Issuer certificate file. Required.
|
||||
.TP
|
||||
.BI "\-l, \-\-lifetime " hours
|
||||
Hours the attribute certificate is valid, default: 24. Ignored if both
|
||||
an absolute start and end time are given.
|
||||
.TP
|
||||
.BI "\-F, \-\-not-before " datetime
|
||||
Absolute time when the validity of the AC begins. The datetime format is
|
||||
defined by the
|
||||
.B \-\-dateform
|
||||
option.
|
||||
.TP
|
||||
.BI "\-T, \-\-not-after " datetime
|
||||
Absolute time when the validity of the AC ends. The datetime format is
|
||||
defined by the
|
||||
.B \-\-dateform
|
||||
option.
|
||||
.TP
|
||||
.BI "\-D, \-\-dateform " form
|
||||
strptime(3) format for the
|
||||
.B \-\-not\-before
|
||||
and
|
||||
.B \-\-not\-after
|
||||
options, default:
|
||||
.B %d.%m.%y %T
|
||||
.TP
|
||||
.BI "\-s, \-\-serial " hex
|
||||
Serial number in hex. It is randomly allocated by default.
|
||||
.TP
|
||||
.BI "\-g, \-\-digest " digest
|
||||
Digest to use for signature creation. One of \fImd5\fR, \fIsha1\fR,
|
||||
\fIsha224\fR, \fIsha256\fR, \fIsha384\fR, or \fIsha512\fR. Defaults to
|
||||
\fIsha1\fR.
|
||||
.TP
|
||||
.BI "\-f, \-\-outform " encoding
|
||||
Encoding of the created certificate file. Either \fIder\fR (ASN.1 DER) or
|
||||
\fIpem\fR (Base64 PEM), defaults to \fIder\fR.
|
||||
.
|
||||
.SH "EXAMPLES"
|
||||
.
|
||||
To save repetitive typing, command line options can be stored in files.
|
||||
Lets assume
|
||||
.I acert.opt
|
||||
contains the following contents:
|
||||
.PP
|
||||
.EX
|
||||
--issuercert aacert.der --issuerkey aakey.der --digest sha256 --lifetime 4
|
||||
.EE
|
||||
.PP
|
||||
Then the following command can be used to issue an attribute certificate based
|
||||
on a holder certificate and the options above:
|
||||
.PP
|
||||
.EX
|
||||
pki --acert --options acert.opt --in holder.der --group sales --group finance -f pem
|
||||
.EE
|
||||
.PP
|
||||
.
|
||||
.SH "SEE ALSO"
|
||||
.
|
||||
.BR pki (1)
|
|
@ -14,6 +14,8 @@ pki \-\-issue \- Issue a certificate using a CA certificate and key
|
|||
.OP \-\-dn subject-dn
|
||||
.OP \-\-san subjectAltName
|
||||
.OP \-\-lifetime days
|
||||
.OP \-\-not-before datetime
|
||||
.OP \-\-not-after datetime
|
||||
.OP \-\-serial hex
|
||||
.OP \-\-flag flag
|
||||
.OP \-\-digest digest
|
||||
|
@ -88,7 +90,28 @@ Subject distinguished name (DN) of the issued certificate.
|
|||
subjectAltName extension to include in certificate. Can be used multiple times.
|
||||
.TP
|
||||
.BI "\-l, \-\-lifetime " days
|
||||
Days the certificate is valid, default: 1095.
|
||||
Days the certificate is valid, default: 1095. Ignored if both
|
||||
an absolute start and end time are given.
|
||||
.TP
|
||||
.BI "\-F, \-\-not-before " datetime
|
||||
Absolute time when the validity of the certificate begins. The datetime format
|
||||
is defined by the
|
||||
.B \-\-dateform
|
||||
option.
|
||||
.TP
|
||||
.BI "\-T, \-\-not-after " datetime
|
||||
Absolute time when the validity of the certificate ends. The datetime format is
|
||||
defined by the
|
||||
.B \-\-dateform
|
||||
option.
|
||||
.TP
|
||||
.BI "\-D, \-\-dateform " form
|
||||
strptime(3) format for the
|
||||
.B \-\-not\-before
|
||||
and
|
||||
.B \-\-not\-after
|
||||
options, default:
|
||||
.B %d.%m.%y %T
|
||||
.TP
|
||||
.BI "\-s, \-\-serial " hex
|
||||
Serial number in hex. It is randomly allocated by default.
|
||||
|
@ -176,4 +199,4 @@ given PKCS#10 certificate request and the options above:
|
|||
.
|
||||
.SH "SEE ALSO"
|
||||
.
|
||||
.BR pki (1)
|
||||
.BR pki (1)
|
||||
|
|
|
@ -46,8 +46,9 @@ Input file. If not given the input is read from \fISTDIN\fR.
|
|||
.BI "\-t, \-\-type " type
|
||||
Type of input. One of \fIrsa-priv\fR (RSA private key), \fIecdsa-priv\fR (ECDSA
|
||||
private key), \fIpub\fR (public key), \fIx509\fR (X.509 certificate), \fIcrl\fR
|
||||
(Certificate Revocation List, CRL), defaults to \fIx509\fR.
|
||||
(Certificate Revocation List, CRL), \fIac\fR (Attribute Certificate),
|
||||
defaults to \fIx509\fR.
|
||||
.
|
||||
.SH "SEE ALSO"
|
||||
.
|
||||
.BR pki (1)
|
||||
.BR pki (1)
|
||||
|
|
|
@ -14,6 +14,8 @@ pki \-\-self \- Create a self-signed certificate
|
|||
.BI \-\-dn\~ distinguished-name
|
||||
.OP \-\-san subjectAltName
|
||||
.OP \-\-lifetime days
|
||||
.OP \-\-not-before datetime
|
||||
.OP \-\-not-after datetime
|
||||
.OP \-\-serial hex
|
||||
.OP \-\-flag flag
|
||||
.OP \-\-digest digest
|
||||
|
@ -75,7 +77,28 @@ Subject and issuer distinguished name (DN). Required.
|
|||
subjectAltName extension to include in certificate. Can be used multiple times.
|
||||
.TP
|
||||
.BI "\-l, \-\-lifetime " days
|
||||
Days the certificate is valid, default: 1095.
|
||||
Days the certificate is valid, default: 1095. Ignored if both
|
||||
an absolute start and end time are given.
|
||||
.TP
|
||||
.BI "\-F, \-\-not-before " datetime
|
||||
Absolute time when the validity of the certificate begins. The datetime format
|
||||
is defined by the
|
||||
.B \-\-dateform
|
||||
option.
|
||||
.TP
|
||||
.BI "\-T, \-\-not-after " datetime
|
||||
Absolute time when the validity of the certificate ends. The datetime format is
|
||||
defined by the
|
||||
.B \-\-dateform
|
||||
option.
|
||||
.TP
|
||||
.BI "\-D, \-\-dateform " form
|
||||
strptime(3) format for the
|
||||
.B \-\-not\-before
|
||||
and
|
||||
.B \-\-not\-after
|
||||
options, default:
|
||||
.B %d.%m.%y %T
|
||||
.TP
|
||||
.BI "\-s, \-\-serial " hex
|
||||
Serial number in hex. It is randomly allocated by default.
|
||||
|
@ -145,4 +168,4 @@ Generate a self-signed certificate using the given RSA key:
|
|||
.
|
||||
.SH "SEE ALSO"
|
||||
.
|
||||
.BR pki (1)
|
||||
.BR pki (1)
|
||||
|
|
|
@ -10,6 +10,8 @@ pki \-\-signcrl \- Issue a Certificate Revocation List (CRL) using a CA certific
|
|||
.BI \-\-cakey\~ file |\-\-cakeyid\~ hex
|
||||
.BI \-\-cacert\~ file
|
||||
.OP \-\-lifetime days
|
||||
.OP \-\-this-update datetime
|
||||
.OP \-\-next-update datetime
|
||||
.OP \-\-lastcrl crl
|
||||
.OP \-\-basecrl crl
|
||||
.OP \-\-crluri uri
|
||||
|
@ -62,7 +64,28 @@ is required.
|
|||
CA certificate file. Required.
|
||||
.TP
|
||||
.BI "\-l, \-\-lifetime " days
|
||||
Days until the CRL gets a nextUpdate, default: 15.
|
||||
Days until the CRL gets a nextUpdate, default: 15. Ignored if both
|
||||
an absolute start and end time are given.
|
||||
.TP
|
||||
.BI "\-F, \-\-this-update " datetime
|
||||
Absolute time when the validity of the CRL begins. The datetime format is
|
||||
defined by the
|
||||
.B \-\-dateform
|
||||
option.
|
||||
.TP
|
||||
.BI "\-T, \-\-next-update " datetime
|
||||
Absolute time when the validity of the CRL end. The datetime format is
|
||||
defined by the
|
||||
.B \-\-dateform
|
||||
option.
|
||||
.TP
|
||||
.BI "\-D, \-\-dateform " form
|
||||
strptime(3) format for the
|
||||
.B \-\-this\-update
|
||||
and
|
||||
.B \-\-next\-update
|
||||
options, default:
|
||||
.B %d.%m.%y %T
|
||||
.TP
|
||||
.BI "\-a, \-\-lastcrl " crl
|
||||
CRL of lastUpdate to copy revocations from.
|
||||
|
@ -121,4 +144,4 @@ number, but no reason:
|
|||
.PP
|
||||
.SH "SEE ALSO"
|
||||
.
|
||||
.BR pki (1)
|
||||
.BR pki (1)
|
||||
|
|
|
@ -49,6 +49,9 @@ Issue a certificate using a CA certificate and key.
|
|||
.B "\-c, \-\-signcrl"
|
||||
Issue a CRL using a CA certificate and key.
|
||||
.TP
|
||||
.B "\-z, \-\-acert"
|
||||
Issue an attribute certificate.
|
||||
.TP
|
||||
.B "\-r, \-\-req"
|
||||
Create a PKCS#10 certificate request.
|
||||
.TP
|
||||
|
@ -148,6 +151,7 @@ certificates with the \-\-crl option.
|
|||
.BR pki\ \-\-self (1),
|
||||
.BR pki\ \-\-issue (1),
|
||||
.BR pki\ \-\-signcrl (1),
|
||||
.BR pki\ \-\-acert (1),
|
||||
.BR pki\ \-\-req (1),
|
||||
.BR pki\ \-\-pkcs7 (1),
|
||||
.BR pki\ \-\-keyid (1),
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
* for more details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "command.h"
|
||||
#include "pki.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
@ -101,6 +103,56 @@ bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
|
||||
time_t *nb, time_t *na)
|
||||
{
|
||||
struct tm tm;
|
||||
time_t now;
|
||||
char *end;
|
||||
|
||||
if (!format)
|
||||
{
|
||||
format = "%d.%m.%y %T";
|
||||
}
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
localtime_r(&now, &tm);
|
||||
if (nbstr)
|
||||
{
|
||||
end = strptime(nbstr, format, &tm);
|
||||
if (end == NULL || *end != '\0')
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
*nb = mktime(&tm);
|
||||
|
||||
localtime_r(&now, &tm);
|
||||
if (nastr)
|
||||
{
|
||||
end = strptime(nastr, format, &tm);
|
||||
if (end == NULL || *end != '\0')
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
*na = mktime(&tm);
|
||||
|
||||
if (!nbstr && nastr)
|
||||
{
|
||||
*nb = *na - span;
|
||||
}
|
||||
else if (!nastr)
|
||||
{
|
||||
*na = *nb + span;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback credential set pki uses
|
||||
*/
|
||||
|
@ -188,4 +240,3 @@ int main(int argc, char *argv[])
|
|||
atexit(remove_callback);
|
||||
return command_dispatch(argc, argv);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,4 +33,21 @@
|
|||
*/
|
||||
bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type);
|
||||
|
||||
/**
|
||||
* Calculate start/end lifetime for certificates.
|
||||
*
|
||||
* If both nbstr and nastr are given, span is ignored. Otherwise missing
|
||||
* arguments are calculated, or assumed to be now.
|
||||
*
|
||||
* @param format strptime() format, NULL for default: %d.%m.%y %T
|
||||
* @param nbstr string describing notBefore datetime, or NULL
|
||||
* @param nastr string describing notAfter datetime, or NULL
|
||||
* @param span lifetime span, from notBefore to notAfter
|
||||
* @param nb calculated notBefore time
|
||||
* @param na calculated notAfter time
|
||||
* @return TRUE of nb/na calculated successfully
|
||||
*/
|
||||
bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
|
||||
time_t *nb, time_t *na);
|
||||
|
||||
#endif /** PKI_H_ @}*/
|
||||
|
|
|
@ -76,6 +76,7 @@ CONFIG_OPTS = \
|
|||
--enable-unbound \
|
||||
--enable-ipseckey \
|
||||
--enable-dnscert \
|
||||
--enable-acert \
|
||||
--enable-cmd \
|
||||
--enable-libipsec \
|
||||
--enable-kernel-libipsec \
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<p>The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each
|
||||
to gateway <b>moon</b>. The authentication is based on <b>X.509 certificates</b>.
|
||||
To authorize clients, <b>moon</b> uses locally cached attribute certificates.
|
||||
While for <b>carol</b> a valid attribute certificate for the group <i>sales</i>
|
||||
is available, <b>dave</b>'s attribute certificates are either expired or
|
||||
do not grant permissions for the <i>sales</i> group.</p>
|
||||
<p>Upon the successful establishment of the IPsec tunnels, <b>leftfirewall=yes</b>
|
||||
automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
|
||||
In order to test both tunnel and firewall, both <b>carol</b> and <b>dave</b> try
|
||||
to ping the client <b>alice</b> behind the gateway <b>moon</b>, but dave fails
|
||||
to do so.</p>
|
|
@ -0,0 +1,12 @@
|
|||
carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol@strongswan.org.*moon.strongswan.org::YES
|
||||
dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave@strongswan.org.*moon.strongswan.org::NO
|
||||
moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol@strongswan.org::YES
|
||||
moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave@strongswan.org::NO
|
||||
moon::cat /var/log/daemon.log::constraint check failed: group membership to 'sales' required::YES
|
||||
dave::cat /var/log/daemon.log::received AUTHENTICATION_FAILED notify error::YES
|
||||
carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
|
||||
dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
|
||||
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::NO
|
||||
moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::NO
|
|
@ -0,0 +1,20 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
|
||||
conn home
|
||||
left=PH_IP_CAROL
|
||||
leftcert=carolCert.pem
|
||||
leftid=carol@strongswan.org
|
||||
leftfirewall=yes
|
||||
right=PH_IP_MOON
|
||||
rightid=@moon.strongswan.org
|
||||
rightsubnet=10.1.0.0/16
|
||||
keyexchange=ikev2
|
||||
auto=add
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
|
||||
conn home
|
||||
left=PH_IP_DAVE
|
||||
leftcert=daveCert.pem
|
||||
leftid=dave@strongswan.org
|
||||
leftfirewall=yes
|
||||
right=PH_IP_MOON
|
||||
rightid=@moon.strongswan.org
|
||||
rightsubnet=10.1.0.0/16
|
||||
keyexchange=ikev2
|
||||
auto=add
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
|
||||
conn rw
|
||||
left=PH_IP_MOON
|
||||
leftcert=moonCert.pem
|
||||
leftid=@moon.strongswan.org
|
||||
leftsubnet=10.1.0.0/16
|
||||
leftfirewall=yes
|
||||
right=%any
|
||||
rightgroups=sales
|
||||
keyexchange=ikev2
|
||||
auto=add
|
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDKjCCAhKgAwIBAgIIFU5+Fa8cF2EwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE
|
||||
BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u
|
||||
Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDcwODUwMzVaFw0yMjA0MjYwODUwMzVaMEAx
|
||||
CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRYwFAYDVQQD
|
||||
Ew1zdHJvbmdTd2FuIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||
y6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTFFbSbpQJxWk603BJH
|
||||
hlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsAQ3yWfkZZK1jxTdTP
|
||||
dvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqYzdWFCUINTXUGEr/L
|
||||
lt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNTjS2xaaklUCq2auR/
|
||||
QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf+7suyGczSRMP6+5N
|
||||
jqNqab7l/SHwHQMVEE5ihwIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2
|
||||
bbO15eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAakPgMKVjkQmpI1VROcetvZzM
|
||||
ZHMWwdu9IcwNpi/8qs2qNh6wCYv9c4V6O4zRCB1u8TuAIQiwLNZgjk+OKKLzvUik
|
||||
gBRogn/apXsvAtfu9ODv5GuS6F38OYWDu/c3fiCZB2MKTtmEro2EkxxMw4DkfJ02
|
||||
R/xrhAnjeQlRQOChgQ3fHNmH9gVNaKXNq+JaoU2TfHFwuYMMe6q1L+vhOaBd58YA
|
||||
6wPHOOLcIEaebHIqa4duAE5txJsZCEEySrr5stqo4j7929BAw+U6f+6Wb+UAEW6g
|
||||
91PKAl5QVbAzgPFWoPkOTNdDOprT+B4eGx0EC2QTEtxxDv5589choF7BMRCzsQ==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN ATTRIBUTE CERTIFICATE-----
|
||||
MIIC+DCCAeACAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
|
||||
bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe
|
||||
pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
|
||||
BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG
|
||||
MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW
|
||||
MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIIWCKrRUelL+kw
|
||||
IhgPMjAxNDAyMDcwODU4MTJaGA8yMDIyMDQyNjA4NTgxMlowIjAgBggrBgEFBQcK
|
||||
BDEUMBIwEAwFc2FsZXMMB2ZpbmFuY2UwfzByBgNVHSMEazBpCwHqxzoCXPi2xMHh
|
||||
2q7CV/ZSsLChSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJv
|
||||
bmdTd2FuMRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCCBVOfhWvHBdhMAkG
|
||||
A1UdOAQCBQAwDQYJKoZIhvcNAQEFBQADggEBADNSv52dbBOp30L0kJse9HqWMBaR
|
||||
SA5IDrF1FMLVZfI0Vb9XgEmk1SXAnMmPm7bfk+2w0Rd1jL7D905nel3LXuvohSR9
|
||||
wd4Vo8XX3WUlzNfjUEFFJb0nU2ybr7SmxF+K4wGnhvBAym2y/hNA0glp2hNjYTds
|
||||
g+RUpM4bSqP5DpUfRBl19VHeEu/OymoACOzuHuNc1IndYM1mkSJYumX6YW60DpF/
|
||||
TaK1So3FyEWucHeoFCziNbclrjWwB8OS3JfCOl95rxu+0JhyWc+3x1E50W8DaAnY
|
||||
ZRyYxDjYT9/E9xyzV45yo0xFODIgDgfKMsDjfUmfny3dTesdFUf3Ar3vTfA=
|
||||
-----END ATTRIBUTE CERTIFICATE-----
|
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN ATTRIBUTE CERTIFICATE-----
|
||||
MIIC9DCCAdwCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
|
||||
bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf
|
||||
pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR
|
||||
BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg
|
||||
RjBEpEIwQDELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
|
||||
FjAUBgNVBAMTDXN0cm9uZ1N3YW4gQUEwDQYJKoZIhvcNAQEFBQACCCPxWgWKmOUM
|
||||
MCIYDzIwMTQwMjA3MDg1OTM3WhgPMjAyMjA0MjYwODU5MzdaMB0wGwYIKwYBBQUH
|
||||
CgQxDzANMAsMCW1hcmtldGluZzB/MHIGA1UdIwRrMGkLAerHOgJc+LbEweHarsJX
|
||||
9lKwsKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3
|
||||
YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIIFU5+Fa8cF2EwCQYDVR04
|
||||
BAIFADANBgkqhkiG9w0BAQUFAAOCAQEAThlKhGVv34sfnCSQn6nYUdxMhboTuC98
|
||||
+DgvTQ/tH0hddCJNg00SpO8AbStwEsqHFaSqFzAGHcMk+XUrBRSGszAwg8nKAKfT
|
||||
MCvJbK6lWQcPF0WPSSk9/r1TLan4I9xhneNIIGQf1fnNo7NrQnmhJjolUgXQNwFA
|
||||
qZgKBsk0jWcOSvI0bpK90km5flCHn/OA1rDCdaPuMwreDhvNDoApORYFPZVsLhid
|
||||
CXSqT+FWfm2NfegS+Q4VHP3YLbY4vLepCerU9aMTUIPit0kf1N8piG/l6AUno1XP
|
||||
VrcTvruQUWQb08H9aYt7l7kyhzOKkuXjVbdn5egZnK0m4WKmV50guA==
|
||||
-----END ATTRIBUTE CERTIFICATE-----
|
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN ATTRIBUTE CERTIFICATE-----
|
||||
MIIC8DCCAdgCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
|
||||
bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf
|
||||
pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR
|
||||
BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg
|
||||
RjBEpEIwQDELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
|
||||
FjAUBgNVBAMTDXN0cm9uZ1N3YW4gQUEwDQYJKoZIhvcNAQEFBQACCEuGbFvrRrtr
|
||||
MCIYDzIwMTQwMjA3MDgwMTE3WhgPMjAxNDAyMDcwOTAxMTdaMBkwFwYIKwYBBQUH
|
||||
CgQxCzAJMAcMBXNhbGVzMH8wcgYDVR0jBGswaQsB6sc6Alz4tsTB4dquwlf2UrCw
|
||||
oUmkRzBFMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEb
|
||||
MBkGA1UEAxMSc3Ryb25nU3dhbiBSb290IENBgggVTn4VrxwXYTAJBgNVHTgEAgUA
|
||||
MA0GCSqGSIb3DQEBBQUAA4IBAQBYnOq716FJ079kXAt8vmi2GpEyyCqSBqqjr0lR
|
||||
X9mGQqWKmpj88ZP61tCooCy8HaJsgKBvedKJHJ4e/YxR+fqBDkT4apFu4wX8P/xh
|
||||
yKy6/RMAdTtkwVTE6flXdQryCQ/PGhSMuwwH/URFg65mixAatyyaoat4+mZ506u3
|
||||
F9ZZXkHPP4nZXAJqYjLLcNXPqC4lGoXXT+9dgsm6RLAdnBXT1GGff9tmqt9CcspW
|
||||
XPjoqy9AxNr6FnItvMGw0CC6MPyVOJImlSxdhFW7waZkpNfmGzRdylXMwHXk8PbW
|
||||
gjmlDUbyWquu8xBlpron3X/Jx3YNGVNrhgfZLlmhzCRouMqc
|
||||
-----END ATTRIBUTE CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAy6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTF
|
||||
FbSbpQJxWk603BJHhlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsA
|
||||
Q3yWfkZZK1jxTdTPdvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqY
|
||||
zdWFCUINTXUGEr/Llt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNT
|
||||
jS2xaaklUCq2auR/QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf
|
||||
+7suyGczSRMP6+5NjqNqab7l/SHwHQMVEE5ihwIDAQABAoIBAQCIvn5QfkYUG87+
|
||||
eyirV2xTjdMw/Md1UfBgP4yTTsmpqr79K5fUqg5zLX+0VfJDbRaPEICBKCVrKDfz
|
||||
d5QFwAsTiXf8CKwQqFdEunWmJfgppEQIYGzN40IciNloLHDghEnEI9GGpv9glLQn
|
||||
DugjRprEUmWJ+HpB0LH9fc2Ums704Fcd8ud3bStCRxU1TA5VGBHmnyK5/n1Lb1oB
|
||||
01LoW8ins8lATuV+MAaWZgmCbPajfXY9wQGq3IDMVlOUOTxRo742T1GTrwBZR8ot
|
||||
mgs/Gs1XkJRC1x9Z9Z1Cej1iC5llv0zX8AUdejczGHQGHj1a1Dg8FpRneW6rrLyK
|
||||
vvKR8jtRAoGBAOpyk63yCPM2LqU4US5aHXPoLyyGeo4v7okTKIuoUfosQ4XJvylM
|
||||
lEYoFVFKYBKcXRQhmeWyILtto2BBDnG1HWAi1MbUWLxDNEYieurzJiv4i0XbR6cH
|
||||
mLhMMlQyKmwLRF5v3EiupjKBZRk2iYcx4eeL3gsUWUzRPeWJHKDgYF4PAoGBAN5i
|
||||
xyOsU/32gQ6vLQxt8us6n3OBr1PiFg8JIdADPnKOCxJ5uS8dkqOQHCMKyvS9MWrf
|
||||
3Wj4MOBEgW7fBBAxkvjJdPhBW70/pGM46mb991dTHJ4gIAzGxgvJIqw/FjqEC7Oo
|
||||
vWDRS4dxW56Rs2tdLn2GRvvlS3+3z90twqS/t6wJAoGBAJpzhzT2Gc1YaZxxIJI/
|
||||
zd15HfLgWUbo7uWhGHoBFpiQpp8yDNzBVYFukLSwIeDA4FUN2dxH4GZ50ULtOP3S
|
||||
Cps19yVR6W+Fep+lwYKdUw1uvRn1Xxv71jG8CQAM2IO7XHw2h1HetSDau+bDVhEZ
|
||||
3LB1JX/5FOeVhYh9Lr4Rc4sjAoGBAJCTCv+oEtqyHOjc/Z5tBFXkwLCpCMCx5MFV
|
||||
oIPI+BolOhGCzN9SjHiFQaWOaK9/J9dhPmH1qGDEaJkZp1yXvgK7ha23X9rCuy4+
|
||||
XDUkul4tDBfIrs1flHUpB7+PK/ZSzgC4nJWKu12MVpHaCxirdYPpfdBZGyIm753N
|
||||
GBNfCBtxAoGAKkrHlsfq7GVVU7Jj1AlNCwmlm21vSJ45G3cNR1GpgdplB5JR1ldV
|
||||
2kxA4xm8uFVIJ60OQ9VZ5Svaovqh8iX2sndSOZMefjH3qiDu/4mJqRA3xV5ugon3
|
||||
RAzinJzUU4tnk9pajOMD3FHOHvUO4hAJjVYEzqLIIRE7QhPuEpLevZ4=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation acert hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
moon::ipsec stop
|
||||
carol::ipsec stop
|
||||
dave::ipsec stop
|
||||
moon::iptables-restore < /etc/iptables.flush
|
||||
carol::iptables-restore < /etc/iptables.flush
|
||||
dave::iptables-restore < /etc/iptables.flush
|
||||
moon::rm /etc/ipsec.d/acerts/carol-sales-finance.pem
|
||||
moon::rm /etc/ipsec.d/acerts/dave-sales-expired.pem
|
||||
moon::rm /etc/ipsec.d/acerts/dave-marketing.pem
|
||||
moon::rm /etc/ipsec.d/private/aa.pem
|
||||
moon::rm /etc/ipsec.d/aacerts/aa.pem
|
|
@ -0,0 +1,9 @@
|
|||
moon::iptables-restore < /etc/iptables.rules
|
||||
carol::iptables-restore < /etc/iptables.rules
|
||||
dave::iptables-restore < /etc/iptables.rules
|
||||
moon::ipsec start
|
||||
carol::ipsec start
|
||||
dave::ipsec start
|
||||
carol::sleep 1
|
||||
carol::ipsec up home
|
||||
dave::ipsec up home
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="alice moon carol winnetou dave"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="a-m-c-w-d.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS="moon"
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon carol dave"
|
|
@ -0,0 +1,12 @@
|
|||
<p>The roadwarrior <b>carol</b> sets up a connection to gateway <b>moon</b>.
|
||||
The authentication is based on <b>X.509 certificates</b>. To authorize clients,
|
||||
<b>moon</b> expects attribute certificates sent inline in IKEv2 CERT payloads.
|
||||
<b>Carol</b> has attribute certificates for both the <i>sales</i> and
|
||||
the <i>finance</i> groups. The attribute certificate for <i>finance</i> is not
|
||||
valid anymore, hence <b>carol</b> gets access to the <i>sales</i> connection
|
||||
only.</p>
|
||||
<p>Upon the successful establishment of the IPsec tunnel, <b>leftfirewall=yes</b>
|
||||
automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
|
||||
In order to test both tunnel and firewall, <b>carol</b> tries to ping both
|
||||
<b>alice</b> and <b>venus</b>, but only the ping for the <i>sales</i> related
|
||||
host <b>venus</b> succeeds.</p>
|
|
@ -0,0 +1,8 @@
|
|||
carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol@strongswan.org.*moon.strongswan.org::YES
|
||||
moon:: ipsec status 2> /dev/null::finance.*: ESTABLISHED.*moon.strongswan.org.*dave@strongswan.org::NO
|
||||
moon:: ipsec status 2> /dev/null::sales.*: ESTABLISHED.*moon.strongswan.org.*carol@strongswan.org::YES
|
||||
moon::cat /var/log/daemon.log::constraint check failed: group membership to 'finance' required::YES
|
||||
carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
|
||||
carol::ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
|
||||
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
|
|
@ -0,0 +1,20 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
|
||||
conn home
|
||||
left=PH_IP_CAROL
|
||||
leftcert=carolCert.pem
|
||||
leftid=carol@strongswan.org
|
||||
leftfirewall=yes
|
||||
right=PH_IP_MOON
|
||||
rightid=@moon.strongswan.org
|
||||
rightsubnet=10.1.0.0/16
|
||||
keyexchange=ikev2
|
||||
auto=add
|
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN ATTRIBUTE CERTIFICATE-----
|
||||
MIIC8TCCAdkCAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
|
||||
bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe
|
||||
pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
|
||||
BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG
|
||||
MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW
|
||||
MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIISLuuiWM2O9Yw
|
||||
IhgPMjAxNDAyMDcwODQyMDVaGA8yMDE0MDIwNzA5NDIwNVowGzAZBggrBgEFBQcK
|
||||
BDENMAswCQwHZmluYW5jZTB/MHIGA1UdIwRrMGkLAerHOgJc+LbEweHarsJX9lKw
|
||||
sKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
|
||||
GzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIIFU5+Fa8cF2EwCQYDVR04BAIF
|
||||
ADANBgkqhkiG9w0BAQUFAAOCAQEAaDwqM5BY9pXhlSlT3cpCJYsNCfk6T1nG5s5J
|
||||
Dtgwojw0BVSoxKqcbpWdP09HOpBcwbPVk++I19wd5VsdHxtQ4/o2Hoevg4QWxUUx
|
||||
t3qsdMDjg7U2iH+JppYsEDmXmx9k1hvV1OiEzHJKTDlZqXkhiItLatKSptTG3c0A
|
||||
DdJVS05sdepzhkRGimE/QwO7nJ3v5ixFNIetgfbojbjhJPpNfXPIgMMHerK/hAlo
|
||||
ekSwcmh9ufFuEXg8C0NunQqf6Z6FbxiUXUF9j7dvlEp3n5YFsv3WSMUjE3Sb7r8T
|
||||
3e2A/LXb05ky0/SNebgS4fU9oi8acEgwN2Vqwu82hClwYAcHJg==
|
||||
-----END ATTRIBUTE CERTIFICATE-----
|
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN ATTRIBUTE CERTIFICATE-----
|
||||
MIIC7zCCAdcCAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
|
||||
bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe
|
||||
pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
|
||||
BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG
|
||||
MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW
|
||||
MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIIYO/yp98Yxu4w
|
||||
IhgPMjAxNDAyMDcxMDAxNTdaGA8yMDIyMDQyNjEwMDE1N1owGTAXBggrBgEFBQcK
|
||||
BDELMAkwBwwFc2FsZXMwfzByBgNVHSMEazBpCwHqxzoCXPi2xMHh2q7CV/ZSsLCh
|
||||
SaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRsw
|
||||
GQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCCBVOfhWvHBdhMAkGA1UdOAQCBQAw
|
||||
DQYJKoZIhvcNAQEFBQADggEBAJA/duSysWae5X9JTC0BLY6gK8ggj5V9H3d60rM4
|
||||
7A8HVQldWe5QwYIRZmLS0XhMVHWiIvXJHwue2Xgs8DyAqILSCKIKpCJRhqPIxHCh
|
||||
bek1nzw2YzVaU+E37He5V9PSkkRFO9tRvELhW3t4Wya7p4l6MVFW9ETOOtUqZYmt
|
||||
bxAq/XEFZl/aFb2FW2RoKjUZpwxbrccCaV1hKIxtNen2ro31dNd9YHXe+fE4Fc7r
|
||||
FTwbhOg3QLvZDXmiZt3LCXdMKAhayLbuSVsycuEtac44OVSvKhJ8GYykTRRn67nU
|
||||
qCFNDe266KTNDqUMilrHm3FYGkpFtREOBajH4EqdMAJSdXg=
|
||||
-----END ATTRIBUTE CERTIFICATE-----
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
|
||||
conn finance
|
||||
left=PH_IP_MOON
|
||||
leftcert=moonCert.pem
|
||||
leftid=@moon.strongswan.org
|
||||
leftsubnet=10.1.0.10/32
|
||||
leftfirewall=yes
|
||||
right=%any
|
||||
rightid=*@strongswan.org
|
||||
rightgroups=finance
|
||||
keyexchange=ikev2
|
||||
auto=add
|
||||
|
||||
conn sales
|
||||
left=PH_IP_MOON
|
||||
leftcert=moonCert.pem
|
||||
leftid=@moon.strongswan.org
|
||||
leftsubnet=10.1.0.20/32
|
||||
leftfirewall=yes
|
||||
right=%any
|
||||
rightgroups=sales
|
||||
keyexchange=ikev2
|
||||
auto=add
|
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDKjCCAhKgAwIBAgIIFU5+Fa8cF2EwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE
|
||||
BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u
|
||||
Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDcwODUwMzVaFw0yMjA0MjYwODUwMzVaMEAx
|
||||
CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRYwFAYDVQQD
|
||||
Ew1zdHJvbmdTd2FuIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||
y6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTFFbSbpQJxWk603BJH
|
||||
hlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsAQ3yWfkZZK1jxTdTP
|
||||
dvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqYzdWFCUINTXUGEr/L
|
||||
lt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNTjS2xaaklUCq2auR/
|
||||
QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf+7suyGczSRMP6+5N
|
||||
jqNqab7l/SHwHQMVEE5ihwIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2
|
||||
bbO15eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAakPgMKVjkQmpI1VROcetvZzM
|
||||
ZHMWwdu9IcwNpi/8qs2qNh6wCYv9c4V6O4zRCB1u8TuAIQiwLNZgjk+OKKLzvUik
|
||||
gBRogn/apXsvAtfu9ODv5GuS6F38OYWDu/c3fiCZB2MKTtmEro2EkxxMw4DkfJ02
|
||||
R/xrhAnjeQlRQOChgQ3fHNmH9gVNaKXNq+JaoU2TfHFwuYMMe6q1L+vhOaBd58YA
|
||||
6wPHOOLcIEaebHIqa4duAE5txJsZCEEySrr5stqo4j7929BAw+U6f+6Wb+UAEW6g
|
||||
91PKAl5QVbAzgPFWoPkOTNdDOprT+B4eGx0EC2QTEtxxDv5589choF7BMRCzsQ==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAy6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTF
|
||||
FbSbpQJxWk603BJHhlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsA
|
||||
Q3yWfkZZK1jxTdTPdvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqY
|
||||
zdWFCUINTXUGEr/Llt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNT
|
||||
jS2xaaklUCq2auR/QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf
|
||||
+7suyGczSRMP6+5NjqNqab7l/SHwHQMVEE5ihwIDAQABAoIBAQCIvn5QfkYUG87+
|
||||
eyirV2xTjdMw/Md1UfBgP4yTTsmpqr79K5fUqg5zLX+0VfJDbRaPEICBKCVrKDfz
|
||||
d5QFwAsTiXf8CKwQqFdEunWmJfgppEQIYGzN40IciNloLHDghEnEI9GGpv9glLQn
|
||||
DugjRprEUmWJ+HpB0LH9fc2Ums704Fcd8ud3bStCRxU1TA5VGBHmnyK5/n1Lb1oB
|
||||
01LoW8ins8lATuV+MAaWZgmCbPajfXY9wQGq3IDMVlOUOTxRo742T1GTrwBZR8ot
|
||||
mgs/Gs1XkJRC1x9Z9Z1Cej1iC5llv0zX8AUdejczGHQGHj1a1Dg8FpRneW6rrLyK
|
||||
vvKR8jtRAoGBAOpyk63yCPM2LqU4US5aHXPoLyyGeo4v7okTKIuoUfosQ4XJvylM
|
||||
lEYoFVFKYBKcXRQhmeWyILtto2BBDnG1HWAi1MbUWLxDNEYieurzJiv4i0XbR6cH
|
||||
mLhMMlQyKmwLRF5v3EiupjKBZRk2iYcx4eeL3gsUWUzRPeWJHKDgYF4PAoGBAN5i
|
||||
xyOsU/32gQ6vLQxt8us6n3OBr1PiFg8JIdADPnKOCxJ5uS8dkqOQHCMKyvS9MWrf
|
||||
3Wj4MOBEgW7fBBAxkvjJdPhBW70/pGM46mb991dTHJ4gIAzGxgvJIqw/FjqEC7Oo
|
||||
vWDRS4dxW56Rs2tdLn2GRvvlS3+3z90twqS/t6wJAoGBAJpzhzT2Gc1YaZxxIJI/
|
||||
zd15HfLgWUbo7uWhGHoBFpiQpp8yDNzBVYFukLSwIeDA4FUN2dxH4GZ50ULtOP3S
|
||||
Cps19yVR6W+Fep+lwYKdUw1uvRn1Xxv71jG8CQAM2IO7XHw2h1HetSDau+bDVhEZ
|
||||
3LB1JX/5FOeVhYh9Lr4Rc4sjAoGBAJCTCv+oEtqyHOjc/Z5tBFXkwLCpCMCx5MFV
|
||||
oIPI+BolOhGCzN9SjHiFQaWOaK9/J9dhPmH1qGDEaJkZp1yXvgK7ha23X9rCuy4+
|
||||
XDUkul4tDBfIrs1flHUpB7+PK/ZSzgC4nJWKu12MVpHaCxirdYPpfdBZGyIm753N
|
||||
GBNfCBtxAoGAKkrHlsfq7GVVU7Jj1AlNCwmlm21vSJ45G3cNR1GpgdplB5JR1ldV
|
||||
2kxA4xm8uFVIJ60OQ9VZ5Svaovqh8iX2sndSOZMefjH3qiDu/4mJqRA3xV5ugon3
|
||||
RAzinJzUU4tnk9pajOMD3FHOHvUO4hAJjVYEzqLIIRE7QhPuEpLevZ4=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation acert hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
moon::ipsec stop
|
||||
carol::ipsec stop
|
||||
moon::iptables-restore < /etc/iptables.flush
|
||||
carol::iptables-restore < /etc/iptables.flush
|
||||
carol::rm /etc/ipsec.d/acerts/carol-sales.pem
|
||||
carol::rm /etc/ipsec.d/acerts/carol-finance-expired.pem
|
||||
moon::rm /etc/ipsec.d/private/aa.pem
|
||||
moon::rm /etc/ipsec.d/aacerts/aa.pem
|
|
@ -0,0 +1,6 @@
|
|||
moon::iptables-restore < /etc/iptables.rules
|
||||
carol::iptables-restore < /etc/iptables.rules
|
||||
moon::ipsec start
|
||||
carol::ipsec start
|
||||
carol::sleep 1
|
||||
carol::ipsec up home
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="alice venus moon carol winnetou"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="a-v-m-c-w-d.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS=""
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon carol"
|
|
@ -0,0 +1,12 @@
|
|||
<p>The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each
|
||||
to gateway <b>moon</b>. The authentication is based on <b>X.509 certificates</b>.
|
||||
To authorize clients, <b>moon</b> expects attribute certificates sent inline in
|
||||
IKEv2 CERT payloads. <b>Carol</b> provides a valid attribute certificate for
|
||||
the group <i>sales</i>, but <b>dave</b> offers two invalid attribute
|
||||
certificates: One is not for the <i>sales</i> group, and the other is issued by
|
||||
an AA that has been expired.</p>
|
||||
<p>Upon the successful establishment of the IPsec tunnels, <b>leftfirewall=yes</b>
|
||||
automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
|
||||
In order to test both tunnel and firewall, both <b>carol</b> and <b>dave</b> try
|
||||
to ping the client <b>alice</b> behind the gateway <b>moon</b>, but dave fails
|
||||
to do so.</p>
|
|
@ -0,0 +1,15 @@
|
|||
carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol@strongswan.org.*moon.strongswan.org::YES
|
||||
dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave@strongswan.org.*moon.strongswan.org::NO
|
||||
moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol@strongswan.org::YES
|
||||
moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave@strongswan.org::NO
|
||||
moon::cat /var/log/daemon.log::constraint check failed: group membership to 'sales' required::YES
|
||||
carol::cat /var/log/daemon.log::sending attribute certificate issued by \"C=CH, O=Linux strongSwan, CN=strongSwan AA\"::YES
|
||||
dave::cat /var/log/daemon.log::sending attribute certificate issued by \"C=CH, O=Linux strongSwan, CN=strongSwan AA\"::YES
|
||||
dave::cat /var/log/daemon.log::sending attribute certificate issued by \"C=CH, O=Linux strongSwan, CN=expired AA\"::YES
|
||||
dave::cat /var/log/daemon.log::received AUTHENTICATION_FAILED notify error::YES
|
||||
carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES
|
||||
dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO
|
||||
moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES
|
||||
moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::NO
|
||||
moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::NO
|
|
@ -0,0 +1,20 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
|
||||
conn home
|
||||
left=PH_IP_CAROL
|
||||
leftcert=carolCert.pem
|
||||
leftid=carol@strongswan.org
|
||||
leftfirewall=yes
|
||||
right=PH_IP_MOON
|
||||
rightid=@moon.strongswan.org
|
||||
rightsubnet=10.1.0.0/16
|
||||
keyexchange=ikev2
|
||||
auto=add
|
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN ATTRIBUTE CERTIFICATE-----
|
||||
MIIC7zCCAdcCAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
|
||||
bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe
|
||||
pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
|
||||
BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG
|
||||
MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW
|
||||
MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIIYO/yp98Yxu4w
|
||||
IhgPMjAxNDAyMDcxMDAxNTdaGA8yMDIyMDQyNjEwMDE1N1owGTAXBggrBgEFBQcK
|
||||
BDELMAkwBwwFc2FsZXMwfzByBgNVHSMEazBpCwHqxzoCXPi2xMHh2q7CV/ZSsLCh
|
||||
SaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRsw
|
||||
GQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCCBVOfhWvHBdhMAkGA1UdOAQCBQAw
|
||||
DQYJKoZIhvcNAQEFBQADggEBAJA/duSysWae5X9JTC0BLY6gK8ggj5V9H3d60rM4
|
||||
7A8HVQldWe5QwYIRZmLS0XhMVHWiIvXJHwue2Xgs8DyAqILSCKIKpCJRhqPIxHCh
|
||||
bek1nzw2YzVaU+E37He5V9PSkkRFO9tRvELhW3t4Wya7p4l6MVFW9ETOOtUqZYmt
|
||||
bxAq/XEFZl/aFb2FW2RoKjUZpwxbrccCaV1hKIxtNen2ro31dNd9YHXe+fE4Fc7r
|
||||
FTwbhOg3QLvZDXmiZt3LCXdMKAhayLbuSVsycuEtac44OVSvKhJ8GYykTRRn67nU
|
||||
qCFNDe266KTNDqUMilrHm3FYGkpFtREOBajH4EqdMAJSdXg=
|
||||
-----END ATTRIBUTE CERTIFICATE-----
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
|
||||
conn home
|
||||
left=PH_IP_DAVE
|
||||
leftcert=daveCert.pem
|
||||
leftid=dave@strongswan.org
|
||||
leftfirewall=yes
|
||||
right=PH_IP_MOON
|
||||
rightid=@moon.strongswan.org
|
||||
rightsubnet=10.1.0.0/16
|
||||
keyexchange=ikev2
|
||||
auto=add
|
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN ATTRIBUTE CERTIFICATE-----
|
||||
MIIC7TCCAdUCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
|
||||
bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf
|
||||
pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR
|
||||
BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg
|
||||
QzBBpD8wPTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
|
||||
EzARBgNVBAMTCmV4cGlyZWQgQUEwDQYJKoZIhvcNAQEFBQACCG25qKzXgZ9HMCIY
|
||||
DzIwMTQwMjA3MTAxMzQyWhgPMjAyMjA0MjYxMDEzNDJaMBkwFwYIKwYBBQUHCgQx
|
||||
CzAJMAcMBXNhbGVzMH8wcgYDVR0jBGswabOoTOBJ6lXcG4NAowI32Y/oXa9/oUmk
|
||||
RzBFMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkG
|
||||
A1UEAxMSc3Ryb25nU3dhbiBSb290IENBgggqIkNljRd9CTAJBgNVHTgEAgUAMA0G
|
||||
CSqGSIb3DQEBBQUAA4IBAQCfX/84tHCidlVbOU4is/1hZc+FpK4GG1jcywM9mtjB
|
||||
QUeX28LYkewDdRpe49zJuTbvuIIABTp+4alf/oo7sKLk+o2/qq6CPfx8BSRL1a61
|
||||
Y1wVeGmXqcRQgtX+r3asMtLBoAFO8VaHt6pY52bg2YMNVRrUnCUVLqQjT+/Ujr4f
|
||||
Lhs74VOxn7S94YbqvP5rytNFjdzBREipmb8j4mhIyfwUluoWFCkzxuwRaSEGhSMO
|
||||
NobJuj/mK0PUU+TMYEcOMpQ/nVyb9rBtOvDoNU3BeD+ovuamErT9/9vWhEOwMD4C
|
||||
OeR+ofespDX+AdCyZ1Dr1GMyUmIRK7GERdasIhx5pYMk
|
||||
-----END ATTRIBUTE CERTIFICATE-----
|
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN ATTRIBUTE CERTIFICATE-----
|
||||
MIIC9DCCAdwCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp
|
||||
bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf
|
||||
pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR
|
||||
BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg
|
||||
RjBEpEIwQDELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x
|
||||
FjAUBgNVBAMTDXN0cm9uZ1N3YW4gQUEwDQYJKoZIhvcNAQEFBQACCCPxWgWKmOUM
|
||||
MCIYDzIwMTQwMjA3MDg1OTM3WhgPMjAyMjA0MjYwODU5MzdaMB0wGwYIKwYBBQUH
|
||||
CgQxDzANMAsMCW1hcmtldGluZzB/MHIGA1UdIwRrMGkLAerHOgJc+LbEweHarsJX
|
||||
9lKwsKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3
|
||||
YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIIFU5+Fa8cF2EwCQYDVR04
|
||||
BAIFADANBgkqhkiG9w0BAQUFAAOCAQEAThlKhGVv34sfnCSQn6nYUdxMhboTuC98
|
||||
+DgvTQ/tH0hddCJNg00SpO8AbStwEsqHFaSqFzAGHcMk+XUrBRSGszAwg8nKAKfT
|
||||
MCvJbK6lWQcPF0WPSSk9/r1TLan4I9xhneNIIGQf1fnNo7NrQnmhJjolUgXQNwFA
|
||||
qZgKBsk0jWcOSvI0bpK90km5flCHn/OA1rDCdaPuMwreDhvNDoApORYFPZVsLhid
|
||||
CXSqT+FWfm2NfegS+Q4VHP3YLbY4vLepCerU9aMTUIPit0kf1N8piG/l6AUno1XP
|
||||
VrcTvruQUWQb08H9aYt7l7kyhzOKkuXjVbdn5egZnK0m4WKmV50guA==
|
||||
-----END ATTRIBUTE CERTIFICATE-----
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
# /etc/ipsec.conf - strongSwan IPsec configuration file
|
||||
|
||||
config setup
|
||||
|
||||
conn %default
|
||||
ikelifetime=60m
|
||||
keylife=20m
|
||||
rekeymargin=3m
|
||||
keyingtries=1
|
||||
|
||||
conn rw
|
||||
left=PH_IP_MOON
|
||||
leftcert=moonCert.pem
|
||||
leftid=@moon.strongswan.org
|
||||
leftsubnet=10.1.0.0/16
|
||||
leftfirewall=yes
|
||||
right=%any
|
||||
rightgroups="finance, sales"
|
||||
keyexchange=ikev2
|
||||
auto=add
|
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDJzCCAg+gAwIBAgIIKiJDZY0XfQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE
|
||||
BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u
|
||||
Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDYwOTQ4NTJaFw0xNDAyMDcwOTQ4NTJaMD0x
|
||||
CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRMwEQYDVQQD
|
||||
EwpleHBpcmVkIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0s5R
|
||||
X2Y9KUSoNewtwOhQunET9VRGrVYS+xDewmIuAHZt4jhbETSHS+r/qipV4mI+/orS
|
||||
zma0+GVcDwbHRT3oDCrpG/DMpPznki+OzHT9e/HHk0yxb0Ti6vDDbZOM8y3r7ak0
|
||||
Dcq6BgGwPxwIW2u1YHRTj4yxlr5wj9iKU1SQGCwZIQZmjqrjoQlcrThIXju2bqN3
|
||||
SOjuaN6A2GAvcbb/IeQEm8HBqulmyBuGV7Gk9umG/nr61rulNxEp+3Dsce5mv7JR
|
||||
dX5W8P6pv38A/f31Bh/EetEkv8qdnkH0aVAvd8Kb2yxc8Ofdu0kJNoPHGjrnSywl
|
||||
kPh3z2pw6nOFpyFHoQIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2bbO1
|
||||
5eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAh9Sxryf5ip00ykCMStDYzQk27l4N
|
||||
ncjU19RJqjrCuHupvWPJ+aYQFvssAnGGuK2rbw3rzVQba/Vn/o5d5wr1gxRtNQjv
|
||||
z60jbqllmjF0TWvPf/CM/5LVAQJs2x5Mqtvy3pbNvetFHjZrzVDobdVJpqzaZGnh
|
||||
oP0+HUMdE+fyLa0LfaRKYNv7r/vxvzsHZvgJawHK1b/2VWtrkIMyhAgHYViih06j
|
||||
2bfVI/f5tk7/UljzLOCB22IFIn05wh4jyKq6az7B2Xu1Kk0/eA12eRqG134P8OYe
|
||||
hAPcuj4QEDwV0ESw5cueD2I0MxbXuH2vBG5ziSBfw2Phj7f9iYurmMsZew==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDKjCCAhKgAwIBAgIIFU5+Fa8cF2EwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE
|
||||
BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u
|
||||
Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDcwODUwMzVaFw0yMjA0MjYwODUwMzVaMEAx
|
||||
CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRYwFAYDVQQD
|
||||
Ew1zdHJvbmdTd2FuIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||
y6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTFFbSbpQJxWk603BJH
|
||||
hlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsAQ3yWfkZZK1jxTdTP
|
||||
dvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqYzdWFCUINTXUGEr/L
|
||||
lt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNTjS2xaaklUCq2auR/
|
||||
QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf+7suyGczSRMP6+5N
|
||||
jqNqab7l/SHwHQMVEE5ihwIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2
|
||||
bbO15eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAakPgMKVjkQmpI1VROcetvZzM
|
||||
ZHMWwdu9IcwNpi/8qs2qNh6wCYv9c4V6O4zRCB1u8TuAIQiwLNZgjk+OKKLzvUik
|
||||
gBRogn/apXsvAtfu9ODv5GuS6F38OYWDu/c3fiCZB2MKTtmEro2EkxxMw4DkfJ02
|
||||
R/xrhAnjeQlRQOChgQ3fHNmH9gVNaKXNq+JaoU2TfHFwuYMMe6q1L+vhOaBd58YA
|
||||
6wPHOOLcIEaebHIqa4duAE5txJsZCEEySrr5stqo4j7929BAw+U6f+6Wb+UAEW6g
|
||||
91PKAl5QVbAzgPFWoPkOTNdDOprT+B4eGx0EC2QTEtxxDv5589choF7BMRCzsQ==
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA0s5RX2Y9KUSoNewtwOhQunET9VRGrVYS+xDewmIuAHZt4jhb
|
||||
ETSHS+r/qipV4mI+/orSzma0+GVcDwbHRT3oDCrpG/DMpPznki+OzHT9e/HHk0yx
|
||||
b0Ti6vDDbZOM8y3r7ak0Dcq6BgGwPxwIW2u1YHRTj4yxlr5wj9iKU1SQGCwZIQZm
|
||||
jqrjoQlcrThIXju2bqN3SOjuaN6A2GAvcbb/IeQEm8HBqulmyBuGV7Gk9umG/nr6
|
||||
1rulNxEp+3Dsce5mv7JRdX5W8P6pv38A/f31Bh/EetEkv8qdnkH0aVAvd8Kb2yxc
|
||||
8Ofdu0kJNoPHGjrnSywlkPh3z2pw6nOFpyFHoQIDAQABAoIBAQCRRwiDM2VhBGTc
|
||||
THi3oiLIaldz0fGnUVNhXR33XkwPm45cwbPY5pd7NWeecPChRE3fg/KFtfhv2wKX
|
||||
hHdd+6zofcYKsGeIKJa6gzXpJ5LtkRGWLNt3MEUl3mkAIhiYGoSmU96Axr5ul0lM
|
||||
JNiJkG/+GgzgN/jHR1UxfOzPQs7PKIyzCE2N0v8dRxHWeyPCRxSavlhAoQKjWxCe
|
||||
FfVBzLi+L1faidcwf4GWyeTfhvALXQnQGgVPH6PX0z3mwaeYHPWVXWJGcaF0bi3H
|
||||
HaEb2YexTDkEVU0PUVYO40OgtmKVLmi5t+ZP+/dFasy9elzgM3sSmVc7IBp6BBCH
|
||||
NgUcWcf1AoGBAOiti9raozwdA/wHAMaCCbgXq8Dg0+3LYnb0ob7w8OaHRl4Mvpup
|
||||
7MtxPGmr9IOddf8/49+L9STsioMllGt0TrkMrlKyg/eglGMalvbJmUYw1kERtQZw
|
||||
0CYYE8DXR3fvN+eMl1maZ4Wf048UugWQhsRGzOyUKcMXhAlIXwTevnCfAoGBAOfv
|
||||
isxrw5vttRxfszZaWeomos9bk6NA9FJYG1rS6ocR+Ww2OpQSJVTmbjpYv1lTb9yr
|
||||
PvcZtPbWP/6g8kjPTQQ+ZnJQB4RpWek0KlxwxC6JW5HzqMJFn68zX4/jE5kXqVow
|
||||
Y+Sfgrkr4QXX8vjzp9GFRhAW6bA5DlswqH7XmB+/AoGARHYDx3I7Q026RWZ+GOpc
|
||||
F7mHRKoiUT5di2ixSrA0AXBeCQAw+TZHQRjhUKpSuIMVG/RdhQH2MFYU7z+YawF+
|
||||
xD3x8M0rvSmXX42MS7LHkXp/IAgovmtlI0BEV6JAGg7d4Rhh0/B1c0Cyi8/qaAa9
|
||||
UHUQiK+Tlh6OL/kGVDWBzTsCgYBTW5Jk+e4pontPIU4FoN9j+lLVd7JOIFAvMB9U
|
||||
uy0zMlCUhcDz6rmkE9VV/wN2lThE9P8CTCjv9fy2BR5O8MJbXhnvx7eL7Vk1KVx4
|
||||
MMcxeoiAojPq7p7/ltUnn5MxmIFzOqUMTA/tgUm0kfJvaxLLiLyvl6yRe1AfkhNc
|
||||
0xuHfQKBgQCyQEcvtmR1Qx82ob5uTvBbKFDbSniiJMi9kgMk266PNRdg85Q4RC7X
|
||||
j5KNALOb5u2oMT6/Hzi4KruDBc/6viXRuMYM+L1JIy8y6wcVjCQetxyUIGgc9Ouh
|
||||
59bOkD+SOth52Y+AYFyCaJOSoTFHlTcLwCvk9gVdbgVYJi7/jyohSQ==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAy6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTF
|
||||
FbSbpQJxWk603BJHhlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsA
|
||||
Q3yWfkZZK1jxTdTPdvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqY
|
||||
zdWFCUINTXUGEr/Llt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNT
|
||||
jS2xaaklUCq2auR/QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf
|
||||
+7suyGczSRMP6+5NjqNqab7l/SHwHQMVEE5ihwIDAQABAoIBAQCIvn5QfkYUG87+
|
||||
eyirV2xTjdMw/Md1UfBgP4yTTsmpqr79K5fUqg5zLX+0VfJDbRaPEICBKCVrKDfz
|
||||
d5QFwAsTiXf8CKwQqFdEunWmJfgppEQIYGzN40IciNloLHDghEnEI9GGpv9glLQn
|
||||
DugjRprEUmWJ+HpB0LH9fc2Ums704Fcd8ud3bStCRxU1TA5VGBHmnyK5/n1Lb1oB
|
||||
01LoW8ins8lATuV+MAaWZgmCbPajfXY9wQGq3IDMVlOUOTxRo742T1GTrwBZR8ot
|
||||
mgs/Gs1XkJRC1x9Z9Z1Cej1iC5llv0zX8AUdejczGHQGHj1a1Dg8FpRneW6rrLyK
|
||||
vvKR8jtRAoGBAOpyk63yCPM2LqU4US5aHXPoLyyGeo4v7okTKIuoUfosQ4XJvylM
|
||||
lEYoFVFKYBKcXRQhmeWyILtto2BBDnG1HWAi1MbUWLxDNEYieurzJiv4i0XbR6cH
|
||||
mLhMMlQyKmwLRF5v3EiupjKBZRk2iYcx4eeL3gsUWUzRPeWJHKDgYF4PAoGBAN5i
|
||||
xyOsU/32gQ6vLQxt8us6n3OBr1PiFg8JIdADPnKOCxJ5uS8dkqOQHCMKyvS9MWrf
|
||||
3Wj4MOBEgW7fBBAxkvjJdPhBW70/pGM46mb991dTHJ4gIAzGxgvJIqw/FjqEC7Oo
|
||||
vWDRS4dxW56Rs2tdLn2GRvvlS3+3z90twqS/t6wJAoGBAJpzhzT2Gc1YaZxxIJI/
|
||||
zd15HfLgWUbo7uWhGHoBFpiQpp8yDNzBVYFukLSwIeDA4FUN2dxH4GZ50ULtOP3S
|
||||
Cps19yVR6W+Fep+lwYKdUw1uvRn1Xxv71jG8CQAM2IO7XHw2h1HetSDau+bDVhEZ
|
||||
3LB1JX/5FOeVhYh9Lr4Rc4sjAoGBAJCTCv+oEtqyHOjc/Z5tBFXkwLCpCMCx5MFV
|
||||
oIPI+BolOhGCzN9SjHiFQaWOaK9/J9dhPmH1qGDEaJkZp1yXvgK7ha23X9rCuy4+
|
||||
XDUkul4tDBfIrs1flHUpB7+PK/ZSzgC4nJWKu12MVpHaCxirdYPpfdBZGyIm753N
|
||||
GBNfCBtxAoGAKkrHlsfq7GVVU7Jj1AlNCwmlm21vSJ45G3cNR1GpgdplB5JR1ldV
|
||||
2kxA4xm8uFVIJ60OQ9VZ5Svaovqh8iX2sndSOZMefjH3qiDu/4mJqRA3xV5ugon3
|
||||
RAzinJzUU4tnk9pajOMD3FHOHvUO4hAJjVYEzqLIIRE7QhPuEpLevZ4=
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,5 @@
|
|||
# /etc/strongswan.conf - strongSwan configuration file
|
||||
|
||||
charon {
|
||||
load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation acert hmac xcbc stroke kernel-netlink socket-default updown
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
moon::ipsec stop
|
||||
carol::ipsec stop
|
||||
dave::ipsec stop
|
||||
moon::iptables-restore < /etc/iptables.flush
|
||||
carol::iptables-restore < /etc/iptables.flush
|
||||
dave::iptables-restore < /etc/iptables.flush
|
||||
carol::rm /etc/ipsec.d/acerts/carol-sales.pem
|
||||
dave::rm /etc/ipsec.d/acerts/dave-expired-aa.pem
|
||||
dave::rm /etc/ipsec.d/acerts/dave-marketing.pem
|
||||
moon::rm /etc/ipsec.d/private/aa-expired.pem
|
||||
moon::rm /etc/ipsec.d/private/aa.pem
|
||||
moon::rm /etc/ipsec.d/aacerts/aa-expired.pem
|
||||
moon::rm /etc/ipsec.d/aacerts/aa.pem
|
|
@ -0,0 +1,9 @@
|
|||
moon::iptables-restore < /etc/iptables.rules
|
||||
carol::iptables-restore < /etc/iptables.rules
|
||||
dave::iptables-restore < /etc/iptables.rules
|
||||
moon::ipsec start
|
||||
carol::ipsec start
|
||||
dave::ipsec start
|
||||
carol::sleep 1
|
||||
carol::ipsec up home
|
||||
dave::ipsec up home
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This configuration file provides information on the
|
||||
# guest instances used for this test
|
||||
|
||||
# All guest instances that are required for this test
|
||||
#
|
||||
VIRTHOSTS="alice moon carol winnetou dave"
|
||||
|
||||
# Corresponding block diagram
|
||||
#
|
||||
DIAGRAM="a-m-c-w-d.png"
|
||||
|
||||
# Guest instances on which tcpdump is to be started
|
||||
#
|
||||
TCPDUMPHOSTS="moon"
|
||||
|
||||
# Guest instances on which IPsec is started
|
||||
# Used for IPsec logging purposes
|
||||
#
|
||||
IPSECHOSTS="moon carol dave"
|
Loading…
Reference in New Issue