pluto now uses x509 plugin for attribute certificate handling

This commit is contained in:
Andreas Steffen 2009-10-05 07:24:28 +02:00
parent 0ea9cbc6e9
commit fc12e3cd2e
28 changed files with 985 additions and 1445 deletions

View File

@ -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 \

View File

@ -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
*

View File

@ -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",

View File

@ -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 */

View 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 **)&current_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);
}

View File

@ -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_ @}*/

View File

@ -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

View File

@ -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 **)&current_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));
}

View File

@ -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_ @}*/

View File

@ -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*);

View File

@ -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)
{

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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;
}

View File

@ -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)

View File

@ -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);

View File

@ -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);
}
/**

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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).

View File

@ -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
{

View File

@ -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) */

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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