branch | RCL_3 |
changeset 46 | c74b3d9f6b9e |
parent 45 | bad0cc58d154 |
45:bad0cc58d154 | 46:c74b3d9f6b9e |
---|---|
14 * Description: EAP and WLAN authentication protocols. |
14 * Description: EAP and WLAN authentication protocols. |
15 * |
15 * |
16 */ |
16 */ |
17 |
17 |
18 /* |
18 /* |
19 * %version: 100 % |
19 * %version: 67.1.2.1.2 % |
20 */ |
20 */ |
21 |
21 |
22 // This is enumeration of EAPOL source code. |
22 // This is enumeration of EAPOL source code. |
23 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
23 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
24 #undef EAP_FILE_NUMBER_ENUM |
24 #undef EAP_FILE_NUMBER_ENUM |
25 #define EAP_FILE_NUMBER_ENUM 747 |
25 #define EAP_FILE_NUMBER_ENUM 48 |
26 #undef EAP_FILE_NUMBER_DATE |
26 #undef EAP_FILE_NUMBER_DATE |
27 #define EAP_FILE_NUMBER_DATE 1127594498 |
27 #define EAP_FILE_NUMBER_DATE 1127594498 |
28 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
28 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
29 |
29 |
30 |
30 |
59 this)); |
59 this)); |
60 |
60 |
61 EAP_ASSERT(m_shutdown_was_called == true); |
61 EAP_ASSERT(m_shutdown_was_called == true); |
62 |
62 |
63 delete m_eap_core; |
63 delete m_eap_core; |
64 m_eap_core = 0; |
|
65 |
64 |
66 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
65 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
67 } |
66 } |
68 |
67 |
69 //-------------------------------------------------- |
68 //-------------------------------------------------- |
76 EAP_FUNC_EXPORT eapol_core_c::eapol_core_c( |
75 EAP_FUNC_EXPORT eapol_core_c::eapol_core_c( |
77 abs_eap_am_tools_c * const tools, |
76 abs_eap_am_tools_c * const tools, |
78 abs_eapol_core_c * const partner, |
77 abs_eapol_core_c * const partner, |
79 const bool is_client_when_true) |
78 const bool is_client_when_true) |
80 : m_partner(partner) |
79 : m_partner(partner) |
81 , m_eap_core(0) |
80 #if !defined(NO_EAP_SESSION_CORE) |
81 , m_eap_core(new eap_session_core_c(tools, this, is_client_when_true)) |
|
82 #else |
|
83 , m_eap_core(new eap_core_c(tools, this, is_client_when_true, 0, false)) |
|
84 #endif |
|
85 #if defined(USE_EAPOL_KEY_STATE) |
|
82 , m_eapol_key_state_map(tools, this) |
86 , m_eapol_key_state_map(tools, this) |
87 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
83 , m_am_tools(tools) |
88 , m_am_tools(tools) |
84 , m_master_session_key(m_am_tools) |
89 , m_master_session_key(m_am_tools) |
85 , m_authentication_type(eapol_key_authentication_type_none) |
90 , m_authentication_type(eapol_key_authentication_type_none) |
86 , m_eapol_header_offset(0u) |
91 , m_eapol_header_offset(0u) |
87 , m_MTU(0u) |
92 , m_MTU(0u) |
91 , m_eapol_starts_sent(0u) |
96 , m_eapol_starts_sent(0u) |
92 , m_is_client(is_client_when_true) |
97 , m_is_client(is_client_when_true) |
93 , m_is_valid(false) |
98 , m_is_valid(false) |
94 , m_shutdown_was_called(false) |
99 , m_shutdown_was_called(false) |
95 , m_block_state_notifications(false) |
100 , m_block_state_notifications(false) |
101 #if defined(USE_EAPOL_KEY_STATE) |
|
96 , m_skip_start_4_way_handshake(false) |
102 , m_skip_start_4_way_handshake(false) |
103 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
97 { |
104 { |
98 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
105 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
99 |
106 |
100 EAP_TRACE_DEBUG( |
107 EAP_TRACE_DEBUG( |
101 m_am_tools, |
108 m_am_tools, |
105 this, |
112 this, |
106 dynamic_cast<abs_eap_base_timer_c *>(this), |
113 dynamic_cast<abs_eap_base_timer_c *>(this), |
107 __DATE__, |
114 __DATE__, |
108 __TIME__)); |
115 __TIME__)); |
109 |
116 |
110 #if defined(EAP_USE_WPXM) |
117 if (m_eap_core != 0 |
111 EAP_TRACE_DEBUG( |
118 && m_eap_core->get_is_valid() == true) |
112 m_am_tools, |
|
113 TRACE_FLAGS_DEFAULT, |
|
114 (EAPL("eapol_core_c::eapol_core_c(): WPX enabled."))); |
|
115 #else |
|
116 EAP_TRACE_DEBUG( |
|
117 m_am_tools, |
|
118 TRACE_FLAGS_DEFAULT, |
|
119 (EAPL("eapol_core_c::eapol_core_c(): WPX disabled."))); |
|
120 #endif //#if defined(EAP_USE_WPXM) |
|
121 |
|
122 if (m_partner != 0) |
|
123 { |
119 { |
124 set_is_valid(); |
120 set_is_valid(); |
125 } |
121 } |
126 |
122 |
127 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
123 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
128 } |
|
129 |
|
130 //-------------------------------------------------- |
|
131 |
|
132 // |
|
133 EAP_FUNC_EXPORT eap_status_e eapol_core_c::configure() |
|
134 { |
|
135 EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true); |
|
136 |
|
137 EAP_TRACE_DEBUG( |
|
138 m_am_tools, |
|
139 TRACE_FLAGS_DEFAULT, |
|
140 (EAPL("%s: eapol_core_c::configure()\n"), |
|
141 (m_is_client == true) ? "client": "server")); |
|
142 |
|
143 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::configure()"); |
|
144 |
|
145 eap_status_e status(eap_status_process_general_error); |
|
146 |
|
147 m_eapol_header_offset = m_partner->get_header_offset( |
|
148 &m_MTU, &m_trailer_length); |
|
149 |
|
150 #if defined(NO_EAP_CORE_CLIENT_MESSAGE_IF) |
|
151 m_eap_core = eap_session_core_base_c::new_eap_session_core_c( |
|
152 m_am_tools, |
|
153 this, |
|
154 m_is_client, |
|
155 m_MTU-eapol_header_wr_c::get_header_length()); |
|
156 #else |
|
157 m_eap_core = new_eap_core_client_message_if_c( |
|
158 m_am_tools, |
|
159 this, |
|
160 m_is_client, |
|
161 m_MTU-eapol_header_wr_c::get_header_length()); |
|
162 #endif |
|
163 |
|
164 if (m_eap_core == 0 |
|
165 || m_eap_core->get_is_valid() == false) |
|
166 { |
|
167 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
168 } |
|
169 |
|
170 { |
|
171 eap_variable_data_c max_eapol_starts(m_am_tools); |
|
172 |
|
173 status = read_configure( |
|
174 cf_str_EAPOL_CORE_starts_max_count.get_field(), |
|
175 &max_eapol_starts); |
|
176 if (status != eap_status_ok |
|
177 || max_eapol_starts.get_is_valid_data() == false |
|
178 || max_eapol_starts.get_data_length() < sizeof(u32_t)) |
|
179 { |
|
180 // Probably not found from db. Use the default value. |
|
181 m_max_eapol_starts = EAPOL_CORE_MAX_EAPOL_START_SENDINGS; |
|
182 } |
|
183 else |
|
184 { |
|
185 m_max_eapol_starts = *reinterpret_cast<u32_t *>( |
|
186 max_eapol_starts.get_data(sizeof(u32_t))); |
|
187 } |
|
188 } |
|
189 |
|
190 { |
|
191 eap_variable_data_c eapol_start_interval(m_am_tools); |
|
192 |
|
193 status = read_configure( |
|
194 cf_str_EAPOL_CORE_send_start_interval.get_field(), |
|
195 &eapol_start_interval); |
|
196 if (status != eap_status_ok |
|
197 || eapol_start_interval.get_is_valid_data() == false |
|
198 || eapol_start_interval.get_data_length() < sizeof(u32_t)) |
|
199 { |
|
200 // Probably not found from db. Use the default value. |
|
201 m_eapol_start_interval = EAPOL_CORE_TIMER_SEND_START_AGAIN_TIMEOUT; |
|
202 } |
|
203 else |
|
204 { |
|
205 m_eapol_start_interval = *reinterpret_cast<u32_t *>( |
|
206 eapol_start_interval.get_data(sizeof(u32_t))); |
|
207 } |
|
208 } |
|
209 |
|
210 #if defined(USE_EAP_CORE_SERVER) |
|
211 if (m_is_client == false) |
|
212 { |
|
213 eap_variable_data_c data(m_am_tools); |
|
214 |
|
215 eap_status_e status = read_configure( |
|
216 cf_str_EAPOL_CORE_skip_start_4_way_handshake.get_field(), |
|
217 &data); |
|
218 if (status == eap_status_ok |
|
219 && data.get_data_length() == sizeof(u32_t) |
|
220 && data.get_data(data.get_data_length()) != 0) |
|
221 { |
|
222 u32_t *flag = reinterpret_cast<u32_t *>(data.get_data(data.get_data_length())); |
|
223 |
|
224 if (flag != 0) |
|
225 { |
|
226 if ((*flag) != 0ul) |
|
227 { |
|
228 m_skip_start_4_way_handshake = true; |
|
229 } |
|
230 else |
|
231 { |
|
232 m_skip_start_4_way_handshake = false; |
|
233 } |
|
234 } |
|
235 } |
|
236 } |
|
237 #endif //#if defined(USE_EAP_CORE_SERVER) |
|
238 |
|
239 return EAP_STATUS_RETURN(m_am_tools, m_eap_core->configure()); |
|
240 } |
124 } |
241 |
125 |
242 //-------------------------------------------------- |
126 //-------------------------------------------------- |
243 |
127 |
244 // |
128 // |
379 && m_authentication_type != eapol_key_authentication_type_WPA_EAP |
263 && m_authentication_type != eapol_key_authentication_type_WPA_EAP |
380 && m_authentication_type != eapol_key_authentication_type_dynamic_WEP |
264 && m_authentication_type != eapol_key_authentication_type_dynamic_WEP |
381 #if defined(EAP_USE_WPXM) |
265 #if defined(EAP_USE_WPXM) |
382 && m_authentication_type != eapol_key_authentication_type_WPXM |
266 && m_authentication_type != eapol_key_authentication_type_WPXM |
383 #endif //#if defined(EAP_USE_WPXM) |
267 #endif //#if defined(EAP_USE_WPXM) |
384 && m_authentication_type != eapol_key_authentication_type_WPS |
268 && m_authentication_type != eapol_key_authentication_type_WFA_SC |
385 && m_authentication_type != eapol_key_authentication_type_EAP_authentication_no_encryption |
269 && m_authentication_type != eapol_key_authentication_type_EAP_authentication_no_encryption |
386 ) |
270 ) |
387 { |
271 { |
388 EAP_TRACE_DEBUG( |
272 EAP_TRACE_DEBUG( |
389 m_am_tools, |
273 m_am_tools, |
393 |
277 |
394 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
278 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
395 return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eapol_type); |
279 return EAP_STATUS_RETURN(m_am_tools, eap_status_wrong_eapol_type); |
396 } |
280 } |
397 |
281 |
282 |
|
283 #if defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
284 |
|
398 // Test first we are connected. |
285 // Test first we are connected. |
399 if (eapol_key_state->get_is_associated() == true) |
286 if (eapol_key_state->get_is_associated() == true) |
400 { |
287 { |
401 eap_header_wr_c eap( |
288 status = m_eap_core->synchronous_create_eap_session(receive_network_id); |
402 m_am_tools, |
289 if (status != eap_status_ok) |
403 eapol.get_eap_header(), |
290 { |
404 eapol.get_data_length()); |
291 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
405 |
292 return EAP_STATUS_RETURN(m_am_tools, status); |
406 status = m_eap_core->packet_process( |
293 } |
407 receive_network_id, |
294 } |
408 &eap, |
295 |
409 eapol.get_data_length()); |
296 #endif //#if !defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
410 |
297 |
411 EAP_GENERAL_HEADER_COPY_ERROR_PARAMETERS(packet_data, &eap); |
298 |
412 } |
299 eap_header_wr_c eap( |
413 else |
300 m_am_tools, |
414 { |
301 eapol.get_eap_header(), |
415 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
302 eapol.get_data_length()); |
416 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
303 |
417 } |
304 status = m_eap_core->packet_process( |
305 receive_network_id, |
|
306 &eap, |
|
307 eapol.get_data_length()); |
|
308 |
|
309 EAP_GENERAL_HEADER_COPY_ERROR_PARAMETERS(packet_data, &eap); |
|
418 } |
310 } |
419 else if (m_is_client == false |
311 else if (m_is_client == false |
420 && eapol.get_packet_type() == eapol_packet_type_logoff) |
312 && eapol.get_packet_type() == eapol_packet_type_logoff) |
421 { |
313 { |
422 status = eap_status_ok; |
314 status = eap_status_ok; |
425 && eapol.get_packet_type() == eapol_packet_type_start) |
317 && eapol.get_packet_type() == eapol_packet_type_start) |
426 { |
318 { |
427 if (m_authentication_type != eapol_key_authentication_type_RSNA_EAP |
319 if (m_authentication_type != eapol_key_authentication_type_RSNA_EAP |
428 && m_authentication_type != eapol_key_authentication_type_WPA_EAP |
320 && m_authentication_type != eapol_key_authentication_type_WPA_EAP |
429 && m_authentication_type != eapol_key_authentication_type_dynamic_WEP |
321 && m_authentication_type != eapol_key_authentication_type_dynamic_WEP |
430 && m_authentication_type != eapol_key_authentication_type_WPS |
322 && m_authentication_type != eapol_key_authentication_type_WFA_SC |
431 #if defined(EAP_USE_WPXM) |
323 #if defined(EAP_USE_WPXM) |
432 && m_authentication_type != eapol_key_authentication_type_WPXM |
324 && m_authentication_type != eapol_key_authentication_type_WPXM |
433 #endif //#if defined(EAP_USE_WPXM) |
325 #endif //#if defined(EAP_USE_WPXM) |
434 && m_authentication_type != eapol_key_authentication_type_EAP_authentication_no_encryption |
326 && m_authentication_type != eapol_key_authentication_type_EAP_authentication_no_encryption |
435 ) |
327 ) |
448 status = restart_authentication( |
340 status = restart_authentication( |
449 receive_network_id, |
341 receive_network_id, |
450 m_is_client, |
342 m_is_client, |
451 false); |
343 false); |
452 } |
344 } |
345 #if defined(USE_EAPOL_KEY_STATE) |
|
453 else if (eapol.get_packet_type() == eapol_packet_type_key) |
346 else if (eapol.get_packet_type() == eapol_packet_type_key) |
454 { |
347 { |
455 if (m_authentication_type != eapol_key_authentication_type_RSNA_EAP |
348 if (m_authentication_type != eapol_key_authentication_type_RSNA_EAP |
456 && m_authentication_type != eapol_key_authentication_type_RSNA_PSK |
349 && m_authentication_type != eapol_key_authentication_type_RSNA_PSK |
457 && m_authentication_type != eapol_key_authentication_type_WPA_EAP |
350 && m_authentication_type != eapol_key_authentication_type_WPA_EAP |
494 (EAPL("ERROR: process_eapol_key_frame() failed, no eapol_key_state_c object\n"))); |
387 (EAPL("ERROR: process_eapol_key_frame() failed, no eapol_key_state_c object\n"))); |
495 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
388 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
496 return EAP_STATUS_RETURN(m_am_tools, eap_status_handler_does_not_exists_error); |
389 return EAP_STATUS_RETURN(m_am_tools, eap_status_handler_does_not_exists_error); |
497 } |
390 } |
498 } |
391 } |
392 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
393 #if ! defined(USE_EAPOL_KEY_STATE) |
|
394 else if ( |
|
395 m_is_client == true |
|
396 && eapol.get_packet_type() == eapol_packet_type_key) |
|
397 { |
|
398 // Handle EAPOL-Key frame. |
|
399 // Here is assumed the EAPOL-Key frame includes RC4 Key Descriptor. |
|
400 /** |
|
401 * @{ Here we need to check the Descriptor Type field. |
|
402 * It may be RC4 Key Descriptor, RSNA Key Descriptor or other descriptor. } |
|
403 */ |
|
404 |
|
405 eapol_RC4_key_header_c eapol_key_msg( |
|
406 m_am_tools, |
|
407 eapol.get_header_buffer(eapol.get_header_buffer_length()), |
|
408 eapol.get_header_buffer_length()); |
|
409 if (eapol_key_msg.get_is_valid() == false) |
|
410 { |
|
411 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
412 return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted); |
|
413 } |
|
414 else if (eapol_key_msg.check_header() != eap_status_ok) |
|
415 { |
|
416 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
417 return EAP_STATUS_RETURN(m_am_tools, status); |
|
418 } |
|
419 |
|
420 status = handle_RC4_key_descriptor( |
|
421 receive_network_id, |
|
422 &eapol_key_msg, |
|
423 packet_length); |
|
424 } |
|
425 #endif //#if ! defined(USE_EAPOL_KEY_STATE) |
|
499 else |
426 else |
500 { |
427 { |
501 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: %s, packet_type=0x%02x=%s not handled, data length 0x%04x.\n"), |
428 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: %s, packet_type=0x%02x=%s not handled, data length 0x%04x.\n"), |
502 (m_is_client == true) ? "client": "server", |
429 (m_is_client == true) ? "client": "server", |
503 eapol.get_packet_type(), |
430 eapol.get_packet_type(), |
528 EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true); |
455 EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true); |
529 EAP_ASSERT(header_offset < sent_packet->get_data_length()); |
456 EAP_ASSERT(header_offset < sent_packet->get_data_length()); |
530 EAP_ASSERT(data_length <= sent_packet->get_data_length()); |
457 EAP_ASSERT(data_length <= sent_packet->get_data_length()); |
531 EAP_ASSERT(sent_packet->get_data_length() <= buffer_length); |
458 EAP_ASSERT(sent_packet->get_data_length() <= buffer_length); |
532 |
459 |
533 if (header_offset < m_eapol_header_offset+eapol_header_wr_c::get_header_length()) |
460 if (header_offset < eap_header_wr_c::get_header_length()) |
534 { |
461 { |
535 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet_send: packet buffer corrupted.\n"))); |
462 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet_send: packet buffer corrupted.\n"))); |
536 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
463 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
537 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); |
464 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); |
538 } |
465 } |
539 |
466 |
540 eapol_header_wr_c eapol( |
467 eapol_header_wr_c eapol( |
541 m_am_tools, |
468 m_am_tools, |
542 sent_packet->get_data_offset( |
469 sent_packet->get_data_offset( |
543 header_offset-eapol_header_wr_c::get_header_length(), data_length), |
470 header_offset-eap_header_wr_c::get_header_length(), data_length), |
544 data_length); |
471 data_length); |
545 |
472 |
546 if (eapol.get_is_valid() == false) |
473 if (eapol.get_is_valid() == false) |
547 { |
474 { |
548 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet_send: packet buffer corrupted.\n"))); |
475 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet_send: packet buffer corrupted.\n"))); |
610 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
537 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
611 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
538 return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly); |
612 } |
539 } |
613 |
540 |
614 eap_status_e status = m_partner->packet_send( |
541 eap_status_e status = m_partner->packet_send( |
615 send_network_id, |
542 send_network_id, sent_packet, header_offset-eapol_header_wr_c::get_header_length(), |
616 sent_packet, |
543 data_length+eapol_header_wr_c::get_header_length(), buffer_length); |
617 header_offset-eapol_header_wr_c::get_header_length(), |
|
618 data_length+eapol_header_wr_c::get_header_length(), |
|
619 buffer_length); |
|
620 |
544 |
621 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
545 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
622 return EAP_STATUS_RETURN(m_am_tools, status); |
546 return EAP_STATUS_RETURN(m_am_tools, status); |
623 } |
547 } |
624 |
548 |
745 { |
669 { |
746 // Client sends a EAPOL-Start message. |
670 // Client sends a EAPOL-Start message. |
747 (void) m_partner->cancel_timer( |
671 (void) m_partner->cancel_timer( |
748 this, |
672 this, |
749 EAPOL_CORE_TIMER_SEND_START_AGAIN_ID); |
673 EAPOL_CORE_TIMER_SEND_START_AGAIN_ID); |
674 |
|
675 #if !defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
676 #if !defined(NO_EAP_SESSION_CORE) |
|
677 // First we remove possible EAP session. |
|
678 (void) m_eap_core->synchronous_remove_eap_session(receive_network_id); |
|
679 #endif |
|
680 #endif //#if defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
750 |
681 |
751 // Here we swap the addresses. |
682 // Here we swap the addresses. |
752 eap_am_network_id_c send_network_id(m_am_tools, |
683 eap_am_network_id_c send_network_id(m_am_tools, |
753 receive_network_id->get_destination_id(), |
684 receive_network_id->get_destination_id(), |
754 receive_network_id->get_source_id(), |
685 receive_network_id->get_source_id(), |
824 return EAP_STATUS_RETURN(m_am_tools, status); |
755 return EAP_STATUS_RETURN(m_am_tools, status); |
825 } |
756 } |
826 |
757 |
827 if (m_authentication_type == eapol_key_authentication_type_EAP_authentication_no_encryption) |
758 if (m_authentication_type == eapol_key_authentication_type_EAP_authentication_no_encryption) |
828 { |
759 { |
829 // Some APs need broadcast EAPOL-Start-message. |
760 // This is a hack for this security mode. Some APs need broadcast EAPOL-Start-message. |
830 |
761 |
831 const u8_t BROADCAST_ADDRESS[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
762 const u8_t BROADCAST_ADDRESS[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
832 |
763 |
833 eap_variable_data_c broadcast_destination( |
764 eap_variable_data_c broadcast_destination( |
834 m_am_tools, |
765 m_am_tools, |
931 |
862 |
932 if (force_clean_restart == true) |
863 if (force_clean_restart == true) |
933 { |
864 { |
934 // It is bad idea to terminate on-going authentication |
865 // It is bad idea to terminate on-going authentication |
935 // when EAPOL-Start is received. |
866 // when EAPOL-Start is received. |
936 // Because of that remove_eap_session() is called |
867 // Because of that synchronous_remove_eap_session() is called |
937 // only when force_clean_restart is true. |
868 // only when force_clean_restart is true. |
869 #if !defined(NO_EAP_SESSION_CORE) |
|
938 bool previous_block = m_block_state_notifications; |
870 bool previous_block = m_block_state_notifications; |
939 m_block_state_notifications = true; |
871 m_block_state_notifications = true; |
940 (void) m_eap_core->remove_eap_session(false, receive_network_id); |
872 (void) m_eap_core->synchronous_remove_eap_session(receive_network_id); |
941 m_block_state_notifications = previous_block; |
873 m_block_state_notifications = previous_block; |
874 #endif |
|
942 } |
875 } |
943 |
876 |
944 if (m_authentication_type == eapol_key_authentication_type_RSNA_EAP |
877 if (m_authentication_type == eapol_key_authentication_type_RSNA_EAP |
945 || m_authentication_type == eapol_key_authentication_type_WPA_EAP |
878 || m_authentication_type == eapol_key_authentication_type_WPA_EAP |
946 || m_authentication_type == eapol_key_authentication_type_dynamic_WEP |
879 || m_authentication_type == eapol_key_authentication_type_dynamic_WEP |
947 #if defined(EAP_USE_WPXM) |
880 #if defined(EAP_USE_WPXM) |
948 || m_authentication_type == eapol_key_authentication_type_WPXM |
881 || m_authentication_type == eapol_key_authentication_type_WPXM |
949 #endif //#if defined(EAP_USE_WPXM) |
882 #endif //#if defined(EAP_USE_WPXM) |
950 || m_authentication_type == eapol_key_authentication_type_WPS |
883 || m_authentication_type == eapol_key_authentication_type_WFA_SC |
951 || m_authentication_type == eapol_key_authentication_type_EAP_authentication_no_encryption |
884 || m_authentication_type == eapol_key_authentication_type_EAP_authentication_no_encryption |
952 ) |
885 ) |
953 { |
886 { |
954 status = m_eap_core->send_eap_identity_request(receive_network_id); |
887 status = m_eap_core->send_eap_identity_request(receive_network_id); |
955 } |
888 } |
1060 // Check the next index. |
993 // Check the next index. |
1061 ++ind; |
994 ++ind; |
1062 } |
995 } |
1063 } // for() |
996 } // for() |
1064 |
997 |
1065 #if 1 |
|
1066 |
|
1067 status = m_partner->complete_check_pmksa_cache(bssid_sta_receive_network_ids); |
|
1068 return EAP_STATUS_RETURN(m_am_tools, status); |
|
1069 |
|
1070 #else |
|
1071 |
|
1072 if (bssid_sta_receive_network_ids->get_object_count() > 0ul) |
998 if (bssid_sta_receive_network_ids->get_object_count() > 0ul) |
1073 { |
999 { |
1074 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1000 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1075 return EAP_STATUS_RETURN(m_am_tools, status); |
1001 return EAP_STATUS_RETURN(m_am_tools, status); |
1076 } |
1002 } |
1077 else |
1003 else |
1078 { |
1004 { |
1079 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1005 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1080 return EAP_STATUS_RETURN(m_am_tools, eap_status_not_found); |
1006 return EAP_STATUS_RETURN(m_am_tools, eap_status_not_found); |
1081 } |
1007 } |
1082 |
|
1083 #endif |
|
1084 |
|
1085 } |
1008 } |
1086 |
1009 |
1087 //-------------------------------------------------- |
1010 //-------------------------------------------------- |
1088 |
1011 |
1089 /** |
1012 /** |
1121 { |
1044 { |
1122 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
1045 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
1123 } |
1046 } |
1124 |
1047 |
1125 status = remove_eapol_key_state( |
1048 status = remove_eapol_key_state( |
1126 &send_network_id, |
1049 &send_network_id); |
1127 true); |
|
1128 if (status != eap_status_ok) |
1050 if (status != eap_status_ok) |
1129 { |
1051 { |
1130 EAP_TRACE_DEBUG( |
1052 EAP_TRACE_DEBUG( |
1131 m_am_tools, |
1053 m_am_tools, |
1132 TRACE_FLAGS_DEFAULT, |
1054 TRACE_FLAGS_DEFAULT, |
1133 (EAPL("WARNING: eapol_core_c::remove_pmksa_from_cache(): ") |
1055 (EAPL("WARNING: eapol_core_c::disassociation(): ") |
1134 EAPL("remove_eapol_key_state(), eap_status_e %d\n"), |
1056 EAPL("remove_eapol_key_state(), eap_status_e %d\n"), |
1135 status)); |
1057 status)); |
1136 return EAP_STATUS_RETURN(m_am_tools, status); |
1058 return EAP_STATUS_RETURN(m_am_tools, status); |
1137 } |
1059 } |
1138 |
1060 |
1153 TRACE_FLAGS_DEFAULT, |
1075 TRACE_FLAGS_DEFAULT, |
1154 (EAPL("%s: eapol_core_c::start_preauthentication().\n"), |
1076 (EAPL("%s: eapol_core_c::start_preauthentication().\n"), |
1155 (m_is_client == true) ? "client": "server")); |
1077 (m_is_client == true) ? "client": "server")); |
1156 |
1078 |
1157 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::start_preauthentication()"); |
1079 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::start_preauthentication()"); |
1080 |
|
1081 #if defined(USE_EAPOL_KEY_STATE) |
|
1158 |
1082 |
1159 if (receive_network_id->get_type() != eapol_ethernet_type_preauthentication) |
1083 if (receive_network_id->get_type() != eapol_ethernet_type_preauthentication) |
1160 { |
1084 { |
1161 EAP_TRACE_DEBUG( |
1085 EAP_TRACE_DEBUG( |
1162 m_am_tools, |
1086 m_am_tools, |
1296 |
1220 |
1297 status = eapol_key_state->configure(); |
1221 status = eapol_key_state->configure(); |
1298 if (status != eap_status_ok) |
1222 if (status != eap_status_ok) |
1299 { |
1223 { |
1300 status = remove_eapol_key_state( |
1224 status = remove_eapol_key_state( |
1301 &send_network_id, |
1225 &send_network_id); |
1302 true); |
|
1303 if (status != eap_status_ok) |
1226 if (status != eap_status_ok) |
1304 { |
1227 { |
1305 EAP_TRACE_DEBUG( |
1228 EAP_TRACE_DEBUG( |
1306 m_am_tools, |
1229 m_am_tools, |
1307 TRACE_FLAGS_DEFAULT, |
1230 TRACE_FLAGS_DEFAULT, |
1319 receive_network_id, |
1242 receive_network_id, |
1320 m_is_client, |
1243 m_is_client, |
1321 true, |
1244 true, |
1322 false); |
1245 false); |
1323 |
1246 |
1247 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
1248 |
|
1324 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1249 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1325 return EAP_STATUS_RETURN(m_am_tools, status); |
1250 return EAP_STATUS_RETURN(m_am_tools, status); |
1326 } |
1251 } |
1327 |
1252 |
1328 //-------------------------------------------------- |
1253 //-------------------------------------------------- |
1356 || new_receive_network_id->get_is_valid_data() == false) |
1281 || new_receive_network_id->get_is_valid_data() == false) |
1357 { |
1282 { |
1358 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1283 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1359 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
1284 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
1360 } |
1285 } |
1286 |
|
1287 #if defined(USE_EAPOL_KEY_STATE) |
|
1361 |
1288 |
1362 // Here we swap the addresses. |
1289 // Here we swap the addresses. |
1363 eap_am_network_id_c old_send_network_id( |
1290 eap_am_network_id_c old_send_network_id( |
1364 m_am_tools, |
1291 m_am_tools, |
1365 old_receive_network_id->get_destination_id(), |
1292 old_receive_network_id->get_destination_id(), |
1453 return EAP_STATUS_RETURN(m_am_tools, status); |
1380 return EAP_STATUS_RETURN(m_am_tools, status); |
1454 } |
1381 } |
1455 } |
1382 } |
1456 } |
1383 } |
1457 |
1384 |
1385 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
1386 |
|
1458 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1387 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1459 return EAP_STATUS_RETURN(m_am_tools, status); |
1388 return EAP_STATUS_RETURN(m_am_tools, status); |
1460 } |
1389 } |
1461 |
1390 |
1462 //-------------------------------------------------- |
1391 //-------------------------------------------------- |
1497 || new_receive_network_id->get_is_valid_data() == false) |
1426 || new_receive_network_id->get_is_valid_data() == false) |
1498 { |
1427 { |
1499 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1428 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1500 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
1429 return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter); |
1501 } |
1430 } |
1431 |
|
1432 #if defined(USE_EAPOL_KEY_STATE) |
|
1502 |
1433 |
1503 // Here we swap the addresses. |
1434 // Here we swap the addresses. |
1504 eap_am_network_id_c old_send_network_id( |
1435 eap_am_network_id_c old_send_network_id( |
1505 m_am_tools, |
1436 m_am_tools, |
1506 old_receive_network_id->get_destination_id(), |
1437 old_receive_network_id->get_destination_id(), |
1597 else |
1528 else |
1598 { |
1529 { |
1599 status = eap_status_not_found; |
1530 status = eap_status_not_found; |
1600 } |
1531 } |
1601 |
1532 |
1533 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
1534 |
|
1602 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1535 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1603 return EAP_STATUS_RETURN(m_am_tools, status); |
1536 return EAP_STATUS_RETURN(m_am_tools, status); |
1604 } |
1537 } |
1605 |
1538 |
1606 //-------------------------------------------------- |
1539 //-------------------------------------------------- |
1607 |
1540 |
1608 // |
1541 // |
1609 EAP_FUNC_EXPORT eap_status_e eapol_core_c::read_reassociation_parameters( |
1542 eap_status_e eapol_core_c::read_reassociation_parameters( |
1610 const eap_am_network_id_c * const old_receive_network_id, ///< source includes remote address, destination includes local address. |
1543 const eap_am_network_id_c * const old_receive_network_id, ///< source includes remote address, destination includes local address. |
1611 const eap_am_network_id_c * const new_receive_network_id, ///< source includes remote address, destination includes local address. |
1544 const eap_am_network_id_c * const new_receive_network_id, ///< source includes remote address, destination includes local address. |
1612 const eapol_key_authentication_type_e authentication_type, |
1545 const eapol_key_authentication_type_e authentication_type, |
1613 eap_variable_data_c * const PMKID, |
1546 eap_variable_data_c * const PMKID, |
1614 const eap_variable_data_c * const received_WPA_ie, |
1547 const eap_variable_data_c * const received_WPA_ie, |
1623 (m_is_client == true) ? "client": "server")); |
1556 (m_is_client == true) ? "client": "server")); |
1624 |
1557 |
1625 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::read_reassociation_parameters()"); |
1558 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::read_reassociation_parameters()"); |
1626 |
1559 |
1627 eap_status_e status(eap_status_process_general_error); |
1560 eap_status_e status(eap_status_process_general_error); |
1561 |
|
1562 #if defined(USE_EAPOL_KEY_STATE) |
|
1628 |
1563 |
1629 // No need to check authentication type anymore. It can be changed in reassociation. |
1564 // No need to check authentication type anymore. It can be changed in reassociation. |
1630 |
1565 |
1631 #if defined(EAP_USE_WPXM) |
1566 #if defined(EAP_USE_WPXM) |
1632 if (authentication_type == eapol_key_authentication_type_WPXM) |
1567 if (authentication_type == eapol_key_authentication_type_WPXM) |
1729 else |
1664 else |
1730 { |
1665 { |
1731 status = eap_status_not_found; |
1666 status = eap_status_not_found; |
1732 } |
1667 } |
1733 |
1668 |
1669 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
1670 |
|
1734 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1671 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1735 return EAP_STATUS_RETURN(m_am_tools, status); |
1672 return EAP_STATUS_RETURN(m_am_tools, status); |
1736 } |
1673 } |
1737 |
1674 |
1738 //-------------------------------------------------- |
1675 //-------------------------------------------------- |
1795 (EAPL("eapol_core_c::start_reassociation(): eapol_key_state NOT reused.\n"))); |
1732 (EAPL("eapol_core_c::start_reassociation(): eapol_key_state NOT reused.\n"))); |
1796 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1733 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1797 return EAP_STATUS_RETURN(m_am_tools, status); |
1734 return EAP_STATUS_RETURN(m_am_tools, status); |
1798 } |
1735 } |
1799 |
1736 |
1737 #if defined(USE_EAPOL_KEY_STATE) |
|
1800 if (m_skip_start_4_way_handshake == true |
1738 if (m_skip_start_4_way_handshake == true |
1801 && (authentication_type == eapol_key_authentication_type_RSNA_EAP |
1739 && (authentication_type == eapol_key_authentication_type_RSNA_EAP |
1802 || authentication_type == eapol_key_authentication_type_RSNA_PSK |
1740 || authentication_type == eapol_key_authentication_type_RSNA_PSK |
1803 || authentication_type == eapol_key_authentication_type_WPA_EAP |
1741 || authentication_type == eapol_key_authentication_type_WPA_EAP |
1804 || authentication_type == eapol_key_authentication_type_WPA_PSK)) |
1742 || authentication_type == eapol_key_authentication_type_WPA_PSK)) |
1811 EAPL("skips start_4_way_handshake()\n"))); |
1749 EAPL("skips start_4_way_handshake()\n"))); |
1812 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1750 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1813 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
1751 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
1814 } |
1752 } |
1815 else |
1753 else |
1754 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
1816 { |
1755 { |
1817 #if !defined(NO_EAPOL_KEY_STATE_SERVER) |
1756 #if !defined(NO_EAPOL_KEY_STATE_SERVER) |
1818 status = eapol_key_state->start_4_way_handshake( |
1757 status = eapol_key_state->start_4_way_handshake( |
1819 receive_network_id); |
1758 receive_network_id); |
1820 #endif //#if !defined(NO_EAPOL_KEY_STATE_SERVER) |
1759 #endif //#if !defined(NO_EAPOL_KEY_STATE_SERVER) |
1848 } |
1787 } |
1849 |
1788 |
1850 //-------------------------------------------------- |
1789 //-------------------------------------------------- |
1851 |
1790 |
1852 // |
1791 // |
1853 EAP_FUNC_EXPORT eap_status_e eapol_core_c::complete_reassociation( |
1792 eap_status_e eapol_core_c::complete_reassociation( |
1854 const eapol_wlan_authentication_state_e reassociation_result, |
1793 const eapol_wlan_authentication_state_e reassociation_result, |
1855 const eap_am_network_id_c * const receive_network_id, |
1794 const eap_am_network_id_c * const receive_network_id, |
1856 const eapol_key_authentication_type_e authentication_type, |
1795 const eapol_key_authentication_type_e authentication_type, |
1857 const eap_variable_data_c * const received_WPA_IE, |
1796 const eap_variable_data_c * const received_WPA_IE, |
1858 const eap_variable_data_c * const sent_WPA_IE, |
1797 const eap_variable_data_c * const sent_WPA_IE, |
1867 TRACE_FLAGS_DEFAULT, |
1806 TRACE_FLAGS_DEFAULT, |
1868 (EAPL("%s: eapol_core_c::complete_reassociation()\n"), |
1807 (EAPL("%s: eapol_core_c::complete_reassociation()\n"), |
1869 (m_is_client == true) ? "client": "server")); |
1808 (m_is_client == true) ? "client": "server")); |
1870 |
1809 |
1871 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::complete_reassociation()"); |
1810 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::complete_reassociation()"); |
1811 |
|
1812 #if defined(USE_EAPOL_KEY_STATE) |
|
1872 |
1813 |
1873 // Here we swap the addresses. |
1814 // Here we swap the addresses. |
1874 eap_am_network_id_c send_network_id( |
1815 eap_am_network_id_c send_network_id( |
1875 m_am_tools, |
1816 m_am_tools, |
1876 receive_network_id->get_destination_id(), |
1817 receive_network_id->get_destination_id(), |
1920 |
1861 |
1921 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1862 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1922 return EAP_STATUS_RETURN(m_am_tools, status); |
1863 return EAP_STATUS_RETURN(m_am_tools, status); |
1923 } |
1864 } |
1924 else |
1865 else |
1866 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
1925 { |
1867 { |
1926 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1868 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
1927 return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure); |
1869 return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure); |
1928 } |
1870 } |
1929 } |
1871 } |
2055 (EAPL("master session key"), |
1997 (EAPL("master session key"), |
2056 master_session_key->get_data(master_session_key->get_data_length()), |
1998 master_session_key->get_data(master_session_key->get_data_length()), |
2057 master_session_key->get_data_length())); |
1999 master_session_key->get_data_length())); |
2058 } |
2000 } |
2059 |
2001 |
2002 #if defined(USE_EAPOL_KEY_STATE) |
|
2003 |
|
2060 eap_network_id_selector_c state_selector( |
2004 eap_network_id_selector_c state_selector( |
2061 m_am_tools, |
2005 m_am_tools, |
2062 send_network_id); |
2006 send_network_id); |
2063 |
2007 |
2064 if (state_selector.get_is_valid() == false) |
2008 if (state_selector.get_is_valid() == false) |
2089 TRACE_FLAGS_DEFAULT, |
2033 TRACE_FLAGS_DEFAULT, |
2090 (EAPL("ERROR: packet_data_crypto_keys() failed, no eapol_key_state_c object\n"))); |
2034 (EAPL("ERROR: packet_data_crypto_keys() failed, no eapol_key_state_c object\n"))); |
2091 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
2035 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
2092 return EAP_STATUS_RETURN(m_am_tools, eap_status_handler_does_not_exists_error); |
2036 return EAP_STATUS_RETURN(m_am_tools, eap_status_handler_does_not_exists_error); |
2093 } |
2037 } |
2038 |
|
2039 #else |
|
2040 |
|
2041 // Store the session key so it can be used when EAPOL-Key is received. |
|
2042 m_master_session_key.reset(); |
|
2043 |
|
2044 status = m_master_session_key.set_copy_of_buffer(master_session_key); |
|
2045 if (status != eap_status_ok) |
|
2046 { |
|
2047 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2048 return EAP_STATUS_RETURN(m_am_tools, status); |
|
2049 } |
|
2050 |
|
2051 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2094 |
2052 |
2095 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
2053 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
2096 return EAP_STATUS_RETURN(m_am_tools, status); |
2054 return EAP_STATUS_RETURN(m_am_tools, status); |
2097 } |
2055 } |
2098 |
2056 |
2144 return EAP_STATUS_RETURN(m_am_tools, status); |
2102 return EAP_STATUS_RETURN(m_am_tools, status); |
2145 } |
2103 } |
2146 |
2104 |
2147 //-------------------------------------------------- |
2105 //-------------------------------------------------- |
2148 |
2106 |
2107 #if !defined(USE_EAPOL_KEY_STATE) |
|
2108 |
|
2109 // |
|
2110 eap_status_e eapol_core_c::handle_RC4_key_descriptor( |
|
2111 const eap_am_network_id_c * const receive_network_id, |
|
2112 eapol_RC4_key_header_c* const packet, |
|
2113 const u32_t packet_length) |
|
2114 { |
|
2115 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2116 |
|
2117 EAP_TRACE_DEBUG( |
|
2118 m_am_tools, |
|
2119 TRACE_FLAGS_DEFAULT, |
|
2120 (EAPL("%s: eapol_core_c::handle_RC4_key_descriptor()\n"), |
|
2121 (m_is_client == true) ? "client": "server")); |
|
2122 |
|
2123 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::handle_RC4_key_descriptor()"); |
|
2124 |
|
2125 eap_status_e status = eap_status_process_general_error; |
|
2126 |
|
2127 // Check the packet length |
|
2128 if (static_cast<u32_t>(packet->get_header_length()) != packet_length |
|
2129 && static_cast<u32_t>(packet->get_header_length() + packet->get_key_length()) != packet_length) |
|
2130 { |
|
2131 EAP_TRACE_DEBUG( |
|
2132 m_am_tools, |
|
2133 TRACE_FLAGS_DEFAULT, |
|
2134 (EAPL("ERROR: Illegal EAPOL-Key frame length, packet->get_header_length() %d, packet_length %d\n"), |
|
2135 packet->get_header_length(), |
|
2136 packet_length)); |
|
2137 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2138 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error); |
|
2139 } |
|
2140 |
|
2141 // Get MS-MPPE-Recv-Key and MS-MPPE-Send-Key |
|
2142 // Recv-Key is the first 32 bytes of master session key and Send-Key is the next 32 bytes. |
|
2143 eap_variable_data_c mppe_recv_key(m_am_tools); |
|
2144 eap_variable_data_c mppe_send_key(m_am_tools); |
|
2145 if (m_master_session_key.get_data_length() == 16ul) |
|
2146 { |
|
2147 status = mppe_recv_key.set_buffer( |
|
2148 m_master_session_key.get_data(m_master_session_key.get_data_length()), |
|
2149 m_master_session_key.get_data_length(), |
|
2150 false, |
|
2151 false); |
|
2152 if (status != eap_status_ok) |
|
2153 { |
|
2154 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2155 return EAP_STATUS_RETURN(m_am_tools, status); |
|
2156 } |
|
2157 |
|
2158 status = mppe_send_key.set_buffer( |
|
2159 m_master_session_key.get_data(m_master_session_key.get_data_length()), |
|
2160 m_master_session_key.get_data_length(), |
|
2161 false, |
|
2162 false); |
|
2163 if (status != eap_status_ok) |
|
2164 { |
|
2165 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2166 return EAP_STATUS_RETURN(m_am_tools, status); |
|
2167 } |
|
2168 } |
|
2169 else |
|
2170 { |
|
2171 status = mppe_recv_key.set_buffer( |
|
2172 m_master_session_key.get_data(MPPE_KEY_LENGTH), |
|
2173 MPPE_KEY_LENGTH, |
|
2174 false, |
|
2175 false); |
|
2176 if (status != eap_status_ok) |
|
2177 { |
|
2178 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2179 return EAP_STATUS_RETURN(m_am_tools, status); |
|
2180 } |
|
2181 |
|
2182 status = mppe_send_key.set_buffer( |
|
2183 m_master_session_key.get_data_offset(MPPE_KEY_LENGTH, MPPE_KEY_LENGTH), |
|
2184 MPPE_KEY_LENGTH, |
|
2185 false, |
|
2186 false); |
|
2187 if (status != eap_status_ok) |
|
2188 { |
|
2189 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2190 return EAP_STATUS_RETURN(m_am_tools, status); |
|
2191 } |
|
2192 } |
|
2193 |
|
2194 if (mppe_recv_key.get_is_valid() == false |
|
2195 || mppe_send_key.get_is_valid() == false) |
|
2196 { |
|
2197 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2198 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
2199 } |
|
2200 |
|
2201 // Verify the the MD5 signature in Eapol-Key |
|
2202 crypto_md5_c md5(m_am_tools); |
|
2203 crypto_hmac_c hmac_md5(m_am_tools, &md5, false); |
|
2204 if (hmac_md5.get_is_valid() == false) |
|
2205 { |
|
2206 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2207 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
2208 } |
|
2209 |
|
2210 // MPPE-Send-Key is used as the signature key. |
|
2211 if (hmac_md5.hmac_set_key(&mppe_send_key) != eap_status_ok) |
|
2212 { |
|
2213 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: hmac_md5_init failed\n"))); |
|
2214 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2215 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
2216 } |
|
2217 |
|
2218 // Save the signature from the packet |
|
2219 eap_variable_data_c signature(m_am_tools); |
|
2220 status = signature.set_copy_of_buffer(packet->get_key_signature(), EAPOL_RC4_KEY_SIGNATURE_LENGTH); |
|
2221 if (status != eap_status_ok) |
|
2222 { |
|
2223 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2224 return EAP_STATUS_RETURN(m_am_tools, status); |
|
2225 } |
|
2226 |
|
2227 // Replace the signature with zeros. |
|
2228 packet->zero_key_signature(m_am_tools); |
|
2229 |
|
2230 // Send the data to HMAC-MD5 module |
|
2231 if (hmac_md5.hmac_update(packet->get_header_buffer(packet_length), packet_length) != eap_status_ok) |
|
2232 { |
|
2233 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: hmac_md5_update failed\n"))); |
|
2234 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2235 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); |
|
2236 } |
|
2237 |
|
2238 // Get the calculated signature |
|
2239 u8_t tmp_signature[EAPOL_RC4_KEY_SIGNATURE_LENGTH]; |
|
2240 u32_t length = EAPOL_RC4_KEY_SIGNATURE_LENGTH; |
|
2241 if (hmac_md5.hmac_final(tmp_signature, &length) != eap_status_ok) |
|
2242 { |
|
2243 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: hmac_md5_final failed\n"))); |
|
2244 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2245 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); |
|
2246 } |
|
2247 |
|
2248 // Compare the calculated and original signature |
|
2249 if (m_am_tools->memcmp( |
|
2250 tmp_signature, |
|
2251 signature.get_data( |
|
2252 EAPOL_RC4_KEY_SIGNATURE_LENGTH), |
|
2253 EAPOL_RC4_KEY_SIGNATURE_LENGTH) != 0) |
|
2254 { |
|
2255 // Signatures did not match. Something's wrong. |
|
2256 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: EAPOL-Key HMAC-MD5 check failed.\n"))); |
|
2257 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2258 return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted); |
|
2259 } |
|
2260 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAPOL-Key HMAC-MD5 check passed.\n"))); |
|
2261 |
|
2262 eap_variable_data_c key_out(m_am_tools); |
|
2263 // Decrypt the RC4 encrypted key |
|
2264 if (packet->get_key() == 0) |
|
2265 { |
|
2266 // EAPOL-Key does not contain the key. This means that we should use |
|
2267 // the first bytes from MS-MPPE-Recv-Key as the key. There is a slight |
|
2268 // confusion in draft-congdon-radius-8021x-23.txt regarding this but this is how |
|
2269 // it works. |
|
2270 if (packet->get_key_length() > 0) |
|
2271 { |
|
2272 status = key_out.set_copy_of_buffer(mppe_recv_key.get_data(packet->get_key_length()), packet->get_key_length()); |
|
2273 if (status != eap_status_ok) |
|
2274 { |
|
2275 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2276 return EAP_STATUS_RETURN(m_am_tools, status); |
|
2277 } |
|
2278 } |
|
2279 else |
|
2280 { |
|
2281 // Key message with no key length? |
|
2282 // Just ignore the message. |
|
2283 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("Got empty WEP unicast key message.\n"))); |
|
2284 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2285 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
|
2286 } |
|
2287 } |
|
2288 else |
|
2289 { |
|
2290 // Set-up RC4 key. Key is the IV and the MS-MPPE-Recv-Key truncated together. |
|
2291 eap_variable_data_c rc4_key(m_am_tools); |
|
2292 status = rc4_key.set_copy_of_buffer(packet->get_key_IV(), EAPOL_RC4_KEY_IV_LENGTH); |
|
2293 if (status != eap_status_ok) |
|
2294 { |
|
2295 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2296 return EAP_STATUS_RETURN(m_am_tools, status); |
|
2297 } |
|
2298 |
|
2299 rc4_key.add_data(&mppe_recv_key); |
|
2300 |
|
2301 // Set-up RC4 module |
|
2302 crypto_rc4_c rc4(m_am_tools); |
|
2303 // Set the key for RC4 |
|
2304 if (rc4.set_key(&rc4_key) != eap_status_ok) |
|
2305 { |
|
2306 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: rc4_set_key failed\n"))); |
|
2307 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2308 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); |
|
2309 } |
|
2310 |
|
2311 // Decrypt the key to key_out |
|
2312 key_out.set_buffer_length(packet->get_key_length()); |
|
2313 if (rc4.decrypt_data(packet->get_key(), key_out.get_data(packet->get_key_length()), packet->get_key_length()) != eap_status_ok) |
|
2314 { |
|
2315 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("ERROR: rc4 failed\n"))); |
|
2316 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2317 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); |
|
2318 } |
|
2319 key_out.set_data_length(packet->get_key_length()); |
|
2320 } |
|
2321 |
|
2322 // Find out the key type. At the moment only WEP keys are supported. |
|
2323 eapol_key_type_e key_type; |
|
2324 switch (packet->get_key_flag()) |
|
2325 { |
|
2326 case eapol_RC4_key_flag_broadcast: |
|
2327 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("Got WEP broadcast key\n"))); |
|
2328 key_type = eapol_key_type_broadcast; |
|
2329 break; |
|
2330 case eapol_RC4_key_flag_unicast: |
|
2331 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("Got WEP unicast key\n"))); |
|
2332 key_type = eapol_key_type_unicast; |
|
2333 break; |
|
2334 default: |
|
2335 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2336 return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted); |
|
2337 } |
|
2338 |
|
2339 EAP_TRACE_DATA_DEBUG( |
|
2340 m_am_tools, |
|
2341 TRACE_FLAGS_DEFAULT, |
|
2342 (EAPL("Key"), |
|
2343 key_out.get_data(key_out.get_data_length()), |
|
2344 key_out.get_data_length())); |
|
2345 |
|
2346 // Here we swap the addresses. |
|
2347 eap_am_network_id_c send_network_id(m_am_tools, |
|
2348 receive_network_id->get_destination_id(), |
|
2349 receive_network_id->get_source_id(), |
|
2350 receive_network_id->get_type()); |
|
2351 if (send_network_id.get_is_valid_data() == false) |
|
2352 { |
|
2353 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
2354 } |
|
2355 |
|
2356 eapol_session_key_c wep_key( |
|
2357 m_am_tools, |
|
2358 &key_out, |
|
2359 key_type, |
|
2360 packet->get_key_index(), |
|
2361 true); |
|
2362 |
|
2363 // Forward the keys to lower layers |
|
2364 status = m_partner->packet_data_session_key( |
|
2365 &send_network_id, |
|
2366 &wep_key); |
|
2367 |
|
2368 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
2369 return EAP_STATUS_RETURN(m_am_tools, status); |
|
2370 } |
|
2371 |
|
2372 #endif //#if !defined(USE_EAPOL_KEY_STATE) |
|
2373 |
|
2374 //-------------------------------------------------- |
|
2375 |
|
2376 // |
|
2377 EAP_FUNC_EXPORT eap_status_e eapol_core_c::configure() |
|
2378 { |
|
2379 EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true); |
|
2380 |
|
2381 EAP_TRACE_DEBUG( |
|
2382 m_am_tools, |
|
2383 TRACE_FLAGS_DEFAULT, |
|
2384 (EAPL("%s: eapol_core_c::configure()\n"), |
|
2385 (m_is_client == true) ? "client": "server")); |
|
2386 |
|
2387 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::configure()"); |
|
2388 |
|
2389 m_eapol_header_offset = m_partner->get_header_offset( |
|
2390 &m_MTU, &m_trailer_length); |
|
2391 |
|
2392 eap_status_e status = eap_status_process_general_error; |
|
2393 |
|
2394 { |
|
2395 eap_variable_data_c max_eapol_starts(m_am_tools); |
|
2396 |
|
2397 status = read_configure( |
|
2398 cf_str_EAPOL_CORE_starts_max_count.get_field(), |
|
2399 &max_eapol_starts); |
|
2400 if (status != eap_status_ok |
|
2401 || max_eapol_starts.get_is_valid_data() == false |
|
2402 || max_eapol_starts.get_data_length() < sizeof(u32_t)) |
|
2403 { |
|
2404 // Probably not found from db. Use the default value. |
|
2405 m_max_eapol_starts = EAPOL_CORE_MAX_EAPOL_START_SENDINGS; |
|
2406 } |
|
2407 else |
|
2408 { |
|
2409 m_max_eapol_starts = *reinterpret_cast<u32_t *>( |
|
2410 max_eapol_starts.get_data(sizeof(u32_t))); |
|
2411 } |
|
2412 } |
|
2413 |
|
2414 { |
|
2415 eap_variable_data_c eapol_start_interval(m_am_tools); |
|
2416 |
|
2417 status = read_configure( |
|
2418 cf_str_EAPOL_CORE_send_start_interval.get_field(), |
|
2419 &eapol_start_interval); |
|
2420 if (status != eap_status_ok |
|
2421 || eapol_start_interval.get_is_valid_data() == false |
|
2422 || eapol_start_interval.get_data_length() < sizeof(u32_t)) |
|
2423 { |
|
2424 // Probably not found from db. Use the default value. |
|
2425 m_eapol_start_interval = EAPOL_CORE_TIMER_SEND_START_AGAIN_TIMEOUT; |
|
2426 } |
|
2427 else |
|
2428 { |
|
2429 m_eapol_start_interval = *reinterpret_cast<u32_t *>( |
|
2430 eapol_start_interval.get_data(sizeof(u32_t))); |
|
2431 } |
|
2432 } |
|
2433 |
|
2434 #if defined(USE_EAP_CORE_SERVER) |
|
2435 if (m_is_client == false) |
|
2436 { |
|
2437 eap_variable_data_c data(m_am_tools); |
|
2438 |
|
2439 eap_status_e status = read_configure( |
|
2440 cf_str_EAPOL_CORE_skip_start_4_way_handshake.get_field(), |
|
2441 &data); |
|
2442 if (status == eap_status_ok |
|
2443 && data.get_data_length() == sizeof(u32_t) |
|
2444 && data.get_data(data.get_data_length()) != 0) |
|
2445 { |
|
2446 u32_t *flag = reinterpret_cast<u32_t *>(data.get_data(data.get_data_length())); |
|
2447 |
|
2448 if (flag != 0) |
|
2449 { |
|
2450 if ((*flag) != 0ul) |
|
2451 { |
|
2452 m_skip_start_4_way_handshake = true; |
|
2453 } |
|
2454 else |
|
2455 { |
|
2456 m_skip_start_4_way_handshake = false; |
|
2457 } |
|
2458 } |
|
2459 } |
|
2460 } |
|
2461 #endif //#if defined(USE_EAP_CORE_SERVER) |
|
2462 |
|
2463 return EAP_STATUS_RETURN(m_am_tools, m_eap_core->configure()); |
|
2464 } |
|
2465 |
|
2466 //-------------------------------------------------- |
|
2467 |
|
2468 #if defined(USE_EAPOL_KEY_STATE) |
|
2469 |
|
2149 // |
2470 // |
2150 EAP_FUNC_EXPORT eap_status_e eapol_core_c::shutdown_operation( |
2471 EAP_FUNC_EXPORT eap_status_e eapol_core_c::shutdown_operation( |
2151 eapol_key_state_c * const handler, |
2472 eapol_key_state_c * const handler, |
2152 abs_eap_am_tools_c * const m_am_tools) |
2473 abs_eap_am_tools_c * const m_am_tools) |
2153 { |
2474 { |
2159 |
2480 |
2160 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
2481 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
2161 return EAP_STATUS_RETURN(m_am_tools, status); |
2482 return EAP_STATUS_RETURN(m_am_tools, status); |
2162 } |
2483 } |
2163 |
2484 |
2485 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2486 |
|
2164 //-------------------------------------------------- |
2487 //-------------------------------------------------- |
2165 |
2488 |
2166 // |
2489 // |
2167 EAP_FUNC_EXPORT eap_status_e eapol_core_c::shutdown() |
2490 EAP_FUNC_EXPORT eap_status_e eapol_core_c::shutdown() |
2168 { |
2491 { |
2182 // Shutdown function was called already. |
2505 // Shutdown function was called already. |
2183 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
2506 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
2184 } |
2507 } |
2185 m_shutdown_was_called = true; |
2508 m_shutdown_was_called = true; |
2186 |
2509 |
2187 eap_status_e status = m_eapol_key_state_map.for_each(shutdown_operation, true); |
2510 eap_status_e status; |
2511 #if defined(USE_EAPOL_KEY_STATE) |
|
2512 status = m_eapol_key_state_map.for_each(shutdown_operation, true); |
|
2513 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2188 |
2514 |
2189 if (m_eap_core != 0) |
2515 if (m_eap_core != 0) |
2190 { |
2516 { |
2191 status = m_eap_core->shutdown(); |
2517 status = m_eap_core->shutdown(); |
2192 } |
2518 } |
2193 |
2519 |
2194 // This will cancel all timers of this object. |
2520 // This will cancel all timers of this object. |
2195 m_partner->cancel_timer(this, EAPOL_CORE_TIMER_SEND_START_AGAIN_ID); |
2521 m_partner->cancel_timer(this, EAPOL_CORE_TIMER_SEND_START_AGAIN_ID); |
2522 #if defined(USE_EAPOL_KEY_STATE) |
|
2196 m_partner->cancel_timer(this, EAPOL_REMOVE_EAPOL_KEY_HANDSHAKE_ID); |
2523 m_partner->cancel_timer(this, EAPOL_REMOVE_EAPOL_KEY_HANDSHAKE_ID); |
2524 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2197 |
2525 |
2198 return EAP_STATUS_RETURN(m_am_tools, status); |
2526 return EAP_STATUS_RETURN(m_am_tools, status); |
2199 } |
2527 } |
2200 |
2528 |
2201 //-------------------------------------------------- |
2529 //-------------------------------------------------- |
2317 notification.set_authentication_error(eap_status_authentication_failure); |
2645 notification.set_authentication_error(eap_status_authentication_failure); |
2318 |
2646 |
2319 state_notification(¬ification); |
2647 state_notification(¬ification); |
2320 } |
2648 } |
2321 } |
2649 } |
2650 #if defined(USE_EAPOL_KEY_STATE) |
|
2322 else if (id == EAPOL_REMOVE_EAPOL_KEY_HANDSHAKE_ID) |
2651 else if (id == EAPOL_REMOVE_EAPOL_KEY_HANDSHAKE_ID) |
2323 { |
2652 { |
2324 EAP_TRACE_DEBUG( |
2653 EAP_TRACE_DEBUG( |
2325 m_am_tools, |
2654 m_am_tools, |
2326 TRACE_FLAGS_DEFAULT, |
2655 TRACE_FLAGS_DEFAULT, |
2332 if (send_network_id->get_is_valid_data() == false) |
2661 if (send_network_id->get_is_valid_data() == false) |
2333 { |
2662 { |
2334 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
2663 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
2335 } |
2664 } |
2336 |
2665 |
2337 (void) remove_eapol_key_state(send_network_id, false); |
2666 (void) remove_eapol_key_state(send_network_id); |
2338 } |
2667 } |
2668 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2339 |
2669 |
2340 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
2670 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
2341 } |
2671 } |
2342 |
2672 |
2343 //-------------------------------------------------- |
2673 //-------------------------------------------------- |
2361 { |
2691 { |
2362 const eap_am_network_id_c * const send_network_id |
2692 const eap_am_network_id_c * const send_network_id |
2363 = reinterpret_cast<const eap_am_network_id_c *>(data); |
2693 = reinterpret_cast<const eap_am_network_id_c *>(data); |
2364 delete send_network_id; |
2694 delete send_network_id; |
2365 } |
2695 } |
2696 #if defined(USE_EAPOL_KEY_STATE) |
|
2366 else if (id == EAPOL_REMOVE_EAPOL_KEY_HANDSHAKE_ID) |
2697 else if (id == EAPOL_REMOVE_EAPOL_KEY_HANDSHAKE_ID) |
2367 |
2698 |
2368 { |
2699 { |
2369 const eap_am_network_id_c * const send_network_id |
2700 const eap_am_network_id_c * const send_network_id |
2370 = reinterpret_cast<const eap_am_network_id_c *>(data); |
2701 = reinterpret_cast<const eap_am_network_id_c *>(data); |
2371 delete send_network_id; |
2702 delete send_network_id; |
2372 } |
2703 } |
2704 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2373 |
2705 |
2374 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
2706 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
2375 } |
2707 } |
2376 |
2708 |
2377 //-------------------------------------------------- |
2709 //-------------------------------------------------- |
2710 |
|
2711 #if defined(USE_EAPOL_KEY_STATE) |
|
2378 |
2712 |
2379 // |
2713 // |
2380 EAP_FUNC_EXPORT eap_status_e eapol_core_c::init_eapol_key_pmksa_caching_timeout( |
2714 EAP_FUNC_EXPORT eap_status_e eapol_core_c::init_eapol_key_pmksa_caching_timeout( |
2381 const eap_am_network_id_c * const send_network_id) |
2715 const eap_am_network_id_c * const send_network_id) |
2382 { |
2716 { |
2432 } |
2766 } |
2433 |
2767 |
2434 return EAP_STATUS_RETURN(m_am_tools, status); |
2768 return EAP_STATUS_RETURN(m_am_tools, status); |
2435 } |
2769 } |
2436 |
2770 |
2437 //-------------------------------------------------- |
2771 #endif //#if defined(USE_EAPOL_KEY_STATE) |
2772 |
|
2773 //-------------------------------------------------- |
|
2774 |
|
2775 #if defined(USE_EAPOL_KEY_STATE) |
|
2438 |
2776 |
2439 // |
2777 // |
2440 EAP_FUNC_EXPORT eap_status_e eapol_core_c::indicate_eapol_key_state_started_eap_authentication( |
2778 EAP_FUNC_EXPORT eap_status_e eapol_core_c::indicate_eapol_key_state_started_eap_authentication( |
2441 const eap_am_network_id_c * const send_network_id) |
2779 const eap_am_network_id_c * const send_network_id) |
2442 { |
2780 { |
2484 } |
2822 } |
2485 |
2823 |
2486 return EAP_STATUS_RETURN(m_am_tools, status); |
2824 return EAP_STATUS_RETURN(m_am_tools, status); |
2487 } |
2825 } |
2488 |
2826 |
2489 //-------------------------------------------------- |
2827 #endif //#if defined(USE_EAPOL_KEY_STATE) |
2828 |
|
2829 //-------------------------------------------------- |
|
2830 |
|
2831 #if defined(USE_EAPOL_KEY_STATE) |
|
2490 |
2832 |
2491 // |
2833 // |
2492 EAP_FUNC_EXPORT eap_status_e eapol_core_c::remove_eapol_key_state( |
2834 EAP_FUNC_EXPORT eap_status_e eapol_core_c::remove_eapol_key_state( |
2493 const eap_am_network_id_c * const send_network_id, |
2835 const eap_am_network_id_c * const send_network_id) |
2494 const bool force_remove) |
|
2495 { |
2836 { |
2496 EAP_TRACE_DEBUG( |
2837 EAP_TRACE_DEBUG( |
2497 m_am_tools, |
2838 m_am_tools, |
2498 TRACE_FLAGS_DEFAULT, |
2839 TRACE_FLAGS_DEFAULT, |
2499 (EAPL("%s: eapol_core_c::remove_eapol_key_state().\n"), |
2840 (EAPL("%s: eapol_core_c::remove_eapol_key_state().\n"), |
2521 |
2862 |
2522 eapol_key_state_c *eapol_key_state = m_eapol_key_state_map.get_handler(&state_selector); |
2863 eapol_key_state_c *eapol_key_state = m_eapol_key_state_map.get_handler(&state_selector); |
2523 |
2864 |
2524 if (eapol_key_state != 0) |
2865 if (eapol_key_state != 0) |
2525 { |
2866 { |
2526 if (force_remove == false |
2867 if (eapol_key_state->get_marked_removed() == false) |
2527 && eapol_key_state->get_marked_removed() == false) |
|
2528 { |
2868 { |
2529 // Do not remove object in use. |
2869 // Do not remove object in use. |
2530 EAP_TRACE_DEBUG( |
2870 EAP_TRACE_DEBUG( |
2531 m_am_tools, |
2871 m_am_tools, |
2532 TRACE_FLAGS_DEFAULT, |
2872 TRACE_FLAGS_DEFAULT, |
2558 } |
2898 } |
2559 |
2899 |
2560 return EAP_STATUS_RETURN(m_am_tools, status); |
2900 return EAP_STATUS_RETURN(m_am_tools, status); |
2561 } |
2901 } |
2562 |
2902 |
2563 //-------------------------------------------------- |
2903 #endif //#if defined(USE_EAPOL_KEY_STATE) |
2904 |
|
2905 //-------------------------------------------------- |
|
2906 |
|
2907 #if defined(USE_EAPOL_KEY_STATE) |
|
2564 |
2908 |
2565 // |
2909 // |
2566 EAP_FUNC_EXPORT eap_status_e eapol_core_c::asynchronous_init_remove_eapol_key_state( |
2910 eap_status_e eapol_core_c::asynchronous_init_remove_eapol_key_state( |
2567 const eap_am_network_id_c * const send_network_id) |
2911 const eap_am_network_id_c * const send_network_id) |
2568 { |
2912 { |
2569 EAP_TRACE_DEBUG( |
2913 EAP_TRACE_DEBUG( |
2570 m_am_tools, |
2914 m_am_tools, |
2571 TRACE_FLAGS_DEFAULT, |
2915 TRACE_FLAGS_DEFAULT, |
2644 status = eap_status_ok; |
2988 status = eap_status_ok; |
2645 } |
2989 } |
2646 |
2990 |
2647 return EAP_STATUS_RETURN(m_am_tools, status); |
2991 return EAP_STATUS_RETURN(m_am_tools, status); |
2648 } |
2992 } |
2993 |
|
2994 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2649 |
2995 |
2650 //-------------------------------------------------- |
2996 //-------------------------------------------------- |
2651 |
2997 |
2652 EAP_FUNC_EXPORT void eapol_core_c::state_notification( |
2998 EAP_FUNC_EXPORT void eapol_core_c::state_notification( |
2653 const abs_eap_state_notification_c * const state) |
2999 const abs_eap_state_notification_c * const state) |
2695 } |
3041 } |
2696 |
3042 |
2697 if (state->get_current_state() == eap_state_identity_request_received |
3043 if (state->get_current_state() == eap_state_identity_request_received |
2698 || state->get_current_state() == eap_state_eap_response_sent) |
3044 || state->get_current_state() == eap_state_eap_response_sent) |
2699 { |
3045 { |
3046 #if defined(USE_EAPOL_KEY_STATE) |
|
2700 // Indicate EAPOL Key state the started EAP-authentication. |
3047 // Indicate EAPOL Key state the started EAP-authentication. |
2701 status = indicate_eapol_key_state_started_eap_authentication( |
3048 status = indicate_eapol_key_state_started_eap_authentication( |
2702 state->get_send_network_id()); |
3049 state->get_send_network_id()); |
2703 if (status != eap_status_ok) |
3050 if (status != eap_status_ok) |
2704 { |
3051 { |
2707 TRACE_FLAGS_DEFAULT, |
3054 TRACE_FLAGS_DEFAULT, |
2708 (EAPL("WARNING: eapol_core_c::state_notification(): ") |
3055 (EAPL("WARNING: eapol_core_c::state_notification(): ") |
2709 EAPL("indicate_eapol_key_state_started_eap_authentication(), eap_status_e %d\n"), |
3056 EAPL("indicate_eapol_key_state_started_eap_authentication(), eap_status_e %d\n"), |
2710 status)); |
3057 status)); |
2711 } |
3058 } |
3059 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2712 } |
3060 } |
2713 |
3061 |
2714 } |
3062 } |
2715 else if (state->get_current_state() == eap_state_authentication_terminated_unsuccessfully) |
3063 else if (state->get_current_state() == eap_state_authentication_terminated_unsuccessfully) |
2716 { |
3064 { |
2718 m_am_tools, |
3066 m_am_tools, |
2719 TRACE_FLAGS_DEFAULT, |
3067 TRACE_FLAGS_DEFAULT, |
2720 (EAPL("ERROR: eapol_core_c::state_notification(): %s: EAP-authentication FAILED\n"), |
3068 (EAPL("ERROR: eapol_core_c::state_notification(): %s: EAP-authentication FAILED\n"), |
2721 (state->get_is_client() == true ? "client": "server"))); |
3069 (state->get_is_client() == true ? "client": "server"))); |
2722 |
3070 |
3071 #if defined(USE_EAPOL_KEY_STATE) |
|
2723 // Remove possible EAPOL Key state. |
3072 // Remove possible EAPOL Key state. |
2724 status = remove_eapol_key_state( |
3073 status = remove_eapol_key_state( |
2725 state->get_send_network_id(), |
3074 state->get_send_network_id()); |
2726 true); |
|
2727 if (status != eap_status_ok) |
3075 if (status != eap_status_ok) |
2728 { |
3076 { |
2729 EAP_TRACE_DEBUG( |
3077 EAP_TRACE_DEBUG( |
2730 m_am_tools, |
3078 m_am_tools, |
2731 TRACE_FLAGS_DEFAULT, |
3079 TRACE_FLAGS_DEFAULT, |
2732 (EAPL("WARNING: eapol_core_c::state_notification(): ") |
3080 (EAPL("WARNING: eapol_core_c::state_notification(): ") |
2733 EAPL("remove_eapol_key_state(), eap_status_e %d\n"), |
3081 EAPL("remove_eapol_key_state(), eap_status_e %d\n"), |
2734 status)); |
3082 status)); |
2735 } |
3083 } |
3084 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2736 |
3085 |
2737 } |
3086 } |
2738 else if (state->get_current_state() == eap_state_authentication_finished_successfully) |
3087 else if (state->get_current_state() == eap_state_authentication_finished_successfully) |
2739 { |
3088 { |
2740 EAP_TRACE_DEBUG( |
3089 EAP_TRACE_DEBUG( |
2741 m_am_tools, |
3090 m_am_tools, |
2742 TRACE_FLAGS_DEFAULT, |
3091 TRACE_FLAGS_DEFAULT, |
2743 (EAPL("eapol_core_c::state_notification(): %s: EAP authentication SUCCESS\n"), |
3092 (EAPL("eapol_core_c::state_notification(): %s: EAP authentication SUCCESS\n"), |
2744 (state->get_is_client() == true ? "client": "server"))); |
3093 (state->get_is_client() == true ? "client": "server"))); |
2745 |
3094 |
3095 #if defined(USE_EAPOL_KEY_STATE) |
|
2746 eap_network_id_selector_c state_selector( |
3096 eap_network_id_selector_c state_selector( |
2747 m_am_tools, |
3097 m_am_tools, |
2748 state->get_send_network_id()); |
3098 state->get_send_network_id()); |
2749 |
3099 |
2750 if (state_selector.get_is_valid() == false) |
3100 if (state_selector.get_is_valid() == false) |
2868 TRACE_FLAGS_DEFAULT, |
3218 TRACE_FLAGS_DEFAULT, |
2869 (EAPL("ERROR: eapol_core_c::state_notification(): ") |
3219 (EAPL("ERROR: eapol_core_c::state_notification(): ") |
2870 EAPL("allow_4_way_handshake() failed, no eapol_key_state_c object\n"))); |
3220 EAPL("allow_4_way_handshake() failed, no eapol_key_state_c object\n"))); |
2871 } |
3221 } |
2872 } |
3222 } |
3223 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
2873 } |
3224 } |
2874 else |
3225 else |
2875 { |
3226 { |
2876 EAP_TRACE_DEBUG( |
3227 EAP_TRACE_DEBUG( |
2877 m_am_tools, |
3228 m_am_tools, |
2886 state->get_current_state(), |
3237 state->get_current_state(), |
2887 state->get_current_state_string(), |
3238 state->get_current_state_string(), |
2888 state->get_is_client())); |
3239 state->get_is_client())); |
2889 } |
3240 } |
2890 } |
3241 } |
3242 #if defined(USE_EAPOL_KEY_STATE) |
|
2891 else if (state->get_protocol_layer() == eap_protocol_layer_eapol_key) |
3243 else if (state->get_protocol_layer() == eap_protocol_layer_eapol_key) |
2892 { |
3244 { |
2893 // This nofifation is from eapol_key_state_c object. |
3245 // This nofifation is from eapol_key_state_c object. |
2894 if (state->get_current_state() |
3246 if (state->get_current_state() |
2895 == eapol_key_state_802_11i_authentication_terminated_unsuccessfull) |
3247 == eapol_key_state_802_11i_authentication_terminated_unsuccessfull) |
3039 state->get_current_state(), |
3391 state->get_current_state(), |
3040 state->get_current_state_string(), |
3392 state->get_current_state_string(), |
3041 state->get_is_client())); |
3393 state->get_is_client())); |
3042 } |
3394 } |
3043 } |
3395 } |
3396 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
3397 |
|
3044 |
3398 |
3045 m_partner->state_notification(state); |
3399 m_partner->state_notification(state); |
3046 } |
3400 } |
3047 |
3401 |
3048 //-------------------------------------------------- |
3402 //-------------------------------------------------- |
3107 return EAP_STATUS_RETURN(m_am_tools, status); |
3461 return EAP_STATUS_RETURN(m_am_tools, status); |
3108 } |
3462 } |
3109 |
3463 |
3110 //-------------------------------------------------- |
3464 //-------------------------------------------------- |
3111 |
3465 |
3466 // |
|
3467 EAP_FUNC_EXPORT eap_status_e eapol_core_c::cancel_all_timers() |
|
3468 { |
|
3469 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3470 |
|
3471 EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true); |
|
3472 |
|
3473 const eap_status_e status = m_partner->cancel_all_timers(); |
|
3474 |
|
3475 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3476 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3477 } |
|
3478 |
|
3479 //-------------------------------------------------- |
|
3480 |
|
3112 EAP_FUNC_EXPORT eap_status_e eapol_core_c::check_is_valid_eap_type( |
3481 EAP_FUNC_EXPORT eap_status_e eapol_core_c::check_is_valid_eap_type( |
3113 const eap_type_value_e eap_type) |
3482 const eap_type_value_e eap_type) |
3114 { |
3483 { |
3115 eap_status_e status = m_partner->check_is_valid_eap_type(eap_type); |
3484 eap_status_e status = m_partner->check_is_valid_eap_type(eap_type); |
3116 |
3485 |
3126 |
3495 |
3127 return EAP_STATUS_RETURN(m_am_tools, status); |
3496 return EAP_STATUS_RETURN(m_am_tools, status); |
3128 } |
3497 } |
3129 |
3498 |
3130 //-------------------------------------------------- |
3499 //-------------------------------------------------- |
3500 |
|
3501 #if defined(USE_EAPOL_KEY_STATE) |
|
3131 |
3502 |
3132 // |
3503 // |
3133 EAP_FUNC_EXPORT eap_status_e eapol_core_c::cancel_authentication_session( |
3504 EAP_FUNC_EXPORT eap_status_e eapol_core_c::cancel_authentication_session( |
3134 eapol_key_state_c * const handler, |
3505 eapol_key_state_c * const handler, |
3135 abs_eap_am_tools_c * const m_am_tools) |
3506 abs_eap_am_tools_c * const m_am_tools) |
3149 |
3520 |
3150 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3521 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3151 return EAP_STATUS_RETURN(m_am_tools, status); |
3522 return EAP_STATUS_RETURN(m_am_tools, status); |
3152 } |
3523 } |
3153 |
3524 |
3525 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
3526 |
|
3154 //-------------------------------------------------- |
3527 //-------------------------------------------------- |
3155 |
3528 |
3156 EAP_FUNC_EXPORT eap_status_e eapol_core_c::cancel_all_authentication_sessions() |
3529 EAP_FUNC_EXPORT eap_status_e eapol_core_c::cancel_all_authentication_sessions() |
3157 { |
3530 { |
3158 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
3531 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
3170 |
3543 |
3171 |
3544 |
3172 bool previous_block = m_block_state_notifications; |
3545 bool previous_block = m_block_state_notifications; |
3173 m_block_state_notifications = true; |
3546 m_block_state_notifications = true; |
3174 |
3547 |
3548 #if !defined(NO_EAP_SESSION_CORE) |
|
3175 if (m_eap_core != 0) |
3549 if (m_eap_core != 0) |
3176 { |
3550 { |
3177 status = m_eap_core->cancel_all_eap_sessions(); |
3551 status = m_eap_core->synchronous_cancel_all_eap_sessions(); |
3178 } |
3552 } |
3179 |
3553 #endif //#if !defined(NO_EAP_SESSION_CORE) |
3554 |
|
3555 |
|
3556 #if defined(USE_EAPOL_KEY_STATE) |
|
3180 status = m_eapol_key_state_map.for_each(cancel_authentication_session, true); |
3557 status = m_eapol_key_state_map.for_each(cancel_authentication_session, true); |
3558 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
3181 |
3559 |
3182 m_block_state_notifications = previous_block; |
3560 m_block_state_notifications = previous_block; |
3183 |
3561 |
3184 |
3562 |
3185 // This will cancel all timers of this object. |
3563 // This will cancel all timers of this object. |
3186 m_partner->cancel_timer(this, EAPOL_CORE_TIMER_SEND_START_AGAIN_ID); |
3564 m_partner->cancel_timer(this, EAPOL_CORE_TIMER_SEND_START_AGAIN_ID); |
3565 #if defined(USE_EAPOL_KEY_STATE) |
|
3187 m_partner->cancel_timer(this, EAPOL_REMOVE_EAPOL_KEY_HANDSHAKE_ID); |
3566 m_partner->cancel_timer(this, EAPOL_REMOVE_EAPOL_KEY_HANDSHAKE_ID); |
3567 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
3188 |
3568 |
3189 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3569 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3190 return EAP_STATUS_RETURN(m_am_tools, status); |
3570 return EAP_STATUS_RETURN(m_am_tools, status); |
3191 } |
3571 } |
3192 |
3572 |
3193 //-------------------------------------------------- |
3573 //-------------------------------------------------- |
3194 |
3574 |
3575 #if defined(USE_EAPOL_KEY_STATE) |
|
3576 |
|
3195 EAP_FUNC_EXPORT eap_status_e eapol_core_c::get_and_increment_global_key_counter( |
3577 EAP_FUNC_EXPORT eap_status_e eapol_core_c::get_and_increment_global_key_counter( |
3196 eap_variable_data_c * const key_counter) |
3578 eap_variable_data_c * const key_counter) |
3197 { |
3579 { |
3198 key_counter->reset(); |
3580 key_counter->reset(); |
3199 return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported); |
3581 return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported); |
3200 } |
3582 } |
3201 |
3583 |
3202 //-------------------------------------------------- |
3584 #endif //#if defined(USE_EAPOL_KEY_STATE) |
3203 |
3585 |
3586 //-------------------------------------------------- |
|
3587 |
|
3588 #if defined(USE_EAPOL_KEY_STATE) && defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
3204 /** |
3589 /** |
3205 * Function creates a state for later use. This is for optimazing 4-Way Handshake. |
3590 * Function creates a state for later use. This is for optimazing 4-Way Handshake. |
3206 * @param receive_network_id carries the MAC addresses. |
3591 * @param receive_network_id carries the MAC addresses. |
3207 * MAC address of Authenticator should be in source address. MAC address of |
3592 * MAC address of Authenticator should be in source address. MAC address of |
3208 * Supplicant should be in destination address. |
3593 * Supplicant should be in destination address. |
3366 |
3751 |
3367 status = eapol_key_state->configure(); |
3752 status = eapol_key_state->configure(); |
3368 if (status != eap_status_ok) |
3753 if (status != eap_status_ok) |
3369 { |
3754 { |
3370 status = remove_eapol_key_state( |
3755 status = remove_eapol_key_state( |
3371 &send_network_id, |
3756 &send_network_id); |
3372 true); |
|
3373 if (status != eap_status_ok) |
3757 if (status != eap_status_ok) |
3374 { |
3758 { |
3375 EAP_TRACE_DEBUG( |
3759 EAP_TRACE_DEBUG( |
3376 m_am_tools, |
3760 m_am_tools, |
3377 TRACE_FLAGS_DEFAULT, |
3761 TRACE_FLAGS_DEFAULT, |
3385 } |
3769 } |
3386 |
3770 |
3387 return EAP_STATUS_RETURN(m_am_tools, status); |
3771 return EAP_STATUS_RETURN(m_am_tools, status); |
3388 } |
3772 } |
3389 |
3773 |
3390 //-------------------------------------------------- |
3774 #endif //#if defined(USE_EAPOL_KEY_STATE) && defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
3391 |
3775 |
3776 //-------------------------------------------------- |
|
3777 |
|
3778 #if defined(USE_EAPOL_KEY_STATE) |
|
3392 /** |
3779 /** |
3393 * @param receive_network_id carries the MAC addresses. |
3780 * @param receive_network_id carries the MAC addresses. |
3394 * MAC address of Authenticator should be in source address. MAC address of |
3781 * MAC address of Authenticator should be in source address. MAC address of |
3395 * Supplicant should be in destination address. |
3782 * Supplicant should be in destination address. |
3396 * @param authenticator_RSNA_IE is RSN IE of authenticator. Authenticator |
3783 * @param authenticator_RSNA_IE is RSN IE of authenticator. Authenticator |
3463 state_selector.get_data_length())); |
3850 state_selector.get_data_length())); |
3464 |
3851 |
3465 |
3852 |
3466 eapol_key_state_c *eapol_key_state = m_eapol_key_state_map.get_handler(&state_selector); |
3853 eapol_key_state_c *eapol_key_state = m_eapol_key_state_map.get_handler(&state_selector); |
3467 |
3854 |
3855 #if !defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
3856 if (eapol_key_state != 0) |
|
3857 { |
|
3858 // Reuse the session. |
|
3859 eapol_key_state->unset_marked_removed(); |
|
3860 |
|
3861 if (m_is_client == false) |
|
3862 { |
|
3863 // In test version do not reset server. |
|
3864 } |
|
3865 else |
|
3866 { |
|
3867 status = eapol_key_state->reset(); |
|
3868 if (status != eap_status_ok) |
|
3869 { |
|
3870 // We cannot reuse the session. |
|
3871 EAP_TRACE_ERROR( |
|
3872 m_am_tools, |
|
3873 TRACE_FLAGS_ERROR, |
|
3874 (EAPL("eapol_core_c::association(): eapol_key_state NOT reused.\n"))); |
|
3875 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3876 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3877 } |
|
3878 } |
|
3879 } |
|
3880 #endif //#if !defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
3881 |
|
3882 |
|
3468 if (eapol_key_state == 0) |
3883 if (eapol_key_state == 0) |
3469 { |
3884 { |
3470 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3885 |
3471 return EAP_STATUS_RETURN(m_am_tools, eap_status_handler_does_not_exists_error); |
3886 #if !defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
3472 } |
3887 |
3473 else |
3888 eapol_key_state = new eapol_key_state_c( |
3474 { |
3889 m_am_tools, |
3890 this, |
|
3891 m_partner, |
|
3892 m_is_client, |
|
3893 receive_network_id, |
|
3894 authentication_type, |
|
3895 authenticator_RSNA_IE, |
|
3896 supplicant_RSNA_IE, |
|
3897 eapol_pairwise_cipher, |
|
3898 eapol_group_cipher, |
|
3899 pre_shared_key_PSK); |
|
3900 if (eapol_key_state == 0 |
|
3901 || eapol_key_state->get_is_valid() == false) |
|
3902 { |
|
3903 if (eapol_key_state != 0) |
|
3904 { |
|
3905 eapol_key_state->shutdown(); |
|
3906 } |
|
3907 else |
|
3908 { |
|
3909 EAP_TRACE_DEBUG( |
|
3910 m_am_tools, |
|
3911 TRACE_FLAGS_DEFAULT, |
|
3912 (EAPL("WARNING: eapol_core_c::association(): Cannot run eapol_key_state->shutdown() 0x%08x\n"), |
|
3913 eapol_key_state)); |
|
3914 } |
|
3915 delete eapol_key_state; |
|
3916 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3917 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
3918 } |
|
3919 |
|
3475 status = eapol_key_state->initialize( |
3920 status = eapol_key_state->initialize( |
3476 receive_network_id, |
3921 receive_network_id, |
3477 authentication_type, |
3922 authentication_type, |
3478 authenticator_RSNA_IE, |
3923 authenticator_RSNA_IE, |
3479 supplicant_RSNA_IE, |
3924 supplicant_RSNA_IE, |
3483 if (status != eap_status_ok) |
3928 if (status != eap_status_ok) |
3484 { |
3929 { |
3485 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3930 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3486 return EAP_STATUS_RETURN(m_am_tools, status); |
3931 return EAP_STATUS_RETURN(m_am_tools, status); |
3487 } |
3932 } |
3488 } |
3933 |
3934 status = m_eapol_key_state_map.add_handler(&state_selector, eapol_key_state); |
|
3935 if (status != eap_status_ok) |
|
3936 { |
|
3937 if (eapol_key_state != 0) |
|
3938 { |
|
3939 eapol_key_state->shutdown(); |
|
3940 } |
|
3941 else |
|
3942 { |
|
3943 EAP_TRACE_DEBUG( |
|
3944 m_am_tools, |
|
3945 TRACE_FLAGS_DEFAULT, |
|
3946 (EAPL("WARNING: eapol_core_c::association(): Cannot run eapol_key_state->shutdown() 0x%08x\n"), |
|
3947 eapol_key_state)); |
|
3948 } |
|
3949 delete eapol_key_state; |
|
3950 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3951 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3952 } |
|
3953 |
|
3954 #else |
|
3955 |
|
3956 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3957 return EAP_STATUS_RETURN(m_am_tools, eap_status_handler_does_not_exists_error); |
|
3958 |
|
3959 #endif //#if !defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
3960 |
|
3961 } |
|
3962 else |
|
3963 { |
|
3964 status = eapol_key_state->initialize( |
|
3965 receive_network_id, |
|
3966 authentication_type, |
|
3967 authenticator_RSNA_IE, |
|
3968 supplicant_RSNA_IE, |
|
3969 eapol_pairwise_cipher, |
|
3970 eapol_group_cipher, |
|
3971 pre_shared_key_PSK); |
|
3972 if (status != eap_status_ok) |
|
3973 { |
|
3974 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3975 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3976 } |
|
3977 } |
|
3978 |
|
3979 |
|
3980 #if !defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
3981 status = eapol_key_state->configure(); |
|
3982 if (status != eap_status_ok) |
|
3983 { |
|
3984 status = remove_eapol_key_state( |
|
3985 &send_network_id); |
|
3986 if (status != eap_status_ok) |
|
3987 { |
|
3988 EAP_TRACE_DEBUG( |
|
3989 m_am_tools, |
|
3990 TRACE_FLAGS_DEFAULT, |
|
3991 (EAPL("WARNING: eapol_core_c::association(): ") |
|
3992 EAPL("remove_eapol_key_state(), eap_status_e %d\n"), |
|
3993 status)); |
|
3994 } |
|
3995 |
|
3996 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3997 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3998 } |
|
3999 #endif //#if !defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
4000 |
|
3489 |
4001 |
3490 if (authentication_type == eapol_key_authentication_type_RSNA_PSK |
4002 if (authentication_type == eapol_key_authentication_type_RSNA_PSK |
3491 || authentication_type == eapol_key_authentication_type_WPA_PSK) |
4003 || authentication_type == eapol_key_authentication_type_WPA_PSK) |
3492 { |
4004 { |
3493 |
4005 |
3494 #if !defined(NO_EAPOL_KEY_STATE_SERVER) |
4006 #if !defined(NO_EAPOL_KEY_STATE_SERVER) |
3495 if (m_is_client == false) |
4007 if (m_is_client == false) |
3496 { |
4008 { |
4009 #if defined(USE_EAPOL_KEY_STATE) |
|
3497 if (m_skip_start_4_way_handshake == true) |
4010 if (m_skip_start_4_way_handshake == true) |
3498 { |
4011 { |
3499 // This is test to skip 4-Way Handshake start. |
4012 // This is test to skip 4-Way Handshake start. |
3500 EAP_TRACE_DEBUG( |
4013 EAP_TRACE_DEBUG( |
3501 m_am_tools, |
4014 m_am_tools, |
3504 EAPL("skips start_4_way_handshake()\n"))); |
4017 EAPL("skips start_4_way_handshake()\n"))); |
3505 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
4018 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3506 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
4019 return EAP_STATUS_RETURN(m_am_tools, eap_status_ok); |
3507 } |
4020 } |
3508 else |
4021 else |
4022 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
3509 { |
4023 { |
3510 status = eapol_key_state->start_4_way_handshake( |
4024 status = eapol_key_state->start_4_way_handshake( |
3511 receive_network_id); |
4025 receive_network_id); |
3512 } |
4026 } |
3513 |
4027 |
3521 #endif //#if !defined(NO_EAPOL_KEY_STATE_SERVER) |
4035 #endif //#if !defined(NO_EAPOL_KEY_STATE_SERVER) |
3522 { |
4036 { |
3523 eapol_key_state->allow_4_way_handshake(); |
4037 eapol_key_state->allow_4_way_handshake(); |
3524 } |
4038 } |
3525 } |
4039 } |
4040 #if defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
3526 else if (authentication_type == eapol_key_authentication_type_RSNA_EAP |
4041 else if (authentication_type == eapol_key_authentication_type_RSNA_EAP |
3527 || authentication_type == eapol_key_authentication_type_WPA_EAP |
4042 || authentication_type == eapol_key_authentication_type_WPA_EAP |
3528 || authentication_type == eapol_key_authentication_type_dynamic_WEP |
4043 || authentication_type == eapol_key_authentication_type_dynamic_WEP |
3529 || authentication_type == eapol_key_authentication_type_WPXM |
4044 || authentication_type == eapol_key_authentication_type_WPXM |
3530 || authentication_type == eapol_key_authentication_type_WPS |
4045 || authentication_type == eapol_key_authentication_type_WFA_SC |
3531 || authentication_type == eapol_key_authentication_type_EAP_authentication_no_encryption |
4046 || authentication_type == eapol_key_authentication_type_EAP_authentication_no_encryption |
3532 ) |
4047 ) |
3533 { |
4048 { |
3534 // Creates a EAP-session. |
4049 // Creates a EAP-session. |
3535 status = m_eap_core->create_eap_session(receive_network_id); |
4050 status = m_eap_core->synchronous_create_eap_session(receive_network_id); |
3536 if (status != eap_status_ok) |
4051 if (status != eap_status_ok) |
3537 { |
4052 { |
3538 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
4053 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3539 return EAP_STATUS_RETURN(m_am_tools, status); |
4054 return EAP_STATUS_RETURN(m_am_tools, status); |
3540 } |
4055 } |
3541 } |
4056 } |
4057 #endif //#if defined(USE_EAPOL_KEY_STATE_OPTIMIZED_4_WAY_HANDSHAKE) |
|
4058 |
|
3542 |
4059 |
3543 return EAP_STATUS_RETURN(m_am_tools, status); |
4060 return EAP_STATUS_RETURN(m_am_tools, status); |
3544 } |
4061 } |
3545 |
4062 |
3546 //-------------------------------------------------- |
4063 #endif //#if defined(USE_EAPOL_KEY_STATE) |
3547 |
4064 |
4065 //-------------------------------------------------- |
|
4066 |
|
4067 #if defined(USE_EAPOL_KEY_STATE) |
|
3548 /** |
4068 /** |
3549 * @param receive_network_id carries the MAC addresses. |
4069 * @param receive_network_id carries the MAC addresses. |
3550 * MAC address of Authenticator should be in source address. |
4070 * MAC address of Authenticator should be in source address. |
3551 * MAC address of Supplicant should be in destination address. |
4071 * MAC address of Supplicant should be in destination address. |
3552 */ |
4072 */ |
3553 EAP_FUNC_EXPORT eap_status_e eapol_core_c::disassociation( |
4073 EAP_FUNC_EXPORT eap_status_e eapol_core_c::disassociation( |
3554 const bool complete_to_lower_layer, |
|
3555 const eap_am_network_id_c * const receive_network_id |
4074 const eap_am_network_id_c * const receive_network_id |
3556 ) |
4075 ) |
3557 { |
4076 { |
3558 eap_status_e status = eap_status_process_general_error; |
4077 eap_status_e status = eap_status_process_general_error; |
3559 |
4078 |
3582 } |
4101 } |
3583 |
4102 |
3584 |
4103 |
3585 (void) m_partner->cancel_timer(this, EAPOL_CORE_TIMER_SEND_START_AGAIN_ID); |
4104 (void) m_partner->cancel_timer(this, EAPOL_CORE_TIMER_SEND_START_AGAIN_ID); |
3586 |
4105 |
4106 #if !defined(NO_EAP_SESSION_CORE) |
|
3587 // First we remove possible EAP session. |
4107 // First we remove possible EAP session. |
3588 (void) m_eap_core->remove_eap_session( |
4108 (void) m_eap_core->synchronous_remove_eap_session(receive_network_id); |
3589 complete_to_lower_layer, |
4109 #endif |
3590 receive_network_id); |
|
3591 |
4110 |
3592 status = init_eapol_key_pmksa_caching_timeout( |
4111 status = init_eapol_key_pmksa_caching_timeout( |
3593 &send_network_id); |
4112 &send_network_id); |
3594 if (status != eap_status_ok) |
4113 if (status != eap_status_ok) |
3595 { |
4114 { |
3603 } |
4122 } |
3604 |
4123 |
3605 return EAP_STATUS_RETURN(m_am_tools, status); |
4124 return EAP_STATUS_RETURN(m_am_tools, status); |
3606 } |
4125 } |
3607 |
4126 |
4127 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
4128 |
|
3608 //-------------------------------------------------- |
4129 //-------------------------------------------------- |
3609 |
4130 |
3610 /// @see abs_eap_core_c::add_rogue_ap(). |
4131 /// @see abs_eap_core_c::add_rogue_ap(). |
3611 EAP_FUNC_EXPORT eap_status_e eapol_core_c::add_rogue_ap( |
4132 EAP_FUNC_EXPORT eap_status_e eapol_core_c::add_rogue_ap( |
3612 eap_array_c<eap_rogue_ap_entry_c> & rogue_ap_list) |
4133 eap_array_c<eap_rogue_ap_entry_c> & rogue_ap_list) |
3640 (EAPL("%s: eapol_core_c::tkip_mic_failure().\n"), |
4161 (EAPL("%s: eapol_core_c::tkip_mic_failure().\n"), |
3641 (m_is_client == true) ? "client": "server")); |
4162 (m_is_client == true) ? "client": "server")); |
3642 |
4163 |
3643 eap_status_e status = eap_status_process_general_error; |
4164 eap_status_e status = eap_status_process_general_error; |
3644 |
4165 |
4166 #if defined(USE_EAPOL_KEY_STATE) |
|
4167 |
|
3645 // Here we swap the addresses. |
4168 // Here we swap the addresses. |
3646 eap_am_network_id_c send_network_id( |
4169 eap_am_network_id_c send_network_id( |
3647 m_am_tools, |
4170 m_am_tools, |
3648 receive_network_id->get_destination_id(), |
4171 receive_network_id->get_destination_id(), |
3649 receive_network_id->get_source_id(), |
4172 receive_network_id->get_source_id(), |
3682 else |
4205 else |
3683 { |
4206 { |
3684 status = eap_status_handler_does_not_exists_error; |
4207 status = eap_status_handler_does_not_exists_error; |
3685 } |
4208 } |
3686 |
4209 |
4210 #else |
|
4211 |
|
4212 status = eap_status_not_supported; |
|
4213 |
|
4214 #endif //#if defined(USE_EAPOL_KEY_STATE) |
|
4215 |
|
3687 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
4216 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
3688 return EAP_STATUS_RETURN(m_am_tools, status); |
4217 return EAP_STATUS_RETURN(m_am_tools, status); |
3689 } |
4218 } |
3690 |
4219 |
3691 //-------------------------------------------------- |
4220 //-------------------------------------------------- |
3702 return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported); |
4231 return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported); |
3703 } |
4232 } |
3704 |
4233 |
3705 //-------------------------------------------------- |
4234 //-------------------------------------------------- |
3706 |
4235 |
3707 #if defined(USE_EAP_SIMPLE_CONFIG) |
4236 |
3708 |
4237 |
3709 EAP_FUNC_EXPORT eap_status_e eapol_core_c::save_simple_config_session( |
|
3710 const simple_config_state_e state, |
|
3711 EAP_TEMPLATE_CONST eap_array_c<simple_config_credential_c> * const credential_array, |
|
3712 const eap_variable_data_c * const new_password, |
|
3713 const simple_config_Device_Password_ID_e Device_Password_ID, |
|
3714 const simple_config_payloads_c * const other_configuration) |
|
3715 { |
|
3716 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3717 |
|
3718 EAP_TRACE_DEBUG( |
|
3719 m_am_tools, |
|
3720 TRACE_FLAGS_DEFAULT, |
|
3721 (EAPL("%s: eapol_core_c::save_simple_config_session().\n"), |
|
3722 (m_is_client == true) ? "client": "server")); |
|
3723 |
|
3724 const eap_status_e status = m_partner->save_simple_config_session( |
|
3725 state, |
|
3726 credential_array, |
|
3727 new_password, |
|
3728 Device_Password_ID, |
|
3729 other_configuration); |
|
3730 |
|
3731 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3732 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3733 } |
|
3734 |
|
3735 #endif // #if defined(USE_EAP_SIMPLE_CONFIG) |
|
3736 |
|
3737 //-------------------------------------------------- |
|
3738 |
|
3739 // |
|
3740 EAP_FUNC_EXPORT eap_status_e eapol_core_c::set_eap_database_reference_values( |
|
3741 const eap_variable_data_c * const reference) |
|
3742 { |
|
3743 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3744 |
|
3745 EAP_TRACE_DEBUG( |
|
3746 m_am_tools, |
|
3747 TRACE_FLAGS_DEFAULT, |
|
3748 (EAPL("eapol_core_c::set_eap_database_reference_values()\n"))); |
|
3749 |
|
3750 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::set_eap_database_reference_values()"); |
|
3751 |
|
3752 eap_status_e status(eap_status_ok); |
|
3753 |
|
3754 if (m_eap_core != 0) |
|
3755 { |
|
3756 status = m_eap_core->set_eap_database_reference_values(reference); |
|
3757 } |
|
3758 |
|
3759 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3760 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3761 } |
|
3762 |
|
3763 //-------------------------------------------------- |
|
3764 |
|
3765 // |
|
3766 EAP_FUNC_EXPORT eap_status_e eapol_core_c::get_802_11_authentication_mode( |
|
3767 const eap_am_network_id_c * const receive_network_id, |
|
3768 const eapol_key_authentication_type_e authentication_type, |
|
3769 const eap_variable_data_c * const SSID, |
|
3770 const eap_variable_data_c * const preshared_key) |
|
3771 { |
|
3772 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3773 |
|
3774 EAP_TRACE_DEBUG( |
|
3775 m_am_tools, |
|
3776 TRACE_FLAGS_DEFAULT, |
|
3777 (EAPL("eapol_core_c::get_802_11_authentication_mode()\n"))); |
|
3778 |
|
3779 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::get_802_11_authentication_mode()"); |
|
3780 |
|
3781 eap_status_e status(eap_status_ok); |
|
3782 |
|
3783 if (m_eap_core != 0) |
|
3784 { |
|
3785 status = m_eap_core->get_802_11_authentication_mode( |
|
3786 receive_network_id, |
|
3787 authentication_type, |
|
3788 SSID, |
|
3789 preshared_key); |
|
3790 } |
|
3791 |
|
3792 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3793 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3794 } |
|
3795 |
|
3796 //-------------------------------------------------- |
|
3797 |
|
3798 // |
|
3799 EAP_FUNC_EXPORT eap_status_e eapol_core_c::complete_get_802_11_authentication_mode( |
|
3800 const eap_status_e completion_status, |
|
3801 const eap_am_network_id_c * const receive_network_id, |
|
3802 const eapol_key_802_11_authentication_mode_e mode) |
|
3803 { |
|
3804 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3805 |
|
3806 EAP_TRACE_DEBUG( |
|
3807 m_am_tools, |
|
3808 TRACE_FLAGS_DEFAULT, |
|
3809 (EAPL("eapol_core_c::complete_get_802_11_authentication_mode()\n"))); |
|
3810 |
|
3811 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::complete_get_802_11_authentication_mode()"); |
|
3812 |
|
3813 eap_status_e status(eap_status_ok); |
|
3814 |
|
3815 if (m_partner != 0) |
|
3816 { |
|
3817 status = m_partner->complete_get_802_11_authentication_mode( |
|
3818 completion_status, |
|
3819 receive_network_id, |
|
3820 mode); |
|
3821 } |
|
3822 |
|
3823 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3824 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3825 } |
|
3826 |
|
3827 //-------------------------------------------------- |
|
3828 |
|
3829 // |
|
3830 EAP_FUNC_EXPORT eap_status_e eapol_core_c::complete_remove_eap_session( |
|
3831 const bool complete_to_lower_layer, |
|
3832 const eap_am_network_id_c * const receive_network_id) |
|
3833 { |
|
3834 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3835 |
|
3836 EAP_TRACE_DEBUG( |
|
3837 m_am_tools, |
|
3838 TRACE_FLAGS_DEFAULT, |
|
3839 (EAPL("eapol_core_c::complete_remove_eap_session()\n"))); |
|
3840 |
|
3841 EAP_TRACE_RETURN_STRING(m_am_tools, "returns: eapol_core_c::complete_remove_eap_session()"); |
|
3842 |
|
3843 eap_status_e status(eap_status_ok); |
|
3844 |
|
3845 if (m_partner != 0) |
|
3846 { |
|
3847 status = m_partner->complete_disassociation( |
|
3848 complete_to_lower_layer, |
|
3849 receive_network_id); |
|
3850 } |
|
3851 |
|
3852 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
3853 return EAP_STATUS_RETURN(m_am_tools, status); |
|
3854 } |
|
3855 |
|
3856 //-------------------------------------------------- |
|
3857 // End. |
4238 // End. |