1 /*
2 * EAP peer method: EAP-GTC (RFC 3748)
3 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eap_i.h"
19
20
21 struct eap_gtc_data {
22 int prefix;
23 };
24
25
eap_gtc_init(struct eap_sm * sm)26 static void * eap_gtc_init(struct eap_sm *sm)
27 {
28 struct eap_gtc_data *data;
29 data = os_zalloc(sizeof(*data));
30 if (data == NULL)
31 return NULL;
32
33 if (sm->m && sm->m->method == EAP_TYPE_FAST) {
34 wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
35 "with challenge/response");
36 data->prefix = 1;
37 }
38 return data;
39 }
40
41
eap_gtc_deinit(struct eap_sm * sm,void * priv)42 static void eap_gtc_deinit(struct eap_sm *sm, void *priv)
43 {
44 struct eap_gtc_data *data = priv;
45 os_free(data);
46 }
47
48
eap_gtc_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const u8 * reqData,size_t reqDataLen,size_t * respDataLen)49 static u8 * eap_gtc_process(struct eap_sm *sm, void *priv,
50 struct eap_method_ret *ret,
51 const u8 *reqData, size_t reqDataLen,
52 size_t *respDataLen)
53 {
54 struct eap_gtc_data *data = priv;
55 const struct eap_hdr *req;
56 struct eap_hdr *resp;
57 const u8 *pos, *password, *identity;
58 u8 *rpos;
59 size_t password_len, identity_len, len, plen;
60 int otp;
61
62 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC,
63 reqData, reqDataLen, &len);
64 if (pos == NULL) {
65 ret->ignore = TRUE;
66 return NULL;
67 }
68 req = (const struct eap_hdr *) reqData;
69
70 wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len);
71 if (data->prefix &&
72 (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) {
73 wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with "
74 "expected prefix");
75
76 /* Send an empty response in order to allow tunneled
77 * acknowledgement of the failure. This will also cover the
78 * error case which seems to use EAP-MSCHAPv2 like error
79 * reporting with EAP-GTC inside EAP-FAST tunnel. */
80 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC,
81 respDataLen, 0, EAP_CODE_RESPONSE,
82 req->identifier, NULL);
83 return (u8 *) resp;
84 }
85
86 password = eap_get_config_otp(sm, &password_len);
87 if (password)
88 otp = 1;
89 else {
90 password = eap_get_config_password(sm, &password_len);
91 otp = 0;
92 }
93
94 if (password == NULL) {
95 wpa_printf(MSG_INFO, "EAP-GTC: Password not configured");
96 eap_sm_request_otp(sm, (const char *) pos, len);
97 ret->ignore = TRUE;
98 return NULL;
99 }
100
101 ret->ignore = FALSE;
102
103 ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE;
104 ret->decision = DECISION_COND_SUCC;
105 ret->allowNotifications = FALSE;
106
107 plen = password_len;
108 identity = eap_get_config_identity(sm, &identity_len);
109 if (identity == NULL)
110 return NULL;
111 if (data->prefix)
112 plen += 9 + identity_len + 1;
113 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, respDataLen,
114 plen, EAP_CODE_RESPONSE, req->identifier, &rpos);
115 if (resp == NULL)
116 return NULL;
117 if (data->prefix) {
118 os_memcpy(rpos, "RESPONSE=", 9);
119 rpos += 9;
120 os_memcpy(rpos, identity, identity_len);
121 rpos += identity_len;
122 *rpos++ = '\0';
123 }
124 os_memcpy(rpos, password, password_len);
125 wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response",
126 (u8 *) (resp + 1) + 1, plen);
127
128 if (otp) {
129 wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password");
130 eap_clear_config_otp(sm);
131 }
132
133 return (u8 *) resp;
134 }
135
136
eap_peer_gtc_register(void)137 int eap_peer_gtc_register(void)
138 {
139 struct eap_method *eap;
140 int ret;
141
142 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
143 EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
144 if (eap == NULL)
145 return -1;
146
147 eap->init = eap_gtc_init;
148 eap->deinit = eap_gtc_deinit;
149 eap->process = eap_gtc_process;
150
151 ret = eap_peer_method_register(eap);
152 if (ret)
153 eap_peer_method_free(eap);
154 return ret;
155 }
156