wpa_supplicant 是什麼 ? 負責wifi在user space的管理daemon

根據wiki說明, wpa_supplicant 是一個免費軟體實現了 IEEE 802.11i 管理控制 (在多平台上 Linux, FreeBSD, NetBSD, AROS, Microsoft Windows, Solaris, OS/2 ), 而且wpa_supplicant 既可達到全功能的WPA2 管理控制,它也同時實現了WPA和較舊的無線局域網安全協議。

簡介

IEEE802.11i協議(無線安全標準)作為IEEE802.11協議的一部分,制定了無線安全接入的標準。 WPA和WPA2(RSN)是無線安全標準中的兩種密鑰管理規範。 WPA(或WPA2)無線安全接入又包括使用802.1x協議認證的企業版和使用PSK(預共享密鑰)認證的個人版。 Supplicant是無線客戶端上實現WPA/802.1x認證功能的組件。 wpa_supplicant是無線客戶端上實現密鑰管理和認證的supplicant軟件(對應服務器端的軟件則為hostapd)。

wpa_supplicant功能支持

支援 WPA/IEEE 802.11i features 與 EAP methods (IEEE 802.1X Supplicant):

Supported WPA/IEEE 802.11i features
– WPA-PSK (“WPA-Personal”)
– WPA with EAP (e.g., with RADIUS authentication server) (“WPA-Enterprise”)
– key management for CCMP, TKIP, WEP104, WEP40
– WPA and full IEEE 802.11i/RSN/WPA2
– RSN: PMKSA caching, pre-authentication
– IEEE 802.11r
– IEEE 802.11w
– Wi-Fi Protected Setup (WPS)

Supported EAP methods (IEEE 802.1X Supplicant)
– EAP-TLS
– EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1)
– EAP-PEAP/TLS (both PEAPv0 and PEAPv1)
– EAP-PEAP/GTC (both PEAPv0 and PEAPv1)
– EAP-PEAP/OTP (both PEAPv0 and PEAPv1)
– EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1)
– EAP-TTLS/EAP-MD5-Challenge
– EAP-TTLS/EAP-GTC
– EAP-TTLS/EAP-OTP
– EAP-TTLS/EAP-MSCHAPv2
– EAP-TTLS/EAP-TLS
– EAP-TTLS/MSCHAPv2
– EAP-TTLS/MSCHAP
– EAP-TTLS/PAP
– EAP-TTLS/CHAP
– EAP-SIM
– EAP-AKA
– EAP-AKA’
– EAP-PSK
– EAP-FAST
– EAP-PAX
– EAP-SAKE
– EAP-IKEv2
– EAP-GPSK
– LEAP (note: requires special support from the driver)

補充:無線網路使用者身份認證及加密
無線網路以空氣作為傳輸的介質,透過無線網路傳送資料時,任何人只要透過適當的設備,就可以收集並且竊取未經保護的資料。因此,如果以未加密的方式透過無線傳送是相當危險的!假定有意的攻擊者已準備竊聽您所傳送的資料,那麼,前述適當的設備有可能只需要一支高增益天線以及一台筆記型電腦,攻擊者就可以躲在遠處準備搜集您的資料,而整個過程中使用者可能都毫無警覺。

[WEP]
當傳送資料無可避免地會被有心人士竊取,又必須保護其安全性,最有效的方法就是對傳送的資料進行加密。起初,WEP(Wired Equivalent Privacy, 有線等效加密)為1999年9月通過的IEEE 802.11標準的一部份,當初被視為無線安全解決方案。WEP使用RC4(Rivest Cipher)加密技術達到機密性,RC4密碼鎖是屬於一種對稱串流密碼鎖。傳送端使用金鑰串流與訊息結合產生密文傳送;接收端收到密文後,再使用同一把金鑰串流處理密文還原原始資料。由於RC4演算法設計所造成的先天性弱點,一旦重覆使用金鑰串流、串流密碼鎖,且WEP採用IV的方式,讓攻擊者在搜集到夠多的資訊後,就能夠針對其重覆部份進行分析。可供運用的IV值並不大(小於一千七百萬),在繁忙的網路環境中必然會產生重覆的狀況。不過由於WEP設計相當容易實作,設備並不需要相當強大的計算能力,在許多的設備上也必定會支援。

