|
1 /* |
|
2 * Copyright (c) 2005-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: State machine for connecting to a WPA network |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "core_sub_operation_wpa_connect.h" |
|
20 #include "core_sub_operation_connect.h" |
|
21 #include "core_server.h" |
|
22 #include "core_tools.h" |
|
23 #include "core_tools_parser.h" |
|
24 #include "core_ap_data.h" |
|
25 #include "core_frame_rsn_ie.h" |
|
26 #include "core_frame_wpa_ie.h" |
|
27 #include "core_frame_wapi_ie.h" |
|
28 #include "am_debug.h" |
|
29 |
|
30 // ======== MEMBER FUNCTIONS ======== |
|
31 |
|
32 // --------------------------------------------------------------------------- |
|
33 // --------------------------------------------------------------------------- |
|
34 // |
|
35 core_sub_operation_wpa_connect_c::core_sub_operation_wpa_connect_c( |
|
36 u32_t request_id, |
|
37 core_server_c* server, |
|
38 abs_core_driverif_c* drivers, |
|
39 abs_core_server_callback_c* adaptation, |
|
40 bool_t& is_connected, |
|
41 core_management_status_e& connect_status, |
|
42 const core_ssid_s& ssid, |
|
43 core_ap_data_c& ap_data, |
|
44 bool_t& is_cached_sa_used, |
|
45 core_type_list_c<core_frame_dot11_ie_c>& assoc_ie_list, |
|
46 core_frame_assoc_resp_c** assoc_resp ) : |
|
47 core_operation_base_c( core_operation_unspecified, request_id, server, drivers, adaptation, |
|
48 core_base_flag_drivers_needed ), |
|
49 abs_wlan_eapol_callback_interface_c(), |
|
50 is_connected_m( is_connected ), |
|
51 is_cached_sa_used_m( is_cached_sa_used ), |
|
52 connect_status_m( connect_status ), |
|
53 ssid_m( ssid ), |
|
54 ap_data_m( ap_data ), |
|
55 current_bssid_m( ZERO_MAC_ADDR ), |
|
56 pmkid_length_m( 0 ), |
|
57 sent_ie_m( NULL ), |
|
58 auth_algorithm_m( core_authentication_mode_open ), |
|
59 eapol_auth_type_m( wlan_eapol_if_eapol_key_authentication_type_none ), |
|
60 assoc_ie_list_m( assoc_ie_list ), |
|
61 assoc_resp_m( assoc_resp ), |
|
62 is_key_caching_used_m( false_t ) |
|
63 { |
|
64 DEBUG( "core_sub_operation_wpa_connect_c::core_sub_operation_wpa_connect_c()" ); |
|
65 } |
|
66 |
|
67 // --------------------------------------------------------------------------- |
|
68 // --------------------------------------------------------------------------- |
|
69 // |
|
70 core_sub_operation_wpa_connect_c::~core_sub_operation_wpa_connect_c() |
|
71 { |
|
72 DEBUG( "core_sub_operation_wpa_connect_c::~core_sub_operation_wpa_connect_c()" ); |
|
73 |
|
74 /** |
|
75 * Ownership of sent_ie_m has been transferred to assoc_ie_list_m, |
|
76 * no need delete it. |
|
77 */ |
|
78 sent_ie_m = NULL; |
|
79 |
|
80 server_m->set_eapol_handler( NULL ); |
|
81 server_m->unregister_event_handler( this ); |
|
82 assoc_resp_m = NULL; |
|
83 } |
|
84 |
|
85 // --------------------------------------------------------------------------- |
|
86 // --------------------------------------------------------------------------- |
|
87 // |
|
88 core_error_e core_sub_operation_wpa_connect_c::next_state() |
|
89 { |
|
90 DEBUG( "core_sub_operation_wpa_connect_c::next_state()" ); |
|
91 |
|
92 switch ( operation_state_m ) |
|
93 { |
|
94 case core_state_init: |
|
95 { |
|
96 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_authentication_started as true" ); |
|
97 server_m->get_connection_data()->set_eapol_authentication_started( |
|
98 true_t ); |
|
99 server_m->get_connection_data()->set_eapol_auth_bssid( |
|
100 ZERO_MAC_ADDR ); |
|
101 |
|
102 eapol_auth_type_m = core_tools_c::eap_authentication_type( |
|
103 server_m->get_connection_data()->iap_data(), |
|
104 ap_data_m ); |
|
105 current_bssid_m = ap_data_m.bssid(); |
|
106 |
|
107 server_m->set_eapol_handler( this ); |
|
108 |
|
109 server_m->get_eapol_instance().clear_stored_frame(); |
|
110 |
|
111 /** |
|
112 * If roaming to a WPA2-EAP AP without a cached PMKSA, attempt |
|
113 * to use proactive key caching if not previously done so. |
|
114 */ |
|
115 if( !is_key_caching_used_m && |
|
116 !is_cached_sa_used_m && |
|
117 server_m->get_connection_data()->current_ap_data() && |
|
118 eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_rsna_eap ) |
|
119 { |
|
120 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - attempting to use proactive key caching" ); |
|
121 |
|
122 is_cached_sa_used_m = true_t; |
|
123 is_key_caching_used_m = true_t; |
|
124 } |
|
125 else if( is_key_caching_used_m ) |
|
126 { |
|
127 is_cached_sa_used_m = false_t; |
|
128 is_key_caching_used_m = false_t; |
|
129 } |
|
130 |
|
131 // update_wlan_database_reference_values must be sent before start_authentication and start_reassociation. |
|
132 u32_t reference[2] = { |
|
133 3, // ELan |
|
134 server_m->get_connection_data()->iap_data().id() }; |
|
135 core_error_e ret = server_m->get_eapol_instance().update_wlan_database_reference_values( |
|
136 reinterpret_cast<u8_t*>( reference ), 2*sizeof( u32_t ) ); |
|
137 |
|
138 if( is_cached_sa_used_m ) |
|
139 { |
|
140 if( eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam ) |
|
141 { |
|
142 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - starting a WPX fast-roam reassociation" ); |
|
143 |
|
144 core_error_e ret = server_m->get_wpx_adaptation_instance().handle_fast_roam_start_reassociation( |
|
145 ap_data_m, |
|
146 assoc_ie_list_m ); |
|
147 DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - handle_fast_roam_start_reassociation returned with %u", |
|
148 ret ); |
|
149 /* |
|
150 * State machine will move forward from here by: |
|
151 * - complete_start_wpx_fast_roam_reassociation() |
|
152 * -> core_state_do_connect |
|
153 * - Error message (start_wpx_fast_roam_reassociation) |
|
154 * -> core_state_init (with is_cached_sa_used_m = false_t) |
|
155 */ |
|
156 } |
|
157 else |
|
158 { |
|
159 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - starting a reassociation" ); |
|
160 |
|
161 operation_state_m = core_state_do_connect; |
|
162 |
|
163 core_mac_address_s previous_bssid( ZERO_MAC_ADDR ); |
|
164 if( server_m->get_connection_data()->current_ap_data() ) |
|
165 { |
|
166 previous_bssid = server_m->get_connection_data()->current_ap_data()->bssid(); |
|
167 } |
|
168 |
|
169 network_id_c previous_ap( |
|
170 &previous_bssid.addr[0], |
|
171 MAC_ADDR_LEN, |
|
172 &server_m->own_mac_addr().addr[0], |
|
173 MAC_ADDR_LEN, |
|
174 server_m->get_eapol_instance().ethernet_type() ); |
|
175 |
|
176 network_id_c new_ap( |
|
177 ¤t_bssid_m.addr[0], |
|
178 MAC_ADDR_LEN, |
|
179 &server_m->own_mac_addr().addr[0], |
|
180 MAC_ADDR_LEN, |
|
181 server_m->get_eapol_instance().ethernet_type() ); |
|
182 |
|
183 ret = server_m->get_eapol_instance().start_reassociation( |
|
184 &previous_ap, &new_ap, eapol_auth_type_m ); |
|
185 DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - start_reassociation returned with %u", |
|
186 ret ); |
|
187 /* |
|
188 * State machine will move forward from here by: |
|
189 * - reassociate(), when reassociation is possible |
|
190 * -> core_state_do_connect |
|
191 * - Error message (start_reassociation), when start_reassociation is not possible |
|
192 * -> core_state_start_authentication_needed |
|
193 */ |
|
194 } |
|
195 } |
|
196 else |
|
197 { |
|
198 // Full authentication is needed. |
|
199 operation_state_m = core_state_start_authentication_needed; |
|
200 return next_state(); |
|
201 } |
|
202 break; |
|
203 } |
|
204 case core_state_start_authentication_needed: |
|
205 { |
|
206 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - starting a full authentication" ); |
|
207 |
|
208 operation_state_m = core_state_do_connect; |
|
209 |
|
210 network_id_c network_id( |
|
211 ¤t_bssid_m.addr[0], |
|
212 MAC_ADDR_LEN, |
|
213 &server_m->own_mac_addr().addr[0], |
|
214 MAC_ADDR_LEN, |
|
215 server_m->get_eapol_instance().ethernet_type() ); |
|
216 |
|
217 core_error_e ret = server_m->get_eapol_instance().start_authentication( |
|
218 const_cast<u8_t*>( &ssid_m.ssid[0] ), ssid_m.length, |
|
219 eapol_auth_type_m, |
|
220 const_cast<u8_t*>( &server_m->get_connection_data()->iap_data().psk_key().key_data[0] ), |
|
221 server_m->get_connection_data()->iap_data().psk_key().key_length, |
|
222 server_m->get_connection_data()->iap_data().is_psk_overridden(), |
|
223 &network_id ); |
|
224 DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - start_authentication returned with %u", |
|
225 ret ); |
|
226 |
|
227 break; |
|
228 } |
|
229 case core_state_do_connect: |
|
230 { |
|
231 core_key_management_e key_management( core_key_management_eap ); |
|
232 core_encryption_mode_e encryption_mode( core_encryption_mode_wpa ); |
|
233 bool_t is_pairwise_key_invalidated( true_t ); |
|
234 |
|
235 switch ( eapol_auth_type_m ) |
|
236 { |
|
237 case wlan_eapol_if_eapol_key_authentication_type_rsna_eap: |
|
238 /** Falls through on purpose. */ |
|
239 case wlan_eapol_if_eapol_key_authentication_type_wpa_eap: |
|
240 { |
|
241 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_eap" ); |
|
242 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_wpa" ); |
|
243 key_management = core_key_management_eap; |
|
244 encryption_mode = core_encryption_mode_wpa; |
|
245 break; |
|
246 } |
|
247 case wlan_eapol_if_eapol_key_authentication_type_wfa_sc: |
|
248 { |
|
249 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_eap" ); |
|
250 key_management = core_key_management_eap; |
|
251 |
|
252 if ( ap_data_m.is_privacy_enabled() ) |
|
253 { |
|
254 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_wpa" ); |
|
255 encryption_mode = core_encryption_mode_wpa; |
|
256 } |
|
257 else |
|
258 { |
|
259 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_disabled" ); |
|
260 encryption_mode = core_encryption_mode_disabled; |
|
261 } |
|
262 break; |
|
263 } |
|
264 case wlan_eapol_if_eapol_key_authentication_type_rsna_psk: |
|
265 /** Falls through on purpose. */ |
|
266 case wlan_eapol_if_eapol_key_authentication_type_wpa_psk: |
|
267 { |
|
268 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_preshared" ); |
|
269 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_wpa" ); |
|
270 key_management = core_key_management_preshared; |
|
271 encryption_mode = core_encryption_mode_wpa; |
|
272 break; |
|
273 } |
|
274 case wlan_eapol_if_eapol_key_authentication_type_802_1x: |
|
275 { |
|
276 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_eap" ); |
|
277 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_802dot1x" ); |
|
278 key_management = core_key_management_eap; |
|
279 encryption_mode = core_encryption_mode_802dot1x; |
|
280 break; |
|
281 } |
|
282 case wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam: |
|
283 { |
|
284 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam" ); |
|
285 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_encryption_mode_802dot1x" ); |
|
286 key_management = core_key_management_wpx_fast_roam; |
|
287 encryption_mode = core_encryption_mode_802dot1x; |
|
288 if( is_cached_sa_used_m ) |
|
289 { |
|
290 is_pairwise_key_invalidated = false_t; |
|
291 } |
|
292 break; |
|
293 } |
|
294 case wlan_eapol_if_eapol_key_authentication_type_wapi: |
|
295 { |
|
296 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_wapi_certificate" ); |
|
297 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_security_mode_wapi" ); |
|
298 key_management = core_key_management_wapi_certificate; |
|
299 encryption_mode = core_encryption_mode_wpi; |
|
300 break; |
|
301 } |
|
302 case wlan_eapol_if_eapol_key_authentication_type_wapi_psk: |
|
303 { |
|
304 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using key management core_key_management_wapi_psk" ); |
|
305 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - using encryption mode core_security_mode_wapi" ); |
|
306 key_management = core_key_management_wapi_psk; |
|
307 encryption_mode = core_encryption_mode_wpi; |
|
308 break; |
|
309 } |
|
310 default: |
|
311 { |
|
312 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - unknown authentication type" ); |
|
313 ASSERT( false_t ); |
|
314 } |
|
315 } |
|
316 |
|
317 operation_state_m = core_state_req_connect; |
|
318 |
|
319 if( ap_data_m.is_rsn_ie_present() ) |
|
320 { |
|
321 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - generating RSN IE" ); |
|
322 |
|
323 sent_ie_m = core_frame_rsn_ie_c::instance( |
|
324 server_m->get_wpx_adaptation_instance(), |
|
325 ap_data_m.best_group_cipher(), |
|
326 ap_data_m.best_pairwise_cipher(), |
|
327 key_management, |
|
328 pmkid_length_m, |
|
329 &pmkid_data_m[0] ); |
|
330 } |
|
331 else if( ap_data_m.is_wpa_ie_present() ) |
|
332 { |
|
333 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - generating WPA IE" ); |
|
334 |
|
335 sent_ie_m = core_frame_wpa_ie_c::instance( |
|
336 server_m->get_wpx_adaptation_instance(), |
|
337 ap_data_m.best_group_cipher(), |
|
338 ap_data_m.best_pairwise_cipher(), |
|
339 key_management ); |
|
340 } |
|
341 else if( ap_data_m.is_wapi_ie_present() ) |
|
342 { |
|
343 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - generating WAPI IE" ); |
|
344 |
|
345 sent_ie_m = core_frame_wapi_ie_c::instance( |
|
346 ap_data_m.best_group_cipher(), |
|
347 ap_data_m.best_pairwise_cipher(), |
|
348 key_management, |
|
349 0, |
|
350 pmkid_length_m, |
|
351 &pmkid_data_m[0] ); |
|
352 } |
|
353 |
|
354 if( sent_ie_m && |
|
355 eapol_auth_type_m != wlan_eapol_if_eapol_key_authentication_type_wfa_sc ) |
|
356 { |
|
357 assoc_ie_list_m.append( |
|
358 sent_ie_m, |
|
359 sent_ie_m->element_id() ); |
|
360 } |
|
361 |
|
362 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_connecting as true" ); |
|
363 server_m->get_connection_data()->set_eapol_connecting( |
|
364 true_t ); |
|
365 |
|
366 core_operation_base_c* operation = new core_sub_operation_connect_c( |
|
367 request_id_m, |
|
368 server_m, |
|
369 drivers_m, |
|
370 adaptation_m, |
|
371 is_connected_m, |
|
372 connect_status_m, |
|
373 ssid_m, |
|
374 ap_data_m, |
|
375 auth_algorithm_m, |
|
376 server_m->get_wpx_adaptation_instance().encryption_mode( |
|
377 ap_data_m, encryption_mode ), |
|
378 core_tools_c::cipher_key_type( |
|
379 ap_data_m.best_pairwise_cipher() ), |
|
380 assoc_ie_list_m, |
|
381 assoc_resp_m, |
|
382 is_pairwise_key_invalidated, |
|
383 true_t ); |
|
384 |
|
385 return run_sub_operation( operation ); |
|
386 } |
|
387 case core_state_req_connect: |
|
388 { |
|
389 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - connection success" ); |
|
390 |
|
391 operation_state_m = core_state_req_state_notification; |
|
392 |
|
393 network_id_c network( |
|
394 ¤t_bssid_m.addr[0], |
|
395 MAC_ADDR_LEN, |
|
396 &server_m->own_mac_addr().addr[0], |
|
397 MAC_ADDR_LEN, |
|
398 server_m->get_eapol_instance().ethernet_type() ); |
|
399 |
|
400 const core_frame_dot11_ie_c* ie = NULL; |
|
401 if( ap_data_m.is_rsn_ie_present() ) |
|
402 { |
|
403 ie = ap_data_m.rsn_ie(); |
|
404 } |
|
405 else if( ap_data_m.is_wpa_ie_present() ) |
|
406 { |
|
407 ie = ap_data_m.wpa_ie(); |
|
408 } |
|
409 else if( ap_data_m.is_wapi_ie_present() ) |
|
410 { |
|
411 ie = ap_data_m.wapi_ie(); |
|
412 } |
|
413 |
|
414 core_frame_dot11_ie_c * recv_ie = NULL; |
|
415 core_frame_dot11_ie_c * sent_ie = NULL; |
|
416 |
|
417 if ( sent_ie_m ) |
|
418 { |
|
419 sent_ie = sent_ie_m; |
|
420 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - sent IE: " ); |
|
421 DEBUG_BUFFER( sent_ie_m->data_length(), sent_ie_m->data() ); |
|
422 } |
|
423 |
|
424 if ( ie ) |
|
425 { |
|
426 recv_ie = core_frame_dot11_ie_c::instance( ie->data_length(), ie->data() ); |
|
427 |
|
428 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - received IE: " ); |
|
429 DEBUG_BUFFER( ie->data_length(), ie->data() ); |
|
430 } |
|
431 |
|
432 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_connecting as false" ); |
|
433 server_m->get_connection_data()->set_eapol_connecting( |
|
434 false_t ); |
|
435 server_m->get_connection_data()->set_eapol_auth_bssid( |
|
436 current_bssid_m ); |
|
437 |
|
438 /** |
|
439 * WPX fast-roam reassociation is handled differently, EAPOL indication will |
|
440 * move the state machine forward. |
|
441 */ |
|
442 if ( is_cached_sa_used_m && |
|
443 eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam ) |
|
444 { |
|
445 server_m->get_wpx_adaptation_instance().handle_fast_roam_reassoc_resp( |
|
446 assoc_resp_m ? *assoc_resp_m : NULL ); |
|
447 |
|
448 delete recv_ie; |
|
449 recv_ie = NULL; |
|
450 delete ie; |
|
451 ie = NULL; |
|
452 return core_error_request_pending; |
|
453 } |
|
454 |
|
455 u8_t * temp_recv_ie( NULL ); |
|
456 u32_t temp_recv_ie_length( 0 ); |
|
457 u8_t * temp_sent_ie( NULL ); |
|
458 u32_t temp_sent_ie_length( 0 ); |
|
459 |
|
460 if ( recv_ie ) |
|
461 { |
|
462 temp_recv_ie = const_cast<u8_t*>( recv_ie->data() ); |
|
463 temp_recv_ie_length = recv_ie->data_length(); |
|
464 } |
|
465 if ( sent_ie_m ) |
|
466 { |
|
467 temp_sent_ie = const_cast<u8_t*>( sent_ie->data() ); |
|
468 temp_sent_ie_length = sent_ie->data_length(); |
|
469 } |
|
470 |
|
471 if ( is_cached_sa_used_m ) |
|
472 { |
|
473 server_m->get_eapol_instance().complete_reassociation( |
|
474 wlan_eapol_if_eapol_wlan_authentication_state_association_ok, |
|
475 &network, |
|
476 temp_recv_ie, temp_recv_ie_length, |
|
477 temp_sent_ie, temp_sent_ie_length, |
|
478 core_tools_c::eapol_cipher( ap_data_m.best_pairwise_cipher() ), |
|
479 core_tools_c::eapol_cipher( ap_data_m.best_group_cipher() ) ); |
|
480 } |
|
481 else |
|
482 { |
|
483 server_m->get_eapol_instance().complete_association( |
|
484 wlan_eapol_if_eapol_wlan_authentication_state_association_ok, |
|
485 &network, |
|
486 temp_recv_ie, temp_recv_ie_length, |
|
487 temp_sent_ie, temp_sent_ie_length, |
|
488 core_tools_c::eapol_cipher( ap_data_m.best_pairwise_cipher() ), |
|
489 core_tools_c::eapol_cipher( ap_data_m.best_group_cipher() ) ); |
|
490 } |
|
491 |
|
492 delete recv_ie; |
|
493 recv_ie = NULL; |
|
494 delete ie; |
|
495 ie = NULL; |
|
496 |
|
497 // Send EAPOL frame after timer. This will allow new EAPOL frames to come from queue. |
|
498 return asynch_goto( core_state_process_eapol_frame, CORE_TIMER_IMMEDIATELY ); |
|
499 } |
|
500 case core_state_process_eapol_frame: |
|
501 { |
|
502 operation_state_m = core_state_req_state_notification; |
|
503 |
|
504 server_m->get_eapol_instance().process_stored_frame(); |
|
505 server_m->register_event_handler( this ); |
|
506 |
|
507 break; |
|
508 } |
|
509 case core_state_req_state_notification: |
|
510 { |
|
511 server_m->unregister_event_handler( this ); |
|
512 |
|
513 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - authentication success" ); |
|
514 |
|
515 return core_error_ok; |
|
516 } |
|
517 case core_state_req_connect_failed: |
|
518 { |
|
519 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - connection failed" ); |
|
520 |
|
521 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_authentication_started as false" ); |
|
522 server_m->get_connection_data()->set_eapol_authentication_started( |
|
523 false_t ); |
|
524 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_connecting as false" ); |
|
525 server_m->get_connection_data()->set_eapol_connecting( |
|
526 false_t ); |
|
527 |
|
528 /** The connection attempt failed, we are no longer connected. */ |
|
529 is_connected_m = false_t; |
|
530 |
|
531 /** |
|
532 * WPX fast-roam reassociation is handled differently, EAPOL indication will |
|
533 * move the state machine forward. |
|
534 * |
|
535 * This completion should be before clearing eapol_handler. |
|
536 * Otherwise we don't get error message. |
|
537 */ |
|
538 if ( is_cached_sa_used_m && |
|
539 eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam ) |
|
540 { |
|
541 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - calling EAPOL complete_fast_roam_reassociation (this_ap_failed)" ); |
|
542 server_m->get_wpx_adaptation_instance().handle_fast_roam_reassoc_resp( NULL ); |
|
543 |
|
544 return core_error_request_pending; |
|
545 } |
|
546 |
|
547 /** |
|
548 * We already know the connection has failed so don't process the failure |
|
549 * indication from EAPOL. |
|
550 */ |
|
551 server_m->set_eapol_handler( NULL ); |
|
552 |
|
553 wlan_eapol_if_eapol_wlan_authentication_state_e eapol_reason( |
|
554 wlan_eapol_if_eapol_wlan_authentication_state_this_ap_failed ); |
|
555 |
|
556 if ( connect_status_m == core_management_status_auth_algo_not_supported ) |
|
557 { |
|
558 eapol_reason = wlan_eapol_if_eapol_wlan_authentication_state_802_11_auth_algorithm_not_supported; |
|
559 } |
|
560 else if ( failure_reason_m == core_error_timeout ) |
|
561 { |
|
562 eapol_reason = wlan_eapol_if_eapol_wlan_authentication_state_no_response; |
|
563 } |
|
564 |
|
565 network_id_c network( |
|
566 ¤t_bssid_m.addr[0], |
|
567 MAC_ADDR_LEN, |
|
568 &server_m->own_mac_addr().addr[0], |
|
569 MAC_ADDR_LEN, |
|
570 server_m->get_eapol_instance().ethernet_type() ); |
|
571 |
|
572 if ( is_cached_sa_used_m ) |
|
573 { |
|
574 DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - calling EAPOL complete_reassociation with code %u", |
|
575 eapol_reason ); |
|
576 |
|
577 server_m->get_eapol_instance().complete_reassociation( |
|
578 eapol_reason, |
|
579 &network, |
|
580 NULL, 0, |
|
581 NULL, 0, |
|
582 wlan_eapol_if_rsna_cipher_none, |
|
583 wlan_eapol_if_rsna_cipher_none ); |
|
584 } |
|
585 else |
|
586 { |
|
587 DEBUG1( "core_sub_operation_wpa_connect_c::next_state() - calling EAPOL complete_association with code %u", |
|
588 eapol_reason ); |
|
589 |
|
590 server_m->get_eapol_instance().complete_association( |
|
591 eapol_reason, |
|
592 &network, |
|
593 NULL, 0, |
|
594 NULL, 0, |
|
595 wlan_eapol_if_rsna_cipher_none, |
|
596 wlan_eapol_if_rsna_cipher_none ); |
|
597 } |
|
598 |
|
599 return cancel(); |
|
600 } |
|
601 case core_state_req_association_failed: |
|
602 { |
|
603 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - association, reassociation or WPX fast-roam reassociation failed" ); |
|
604 |
|
605 server_m->set_eapol_handler( NULL ); |
|
606 |
|
607 return cancel(); |
|
608 } |
|
609 case core_state_bss_lost: |
|
610 { |
|
611 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - authentication failed due to BSS lost" ); |
|
612 |
|
613 /** The connection attempt failed, we are no longer connected. */ |
|
614 is_connected_m = false_t; |
|
615 |
|
616 return core_error_timeout; |
|
617 } |
|
618 case core_state_user_cancel: |
|
619 { |
|
620 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - pending request has been completed, proceeding with user cancel" ); |
|
621 |
|
622 network_id_c network( |
|
623 ¤t_bssid_m.addr[0], |
|
624 MAC_ADDR_LEN, |
|
625 &server_m->own_mac_addr().addr[0], |
|
626 MAC_ADDR_LEN, |
|
627 server_m->get_eapol_instance().ethernet_type() ); |
|
628 |
|
629 DEBUG6( "core_sub_operation_wpa_connect_c::next_state() - EAPOL disassociation from BSSID %02X:%02X:%02X:%02X:%02X:%02X", |
|
630 current_bssid_m.addr[0], current_bssid_m.addr[1], current_bssid_m.addr[2], |
|
631 current_bssid_m.addr[3], current_bssid_m.addr[4], current_bssid_m.addr[5] ); |
|
632 |
|
633 server_m->get_eapol_instance().disassociation( &network ); |
|
634 |
|
635 /** The connection attempt failed, we are no longer connected. */ |
|
636 is_connected_m = false_t; |
|
637 |
|
638 return core_error_cancel; |
|
639 } |
|
640 default: |
|
641 { |
|
642 ASSERT( false_t ); |
|
643 } |
|
644 } |
|
645 |
|
646 return core_error_request_pending; |
|
647 } |
|
648 |
|
649 // --------------------------------------------------------------------------- |
|
650 // --------------------------------------------------------------------------- |
|
651 // |
|
652 core_error_e core_sub_operation_wpa_connect_c::cancel() |
|
653 { |
|
654 DEBUG( "core_sub_operation_wpa_connect_c::cancel()" ); |
|
655 |
|
656 switch( operation_state_m ) |
|
657 { |
|
658 case core_state_req_connect: |
|
659 { |
|
660 return goto_state( core_state_req_connect_failed ); |
|
661 } |
|
662 case core_state_req_state_notification: |
|
663 { |
|
664 if( server_m->get_connection_data()->is_eapol_require_immediate_reconnect() || |
|
665 ( is_key_caching_used_m && |
|
666 failure_reason_m == core_error_eapol_auth_start_timeout ) ) |
|
667 { |
|
668 DEBUG( "core_sub_operation_wpa_connect_c::cancel() - re-attempting authentication" ); |
|
669 server_m->get_connection_data()->set_eapol_require_immediate_reconnect( false_t ); |
|
670 assoc_ie_list_m.clear(); |
|
671 |
|
672 return asynch_goto( core_state_init, 100000 ); // 100 ms delay before new connect |
|
673 } |
|
674 |
|
675 /** The connection attempt failed, we are no longer connected. */ |
|
676 is_connected_m = false_t; |
|
677 |
|
678 return failure_reason_m; |
|
679 } |
|
680 default: |
|
681 { |
|
682 return failure_reason_m; |
|
683 } |
|
684 } |
|
685 } |
|
686 |
|
687 // --------------------------------------------------------------------------- |
|
688 // --------------------------------------------------------------------------- |
|
689 // |
|
690 void core_sub_operation_wpa_connect_c::user_cancel( |
|
691 bool_t /* do_graceful_cancel */ ) |
|
692 { |
|
693 DEBUG( "core_sub_operation_wpa_connect_c::user_cancel()" ); |
|
694 |
|
695 /** |
|
696 * Do not handle any EAPOL indications that might occur during our |
|
697 * transition to core_state_user_cancel state. |
|
698 */ |
|
699 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_authenticating as false" ); |
|
700 server_m->get_connection_data()->set_eapol_authenticating( |
|
701 false_t ); |
|
702 DEBUG( "core_sub_operation_wpa_connect_c::next_state() - marking is_eapol_authentication_started as false" ); |
|
703 server_m->get_connection_data()->set_eapol_authentication_started( |
|
704 false_t ); |
|
705 |
|
706 /** |
|
707 * If we are waiting for an EAPOL indication, we'll have to schedule |
|
708 * our own timer to proceed. |
|
709 */ |
|
710 if( operation_state_m == core_state_req_state_notification ) |
|
711 { |
|
712 asynch_goto( core_state_user_cancel, CORE_TIMER_IMMEDIATELY ); |
|
713 |
|
714 return; |
|
715 } |
|
716 |
|
717 /** |
|
718 * Otherwise we'll just wait for the pending request complete |
|
719 * before continuing. |
|
720 */ |
|
721 operation_state_m = core_state_user_cancel; |
|
722 } |
|
723 |
|
724 // --------------------------------------------------------------------------- |
|
725 // --------------------------------------------------------------------------- |
|
726 // |
|
727 core_error_e core_sub_operation_wpa_connect_c::packet_send( |
|
728 network_id_c * send_network_id, |
|
729 u8_t * packet_data, |
|
730 u32_t packet_data_length, |
|
731 bool_t send_unencrypted ) |
|
732 { |
|
733 DEBUG( "core_sub_operation_wpa_connect_c::packet_send()" ); |
|
734 |
|
735 server_m->send_data_frame( |
|
736 ap_data_m, |
|
737 core_frame_type_ethernet, |
|
738 static_cast<u16_t>( packet_data_length ), |
|
739 packet_data, |
|
740 core_access_class_voice, |
|
741 send_network_id->destination(), |
|
742 send_unencrypted ); |
|
743 |
|
744 return core_error_ok; |
|
745 } |
|
746 |
|
747 // --------------------------------------------------------------------------- |
|
748 // --------------------------------------------------------------------------- |
|
749 // |
|
750 core_error_e core_sub_operation_wpa_connect_c::associate( |
|
751 wlan_eapol_if_eapol_key_authentication_mode_e authentication_mode ) |
|
752 { |
|
753 DEBUG( "core_sub_operation_wpa_connect_c::associate()" ); |
|
754 |
|
755 auth_algorithm_m = server_m->get_wpx_adaptation_instance().authentication_algorithm( |
|
756 eapol_auth_type_m, |
|
757 authentication_mode ); |
|
758 |
|
759 next_state(); |
|
760 |
|
761 return core_error_ok; |
|
762 } |
|
763 |
|
764 // --------------------------------------------------------------------------- |
|
765 // --------------------------------------------------------------------------- |
|
766 // |
|
767 core_error_e core_sub_operation_wpa_connect_c::disassociate( |
|
768 network_id_c * /*receive_network_id*/, |
|
769 const bool_t /* self_disassociation */ ) |
|
770 { |
|
771 DEBUG( "core_sub_operation_wpa_connect_c::disassociate()" ); |
|
772 |
|
773 return core_error_ok; |
|
774 } |
|
775 |
|
776 // --------------------------------------------------------------------------- |
|
777 // --------------------------------------------------------------------------- |
|
778 // |
|
779 core_error_e core_sub_operation_wpa_connect_c::packet_data_session_key( |
|
780 network_id_c * send_network_id, |
|
781 session_key_c * key ) |
|
782 { |
|
783 DEBUG( "core_sub_operation_wpa_connect_c::packet_data_session_key()" ); |
|
784 ASSERT ( key != NULL ); |
|
785 ASSERT ( send_network_id != NULL ); |
|
786 |
|
787 core_mac_address_s mac( BROADCAST_MAC_ADDR ); |
|
788 |
|
789 if ( key->eapol_key_type == wlan_eapol_if_eapol_key_type_unicast ) |
|
790 { |
|
791 mac = send_network_id->destination(); |
|
792 } |
|
793 |
|
794 core_cipher_key_type_e type = |
|
795 core_tools_c::cipher_key_type( |
|
796 key->eapol_key_type, |
|
797 ap_data_m.best_pairwise_cipher(), |
|
798 ap_data_m.best_group_cipher() ); |
|
799 |
|
800 ASSERT( drivers_m ); |
|
801 drivers_m->add_cipher_key( |
|
802 type, |
|
803 static_cast<u8_t>( key->key_index ), |
|
804 static_cast<u16_t>( key->key_length ), |
|
805 key->key, |
|
806 mac, |
|
807 true_t ); |
|
808 |
|
809 return core_error_ok; |
|
810 } |
|
811 |
|
812 // --------------------------------------------------------------------------- |
|
813 // --------------------------------------------------------------------------- |
|
814 // |
|
815 void core_sub_operation_wpa_connect_c::state_notification( |
|
816 state_notification_c * /*state*/ ) |
|
817 { |
|
818 DEBUG( "core_sub_operation_wpa_connect_c::state_notification()" ); |
|
819 } |
|
820 |
|
821 // --------------------------------------------------------------------------- |
|
822 // --------------------------------------------------------------------------- |
|
823 // |
|
824 core_error_e core_sub_operation_wpa_connect_c::reassociate( |
|
825 network_id_c * /* send_network_id */, |
|
826 const wlan_eapol_if_eapol_key_authentication_type_e /* authentication_type */, |
|
827 u8_t * PMKID, |
|
828 u32_t PMKID_length ) |
|
829 { |
|
830 DEBUG( "core_sub_operation_wpa_connect_c::reassociate()" ); |
|
831 |
|
832 if( PMKID ) |
|
833 { |
|
834 pmkid_length_m = PMKID_length; |
|
835 core_tools_c::copy( |
|
836 &pmkid_data_m[0], |
|
837 PMKID, |
|
838 pmkid_length_m ); |
|
839 } |
|
840 |
|
841 DEBUG( "core_sub_operation_wpa_connect_c::reassociate() - using open authentication algorithm" ); |
|
842 auth_algorithm_m = core_authentication_mode_open; |
|
843 |
|
844 next_state(); |
|
845 |
|
846 return core_error_ok; |
|
847 } |
|
848 |
|
849 // --------------------------------------------------------------------------- |
|
850 // --------------------------------------------------------------------------- |
|
851 // |
|
852 core_error_e core_sub_operation_wpa_connect_c::complete_check_pmksa_cache( |
|
853 core_type_list_c<network_id_c> & /* network_id_list */ ) |
|
854 { |
|
855 DEBUG( "core_sub_operation_wpa_connect_c::complete_check_pmksa_cache()" ); |
|
856 return core_error_ok; |
|
857 } |
|
858 |
|
859 // --------------------------------------------------------------------------- |
|
860 // --------------------------------------------------------------------------- |
|
861 // |
|
862 core_error_e core_sub_operation_wpa_connect_c::complete_start_wpx_fast_roam_reassociation( |
|
863 network_id_c * /* receive_network_id */, |
|
864 u8_t * reassociation_request_ie, |
|
865 u32_t reassociation_request_ie_length ) |
|
866 { |
|
867 DEBUG( "core_sub_operation_wpa_connect_c::complete_start_wpx_fast_roam_reassociation()" ); |
|
868 |
|
869 // Generate a WPX fast-roam IE and append it to assoc_ie_list. |
|
870 // Actually this could be done with core_wpx_frame_fast_roam_req_ie_c::instance() to make sure it's size is correct. |
|
871 core_frame_dot11_ie_c* ie = core_frame_dot11_ie_c::instance( |
|
872 reassociation_request_ie_length, |
|
873 reassociation_request_ie, |
|
874 true_t ); |
|
875 if ( !ie ) |
|
876 { |
|
877 DEBUG( "core_sub_operation_wpa_connect_c::complete_start_wpx_fast_roam_reassociation() - unable to generate a dot11 IE" ); |
|
878 is_cached_sa_used_m = false_t; |
|
879 //asynch_goto( core_state_init, CORE_TIMER_IMMEDIATELY ); |
|
880 return core_error_no_memory; |
|
881 } |
|
882 |
|
883 assoc_ie_list_m.append( |
|
884 ie, |
|
885 ie->element_id() ); |
|
886 |
|
887 if( eapol_auth_type_m == wlan_eapol_if_eapol_key_authentication_type_wpx_fast_roam && |
|
888 is_cached_sa_used_m ) |
|
889 { |
|
890 server_m->get_connection_data()->set_eapol_authenticating( |
|
891 true_t ); |
|
892 } |
|
893 |
|
894 asynch_goto( core_state_do_connect, CORE_TIMER_IMMEDIATELY ); |
|
895 return core_error_ok; |
|
896 } |
|
897 |
|
898 |
|
899 // --------------------------------------------------------------------------- |
|
900 // --------------------------------------------------------------------------- |
|
901 // |
|
902 core_error_e core_sub_operation_wpa_connect_c::new_protected_setup_credentials( |
|
903 core_type_list_c< protected_setup_credential_c > & /* credential_list */ ) |
|
904 { |
|
905 DEBUG( "core_sub_operation_wpa_connect_c::new_protected_setup_credentials()" ); |
|
906 |
|
907 ASSERT( false_t ); |
|
908 |
|
909 return core_error_ok; |
|
910 } |
|
911 |
|
912 |
|
913 // --------------------------------------------------------------------------- |
|
914 // --------------------------------------------------------------------------- |
|
915 // |
|
916 void core_sub_operation_wpa_connect_c::handle_error( |
|
917 wlan_eapol_if_error_e errorcode, |
|
918 wlan_eapol_if_message_type_function_e function ) |
|
919 { |
|
920 DEBUG3( "core_sub_operation_wpa_connect_c::handle_error() - Received error message: errorcode=%i, function=%i (operation_state_m=%i)", |
|
921 errorcode, |
|
922 function, |
|
923 operation_state_m ); |
|
924 |
|
925 if ( errorcode != wlan_eapol_if_error_ok |
|
926 && errorcode != wlan_eapol_if_error_pending_request ) |
|
927 { |
|
928 if ( function == wlan_eapol_if_message_type_function_start_reassociation ) |
|
929 { |
|
930 // Full authentication is needed. |
|
931 is_cached_sa_used_m = false_t; |
|
932 asynch_goto( core_state_start_authentication_needed, CORE_TIMER_IMMEDIATELY ); |
|
933 } |
|
934 else if ( function == wlan_eapol_if_message_type_function_start_wpx_fast_roam_reassociation ) |
|
935 { |
|
936 is_cached_sa_used_m = false_t; |
|
937 |
|
938 asynch_goto( core_state_init, CORE_TIMER_IMMEDIATELY ); |
|
939 } |
|
940 else if ( function == wlan_eapol_if_message_type_function_complete_association |
|
941 || function == wlan_eapol_if_message_type_function_complete_reassociation |
|
942 || function == wlan_eapol_if_message_type_function_complete_wpx_fast_roam_reassociation ) |
|
943 { |
|
944 DEBUG( "core_sub_operation_wpa_connect_c::handle_error() - (WPX fast-roam) (re-)association failed" ); |
|
945 asynch_goto( core_state_req_association_failed, CORE_TIMER_IMMEDIATELY ); |
|
946 } |
|
947 /*else if ( function == wlan_eapol_if_message_type_function_start_authentication ) |
|
948 { |
|
949 }*/ |
|
950 else |
|
951 { |
|
952 DEBUG( "core_sub_operation_wpa_connect_c::handle_error() - Error ignored." ); |
|
953 } |
|
954 } |
|
955 } |
|
956 |
|
957 |
|
958 // --------------------------------------------------------------------------- |
|
959 // --------------------------------------------------------------------------- |
|
960 // |
|
961 bool_t core_sub_operation_wpa_connect_c::notify( |
|
962 core_am_indication_e indication ) |
|
963 { |
|
964 if ( operation_state_m == core_state_req_state_notification && |
|
965 ( indication == core_am_indication_wlan_media_disconnect || |
|
966 indication == core_am_indication_wlan_beacon_lost || |
|
967 indication == core_am_indication_wlan_power_mode_failure || |
|
968 indication == core_am_indication_wlan_tx_fail ) ) |
|
969 { |
|
970 server_m->unregister_event_handler( this ); |
|
971 |
|
972 if ( indication == core_am_indication_wlan_media_disconnect ) |
|
973 { |
|
974 DEBUG( "core_sub_operation_wpa_connect_c::notify() - AP has disconnected us during authentication, notifying EAPOL" ); |
|
975 } |
|
976 else |
|
977 { |
|
978 DEBUG( "core_sub_operation_wpa_connect_c::notify() - connection to the AP has been lost, notifying EAPOL" ); |
|
979 } |
|
980 |
|
981 network_id_c network( |
|
982 ¤t_bssid_m.addr[0], |
|
983 MAC_ADDR_LEN, |
|
984 &server_m->own_mac_addr().addr[0], |
|
985 MAC_ADDR_LEN, |
|
986 server_m->get_eapol_instance().ethernet_type() ); |
|
987 |
|
988 DEBUG6( "core_sub_operation_wpa_connect_c::notify() - EAPOL disassociation from BSSID %02X:%02X:%02X:%02X:%02X:%02X", |
|
989 current_bssid_m.addr[0], current_bssid_m.addr[1], current_bssid_m.addr[2], |
|
990 current_bssid_m.addr[3], current_bssid_m.addr[4], current_bssid_m.addr[5] ); |
|
991 |
|
992 server_m->get_eapol_instance().disassociation( &network ); |
|
993 |
|
994 if ( indication != core_am_indication_wlan_media_disconnect ) |
|
995 { |
|
996 DEBUG( "core_sub_operation_wpa_connect_c::notify() - marking is_eapol_authenticating as false" ); |
|
997 server_m->get_connection_data()->set_eapol_authenticating( |
|
998 false_t ); |
|
999 DEBUG( "core_sub_operation_wpa_connect_c::notify() - marking is_eapol_authentication_started as false" ); |
|
1000 server_m->get_connection_data()->set_eapol_authentication_started( |
|
1001 false_t ); |
|
1002 |
|
1003 asynch_goto( core_state_bss_lost ); |
|
1004 |
|
1005 return true_t; |
|
1006 } |
|
1007 |
|
1008 /** |
|
1009 * EAPOL indication will move the state machine forward. |
|
1010 */ |
|
1011 |
|
1012 return true_t; |
|
1013 } |
|
1014 |
|
1015 return false_t; |
|
1016 } |