⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32unsecure.c

📁 IBE是一种非对称密码技术
💻 C
字号:
/* Copyright 2003-2006, Voltage Security, all rights reserved.
 */

#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "vsdistrict.h"
#include "derhelp.h"
#include "oidlist.h"
#include "ibe.h"
#include "vtime.h"


#if VOLT_OS == VOLT_WINDOWS_32

#include <windows.h>
#include <tchar.h>
#include <wininet.h>
//#define _MT
#include <process.h>

/* This file contains an alternate implementation of DoHTTP. Changes to
 * the "true" version may need to be reflected here. It is less
 * efficient to have two copies of code, but because this is an
 * unsecure version, we'll live with the inconvenience.
 */

typedef struct
{
  HINTERNET hReq;
  int err;
  const char *header;
  const char *postData;
} sendRequestDataT;

typedef struct
{
  HINTERNET hReq;
  char *data;
  VoltLibCtx *libCtx;
} doReadDataT;

static unsigned __stdcall DoSendRequest (
   LPVOID pParam
);

static unsigned __stdcall DoReadData (
   LPVOID pParam
);

static unsigned __stdcall DoCheckNetwork (
   LPVOID pParam
);

static int ConfirmConnected (
   HWND uiOwner
);

static unsigned __stdcall DoSendRequest (
   LPVOID pParam
   )
{
  sendRequestDataT *data = (sendRequestDataT *)pParam;

  HttpSendRequestA (
    data->hReq, data->header,
    (data->header != (void *) 0 ? strlen(data->header) : 0), 
    (void *)data->postData,
    (data->postData != (void *) 0 ? strlen(data->postData) : 0));
  data->err = GetLastError();

  return 0;
}

static unsigned __stdcall DoReadData (
   LPVOID pParam
   )
{
  int max, len;
  ULONG num, read;
  int changed;
  VoltLibCtx *libCtx;

  doReadDataT *data = (doReadDataT *)pParam;
  libCtx = data->libCtx;

  max = 512;
  data->data = (char *)Z2Realloc (data->data, sizeof(char) * (max + 1));
  len = 0;

  num = 1;
  while (num > 0)
  {
    InternetQueryDataAvailable (data->hReq, &num, 0, 0);
    changed = 0;
    while ((ULONG)len + num > (ULONG) max)
    {
      max *= 2;
      changed = 1;
    }
    if (changed == 1)
      data->data = (char *)Z2Realloc (data->data, sizeof(char) * (max + 1));

    if (!InternetReadFile (data->hReq, data->data + len, num, &read))
    {
      Z2Free(data->data);
      data->data = (char *)0;
      return -1;
    }

    len += read;
  }

  (data->data)[len] = 0;

  return 0;
}

static unsigned __stdcall DoCheckNetwork( LPVOID pParam )
{
  return (0);
}

static int ConfirmConnected (
   HWND uiOwner
   )
{
  return (0);
}

