diff options
author | tobhe <tobhe@cvs.openbsd.org> | 2020-09-16 21:37:36 +0000 |
---|---|---|
committer | tobhe <tobhe@cvs.openbsd.org> | 2020-09-16 21:37:36 +0000 |
commit | acb9e6b38f7641e071bd548338ce93c9b3314e82 (patch) | |
tree | 97b0dca1a183f0ead93360cdce04d9577a2d103a /sbin/iked | |
parent | 9e307b29862ebf9bc1d5e591bf93c6115aee9352 (diff) |
Move all the EAP logic from a single branch in the message parsing code to
somewhere past successful message verification, closer to where the other
exchanges are handled. EAP is stll special, but this fits a lot better into
the overall architecture.
Tested with iOS, Stronswan and Windows
ok patrick@ sthen@
Diffstat (limited to 'sbin/iked')
-rw-r--r-- | sbin/iked/eap.c | 330 | ||||
-rw-r--r-- | sbin/iked/eap.h | 4 | ||||
-rw-r--r-- | sbin/iked/iked.h | 32 | ||||
-rw-r--r-- | sbin/iked/ikev2.c | 206 | ||||
-rw-r--r-- | sbin/iked/ikev2_pld.c | 5 |
5 files changed, 352 insertions, 225 deletions
diff --git a/sbin/iked/eap.c b/sbin/iked/eap.c index 9a75bfa7de3..a195ff6a25b 100644 --- a/sbin/iked/eap.c +++ b/sbin/iked/eap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eap.c,v 1.15 2020/06/18 19:55:03 tobhe Exp $ */ +/* $OpenBSD: eap.c,v 1.16 2020/09/16 21:37:35 tobhe Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -40,16 +40,15 @@ #include "iked.h" #include "ikev2.h" #include "eap.h" -#include "chap_ms.h" -char *eap_identity_response(struct eap_message *); -int eap_challenge_request(struct iked *env, struct iked_sa *, - struct eap_header *); -int eap_success(struct iked *, struct iked_sa *, struct eap_header *); -int eap_mschap(struct iked *, struct iked_sa *, struct eap_message *); +int eap_message_send(struct iked *, struct iked_sa *, int, int); +ssize_t eap_add_id_request(struct ibuf *); +char *eap_validate_id_response(struct eap_message *); +int eap_mschap(struct iked *, struct iked_sa *, struct iked_message *, + struct eap_message *); ssize_t -eap_identity_request(struct ibuf *e) +eap_add_id_request(struct ibuf *e) { struct eap_message *eap; @@ -64,7 +63,7 @@ eap_identity_request(struct ibuf *e) } char * -eap_identity_response(struct eap_message *eap) +eap_validate_id_response(struct eap_message *eap) { size_t len; char *str; @@ -83,8 +82,91 @@ eap_identity_response(struct eap_message *eap) } int +eap_identity_request(struct iked *env, struct iked_sa *sa) +{ + struct ikev2_payload *pld; + struct ikev2_cert *cert; + struct ikev2_auth *auth; + struct iked_id *id, *certid; + struct ibuf *e = NULL; + uint8_t firstpayload; + int ret = -1; + ssize_t len = 0; + + /* Responder only */ + if (sa->sa_hdr.sh_initiator) + return (-1); + + /* Check if "ca" has done it's job yet */ + if (!sa->sa_localauth.id_type) + return (0); + + /* New encrypted message buffer */ + if ((e = ibuf_static()) == NULL) + goto done; + + id = &sa->sa_rid; + certid = &sa->sa_rcert; + + /* ID payload */ + if ((pld = ikev2_add_payload(e)) == NULL) + goto done; + firstpayload = IKEV2_PAYLOAD_IDr; + if (ibuf_cat(e, id->id_buf) != 0) + goto done; + len = ibuf_size(id->id_buf); + + if ((sa->sa_statevalid & IKED_REQ_CERT) && + (certid->id_type != IKEV2_CERT_NONE)) { + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CERT) == -1) + goto done; + + /* CERT payload */ + if ((pld = ikev2_add_payload(e)) == NULL) + goto done; + if ((cert = ibuf_advance(e, sizeof(*cert))) == NULL) + goto done; + cert->cert_type = certid->id_type; + if (ibuf_cat(e, certid->id_buf) != 0) + goto done; + len = ibuf_size(certid->id_buf) + sizeof(*cert); + } + + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH) == -1) + goto done; + + /* AUTH payload */ + if ((pld = ikev2_add_payload(e)) == NULL) + goto done; + if ((auth = ibuf_advance(e, sizeof(*auth))) == NULL) + goto done; + auth->auth_method = sa->sa_localauth.id_type; + if (ibuf_cat(e, sa->sa_localauth.id_buf) != 0) + goto done; + len = ibuf_size(sa->sa_localauth.id_buf) + sizeof(*auth); + + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_EAP) == -1) + goto done; + + /* EAP payload */ + if ((pld = ikev2_add_payload(e)) == NULL) + goto done; + if ((len = eap_add_id_request(e)) == -1) + goto done; + + if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE) == -1) + goto done; + + ret = ikev2_msg_send_encrypt(env, sa, &e, + IKEV2_EXCHANGE_IKE_AUTH, firstpayload, 1); + done: + ibuf_release(e); + return (ret); +} + +int eap_challenge_request(struct iked *env, struct iked_sa *sa, - struct eap_header *hdr) + int eap_id) { struct eap_message *eap; struct eap_mschap_challenge *ms; @@ -98,7 +180,7 @@ eap_challenge_request(struct iked *env, struct iked_sa *sa, if ((eap = ibuf_advance(e, sizeof(*eap))) == NULL) goto done; eap->eap_code = EAP_CODE_REQUEST; - eap->eap_id = hdr->eap_id + 1; + eap->eap_id = eap_id + 1; eap->eap_type = sa->sa_policy->pol_auth.auth_eap; switch (sa->sa_policy->pol_auth.auth_eap) { @@ -131,15 +213,13 @@ eap_challenge_request(struct iked *env, struct iked_sa *sa, ret = ikev2_send_ike_e(env, sa, e, IKEV2_PAYLOAD_EAP, IKEV2_EXCHANGE_IKE_AUTH, 1); - done: ibuf_release(e); - return (ret); } int -eap_success(struct iked *env, struct iked_sa *sa, struct eap_header *hdr) +eap_message_send(struct iked *env, struct iked_sa *sa, int eap_code, int eap_id) { struct eap_header *resp; int ret = -1; @@ -150,34 +230,99 @@ eap_success(struct iked *env, struct iked_sa *sa, struct eap_header *hdr) if ((resp = ibuf_advance(e, sizeof(*resp))) == NULL) goto done; - resp->eap_code = EAP_CODE_SUCCESS; - resp->eap_id = hdr->eap_id; + resp->eap_code = eap_code; + resp->eap_id = eap_id; resp->eap_length = htobe16(sizeof(*resp)); ret = ikev2_send_ike_e(env, sa, e, IKEV2_PAYLOAD_EAP, IKEV2_EXCHANGE_IKE_AUTH, 1); - done: ibuf_release(e); + return (ret); +} + +int +eap_success(struct iked *env, struct iked_sa *sa, int eap_id) +{ + return (eap_message_send(env, sa, EAP_CODE_SUCCESS, eap_id)); +} + +int +eap_mschap_challenge(struct iked *env, struct iked_sa *sa, int eap_id, + int msr_id, uint8_t *successmsg, size_t success_size) +{ + struct ibuf *eapmsg = NULL; + struct eap_message *resp; + struct eap_mschap_success *mss; + char *msg; + int ret = -1; + + if ((eapmsg = ibuf_static()) == NULL) + return (-1); + + msg = " M=Welcome"; + + if ((resp = ibuf_advance(eapmsg, sizeof(*resp))) == NULL) + goto done; + resp->eap_code = EAP_CODE_REQUEST; + resp->eap_id = eap_id + 1; + resp->eap_length = htobe16(sizeof(*resp) + sizeof(*mss) + + success_size + strlen(msg)); + resp->eap_type = EAP_TYPE_MSCHAP_V2; + + if ((mss = ibuf_advance(eapmsg, sizeof(*mss))) == NULL) + goto done; + mss->mss_opcode = EAP_MSOPCODE_SUCCESS; + mss->mss_id = msr_id; + mss->mss_length = htobe16(sizeof(*mss) + + success_size + strlen(msg)); + if (ibuf_add(eapmsg, successmsg, success_size) != 0) + goto done; + if (ibuf_add(eapmsg, msg, strlen(msg)) != 0) + goto done; + ret = ikev2_send_ike_e(env, sa, eapmsg, + IKEV2_PAYLOAD_EAP, IKEV2_EXCHANGE_IKE_AUTH, 1); + done: + ibuf_release(eapmsg); return (ret); } int -eap_mschap(struct iked *env, struct iked_sa *sa, struct eap_message *eap) +eap_mschap_success(struct iked *env, struct iked_sa *sa, int eap_id) { - struct iked_user *usr; + struct ibuf *eapmsg = NULL; struct eap_message *resp; + struct eap_mschap *ms; + int ret = -1; + + if ((eapmsg = ibuf_static()) == NULL) + return (-1); + if ((resp = ibuf_advance(eapmsg, sizeof(*resp))) == NULL) + goto done; + resp->eap_code = EAP_CODE_RESPONSE; + resp->eap_id = eap_id; + resp->eap_length = htobe16(sizeof(*resp) + sizeof(*ms)); + resp->eap_type = EAP_TYPE_MSCHAP_V2; + if ((ms = ibuf_advance(eapmsg, sizeof(*ms))) == NULL) + goto done; + ms->ms_opcode = EAP_MSOPCODE_SUCCESS; + + ret = ikev2_send_ike_e(env, sa, eapmsg, + IKEV2_PAYLOAD_EAP, IKEV2_EXCHANGE_IKE_AUTH, 1); + done: + ibuf_release(eapmsg); + return (ret); +} + +int +eap_mschap(struct iked *env, struct iked_sa *sa, struct iked_message *msg, struct eap_message *eap) +{ struct eap_mschap_response *msr; struct eap_mschap_peer *msp; struct eap_mschap *ms; - struct eap_mschap_success *mss; - uint8_t *ptr, *pass; - size_t len, passlen; - char *name, *msg; - uint8_t ntresponse[EAP_MSCHAP_NTRESPONSE_SZ]; - uint8_t successmsg[EAP_MSCHAP_SUCCESS_SZ]; - struct ibuf *eapmsg = NULL; + uint8_t *ptr; + size_t len; int ret = -1; if (!sa_stateok(sa, IKEV2_STATE_EAP)) { @@ -215,93 +360,21 @@ eap_mschap(struct iked *env, struct iked_sa *sa, struct eap_message *eap) ptr += sizeof(*msr); len = betoh16(eap->eap_length) - sizeof(*eap) - sizeof(*msr); - if (len == 0 && sa->sa_eapid != NULL) - name = strdup(sa->sa_eapid); - else - name = get_string(ptr, len); - if (name == NULL) { - log_debug("%s: invalid response name", __func__); - return (-1); - } - if ((usr = user_lookup(env, name)) == NULL) { - log_debug("%s: unknown user '%s'", __func__, name); - free(name); - return (-1); - } - free(name); - - if ((pass = string2unicode(usr->usr_pass, &passlen)) == NULL) - return (-1); + if (len != 0) + msg->msg_parent->msg_eap.eam_user = get_string(ptr, len); + msg->msg_parent->msg_eap.eam_msrid = msr->msr_id; msp = &msr->msr_response.resp_peer; - mschap_nt_response(ibuf_data(sa->sa_eap.id_buf), - msp->msp_challenge, usr->usr_name, strlen(usr->usr_name), - pass, passlen, ntresponse); - - if (memcmp(ntresponse, msp->msp_ntresponse, - sizeof(ntresponse)) != 0) { - log_debug("%s: '%s' authentication failed", __func__, - usr->usr_name); - free(pass); - - /* XXX should we send an EAP failure packet? */ - return (-1); - } - - bzero(&successmsg, sizeof(successmsg)); - mschap_auth_response(pass, passlen, - ntresponse, ibuf_data(sa->sa_eap.id_buf), - msp->msp_challenge, usr->usr_name, strlen(usr->usr_name), - successmsg); - if ((sa->sa_eapmsk = ibuf_new(NULL, MSCHAP_MSK_SZ)) == NULL) { - log_debug("%s: failed to get MSK", __func__); - free(pass); - return (-1); - } - mschap_msk(pass, passlen, ntresponse, - ibuf_data(sa->sa_eapmsk)); - free(pass); - - log_info("%s: '%s' authenticated", __func__, usr->usr_name); - - - if ((eapmsg = ibuf_static()) == NULL) - return (-1); - - msg = " M=Welcome"; - - if ((resp = ibuf_advance(eapmsg, sizeof(*resp))) == NULL) - goto done; - resp->eap_code = EAP_CODE_REQUEST; - resp->eap_id = eap->eap_id + 1; - resp->eap_length = htobe16(sizeof(*resp) + sizeof(*mss) + - sizeof(successmsg) + strlen(msg)); - resp->eap_type = EAP_TYPE_MSCHAP_V2; - - if ((mss = ibuf_advance(eapmsg, sizeof(*mss))) == NULL) - goto done; - mss->mss_opcode = EAP_MSOPCODE_SUCCESS; - mss->mss_id = msr->msr_id; - mss->mss_length = htobe16(sizeof(*mss) + - sizeof(successmsg) + strlen(msg)); - if (ibuf_add(eapmsg, successmsg, sizeof(successmsg)) != 0) - goto done; - if (ibuf_add(eapmsg, msg, strlen(msg)) != 0) - goto done; - break; + memcpy(msg->msg_parent->msg_eap.eam_challenge, + msp->msp_challenge, EAP_MSCHAP_CHALLENGE_SZ); + memcpy(msg->msg_parent->msg_eap.eam_ntresponse, + msp->msp_ntresponse, EAP_MSCHAP_NTRESPONSE_SZ); + msg->msg_parent->msg_eap.eam_state = + EAP_STATE_MSCHAPV2_CHALLENGE; + return (0); case EAP_MSOPCODE_SUCCESS: - if ((eapmsg = ibuf_static()) == NULL) - return (-1); - if ((resp = ibuf_advance(eapmsg, sizeof(*resp))) == NULL) - goto done; - resp->eap_code = EAP_CODE_RESPONSE; - resp->eap_id = eap->eap_id; - resp->eap_length = htobe16(sizeof(*resp) + sizeof(*ms)); - resp->eap_type = EAP_TYPE_MSCHAP_V2; - if ((ms = ibuf_advance(eapmsg, sizeof(*ms))) == NULL) - goto done; - ms->ms_opcode = EAP_MSOPCODE_SUCCESS; - break; + msg->msg_parent->msg_eap.eam_state = EAP_STATE_MSCHAPV2_SUCCESS; + return (0); case EAP_MSOPCODE_FAILURE: case EAP_MSOPCODE_CHANGE_PASSWORD: case EAP_MSOPCODE_CHALLENGE: @@ -312,21 +385,12 @@ eap_mschap(struct iked *env, struct iked_sa *sa, struct eap_message *eap) print_map(ms->ms_opcode, eap_msopcode_map)); return (-1); } - - if (eapmsg != NULL) - ret = ikev2_send_ike_e(env, sa, eapmsg, - IKEV2_PAYLOAD_EAP, IKEV2_EXCHANGE_IKE_AUTH, 1); - - if (ret == 0) - sa_state(env, sa, IKEV2_STATE_AUTH_SUCCESS); - - done: - ibuf_release(eapmsg); return (ret); } int -eap_parse(struct iked *env, struct iked_sa *sa, void *data, int response) +eap_parse(struct iked *env, struct iked_sa *sa, struct iked_message *msg, void *data, + int response) { struct eap_header *hdr = data; struct eap_message *eap = data; @@ -362,11 +426,14 @@ eap_parse(struct iked *env, struct iked_sa *sa, void *data, int response) return (-1); } + msg->msg_parent->msg_eap.eam_id = hdr->eap_id; + msg->msg_parent->msg_eap.eam_type = eap->eap_type; + switch (eap->eap_type) { case EAP_TYPE_IDENTITY: if (eap->eap_code == EAP_CODE_REQUEST) break; - if ((str = eap_identity_response(eap)) == NULL) + if ((str = eap_validate_id_response(eap)) == NULL) return (-1); if (response) { free(str); @@ -377,8 +444,11 @@ eap_parse(struct iked *env, struct iked_sa *sa, void *data, int response) log_debug("%s: EAP identity already known", __func__); return (0); } - sa->sa_eapid = str; - return (eap_challenge_request(env, sa, hdr)); + msg->msg_parent->msg_eap.eam_response = 1; + msg->msg_parent->msg_eap.eam_identity = str; + msg->msg_parent->msg_eap.eam_state = + EAP_STATE_IDENTITY; + return (0); case EAP_TYPE_MSCHAP_V2: if (len < sizeof(*ms)) goto fail; @@ -397,7 +467,7 @@ eap_parse(struct iked *env, struct iked_sa *sa, void *data, int response) } log_info("%s: %s %s id %d " "length %d valuesize %d name '%s' length %zu", - __func__, + SPI_SA(sa, __func__), print_map(eap->eap_type, eap_type_map), print_map(ms->ms_opcode, eap_msopcode_map), msc->msc_id, betoh16(msc->msc_length), @@ -457,10 +527,10 @@ eap_parse(struct iked *env, struct iked_sa *sa, void *data, int response) print_map(ms->ms_opcode, eap_msopcode_map)); if (response) break; - if (!sa_stateok(sa, IKEV2_STATE_AUTH_SUCCESS)) - return (-1); - - return (eap_success(env, sa, hdr)); + msg->msg_parent->msg_eap.eam_success = 1; + msg->msg_parent->msg_eap.eam_state = + EAP_STATE_SUCCESS; + return (0); } break; case EAP_MSOPCODE_FAILURE: @@ -489,7 +559,7 @@ eap_parse(struct iked *env, struct iked_sa *sa, void *data, int response) if (response) break; - return (eap_mschap(env, sa, eap)); + return (eap_mschap(env, sa, msg, eap)); default: log_debug("%s: unsupported EAP type %s", __func__, print_map(eap->eap_type, eap_type_map)); diff --git a/sbin/iked/eap.h b/sbin/iked/eap.h index cc567eaaa53..509da7ac6f3 100644 --- a/sbin/iked/eap.h +++ b/sbin/iked/eap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: eap.h,v 1.5 2015/08/21 11:59:27 reyk Exp $ */ +/* $OpenBSD: eap.h,v 1.6 2020/09/16 21:37:35 tobhe Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -52,7 +52,7 @@ extern struct iked_constmap eap_code_map[]; #define EAP_TYPE_DSS 10 /* Nace */ #define EAP_TYPE_KEA 11 /* Nace */ #define EAP_TYPE_KEA_VALIDATE 12 /* Nace */ -#define EAP_TYPE_TLS 13 /* RFC-simon-emu-rfc2716bis-13.txt */ +#define EAP_TYPE_TLS 13 /* RFC5216 */ #define EAP_TYPE_AXENT 14 /* Rosselli */ #define EAP_TYPE_SECURID 15 /* Nystrm */ #define EAP_TYPE_ARCOT 16 /* Jerdonek */ diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index 5f345f2791d..496d80c6e74 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iked.h,v 1.164 2020/08/28 13:37:52 tobhe Exp $ */ +/* $OpenBSD: iked.h,v 1.165 2020/09/16 21:37:35 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> @@ -533,6 +533,25 @@ struct iked_certreq { }; SIMPLEQ_HEAD(iked_certreqs, iked_certreq); +#define EAP_STATE_IDENTITY (1) +#define EAP_STATE_MSCHAPV2_CHALLENGE (2) +#define EAP_STATE_MSCHAPV2_SUCCESS (3) +#define EAP_STATE_SUCCESS (4) + +struct eap_msg { + char *eam_identity; + char *eam_user; + int eam_type; + uint8_t eam_id; + uint8_t eam_msrid; + int eam_success; + int eam_found; + int eam_response; + uint8_t eam_challenge[16]; + uint8_t eam_ntresponse[24]; + uint32_t eam_state; +}; + struct iked_message { struct ibuf *msg_data; size_t msg_offset; @@ -578,6 +597,7 @@ struct iked_message { uint16_t msg_cpi; uint8_t msg_transform; uint16_t msg_flags; + struct eap_msg msg_eap; /* MOBIKE */ int msg_update_sa_addresses; @@ -995,8 +1015,14 @@ int ikev2_pld_parse(struct iked *, struct ike_header *, struct iked_message *, size_t); /* eap.c */ -ssize_t eap_identity_request(struct ibuf *); -int eap_parse(struct iked *, struct iked_sa *, void *, int); +int eap_parse(struct iked *, struct iked_sa *, struct iked_message*, + void *, int); +int eap_success(struct iked *, struct iked_sa *, int); +int eap_identity_request(struct iked *, struct iked_sa *); +int eap_mschap_challenge(struct iked *, struct iked_sa *, int, int, + uint8_t *, size_t); +int eap_mschap_success(struct iked *, struct iked_sa *, int); +int eap_challenge_request(struct iked *, struct iked_sa *, int); /* pfkey.c */ int pfkey_couple(int, struct iked_sas *, int); diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c index 10fb424f53b..25adc60432d 100644 --- a/sbin/iked/ikev2.c +++ b/sbin/iked/ikev2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2.c,v 1.255 2020/09/06 19:08:58 tobhe Exp $ */ +/* $OpenBSD: ikev2.c,v 1.256 2020/09/16 21:37:35 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> @@ -46,6 +46,7 @@ #include "ikev2.h" #include "eap.h" #include "dh.h" +#include "chap_ms.h" void ikev2_info(struct iked *, int); void ikev2_info_sa(struct iked *, int, const char *, struct iked_sa *); @@ -89,8 +90,11 @@ void ikev2_disable_timer(struct iked *, struct iked_sa *); void ikev2_resp_recv(struct iked *, struct iked_message *, struct ike_header *); int ikev2_resp_ike_sa_init(struct iked *, struct iked_message *); +int ikev2_resp_ike_eap(struct iked *, struct iked_sa *, + struct iked_message *); +int ikev2_resp_ike_eap_mschap(struct iked *, struct iked_sa *, + struct iked_message *); int ikev2_resp_ike_auth(struct iked *, struct iked_sa *); -int ikev2_resp_ike_eap(struct iked *, struct iked_sa *, struct ibuf *); int ikev2_send_auth_failed(struct iked *, struct iked_sa *); int ikev2_send_error(struct iked *, struct iked_sa *, struct iked_message *, uint8_t); @@ -2592,6 +2596,18 @@ ikev2_resp_recv(struct iked *env, struct iked_message *msg, return; } + /* Handle EAP authentication */ + if (msg->msg_eap.eam_found) { + if (ikev2_resp_ike_eap(env, sa, msg)) { + log_info("%s: failed eap response", + SPI_SA(sa, __func__)); + ikev2_ike_sa_setreason(sa, "EAP failed"); + sa_state(env, sa, IKEV2_STATE_CLOSED); + return; + } + return; + } + if (ikev2_ike_auth_recv(env, sa, msg) != 0) { log_debug("%s: failed to send auth response", __func__); ikev2_send_error(env, sa, msg, hdr->ike_exchange); @@ -3136,6 +3152,105 @@ ikev2_handle_certreq(struct iked* env, struct iked_message *msg) return (0); } +int +ikev2_resp_ike_eap_mschap(struct iked *env, struct iked_sa *sa, + struct iked_message *msg) +{ + uint8_t successmsg[EAP_MSCHAP_SUCCESS_SZ]; + uint8_t ntresponse[EAP_MSCHAP_NTRESPONSE_SZ]; + struct eap_msg *eap = &msg->msg_eap; + struct iked_user *usr; + uint8_t *pass; + char *name = NULL; + size_t passlen; + int ret; + + switch (eap->eam_state) { + case EAP_STATE_IDENTITY: + sa->sa_eapid = eap->eam_identity; + return (eap_challenge_request(env, sa, eap->eam_id)); + case EAP_STATE_MSCHAPV2_CHALLENGE: + if (eap->eam_user) { + name = eap->eam_user; + } else if (sa->sa_eapid) { + name = sa->sa_eapid; + } + if (name == NULL) { + log_info("%s: invalid response name", + SPI_SA(sa, __func__)); + return (-1); + } + if ((usr = user_lookup(env, name)) == NULL) { + log_info("%s: unknown user '%s'", SPI_SA(sa, __func__), + name); + return (-1); + } + + if ((pass = string2unicode(usr->usr_pass, &passlen)) == NULL) + return (-1); + + mschap_nt_response(ibuf_data(sa->sa_eap.id_buf), + eap->eam_challenge, usr->usr_name, strlen(usr->usr_name), + pass, passlen, ntresponse); + + if (memcmp(ntresponse, eap->eam_ntresponse, + sizeof(ntresponse)) != 0) { + log_info("%s: '%s' authentication failed", + SPI_SA(sa, __func__), usr->usr_name); + free(pass); + + /* XXX should we send an EAP failure packet? */ + return (-1); + } + + bzero(&successmsg, sizeof(successmsg)); + + mschap_auth_response(pass, passlen, + ntresponse, ibuf_data(sa->sa_eap.id_buf), + eap->eam_challenge, usr->usr_name, strlen(usr->usr_name), + successmsg); + if ((sa->sa_eapmsk = ibuf_new(NULL, MSCHAP_MSK_SZ)) == NULL) { + log_info("%s: failed to get MSK", SPI_SA(sa, __func__)); + free(pass); + return (-1); + } + mschap_msk(pass, passlen, ntresponse, + ibuf_data(sa->sa_eapmsk)); + free(pass); + + log_info("%s: '%s' authenticated", __func__, usr->usr_name); + + ret = eap_mschap_challenge(env, sa, eap->eam_id, eap->eam_msrid, + successmsg, EAP_MSCHAP_SUCCESS_SZ); + if (ret == 0) + sa_state(env, sa, IKEV2_STATE_AUTH_SUCCESS); + break; + case EAP_STATE_MSCHAPV2_SUCCESS: + return (eap_mschap_success(env, sa, eap->eam_id)); + case EAP_STATE_SUCCESS: + if (!sa_stateok(sa, IKEV2_STATE_AUTH_SUCCESS)) + return (-1); + return (eap_success(env, sa, msg->msg_eap.eam_id)); + default: + log_info("%s: eap ignored.", __func__); + break; + } + return 0; +} + +int +ikev2_resp_ike_eap(struct iked *env, struct iked_sa *sa, + struct iked_message *msg) +{ + if (!sa_stateok(sa, IKEV2_STATE_EAP)) + return (-1); + + switch (sa->sa_policy->pol_auth.auth_eap) { + case EAP_TYPE_MSCHAP_V2: + return ikev2_resp_ike_eap_mschap(env, sa, msg); + } + return -1; +} int ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa) @@ -3153,7 +3268,7 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa) return (-1); if (sa->sa_state == IKEV2_STATE_EAP) - return (ikev2_resp_ike_eap(env, sa, NULL)); + return (eap_identity_request(env, sa)); if (!sa_stateok(sa, IKEV2_STATE_VALID)) return (0); /* ignore */ @@ -3284,91 +3399,6 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa) } int -ikev2_resp_ike_eap(struct iked *env, struct iked_sa *sa, struct ibuf *eapmsg) -{ - struct ikev2_payload *pld; - struct ikev2_cert *cert; - struct ikev2_auth *auth; - struct iked_id *id, *certid; - struct ibuf *e = NULL; - uint8_t firstpayload; - int ret = -1; - ssize_t len = 0; - - /* Responder only */ - if (sa->sa_hdr.sh_initiator) - return (-1); - - /* Check if "ca" has done it's job yet */ - if (!sa->sa_localauth.id_type) - return (0); - - /* New encrypted message buffer */ - if ((e = ibuf_static()) == NULL) - goto done; - - id = &sa->sa_rid; - certid = &sa->sa_rcert; - - /* ID payload */ - if ((pld = ikev2_add_payload(e)) == NULL) - goto done; - firstpayload = IKEV2_PAYLOAD_IDr; - if (ibuf_cat(e, id->id_buf) != 0) - goto done; - len = ibuf_size(id->id_buf); - - if ((sa->sa_statevalid & IKED_REQ_CERT) && - (certid->id_type != IKEV2_CERT_NONE)) { - if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CERT) == -1) - goto done; - - /* CERT payload */ - if ((pld = ikev2_add_payload(e)) == NULL) - goto done; - if ((cert = ibuf_advance(e, sizeof(*cert))) == NULL) - goto done; - cert->cert_type = certid->id_type; - if (ibuf_cat(e, certid->id_buf) != 0) - goto done; - len = ibuf_size(certid->id_buf) + sizeof(*cert); - } - - if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH) == -1) - goto done; - - /* AUTH payload */ - if ((pld = ikev2_add_payload(e)) == NULL) - goto done; - if ((auth = ibuf_advance(e, sizeof(*auth))) == NULL) - goto done; - auth->auth_method = sa->sa_localauth.id_type; - if (ibuf_cat(e, sa->sa_localauth.id_buf) != 0) - goto done; - len = ibuf_size(sa->sa_localauth.id_buf) + sizeof(*auth); - - if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_EAP) == -1) - goto done; - - /* EAP payload */ - if ((pld = ikev2_add_payload(e)) == NULL) - goto done; - if ((len = eap_identity_request(e)) == -1) - goto done; - - if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE) == -1) - goto done; - - ret = ikev2_msg_send_encrypt(env, sa, &e, - IKEV2_EXCHANGE_IKE_AUTH, firstpayload, 1); - - done: - ibuf_release(e); - - return (ret); -} - -int ikev2_send_ike_e(struct iked *env, struct iked_sa *sa, struct ibuf *buf, uint8_t firstpayload, uint8_t exchange, int response) { diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c index f4196af0ff6..0c0b17e4e29 100644 --- a/sbin/iked/ikev2_pld.c +++ b/sbin/iked/ikev2_pld.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_pld.c,v 1.94 2020/08/20 19:28:01 tobhe Exp $ */ +/* $OpenBSD: ikev2_pld.c,v 1.95 2020/09/16 21:37:35 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> @@ -2005,8 +2005,9 @@ ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld, eap->eap_id, betoh16(eap->eap_length), print_map(eap->eap_type, eap_type_map)); - if (eap_parse(env, sa, eap, msg->msg_response) == -1) + if (eap_parse(env, sa, msg, eap, msg->msg_response) == -1) return (-1); + msg->msg_parent->msg_eap.eam_found = 1; } return (0); |