mirror of
https://github.com/strongswan/strongswan.git
synced 2025-12-11 00:00:58 -05:00
pluto now uses x509 plugin for attribute certificate handling
This commit is contained in:
parent
0ea9cbc6e9
commit
fc12e3cd2e
@ -36,6 +36,7 @@ credentials/certificates/pkcs10.h \
|
|||||||
credentials/certificates/ocsp_request.h \
|
credentials/certificates/ocsp_request.h \
|
||||||
credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
|
credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
|
||||||
credentials/certificates/pgp_certificate.h \
|
credentials/certificates/pgp_certificate.h \
|
||||||
|
credentials/ietf_attributes/ietf_attributes.c credentials/ietf_attributes/ietf_attributes.h \
|
||||||
database/database.h database/database_factory.h database/database_factory.c \
|
database/database.h database/database_factory.h database/database_factory.c \
|
||||||
fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
|
fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
|
||||||
utils.h utils.c \
|
utils.h utils.c \
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
|
* Copyright (C) 2002-2009 Andreas Steffen
|
||||||
* Copyright (C) 2003 Martin Berner, Lukas Suter
|
|
||||||
* Copyright (C) 2002-2008 Andreas Steffen
|
|
||||||
*
|
*
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@ -26,6 +24,7 @@
|
|||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <credentials/certificates/certificate.h>
|
#include <credentials/certificates/certificate.h>
|
||||||
|
#include <credentials/ietf_attributes/ietf_attributes.h>
|
||||||
|
|
||||||
typedef struct ac_t ac_t;
|
typedef struct ac_t ac_t;
|
||||||
|
|
||||||
@ -64,12 +63,19 @@ struct ac_t {
|
|||||||
identification_t* (*get_holderIssuer)(ac_t *this);
|
identification_t* (*get_holderIssuer)(ac_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the thauthorityKeyIdentifier.
|
* Get the authorityKeyIdentifier.
|
||||||
*
|
*
|
||||||
* @return authKeyIdentifier as chunk_t, to internal data
|
* @return authKeyIdentifier as chunk_t, to internal data
|
||||||
*/
|
*/
|
||||||
chunk_t (*get_authKeyIdentifier)(ac_t *this);
|
chunk_t (*get_authKeyIdentifier)(ac_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the group memberships as a list of IETF attributes
|
||||||
|
*
|
||||||
|
* @return object containing a list of IETF attributes
|
||||||
|
*/
|
||||||
|
ietf_attributes_t* (*get_groups)(ac_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks if two attribute certificates belong to the same holder
|
* @brief Checks if two attribute certificates belong to the same holder
|
||||||
*
|
*
|
||||||
|
|||||||
@ -15,7 +15,8 @@
|
|||||||
|
|
||||||
#include "x509.h"
|
#include "x509.h"
|
||||||
|
|
||||||
ENUM(x509_flag_names, X509_CA, X509_SELF_SIGNED,
|
ENUM(x509_flag_names, X509_NONE, X509_SELF_SIGNED,
|
||||||
|
"X509_NONE",
|
||||||
"X509_CA",
|
"X509_CA",
|
||||||
"X509_AA",
|
"X509_AA",
|
||||||
"X509_OCSP_SIGNER",
|
"X509_OCSP_SIGNER",
|
||||||
|
|||||||
@ -31,6 +31,8 @@ typedef enum x509_flag_t x509_flag_t;
|
|||||||
* X.509 certificate flags.
|
* X.509 certificate flags.
|
||||||
*/
|
*/
|
||||||
enum x509_flag_t {
|
enum x509_flag_t {
|
||||||
|
/** cert has no constraints */
|
||||||
|
X509_NONE = 0,
|
||||||
/** cert has CA constraint */
|
/** cert has CA constraint */
|
||||||
X509_CA = (1<<0),
|
X509_CA = (1<<0),
|
||||||
/** cert has AA constraint */
|
/** cert has AA constraint */
|
||||||
|
|||||||
533
src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c
Normal file
533
src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c
Normal file
@ -0,0 +1,533 @@
|
|||||||
|
/*
|
||||||
|
* 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 <utils/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 = malloc_thing(ietf_attr_t);
|
||||||
|
|
||||||
|
/* initialize */
|
||||||
|
this->type = type;
|
||||||
|
this->value = chunk_clone(value);
|
||||||
|
|
||||||
|
/* function */
|
||||||
|
this->compare = ietf_attr_compare;
|
||||||
|
this->destroy = ietf_attr_destroy;
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ietf_attributes_t.get_string.
|
||||||
|
*/
|
||||||
|
static char* get_string(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 = 0;
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
first = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
written = snprintf(pos, len, ", ");
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos += written;
|
||||||
|
len -= written;
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
if (len < BUF_LEN)
|
||||||
|
{
|
||||||
|
this->string = strdup(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this->string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ietf_attributes_t.get_encoding.
|
||||||
|
*/
|
||||||
|
static chunk_t get_encoding(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
bool 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ietf_attributes_t.get_ref
|
||||||
|
*/
|
||||||
|
static private_ietf_attributes_t* get_ref(private_ietf_attributes_t *this)
|
||||||
|
{
|
||||||
|
ref_get(&this->ref);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ietf_attributes_t.destroy.
|
||||||
|
*/
|
||||||
|
static void destroy(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 = malloc_thing(private_ietf_attributes_t);
|
||||||
|
|
||||||
|
this->public.get_string = (char* (*)(ietf_attributes_t*))get_string;
|
||||||
|
this->public.get_encoding = (chunk_t (*)(ietf_attributes_t*))get_encoding;
|
||||||
|
this->public.equals = (bool (*)(ietf_attributes_t*,ietf_attributes_t*))equals;
|
||||||
|
this->public.matches = (bool (*)(ietf_attributes_t*,ietf_attributes_t*))matches;
|
||||||
|
this->public.get_ref = (ietf_attributes_t* (*)(ietf_attributes_t*))get_ref;
|
||||||
|
this->public.destroy = (void (*)(ietf_attributes_t*))destroy;
|
||||||
|
|
||||||
|
this->list = linked_list_create();
|
||||||
|
this->string = NULL;
|
||||||
|
this->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;
|
||||||
|
bool found = FALSE;
|
||||||
|
iterator_t *iterator;
|
||||||
|
|
||||||
|
iterator = this->list->create_iterator(this->list, TRUE);
|
||||||
|
while (iterator->iterate(iterator, (void **)¤t_attr))
|
||||||
|
{
|
||||||
|
int cmp = attr->compare(attr, current_attr);
|
||||||
|
|
||||||
|
if (cmp > 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cmp == 0)
|
||||||
|
{
|
||||||
|
attr->destroy(attr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iterator->insert_before(iterator, attr);
|
||||||
|
}
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
this->list->insert_last(this->list, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* 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_ @}*/
|
||||||
|
|
||||||
@ -11,7 +11,6 @@ libstrongswan_x509_la_SOURCES = x509_plugin.h x509_plugin.c \
|
|||||||
x509_ac.h x509_ac.c \
|
x509_ac.h x509_ac.c \
|
||||||
x509_pkcs10.h x509_pkcs10.c \
|
x509_pkcs10.h x509_pkcs10.c \
|
||||||
x509_ocsp_request.h x509_ocsp_request.c \
|
x509_ocsp_request.h x509_ocsp_request.c \
|
||||||
x509_ocsp_response.h x509_ocsp_response.c \
|
x509_ocsp_response.h x509_ocsp_response.c
|
||||||
ietf_attr_list.h ietf_attr_list.c
|
|
||||||
libstrongswan_x509_la_LDFLAGS = -module -avoid-version
|
libstrongswan_x509_la_LDFLAGS = -module -avoid-version
|
||||||
|
|
||||||
|
|||||||
@ -1,396 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007 Andreas Steffen, 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 <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
#include <library.h>
|
|
||||||
|
|
||||||
#include <asn1/oid.h>
|
|
||||||
#include <asn1/asn1.h>
|
|
||||||
#include <asn1/asn1_parser.h>
|
|
||||||
#include <utils/lexparser.h>
|
|
||||||
|
|
||||||
#include "ietf_attr_list.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private definition of ietfAttribute kinds
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
IETF_ATTRIBUTE_OCTETS = 0,
|
|
||||||
IETF_ATTRIBUTE_OID = 1,
|
|
||||||
IETF_ATTRIBUTE_STRING = 2
|
|
||||||
} ietfAttribute_t;
|
|
||||||
|
|
||||||
typedef struct ietfAttr_t ietfAttr_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private definition of an ietfAttribute
|
|
||||||
*/
|
|
||||||
struct ietfAttr_t {
|
|
||||||
/**
|
|
||||||
* IETF attribute kind
|
|
||||||
*/
|
|
||||||
ietfAttribute_t kind;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IETF attribute valuse
|
|
||||||
*/
|
|
||||||
chunk_t value;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares two ietfAttributes
|
|
||||||
*
|
|
||||||
* 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 this calling object
|
|
||||||
* @param other other object
|
|
||||||
*/
|
|
||||||
int (*compare) (const ietfAttr_t *this ,const ietfAttr_t *other);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the ietfAttr_t object.
|
|
||||||
*
|
|
||||||
* @param this ietfAttr_t to destroy
|
|
||||||
*/
|
|
||||||
void (*destroy) (ietfAttr_t *this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements ietfAttr_t.compare.
|
|
||||||
*/
|
|
||||||
static int ietfAttr_compare(const ietfAttr_t *this ,const ietfAttr_t *other)
|
|
||||||
{
|
|
||||||
int cmp_len, len, cmp_value;
|
|
||||||
|
|
||||||
/* OID attributes are appended after STRING and OCTETS attributes */
|
|
||||||
if (this->kind != IETF_ATTRIBUTE_OID && other->kind == IETF_ATTRIBUTE_OID)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (this->kind == IETF_ATTRIBUTE_OID && other->kind != 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 ietfAttr_t.destroy.
|
|
||||||
*/
|
|
||||||
static void ietfAttr_destroy(ietfAttr_t *this)
|
|
||||||
{
|
|
||||||
free(this->value.ptr);
|
|
||||||
free(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an ietfAttr_t object.
|
|
||||||
*/
|
|
||||||
static ietfAttr_t *ietfAttr_create(ietfAttribute_t kind, chunk_t value)
|
|
||||||
{
|
|
||||||
ietfAttr_t *this = malloc_thing(ietfAttr_t);
|
|
||||||
|
|
||||||
/* initialize */
|
|
||||||
this->kind = kind;
|
|
||||||
this->value = chunk_clone(value);
|
|
||||||
|
|
||||||
/* function */
|
|
||||||
this->compare = ietfAttr_compare;
|
|
||||||
this->destroy = ietfAttr_destroy;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an ietfAttr_t object to a sorted linked list
|
|
||||||
*/
|
|
||||||
static void ietfAttr_add(linked_list_t *list, ietfAttr_t *attr)
|
|
||||||
{
|
|
||||||
iterator_t *iterator = list->create_iterator(list, TRUE);
|
|
||||||
ietfAttr_t *current_attr;
|
|
||||||
bool found = FALSE;
|
|
||||||
|
|
||||||
while (iterator->iterate(iterator, (void **)¤t_attr))
|
|
||||||
{
|
|
||||||
int cmp = attr->compare(attr, current_attr);
|
|
||||||
|
|
||||||
if (cmp > 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (cmp == 0)
|
|
||||||
{
|
|
||||||
attr->destroy(attr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iterator->insert_before(iterator, attr);
|
|
||||||
}
|
|
||||||
found = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
iterator->destroy(iterator);
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
list->insert_last(list, attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Described in header.
|
|
||||||
*/
|
|
||||||
bool ietfAttr_list_equals(linked_list_t *list_a, linked_list_t *list_b)
|
|
||||||
{
|
|
||||||
bool result = TRUE;
|
|
||||||
|
|
||||||
/* lists must have the same number of attributes */
|
|
||||||
if (list_a->get_count(list_a) != list_b->get_count(list_b))
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
/* empty lists - no attributes */
|
|
||||||
if (list_a->get_count(list_a) == 0)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compare two alphabetically-sorted lists */
|
|
||||||
{
|
|
||||||
iterator_t *iterator_a = list_a->create_iterator(list_a, TRUE);
|
|
||||||
iterator_t *iterator_b = list_b->create_iterator(list_b, TRUE);
|
|
||||||
ietfAttr_t *attr_a, *attr_b;
|
|
||||||
|
|
||||||
while (iterator_a->iterate(iterator_a, (void **)&attr_a) &&
|
|
||||||
iterator_b->iterate(iterator_b, (void **)&attr_b))
|
|
||||||
{
|
|
||||||
if (attr_a->compare(attr_a, attr_b) != 0)
|
|
||||||
{
|
|
||||||
/* we have a mismatch */
|
|
||||||
result = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterator_a->destroy(iterator_a);
|
|
||||||
iterator_b->destroy(iterator_b);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Described in header.
|
|
||||||
*/
|
|
||||||
void ietfAttr_list_list(linked_list_t *list, FILE *out)
|
|
||||||
{
|
|
||||||
iterator_t *iterator = list->create_iterator(list, TRUE);
|
|
||||||
ietfAttr_t *attr;
|
|
||||||
bool first = TRUE;
|
|
||||||
|
|
||||||
while (iterator->iterate(iterator, (void **)&attr))
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
first = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(out, ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (attr->kind)
|
|
||||||
{
|
|
||||||
case IETF_ATTRIBUTE_OCTETS:
|
|
||||||
case IETF_ATTRIBUTE_STRING:
|
|
||||||
fprintf(out, "%.*s", (int)attr->value.len, attr->value.ptr);
|
|
||||||
break;
|
|
||||||
case IETF_ATTRIBUTE_OID:
|
|
||||||
{
|
|
||||||
int oid = asn1_known_oid(attr->value);
|
|
||||||
|
|
||||||
if (oid == OID_UNKNOWN)
|
|
||||||
{
|
|
||||||
fprintf(out, "0x#B", &attr->value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(out, "%s", oid_names[oid]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterator->destroy(iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Described in header.
|
|
||||||
*/
|
|
||||||
void ietfAttr_list_create_from_string(char *msg, linked_list_t *list)
|
|
||||||
{
|
|
||||||
chunk_t line = { msg, strlen(msg) };
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
ietfAttr_t *attr = ietfAttr_create(IETF_ATTRIBUTE_STRING, group);
|
|
||||||
|
|
||||||
ietfAttr_add(list, attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
void ietfAttr_list_create_from_chunk(chunk_t chunk, linked_list_t *list, int level0)
|
|
||||||
{
|
|
||||||
asn1_parser_t *parser;
|
|
||||||
chunk_t object;
|
|
||||||
int objectID;
|
|
||||||
|
|
||||||
parser = asn1_parser_create(ietfAttrSyntaxObjects, chunk);
|
|
||||||
parser->set_top_level(parser, level0);
|
|
||||||
|
|
||||||
while (parser->iterate(parser, &objectID, &object))
|
|
||||||
{
|
|
||||||
switch (objectID)
|
|
||||||
{
|
|
||||||
case IETF_ATTR_OCTETS:
|
|
||||||
case IETF_ATTR_OID:
|
|
||||||
case IETF_ATTR_STRING:
|
|
||||||
{
|
|
||||||
ietfAttribute_t kind = (objectID - IETF_ATTR_OCTETS) / 2;
|
|
||||||
ietfAttr_t *attr = ietfAttr_create(kind, object);
|
|
||||||
ietfAttr_add(list, attr);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parser->destroy(parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Described in header.
|
|
||||||
*/
|
|
||||||
chunk_t ietfAttr_list_encode(linked_list_t *list)
|
|
||||||
{
|
|
||||||
chunk_t ietfAttributes;
|
|
||||||
size_t size = 0;
|
|
||||||
u_char *pos;
|
|
||||||
iterator_t *iterator = list->create_iterator(list, TRUE);
|
|
||||||
ietfAttr_t *attr;
|
|
||||||
|
|
||||||
/* precalculate the total size of all values */
|
|
||||||
while (iterator->iterate(iterator, (void **)&attr))
|
|
||||||
{
|
|
||||||
size_t len = attr->value.len;
|
|
||||||
|
|
||||||
size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len;
|
|
||||||
}
|
|
||||||
iterator->destroy(iterator);
|
|
||||||
|
|
||||||
pos = asn1_build_object(&ietfAttributes, ASN1_SEQUENCE, size);
|
|
||||||
|
|
||||||
iterator = list->create_iterator(list, TRUE);
|
|
||||||
while (iterator->iterate(iterator, (void **)&attr))
|
|
||||||
{
|
|
||||||
chunk_t ietfAttribute;
|
|
||||||
asn1_t type = ASN1_NULL;
|
|
||||||
|
|
||||||
switch (attr->kind)
|
|
||||||
{
|
|
||||||
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 ietfAttributes chunk */
|
|
||||||
memcpy(pos, ietfAttribute.ptr, ietfAttribute.len);
|
|
||||||
pos += ietfAttribute.len;
|
|
||||||
free(ietfAttribute.ptr);
|
|
||||||
}
|
|
||||||
iterator->destroy(iterator);
|
|
||||||
|
|
||||||
return asn1_wrap(ASN1_SEQUENCE, "m", ietfAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Described in header.
|
|
||||||
*/
|
|
||||||
void ietfAttr_list_destroy(linked_list_t *list)
|
|
||||||
{
|
|
||||||
list->destroy_offset(list, offsetof(ietfAttr_t, destroy));
|
|
||||||
}
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007 Andreas Steffen
|
|
||||||
*
|
|
||||||
* 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_attr_list ietf_attr_list
|
|
||||||
* @{ @ingroup x509_p
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IETF_ATTR_LIST_H_
|
|
||||||
#define IETF_ATTR_LIST_H_
|
|
||||||
|
|
||||||
#include <library.h>
|
|
||||||
#include <utils/linked_list.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Compare two linked lists of ietfAttr_t objects for equality
|
|
||||||
*
|
|
||||||
* @param list_a first alphabetically-sorted list
|
|
||||||
* @param list_b second alphabetically-sorted list
|
|
||||||
* @return TRUE if equal
|
|
||||||
*/
|
|
||||||
bool ietfAttr_list_equals(linked_list_t *list_a, linked_list_t *list_b);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Lists a linked list of ietfAttr_t objects
|
|
||||||
*
|
|
||||||
* @param list alphabetically-sorted linked list of attributes
|
|
||||||
* @param out output file
|
|
||||||
*/
|
|
||||||
void ietfAttr_list_list(linked_list_t *list, FILE *out);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a linked list of ietfAttr_t objects from a string
|
|
||||||
*
|
|
||||||
* @param msg string with comma-separated group names
|
|
||||||
* @param list alphabetically-sorted linked list of attributes
|
|
||||||
*/
|
|
||||||
void ietfAttr_list_create_from_string(char *msg, linked_list_t *list);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a linked list of ietfAttr_t objects from an ASN.1-coded chunk
|
|
||||||
*
|
|
||||||
* @param chunk chunk containing ASN.1-coded attributes
|
|
||||||
* @param list alphabetically-sorted linked list of attributes
|
|
||||||
* @param level0 parsing level
|
|
||||||
*/
|
|
||||||
void ietfAttr_list_create_from_chunk(chunk_t chunk, linked_list_t *list, int level0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Encode a linked list of ietfAttr_t objects into an ASN.1-coded chunk
|
|
||||||
*
|
|
||||||
* @param list alphabetically-sorted linked list of attributes
|
|
||||||
* @return chunk containing ASN.1-coded attributes
|
|
||||||
*/
|
|
||||||
chunk_t ietfAttr_list_encode(linked_list_t *list);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroys a linked list of ietfAttr_t objects
|
|
||||||
*
|
|
||||||
* @param list list to be destroyed
|
|
||||||
*/
|
|
||||||
void ietfAttr_list_destroy(linked_list_t *list);
|
|
||||||
|
|
||||||
#endif /** IETF_ATTR_LIST_H_ @}*/
|
|
||||||
|
|
||||||
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
|
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
|
||||||
* Copyright (C) 2003 Martin Berner, Lukas Suter
|
* Copyright (C) 2003 Martin Berner, Lukas Suter
|
||||||
* Copyright (C) 2002-2008 Andreas Steffen
|
* Copyright (C) 2002-2009 Andreas Steffen
|
||||||
* Copyright (C) 2009 Martin Willi
|
* Copyright (C) 2009 Martin Willi
|
||||||
*
|
*
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "x509_ac.h"
|
#include "x509_ac.h"
|
||||||
#include "ietf_attr_list.h"
|
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -30,6 +29,7 @@
|
|||||||
#include <utils/identification.h>
|
#include <utils/identification.h>
|
||||||
#include <utils/linked_list.h>
|
#include <utils/linked_list.h>
|
||||||
#include <credentials/certificates/x509.h>
|
#include <credentials/certificates/x509.h>
|
||||||
|
#include <credentials/ietf_attributes/ietf_attributes.h>
|
||||||
#include <credentials/keys/private_key.h>
|
#include <credentials/keys/private_key.h>
|
||||||
|
|
||||||
extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob,
|
extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob,
|
||||||
@ -100,12 +100,12 @@ struct private_x509_ac_t {
|
|||||||
/**
|
/**
|
||||||
* List of charging attributes
|
* List of charging attributes
|
||||||
*/
|
*/
|
||||||
linked_list_t *charging;
|
ietf_attributes_t *charging;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of groub attributes
|
* List of groub attributes
|
||||||
*/
|
*/
|
||||||
linked_list_t *groups;
|
ietf_attributes_t *groups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authority Key Identifier
|
* Authority Key Identifier
|
||||||
@ -413,10 +413,14 @@ static bool parse_certificate(private_x509_ac_t *this)
|
|||||||
DBG2(" need to parse accessIdentity");
|
DBG2(" need to parse accessIdentity");
|
||||||
break;
|
break;
|
||||||
case OID_CHARGING_IDENTITY:
|
case OID_CHARGING_IDENTITY:
|
||||||
ietfAttr_list_create_from_chunk(object, this->charging, level);
|
DBG2("-- > --");
|
||||||
|
this->charging = ietf_attributes_create_from_encoding(object);
|
||||||
|
DBG2("-- < --");
|
||||||
break;
|
break;
|
||||||
case OID_GROUP:
|
case OID_GROUP:
|
||||||
ietfAttr_list_create_from_chunk(object, this->groups, level);
|
DBG2("-- > --");
|
||||||
|
this->groups = ietf_attributes_create_from_encoding(object);
|
||||||
|
DBG2("-- < --");
|
||||||
break;
|
break;
|
||||||
case OID_ROLE:
|
case OID_ROLE:
|
||||||
parse_roleSyntax(object, level);
|
parse_roleSyntax(object, level);
|
||||||
@ -543,7 +547,7 @@ static chunk_t build_attribute_type(int type, chunk_t content)
|
|||||||
static chunk_t build_attributes(private_x509_ac_t *this)
|
static chunk_t build_attributes(private_x509_ac_t *this)
|
||||||
{
|
{
|
||||||
return asn1_wrap(ASN1_SEQUENCE, "m",
|
return asn1_wrap(ASN1_SEQUENCE, "m",
|
||||||
build_attribute_type(OID_GROUP, ietfAttr_list_encode(this->groups)));
|
build_attribute_type(OID_GROUP, this->groups->get_encoding(this->groups)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -663,6 +667,14 @@ static chunk_t get_authKeyIdentifier(private_x509_ac_t *this)
|
|||||||
return this->authKeyIdentifier;
|
return this->authKeyIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of certificate_t.get_groups.
|
||||||
|
*/
|
||||||
|
static ietf_attributes_t* get_groups(private_x509_ac_t *this)
|
||||||
|
{
|
||||||
|
return this->groups ? this->groups->get_ref(this->groups) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of certificate_t.get_type
|
* Implementation of certificate_t.get_type
|
||||||
*/
|
*/
|
||||||
@ -881,9 +893,8 @@ static void destroy(private_x509_ac_t *this)
|
|||||||
DESTROY_IF(this->holderCert);
|
DESTROY_IF(this->holderCert);
|
||||||
DESTROY_IF(this->signerCert);
|
DESTROY_IF(this->signerCert);
|
||||||
DESTROY_IF(this->signerKey);
|
DESTROY_IF(this->signerKey);
|
||||||
|
DESTROY_IF(this->charging);
|
||||||
ietfAttr_list_destroy(this->charging);
|
DESTROY_IF(this->groups);
|
||||||
ietfAttr_list_destroy(this->groups);
|
|
||||||
free(this->serialNumber.ptr);
|
free(this->serialNumber.ptr);
|
||||||
free(this->authKeyIdentifier.ptr);
|
free(this->authKeyIdentifier.ptr);
|
||||||
free(this->encoding.ptr);
|
free(this->encoding.ptr);
|
||||||
@ -902,7 +913,8 @@ static private_x509_ac_t *create_empty(void)
|
|||||||
this->public.interface.get_serial = (chunk_t (*)(ac_t*))get_serial;
|
this->public.interface.get_serial = (chunk_t (*)(ac_t*))get_serial;
|
||||||
this->public.interface.get_holderSerial = (chunk_t (*)(ac_t*))get_holderSerial;
|
this->public.interface.get_holderSerial = (chunk_t (*)(ac_t*))get_holderSerial;
|
||||||
this->public.interface.get_holderIssuer = (identification_t* (*)(ac_t*))get_holderIssuer;
|
this->public.interface.get_holderIssuer = (identification_t* (*)(ac_t*))get_holderIssuer;
|
||||||
this->public.interface.get_authKeyIdentifier = (chunk_t(*)(ac_t*))get_authKeyIdentifier;
|
this->public.interface.get_authKeyIdentifier = (chunk_t (*)(ac_t*))get_authKeyIdentifier;
|
||||||
|
this->public.interface.get_groups = (ietf_attributes_t* (*)(ac_t*))get_groups;
|
||||||
this->public.interface.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
|
this->public.interface.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
|
||||||
this->public.interface.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_subject;
|
this->public.interface.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_subject;
|
||||||
this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
|
||||||
@ -928,8 +940,8 @@ static private_x509_ac_t *create_empty(void)
|
|||||||
this->holderCert = NULL;
|
this->holderCert = NULL;
|
||||||
this->signerCert = NULL;
|
this->signerCert = NULL;
|
||||||
this->signerKey = NULL;
|
this->signerKey = NULL;
|
||||||
this->charging = linked_list_create();
|
this->charging = NULL;
|
||||||
this->groups = linked_list_create();
|
this->groups = NULL;
|
||||||
this->ref = 1;
|
this->ref = 1;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@ -992,7 +1004,7 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args)
|
|||||||
ac->serialNumber = chunk_clone(va_arg(args, chunk_t));
|
ac->serialNumber = chunk_clone(va_arg(args, chunk_t));
|
||||||
continue;
|
continue;
|
||||||
case BUILD_IETF_GROUP_ATTR:
|
case BUILD_IETF_GROUP_ATTR:
|
||||||
ietfAttr_list_create_from_string(va_arg(args, char*), ac->groups);
|
ac->groups = ietf_attributes_create_from_string(va_arg(args, char*));
|
||||||
continue;
|
continue;
|
||||||
case BUILD_CERT:
|
case BUILD_CERT:
|
||||||
ac->holderCert = va_arg(args, certificate_t*);
|
ac->holderCert = va_arg(args, certificate_t*);
|
||||||
|
|||||||
@ -448,7 +448,6 @@ int main(int argc, char **argv)
|
|||||||
signerCert = lib->creds->create(lib->creds,
|
signerCert = lib->creds->create(lib->creds,
|
||||||
CRED_CERTIFICATE, CERT_X509,
|
CRED_CERTIFICATE, CERT_X509,
|
||||||
BUILD_FROM_FILE, certfile,
|
BUILD_FROM_FILE, certfile,
|
||||||
BUILD_X509_FLAG, 0,
|
|
||||||
BUILD_END);
|
BUILD_END);
|
||||||
if (signerCert == NULL)
|
if (signerCert == NULL)
|
||||||
{
|
{
|
||||||
@ -462,7 +461,6 @@ int main(int argc, char **argv)
|
|||||||
userCert = lib->creds->create(lib->creds,
|
userCert = lib->creds->create(lib->creds,
|
||||||
CRED_CERTIFICATE, CERT_X509,
|
CRED_CERTIFICATE, CERT_X509,
|
||||||
BUILD_FROM_FILE, usercertfile,
|
BUILD_FROM_FILE, usercertfile,
|
||||||
BUILD_X509_FLAG, 0,
|
|
||||||
BUILD_END);
|
BUILD_END);
|
||||||
if (userCert == NULL)
|
if (userCert == NULL)
|
||||||
{
|
{
|
||||||
|
|||||||
871
src/pluto/ac.c
871
src/pluto/ac.c
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
|||||||
/* Support of X.509 attribute certificates
|
/* Support of X.509 attribute certificates
|
||||||
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
|
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
|
||||||
* Copyright (C) 2003 Martin Berner, Lukas Suter
|
* Copyright (C) 2003 Martin Berner, Lukas Suter
|
||||||
|
* Copyright (C) 2009 Andreas Steffen
|
||||||
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@ -17,85 +18,28 @@
|
|||||||
#ifndef _AC_H
|
#ifndef _AC_H
|
||||||
#define _AC_H
|
#define _AC_H
|
||||||
|
|
||||||
/* definition of ietfAttribute kinds */
|
#include <time.h>
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
IETF_ATTRIBUTE_OCTETS = 0,
|
|
||||||
IETF_ATTRIBUTE_OID = 1,
|
|
||||||
IETF_ATTRIBUTE_STRING = 2
|
|
||||||
} ietfAttribute_t;
|
|
||||||
|
|
||||||
/* access structure for an ietfAttribute */
|
|
||||||
|
|
||||||
typedef struct ietfAttr ietfAttr_t;
|
|
||||||
|
|
||||||
struct ietfAttr {
|
|
||||||
time_t installed;
|
|
||||||
int count;
|
|
||||||
ietfAttribute_t kind;
|
|
||||||
chunk_t value;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct ietfAttrList ietfAttrList_t;
|
|
||||||
|
|
||||||
struct ietfAttrList {
|
|
||||||
ietfAttrList_t *next;
|
|
||||||
ietfAttr_t *attr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
#include <credentials/certificates/certificate.h>
|
||||||
|
#include <credentials/ietf_attributes/ietf_attributes.h>
|
||||||
|
|
||||||
/* access structure for an X.509 attribute certificate */
|
/* access structure for an X.509 attribute certificate */
|
||||||
|
|
||||||
typedef struct x509acert x509acert_t;
|
typedef struct x509acert x509acert_t;
|
||||||
|
|
||||||
struct x509acert {
|
struct x509acert {
|
||||||
x509acert_t *next;
|
certificate_t *ac;
|
||||||
time_t installed;
|
x509acert_t *next;
|
||||||
chunk_t certificate;
|
time_t installed;
|
||||||
chunk_t certificateInfo;
|
|
||||||
u_int version;
|
|
||||||
/* holder */
|
|
||||||
/* baseCertificateID */
|
|
||||||
chunk_t holderIssuer;
|
|
||||||
chunk_t holderSerial;
|
|
||||||
chunk_t entityName;
|
|
||||||
/* v2Form */
|
|
||||||
chunk_t issuerName;
|
|
||||||
/* signature */
|
|
||||||
int sigAlg;
|
|
||||||
chunk_t serialNumber;
|
|
||||||
/* attrCertValidityPeriod */
|
|
||||||
time_t notBefore;
|
|
||||||
time_t notAfter;
|
|
||||||
/* attributes */
|
|
||||||
ietfAttrList_t *charging;
|
|
||||||
ietfAttrList_t *groups;
|
|
||||||
/* extensions */
|
|
||||||
chunk_t authKeyID;
|
|
||||||
chunk_t authKeySerialNumber;
|
|
||||||
bool noRevAvail;
|
|
||||||
/* signatureAlgorithm */
|
|
||||||
int algorithm;
|
|
||||||
chunk_t signature;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* used for initialization */
|
|
||||||
extern const x509acert_t empty_ac;
|
|
||||||
|
|
||||||
extern void unshare_ietfAttrList(ietfAttrList_t **listp);
|
|
||||||
extern void free_ietfAttrList(ietfAttrList_t *list);
|
|
||||||
extern void decode_groups(char *groups, ietfAttrList_t **listp);
|
|
||||||
extern bool group_membership(const ietfAttrList_t *my_list
|
|
||||||
, const char *conn, const ietfAttrList_t *conn_list);
|
|
||||||
extern bool parse_ac(chunk_t blob, x509acert_t *ac);
|
|
||||||
extern bool verify_x509acert(x509acert_t *ac, bool strict);
|
extern bool verify_x509acert(x509acert_t *ac, bool strict);
|
||||||
|
extern bool match_group_membership(ietf_attributes_t *peer_attributes, char *conn,
|
||||||
|
ietf_attributes_t *conn_attributes);
|
||||||
extern x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial);
|
extern x509acert_t* get_x509acert(chunk_t issuer, chunk_t serial);
|
||||||
extern void load_acerts(void);
|
extern void load_acerts(void);
|
||||||
extern void free_acert(x509acert_t *ac);
|
extern void free_acert(x509acert_t *ac);
|
||||||
extern void free_acerts(void);
|
extern void free_acerts(void);
|
||||||
extern void list_acerts(bool utc);
|
extern void list_acerts(bool utc);
|
||||||
extern void list_groups(bool utc);
|
|
||||||
extern void format_groups(const ietfAttrList_t *list, char *buf, int len);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _AH_H */
|
#endif /* _AH_H */
|
||||||
|
|||||||
@ -40,6 +40,7 @@
|
|||||||
*/
|
*/
|
||||||
static cert_t *builder_load_cert(certificate_type_t type, va_list args)
|
static cert_t *builder_load_cert(certificate_type_t type, va_list args)
|
||||||
{
|
{
|
||||||
|
x509_flag_t flags = 0;
|
||||||
chunk_t blob = chunk_empty;
|
chunk_t blob = chunk_empty;
|
||||||
bool pgp = FALSE;
|
bool pgp = FALSE;
|
||||||
|
|
||||||
@ -53,6 +54,9 @@ static cert_t *builder_load_cert(certificate_type_t type, va_list args)
|
|||||||
case BUILD_BLOB_ASN1_DER:
|
case BUILD_BLOB_ASN1_DER:
|
||||||
blob = va_arg(args, chunk_t);
|
blob = va_arg(args, chunk_t);
|
||||||
continue;
|
continue;
|
||||||
|
case BUILD_X509_FLAG:
|
||||||
|
flags |= va_arg(args, x509_flag_t);
|
||||||
|
continue;
|
||||||
case BUILD_END:
|
case BUILD_END:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -85,6 +89,7 @@ static cert_t *builder_load_cert(certificate_type_t type, va_list args)
|
|||||||
x509cert->cert = lib->creds->create(lib->creds,
|
x509cert->cert = lib->creds->create(lib->creds,
|
||||||
CRED_CERTIFICATE, CERT_X509,
|
CRED_CERTIFICATE, CERT_X509,
|
||||||
BUILD_BLOB_ASN1_DER, blob,
|
BUILD_BLOB_ASN1_DER, blob,
|
||||||
|
BUILD_X509_FLAG, flags,
|
||||||
BUILD_END);
|
BUILD_END);
|
||||||
if (x509cert->cert)
|
if (x509cert->cert)
|
||||||
{
|
{
|
||||||
@ -128,9 +133,12 @@ static x509acert_t *builder_load_ac(certificate_type_t type, va_list args)
|
|||||||
if (blob.ptr)
|
if (blob.ptr)
|
||||||
{
|
{
|
||||||
ac = malloc_thing(x509acert_t);
|
ac = malloc_thing(x509acert_t);
|
||||||
*ac = empty_ac;
|
ac->next = NULL;
|
||||||
if (parse_ac(chunk_clone(blob), ac) &&
|
ac->installed = UNDEFINED_TIME;
|
||||||
verify_x509acert(ac, FALSE))
|
ac->ac = lib->creds->create(lib->creds,
|
||||||
|
CRED_CERTIFICATE, CERT_X509_AC,
|
||||||
|
BUILD_BLOB_ASN1_DER, blob, BUILD_END);
|
||||||
|
if (ac->ac && verify_x509acert(ac, FALSE))
|
||||||
{
|
{
|
||||||
return ac;
|
return ac;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,7 +81,7 @@ bool trusted_ca(chunk_t a, chunk_t b, int *pathlen)
|
|||||||
chunk_t issuer_dn;
|
chunk_t issuer_dn;
|
||||||
x509cert_t *cacert;
|
x509cert_t *cacert;
|
||||||
|
|
||||||
cacert = get_authcert(a, chunk_empty, AUTH_CA);
|
cacert = get_authcert(a, chunk_empty, X509_CA);
|
||||||
if (cacert == NULL)
|
if (cacert == NULL)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@ -180,7 +180,7 @@ void free_authcerts(void)
|
|||||||
/*
|
/*
|
||||||
* get a X.509 authority certificate with a given subject or keyid
|
* get a X.509 authority certificate with a given subject or keyid
|
||||||
*/
|
*/
|
||||||
x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags)
|
x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, x509_flag_t auth_flags)
|
||||||
{
|
{
|
||||||
x509cert_t *cert, *prev_cert = NULL;
|
x509cert_t *cert, *prev_cert = NULL;
|
||||||
|
|
||||||
@ -193,11 +193,12 @@ x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags)
|
|||||||
for (cert = x509authcerts; cert != NULL; prev_cert = cert, cert = cert->next)
|
for (cert = x509authcerts; cert != NULL; prev_cert = cert, cert = cert->next)
|
||||||
{
|
{
|
||||||
certificate_t *certificate = cert->cert;
|
certificate_t *certificate = cert->cert;
|
||||||
|
x509_t *x509 = (x509_t*)certificate;
|
||||||
identification_t *cert_subject;
|
identification_t *cert_subject;
|
||||||
chunk_t cert_subject_dn;
|
chunk_t cert_subject_dn;
|
||||||
|
|
||||||
/* skip non-matching types of authority certificates */
|
/* skip non-matching types of authority certificates */
|
||||||
if (!(cert->authority_flags & auth_flags))
|
if (!(x509->get_flags(x509) & auth_flags))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -205,7 +206,6 @@ x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags)
|
|||||||
/* compare the keyid with the certificate's subjectKeyIdentifier */
|
/* compare the keyid with the certificate's subjectKeyIdentifier */
|
||||||
if (keyid.ptr)
|
if (keyid.ptr)
|
||||||
{
|
{
|
||||||
x509_t *x509 = (x509_t*)certificate;
|
|
||||||
chunk_t subjectKeyId;
|
chunk_t subjectKeyId;
|
||||||
|
|
||||||
subjectKeyId = x509->get_subjectKeyIdentifier(x509);
|
subjectKeyId = x509->get_subjectKeyIdentifier(x509);
|
||||||
@ -239,7 +239,7 @@ x509cert_t* get_authcert(chunk_t subject, chunk_t keyid, u_char auth_flags)
|
|||||||
/*
|
/*
|
||||||
* add an authority certificate to the chained list
|
* add an authority certificate to the chained list
|
||||||
*/
|
*/
|
||||||
x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags)
|
x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags)
|
||||||
{
|
{
|
||||||
certificate_t *certificate = cert->cert;
|
certificate_t *certificate = cert->cert;
|
||||||
x509_t *x509 = (x509_t*)certificate;
|
x509_t *x509 = (x509_t*)certificate;
|
||||||
@ -247,9 +247,6 @@ x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags)
|
|||||||
chunk_t cert_subject_dn = cert_subject->get_encoding(cert_subject);
|
chunk_t cert_subject_dn = cert_subject->get_encoding(cert_subject);
|
||||||
x509cert_t *old_cert;
|
x509cert_t *old_cert;
|
||||||
|
|
||||||
/* set authority flags */
|
|
||||||
cert->authority_flags |= auth_flags;
|
|
||||||
|
|
||||||
lock_authcert_list("add_authcert");
|
lock_authcert_list("add_authcert");
|
||||||
|
|
||||||
old_cert = get_authcert(cert_subject_dn,
|
old_cert = get_authcert(cert_subject_dn,
|
||||||
@ -259,8 +256,6 @@ x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags)
|
|||||||
{
|
{
|
||||||
if (certificate->equals(certificate, old_cert->cert))
|
if (certificate->equals(certificate, old_cert->cert))
|
||||||
{
|
{
|
||||||
/* cert is already present, just add additional authority flags */
|
|
||||||
old_cert->authority_flags |= cert->authority_flags;
|
|
||||||
DBG(DBG_CONTROL | DBG_PARSING ,
|
DBG(DBG_CONTROL | DBG_PARSING ,
|
||||||
DBG_log(" authcert is already present and identical")
|
DBG_log(" authcert is already present and identical")
|
||||||
)
|
)
|
||||||
@ -293,7 +288,7 @@ x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags)
|
|||||||
/*
|
/*
|
||||||
* Loads authority certificates
|
* Loads authority certificates
|
||||||
*/
|
*/
|
||||||
void load_authcerts(const char *type, const char *path, u_char auth_flags)
|
void load_authcerts(const char *type, const char *path, x509_flag_t auth_flags)
|
||||||
{
|
{
|
||||||
struct dirent **filelist;
|
struct dirent **filelist;
|
||||||
u_char buf[BUF_LEN];
|
u_char buf[BUF_LEN];
|
||||||
@ -320,9 +315,10 @@ void load_authcerts(const char *type, const char *path, u_char auth_flags)
|
|||||||
{
|
{
|
||||||
cert_t cert;
|
cert_t cert;
|
||||||
|
|
||||||
if (load_cert(filelist[n]->d_name, type, &cert))
|
if (load_cert(filelist[n]->d_name, type, auth_flags, &cert))
|
||||||
|
{
|
||||||
add_authcert(cert.u.x509, auth_flags);
|
add_authcert(cert.u.x509, auth_flags);
|
||||||
|
}
|
||||||
free(filelist[n]);
|
free(filelist[n]);
|
||||||
}
|
}
|
||||||
free(filelist);
|
free(filelist);
|
||||||
@ -335,7 +331,7 @@ void load_authcerts(const char *type, const char *path, u_char auth_flags)
|
|||||||
/*
|
/*
|
||||||
* list all X.509 authcerts with given auth flags in a chained list
|
* list all X.509 authcerts with given auth flags in a chained list
|
||||||
*/
|
*/
|
||||||
void list_authcerts(const char *caption, u_char auth_flags, bool utc)
|
void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc)
|
||||||
{
|
{
|
||||||
lock_authcert_list("list_authcerts");
|
lock_authcert_list("list_authcerts");
|
||||||
list_x509cert_chain(caption, x509authcerts, auth_flags, utc);
|
list_x509cert_chain(caption, x509authcerts, auth_flags, utc);
|
||||||
@ -426,7 +422,7 @@ bool trust_authcert_candidate(const x509cert_t *cert, const x509cert_t *alt_chai
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* search in trusted chain */
|
/* search in trusted chain */
|
||||||
authcert = get_authcert(issuer_dn, authKeyID, AUTH_CA);
|
authcert = get_authcert(issuer_dn, authKeyID, X509_CA);
|
||||||
|
|
||||||
if (authcert != NULL)
|
if (authcert != NULL)
|
||||||
{
|
{
|
||||||
@ -670,7 +666,7 @@ void add_ca_info(const whack_message_t *msg)
|
|||||||
unlock_ca_info_list("add_ca_info");
|
unlock_ca_info_list("add_ca_info");
|
||||||
|
|
||||||
/* add cacert to list of authcerts */
|
/* add cacert to list of authcerts */
|
||||||
cacert = add_authcert(cacert, AUTH_CA);
|
cacert = add_authcert(cacert, X509_CA);
|
||||||
if (!cached_cert && sc != NULL)
|
if (!cached_cert && sc != NULL)
|
||||||
{
|
{
|
||||||
if (sc->last_cert.type == CERT_X509_SIGNATURE)
|
if (sc->last_cert.type == CERT_X509_SIGNATURE)
|
||||||
|
|||||||
@ -22,13 +22,6 @@
|
|||||||
|
|
||||||
#define MAX_CA_PATH_LEN 7
|
#define MAX_CA_PATH_LEN 7
|
||||||
|
|
||||||
/* authority flags */
|
|
||||||
|
|
||||||
#define AUTH_NONE 0x00 /* no authorities */
|
|
||||||
#define AUTH_CA 0x01 /* certification authority */
|
|
||||||
#define AUTH_AA 0x02 /* authorization authority */
|
|
||||||
#define AUTH_OCSP 0x04 /* ocsp signing authority */
|
|
||||||
|
|
||||||
/* CA info structures */
|
/* CA info structures */
|
||||||
|
|
||||||
typedef struct ca_info ca_info_t;
|
typedef struct ca_info ca_info_t;
|
||||||
@ -47,17 +40,17 @@ struct ca_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern bool trusted_ca(chunk_t a, chunk_t b, int *pathlen);
|
extern bool trusted_ca(chunk_t a, chunk_t b, int *pathlen);
|
||||||
extern bool match_requested_ca(generalName_t *requested_ca
|
extern bool match_requested_ca(generalName_t *requested_ca, chunk_t our_ca,
|
||||||
, chunk_t our_ca, int *our_pathlen);
|
int *our_pathlen);
|
||||||
extern x509cert_t* get_authcert(chunk_t subject, chunk_t keyid,
|
extern x509cert_t* get_authcert(chunk_t subject, chunk_t keyid,
|
||||||
u_char auth_flags);
|
x509_flag_t auth_flags);
|
||||||
extern void load_authcerts(const char *type, const char *path
|
extern void load_authcerts(const char *type, const char *path,
|
||||||
, u_char auth_flags);
|
x509_flag_t auth_flags);
|
||||||
extern x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags);
|
extern x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags);
|
||||||
extern void free_authcerts(void);
|
extern void free_authcerts(void);
|
||||||
extern void list_authcerts(const char *caption, u_char auth_flags, bool utc);
|
extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc);
|
||||||
extern bool trust_authcert_candidate(const x509cert_t *cert
|
extern bool trust_authcert_candidate(const x509cert_t *cert,
|
||||||
, const x509cert_t *alt_chain);
|
const x509cert_t *alt_chain);
|
||||||
extern ca_info_t* get_ca_info(chunk_t name, chunk_t keyid);
|
extern ca_info_t* get_ca_info(chunk_t name, chunk_t keyid);
|
||||||
extern bool find_ca_info_by_name(const char *name, bool delete);
|
extern bool find_ca_info_by_name(const char *name, bool delete);
|
||||||
extern void add_ca_info(const whack_message_t *msg);
|
extern void add_ca_info(const whack_message_t *msg);
|
||||||
|
|||||||
@ -162,12 +162,14 @@ private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
|
|||||||
/**
|
/**
|
||||||
* Loads a X.509 or OpenPGP certificate
|
* Loads a X.509 or OpenPGP certificate
|
||||||
*/
|
*/
|
||||||
bool load_cert(char *filename, const char *label, cert_t *out)
|
bool load_cert(char *filename, const char *label, x509_flag_t flags, cert_t *out)
|
||||||
{
|
{
|
||||||
cert_t *cert;
|
cert_t *cert;
|
||||||
|
|
||||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT,
|
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT,
|
||||||
BUILD_FROM_FILE, filename, BUILD_END);
|
BUILD_FROM_FILE, filename,
|
||||||
|
BUILD_X509_FLAG, flags,
|
||||||
|
BUILD_END);
|
||||||
if (cert)
|
if (cert)
|
||||||
{
|
{
|
||||||
/* the API passes an empty cert_t, we move over and free the built one */
|
/* the API passes an empty cert_t, we move over and free the built one */
|
||||||
@ -186,7 +188,7 @@ bool load_host_cert(char *filename, cert_t *cert)
|
|||||||
{
|
{
|
||||||
char *path = concatenate_paths(HOST_CERT_PATH, filename);
|
char *path = concatenate_paths(HOST_CERT_PATH, filename);
|
||||||
|
|
||||||
return load_cert(path, "host", cert);
|
return load_cert(path, "host", X509_NONE, cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,7 +198,7 @@ bool load_ca_cert(char *filename, cert_t *cert)
|
|||||||
{
|
{
|
||||||
char *path = concatenate_paths(CA_CERT_PATH, filename);
|
char *path = concatenate_paths(CA_CERT_PATH, filename);
|
||||||
|
|
||||||
return load_cert(path, "CA", cert);
|
return load_cert(path, "CA", X509_NONE, cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -66,7 +66,8 @@ extern public_key_t* cert_get_public_key(const cert_t cert);
|
|||||||
extern chunk_t cert_get_encoding(cert_t cert);
|
extern chunk_t cert_get_encoding(cert_t cert);
|
||||||
extern private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
|
extern private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
|
||||||
key_type_t type);
|
key_type_t type);
|
||||||
extern bool load_cert(char *filename, const char *label, cert_t *cert);
|
extern bool load_cert(char *filename, const char *label, x509_flag_t flags,
|
||||||
|
cert_t *cert);
|
||||||
extern bool load_host_cert(char *filename, cert_t *cert);
|
extern bool load_host_cert(char *filename, cert_t *cert);
|
||||||
extern bool load_ca_cert(char *filename, cert_t *cert);
|
extern bool load_ca_cert(char *filename, cert_t *cert);
|
||||||
extern bool same_cert(const cert_t *a, const cert_t *b);
|
extern bool same_cert(const cert_t *a, const cert_t *b);
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
#include <freeswan.h>
|
#include <freeswan.h>
|
||||||
#include "kameipsec.h"
|
#include "kameipsec.h"
|
||||||
|
|
||||||
|
#include <credentials/certificates/ac.h>
|
||||||
#include <credentials/keys/private_key.h>
|
#include <credentials/keys/private_key.h>
|
||||||
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
@ -336,11 +337,11 @@ void delete_connection(connection_t *c, bool relations)
|
|||||||
free_id_content(&c->spd.this.id);
|
free_id_content(&c->spd.this.id);
|
||||||
free(c->spd.this.updown);
|
free(c->spd.this.updown);
|
||||||
free(c->spd.this.ca.ptr);
|
free(c->spd.this.ca.ptr);
|
||||||
free_ietfAttrList(c->spd.this.groups);
|
DESTROY_IF(c->spd.this.groups);
|
||||||
free_id_content(&c->spd.that.id);
|
free_id_content(&c->spd.that.id);
|
||||||
free(c->spd.that.updown);
|
free(c->spd.that.updown);
|
||||||
free(c->spd.that.ca.ptr);
|
free(c->spd.that.ca.ptr);
|
||||||
free_ietfAttrList(c->spd.that.groups);
|
DESTROY_IF(c->spd.that.groups);
|
||||||
free_generalNames(c->requested_ca, TRUE);
|
free_generalNames(c->requested_ca, TRUE);
|
||||||
gw_delref(&c->gw_info);
|
gw_delref(&c->gw_info);
|
||||||
|
|
||||||
@ -812,7 +813,7 @@ static bool extract_end(struct end *dst, const whack_end_t *src,
|
|||||||
dst->ca = chunk_empty;
|
dst->ca = chunk_empty;
|
||||||
|
|
||||||
/* decode CA distinguished name, if any */
|
/* decode CA distinguished name, if any */
|
||||||
if (src->ca != NULL)
|
if (src->ca)
|
||||||
{
|
{
|
||||||
if streq(src->ca, "%same")
|
if streq(src->ca, "%same")
|
||||||
same_ca = TRUE;
|
same_ca = TRUE;
|
||||||
@ -837,7 +838,10 @@ static bool extract_end(struct end *dst, const whack_end_t *src,
|
|||||||
dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0;
|
dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0;
|
||||||
|
|
||||||
/* decode group attributes, if any */
|
/* decode group attributes, if any */
|
||||||
decode_groups(src->groups, &dst->groups);
|
if (src->groups)
|
||||||
|
{
|
||||||
|
dst->groups = ietf_attributes_create_from_string(src->groups);
|
||||||
|
}
|
||||||
|
|
||||||
/* the rest is simple copying of corresponding fields */
|
/* the rest is simple copying of corresponding fields */
|
||||||
dst->host_addr = src->host_addr;
|
dst->host_addr = src->host_addr;
|
||||||
@ -1261,8 +1265,14 @@ static connection_t *instantiate(connection_t *c,
|
|||||||
d->spd.that.has_id_wildcards = FALSE;
|
d->spd.that.has_id_wildcards = FALSE;
|
||||||
}
|
}
|
||||||
unshare_connection_strings(d);
|
unshare_connection_strings(d);
|
||||||
unshare_ietfAttrList(&d->spd.this.groups);
|
if (d->spd.this.groups)
|
||||||
unshare_ietfAttrList(&d->spd.that.groups);
|
{
|
||||||
|
d->spd.this.groups = d->spd.this.groups->get_ref(d->spd.this.groups);
|
||||||
|
}
|
||||||
|
if (d->spd.that.groups)
|
||||||
|
{
|
||||||
|
d->spd.that.groups = d->spd.that.groups->get_ref(d->spd.that.groups);
|
||||||
|
}
|
||||||
d->kind = CK_INSTANCE;
|
d->kind = CK_INSTANCE;
|
||||||
|
|
||||||
passert(oriented(*d));
|
passert(oriented(*d));
|
||||||
@ -1519,7 +1529,9 @@ connection_t *find_connection_for_clients(struct spd_route **srp,
|
|||||||
for (c = connections; c != NULL; c = c->ac_next)
|
for (c = connections; c != NULL; c = c->ac_next)
|
||||||
{
|
{
|
||||||
if (c->kind == CK_GROUP)
|
if (c->kind == CK_GROUP)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (sr = &c->spd; best!=c && sr; sr = sr->next)
|
for (sr = &c->spd; best!=c && sr; sr = sr->next)
|
||||||
{
|
{
|
||||||
@ -1727,7 +1739,9 @@ bool orient(connection_t *c)
|
|||||||
for (p = interfaces; p != NULL; p = p->next)
|
for (p = interfaces; p != NULL; p = p->next)
|
||||||
{
|
{
|
||||||
if (p->ike_float)
|
if (p->ike_float)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -3036,11 +3050,17 @@ connection_t *route_owner(connection_t *c, struct spd_route **srp,
|
|||||||
for (src = &c->spd; src; src=src->next)
|
for (src = &c->spd; src; src=src->next)
|
||||||
{
|
{
|
||||||
if (!samesubnet(&src->that.client, &srd->that.client))
|
if (!samesubnet(&src->that.client, &srd->that.client))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (src->that.protocol != srd->that.protocol)
|
if (src->that.protocol != srd->that.protocol)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (src->that.port != srd->that.port)
|
if (src->that.port != srd->that.port)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
passert(oriented(*d));
|
passert(oriented(*d));
|
||||||
if (srd->routing > best_routing)
|
if (srd->routing > best_routing)
|
||||||
{
|
{
|
||||||
@ -3050,11 +3070,17 @@ connection_t *route_owner(connection_t *c, struct spd_route **srp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!samesubnet(&src->this.client, &srd->this.client))
|
if (!samesubnet(&src->this.client, &srd->this.client))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (src->this.protocol != srd->this.protocol)
|
if (src->this.protocol != srd->this.protocol)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (src->this.port != srd->this.port)
|
if (src->this.port != srd->this.port)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (srd->routing > best_erouting)
|
if (srd->routing > best_erouting)
|
||||||
{
|
{
|
||||||
best_ero = d;
|
best_ero = d;
|
||||||
@ -3332,11 +3358,15 @@ connection_t *refine_host_connection(const struct state *st,
|
|||||||
|
|
||||||
/* do we have a match? */
|
/* do we have a match? */
|
||||||
if (!match)
|
if (!match)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* ignore group connections */
|
/* ignore group connections */
|
||||||
if (d->policy & POLICY_GROUP)
|
if (d->policy & POLICY_GROUP)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (c->spd.that.host_port != d->spd.that.host_port
|
if (c->spd.that.host_port != d->spd.that.host_port
|
||||||
&& d->kind == CK_INSTANCE)
|
&& d->kind == CK_INSTANCE)
|
||||||
@ -3354,12 +3384,17 @@ connection_t *refine_host_connection(const struct state *st,
|
|||||||
const chunk_t *dpsk = get_preshared_secret(d);
|
const chunk_t *dpsk = get_preshared_secret(d);
|
||||||
|
|
||||||
if (dpsk == NULL)
|
if (dpsk == NULL)
|
||||||
|
{
|
||||||
continue; /* no secret */
|
continue; /* no secret */
|
||||||
|
}
|
||||||
if (psk != dpsk)
|
if (psk != dpsk)
|
||||||
|
{
|
||||||
if (psk->len != dpsk->len
|
if (psk->len != dpsk->len
|
||||||
|| memcmp(psk->ptr, dpsk->ptr, psk->len) != 0)
|
|| memcmp(psk->ptr, dpsk->ptr, psk->len) != 0)
|
||||||
|
{
|
||||||
continue; /* different secret */
|
continue; /* different secret */
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3374,7 +3409,9 @@ connection_t *refine_host_connection(const struct state *st,
|
|||||||
.*/
|
.*/
|
||||||
if (d->spd.this.sc == NULL /* no smartcard */
|
if (d->spd.this.sc == NULL /* no smartcard */
|
||||||
&& get_private_key(d) == NULL) /* no private key */
|
&& get_private_key(d) == NULL) /* no private key */
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -3488,7 +3525,7 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
|
|||||||
const u_int8_t peer_protocol,
|
const u_int8_t peer_protocol,
|
||||||
const u_int16_t peer_port,
|
const u_int16_t peer_port,
|
||||||
chunk_t peer_ca,
|
chunk_t peer_ca,
|
||||||
const ietfAttrList_t *peer_list)
|
ietf_attributes_t *peer_attributes)
|
||||||
{
|
{
|
||||||
connection_t *d;
|
connection_t *d;
|
||||||
connection_t *best = NULL;
|
connection_t *best = NULL;
|
||||||
@ -3502,20 +3539,26 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
|
|||||||
struct spd_route *sr;
|
struct spd_route *sr;
|
||||||
|
|
||||||
if (d->policy & POLICY_GROUP)
|
if (d->policy & POLICY_GROUP)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(same_id(&c->spd.this.id, &d->spd.this.id)
|
if (!(same_id(&c->spd.this.id, &d->spd.this.id)
|
||||||
&& match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
|
&& match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
|
||||||
&& trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
|
&& trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
|
||||||
&& group_membership(peer_list, d->name, d->spd.that.groups)))
|
&& match_group_membership(peer_attributes, d->name, d->spd.that.groups)))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* compare protocol and ports */
|
/* compare protocol and ports */
|
||||||
if (d->spd.this.protocol != our_protocol
|
if (d->spd.this.protocol != our_protocol
|
||||||
|| d->spd.this.port != our_port
|
|| d->spd.this.port != our_port
|
||||||
|| d->spd.that.protocol != peer_protocol
|
|| d->spd.that.protocol != peer_protocol
|
||||||
|| (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
|
|| (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* non-Opportunistic case:
|
/* non-Opportunistic case:
|
||||||
* our_client must match.
|
* our_client must match.
|
||||||
@ -3552,29 +3595,38 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
|
|||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
if (!samesubnet(&sr->this.client, our_net))
|
if (!samesubnet(&sr->this.client, our_net))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (sr->that.has_client)
|
if (sr->that.has_client)
|
||||||
{
|
{
|
||||||
if (sr->that.has_client_wildcard)
|
if (sr->that.has_client_wildcard)
|
||||||
{
|
{
|
||||||
if (!subnetinsubnet(peer_net, &sr->that.client))
|
if (!subnetinsubnet(peer_net, &sr->that.client))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d))
|
if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (is_virtual_connection(d)
|
if (is_virtual_connection(d)
|
||||||
&& (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr)
|
&& (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr)
|
||||||
|| is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id)))
|
|| is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id)))
|
||||||
continue;
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!peer_net_is_host)
|
if (!peer_net_is_host)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We've run the gauntlet -- success:
|
/* We've run the gauntlet -- success:
|
||||||
@ -3616,7 +3668,7 @@ static connection_t *fc_try_oppo(const connection_t *c,
|
|||||||
const u_int8_t peer_protocol,
|
const u_int8_t peer_protocol,
|
||||||
const u_int16_t peer_port,
|
const u_int16_t peer_port,
|
||||||
chunk_t peer_ca,
|
chunk_t peer_ca,
|
||||||
const ietfAttrList_t *peer_list)
|
ietf_attributes_t *peer_attributes)
|
||||||
{
|
{
|
||||||
connection_t *d;
|
connection_t *d;
|
||||||
connection_t *best = NULL;
|
connection_t *best = NULL;
|
||||||
@ -3629,20 +3681,25 @@ static connection_t *fc_try_oppo(const connection_t *c,
|
|||||||
policy_prio_t prio;
|
policy_prio_t prio;
|
||||||
|
|
||||||
if (d->policy & POLICY_GROUP)
|
if (d->policy & POLICY_GROUP)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (!(same_id(&c->spd.this.id, &d->spd.this.id)
|
if (!(same_id(&c->spd.this.id, &d->spd.this.id)
|
||||||
&& match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
|
&& match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
|
||||||
&& trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
|
&& trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
|
||||||
&& group_membership(peer_list, d->name, d->spd.that.groups)))
|
&& match_group_membership(peer_attributes, d->name, d->spd.that.groups)))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* compare protocol and ports */
|
/* compare protocol and ports */
|
||||||
if (d->spd.this.protocol != our_protocol
|
if (d->spd.this.protocol != our_protocol
|
||||||
|| d->spd.this.port != our_port
|
|| d->spd.this.port != our_port
|
||||||
|| d->spd.that.protocol != peer_protocol
|
|| d->spd.that.protocol != peer_protocol
|
||||||
|| (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
|
|| (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Opportunistic case:
|
/* Opportunistic case:
|
||||||
* our_net must be inside d->spd.this.client
|
* our_net must be inside d->spd.this.client
|
||||||
@ -3670,7 +3727,9 @@ static connection_t *fc_try_oppo(const connection_t *c,
|
|||||||
|
|
||||||
if (!subnetinsubnet(our_net, &sr->this.client)
|
if (!subnetinsubnet(our_net, &sr->this.client)
|
||||||
|| !subnetinsubnet(peer_net, &sr->that.client))
|
|| !subnetinsubnet(peer_net, &sr->that.client))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* The connection is feasible, but we continue looking for the best.
|
/* The connection is feasible, but we continue looking for the best.
|
||||||
* The highest priority wins, implementing eroute-like rule.
|
* The highest priority wins, implementing eroute-like rule.
|
||||||
@ -3710,21 +3769,25 @@ static connection_t *fc_try_oppo(const connection_t *c,
|
|||||||
/*
|
/*
|
||||||
* get the peer's CA and group attributes
|
* get the peer's CA and group attributes
|
||||||
*/
|
*/
|
||||||
chunk_t get_peer_ca_and_groups(connection_t *c, const ietfAttrList_t **peer_list)
|
chunk_t get_peer_ca_and_groups(connection_t *c, ietf_attributes_t **peer_attributes)
|
||||||
{
|
{
|
||||||
struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
|
struct state *p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES);
|
||||||
|
|
||||||
*peer_list = NULL;
|
*peer_attributes = NULL;
|
||||||
|
|
||||||
if (p1st != NULL
|
if (p1st != NULL
|
||||||
&& p1st->st_peer_pubkey != NULL
|
&& p1st->st_peer_pubkey != NULL
|
||||||
&& p1st->st_peer_pubkey->issuer.ptr != NULL)
|
&& p1st->st_peer_pubkey->issuer.ptr != NULL)
|
||||||
{
|
{
|
||||||
x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer
|
x509acert_t *x509ac = get_x509acert(p1st->st_peer_pubkey->issuer,
|
||||||
, p1st->st_peer_pubkey->serial);;
|
p1st->st_peer_pubkey->serial);
|
||||||
|
|
||||||
if (ac != NULL && verify_x509acert(ac, strict_crl_policy))
|
if (x509ac && verify_x509acert(x509ac, strict_crl_policy))
|
||||||
*peer_list = ac->groups;
|
{
|
||||||
|
ac_t * ac = (ac_t*)x509ac->ac;
|
||||||
|
|
||||||
|
*peer_attributes = ac->get_groups(ac);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG(DBG_CONTROL,
|
DBG(DBG_CONTROL,
|
||||||
@ -3746,9 +3809,8 @@ connection_t *find_client_connection(connection_t *c,
|
|||||||
{
|
{
|
||||||
connection_t *d;
|
connection_t *d;
|
||||||
struct spd_route *sr;
|
struct spd_route *sr;
|
||||||
|
ietf_attributes_t *peer_attributes = NULL;
|
||||||
const ietfAttrList_t *peer_list = NULL;
|
chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_attributes);
|
||||||
chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (DBGP(DBG_CONTROLMORE))
|
if (DBGP(DBG_CONTROLMORE))
|
||||||
@ -3795,12 +3857,14 @@ connection_t *find_client_connection(connection_t *c,
|
|||||||
&& sr->this.port == our_port
|
&& sr->this.port == our_port
|
||||||
&& sr->that.protocol == peer_protocol
|
&& sr->that.protocol == peer_protocol
|
||||||
&& sr->that.port == peer_port
|
&& sr->that.port == peer_port
|
||||||
&& group_membership(peer_list, c->name, sr->that.groups))
|
&& match_group_membership(peer_attributes, c->name, sr->that.groups))
|
||||||
{
|
{
|
||||||
passert(oriented(*c));
|
passert(oriented(*c));
|
||||||
if (routed(sr->routing))
|
if (routed(sr->routing))
|
||||||
|
{
|
||||||
|
DESTROY_IF(peer_attributes);
|
||||||
return c;
|
return c;
|
||||||
|
}
|
||||||
unrouted = c;
|
unrouted = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3808,7 +3872,7 @@ connection_t *find_client_connection(connection_t *c,
|
|||||||
/* exact match? */
|
/* exact match? */
|
||||||
d = fc_try(c, c->host_pair, NULL, our_net, peer_net
|
d = fc_try(c, c->host_pair, NULL, our_net, peer_net
|
||||||
, our_protocol, our_port, peer_protocol, peer_port
|
, our_protocol, our_port, peer_protocol, peer_port
|
||||||
, peer_ca, peer_list);
|
, peer_ca, peer_attributes);
|
||||||
|
|
||||||
DBG(DBG_CONTROLMORE,
|
DBG(DBG_CONTROLMORE,
|
||||||
DBG_log(" fc_try %s gives %s"
|
DBG_log(" fc_try %s gives %s"
|
||||||
@ -3817,7 +3881,9 @@ connection_t *find_client_connection(connection_t *c,
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (d == NULL)
|
if (d == NULL)
|
||||||
|
{
|
||||||
d = unrouted;
|
d = unrouted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d == NULL)
|
if (d == NULL)
|
||||||
@ -3852,7 +3918,7 @@ connection_t *find_client_connection(connection_t *c,
|
|||||||
/* RW match with actual peer_id or abstract peer_id? */
|
/* RW match with actual peer_id or abstract peer_id? */
|
||||||
d = fc_try(c, hp, NULL, our_net, peer_net
|
d = fc_try(c, hp, NULL, our_net, peer_net
|
||||||
, our_protocol, our_port, peer_protocol, peer_port
|
, our_protocol, our_port, peer_protocol, peer_port
|
||||||
, peer_ca, peer_list);
|
, peer_ca, peer_attributes);
|
||||||
|
|
||||||
if (d == NULL
|
if (d == NULL
|
||||||
&& subnetishost(our_net)
|
&& subnetishost(our_net)
|
||||||
@ -3864,7 +3930,7 @@ connection_t *find_client_connection(connection_t *c,
|
|||||||
*/
|
*/
|
||||||
d = fc_try_oppo(c, hp, our_net, peer_net
|
d = fc_try_oppo(c, hp, our_net, peer_net
|
||||||
, our_protocol, our_port, peer_protocol, peer_port
|
, our_protocol, our_port, peer_protocol, peer_port
|
||||||
, peer_ca, peer_list);
|
, peer_ca, peer_attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3873,6 +3939,7 @@ connection_t *find_client_connection(connection_t *c,
|
|||||||
DBG_log(" concluding with d = %s"
|
DBG_log(" concluding with d = %s"
|
||||||
, (d ? d->name : "none"))
|
, (d ? d->name : "none"))
|
||||||
)
|
)
|
||||||
|
DESTROY_IF(peer_attributes);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3978,8 +4045,7 @@ void show_connections_status(bool all, const char *name)
|
|||||||
dntoa_or_null(this_ca, BUF_LEN, c->spd.this.ca, "%any");
|
dntoa_or_null(this_ca, BUF_LEN, c->spd.this.ca, "%any");
|
||||||
dntoa_or_null(that_ca, BUF_LEN, c->spd.that.ca, "%any");
|
dntoa_or_null(that_ca, BUF_LEN, c->spd.that.ca, "%any");
|
||||||
|
|
||||||
whack_log(RC_COMMENT
|
whack_log(RC_COMMENT, "\"%s\"%s: CAs: '%s'...'%s'"
|
||||||
, "\"%s\"%s: CAs: '%s'...'%s'"
|
|
||||||
, c->name
|
, c->name
|
||||||
, instance
|
, instance
|
||||||
, this_ca
|
, this_ca
|
||||||
@ -3989,14 +4055,10 @@ void show_connections_status(bool all, const char *name)
|
|||||||
/* show group attributes if defined */
|
/* show group attributes if defined */
|
||||||
if (c->spd.that.groups != NULL)
|
if (c->spd.that.groups != NULL)
|
||||||
{
|
{
|
||||||
char buf[BUF_LEN];
|
whack_log(RC_COMMENT, "\"%s\"%s: groups: %s"
|
||||||
|
|
||||||
format_groups(c->spd.that.groups, buf, BUF_LEN);
|
|
||||||
whack_log(RC_COMMENT
|
|
||||||
, "\"%s\"%s: groups: %s"
|
|
||||||
, c->name
|
, c->name
|
||||||
, instance
|
, instance
|
||||||
, buf);
|
, c->spd.that.groups->get_string(c->spd.that.groups));
|
||||||
}
|
}
|
||||||
|
|
||||||
whack_log(RC_COMMENT
|
whack_log(RC_COMMENT
|
||||||
|
|||||||
@ -146,7 +146,7 @@ struct end {
|
|||||||
u_int8_t protocol;
|
u_int8_t protocol;
|
||||||
cert_t cert; /* end certificate */
|
cert_t cert; /* end certificate */
|
||||||
chunk_t ca; /* CA distinguished name */
|
chunk_t ca; /* CA distinguished name */
|
||||||
struct ietfAttrList *groups;/* access control groups */
|
ietf_attributes_t *groups; /* access control groups */
|
||||||
smartcard_t *sc; /* smartcard reader and key info */
|
smartcard_t *sc; /* smartcard reader and key info */
|
||||||
struct virtual_t *virt;
|
struct virtual_t *virt;
|
||||||
bool modecfg; /* this end: request local address from server */
|
bool modecfg; /* this end: request local address from server */
|
||||||
@ -288,8 +288,8 @@ find_connection_for_clients(struct spd_route **srp
|
|||||||
, const ip_address *peer_client
|
, const ip_address *peer_client
|
||||||
, int transport_proto);
|
, int transport_proto);
|
||||||
|
|
||||||
extern chunk_t get_peer_ca_and_groups(connection_t *c
|
extern chunk_t get_peer_ca_and_groups(connection_t *c,
|
||||||
, const ietfAttrList_t **peer_list);
|
ietf_attributes_t **peer_attributes);
|
||||||
|
|
||||||
/* instantiating routines
|
/* instantiating routines
|
||||||
* Note: connection_discard() is in state.h because all its work
|
* Note: connection_discard() is in state.h because all its work
|
||||||
|
|||||||
@ -133,7 +133,7 @@ bool insert_crl(x509crl_t *x509crl, char *crl_uri, bool cache_crl)
|
|||||||
lock_authcert_list("insert_crl");
|
lock_authcert_list("insert_crl");
|
||||||
|
|
||||||
/* get the issuer cacert */
|
/* get the issuer cacert */
|
||||||
issuer_cert = get_authcert(issuer_dn, authKeyID, AUTH_CA);
|
issuer_cert = get_authcert(issuer_dn, authKeyID, X509_CA);
|
||||||
if (issuer_cert == NULL)
|
if (issuer_cert == NULL)
|
||||||
{
|
{
|
||||||
plog("crl issuer cacert not found");
|
plog("crl issuer cacert not found");
|
||||||
@ -434,7 +434,7 @@ cert_status_t verify_by_crl(const x509cert_t *cert, time_t *until,
|
|||||||
|
|
||||||
lock_authcert_list("verify_by_crl");
|
lock_authcert_list("verify_by_crl");
|
||||||
|
|
||||||
issuer_cert = get_authcert(issuer_dn, authKeyID, AUTH_CA);
|
issuer_cert = get_authcert(issuer_dn, authKeyID, X509_CA);
|
||||||
valid = cert_crl->issued_by(cert_crl, issuer_cert->cert);
|
valid = cert_crl->issued_by(cert_crl, issuer_cert->cert);
|
||||||
|
|
||||||
unlock_authcert_list("verify_by_crl");
|
unlock_authcert_list("verify_by_crl");
|
||||||
|
|||||||
@ -5182,29 +5182,33 @@ stf_status quick_inR1_outI2(struct msg_digest *md)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check the peer's group attributes */
|
/* check the peer's group attributes */
|
||||||
|
|
||||||
{
|
{
|
||||||
const ietfAttrList_t *peer_list = NULL;
|
ietf_attributes_t *peer_attributes = NULL;
|
||||||
|
bool match;
|
||||||
|
|
||||||
get_peer_ca_and_groups(st->st_connection, &peer_list);
|
get_peer_ca_and_groups(st->st_connection, &peer_attributes);
|
||||||
|
match = match_group_membership(peer_attributes,
|
||||||
|
st->st_connection->name,
|
||||||
|
st->st_connection->spd.that.groups);
|
||||||
|
DESTROY_IF(peer_attributes);
|
||||||
|
|
||||||
if (!group_membership(peer_list, st->st_connection->name
|
if (!match)
|
||||||
, st->st_connection->spd.that.groups))
|
|
||||||
{
|
{
|
||||||
char buf[BUF_LEN];
|
ietf_attributes_t *groups = st->st_connection->spd.that.groups;
|
||||||
|
|
||||||
format_groups(st->st_connection->spd.that.groups, buf, BUF_LEN);
|
loglog(RC_LOG_SERIOUS,
|
||||||
loglog(RC_LOG_SERIOUS, "peer is not member of one of the groups: %s"
|
"peer with attributes '%s' is not a member of the groups '%s'",
|
||||||
, buf);
|
peer_attributes->get_string(peer_attributes),
|
||||||
|
groups->get_string(groups));
|
||||||
return STF_FAIL + INVALID_ID_INFORMATION;
|
return STF_FAIL + INVALID_ID_INFORMATION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((st->nat_traversal & NAT_T_DETECTED)
|
if ((st->nat_traversal & NAT_T_DETECTED)
|
||||||
&& (st->nat_traversal & NAT_T_WITH_NATOA))
|
&& (st->nat_traversal & NAT_T_WITH_NATOA))
|
||||||
{
|
{
|
||||||
nat_traversal_natoa_lookup(md);
|
nat_traversal_natoa_lookup(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ??? We used to copy the accepted proposal into the state, but it was
|
/* ??? We used to copy the accepted proposal into the state, but it was
|
||||||
* never used. From sa_pd->pbs.start, length pbs_room(&sa_pd->pbs).
|
* never used. From sa_pd->pbs.start, length pbs_room(&sa_pd->pbs).
|
||||||
|
|||||||
@ -329,7 +329,7 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio
|
|||||||
|
|
||||||
if (authKeyID.ptr == NULL)
|
if (authKeyID.ptr == NULL)
|
||||||
{
|
{
|
||||||
x509cert_t *authcert = get_authcert(issuer_dn, authKeyID, AUTH_CA);
|
x509cert_t *authcert = get_authcert(issuer_dn, authKeyID, X509_CA);
|
||||||
|
|
||||||
if (authcert != NULL)
|
if (authcert != NULL)
|
||||||
{
|
{
|
||||||
@ -983,7 +983,7 @@ static bool valid_ocsp_response(response_t *res)
|
|||||||
lock_authcert_list("valid_ocsp_response");
|
lock_authcert_list("valid_ocsp_response");
|
||||||
|
|
||||||
authcert = get_authcert(res->responder_id_name, res->responder_id_key,
|
authcert = get_authcert(res->responder_id_name, res->responder_id_key,
|
||||||
AUTH_OCSP | AUTH_CA);
|
X509_OCSP_SIGNER | X509_CA);
|
||||||
if (authcert == NULL)
|
if (authcert == NULL)
|
||||||
{
|
{
|
||||||
plog("no matching ocsp signer cert found");
|
plog("no matching ocsp signer cert found");
|
||||||
@ -1040,7 +1040,7 @@ static bool valid_ocsp_response(response_t *res)
|
|||||||
DBG_log("certificate is valid")
|
DBG_log("certificate is valid")
|
||||||
)
|
)
|
||||||
|
|
||||||
authcert = get_authcert(issuer->get_encoding(issuer), authKeyID, AUTH_CA);
|
authcert = get_authcert(issuer->get_encoding(issuer), authKeyID, X509_CA);
|
||||||
if (authcert == NULL)
|
if (authcert == NULL)
|
||||||
{
|
{
|
||||||
plog("issuer cacert not found");
|
plog("issuer cacert not found");
|
||||||
@ -1168,7 +1168,7 @@ static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
|
|||||||
if ((x509->get_flags(x509) & X509_OCSP_SIGNER) &&
|
if ((x509->get_flags(x509) & X509_OCSP_SIGNER) &&
|
||||||
trust_authcert_candidate(cert, NULL))
|
trust_authcert_candidate(cert, NULL))
|
||||||
{
|
{
|
||||||
add_authcert(cert, AUTH_OCSP);
|
add_authcert(cert, X509_OCSP_SIGNER);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -720,11 +720,11 @@ int main(int argc, char **argv)
|
|||||||
#endif /* CAPABILITIES */
|
#endif /* CAPABILITIES */
|
||||||
|
|
||||||
/* loading X.509 CA certificates */
|
/* loading X.509 CA certificates */
|
||||||
load_authcerts("CA", CA_CERT_PATH, AUTH_CA);
|
load_authcerts("CA", CA_CERT_PATH, X509_CA);
|
||||||
/* loading X.509 AA certificates */
|
/* loading X.509 AA certificates */
|
||||||
load_authcerts("AA", AA_CERT_PATH, AUTH_AA);
|
load_authcerts("AA", AA_CERT_PATH, X509_AA);
|
||||||
/* loading X.509 OCSP certificates */
|
/* loading X.509 OCSP certificates */
|
||||||
load_authcerts("OCSP", OCSP_CERT_PATH, AUTH_OCSP);
|
load_authcerts("OCSP", OCSP_CERT_PATH, X509_OCSP_SIGNER);
|
||||||
/* loading X.509 CRLs */
|
/* loading X.509 CRLs */
|
||||||
load_crls();
|
load_crls();
|
||||||
/* loading attribute certificates (experimental) */
|
/* loading attribute certificates (experimental) */
|
||||||
|
|||||||
@ -451,17 +451,17 @@ whack_handle(int whackctlfd)
|
|||||||
|
|
||||||
if (msg.whack_reread & REREAD_CACERTS)
|
if (msg.whack_reread & REREAD_CACERTS)
|
||||||
{
|
{
|
||||||
load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
|
load_authcerts("CA cert", CA_CERT_PATH, X509_CA);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.whack_reread & REREAD_AACERTS)
|
if (msg.whack_reread & REREAD_AACERTS)
|
||||||
{
|
{
|
||||||
load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
|
load_authcerts("AA cert", AA_CERT_PATH, X509_AA);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.whack_reread & REREAD_OCSPCERTS)
|
if (msg.whack_reread & REREAD_OCSPCERTS)
|
||||||
{
|
{
|
||||||
load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);
|
load_authcerts("OCSP cert", OCSP_CERT_PATH, X509_OCSP_SIGNER);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.whack_reread & REREAD_ACERTS)
|
if (msg.whack_reread & REREAD_ACERTS)
|
||||||
@ -492,17 +492,17 @@ whack_handle(int whackctlfd)
|
|||||||
|
|
||||||
if (msg.whack_list & LIST_CACERTS)
|
if (msg.whack_list & LIST_CACERTS)
|
||||||
{
|
{
|
||||||
list_authcerts("CA", AUTH_CA, msg.whack_utc);
|
list_authcerts("CA", X509_CA, msg.whack_utc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.whack_list & LIST_AACERTS)
|
if (msg.whack_list & LIST_AACERTS)
|
||||||
{
|
{
|
||||||
list_authcerts("AA", AUTH_AA, msg.whack_utc);
|
list_authcerts("AA", X509_AA, msg.whack_utc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.whack_list & LIST_OCSPCERTS)
|
if (msg.whack_list & LIST_OCSPCERTS)
|
||||||
{
|
{
|
||||||
list_authcerts("OCSP", AUTH_OCSP, msg.whack_utc);
|
list_authcerts("OCSP", X509_OCSP_SIGNER, msg.whack_utc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.whack_list & LIST_ACERTS)
|
if (msg.whack_list & LIST_ACERTS)
|
||||||
@ -510,11 +510,6 @@ whack_handle(int whackctlfd)
|
|||||||
list_acerts(msg.whack_utc);
|
list_acerts(msg.whack_utc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.whack_list & LIST_GROUPS)
|
|
||||||
{
|
|
||||||
list_groups(msg.whack_utc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg.whack_list & LIST_CAINFOS)
|
if (msg.whack_list & LIST_CAINFOS)
|
||||||
{
|
{
|
||||||
list_ca_infos(msg.whack_utc);
|
list_ca_infos(msg.whack_utc);
|
||||||
|
|||||||
@ -126,8 +126,7 @@ const x509cert_t empty_x509cert = {
|
|||||||
NULL , /* *next */
|
NULL , /* *next */
|
||||||
UNDEFINED_TIME, /* installed */
|
UNDEFINED_TIME, /* installed */
|
||||||
0 , /* count */
|
0 , /* count */
|
||||||
FALSE , /* smartcard */
|
FALSE /* smartcard */
|
||||||
AUTH_NONE , /* authority_flags */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* coding of X.501 distinguished name */
|
/* coding of X.501 distinguished name */
|
||||||
@ -1038,7 +1037,7 @@ void store_x509certs(x509cert_t **firstcert, bool strict)
|
|||||||
|
|
||||||
if (trust_authcert_candidate(cert, cacerts))
|
if (trust_authcert_candidate(cert, cacerts))
|
||||||
{
|
{
|
||||||
add_authcert(cert, AUTH_CA);
|
add_authcert(cert, X509_CA);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1393,7 +1392,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
|
|||||||
|
|
||||||
lock_authcert_list("verify_x509cert");
|
lock_authcert_list("verify_x509cert");
|
||||||
issuer_cert = get_authcert(issuer->get_encoding(issuer),
|
issuer_cert = get_authcert(issuer->get_encoding(issuer),
|
||||||
authKeyID, AUTH_CA);
|
authKeyID, X509_CA);
|
||||||
if (issuer_cert == NULL)
|
if (issuer_cert == NULL)
|
||||||
{
|
{
|
||||||
plog("issuer cacert not found");
|
plog("issuer cacert not found");
|
||||||
@ -1495,7 +1494,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
|
|||||||
* List all X.509 certs in a chained list
|
* List all X.509 certs in a chained list
|
||||||
*/
|
*/
|
||||||
void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
||||||
u_char auth_flags, bool utc)
|
x509_flag_t flags, bool utc)
|
||||||
{
|
{
|
||||||
bool first = TRUE;
|
bool first = TRUE;
|
||||||
time_t now;
|
time_t now;
|
||||||
@ -1505,14 +1504,15 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
|||||||
|
|
||||||
while (cert != NULL)
|
while (cert != NULL)
|
||||||
{
|
{
|
||||||
if (auth_flags == AUTH_NONE || (auth_flags & cert->authority_flags))
|
certificate_t *certificate = cert->cert;
|
||||||
|
x509_t *x509 = (x509_t*)certificate;
|
||||||
|
|
||||||
|
if (flags == X509_NONE || (flags & x509->get_flags(x509)))
|
||||||
{
|
{
|
||||||
time_t notBefore, notAfter;
|
time_t notBefore, notAfter;
|
||||||
public_key_t *key;
|
public_key_t *key;
|
||||||
chunk_t serial, keyid, subjkey, authkey;
|
chunk_t serial, keyid, subjkey, authkey;
|
||||||
cert_t c;
|
cert_t c;
|
||||||
certificate_t *certificate = cert->cert;
|
|
||||||
x509_t *x509 = (x509_t*)certificate;
|
|
||||||
|
|
||||||
c.type = CERT_X509_SIGNATURE;
|
c.type = CERT_X509_SIGNATURE;
|
||||||
c.u.x509 = cert;
|
c.u.x509 = cert;
|
||||||
@ -1579,5 +1579,5 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
|||||||
*/
|
*/
|
||||||
void list_x509_end_certs(bool utc)
|
void list_x509_end_certs(bool utc)
|
||||||
{
|
{
|
||||||
list_x509cert_chain("End", x509certs, AUTH_NONE, utc);
|
list_x509cert_chain("End", x509certs, X509_NONE, utc);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,6 @@ struct x509cert {
|
|||||||
time_t installed;
|
time_t installed;
|
||||||
int count;
|
int count;
|
||||||
bool smartcard;
|
bool smartcard;
|
||||||
u_char authority_flags;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* used for initialization */
|
/* used for initialization */
|
||||||
@ -91,7 +90,7 @@ extern void release_x509cert(x509cert_t *cert);
|
|||||||
extern void free_x509cert(x509cert_t *cert);
|
extern void free_x509cert(x509cert_t *cert);
|
||||||
extern void store_x509certs(x509cert_t **firstcert, bool strict);
|
extern void store_x509certs(x509cert_t **firstcert, bool strict);
|
||||||
extern void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
extern void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
||||||
u_char auth_flags, bool utc);
|
x509_flag_t flags, bool utc);
|
||||||
extern void list_x509_end_certs(bool utc);
|
extern void list_x509_end_certs(bool utc);
|
||||||
extern void free_generalNames(generalName_t* gn, bool free_name);
|
extern void free_generalNames(generalName_t* gn, bool free_name);
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
carol::ipsec status::alice.*STATE_QUICK_I2.*IPsec SA established::YES
|
carol::ipsec status::alice.*STATE_QUICK_I2.*IPsec SA established::YES
|
||||||
moon::cat /var/log/auth.log::alice.*peer matches group 'Research'::YES
|
moon::cat /var/log/auth.log::alice.*peer with attributes .*Research.* is a member of the groups .*Research::YES
|
||||||
moon::ipsec status::alice.*PH_IP_CAROL.*STATE_QUICK_R2.*IPsec SA established::YES
|
moon::ipsec status::alice.*PH_IP_CAROL.*STATE_QUICK_R2.*IPsec SA established::YES
|
||||||
carol::ipsec status::venus.*STATE_QUICK_I2.*IPsec SA established::NO
|
carol::ipsec status::venus.*STATE_QUICK_I2.*IPsec SA established::NO
|
||||||
moon::cat /var/log/auth.log::venus.*peer doesn't match any group::YES
|
moon::cat /var/log/auth.log::venus.*peer with attributes .*Research.* is not a member of the groups .*Accounting::YES
|
||||||
moon::ipsec status::venus.*PH_IP_CAROL.*STATE_QUICK_R2.*IPsec SA established::NO
|
moon::ipsec status::venus.*PH_IP_CAROL.*STATE_QUICK_R2.*IPsec SA established::NO
|
||||||
dave::ipsec status::venus.*STATE_QUICK_I2.*IPsec SA established::YES
|
dave::ipsec status::venus.*STATE_QUICK_I2.*IPsec SA established::YES
|
||||||
moon::cat /var/log/auth.log::venus.*peer matches group 'Accounting'::YES
|
moon::cat /var/log/auth.log::venus.*peer with attributes .*Accounting.* is a member of the groups .*Accounting::YES
|
||||||
moon::ipsec status::venus.*PH_IP_DAVE.*STATE_QUICK_R2.*IPsec SA established::YES
|
moon::ipsec status::venus.*PH_IP_DAVE.*STATE_QUICK_R2.*IPsec SA established::YES
|
||||||
dave::ipsec status::alice.*STATE_QUICK_I2.*IPsec SA established::NO
|
dave::ipsec status::alice.*STATE_QUICK_I2.*IPsec SA established::NO
|
||||||
moon::cat /var/log/auth.log::alice.*peer doesn't match any group::YES
|
moon::cat /var/log/auth.log::alice.*peer with attributes .*Accounting.* is not a member of the groups .*Research::YES
|
||||||
moon::ipsec status::alice.*PH_IP_DAVE.*STATE_QUICK_R2.*IPsec SA established::NO
|
moon::ipsec status::alice.*PH_IP_DAVE.*STATE_QUICK_R2.*IPsec SA established::NO
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user