cardif_windows.c

来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 2,063 行 · 第 1/5 页

C
2,063
字号
 * \retval HANDLE a handle to the device, or INVALID_HANDLE_VALUE on error.
 **/
HANDLE GetHandle(char *devName)
{
		HANDLE retHandle = INVALID_HANDLE_VALUE;
		LPVOID lpMsgBuf = NULL;
		int result = 0;
		DWORD BytesWritten = 0;

		if (devName == NULL)
		{
			debug_printf(DEBUG_NORMAL, "Invalid device name in %s()!\n", __FUNCTION__);
			return INVALID_HANDLE_VALUE;
		}

		retHandle = CreateFile(devName, 
							   FILE_READ_DATA | FILE_WRITE_DATA,
							   FILE_SHARE_READ | FILE_SHARE_WRITE,
							   NULL, OPEN_EXISTING, 
							   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
							   INVALID_HANDLE_VALUE);

		if (retHandle == INVALID_HANDLE_VALUE)
		{
			lpMsgBuf = GetLastErrorStr(GetLastError());

			fprintf(stderr, "Couldn't establish a connection to the Open1X "
				"protocol service!\n  Error was : %s", lpMsgBuf);

			LocalFree(lpMsgBuf);
		}

		if (devioctl7(retHandle, IOCTL_NDISPROT_BIND_WAIT, NULL, 0,
			NULL, 0, &BytesWritten) != 0)
		{
			debug_printf(DEBUG_NORMAL, "Device handle bind wait failed.  Returned %d.  We will try to continue anyway.\n", result);
		}

		return retHandle;
}

// This function is found in mschapv2.c, but we need it here, so
// prototype it, and let the linker figure it out. ;)
char *to_unicode(char *);

/**
 *  \brief Bind an NDIS device to a specific device handle.  This allows
 *         us to perform read/write operations on the device.  (Basically,
 *         it lets us send and receive frames.)
 *
 * @param[in] devHandle   A handle created by a call to \ref GetHandle().  After this
 *                        call, the handle will refer to a specific interface, instead
 *                        of the "file" that connects to the protocol handler.
 *
 * @param[in] devName   A non-unicode string that identifies the device that we want
 *                      to bind to.
 *
 * \retval FALSE on error
 * \retval TRUE on success
 **/
int BindNDISDevice(HANDLE devHandle, char *devName)
{
	WCHAR *uniDevName = NULL;
	int NameLen = 0;
	DWORD retbytes = 0;
	DWORD result = 0;

	NameLen = strlen(devName);
	uniDevName = (WCHAR *)to_unicode(devName);

	debug_printf(DEBUG_INT, "Trying to bind to network interface : %ws\n",
			uniDevName);

	result = devioctl(devHandle, IOCTL_NDISPROT_OPEN_DEVICE,
					  uniDevName, NameLen * 2, NULL, 0, &retbytes);

	FREE(uniDevName);

	if ((result != WAIT_OBJECT_0) && (result != WAIT_IO_COMPLETION))
    {
		return FALSE;
	}

	return TRUE;
}

/**
 *  \brief Determine if the named interface is wireless.
 *
 * @param[in] intname   A non-unicode string that identifies the device that we
 *                      want to check.
 *
 * \retval -1 on error
 * \retval FALSE if interface is no wireless
 * \retval TRUE if interface is wireless
 **/
char is_wireless(char *intname)
{
  int retVal;
  DWORD result, *state;
  UCHAR QueryBuffer[sizeof(NDIS_OID) + 4000];
  DWORD BytesReturned;
  PNDISPROT_QUERY_OID pQueryOid;
  LPVOID lpMsgBuf;
  HANDLE temphandle = INVALID_HANDLE_VALUE;

	temphandle = GetHandle((char *)&NdisDev);

	if (temphandle == INVALID_HANDLE_VALUE)
		return -1;

	if (BindNDISDevice(temphandle, intname) == 0)
	{
		ipc_events_error(NULL, IPC_EVENT_ERROR_FAILED_TO_BIND, intname);

		lpMsgBuf = GetLastErrorStr(GetLastError());
		debug_printf(DEBUG_NORMAL, "Failed to bind interface %s to device "
			"handle.  Error was : %s\n", intname, lpMsgBuf);

		LocalFree(lpMsgBuf);
		CloseHandle(temphandle);
		return -1;
	}

  pQueryOid = (PNDISPROT_QUERY_OID)&QueryBuffer[0];
  pQueryOid->Oid = OID_GEN_PHYSICAL_MEDIUM;

  result = devioctl(temphandle, 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)
		{
			// The IOCTL isn't supported.
			debug_printf(DEBUG_INT, "The IOCTL to determine if this interface is wireless "
					"does not appear to be implemented in this driver!  Assuming it is "
					"wired.\n");
			CloseHandle(temphandle);
			return FALSE;
		}

        debug_printf(DEBUG_NORMAL, "Get physical media type IOCTL failed on interface '%s'.\n", intname);

		// Assume the interface is wired, so we don't try to do anything fancy with it.
        return FALSE;
    }

  state = (DWORD *)&pQueryOid->Data[0];
  result = (*state);

