diff options
-rw-r--r-- | src/charon/config/credentials/local_credential_store.c | 28 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ac.c | 71 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ac.h | 19 |
3 files changed, 106 insertions, 12 deletions
diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c index 60a01778f..3bd1db320 100644 --- a/src/charon/config/credentials/local_credential_store.c +++ b/src/charon/config/credentials/local_credential_store.c @@ -258,7 +258,6 @@ static status_t get_key(linked_list_t *keys, } } - /** * Implementation of local_credential_store_t.get_shared_key. */ @@ -1093,9 +1092,32 @@ static void load_aa_certificates(private_local_credential_store_t *this) */ static void add_attr_certificate(private_local_credential_store_t *this, x509ac_t *cert) { - /* TODO replace stale attribute certificates by fresh ones */ + iterator_t *iterator; + x509ac_t *current_cert; + pthread_mutex_lock(&(this->acerts_mutex)); - this->acerts->insert_last(this->acerts, (void*)cert); + iterator = this->acerts->create_iterator(this->acerts, TRUE); + + while (iterator->iterate(iterator, (void **)¤t_cert)) + { + if (cert->equals_holder(cert, current_cert)) + { + if (cert->is_newer(cert, current_cert)) + { + iterator->replace(iterator, NULL, (void *)cert); + current_cert->destroy(current_cert); + DBG1(DBG_CFG, " this attr cert is newer - existing attr cert replaced"); + } + else + { + cert->destroy(cert); + DBG1(DBG_CFG, " this attr cert is not newer - existing attr cert retained"); + } + break; + } + } + + iterator->destroy(iterator); pthread_mutex_unlock(&(this->acerts_mutex)); } diff --git a/src/libstrongswan/crypto/ac.c b/src/libstrongswan/crypto/ac.c index 29431ad69..d92c7b816 100644 --- a/src/libstrongswan/crypto/ac.c +++ b/src/libstrongswan/crypto/ac.c @@ -175,6 +175,42 @@ struct ietfAttr_t { }; /** + * 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: + fprintf(out, "0x#B", &attr->value); + break; + default: + break; + } + } + iterator->destroy(iterator); +} + +/** * Destroys an ietfAttr_t object */ static void ietfAttr_destroy(ietfAttr_t *this) @@ -361,6 +397,23 @@ static err_t is_valid(const private_x509ac_t *this, time_t *until) } /** + * Implements x509ac_t.is_newer + */ +static bool is_newer(const private_x509ac_t *this, const private_x509ac_t *other) +{ + return this->notBefore > other->notBefore; +} + +/** + * Implements x509ac_t.equals_holder. + */ +static bool equals_holder(const private_x509ac_t *this, const private_x509ac_t *other) +{ + return this->holderIssuer->equals(this->holderIssuer, other->holderIssuer) + && chunk_equals(this->holderSerial, other->holderSerial); +} + +/** * parses a directoryName */ static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name) @@ -613,7 +666,7 @@ static bool parse_certificate(chunk_t blob, private_x509ac_t *this) /** * Implementation of x509ac_t.list. */ -static void list(private_x509ac_t *this, FILE *out, bool utc) +static void list(const private_x509ac_t *this, FILE *out, bool utc) { time_t now = time(NULL); @@ -631,12 +684,12 @@ static void list(private_x509ac_t *this, FILE *out, bool utc) { fprintf(out, " hserial: %#B\n", &this->holderSerial); } -/* if (ac->groups != NULL) - { - format_groups(ac->groups, buf, BUF_LEN); - whack_log(RC_COMMENT, " groups: %s", buf); - } -*/ + + /* list all group attributes on a single line */ + fprintf(out, " groups: "); + ietfAttr_list(this->groups, out); + fprintf(out, "\n"); + fprintf(out, " issuer: '%D'\n", this->issuerName); fprintf(out, " serial: %#B\n", &this->serialNumber); @@ -707,7 +760,9 @@ x509ac_t *x509ac_create_from_chunk(chunk_t chunk) /* public functions */ this->public.is_valid = (err_t (*) (const x509ac_t*,time_t*))is_valid; - this->public.list = (void(*)(x509ac_t*, FILE *out, bool utc))list; + this->public.is_newer = (bool (*) (const x509ac_t*,const x509ac_t*))is_newer; + this->public.equals_holder = (bool (*) (const x509ac_t*,const x509ac_t*))equals_holder; + this->public.list = (void (*) (const x509ac_t*,FILE*,bool))list; this->public.destroy = (void (*) (x509ac_t*))destroy; if (!parse_certificate(chunk, this)) diff --git a/src/libstrongswan/crypto/ac.h b/src/libstrongswan/crypto/ac.h index 1886d4971..dc344292d 100644 --- a/src/libstrongswan/crypto/ac.h +++ b/src/libstrongswan/crypto/ac.h @@ -48,6 +48,23 @@ struct x509ac_t { */ err_t (*is_valid) (const x509ac_t *this, time_t *until); + /** @brief Checks if this attr cert is newer than the other attr cert + * + * @param this calling object + * @param other other attr cert object + * @return TRUE if this was issued more recently than other + */ + bool (*is_newer) (const x509ac_t *this, const x509ac_t *other); + + /** + * @brief Checks if two attribute certificates belong to the same holder + * + * @param this calling attribute certificate + * @param that other attribute certificate + * @return TRUE if same holder + */ + bool (*equals_holder) (const x509ac_t *this, const x509ac_t *other); + /** * @brief Log the attribute certificate info to out. * @@ -55,7 +72,7 @@ struct x509ac_t { * @param out stream to write to * @param utc TRUE for UTC times, FALSE for local time */ - void (*list)(x509ac_t *this, FILE *out, bool utc); + void (*list)(const x509ac_t *this, FILE *out, bool utc); /** * @brief Destroys the attribute certificate. |