跟一下wpa_supplicant(3-2) connect AP

来源:互联网 发布:matlab 关联矩阵代码 编辑:程序博客网 时间:2024/06/07 00:25
转:http://blog.chinaunix.net/uid-20514606-id-3260320.html
接前面(3-1)继续:
 
5. 接分支4.
authenticate response 来了
和前面一样:
wpa_driver_nl80211_event_receive到
=> process_event
   收到 NL80211_CMD_AUTHENTICATE=37
   ==> mlme_event (37)
       ===> mlme_event_auth
            authenticate response 管理帧中的AP mac 是我们感兴趣的,
     收了它,放wpa_driver_nl80211_data 的auth_bssid
            并放到wpa_event_data->auth_info->peer 
     ====> wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);
           Event 11 received on interface wlan0 被扔出来
          =====> sme_event_auth(wpa_s, data);
                       紧接着
         D/wpa_supplicant( 2129): SME: Authentication response:
                        peer=00:1f:33:b9:5d:e0 auth_type=0 status_code=0
                       被扔出来
                       ======> eloop_cancel_timeout(sme_auth_timer, 
                     wpa_s, NULL);
                               取消auth 失败的警戒,可以进城了
                       ======> sme_associate(wpa_s, ssid->mode, 
                  data->auth.peer, data->auth.auth_type);
    启动关联
                               =======>wpa_supplicant_set_state(wpa_s, 
                    WPA_ASSOCIATING);
                               ========> wpa_s->new_connection = 1;
                               ========> wpa_drv_set_operstate(wpa_s, 0);
                   /* 设置到IF_OPER_DORMANT */
                               ========> wpa_s->wpa_state = state;
                               ========> wpas_notify_state_changed(wpa_s, 
             wpa_s->wpa_state, old_state); 
        如果 oldstate  不同情况下执行
                               =======> 设置参数等,ie 
                               =======> wpa_drv_associate(wpa_s, &params) 
                                wpa_driver_nl80211_associate  driver interface
           通过netlink 给dirver 发assoc request
                                wpa_printf(MSG_DEBUG, "nl80211: 
       Association request send "  "successfully");
                                发完了应该,别忘警戒下:
                       =======> eloop_register_timeout(SME_ASSOC_TIMEOUT, 
                                 0, sme_assoc_timer, wpa_s,  NULL);
                                 /* 关联超时失败处理*/
        
                             接下来到分支6.
6. 接分支5.
38 event 来了!
wpa_driver_nl80211_event_receive到
=> process_event
   ==> mlme_event (38= NL80211_CMD_ASSOCIATE)
       asscoicate response 来了
      ===> mlme_event_assoc(drv, nla_data(frame),
             nla_len(frame));
      这里的 frame 应该就是关联响应帧
             去读下rp frame state 判断response为成功
          ====> drv->associated = 1;
          ====> 获得resp 中的IE们 到 event.assoc_info.resp_ies
          ====> event.assoc_info.freq = drv->assoc_freq;
        关联时的频率放到 struct assoc_info
         有了IE,就象口袋有钱,可以来事了,EVENT_ASSOC发出去
          ====> wpa_supplicant_event(drv->ctx, EVENT_ASSOC,&event);
               =====> wpa_supplicant_event_assoc(wpa_s, data);
                     ======> wpa_supplicant_event_associnfo
                            获取AP 的assoc info!
       就是挖掘前面说的已经存到event.assoc_info的resp ie
       其中如果挖到PMKID,是要注意
       去call wpa_find_assoc_pmkid
       干什么? 如果忘记了,到第1篇搜索:
       '成对主蜜钥安全关联'字样,我就不讲了
                     ======> wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
                             State: ASSOCIATING -> ASSOCIATED
                     ======> wpa_clear_keys (clear driver config key)
                     ======> wpa_supplicant_select_config
              我们设置为AP_SCAN =1(让wpa_supplciant选择AP)
       所以它什么也不做,return
                     ======> wpa_sm_notify_assoc(wpa_s->wpa, bssid);
                            WPA state machine 的rx_replay_counter_set 清0,
       的renew_snonce 置1
       比较下是否是在preauth的ap 的mac,是的话就deinit它
       最后清下wap state machine 的 old PTK
       这么做是因为人家IEEE 802.11协议8.4.10部分说了
                            Delete PTK SA on (re)association if this is not 
          part of a Fast BSS Transition.
                            
                            PTK 有两种格式,TKIP,和CCMP
                     ======> eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
                     ======>eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
       ======> if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || 
                                   ft_completed)
                          eapol_sm_notify_eap_success(wpa_s->eapol,
                                FALSE);   
                      到这里PAE还没变化,下面就要变了
                     ======> eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
                            portEnabled=1
       PAE状态要发生变化了,从disconnect 变到connecting
                            这个disconnect是在 eapol_sm_init,开始设置的
       之后一直保持该状态
       EAP状态一直为disable,因为我们是WPA-psk,所以
       没有EAP,他就一直处于disable
                     ======> /* Timeout for receiving the first
                  EAPOL packet */
                       wpa_supplicant_req_auth_timeout(wpa_s, 10, 0);
         /* 10  秒后没收到第1个 eapol packet 后 ,
         就处理auth 失败 */
                     ======> wpa_supplicant_cancel_sched_scan(wpa_s);
       /* 要做正事了, 就先停sched scan ,scan  */
                  wpa_supplicant_cancel_scan(wpa_s);
                     ======> wpa_supplicant_event_assoc中
                接下来的部分不会执行到

