|
@@ -445,62 +445,6 @@ static struct wpabuf * eap_ttls_build_start(struct eap_sm *sm,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-static struct wpabuf * eap_ttls_build_req(struct eap_sm *sm,
|
|
|
|
- struct eap_ttls_data *data, u8 id)
|
|
|
|
-{
|
|
|
|
- int res;
|
|
|
|
- struct wpabuf *req;
|
|
|
|
-
|
|
|
|
- res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_TTLS,
|
|
|
|
- data->ttls_version, id, &req);
|
|
|
|
-
|
|
|
|
- if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
|
|
|
|
- wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, starting "
|
|
|
|
- "Phase2");
|
|
|
|
- eap_ttls_state(data, PHASE2_START);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (res == 1)
|
|
|
|
- return eap_server_tls_build_ack(id, EAP_TYPE_TTLS,
|
|
|
|
- data->ttls_version);
|
|
|
|
- return req;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-static struct wpabuf * eap_ttls_encrypt(struct eap_sm *sm,
|
|
|
|
- struct eap_ttls_data *data,
|
|
|
|
- u8 id, u8 *plain, size_t plain_len)
|
|
|
|
-{
|
|
|
|
- int res;
|
|
|
|
- struct wpabuf *buf;
|
|
|
|
-
|
|
|
|
- /* TODO: add support for fragmentation, if needed. This will need to
|
|
|
|
- * add TLS Message Length field, if the frame is fragmented. */
|
|
|
|
- buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS,
|
|
|
|
- 1 + data->ssl.tls_out_limit,
|
|
|
|
- EAP_CODE_REQUEST, id);
|
|
|
|
- if (buf == NULL)
|
|
|
|
- return NULL;
|
|
|
|
-
|
|
|
|
- wpabuf_put_u8(buf, data->ttls_version);
|
|
|
|
-
|
|
|
|
- res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
|
|
|
|
- plain, plain_len, wpabuf_put(buf, 0),
|
|
|
|
- data->ssl.tls_out_limit);
|
|
|
|
- if (res < 0) {
|
|
|
|
- wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 "
|
|
|
|
- "data");
|
|
|
|
- wpabuf_free(buf);
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- wpabuf_put(buf, res);
|
|
|
|
- eap_update_len(buf);
|
|
|
|
-
|
|
|
|
- return buf;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
static struct wpabuf * eap_ttls_build_phase2_eap_req(
|
|
static struct wpabuf * eap_ttls_build_phase2_eap_req(
|
|
struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
|
|
struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
|
|
{
|
|
{
|
|
@@ -528,7 +472,7 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
|
|
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase "
|
|
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase "
|
|
"2 data", req, req_len);
|
|
"2 data", req, req_len);
|
|
|
|
|
|
- encr_req = eap_ttls_encrypt(sm, data, id, req, req_len);
|
|
|
|
|
|
+ encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
|
|
wpabuf_free(buf);
|
|
wpabuf_free(buf);
|
|
|
|
|
|
return encr_req;
|
|
return encr_req;
|
|
@@ -536,7 +480,7 @@ static struct wpabuf * eap_ttls_build_phase2_eap_req(
|
|
|
|
|
|
|
|
|
|
static struct wpabuf * eap_ttls_build_phase2_mschapv2(
|
|
static struct wpabuf * eap_ttls_build_phase2_mschapv2(
|
|
- struct eap_sm *sm, struct eap_ttls_data *data, u8 id)
|
|
|
|
|
|
+ struct eap_sm *sm, struct eap_ttls_data *data)
|
|
{
|
|
{
|
|
struct wpabuf *encr_req;
|
|
struct wpabuf *encr_req;
|
|
u8 *req, *pos, *end;
|
|
u8 *req, *pos, *end;
|
|
@@ -570,7 +514,7 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2(
|
|
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
|
|
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 "
|
|
"data", req, req_len);
|
|
"data", req, req_len);
|
|
|
|
|
|
- encr_req = eap_ttls_encrypt(sm, data, id, req, req_len);
|
|
|
|
|
|
+ encr_req = eap_server_tls_encrypt(sm, &data->ssl, req, req_len);
|
|
os_free(req);
|
|
os_free(req);
|
|
|
|
|
|
return encr_req;
|
|
return encr_req;
|
|
@@ -578,20 +522,16 @@ static struct wpabuf * eap_ttls_build_phase2_mschapv2(
|
|
|
|
|
|
|
|
|
|
static struct wpabuf * eap_ttls_build_phase_finished(
|
|
static struct wpabuf * eap_ttls_build_phase_finished(
|
|
- struct eap_sm *sm, struct eap_ttls_data *data, u8 id, int final)
|
|
|
|
|
|
+ struct eap_sm *sm, struct eap_ttls_data *data, int final)
|
|
{
|
|
{
|
|
int len;
|
|
int len;
|
|
struct wpabuf *req;
|
|
struct wpabuf *req;
|
|
const int max_len = 300;
|
|
const int max_len = 300;
|
|
|
|
|
|
- len = 1 + max_len;
|
|
|
|
- req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, len,
|
|
|
|
- EAP_CODE_REQUEST, id);
|
|
|
|
|
|
+ req = wpabuf_alloc(max_len);
|
|
if (req == NULL)
|
|
if (req == NULL)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
- wpabuf_put_u8(req, data->ttls_version);
|
|
|
|
-
|
|
|
|
len = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
|
|
len = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
|
|
data->ssl.conn, final,
|
|
data->ssl.conn, final,
|
|
wpabuf_mhead(req),
|
|
wpabuf_mhead(req),
|
|
@@ -601,7 +541,6 @@ static struct wpabuf * eap_ttls_build_phase_finished(
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
wpabuf_put(req, len);
|
|
wpabuf_put(req, len);
|
|
- eap_update_len(req);
|
|
|
|
|
|
|
|
return req;
|
|
return req;
|
|
}
|
|
}
|
|
@@ -611,22 +550,50 @@ static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id)
|
|
{
|
|
{
|
|
struct eap_ttls_data *data = priv;
|
|
struct eap_ttls_data *data = priv;
|
|
|
|
|
|
|
|
+ if (data->ssl.state == FRAG_ACK) {
|
|
|
|
+ return eap_server_tls_build_ack(id, EAP_TYPE_TTLS,
|
|
|
|
+ data->ttls_version);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (data->ssl.state == WAIT_FRAG_ACK) {
|
|
|
|
+ return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS,
|
|
|
|
+ data->ttls_version, id);
|
|
|
|
+ }
|
|
|
|
+
|
|
switch (data->state) {
|
|
switch (data->state) {
|
|
case START:
|
|
case START:
|
|
return eap_ttls_build_start(sm, data, id);
|
|
return eap_ttls_build_start(sm, data, id);
|
|
case PHASE1:
|
|
case PHASE1:
|
|
- return eap_ttls_build_req(sm, data, id);
|
|
|
|
|
|
+ if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
|
|
|
|
+ wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase1 done, "
|
|
|
|
+ "starting Phase2");
|
|
|
|
+ eap_ttls_state(data, PHASE2_START);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
case PHASE2_METHOD:
|
|
case PHASE2_METHOD:
|
|
- return eap_ttls_build_phase2_eap_req(sm, data, id);
|
|
|
|
|
|
+ wpabuf_free(data->ssl.out_buf);
|
|
|
|
+ data->ssl.out_used = 0;
|
|
|
|
+ data->ssl.out_buf = eap_ttls_build_phase2_eap_req(sm, data,
|
|
|
|
+ id);
|
|
|
|
+ break;
|
|
case PHASE2_MSCHAPV2_RESP:
|
|
case PHASE2_MSCHAPV2_RESP:
|
|
- return eap_ttls_build_phase2_mschapv2(sm, data, id);
|
|
|
|
|
|
+ wpabuf_free(data->ssl.out_buf);
|
|
|
|
+ data->ssl.out_used = 0;
|
|
|
|
+ data->ssl.out_buf = eap_ttls_build_phase2_mschapv2(sm, data);
|
|
|
|
+ break;
|
|
case PHASE_FINISHED:
|
|
case PHASE_FINISHED:
|
|
- return eap_ttls_build_phase_finished(sm, data, id, 1);
|
|
|
|
|
|
+ wpabuf_free(data->ssl.out_buf);
|
|
|
|
+ data->ssl.out_used = 0;
|
|
|
|
+ data->ssl.out_buf = eap_ttls_build_phase_finished(sm, data, 1);
|
|
|
|
+ break;
|
|
default:
|
|
default:
|
|
wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
|
|
wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d",
|
|
__func__, data->state);
|
|
__func__, data->state);
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_TTLS,
|
|
|
|
+ data->ttls_version, id);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1148,12 +1115,17 @@ static void eap_ttls_process_phase2_eap(struct eap_sm *sm,
|
|
|
|
|
|
static void eap_ttls_process_phase2(struct eap_sm *sm,
|
|
static void eap_ttls_process_phase2(struct eap_sm *sm,
|
|
struct eap_ttls_data *data,
|
|
struct eap_ttls_data *data,
|
|
- u8 *in_data, size_t in_len)
|
|
|
|
|
|
+ struct wpabuf *in_buf)
|
|
{
|
|
{
|
|
u8 *in_decrypted;
|
|
u8 *in_decrypted;
|
|
- int len_decrypted, res;
|
|
|
|
|
|
+ int len_decrypted;
|
|
struct eap_ttls_avp parse;
|
|
struct eap_ttls_avp parse;
|
|
size_t buf_len;
|
|
size_t buf_len;
|
|
|
|
+ u8 *in_data;
|
|
|
|
+ size_t in_len;
|
|
|
|
+
|
|
|
|
+ in_data = wpabuf_mhead(in_buf);
|
|
|
|
+ in_len = wpabuf_len(in_buf);
|
|
|
|
|
|
wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
|
|
wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
|
|
" Phase 2", (unsigned long) in_len);
|
|
" Phase 2", (unsigned long) in_len);
|
|
@@ -1169,14 +1141,7 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- res = eap_server_tls_data_reassemble(sm, &data->ssl, &in_data,
|
|
|
|
- &in_len);
|
|
|
|
- if (res < 0 || res == 1)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
buf_len = in_len;
|
|
buf_len = in_len;
|
|
- if (data->ssl.tls_in_total > buf_len)
|
|
|
|
- buf_len = data->ssl.tls_in_total;
|
|
|
|
/*
|
|
/*
|
|
* Even though we try to disable TLS compression, it is possible that
|
|
* Even though we try to disable TLS compression, it is possible that
|
|
* this cannot be done with all TLS libraries. Add extra buffer space
|
|
* this cannot be done with all TLS libraries. Add extra buffer space
|
|
@@ -1187,9 +1152,6 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
|
|
buf_len *= 3;
|
|
buf_len *= 3;
|
|
in_decrypted = os_malloc(buf_len);
|
|
in_decrypted = os_malloc(buf_len);
|
|
if (in_decrypted == NULL) {
|
|
if (in_decrypted == NULL) {
|
|
- os_free(data->ssl.tls_in);
|
|
|
|
- data->ssl.tls_in = NULL;
|
|
|
|
- data->ssl.tls_in_len = 0;
|
|
|
|
wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "
|
|
wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "
|
|
"for decryption");
|
|
"for decryption");
|
|
return;
|
|
return;
|
|
@@ -1198,9 +1160,6 @@ static void eap_ttls_process_phase2(struct eap_sm *sm,
|
|
len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
|
|
len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
|
|
in_data, in_len,
|
|
in_data, in_len,
|
|
in_decrypted, buf_len);
|
|
in_decrypted, buf_len);
|
|
- os_free(data->ssl.tls_in);
|
|
|
|
- data->ssl.tls_in = NULL;
|
|
|
|
- data->ssl.tls_in_len = 0;
|
|
|
|
if (len_decrypted < 0) {
|
|
if (len_decrypted < 0) {
|
|
wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
|
|
wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
|
|
"data");
|
|
"data");
|
|
@@ -1313,6 +1272,29 @@ static void eap_ttls_start_tnc(struct eap_sm *sm, struct eap_ttls_data *data)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+static void eap_ttls_process_version(struct eap_sm *sm,
|
|
|
|
+ struct eap_ttls_data *data,
|
|
|
|
+ int peer_version)
|
|
|
|
+{
|
|
|
|
+ if (peer_version < data->ttls_version) {
|
|
|
|
+ wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; "
|
|
|
|
+ "use version %d",
|
|
|
|
+ peer_version, data->ttls_version, peer_version);
|
|
|
|
+ data->ttls_version = peer_version;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (data->ttls_version > 0 && !data->tls_ia_configured) {
|
|
|
|
+ if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) {
|
|
|
|
+ wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable "
|
|
|
|
+ "TLS/IA");
|
|
|
|
+ eap_ttls_state(data, FAILURE);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ data->tls_ia_configured = 1;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
static void eap_ttls_process(struct eap_sm *sm, void *priv,
|
|
static void eap_ttls_process(struct eap_sm *sm, void *priv,
|
|
struct wpabuf *respData)
|
|
struct wpabuf *respData)
|
|
{
|
|
{
|
|
@@ -1320,8 +1302,7 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv,
|
|
const u8 *pos;
|
|
const u8 *pos;
|
|
u8 flags;
|
|
u8 flags;
|
|
size_t left;
|
|
size_t left;
|
|
- unsigned int tls_msg_len;
|
|
|
|
- int peer_version;
|
|
|
|
|
|
+ int ret;
|
|
|
|
|
|
pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData,
|
|
pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData,
|
|
&left);
|
|
&left);
|
|
@@ -1332,59 +1313,25 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv,
|
|
wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - "
|
|
wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - "
|
|
"Flags 0x%02x", (unsigned long) wpabuf_len(respData),
|
|
"Flags 0x%02x", (unsigned long) wpabuf_len(respData),
|
|
flags);
|
|
flags);
|
|
- peer_version = flags & EAP_PEAP_VERSION_MASK;
|
|
|
|
- if (peer_version < data->ttls_version) {
|
|
|
|
- wpa_printf(MSG_DEBUG, "EAP-TTLS: peer ver=%d, own ver=%d; "
|
|
|
|
- "use version %d",
|
|
|
|
- peer_version, data->ttls_version, peer_version);
|
|
|
|
- data->ttls_version = peer_version;
|
|
|
|
- }
|
|
|
|
|
|
|
|
- if (data->ttls_version > 0 && !data->tls_ia_configured) {
|
|
|
|
- if (tls_connection_set_ia(sm->ssl_ctx, data->ssl.conn, 1)) {
|
|
|
|
- wpa_printf(MSG_INFO, "EAP-TTLS: Failed to enable "
|
|
|
|
- "TLS/IA");
|
|
|
|
- eap_ttls_state(data, FAILURE);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- data->tls_ia_configured = 1;
|
|
|
|
- }
|
|
|
|
|
|
+ eap_ttls_process_version(sm, data, flags & EAP_PEAP_VERSION_MASK);
|
|
|
|
|
|
- if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
|
|
|
|
- if (left < 4) {
|
|
|
|
- wpa_printf(MSG_INFO, "EAP-TTLS: Short frame with TLS "
|
|
|
|
- "length");
|
|
|
|
- eap_ttls_state(data, FAILURE);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- tls_msg_len = WPA_GET_BE32(pos);
|
|
|
|
- wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS Message Length: %d",
|
|
|
|
- tls_msg_len);
|
|
|
|
- if (data->ssl.tls_in_left == 0) {
|
|
|
|
- data->ssl.tls_in_total = tls_msg_len;
|
|
|
|
- data->ssl.tls_in_left = tls_msg_len;
|
|
|
|
- os_free(data->ssl.tls_in);
|
|
|
|
- data->ssl.tls_in = NULL;
|
|
|
|
- data->ssl.tls_in_len = 0;
|
|
|
|
- }
|
|
|
|
- pos += 4;
|
|
|
|
- left -= 4;
|
|
|
|
- }
|
|
|
|
|
|
+ ret = eap_server_tls_reassemble(&data->ssl, flags, &pos, &left);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ eap_ttls_state(data, FAILURE);
|
|
|
|
+ return;
|
|
|
|
+ } else if (ret == 1)
|
|
|
|
+ return;
|
|
|
|
|
|
switch (data->state) {
|
|
switch (data->state) {
|
|
case PHASE1:
|
|
case PHASE1:
|
|
- if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) <
|
|
|
|
- 0) {
|
|
|
|
- wpa_printf(MSG_INFO, "EAP-TTLS: TLS processing "
|
|
|
|
- "failed");
|
|
|
|
|
|
+ if (eap_server_tls_phase1(sm, &data->ssl) < 0)
|
|
eap_ttls_state(data, FAILURE);
|
|
eap_ttls_state(data, FAILURE);
|
|
- }
|
|
|
|
break;
|
|
break;
|
|
case PHASE2_START:
|
|
case PHASE2_START:
|
|
case PHASE2_METHOD:
|
|
case PHASE2_METHOD:
|
|
case PHASE_FINISHED:
|
|
case PHASE_FINISHED:
|
|
- /* FIX: get rid of const->non-const typecast */
|
|
|
|
- eap_ttls_process_phase2(sm, data, (u8 *) pos, left);
|
|
|
|
|
|
+ eap_ttls_process_phase2(sm, data, data->ssl.in_buf);
|
|
eap_ttls_start_tnc(sm, data);
|
|
eap_ttls_start_tnc(sm, data);
|
|
break;
|
|
break;
|
|
case PHASE2_MSCHAPV2_RESP:
|
|
case PHASE2_MSCHAPV2_RESP:
|
|
@@ -1417,6 +1364,8 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv,
|
|
"in TLS processing");
|
|
"in TLS processing");
|
|
eap_ttls_state(data, FAILURE);
|
|
eap_ttls_state(data, FAILURE);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ eap_server_tls_free_in_buf(&data->ssl);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|