#if 0
  if (result == NdisPhysicalMediumBluetooth)
  {
	  debug_printf(DEBUG_INT, "Interface appears to be BLUETOOTH!\n");
	  CloseHandle(temphandle);
	  return FALSE;
  }
#endif

  if ((result == NdisPhysicalMediumWirelessLan) || (result == NdisPhysicalMediumNative802_11))
    {
	  debug_printf(DEBUG_INT, "Interface appears to be wireless!\n");
	  CloseHandle(temphandle);
      return TRUE;
    } 
	
  debug_printf(DEBUG_INT, "Interface is wired, or unknown.\n");
  CloseHandle(temphandle);
  return FALSE;
}

/**
 *  \brief Obtain the hardware (MAC) address for the given interface.
 *
 * @param[in] devHandle   A handle for an interface that has been bound using the
 *                        BindNDISDevice() call.
 *
 * \retval NULL on error
 * \retval ptr to the MAC address for the interface specified by \ref devHandle.
 **/
char *getmac(HANDLE devHandle)
{
  PNDISPROT_QUERY_OID    pOidData = NULL;
  CHAR *pStr = NULL;
  char *mac = NULL;
  DWORD bytesreturned = 0, result = 0;

  pStr = Malloc(sizeof(NDISPROT_QUERY_OID)+6);
  if (pStr == NULL) 
  {
	  debug_printf(DEBUG_NORMAL, "Couldn't allocate memory!\n");
	  ipc_events_error(NULL, IPC_EVENT_ERROR_MALLOC, __FUNCTION__);
	  return NULL;
  }

  pOidData = (PNDISPROT_QUERY_OID) pStr;
  pOidData->Oid = OID_802_3_CURRENT_ADDRESS;
  
  result = devioctl(devHandle, IOCTL_NDISPROT_QUERY_OID_VALUE,
					pStr, (sizeof(NDISPROT_QUERY_OID)+6), 
					pStr, (sizeof(NDISPROT_QUERY_OID)+6),
					&bytesreturned);

  if ((result != WAIT_OBJECT_0) && (result != WAIT_IO_COMPLETION))
  {
	  debug_printf(DEBUG_NORMAL, "Unable to request the MAC address for an interface!\n");
	  return NULL;
  }

  mac = Malloc(6);
  if (mac == NULL)
  {
	  debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store interface MAC address!\n");
	  return NULL;
  }

  memcpy(mac, pOidData->Data, 6);
  
  debug_printf(DEBUG_INT, "MAC : %02X:%02X:%02X:%02X:%02X:%02X\n", pOidData->Data[0], pOidData->Data[1], pOidData->Data[2],
				pOidData->Data[3], pOidData->Data[4], pOidData->Data[5]);

  FREE(pStr);

  return mac;
}

/**
 * \brief Determine if the interface pointed to by "ctx" is wireless.
 *
 * @param[in] ctx   A pointer to the context that contains the interface to check
 *                  for wirelessness.
 *
 * \retval XEMALLOC on memory allocation error
 * \retval TRUE on success
 * \retval FALSE on failure
 **/
int cardif_int_is_wireless(context *ctx)
{
  int retVal = 0;
  DWORD result = 0, *state = NULL;
  struct win_sock_data *sockData = NULL;
  UCHAR QueryBuffer[sizeof(NDIS_OID) + 4];
  DWORD BytesReturned = 0;
  PNDISPROT_QUERY_OID pQueryOid = NULL;

  if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
    return XEMALLOC;

  sockData = ctx->sockData;

  if (!xsup_assert((sockData != NULL), "sockData != NULL", FALSE))
    return XEMALLOC;

  pQueryOid = (PNDISPROT_QUERY_OID)&QueryBuffer[0];
  pQueryOid->Oid = OID_GEN_PHYSICAL_MEDIUM;

  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)
		{
			// The IOCTL isn't supported.
			debug_printf(DEBUG_INT, "The IOCTL to determine if this interface is wireless "
					"does not appear to be implemented in this driver!  Assuming it is "
					"wired.\n");
			return FALSE;
		}

		debug_printf(DEBUG_NORMAL, "Get physical media type IOCTL failed on interface '%s'.\n", ctx->desc);

		// Assume the interface is wired, so we don't try to do anything fancy with it.
        return FALSE;
    }

  state = (DWORD *)&pQueryOid->Data[0];
  result = (*state);

  if ((result == NdisPhysicalMediumWirelessLan) || (result == NdisPhysicalMediumNative802_11))
    {
	  debug_printf(DEBUG_INT, "Interface appears to be wireless!\n");
      return TRUE;
    } 
	
  debug_printf(DEBUG_INT, "Interface is wired, or unknown.\n");
  return FALSE;
}