到这里已经关联已经完成,在AP 发来EAPOL frame 前,我们会收到
NL80211_CMD_CONNECT 通知,根据cmd注释,可以了解该命令是在不分开进行认证
和关联的情况下,来请求连接到一个指点网络的,连接完成会收到NL80211_CMD_CONNECT
的response,目前的driver capa里设置了WPA_DRIVER_FLAGS_SME,表示driver 支持
auth 和associate 分开的命令,所以能收到NL80211_CMD_CONNECT,但不处理
为什么呢? 注释里已经写了,为了避免2次报告关联事件,引起核心代码混乱
/** Avoid reporting two association events that would confuse
 * the core code.
 */
                   进入7. 继续
7. 前面6.中完成asscicate 后,讲过就会等待EAPOL FRAME到来
  在wpa init 中 wpa_supplicant_driver_init 会注册 l2 rx callback
wpa_s->l2 = l2_packet_init(wpa_s->ifname,
     wpa_drv_get_mac_addr(wpa_s),
     ETH_P_EAPOL,
     wpa_supplicant_rx_eapol, wpa_s, 0);
可以看出收到l2 packet 后call back wpa_supplicant_rx_eapol,就从它开始
=> wpa_supplicant_rx_eapol:
   ==> wpa_supplicant_req_auth_timeout(wpa_s,
              (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
       wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA 
               || wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ? 70 : 10, 0);
        和前面associate最后设置的10s timeout 一样,这里只是收到
 第1个,reset 下一次认证超时为10s
   ==> wpa_s->eapol_received++;  是第1次,eapol_received++ 后等于1
   ==> wpa_drv_poll(wpa_s);
   ==> if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
          ===> wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
              该函数处理收到的 EAPOL frame
              分析可得:
                * type =2 时 EAPOL-Key
  * key_info =0x8a
     (ver=2 keyidx=0 rsvd=0 Pairwise Ack)
  * key length =16, key data lenght 22
key_info 各bit 所代表的内容在:
wpa_comm.h中定义如下:

点击(此处)折叠或打开

  1. /* IEEE 802.11, 8.5.2 EAPOL-Key frames */
  2. #define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2)))
  3. #define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0)
  4. #define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1)
  5. #define WPA_KEY_INFO_TYPE_AES_128_CMAC 3
  6. #define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */
  7. /* bit4..is used in WPA, but is reserved in IEEE 802.11i/RSN */
  8. #define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5))
  9. #define WPA_KEY_INFO_KEY_INDEX_SHIFT 4
  10. #define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */
  11. #define WPA_KEY_INFO_TXRX BIT(6) /* group */
  12. #define WPA_KEY_INFO_ACK BIT(7)
  13. #define WPA_KEY_INFO_MIC BIT(8)
  14. #define WPA_KEY_INFO_SECURE BIT(9)
  15. #define WPA_KEY_INFO_ERROR BIT(10)
  16. #define WPA_KEY_INFO_REQUEST BIT(11)
  17. #define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */
  18. #define WPA_KEY_INFO_SMK_MESSAGE BIT(13)


第1个发过来的eapol frame 表示4次握手的第1次握手已经开始了!!!
   ==> 接下来就是部分4 way handle 的代码,直接贴上:

点击(此处)折叠或打开

  1. if (key_info & WPA_KEY_INFO_KEY_TYPE) { 
  2.      /* 走到这里, WPA_KEY_INFO_KEY_TYPE ,pairwise ,or group key !!!*/
  3.    if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
  4.  wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  5.  "WPA: Ignored EAPOL-Key (Pairwise) with "
  6.  "non-zero key index");
  7.  goto out;
  8.    }
  9.    if (peerkey) { /* 如果4way 的第1次没有peerkey */
  10.       /* PeerKey 4-Way Handshake */
  11.   peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver);
  12.    } else if (key_info & WPA_KEY_INFO_MIC) {
  13.      /* 3/4 4-Way Handshake */
  14.      wpa_supplicant_process_3_of_4(sm, key, ver);
  15.    } else {
  16.        /* 1/4 4-Way Handshake */
  17.  wpa_supplicant_process_1_of_4(sm, src_addr, key, ver);
  18.    }
  19. } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
  20.      /* PeerKey SMK Handshake */
  21.      peerkey_rx_eapol_smk(sm, src_addr, key, extra_len, key_info,ver);
  22. } else {
  23.  if (key_info & WPA_KEY_INFO_MIC) {
  24.  /* 1/2 Group Key Handshake */
  25.  wpa_supplicant_process_1_of_2(sm, src_addr, key, extra_len, ver);
  26.   } else {
  27.          wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
  28.         "WPA: EAPOL-Key (Group) without Mic bit - "
  29.   "dropped");
  30.  }
  31. }

 
