remove @EAP_LDFLAGS@, no longer exists
[mech_eap.orig] / libeap / src / eap_server / eap_server_gtc.c
1 /*
2  * hostapd / 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         enum { CONTINUE, SUCCESS, FAILURE } state;
23         int prefix;
24 };
25
26
27 static void * eap_gtc_init(struct eap_sm *sm)
28 {
29         struct eap_gtc_data *data;
30
31         data = os_zalloc(sizeof(*data));
32         if (data == NULL)
33                 return NULL;
34         data->state = CONTINUE;
35
36 #ifdef EAP_SERVER_FAST
37         if (sm->m && sm->m->vendor == EAP_VENDOR_IETF &&
38             sm->m->method == EAP_TYPE_FAST) {
39                 wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
40                            "with challenge/response");
41                 data->prefix = 1;
42         }
43 #endif /* EAP_SERVER_FAST */
44
45         return data;
46 }
47
48
49 static void eap_gtc_reset(struct eap_sm *sm, void *priv)
50 {
51         struct eap_gtc_data *data = priv;
52         os_free(data);
53 }
54
55
56 static struct wpabuf * eap_gtc_buildReq(struct eap_sm *sm, void *priv, u8 id)
57 {
58         struct eap_gtc_data *data = priv;
59         struct wpabuf *req;
60         char *msg;
61         size_t msg_len;
62
63         msg = data->prefix ? "CHALLENGE=Password" : "Password";
64
65         msg_len = os_strlen(msg);
66         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, msg_len,
67                             EAP_CODE_REQUEST, id);
68         if (req == NULL) {
69                 wpa_printf(MSG_ERROR, "EAP-GTC: Failed to allocate memory for "
70                            "request");
71                 data->state = FAILURE;
72                 return NULL;
73         }
74
75         wpabuf_put_data(req, msg, msg_len);
76
77         data->state = CONTINUE;
78
79         return req;
80 }
81
82
83 static Boolean eap_gtc_check(struct eap_sm *sm, void *priv,
84                              struct wpabuf *respData)
85 {
86         const u8 *pos;
87         size_t len;
88
89         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &len);
90         if (pos == NULL || len < 1) {
91                 wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame");
92                 return TRUE;
93         }
94
95         return FALSE;
96 }
97
98
99 static void eap_gtc_process(struct eap_sm *sm, void *priv,
100                             struct wpabuf *respData)
101 {
102         struct eap_gtc_data *data = priv;
103         const u8 *pos;
104         size_t rlen;
105
106         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &rlen);
107         if (pos == NULL || rlen < 1)
108                 return; /* Should not happen - frame already validated */
109
110         wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen);
111
112 #ifdef EAP_SERVER_FAST
113         if (data->prefix) {
114                 const u8 *pos2, *end;
115                 /* "RESPONSE=<user>\0<password>" */
116                 if (rlen < 10) {
117                         wpa_printf(MSG_DEBUG, "EAP-GTC: Too short response "
118                                    "for EAP-FAST prefix");
119                         data->state = FAILURE;
120                         return;
121                 }
122
123                 end = pos + rlen;
124                 pos += 9;
125                 pos2 = pos;
126                 while (pos2 < end && *pos2)
127                         pos2++;
128                 if (pos2 == end) {
129                         wpa_printf(MSG_DEBUG, "EAP-GTC: No password in "
130                                    "response to EAP-FAST prefix");
131                         data->state = FAILURE;
132                         return;
133                 }
134
135                 wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Response user",
136                                   pos, pos2 - pos);
137                 if (sm->identity && sm->require_identity_match &&
138                     (pos2 - pos != (int) sm->identity_len ||
139                      os_memcmp(pos, sm->identity, sm->identity_len))) {
140                         wpa_printf(MSG_DEBUG, "EAP-GTC: Phase 2 Identity did "
141                                    "not match with required Identity");
142                         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Expected "
143                                           "identity",
144                                           sm->identity, sm->identity_len);
145                         data->state = FAILURE;
146                         return;
147                 } else {
148                         os_free(sm->identity);
149                         sm->identity_len = pos2 - pos;
150                         sm->identity = os_malloc(sm->identity_len);
151                         if (sm->identity == NULL) {
152                                 data->state = FAILURE;
153                                 return;
154                         }
155                         os_memcpy(sm->identity, pos, sm->identity_len);
156                 }
157
158                 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
159                         wpa_hexdump_ascii(MSG_DEBUG, "EAP-GTC: Phase2 "
160                                           "Identity not found in the user "
161                                           "database",
162                                           sm->identity, sm->identity_len);
163                         data->state = FAILURE;
164                         return;
165                 }
166
167                 pos = pos2 + 1;
168                 rlen = end - pos;
169                 wpa_hexdump_ascii_key(MSG_MSGDUMP,
170                                       "EAP-GTC: Response password",
171                                       pos, rlen);
172         }
173 #endif /* EAP_SERVER_FAST */
174
175         if (sm->user == NULL || sm->user->password == NULL ||
176             sm->user->password_hash) {
177                 wpa_printf(MSG_INFO, "EAP-GTC: Plaintext password not "
178                            "configured");
179                 data->state = FAILURE;
180                 return;
181         }
182
183         if (rlen != sm->user->password_len ||
184             os_memcmp(pos, sm->user->password, rlen) != 0) {
185                 wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Failure");
186                 data->state = FAILURE;
187         } else {
188                 wpa_printf(MSG_DEBUG, "EAP-GTC: Done - Success");
189                 data->state = SUCCESS;
190         }
191 }
192
193
194 static Boolean eap_gtc_isDone(struct eap_sm *sm, void *priv)
195 {
196         struct eap_gtc_data *data = priv;
197         return data->state != CONTINUE;
198 }
199
200
201 static Boolean eap_gtc_isSuccess(struct eap_sm *sm, void *priv)
202 {
203         struct eap_gtc_data *data = priv;
204         return data->state == SUCCESS;
205 }
206
207
208 int eap_server_gtc_register(void)
209 {
210         struct eap_method *eap;
211         int ret;
212
213         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
214                                       EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
215         if (eap == NULL)
216                 return -1;
217
218         eap->init = eap_gtc_init;
219         eap->reset = eap_gtc_reset;
220         eap->buildReq = eap_gtc_buildReq;
221         eap->check = eap_gtc_check;
222         eap->process = eap_gtc_process;
223         eap->isDone = eap_gtc_isDone;
224         eap->isSuccess = eap_gtc_isSuccess;
225
226         ret = eap_server_method_register(eap);
227         if (ret)
228                 eap_server_method_free(eap);
229         return ret;
230 }