From 7585facf05d927eb6df3929ce09ed5e60d905437 Mon Sep 17 00:00:00 2001 From: Yves-Alexis Perez Date: Thu, 7 Feb 2013 13:27:27 +0100 Subject: Imported Upstream version 5.0.2 --- src/libcharon/sa/ikev2/tasks/child_create.c | 11 +- src/libcharon/sa/ikev2/tasks/ike_auth.c | 19 ++- src/libcharon/sa/ikev2/tasks/ike_cert_pre.c | 253 ++++++++++++++++------------ src/libcharon/sa/ikev2/tasks/ike_config.c | 2 + src/libcharon/sa/ikev2/tasks/ike_init.c | 7 +- src/libcharon/sa/ikev2/tasks/ike_mobike.h | 2 +- 6 files changed, 172 insertions(+), 122 deletions(-) (limited to 'src/libcharon/sa/ikev2/tasks') diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index 46a165546..eb3972c29 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -377,6 +377,8 @@ static status_t select_and_install(private_child_create_t *this, if (this->proposal == NULL) { DBG1(DBG_IKE, "no acceptable proposal found"); + charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_CHILD, + this->proposals); return FAILED; } this->other_spi = this->proposal->get_spi(this->proposal); @@ -452,6 +454,7 @@ static status_t select_and_install(private_child_create_t *this, if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0) { + charon->bus->alert(charon->bus, ALERT_TS_MISMATCH, this->tsi, this->tsr); my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy)); other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy)); DBG1(DBG_IKE, "no acceptable traffic selectors found"); @@ -549,6 +552,8 @@ static status_t select_and_install(private_child_create_t *this, (status_i != SUCCESS) ? "inbound " : "", (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "", (status_o != SUCCESS) ? "outbound " : ""); + charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED, + this->child_sa); return FAILED; } @@ -581,6 +586,8 @@ static status_t select_and_install(private_child_create_t *this, if (status != SUCCESS) { DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel"); + charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_POLICY_FAILED, + this->child_sa); return NOT_FOUND; } @@ -982,6 +989,7 @@ static void handle_child_sa_failure(private_child_create_t *this, else { DBG1(DBG_IKE, "failed to establish CHILD_SA, keeping IKE_SA"); + charon->bus->alert(charon->bus, ALERT_KEEP_ON_CHILD_SA_FAILURE); } } @@ -1040,6 +1048,7 @@ METHOD(task_t, build_r, status_t, { DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable", this->tsr, this->tsi); + charon->bus->alert(charon->bus, ALERT_TS_MISMATCH, this->tsi, this->tsr); message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty); handle_child_sa_failure(this, message); return SUCCESS; @@ -1154,7 +1163,7 @@ METHOD(task_t, process_i, status_t, break; } - /* check for erronous notifies */ + /* check for erroneous notifies */ enumerator = message->create_payload_enumerator(message); while (enumerator->enumerate(enumerator, &payload)) { diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c index cd94ccd9e..70efcd7af 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_auth.c +++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c @@ -12,7 +12,7 @@ * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details + * for more details. */ #include "ike_auth.h" @@ -457,6 +457,7 @@ METHOD(task_t, build_i, status_t, this->reserved); if (!this->my_auth) { + charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); return FAILED; } } @@ -473,6 +474,7 @@ METHOD(task_t, build_i, status_t, case NEED_MORE: break; default: + charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); return FAILED; } @@ -748,7 +750,7 @@ METHOD(task_t, build_r, status_t, this->reserved); if (!this->my_auth) { - goto peer_auth_failed; + goto local_auth_failed; } } } @@ -786,9 +788,7 @@ METHOD(task_t, build_r, status_t, case NEED_MORE: break; default: - message->add_notify(message, TRUE, AUTHENTICATION_FAILED, - chunk_empty); - return FAILED; + goto local_auth_failed; } } @@ -807,6 +807,7 @@ METHOD(task_t, build_r, status_t, this->ike_sa, FALSE)) { DBG1(DBG_IKE, "cancelling IKE_SA setup due to uniqueness policy"); + charon->bus->alert(charon->bus, ALERT_UNIQUE_KEEP); message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); return FAILED; @@ -830,11 +831,14 @@ METHOD(task_t, build_r, status_t, return NEED_MORE; peer_auth_failed: - message->add_notify(message, TRUE, AUTHENTICATION_FAILED, - chunk_empty); + message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); peer_auth_failed_no_notify: charon->bus->alert(charon->bus, ALERT_PEER_AUTH_FAILED); return FAILED; +local_auth_failed: + message->add_notify(message, TRUE, AUTHENTICATION_FAILED, chunk_empty); + charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); + return FAILED; } METHOD(task_t, process_i, status_t, @@ -987,6 +991,7 @@ METHOD(task_t, process_i, status_t, case NEED_MORE: break; default: + charon->bus->alert(charon->bus, ALERT_LOCAL_AUTH_FAILED); return FAILED; } } diff --git a/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c index 60e878777..2cbe8f8c5 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c +++ b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c @@ -56,6 +56,72 @@ struct private_ike_cert_pre_t { bool final; }; +/** + * Process a single certificate request payload + */ +static void process_certreq(private_ike_cert_pre_t *this, + certreq_payload_t *certreq, auth_cfg_t *auth) +{ + enumerator_t *enumerator; + u_int unknown = 0; + chunk_t keyid; + + this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE); + + if (certreq->get_cert_type(certreq) != CERT_X509) + { + DBG1(DBG_IKE, "cert payload %N not supported - ignored", + certificate_type_names, certreq->get_cert_type(certreq)); + return; + } + + enumerator = certreq->create_keyid_enumerator(certreq); + while (enumerator->enumerate(enumerator, &keyid)) + { + identification_t *id; + certificate_t *cert; + + id = identification_create_from_encoding(ID_KEY_ID, keyid); + cert = lib->credmgr->get_cert(lib->credmgr, + CERT_X509, KEY_ANY, id, TRUE); + if (cert) + { + DBG1(DBG_IKE, "received cert request for \"%Y\"", + cert->get_subject(cert)); + auth->add(auth, AUTH_RULE_CA_CERT, cert); + } + else + { + DBG2(DBG_IKE, "received cert request for unknown ca with keyid %Y", + id); + unknown++; + } + id->destroy(id); + } + enumerator->destroy(enumerator); + if (unknown) + { + DBG1(DBG_IKE, "received %u cert requests for an unknown ca", + unknown); + } +} + +/** + * Process a single notify payload + */ +static void process_notify(private_ike_cert_pre_t *this, + notify_payload_t *notify) +{ + switch (notify->get_notify_type(notify)) + { + case HTTP_CERT_LOOKUP_SUPPORTED: + this->ike_sa->enable_extension(this->ike_sa, EXT_HASH_AND_URL); + break; + default: + break; + } +} + /** * read certificate requests */ @@ -73,62 +139,11 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message) switch (payload->get_type(payload)) { case CERTIFICATE_REQUEST: - { - certreq_payload_t *certreq = (certreq_payload_t*)payload; - enumerator_t *enumerator; - u_int unknown = 0; - chunk_t keyid; - - this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE); - - if (certreq->get_cert_type(certreq) != CERT_X509) - { - DBG1(DBG_IKE, "cert payload %N not supported - ignored", - certificate_type_names, certreq->get_cert_type(certreq)); - break; - } - enumerator = certreq->create_keyid_enumerator(certreq); - while (enumerator->enumerate(enumerator, &keyid)) - { - identification_t *id; - certificate_t *cert; - - id = identification_create_from_encoding(ID_KEY_ID, keyid); - cert = lib->credmgr->get_cert(lib->credmgr, - CERT_X509, KEY_ANY, id, TRUE); - if (cert) - { - DBG1(DBG_IKE, "received cert request for \"%Y\"", - cert->get_subject(cert)); - auth->add(auth, AUTH_RULE_CA_CERT, cert); - } - else - { - DBG2(DBG_IKE, "received cert request for unknown ca " - "with keyid %Y", id); - unknown++; - } - id->destroy(id); - } - enumerator->destroy(enumerator); - if (unknown) - { - DBG1(DBG_IKE, "received %u cert requests for an unknown ca", - unknown); - } + process_certreq(this, (certreq_payload_t*)payload, auth); break; - } case NOTIFY: - { - notify_payload_t *notify = (notify_payload_t*)payload; - - /* we only handle one type of notify here */ - if (notify->get_notify_type(notify) == HTTP_CERT_LOOKUP_SUPPORTED) - { - this->ike_sa->enable_extension(this->ike_sa, EXT_HASH_AND_URL); - } + process_notify(this, (notify_payload_t*)payload); break; - } default: /* ignore other payloads here, these are handled elsewhere */ break; @@ -177,7 +192,75 @@ static certificate_t *try_get_cert(cert_payload_t *cert_payload) } /** - * import certificates + * Process a X509 certificate payload + */ +static void process_x509(cert_payload_t *payload, auth_cfg_t *auth, + cert_encoding_t encoding, bool *first) +{ + certificate_t *cert; + char *url; + + cert = try_get_cert(payload); + if (cert) + { + if (*first) + { /* the first is an end entity certificate */ + DBG1(DBG_IKE, "received end entity cert \"%Y\"", + cert->get_subject(cert)); + auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert); + *first = FALSE; + } + else + { + DBG1(DBG_IKE, "received issuer cert \"%Y\"", + cert->get_subject(cert)); + auth->add(auth, AUTH_HELPER_IM_CERT, cert); + } + } + else if (encoding == ENC_X509_HASH_AND_URL) + { + /* we fetch the certificate not yet, but only if + * it is really needed during authentication */ + url = payload->get_url(payload); + if (!url) + { + DBG1(DBG_IKE, "received invalid hash-and-url " + "encoded cert, ignore"); + return; + } + url = strdup(url); + if (first) + { /* first URL is for an end entity certificate */ + DBG1(DBG_IKE, "received hash-and-url for end entity cert \"%s\"", + url); + auth->add(auth, AUTH_HELPER_SUBJECT_HASH_URL, url); + first = FALSE; + } + else + { + DBG1(DBG_IKE, "received hash-and-url for issuer cert \"%s\"", url); + auth->add(auth, AUTH_HELPER_IM_HASH_URL, url); + } + } +} + +/** + * Process a CRL certificate payload + */ +static void process_crl(cert_payload_t *payload, auth_cfg_t *auth) +{ + certificate_t *cert; + + cert = payload->get_cert(payload); + if (cert) + { + DBG1(DBG_IKE, "received CRL \"%Y\"", cert->get_subject(cert)); + auth->add(auth, AUTH_HELPER_REVOCATION_CERT, cert); + } +} + +/** + * Process certificate payloads */ static void process_certs(private_ike_cert_pre_t *this, message_t *message) { @@ -195,8 +278,6 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message) { cert_payload_t *cert_payload; cert_encoding_t encoding; - certificate_t *cert; - char *url; cert_payload = (cert_payload_t*)payload; encoding = cert_payload->get_cert_encoding(cert_payload); @@ -204,70 +285,18 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message) switch (encoding) { case ENC_X509_HASH_AND_URL: - { if (!this->do_http_lookup) { - DBG1(DBG_IKE, "received hash-and-url encoded cert, but" - " we don't accept them, ignore"); + DBG1(DBG_IKE, "received hash-and-url encoded cert, but " + "we don't accept them, ignore"); break; } /* FALL */ - } case ENC_X509_SIGNATURE: - { - cert = try_get_cert(cert_payload); - if (cert) - { - if (first) - { /* the first is an end entity certificate */ - DBG1(DBG_IKE, "received end entity cert \"%Y\"", - cert->get_subject(cert)); - auth->add(auth, AUTH_HELPER_SUBJECT_CERT, cert); - first = FALSE; - } - else - { - DBG1(DBG_IKE, "received issuer cert \"%Y\"", - cert->get_subject(cert)); - auth->add(auth, AUTH_HELPER_IM_CERT, cert); - } - } - else if (encoding == ENC_X509_HASH_AND_URL) - { - /* we fetch the certificate not yet, but only if - * it is really needed during authentication */ - url = cert_payload->get_url(cert_payload); - if (!url) - { - DBG1(DBG_IKE, "received invalid hash-and-url " - "encoded cert, ignore"); - break; - } - url = strdup(url); - if (first) - { /* first URL is for an end entity certificate */ - DBG1(DBG_IKE, "received hash-and-url for end" - " entity cert \"%s\"", url); - auth->add(auth, AUTH_HELPER_SUBJECT_HASH_URL, url); - first = FALSE; - } - else - { - DBG1(DBG_IKE, "received hash-and-url for issuer" - " cert \"%s\"", url); - auth->add(auth, AUTH_HELPER_IM_HASH_URL, url); - } - } + process_x509(cert_payload, auth, encoding, &first); break; - } case ENC_CRL: - cert = cert_payload->get_cert(cert_payload); - if (cert) - { - DBG1(DBG_IKE, "received CRL \"%Y\"", - cert->get_subject(cert)); - auth->add(auth, AUTH_HELPER_REVOCATION_CERT, cert); - } + process_crl(cert_payload, auth); break; case ENC_PKCS7_WRAPPED_X509: case ENC_PGP: diff --git a/src/libcharon/sa/ikev2/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c index c44f0452c..d637c26fe 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_config.c +++ b/src/libcharon/sa/ikev2/tasks/ike_config.c @@ -380,6 +380,7 @@ METHOD(task_t, build_r, status_t, { DBG1(DBG_IKE, "no virtual IP found, sending %N", notify_type_names, INTERNAL_ADDRESS_FAILURE); + charon->bus->alert(charon->bus, ALERT_VIP_FAILURE, this->vips); message->add_notify(message, FALSE, INTERNAL_ADDRESS_FAILURE, chunk_empty); vips->destroy_offset(vips, offsetof(host_t, destroy)); @@ -390,6 +391,7 @@ METHOD(task_t, build_r, status_t, { DBG1(DBG_IKE, "expected a virtual IP request, sending %N", notify_type_names, FAILED_CP_REQUIRED); + charon->bus->alert(charon->bus, ALERT_VIP_FAILURE, this->vips); message->add_notify(message, FALSE, FAILED_CP_REQUIRED, chunk_empty); vips->destroy_offset(vips, offsetof(host_t, destroy)); pools->destroy(pools); diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c index f2a06735e..7542937b3 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_init.c +++ b/src/libcharon/sa/ikev2/tasks/ike_init.c @@ -187,6 +187,11 @@ static void process_payloads(private_ike_init_t *this, message_t *message) EXT_STRONGSWAN); this->proposal = this->config->select_proposal(this->config, proposal_list, private); + if (!this->proposal) + { + charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_IKE, + proposal_list); + } proposal_list->destroy_offset(proposal_list, offsetof(proposal_t, destroy)); break; @@ -421,7 +426,7 @@ METHOD(task_t, process_i, status_t, enumerator_t *enumerator; payload_t *payload; - /* check for erronous notifies */ + /* check for erroneous notifies */ enumerator = message->create_payload_enumerator(message); while (enumerator->enumerate(enumerator, &payload)) { diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.h b/src/libcharon/sa/ikev2/tasks/ike_mobike.h index 3b447af51..b145a9a8b 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_mobike.h +++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.h @@ -26,7 +26,7 @@ typedef struct ike_mobike_t ike_mobike_t; #include #include #include -#include +#include /** * Task of type ike_mobike, detects and handles MOBIKE extension. -- cgit v1.2.3