wpa_supplicant_process_1_of_4(sm, src_addr, key, ver);
wpa_supplicant_process_3_of_4(sm, key, ver);
是我们关心的
为什么没有0_of_4, 2_of_4? 不是没有,4次握手的第1,3次都在AP端处理
我们不管了,所以目前阶段,直接跑到1_fo_4,处理如下
 
       ===> wpa_supplicant_process_1_of_4(sm, src_addr, key,  ver);
            ====> wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); 
                  wap state 变化了 , ASSOCIATED -> 4WAY_HANDSHAKE
            ====> wpa_supplicant_parse_ies(_buf, len, &ie);
                  将buf 内容解析到 struct wpa_eapol_ie_parse
                  包括我们下面要用的pmkid 
            ====> wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
       如果pmksa cashe 不空,
       先从PMKSA cache中根据传来的ie.pmkid 去匹配
       然后获得PMK,它是计算 PTK必须的,但现在cur_pmksa
       为空,那如何获得pmk ,其实上面已经设置了,
       在wpa_supplicant_associate 的
       最后 wpa_sm_set_pmk 将预共享密钥PSK,copy到
        struct wpa_sm->pmk
                    
            ====> ptk = &sm->tptk;
            ====> wpa_derive_ptk(sm, src_addr, key, ptk);
                  计算方法:
               wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
                  sm->own_addr, sm->bssid, sm->snonce, key->key_nonce,
                  (u8 *) ptk, ptk_len,
                  wpa_key_mgmt_sha256(sm->key_mgmt));
                  公式:
                  * PTK = PRF-X(PMK, "Pairwise key expansion",
                  *             Min(AA, SA) || Max(AA, SA) ||
                  *             Min(ANonce, SNonce) || Max(ANonce, SNonce))
            ====> wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, 
         sm->snonce, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, ptk)
                  =====> wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, 
            NULL, sizeof(*reply) + wpa_ie_len, &rlen, 
     (void *) &reply);
                       os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
                       wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL,  
             rbuf, rlen, reply->key_mic);
                      /* 发出去,然后等下次 wpa_supplicant_rx_eapol*/
                   接下来到8.
 
