EAP-TEAP server: Allow a specific Identity-Type to be requested/required
The new hostapd configuration parameter eap_teap_id can be used to configure the expected behavior for used identity type. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
f186ec54c3
commit
e54cfbb56a
9 changed files with 98 additions and 12 deletions
|
@ -2622,6 +2622,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
bss->eap_teap_pac_no_inner = atoi(pos);
|
bss->eap_teap_pac_no_inner = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "eap_teap_separate_result") == 0) {
|
} else if (os_strcmp(buf, "eap_teap_separate_result") == 0) {
|
||||||
bss->eap_teap_separate_result = atoi(pos);
|
bss->eap_teap_separate_result = atoi(pos);
|
||||||
|
} else if (os_strcmp(buf, "eap_teap_id") == 0) {
|
||||||
|
bss->eap_teap_id = atoi(pos);
|
||||||
#endif /* EAP_SERVER_TEAP */
|
#endif /* EAP_SERVER_TEAP */
|
||||||
#ifdef EAP_SERVER_SIM
|
#ifdef EAP_SERVER_SIM
|
||||||
} else if (os_strcmp(buf, "eap_sim_db") == 0) {
|
} else if (os_strcmp(buf, "eap_sim_db") == 0) {
|
||||||
|
|
|
@ -1206,6 +1206,14 @@ eap_server=0
|
||||||
# 1 = send in a separate message (for testing purposes)
|
# 1 = send in a separate message (for testing purposes)
|
||||||
#eap_teap_separate_result=0
|
#eap_teap_separate_result=0
|
||||||
|
|
||||||
|
# EAP-TEAP identities
|
||||||
|
# 0 = allow any identity type (default)
|
||||||
|
# 1 = require user identity
|
||||||
|
# 2 = require machine identity
|
||||||
|
# 3 = request user identity; accept either user or machine identity
|
||||||
|
# 4 = request machine identity; accept either user or machine identity
|
||||||
|
#eap_teap_id=0
|
||||||
|
|
||||||
# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND
|
# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND
|
||||||
# (default: 0 = disabled).
|
# (default: 0 = disabled).
|
||||||
#eap_sim_aka_result_ind=1
|
#eap_sim_aka_result_ind=1
|
||||||
|
|
|
@ -430,6 +430,7 @@ struct hostapd_bss_config {
|
||||||
int eap_teap_auth;
|
int eap_teap_auth;
|
||||||
int eap_teap_pac_no_inner;
|
int eap_teap_pac_no_inner;
|
||||||
int eap_teap_separate_result;
|
int eap_teap_separate_result;
|
||||||
|
int eap_teap_id;
|
||||||
int eap_sim_aka_result_ind;
|
int eap_sim_aka_result_ind;
|
||||||
int eap_sim_id;
|
int eap_sim_id;
|
||||||
int tnc;
|
int tnc;
|
||||||
|
|
|
@ -123,6 +123,7 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
|
||||||
srv.eap_teap_auth = conf->eap_teap_auth;
|
srv.eap_teap_auth = conf->eap_teap_auth;
|
||||||
srv.eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner;
|
srv.eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner;
|
||||||
srv.eap_teap_separate_result = conf->eap_teap_separate_result;
|
srv.eap_teap_separate_result = conf->eap_teap_separate_result;
|
||||||
|
srv.eap_teap_id = conf->eap_teap_id;
|
||||||
srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
|
srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
|
||||||
srv.eap_sim_id = conf->eap_sim_id;
|
srv.eap_sim_id = conf->eap_sim_id;
|
||||||
srv.tnc = conf->tnc;
|
srv.tnc = conf->tnc;
|
||||||
|
|
|
@ -2433,6 +2433,7 @@ static struct eap_config * ieee802_1x_eap_config(struct hostapd_data *hapd)
|
||||||
cfg->pac_key_refresh_time = hapd->conf->pac_key_refresh_time;
|
cfg->pac_key_refresh_time = hapd->conf->pac_key_refresh_time;
|
||||||
cfg->eap_teap_auth = hapd->conf->eap_teap_auth;
|
cfg->eap_teap_auth = hapd->conf->eap_teap_auth;
|
||||||
cfg->eap_teap_separate_result = hapd->conf->eap_teap_separate_result;
|
cfg->eap_teap_separate_result = hapd->conf->eap_teap_separate_result;
|
||||||
|
cfg->eap_teap_id = hapd->conf->eap_teap_id;
|
||||||
cfg->eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
|
cfg->eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind;
|
||||||
cfg->eap_sim_id = hapd->conf->eap_sim_id;
|
cfg->eap_sim_id = hapd->conf->eap_sim_id;
|
||||||
cfg->tnc = hapd->conf->tnc;
|
cfg->tnc = hapd->conf->tnc;
|
||||||
|
|
|
@ -198,6 +198,13 @@ struct eap_config {
|
||||||
int eap_teap_auth;
|
int eap_teap_auth;
|
||||||
int eap_teap_pac_no_inner;
|
int eap_teap_pac_no_inner;
|
||||||
int eap_teap_separate_result;
|
int eap_teap_separate_result;
|
||||||
|
enum eap_teap_id {
|
||||||
|
EAP_TEAP_ID_ALLOW_ANY = 0,
|
||||||
|
EAP_TEAP_ID_REQUIRE_USER = 1,
|
||||||
|
EAP_TEAP_ID_REQUIRE_MACHINE = 2,
|
||||||
|
EAP_TEAP_ID_REQUEST_USER_ACCEPT_MACHINE = 3,
|
||||||
|
EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER = 4,
|
||||||
|
} eap_teap_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
|
* eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
|
||||||
|
|
|
@ -529,30 +529,56 @@ static struct wpabuf * eap_teap_build_phase2_req(struct eap_sm *sm,
|
||||||
struct eap_teap_data *data,
|
struct eap_teap_data *data,
|
||||||
u8 id)
|
u8 id)
|
||||||
{
|
{
|
||||||
struct wpabuf *req;
|
struct wpabuf *req, *id_tlv = NULL;
|
||||||
|
|
||||||
|
if (sm->cfg->eap_teap_auth == 1 ||
|
||||||
|
(data->phase2_priv && data->phase2_method &&
|
||||||
|
data->phase2_method->vendor == EAP_VENDOR_IETF &&
|
||||||
|
data->phase2_method->method == EAP_TYPE_IDENTITY)) {
|
||||||
|
switch (sm->cfg->eap_teap_id) {
|
||||||
|
case EAP_TEAP_ID_ALLOW_ANY:
|
||||||
|
break;
|
||||||
|
case EAP_TEAP_ID_REQUIRE_USER:
|
||||||
|
case EAP_TEAP_ID_REQUEST_USER_ACCEPT_MACHINE:
|
||||||
|
id_tlv = eap_teap_tlv_identity_type(
|
||||||
|
TEAP_IDENTITY_TYPE_USER);
|
||||||
|
break;
|
||||||
|
case EAP_TEAP_ID_REQUIRE_MACHINE:
|
||||||
|
case EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER:
|
||||||
|
id_tlv = eap_teap_tlv_identity_type(
|
||||||
|
TEAP_IDENTITY_TYPE_MACHINE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sm->cfg->eap_teap_auth == 1) {
|
if (sm->cfg->eap_teap_auth == 1) {
|
||||||
wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate Basic-Password-Auth");
|
wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate Basic-Password-Auth");
|
||||||
req = wpabuf_alloc(sizeof(struct teap_tlv_hdr));
|
req = wpabuf_alloc(sizeof(struct teap_tlv_hdr));
|
||||||
if (!req)
|
if (!req) {
|
||||||
|
wpabuf_free(id_tlv);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
eap_teap_put_tlv_hdr(req, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ, 0);
|
eap_teap_put_tlv_hdr(req, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ, 0);
|
||||||
return req;
|
return wpabuf_concat(req, id_tlv);
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate inner EAP method");
|
wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate inner EAP method");
|
||||||
if (!data->phase2_priv) {
|
if (!data->phase2_priv) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"EAP-TEAP: Phase 2 method not initialized");
|
"EAP-TEAP: Phase 2 method not initialized");
|
||||||
|
wpabuf_free(id_tlv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
req = data->phase2_method->buildReq(sm, data->phase2_priv, id);
|
req = data->phase2_method->buildReq(sm, data->phase2_priv, id);
|
||||||
if (!req)
|
if (!req) {
|
||||||
|
wpabuf_free(id_tlv);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_hexdump_buf_key(MSG_MSGDUMP, "EAP-TEAP: Phase 2 EAP-Request", req);
|
wpa_hexdump_buf_key(MSG_MSGDUMP, "EAP-TEAP: Phase 2 EAP-Request", req);
|
||||||
return eap_teap_tlv_eap_payload(req);
|
|
||||||
|
return wpabuf_concat(eap_teap_tlv_eap_payload(req), id_tlv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -960,9 +986,27 @@ static int eap_teap_phase2_init(struct eap_sm *sm, struct eap_teap_data *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int eap_teap_valid_id_type(struct eap_sm *sm,
|
||||||
|
enum teap_identity_types id_type)
|
||||||
|
{
|
||||||
|
if (sm->cfg->eap_teap_id == EAP_TEAP_ID_REQUIRE_USER &&
|
||||||
|
id_type != TEAP_IDENTITY_TYPE_USER)
|
||||||
|
return 0;
|
||||||
|
if (sm->cfg->eap_teap_id == EAP_TEAP_ID_REQUIRE_MACHINE &&
|
||||||
|
id_type != TEAP_IDENTITY_TYPE_MACHINE)
|
||||||
|
return 0;
|
||||||
|
if (sm->cfg->eap_teap_id != EAP_TEAP_ID_ALLOW_ANY &&
|
||||||
|
id_type != TEAP_IDENTITY_TYPE_USER &&
|
||||||
|
id_type != TEAP_IDENTITY_TYPE_MACHINE)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void eap_teap_process_phase2_response(struct eap_sm *sm,
|
static void eap_teap_process_phase2_response(struct eap_sm *sm,
|
||||||
struct eap_teap_data *data,
|
struct eap_teap_data *data,
|
||||||
u8 *in_data, size_t in_len)
|
u8 *in_data, size_t in_len,
|
||||||
|
enum teap_identity_types id_type)
|
||||||
{
|
{
|
||||||
int next_vendor = EAP_VENDOR_IETF;
|
int next_vendor = EAP_VENDOR_IETF;
|
||||||
enum eap_type next_type = EAP_TYPE_NONE;
|
enum eap_type next_type = EAP_TYPE_NONE;
|
||||||
|
@ -1041,6 +1085,13 @@ static void eap_teap_process_phase2_response(struct eap_sm *sm,
|
||||||
|
|
||||||
switch (data->state) {
|
switch (data->state) {
|
||||||
case PHASE2_ID:
|
case PHASE2_ID:
|
||||||
|
if (!eap_teap_valid_id_type(sm, id_type)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"EAP-TEAP: Provided Identity-Type %u not allowed",
|
||||||
|
id_type);
|
||||||
|
eap_teap_req_failure(data, TEAP_ERROR_INNER_METHOD);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
|
if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
|
||||||
wpa_hexdump_ascii(MSG_DEBUG,
|
wpa_hexdump_ascii(MSG_DEBUG,
|
||||||
"EAP-TEAP: Phase 2 Identity not found in the user database",
|
"EAP-TEAP: Phase 2 Identity not found in the user database",
|
||||||
|
@ -1097,7 +1148,8 @@ static void eap_teap_process_phase2_response(struct eap_sm *sm,
|
||||||
|
|
||||||
static void eap_teap_process_phase2_eap(struct eap_sm *sm,
|
static void eap_teap_process_phase2_eap(struct eap_sm *sm,
|
||||||
struct eap_teap_data *data,
|
struct eap_teap_data *data,
|
||||||
u8 *in_data, size_t in_len)
|
u8 *in_data, size_t in_len,
|
||||||
|
enum teap_identity_types id_type)
|
||||||
{
|
{
|
||||||
struct eap_hdr *hdr;
|
struct eap_hdr *hdr;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -1124,7 +1176,8 @@ static void eap_teap_process_phase2_eap(struct eap_sm *sm,
|
||||||
(unsigned long) len);
|
(unsigned long) len);
|
||||||
switch (hdr->code) {
|
switch (hdr->code) {
|
||||||
case EAP_CODE_RESPONSE:
|
case EAP_CODE_RESPONSE:
|
||||||
eap_teap_process_phase2_response(sm, data, (u8 *) hdr, len);
|
eap_teap_process_phase2_response(sm, data, (u8 *) hdr, len,
|
||||||
|
id_type);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
wpa_printf(MSG_INFO,
|
wpa_printf(MSG_INFO,
|
||||||
|
@ -1137,11 +1190,20 @@ static void eap_teap_process_phase2_eap(struct eap_sm *sm,
|
||||||
|
|
||||||
static void eap_teap_process_basic_auth_resp(struct eap_sm *sm,
|
static void eap_teap_process_basic_auth_resp(struct eap_sm *sm,
|
||||||
struct eap_teap_data *data,
|
struct eap_teap_data *data,
|
||||||
u8 *in_data, size_t in_len)
|
u8 *in_data, size_t in_len,
|
||||||
{
|
enum teap_identity_types id_type)
|
||||||
|
{
|
||||||
u8 *pos, *end, *username, *password, *new_id;
|
u8 *pos, *end, *username, *password, *new_id;
|
||||||
u8 userlen, passlen;
|
u8 userlen, passlen;
|
||||||
|
|
||||||
|
if (!eap_teap_valid_id_type(sm, id_type)) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"EAP-TEAP: Provided Identity-Type %u not allowed",
|
||||||
|
id_type);
|
||||||
|
eap_teap_req_failure(data, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pos = in_data;
|
pos = in_data;
|
||||||
end = pos + in_len;
|
end = pos + in_len;
|
||||||
|
|
||||||
|
@ -1533,7 +1595,8 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eap_teap_process_basic_auth_resp(sm, data, tlv.basic_auth_resp,
|
eap_teap_process_basic_auth_resp(sm, data, tlv.basic_auth_resp,
|
||||||
tlv.basic_auth_resp_len);
|
tlv.basic_auth_resp_len,
|
||||||
|
tlv.identity_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tlv.eap_payload_tlv) {
|
if (tlv.eap_payload_tlv) {
|
||||||
|
@ -1544,7 +1607,8 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eap_teap_process_phase2_eap(sm, data, tlv.eap_payload_tlv,
|
eap_teap_process_phase2_eap(sm, data, tlv.eap_payload_tlv,
|
||||||
tlv.eap_payload_tlv_len);
|
tlv.eap_payload_tlv_len,
|
||||||
|
tlv.identity_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->state == SUCCESS_SEND_RESULT &&
|
if (data->state == SUCCESS_SEND_RESULT &&
|
||||||
|
|
|
@ -2242,6 +2242,7 @@ radius_server_init(struct radius_server_conf *conf)
|
||||||
eap_cfg->eap_teap_auth = conf->eap_teap_auth;
|
eap_cfg->eap_teap_auth = conf->eap_teap_auth;
|
||||||
eap_cfg->eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner;
|
eap_cfg->eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner;
|
||||||
eap_cfg->eap_teap_separate_result = conf->eap_teap_separate_result;
|
eap_cfg->eap_teap_separate_result = conf->eap_teap_separate_result;
|
||||||
|
eap_cfg->eap_teap_id = conf->eap_teap_id;
|
||||||
data->get_eap_user = conf->get_eap_user;
|
data->get_eap_user = conf->get_eap_user;
|
||||||
eap_cfg->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
|
eap_cfg->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
|
||||||
eap_cfg->eap_sim_id = conf->eap_sim_id;
|
eap_cfg->eap_sim_id = conf->eap_sim_id;
|
||||||
|
|
|
@ -131,6 +131,7 @@ struct radius_server_conf {
|
||||||
int eap_teap_auth;
|
int eap_teap_auth;
|
||||||
int eap_teap_pac_no_inner;
|
int eap_teap_pac_no_inner;
|
||||||
int eap_teap_separate_result;
|
int eap_teap_separate_result;
|
||||||
|
int eap_teap_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
|
* eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication
|
||||||
|
|
Loading…
Reference in a new issue