diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2006-07-03 06:27:45 +0000 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2006-07-03 06:27:45 +0000 |
commit | 971218c3ae71713e4bcff6113331c98d6a05f898 (patch) | |
tree | e038fea582349b5160209b92b3314811b6140771 | |
parent | 1d390631d7f6e8ec61b8daeafa5d3256b35feec1 (diff) | |
download | strongswan-971218c3ae71713e4bcff6113331c98d6a05f898.tar.bz2 strongswan-971218c3ae71713e4bcff6113331c98d6a05f898.tar.xz |
support of cert payloads
27 files changed, 1082 insertions, 634 deletions
diff --git a/src/charon/config/connections/connection.c b/src/charon/config/connections/connection.c index f3c4bddfb..ce1f0f31a 100644 --- a/src/charon/config/connections/connection.c +++ b/src/charon/config/connections/connection.c @@ -72,7 +72,7 @@ struct private_connection_t { /** * should we send a certificate request? */ - cert_policy_t cert_req_policy; + cert_policy_t certreq_policy; /** * should we send a certificates? @@ -122,11 +122,11 @@ static bool is_ikev2 (private_connection_t *this) } /** - * Implementation of connection_t.get_cert_req_policy. + * Implementation of connection_t.get_certreq_policy. */ -static cert_policy_t get_cert_req_policy (private_connection_t *this) +static cert_policy_t get_certreq_policy (private_connection_t *this) { - return this->cert_req_policy; + return this->certreq_policy; } /** @@ -295,7 +295,8 @@ static connection_t *clone(private_connection_t *this) proposal_t *proposal; private_connection_t *clone = (private_connection_t*)connection_create( this->name, this->ikev2, - this->cert_policy, this->cert_req_policy, + this->cert_policy, + this->certreq_policy, this->my_host->clone(this->my_host), this->other_host->clone(this->other_host), this->auth_method); @@ -336,7 +337,8 @@ static void destroy(private_connection_t *this) * Described in header. */ connection_t * connection_create(char *name, bool ikev2, - cert_policy_t cert_policy, cert_policy_t cert_req_policy, + cert_policy_t cert_policy, + cert_policy_t certreq_policy, host_t *my_host, host_t *other_host, auth_method_t auth_method) { @@ -346,7 +348,7 @@ connection_t * connection_create(char *name, bool ikev2, this->public.get_name = (char*(*)(connection_t*))get_name; this->public.is_ikev2 = (bool(*)(connection_t*))is_ikev2; this->public.get_cert_policy = (cert_policy_t(*)(connection_t*))get_cert_policy; - this->public.get_cert_req_policy = (cert_policy_t(*)(connection_t*))get_cert_req_policy; + this->public.get_certreq_policy = (cert_policy_t(*)(connection_t*))get_certreq_policy; this->public.get_my_host = (host_t*(*)(connection_t*))get_my_host; this->public.update_my_host = (void(*)(connection_t*,host_t*))update_my_host; this->public.update_other_host = (void(*)(connection_t*,host_t*))update_other_host; @@ -364,7 +366,7 @@ connection_t * connection_create(char *name, bool ikev2, this->name = strdup(name); this->ikev2 = ikev2; this->cert_policy = cert_policy; - this->cert_req_policy = cert_req_policy; + this->certreq_policy = certreq_policy; this->my_host = my_host; this->other_host = other_host; this->auth_method = auth_method; diff --git a/src/charon/config/connections/connection.h b/src/charon/config/connections/connection.h index 50563da4e..de6cb4616 100644 --- a/src/charon/config/connections/connection.h +++ b/src/charon/config/connections/connection.h @@ -228,7 +228,7 @@ struct connection_t { * @param this calling object * @return - TRUE, if certificate request should be sent */ - cert_policy_t (*get_cert_req_policy) (connection_t *this); + cert_policy_t (*get_certreq_policy) (connection_t *this); /** * @brief Should be sent a certificate for this connection? diff --git a/src/charon/config/credentials/credential_store.h b/src/charon/config/credentials/credential_store.h index b1dd87784..d08a451c0 100755 --- a/src/charon/config/credentials/credential_store.h +++ b/src/charon/config/credentials/credential_store.h @@ -63,8 +63,6 @@ struct credential_store_t { /** * @brief Returns the RSA public key of a specific ID. * - * The returned rsa_public_key_t must be destroyed by the caller after usage. - * * @param this calling object * @param id identification_t object identifiying the key. * @return public key, or NULL if not found @@ -72,6 +70,15 @@ struct credential_store_t { rsa_public_key_t* (*get_rsa_public_key) (credential_store_t *this, identification_t *id); /** + * @brief Returns the RSA public key of a specific ID if is trusted + * + * @param this calling object + * @param id identification_t object identifiying the key. + * @return public key, or NULL if not found or not trusted + */ + rsa_public_key_t* (*get_trusted_public_key) (credential_store_t *this, identification_t *id); + + /** * @brief Returns the RSA private key belonging to an RSA public key * * The returned rsa_private_key_t must be destroyed by the caller after usage. @@ -92,14 +99,23 @@ struct credential_store_t { bool (*has_rsa_private_key) (credential_store_t *this, rsa_public_key_t *pubkey); /** + * @brief Returns the certificate of a specific ID. + * + * @param this calling object + * @param id identification_t object identifiying the key. + * @return certificate, or NULL if not found + */ + x509_t* (*get_certificate) (credential_store_t *this, identification_t *id); + + /** * @brief Verify an X.509 certificate up to trust anchor including revocation checks * * @param this calling object * @param cert certificate to be verified - * @param until time until which the cert can be trusted + * @param found found a certificate copy in the credential store * @return TRUE if trusted */ - bool (*verify) (credential_store_t *this, const x509_t *cert, time_t *until); + bool (*verify) (credential_store_t *this, x509_t *cert, bool *found); /** * @brief If an end certificate does not already exists in the credential store then add it. diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c index 53e9cb64f..96c16d7ae 100644 --- a/src/charon/config/credentials/local_credential_store.c +++ b/src/charon/config/credentials/local_credential_store.c @@ -25,6 +25,7 @@ #include <string.h> #include <pthread.h> +#include <types.h> #include <utils/lexparser.h> #include <utils/linked_list.h> #include <utils/logger_manager.h> @@ -96,11 +97,11 @@ static status_t get_shared_secret(private_local_credential_store_t *this, identi } /** - * Implementation of local_credential_store_t.get_rsa_public_key. + * Implementation of credential_store_t.get_certificate. */ -static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *this, identification_t *id) +static x509_t* get_certificate(private_local_credential_store_t *this, identification_t * id) { - rsa_public_key_t *found = NULL; + x509_t *found = NULL; iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE); @@ -112,7 +113,7 @@ static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *th if (id->equals(id, cert->get_subject(cert)) || cert->equals_subjectAltName(cert, id)) { - found = cert->get_public_key(cert); + found = cert; break; } } @@ -121,6 +122,52 @@ static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *th } /** + * Implementation of local_credential_store_t.get_rsa_public_key. + */ +static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *this, identification_t *id) +{ + x509_t *cert = get_certificate(this, id); + + return (cert == NULL)? NULL:cert->get_public_key(cert); +} + +/** + * Implementation of local_credential_store_t.get_trusted_public_key. + */ +static rsa_public_key_t *get_trusted_public_key(private_local_credential_store_t *this, identification_t *id) +{ + cert_status_t status; + err_t ugh; + + x509_t *cert = get_certificate(this, id); + + if (cert == NULL) + return NULL; + + ugh = cert->is_valid(cert, NULL); + if (ugh != NULL) + { + this->logger->log(this->logger, ERROR, "certificate %s"); + return NULL; + } + + status = cert->get_status(cert); + if (status == CERT_REVOKED || status == CERT_UNTRUSTED || (this->strict && status != CERT_GOOD)) + { + this->logger->log(this->logger, ERROR, "certificate status: %s", + enum_name(&cert_status_names, status)); + return NULL; + } + if (status == CERT_GOOD && cert->get_until(cert) < time(NULL)) + { + this->logger->log(this->logger, ERROR, "certificate is good but crl is stale"); + return NULL; + } + + return cert->get_public_key(cert); +} + +/** * Implementation of local_credential_store_t.get_rsa_private_key. */ static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t *this, rsa_public_key_t *pubkey) @@ -241,7 +288,6 @@ static cert_status_t verify_by_crl(private_local_credential_store_t* this, const issuer_public_key = issuer_cert->get_public_key(issuer_cert); valid_signature = crl->verify(crl, issuer_public_key); - issuer_public_key->destroy(issuer_public_key); if (!valid_signature) { @@ -268,21 +314,47 @@ static cert_status_t verify_by_ocsp(private_local_credential_store_t* this, } /** - * Remove a public key for the linked list - */ -static void remove_public_key(private_local_credential_store_t *this, const x509_t *cert) + * Find an exact copy of a certificate in a linked list + */ +static x509_t* find_certificate_copy(linked_list_t *certs, x509_t *cert) { - /* TODO implement function */ + x509_t *found_cert = NULL; + + iterator_t *iterator = certs->create_iterator(certs, TRUE); + + while (iterator->has_next(iterator)) + { + x509_t *current_cert; + + iterator->current(iterator, (void**)¤t_cert); + if (cert->equals(cert, current_cert)) + { + found_cert = current_cert; + break; + } + } + iterator->destroy(iterator); + + return found_cert; } /** * Implementation of credential_store_t.verify. */ -static bool verify(private_local_credential_store_t *this, const x509_t *cert, time_t *until) +static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *found) { int pathlen; + time_t until = UNDEFINED_TIME; + + x509_t *end_cert = cert; + x509_t *cert_copy = find_certificate_copy(this->certs, end_cert); - *until = UNDEFINED_TIME; + *found = (cert_copy != NULL); + if (*found) + { + this->logger->log(this->logger, CONTROL|LEVEL1, + "end entitity certificate is already in credential store"); + } for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) { @@ -297,7 +369,7 @@ static bool verify(private_local_credential_store_t *this, const x509_t *cert, t this->logger->log(this->logger, CONTROL|LEVEL1, "subject: '%s'", subject->get_string(subject)); this->logger->log(this->logger, CONTROL|LEVEL1, "issuer: '%s'", issuer->get_string(issuer)); - ugh = cert->is_valid(cert, until); + ugh = cert->is_valid(cert, &until); if (ugh != NULL) { this->logger->log(this->logger, ERROR, "certificate %s", ugh); @@ -315,7 +387,6 @@ static bool verify(private_local_credential_store_t *this, const x509_t *cert, t issuer_public_key = issuer_cert->get_public_key(issuer_cert); valid_signature = cert->verify(cert, issuer_public_key); - issuer_public_key->destroy(issuer_public_key); if (!valid_signature) { @@ -328,6 +399,14 @@ static bool verify(private_local_credential_store_t *this, const x509_t *cert, t if (pathlen > 0 && cert->is_self_signed(cert)) { this->logger->log(this->logger, CONTROL|LEVEL1, "reached self-signed root ca"); + + /* set the definite status and trust interval of the end entity certificate */ + end_cert->set_until(end_cert, until); + if (cert_copy) + { + cert_copy->set_status(cert_copy, end_cert->get_status(end_cert)); + cert_copy->set_until(cert_copy, until); + } return TRUE; } else @@ -336,7 +415,7 @@ static bool verify(private_local_credential_store_t *this, const x509_t *cert, t cert_status_t status; certinfo_t *certinfo = certinfo_create(cert->get_serialNumber(cert)); - certinfo->set_nextUpdate(certinfo, *until); + certinfo->set_nextUpdate(certinfo, until); /* first check certificate revocation using ocsp */ status = verify_by_ocsp(this, cert, certinfo); @@ -348,24 +427,27 @@ static bool verify(private_local_credential_store_t *this, const x509_t *cert, t } nextUpdate = certinfo->get_nextUpdate(certinfo); + cert->set_status(cert, status); switch (status) { case CERT_GOOD: + /* set nextUpdate */ + cert->set_until(cert, nextUpdate); + /* if status information is stale */ if (this->strict && nextUpdate < time(NULL)) { this->logger->log(this->logger, CONTROL|LEVEL1, "certificate is good but status is stale"); - remove_public_key(this, cert); return FALSE; } this->logger->log(this->logger, CONTROL|LEVEL1, "certificate is good"); - + /* with strict crl policy the public key must have the same * lifetime as the validity of the ocsp status or crl lifetime */ - if (this->strict && nextUpdate < *until) - *until = nextUpdate; + if (this->strict && nextUpdate < until) + until = nextUpdate; break; case CERT_REVOKED: { @@ -375,7 +457,23 @@ static bool verify(private_local_credential_store_t *this, const x509_t *cert, t timetoa(buf, TIMETOA_BUF, &revocationTime, TRUE); this->logger->log(this->logger, ERROR, "certificate was revoked on %s, reason: %s", buf, certinfo->get_revocationReason(certinfo)); - remove_public_key(this, cert); + + /* set revocationTime */ + cert->set_until(cert, revocationTime); + + /* update status of end certificate in the credential store */ + if (cert_copy) + { + if (pathlen > 0) + { + cert_copy->set_status(cert_copy, CERT_UNTRUSTED); + } + else + { + cert_copy->set_status(cert_copy, CERT_REVOKED); + cert_copy->set_until(cert_copy, certinfo->get_revocationTime(certinfo)); + } + } return FALSE; } case CERT_UNKNOWN: @@ -384,7 +482,11 @@ static bool verify(private_local_credential_store_t *this, const x509_t *cert, t this->logger->log(this->logger, CONTROL|LEVEL1, "certificate status unknown"); if (this->strict) { - remove_public_key(this, cert); + /* update status of end certificate in the credential store */ + if (cert_copy) + { + cert_copy->set_status(cert_copy, CERT_UNTRUSTED); + } return FALSE; } break; @@ -403,30 +505,18 @@ static bool verify(private_local_credential_store_t *this, const x509_t *cert, t */ static x509_t* add_certificate(linked_list_t *certs, x509_t *cert) { - bool found = FALSE; - - iterator_t *iterator = certs->create_iterator(certs, TRUE); + x509_t *found_cert = find_certificate_copy(certs, cert); - while (iterator->has_next(iterator)) + if (found_cert) { - x509_t *current_cert; - - iterator->current(iterator, (void**)¤t_cert); - if (cert->equals(cert, current_cert)) - { - found = TRUE; - cert->destroy(cert); - cert = current_cert; - break; - } + cert->destroy(cert); + return found_cert; } - iterator->destroy(iterator); - - if (!found) + else { certs->insert_last(certs, (void*)cert); + return cert; } - return cert; } /** @@ -829,20 +919,22 @@ local_credential_store_t * local_credential_store_create(bool strict) { private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t); - this->public.credential_store.get_shared_secret = (status_t(*)(credential_store_t*,identification_t*,chunk_t*))get_shared_secret; - this->public.credential_store.get_rsa_private_key = (rsa_private_key_t*(*)(credential_store_t*,rsa_public_key_t*))get_rsa_private_key; - this->public.credential_store.has_rsa_private_key = (bool(*)(credential_store_t*,rsa_public_key_t*))has_rsa_private_key; + this->public.credential_store.get_shared_secret = (status_t (*) (credential_store_t*,identification_t*,chunk_t*))get_shared_secret; this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key; - this->public.credential_store.verify = (bool(*)(credential_store_t*,const x509_t*,time_t*))verify; - this->public.credential_store.add_end_certificate = (x509_t*(*)(credential_store_t*,x509_t*))add_end_certificate; - this->public.credential_store.add_ca_certificate = (x509_t*(*)(credential_store_t*,x509_t*))add_ca_certificate; - this->public.credential_store.log_certificates = (void(*)(credential_store_t*,logger_t*,bool))log_certificates; - this->public.credential_store.log_ca_certificates = (void(*)(credential_store_t*,logger_t*,bool))log_ca_certificates; - this->public.credential_store.log_crls = (void(*)(credential_store_t*,logger_t*,bool))log_crls; - this->public.credential_store.load_ca_certificates = (void(*)(credential_store_t*))load_ca_certificates; - this->public.credential_store.load_crls = (void(*)(credential_store_t*))load_crls; - this->public.credential_store.load_private_keys = (void(*)(credential_store_t*))load_private_keys; - this->public.credential_store.destroy = (void(*)(credential_store_t*))destroy; + this->public.credential_store.get_rsa_private_key = (rsa_private_key_t* (*) (credential_store_t*,rsa_public_key_t*))get_rsa_private_key; + this->public.credential_store.has_rsa_private_key = (bool (*) (credential_store_t*,rsa_public_key_t*))has_rsa_private_key; + this->public.credential_store.get_trusted_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_trusted_public_key; + this->public.credential_store.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate; + this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify; + this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate; + this->public.credential_store.add_ca_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_ca_certificate; + this->public.credential_store.log_certificates = (void (*) (credential_store_t*,logger_t*,bool))log_certificates; + this->public.credential_store.log_ca_certificates = (void (*) (credential_store_t*,logger_t*,bool))log_ca_certificates; + this->public.credential_store.log_crls = (void (*) (credential_store_t*,logger_t*,bool))log_crls; + this->public.credential_store.load_ca_certificates = (void (*) (credential_store_t*))load_ca_certificates; + this->public.credential_store.load_crls = (void (*) (credential_store_t*))load_crls; + this->public.credential_store.load_private_keys = (void (*) (credential_store_t*))load_private_keys; + this->public.credential_store.destroy = (void (*) (credential_store_t*))destroy; /* initialize mutexes */ pthread_mutex_init(&(this->crls_mutex), NULL); diff --git a/src/charon/config/policies/policy.c b/src/charon/config/policies/policy.c index ac8ae89b7..9e163f9de 100644 --- a/src/charon/config/policies/policy.c +++ b/src/charon/config/policies/policy.c @@ -68,6 +68,11 @@ struct private_policy_t { identification_t *other_ca; /** + * updown script + */ + char *updown; + + /** * list for all proposals */ linked_list_t *proposals; @@ -304,6 +309,14 @@ static void add_authorities(private_policy_t *this, identification_t *my_ca, ide } /** + * Implementation of policy_t.add_updown + */ +static void add_updown(private_policy_t *this, char *updown) +{ + this->updown = (updown == NULL)? NULL:strdup(updown); +} + +/** * Implementation of policy_t.add_my_traffic_selector */ static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector) @@ -371,6 +384,9 @@ static policy_t *clone(private_policy_t *this) { clone->other_ca = this->other_ca->clone(this->other_ca); } + + /* clone updown script */ + clone->updown = (this->updown == NULL)? NULL:strdup(this->updown); /* clone all proposals */ iterator = this->proposals->create_iterator(this->proposals, TRUE); @@ -445,6 +461,12 @@ static status_t destroy(private_policy_t *this) this->other_ca->destroy(this->other_ca); } + /* delete updown script */ + if (this->updown) + { + free(this->updown); + } + /* delete ids */ this->my_id->destroy(this->my_id); this->other_id->destroy(this->other_id); @@ -481,6 +503,7 @@ policy_t *policy_create(char *name, identification_t *my_id, identification_t *o this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector; this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal; this->public.add_authorities = (void(*)(policy_t*,identification_t*, identification_t*))add_authorities; + this->public.add_updown = (void(*)(policy_t*,identification_t*,char*))add_updown; this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime; this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime; this->public.clone = (policy_t*(*)(policy_t*))clone; diff --git a/src/charon/config/policies/policy.h b/src/charon/config/policies/policy.h index 089d75112..e6728b3d7 100644 --- a/src/charon/config/policies/policy.h +++ b/src/charon/config/policies/policy.h @@ -239,6 +239,14 @@ struct policy_t { void (*add_authorities) (policy_t *this, identification_t *my_ca, identification_t *other_ca); /** + * @brief Add updown script + * + * @param this calling object + * @param updown updown script + */ + void (*add_updown) (policy_t *this, char *updown); + + /** * @brief Get the lifetime of a policy, before rekeying starts. * * A call to this function automatically adds a jitter to diff --git a/src/charon/encoding/payloads/cert_payload.c b/src/charon/encoding/payloads/cert_payload.c index 146d42eda..18bf24d47 100644 --- a/src/charon/encoding/payloads/cert_payload.c +++ b/src/charon/encoding/payloads/cert_payload.c @@ -28,22 +28,25 @@ /** * String mappings for cert_encoding_t. */ -mapping_t cert_encoding_m[] = { - {PKCS7_WRAPPED_X509_CERTIFICATE, "PKCS7_WRAPPED_X509_CERTIFICATE"}, - {PGP_CERTIFICATE, "PGP_CERTIFICATE"}, - {DNS_SIGNED_KEY, "DNS_SIGNED_KEY"}, - {X509_CERTIFICATE_SIGNATURE, "X509_CERTIFICATE_SIGNATURE"}, - {KERBEROS_TOKEN, "KERBEROS_TOKEN"}, - {CERTIFICATE_REVOCATION_LIST, "CERTIFICATE_REVOCATION_LIST"}, - {AUTHORITY_REVOCATION_LIST, "AUTHORITY_REVOCATION_LIST"}, - {SPKI_CERTIFICATE, "SPKI_CERTIFICATE"}, - {X509_CERTIFICATE_ATTRIBUTE, "X509_CERTIFICATE_ATTRIBUTE"}, - {RAW_SA_KEY, "RAW_SA_KEY"}, - {HASH_AND_URL_X509_CERTIFICATE, "HASH_AND_URL_X509_CERTIFICATE"}, - {HASH_AND_URL_X509_BUNDLE, "HASH_AND_URL_X509_BUNDLE"}, - {MAPPING_END, NULL} +static const char *const cert_encoding_name[] = { + "CERT_NONE", + "CERT_PKCS7_WRAPPED_X509", + "CERT_PGP", + "CERT_DNS_SIGNED_KEY", + "CERT_X509_SIGNATURE", + "CERT_X509_KEY_EXCHANGE", + "CERT_KERBEROS_TOKENS", + "CERT_CRL", + "CERT_ARL", + "CERT_SPKI", + "CERT_X509_ATTRIBUTE", + "CERT_RAW_RSA_KEY", + "CERT_X509_HASH_AND_URL", + "CERT_X509_HASH_AND_URL_BUNDLE" }; +enum_names cert_encoding_names = + { CERT_NONE, CERT_X509_HASH_AND_URL_BUNDLE, cert_encoding_name, NULL }; typedef struct private_cert_payload_t private_cert_payload_t; @@ -277,3 +280,15 @@ cert_payload_t *cert_payload_create() return (&(this->public)); } + +/* + * Described in header + */ +cert_payload_t *cert_payload_create_from_x509(x509_t *cert) +{ + cert_payload_t *this = cert_payload_create(); + + this->set_cert_encoding(this, CERT_X509_SIGNATURE); + this->set_data(this, cert->get_certificate(cert)); + return this; +}
\ No newline at end of file diff --git a/src/charon/encoding/payloads/cert_payload.h b/src/charon/encoding/payloads/cert_payload.h index 51620d699..4c40ed7dc 100644 --- a/src/charon/encoding/payloads/cert_payload.h +++ b/src/charon/encoding/payloads/cert_payload.h @@ -24,6 +24,7 @@ #define CERT_PAYLOAD_H_ #include <types.h> +#include <crypto/x509.h> #include <encoding/payloads/payload.h> /** @@ -42,18 +43,19 @@ typedef enum cert_encoding_t cert_encoding_t; * @ingroup payloads */ enum cert_encoding_t { - PKCS7_WRAPPED_X509_CERTIFICATE = 1, - PGP_CERTIFICATE = 2, - DNS_SIGNED_KEY = 3, - X509_CERTIFICATE_SIGNATURE = 4, - KERBEROS_TOKEN = 6, - CERTIFICATE_REVOCATION_LIST = 7, - AUTHORITY_REVOCATION_LIST = 8, - SPKI_CERTIFICATE = 9, - X509_CERTIFICATE_ATTRIBUTE = 10, - RAW_SA_KEY = 11, - HASH_AND_URL_X509_CERTIFICATE = 12, - HASH_AND_URL_X509_BUNDLE = 13 + CERT_NONE = 0, + CERT_PKCS7_WRAPPED_X509 = 1, + CERT_PGP = 2, + CERT_DNS_SIGNED_KEY = 3, + CERT_X509_SIGNATURE = 4, + CERT_KERBEROS_TOKEN = 6, + CERT_CRL = 7, + CERT_ARL = 8, + CERT_SPKI = 9, + CERT_X509_ATTRIBUTE = 10, + CERT_RAW_RSA_KEY = 11, + CERT_X509_HASH_AND_URL = 12, + CERT_X509_HASH_AND_URL_BUNDLE = 13 }; /** @@ -61,8 +63,7 @@ enum cert_encoding_t { * * @ingroup payloads */ -extern mapping_t cert_encoding_m[]; - +extern enum_names cert_encoding_names; typedef struct cert_payload_t cert_payload_t; @@ -145,11 +146,20 @@ struct cert_payload_t { /** * @brief Creates an empty cert_payload_t object. * - * @return cert_payload_t object + * @return cert_payload_t object * * @ingroup payloads */ cert_payload_t *cert_payload_create(void); +/** + * @brief Creates a cert_payload_t object with an X.509 certificate. + * + * @param cert X.509 certificate + * @return cert_payload_t object + * + * @ingroup payloads + */ +cert_payload_t *cert_payload_create_from_x509(x509_t *cert); #endif /* CERT_PAYLOAD_H_ */ diff --git a/src/charon/encoding/payloads/payload.h b/src/charon/encoding/payloads/payload.h index fc3457832..bc593f618 100644 --- a/src/charon/encoding/payloads/payload.h +++ b/src/charon/encoding/payloads/payload.h @@ -199,7 +199,7 @@ typedef struct payload_t payload_t; * handling of all payloads. * * @b Constructors: - * - payload_create() with the payload to instanciate. + * - payload_create() with the payload to instantiate. * * @ingroup payloads */ diff --git a/src/charon/sa/authenticator.c b/src/charon/sa/authenticator.c index e895e2df3..aefd1e941 100644 --- a/src/charon/sa/authenticator.c +++ b/src/charon/sa/authenticator.c @@ -243,15 +243,14 @@ static status_t verify_auth_data (private_authenticator_t *this, } case RSA_DIGITAL_SIGNATURE: { - identification_t *other_id = other_id_payload->get_identification(other_id_payload); - rsa_public_key_t *public_key; status_t status; - chunk_t octets, auth_data; - - auth_data = auth_payload->get_data(auth_payload); - - public_key = charon->credentials->get_rsa_public_key(charon->credentials, - other_id); + chunk_t octets; + chunk_t auth_data = auth_payload->get_data(auth_payload); + identification_t *other_id = other_id_payload->get_identification(other_id_payload); + + rsa_public_key_t *public_key = + charon->credentials->get_trusted_public_key(charon->credentials, other_id); + if (public_key == NULL) { this->logger->log(this->logger, ERROR, "no public key found for '%s'", @@ -274,7 +273,6 @@ static status_t verify_auth_data (private_authenticator_t *this, other_id->get_string(other_id)); } - public_key->destroy(public_key); other_id->destroy(other_id); chunk_free(&octets); return status; @@ -356,7 +354,6 @@ static status_t compute_auth_data (private_authenticator_t *this, this->logger->log(this->logger, CONTROL|LEVEL1, "looking for private key with keyid %s", buf); my_key = charon->credentials->get_rsa_private_key(charon->credentials, my_pubkey); - my_pubkey->destroy(my_pubkey); if (my_key == NULL) { char buf[BUF_LEN]; diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 2ba9c7432..4bff80846 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -230,7 +230,7 @@ static void build_message(private_ike_sa_t *this, exchange_type_t type, bool req me = this->connection->get_my_host(this->connection); other = this->connection->get_other_host(this->connection); - this->logger->log(this->logger, CONTROL|LEVEL2, "Build empty message"); + this->logger->log(this->logger, CONTROL|LEVEL2, "build empty message"); new_message = message_create(); new_message->set_source(new_message, me->clone(me)); new_message->set_destination(new_message, other->clone(other)); @@ -255,7 +255,7 @@ static ike_sa_state_t get_state(private_ike_sa_t *this) */ static void set_new_state(private_ike_sa_t *this, state_t *state) { - this->logger->log(this->logger, CONTROL, "statechange: %s => %s", + this->logger->log(this->logger, CONTROL, "state change: %s => %s", mapping_find(ike_sa_state_m, get_state(this)), mapping_find(ike_sa_state_m, state->get_state(state))); this->current_state = state; @@ -387,7 +387,7 @@ static status_t retransmit_request(private_ike_sa_t *this, u_int32_t message_id) return NOT_FOUND; } - this->logger->log(this->logger, CONTROL | LEVEL1, "Going to retransmit message with id %d",message_id); + this->logger->log(this->logger, CONTROL | LEVEL1, "going to retransmit message with id %d",message_id); packet = this->last_requested_message->get_packet(this->last_requested_message); charon->send_queue->add(charon->send_queue, packet); this->update_timestamp(this, FALSE); @@ -414,7 +414,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d } if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo)) { - this->logger->log(this->logger, ERROR|LEVEL2, "No PRF algoithm selected!?"); + this->logger->log(this->logger, ERROR|LEVEL2, "no PRF algoithm selected!?"); return FAILED; } this->prf = prf_create(algo->algorithm); @@ -441,7 +441,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d /* SKEYSEED = prf(Ni | Nr, g^ir) */ dh->get_shared_secret(dh, &secret); - this->logger->log_chunk(this->logger, PRIVATE, "Shared Diffie Hellman secret", secret); + this->logger->log_chunk(this->logger, PRIVATE, "shared Diffie-Hellman secret", secret); this->prf->set_key(this->prf, nonces); this->prf->allocate_bytes(this->prf, secret, &skeyseed); this->logger->log_chunk(this->logger, PRIVATE | LEVEL1, "SKEYSEED", skeyseed); @@ -479,7 +479,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d /* SK_ai/SK_ar used for integrity protection */ if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo)) { - this->logger->log(this->logger, ERROR, "No integrity algoithm selected?!"); + this->logger->log(this->logger, ERROR, "no integrity algoithm selected?!"); return FAILED; } if (this->signer_initiator != NULL) @@ -516,7 +516,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d /* SK_ei/SK_er used for encryption */ if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo)) { - this->logger->log(this->logger, ERROR, "No encryption algoithm selected!?"); + this->logger->log(this->logger, ERROR, "no encryption algoithm selected!?"); return FAILED; } if (this->crypter_initiator != NULL) @@ -631,7 +631,7 @@ static void update_timestamp(private_ike_sa_t *this, bool in) if (0 > gettimeofday(tv, NULL)) { this->logger->log(this->logger, ERROR|LEVEL1, - "Warning: Failed to get time of day."); + "warning: failed to get time of day."); } } @@ -649,13 +649,13 @@ static status_t send_request(private_ike_sa_t *this, message_t *message) if (message->get_message_id(message) != this->message_id_out) { - this->logger->log(this->logger, ERROR, "Message could not be sent cause id (%d) was not as expected (%d)", + this->logger->log(this->logger, ERROR, "message could not be sent cause id (%d) was not as expected (%d)", message->get_message_id(message),this->message_id_out); return FAILED; } /* generate packet */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Generate packet from message"); + this->logger->log(this->logger, CONTROL|LEVEL2, "generate packet from message"); if (this->ike_sa_id->is_initiator(this->ike_sa_id)) { @@ -671,12 +671,12 @@ static status_t send_request(private_ike_sa_t *this, message_t *message) status = message->generate(message, crypter,signer, &packet); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR, "Could not generate packet from message"); + this->logger->log(this->logger, ERROR, "could not generate packet from message"); return FAILED; } this->logger->log(this->logger, CONTROL|LEVEL3, - "Add request packet with message id %d to global send queue", + "add request packet with message id %d to global send queue", this->message_id_out); charon->send_queue->add(charon->send_queue, packet); @@ -685,25 +685,25 @@ static status_t send_request(private_ike_sa_t *this, message_t *message) { this->last_requested_message->destroy(this->last_requested_message); } - this->logger->log(this->logger, CONTROL|LEVEL3, "Replace last requested message with new one"); + this->logger->log(this->logger, CONTROL|LEVEL3, "replace last requested message with new one"); this->last_requested_message = message; /* schedule a job for retransmission */ status = charon->configuration->get_retransmit_timeout(charon->configuration, 0, &timeout); if (status != SUCCESS) { - this->logger->log(this->logger, CONTROL|LEVEL2, "No retransmit job for message created!"); + this->logger->log(this->logger, CONTROL|LEVEL2, "no retransmit job for message created!"); } else { - this->logger->log(this->logger, CONTROL|LEVEL2, "Request will be retransmitted in %d ms.", timeout); + this->logger->log(this->logger, CONTROL|LEVEL2, "request will be retransmitted in %d ms.", timeout); retransmit_job = retransmit_request_job_create(this->message_id_out, this->ike_sa_id); charon->event_queue->add_relative(charon->event_queue, (job_t *)retransmit_job, timeout); } /* message counter can now be increased */ this->logger->log(this->logger, CONTROL|LEVEL3, - "Increase message counter for outgoing messages from %d", + "increase message counter for outgoing messages from %d", this->message_id_out); this->message_id_out++; @@ -724,7 +724,7 @@ static status_t send_response(private_ike_sa_t *this, message_t *message) if (message->get_message_id(message) != this->message_id_in) { - this->logger->log(this->logger, ERROR, "Message could not be sent cause id (%d) was not as expected (%d)", + this->logger->log(this->logger, ERROR, "message could not be sent cause id (%d) was not as expected (%d)", message->get_message_id(message),this->message_id_in); return FAILED; } @@ -743,12 +743,12 @@ static status_t send_response(private_ike_sa_t *this, message_t *message) status = message->generate(message, crypter,signer, &packet); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR, "Could not generate packet from message"); + this->logger->log(this->logger, ERROR, "could not generate packet from message"); return FAILED; } this->logger->log(this->logger, CONTROL|LEVEL3, - "Add response packet with message id %d to global send queue", + "add response packet with message id %d to global send queue", this->message_id_in); charon->send_queue->add(charon->send_queue, packet); @@ -758,11 +758,11 @@ static status_t send_response(private_ike_sa_t *this, message_t *message) this->last_responded_message->destroy(this->last_responded_message); } - this->logger->log(this->logger, CONTROL|LEVEL3, "Replace last responded message with new one"); + this->logger->log(this->logger, CONTROL|LEVEL3, "replace last responded message with new one"); this->last_responded_message = message; /* message counter can now be increased */ - this->logger->log(this->logger, CONTROL|LEVEL3, "Increase message counter for incoming messages"); + this->logger->log(this->logger, CONTROL|LEVEL3, "increase message counter for incoming messages"); this->message_id_in++; this->update_timestamp(this, FALSE); @@ -780,32 +780,32 @@ static void send_notify(private_ike_sa_t *this, exchange_type_t exchange_type, n packet_t *packet; status_t status; - this->logger->log(this->logger, CONTROL|LEVEL2, "Going to build message with notify payload"); + this->logger->log(this->logger, CONTROL|LEVEL2, "going to build message with notify payload"); /* set up the reply */ build_message(this, exchange_type, FALSE, &response); payload = notify_payload_create_from_protocol_and_type(PROTO_NONE, type); if ((data.ptr != NULL) && (data.len > 0)) { - this->logger->log(this->logger, CONTROL|LEVEL2, "Add Data to notify payload"); + this->logger->log(this->logger, CONTROL|LEVEL2, "add Data to notify payload"); payload->set_notification_data(payload,data); } - this->logger->log(this->logger, CONTROL|LEVEL2, "Add Notify payload to message"); + this->logger->log(this->logger, CONTROL|LEVEL2, "add Notify payload to message"); response->add_payload(response,(payload_t *) payload); /* generate packet */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Generate packet from message"); + this->logger->log(this->logger, CONTROL|LEVEL2, "generate packet from message"); status = response->generate(response, this->crypter_responder, this->signer_responder, &packet); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR|LEVEL1, "Could not generate notify message"); + this->logger->log(this->logger, ERROR|LEVEL1, "could not generate notify message"); response->destroy(response); return; } - this->logger->log(this->logger, CONTROL|LEVEL2, "Add packet to global send queue"); + this->logger->log(this->logger, CONTROL|LEVEL2, "add packet to global send queue"); charon->send_queue->add(charon->send_queue, packet); - this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy message"); + this->logger->log(this->logger, CONTROL|LEVEL2, "destroy message"); response->destroy(response); this->update_timestamp(this, FALSE); @@ -856,7 +856,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) is_request = message->get_request(message); exchange_type = message->get_exchange_type(message); - this->logger->log(this->logger, CONTROL|LEVEL1, "Process %s of exchange type %s", + this->logger->log(this->logger, CONTROL|LEVEL1, "process %s of exchange type %s", (is_request) ? "request" : "response", mapping_find(exchange_type_m, exchange_type)); @@ -869,7 +869,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) if (this->last_responded_message) { packet_t *packet = this->last_responded_message->get_packet(this->last_responded_message); - this->logger->log(this->logger, CONTROL|LEVEL1, "Resent request detected. Send stored reply."); + this->logger->log(this->logger, CONTROL|LEVEL1, "resent request detected. Send stored reply."); charon->send_queue->add(charon->send_queue, packet); this->update_timestamp(this, FALSE); return SUCCESS; @@ -888,7 +888,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) if (message_id != this->message_id_in) { this->logger->log(this->logger, ERROR | LEVEL1, - "Message request with message id %d received, but %d expected", + "message request with message id %d received, but %d expected", message_id,this->message_id_in); return FAILED; } @@ -899,7 +899,7 @@ static status_t process_message(private_ike_sa_t *this, message_t *message) if (message_id != (this->message_id_out - 1)) { this->logger->log(this->logger, ERROR | LEVEL1, - "Message reply with message id %d received, but %d expected", + "message reply with message id %d received, but %d expected", message_id,this->message_id_in); return FAILED; } @@ -1003,7 +1003,7 @@ static status_t update_connection_hosts(private_ike_sa_t *this, host_t *me, host if (other_changes & HOST_DIFF_ADDR) { this->logger->log(this->logger, ERROR|LEVEL1, - "Destination ip changed from %s to %s. As we are NATed this is not allowed!", + "destination ip changed from %s to %s. As we are NATed this is not allowed!", old_other->get_address(old_other), other->get_address(other)); return DESTROY_ME; } @@ -1123,7 +1123,7 @@ static status_t delete_child_sa(private_ike_sa_t *this, u_int32_t reqid) if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED) { this->logger->log(this->logger, ERROR|LEVEL1, - "Delete of a CHILD_SA whose IKE_SA not in state IKE_SA_ESTABLISHED, aborting"); + "delete of a CHILD_SA whose IKE_SA not in state IKE_SA_ESTABLISHED, aborting"); return FAILED; } @@ -1222,7 +1222,7 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid) if (this->current_state->get_state(this->current_state) != IKE_SA_ESTABLISHED) { this->logger->log(this->logger, ERROR|LEVEL1, - "Rekeying of an CHILD_SA whose IKE_SA not in state IKE_SA_ESTABLISHED, aborting"); + "rekeying of an CHILD_SA whose IKE_SA not in state IKE_SA_ESTABLISHED, aborting"); return FAILED; } @@ -1278,11 +1278,34 @@ static status_t rekey_child_sa(private_ike_sa_t *this, u_int32_t reqid) } /** + * Implementation of protected_ike_sa_t.establish. + */ +static void establish(private_ike_sa_t *this) +{ + protected_ike_sa_t *ike_sa = (protected_ike_sa_t *)this; + + connection_t *connection = ike_sa->get_connection(ike_sa); + host_t *my_host = connection->get_my_host(connection); + host_t *other_host = connection->get_other_host(connection); + policy_t *policy = ike_sa->get_policy(ike_sa); + identification_t *my_id = policy->get_my_id(policy); + identification_t *other_id = policy->get_other_id(policy); + + ike_sa->set_new_state(ike_sa, (state_t*)ike_sa_established_create(ike_sa)); + + this->logger->log(this->logger, AUDIT, "IKE_SA established %s[%s]...%s[%s]", + my_host->get_address(my_host), + my_id->get_string(my_id), + other_host->get_address(other_host), + other_id->get_string(other_id)); +} + +/** * Implementation of protected_ike_sa_t.reset_message_buffers. */ static void reset_message_buffers(private_ike_sa_t *this) { - this->logger->log(this->logger, CONTROL|LEVEL2, "Reset message counters and destroy stored messages"); + this->logger->log(this->logger, CONTROL|LEVEL2, "reset message counters and destroy stored messages"); /* destroy stored requested message */ if (this->last_requested_message != NULL) { @@ -1497,14 +1520,14 @@ static void destroy(private_ike_sa_t *this) { child_sa_t *child_sa; - this->logger->log(this->logger, CONTROL|LEVEL2, "Going to destroy IKE SA %llu:%llu, role %s", + this->logger->log(this->logger, CONTROL|LEVEL2, "going to destroy IKE SA %llu:%llu, role %s", this->ike_sa_id->get_initiator_spi(this->ike_sa_id), this->ike_sa_id->get_responder_spi(this->ike_sa_id), this->ike_sa_id->is_initiator(this->ike_sa_id) ? "initiator" : "responder"); if (get_state(this) == IKE_SA_ESTABLISHED) { - this->logger->log(this->logger, ERROR, "Destroying an established IKE SA without knowledge from remote peer!"); + this->logger->log(this->logger, ERROR, "destroying an established IKE SA without knowledge from remote peer!"); } while (this->child_sas->remove_last(this->child_sas, (void**)&child_sa) == SUCCESS) @@ -1591,66 +1614,67 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) private_ike_sa_t *this = malloc_thing(private_ike_sa_t); /* Public functions */ - this->protected.public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message; - this->protected.public.initiate_connection = (status_t(*)(ike_sa_t*,connection_t*)) initiate_connection; - this->protected.public.delete_child_sa = (status_t(*)(ike_sa_t*,u_int32_t)) delete_child_sa; - this->protected.public.rekey_child_sa = (status_t(*)(ike_sa_t*,u_int32_t)) rekey_child_sa; - this->protected.public.get_child_sa = (child_sa_t*(*)(ike_sa_t*,u_int32_t))get_child_sa; - this->protected.public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id; - this->protected.public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host; - this->protected.public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host; - this->protected.public.get_my_id = (identification_t*(*)(ike_sa_t*)) get_my_id; - this->protected.public.get_other_id = (identification_t*(*)(ike_sa_t*)) get_other_id; - this->protected.public.get_connection = (connection_t*(*)(ike_sa_t*)) get_connection; - this->protected.public.retransmit_possible = (bool (*) (ike_sa_t *, u_int32_t)) retransmit_possible; - this->protected.public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request; - this->protected.public.get_state = (ike_sa_state_t (*) (ike_sa_t *this)) get_state; + this->protected.public.process_message = (status_t (*) (ike_sa_t*,message_t*)) process_message; + this->protected.public.initiate_connection = (status_t (*) (ike_sa_t*,connection_t*)) initiate_connection; + this->protected.public.delete_child_sa = (status_t (*) (ike_sa_t*,u_int32_t)) delete_child_sa; + this->protected.public.rekey_child_sa = (status_t (*) (ike_sa_t*,u_int32_t)) rekey_child_sa; + this->protected.public.get_child_sa = (child_sa_t* (*) (ike_sa_t*,u_int32_t))get_child_sa; + this->protected.public.get_id = (ike_sa_id_t* (*) (ike_sa_t*)) get_id; + this->protected.public.get_my_host = (host_t* (*) (ike_sa_t*)) get_my_host; + this->protected.public.get_other_host = (host_t* (*) (ike_sa_t*)) get_other_host; + this->protected.public.get_my_id = (identification_t* (*) (ike_sa_t*)) get_my_id; + this->protected.public.get_other_id = (identification_t* (*) (ike_sa_t*)) get_other_id; + this->protected.public.get_connection = (connection_t* (*) (ike_sa_t*)) get_connection; + this->protected.public.retransmit_possible = (bool (*) (ike_sa_t*,u_int32_t)) retransmit_possible; + this->protected.public.retransmit_request = (status_t (*) (ike_sa_t*,u_int32_t)) retransmit_request; + this->protected.public.get_state = (ike_sa_state_t (*) (ike_sa_t*)) get_state; this->protected.public.log_status = (void (*) (ike_sa_t*,logger_t*,char*))log_status; - this->protected.public.delete = (status_t(*)(ike_sa_t*))delete_; - this->protected.public.destroy = (void(*)(ike_sa_t*))destroy; - this->protected.public.is_my_host_behind_nat = (bool(*)(ike_sa_t*)) is_my_host_behind_nat; - this->protected.public.is_other_host_behind_nat = (bool(*)(ike_sa_t*)) is_other_host_behind_nat; - this->protected.public.is_any_host_behind_nat = (bool(*)(ike_sa_t*)) is_any_host_behind_nat; - this->protected.public.get_last_traffic_in_tv = (struct timeval (*)(ike_sa_t*)) get_last_traffic_in_tv; - this->protected.public.get_last_traffic_out_tv = (struct timeval (*)(ike_sa_t*)) get_last_traffic_out_tv; - this->protected.public.send_dpd_request = (status_t (*)(ike_sa_t*)) send_dpd_request; + this->protected.public.delete = (status_t (*) (ike_sa_t*))delete_; + this->protected.public.destroy = (void (*) (ike_sa_t*))destroy; + this->protected.public.is_my_host_behind_nat = (bool (*) (ike_sa_t*)) is_my_host_behind_nat; + this->protected.public.is_other_host_behind_nat = (bool (*) (ike_sa_t*)) is_other_host_behind_nat; + this->protected.public.is_any_host_behind_nat = (bool (*) (ike_sa_t*)) is_any_host_behind_nat; + this->protected.public.get_last_traffic_in_tv = (struct timeval (*) (ike_sa_t*)) get_last_traffic_in_tv; + this->protected.public.get_last_traffic_out_tv = (struct timeval (*) (ike_sa_t*)) get_last_traffic_out_tv; + this->protected.public.send_dpd_request = (status_t (*) (ike_sa_t*)) send_dpd_request; /* protected functions */ - this->protected.build_message = (void (*) (protected_ike_sa_t *, exchange_type_t,bool,message_t**)) build_message; - this->protected.get_prf = (prf_t *(*) (protected_ike_sa_t *)) get_prf; - this->protected.get_child_prf = (prf_t *(*) (protected_ike_sa_t *)) get_child_prf; - this->protected.get_prf_auth_i = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_i; - this->protected.get_prf_auth_r = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_r; + this->protected.build_message = (void (*) (protected_ike_sa_t*,exchange_type_t,bool,message_t**)) build_message; + this->protected.get_prf = (prf_t *(*) (protected_ike_sa_t*)) get_prf; + this->protected.get_child_prf = (prf_t* (*) (protected_ike_sa_t*)) get_child_prf; + this->protected.get_prf_auth_i = (prf_t* (*) (protected_ike_sa_t*)) get_prf_auth_i; + this->protected.get_prf_auth_r = (prf_t* (*) (protected_ike_sa_t*)) get_prf_auth_r; this->protected.add_child_sa = (void (*) (protected_ike_sa_t*,child_sa_t*)) add_child_sa; - this->protected.set_connection = (void (*) (protected_ike_sa_t *,connection_t *)) set_connection; - this->protected.get_connection = (connection_t *(*) (protected_ike_sa_t *)) get_connection; - this->protected.set_policy = (void (*) (protected_ike_sa_t *,policy_t *)) set_policy; - this->protected.get_policy = (policy_t *(*) (protected_ike_sa_t *)) get_policy; - this->protected.get_randomizer = (randomizer_t *(*) (protected_ike_sa_t *)) get_randomizer; - this->protected.send_request = (status_t (*) (protected_ike_sa_t *,message_t *)) send_request; - this->protected.send_response = (status_t (*) (protected_ike_sa_t *,message_t *)) send_response; - this->protected.send_notify = (void (*)(protected_ike_sa_t*,exchange_type_t,notify_message_type_t,chunk_t)) send_notify; - this->protected.build_transforms = (status_t (*) (protected_ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t)) build_transforms; - this->protected.set_new_state = (void (*) (protected_ike_sa_t *,state_t *)) set_new_state; - this->protected.get_crypter_initiator = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_initiator; - this->protected.get_signer_initiator = (signer_t *(*) (protected_ike_sa_t *)) get_signer_initiator; - this->protected.get_crypter_responder = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_responder; - this->protected.get_signer_responder = (signer_t *(*) (protected_ike_sa_t *)) get_signer_responder; - this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t *)) reset_message_buffers; - this->protected.get_last_responded_message = (message_t * (*) (protected_ike_sa_t *)) get_last_responded_message; - this->protected.get_last_requested_message = (message_t * (*) (protected_ike_sa_t *)) get_last_requested_message; - this->protected.set_last_replied_message_id = (void (*) (protected_ike_sa_t *,u_int32_t)) set_last_replied_message_id; - this->protected.destroy_child_sa = (u_int32_t (*)(protected_ike_sa_t*,u_int32_t))destroy_child_sa; - this->protected.get_child_sa = (child_sa_t* (*)(protected_ike_sa_t*,u_int32_t))get_child_sa_by_spi; - this->protected.set_my_host_behind_nat = (void(*)(protected_ike_sa_t*, bool)) set_my_host_behind_nat; - this->protected.set_other_host_behind_nat = (void(*)(protected_ike_sa_t*, bool)) set_other_host_behind_nat; - this->protected.generate_natd_hash = (chunk_t (*) (protected_ike_sa_t *, u_int64_t, u_int64_t, host_t*)) generate_natd_hash; + this->protected.establish = (void (*) (protected_ike_sa_t*)) establish; + this->protected.set_connection = (void (*) (protected_ike_sa_t*,connection_t*)) set_connection; + this->protected.get_connection = (connection_t* (*) (protected_ike_sa_t*)) get_connection; + this->protected.set_policy = (void (*) (protected_ike_sa_t *,policy_t*)) set_policy; + this->protected.get_policy = (policy_t* (*) (protected_ike_sa_t*)) get_policy; + this->protected.get_randomizer = (randomizer_t* (*) (protected_ike_sa_t*)) get_randomizer; + this->protected.send_request = (status_t (*) (protected_ike_sa_t*,message_t*)) send_request; + this->protected.send_response = (status_t (*) (protected_ike_sa_t*,message_t*)) send_response; + this->protected.send_notify = (void (*) (protected_ike_sa_t*,exchange_type_t,notify_message_type_t,chunk_t)) send_notify; + this->protected.build_transforms = (status_t (*) (protected_ike_sa_t*,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t)) build_transforms; + this->protected.set_new_state = (void (*) (protected_ike_sa_t*,state_t*)) set_new_state; + this->protected.get_crypter_initiator = (crypter_t* (*) (protected_ike_sa_t*)) get_crypter_initiator; + this->protected.get_signer_initiator = (signer_t* (*) (protected_ike_sa_t*)) get_signer_initiator; + this->protected.get_crypter_responder = (crypter_t* (*) (protected_ike_sa_t*)) get_crypter_responder; + this->protected.get_signer_responder = (signer_t* (*) (protected_ike_sa_t*)) get_signer_responder; + this->protected.reset_message_buffers = (void (*) (protected_ike_sa_t*)) reset_message_buffers; + this->protected.get_last_responded_message = (message_t* (*) (protected_ike_sa_t*)) get_last_responded_message; + this->protected.get_last_requested_message = (message_t* (*) (protected_ike_sa_t*)) get_last_requested_message; + this->protected.set_last_replied_message_id = (void (*) (protected_ike_sa_t*,u_int32_t)) set_last_replied_message_id; + this->protected.destroy_child_sa = (u_int32_t (*) (protected_ike_sa_t*,u_int32_t))destroy_child_sa; + this->protected.get_child_sa = (child_sa_t* (*) (protected_ike_sa_t*,u_int32_t))get_child_sa_by_spi; + this->protected.set_my_host_behind_nat = (void (*) (protected_ike_sa_t*,bool)) set_my_host_behind_nat; + this->protected.set_other_host_behind_nat = (void (*) (protected_ike_sa_t*,bool)) set_other_host_behind_nat; + this->protected.generate_natd_hash = (chunk_t (*) (protected_ike_sa_t*,u_int64_t, u_int64_t, host_t*)) generate_natd_hash; this->protected.get_last_dpd_message_id = (u_int32_t (*) (protected_ike_sa_t*)) get_last_dpd_message_id; - this->protected.update_connection_hosts = (status_t (*) (protected_ike_sa_t *, host_t*, host_t*)) update_connection_hosts; + this->protected.update_connection_hosts = (status_t (*) (protected_ike_sa_t*,host_t*,host_t*)) update_connection_hosts; /* private functions */ this->update_timestamp = (void (*) (private_ike_sa_t*,bool))update_timestamp; - this->get_last_esp_traffic_tv = (struct timeval (*) (private_ike_sa_t *,bool))get_last_esp_traffic_tv; + this->get_last_esp_traffic_tv = (struct timeval (*) (private_ike_sa_t*,bool))get_last_esp_traffic_tv; /* initialize private fields */ this->logger = logger_manager->get_logger(logger_manager, IKE_SA); @@ -1671,7 +1695,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) this->prf = NULL; this->prf_auth_i = NULL; this->prf_auth_r = NULL; - this->child_prf = NULL; + this->child_prf = NULL; this->connection = NULL; this->policy = NULL; this->nat_hasher = hasher_create(HASH_SHA1); @@ -1686,12 +1710,12 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id) /* at creation time, IKE_SA is in a initiator state */ if (ike_sa_id->is_initiator(ike_sa_id)) { - this->logger->log(this->logger, CONTROL | LEVEL2, "Create first state_t object of type INITIATOR_INIT"); + this->logger->log(this->logger, CONTROL | LEVEL2, "create first state_t object of type INITIATOR_INIT"); this->current_state = (state_t *) initiator_init_create(&(this->protected)); } else { - this->logger->log(this->logger, CONTROL | LEVEL2, "Create first state_t object of type RESPONDER_INIT"); + this->logger->log(this->logger, CONTROL | LEVEL2, "create first state_t object of type RESPONDER_INIT"); this->current_state = (state_t *) responder_init_create(&(this->protected)); } return &(this->protected.public); diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index 719aa94b0..06a5930e4 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -539,7 +539,14 @@ struct protected_ike_sa_t { * @return child_sa, or NULL if none found */ child_sa_t* (*get_child_sa) (protected_ike_sa_t *this, u_int32_t spi); - + + /** + * @brief establish the IKE SA + * + * @param this calling object + */ + void (*establish) (protected_ike_sa_t *this); + /** * @brief Get the last responded message. * diff --git a/src/charon/sa/states/ike_auth_requested.c b/src/charon/sa/states/ike_auth_requested.c index e7797d5ea..b2d42fd60 100644 --- a/src/charon/sa/states/ike_auth_requested.c +++ b/src/charon/sa/states/ike_auth_requested.c @@ -29,6 +29,7 @@ #include <encoding/payloads/ts_payload.h> #include <encoding/payloads/sa_payload.h> #include <encoding/payloads/id_payload.h> +#include <encoding/payloads/cert_payload.h> #include <encoding/payloads/auth_payload.h> #include <encoding/payloads/notify_payload.h> #include <crypto/signers/signer.h> @@ -113,6 +114,17 @@ struct private_ike_auth_requested_t { status_t (*process_idr_payload) (private_ike_auth_requested_t *this, id_payload_t *idr_payload); /** + * Process received CERT payload + * + * @param this calling object + * @param cert_payload payload to process + * @return + * - DESTROY_ME if IKE_SA should be deleted + * - SUCCSS if processed successful + */ + status_t (*process_cert_payload) (private_ike_auth_requested_t *this, cert_payload_t *cert_payload); + + /** * Process the SA payload (check if selected proposals are valid, setup child sa) * * @param this calling object @@ -176,8 +188,10 @@ struct private_ike_auth_requested_t { */ static status_t process_message(private_ike_auth_requested_t *this, message_t *ike_auth_reply) { - ts_payload_t *tsi_payload = NULL, *tsr_payload = NULL; + ts_payload_t *tsi_payload = NULL; + ts_payload_t *tsr_payload = NULL; id_payload_t *idr_payload = NULL; + cert_payload_t *cert_payload = NULL; auth_payload_t *auth_payload = NULL; sa_payload_t *sa_payload = NULL; iterator_t *payloads = NULL; @@ -193,7 +207,7 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i if (ike_auth_reply->get_exchange_type(ike_auth_reply) != IKE_AUTH) { - this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_auth_requested", + this->logger->log(this->logger, ERROR | LEVEL1, "message of type %s not supported in state ike_auth_requested", mapping_find(exchange_type_m,ike_auth_reply->get_exchange_type(ike_auth_reply))); return FAILED; } @@ -230,33 +244,34 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i switch (payload->get_type(payload)) { case AUTHENTICATION: - { auth_payload = (auth_payload_t*)payload; break; - } + case CERTIFICATE: + cert_payload = (cert_payload_t*)payload; + status = this->process_cert_payload(this, cert_payload); + if (status != SUCCESS) + { + payloads->destroy(payloads); + return status; + + } + break; case ID_RESPONDER: - { idr_payload = (id_payload_t*)payload; break; - } case SECURITY_ASSOCIATION: - { sa_payload = (sa_payload_t*)payload; break; - } case TRAFFIC_SELECTOR_INITIATOR: - { tsi_payload = (ts_payload_t*)payload; break; - } case TRAFFIC_SELECTOR_RESPONDER: - { tsr_payload = (ts_payload_t*)payload; break; - } case NOTIFY: { notify_payload_t *notify_payload = (notify_payload_t *) payload; + /* handle the notify directly, abort if no further processing required */ status = this->process_notify_payload(this, notify_payload); if (status != SUCCESS) @@ -265,16 +280,10 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i return status; } } - case CERTIFICATE: - { - /* TODO handle cert payloads */ - } default: - { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)", + this->logger->log(this->logger, ERROR|LEVEL1, "ignoring Payload %s (%d)", mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); break; - } } } /* iterator can be destroyed */ @@ -291,51 +300,43 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i ike_auth_reply->get_destination(ike_auth_reply), ike_auth_reply->get_source(ike_auth_reply)); if (status != SUCCESS) - { return status; - } /* process all payloads */ status = this->process_idr_payload(this, idr_payload); if (status != SUCCESS) - { return status; - } + status = this->process_auth_payload(this, auth_payload,idr_payload); if (status != SUCCESS) - { return status; - } + status = this->process_sa_payload(this, sa_payload); if (status != SUCCESS) - { return status; - } + status = this->process_ts_payload(this, TRUE, tsi_payload); if (status != SUCCESS) - { return status; - } + status = this->process_ts_payload(this, FALSE, tsr_payload); if (status != SUCCESS) - { return status; - } /* install child SAs for AH and esp */ if (!this->child_sa) { - this->logger->log(this->logger, CONTROL, "No CHILD_SA requested, no CHILD_SA built"); + this->logger->log(this->logger, CONTROL, "no CHILD_SA requested, no CHILD_SA built"); } else if (!this->proposal) { - this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built"); + this->logger->log(this->logger, CONTROL, "proposal negotiation failed, no CHILD_SA built"); this->child_sa->destroy(this->child_sa); this->child_sa = NULL; } else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) { - this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built"); + this->logger->log(this->logger, CONTROL, "traffic selector negotiation failed, no CHILD_SA built"); this->child_sa->destroy(this->child_sa); this->child_sa = NULL; } @@ -351,13 +352,13 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i prf_plus->destroy(prf_plus); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "could not install CHILD_SA! Deleting IKE_SA"); return DESTROY_ME; } status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "could not install CHILD_SA policy! Deleting IKE_SA"); return DESTROY_ME; } this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); @@ -366,19 +367,8 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i this->ike_sa->set_last_replied_message_id(this->ike_sa,ike_auth_reply->get_message_id(ike_auth_reply)); /* create new state */ - this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); + this->ike_sa->establish(this->ike_sa); this->destroy_after_state_change(this); - - connection = this->ike_sa->get_connection(this->ike_sa); - my_host = connection->get_my_host(connection); - other_host = connection->get_other_host(connection); - policy = this->ike_sa->get_policy(this->ike_sa); - my_id = policy->get_my_id(policy); - other_id = policy->get_other_id(policy); - this->logger->log(this->logger, AUDIT, "IKE_SA established %s[%s]...%s[%s]", - my_host->get_address(my_host), my_id->get_string(my_id), - other_host->get_address(other_host), other_id->get_string(other_id)); - return SUCCESS; } @@ -408,6 +398,38 @@ static status_t process_idr_payload(private_ike_auth_requested_t *this, id_paylo } /** + * Implements private_ike_auth_requested_t.process_cert_payload + */ +static status_t process_cert_payload(private_ike_auth_requested_t *this, cert_payload_t * cert_payload) +{ + bool found; + x509_t *cert; + + if (cert_payload->get_cert_encoding(cert_payload) != CERT_X509_SIGNATURE) + { + this->logger->log(this->logger, CONTROL, "certificate encoding is %s, ignored", + enum_name(&cert_encoding_names, cert_payload->get_cert_encoding(cert_payload))); + return SUCCESS; + } + cert = x509_create_from_chunk(cert_payload->get_data_clone(cert_payload)); + + if (charon->credentials->verify(charon->credentials, cert, &found)) + { + this->logger->log(this->logger, CONTROL, "end entity certificate is trusted"); + if (!found) + { + cert = charon->credentials->add_end_certificate(charon->credentials, cert); + } + } + else + { + this->logger->log(this->logger, ERROR, "end entity certificate is not trusted"); + } + return SUCCESS; +} + + +/** * Implements private_ike_auth_requested_t.process_sa_payload */ static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payload_t *sa_payload) @@ -472,7 +494,7 @@ static status_t process_auth_payload(private_ike_auth_requested_t *this, auth_pa authenticator->destroy(authenticator); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Verification of IKE_AUTH reply failed. Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "verification of IKE_AUTH reply failed. Deleting IKE_SA"); return DESTROY_ME; } @@ -524,7 +546,7 @@ static status_t process_notify_payload(private_ike_auth_requested_t *this, notif { notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); - this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", + this->logger->log(this->logger, CONTROL|LEVEL1, "process notify type %s", mapping_find(notify_message_type_m, notify_message_type)); switch (notify_message_type) @@ -675,6 +697,7 @@ ike_auth_requested_t *ike_auth_requested_create(protected_ike_sa_t *ike_sa,chunk /* private functions */ this->process_idr_payload = process_idr_payload; + this->process_cert_payload = process_cert_payload; this->process_sa_payload = process_sa_payload; this->process_auth_payload = process_auth_payload; this->process_ts_payload = process_ts_payload; diff --git a/src/charon/sa/states/ike_sa_established.c b/src/charon/sa/states/ike_sa_established.c index 800380680..1a29fbba3 100644 --- a/src/charon/sa/states/ike_sa_established.c +++ b/src/charon/sa/states/ike_sa_established.c @@ -123,7 +123,7 @@ static status_t build_sa_payload(private_ike_sa_established_t *this, sa_payload_ /* get proposals from request, and select one with ours */ policy = this->ike_sa->get_policy(this->ike_sa); proposal_list = request->get_proposals(request); - this->logger->log(this->logger, CONTROL|LEVEL1, "Selecting proposals:"); + this->logger->log(this->logger, CONTROL|LEVEL1, "selecting proposals:"); proposal = policy->select_proposal(policy, proposal_list); /* list is not needed anymore */ while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS) @@ -148,7 +148,7 @@ static status_t build_sa_payload(private_ike_sa_established_t *this, sa_payload_ memcpy(seed.ptr, this->nonce_i.ptr, this->nonce_i.len); memcpy(seed.ptr + this->nonce_i.len, this->nonce_r.ptr, this->nonce_r.len); prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "Rekey seed", seed); + this->logger->log_chunk(this->logger, RAW|LEVEL2, "sekey seed", seed); chunk_free(&seed); chunk_free(&this->nonce_i); chunk_free(&this->nonce_r); @@ -171,7 +171,7 @@ static status_t build_sa_payload(private_ike_sa_established_t *this, sa_payload_ prf_plus->destroy(prf_plus); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA!"); + this->logger->log(this->logger, AUDIT, "sould not install CHILD_SA!"); sa_response->destroy(sa_response); proposal->destroy(proposal); return DESTROY_ME; @@ -322,7 +322,7 @@ static status_t process_create_child_sa(private_ike_sa_established_t *this, mess } default: { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", + this->logger->log(this->logger, ERROR|LEVEL1, "sgnoring payload %s (%d)", mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); break; } @@ -342,11 +342,11 @@ static status_t process_create_child_sa(private_ike_sa_established_t *this, mess { u_int32_t spi = notify->get_spi(notify); this->old_child_sa = this->ike_sa->get_child_sa(this->ike_sa, spi); - this->logger->log(this->logger, CONTROL, "Rekeying CHILD_SA with SPI 0x%x", spi); + this->logger->log(this->logger, CONTROL, "sekeying CHILD_SA with SPI 0x%x", spi); } else { - this->logger->log(this->logger, CONTROL, "Create new CHILD_SA"); + this->logger->log(this->logger, CONTROL, "create new CHILD_SA"); } /* build response */ @@ -382,7 +382,7 @@ static status_t process_create_child_sa(private_ike_sa_established_t *this, mess /* message can now be sent (must not be destroyed) */ if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Unable to send CREATE_CHILD_SA reply. Ignored"); + this->logger->log(this->logger, AUDIT, "unable to send CREATE_CHILD_SA reply. Ignored"); response->destroy(response); return FAILED; } @@ -390,11 +390,11 @@ static status_t process_create_child_sa(private_ike_sa_established_t *this, mess /* install child SA policies */ if (!this->child_sa) { - this->logger->log(this->logger, ERROR, "Proposal negotiation failed, no CHILD_SA built"); + this->logger->log(this->logger, ERROR, "proposal negotiation failed, no CHILD_SA built"); } else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) { - this->logger->log(this->logger, ERROR, "Traffic selector negotiation failed, no CHILD_SA built"); + this->logger->log(this->logger, ERROR, "traffic selector negotiation failed, no CHILD_SA built"); this->child_sa->destroy(this->child_sa); this->child_sa = NULL; } @@ -403,7 +403,7 @@ static status_t process_create_child_sa(private_ike_sa_established_t *this, mess status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy!"); + this->logger->log(this->logger, AUDIT, "could not install CHILD_SA policy!"); } if (this->old_child_sa) { /* mark old child sa as rekeyed */ @@ -443,7 +443,7 @@ static status_t process_informational(private_ike_sa_established_t *this, messag } default: { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)", + this->logger->log(this->logger, ERROR|LEVEL1, "ignoring Payload %s (%d)", mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); break; @@ -489,7 +489,7 @@ static status_t process_informational(private_ike_sa_established_t *this, messag if (this->ike_sa->send_response(this->ike_sa, response) != SUCCESS) { /* something is seriously wrong, kill connection */ - this->logger->log(this->logger, AUDIT, "Unable to send reply. Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "unable to send reply. Deleting IKE_SA"); response->destroy(response); return DESTROY_ME; } @@ -529,7 +529,7 @@ static status_t process_informational_response(private_ike_sa_established_t *thi { default: { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring Payload %s (%d)", + this->logger->log(this->logger, ERROR|LEVEL1, "ignoring Payload %s (%d)", mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); break; @@ -619,7 +619,7 @@ static status_t process_message(private_ike_sa_established_t *this, message_t *m break; default: this->logger->log(this->logger, ERROR | LEVEL1, - "Message of type %s not supported in state ike_sa_established", + "message of type %s not supported in state ike_sa_established", mapping_find(exchange_type_m, message->get_exchange_type(message))); status = NOT_SUPPORTED; } diff --git a/src/charon/sa/states/ike_sa_init_requested.c b/src/charon/sa/states/ike_sa_init_requested.c index 1383ac4c6..1278fdb76 100644 --- a/src/charon/sa/states/ike_sa_init_requested.c +++ b/src/charon/sa/states/ike_sa_init_requested.c @@ -29,6 +29,8 @@ #include <encoding/payloads/nonce_payload.h> #include <encoding/payloads/notify_payload.h> #include <encoding/payloads/id_payload.h> +#include <encoding/payloads/cert_payload.h> +#include <encoding/payloads/certreq_payload.h> #include <encoding/payloads/auth_payload.h> #include <encoding/payloads/ts_payload.h> #include <crypto/diffie_hellman.h> @@ -158,12 +160,34 @@ struct private_ike_sa_init_requested_t { * * @param this calling object * @param[out] id_payload buildet ID payload - * @param response created payload will be added to this message_t object + * @param msg created payload will be added to this message_t object * @return * - SUCCESS * - FAILED */ - status_t (*build_id_payload) (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *response); + status_t (*build_id_payload) (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *msg); + + /** + * Build CERT payload for IKE_AUTH request. + * + * @param this calling object + * @param msg created payload will be added to this message_t object + * @return + * - SUCCESS + * - FAILED + */ + status_t (*build_cert_payload) (private_ike_sa_init_requested_t *this, message_t *msg); + + /** + * Build CERTREQ payload for IKE_AUTH request. + * + * @param this calling object + * @param msg created payload will be added to this message_t object + * @return + * - SUCCESS + * - FAILED + */ + status_t (*build_certreq_payload) (private_ike_sa_init_requested_t *this, message_t *msg); /** * Build IDr payload for IKE_AUTH request. @@ -171,57 +195,57 @@ struct private_ike_sa_init_requested_t { * Only built when the ID of the responder contains no wildcards. * * @param this calling object - * @param response created payload will be added to this message_t object + * @param msg created payload will be added to this message_t object * @return * - SUCCESS * - FAILED */ - status_t (*build_idr_payload) (private_ike_sa_init_requested_t *this, message_t *response); + status_t (*build_idr_payload) (private_ike_sa_init_requested_t *this, message_t *msg); /** * Build AUTH payload for IKE_AUTH request. * * @param this calling object * @param my_id_payload buildet ID payload - * @param response created payload will be added to this message_t object + * @param msg created payload will be added to this message_t object * @return * - SUCCESS * - FAILED */ - status_t (*build_auth_payload) (private_ike_sa_init_requested_t *this,id_payload_t *my_id_payload, message_t *response); + status_t (*build_auth_payload) (private_ike_sa_init_requested_t *this,id_payload_t *my_id_payload, message_t *msg); /** * Build SA payload for IKE_AUTH request. * * @param this calling object - * @param response created payload will be added to this message_t object + * @param msg created payload will be added to this message_t object * @return * - SUCCESS * - FAILED */ - status_t (*build_sa_payload) (private_ike_sa_init_requested_t *this, message_t *response); + status_t (*build_sa_payload) (private_ike_sa_init_requested_t *this, message_t *msg); /** * Build TSi payload for IKE_AUTH request. * * @param this calling object - * @param response created payload will be added to this message_t object + * @param msg created payload will be added to this message_t object * @return * - SUCCESS * - FAILED */ - status_t (*build_tsi_payload) (private_ike_sa_init_requested_t *this, message_t *response); + status_t (*build_tsi_payload) (private_ike_sa_init_requested_t *this, message_t *msg); /** * Build TSr payload for IKE_AUTH request. * * @param this calling object - * @param response created payload will be added to this message_t object + * @param msg created payload will be added to this message_t object * @return * - SUCCESS * - FAILED */ - status_t (*build_tsr_payload) (private_ike_sa_init_requested_t *this, message_t *response); + status_t (*build_tsr_payload) (private_ike_sa_init_requested_t *this, message_t *msg); /** * Process a notify payload and react. @@ -273,7 +297,7 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t if (ike_sa_init_reply->get_exchange_type(ike_sa_init_reply) != IKE_SA_INIT) { - this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_init_requested", + this->logger->log(this->logger, ERROR | LEVEL1, "message of type %s not supported in state ike_sa_init_requested", mapping_find(exchange_type_m,ike_sa_init_reply->get_exchange_type(ike_sa_init_reply))); return FAILED; } @@ -335,20 +359,14 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t switch (payload->get_type(payload)) { case SECURITY_ASSOCIATION: - { sa_payload = (sa_payload_t*)payload; break; - } case KEY_EXCHANGE: - { ke_payload = (ke_payload_t*)payload; break; - } case NONCE: - { nonce_payload = (nonce_payload_t*)payload; break; - } case NOTIFY: { notify_payload_t *notify_payload = (notify_payload_t *) payload; @@ -362,12 +380,9 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t break; } default: - { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", + this->logger->log(this->logger, ERROR|LEVEL1, "ignoring payload %s (%d)", mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); break; - } - } } @@ -381,27 +396,21 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t status = this->process_nonce_payload (this,nonce_payload); if (status != SUCCESS) - { return status; - } status = this->process_sa_payload (this,sa_payload); if (status != SUCCESS) - { return status; - } status = this->process_ke_payload (this,ke_payload); if (status != SUCCESS) - { return status; - } /* derive all the keys used in the IKE_SA */ status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->sent_nonce, this->received_nonce); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "transform objects could not be created from selected proposal. Deleting IKE_SA"); return DESTROY_ME; } @@ -414,16 +423,16 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t } if (this->natd_seen_r > 1) { - this->logger->log(this->logger, AUDIT, "Warning: IKE_SA_INIT request contained multiple Notify(NAT_DETECTION_DESTINATION_IP) payloads."); + this->logger->log(this->logger, AUDIT, "warning: IKE_SA_INIT request contained multiple Notify(NAT_DETECTION_DESTINATION_IP) payloads."); } if (this->natd_seen_i > 0 && !this->natd_hash_i_matched) { - this->logger->log(this->logger, AUDIT, "Remote host is behind NAT, using NAT-T."); + this->logger->log(this->logger, AUDIT, "remote host is behind NAT, using NAT-Traversal"); this->ike_sa->set_other_host_behind_nat(this->ike_sa, TRUE); } if (this->natd_seen_r > 0 && !this->natd_hash_r_matched) { - this->logger->log(this->logger, AUDIT, "Local host is behind NAT, using NAT-T."); + this->logger->log(this->logger, AUDIT, "local host is behind NAT, using NAT-Traversal"); this->ike_sa->set_my_host_behind_nat(this->ike_sa, TRUE); } @@ -438,11 +447,11 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t { me->set_port(me, IKEV2_NATT_PORT); other->set_port(other, IKEV2_NATT_PORT); - this->logger->log(this->logger, AUDIT, "Switching to port %d.", IKEV2_NATT_PORT); + this->logger->log(this->logger, AUDIT, "switching to port %d.", IKEV2_NATT_PORT); } else { - this->logger->log(this->logger, AUDIT, "No NAT detected, not using NAT-T."); + this->logger->log(this->logger, AUDIT, "no NAT detected, not using NAT-Traversal"); } if (this->ike_sa->public.is_my_host_behind_nat(&this->ike_sa->public)) @@ -454,9 +463,7 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t status = this->ike_sa->update_connection_hosts(this->ike_sa, me, other); if (status != SUCCESS) - { return status; - } policy = this->ike_sa->get_policy(this->ike_sa); policy->update_my_ts(policy, me); @@ -467,46 +474,41 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t status = this->build_id_payload(this, &id_payload, request); if (status != SUCCESS) - { - request->destroy(request); - return status; - } + goto destroy_request; + + status = this->build_cert_payload(this, request); + if (status != SUCCESS) + goto destroy_request; + + status = this->build_certreq_payload(this, request); + if (status != SUCCESS) + goto destroy_request; + status = this->build_idr_payload(this, request); if (status != SUCCESS) - { - request->destroy(request); - return status; - } + goto destroy_request; + status = this->build_auth_payload(this, (id_payload_t*)id_payload, request); if (status != SUCCESS) - { - request->destroy(request); - return status; - } + goto destroy_request; + status = this->build_sa_payload(this, request); if (status != SUCCESS) - { - request->destroy(request); - return status; - } + goto destroy_request; + status = this->build_tsi_payload(this, request); if (status != SUCCESS) - { - request->destroy(request); - return status; - } + goto destroy_request; + status = this->build_tsr_payload(this, request); if (status != SUCCESS) - { - request->destroy(request); - return status; - } + goto destroy_request; /* message can now be sent (must not be destroyed) */ status = this->ike_sa->send_request(this->ike_sa, request); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Unable to send IKE_AUTH request. Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "unable to send IKE_AUTH request. Deleting IKE_SA"); request->destroy(request); return DESTROY_ME; } @@ -522,6 +524,11 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t this->destroy_after_state_change(this); return SUCCESS; + +destroy_request: + request->destroy(request); + return status; + } @@ -590,18 +597,18 @@ status_t process_ke_payload (private_ike_sa_init_requested_t *this, ke_payload_t /** * Implementation of private_ike_sa_init_requested_t.build_id_payload. */ -static status_t build_id_payload (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *request) +static status_t build_id_payload (private_ike_sa_init_requested_t *this,id_payload_t **id_payload, message_t *msg) { policy_t *policy; + identification_t *my_id; id_payload_t *new_id_payload; - identification_t *identification; policy = this->ike_sa->get_policy(this->ike_sa); - identification = policy->get_my_id(policy); - new_id_payload = id_payload_create_from_identification(TRUE, identification); + my_id = policy->get_my_id(policy); + new_id_payload = id_payload_create_from_identification(TRUE, my_id); - this->logger->log(this->logger, CONTROL|LEVEL2, "Add ID payload to message"); - request->add_payload(request,(payload_t *) new_id_payload); + this->logger->log(this->logger, CONTROL|LEVEL2, "add ID payload to message"); + msg->add_payload(msg, (payload_t *) new_id_payload); *id_payload = new_id_payload; @@ -609,22 +616,64 @@ static status_t build_id_payload (private_ike_sa_init_requested_t *this,id_paylo } /** + * Implementation of private_ike_sa_init_requested_t.build_cert_payload. + */ +static status_t build_cert_payload (private_ike_sa_init_requested_t *this, message_t *msg) +{ + connection_t *connection = this->ike_sa->get_connection(this->ike_sa); + + if (connection->get_cert_policy(connection) != CERT_NEVER_SEND) + { + policy_t *policy; + identification_t *my_id; + x509_t *cert; + cert_payload_t *cert_payload; + + policy = this->ike_sa->get_policy(this->ike_sa); + my_id = policy->get_my_id(policy); + + cert = charon->credentials->get_certificate(charon->credentials, my_id); + if (cert == NULL) + { + this->logger->log(this->logger, ERROR, "could not find my certificate"); + return NOT_FOUND; + } + cert_payload = cert_payload_create_from_x509(cert); + this->logger->log(this->logger, CONTROL|LEVEL2, "add CERT payload to message"); + msg->add_payload(msg, (payload_t *) cert_payload); + } + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_requested_t.build_certreq_payload. + */ +static status_t build_certreq_payload (private_ike_sa_init_requested_t *this, message_t *msg) +{ + if (FALSE) + { + certreq_payload_t *certreq_payload; + + this->logger->log(this->logger, CONTROL|LEVEL2, "add CERTREQ payload to message"); + msg->add_payload(msg, (payload_t *) certreq_payload); + } + return SUCCESS; +} + +/** * Implementation of private_ike_sa_init_requested_t.build_idr_payload. */ -static status_t build_idr_payload (private_ike_sa_init_requested_t *this, message_t *request) +static status_t build_idr_payload (private_ike_sa_init_requested_t *this, message_t *msg) { - policy_t *policy; - id_payload_t *idr_payload; - identification_t *identification; - - policy = this->ike_sa->get_policy(this->ike_sa); - identification = policy->get_other_id(policy); + policy_t *policy = this->ike_sa->get_policy(this->ike_sa); + identification_t *identification = policy->get_other_id(policy); + if (!identification->contains_wildcards(identification)) { - idr_payload = id_payload_create_from_identification(FALSE, identification); + id_payload_t *idr_payload = id_payload_create_from_identification(FALSE, identification); - this->logger->log(this->logger, CONTROL|LEVEL2, "Add IDr payload to message"); - request->add_payload(request,(payload_t *) idr_payload); + this->logger->log(this->logger, CONTROL|LEVEL2, "add IDr payload to message"); + msg->add_payload(msg, (payload_t *) idr_payload); } return SUCCESS; } @@ -632,7 +681,7 @@ static status_t build_idr_payload (private_ike_sa_init_requested_t *this, messag /** * Implementation of private_ike_sa_init_requested_t.build_auth_payload. */ -static status_t build_auth_payload (private_ike_sa_init_requested_t *this, id_payload_t *my_id_payload, message_t *request) +static status_t build_auth_payload (private_ike_sa_init_requested_t *this, id_payload_t *my_id_payload, message_t *msg) { authenticator_t *authenticator; auth_payload_t *auth_payload; @@ -644,12 +693,12 @@ static status_t build_auth_payload (private_ike_sa_init_requested_t *this, id_pa if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Could not generate AUTH data for IKE_AUTH request. Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "could not generate AUTH data for IKE_AUTH request. Deleting IKE_SA"); return DESTROY_ME; } - this->logger->log(this->logger, CONTROL|LEVEL2, "Add AUTH payload to message"); - request->add_payload(request,(payload_t *) auth_payload); + this->logger->log(this->logger, CONTROL|LEVEL2, "add AUTH payload to message"); + msg->add_payload(msg, (payload_t *) auth_payload); return SUCCESS; } @@ -657,7 +706,7 @@ static status_t build_auth_payload (private_ike_sa_init_requested_t *this, id_pa /** * Implementation of private_ike_sa_init_requested_t.build_sa_payload. */ -static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message_t *request) +static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message_t *msg) { linked_list_t *proposal_list; sa_payload_t *sa_payload; @@ -677,14 +726,14 @@ static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message this->ike_sa->public.is_any_host_behind_nat(&this->ike_sa->public)); if (this->child_sa->alloc(this->child_sa, proposal_list) != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "could not install CHILD_SA! Deleting IKE_SA"); return DESTROY_ME; } sa_payload = sa_payload_create_from_proposal_list(proposal_list); - this->logger->log(this->logger, CONTROL|LEVEL2, "Add SA payload to message"); - request->add_payload(request,(payload_t *) sa_payload); + this->logger->log(this->logger, CONTROL|LEVEL2, "add SA payload to message"); + msg->add_payload(msg, (payload_t *) sa_payload); return SUCCESS; } @@ -692,18 +741,14 @@ static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message /** * Implementation of private_ike_sa_init_requested_t.build_tsi_payload. */ -static status_t build_tsi_payload (private_ike_sa_init_requested_t *this, message_t *request) +static status_t build_tsi_payload (private_ike_sa_init_requested_t *this, message_t *msg) { - linked_list_t *ts_list; - ts_payload_t *ts_payload; - policy_t *policy; - - policy = this->ike_sa->get_policy(this->ike_sa); - ts_list = policy->get_my_traffic_selectors(policy); - ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list); + policy_t *policy = this->ike_sa->get_policy(this->ike_sa); + linked_list_t *ts_list = policy->get_my_traffic_selectors(policy); + ts_payload_t *ts_payload = ts_payload_create_from_traffic_selectors(TRUE, ts_list); - this->logger->log(this->logger, CONTROL|LEVEL2, "Add TSi payload to message"); - request->add_payload(request,(payload_t *) ts_payload); + this->logger->log(this->logger, CONTROL|LEVEL2, "add TSi payload to message"); + msg->add_payload(msg, (payload_t *) ts_payload); return SUCCESS; } @@ -711,18 +756,14 @@ static status_t build_tsi_payload (private_ike_sa_init_requested_t *this, messag /** * Implementation of private_ike_sa_init_requested_t.build_tsr_payload. */ -static status_t build_tsr_payload (private_ike_sa_init_requested_t *this, message_t *request) +static status_t build_tsr_payload (private_ike_sa_init_requested_t *this, message_t *msg) { - linked_list_t *ts_list; - ts_payload_t *ts_payload; - policy_t *policy; - - policy = this->ike_sa->get_policy(this->ike_sa); - ts_list = policy->get_other_traffic_selectors(policy); - ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list); + policy_t *policy = this->ike_sa->get_policy(this->ike_sa); + linked_list_t *ts_list = policy->get_other_traffic_selectors(policy); + ts_payload_t *ts_payload = ts_payload_create_from_traffic_selectors(FALSE, ts_list); - this->logger->log(this->logger, CONTROL|LEVEL2, "Add TSr payload to message"); - request->add_payload(request,(payload_t *) ts_payload); + this->logger->log(this->logger, CONTROL|LEVEL2, "add TSr payload to message"); + msg->add_payload(msg, (payload_t *) ts_payload); return SUCCESS; } @@ -735,7 +776,7 @@ static status_t process_notify_payload(private_ike_sa_init_requested_t *this, no chunk_t notification_data; notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); - this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", + this->logger->log(this->logger, CONTROL|LEVEL1, "process notify type %s", mapping_find(notify_message_type_m, notify_message_type)); switch (notify_message_type) @@ -768,20 +809,20 @@ static status_t process_notify_payload(private_ike_sa_init_requested_t *this, no * is cancelled... */ - this->logger->log(this->logger, AUDIT, "Peer didn't accept %s, it requested %s!", + this->logger->log(this->logger, AUDIT, "peer didn't accept %s, it requested %s!", mapping_find(diffie_hellman_group_m, old_dh_group), mapping_find(diffie_hellman_group_m, dh_group)); /* check if we can accept this dh group */ if (!connection->check_dh_group(connection, dh_group)) { this->logger->log(this->logger, AUDIT, - "Peer does only accept DH group %s, which we do not accept! Aborting", + "peer does only accept DH group %s, which we do not accept! Aborting", mapping_find(diffie_hellman_group_m, dh_group)); return DESTROY_ME; } /* Going to change state back to initiator_init_t */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object"); + this->logger->log(this->logger, CONTROL|LEVEL2, "create next state object"); initiator_init_state = initiator_init_create(this->ike_sa); /* buffer of sent and received messages has to get reseted */ @@ -791,8 +832,8 @@ static status_t process_notify_payload(private_ike_sa_init_requested_t *this, no this->ike_sa->set_new_state(this->ike_sa,(state_t *) initiator_init_state); /* state has NOW changed :-) */ - this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy old sate object"); - this->logger->log(this->logger, CONTROL|LEVEL2, "Going to retry initialization of connection"); + this->logger->log(this->logger, CONTROL|LEVEL2, "destroy old sate object"); + this->logger->log(this->logger, CONTROL|LEVEL2, "going to retry initialization of connection"); this->public.state_interface.destroy(&(this->public.state_interface)); if (initiator_init_state->retry_initiate_connection (initiator_init_state, dh_group) != SUCCESS) @@ -925,6 +966,8 @@ ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa this->build_tsr_payload = build_tsr_payload; this->build_id_payload = build_id_payload; this->build_idr_payload = build_idr_payload; + this->build_cert_payload = build_cert_payload; + this->build_certreq_payload = build_certreq_payload; this->build_sa_payload = build_sa_payload; this->process_notify_payload = process_notify_payload; diff --git a/src/charon/sa/states/ike_sa_init_responded.c b/src/charon/sa/states/ike_sa_init_responded.c index d8f380552..860a53f7b 100644 --- a/src/charon/sa/states/ike_sa_init_responded.c +++ b/src/charon/sa/states/ike_sa_init_responded.c @@ -31,6 +31,7 @@ #include <encoding/payloads/ts_payload.h> #include <encoding/payloads/sa_payload.h> #include <encoding/payloads/id_payload.h> +#include <encoding/payloads/cert_payload.h> #include <encoding/payloads/auth_payload.h> #include <encoding/payloads/notify_payload.h> #include <crypto/signers/signer.h> @@ -108,23 +109,22 @@ struct private_ike_sa_init_responded_t { * @param this calling object * @param request_idi ID payload representing initiator * @param request_idr ID payload representing responder (May be zero) - * @param response The created IDr payload is added to this message_t object + * @param msg The created IDr payload is added to this message_t object * @param response_idr The created IDr payload is also written to this location */ status_t (*build_idr_payload) (private_ike_sa_init_responded_t *this, id_payload_t *request_idi, id_payload_t *request_idr, - message_t *response, + message_t *msg, id_payload_t **response_idr); /** - * Process received SA payload and build SA payload for IKE_AUTH response. + * Build CERT payload for IKE_AUTH response. * * @param this calling object - * @param request SA payload received in IKE_AUTH request - * @param response The created SA payload is added to this message_t object + * @param msg The created CERT payload is added to this message_t object */ - status_t (*build_sa_payload) (private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response); + status_t (*build_cert_payload) (private_ike_sa_init_responded_t *this, message_t *msg); /** * Process received AUTH payload and build AUTH payload for IKE_AUTH response. @@ -133,19 +133,39 @@ struct private_ike_sa_init_responded_t { * @param request AUTH payload received in IKE_AUTH request * @param other_id_payload other ID payload needed to verify AUTH data * @param my_id_payload my ID payload needed to compute AUTH data - * @param response The created AUTH payload is added to this message_t object + * @param msg The created AUTH payload is added to this message_t object */ - status_t (*build_auth_payload) (private_ike_sa_init_responded_t *this, auth_payload_t *request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* response); + status_t (*build_auth_payload) (private_ike_sa_init_responded_t *this, auth_payload_t *request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* msg); /** + * Process received SA payload and build SA payload for IKE_AUTH response. + * + * @param this calling object + * @param request SA payload received in IKE_AUTH request + * @param msg The created SA payload is added to this message_t object + */ + status_t (*build_sa_payload) (private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *msg); + + /** * Process received TS payload and build TS payload for IKE_AUTH response. * * @param this calling object * @param is_initiator type of TS payload. TRUE for TSi, FALSE for TSr * @param request TS payload received in IKE_AUTH request - * @param response the created TS payload is added to this message_t object + * @param msg the created TS payload is added to this message_t object */ - status_t (*build_ts_payload) (private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t *response); + status_t (*build_ts_payload) (private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t *msg); + + /** + * Process received CERT payload + * + * @param this calling object + * @param cert_payload payload to process + * @return + * - DESTROY_ME if IKE_SA should be deleted + * - SUCCSS if processed successful + */ + status_t (*process_cert_payload) (private_ike_sa_init_responded_t *this, cert_payload_t *cert_payload); /** * Sends a IKE_AUTH reply containing a notify payload. @@ -154,7 +174,7 @@ struct private_ike_sa_init_responded_t { * @param notify_payload payload to process * @return * - DESTROY_ME if IKE_SA should be deleted - * - SUCCSS if processed successfull + * - SUCCSS if processed successful */ status_t (*process_notify_payload) (private_ike_sa_init_responded_t *this, notify_payload_t* notify_payload); @@ -170,14 +190,18 @@ struct private_ike_sa_init_responded_t { }; /** - * Implements state_t.get_state + * Implements state_t.process_message */ static status_t process_message(private_ike_sa_init_responded_t *this, message_t *request) { - id_payload_t *idi_request = NULL, *idr_request = NULL,*idr_response; - ts_payload_t *tsi_request = NULL, *tsr_request = NULL; + id_payload_t *idi_request = NULL; + id_payload_t *idr_request = NULL; + id_payload_t *idr_response; + ts_payload_t *tsi_request = NULL; + ts_payload_t *tsr_request = NULL; auth_payload_t *auth_request = NULL; sa_payload_t *sa_request = NULL; + cert_payload_t *cert_request = NULL; iterator_t *payloads; message_t *response; crypter_t *crypter; @@ -190,7 +214,7 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t if (request->get_exchange_type(request) != IKE_AUTH) { - this->logger->log(this->logger, ERROR | LEVEL1, "Message of type %s not supported in state ike_sa_init_responded", + this->logger->log(this->logger, ERROR | LEVEL1, "message of type %s not supported in state ike_sa_init_respondd", mapping_find(exchange_type_m,request->get_exchange_type(request))); return FAILED; } @@ -232,35 +256,32 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t switch (payload->get_type(payload)) { case ID_INITIATOR: - { idi_request = (id_payload_t*)payload; break; - } + case CERTIFICATE: + cert_request = (cert_payload_t*)payload; + status = this->process_cert_payload(this, cert_request); + if (status != SUCCESS) + { + payloads->destroy(payloads); + return status; + } + break; case AUTHENTICATION: - { auth_request = (auth_payload_t*)payload; break; - } case ID_RESPONDER: - { idr_request = (id_payload_t*)payload; break; - } case SECURITY_ASSOCIATION: - { sa_request = (sa_payload_t*)payload; break; - } case TRAFFIC_SELECTOR_INITIATOR: - { tsi_request = (ts_payload_t*)payload; break; - } case TRAFFIC_SELECTOR_RESPONDER: - { tsr_request = (ts_payload_t*)payload; break; - } case NOTIFY: { notify_payload_t *notify_payload = (notify_payload_t *) payload; @@ -271,20 +292,14 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t return status; } } - case CERTIFICATE: - { - /* TODO handle cert payloads */ - } case CERTIFICATE_REQUEST: { /* TODO handle certrequest payloads */ } default: - { - this->logger->log(this->logger, ERROR|LEVEL1, "Ignoring payload %s (%d)", + this->logger->log(this->logger, ERROR|LEVEL1, "ignoring payload %s (%d)", mapping_find(payload_type_m, payload->get_type(payload)), payload->get_type(payload)); break; - } } } /* iterator can be destroyed */ @@ -300,9 +315,7 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t status = this->ike_sa->update_connection_hosts(this->ike_sa, request->get_destination(request), request->get_source(request)); if (status != SUCCESS) - { return status; - } /* build response */ this->ike_sa->build_message(this->ike_sa, IKE_AUTH, FALSE, &response); @@ -310,40 +323,34 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t /* add payloads to it */ status = this->build_idr_payload(this, idi_request, idr_request, response, &idr_response); if (status != SUCCESS) - { - response->destroy(response); - return status; - } + goto destroy_response; + + status = this->build_cert_payload(this, response); + if (status != SUCCESS) + goto destroy_response; + status = this->build_auth_payload(this, auth_request,idi_request, idr_response,response); if (status != SUCCESS) - { - response->destroy(response); - return status; - } + goto destroy_response; + status = this->build_sa_payload(this, sa_request, response); if (status != SUCCESS) - { - response->destroy(response); - return status; - } + goto destroy_response; + status = this->build_ts_payload(this, TRUE, tsi_request, response); if (status != SUCCESS) - { - response->destroy(response); - return status; - } + goto destroy_response; + status = this->build_ts_payload(this, FALSE, tsr_request, response); if (status != SUCCESS) - { - response->destroy(response); - return status; - } + goto destroy_response; status = this->ike_sa->send_response(this->ike_sa, response); /* message can now be sent (must not be destroyed) */ + if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Unable to send IKE_AUTH reply. Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "unable to send IKE_AUTH reply. Deleting IKE_SA"); response->destroy(response); return DESTROY_ME; } @@ -351,11 +358,11 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t /* install child SA policies */ if (!this->child_sa) { - this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built"); + this->logger->log(this->logger, CONTROL, "proposal negotiation failed, no CHILD_SA built"); } else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) { - this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built"); + this->logger->log(this->logger, CONTROL, "traffic selector negotiation failed, no CHILD_SA built"); this->child_sa->destroy(this->child_sa); this->child_sa = NULL; } @@ -364,33 +371,27 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "could not install CHILD_SA policy! Deleting IKE_SA"); return DESTROY_ME; } this->ike_sa->add_child_sa(this->ike_sa, this->child_sa); } /* create new state */ - this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); + this->ike_sa->establish(this->ike_sa); this->destroy_after_state_change(this); - - connection = this->ike_sa->get_connection(this->ike_sa); - my_host = connection->get_my_host(connection); - other_host = connection->get_other_host(connection); - policy = this->ike_sa->get_policy(this->ike_sa); - my_id = policy->get_my_id(policy); - other_id = policy->get_other_id(policy); - this->logger->log(this->logger, AUDIT, "IKE_SA established %s[%s]...%s[%s]", - my_host->get_address(my_host), my_id->get_string(my_id), - other_host->get_address(other_host), other_id->get_string(other_id)); - return SUCCESS; + +destroy_response: + response->destroy(response); + return status; + } /** * Implementation of private_ike_sa_init_responded_t.build_idr_payload. */ -static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payload_t *request_idi, id_payload_t *request_idr, message_t *response,id_payload_t **response_idr) +static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payload_t *request_idi, id_payload_t *request_idr, message_t *msg,id_payload_t **response_idr) { identification_t *other_id, *my_id; id_payload_t *idr_response; @@ -410,7 +411,7 @@ static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payl this->policy = charon->policies->get_policy_by_ids(charon->policies, my_id, other_id); if (this->policy == NULL) { - this->logger->log(this->logger, AUDIT, "We don't have a policy for IDs %s - %s. Deleting IKE_SA", + this->logger->log(this->logger, AUDIT, "we don't have a policy for IDs %s - %s. Deleting IKE_SA", my_id->get_string(my_id), other_id->get_string(other_id)); my_id->destroy(my_id); other_id->destroy(other_id); @@ -423,24 +424,86 @@ static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payl my_id = this->policy->get_my_id(this->policy); /* update others traffic selectors with actually used address */ - this->policy->update_my_ts(this->policy, response->get_source(response)); - this->policy->update_other_ts(this->policy, response->get_destination(response)); + this->policy->update_my_ts(this->policy, msg->get_source(msg)); + this->policy->update_other_ts(this->policy, msg->get_destination(msg)); /* set policy in ike_sa for other states */ this->ike_sa->set_policy(this->ike_sa, this->policy); /* build response */ idr_response = id_payload_create_from_identification(FALSE, my_id); - response->add_payload(response, (payload_t*)idr_response); + msg->add_payload(msg, (payload_t*)idr_response); *response_idr = idr_response; return SUCCESS; } /** + * Implementation of private_ike_sa_init_responded_t.build_cert_payload. + */ +static status_t build_cert_payload (private_ike_sa_init_responded_t *this, message_t *msg) +{ + connection_t *connection = this->ike_sa->get_connection(this->ike_sa); + + if (connection->get_cert_policy(connection) != CERT_NEVER_SEND) + { + policy_t *policy; + identification_t *my_id; + x509_t *cert; + cert_payload_t *cert_payload; + + policy = this->ike_sa->get_policy(this->ike_sa); + my_id = policy->get_my_id(policy); + + cert = charon->credentials->get_certificate(charon->credentials, my_id); + if (cert == NULL) + { + this->logger->log(this->logger, ERROR, "could not find my certificate"); + return NOT_FOUND; + } + cert_payload = cert_payload_create_from_x509(cert); + this->logger->log(this->logger, CONTROL|LEVEL2, "add CERT payload to message"); + msg->add_payload(msg, (payload_t *) cert_payload); + } + return SUCCESS; +} + +/** + * Implementation of private_ike_sa_init_responded_t.build_auth_payload. + */ +static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_payload_t *auth_request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* msg) +{ + authenticator_t *authenticator; + auth_payload_t *auth_reply; + status_t status; + + authenticator = authenticator_create(this->ike_sa); + status = authenticator->verify_auth_data(authenticator,auth_request, this->ike_sa_init_request_data,this->sent_nonce,other_id_payload,TRUE); + + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "IKE_AUTH request verification failed. Deleting IKE_SA"); + this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, AUTHENTICATION_FAILED, CHUNK_INITIALIZER); + authenticator->destroy(authenticator); + return DESTROY_ME; + } + + status = authenticator->compute_auth_data(authenticator,&auth_reply, this->ike_sa_init_response_data,this->received_nonce,my_id_payload,FALSE); + authenticator->destroy(authenticator); + if (status != SUCCESS) + { + this->logger->log(this->logger, AUDIT, "unable to build authentication data for IKE_AUTH reply. Deleting IKE_S"); + return DESTROY_ME; + } + + msg->add_payload(msg, (payload_t *)auth_reply); + return SUCCESS; +} + +/** * Implementation of private_ike_sa_init_responded_t.build_sa_payload. */ -static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response) +static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *msg) { proposal_t *proposal, *proposal_tmp; linked_list_t *proposal_list; @@ -457,7 +520,7 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo /* get proposals from request, and select one with ours */ proposal_list = request->get_proposals(request); - this->logger->log(this->logger, CONTROL|LEVEL1, "Selecting proposals:"); + this->logger->log(this->logger, CONTROL|LEVEL1, "selecting proposals:"); proposal = this->policy->select_proposal(this->policy, proposal_list); /* list is not needed anymore */ while (proposal_list->remove_last(proposal_list, (void**)&proposal_tmp) == SUCCESS) @@ -473,7 +536,7 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo "Adding NO_PROPOSAL_CHOSEN notify"); /* add NO_PROPOSAL_CHOSEN and an empty SA payload */ notify = notify_payload_create_from_protocol_and_type(PROTO_IKE, NO_PROPOSAL_CHOSEN); - response->add_payload(response, (payload_t*)notify); + msg->add_payload(msg, (payload_t*) notify); } else { @@ -498,7 +561,7 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo prf_plus->destroy(prf_plus); if (status != SUCCESS) { - this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); + this->logger->log(this->logger, AUDIT, "could not install CHILD_SA! Deleting IKE_SA"); /* TODO: how do we handle this cleanly? */ sa_response->destroy(sa_response); proposal->destroy(proposal); @@ -509,46 +572,14 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo sa_response->add_proposal(sa_response, proposal); proposal->destroy(proposal); } - response->add_payload(response, (payload_t*)sa_response); + msg->add_payload(msg, (payload_t*)sa_response); return SUCCESS; } /** - * Implementation of private_ike_sa_init_responded_t.build_auth_payload. - */ -static status_t build_auth_payload(private_ike_sa_init_responded_t *this, auth_payload_t *auth_request,id_payload_t *other_id_payload,id_payload_t *my_id_payload, message_t* response) -{ - authenticator_t *authenticator; - auth_payload_t *auth_reply; - status_t status; - - authenticator = authenticator_create(this->ike_sa); - status = authenticator->verify_auth_data(authenticator,auth_request, this->ike_sa_init_request_data,this->sent_nonce,other_id_payload,TRUE); - - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "IKE_AUTH request verification failed. Deleting IKE_SA"); - this->ike_sa->send_notify(this->ike_sa, IKE_AUTH, AUTHENTICATION_FAILED, CHUNK_INITIALIZER); - authenticator->destroy(authenticator); - return DESTROY_ME; - } - - status = authenticator->compute_auth_data(authenticator,&auth_reply, this->ike_sa_init_response_data,this->received_nonce,my_id_payload,FALSE); - authenticator->destroy(authenticator); - if (status != SUCCESS) - { - this->logger->log(this->logger, AUDIT, "Unable to build authentication data for IKE_AUTH reply. Deleting IKE_SA"); - return DESTROY_ME; - } - - response->add_payload(response, (payload_t *)auth_reply); - return SUCCESS; -} - -/** * Implementation of private_ike_sa_init_responded_t.build_ts_payload. */ -static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t* response) +static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_initiator, ts_payload_t *request, message_t* msg) { linked_list_t *ts_received, *ts_selected; traffic_selector_t *ts; @@ -570,7 +601,7 @@ static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_ } ts_response = ts_payload_create_from_traffic_selectors(ts_initiator, ts_selected); - response->add_payload(response, (payload_t*)ts_response); + msg->add_payload(msg, (payload_t*) ts_response); /* add notify if traffic selectors do not match */ if (!ts_initiator && @@ -582,7 +613,7 @@ static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_ "Adding TS_UNACCEPTABLE notify"); notify = notify_payload_create_from_protocol_and_type(0, TS_UNACCEPTABLE); - response->add_payload(response, (payload_t*)notify); + msg->add_payload(msg, (payload_t*)notify); } /* cleanup */ @@ -595,11 +626,45 @@ static status_t build_ts_payload(private_ike_sa_init_responded_t *this, bool ts_ return status; } +/** + * Implements private_ike_sa_init_responded_t.process_cert_payload + */ +static status_t process_cert_payload(private_ike_sa_init_responded_t *this, cert_payload_t * cert_payload) +{ + bool found; + x509_t *cert; + + if (cert_payload->get_cert_encoding(cert_payload) != CERT_X509_SIGNATURE) + { + this->logger->log(this->logger, CONTROL, "certificate encoding is %s, ignored", + enum_name(&cert_encoding_names, cert_payload->get_cert_encoding(cert_payload))); + return SUCCESS; + } + cert = x509_create_from_chunk(cert_payload->get_data_clone(cert_payload)); + + if (charon->credentials->verify(charon->credentials, cert, &found)) + { + this->logger->log(this->logger, CONTROL, "end entity certificate is trusted"); + if (!found) + { + cert = charon->credentials->add_end_certificate(charon->credentials, cert); + } + } + else + { + this->logger->log(this->logger, ERROR, "end entity certificate is not trusted"); + } + return SUCCESS; +} + +/** + * Implements private_ike_sa_init_responded_t.process_notify_payload + */ static status_t process_notify_payload(private_ike_sa_init_responded_t *this, notify_payload_t *notify_payload) { notify_message_type_t notify_message_type = notify_payload->get_notify_message_type(notify_payload); - this->logger->log(this->logger, CONTROL|LEVEL1, "Process notify type %s", + this->logger->log(this->logger, CONTROL|LEVEL1, "process notify type %s", mapping_find(notify_message_type_m, notify_message_type)); switch (notify_message_type) @@ -708,9 +773,11 @@ ike_sa_init_responded_t *ike_sa_init_responded_create(protected_ike_sa_t *ike_sa /* private functions */ this->build_idr_payload = build_idr_payload; - this->build_sa_payload = build_sa_payload; + this->build_cert_payload = build_cert_payload; this->build_auth_payload = build_auth_payload; + this->build_sa_payload = build_sa_payload; this->build_ts_payload = build_ts_payload; + this->process_cert_payload = process_cert_payload; this->process_notify_payload = process_notify_payload; this->destroy_after_state_change = destroy_after_state_change; diff --git a/src/charon/sa/states/initiator_init.c b/src/charon/sa/states/initiator_init.c index 503bfef5a..aa86b514b 100644 --- a/src/charon/sa/states/initiator_init.c +++ b/src/charon/sa/states/initiator_init.c @@ -75,43 +75,43 @@ struct private_initiator_init_t { * Builds the SA payload for this state. * * @param this calling object - * @param request message_t object to add the SA payload + * @param msg message_t object to add the SA payload */ - void (*build_sa_payload) (private_initiator_init_t *this, message_t *request); + void (*build_sa_payload) (private_initiator_init_t *this, message_t *msg); /** * Builds the KE payload for this state. * * @param this calling object - * @param request message_t object to add the KE payload + * @param msg message_t object to add the KE payload */ - void (*build_ke_payload) (private_initiator_init_t *this, message_t *request); + void (*build_ke_payload) (private_initiator_init_t *this, message_t *msg); /** * Builds the NONCE payload for this state. * * @param this calling object - * @param request message_t object to add the NONCE payload + * @param msg message_t object to add the NONCE payload */ - status_t (*build_nonce_payload) (private_initiator_init_t *this,message_t *request); + status_t (*build_nonce_payload) (private_initiator_init_t *this,message_t *msg); /** * Builds the NAT-T Notify(NAT_DETECTION_SOURCE_IP) and * Notify(NAT_DETECTION_DESTINATION_IP) payloads for this state. * * @param this calling object - * @param request message_t object to add the Notify payloads + * @param msg message_t object to add the Notify payloads */ - void (*build_natd_payload) (private_initiator_init_t *this, message_t *request, notify_message_type_t type, host_t *host); + void (*build_natd_payload) (private_initiator_init_t *this, message_t *msg, notify_message_type_t type, host_t *host); /** * Builds the NAT-T Notify(NAT_DETECTION_SOURCE_IP) and * Notify(NAT_DETECTION_DESTINATION_IP) payloads for this state. * * @param this calling object - * @param request message_t object to add the Notify payloads + * @param msg message_t object to add the Notify payloads */ - void (*build_natd_payloads) (private_initiator_init_t *this, message_t *request); + void (*build_natd_payloads) (private_initiator_init_t *this, message_t *msg); /** * Destroy function called internally of this class after state change to state @@ -237,7 +237,7 @@ status_t retry_initiate_connection (private_initiator_init_t *this, diffie_hellm /** * Implementation of private_initiator_init_t.build_sa_payload. */ -static void build_sa_payload(private_initiator_init_t *this, message_t *request) +static void build_sa_payload(private_initiator_init_t *this, message_t *msg) { sa_payload_t* sa_payload; linked_list_t *proposal_list; @@ -252,13 +252,13 @@ static void build_sa_payload(private_initiator_init_t *this, message_t *request) sa_payload = sa_payload_create_from_proposal_list(proposal_list); this->logger->log(this->logger, CONTROL|LEVEL2, "add SA payload to message"); - request->add_payload(request, (payload_t *) sa_payload); + msg->add_payload(msg, (payload_t *) sa_payload); } /** * Implementation of private_initiator_init_t.build_ke_payload. */ -static void build_ke_payload(private_initiator_init_t *this, message_t *request) +static void build_ke_payload(private_initiator_init_t *this, message_t *msg) { ke_payload_t *ke_payload; chunk_t key_data; @@ -276,13 +276,13 @@ static void build_ke_payload(private_initiator_init_t *this, message_t *request) chunk_free(&key_data); this->logger->log(this->logger, CONTROL|LEVEL2, "add KE payload to message"); - request->add_payload(request, (payload_t *) ke_payload); + msg->add_payload(msg, (payload_t *) ke_payload); } /** * Implementation of private_initiator_init_t.build_nonce_payload. */ -static status_t build_nonce_payload(private_initiator_init_t *this, message_t *request) +static status_t build_nonce_payload(private_initiator_init_t *this, message_t *msg) { nonce_payload_t *nonce_payload; randomizer_t *randomizer; @@ -306,36 +306,36 @@ static status_t build_nonce_payload(private_initiator_init_t *this, message_t *r nonce_payload->set_nonce(nonce_payload, this->sent_nonce); this->logger->log(this->logger, CONTROL|LEVEL2, "add NONCE payload to message"); - request->add_payload(request, (payload_t *) nonce_payload); + msg->add_payload(msg, (payload_t *) nonce_payload); return SUCCESS; } /** * Implementation of private_initiator_init_t.build_natd_payload. */ -static void build_natd_payload(private_initiator_init_t *this, message_t *request, notify_message_type_t type, host_t *host) +static void build_natd_payload(private_initiator_init_t *this, message_t *msg, notify_message_type_t type, host_t *host) { chunk_t hash; - this->logger->log(this->logger, CONTROL|LEVEL1, "Building Notify(NAT-D) payload"); + this->logger->log(this->logger, CONTROL|LEVEL1, "building Notify(NAT-D) payload"); notify_payload_t *notify_payload; notify_payload = notify_payload_create(); /*notify_payload->set_protocol_id(notify_payload, NULL);*/ /*notify_payload->set_spi(notify_payload, NULL);*/ notify_payload->set_notify_message_type(notify_payload, type); hash = this->ike_sa->generate_natd_hash(this->ike_sa, - request->get_initiator_spi(request), - request->get_responder_spi(request), - host); + msg->get_initiator_spi(msg), + msg->get_responder_spi(msg), + host); notify_payload->set_notification_data(notify_payload, hash); chunk_free(&hash); - this->logger->log(this->logger, CONTROL|LEVEL2, "Add Notify(NAT-D) payload to message"); - request->add_payload(request, (payload_t *) notify_payload); + this->logger->log(this->logger, CONTROL|LEVEL2, "add Notify(NAT-D) payload to message"); + msg->add_payload(msg, (payload_t *) notify_payload); } /** * Implementation of private_initiator_init_t.build_natd_payloads. */ -static void build_natd_payloads(private_initiator_init_t *this, message_t *request) +static void build_natd_payloads(private_initiator_init_t *this, message_t *msg) { connection_t *connection; linked_list_t *hostlist; @@ -348,7 +348,7 @@ static void build_natd_payloads(private_initiator_init_t *this, message_t *reque hostlist = charon->interfaces->get_addresses(charon->interfaces); hostiter = hostlist->create_iterator(hostlist, TRUE); while(hostiter->iterate(hostiter, (void**)&host)) { - this->build_natd_payload(this, request, NAT_DETECTION_SOURCE_IP, + this->build_natd_payload(this, msg, NAT_DETECTION_SOURCE_IP, host); } hostiter->destroy(hostiter); @@ -357,7 +357,7 @@ static void build_natd_payloads(private_initiator_init_t *this, message_t *reque * N(NAT_DETECTION_DESTINATION_IP) */ connection = this->ike_sa->get_connection(this->ike_sa); - this->build_natd_payload(this, request, NAT_DETECTION_DESTINATION_IP, + this->build_natd_payload(this, msg, NAT_DETECTION_DESTINATION_IP, connection->get_other_host(connection)); } diff --git a/src/charon/sa/states/responder_init.c b/src/charon/sa/states/responder_init.c index 5dad9e78e..f9d61f90d 100644 --- a/src/charon/sa/states/responder_init.c +++ b/src/charon/sa/states/responder_init.c @@ -29,6 +29,7 @@ #include <encoding/payloads/sa_payload.h> #include <encoding/payloads/ke_payload.h> #include <encoding/payloads/nonce_payload.h> +#include <encoding/payloads/certreq_payload.h> #include <encoding/payloads/notify_payload.h> #include <crypto/diffie_hellman.h> #include <queues/jobs/send_keepalive_job.h> @@ -128,52 +129,66 @@ struct private_responder_init_t { * * @param this calling object * @param sa_request The received SA payload - * @param response the SA payload is added to this response message_t object. + * @param msg the SA payload is added to this message_t object. * @return * - DESTROY_ME * - SUCCESS */ - status_t (*build_sa_payload) (private_responder_init_t *this,sa_payload_t *sa_request, message_t *response); + status_t (*build_sa_payload) (private_responder_init_t *this,sa_payload_t *sa_request, message_t *msg); /** * Handles received KE payload and builds the KE payload for the response. * - * @param this calling object + * @param this calling object * @param ke_request The received KE payload - * @param response the KE payload is added to this response message_t object. + * @param msg the KE payload is added to this message_t object. + * @return * - DESTROY_ME * - SUCCESS */ - status_t (*build_ke_payload) (private_responder_init_t *this,ke_payload_t *ke_request, message_t *response); + status_t (*build_ke_payload) (private_responder_init_t *this,ke_payload_t *ke_request, message_t *msg); /** * Handles received NONCE payload and builds the NONCE payload for the response. * * @param this calling object * @param nonce_request The received NONCE payload - * @param response the NONCE payload is added to this response message_t object. + * @param msg the NONCE payload is added to this message_t object. + * @return * - DESTROY_ME * - SUCCESS */ - status_t (*build_nonce_payload) (private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *response); + status_t (*build_nonce_payload) (private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *msg); + + /** + * Build CERTREQ payload for the response. + * + * @param this calling object + * @param msg the CERTREQ payload is added to this message_t object + * @return + * - SUCCESS + * - FAILED + */ + status_t (*build_certreq_payload) (private_responder_init_t *this, message_t *msg); + /** * Builds the NAT-T Notify(NAT_DETECTION_SOURCE_IP) and * Notify(NAT_DETECTION_DESTINATION_IP) payloads for this state. * * @param this calling object - * @param request message_t object to add the Notify payloads + * @param msg message_t object to add the Notify payloads */ - void (*build_natd_payload) (private_responder_init_t *this, message_t *request, notify_message_type_t type, host_t *host); + void (*build_natd_payload) (private_responder_init_t *this, message_t *msg, notify_message_type_t type, host_t *host); /** * Builds the NAT-T Notify(NAT_DETECTION_SOURCE_IP) and * Notify(NAT_DETECTION_DESTINATION_IP) payloads for this state. * * @param this calling object - * @param request message_t object to add the Notify payloads + * @param msg message_t object to add the Notify payloads */ - void (*build_natd_payloads) (private_responder_init_t *this, message_t *request); + void (*build_natd_payloads) (private_responder_init_t *this, message_t *msg); /** * Sends a IKE_SA_INIT reply containing a notify payload. @@ -346,16 +361,16 @@ static status_t process_message(private_responder_init_t *this, message_t *messa } if (this->natd_seen_r > 1) { - this->logger->log(this->logger, AUDIT, "Warning: IKE_SA_INIT request contained multiple Notify(NAT_DETECTION_DESTINATION_IP) payloads."); + this->logger->log(this->logger, AUDIT, "warning: IKE_SA_INIT request contained multiple Notify(NAT_DETECTION_DESTINATION_IP) payloads."); } if (this->natd_seen_i > 0 && !this->natd_hash_i_matched) { - this->logger->log(this->logger, AUDIT, "Remote host is behind NAT, using NAT-T."); + this->logger->log(this->logger, AUDIT, "remote host is behind NAT, using NAT-Traversal"); this->ike_sa->set_other_host_behind_nat(this->ike_sa, TRUE); } if (this->natd_seen_r > 0 && !this->natd_hash_r_matched) { - this->logger->log(this->logger, AUDIT, "Local host is behind NAT, using NAT-T."); + this->logger->log(this->logger, AUDIT, "local host is behind NAT, using NAT-Traversal"); this->ike_sa->set_my_host_behind_nat(this->ike_sa, TRUE); charon->event_queue->add_relative(charon->event_queue, (job_t*)send_keepalive_job_create(this->ike_sa->public.get_id((ike_sa_t*)this->ike_sa)), @@ -363,32 +378,27 @@ static status_t process_message(private_responder_init_t *this, message_t *messa } if (!this->ike_sa->public.is_any_host_behind_nat((ike_sa_t*)this->ike_sa)) { - this->logger->log(this->logger, AUDIT, "No NAT detected, not using NAT-T."); + this->logger->log(this->logger, AUDIT, "no NAT detected, not using NAT-Traversal"); } this->ike_sa->build_message(this->ike_sa, IKE_SA_INIT, FALSE, &response); status = this->build_sa_payload(this, sa_request, response); if (status != SUCCESS) - { - response->destroy(response); - return status; - } + goto destroy_response; status = this->build_ke_payload(this, ke_request, response); if (status != SUCCESS) - { - response->destroy(response); - return status; - } + goto destroy_response; status = this->build_nonce_payload(this, nonce_request, response); if (status != SUCCESS) - { - response->destroy(response); - return status; - } - + goto destroy_response; + + status = this->build_certreq_payload(this, response); + if (status != SUCCESS) + goto destroy_response; + /* build Notify(NAT-D) payloads */ this->build_natd_payloads(this, response); @@ -422,14 +432,18 @@ static status_t process_message(private_responder_init_t *this, message_t *messa /* state can now be changed */ this->ike_sa->set_new_state(this->ike_sa, (state_t *) next_state); this->destroy_after_state_change(this); - return SUCCESS; + +destroy_response: + response->destroy(response); + return status; + } /** * Implementation of private_initiator_init_t.build_sa_payload. */ -static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa_request, message_t *response) +static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa_request, message_t *msg) { proposal_t *proposal; linked_list_t *proposal_list; @@ -468,7 +482,7 @@ static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa this->logger->log(this->logger, CONTROL|LEVEL2, "building SA payload"); sa_payload = sa_payload_create_from_proposal(this->proposal); this->logger->log(this->logger, CONTROL|LEVEL2, "add SA payload to message"); - response->add_payload(response,(payload_t *) sa_payload); + msg->add_payload(msg, (payload_t *) sa_payload); return SUCCESS; } @@ -476,7 +490,7 @@ static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa /** * Implementation of private_initiator_init_t.build_ke_payload. */ -static status_t build_ke_payload(private_responder_init_t *this,ke_payload_t *ke_request, message_t *response) +static status_t build_ke_payload(private_responder_init_t *this,ke_payload_t *ke_request, message_t *msg) { diffie_hellman_group_t group; ke_payload_t *ke_payload; @@ -532,7 +546,7 @@ static status_t build_ke_payload(private_responder_init_t *this,ke_payload_t *ke chunk_free(&key_data); this->logger->log(this->logger, CONTROL|LEVEL2, "add KE payload to message"); - response->add_payload(response,(payload_t *) ke_payload); + msg->add_payload(msg, (payload_t *) ke_payload); return SUCCESS; } @@ -540,7 +554,7 @@ static status_t build_ke_payload(private_responder_init_t *this,ke_payload_t *ke /** * Implementation of private_responder_init_t.build_nonce_payload. */ -static status_t build_nonce_payload(private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *response) +static status_t build_nonce_payload(private_responder_init_t *this,nonce_payload_t *nonce_request, message_t *msg) { nonce_payload_t *nonce_payload; randomizer_t *randomizer; @@ -567,43 +581,58 @@ static status_t build_nonce_payload(private_responder_init_t *this,nonce_payload nonce_payload->set_nonce(nonce_payload, this->sent_nonce); this->logger->log(this->logger, CONTROL|LEVEL2, "add NONCE payload to message"); - response->add_payload(response,(payload_t *) nonce_payload); + msg->add_payload(msg, (payload_t *) nonce_payload); return SUCCESS; } /** + * Implementation of private_responder_init_t.build_certreq_payload. + */ +static status_t build_certreq_payload (private_responder_init_t *this, message_t *msg) +{ + if (FALSE) + { + certreq_payload_t *certreq_payload; + + this->logger->log(this->logger, CONTROL|LEVEL2, "add CERTREQ payload to message"); + msg->add_payload(msg, (payload_t *) certreq_payload); + } + return SUCCESS; +} + +/** * Implementation of private_initiator_init_t.build_natd_payload. */ -static void build_natd_payload(private_responder_init_t *this, message_t *request, notify_message_type_t type, host_t *host) +static void build_natd_payload(private_responder_init_t *this, message_t *msg, notify_message_type_t type, host_t *host) { chunk_t hash; - this->logger->log(this->logger, CONTROL|LEVEL1, "Building Notify(NAT-D) payload"); + this->logger->log(this->logger, CONTROL|LEVEL1, "building Notify(NAT-D) payload"); notify_payload_t *notify_payload; notify_payload = notify_payload_create(); /*notify_payload->set_protocol_id(notify_payload, NULL);*/ /*notify_payload->set_spi(notify_payload, NULL);*/ notify_payload->set_notify_message_type(notify_payload, type); hash = this->ike_sa->generate_natd_hash(this->ike_sa, - request->get_initiator_spi(request), - request->get_responder_spi(request), - host); + msg->get_initiator_spi(msg), + msg->get_responder_spi(msg), + host); notify_payload->set_notification_data(notify_payload, hash); chunk_free(&hash); - this->logger->log(this->logger, CONTROL|LEVEL2, "Add Notify(NAT-D) payload to message"); - request->add_payload(request, (payload_t *) notify_payload); + this->logger->log(this->logger, CONTROL|LEVEL2, "add Notify(NAT-D) payload to message"); + msg->add_payload(msg, (payload_t *) notify_payload); } /** * Implementation of private_initiator_init_t.build_natd_payloads. */ -static void build_natd_payloads(private_responder_init_t *this, message_t *request) +static void build_natd_payloads(private_responder_init_t *this, message_t *msg) { connection_t *connection; connection = this->ike_sa->get_connection(this->ike_sa); - this->build_natd_payload(this, request, NAT_DETECTION_SOURCE_IP, + this->build_natd_payload(this, msg, NAT_DETECTION_SOURCE_IP, connection->get_my_host(connection)); - this->build_natd_payload(this, request, NAT_DETECTION_DESTINATION_IP, + this->build_natd_payload(this, msg, NAT_DETECTION_DESTINATION_IP, connection->get_other_host(connection)); } @@ -744,6 +773,7 @@ responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa) this->build_sa_payload = build_sa_payload; this->build_ke_payload = build_ke_payload; this->build_nonce_payload = build_nonce_payload; + this->build_certreq_payload = build_certreq_payload; this->destroy_after_state_change = destroy_after_state_change; this->process_notify_payload = process_notify_payload; this->build_natd_payload = build_natd_payload; diff --git a/src/charon/testing/generator_test.c b/src/charon/testing/generator_test.c index ac2c4cf32..b557b5880 100644 --- a/src/charon/testing/generator_test.c +++ b/src/charon/testing/generator_test.c @@ -996,7 +996,7 @@ void test_generator_with_cert_payload(protected_tester_t *tester) cert.ptr = "123456789012"; cert.len = strlen(cert.ptr); - cert_payload->set_cert_encoding(cert_payload,PGP_CERTIFICATE); + cert_payload->set_cert_encoding(cert_payload, CERT_PGP); cert_payload->set_data(cert_payload,cert); generator->generate_payload(generator,(payload_t *)cert_payload); @@ -1046,7 +1046,7 @@ void test_generator_with_certreq_payload(protected_tester_t *tester) certreq.ptr = "123456789012"; certreq.len = strlen(certreq.ptr); - certreq_payload->set_cert_encoding(certreq_payload,PGP_CERTIFICATE); + certreq_payload->set_cert_encoding(certreq_payload, CERT_PGP); certreq_payload->set_data(certreq_payload,certreq); generator->generate_payload(generator,(payload_t *)certreq_payload); diff --git a/src/charon/testing/parser_test.c b/src/charon/testing/parser_test.c index 87069cda0..66e65479b 100644 --- a/src/charon/testing/parser_test.c +++ b/src/charon/testing/parser_test.c @@ -727,7 +727,7 @@ void test_parser_with_cert_payload(protected_tester_t *tester) return; } result = cert_payload->get_data_clone(cert_payload); - tester->assert_true(tester,(cert_payload->get_cert_encoding(cert_payload) == DNS_SIGNED_KEY), "is DNS_SIGNED_KEY encoding"); + tester->assert_true(tester,(cert_payload->get_cert_encoding(cert_payload) == CERT_DNS_SIGNED_KEY), "is DNS_SIGNED_KEY encoding"); tester->assert_true(tester,(result.len == 12), "parsed data lenght"); tester->assert_false(tester,(memcmp(cert_bytes + 5, result.ptr, result.len)), "parsed data"); cert_payload->destroy(cert_payload); @@ -766,8 +766,8 @@ void test_parser_with_certreq_payload(protected_tester_t *tester) return; } result = certreq_payload->get_data_clone(certreq_payload); - tester->assert_true(tester,(certreq_payload->get_cert_encoding(certreq_payload) == DNS_SIGNED_KEY), "is DNS_SIGNED_KEY encoding"); - tester->assert_true(tester,(result.len == 12), "parsed data lenght"); + tester->assert_true(tester,(certreq_payload->get_cert_encoding(certreq_payload) == CERT_DNS_SIGNED_KEY), "is DNS_SIGNED_KEY encoding"); + tester->assert_true(tester,(result.len == 12), "parsed data length"); tester->assert_false(tester,(memcmp(certreq_bytes + 5, result.ptr, result.len)), "parsed data"); certreq_payload->destroy(certreq_payload); chunk_free(&result); diff --git a/src/charon/testing/rsa_test.c b/src/charon/testing/rsa_test.c index 90baf3f5a..ee0d78259 100644 --- a/src/charon/testing/rsa_test.c +++ b/src/charon/testing/rsa_test.c @@ -177,7 +177,6 @@ void test_rsa(protected_tester_t *tester) // free(signature.ptr); // // private_key->destroy(private_key); -// public_key->destroy(public_key); /* key setting */ private_key = rsa_private_key_create_from_chunk(der_private_key); @@ -220,7 +219,6 @@ void test_rsa(protected_tester_t *tester) free(signature.ptr); certificate->destroy(certificate); - public_key->destroy(public_key); private_key->destroy(private_key); } diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c index 912213b1c..528d490d4 100755 --- a/src/charon/threads/stroke_interface.c +++ b/src/charon/threads/stroke_interface.c @@ -134,9 +134,9 @@ static x509_t* load_end_certificate(const char *filename, identification_t **idp if (cert) { + bool found; identification_t *id = *idp; identification_t *subject = cert->get_subject(cert); - time_t until; err_t ugh = cert->is_valid(cert, NULL); @@ -150,20 +150,6 @@ static x509_t* load_end_certificate(const char *filename, identification_t **idp id = subject; *idp = id->clone(id); } - /* test output */ - if (charon->credentials->verify(charon->credentials, cert, &until)) - { - char buf[TIMETOA_BUF]; - - timetoa(buf, TIMETOA_BUF, &until, TRUE); - logger->log(logger, CONTROL, " end entity certificate is trusted until %s", buf); - cert->set_until(cert, until); - } - else - { - logger->log(logger, ERROR, " end entity certificate is not trusted"); - } - /* end of test output */ return charon->credentials->add_end_certificate(charon->credentials, cert); } return NULL; @@ -196,6 +182,8 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) pop_string(msg, &msg->add_conn.other.cert); pop_string(msg, &msg->add_conn.me.ca); pop_string(msg, &msg->add_conn.other.ca); + pop_string(msg, &msg->add_conn.me.updown); + pop_string(msg, &msg->add_conn.other.updown); pop_string(msg, &msg->add_conn.algorithms.ike); pop_string(msg, &msg->add_conn.algorithms.esp); @@ -236,10 +224,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) else if (!charon->interfaces->is_local_address(charon->interfaces, my_host)) { this->stroke_logger->log(this->stroke_logger, ERROR, "left nor right host is our side, aborting"); - - my_host->destroy(my_host); - other_host->destroy(other_host); - return; + goto destroy_hosts; } my_id = identification_create_from_string(msg->add_conn.me.id ? @@ -247,45 +232,33 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) if (my_id == NULL) { this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.me.id); - my_host->destroy(my_host); - other_host->destroy(other_host); - return; + goto destroy_hosts; } other_id = identification_create_from_string(msg->add_conn.other.id ? msg->add_conn.other.id : msg->add_conn.other.address); if (other_id == NULL) { - my_host->destroy(my_host); - other_host->destroy(other_host); - my_id->destroy(my_id); this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.other.id); - return; + my_id->destroy(my_id); + goto destroy_hosts; } my_subnet = host_create(AF_INET, msg->add_conn.me.subnet ? msg->add_conn.me.subnet : msg->add_conn.me.address, IKE_PORT); if (my_subnet == NULL) { - my_host->destroy(my_host); - other_host->destroy(other_host); - my_id->destroy(my_id); - other_id->destroy(other_id); this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet); - return; + goto destroy_ids; } other_subnet = host_create(AF_INET, msg->add_conn.other.subnet ? msg->add_conn.other.subnet : msg->add_conn.other.address, IKE_PORT); if (other_subnet == NULL) { - my_host->destroy(my_host); - other_host->destroy(other_host); - my_id->destroy(my_id); - other_id->destroy(other_id); - my_subnet->destroy(my_subnet); this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet); - return; + my_subnet->destroy(my_subnet); + goto destroy_ids; } my_ts = traffic_selector_create_from_subnet(my_subnet, msg->add_conn.me.subnet ? @@ -358,23 +331,26 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) } this->logger->log(this->logger, CONTROL|LEVEL1, " my ca: '%s'", my_ca->get_string(my_ca)); this->logger->log(this->logger, CONTROL|LEVEL1, " other ca:'%s'", other_ca->get_string(other_ca)); + this->logger->log(this->logger, CONTROL|LEVEL1, " updown:'%s'", msg->add_conn.me.updown); - connection = connection_create(msg->add_conn.name, msg->add_conn.ikev2, - msg->add_conn.me.sendcert, msg->add_conn.other.sendcert, + connection = connection_create(msg->add_conn.name, + msg->add_conn.ikev2, + msg->add_conn.me.sendcert, + msg->add_conn.other.sendcert, my_host, other_host, - RSA_DIGITAL_SIGNATURE); + RSA_DIGITAL_SIGNATURE + ); + if (msg->add_conn.algorithms.ike) { char *proposal_string; char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1; + if (*strict == '!') - { *strict = '\0'; - } else - { strict = NULL; - } + while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ","))) { proposal = proposal_create_from_string(PROTO_IKE, proposal_string); @@ -411,19 +387,17 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) policy->add_my_traffic_selector(policy, my_ts); policy->add_other_traffic_selector(policy, other_ts); policy->add_authorities(policy, my_ca, other_ca); + policy->add_updown(policy, msg->add_conn.me.updown); if (msg->add_conn.algorithms.esp) { char *proposal_string; char *strict = msg->add_conn.algorithms.esp + strlen(msg->add_conn.algorithms.esp) - 1; + if (*strict == '!') - { *strict = '\0'; - } else - { strict = NULL; - } while ((proposal_string = strsep(&msg->add_conn.algorithms.esp, ","))) { @@ -460,6 +434,17 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) other_id->get_string(other_id)); /* add to global policy list */ charon->policies->add_policy(charon->policies, policy); + return; + + /* mopping up after parsing errors */ + +destroy_ids: + my_id->destroy(my_id); + other_id->destroy(other_id); + +destroy_hosts: + my_host->destroy(my_host); + other_host->destroy(other_host); } /** diff --git a/src/libfreeswan/ipsec_policy.h b/src/libfreeswan/ipsec_policy.h index 90b58ad52..671919e4b 100644 --- a/src/libfreeswan/ipsec_policy.h +++ b/src/libfreeswan/ipsec_policy.h @@ -149,10 +149,10 @@ enum ipsec_id_type { * RFC 2408 ISAKMP, chapter 3.9 */ enum ipsec_cert_type { - CERT_NONE= 0, - CERT_PKCS7_WRAPPED_X509= 1, /* self-signed certificate from disk */ + CERT_NONE= 0, + CERT_PKCS7_WRAPPED_X509= 1, CERT_PGP= 2, - CERT_DNS_SIGNED_KEY= 3, /* KEY RR from DNS */ + CERT_DNS_SIGNED_KEY= 3, CERT_X509_SIGNATURE= 4, CERT_X509_KEY_EXCHANGE= 5, CERT_KERBEROS_TOKENS= 6, @@ -160,7 +160,7 @@ enum ipsec_cert_type { CERT_ARL= 8, CERT_SPKI= 9, CERT_X509_ATTRIBUTE= 10, - CERT_RAW_RSA= 11, /* raw RSA from config file */ + CERT_RAW_RSA_KEY= 11 }; /* a SIG record in ASCII */ diff --git a/src/libstrongswan/crypto/certinfo.c b/src/libstrongswan/crypto/certinfo.c index 7fef2fa4f..a289d6562 100644 --- a/src/libstrongswan/crypto/certinfo.c +++ b/src/libstrongswan/crypto/certinfo.c @@ -70,6 +70,20 @@ struct private_certinfo_t { }; /** + * RFC 2560 OCSP - certificate status + */ +static const char *const cert_status_name[] = { + "good", + "revoked", + "unknown", + "unknown", + "untrusted" + }; + +enum_names cert_status_names = + { CERT_GOOD, CERT_UNTRUSTED, cert_status_name, NULL}; + +/** * RFC 2459 CRL reason codes */ static const char *const crl_reason_name[] = { diff --git a/src/libstrongswan/crypto/certinfo.h b/src/libstrongswan/crypto/certinfo.h index 81707fad8..45090eafc 100644 --- a/src/libstrongswan/crypto/certinfo.h +++ b/src/libstrongswan/crypto/certinfo.h @@ -29,11 +29,14 @@ /** * RFC 2560 OCSP - certificate status */ +extern enum_names cert_status_names; + typedef enum { CERT_GOOD = 0, CERT_REVOKED = 1, CERT_UNKNOWN = 2, - CERT_UNDEFINED = 3 + CERT_UNDEFINED = 3, + CERT_UNTRUSTED = 4 /* private use */ } cert_status_t; /** diff --git a/src/libstrongswan/crypto/x509.c b/src/libstrongswan/crypto/x509.c index c65071c72..2a25ac179 100755 --- a/src/libstrongswan/crypto/x509.c +++ b/src/libstrongswan/crypto/x509.c @@ -79,6 +79,11 @@ struct private_x509_t { time_t until; /** + * Certificate status + */ + cert_status_t status; + + /** * X.509 Certificate in DER format */ chunk_t certificate; @@ -957,11 +962,19 @@ static bool is_issuer(const private_x509_t *this, const private_x509_t *issuer) } /** + * Implements x509_t.get_certificate + */ +static chunk_t get_certificate(const private_x509_t *this) +{ + return this->certificate; +} + +/** * Implements x509_t.get_public_key */ static rsa_public_key_t *get_public_key(const private_x509_t *this) { - return this->public_key->clone(this->public_key); + return this->public_key; } /** @@ -1005,6 +1018,30 @@ static void set_until(private_x509_t *this, time_t until) } /** + * Implements x509_t.get_until + */ +static time_t get_until(const private_x509_t *this) +{ + return this->until; +} + +/** + * Implements x509_t.set_status + */ +static void set_status(private_x509_t *this, cert_status_t status) +{ + this->status = status; +} + +/** + * Implements x509_t.get_status + */ +static cert_status_t get_status(const private_x509_t *this) +{ + return this->status; +} + +/** * Implements x509_t.verify */ static bool verify(const private_x509_t *this, const rsa_public_key_t *signer) @@ -1096,30 +1133,46 @@ static void log_certificate(const private_x509_t *this, logger_t *logger, bool u rsa_public_key_t *pubkey = this->public_key; char buf[BUF_LEN]; + char time_buf[TIMETOA_BUF]; /* determine the current time */ time_t now = time(NULL); - timetoa(buf, BUF_LEN, &this->installed, utc); - logger->log(logger, CONTROL, "%s", buf); + timetoa(time_buf, TIMETOA_BUF, &this->installed, utc); + logger->log(logger, CONTROL, "%s", time_buf); logger->log(logger, CONTROL, " subject: '%s'", subject->get_string(subject)); logger->log(logger, CONTROL, " issuer: '%s'", issuer->get_string(issuer)); chunk_to_hex(buf, BUF_LEN, this->serialNumber); logger->log(logger, CONTROL, " serial: %s", buf); - timetoa(buf, BUF_LEN, &this->notBefore, utc); - logger->log(logger, CONTROL, " validity: not before %s %s", buf, + timetoa(time_buf, TIMETOA_BUF, &this->notBefore, utc); + logger->log(logger, CONTROL, " validity: not before %s %s", time_buf, (this->notBefore < now)? "ok":"fatal (not valid yet)"); - timetoa(buf, BUF_LEN, &this->notAfter, utc); - logger->log(logger, CONTROL, " not after %s %s", buf, + timetoa(time_buf, TIMETOA_BUF, &this->notAfter, utc); + logger->log(logger, CONTROL, " not after %s %s", time_buf, check_expiry(this->notAfter, CERT_WARNING_INTERVAL, TRUE)); - timetoa(buf, BUF_LEN, &this->until, utc); - logger->log(logger, CONTROL, " pubkey: RSA %d bits%s, until %s", + timetoa(time_buf, TIMETOA_BUF, &this->until, utc); + switch (this->status) + { + case CERT_GOOD: + snprintf(buf, BUF_LEN, " until %s", time_buf); + break; + case CERT_REVOKED: + snprintf(buf, BUF_LEN, " on %s", time_buf); + break; + case CERT_UNKNOWN: + case CERT_UNDEFINED: + case CERT_UNTRUSTED: + default: + *buf = '\0'; + } + logger->log(logger, CONTROL, " pubkey: RSA %d bits%s, status %s%s", BITS_PER_BYTE * pubkey->get_keysize(pubkey), - has_key? ", has private key":"", buf); + has_key? ", has private key":"", + enum_name(&cert_status_names, this->status), buf); chunk_to_hex(buf, BUF_LEN, pubkey->get_keyid(pubkey)); logger->log(logger, CONTROL, " keyid: %s", buf); @@ -1166,12 +1219,16 @@ x509_t *x509_create_from_chunk(chunk_t chunk) this->public.is_valid = (err_t (*) (const x509_t*,time_t*))is_valid; this->public.is_ca = (bool (*) (const x509_t*))is_ca; this->public.is_self_signed = (bool (*) (const x509_t*))is_self_signed; + this->public.get_certificate = (chunk_t (*) (const x509_t*))get_certificate; this->public.get_public_key = (rsa_public_key_t* (*) (const x509_t*))get_public_key; this->public.get_serialNumber = (chunk_t (*) (const x509_t*))get_serialNumber; this->public.get_subjectKeyID = (chunk_t (*) (const x509_t*))get_subjectKeyID; this->public.get_issuer = (identification_t* (*) (const x509_t*))get_issuer; this->public.get_subject = (identification_t* (*) (const x509_t*))get_subject; this->public.set_until = (void (*) (x509_t*,time_t))set_until; + this->public.get_until = (time_t (*) (const x509_t*))get_until; + this->public.set_status = (void (*) (x509_t*,cert_status_t))set_status; + this->public.get_status = (cert_status_t (*) (const x509_t*))get_status; this->public.verify = (bool (*) (const x509_t*,const rsa_public_key_t*))verify; this->public.destroy = (void (*) (x509_t*))destroy; this->public.log_certificate = (void (*) (const x509_t*,logger_t*,bool,bool))log_certificate; @@ -1193,6 +1250,7 @@ x509_t *x509_create_from_chunk(chunk_t chunk) return NULL; } /* set trusted lifetime of public key to notAfter */ + this->status = is_self_signed(this)? CERT_GOOD:CERT_UNDEFINED; this->until = this->notAfter; return &this->public; } diff --git a/src/libstrongswan/crypto/x509.h b/src/libstrongswan/crypto/x509.h index a4451eb41..866659e3b 100755 --- a/src/libstrongswan/crypto/x509.h +++ b/src/libstrongswan/crypto/x509.h @@ -26,6 +26,7 @@ #include <types.h> #include <definitions.h> #include <crypto/rsa/rsa_public_key.h> +#include <crypto/certinfo.h> #include <utils/identification.h> #include <utils/iterator.h> #include <utils/logger.h> @@ -57,6 +58,38 @@ struct x509_t { void (*set_until) (x509_t *this, time_t until); /** + * @brief Get trusted public key life. + * + * @param this calling object + * @return time until public key is trusted + */ + time_t (*get_until) (const x509_t *this); + + /** + * @brief Set the certificate status + * + * @param this calling object + * @param status certificate status + */ + void (*set_status) (x509_t *this, cert_status_t status); + + /** + * @brief Get the certificate status + * + * @param this calling object + * @return certificate status + */ + cert_status_t (*get_status) (const x509_t *this); + + /** + * @brief Get the DER-encoded X.509 certificate body + * + * @param this calling object + * @return DER-encoded X.509 certificate + */ + chunk_t (*get_certificate) (const x509_t *this); + + /** * @brief Get the RSA public key from the certificate. * * @param this calling object |