summaryrefslogtreecommitdiff
path: root/sbin/iked
diff options
context:
space:
mode:
authortobhe <tobhe@cvs.openbsd.org>2020-09-16 21:37:36 +0000
committertobhe <tobhe@cvs.openbsd.org>2020-09-16 21:37:36 +0000
commitacb9e6b38f7641e071bd548338ce93c9b3314e82 (patch)
tree97b0dca1a183f0ead93360cdce04d9577a2d103a /sbin/iked
parent9e307b29862ebf9bc1d5e591bf93c6115aee9352 (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.c330
-rw-r--r--sbin/iked/eap.h4
-rw-r--r--sbin/iked/iked.h32
-rw-r--r--sbin/iked/ikev2.c206
-rw-r--r--sbin/iked/ikev2_pld.c5
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);