|
1 /* |
|
2 * Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: EAP and WLAN authentication protocols. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // This is enumeration of EAPOL source code. |
|
20 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
|
21 #undef EAP_FILE_NUMBER_ENUM |
|
22 #define EAP_FILE_NUMBER_ENUM 99 |
|
23 #undef EAP_FILE_NUMBER_DATE |
|
24 #define EAP_FILE_NUMBER_DATE 1127594498 |
|
25 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
|
26 |
|
27 |
|
28 |
|
29 #include "eap_am_memory.h" |
|
30 #include "eap_tools.h" |
|
31 #include "eap_type_mschapv2.h" |
|
32 #include "eap_buffer.h" |
|
33 #include "eap_master_session_key.h" |
|
34 #include "eap_network_id_selector.h" |
|
35 #include "eap_tlv_message_data.h" |
|
36 #include "eap_automatic_variable.h" |
|
37 |
|
38 |
|
39 #if defined(EAP_MSCHAPV2_SERVER) |
|
40 |
|
41 eap_status_e eap_type_mschapv2_c::server_packet_process( |
|
42 eap_header_wr_c * const received_eap, |
|
43 const u32_t eap_packet_length) |
|
44 { |
|
45 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
46 eap_status_e status = eap_status_drop_packet_quietly; |
|
47 |
|
48 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK) |
|
49 if (m_session.get_state() != eap_type_mschapv2_state_none |
|
50 && m_use_implicit_challenge == false |
|
51 && m_identifier != received_eap->get_identifier()) |
|
52 { |
|
53 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
54 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
55 } |
|
56 else |
|
57 { |
|
58 m_identifier = received_eap->get_identifier(); |
|
59 } |
|
60 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK) |
|
61 |
|
62 if (received_eap->get_type() == eap_type_identity) |
|
63 { |
|
64 status = handle_identity_response_message(); |
|
65 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
66 return EAP_STATUS_RETURN(m_am_tools, status); |
|
67 } |
|
68 |
|
69 if (received_eap->get_code() == eap_code_success |
|
70 || received_eap->get_code() == eap_code_failure) |
|
71 { |
|
72 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
73 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
74 } |
|
75 else if (received_eap->get_code() == eap_code_response) // Response |
|
76 { |
|
77 if (eap_packet_length <= eap_header_base_c::get_header_length()) |
|
78 { |
|
79 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
80 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
81 } |
|
82 |
|
83 // MsChapV2 |
|
84 if (received_eap->get_type() == eap_type_mschapv2) |
|
85 { |
|
86 status = server_mschapv2_packet_process( |
|
87 received_eap, |
|
88 eap_packet_length); |
|
89 } |
|
90 } |
|
91 |
|
92 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
93 return EAP_STATUS_RETURN(m_am_tools, status); |
|
94 } |
|
95 |
|
96 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
97 |
|
98 |
|
99 #if defined(EAP_MSCHAPV2_SERVER) |
|
100 |
|
101 eap_status_e eap_type_mschapv2_c::server_mschapv2_packet_process( |
|
102 eap_header_wr_c * const received_eap, |
|
103 const u32_t eap_packet_length) |
|
104 { |
|
105 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
106 eap_status_e status = eap_status_drop_packet_quietly; |
|
107 |
|
108 u32_t type_data_length = received_eap->get_type_data_length(); |
|
109 |
|
110 mschapv2_header_c mschapv2_header( |
|
111 m_am_tools, |
|
112 received_eap->get_type_data_offset(0, type_data_length), |
|
113 type_data_length); |
|
114 |
|
115 if (mschapv2_header.check_header() != eap_status_ok) |
|
116 { |
|
117 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
118 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
119 } |
|
120 |
|
121 if (eap_packet_length <= eap_header_base_c::get_header_length()) |
|
122 { |
|
123 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAP_type_MSCHAPV2: illegal mschapv2 packet length\n"))); |
|
124 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
125 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
126 } |
|
127 |
|
128 if ((mschapv2_header.get_opcode() == mschapv2_opcode_response |
|
129 || mschapv2_header.get_opcode() == mschapv2_opcode_change_password) |
|
130 && type_data_length != mschapv2_header.get_ms_length()) |
|
131 { |
|
132 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAP_type_MSCHAPV2: illegal mschapv2 packet length\n"))); |
|
133 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
134 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
135 } |
|
136 |
|
137 switch (mschapv2_header.get_opcode()) |
|
138 { |
|
139 case mschapv2_opcode_response: |
|
140 status = server_handle_challenge_response(mschapv2_header); |
|
141 break; |
|
142 |
|
143 case mschapv2_opcode_success: |
|
144 status = server_handle_success_response(); |
|
145 break; |
|
146 |
|
147 case mschapv2_opcode_failure: |
|
148 status = server_handle_failure_response(); |
|
149 break; |
|
150 |
|
151 case mschapv2_opcode_change_password: |
|
152 status = server_handle_password_change(mschapv2_header); |
|
153 break; |
|
154 |
|
155 default: |
|
156 break; |
|
157 } |
|
158 |
|
159 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
160 return EAP_STATUS_RETURN(m_am_tools, status); |
|
161 } |
|
162 |
|
163 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
164 |
|
165 |
|
166 #if defined(EAP_MSCHAPV2_SERVER) |
|
167 |
|
168 bool eap_type_mschapv2_c::check_expired_password() |
|
169 { |
|
170 if (m_do_password_expiration_tests == true) |
|
171 { |
|
172 if (m_password_expired == false) |
|
173 { |
|
174 m_password_expired = true; |
|
175 } |
|
176 else |
|
177 { |
|
178 m_password_expired = false; |
|
179 } |
|
180 |
|
181 return m_password_expired; |
|
182 } |
|
183 |
|
184 return false; |
|
185 } |
|
186 |
|
187 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
188 |
|
189 |
|
190 #if defined(EAP_MSCHAPV2_SERVER) |
|
191 |
|
192 static const u8_t eap_mschapv2_challenge_response_message[] = "Message1"; |
|
193 static const u8_t eap_mschapv2_failure_message[] = "Message3"; |
|
194 |
|
195 |
|
196 eap_status_e eap_type_mschapv2_c::server_handle_challenge_response(mschapv2_header_c &machapv2_packet) |
|
197 { |
|
198 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
199 eap_status_e status = eap_status_header_corrupted; |
|
200 |
|
201 mschapv2_response_c response( |
|
202 m_am_tools, |
|
203 machapv2_packet.get_data(), |
|
204 machapv2_packet.get_data_length()); |
|
205 if (response.get_is_valid() == false) |
|
206 { |
|
207 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
208 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
209 } |
|
210 |
|
211 EAP_TRACE_DATA_DEBUG( |
|
212 m_am_tools, |
|
213 TRACE_FLAGS_DEFAULT, |
|
214 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): response packet:"), |
|
215 response.get_header_buffer(response.get_header_buffer_length()), |
|
216 response.get_header_buffer_length())); |
|
217 |
|
218 if (response.check_header() != eap_status_ok) |
|
219 { |
|
220 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
221 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
222 } |
|
223 |
|
224 if (!m_session.is_valid_state(eap_type_mschapv2_state_challenge_response)) |
|
225 { |
|
226 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
227 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
228 } |
|
229 |
|
230 // Check username |
|
231 m_am_tools->memmove( |
|
232 m_peer_challenge, |
|
233 response.get_peer_challenge(), |
|
234 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE); |
|
235 |
|
236 #if defined(USE_FAST_EAP_TYPE) |
|
237 if (m_use_EAP_FAST_challenge == true) |
|
238 { |
|
239 // Note the received authenticator challenge is zero bytes in EAP-FAST. |
|
240 if (m_client_EAP_FAST_challenge.get_is_valid_data() == false |
|
241 || m_client_EAP_FAST_challenge.get_data_length() != EAP_MSCHAPV2_PEER_CHALLENGE_SIZE) |
|
242 { |
|
243 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
244 return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure); |
|
245 } |
|
246 |
|
247 m_am_tools->memmove( |
|
248 m_peer_challenge, |
|
249 m_client_EAP_FAST_challenge.get_data(), |
|
250 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE); |
|
251 |
|
252 EAP_TRACE_DATA_DEBUG( |
|
253 m_am_tools, |
|
254 TRACE_FLAGS_DEFAULT, |
|
255 (EAPL("client_handle_challenge_request(): EAP-FAST m_peer_challenge"), |
|
256 m_peer_challenge, |
|
257 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE)); |
|
258 } |
|
259 #endif //#if defined(USE_FAST_EAP_TYPE) |
|
260 |
|
261 crypto_nt_hash_c nt_hash(m_am_tools); |
|
262 if (nt_hash.get_is_valid() == false) |
|
263 { |
|
264 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
265 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
266 } |
|
267 |
|
268 status = nt_hash.nt_password_hash( |
|
269 &m_password_utf8, |
|
270 &m_password_hash, |
|
271 EAP_MSCHAPV2_MD4_DIGEST_SIZE); |
|
272 if (status != eap_status_ok) |
|
273 { |
|
274 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
275 return EAP_STATUS_RETURN(m_am_tools, status); |
|
276 } |
|
277 |
|
278 status = nt_hash.hash_nt_password_hash( |
|
279 &m_password_hash, |
|
280 &m_password_hash_hash, |
|
281 EAP_MSCHAPV2_MD4_DIGEST_SIZE); |
|
282 if (status != eap_status_ok) |
|
283 { |
|
284 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
285 return EAP_STATUS_RETURN(m_am_tools, status); |
|
286 } |
|
287 |
|
288 EAP_TRACE_DATA_DEBUG( |
|
289 m_am_tools, |
|
290 TRACE_FLAGS_DEFAULT, |
|
291 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_password_utf8"), |
|
292 m_password_utf8.get_data(), |
|
293 m_password_utf8.get_data_length())); |
|
294 |
|
295 EAP_TRACE_DATA_DEBUG( |
|
296 m_am_tools, |
|
297 TRACE_FLAGS_DEFAULT, |
|
298 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_authenticator_challenge"), |
|
299 m_authenticator_challenge, |
|
300 EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE)); |
|
301 |
|
302 EAP_TRACE_DATA_DEBUG( |
|
303 m_am_tools, |
|
304 TRACE_FLAGS_DEFAULT, |
|
305 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_peer_challenge"), |
|
306 m_peer_challenge, |
|
307 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE)); |
|
308 |
|
309 EAP_TRACE_DATA_DEBUG( |
|
310 m_am_tools, |
|
311 TRACE_FLAGS_DEFAULT, |
|
312 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_password_hash"), |
|
313 m_password_hash.get_data(), |
|
314 m_password_hash.get_data_length())); |
|
315 |
|
316 EAP_TRACE_DATA_DEBUG( |
|
317 m_am_tools, |
|
318 TRACE_FLAGS_DEFAULT, |
|
319 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_username_utf8"), |
|
320 m_username_utf8.get_data(), |
|
321 m_username_utf8.get_data_length())); |
|
322 |
|
323 status = generate_nt_response( |
|
324 m_authenticator_challenge, |
|
325 m_peer_challenge, |
|
326 m_username_utf8.get_data(), |
|
327 m_username_utf8.get_data_length(), |
|
328 &m_password_hash, |
|
329 m_nt_response); |
|
330 if (status != eap_status_ok) |
|
331 { |
|
332 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
333 return EAP_STATUS_RETURN(m_am_tools, status); |
|
334 } |
|
335 |
|
336 EAP_TRACE_DATA_DEBUG( |
|
337 m_am_tools, |
|
338 TRACE_FLAGS_DEFAULT, |
|
339 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_nt_response:"), |
|
340 m_nt_response, |
|
341 EAP_MSCHAPV2_NT_RESPONSE_SIZE)); |
|
342 |
|
343 // Check peer_response == nt_response |
|
344 if (m_am_tools->memcmp( |
|
345 m_nt_response, |
|
346 response.get_nt_response(), |
|
347 EAP_MSCHAPV2_NT_RESPONSE_SIZE) |
|
348 == 0) |
|
349 { |
|
350 EAP_TRACE_DEBUG( |
|
351 m_am_tools, |
|
352 TRACE_FLAGS_DEFAULT, |
|
353 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): correct password\n"))); |
|
354 |
|
355 // Is password expired? |
|
356 if (check_expired_password() == true) |
|
357 { |
|
358 m_error_code = EAP_MSCHAPV2_ERROR_PASSWD_EXPIRED; |
|
359 bool retry_allowed = true; // ? |
|
360 |
|
361 u32_t message_length = sizeof(eap_mschapv2_challenge_response_message) - 1; |
|
362 |
|
363 status = send_failure_request( |
|
364 retry_allowed, |
|
365 eap_mschapv2_challenge_response_message, |
|
366 message_length); |
|
367 if (status != eap_status_ok) |
|
368 { |
|
369 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
370 return EAP_STATUS_RETURN(m_am_tools, status); |
|
371 } |
|
372 |
|
373 m_session.set_state(eap_type_mschapv2_state_challenge_response, eap_type_mschapv2_state_change_password_response); |
|
374 |
|
375 // Any other restrictions? |
|
376 status = eap_status_ok; |
|
377 } |
|
378 else |
|
379 { |
|
380 u32_t message_length = sizeof(eap_mschapv2_challenge_response_message) - 1; |
|
381 |
|
382 status = send_success_request( |
|
383 eap_mschapv2_challenge_response_message, |
|
384 message_length); |
|
385 if (status != eap_status_ok) |
|
386 { |
|
387 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
388 return EAP_STATUS_RETURN(m_am_tools, status); |
|
389 } |
|
390 |
|
391 m_session.set_state(eap_type_mschapv2_state_challenge_response, eap_type_mschapv2_state_success_response); |
|
392 status = eap_status_ok; |
|
393 } |
|
394 } |
|
395 else // Incorrect password |
|
396 { |
|
397 EAP_TRACE_DEBUG( |
|
398 m_am_tools, |
|
399 TRACE_FLAGS_DEFAULT, |
|
400 (EAPL("ERROR: EAP_type_MSCHAPV2: server_handle_challenge_response(): incorrect password\n"))); |
|
401 |
|
402 EAP_TRACE_DATA_DEBUG( |
|
403 m_am_tools, |
|
404 TRACE_FLAGS_DEFAULT, |
|
405 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_nt_response:"), |
|
406 m_nt_response, |
|
407 EAP_MSCHAPV2_NT_RESPONSE_SIZE)); |
|
408 |
|
409 EAP_TRACE_DATA_DEBUG( |
|
410 m_am_tools, |
|
411 TRACE_FLAGS_DEFAULT, |
|
412 (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): response.get_nt_response():"), |
|
413 response.get_nt_response(), |
|
414 EAP_MSCHAPV2_NT_RESPONSE_SIZE)); |
|
415 |
|
416 m_error_code = EAP_MSCHAPV2_ERROR_AUTHENTICATION_FAILURE; |
|
417 |
|
418 bool retry_allowed = true; // TEST |
|
419 |
|
420 u32_t message_length = sizeof(eap_mschapv2_failure_message) - 1; |
|
421 |
|
422 status = send_failure_request( |
|
423 retry_allowed, |
|
424 eap_mschapv2_failure_message, |
|
425 message_length); |
|
426 if (status != eap_status_ok) |
|
427 { |
|
428 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
429 return EAP_STATUS_RETURN(m_am_tools, status); |
|
430 } |
|
431 |
|
432 #if defined(USE_FAST_EAP_TYPE) |
|
433 if (m_use_EAP_FAST_challenge == true) |
|
434 { |
|
435 (void) send_error_notification(eap_status_tunnel_compromise_error); |
|
436 } |
|
437 #endif //#if defined(USE_FAST_EAP_TYPE) |
|
438 |
|
439 m_session.set_state(eap_type_mschapv2_state_challenge_response, eap_type_mschapv2_state_challenge_response); |
|
440 status = eap_status_ok; |
|
441 } |
|
442 |
|
443 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
444 return EAP_STATUS_RETURN(m_am_tools, status); |
|
445 } |
|
446 |
|
447 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
448 |
|
449 |
|
450 #if defined(EAP_MSCHAPV2_SERVER) |
|
451 |
|
452 eap_status_e eap_type_mschapv2_c::server_handle_success_response() |
|
453 { |
|
454 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
455 eap_status_e status = eap_status_drop_packet_quietly; |
|
456 |
|
457 if (m_session.is_valid_state(eap_type_mschapv2_state_success_response)) |
|
458 { |
|
459 eap_master_session_key_c key( |
|
460 m_am_tools, |
|
461 eap_type_mschapv2); |
|
462 |
|
463 status = generate_session_key(&key); |
|
464 if (status != eap_status_ok) |
|
465 { |
|
466 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
467 return EAP_STATUS_RETURN(m_am_tools, status); |
|
468 } |
|
469 |
|
470 status = get_type_partner()->packet_data_crypto_keys(&m_send_network_id, &key); |
|
471 if (status != eap_status_ok) |
|
472 { |
|
473 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
474 return EAP_STATUS_RETURN(m_am_tools, status); |
|
475 } |
|
476 |
|
477 status = finish_successful_authentication(); |
|
478 |
|
479 m_session.set_state(eap_type_mschapv2_state_success_response); |
|
480 |
|
481 status = eap_status_ok; |
|
482 } |
|
483 |
|
484 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
485 return EAP_STATUS_RETURN(m_am_tools, status); |
|
486 } |
|
487 |
|
488 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
489 |
|
490 |
|
491 #if defined(EAP_MSCHAPV2_SERVER) |
|
492 |
|
493 eap_status_e eap_type_mschapv2_c::server_handle_failure_response() |
|
494 { |
|
495 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
496 if (m_session.is_valid_state(eap_type_mschapv2_state_failure_response)) |
|
497 { |
|
498 finish_unsuccessful_authentication(false); |
|
499 m_session.set_state(eap_type_mschapv2_state_failure_response); |
|
500 |
|
501 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
502 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
503 } |
|
504 |
|
505 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
506 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
507 } |
|
508 |
|
509 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
510 |
|
511 |
|
512 #if defined(EAP_MSCHAPV2_SERVER) |
|
513 |
|
514 static const u8_t eap_mschapv2_password_change_message[] = "Message4"; |
|
515 |
|
516 eap_status_e eap_type_mschapv2_c::server_handle_password_change(mschapv2_header_c &machapv2_packet) |
|
517 { |
|
518 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
519 if (!m_session.is_valid_state(eap_type_mschapv2_state_change_password_response)) |
|
520 { |
|
521 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
522 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
|
523 } |
|
524 |
|
525 if (machapv2_packet.get_data_length() < mschapv2_change_password_c::get_header_minimum_size()) |
|
526 { |
|
527 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
528 return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted); |
|
529 } |
|
530 |
|
531 mschapv2_change_password_c change_password_payload( |
|
532 m_am_tools, |
|
533 machapv2_packet.get_data(), |
|
534 machapv2_packet.get_data_length()); |
|
535 if (change_password_payload.get_is_valid() == false) |
|
536 { |
|
537 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
538 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
539 } |
|
540 |
|
541 if (change_password_payload.check_header() != eap_status_ok) |
|
542 { |
|
543 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
544 return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted); |
|
545 } |
|
546 |
|
547 m_am_tools->memmove( |
|
548 m_peer_challenge, |
|
549 change_password_payload.get_peer_challenge(), |
|
550 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE); |
|
551 |
|
552 #if defined(USE_FAST_EAP_TYPE) |
|
553 if (m_use_EAP_FAST_challenge == true) |
|
554 { |
|
555 if (m_client_EAP_FAST_challenge.get_is_valid_data() == false |
|
556 || m_client_EAP_FAST_challenge.get_data_length() != EAP_MSCHAPV2_PEER_CHALLENGE_SIZE |
|
557 || m_client_EAP_FAST_challenge.compare(m_peer_challenge, EAP_MSCHAPV2_PEER_CHALLENGE_SIZE) != 0) |
|
558 { |
|
559 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
560 return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure); |
|
561 } |
|
562 } |
|
563 #endif //#if defined(USE_FAST_EAP_TYPE) |
|
564 |
|
565 // Encypted-Password has been made by NewPasswordEncryptedWithOldNtPassword() |
|
566 eap_variable_data_c old_password_hash(m_am_tools); |
|
567 |
|
568 crypto_nt_hash_c nt_hash(m_am_tools); |
|
569 if (nt_hash.get_is_valid() == false) |
|
570 { |
|
571 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
572 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
573 } |
|
574 |
|
575 eap_status_e status = nt_hash.nt_password_hash( |
|
576 &m_password_utf8, |
|
577 &old_password_hash, |
|
578 EAP_MSCHAPV2_MD4_DIGEST_SIZE); |
|
579 if (status != eap_status_ok) |
|
580 { |
|
581 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
582 return EAP_STATUS_RETURN(m_am_tools, status); |
|
583 } |
|
584 |
|
585 |
|
586 eap_variable_data_c tmp_password_unicode( |
|
587 m_am_tools); |
|
588 |
|
589 eap_variable_data_c tmp_password_utf8( |
|
590 m_am_tools); |
|
591 |
|
592 u8_t * new_password = 0; |
|
593 |
|
594 u32_t pw_size; |
|
595 |
|
596 { |
|
597 pw_block_s * new_pw_block = new pw_block_s; |
|
598 |
|
599 eap_automatic_variable_c<pw_block_s> automatic_new_pw_block(m_am_tools, new_pw_block); |
|
600 |
|
601 if (!new_pw_block) |
|
602 { |
|
603 status = eap_status_allocation_error; |
|
604 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
605 return EAP_STATUS_RETURN(m_am_tools, status); |
|
606 } |
|
607 |
|
608 status = rc4_decrypt( |
|
609 change_password_payload.get_encrypted_pw_block(), // cypher |
|
610 sizeof(pw_block_s), |
|
611 old_password_hash.get_data(EAP_MSCHAPV2_MD4_DIGEST_SIZE), // key |
|
612 EAP_MSCHAPV2_MD4_DIGEST_SIZE, |
|
613 reinterpret_cast<u8_t *>(new_pw_block)); // plain |
|
614 |
|
615 if (status != eap_status_ok) |
|
616 { |
|
617 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
618 return EAP_STATUS_RETURN(m_am_tools, status); |
|
619 } |
|
620 |
|
621 #ifdef EAP_BIG_ENDIAN |
|
622 pw_size = eap_ntohl(new_pw_block->password_length); |
|
623 #else |
|
624 pw_size = new_pw_block->password_length; |
|
625 #endif |
|
626 if (pw_size > EAP_MSCHAPV2_PASSWORD_MAX_SIZE) |
|
627 { |
|
628 const u32_t message_length = sizeof(eap_mschapv2_password_change_message) - 1; |
|
629 m_error_code = EAP_MSCHAPV2_ERROR_CHANGING_PASSWORD; |
|
630 bool retry_allowed = true; |
|
631 |
|
632 status = send_failure_request( |
|
633 retry_allowed, |
|
634 eap_mschapv2_password_change_message, |
|
635 message_length); |
|
636 if (status != eap_status_ok) |
|
637 { |
|
638 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
639 return EAP_STATUS_RETURN(m_am_tools, status); |
|
640 } |
|
641 |
|
642 m_session.set_state(eap_type_mschapv2_state_change_password_response, eap_type_mschapv2_state_change_password_response); |
|
643 |
|
644 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
645 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
646 } |
|
647 |
|
648 status = tmp_password_unicode.set_copy_of_buffer( |
|
649 (reinterpret_cast<u8_t *>(new_pw_block)) + EAP_MSCHAPV2_PASSWORD_MAX_SIZE - pw_size, // offset, |
|
650 pw_size); |
|
651 if (status != eap_status_ok) |
|
652 { |
|
653 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
654 return EAP_STATUS_RETURN(m_am_tools, status); |
|
655 } |
|
656 |
|
657 status = m_am_tools->convert_unicode_to_utf8(tmp_password_utf8, tmp_password_unicode); |
|
658 if (status != eap_status_ok) |
|
659 { |
|
660 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
661 return EAP_STATUS_RETURN(m_am_tools, status); |
|
662 } |
|
663 } |
|
664 |
|
665 // Encrypted-Hash has been made by old_nt_password_hash_encrypted_with_new_password_hash() |
|
666 |
|
667 eap_variable_data_c new_password_hash(m_am_tools); |
|
668 |
|
669 status = nt_hash.nt_password_hash( |
|
670 &tmp_password_utf8, |
|
671 &new_password_hash, |
|
672 EAP_MSCHAPV2_MD4_DIGEST_SIZE); |
|
673 if (status != eap_status_ok) |
|
674 { |
|
675 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
676 return EAP_STATUS_RETURN(m_am_tools, status); |
|
677 } |
|
678 |
|
679 eap_variable_data_c encrypted_pw_hash(m_am_tools); |
|
680 |
|
681 status = old_nt_password_hash_encrypted_with_new_nt_password_hash( |
|
682 &new_password_hash, |
|
683 &m_password_hash, |
|
684 &encrypted_pw_hash); |
|
685 if (status != eap_status_ok) |
|
686 { |
|
687 delete [] new_password; |
|
688 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
689 return EAP_STATUS_RETURN(m_am_tools, status); |
|
690 } |
|
691 |
|
692 if (m_am_tools->memcmp( |
|
693 encrypted_pw_hash.get_data(EAP_MSCHAPV2_MD4_DIGEST_SIZE), |
|
694 change_password_payload.get_encrypted_hash(), |
|
695 EAP_MSCHAPV2_MD4_DIGEST_SIZE) == 0) |
|
696 { |
|
697 EAP_TRACE_DEBUG( |
|
698 m_am_tools, |
|
699 TRACE_FLAGS_DEFAULT, |
|
700 (EAPL("EAP_type_MSCHAPV2: server_handle_password_change(): password change accepted\n"))); |
|
701 |
|
702 // Checked |
|
703 |
|
704 // Store new password |
|
705 status = m_password_utf8.set_copy_of_buffer(&tmp_password_utf8); |
|
706 if (status != eap_status_ok) |
|
707 { |
|
708 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
709 return EAP_STATUS_RETURN(m_am_tools, status); |
|
710 } |
|
711 |
|
712 status = m_password_hash.set_copy_of_buffer(&new_password_hash); |
|
713 if (status != eap_status_ok) |
|
714 { |
|
715 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
716 return EAP_STATUS_RETURN(m_am_tools, status); |
|
717 } |
|
718 |
|
719 status = nt_hash.hash_nt_password_hash( |
|
720 &m_password_hash, |
|
721 &m_password_hash_hash, |
|
722 EAP_MSCHAPV2_MD4_DIGEST_SIZE); |
|
723 if (status != eap_status_ok) |
|
724 { |
|
725 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
726 return EAP_STATUS_RETURN(m_am_tools, status); |
|
727 } |
|
728 |
|
729 EAP_TRACE_DATA_DEBUG( |
|
730 m_am_tools, |
|
731 TRACE_FLAGS_DEFAULT, |
|
732 (EAPL("server_handle_password_change(): m_authenticator_challenge"), |
|
733 m_authenticator_challenge, |
|
734 EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE)); |
|
735 |
|
736 EAP_TRACE_DATA_DEBUG( |
|
737 m_am_tools, |
|
738 TRACE_FLAGS_DEFAULT, |
|
739 (EAPL("server_handle_password_change(): m_peer_challenge"), |
|
740 m_peer_challenge, |
|
741 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE)); |
|
742 |
|
743 // Generate new nt_response |
|
744 status = generate_nt_response( |
|
745 m_authenticator_challenge, |
|
746 m_peer_challenge, |
|
747 m_username_utf8.get_data(), |
|
748 m_username_utf8.get_data_length(), |
|
749 &m_password_hash, |
|
750 m_nt_response); |
|
751 if (status != eap_status_ok) |
|
752 { |
|
753 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
754 return EAP_STATUS_RETURN(m_am_tools, status); |
|
755 } |
|
756 |
|
757 // Send Success request |
|
758 |
|
759 u8_t message[] = ""; |
|
760 u32_t message_length = 0; |
|
761 |
|
762 status = send_success_request( |
|
763 message, |
|
764 message_length); |
|
765 if (status != eap_status_ok) |
|
766 { |
|
767 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
768 return EAP_STATUS_RETURN(m_am_tools, status); |
|
769 } |
|
770 |
|
771 m_session.set_state(eap_type_mschapv2_state_change_password_response, eap_type_mschapv2_state_success_response); |
|
772 } |
|
773 else // Challenge response didn't match |
|
774 { |
|
775 EAP_TRACE_DEBUG( |
|
776 m_am_tools, |
|
777 TRACE_FLAGS_DEFAULT, |
|
778 (EAPL("EAP_type_MSCHAPV2: server_handle_password_change(): password change NOT accepted\n"))); |
|
779 |
|
780 delete [] new_password; |
|
781 |
|
782 u32_t message_length = sizeof(eap_mschapv2_password_change_message) - 1; |
|
783 m_error_code = EAP_MSCHAPV2_ERROR_CHANGING_PASSWORD; |
|
784 bool retry_allowed = true; |
|
785 |
|
786 status = send_failure_request( |
|
787 retry_allowed, |
|
788 eap_mschapv2_password_change_message, |
|
789 message_length); |
|
790 if (status != eap_status_ok) |
|
791 { |
|
792 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
793 return EAP_STATUS_RETURN(m_am_tools, status); |
|
794 } |
|
795 |
|
796 m_session.set_state(eap_type_mschapv2_state_change_password_response, eap_type_mschapv2_state_failure_response); |
|
797 } |
|
798 |
|
799 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
800 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
801 } |
|
802 |
|
803 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
804 |
|
805 |
|
806 #if defined(EAP_MSCHAPV2_SERVER) |
|
807 |
|
808 EAP_FUNC_EXPORT eap_status_e eap_type_mschapv2_c::handle_identity_response_message() |
|
809 { |
|
810 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
811 eap_status_e status = eap_status_process_general_error; |
|
812 |
|
813 // Send challenge |
|
814 |
|
815 status = m_rand.add_rand_seed_hw_ticks(); |
|
816 if (status != eap_status_ok) |
|
817 { |
|
818 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
819 return EAP_STATUS_RETURN(m_am_tools, status); |
|
820 } |
|
821 |
|
822 |
|
823 #if defined(USE_FAST_EAP_TYPE) |
|
824 if (m_use_EAP_FAST_challenge == true |
|
825 && m_server_EAP_FAST_challenge.get_is_valid_data() == true |
|
826 && m_server_EAP_FAST_challenge.get_data_length() == EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE) |
|
827 { |
|
828 m_am_tools->memmove( |
|
829 m_authenticator_challenge, |
|
830 m_server_EAP_FAST_challenge.get_data(), |
|
831 EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE); |
|
832 } |
|
833 else |
|
834 #endif //#if defined(USE_FAST_EAP_TYPE) |
|
835 #if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK) |
|
836 if (m_use_implicit_challenge == true) |
|
837 { |
|
838 eap_variable_data_c memory_store_key(m_am_tools); |
|
839 |
|
840 eap_status_e status = memory_store_key.set_copy_of_buffer( |
|
841 EAP_MSCHAPV2_IMPLICIT_CHALLENGE_HANDLE_KEY, |
|
842 sizeof(EAP_MSCHAPV2_IMPLICIT_CHALLENGE_HANDLE_KEY)); |
|
843 if (status != eap_status_ok) |
|
844 { |
|
845 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
846 return EAP_STATUS_RETURN(m_am_tools, status); |
|
847 } |
|
848 |
|
849 status = memory_store_key.add_data( |
|
850 &m_is_client, |
|
851 sizeof(m_is_client)); |
|
852 if (status != eap_status_ok) |
|
853 { |
|
854 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
855 return EAP_STATUS_RETURN(m_am_tools, status); |
|
856 } |
|
857 |
|
858 eap_am_network_id_c receive_network_id(m_am_tools, |
|
859 m_send_network_id.get_destination_id(), |
|
860 m_send_network_id.get_source_id(), |
|
861 m_send_network_id.get_type()); |
|
862 |
|
863 eap_network_id_selector_c state_selector( |
|
864 m_am_tools, |
|
865 &receive_network_id); |
|
866 |
|
867 status = memory_store_key.add_data( |
|
868 &state_selector); |
|
869 if (status != eap_status_ok) |
|
870 { |
|
871 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
872 return EAP_STATUS_RETURN(m_am_tools, status); |
|
873 } |
|
874 |
|
875 eap_tlv_message_data_c tlv_data(m_am_tools); |
|
876 |
|
877 status = m_am_tools->memory_store_get_data( |
|
878 &memory_store_key, |
|
879 &tlv_data); |
|
880 if (status != eap_status_ok) |
|
881 { |
|
882 EAP_TRACE_DEBUG( |
|
883 m_am_tools, |
|
884 TRACE_FLAGS_DEFAULT, |
|
885 (EAPL("EAP_type_MSCHAPV2: handle_identity_response_message(): cannot get credentials\n"))); |
|
886 } |
|
887 else |
|
888 { |
|
889 EAP_TRACE_DEBUG( |
|
890 m_am_tools, |
|
891 TRACE_FLAGS_DEFAULT, |
|
892 (EAPL("EAP_type_MSCHAPV2: handle_identity_response_message(): credentials found\n"))); |
|
893 |
|
894 // Parse read data. |
|
895 eap_array_c<eap_tlv_header_c> tlv_blocks(m_am_tools); |
|
896 |
|
897 status = tlv_data.parse_message_data(&tlv_blocks); |
|
898 if (status != eap_status_ok) |
|
899 { |
|
900 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
901 return EAP_STATUS_RETURN(m_am_tools, status); |
|
902 } |
|
903 |
|
904 bool implicit_challenge_read(false); |
|
905 |
|
906 for (u32_t ind = 0ul; ind < tlv_blocks.get_object_count(); ind++) |
|
907 { |
|
908 eap_tlv_header_c * const tlv = tlv_blocks.get_object(ind); |
|
909 if (tlv != 0) |
|
910 { |
|
911 if (tlv->get_type() == eap_type_mschapv2_implicit_challenge) |
|
912 { |
|
913 m_am_tools->memmove( |
|
914 m_authenticator_challenge, |
|
915 tlv->get_value(tlv->get_value_length()), |
|
916 tlv->get_value_length()); |
|
917 |
|
918 implicit_challenge_read = true; |
|
919 } |
|
920 } |
|
921 } // for() |
|
922 |
|
923 if (implicit_challenge_read == false) |
|
924 { |
|
925 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
926 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
927 } |
|
928 } |
|
929 } |
|
930 else |
|
931 #endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK) |
|
932 { |
|
933 status = m_rand.get_rand_bytes(m_authenticator_challenge, EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE); |
|
934 if (status != eap_status_ok) |
|
935 { |
|
936 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
937 return EAP_STATUS_RETURN(m_am_tools, status); |
|
938 } |
|
939 } |
|
940 |
|
941 EAP_TRACE_DATA_DEBUG( |
|
942 m_am_tools, |
|
943 TRACE_FLAGS_DEFAULT, |
|
944 (EAPL("handle_identity_response_message(): m_authenticator_challenge"), |
|
945 m_authenticator_challenge, |
|
946 EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE)); |
|
947 |
|
948 const u32_t name_length = m_username_utf8.get_data_length(); |
|
949 |
|
950 const u32_t type_data_length = EAP_MSCHAPV2_HEADER_SIZE // OpCode, MS-CHAPv2-ID and MS-Length |
|
951 + mschapv2_challenge_c::get_header_minimum_size() |
|
952 + name_length; |
|
953 |
|
954 const u32_t packet_length = eap_header_base_c::get_type_data_start_offset(m_use_eap_expanded_type) |
|
955 + type_data_length; |
|
956 |
|
957 eap_buf_chain_wr_c * packet = create_send_packet(packet_length); |
|
958 if (!packet) |
|
959 { |
|
960 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
961 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
962 } |
|
963 |
|
964 eap_header_base_c eap_header( |
|
965 m_am_tools, |
|
966 packet->get_data_offset(m_offset, packet_length), |
|
967 packet_length); |
|
968 if (eap_header.get_is_valid() == false) |
|
969 { |
|
970 delete packet; |
|
971 packet = 0; |
|
972 |
|
973 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
974 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
975 } |
|
976 eap_header.set_code(eap_code_request); |
|
977 eap_header.set_identifier(++m_identifier); |
|
978 eap_header.set_length( |
|
979 static_cast<u16_t>(packet_length), |
|
980 m_use_eap_expanded_type); |
|
981 eap_header.set_type( |
|
982 eap_type_mschapv2, |
|
983 m_use_eap_expanded_type); |
|
984 |
|
985 mschapv2_header_c mschapv2_header( |
|
986 m_am_tools, |
|
987 eap_header.get_type_data_offset(0, eap_header.get_type_data_length()), |
|
988 eap_header.get_type_data_length()); |
|
989 |
|
990 mschapv2_header.set_opcode(mschapv2_opcode_challenge); |
|
991 mschapv2_header.set_mschapv2_id(static_cast<u8_t>(++m_mschapv2id)); |
|
992 mschapv2_header.set_ms_length(static_cast<u16_t>(type_data_length)); |
|
993 |
|
994 mschapv2_challenge_c challenge_packet( |
|
995 m_am_tools, |
|
996 mschapv2_header.get_data(), |
|
997 mschapv2_header.get_data_length()); |
|
998 if (challenge_packet.get_is_valid() == false) |
|
999 { |
|
1000 delete packet; |
|
1001 packet = 0; |
|
1002 |
|
1003 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1004 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
1005 } |
|
1006 |
|
1007 #if defined(USE_FAST_EAP_TYPE) |
|
1008 if (m_use_EAP_FAST_challenge == true) |
|
1009 { |
|
1010 // EAP-FAST sends authenticator challenge containing only zeroes. |
|
1011 challenge_packet.set_challenge(EAP_MSCHAPV2_ZERO_CHALLENGE); |
|
1012 } |
|
1013 else |
|
1014 #endif //#if defined(USE_FAST_EAP_TYPE) |
|
1015 { |
|
1016 challenge_packet.set_challenge(m_authenticator_challenge); |
|
1017 } |
|
1018 |
|
1019 challenge_packet.set_value_size(); |
|
1020 challenge_packet.set_name(m_username_utf8.get_data(name_length)); |
|
1021 |
|
1022 // This must be set before packet_send() call to allow |
|
1023 // the plain MsChapv2 to work. |
|
1024 m_session.set_state(eap_type_mschapv2_state_identity_response); |
|
1025 |
|
1026 // Send packet |
|
1027 status = packet_send(packet, packet_length); |
|
1028 |
|
1029 delete packet; |
|
1030 packet = 0; |
|
1031 |
|
1032 if (status != eap_status_ok) |
|
1033 { |
|
1034 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1035 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1036 } |
|
1037 |
|
1038 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1039 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1040 } |
|
1041 |
|
1042 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
1043 |
|
1044 |
|
1045 #if defined(EAP_MSCHAPV2_SERVER) |
|
1046 |
|
1047 eap_status_e eap_type_mschapv2_c::send_failure_request( |
|
1048 const bool retry_allowed, |
|
1049 const u8_t * const message, |
|
1050 const u32_t message_length) |
|
1051 { |
|
1052 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1053 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAP_type_MSCHAPV2: send_failure_request\n"))); |
|
1054 |
|
1055 u32_t retry = 0; |
|
1056 if (retry_allowed) |
|
1057 { |
|
1058 retry = 1; |
|
1059 } |
|
1060 |
|
1061 // Generate new auth_challenge |
|
1062 |
|
1063 eap_status_e status = m_rand.add_rand_seed_hw_ticks(); |
|
1064 if (status != eap_status_ok) |
|
1065 { |
|
1066 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1067 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1068 } |
|
1069 |
|
1070 #if defined(USE_FAST_EAP_TYPE) |
|
1071 if (m_use_EAP_FAST_challenge == true |
|
1072 && m_client_EAP_FAST_challenge.get_is_valid_data() == true |
|
1073 && m_client_EAP_FAST_challenge.get_data_length() == EAP_MSCHAPV2_PEER_CHALLENGE_SIZE) |
|
1074 { |
|
1075 m_am_tools->memmove( |
|
1076 m_peer_challenge, |
|
1077 m_client_EAP_FAST_challenge.get_data(), |
|
1078 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE); |
|
1079 } |
|
1080 else |
|
1081 #endif //#if defined(USE_FAST_EAP_TYPE) |
|
1082 { |
|
1083 status = m_rand.get_rand_bytes(m_authenticator_challenge, EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE); |
|
1084 if (status != eap_status_ok) |
|
1085 { |
|
1086 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1087 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1088 } |
|
1089 } |
|
1090 |
|
1091 EAP_TRACE_DATA_DEBUG( |
|
1092 m_am_tools, |
|
1093 TRACE_FLAGS_DEFAULT, |
|
1094 (EAPL("EAP_type_MSCHAPV2: send_failure_request(): m_authenticator_challenge"), |
|
1095 m_authenticator_challenge, |
|
1096 EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE)); |
|
1097 |
|
1098 EAP_TRACE_DATA_DEBUG( |
|
1099 m_am_tools, |
|
1100 TRACE_FLAGS_DEFAULT, |
|
1101 (EAPL("EAP_type_MSCHAPV2: send_failure_request(): m_peer_challenge"), |
|
1102 m_peer_challenge, |
|
1103 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE)); |
|
1104 |
|
1105 u8_t * auth_challenge_str = new u8_t[EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE * 2]; |
|
1106 if (!auth_challenge_str) |
|
1107 { |
|
1108 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1109 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
1110 } |
|
1111 |
|
1112 u32_t length = 2 * EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE; |
|
1113 |
|
1114 status = m_am_tools->convert_bytes_to_hex_ascii( |
|
1115 m_authenticator_challenge, |
|
1116 EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE, |
|
1117 auth_challenge_str, |
|
1118 &length); |
|
1119 if (status != eap_status_ok |
|
1120 || length != 2 * EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE) |
|
1121 { |
|
1122 delete [] auth_challenge_str; |
|
1123 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1124 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); |
|
1125 } |
|
1126 |
|
1127 m_am_tools->convert_ascii_to_uppercase(auth_challenge_str, length); |
|
1128 |
|
1129 const u32_t type_data_length = |
|
1130 + EAP_MSCHAPV2_HEADER_SIZE // OpCode, MS-CHAPv2-ID and MS-Length |
|
1131 + EAP_MSCHAPV2_FAILURE_REQUEST_SIZE |
|
1132 + message_length; |
|
1133 |
|
1134 const u32_t packet_length |
|
1135 = eap_header_base_c::get_type_data_start_offset(m_use_eap_expanded_type) |
|
1136 + type_data_length; |
|
1137 |
|
1138 eap_buf_chain_wr_c * packet = create_send_packet(packet_length); |
|
1139 if (!packet) |
|
1140 { |
|
1141 delete [] auth_challenge_str; |
|
1142 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1143 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
1144 } |
|
1145 |
|
1146 eap_header_base_c eap_header( |
|
1147 m_am_tools, |
|
1148 packet->get_data_offset(m_offset, packet_length), |
|
1149 packet_length); |
|
1150 if (eap_header.get_is_valid() == false) |
|
1151 { |
|
1152 delete [] auth_challenge_str; |
|
1153 delete packet; |
|
1154 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1155 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
1156 } |
|
1157 eap_header.set_code(eap_code_request); |
|
1158 eap_header.set_identifier(++m_identifier); |
|
1159 eap_header.set_length( |
|
1160 static_cast<u16_t>(packet_length), |
|
1161 m_use_eap_expanded_type); |
|
1162 eap_header.set_type( |
|
1163 eap_type_mschapv2, |
|
1164 m_use_eap_expanded_type); |
|
1165 |
|
1166 mschapv2_header_c mschapv2_header( |
|
1167 m_am_tools, |
|
1168 eap_header.get_type_data_offset(0, eap_header.get_type_data_length()), |
|
1169 eap_header.get_type_data_length()); |
|
1170 |
|
1171 mschapv2_header.set_opcode(mschapv2_opcode_failure); |
|
1172 mschapv2_header.set_mschapv2_id(static_cast<u8_t>(++m_mschapv2id)); |
|
1173 mschapv2_header.set_ms_length(static_cast<u16_t>(type_data_length)); |
|
1174 |
|
1175 u8_t * failure_data = mschapv2_header.get_data(); // @{...} |
|
1176 if (failure_data == 0) |
|
1177 { |
|
1178 delete [] auth_challenge_str; |
|
1179 delete packet; |
|
1180 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1181 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
1182 } |
|
1183 if (m_am_tools->snprintf( |
|
1184 failure_data, |
|
1185 EAP_MSCHAPV2_FAILURE_REQUEST_SIZE, |
|
1186 "E=%010u R=%1u C=12345678901234567890123456789012 V=%010u M=", // auth_challenge will be set by memcpy |
|
1187 m_error_code, |
|
1188 retry, |
|
1189 3L) != EAP_MSCHAPV2_FAILURE_REQUEST_SIZE) |
|
1190 { |
|
1191 delete [] auth_challenge_str; |
|
1192 delete packet; |
|
1193 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1194 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
1195 } |
|
1196 |
|
1197 m_am_tools->memmove( |
|
1198 failure_data + 12 + 1 + 3 + 1 + 2, // pointer to just after "C=" |
|
1199 auth_challenge_str, |
|
1200 EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE * 2); |
|
1201 |
|
1202 delete [] auth_challenge_str; |
|
1203 |
|
1204 if (message_length != 0) |
|
1205 { |
|
1206 // Copy message to end of packet |
|
1207 m_am_tools->memmove( |
|
1208 failure_data + EAP_MSCHAPV2_FAILURE_REQUEST_SIZE, |
|
1209 message, |
|
1210 message_length); |
|
1211 } |
|
1212 |
|
1213 status = packet_send(packet, packet_length); |
|
1214 delete packet; |
|
1215 |
|
1216 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1217 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1218 } |
|
1219 |
|
1220 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
1221 |
|
1222 |
|
1223 #if defined(EAP_MSCHAPV2_SERVER) |
|
1224 |
|
1225 eap_status_e eap_type_mschapv2_c::send_success_request( |
|
1226 const u8_t * const message, |
|
1227 const u32_t message_length) |
|
1228 { |
|
1229 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1230 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAP_type_MSCHAPV2: send_success_request\n"))); |
|
1231 |
|
1232 u8_t * auth_response = new u8_t[EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE]; |
|
1233 if (!auth_response) |
|
1234 { |
|
1235 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1236 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
1237 } |
|
1238 |
|
1239 EAP_TRACE_DATA_DEBUG( |
|
1240 m_am_tools, |
|
1241 TRACE_FLAGS_DEFAULT, |
|
1242 (EAPL("send_success_request(): m_authenticator_challenge"), |
|
1243 m_authenticator_challenge, |
|
1244 EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE)); |
|
1245 |
|
1246 EAP_TRACE_DATA_DEBUG( |
|
1247 m_am_tools, |
|
1248 TRACE_FLAGS_DEFAULT, |
|
1249 (EAPL("send_success_request(): m_peer_challenge"), |
|
1250 m_peer_challenge, |
|
1251 EAP_MSCHAPV2_PEER_CHALLENGE_SIZE)); |
|
1252 |
|
1253 eap_status_e status = generate_authenticator_response( |
|
1254 m_password_hash_hash.get_data(EAP_MSCHAPV2_MD4_DIGEST_SIZE), |
|
1255 m_nt_response, |
|
1256 m_peer_challenge, |
|
1257 m_authenticator_challenge, |
|
1258 m_username_utf8.get_data(), |
|
1259 m_username_utf8.get_data_length(), |
|
1260 auth_response); |
|
1261 if (status != eap_status_ok) |
|
1262 { |
|
1263 delete [] auth_response; |
|
1264 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1265 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1266 } |
|
1267 |
|
1268 const u32_t ms_data_length |
|
1269 = EAP_MSCHAPV2_HEADER_SIZE |
|
1270 + EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE |
|
1271 + EAP_MSCHAPV2_MESSAGE_PREFIX_SIZE |
|
1272 + message_length; |
|
1273 |
|
1274 const u32_t packet_length |
|
1275 = eap_header_base_c::get_type_data_start_offset(m_use_eap_expanded_type) |
|
1276 + ms_data_length; |
|
1277 |
|
1278 eap_buf_chain_wr_c * packet = create_send_packet(packet_length); |
|
1279 if (!packet) |
|
1280 { |
|
1281 delete [] auth_response; |
|
1282 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1283 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
1284 } |
|
1285 |
|
1286 eap_header_base_c eap_header( |
|
1287 m_am_tools, |
|
1288 packet->get_data_offset(m_offset, packet_length), |
|
1289 packet_length); |
|
1290 if (eap_header.get_is_valid() == false) |
|
1291 { |
|
1292 delete [] auth_response; |
|
1293 delete packet; |
|
1294 packet = 0; |
|
1295 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1296 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
|
1297 } |
|
1298 eap_header.set_code(eap_code_request); |
|
1299 eap_header.set_identifier(++m_identifier); |
|
1300 eap_header.set_length( |
|
1301 static_cast<u16_t>(packet_length), |
|
1302 m_use_eap_expanded_type); |
|
1303 eap_header.set_type( |
|
1304 eap_type_mschapv2, |
|
1305 m_use_eap_expanded_type); |
|
1306 |
|
1307 mschapv2_header_c mschapv2_header( |
|
1308 m_am_tools, |
|
1309 eap_header.get_type_data_offset(0, eap_header.get_type_data_length()), |
|
1310 eap_header.get_type_data_length()); |
|
1311 |
|
1312 mschapv2_header.set_opcode(mschapv2_opcode_success); |
|
1313 mschapv2_header.set_mschapv2_id(static_cast<u8_t>(++m_mschapv2id)); |
|
1314 mschapv2_header.set_ms_length(static_cast<u16_t>(ms_data_length)); |
|
1315 |
|
1316 u8_t * success_data = mschapv2_header.get_data(); |
|
1317 if (success_data == 0) |
|
1318 { |
|
1319 delete [] auth_response; |
|
1320 delete packet; |
|
1321 packet = 0; |
|
1322 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1323 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
1324 } |
|
1325 |
|
1326 // Copy auth string after headers |
|
1327 m_am_tools->memmove( |
|
1328 success_data, |
|
1329 auth_response, |
|
1330 EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE); |
|
1331 |
|
1332 delete [] auth_response; |
|
1333 |
|
1334 // Copy message after auth string |
|
1335 m_am_tools->memmove( |
|
1336 success_data + EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE, |
|
1337 EAP_MSCHAPV2_MESSAGE_PREFIX, |
|
1338 EAP_MSCHAPV2_MESSAGE_PREFIX_SIZE); |
|
1339 |
|
1340 if (message_length != 0) |
|
1341 { |
|
1342 m_am_tools->memmove( |
|
1343 success_data + EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE + EAP_MSCHAPV2_MESSAGE_PREFIX_SIZE, |
|
1344 message, |
|
1345 message_length); |
|
1346 } |
|
1347 |
|
1348 status = packet_send(packet, packet_length); |
|
1349 delete packet; |
|
1350 packet = 0; |
|
1351 |
|
1352 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1353 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1354 } |
|
1355 |
|
1356 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
1357 |
|
1358 |
|
1359 #if defined(EAP_MSCHAPV2_SERVER) |
|
1360 |
|
1361 eap_status_e eap_type_mschapv2_c::rc4_decrypt( |
|
1362 const u8_t * const cypher, |
|
1363 const u32_t cypher_length, |
|
1364 const u8_t * const key, |
|
1365 const u32_t key_length, |
|
1366 u8_t * const clear) |
|
1367 { |
|
1368 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1369 if (!cypher |
|
1370 || cypher_length == 0 |
|
1371 || !key |
|
1372 || key_length == 0 |
|
1373 || !clear) |
|
1374 { |
|
1375 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1376 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); |
|
1377 } |
|
1378 |
|
1379 eap_variable_data_c v_key(m_am_tools); |
|
1380 |
|
1381 eap_status_e status = v_key.set_buffer(key, key_length, false, false); // Cannot fail |
|
1382 if (status != eap_status_ok |
|
1383 || v_key.get_is_valid_data() == false) |
|
1384 { |
|
1385 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1386 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
1387 } |
|
1388 |
|
1389 crypto_rc4_c rc4(m_am_tools); |
|
1390 |
|
1391 status = rc4.set_key(&v_key); |
|
1392 if (status != eap_status_ok) |
|
1393 { |
|
1394 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1395 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1396 } |
|
1397 |
|
1398 status = rc4.decrypt_data(cypher, clear, cypher_length); |
|
1399 |
|
1400 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
1401 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1402 } |
|
1403 |
|
1404 #endif //#if defined(EAP_MSCHAPV2_SERVER) |
|
1405 |
|
1406 // end |