📄 cardif_windows_dot11.c
字号:
/**
* Windows wireless (ExtSta) interface.
*
* Licensed under a dual GPL/BSD license. (See LICENSE file for more info.)
*
* \file cardif_windows_dot11.c
*
* \authors chris@open1x.org
*
* \par CVS Status Information:
* \code
* $Id: cardif_windows_dot11.c,v 1.1.2.3 2007/04/08 02:39:26 chessing Exp $
* $Date: 2007/04/08 02:39:26 $
* \endcode
*
*/
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <winsock2.h>
#include <NtDDNdis.h>
#include <windot11.h>
// The nuiouser.h file is included with the Windows DDK. Please
// download the DDK and copy the file to the proper location.
#include "../../../vs2005/ndis_proto_driver/nuiouser.h"
#include "../../xsup_common.h"
#include "../../../lib/libxsupconfig/xsupconfig.h"
#include "../../../lib/libxsupconfig/xsupconfig_structs.h"
#include "../../context.h"
#include "../../config_ssid.h"
#include "../../xsup_debug.h"
#include "../../xsup_err.h"
#include "../../wpa.h"
#include "../../wpa2.h"
#include "../../wpa_common.h"
#include "../../cardif/cardif.h"
#include "../../ipc_events.h"
#include "../../ipc_events_index.h"
#include "../../ipc_callout.h"
#include "cardif_windows.h"
#include "cardif_windows_dot11.h"
#include "../../wireless_sm.h"
#include "../../timer.h"
#include "../../wpa.h"
#include "../../wpa2.h"
#ifdef USE_EFENCE
#include <efence.h>
#endif
// In DDK 3790.1830 these values aren't defined. So, define them.
#ifndef OID_802_11_CAPABILITY
#define OID_802_11_CAPABILITY 0x0D010122
// If the capability #define doesn't exist, then these values probably
// don't either. If you have build errors complaining that these are
// already defined, then comment them out.
#define Ndis802_11AuthModeWPA2 6
#define Ndis802_11AuthModeWPA2PSK 7
typedef struct _NDIS_802_11_AUTHENTICATION_ENCRYPTION
{
NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
} NDIS_802_11_AUTHENTICATION_ENCRYPTION, *PNDIS_802_11_AUTHENTICATION_ENCRYPTION;
typedef struct _NDIS_802_11_CAPABILITY
{
ULONG Length;
ULONG Version;
ULONG NoOfPMKIDs;
ULONG NoOfAuthEncryptPairsSupported;
NDIS_802_11_AUTHENTICATION_ENCRYPTION AuthenticationEncryptionSupported[1];
} NDIS_802_11_CAPABILITY, *PNDIS_802_11_CAPABILITY;
#endif
/**
* This will be called ~7 seconds after a request to scan. According to
* the Windows documentation, you need to wait at least 6 seconds before
* requesting scan data, which is where 7 seconds comes from. ;)
**/
void cardif_windows_dot11_scan_timeout(context *ctx)
{
DWORD BytesReturned;
UCHAR Buffer[65535]; // 64k of scan data is a *LOT*!
PNDISPROT_QUERY_OID pQueryOid;
PNDIS_802_11_BSSID_LIST_EX pBssidList;
PNDIS_WLAN_BSSID_EX pBssidEx;
PNDIS_802_11_SSID pSsid;
UCHAR *ofs;
char rssi;
int i;
char ssid[33];
struct win_sock_data *sockData;
LPVOID lpMsgBuf;
wireless_ctx *wctx;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE)) return;
if (ipc_events_scan_complete(ctx) != IPC_SUCCESS)
{
debug_printf(DEBUG_NORMAL, "Couldn't send scan complete event to IPC listeners.\n");
}
timer_cancel(ctx, SCANCHECK_TIMER);
wctx = (wireless_ctx *)ctx->intTypeData;
if (!xsup_assert((wctx != NULL), "wctx != NULL", FALSE)) return;
sockData = ctx->sockData;
if (!xsup_assert((sockData != NULL), "sockData != NULL", FALSE)) return;
memset(&Buffer[0], 0x00, sizeof(Buffer));
pQueryOid = (PNDISPROT_QUERY_OID)&Buffer[0];
pQueryOid->Oid = OID_802_11_BSSID_LIST;
if (devioctl_blk(sockData->devHandle, IOCTL_NDISPROT_QUERY_OID_VALUE,
(LPVOID)&Buffer[0], sizeof(Buffer), (LPVOID)&Buffer[0],
sizeof(Buffer), &BytesReturned) == FALSE)
{
debug_printf(DEBUG_NORMAL, "Attempt to get scan data results failed!\n");
ipc_events_error(ctx, IPC_EVENT_ERROR_GETTING_SCAN_DATA, ctx->desc);
lpMsgBuf = GetLastErrorStr(GetLastError());
debug_printf(DEBUG_NORMAL, "Reason was : %s\n", lpMsgBuf);
LocalFree(lpMsgBuf);
return;
}
// Only clear our cache if we have new data. This allows us to handle situations where
// stale scan data provides a means to authenticate to a connection that associates slowly
// (such as the IPW3945 with Trpz APs.)
config_ssid_clear(wctx);
pBssidList = (PNDIS_802_11_BSSID_LIST_EX)&pQueryOid->Data[0];
debug_printf(DEBUG_INT, "Got %d result(s).\n", pBssidList->NumberOfItems);
pBssidEx = (PNDIS_WLAN_BSSID_EX)&pBssidList->Bssid[0];
ofs = (UCHAR *)pBssidEx;
for (i = 0; i < (int)pBssidList->NumberOfItems; i++)
{
pBssidEx = (PNDIS_WLAN_BSSID_EX)ofs;
pSsid = (PNDIS_802_11_SSID)&pBssidEx->Ssid;
memset(&ssid, 0x00, sizeof(ssid));
if (strncpy_s((void *)&ssid, sizeof(ssid), pSsid->Ssid, pSsid->SsidLength) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't make a copy of the SSID in %s() at %d!\n",
__FUNCTION__, __LINE__);
goto bad_strncpy;
}
debug_printf(DEBUG_INT, "Found SSID : %s\n", ssid);
config_ssid_add_ssid_name(wctx, ssid);
debug_printf(DEBUG_INT, "BSSID : ");
debug_hex_printf(DEBUG_INT, pBssidEx->MacAddress, 6);
config_ssid_add_bssid(wctx, pBssidEx->MacAddress);
rssi = pBssidEx->Rssi;
debug_printf(DEBUG_INT, "RSSI : %d\n", rssi);
config_ssid_add_qual(wctx, 0, rssi, 0);
debug_printf(DEBUG_INT, "Privacy : %d\n", pBssidEx->Privacy);
if (pBssidEx->Privacy == 1) config_ssid_update_abilities(wctx, ENC);
cardif_windows_dot11_parse_ies(ctx, (uint8_t *)&pBssidEx->IEs[sizeof(NDIS_802_11_FIXED_IEs)], pBssidEx->IELength);
bad_strncpy:
ofs += pBssidEx->Length;
}
UNSET_FLAG(wctx->flags, WIRELESS_SCANNING);
return;
}
int cardif_windows_dot11_get_extsta_capabilities(context *ctx, DOT11_EXTSTA_CAPABILITY *capa)
{
DWORD BytesReturned;
UCHAR Buffer[sizeof(NDIS_OID)+sizeof(DOT11_EXTSTA_CAPABILITY)];
PNDISPROT_QUERY_OID pQueryOid;
struct win_sock_data *sockData;
LPVOID lpMsgBuf;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE)) return XEMALLOC;
sockData = ctx->sockData;
if (!xsup_assert((sockData != NULL), "sockData != NULL", FALSE)) return XEMALLOC;
memset(&Buffer, 0x00, sizeof(Buffer));
pQueryOid = (PNDISPROT_QUERY_OID)&Buffer[0];
pQueryOid->Oid = OID_DOT11_EXTSTA_CAPABILITY;
if (devioctl_blk(sockData->devHandle, IOCTL_NDISPROT_QUERY_OID_VALUE, (LPVOID)&Buffer[0], sizeof(Buffer),
(LPVOID)&Buffer[0], sizeof(Buffer), &BytesReturned) == FALSE)
{
debug_printf(DEBUG_NORMAL, "Couldn't get interface capabilities!\n");
//ipc_events_error(ctx, IPC_EVENT_LOG_CANT_GET_CAPABILITIES, ctx->desc, NULL);
lpMsgBuf = GetLastErrorStr(GetLastError());
debug_printf(DEBUG_NORMAL, "Reason was : %s\n", lpMsgBuf);
LocalFree(lpMsgBuf);
return -1;
}
memcpy(capa, &Buffer[sizeof(NDIS_OID)], sizeof(DOT11_EXTSTA_CAPABILITY));
return XENONE;
}
int cardif_windows_dot11_get_mode_capabilities(context *ctx)
{
DWORD BytesReturned;
UCHAR Buffer[sizeof(NDIS_OID)+sizeof(DOT11_OPERATION_MODE_CAPABILITY)+10];
PNDISPROT_QUERY_OID pQueryOid;
struct win_sock_data *sockData;
LPVOID lpMsgBuf;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE)) return XEMALLOC;
sockData = ctx->sockData;
if (!xsup_assert((sockData != NULL), "sockData != NULL", FALSE)) return XEMALLOC;
memset(&Buffer, 0x00, sizeof(Buffer));
pQueryOid = (PNDISPROT_QUERY_OID)&Buffer[0];
pQueryOid->Oid = OID_DOT11_EXTSTA_CAPABILITY;
if (devioctl_blk(sockData->devHandle, IOCTL_NDISPROT_QUERY_OID_VALUE, (LPVOID)&Buffer[0], sizeof(Buffer),
(LPVOID)&Buffer[0], sizeof(Buffer), &BytesReturned) == FALSE)
{
debug_printf(DEBUG_NORMAL, "Couldn't get interface capabilities!\n");
//ipc_events_error(ctx, IPC_EVENT_LOG_CANT_GET_CAPABILITIES, ctx->desc, NULL);
lpMsgBuf = GetLastErrorStr(GetLastError());
debug_printf(DEBUG_NORMAL, "Reason was : %s\n", lpMsgBuf);
LocalFree(lpMsgBuf);
return -1;
}
// memcpy(capa, &Buffer[sizeof(NDIS_OID)], sizeof(DOT11_EXTSTA_CAPABILITY));
return XENONE;
}
/**
* Tell the wireless card to scan for wireless networks.
**/
int cardif_windows_dot11_scan(context *ctx, char passive)
{
DWORD BytesReturned;
UCHAR Buffer[sizeof(NDIS_OID)+4];
PNDISPROT_SET_OID pSetOid;
struct win_sock_data *sockData;
LPVOID lpMsgBuf;
DOT11_EXTSTA_CAPABILITY capa;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE)) return XEMALLOC;
if (passive == TRUE)
{
// Windows XP doesn't do passive, so for now, return an error.
return XECANTPASSIVE;
}
sockData = ctx->sockData;
if (!xsup_assert((sockData != NULL), "sockData != NULL", FALSE)) return XEMALLOC;
cardif_windows_dot11_get_mode_capabilities(ctx);
if (cardif_windows_dot11_get_extsta_capabilities(ctx, &capa) != XEMALLOC)
{
debug_printf(DEBUG_NORMAL, "Couldn't get interface capabilities!\n");
return XEGENERROR;
}
else
{
// Display some information.
printf("SSID Scan List Size = %ld\n", capa.uScanSSIDListSize);
printf("Desired SSID List Size = %ld\n", capa.uDesiredSSIDListSize);
printf("Desired BSSID List Size = %ld\n", capa.uDesiredBSSIDListSize);
}
memset(&Buffer, 0x00, sizeof(Buffer));
pSetOid = (PNDISPROT_SET_OID)&Buffer[0];
pSetOid->Oid = OID_DOT11_SCAN_REQUEST;
if (devioctl_blk(sockData->devHandle, IOCTL_NDISPROT_SET_OID_VALUE, (LPVOID)&Buffer[0], sizeof(NDISPROT_QUERY_OID)+4,
NULL, 0, &BytesReturned) == FALSE)
{
debug_printf(DEBUG_NORMAL, "Couldn't start a scan!\n");
ipc_events_error(ctx, IPC_EVENT_ERROR_CANT_START_SCAN, ctx->desc);
lpMsgBuf = GetLastErrorStr(GetLastError());
debug_printf(DEBUG_NORMAL, "Reason was : %s\n", lpMsgBuf);
LocalFree(lpMsgBuf);
return -1;
}
// Once we had done that, we need to wait for at least 6 seconds to get full scan data back.
// So set a timer to check in 8 seconds.
timer_add_timer(ctx, SCANCHECK_TIMER, 8, NULL, cardif_windows_dot11_scan_timeout);
return XENONE;
}
/**
* Get the list of IEs that we used to associate.
*
* When this function is called, "ie_size" should be the size of the buffer defined by
* "ies". On return, "ie_size" will be the length of the IE block copied in to the buffer.
**/
int cardif_windows_dot11_get_ies(context *ctx, char *ies, int *ie_size)
{
DWORD BytesReturned;
DWORD result;
UCHAR QueryBuffer[65535]; // Unlikely that we would have a result this size!
PNDISPROT_QUERY_OID pQueryOid;
PNDIS_802_11_ASSOCIATION_INFORMATION pInfo;
struct win_sock_data *sockData;
LPVOID lpMsgBuf;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
return -1;
sockData = (struct win_sock_data *)ctx->sockData;
if (!xsup_assert((sockData != NULL), "sockData != NULL", FALSE))
return -1;
memset(&QueryBuffer, 0x00, sizeof(QueryBuffer));
pQueryOid = (PNDISPROT_QUERY_OID)&QueryBuffer[0];
pQueryOid->Oid = OID_802_11_ASSOCIATION_INFORMATION;
result = devioctl(sockData->devHandle, IOCTL_NDISPROT_QUERY_OID_VALUE,
(LPVOID)&QueryBuffer[0], sizeof(QueryBuffer),
(LPVOID)&QueryBuffer[0], sizeof(QueryBuffer), &BytesReturned);
if ((result != WAIT_OBJECT_0) && (result != WAIT_IO_COMPLETION))
{
if (result == 0xffffffff)
{
debug_printf(DEBUG_INT, "IOCTL returned that no association information is available.\n");
debug_printf(DEBUG_INT, "Are you associated to a network!?\n");
return -1;
}
debug_printf(DEBUG_NORMAL, "Get association information failed. (%x)\n", result);
lpMsgBuf = GetLastErrorStr(GetLastError());
debug_printf(DEBUG_NORMAL, "Reason was : %s\n", lpMsgBuf);
LocalFree(lpMsgBuf);
return -1;
}
pInfo = (PNDIS_802_11_ASSOCIATION_INFORMATION)&pQueryOid->Data[0];
if (pInfo->RequestIELength > (*ie_size))
{
debug_printf(DEBUG_NORMAL, "Insufficient buffer space to store resulting IEs!\n");
return -1;
}
memcpy(ies, &pQueryOid->Data[pInfo->OffsetRequestIEs], pInfo->RequestIELength);
(*ie_size) = pInfo->RequestIELength;
return XENONE;
}
/**
* Take a block of IE data specified by "in_ie" and parse it, looking for a
* WPA2 information element. The WPA2 information element will be returned in
* "out_ie", if the return value of the function is XENONE.
*
* Since a WPA2 information element is a variable length field, we will determine
* that we are looking at a WPA2 IE by matching against the static fields that are found
* at the beginning of the IE. The IE should be in the format of :
*
* 0x30 XX 0x01 0x00 0x00 0x0f 0xac GG (Followed by variable length stuff.)
*
* The value for XX needs to be at least 8 for it to be a valid IE.
**/
int cardif_windows_dot11_find_wpa2_ie(context *ctx, char *in_ie, int in_size,
char *out_ie, int *out_size)
{
const char wpa2oui[3] = {0x00, 0x0f, 0xac};
unsigned int i;
char done;
wireless_ctx *wctx;
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE)) return -1;
wctx = (wireless_ctx *)ctx->intTypeData;
if (!xsup_assert((wctx != NULL), "wctx != NULL", FALSE)) return -1;
i = 0;
done = FALSE;
while ((i < in_size) && (done == FALSE))
{
if (in_ie[i] == 0x30)
{
// It may be a WPA 2 IE.
if (in_ie[i+1] >= 8)
{
// Looking good..
if ((in_ie[i+2] == 0x01) && (in_ie[i+3] == 0x00))
{
if (memcmp(&in_ie[i+4], &wpa2oui, 3) == 0)
{
done = TRUE;
}
}
}
}
if (done == FALSE) i+=(unsigned char)(in_ie[i+1]+2);
}
if (done == FALSE)
{
// If we are scanning, then not finding an IE is no big deal. Otherwise, it is
// probably an error worth reporting.
if (TEST_FLAG(wctx->flags, WIRELESS_SCANNING))
{
debug_printf(DEBUG_INT, "IE block didn't contain a valid WPA2 IE!\n");
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -