refactored openac and its attribute certificate factory
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
ipsec_PROGRAMS = openac
|
||||
openac_SOURCES = openac.c build.c build.h
|
||||
openac_SOURCES = openac.c
|
||||
dist_man_MANS = openac.8
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
/* Build a X.509 attribute certificate
|
||||
* 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.
|
||||
*
|
||||
* RCSID $Id$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <asn1/oid.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <crypto/ietf_attr_list.h>
|
||||
#include <utils/identification.h>
|
||||
|
||||
#include "build.h"
|
||||
|
||||
static u_char ASN1_group_oid_str[] = {
|
||||
0x06, 0x08,
|
||||
0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a ,0x04
|
||||
};
|
||||
|
||||
static const chunk_t ASN1_group_oid = chunk_from_buf(ASN1_group_oid_str);
|
||||
|
||||
static u_char ASN1_authorityKeyIdentifier_oid_str[] = {
|
||||
0x06, 0x03,
|
||||
0x55, 0x1d, 0x23
|
||||
};
|
||||
|
||||
static const chunk_t ASN1_authorityKeyIdentifier_oid =
|
||||
chunk_from_buf(ASN1_authorityKeyIdentifier_oid_str);
|
||||
|
||||
static u_char ASN1_noRevAvail_ext_str[] = {
|
||||
0x30, 0x09,
|
||||
0x06, 0x03,
|
||||
0x55, 0x1d, 0x38,
|
||||
0x04, 0x02,
|
||||
0x05, 0x00
|
||||
};
|
||||
|
||||
static const chunk_t ASN1_noRevAvail_ext = chunk_from_buf(ASN1_noRevAvail_ext_str);
|
||||
|
||||
/**
|
||||
* build directoryName
|
||||
*/
|
||||
static chunk_t build_directoryName(asn1_t tag, chunk_t name)
|
||||
{
|
||||
return asn1_wrap(tag, "m",
|
||||
asn1_simple_object(ASN1_CONTEXT_C_4, name));
|
||||
}
|
||||
|
||||
/**
|
||||
* build holder
|
||||
*/
|
||||
static chunk_t build_holder(void)
|
||||
{
|
||||
identification_t *issuer = usercert->get_issuer(usercert);
|
||||
identification_t *subject = usercert->get_subject(usercert);
|
||||
|
||||
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, usercert->get_serialNumber(usercert))
|
||||
),
|
||||
build_directoryName(ASN1_CONTEXT_C_1, subject->get_encoding(subject)));
|
||||
}
|
||||
|
||||
/**
|
||||
* build v2Form
|
||||
*/
|
||||
static chunk_t build_v2_form(void)
|
||||
{
|
||||
identification_t *subject = signercert->get_subject(signercert);
|
||||
|
||||
return asn1_wrap(ASN1_CONTEXT_C_0, "m",
|
||||
build_directoryName(ASN1_SEQUENCE, subject->get_encoding(subject)));
|
||||
}
|
||||
|
||||
/**
|
||||
* build attrCertValidityPeriod
|
||||
*/
|
||||
static chunk_t build_attr_cert_validity(void)
|
||||
{
|
||||
return asn1_wrap(ASN1_SEQUENCE, "mm",
|
||||
timetoasn1(¬Before, ASN1_GENERALIZEDTIME),
|
||||
timetoasn1(¬After, ASN1_GENERALIZEDTIME));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* build attribute type
|
||||
*/
|
||||
static chunk_t build_attribute_type(const chunk_t type, chunk_t content)
|
||||
{
|
||||
return asn1_wrap(ASN1_SEQUENCE, "cm",
|
||||
type,
|
||||
asn1_wrap(ASN1_SET, "m", content));
|
||||
}
|
||||
|
||||
/**
|
||||
* build attributes
|
||||
*/
|
||||
static chunk_t build_attributes(void)
|
||||
{
|
||||
return asn1_wrap(ASN1_SEQUENCE, "m",
|
||||
build_attribute_type(ASN1_group_oid, ietfAttr_list_encode(groups)));
|
||||
}
|
||||
|
||||
/**
|
||||
* build authorityKeyIdentifier
|
||||
*/
|
||||
static chunk_t build_authorityKeyID(x509_t *signer)
|
||||
{
|
||||
identification_t *issuer = signer->get_issuer(signer);
|
||||
chunk_t subjectKeyID = signer->get_subjectKeyID(signer);
|
||||
|
||||
chunk_t keyIdentifier = (subjectKeyID.ptr == NULL)
|
||||
? chunk_empty
|
||||
: asn1_simple_object(ASN1_CONTEXT_S_0, subjectKeyID);
|
||||
|
||||
chunk_t authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1,
|
||||
issuer->get_encoding(issuer));
|
||||
|
||||
chunk_t authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2,
|
||||
signer->get_serialNumber(signer));
|
||||
|
||||
return asn1_wrap(ASN1_SEQUENCE, "cm",
|
||||
ASN1_authorityKeyIdentifier_oid,
|
||||
asn1_wrap(ASN1_OCTET_STRING, "m",
|
||||
asn1_wrap(ASN1_SEQUENCE, "mmm",
|
||||
keyIdentifier,
|
||||
authorityCertIssuer,
|
||||
authorityCertSerialNumber
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* build extensions
|
||||
*/
|
||||
static chunk_t build_extensions(void)
|
||||
{
|
||||
return asn1_wrap(ASN1_SEQUENCE, "mc",
|
||||
build_authorityKeyID(signercert),
|
||||
ASN1_noRevAvail_ext);
|
||||
}
|
||||
|
||||
/**
|
||||
* build attributeCertificateInfo
|
||||
*/
|
||||
static chunk_t build_attr_cert_info(void)
|
||||
{
|
||||
return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm",
|
||||
ASN1_INTEGER_1,
|
||||
build_holder(),
|
||||
build_v2_form(),
|
||||
asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
|
||||
asn1_simple_object(ASN1_INTEGER, serial),
|
||||
build_attr_cert_validity(),
|
||||
build_attributes(),
|
||||
build_extensions());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* build an X.509 attribute certificate
|
||||
*/
|
||||
chunk_t build_attr_cert(void)
|
||||
{
|
||||
chunk_t signatureValue;
|
||||
chunk_t attributeCertificateInfo = build_attr_cert_info();
|
||||
|
||||
signerkey->build_emsa_pkcs1_signature(signerkey, HASH_SHA1,
|
||||
attributeCertificateInfo, &signatureValue);
|
||||
|
||||
return asn1_wrap(ASN1_SEQUENCE, "mcm",
|
||||
attributeCertificateInfo,
|
||||
asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
|
||||
asn1_bitstring("m", signatureValue));
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/* Build a X.509 attribute certificate
|
||||
* 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.
|
||||
*
|
||||
* RCSID $Id$
|
||||
*/
|
||||
|
||||
#ifndef _BUILD_H
|
||||
#define _BUILD_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <library.h>
|
||||
#include <crypto/x509.h>
|
||||
#include <crypto/rsa/rsa_private_key.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
/*
|
||||
* global variables accessible by both main() and build.c
|
||||
*/
|
||||
extern x509_t *usercert;
|
||||
extern x509_t *signercert;
|
||||
extern rsa_private_key_t *signerkey;
|
||||
extern linked_list_t *groups;
|
||||
extern time_t notBefore;
|
||||
extern time_t notAfter;
|
||||
extern chunk_t serial;
|
||||
|
||||
/*
|
||||
* exported functions
|
||||
*/
|
||||
extern chunk_t build_attr_cert(void);
|
||||
|
||||
#endif /* _BUILD_H */
|
||||
+115
-36
@@ -36,8 +36,8 @@
|
||||
#include <debug.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/ttodata.h>
|
||||
#include <crypto/ac.h>
|
||||
#include <crypto/ietf_attr_list.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
#include <credentials/certificates/ac.h>
|
||||
#include <utils/optionsfrom.h>
|
||||
|
||||
#ifdef INTEGRITY_TEST
|
||||
@@ -47,8 +47,10 @@
|
||||
|
||||
#include "build.h"
|
||||
|
||||
#define OPENAC_PATH IPSEC_CONFDIR "/openac"
|
||||
#define OPENAC_SERIAL IPSEC_CONFDIR "/openac/serial"
|
||||
#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
|
||||
@@ -174,19 +176,80 @@ static void write_serial(chunk_t serial)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and parse a private key file
|
||||
*/
|
||||
static private_key_t* private_key_create_from_file(char *path, chunk_t *secret)
|
||||
{
|
||||
bool pgp = FALSE;
|
||||
chunk_t chunk = chunk_empty;
|
||||
private_key_t *key = NULL;
|
||||
|
||||
if (!pem_asn1_load_file(path, &secret, &chunk, &pgp))
|
||||
{
|
||||
DBG1(" could not load private key file '%s'", path);
|
||||
return NULL;
|
||||
}
|
||||
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
|
||||
BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
|
||||
if (key == NULL)
|
||||
{
|
||||
DBG1(" could not parse loaded private key file '%s'", path);
|
||||
return NULL;
|
||||
}
|
||||
DBG1(" loaded private key file '%s'", path);
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and parse an X.509 certificate file
|
||||
*/
|
||||
static x509_t* x509_create_from_file(char *path, char *label, x509_flag_t flag)
|
||||
{
|
||||
|
||||
bool pgp = FALSE;
|
||||
chunk_t chunk;
|
||||
x509_t *x509;
|
||||
certificate_t *cert;
|
||||
time_t notBefore, notAfter, now;
|
||||
|
||||
if (!pem_asn1_load_file(path, NULL, &chunk, &pgp))
|
||||
{
|
||||
DBG1(" could not load %s file '%s'", label, path);
|
||||
return NULL;
|
||||
}
|
||||
x509 = (x509_t*)lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_BLOB_ASN1_DER, chunk,
|
||||
BUILD_X509_FLAG, flag,
|
||||
BUILD_END);
|
||||
if (x509 == NULL)
|
||||
{
|
||||
DBG1(" could not parse loaded %s file '%s'",label, path);
|
||||
return NULL;
|
||||
}
|
||||
DBG1(" loaded %s file '%s'", label, path);
|
||||
|
||||
/* check validity */
|
||||
cert = &x509->interface;
|
||||
now = time(NULL);
|
||||
cert->get_validity(cert, &now, ¬Before, ¬After);
|
||||
if (now > notAfter)
|
||||
{
|
||||
DBG1(" certificate expired at %T, discarded", ¬After);
|
||||
cert->destroy(cert);
|
||||
return NULL;
|
||||
}
|
||||
if (now < notBefore)
|
||||
{
|
||||
DBG1(" certificate not valid before %T", ¬Before);
|
||||
}
|
||||
return x509;
|
||||
}
|
||||
|
||||
/**
|
||||
* global variables accessible by both main() and build.c
|
||||
*/
|
||||
x509_t *usercert = NULL;
|
||||
x509_t *signercert = NULL;
|
||||
|
||||
linked_list_t *groups = NULL;
|
||||
rsa_private_key_t *signerkey = NULL;
|
||||
|
||||
time_t notBefore = UNDEFINED_TIME;
|
||||
time_t notAfter = UNDEFINED_TIME;
|
||||
|
||||
chunk_t serial;
|
||||
|
||||
static int debug_level = 1;
|
||||
static bool stderr_quiet = FALSE;
|
||||
@@ -220,18 +283,26 @@ static void openac_dbg(int level, char *fmt, ...)
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
certificate_t *attr_cert = NULL;
|
||||
certificate_t *user_cert = NULL;
|
||||
certificate_t *signer_cert = NULL;
|
||||
private_key_t *signer_key = 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 serial;
|
||||
chunk_t passphrase = { buf, 0 };
|
||||
chunk_t attr_cert = chunk_empty;
|
||||
x509ac_t *ac = NULL;
|
||||
chunk_t attr_chunk = chunk_empty;
|
||||
|
||||
const time_t default_validity = 24*3600; /* 24 hours */
|
||||
time_t validity = 0;
|
||||
int status = 1;
|
||||
|
||||
options_t *options = options_create();
|
||||
@@ -240,7 +311,6 @@ int main(int argc, char **argv)
|
||||
dbg = openac_dbg;
|
||||
|
||||
passphrase.ptr[0] = '\0';
|
||||
groups = linked_list_create();
|
||||
|
||||
openlog("openac", 0, LOG_AUTHPRIV);
|
||||
|
||||
@@ -337,7 +407,7 @@ int main(int argc, char **argv)
|
||||
continue;
|
||||
|
||||
case 'g': /* --groups */
|
||||
ietfAttr_list_create_from_string(optarg, groups);
|
||||
groups = optarg;
|
||||
continue;
|
||||
|
||||
case 'D': /* --days */
|
||||
@@ -449,9 +519,9 @@ int main(int argc, char **argv)
|
||||
/* load the signer's RSA private key */
|
||||
if (keyfile != NULL)
|
||||
{
|
||||
signerkey = rsa_private_key_create_from_file(keyfile, &passphrase);
|
||||
signer_key = private_key_create_from_file(keyfile, &passphrase);
|
||||
|
||||
if (signerkey == NULL)
|
||||
if (signer_key == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
@@ -460,41 +530,50 @@ int main(int argc, char **argv)
|
||||
/* load the signer's X.509 certificate */
|
||||
if (certfile != NULL)
|
||||
{
|
||||
signercert = x509_create_from_file(certfile, "signer cert");
|
||||
x509_t *x509 = x509_create_from_file(certfile, "signer cert", 0);
|
||||
|
||||
if (signercert == NULL)
|
||||
if (x509 == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
signer_cert = &x509->interface;
|
||||
}
|
||||
|
||||
/* load the users's X.509 certificate */
|
||||
if (usercertfile != NULL)
|
||||
{
|
||||
usercert = x509_create_from_file(usercertfile, "user cert");
|
||||
x509_t *x509 = x509_create_from_file(usercertfile, "user cert", 0);
|
||||
|
||||
if (usercert == NULL)
|
||||
if (x509 == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
user_cert = &x509->interface;
|
||||
}
|
||||
|
||||
/* compute validity interval */
|
||||
validity = (validity)? validity : default_validity;
|
||||
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)
|
||||
if (user_cert != NULL && signer_cert != NULL && signer_key != NULL)
|
||||
{
|
||||
/* read the serial number and increment it by one */
|
||||
serial = read_serial();
|
||||
|
||||
attr_cert = build_attr_cert();
|
||||
ac = x509ac_create_from_chunk(attr_cert);
|
||||
attr_cert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509_AC,
|
||||
BUILD_CERT, user_cert,
|
||||
BUILD_NOT_BEFORE_TIME, ¬Before,
|
||||
BUILD_NOT_AFTER_TIME, ¬After,
|
||||
BUILD_SIGNING_CERT, signer_cert,
|
||||
BUILD_SIGNING_KEY, signer_key,
|
||||
BUILD_END);
|
||||
attr_chunk = attr_cert->get_encoding(attr_cert);
|
||||
|
||||
/* write the attribute certificate to file */
|
||||
if (chunk_write(attr_cert, outfile, "attribute cert", 0022, TRUE))
|
||||
if (chunk_write(attr_chunk, outfile, "attribute cert", 0022, TRUE))
|
||||
{
|
||||
write_serial(serial);
|
||||
status = 0;
|
||||
@@ -503,11 +582,11 @@ int main(int argc, char **argv)
|
||||
|
||||
end:
|
||||
/* delete all dynamically allocated objects */
|
||||
DESTROY_IF(signerkey);
|
||||
DESTROY_IF(signercert);
|
||||
DESTROY_IF(usercert);
|
||||
DESTROY_IF(ac);
|
||||
ietfAttr_list_destroy(groups);
|
||||
DESTROY_IF(signer_key);
|
||||
DESTROY_IF(signer_cert);
|
||||
DESTROY_IF(user_cert);
|
||||
DESTROY_IF(attr_cert);
|
||||
free(attr_chunk.ptr);
|
||||
free(serial.ptr);
|
||||
closelog();
|
||||
dbg = dbg_default;
|
||||
|
||||
Reference in New Issue
Block a user