[802.1X]
使用WEP僅是針對具有加密金鑰的機器進行加密動作,而802.1X則是對於使用者身份進行確認,而不會造成使用同一機器但不同使用者權限授權的困擾。802.1X只是一個架構,是IEEE採用IETF的可延伸身份認證協定(Extensible Authentication Protocol, EAP)制訂而成的,屬於一種架構協定。EAP是一個基礎的封裝方式,可以適於任何的鏈路層如PPP、802.3、802.11,以及各種身份認證的方式如TLS、AKA/SIM、Token card。

EAP身份驗證方式
EAP的使用者身份驗證作業是一個稱為EAP method的附屬協定所處理,這樣的優點是EAP並不需要處理使用者驗證的細節,當有不同的需求產生時,就僅需開發新的EAP method來滿足不同的需求,如MD5 Challenge、GTC、EAP-TLS、TTLS、PEAP、EAP-SIM及MS-CHAP-V2都是常見的EAP method。

[LEAP]
LEAP(Lightweight EAP)為Cisco所專屬的,為最早普遍使用的無線網路身份認證方式。相對於WEP用手動方式設定金鑰,LEAP進行二次MS-CHAP-V1交換程序,在交換MS-CHAP程序時則衍生出動態金鑰。但也因MS-CHAP-V1所致,也導致與EAP-MD5一樣易遭受字典攻擊。不過在Cisco本身的認定上,如果使用十分複雜的密碼,LEAP仍是相當安全可靠的;但對於現實生活中的人們使用複雜的密碼,則是有其困難的一面。而較新的協定在進行MS-CHAP-V2用戶認證程序時,先行建立一個安全的傳輸層安全通道(TLS),如EAP-TTLS、PEAP,則可避免這些問題的發生。

[EAP-TLS]
EAP-TLS(Transport Layer Security)的前身為SSL(Secure Socket Layer),利用PKI來保護RADIUS的通訊。雖然EAP-TLS相當安全,但並未受到廣泛的運用,因為在無線網路環境中使用EAP-TLS,所有潛在的用戶都必須具備數位憑證;而產生以及傳遞憑證與佈置的環境中,都是相當繁雜且不容易的。

wpa_supplicant軟件設計的目標

1)與硬件和驅動不相關性
wpa_supplicant作為應用層軟件,是伴隨著IEEE802.11標準的發展以及各種硬件驅動軟件的發展和不斷完善成熟的。與硬件驅動的不相關性的設計目標也是為了在不同操作系統上的移植以及支持早期的各種wifi協議棧驅動軟件。 wpa_supplicant可以支持windows的ndis驅動,linux平台的hosap驅動,madwif驅動,ralink和atheros驅動,以及目前linux內核中主流支持的mac80211協議棧驅動。

2)OS不相關性
wpa_supplicant支持windows(包括wince),linux,BSD和Mac OS X以及嵌入式系統。

3)所有WPA功能C代碼的可移植性。

4)wpa_supplicant 是被設計成守護進程(daemon)的方式運行,就是在後台執行的程式, 通過控制接口由其他外部控制軟件(wpa_cli, wpa_gui或者其他用戶開放的軟件進行配置控制無線接入)。

總之,靈活的可移植性,可配置編譯方式可以方便地讓開發者根據需要在不同開發平台和嵌入式系統上實現WPA的安全認證功能。

wpa_supplicant軟件架構

下圖為wpa_supplicant的基本架構圖(摘自wpa_supplicant官網開發文檔圖)。

1. event loop 是核心事件處理模塊,也是wpa_supplicant的主進程程序。
從模塊名可知,它負責事件處理,處理所有的其他模塊發送過來的事件以及超時事件。並且是loop循環執行的。

