peer_cfg now knows about group memberships
This commit is contained in:
@@ -146,6 +146,13 @@ static peer_cfg_t *get_peer_cfg(private_local_backend_t *this,
|
||||
int prio = (wc1 + wc2) * (MAX_CA_PATH_LEN + 1);
|
||||
int pathlen = 0;
|
||||
identification_t *other_candidate_ca = current->get_other_ca(current);
|
||||
linked_list_t *groups = current->get_groups(current);
|
||||
|
||||
/* is a group membership required? */
|
||||
if (groups->get_count(groups) > 0)
|
||||
{
|
||||
DBG1(DBG_CFG, " group membership required");
|
||||
}
|
||||
|
||||
/* are there any ca constraints? */
|
||||
if (other_candidate_ca->get_type(other_candidate_ca) != ID_ANY)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <utils/linked_list.h>
|
||||
#include <utils/identification.h>
|
||||
#include <crypto/ietf_attr_list.h>
|
||||
|
||||
ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND,
|
||||
"CERT_ALWAYS_SEND",
|
||||
@@ -104,6 +105,11 @@ struct private_peer_cfg_t {
|
||||
*/
|
||||
identification_t *other_ca;
|
||||
|
||||
/**
|
||||
* we require the other end to belong to at least one group
|
||||
*/
|
||||
linked_list_t *groups;
|
||||
|
||||
/**
|
||||
* should we send a certificate
|
||||
*/
|
||||
@@ -279,10 +285,21 @@ static identification_t *get_my_ca(private_peer_cfg_t *this)
|
||||
return this->my_ca;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_other_ca
|
||||
*/
|
||||
static identification_t *get_other_ca(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->other_ca;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_groups
|
||||
*/
|
||||
static linked_list_t *get_groups(private_peer_cfg_t *this)
|
||||
{
|
||||
return this->groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of peer_cfg_t.get_cert_policy.
|
||||
@@ -417,9 +434,9 @@ static void destroy(private_peer_cfg_t *this)
|
||||
this->other_id->destroy(this->other_id);
|
||||
DESTROY_IF(this->my_ca);
|
||||
DESTROY_IF(this->other_ca);
|
||||
|
||||
DESTROY_IF(this->my_virtual_ip);
|
||||
DESTROY_IF(this->other_virtual_ip);
|
||||
ietfAttr_list_destroy(this->groups);
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
@@ -431,10 +448,11 @@ static void destroy(private_peer_cfg_t *this)
|
||||
peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
|
||||
identification_t *my_id, identification_t *other_id,
|
||||
identification_t *my_ca, identification_t *other_ca,
|
||||
cert_policy_t cert_policy, auth_method_t auth_method,
|
||||
eap_type_t eap_type, u_int32_t keyingtries,
|
||||
u_int32_t lifetime, u_int32_t rekeytime,
|
||||
u_int32_t jitter, bool reauth, bool mobike,
|
||||
linked_list_t *groups, cert_policy_t cert_policy,
|
||||
auth_method_t auth_method, eap_type_t eap_type,
|
||||
u_int32_t keyingtries, u_int32_t lifetime,
|
||||
u_int32_t rekeytime, u_int32_t jitter,
|
||||
bool reauth, bool mobike,
|
||||
u_int32_t dpd_delay, dpd_action_t dpd_action,
|
||||
host_t *my_virtual_ip, host_t *other_virtual_ip)
|
||||
{
|
||||
@@ -451,6 +469,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
|
||||
this->public.get_other_id = (identification_t* (*)(peer_cfg_t *))get_other_id;
|
||||
this->public.get_my_ca = (identification_t* (*)(peer_cfg_t *))get_my_ca;
|
||||
this->public.get_other_ca = (identification_t* (*)(peer_cfg_t *))get_other_ca;
|
||||
this->public.get_groups = (linked_list_t* (*)(peer_cfg_t *))get_groups;
|
||||
this->public.get_cert_policy = (cert_policy_t (*) (peer_cfg_t *))get_cert_policy;
|
||||
this->public.get_auth_method = (auth_method_t (*) (peer_cfg_t *))get_auth_method;
|
||||
this->public.get_eap_type = (eap_type_t (*) (peer_cfg_t *))get_eap_type;
|
||||
@@ -475,6 +494,7 @@ peer_cfg_t *peer_cfg_create(char *name, u_int ike_version, ike_cfg_t *ike_cfg,
|
||||
this->other_id = other_id;
|
||||
this->my_ca = my_ca;
|
||||
this->other_ca = other_ca;
|
||||
this->groups = groups;
|
||||
this->cert_policy = cert_policy;
|
||||
this->auth_method = auth_method;
|
||||
this->eap_type = eap_type;
|
||||
|
||||
@@ -30,6 +30,7 @@ typedef struct peer_cfg_t peer_cfg_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/identification.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <config/traffic_selector.h>
|
||||
#include <config/proposal.h>
|
||||
#include <config/ike_cfg.h>
|
||||
@@ -194,13 +195,21 @@ struct peer_cfg_t {
|
||||
identification_t* (*get_my_ca)(peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get peers CA.
|
||||
* @brief Get peer CA.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return other ca
|
||||
*/
|
||||
identification_t* (*get_other_ca)(peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get list of group attributes.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return linked list of group attributes
|
||||
*/
|
||||
linked_list_t* (*get_groups)(peer_cfg_t *this);
|
||||
|
||||
/**
|
||||
* @brief Should be sent a certificate for this connection?
|
||||
*
|
||||
@@ -347,6 +356,7 @@ struct peer_cfg_t {
|
||||
* @param other_id identification_t for the remote guy
|
||||
* @param my_ca CA to use for us
|
||||
* @param other_ca CA to use for other
|
||||
* @param groups list of group memberships
|
||||
* @param cert_policy should we send a certificate payload?
|
||||
* @param auth_method auth method to use to authenticate us
|
||||
* @param eap_type EAP type to use for peer authentication
|
||||
@@ -367,10 +377,11 @@ struct peer_cfg_t {
|
||||
peer_cfg_t *peer_cfg_create(char *name, u_int ikev_version, ike_cfg_t *ike_cfg,
|
||||
identification_t *my_id, identification_t *other_id,
|
||||
identification_t *my_ca, identification_t *other_ca,
|
||||
cert_policy_t cert_policy, auth_method_t auth_method,
|
||||
eap_type_t eap_type, u_int32_t keyingtries,
|
||||
u_int32_t lifetime, u_int32_t rekeytime,
|
||||
u_int32_t jitter, bool use_reauth, bool use_mobike,
|
||||
linked_list_t *groups, cert_policy_t cert_policy,
|
||||
auth_method_t auth_method, eap_type_t eap_type,
|
||||
u_int32_t keyingtries, u_int32_t lifetime,
|
||||
u_int32_t rekeytime, u_int32_t jitter,
|
||||
bool reauth, bool mobike,
|
||||
u_int32_t dpd_delay, dpd_action_t dpd_action,
|
||||
host_t *my_virtual_ip, host_t *other_virtual_ip);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <stroke.h>
|
||||
#include <daemon.h>
|
||||
#include <crypto/x509.h>
|
||||
#include <crypto/ietf_attr_list.h>
|
||||
#include <crypto/ac.h>
|
||||
#include <crypto/ca.h>
|
||||
#include <crypto/crl.h>
|
||||
@@ -238,6 +239,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
|
||||
bool other_ca_same =FALSE;
|
||||
host_t *my_host, *other_host, *my_subnet, *other_subnet;
|
||||
host_t *my_vip = NULL, *other_vip = NULL;
|
||||
linked_list_t *my_groups = linked_list_create();
|
||||
linked_list_t *other_groups = linked_list_create();
|
||||
proposal_t *proposal;
|
||||
traffic_selector_t *my_ts, *other_ts;
|
||||
char *interface;
|
||||
@@ -475,6 +478,11 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
|
||||
DBG2(DBG_CFG, " my ca: '%D'", my_ca);
|
||||
DBG2(DBG_CFG, " other ca:'%D'", other_ca);
|
||||
|
||||
if (msg->add_conn.other.groups)
|
||||
{
|
||||
ietfAttr_list_create_from_string(msg->add_conn.other.groups, other_groups);
|
||||
}
|
||||
|
||||
/* have a look for an (almost) identical peer config to reuse */
|
||||
iterator = charon->backends->create_iterator(charon->backends);
|
||||
while (iterator->iterate(iterator, (void**)&peer_cfg))
|
||||
@@ -485,6 +493,7 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
|
||||
&& my_host->equals(my_host, ike_cfg->get_my_host(ike_cfg))
|
||||
&& other_host->equals(other_host, ike_cfg->get_other_host(ike_cfg))
|
||||
&& other_ca->equals(other_ca, peer_cfg->get_other_ca(peer_cfg))
|
||||
&& ietfAttr_list_equals(other_groups, peer_cfg->get_groups(peer_cfg))
|
||||
&& peer_cfg->get_ike_version(peer_cfg) == (msg->add_conn.ikev2 ? 2 : 1)
|
||||
&& peer_cfg->get_auth_method(peer_cfg) == msg->add_conn.auth_method
|
||||
&& peer_cfg->get_eap_type(peer_cfg) == msg->add_conn.eap_type)
|
||||
@@ -507,6 +516,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
|
||||
other_host->destroy(other_host);
|
||||
other_id->destroy(other_id);
|
||||
other_ca->destroy(other_ca);
|
||||
ietfAttr_list_destroy(my_groups);
|
||||
ietfAttr_list_destroy(other_groups);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -554,7 +565,8 @@ static void stroke_add_conn(stroke_msg_t *msg, FILE *out)
|
||||
|
||||
|
||||
peer_cfg = peer_cfg_create(msg->add_conn.name, msg->add_conn.ikev2 ? 2 : 1,
|
||||
ike_cfg, my_id, other_id, my_ca, other_ca, msg->add_conn.me.sendcert,
|
||||
ike_cfg, my_id, other_id, my_ca, other_ca, other_groups,
|
||||
msg->add_conn.me.sendcert,
|
||||
msg->add_conn.auth_method, msg->add_conn.eap_type,
|
||||
msg->add_conn.rekey.tries, msg->add_conn.rekey.ike_lifetime,
|
||||
msg->add_conn.rekey.ike_lifetime - msg->add_conn.rekey.margin,
|
||||
@@ -1251,6 +1263,7 @@ static void stroke_status(stroke_msg_t *msg, FILE *out, bool all)
|
||||
{
|
||||
identification_t *my_ca = peer_cfg->get_my_ca(peer_cfg);
|
||||
identification_t *other_ca = peer_cfg->get_other_ca(peer_cfg);
|
||||
linked_list_t *groups = peer_cfg->get_groups(peer_cfg);
|
||||
|
||||
if (my_ca->get_type(my_ca) != ID_ANY
|
||||
|| other_ca->get_type(other_ca) != ID_ANY)
|
||||
@@ -1258,6 +1271,13 @@ static void stroke_status(stroke_msg_t *msg, FILE *out, bool all)
|
||||
fprintf(out, "%12s: CAs: '%D'...'%D'\n", peer_cfg->get_name(peer_cfg),
|
||||
my_ca, other_ca);
|
||||
}
|
||||
if (groups->get_count(groups) > 0)
|
||||
{
|
||||
fprintf(out, "%12s: groups: ", peer_cfg->get_name(peer_cfg));
|
||||
ietfAttr_list_list(groups, out);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
children = peer_cfg->create_child_cfg_iterator(peer_cfg);
|
||||
while (children->iterate(children, (void**)&child_cfg))
|
||||
|
||||
@@ -32,6 +32,7 @@ crypto/hashers/sha1_hasher.c crypto/hashers/sha1_hasher.h \
|
||||
crypto/hashers/sha2_hasher.c crypto/hashers/sha2_hasher.h \
|
||||
crypto/hashers/md5_hasher.c crypto/hashers/md5_hasher.h \
|
||||
crypto/hmac.c crypto/hmac.h \
|
||||
crypto/ietf_attr_list.c crypto/ietf_attr_list.h \
|
||||
crypto/ocsp.c crypto/ocsp.h \
|
||||
crypto/prfs/fips_prf.c crypto/prfs/fips_prf.h \
|
||||
crypto/prfs/hmac_prf.c crypto/prfs/hmac_prf.h \
|
||||
|
||||
@@ -30,8 +30,10 @@
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/pem.h>
|
||||
#include <crypto/x509.h>
|
||||
#include <crypto/ietf_attr_list.h>
|
||||
#include <utils/identification.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <utils/lexparser.h>
|
||||
|
||||
#include "ac.h"
|
||||
|
||||
@@ -144,219 +146,6 @@ struct private_x509ac_t {
|
||||
chunk_t signature;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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_t ietfAttr_t;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a linked list of ietfAttr_t objects from a string
|
||||
*/
|
||||
static void ietfAttr_create_from_string(linked_list_t *list, const char *msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists a linked list of ietfAttr_t objects
|
||||
*/
|
||||
static void ietfAttr_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 = 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys an ietfAttr_t object
|
||||
*/
|
||||
static void ietfAttr_destroy(ietfAttr_t *this)
|
||||
{
|
||||
free(this->value.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ietfAttr_t object.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
};
|
||||
|
||||
#define IETF_ATTR_OCTETS 4
|
||||
#define IETF_ATTR_OID 6
|
||||
#define IETF_ATTR_STRING 8
|
||||
#define IETF_ATTR_ROOF 11
|
||||
|
||||
/**
|
||||
* ASN.1 definition of roleSyntax
|
||||
*/
|
||||
@@ -548,43 +337,6 @@ static bool parse_directoryName(chunk_t blob, int level, bool implicit, identifi
|
||||
return has_directoryName;
|
||||
}
|
||||
|
||||
/**
|
||||
* parses ietfAttrSyntax
|
||||
*/
|
||||
static void parse_ietfAttrSyntax(chunk_t blob, int level0, linked_list_t *list)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
|
||||
asn1_init(&ctx, blob, level0, FALSE, FALSE);
|
||||
|
||||
while (objectID < IETF_ATTR_ROOF)
|
||||
{
|
||||
if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* parses roleSyntax
|
||||
*/
|
||||
@@ -700,10 +452,10 @@ static bool parse_certificate(chunk_t blob, private_x509ac_t *this)
|
||||
DBG2(" need to parse accessIdentity");
|
||||
break;
|
||||
case OID_CHARGING_IDENTITY:
|
||||
parse_ietfAttrSyntax(object, level, this->charging);
|
||||
ietfAttr_list_create_from_chunk(object, this->charging, level);
|
||||
break;
|
||||
case OID_GROUP:
|
||||
parse_ietfAttrSyntax(object, level, this->groups);
|
||||
ietfAttr_list_create_from_chunk(object, this->groups, level);
|
||||
break;
|
||||
case OID_ROLE:
|
||||
parse_roleSyntax(object, level);
|
||||
@@ -781,7 +533,7 @@ static void list(const private_x509ac_t *this, FILE *out, bool utc)
|
||||
|
||||
/* list all group attributes on a single line */
|
||||
fprintf(out, " groups: ");
|
||||
ietfAttr_list(this->groups, out);
|
||||
ietfAttr_list_list(this->groups, out);
|
||||
fprintf(out, "\n");
|
||||
|
||||
fprintf(out, " issuer: '%D'\n", this->issuerName);
|
||||
@@ -830,10 +582,8 @@ static void destroy(private_x509ac_t *this)
|
||||
DESTROY_IF(this->holderIssuer);
|
||||
DESTROY_IF(this->entityName);
|
||||
DESTROY_IF(this->issuerName);
|
||||
this->charging->destroy_offset(this->charging,
|
||||
offsetof(ietfAttr_t, destroy));
|
||||
this->groups->destroy_offset(this->groups,
|
||||
offsetof(ietfAttr_t, destroy));
|
||||
ietfAttr_list_destroy(this->charging);
|
||||
ietfAttr_list_destroy(this->groups);
|
||||
free(this->certificate.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#ifndef AC_H_
|
||||
#define AC_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct x509ac_t x509ac_t;
|
||||
|
||||
/**
|
||||
@@ -94,14 +96,13 @@ x509ac_t *x509ac_create_from_chunk(chunk_t chunk);
|
||||
|
||||
/**
|
||||
* @brief Read a x509 attribute certificate from a DER encoded file.
|
||||
*
|
||||
*
|
||||
* @param filename file containing DER encoded data
|
||||
* @return created x509ac_t certificate, or NULL if invalid.
|
||||
*
|
||||
* @return created x509ac_t certificate, or NULL if invalid.
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
x509ac_t *x509ac_create_from_file(const char *filename);
|
||||
|
||||
|
||||
#endif /* AC_H_ */
|
||||
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
/**
|
||||
* @file ietf_attr.c
|
||||
*
|
||||
* @brief Implementation of ietfAttr_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <asn1/asn1.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 = 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 */
|
||||
};
|
||||
|
||||
#define IETF_ATTR_OCTETS 4
|
||||
#define IETF_ATTR_OID 6
|
||||
#define IETF_ATTR_STRING 8
|
||||
#define IETF_ATTR_ROOF 11
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
void ietfAttr_list_create_from_chunk(chunk_t chunk, linked_list_t *list, int level0)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
|
||||
asn1_init(&ctx, chunk, level0, FALSE, FALSE);
|
||||
|
||||
while (objectID < IETF_ATTR_ROOF)
|
||||
{
|
||||
if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
void ietfAttr_list_destroy(linked_list_t *list)
|
||||
{
|
||||
list->destroy_offset(list, offsetof(ietfAttr_t, destroy));
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @file ietf_attr_list.h
|
||||
*
|
||||
* @brief Handling of ietfAttr_t linked lists
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
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 Destroys a linked list of ietfAttr_t objects
|
||||
*
|
||||
* @param list list to be destroyed
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
void ietfAttr_list_destroy(linked_list_t *list);
|
||||
|
||||
#endif /* IETF_ATTR_LIST_H_ */
|
||||
|
||||
Reference in New Issue
Block a user