diff options
Diffstat (limited to 'src/libcharon/sa/ikev2')
-rw-r--r-- | src/libcharon/sa/ikev2/connect_manager.c | 2 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/mediation_manager.c | 2 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/task_manager_v2.c | 25 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/child_create.c | 11 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_auth.c | 19 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_cert_pre.c | 253 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_config.c | 2 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_init.c | 7 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_mobike.h | 2 |
9 files changed, 196 insertions, 127 deletions
diff --git a/src/libcharon/sa/ikev2/connect_manager.c b/src/libcharon/sa/ikev2/connect_manager.c index 5fdcea1ab..c4e5ea7a0 100644 --- a/src/libcharon/sa/ikev2/connect_manager.c +++ b/src/libcharon/sa/ikev2/connect_manager.c @@ -19,7 +19,7 @@ #include <daemon.h> #include <threading/mutex.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <crypto/hashers/hasher.h> #include <processing/jobs/callback_job.h> diff --git a/src/libcharon/sa/ikev2/mediation_manager.c b/src/libcharon/sa/ikev2/mediation_manager.c index 60eeb5d4b..bf5b2f4b3 100644 --- a/src/libcharon/sa/ikev2/mediation_manager.c +++ b/src/libcharon/sa/ikev2/mediation_manager.c @@ -17,7 +17,7 @@ #include <daemon.h> #include <threading/mutex.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <processing/jobs/mediation_job.h> typedef struct peer_t peer_t; diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index 53051fab4..ea0117c54 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -257,6 +257,8 @@ METHOD(task_manager_t, retransmit, status_t, { DBG1(DBG_IKE, "giving up after %d retransmits", this->initiating.retransmitted - 1); + charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND_TIMEOUT, + this->initiating.packet); return DESTROY_ME; } @@ -264,6 +266,8 @@ METHOD(task_manager_t, retransmit, status_t, { DBG1(DBG_IKE, "retransmit %d of request with message ID %d", this->initiating.retransmitted, message_id); + charon->bus->alert(charon->bus, ALERT_RETRANSMIT_SEND, + this->initiating.packet); } packet = this->initiating.packet->clone(this->initiating.packet); charon->sender->send(charon->sender, packet); @@ -626,6 +630,8 @@ static status_t build_response(private_task_manager_t *this, message_t *request) message_t *message; host_t *me, *other; bool delete = FALSE, hook = FALSE; + ike_sa_id_t *id = NULL; + u_int64_t responder_spi; status_t status; me = request->get_destination(request); @@ -676,10 +682,15 @@ static status_t build_response(private_task_manager_t *this, message_t *request) } enumerator->destroy(enumerator); - /* remove resonder SPI if IKE_SA_INIT failed */ + /* RFC 5996, section 2.6 mentions that in the event of a failure during + * IKE_SA_INIT the responder's SPI will be 0 in the response, while it + * actually explicitly allows it to be non-zero. Since we use the responder + * SPI to create hashes in the IKE_SA manager we can only set the SPI to + * zero temporarily, otherwise checking the SA in would fail. */ if (delete && request->get_exchange_type(request) == IKE_SA_INIT) { - ike_sa_id_t *id = this->ike_sa->get_id(this->ike_sa); + id = this->ike_sa->get_id(this->ike_sa); + responder_spi = id->get_responder_spi(id); id->set_responder_spi(id, 0); } @@ -689,6 +700,10 @@ static status_t build_response(private_task_manager_t *this, message_t *request) status = this->ike_sa->generate_message(this->ike_sa, message, &this->responding.packet); message->destroy(message); + if (id) + { + id->set_responder_spi(id, responder_spi); + } if (status != SUCCESS) { charon->bus->ike_updown(charon->bus, this->ike_sa, FALSE); @@ -1045,6 +1060,8 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg) is_request ? "request" : "response", msg->get_message_id(msg)); + charon->bus->alert(charon->bus, ALERT_PARSE_ERROR_BODY, msg, status); + if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED) { /* invalid initiation attempt, close SA */ return DESTROY_ME; @@ -1077,7 +1094,8 @@ METHOD(task_manager_t, process_message, status_t, ike_sa_id_t *ike_sa_id; ike_cfg_t *ike_cfg; job_t *job; - ike_cfg = charon->backends->get_ike_cfg(charon->backends, me, other); + ike_cfg = charon->backends->get_ike_cfg(charon->backends, + me, other, IKEV2); if (ike_cfg == NULL) { /* no config found for these hosts, destroy */ @@ -1133,6 +1151,7 @@ METHOD(task_manager_t, process_message, status_t, DBG1(DBG_IKE, "received retransmit of request with ID %d, " "retransmitting response", mid); + charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg); clone = this->responding.packet->clone(this->responding.packet); host = msg->get_destination(msg); clone->set_source(clone, host->clone(host)); 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 @@ -57,6 +57,72 @@ struct private_ike_cert_pre_t { }; /** + * 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 */ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message) @@ -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 <library.h> #include <sa/ike_sa.h> #include <sa/task.h> -#include <utils/packet.h> +#include <networking/packet.h> /** * Task of type ike_mobike, detects and handles MOBIKE extension. |