2. driver i/f模塊,是負責配置控制無線驅動的API接口。
真正的功能則在wext,hosap,madwifi等接口模塊中實現。這些驅動接口模塊針對不同的OS 無線驅動的配置接口標準,或者驅動開發者自定義的配置接口。 wext是linux系統早期定義的無線配置接口標準,nl80211也是linux無線配置接口,與wext相比有些技術上的優勢(圖中未列出)。

3. driver event模塊。
wlan網絡設備驅動有些事件需要通知wpa_supplicant,讓wpa_supplicant進行下一步的處理。包括網絡連接,斷開,MIC校驗錯,關聯成功等等。該模塊的實現也是OS相關的,不同的操作系統,事件通知的機制不同。

4. L2 packet模塊。
WPA(WPA2)的安全認證是通過EAPOL幀(以太類型0x888E)來完成的。 L2 packet模塊就是完成驅動層到應用層的EAPOL的獲取和EAPOL幀的發送。 windows系統上採用NDIS協議驅動的抓包技術,wpa_supplicant的實現支持NDISUIO協議驅動(微軟提供的協議驅動)抓包,winpcap的協議驅動抓包技術。 linux系統上則採用Packet socket抓包技術。

5. Configuration模塊。
無線配置功能模塊。

6. Ctrl i/f模塊。
提高外部配置程序的控制和事件通知。

7. WPA/WPA2狀態機。
實現WPA/WPA2的密鑰協商。

8. EAPOL狀態機。
802.1x的狀態機實現。

9. EAP狀態機。
企業級安全認證實現。

Wpa_supplicant提供的接口

從通信層次上劃分,wpa_supplicant提供向上的控制接口control interface,用於與其他模塊(如UI)進行通信,其他模塊可以通過control interface來獲取信息或下發命令。
Wpa_supplicant通過socket通信機制實現下行接口,與內核進行通信,獲取信息或下發命令。

1 上行接口

Wpa_supplicant提供兩種方式的上行接口。一種基於傳統dbus機制實現與其他進程間的IPC通信;另一種通過Unix domain socket機制實現進程間的IPC通信。

1.1 Dbus接口

該接口主要在文件“ ctrl_iface_dbus.h ”,“ ctrl_iface_dbus.c ”,“ ctrl_iface_dbus_handler.h ”和“ ctrl_iface_dbus_handler.c ”中實現,提供一些基本的控制方法。

1.2 Unix domain socket接口
該接口主要在文件“ wpa_ctrl.h ”,“ wpa_ctrl.c ”,“ ctrl_iface_unix.c ”,“ ctrl_iface.h ”和“ ctrl_iface.c ”實現。

(1) “ wpa_ctrl.h ”,“ wpa_ctrl.c ”完成對control interface的封裝,對外提供統一的接口。
其主要的工作是通過Unix domain socket建立一個control interface的client結點,與作為server的wpa_supplicant結點通信。

主要功能函數:

Note: Wpa_supplicant提供兩種由外部模塊獲取信息的方式:一種是外部模塊通過發送request命令然後獲取response的問答模式,另一種是wpa_supplicant主動向外部發送event事件,由外部模塊監聽接收。一般的常用做法是外部模塊通過調用wpa_ctrl_open()兩次,建立兩個control interface接口,一個為ctrl interface,用於發送命令,獲取信息,另一個為monitor interface,用於監聽接收來自於wpa_supplicant的event時間。此舉可以降低通信的耦合性,避免response和event的相互干擾。

int wpa_ctrl_attach (struct wpa_ctrl *ctrl); /*註冊 某個control interface作為monitor interface */ int wpa_ctrl_detach (struct wpa_ctrl *ctrl); /*撤銷某個monitor interface為 普通的control interface */ int wpa_ctrl_pending (struct wpa_ctrl *ctrl); /*判斷是否有掛起的event事件*/ int wpa_ctrl_recv (struct wpa_ctrl *ctrl, char *reply, size_t *reply_len); /*獲取掛起的event事件 */

(2) “ ctrl_iface_unix.c ”實現wpa_supplicant的Unix domain socket通信機制中server結點,完成對client結點的響應。

其中最主要的兩個函數為:

(3) “ ctrl_iface.h ”和“ ctrl_iface.c ”主要實現了各種request命令的底層處理函數。