int UnsecureDoHTTP (
   VtLibCtx libraryCtx,
   char **response,
   int *responseCode,   
   const unsigned char *url,
   const char *postData,
   int allowBadCert,
   unsigned char *trustStore,
   void *appData
   )
{
  HINTERNET hInt, hCon, hReq;
  int ret, tries, err , opt;
  unsigned long len, size;
  char header[128];
  char *headerPtr;
  unsigned int threadID;
  HANDLE hThread;
  sendRequestDataT *reqData;
  doReadDataT *readData = (doReadDataT *)0;
  HWND uiOwner;
  char safeHost[512];
  char safeURL[512];
  char *relative_url = NULL;
  char *hostName = NULL;
  unsigned char *parsedURL = (unsigned char *)0;
  URL_COMPONENTSA URLparts ;
  /* HTTPS is the default
  */
  INTERNET_PORT serverPort = INTERNET_DEFAULT_HTTPS_PORT;
  VoltLibCtx *libCtx = (VoltLibCtx *)libraryCtx;  

  if (appData != (void *) 0)
    uiOwner = (HWND)appData;
  else
    uiOwner = 0;

  /* First parse the URL to get the protocol, server and
  *  relative resource locations. Following determines what values
  *  are extracted from the URL. 
  */
  URLparts.dwStructSize = sizeof(URLparts);
  URLparts.dwSchemeLength    = 1;
  URLparts.dwHostNameLength  = 1;
  URLparts.dwUserNameLength  = 1;
  URLparts.dwPasswordLength  = 1;
  URLparts.dwUrlPathLength   = 1;
  URLparts.dwExtraInfoLength = 1;

  /* Initialize the values to NULL. These will be filled when 
  *  InternetCrackUrl function is called.
  */
  URLparts.lpszScheme     = NULL;
  URLparts.lpszHostName   = NULL;
  URLparts.lpszUserName   = NULL;
  URLparts.lpszPassword   = NULL;
  URLparts.lpszUrlPath    = NULL;
  URLparts.lpszExtraInfo  = NULL;

  if (!InternetCrackUrlA (url, 0, 0, &URLparts) )
  {
    ret = GetLastError();
    goto end;
  }

  /* Allocate the memory to hold the parsed info
  */
  parsedURL = (unsigned char *)Z2Malloc (
    URLparts.dwHostNameLength + URLparts.dwUrlPathLength + 2,
    0);
  if (parsedURL == (unsigned char *)0 )
  {
    ret = VT_ERROR_MEMORY;
    goto end;
  }

  hostName = parsedURL ;
  relative_url = parsedURL + URLparts.dwHostNameLength + 1;

  Z2Memcpy (hostName, URLparts.lpszHostName, URLparts.dwHostNameLength);
  hostName [URLparts.dwHostNameLength]=0 ;
  Z2Memcpy (relative_url , URLparts.lpszUrlPath, URLparts.dwUrlPathLength);
  relative_url[URLparts.dwUrlPathLength] = 0;

  /* Canonicalize the URLs just in case they have unsafe chars
  */
  len = sizeof (safeHost);
  if (!InternetCanonicalizeUrlA (hostName, safeHost, &len, 0))
  {
    ret = GetLastError();
    goto end;
  }
  len = sizeof (safeURL);
  if (!InternetCanonicalizeUrlA (relative_url, safeURL, &len, 0))
  {
    ret = GetLastError();
    goto end;
  }

  /* Set the type of connection and Escape both 
  *  hostname and relative path.  
  */
  if (URLparts.nPort == 80)
    serverPort = INTERNET_DEFAULT_HTTP_PORT;  

  ret = ConfirmConnected (uiOwner);
  if (ret != 0)
    goto end;

  hInt = InternetOpenA (
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)",
    INTERNET_OPEN_TYPE_PRECONFIG, (void *) 0, (void *) 0, 0);
  if (!hInt)
  {
    ret = GetLastError ();
    goto end;
  }

  hCon = InternetConnectA (
    hInt, safeHost, serverPort, (void *) 0, (void *) 0,
    INTERNET_SERVICE_HTTP, 0, 0);
  if (!hCon)
  {    
    ret = GetLastError ();
    goto end;
  }

  if (postData != (void *) 0)
  {
    sprintf (header, "Content-Type: application/x-www-form-urlencoded");
    headerPtr = header;
  }
  else
  {
    headerPtr = (void *) 0;
  }

  tries = 0;

reopen:

  if (postData != (void *) 0)
    hReq = HttpOpenRequestA (
      hCon, "POST", safeURL, (void *) 0, (void *) 0, (void *) 0, 
      INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE, 0);
  else
    hReq = HttpOpenRequestA (
      hCon, "GET", safeURL, (void *) 0, (void *) 0, (void *) 0, 
      INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE, 0);
  if (!hReq)
  {
    ret = GetLastError ();
    goto end;    
  }