/**
 * \brief Clear all keys, and accept unencrypted traffic again.
 *
 * @param[in] ctx   The context that contains the interface that we want to 
 *                  reset.
 **/
void cardif_windows_clear_keys(context *ctx)
{
	debug_printf(DEBUG_INT, "Allowing unencrypted frames again.\n");
	cardif_drop_unencrypted(ctx, 0);
 
	// In Windows, setting the card to infrastructure mode will automatically clear
	// all of the keys in the key cache.  This is more efficient than making an IOCTL
	// for every key we might have, and has the added bonus that it doesn't cause
	// bogus error messages when using the Intel 3945 driver! ;)

	cardif_windows_set_infra_mode(ctx);
}

/**
 * \brief Determine if an interface is currently associated. 
 *
 * @param[in] ctx   The context that contains the interface that we want to check
 *                  the association state of.
 *
 * \note If this call is made against an interface that isn't wireless, the result
 *       is undefined.  (Most likely, it will return IS_UNASSOCIATED.)
 *
 * \retval IS_ASSOCIATED if the interface is associated
 * \retval IS_UNASSOCIATED if the interface is not associated
 **/
int cardif_check_associated(context *ctx)
{
	UCHAR bssid_dest[6];

	if (cardif_windows_wireless_get_bssid(ctx, bssid_dest) == XENONE)
		return IS_ASSOCIATED;

	return IS_UNASSOCIATED;
}

/**
 * \brief We have a frame received event.  So handle it.
 *
 * @param[in] ctx   The context that contains the interface that received a frame.
 * @param[in] devHandle   The device handle for the interface that received a frame.
 *
 * \retval XENONE on success
 **/
int cardif_handle_frame(context *ctx, HANDLE devHandle)
{
	if (cardif_getframe(ctx) != XENOFRAMES)
	{
		if (ctx->intType != ETH_802_11_INT)
			eapol_execute(ctx);
	}

	return XENONE;
}

/**
 * \brief If there is a mismatch between the Windows description and the 
 *        one in our configuration file, we need to go through and rename stuff
 *        in memory.
 *
 * \note  All of the changes that happen in this function *ONLY* happen in memory.
 *        However, if a request to write the configuration file is issued the changed
 *        connection and interface configuration data will be committed to disk!!
 *
 * @param[in] confdesc   The description of the interface in the configuration.
 * @param[in] windesc   The description that Windows is providing us.
 **/
void cardif_windows_fixup_config(char *confdesc, char *windesc)
{
	struct config_connection *confcon = NULL;
	struct xsup_interfaces *confints = NULL;
	char *myconfdesc = NULL;

	confints = config_get_config_ints();
	if (confints == NULL)
	{
		// This should be virtually impossible!  (Unless the caller is being *REALLY* stupid! ;)
		debug_printf(DEBUG_NORMAL, "There was a request to fix some interface/connection issues, but there are no interfaces defined!?\n");
		return;
	}

	while ((confints != NULL) && (strcmp(confints->description, confdesc) != 0))
		confints = confints->next;  // This is okay because we don't want to free the pointer as it points to the master structure. ;)

	if (confints == NULL)
	{
		// This should also be virtually impossible!
		debug_printf(DEBUG_NORMAL, "There was a request to fix some interface/connection issues, but the interface that triggered it isn't in configuration memory!?\n");
		return;
	}

	// Make a copy of the "wrong" description, since we will probably overwrite it in the next set of commands. ;)
	myconfdesc = _strdup(confdesc);

	FREE(confints->description);
	confints->description = _strdup(windesc);  // Set the new interface name.  If a write configuration request is made, this *WILL* get written to the config!!

	confcon = config_get_connections();
	if (confcon == NULL)
	{
		debug_printf(DEBUG_NORMAL, "There are no connections defined to update.\n");
		FREE(myconfdesc);
		return;
	}

	while (confcon != NULL)
	{
		if (strcmp(confcon->device, myconfdesc) == 0)
		{
			// We need to rewrite this.
			FREE(confcon->device);
			confcon->device = _strdup(windesc);
		}

		confcon = confcon->next;
	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?