1 /*
2  * Example application showing how EAP server code from hostapd can be used as
3  * a library.
4  * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9 
10 #include "includes.h"
11 
12 #include "common.h"
13 #include "crypto/tls.h"
14 #include "eap_server/eap.h"
15 #include "wpabuf.h"
16 
17 void eap_example_peer_rx(const u8 *data, size_t data_len);
18 
19 
20 struct eap_server_ctx {
21 	struct eap_eapol_interface *eap_if;
22 	struct eap_sm *eap;
23 	void *tls_ctx;
24 };
25 
26 static struct eap_server_ctx eap_ctx;
27 
28 
server_get_eap_user(void * ctx,const u8 * identity,size_t identity_len,int phase2,struct eap_user * user)29 static int server_get_eap_user(void *ctx, const u8 *identity,
30 			       size_t identity_len, int phase2,
31 			       struct eap_user *user)
32 {
33 	os_memset(user, 0, sizeof(*user));
34 
35 	if (!phase2) {
36 		/* Only allow EAP-PEAP as the Phase 1 method */
37 		user->methods[0].vendor = EAP_VENDOR_IETF;
38 		user->methods[0].method = EAP_TYPE_PEAP;
39 		return 0;
40 	}
41 
42 	if (identity_len != 4 || identity == NULL ||
43 	    os_memcmp(identity, "user", 4) != 0) {
44 		printf("Unknown user\n");
45 		return -1;
46 	}
47 
48 	/* Only allow EAP-MSCHAPv2 as the Phase 2 method */
49 	user->methods[0].vendor = EAP_VENDOR_IETF;
50 	user->methods[0].method = EAP_TYPE_MSCHAPV2;
51 	user->password = (u8 *) os_strdup("password");
52 	user->password_len = 8;
53 
54 	return 0;
55 }
56 
57 
server_get_eap_req_id_text(void * ctx,size_t * len)58 static const char * server_get_eap_req_id_text(void *ctx, size_t *len)
59 {
60 	*len = 0;
61 	return NULL;
62 }
63 
64 
65 static struct eapol_callbacks eap_cb;
66 static struct eap_config eap_conf;
67 
eap_example_server_init_tls(void)68 static int eap_example_server_init_tls(void)
69 {
70 	struct tls_config tconf;
71 	struct tls_connection_params tparams;
72 
73 	os_memset(&tconf, 0, sizeof(tconf));
74 	eap_ctx.tls_ctx = tls_init(&tconf);
75 	if (eap_ctx.tls_ctx == NULL)
76 		return -1;
77 
78 	os_memset(&tparams, 0, sizeof(tparams));
79 	tparams.ca_cert = "ca.pem";
80 	tparams.client_cert = "server.pem";
81 	/* tparams.private_key = "server.key"; */
82 	tparams.private_key = "server-key.pem";
83 	/* tparams.private_key_passwd = "whatever"; */
84 	tparams.dh_file = "dh.conf";
85 
86 	if (tls_global_set_params(eap_ctx.tls_ctx, &tparams)) {
87 		printf("Failed to set TLS parameters\n");
88 		return -1;
89 	}
90 
91 	if (tls_global_set_verify(eap_ctx.tls_ctx, 0, 1)) {
92 		printf("Failed to set check_crl\n");
93 		return -1;
94 	}
95 
96 	return 0;
97 }
98 
99 
eap_server_register_methods(void)100 static int eap_server_register_methods(void)
101 {
102 	int ret = 0;
103 
104 #ifdef EAP_SERVER_IDENTITY
105 	if (ret == 0)
106 		ret = eap_server_identity_register();
107 #endif /* EAP_SERVER_IDENTITY */
108 
109 #ifdef EAP_SERVER_MD5
110 	if (ret == 0)
111 		ret = eap_server_md5_register();
112 #endif /* EAP_SERVER_MD5 */
113 
114 #ifdef EAP_SERVER_TLS
115 	if (ret == 0)
116 		ret = eap_server_tls_register();
117 #endif /* EAP_SERVER_TLS */
118 
119 #ifdef EAP_SERVER_MSCHAPV2
120 	if (ret == 0)
121 		ret = eap_server_mschapv2_register();
122 #endif /* EAP_SERVER_MSCHAPV2 */
123 
124 #ifdef EAP_SERVER_PEAP
125 	if (ret == 0)
126 		ret = eap_server_peap_register();
127 #endif /* EAP_SERVER_PEAP */
128 
129 #ifdef EAP_SERVER_TLV
130 	if (ret == 0)
131 		ret = eap_server_tlv_register();
132 #endif /* EAP_SERVER_TLV */
133 
134 #ifdef EAP_SERVER_GTC
135 	if (ret == 0)
136 		ret = eap_server_gtc_register();
137 #endif /* EAP_SERVER_GTC */
138 
139 #ifdef EAP_SERVER_TTLS
140 	if (ret == 0)
141 		ret = eap_server_ttls_register();
142 #endif /* EAP_SERVER_TTLS */
143 
144 #ifdef EAP_SERVER_SIM
145 	if (ret == 0)
146 		ret = eap_server_sim_register();
147 #endif /* EAP_SERVER_SIM */
148 
149 #ifdef EAP_SERVER_AKA
150 	if (ret == 0)
151 		ret = eap_server_aka_register();
152 #endif /* EAP_SERVER_AKA */
153 
154 #ifdef EAP_SERVER_AKA_PRIME
155 	if (ret == 0)
156 		ret = eap_server_aka_prime_register();
157 #endif /* EAP_SERVER_AKA_PRIME */
158 
159 #ifdef EAP_SERVER_PAX
160 	if (ret == 0)
161 		ret = eap_server_pax_register();
162 #endif /* EAP_SERVER_PAX */
163 
164 #ifdef EAP_SERVER_PSK
165 	if (ret == 0)
166 		ret = eap_server_psk_register();
167 #endif /* EAP_SERVER_PSK */
168 
169 #ifdef EAP_SERVER_SAKE
170 	if (ret == 0)
171 		ret = eap_server_sake_register();
172 #endif /* EAP_SERVER_SAKE */
173 
174 #ifdef EAP_SERVER_GPSK
175 	if (ret == 0)
176 		ret = eap_server_gpsk_register();
177 #endif /* EAP_SERVER_GPSK */
178 
179 #ifdef EAP_SERVER_VENDOR_TEST
180 	if (ret == 0)
181 		ret = eap_server_vendor_test_register();
182 #endif /* EAP_SERVER_VENDOR_TEST */
183 
184 #ifdef EAP_SERVER_FAST
185 	if (ret == 0)
186 		ret = eap_server_fast_register();
187 #endif /* EAP_SERVER_FAST */
188 
189 #ifdef EAP_SERVER_WSC
190 	if (ret == 0)
191 		ret = eap_server_wsc_register();
192 #endif /* EAP_SERVER_WSC */
193 
194 #ifdef EAP_SERVER_IKEV2
195 	if (ret == 0)
196 		ret = eap_server_ikev2_register();
197 #endif /* EAP_SERVER_IKEV2 */
198 
199 #ifdef EAP_SERVER_TNC
200 	if (ret == 0)
201 		ret = eap_server_tnc_register();
202 #endif /* EAP_SERVER_TNC */
203 
204 	return ret;
205 }
206 
207 
eap_example_server_init(void)208 int eap_example_server_init(void)
209 {
210 	struct eap_session_data eap_sess;
211 
212 	if (eap_server_register_methods() < 0)
213 		return -1;
214 
215 	os_memset(&eap_ctx, 0, sizeof(eap_ctx));
216 
217 	if (eap_example_server_init_tls() < 0)
218 		return -1;
219 
220 	os_memset(&eap_cb, 0, sizeof(eap_cb));
221 	eap_cb.get_eap_user = server_get_eap_user;
222 	eap_cb.get_eap_req_id_text = server_get_eap_req_id_text;
223 
224 	os_memset(&eap_conf, 0, sizeof(eap_conf));
225 	eap_conf.eap_server = 1;
226 	eap_conf.ssl_ctx = eap_ctx.tls_ctx;
227 
228 	os_memset(&eap_sess, 0, sizeof(eap_sess));
229 	eap_ctx.eap = eap_server_sm_init(&eap_ctx, &eap_cb, &eap_conf,
230 					 &eap_sess);
231 	if (eap_ctx.eap == NULL)
232 		return -1;
233 
234 	eap_ctx.eap_if = eap_get_interface(eap_ctx.eap);
235 
236 	/* Enable "port" and request EAP to start authentication. */
237 	eap_ctx.eap_if->portEnabled = true;
238 	eap_ctx.eap_if->eapRestart = true;
239 
240 	return 0;
241 }
242 
243 
eap_example_server_deinit(void)244 void eap_example_server_deinit(void)
245 {
246 	eap_server_sm_deinit(eap_ctx.eap);
247 	eap_server_unregister_methods();
248 	tls_deinit(eap_ctx.tls_ctx);
249 }
250 
251 
eap_example_server_step(void)252 int eap_example_server_step(void)
253 {
254 	int res, process = 0;
255 
256 	res = eap_server_sm_step(eap_ctx.eap);
257 
258 	if (eap_ctx.eap_if->eapReq) {
259 		printf("==> Request\n");
260 		process = 1;
261 		eap_ctx.eap_if->eapReq = 0;
262 	}
263 
264 	if (eap_ctx.eap_if->eapSuccess) {
265 		printf("==> Success\n");
266 		process = 1;
267 		res = 0;
268 		eap_ctx.eap_if->eapSuccess = 0;
269 
270 		if (eap_ctx.eap_if->eapKeyAvailable) {
271 			wpa_hexdump(MSG_DEBUG, "EAP keying material",
272 				    eap_ctx.eap_if->eapKeyData,
273 				    eap_ctx.eap_if->eapKeyDataLen);
274 		}
275 	}
276 
277 	if (eap_ctx.eap_if->eapFail) {
278 		printf("==> Fail\n");
279 		process = 1;
280 		eap_ctx.eap_if->eapFail = 0;
281 	}
282 
283 	if (process && eap_ctx.eap_if->eapReqData) {
284 		/* Send EAP request to the peer */
285 		eap_example_peer_rx(wpabuf_head(eap_ctx.eap_if->eapReqData),
286 				    wpabuf_len(eap_ctx.eap_if->eapReqData));
287 	}
288 
289 	return res;
290 }
291 
292 
eap_example_server_rx(const u8 * data,size_t data_len)293 void eap_example_server_rx(const u8 *data, size_t data_len)
294 {
295 	/* Make received EAP message available to the EAP library */
296 	wpabuf_free(eap_ctx.eap_if->eapRespData);
297 	eap_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len);
298 	if (eap_ctx.eap_if->eapRespData)
299 		eap_ctx.eap_if->eapResp = true;
300 }
301