54
50
static u8 * eap_gtc_process(struct eap_sm *sm, void *priv,
55
51
struct eap_method_ret *ret,
56
u8 *reqData, size_t reqDataLen,
52
const u8 *reqData, size_t reqDataLen,
57
53
size_t *respDataLen)
59
55
struct eap_gtc_data *data = priv;
60
struct wpa_ssid *config = eap_get_config(sm);
61
struct eap_hdr *req, *resp;
63
size_t password_len, len, msg_len;
56
const struct eap_hdr *req;
58
const u8 *pos, *password, *identity;
60
size_t password_len, identity_len, len, plen;
65
req = (struct eap_hdr *) reqData;
66
pos = (u8 *) (req + 1);
67
if (reqDataLen < sizeof(*req) + 1 || *pos != EAP_TYPE_GTC ||
68
(len = be_to_host16(req->length)) > reqDataLen) {
69
wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame");
63
pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC,
64
reqData, reqDataLen, &len);
70
66
ret->ignore = TRUE;
74
msg_len = len - sizeof(*req) - 1;
75
wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message",
69
req = (const struct eap_hdr *) reqData;
71
wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len);
77
72
if (data->prefix &&
78
(msg_len < 10 || memcmp(pos, "CHALLENGE=", 10) != 0)) {
73
(len < 10 || memcmp(pos, "CHALLENGE=", 10) != 0)) {
79
74
wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with "
80
75
"expected prefix");
83
78
* acknowledgement of the failure. This will also cover the
84
79
* error case which seems to use EAP-MSCHAPv2 like error
85
80
* reporting with EAP-GTC inside EAP-FAST tunnel. */
86
*respDataLen = sizeof(struct eap_hdr) + 1;
87
resp = malloc(*respDataLen);
90
resp->code = EAP_CODE_RESPONSE;
91
resp->identifier = req->identifier;
92
resp->length = host_to_be16(*respDataLen);
93
pos = (u8 *) (resp + 1);
94
*pos++ = EAP_TYPE_GTC;
81
resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC,
82
respDataLen, 0, EAP_CODE_RESPONSE,
83
req->identifier, NULL);
95
84
return (u8 *) resp;
99
(config->password == NULL && config->otp == NULL)) {
87
password = eap_get_config_otp(sm, &password_len);
91
password = eap_get_config_password(sm, &password_len);
95
if (password == NULL) {
100
96
wpa_printf(MSG_INFO, "EAP-GTC: Password not configured");
101
eap_sm_request_otp(sm, config, (char *) pos,
102
len - sizeof(*req) - 1);
97
eap_sm_request_otp(sm, (const char *) pos, len);
103
98
ret->ignore = TRUE;
108
password = config->otp;
109
password_len = config->otp_len;
111
password = config->password;
112
password_len = config->password_len;
115
102
ret->ignore = FALSE;
117
104
ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE;
118
105
ret->decision = DECISION_COND_SUCC;
119
106
ret->allowNotifications = FALSE;
121
*respDataLen = sizeof(struct eap_hdr) + 1 + password_len;
123
*respDataLen += 9 + config->identity_len + 1;
125
resp = malloc(*respDataLen);
109
identity = eap_get_config_identity(sm, &identity_len);
111
plen += 9 + identity_len + 1;
112
resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, respDataLen,
113
plen, EAP_CODE_RESPONSE, req->identifier, &rpos);
126
114
if (resp == NULL)
128
resp->code = EAP_CODE_RESPONSE;
129
resp->identifier = req->identifier;
130
resp->length = host_to_be16(*respDataLen);
131
pos = (u8 *) (resp + 1);
132
*pos++ = EAP_TYPE_GTC;
133
116
if (data->prefix) {
134
memcpy(pos, "RESPONSE=", 9);
136
memcpy(pos, config->identity, config->identity_len);
137
pos += config->identity_len;
117
memcpy(rpos, "RESPONSE=", 9);
119
memcpy(rpos, identity, identity_len);
120
rpos += identity_len;
140
memcpy(pos, password, password_len);
123
memcpy(rpos, password, password_len);
141
124
wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response",
142
(u8 *) (resp + 1) + 1,
143
*respDataLen - sizeof(struct eap_hdr) - 1);
125
(u8 *) (resp + 1) + 1, plen);
146
128
wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password");
147
memset(config->otp, 0, config->otp_len);
129
eap_clear_config_otp(sm);
153
132
return (u8 *) resp;
157
const struct eap_method eap_method_gtc =
136
int eap_peer_gtc_register(void)
159
.method = EAP_TYPE_GTC,
161
.init = eap_gtc_init,
162
.deinit = eap_gtc_deinit,
163
.process = eap_gtc_process,
138
struct eap_method *eap;
141
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
142
EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
146
eap->init = eap_gtc_init;
147
eap->deinit = eap_gtc_deinit;
148
eap->process = eap_gtc_process;
150
ret = eap_peer_method_register(eap);
152
eap_peer_method_free(eap);