2 下行接口:

wpa_supplicant與kernel(driver)進行通信, wpa_supplicant通過socket通信機制實現下行接口,與kernel(driver)進行通信,獲取信息或下發命令。
附圖說明wpa_supplicant與驅動交互的過程。
從該圖看,因為應用層部分還有WifiLayer類,說明android源碼應該是2.1的,比較老了。
不過分析了下wpa_supplicant,感覺變動不大,還是可以參考一下底層這一部分的。

wpa_supplicant下行接口主要包括三種重要的接口:

1 .PF_INET socket接口,主要用於向kernel發送ioctl命令,控制並獲取相應信息。
2 .PF_NETLINK socket接口,主要用於接收kernel發送上來的event事件。
3 .PF_PACKET socket接口,主要用於向driver傳遞802.1X報文。

主要涉及到的文件包括:
driver.h,drivers.c,driver_wext.h,driver_wext.c,l2_packet.h和l2_packet_linux.c。
其中,
– driver.h,drivers.c,driver_wext.h和driver_wext.c實現PF_INET socket接口和PF_NETLINK socket接口;
– l2_packet.h和l2_packet_linux.c實現PF_PACKET socket接口。

(1) driver.h/drivers.c:主要用於封裝底層差異,對外顯示一個相同的wpa_driver_ops接口。
wpa_supplicant可支持atmel, Broadcom, ipw, madwifi, ndis, nl80211, wext等多種驅動。
其中一個最主要的數據結構為wpa_driver_ops, 其定義了driver相關的各種操作接口。

(2) driver_nl80211.c實現了nl80211形式的wpa_driver_ops

並創建了PF_INET socket接口,然後通過這接口完成與kernel的信息交互。
nl80211提供的一個主要資料結構為:

裡面有一個 struct nl80211_global *global;
看一下定義如下

初始化

將各函式包進wpa_driver_ops類型資料結構 wpa_driver_nl80211_ops裡面
這樣對wpa_supplicant較上層的部分, 可以統一呼叫的API
只要這裡有對應不同平台的function call即可

(3) driver_wext.h/driver_wext.c實現了wext形式的wpa_driver_ops

並創建了PF_INET socket接口和PF_NETLINK socket接口(wpa_supplicant_8中沒有創建PF_NETLINK socket接口),然後通過這兩個接口完成與kernel的信息交互。

wext提供的一個主要數據結構為:

其中event_sock 為PF_NETLINK socket接口,ioctl_sock為PF_INET socket接口。

driver_wext.c 實現了大量底層處理函數用於實現wpa_driver_ops操作參數,其中比較重要的有:

/* 初始化wpa_driver_wext_data數據結構,並創建PF_NETLINK socket和PF_INET socket接口 */
void * wpa_driver_wext_init( void *ctx, const char * ifname);

/* 銷毀wpa_driver_wext_data數據結構,PF_NETLINK socket和PF_INET socket接口 */
void wpa_driver_wext_deinit( void * priv);

最後,將實現的操作函數映射到一個全局的wpa_driver_ops類型數據結構wpa_driver_wext_ops中。

(3) l2_packet.h/l2_packet_linux.c 主要用於實現PF_PACKET socket接口,
通過該接口,wpa_supplicant可以直接將802.1X packet發送到L2層,而不經過TCP/IP協議棧。

其中主要的功能函數為:

ps:l2_packet_init方法中有代碼:

即註冊了與socket關聯的回調方法為l2_packet_receive。

關於 L2_packet 模塊

L2_packet模塊是wpa_supplicant軟件中實現EAPOL幀(frame)的收發功能的模塊。 L2即網絡協議層的數據鏈路層 layer 2 。 wpa_supplicant針對不同的OS系統,採用了不同的抓包技術實現。 windows平台採用NDIS協議驅動抓包技術,linux平台採用packet socket抓包技術。

