mirror of
https://github.com/strongswan/strongswan.git
synced 2025-12-07 00:00:13 -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_response.h credentials/certificates/ocsp_response.c \
|
||||
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 \
|
||||
fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
|
||||
utils.h utils.c \
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
|
||||
* Copyright (C) 2003 Martin Berner, Lukas Suter
|
||||
* Copyright (C) 2002-2008 Andreas Steffen
|
||||
* Copyright (C) 2002-2009 Andreas Steffen
|
||||
*
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* 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
|
||||
@ -26,6 +24,7 @@
|
||||
|
||||
#include <library.h>
|
||||
#include <credentials/certificates/certificate.h>
|
||||
#include <credentials/ietf_attributes/ietf_attributes.h>
|
||||
|
||||
typedef struct ac_t ac_t;
|
||||
|
||||
@ -64,12 +63,19 @@ struct ac_t {
|
||||
identification_t* (*get_holderIssuer)(ac_t *this);
|
||||
|
||||
/**
|
||||
* Get the thauthorityKeyIdentifier.
|
||||
* Get the authorityKeyIdentifier.
|
||||
*
|
||||
* @return authKeyIdentifier as chunk_t, to internal data
|
||||
*/
|
||||
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
|
||||
*
|
||||
|
||||
@ -15,7 +15,8 @@
|
||||
|
||||
#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_AA",
|
||||
"X509_OCSP_SIGNER",
|
||||
|
||||
@ -31,6 +31,8 @@ typedef enum x509_flag_t x509_flag_t;
|
||||
* X.509 certificate flags.
|
||||
*/
|
||||
enum x509_flag_t {
|
||||
/** cert has no constraints */
|
||||
X509_NONE = 0,
|
||||
/** cert has CA constraint */
|
||||
X509_CA = (1<<0),
|
||||
/** 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_pkcs10.h x509_pkcs10.c \
|
||||
x509_ocsp_request.h x509_ocsp_request.c \
|
||||
x509_ocsp_response.h x509_ocsp_response.c \
|
||||
ietf_attr_list.h ietf_attr_list.c
|
||||
x509_ocsp_response.h x509_ocsp_response.c
|
||||
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) 2003 Martin Berner, Lukas Suter
|
||||
* Copyright (C) 2002-2008 Andreas Steffen
|
||||
* Copyright (C) 2002-2009 Andreas Steffen
|
||||
* 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
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@ -18,7 +18,6 @@
|
||||
*/
|
||||
|
||||
#include "x509_ac.h"
|
||||
#include "ietf_attr_list.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@ -30,6 +29,7 @@
|
||||
#include <utils/identification.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
#include <credentials/ietf_attributes/ietf_attributes.h>
|
||||
#include <credentials/keys/private_key.h>
|
||||
|
||||
extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob,
|
||||
@ -100,12 +100,12 @@ struct private_x509_ac_t {
|
||||
/**
|
||||
* List of charging attributes
|
||||
*/
|
||||
linked_list_t *charging;
|
||||
ietf_attributes_t *charging;
|
||||
|
||||
/**
|
||||
* List of groub attributes
|
||||
*/
|
||||
linked_list_t *groups;
|
||||
ietf_attributes_t *groups;
|
||||
|
||||
/**
|
||||
* Authority Key Identifier
|
||||
@ -413,10 +413,14 @@ static bool parse_certificate(private_x509_ac_t *this)
|
||||
DBG2(" need to parse accessIdentity");
|
||||
break;
|
||||
case OID_CHARGING_IDENTITY:
|
||||
ietfAttr_list_create_from_chunk(object, this->charging, level);
|
||||
DBG2("-- > --");
|
||||
this->charging = ietf_attributes_create_from_encoding(object);
|
||||
DBG2("-- < --");
|
||||
break;
|
||||
case OID_GROUP:
|
||||
ietfAttr_list_create_from_chunk(object, this->groups, level);
|
||||
DBG2("-- > --");
|
||||
this->groups = ietf_attributes_create_from_encoding(object);
|
||||
DBG2("-- < --");
|
||||
break;
|
||||
case OID_ROLE:
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@ -881,9 +893,8 @@ static void destroy(private_x509_ac_t *this)
|
||||
DESTROY_IF(this->holderCert);
|
||||
DESTROY_IF(this->signerCert);
|
||||
DESTROY_IF(this->signerKey);
|
||||
|
||||
ietfAttr_list_destroy(this->charging);
|
||||
ietfAttr_list_destroy(this->groups);
|
||||
DESTROY_IF(this->charging);
|
||||
DESTROY_IF(this->groups);
|
||||
free(this->serialNumber.ptr);
|
||||
free(this->authKeyIdentifier.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_holderSerial = (chunk_t (*)(ac_t*))get_holderSerial;
|
||||
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_subject = (identification_t* (*)(certificate_t *this))get_subject;
|
||||
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->signerCert = NULL;
|
||||
this->signerKey = NULL;
|
||||
this->charging = linked_list_create();
|
||||
this->groups = linked_list_create();
|
||||
this->charging = NULL;
|
||||
this->groups = NULL;
|
||||
this->ref = 1;
|
||||
|
||||
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));
|
||||
continue;
|
||||
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;
|
||||
case BUILD_CERT:
|
||||
ac->holderCert = va_arg(args, certificate_t*);
|
||||
|
||||
@ -448,7 +448,6 @@ int main(int argc, char **argv)
|
||||
signerCert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, certfile,
|
||||
BUILD_X509_FLAG, 0,
|
||||
BUILD_END);
|
||||
if (signerCert == NULL)
|
||||
{
|
||||
@ -462,7 +461,6 @@ int main(int argc, char **argv)
|
||||
userCert = lib->creds->create(lib->creds,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, usercertfile,
|
||||
BUILD_X509_FLAG, 0,
|
||||
BUILD_END);
|
||||
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
|
||||
* Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
|
||||
* 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
|
||||
@ -17,85 +18,28 @@
|
||||
#ifndef _AC_H
|
||||
#define _AC_H
|
||||
|
||||
/* definition of ietfAttribute kinds */
|
||||
|
||||
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 <time.h>
|
||||
|
||||
#include <credentials/certificates/certificate.h>
|
||||
#include <credentials/ietf_attributes/ietf_attributes.h>
|
||||
|
||||
/* access structure for an X.509 attribute certificate */
|
||||
|
||||
typedef struct x509acert x509acert_t;
|
||||
|
||||
struct x509acert {
|
||||
x509acert_t *next;
|
||||
time_t installed;
|
||||
chunk_t certificate;
|
||||
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;
|
||||
certificate_t *ac;
|
||||
x509acert_t *next;
|
||||
time_t installed;
|
||||
};
|
||||
|
||||
/* 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 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 void load_acerts(void);
|
||||
extern void free_acert(x509acert_t *ac);
|
||||
extern void free_acerts(void);
|
||||
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 */
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
*/
|
||||
static cert_t *builder_load_cert(certificate_type_t type, va_list args)
|
||||
{
|
||||
x509_flag_t flags = 0;
|
||||
chunk_t blob = chunk_empty;
|
||||
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:
|
||||
blob = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_X509_FLAG:
|
||||
flags |= va_arg(args, x509_flag_t);
|
||||
continue;
|
||||
case BUILD_END:
|
||||
break;
|
||||
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,
|
||||
CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_BLOB_ASN1_DER, blob,
|
||||
BUILD_X509_FLAG, flags,
|
||||
BUILD_END);
|
||||
if (x509cert->cert)
|
||||
{
|
||||
@ -128,9 +133,12 @@ static x509acert_t *builder_load_ac(certificate_type_t type, va_list args)
|
||||
if (blob.ptr)
|
||||
{
|
||||
ac = malloc_thing(x509acert_t);
|
||||
*ac = empty_ac;
|
||||
if (parse_ac(chunk_clone(blob), ac) &&
|
||||
verify_x509acert(ac, FALSE))
|
||||
ac->next = NULL;
|
||||
ac->installed = UNDEFINED_TIME;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ bool trusted_ca(chunk_t a, chunk_t b, int *pathlen)
|
||||
chunk_t issuer_dn;
|
||||
x509cert_t *cacert;
|
||||
|
||||
cacert = get_authcert(a, chunk_empty, AUTH_CA);
|
||||
cacert = get_authcert(a, chunk_empty, X509_CA);
|
||||
if (cacert == NULL)
|
||||
{
|
||||
break;
|
||||
@ -180,7 +180,7 @@ void free_authcerts(void)
|
||||
/*
|
||||
* 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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
certificate_t *certificate = cert->cert;
|
||||
x509_t *x509 = (x509_t*)certificate;
|
||||
identification_t *cert_subject;
|
||||
chunk_t cert_subject_dn;
|
||||
|
||||
/* skip non-matching types of authority certificates */
|
||||
if (!(cert->authority_flags & auth_flags))
|
||||
if (!(x509->get_flags(x509) & auth_flags))
|
||||
{
|
||||
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 */
|
||||
if (keyid.ptr)
|
||||
{
|
||||
x509_t *x509 = (x509_t*)certificate;
|
||||
chunk_t subjectKeyId;
|
||||
|
||||
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
|
||||
*/
|
||||
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;
|
||||
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);
|
||||
x509cert_t *old_cert;
|
||||
|
||||
/* set authority flags */
|
||||
cert->authority_flags |= auth_flags;
|
||||
|
||||
lock_authcert_list("add_authcert");
|
||||
|
||||
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))
|
||||
{
|
||||
/* cert is already present, just add additional authority flags */
|
||||
old_cert->authority_flags |= cert->authority_flags;
|
||||
DBG(DBG_CONTROL | DBG_PARSING ,
|
||||
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
|
||||
*/
|
||||
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;
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
free(filelist[n]);
|
||||
}
|
||||
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
|
||||
*/
|
||||
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");
|
||||
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
|
||||
{
|
||||
/* search in trusted chain */
|
||||
authcert = get_authcert(issuer_dn, authKeyID, AUTH_CA);
|
||||
authcert = get_authcert(issuer_dn, authKeyID, X509_CA);
|
||||
|
||||
if (authcert != NULL)
|
||||
{
|
||||
@ -670,7 +666,7 @@ void add_ca_info(const whack_message_t *msg)
|
||||
unlock_ca_info_list("add_ca_info");
|
||||
|
||||
/* add cacert to list of authcerts */
|
||||
cacert = add_authcert(cacert, AUTH_CA);
|
||||
cacert = add_authcert(cacert, X509_CA);
|
||||
if (!cached_cert && sc != NULL)
|
||||
{
|
||||
if (sc->last_cert.type == CERT_X509_SIGNATURE)
|
||||
|
||||
@ -22,13 +22,6 @@
|
||||
|
||||
#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 */
|
||||
|
||||
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 match_requested_ca(generalName_t *requested_ca
|
||||
, chunk_t our_ca, int *our_pathlen);
|
||||
extern bool match_requested_ca(generalName_t *requested_ca, chunk_t our_ca,
|
||||
int *our_pathlen);
|
||||
extern x509cert_t* get_authcert(chunk_t subject, chunk_t keyid,
|
||||
u_char auth_flags);
|
||||
extern void load_authcerts(const char *type, const char *path
|
||||
, u_char auth_flags);
|
||||
extern x509cert_t* add_authcert(x509cert_t *cert, u_char auth_flags);
|
||||
x509_flag_t auth_flags);
|
||||
extern void load_authcerts(const char *type, const char *path,
|
||||
x509_flag_t auth_flags);
|
||||
extern x509cert_t* add_authcert(x509cert_t *cert, x509_flag_t auth_flags);
|
||||
extern void free_authcerts(void);
|
||||
extern void list_authcerts(const char *caption, u_char auth_flags, bool utc);
|
||||
extern bool trust_authcert_candidate(const x509cert_t *cert
|
||||
, const x509cert_t *alt_chain);
|
||||
extern void list_authcerts(const char *caption, x509_flag_t auth_flags, bool utc);
|
||||
extern bool trust_authcert_candidate(const x509cert_t *cert,
|
||||
const x509cert_t *alt_chain);
|
||||
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 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
|
||||
*/
|
||||
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 = 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)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
|
||||
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 private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
|
||||
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_ca_cert(char *filename, cert_t *cert);
|
||||
extern bool same_cert(const cert_t *a, const cert_t *b);
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include <freeswan.h>
|
||||
#include "kameipsec.h"
|
||||
|
||||
#include <credentials/certificates/ac.h>
|
||||
#include <credentials/keys/private_key.h>
|
||||
|
||||
#include "constants.h"
|
||||
@ -336,11 +337,11 @@ void delete_connection(connection_t *c, bool relations)
|
||||
free_id_content(&c->spd.this.id);
|
||||
free(c->spd.this.updown);
|
||||
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(c->spd.that.updown);
|
||||
free(c->spd.that.ca.ptr);
|
||||
free_ietfAttrList(c->spd.that.groups);
|
||||
DESTROY_IF(c->spd.that.groups);
|
||||
free_generalNames(c->requested_ca, TRUE);
|
||||
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;
|
||||
|
||||
/* decode CA distinguished name, if any */
|
||||
if (src->ca != NULL)
|
||||
if (src->ca)
|
||||
{
|
||||
if streq(src->ca, "%same")
|
||||
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;
|
||||
|
||||
/* 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 */
|
||||
dst->host_addr = src->host_addr;
|
||||
@ -1261,8 +1265,14 @@ static connection_t *instantiate(connection_t *c,
|
||||
d->spd.that.has_id_wildcards = FALSE;
|
||||
}
|
||||
unshare_connection_strings(d);
|
||||
unshare_ietfAttrList(&d->spd.this.groups);
|
||||
unshare_ietfAttrList(&d->spd.that.groups);
|
||||
if (d->spd.this.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;
|
||||
|
||||
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)
|
||||
{
|
||||
if (c->kind == CK_GROUP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (p->ike_float)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -3036,11 +3050,17 @@ connection_t *route_owner(connection_t *c, struct spd_route **srp,
|
||||
for (src = &c->spd; src; src=src->next)
|
||||
{
|
||||
if (!samesubnet(&src->that.client, &srd->that.client))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (src->that.protocol != srd->that.protocol)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (src->that.port != srd->that.port)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
passert(oriented(*d));
|
||||
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))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (src->this.protocol != srd->this.protocol)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (src->this.port != srd->this.port)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (srd->routing > best_erouting)
|
||||
{
|
||||
best_ero = d;
|
||||
@ -3332,11 +3358,15 @@ connection_t *refine_host_connection(const struct state *st,
|
||||
|
||||
/* do we have a match? */
|
||||
if (!match)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ignore group connections */
|
||||
if (d->policy & POLICY_GROUP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->spd.that.host_port != d->spd.that.host_port
|
||||
&& 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);
|
||||
|
||||
if (dpsk == NULL)
|
||||
{
|
||||
continue; /* no secret */
|
||||
|
||||
}
|
||||
if (psk != dpsk)
|
||||
{
|
||||
if (psk->len != dpsk->len
|
||||
|| memcmp(psk->ptr, dpsk->ptr, psk->len) != 0)
|
||||
{
|
||||
continue; /* different secret */
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3374,7 +3409,9 @@ connection_t *refine_host_connection(const struct state *st,
|
||||
.*/
|
||||
if (d->spd.this.sc == NULL /* no smartcard */
|
||||
&& get_private_key(d) == NULL) /* no private key */
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
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_int16_t peer_port,
|
||||
chunk_t peer_ca,
|
||||
const ietfAttrList_t *peer_list)
|
||||
ietf_attributes_t *peer_attributes)
|
||||
{
|
||||
connection_t *d;
|
||||
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;
|
||||
|
||||
if (d->policy & POLICY_GROUP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(same_id(&c->spd.this.id, &d->spd.this.id)
|
||||
&& match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
|
||||
&& 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;
|
||||
}
|
||||
|
||||
/* compare protocol and ports */
|
||||
if (d->spd.this.protocol != our_protocol
|
||||
|| d->spd.this.port != our_port
|
||||
|| d->spd.that.protocol != peer_protocol
|
||||
|| (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* non-Opportunistic case:
|
||||
* our_client must match.
|
||||
@ -3552,29 +3595,38 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
|
||||
#endif /* DEBUG */
|
||||
|
||||
if (!samesubnet(&sr->this.client, our_net))
|
||||
{
|
||||
continue;
|
||||
|
||||
}
|
||||
if (sr->that.has_client)
|
||||
{
|
||||
if (sr->that.has_client_wildcard)
|
||||
{
|
||||
if (!subnetinsubnet(peer_net, &sr->that.client))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!samesubnet(&sr->that.client, peer_net) && !is_virtual_connection(d))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (is_virtual_connection(d)
|
||||
&& (!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)))
|
||||
continue;
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!peer_net_is_host)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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_int16_t peer_port,
|
||||
chunk_t peer_ca,
|
||||
const ietfAttrList_t *peer_list)
|
||||
ietf_attributes_t *peer_attributes)
|
||||
{
|
||||
connection_t *d;
|
||||
connection_t *best = NULL;
|
||||
@ -3629,20 +3681,25 @@ static connection_t *fc_try_oppo(const connection_t *c,
|
||||
policy_prio_t prio;
|
||||
|
||||
if (d->policy & POLICY_GROUP)
|
||||
{
|
||||
continue;
|
||||
|
||||
}
|
||||
if (!(same_id(&c->spd.this.id, &d->spd.this.id)
|
||||
&& match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
|
||||
&& 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;
|
||||
}
|
||||
|
||||
/* compare protocol and ports */
|
||||
if (d->spd.this.protocol != our_protocol
|
||||
|| d->spd.this.port != our_port
|
||||
|| d->spd.that.protocol != peer_protocol
|
||||
|| (d->spd.that.port != peer_port && !d->spd.that.has_port_wildcard))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Opportunistic case:
|
||||
* 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)
|
||||
|| !subnetinsubnet(peer_net, &sr->that.client))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The connection is feasible, but we continue looking for the best.
|
||||
* 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
|
||||
*/
|
||||
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);
|
||||
|
||||
*peer_list = NULL;
|
||||
*peer_attributes = NULL;
|
||||
|
||||
if (p1st != NULL
|
||||
&& p1st->st_peer_pubkey != NULL
|
||||
&& p1st->st_peer_pubkey->issuer.ptr != NULL)
|
||||
{
|
||||
x509acert_t *ac = get_x509acert(p1st->st_peer_pubkey->issuer
|
||||
, p1st->st_peer_pubkey->serial);;
|
||||
x509acert_t *x509ac = get_x509acert(p1st->st_peer_pubkey->issuer,
|
||||
p1st->st_peer_pubkey->serial);
|
||||
|
||||
if (ac != NULL && verify_x509acert(ac, strict_crl_policy))
|
||||
*peer_list = ac->groups;
|
||||
if (x509ac && verify_x509acert(x509ac, strict_crl_policy))
|
||||
{
|
||||
ac_t * ac = (ac_t*)x509ac->ac;
|
||||
|
||||
*peer_attributes = ac->get_groups(ac);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(DBG_CONTROL,
|
||||
@ -3746,9 +3809,8 @@ connection_t *find_client_connection(connection_t *c,
|
||||
{
|
||||
connection_t *d;
|
||||
struct spd_route *sr;
|
||||
|
||||
const ietfAttrList_t *peer_list = NULL;
|
||||
chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_list);
|
||||
ietf_attributes_t *peer_attributes = NULL;
|
||||
chunk_t peer_ca = get_peer_ca_and_groups(c, &peer_attributes);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (DBGP(DBG_CONTROLMORE))
|
||||
@ -3795,12 +3857,14 @@ connection_t *find_client_connection(connection_t *c,
|
||||
&& sr->this.port == our_port
|
||||
&& sr->that.protocol == peer_protocol
|
||||
&& 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));
|
||||
if (routed(sr->routing))
|
||||
{
|
||||
DESTROY_IF(peer_attributes);
|
||||
return c;
|
||||
|
||||
}
|
||||
unrouted = c;
|
||||
}
|
||||
}
|
||||
@ -3808,7 +3872,7 @@ connection_t *find_client_connection(connection_t *c,
|
||||
/* exact match? */
|
||||
d = fc_try(c, c->host_pair, NULL, our_net, peer_net
|
||||
, our_protocol, our_port, peer_protocol, peer_port
|
||||
, peer_ca, peer_list);
|
||||
, peer_ca, peer_attributes);
|
||||
|
||||
DBG(DBG_CONTROLMORE,
|
||||
DBG_log(" fc_try %s gives %s"
|
||||
@ -3817,7 +3881,9 @@ connection_t *find_client_connection(connection_t *c,
|
||||
)
|
||||
|
||||
if (d == NULL)
|
||||
{
|
||||
d = unrouted;
|
||||
}
|
||||
}
|
||||
|
||||
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? */
|
||||
d = fc_try(c, hp, NULL, our_net, peer_net
|
||||
, our_protocol, our_port, peer_protocol, peer_port
|
||||
, peer_ca, peer_list);
|
||||
, peer_ca, peer_attributes);
|
||||
|
||||
if (d == NULL
|
||||
&& 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
|
||||
, 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"
|
||||
, (d ? d->name : "none"))
|
||||
)
|
||||
DESTROY_IF(peer_attributes);
|
||||
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(that_ca, BUF_LEN, c->spd.that.ca, "%any");
|
||||
|
||||
whack_log(RC_COMMENT
|
||||
, "\"%s\"%s: CAs: '%s'...'%s'"
|
||||
whack_log(RC_COMMENT, "\"%s\"%s: CAs: '%s'...'%s'"
|
||||
, c->name
|
||||
, instance
|
||||
, this_ca
|
||||
@ -3989,14 +4055,10 @@ void show_connections_status(bool all, const char *name)
|
||||
/* show group attributes if defined */
|
||||
if (c->spd.that.groups != NULL)
|
||||
{
|
||||
char buf[BUF_LEN];
|
||||
|
||||
format_groups(c->spd.that.groups, buf, BUF_LEN);
|
||||
whack_log(RC_COMMENT
|
||||
, "\"%s\"%s: groups: %s"
|
||||
whack_log(RC_COMMENT, "\"%s\"%s: groups: %s"
|
||||
, c->name
|
||||
, instance
|
||||
, buf);
|
||||
, c->spd.that.groups->get_string(c->spd.that.groups));
|
||||
}
|
||||
|
||||
whack_log(RC_COMMENT
|
||||
|
||||
@ -146,7 +146,7 @@ struct end {
|
||||
u_int8_t protocol;
|
||||
cert_t cert; /* end certificate */
|
||||
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 */
|
||||
struct virtual_t *virt;
|
||||
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
|
||||
, int transport_proto);
|
||||
|
||||
extern chunk_t get_peer_ca_and_groups(connection_t *c
|
||||
, const ietfAttrList_t **peer_list);
|
||||
extern chunk_t get_peer_ca_and_groups(connection_t *c,
|
||||
ietf_attributes_t **peer_attributes);
|
||||
|
||||
/* instantiating routines
|
||||
* 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");
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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");
|
||||
|
||||
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);
|
||||
|
||||
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 */
|
||||
|
||||
{
|
||||
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
|
||||
, st->st_connection->spd.that.groups))
|
||||
if (!match)
|
||||
{
|
||||
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, "peer is not member of one of the groups: %s"
|
||||
, buf);
|
||||
loglog(RC_LOG_SERIOUS,
|
||||
"peer with attributes '%s' is not a member of the groups '%s'",
|
||||
peer_attributes->get_string(peer_attributes),
|
||||
groups->get_string(groups));
|
||||
return STF_FAIL + INVALID_ID_INFORMATION;
|
||||
}
|
||||
}
|
||||
|
||||
if ((st->nat_traversal & NAT_T_DETECTED)
|
||||
&& (st->nat_traversal & NAT_T_WITH_NATOA))
|
||||
{
|
||||
nat_traversal_natoa_lookup(md);
|
||||
}
|
||||
if ((st->nat_traversal & NAT_T_DETECTED)
|
||||
&& (st->nat_traversal & NAT_T_WITH_NATOA))
|
||||
{
|
||||
nat_traversal_natoa_lookup(md);
|
||||
}
|
||||
|
||||
/* ??? 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).
|
||||
|
||||
@ -329,7 +329,7 @@ static bool build_ocsp_location(const x509cert_t *cert, ocsp_location_t *locatio
|
||||
|
||||
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)
|
||||
{
|
||||
@ -983,7 +983,7 @@ static bool valid_ocsp_response(response_t *res)
|
||||
lock_authcert_list("valid_ocsp_response");
|
||||
|
||||
authcert = get_authcert(res->responder_id_name, res->responder_id_key,
|
||||
AUTH_OCSP | AUTH_CA);
|
||||
X509_OCSP_SIGNER | X509_CA);
|
||||
if (authcert == NULL)
|
||||
{
|
||||
plog("no matching ocsp signer cert found");
|
||||
@ -1040,7 +1040,7 @@ static bool valid_ocsp_response(response_t *res)
|
||||
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)
|
||||
{
|
||||
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) &&
|
||||
trust_authcert_candidate(cert, NULL))
|
||||
{
|
||||
add_authcert(cert, AUTH_OCSP);
|
||||
add_authcert(cert, X509_OCSP_SIGNER);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -720,11 +720,11 @@ int main(int argc, char **argv)
|
||||
#endif /* CAPABILITIES */
|
||||
|
||||
/* 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 */
|
||||
load_authcerts("AA", AA_CERT_PATH, AUTH_AA);
|
||||
load_authcerts("AA", AA_CERT_PATH, X509_AA);
|
||||
/* 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 */
|
||||
load_crls();
|
||||
/* loading attribute certificates (experimental) */
|
||||
|
||||
@ -451,17 +451,17 @@ whack_handle(int whackctlfd)
|
||||
|
||||
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)
|
||||
{
|
||||
load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
|
||||
load_authcerts("AA cert", AA_CERT_PATH, X509_AA);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -492,17 +492,17 @@ whack_handle(int whackctlfd)
|
||||
|
||||
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)
|
||||
{
|
||||
list_authcerts("AA", AUTH_AA, msg.whack_utc);
|
||||
list_authcerts("AA", X509_AA, msg.whack_utc);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -510,11 +510,6 @@ whack_handle(int whackctlfd)
|
||||
list_acerts(msg.whack_utc);
|
||||
}
|
||||
|
||||
if (msg.whack_list & LIST_GROUPS)
|
||||
{
|
||||
list_groups(msg.whack_utc);
|
||||
}
|
||||
|
||||
if (msg.whack_list & LIST_CAINFOS)
|
||||
{
|
||||
list_ca_infos(msg.whack_utc);
|
||||
|
||||
@ -126,8 +126,7 @@ const x509cert_t empty_x509cert = {
|
||||
NULL , /* *next */
|
||||
UNDEFINED_TIME, /* installed */
|
||||
0 , /* count */
|
||||
FALSE , /* smartcard */
|
||||
AUTH_NONE , /* authority_flags */
|
||||
FALSE /* smartcard */
|
||||
};
|
||||
|
||||
/* coding of X.501 distinguished name */
|
||||
@ -1038,7 +1037,7 @@ void store_x509certs(x509cert_t **firstcert, bool strict)
|
||||
|
||||
if (trust_authcert_candidate(cert, cacerts))
|
||||
{
|
||||
add_authcert(cert, AUTH_CA);
|
||||
add_authcert(cert, X509_CA);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1393,7 +1392,7 @@ bool verify_x509cert(const x509cert_t *cert, bool strict, time_t *until)
|
||||
|
||||
lock_authcert_list("verify_x509cert");
|
||||
issuer_cert = get_authcert(issuer->get_encoding(issuer),
|
||||
authKeyID, AUTH_CA);
|
||||
authKeyID, X509_CA);
|
||||
if (issuer_cert == NULL)
|
||||
{
|
||||
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
|
||||
*/
|
||||
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;
|
||||
time_t now;
|
||||
@ -1505,14 +1504,15 @@ void list_x509cert_chain(const char *caption, x509cert_t* cert,
|
||||
|
||||
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;
|
||||
public_key_t *key;
|
||||
chunk_t serial, keyid, subjkey, authkey;
|
||||
cert_t c;
|
||||
certificate_t *certificate = cert->cert;
|
||||
x509_t *x509 = (x509_t*)certificate;
|
||||
|
||||
c.type = CERT_X509_SIGNATURE;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
int count;
|
||||
bool smartcard;
|
||||
u_char authority_flags;
|
||||
};
|
||||
|
||||
/* used for initialization */
|
||||
@ -91,7 +90,7 @@ extern void release_x509cert(x509cert_t *cert);
|
||||
extern void free_x509cert(x509cert_t *cert);
|
||||
extern void store_x509certs(x509cert_t **firstcert, bool strict);
|
||||
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 free_generalNames(generalName_t* gn, bool free_name);
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user