8.
l2 packet 又来了
=> wpa_supplicant_rx_eapol:
   ==> wpa_drv_poll(wpa_s);
   ==> if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
        wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
        该函数处理收到的 EAPOL frame
        分析可得:
        * type =2 时 EAPOL-Key
 * key_info =0x13ca
    (ver=2 keyidx=0 rsvd=0 Pairwise Install Ack MIC Secure Encr)
 * key length =16, key data lenght 80
   ==>  else if (key_info & WPA_KEY_INFO_MIC) { 
         /*wpa_commom.h #define WPA_KEY_INFO_MIC BIT(8)*/
  /* 3/4 4-Way Handshake */
   ==>  wpa_supplicant_process_3_of_4(sm, key, ver); 
       其中key 就是 EAPOL-KEY 内容
struct wpa_eapol_key {   /* EAPOL-KEY 结构!!! */
 u8 type;
 /* Note: key_info, key_length, and key_data_length are unaligned */
 u8 key_info[2]; /* big endian */
 u8 key_length[2]; /* big endian */
 u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
 u8 key_nonce[WPA_NONCE_LEN];
 u8 key_iv[16];
 u8 key_rsc[WPA_KEY_RSC_LEN];
 u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */
 u8 key_mic[16];
 u8 key_data_length[2]; /* big endian */
 /* followed by key_data_length bytes of key_data */
} STRUCT_PACKED;
        下面对eapol key data 部分进行处理,将获得的ie,放到
 struct wpa_eapol_ie_parse 
        ===> pos = (const u8 *) (key + 1);  eapol key 后就是ie
             len = WPA_GET_BE16(key->key_data_length);    
             wpa_supplicant_parse_ies(pos, len, &ie);
                     
        ===> wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
                      NULL, 0, &sm->ptk)
             ====> wpa_sm_alloc_eapol ,init epaol packet
                   =====> wpa_eapol_key_send(sm, ptk->kck, ver, dst, 
               ETH_P_EAPOL,  rbuf, rlen, reply->key_mic);
        一个ACK ,没有什么实质内容,也不加密
        ===> wpa_supplicant_install_ptk (struct wpa_sm *sm, 
                   const struct wpa_eapol_key *key)
              ====> 设置driver key !!! wpa_sm_set_key
                    wpa_driver_nl80211_set_key  (nl80211 driver)
                    wap_supplicant 的 终极目标,终于看到了!
      PTK 安装好了,稍侯片刻,马上结束
        ===> eapol_sm_notify_portValid(sm->eapol, TRUE);
               前面associate 成功后 PAE 处于 CONNECTING
               到这里 portValid = TRUE, 但PAE 状态没发生变化
        ===> wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
             WPA State 从 4WAY_HANDSHAKE -> GROUP_HANDSHAKE
        ===> wpa_supplicant_pairwise_gtk(sm, key, ie.gtk,ie.gtk_len, 
                                    key_info)
             从代码中看加密的GTK 3/4 way  中的IE部分就发来了!!!
             wpa_supplicant_check_group_cipher
      用双方都已知道的PTK 的 EPAOL KEK 加的密 )现在解开来
             ====> wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) 
            安装组密码
             ====> wpa_supplicant_key_neg_complete   key 协商完成
                   =====> wpa_sm_cancel_auth_timeout(sm);
            将前面设置的认证超时处理取消
                   =====> wpa_sm_set_state(sm, WPA_COMPLETED);
             wpa state 从 GROUP_HANDSHAKE -> COMPLETED
                   =====> if (secure) {
                            ......
                     eapol_sm_notify_portValid(sm->eapol, TRUE);
                     eapol_sm_notify_eap_success(sm->eapol, TRUE);
       PAE 进入AUTHENTICATING
       BE  进入success
       EAP 返回diable
       PAE 最终进入AUTHENTICATED
         然后eapol_sm_set_port_authorized
                              然后wpa_supplicant_port_cb
         然后wpa_drv_set_supp_port
         设置driver NL80211_STA_FLAG_AUTHORIZED
到此为止,认证完成
整个过程的WPA State变化如下:
(wpa_supplicant)
DISCONNECTED    -> SCANNING
SCANNING        -> AUTHENTICATING      (802.11身份认证 )
AUTHENTICATING  -> ASSOCIATING
SCANNING        -> ASSOCIATING 
ASSOCIATING     -> ASSOCIATED     
      
ASSOCIATED      -> 4WAY_HANDSHAKE
4WAY_HANDSHAKE  -> 4WAY_HANDSHAKE
4WAY_HANDSHAKE  -> GROUP_HANDSHAKE
GROUP_HANDSHAKE -> COMPLETED
PAE supplicant 端状态图
 
 
结束
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 油耳堵住了耳朵怎么办 耳屎突然变湿该怎么办 小孩有耳屎好硬怎么办 小孩的耳屎深硬怎么办 1岁宝宝喉咙发炎怎么办 牙旁边的肉疼怎么办 鼻头软骨捏的痛怎么办 耳洞发炎肿了怎么办 一上火耳朵就疼怎么办 耳朵像隔了层膜怎么办 感冒引起的耳闷怎么办 5岁儿童视力0.6怎么办 柯基耳朵不立怎么办 宝宝一惊一乍睡觉不踏实怎么办 新婴儿睡觉不踏实怎么办 耳朵里面疼肿了怎么办 生出来的孩子是畸形怎么办 二胎生了缺陷儿怎么办 扣完肚脐眼后疼怎么办 刚出生的婴儿屁股红怎么办 狗狗耳朵流血了怎么办 狗狗不让掏耳朵怎么办 下巴总是反复长脓包怎么办 不胖但有双下巴怎么办 早上起床眼肿了怎么办 小孩鼻梁很塌的怎么办 17岁鼻子是塌的,怎么办 鼻子又塌又翘怎么办 戴眼镜鼻子塌了怎么办 耳朵里长了粉刺怎么办 耳洞太大了怎么办变小 天生嘴唇厚又大怎么办 上嘴唇太厚怎么办还翘 20岁欠债5万怎么办 脑袋撞了个包怎么办 交通事故对方全责但不赔偿怎么办 人格分列症的症状怎么办 子宫肌瘤月经量多怎么办 卵泡长得太慢怎么办 后期卵泡长得慢怎么办 促排卵泡长得慢怎么办