resend:
  reqData = (sendRequestDataT *)Z2Malloc (sizeof(sendRequestDataT), VOLT_MEMORY_SENSITIVE);
  if (reqData == (sendRequestDataT *)0 )
  {
    ret = VT_ERROR_MEMORY;
    goto end;
  }    
  reqData->hReq = hReq;
  reqData->postData = postData;
  reqData->header = headerPtr;

  hThread = (HANDLE)CreateThread (
    (void *) 0, 0, DoSendRequest, reqData, 0, &threadID);
  if (hThread == (void *) 0)
  {
    ret = GetLastError ();
    goto end;    
  }

  if (WaitForSingleObject (hThread, 30000) != WAIT_OBJECT_0)
  {
    TerminateThread (hThread, 0);
    CloseHandle (hThread);
    ret = ERR_HTTP_TIMEOUT_SEND_REQUEST;  
    goto end;
  }
  CloseHandle (hThread);

  err = reqData->err;  
  if (reqData != (sendRequestDataT *)0 )
    Z2Free (reqData);

  /* This part needs (a lot of) explanation:
   * There are two cases in which we need to call InternetErrorDlg : bad
   * auth and other (e.g. cert probs)
   * 1) In the bad auth case, if we try to just go back to the
   *    HttpSendRequest and use the same handle, wininet for some reason
   *    doesn't re-POST the data.  So we need to close the handle, and
   *    start again from HttpOpenRequest.  Fortunately, Windows caches the
   *    credentials on the machine, not in hReq, so this works.
   * 2) Unfortunately, for the other case, e.g. invalid CA, if the user
   *    hits OK, we still need to go retry, but wininet caches the user's
   *    OK selection in hReq, so if we close it and reopen, it keeps
   *    asking the user over and over again.
   * Fortunately for us, HttpSendRequest returns two different things in
   * case 1 and case 2.  In case 1, it returns TRUE, so for that case we
   * start over at HttpOpenRequest if InternetErrorDlg returns
   * ERROR_INTERNET_FORCE_RETRY (which basically means the user entered
   * their pass).  In case 2, it returns FALSE, so we just go back to
   * HttpSendRequest if InternetErrorDlg retursn ERROR_SUCCESS.
   *
   * Clearly, WinInet is very broken.  I believe all of the above to be
   * true, but it's very possible that there are cases I didn't account
   * for.  Time will tell.
   */

  if (tries < 3)
  {
    /* Last one is OCSP failure
     */
    if ( (err == ERROR_INTERNET_INVALID_CA) ||
         (err == ERROR_INTERNET_SEC_CERT_CN_INVALID) ||
         (err == ERROR_INTERNET_SEC_CERT_DATE_INVALID) || 
         (err == ERROR_INTERNET_SECURITY_CHANNEL_ERROR) )
    {
      if (allowBadCert == 1)
      {
        size = sizeof(opt);
        InternetQueryOption (
          hReq, INTERNET_OPTION_SECURITY_FLAGS, &opt, &size);
        opt |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
        opt |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
        opt |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
        opt |= SECURITY_FLAG_IGNORE_REVOCATION;

        ret = InternetSetOption (
          hReq, INTERNET_OPTION_SECURITY_FLAGS, &opt, sizeof(opt));

        goto resend;
      }
      else
      {
        ret = err;
        goto end;
      }
    }

    //gDummyWindow->SetWindowPos (
    //  HWND_TOPMOST, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE);
    ret = InternetErrorDlg (
      uiOwner, hReq, err,
      FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
      FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
      FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, (void *) 0);

    if (ret == ERROR_INTERNET_FORCE_RETRY)
    {
      tries++;
      InternetCloseHandle (hReq);
      goto reopen;
    }
    else if (ret == ERROR_SUCCESS &&
      err == ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR)
    {
      goto resend;
    }
  }

  /* I think I should probably do this here, but this is too big a change
   * to put in right now. Without this, we get invalid response received
   * on some errors rather than can't connect to server. One problem with
   * just doing this is that I think in auth failed cases, err will be
   * != 0, but we want to do the HttpQueryInfo and get back the
   * responseCode. One other option would be to check if
   * *responseCode ==0 after the HttpQueryInfo, this might be safer.
   */
//  if (err != 0)
//    return -1;

  len = sizeof (int);
  if (!HttpQueryInfo (
    hReq, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, responseCode,
    &len, (void*) 0))
  {
    ret = GetLastError ();
    goto end;
  }

  if (*responseCode == 0)
  {
    /* We get here on connection errors, and err will actually contain
     * the error we want.
     */
    ret = err;
    goto end;
  }

  readData = (doReadDataT *)Z2Malloc (
    sizeof(doReadDataT), VOLT_MEMORY_SENSITIVE);
  if (readData == (doReadDataT *) 0 )
  {
    ret = VT_ERROR_MEMORY;
    goto end;
  }
  readData->data = (char *)0;
  readData->hReq = hReq;
  readData->libCtx = libCtx;

  hThread = (HANDLE)CreateThread (
    (void*) 0, 0, DoReadData, readData, 0, &threadID);
  if (hThread == (void*) 0)
  {    
    ret = GetLastError ();
    goto end;
  }

  if (WaitForSingleObject (hThread, 30000) != WAIT_OBJECT_0)
  {
    TerminateThread (hThread, 0);
    CloseHandle (hThread);    
    ret = ERR_HTTP_TIMEOUT_READ_DATA;
    goto end;
  }

  CloseHandle (hThread);
  *response = readData->data;  

  ret = 0;

end:
  if (ret != 0)
  {
    if (readData != (doReadDataT *)0 )
    {
      if (readData->data != (char *)0)
        Z2Free (readData->data);
    }
  }

  if (parsedURL != (unsigned char *)0 )
    Z2Free (parsedURL);
  if (readData != (doReadDataT *)0 )
    Z2Free (readData);  
  InternetCloseHandle (hReq);
  InternetCloseHandle (hCon);
  InternetCloseHandle (hInt);
  // Flush any existing credentials
  //InternetSetOption ((void *) 0, INTERNET_OPTION_END_BROWSER_SESSION, (void *) 0, 0L);

  return ret;
}

#endif  /* VOLT_OS == VOLT_WINDOWS_32 */

⌨️ 快捷键说明

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