該模塊的實現代碼在目錄wpa_supplicant/src/l2_packet中。
l2_packet_linux.c是linux系統下的收發EAPOL幀實現。
l2_packet_ndis.c是windows系統下使用ndisuio協議驅動實現收發EAPOL幀實現。
l2_packet_pcap是windows系統下使用winpcap協議驅動實現EAPOL收發,採用輪詢的方式抓包。
l2_packet_winpcap是windows系統下使用winpcap協議驅動實現EAPOL收發,採用接收線程的方式抓包。相比l2_packet_pcap抓包,接收EAPOL幀的延遲從100ms降到了3ms。
l2_packet.h是api接口聲明和struct l2_packet_data聲明頭文件。

l2_packet主要的接口函數說明

l2_packet_init()
l2_packet_init()函數在wpa_supplicant初始化時候調用。

ifname: 網絡設備名
own_addr: mac地址
protocol:協議類型或者以太類型。如抓取EAPOL幀,以太類型為0x888E。
rx_callback: 接收到EAPOL幀的回調處理函數。
ctx:上面回調處理函數的回調參數。
l2_hrd:收發數據是否包含l2層以太頭。通常設置為0,不包含。

l2_packet_deinit
wpa_supplicant退出或清除時調用,釋放相關資源。

l2_packet_send
向驅動發送EAPOL幀(frame)接口函數。

l2_packet_notify_auth_start
該函數接口的實現只在l2_packet_winpcap中實現,因其採用創建一個線程抓包,所以在無線聯網關聯成功之後,喚醒l2_packet接收線程,準備獲取EAPOL幀。

l2_packet_linux的實現分析

在linux系統上,wpa_supplicant採用PACKET SOCKET技術抓取EAPOL幀(frame)。 wpa_supplicant的Event Loop模塊採用輪詢方式獲取EAPOL幀(frame),並處理。

初始化

1)分配struct l2_packet_data,並設置回調函數和回調參數以及l2_hdr標記
2)調用socket創建端口文件句柄,其協議族為PF_PACKET,SOCK_TYPE根據是否包含以太幀頭設置為SOCK_RAW或者SOCK_DGRAM,發送和接收到以太幀類型為EAPOL幀。
3)調用ioctl(l2->fd, SIOCGIFINDEX, &ifr)獲取網絡設備對應的索引值。
4)配置sockaddr_ll數據結構,調用bind函數綁定端口文件句柄。
5)調用ioctl(l2->fd, SIOCGIFHWADDR, &ifr)獲取硬件MAC地址備用。
6)調用eloop_register_read_sock向wpa_supplicant的Event Loop模塊註冊一個讀取socket的操作。事件觸發的回調函數為l2_packet_receive。回調函數上下文參數為l2。

Event Loop 模塊如何調用 l2_packet_receive ?

在l2_packet_init()函數中調用了eloop_register_read_sock註冊了一個讀socket操作。

在Event Loop模塊的eloop_run()函數中
循環執行調用 eloop_sock_table_dispatch(&eloop.readers, rfds) ,對所有註冊的讀取socket的操作進行處理,
通過調用FD_ISSET(table->table[i].sock, fds )判斷socket文件句柄的狀態是否發生變化,如果發生變化,則調用註冊的回調函數(即l2_packet_receive)
在l2_packet_init()註冊: eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);

EAPOL帧frame的接收

1)調用recvfrom把接收到的EAPOL幀拷貝到buf緩存中(最長2300字節)。
2)調用註冊的EAPOL接收處理函數,即wpa_supplicant_rx_eapol()。(註冊在wpa_supplicant_update_mac_addr()裡, 帶入參數去呼叫l2_packet_init(wpa_s->ifname, wpa_drv_get_mac_addr(wpa_s), ETH_P_EAPOL, wpa_supplicant_rx_eapol, wpa_s, 0);)

EAPOL帧frame的發送

1)根據l2_hdr標記,如果l2_hdr配置為1,則直接發送原始數據。如果l2_hdr配置為0,則需要添加Ehernet frame header進行發送。
2)根據兩種情況,分別調用send(RAW) 或者sendto(DGRAM)發送EAPOL幀。

參考:

wpa_supplicant下行接口浅析
wpa_supplicant 2.0版源代码阅读(2) —- L2_packet模块

發表迴響