Esempio n. 1
1
static int apply_default_credentials(HINTERNET request, int mechanisms)
{
	/* Either the caller explicitly requested that default credentials be passed,
	 * or our fallback credential callback was invoked and checked that the target
	 * URI was in the appropriate Internet Explorer security zone. By setting this
	 * flag, we guarantee that the credentials are delivered by WinHTTP. The default
	 * is "medium" which applies to the intranet and sounds like it would correspond
	 * to Internet Explorer security zones, but in fact does not. */
	DWORD data = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
	DWORD native_scheme = 0;

	if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) != 0)
		native_scheme |= WINHTTP_AUTH_SCHEME_NTLM;

	if ((mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE) != 0)
		native_scheme |= WINHTTP_AUTH_SCHEME_NEGOTIATE;

	if (!native_scheme) {
		giterr_set(GITERR_NET, "invalid authentication scheme");
		return -1;
	}

	if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &data, sizeof(DWORD)))
		return -1;

	if (!WinHttpSetCredentials(request, WINHTTP_AUTH_TARGET_SERVER, native_scheme, NULL, NULL, NULL))
		return -1;

	return 0;
}
Esempio n. 2
1
// POST request to URL
void WinHttpIO::post(HttpReq* req, const char* data, unsigned len)
{
    LOG_debug << "POST target URL: " << req->posturl << " chunked: " << req->chunked;

    if (req->binary)
    {
        LOG_debug << "[sending " << (data ? len : req->out->size()) << " bytes of raw data]";
    }
    else
    {
        LOG_debug << "Sending: " << *req->out;
    }

    WinHttpContext* httpctx;

    WCHAR szURL[8192];
    WCHAR szHost[256];
    URL_COMPONENTS urlComp = { sizeof urlComp };

    urlComp.lpszHostName = szHost;
    urlComp.dwHostNameLength = sizeof szHost / sizeof *szHost;
    urlComp.dwUrlPathLength = (DWORD)-1;
    urlComp.dwSchemeLength = (DWORD)-1;

    httpctx = new WinHttpContext;

    httpctx->httpio = this;
    httpctx->req = req;
    httpctx->gzip = false;

    req->httpiohandle = (void*)httpctx;

    if (MultiByteToWideChar(CP_UTF8, 0, req->posturl.c_str(), -1, szURL,
                            sizeof szURL / sizeof *szURL)
     && WinHttpCrackUrl(szURL, 0, 0, &urlComp))
    {
        if ((httpctx->hConnect = WinHttpConnect(hSession, szHost, urlComp.nPort, 0)))
        {
            httpctx->hRequest = WinHttpOpenRequest(httpctx->hConnect, L"POST",
                                                   urlComp.lpszUrlPath, NULL,
                                                   WINHTTP_NO_REFERER,
                                                   WINHTTP_DEFAULT_ACCEPT_TYPES,
                                                   (urlComp.nScheme == INTERNET_SCHEME_HTTPS)
                                                   ? WINHTTP_FLAG_SECURE
                                                   : 0);

            if (httpctx->hRequest)
            {
                if (proxyUsername.size())
                {
                    LOG_verbose << "Setting proxy credentials";

                    WinHttpSetCredentials(httpctx->hRequest, WINHTTP_AUTH_TARGET_PROXY,
                                          WINHTTP_AUTH_SCHEME_BASIC,
                                          (LPWSTR)proxyUsername.data(), (LPWSTR)proxyPassword.data(), NULL);
                }

                WinHttpSetTimeouts(httpctx->hRequest, 58000, 58000, 0, 0);

                WinHttpSetStatusCallback(httpctx->hRequest, asynccallback,
                                         WINHTTP_CALLBACK_FLAG_DATA_AVAILABLE
                                       | WINHTTP_CALLBACK_FLAG_READ_COMPLETE
                                       | WINHTTP_CALLBACK_FLAG_HEADERS_AVAILABLE
                                       | WINHTTP_CALLBACK_FLAG_REQUEST_ERROR
                                       | WINHTTP_CALLBACK_FLAG_SECURE_FAILURE
                                       | WINHTTP_CALLBACK_FLAG_SENDREQUEST_COMPLETE
                                       | WINHTTP_CALLBACK_FLAG_SEND_REQUEST
                                       | WINHTTP_CALLBACK_FLAG_WRITE_COMPLETE
                                       | WINHTTP_CALLBACK_FLAG_HANDLES,
                                         0);

                LPCWSTR pwszHeaders = req->type == REQ_JSON || !req->buf
                                    ? L"Content-Type: application/json\r\nAccept-Encoding: gzip"
                                    : L"Content-Type: application/octet-stream";

                // data is sent in HTTP_POST_CHUNK_SIZE instalments to ensure
                // semi-smooth UI progress info
                if (req->chunkedout.size())
                {
                    req->outbuf.append(req->chunkedout);
                    req->chunkedout.clear();
                }

                req->chunked = 0;

                httpctx->postlen = data ? len : req->out->size();
                httpctx->postdata = data ? data : req->out->data();

                if (urlComp.nPort == 80)
                {
                    LOG_verbose << "HTTP connection";

                    // HTTP connection: send a chunk of data immediately
                    httpctx->postpos = (httpctx->postlen < HTTP_POST_CHUNK_SIZE)
                                      ? httpctx->postlen
                                      : HTTP_POST_CHUNK_SIZE;
                }
                else
                {
                    LOG_verbose << "HTTPS connection";

                    // HTTPS connection: ignore certificate errors, send no data yet
                    DWORD flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID
                                | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
                                | SECURITY_FLAG_IGNORE_UNKNOWN_CA;

                    WinHttpSetOption(httpctx->hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof flags);

                    httpctx->postpos = 0;
                }

                if (WinHttpSendRequest(httpctx->hRequest, pwszHeaders,
                                       wcslen(pwszHeaders),
                                       (LPVOID)httpctx->postdata,
                                       httpctx->postpos,
                                       httpctx->postlen,
                                       (DWORD_PTR)httpctx))
                {
                    LOG_verbose << "Request sent";
                    req->status = REQ_INFLIGHT;
                    return;
                }

                LOG_err << "Error sending request: " << req->posturl << "  Code: " << GetLastError();
            }
            else
            {
                LOG_err << "Error opening request: " << req->posturl << "  Code: " << GetLastError();
            }
        }
        else
        {
            LOG_err << "Error connecting to " << req->posturl << "  Code: " << GetLastError();
            httpctx->hRequest = NULL;
        }
    }
    else
    {
        LOG_err << "Error parsing POST URL: " << req->posturl << "  Code: " << GetLastError();
        httpctx->hRequest = NULL;
        httpctx->hConnect = NULL;
    }

    LOG_err << "Request failed";
    req->status = REQ_FAILURE;
}
Esempio n. 3
0
void WinHttpIO::setproxy(Proxy* proxy)
{
    Proxy* autoProxy = NULL;

    proxyUsername.clear();
    proxyPassword.clear();

    if (proxy->getProxyType() == Proxy::AUTO)
    {
        autoProxy = getautoproxy();
        proxy = autoProxy;
    }

    if (proxy->getProxyType() == Proxy::NONE)
    {
        WINHTTP_PROXY_INFO proxyInfo;
        proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
        proxyInfo.lpszProxy = WINHTTP_NO_PROXY_NAME;
        proxyInfo.lpszProxyBypass = WINHTTP_NO_PROXY_BYPASS;
        WinHttpSetOption(hSession, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo));
        LOG_info << "Proxy disabled";
    }
    else if (proxy->getProxyType() == Proxy::CUSTOM)
    {
        string proxyURL = proxy->getProxyURL();
        proxyURL.append("", 1);
        WINHTTP_PROXY_INFO proxyInfo;
        proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
        proxyInfo.lpszProxy = (LPWSTR)proxyURL.data();
        proxyInfo.lpszProxyBypass = WINHTTP_NO_PROXY_BYPASS;
        WinHttpSetOption(hSession, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo));

        LOG_info << "Proxy enabled";
        if (proxy->credentialsNeeded())
        {
            proxyUsername = proxy->getUsername();

            if (proxyUsername.size())
            {
                proxyUsername.append("", 1);
            }

            proxyPassword = proxy->getPassword();

            if(proxyPassword.size())
            {
                proxyPassword.append("", 1);
            }

            LOG_info << "Proxy requires authentication";
        }
    }

    delete autoProxy;
}
Esempio n. 4
0
// HttpIO implementation using WinHTTP
WinHttpIO::WinHttpIO()
{
    // create the session handle using the default settings.
	hSession = WinHttpOpen(L"MEGA Client Access Engine/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
	ATLASSERT(hSession);

	DWORD receiveTimeOut = 3 * 60 * 1000;	// 3min
	ATLVERIFY(WinHttpSetOption(hSession, WINHTTP_OPTION_RECEIVE_TIMEOUT, &receiveTimeOut, sizeof(receiveTimeOut)));

	completion = 0;
}
Esempio n. 5
0
void SocialWinHttpSetup(WCHAR *DestURL)
{
	WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ProxyConfig;
	WINHTTP_PROXY_INFO ProxyInfoTemp, ProxyInfo;
	WINHTTP_AUTOPROXY_OPTIONS OptPAC;
	DWORD dwOptions = SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;

	ZeroMemory(&ProxyInfo, sizeof(ProxyInfo));
	ZeroMemory(&ProxyConfig, sizeof(ProxyConfig));

	// Crea una sessione per winhttp.
    g_http_social_session = FNC(WinHttpOpen)( L"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2", WINHTTP_ACCESS_TYPE_NO_PROXY, 0, WINHTTP_NO_PROXY_BYPASS, 0);

	// Cerca nel registry le configurazioni del proxy
	if (g_http_social_session && FNC(WinHttpGetIEProxyConfigForCurrentUser)(&ProxyConfig)) {
		if (ProxyConfig.lpszProxy) {
			// Proxy specificato
			ProxyInfo.lpszProxy = ProxyConfig.lpszProxy;
			ProxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
			ProxyInfo.lpszProxyBypass = NULL;
		}

		if (ProxyConfig.lpszAutoConfigUrl) {
			// Script proxy pac
			OptPAC.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
			OptPAC.lpszAutoConfigUrl = ProxyConfig.lpszAutoConfigUrl;
			OptPAC.dwAutoDetectFlags = 0;
			OptPAC.fAutoLogonIfChallenged = TRUE;
			OptPAC.lpvReserved = 0;
			OptPAC.dwReserved = 0;

			if (FNC(WinHttpGetProxyForUrl)(g_http_social_session ,DestURL, &OptPAC, &ProxyInfoTemp))
				memcpy(&ProxyInfo, &ProxyInfoTemp, sizeof(ProxyInfo));
		}

		if (ProxyConfig.fAutoDetect) {
			// Autodetect proxy
			OptPAC.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
			OptPAC.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
			OptPAC.fAutoLogonIfChallenged = TRUE;
			OptPAC.lpszAutoConfigUrl = NULL;
			OptPAC.lpvReserved = 0;
			OptPAC.dwReserved = 0;

			if (FNC(WinHttpGetProxyForUrl)(g_http_social_session ,DestURL, &OptPAC, &ProxyInfoTemp))
				memcpy(&ProxyInfo, &ProxyInfoTemp, sizeof(ProxyInfo));
		}

		if (ProxyInfo.lpszProxy) 		
			FNC(WinHttpSetOption)(g_http_social_session, WINHTTP_OPTION_PROXY, &ProxyInfo, sizeof(ProxyInfo));
	}
	
	 WinHttpSetOption( g_http_social_session, WINHTTP_OPTION_SECURITY_FLAGS, &dwOptions, sizeof (DWORD) ); 
}
Esempio n. 6
0
HINTERNET WinHTTPSession::setup(const Request & request, LPCWSTR method) {
	
	platform::WideString wurl(request.url());
	
	URL_COMPONENTS url;
	ZeroMemory(&url, sizeof(url));
	url.dwStructSize = sizeof(url);
	url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = DWORD(-1);
	if(WinHttpCrackUrl(wurl, 0, 0, &url) != TRUE) {
		throw new Response("Invalid URL: \"" + request.url() + "\"");
	}
	
	DWORD flags = 0;
	if(url.nScheme == INTERNET_SCHEME_HTTPS) {
		flags |= WINHTTP_FLAG_SECURE;
	} else if(url.nScheme != INTERNET_SCHEME_HTTP) {
		throw new Response("Unsupported protocol");
	}
	
	if(m_scheme != url.nScheme || m_port != url.nPort
	   || m_host.compare(0, m_host.length(), url.lpszHostName, url.dwHostNameLength) != 0) {
		if(m_connection) {
			WinHttpCloseHandle(m_connection);
		}
		m_scheme = url.nScheme;
		m_host.assign(url.lpszHostName, url.dwHostNameLength);
		m_port = url.nPort;
		m_connection = WinHttpConnect(m_session, m_host.c_str(), m_port, 0);
	}
	if(!m_connection) {
		throw new Response("Could not create connection object: " + errorString());
	}
	
	LPCWSTR resource = url.dwUrlPathLength ? url.lpszUrlPath : L"/";
	
	LPCWSTR accept[] = { L"*/*", NULL };
	
	HINTERNET wrequest = WinHttpOpenRequest(m_connection, method, resource, NULL,
	                                        WINHTTP_NO_REFERER, accept, flags);
	if(!wrequest) {
		throw new Response("Could not create request object: " + errorString());
	}
	
	if(request.followRedirects()) {
		WinHttpSetStatusCallback(wrequest, statusCallback, WINHTTP_CALLBACK_FLAG_REDIRECT, 0);
	} else {
		ULONG disable = WINHTTP_DISABLE_REDIRECTS;
		WinHttpSetOption(wrequest, WINHTTP_OPTION_DISABLE_FEATURE, &disable, sizeof(disable));
	}
	
	return wrequest;
}
Esempio n. 7
0
static int apply_default_credentials(HINTERNET request)
{
	/* Either the caller explicitly requested that default credentials be passed,
	 * or our fallback credential callback was invoked and checked that the target
	 * URI was in the appropriate Internet Explorer security zone. By setting this
	 * flag, we guarantee that the credentials are delivered by WinHTTP. The default
	 * is "medium" which applies to the intranet and sounds like it would correspond
	 * to Internet Explorer security zones, but in fact does not. */
	DWORD data = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;

	if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &data, sizeof(DWORD)))
		return -1;

	return 0;
}
Esempio n. 8
0
static int apply_default_credentials(HINTERNET request)
{
	/* If we are explicitly asked to deliver default credentials, turn set
	 * the security level to low which will guarantee they are delivered.
	 * The default is "medium" which applies to the intranet and sounds
	 * like it would correspond to Internet Explorer security zones, but
	 * in fact does not.
	 */
	DWORD data = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;

	if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &data, sizeof(DWORD)))
		return -1;

	return 0;
}
Esempio n. 9
0
static void test_redirect( void )
{
    static const WCHAR codeweavers[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};

    HANDLE ses, con, req;
    DWORD size, status;
    BOOL ret;
    struct info info, *context = &info;

    info.test  = redirect_test;
    info.count = sizeof(redirect_test) / sizeof(redirect_test[0]);
    info.index = 0;
    info.wait = NULL;

    ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
    ok(ses != NULL, "failed to open session %u\n", GetLastError());

    WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );

    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_connect, __LINE__ );
    con = WinHttpConnect( ses, codeweavers, 0, 0 );
    ok(con != NULL, "failed to open a connection %u\n", GetLastError());

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );
    WinHttpCloseHandle( con );
    WinHttpCloseHandle( ses );
}
Esempio n. 10
0
static int send_request(winhttp_stream *s, size_t len, int ignore_length)
{
    int request_failed = 0, cert_valid = 1, error = 0;
    DWORD ignore_flags;

    if ((error = do_send_request(s, len, ignore_length)) < 0)
        request_failed = 1;

    if (request_failed) {
        if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) {
            giterr_set(GITERR_OS, "failed to send request");
            return -1;
        } else {
            cert_valid = 0;
        }
    }

    giterr_clear();
    if ((error = certificate_check(s, cert_valid)) < 0) {
        if (!giterr_last())
            giterr_set(GITERR_OS, "user cancelled certificate check");

        return error;
    }

    /* if neither the request nor the certificate check returned errors, we're done */
    if (!request_failed)
        return 0;

    ignore_flags =
        SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
        SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
        SECURITY_FLAG_IGNORE_UNKNOWN_CA;

    if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) {
        giterr_set(GITERR_OS, "failed to set security options");
        return -1;
    }

    if ((error = do_send_request(s, len, ignore_length)) < 0)
        giterr_set(GITERR_OS, "failed to send request");

    return error;
}
Esempio n. 11
0
void WinHttpIO::setuseragent(string* useragent)
{
    string wuseragent;

    wuseragent.resize((useragent->size() + 1) * sizeof(wchar_t));
    wuseragent.resize(sizeof(wchar_t)
                      * (MultiByteToWideChar(CP_UTF8, 0, useragent->c_str(),
                                              -1, (wchar_t*)wuseragent.data(),
                                              wuseragent.size() / sizeof(wchar_t) + 1)
                          - 1));

    // create the session handle using the default settings.
    hSession = WinHttpOpen((LPCWSTR)wuseragent.data(),
                           WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                           WINHTTP_NO_PROXY_NAME,
                           WINHTTP_NO_PROXY_BYPASS,
                           WINHTTP_FLAG_ASYNC);

    DWORD protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
            WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
            WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;

    WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof (protocols));
}
Esempio n. 12
0
khm_int32
HttpRequest::FetchResource(const wchar_t * domain,
                           const wchar_t * resource,
                           const wchar_t ** mimetypes)
{
    HANDLE hFile = INVALID_HANDLE_VALUE;
    HINTERNET hSession = NULL;
    HINTERNET hConnect = NULL;
    HINTERNET hRequest = NULL;
    DWORD nTotalBytes = 0;
    BOOL bContinue = TRUE;
    khm_int32 rv = KHM_ERROR_GENERAL;

    hSession = WinHttpOpen(USER_AGENT, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                           WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS,
                           0);

    if (hSession == NULL) {
        ReportStatus(KHERR_ERROR,
                     L"Can't create HTTP session",
                     L"%s", GetLastErrorString().c_str());
        goto done;
    }

    hConnect = WinHttpConnect(hSession, domain, INTERNET_DEFAULT_HTTP_PORT, 0);

    if (hConnect == NULL) {
        ReportStatus(KHERR_ERROR, L"Can't open HTTP connection",
                     L"%s", GetLastErrorString().c_str());
        goto done;
    }

    hRequest = WinHttpOpenRequest(hConnect, L"GET", resource, NULL, WINHTTP_NO_REFERER,
                                  mimetypes, WINHTTP_FLAG_ESCAPE_PERCENT);

    if (hRequest == NULL) {
        ReportStatus(KHERR_ERROR, L"Can't open request",
                     L"%s", GetLastErrorString().c_str());
        goto done;
    }

    {
        DWORD opt;

        opt = WINHTTP_DISABLE_AUTHENTICATION;
        if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &opt, sizeof(opt)))
            goto done;

        opt = WINHTTP_DISABLE_COOKIES;
        if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &opt, sizeof(opt)))
            goto done;

        opt = WINHTTP_DISABLE_KEEP_ALIVE;
        if (!WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &opt, sizeof(opt)))
            goto done;
    }

    rv = KHM_ERROR_NOT_FOUND;

    if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS,
                            0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) {
        ReportStatus(KHERR_ERROR, L"Can't send request to server",
                     L"Unable to send HTTP request to server at %s.\n"
                     L"%s", domain, GetLastErrorString().c_str());
        goto done;
    }

    if (!WinHttpReceiveResponse(hRequest, NULL)) {
        ReportStatus(KHERR_ERROR, L"Error while receiving response",
                     L"%s", GetLastErrorString().c_str());
        goto done;
    }

    rv = KHM_ERROR_GENERAL;

    {
        DWORD status = 0;
        DWORD nb = sizeof(status);

        if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
                                 WINHTTP_HEADER_NAME_BY_INDEX, &status, &nb, WINHTTP_NO_HEADER_INDEX)) {
            ReportStatus(KHERR_ERROR, L"Error while querying response status",
                         L"%s", GetLastErrorString().c_str());
            goto done;
        }

        if (status == HTTP_STATUS_NOT_FOUND) {
            switch (m_method) {
            case ByFavIcon:
                // Status reports are ignored for Favicon searches
                // anyway.
                break;

            case ByGravatar:
                ReportStatus(KHERR_ERROR, L"Could not find Gravatar",
                             L"An icon could not be found for %s on %s.\n",
                             m_target.c_str(),
                             domain);
                break;

            default:
                ReportStatus(KHERR_ERROR, L"The requested resource was not found",
                             L"The requested resource was not found on %s.", domain);
                break;
            }
            rv = KHM_ERROR_NOT_FOUND;
            goto done;
        }

        if (status != HTTP_STATUS_OK) {
            ReportStatus(KHERR_ERROR, L"The request failed",
                         L"The server at %s returned an unexpected status (%d)", domain, status);
            rv = KHM_ERROR_GENERAL;
            goto done;
        }
    }

    {
        wchar_t contenttype[128];
        DWORD nb = sizeof(contenttype);
        int i;

        if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_TYPE,
                                WINHTTP_HEADER_NAME_BY_INDEX, contenttype, &nb,
                                WINHTTP_NO_HEADER_INDEX)) {
            std::wstring::size_type epos;

            epos = m_path.rfind(L'.');

            if (epos != std::wstring::npos)
                m_path.erase(epos);

            for (i=0; i < ARRAYLENGTH(content_type_map); i++) {
                if (!_wcsicmp(contenttype, content_type_map[i].content_type))
                    break;
            }

            if (i < ARRAYLENGTH(content_type_map)) {
                m_path.append(content_type_map[i].extension);
            } else {
                ReportStatus(KHERR_WARNING, L"Unknown content type",
                             L"The content type %s was not expected for this request.",
                             contenttype);
            }
        } else {
            ReportStatus(KHERR_WARNING, L"Could not query response content type",
                         L"%s", GetLastErrorString().c_str());
        }
    }

    /* The request went through.  Create the file now */
    hFile = CreateFile(m_path.c_str(), GENERIC_WRITE,
                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                       NULL, CREATE_ALWAYS,
                       FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_TEMPORARY,
                       NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        ReportStatus(KHERR_ERROR, L"Can't create file",
                     L"%s", GetLastErrorString().c_str());
        goto done;
    }

    while (nTotalBytes < MAX_ICON_SIZE && bContinue) {
        DWORD nBytes = 0;
        BYTE * buffer = NULL;
        DWORD nRead = 0;
        DWORD nWritten = 0;

        bContinue = FALSE;

        if (!WinHttpQueryDataAvailable(hRequest, &nBytes))
            break;

        if (nBytes == 0) {
            bContinue = TRUE;
            break;
        }

        if (nBytes + nTotalBytes > MAX_ICON_SIZE)
            break;

        buffer = PNEW BYTE[nBytes];
        if (buffer == NULL)
            break;

        if (!WinHttpReadData(hRequest, buffer, nBytes, &nRead) || nRead == 0) {
            /* Fail */
        } else {
            /* Data found */
            if (WriteFile(hFile, buffer, nRead, &nWritten, NULL))
                bContinue = TRUE;
        }

        delete [] buffer;
        nTotalBytes += nBytes;
    }

    if (bContinue) {
        /* Done with file */
        rv = KHM_ERROR_SUCCESS;

    } else {
        /* File is incomplete */
        ReportStatus(KHERR_ERROR, L"Download incomplete",
                     L"The download was terminated unexpectedly.");
        DeleteFile(m_path.c_str());
    }

 done:

    if (hRequest) WinHttpCloseHandle(hRequest);
    if (hConnect) WinHttpCloseHandle(hConnect);
    if (hSession) WinHttpCloseHandle(hSession);

    if (hFile != INVALID_HANDLE_VALUE)
        CloseHandle(hFile);

    ReportComplete(KHM_SUCCEEDED(rv));

    return rv;
}
Esempio n. 13
0
DWORD
ProxyResolver::SetNextProxySettingEx(
    _In_ HINTERNET hInternet,
    _In_ DWORD dwRequestError
)
/*++

Routine Description:

    Finds the next proxy from m_wprProxyResult queried from extended API.
    It is not safe to use this function concurrently.

    Each sequential request to the same URL should use ResetProxyCursor
    before the first call for proxy settings during a single request.

Arguments:

    hInternet - The Session or Request handle to set the proxy info on.

    dwRequestError - The Win32 error code from WinHttpSendRequest (Sync) or from
                     WINHTTP_CALLBACK_STATUS_REQUEST_ERROR (Async) or
                     ERROR_SUCCESS if this is the first usage.
Return Value:

    Win32 Errors Codes.

--*/
{
    DWORD dwError = ERROR_SUCCESS;

    //
    // Use static proxy settings if it's activated.
    //

    if (!m_fProxyFailOverValid)
    {
        if (m_fReturnedFirstProxy)
        {
            dwError = ERROR_NO_MORE_ITEMS;
            goto quit;
        }

        m_fReturnedFirstProxy = TRUE;

        if (!WinHttpSetOption(hInternet,
                              WINHTTP_OPTION_PROXY,
                              &m_wpiProxyInfo,
                              sizeof(m_wpiProxyInfo)))
        {
            dwError = GetLastError();
            goto quit;
        }

        goto quit;
    }

    if (m_dwProxyCursor >= m_wprProxyResult.cEntries)
    {
        dwError = ERROR_NO_MORE_ITEMS;
        goto quit;
    }

    //
    // The first proxy is always valid. Only check request errors after first run.
    //

    if (m_dwProxyCursor != 0 &&
        !IsErrorValidForProxyFailover(dwRequestError))
    {
        dwError = ERROR_NO_MORE_ITEMS;
        goto quit;
    }

    if (!WinHttpSetOption(hInternet,
                          WINHTTP_OPTION_PROXY_RESULT_ENTRY,
                          &m_wprProxyResult.pEntries[m_dwProxyCursor],
                          sizeof(*m_wprProxyResult.pEntries)))
    {
        dwError = GetLastError();
        goto quit;
    }

    m_dwProxyCursor++;

quit:

    return dwError;
}
Esempio n. 14
0
DWORD
ProxyResolver::SetNextProxySetting(
    _In_ HINTERNET hInternet,
    _In_ DWORD dwRequestError
)
/*++

Routine Description:

    Finds the next proxy in a list of proxies separated by whitespace and/or
    semicolons if proxy failover is supported.  It is not safe to use this
    function concurrently, implement a concurrency mechanism for proxy lists
    if needed, such as making a copy or a separate iterator.

    Each sequential request to the same URL should use ResetProxyCursor
    before the first call for proxy settings during a single request.

Arguments:

    hInternet - The Session or Request handle to set the proxy info on.

    dwRequestError - The Win32 error code from WinHttpSendRequest (Sync) or from
                     WINHTTP_CALLBACK_STATUS_REQUEST_ERROR (Async) or
                     ERROR_SUCCESS if this is the first usage.

Return Value:

    ERROR_SUCCESS - Found the next proxy and it has been set on the HINTERNET.

    ERROR_NO_MORE_ITEMS - Reached the end of the list or failover not valid.

    ERROR_INVALID_OPERATION - The class is not initialized.  Call ResolveProxy first.

    Other Win32 Errors returned from WinHttpSetOption.

--*/
{
    DWORD dwError = ERROR_SUCCESS;
    PWSTR pwszCursor = NULL;
    WINHTTP_PROXY_INFO NextProxyInfo = {};

    if (!m_fInit)
    {
        dwError = ERROR_INVALID_OPERATION;
        goto quit;
    }

    if (m_fExtendedAPI)
    {
        dwError = SetNextProxySettingEx(hInternet,
                                        dwRequestError);
        goto quit;
    }

    if (!m_fReturnedFirstProxy)
    {
        //
        //  We have yet to set the first proxy type, the first one is always
        //  valid.
        //

        pwszCursor = m_wpiProxyInfo.lpszProxy;
        m_fReturnedFirstProxy = TRUE;
        goto commit;
    }

    //
    // Find the next proxy in the list if it is valid to do so.
    //

    if (m_fReturnedLastProxy ||
        !m_fProxyFailOverValid ||
        m_wpiProxyInfo.lpszProxy == NULL)
    {
        //
        // Already reached end, failover not valid, or type is not proxy.
        //

        dwError = ERROR_NO_MORE_ITEMS;
        goto quit;
    }

    if (!IsErrorValidForProxyFailover(dwRequestError))
    {
        dwError = ERROR_NO_MORE_ITEMS;
        goto quit;
    }

    pwszCursor = m_pwszProxyCursor;

    //
    // Skip the current entry.
    //

    while (*pwszCursor != L'\0' &&
           *pwszCursor != L';' &&
           !IsWhitespace(*pwszCursor))
    {
        pwszCursor++;
    }

    //
    // Skip any additional separators.
    //

    while (*pwszCursor != L'\0' &&
           (*pwszCursor == L';' ||
           IsWhitespace(*pwszCursor)))
    {
        pwszCursor++;
    }

    if (*pwszCursor == L'\0')
    {
        //
        // Hit the end of the list.
        //

        m_fReturnedLastProxy = TRUE;
        dwError = ERROR_NO_MORE_ITEMS;
        goto quit;
    }

commit:
    NextProxyInfo.dwAccessType = m_wpiProxyInfo.dwAccessType;
    NextProxyInfo.lpszProxy = pwszCursor;
    NextProxyInfo.lpszProxyBypass = m_wpiProxyInfo.lpszProxyBypass;

    if (!WinHttpSetOption(hInternet,
                          WINHTTP_OPTION_PROXY,
                          &NextProxyInfo,
                          sizeof(NextProxyInfo)))
    {
        dwError = GetLastError();
        goto quit;
    }

    m_pwszProxyCursor = pwszCursor;

quit:

    return dwError;
}
Esempio n. 15
0
PSTR VirusTotalSendHttpRequest(
    _In_ PPH_BYTES JsonArray
    )
{
    HANDLE fileHandle = INVALID_HANDLE_VALUE;
    HINTERNET httpSessionHandle = NULL;
    HINTERNET connectHandle = NULL;
    HINTERNET requestHandle = NULL;
    PSTR subRequestBuffer = NULL;
    PPH_STRING phVersion = NULL;
    PPH_STRING userAgent = NULL;
    PPH_STRING urlString = NULL;

    phVersion = PhGetPhVersion();
    userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer);

    if (!(httpSessionHandle = WinHttpOpen(
        userAgent->Buffer,
        WindowsVersion >= WINDOWS_8_1 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
        WINHTTP_NO_PROXY_NAME,
        WINHTTP_NO_PROXY_BYPASS,
        0
        )))
    {
        goto CleanupExit;
    }

    if (WindowsVersion >= WINDOWS_8_1)
    {
        WinHttpSetOption(
            httpSessionHandle, 
            WINHTTP_OPTION_DECOMPRESSION, 
            &(ULONG){ WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE }, 
            sizeof(ULONG)
            );
    }

    if (!(connectHandle = WinHttpConnect(
        httpSessionHandle,
        L"www.virustotal.com",
        INTERNET_DEFAULT_HTTPS_PORT,
        0
        )))
    {
        goto CleanupExit;
    }

    PPH_BYTES resourceString = VirusTotalGetCachedDbHash();

    urlString = PhFormatString(
        L"%s%s%s%s%S",
        L"/partners", 
        L"/sysinternals",
        L"/file-reports",
        L"?apikey=",
        resourceString->Buffer
        );

    PhClearReference(&resourceString);

    if (!(requestHandle = WinHttpOpenRequest(
        connectHandle,
        L"POST",
        PhGetString(urlString),
        NULL,
        WINHTTP_NO_REFERER,
        WINHTTP_DEFAULT_ACCEPT_TYPES,
        WINHTTP_FLAG_SECURE
        )))
    {
        PhClearReference(&urlString);
        goto CleanupExit;
    }

    PhClearReference(&urlString);

    if (!WinHttpAddRequestHeaders(requestHandle, L"Content-Type: application/json", -1L, 0))
    {
        goto CleanupExit;
    }

    if (!WinHttpSendRequest(
        requestHandle, 
        WINHTTP_NO_ADDITIONAL_HEADERS, 
        0, 
        JsonArray->Buffer, 
        (ULONG)JsonArray->Length, 
        (ULONG)JsonArray->Length,
        0
        ))
    {
        goto CleanupExit;
    }

    if (WinHttpReceiveResponse(requestHandle, NULL))
    {
        BYTE buffer[PAGE_SIZE];
        ULONG allocatedLength;
        ULONG dataLength;
        ULONG returnLength;

        allocatedLength = sizeof(buffer);
        subRequestBuffer = PhAllocate(allocatedLength);
        dataLength = 0;

        while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength))
        {
            if (returnLength == 0)
                break;

            if (allocatedLength < dataLength + returnLength)
            {
                allocatedLength *= 2;
                subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength);
            }

            memcpy(subRequestBuffer + dataLength, buffer, returnLength);
            dataLength += returnLength;
        }

        if (allocatedLength < dataLength + 1)
        {
            allocatedLength++;
            subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength);
        }

        // Ensure that the buffer is null-terminated.
        subRequestBuffer[dataLength] = 0;
    }

CleanupExit:

    if (requestHandle)
        WinHttpCloseHandle(requestHandle);

    if (connectHandle)
        WinHttpCloseHandle(connectHandle);

    if (httpSessionHandle)
        WinHttpCloseHandle(httpSessionHandle);

    if (JsonArray)
        PhDereferenceObject(JsonArray);

    return subRequestBuffer;
}
Esempio n. 16
0
static int winhttp_stream_connect(winhttp_stream *s)
{
	winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
	git_buf buf = GIT_BUF_INIT;
	char *proxy_url = NULL;
	wchar_t ct[MAX_CONTENT_TYPE_LEN];
	LPCWSTR types[] = { L"*/*", NULL };
	BOOL peerdist = FALSE;
	int error = -1;
	unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS;
	int default_timeout = TIMEOUT_INFINITE;
	int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;

	/* Prepare URL */
	git_buf_printf(&buf, "%s%s", t->connection_data.path, s->service_url);

	if (git_buf_oom(&buf))
		return -1;

	/* Convert URL to wide characters */
	if (git__utf8_to_16_alloc(&s->request_uri, git_buf_cstr(&buf)) < 0) {
		giterr_set(GITERR_OS, "Failed to convert string to wide form");
		goto on_error;
	}

	/* Establish request */
	s->request = WinHttpOpenRequest(
			t->connection,
			s->verb,
			s->request_uri,
			NULL,
			WINHTTP_NO_REFERER,
			types,
			t->connection_data.use_ssl ? WINHTTP_FLAG_SECURE : 0);

	if (!s->request) {
		giterr_set(GITERR_OS, "Failed to open request");
		goto on_error;
	}

	if (!WinHttpSetTimeouts(s->request, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
		giterr_set(GITERR_OS, "Failed to set timeouts for WinHTTP");
		goto on_error;
	}

	/* Set proxy if necessary */
	if (git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url) < 0)
		goto on_error;

	if (proxy_url) {
		WINHTTP_PROXY_INFO proxy_info;
		wchar_t *proxy_wide;

		/* Convert URL to wide characters */
		int proxy_wide_len = git__utf8_to_16_alloc(&proxy_wide, proxy_url);

		if (proxy_wide_len < 0) {
			giterr_set(GITERR_OS, "Failed to convert string to wide form");
			goto on_error;
		}

		/* Strip any trailing forward slash on the proxy URL;
		 * WinHTTP doesn't like it if one is present */
		if (proxy_wide_len > 1 && L'/' == proxy_wide[proxy_wide_len - 2])
			proxy_wide[proxy_wide_len - 2] = L'\0';

		proxy_info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
		proxy_info.lpszProxy = proxy_wide;
		proxy_info.lpszProxyBypass = NULL;

		if (!WinHttpSetOption(s->request,
			WINHTTP_OPTION_PROXY,
			&proxy_info,
			sizeof(WINHTTP_PROXY_INFO))) {
			giterr_set(GITERR_OS, "Failed to set proxy");
			git__free(proxy_wide);
			goto on_error;
		}

		git__free(proxy_wide);
	}

	/* Disable WinHTTP redirects so we can handle them manually. Why, you ask?
	 * http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/b2ff8879-ab9f-4218-8f09-16d25dff87ae
	 */
	if (!WinHttpSetOption(s->request,
		WINHTTP_OPTION_DISABLE_FEATURE,
		&disable_redirects,
		sizeof(disable_redirects))) {
			giterr_set(GITERR_OS, "Failed to disable redirects");
			goto on_error;
	}

	/* Strip unwanted headers (X-P2P-PeerDist, X-P2P-PeerDistEx) that WinHTTP
	 * adds itself. This option may not be supported by the underlying
	 * platform, so we do not error-check it */
	WinHttpSetOption(s->request,
		WINHTTP_OPTION_PEERDIST_EXTENSION_STATE,
		&peerdist,
		sizeof(peerdist));

	/* Send Pragma: no-cache header */
	if (!WinHttpAddRequestHeaders(s->request, pragma_nocache, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) {
		giterr_set(GITERR_OS, "Failed to add a header to the request");
		goto on_error;
	}

	if (post_verb == s->verb) {
		/* Send Content-Type and Accept headers -- only necessary on a POST */
		git_buf_clear(&buf);
		if (git_buf_printf(&buf,
			"Content-Type: application/x-git-%s-request",
			s->service) < 0)
			goto on_error;

		if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
			giterr_set(GITERR_OS, "Failed to convert content-type to wide characters");
			goto on_error;
		}

		if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
			WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
			giterr_set(GITERR_OS, "Failed to add a header to the request");
			goto on_error;
		}

		git_buf_clear(&buf);
		if (git_buf_printf(&buf,
			"Accept: application/x-git-%s-result",
			s->service) < 0)
			goto on_error;

		if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
			giterr_set(GITERR_OS, "Failed to convert accept header to wide characters");
			goto on_error;
		}

		if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
			WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
			giterr_set(GITERR_OS, "Failed to add a header to the request");
			goto on_error;
		}
	}

	/* If requested, disable certificate validation */
	if (t->connection_data.use_ssl) {
		int flags;

		if (t->owner->parent.read_flags(&t->owner->parent, &flags) < 0)
			goto on_error;
	}

	/* If we have a credential on the subtransport, apply it to the request */
	if (t->cred &&
		t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT &&
		t->auth_mechanism == GIT_WINHTTP_AUTH_BASIC &&
		apply_basic_credential(s->request, t->cred) < 0)
		goto on_error;
	else if (t->cred &&
		t->cred->credtype == GIT_CREDTYPE_DEFAULT &&
		t->auth_mechanism == GIT_WINHTTP_AUTH_NEGOTIATE &&
		apply_default_credentials(s->request) < 0)
		goto on_error;

	/* If no other credentials have been applied and the URL has username and
	 * password, use those */
	if (!t->cred && t->connection_data.user && t->connection_data.pass) {
		if (!t->url_cred &&
			git_cred_userpass_plaintext_new(&t->url_cred, t->connection_data.user, t->connection_data.pass) < 0)
			goto on_error;
		if (apply_basic_credential(s->request, t->url_cred) < 0)
			goto on_error;
	}

	/* We've done everything up to calling WinHttpSendRequest. */

	error = 0;

on_error:
	if (error < 0)
		winhttp_stream_close(s);

	git__free(proxy_url);
	git_buf_free(&buf);
	return error;
}
Esempio n. 17
0
static int winhttp_stream_connect(winhttp_stream *s)
{
	winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
	git_buf buf = GIT_BUF_INIT;
	char *proxy_url = NULL;
	wchar_t ct[MAX_CONTENT_TYPE_LEN];
	LPCWSTR types[] = { L"*/*", NULL };
	BOOL peerdist = FALSE;
	int error = -1;
	unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS;
	int default_timeout = TIMEOUT_INFINITE;
	int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
	size_t i;
	const git_proxy_options *proxy_opts;

	/* Prepare URL */
	git_buf_printf(&buf, "%s%s", t->connection_data.path, s->service_url);

	if (git_buf_oom(&buf))
		return -1;

	/* Convert URL to wide characters */
	if (git__utf8_to_16_alloc(&s->request_uri, git_buf_cstr(&buf)) < 0) {
		giterr_set(GITERR_OS, "failed to convert string to wide form");
		goto on_error;
	}

	/* Establish request */
	s->request = WinHttpOpenRequest(
			t->connection,
			s->verb,
			s->request_uri,
			NULL,
			WINHTTP_NO_REFERER,
			types,
			t->connection_data.use_ssl ? WINHTTP_FLAG_SECURE : 0);

	if (!s->request) {
		giterr_set(GITERR_OS, "failed to open request");
		goto on_error;
	}

	if (!WinHttpSetTimeouts(s->request, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
		giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP");
		goto on_error;
	}

	proxy_opts = &t->owner->proxy;
	if (proxy_opts->type == GIT_PROXY_AUTO) {
		/* Set proxy if necessary */
		if (git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url) < 0)
			goto on_error;
	}
	else if (proxy_opts->type == GIT_PROXY_SPECIFIED) {
		proxy_url = git__strdup(proxy_opts->url);
		GITERR_CHECK_ALLOC(proxy_url);
	}

	if (proxy_url) {
		git_buf processed_url = GIT_BUF_INIT;
		WINHTTP_PROXY_INFO proxy_info;
		wchar_t *proxy_wide;

		if (!git__prefixcmp(proxy_url, SCHEME_HTTP)) {
			t->proxy_connection_data.use_ssl = false;
		} else if (!git__prefixcmp(proxy_url, SCHEME_HTTPS)) {
			t->proxy_connection_data.use_ssl = true;
		} else {
			giterr_set(GITERR_NET, "invalid URL: '%s'", proxy_url);
			return -1;
		}

		gitno_connection_data_free_ptrs(&t->proxy_connection_data);

		if ((error = gitno_extract_url_parts(&t->proxy_connection_data.host, &t->proxy_connection_data.port, NULL,
				&t->proxy_connection_data.user, &t->proxy_connection_data.pass, proxy_url, NULL)) < 0)
			goto on_error;

		if (t->proxy_connection_data.user && t->proxy_connection_data.pass) {
			if (t->proxy_cred) {
				t->proxy_cred->free(t->proxy_cred);
			}

			if ((error = git_cred_userpass_plaintext_new(&t->proxy_cred, t->proxy_connection_data.user, t->proxy_connection_data.pass)) < 0)
				goto on_error;
		}

		if (t->proxy_connection_data.use_ssl)
			git_buf_PUTS(&processed_url, SCHEME_HTTPS);
		else
			git_buf_PUTS(&processed_url, SCHEME_HTTP);

		git_buf_puts(&processed_url, t->proxy_connection_data.host);
		if (t->proxy_connection_data.port)
			git_buf_printf(&processed_url, ":%s", t->proxy_connection_data.port);

		if (git_buf_oom(&processed_url)) {
			giterr_set_oom();
			error = -1;
			goto on_error;
		}

		/* Convert URL to wide characters */
		error = git__utf8_to_16_alloc(&proxy_wide, processed_url.ptr);
		git_buf_free(&processed_url);
		if (error < 0)
			goto on_error;

		proxy_info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
		proxy_info.lpszProxy = proxy_wide;
		proxy_info.lpszProxyBypass = NULL;

		if (!WinHttpSetOption(s->request,
			WINHTTP_OPTION_PROXY,
			&proxy_info,
			sizeof(WINHTTP_PROXY_INFO))) {
			giterr_set(GITERR_OS, "failed to set proxy");
			git__free(proxy_wide);
			goto on_error;
		}

		git__free(proxy_wide);

		if (t->proxy_cred) {
			if (t->proxy_cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT) {
				if ((error = apply_userpass_credential_proxy(s->request, t->proxy_cred)) < 0)
					goto on_error;
			}
		}

	}

	/* Disable WinHTTP redirects so we can handle them manually. Why, you ask?
	 * http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/b2ff8879-ab9f-4218-8f09-16d25dff87ae
	 */
	if (!WinHttpSetOption(s->request,
		WINHTTP_OPTION_DISABLE_FEATURE,
		&disable_redirects,
		sizeof(disable_redirects))) {
			giterr_set(GITERR_OS, "failed to disable redirects");
			goto on_error;
	}

	/* Strip unwanted headers (X-P2P-PeerDist, X-P2P-PeerDistEx) that WinHTTP
	 * adds itself. This option may not be supported by the underlying
	 * platform, so we do not error-check it */
	WinHttpSetOption(s->request,
		WINHTTP_OPTION_PEERDIST_EXTENSION_STATE,
		&peerdist,
		sizeof(peerdist));

	/* Send Pragma: no-cache header */
	if (!WinHttpAddRequestHeaders(s->request, pragma_nocache, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) {
		giterr_set(GITERR_OS, "failed to add a header to the request");
		goto on_error;
	}

	if (post_verb == s->verb) {
		/* Send Content-Type and Accept headers -- only necessary on a POST */
		git_buf_clear(&buf);
		if (git_buf_printf(&buf,
			"Content-Type: application/x-git-%s-request",
			s->service) < 0)
			goto on_error;

		if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
			giterr_set(GITERR_OS, "failed to convert content-type to wide characters");
			goto on_error;
		}

		if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
			WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
			giterr_set(GITERR_OS, "failed to add a header to the request");
			goto on_error;
		}

		git_buf_clear(&buf);
		if (git_buf_printf(&buf,
			"Accept: application/x-git-%s-result",
			s->service) < 0)
			goto on_error;

		if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
			giterr_set(GITERR_OS, "failed to convert accept header to wide characters");
			goto on_error;
		}

		if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
			WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
			giterr_set(GITERR_OS, "failed to add a header to the request");
			goto on_error;
		}
	}

	for (i = 0; i < t->owner->custom_headers.count; i++) {
		if (t->owner->custom_headers.strings[i]) {
			git_buf_clear(&buf);
			git_buf_puts(&buf, t->owner->custom_headers.strings[i]);
			if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
				giterr_set(GITERR_OS, "failed to convert custom header to wide characters");
				goto on_error;
			}

			if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
				WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
				giterr_set(GITERR_OS, "failed to add a header to the request");
				goto on_error;
			}
		}
	}

	/* If requested, disable certificate validation */
	if (t->connection_data.use_ssl) {
		int flags;

		if (t->owner->parent.read_flags(&t->owner->parent, &flags) < 0)
			goto on_error;
	}

	/* If we have a credential on the subtransport, apply it to the request */
	if (t->cred &&
		t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT &&
		apply_userpass_credential(s->request, t->auth_mechanisms, t->cred) < 0)
		goto on_error;
	else if (t->cred &&
		t->cred->credtype == GIT_CREDTYPE_DEFAULT &&
		apply_default_credentials(s->request, t->auth_mechanisms) < 0)
		goto on_error;

	/* If no other credentials have been applied and the URL has username and
	 * password, use those */
	if (!t->cred && t->connection_data.user && t->connection_data.pass) {
		if (!t->url_cred &&
			git_cred_userpass_plaintext_new(&t->url_cred, t->connection_data.user, t->connection_data.pass) < 0)
			goto on_error;
		if (apply_userpass_credential(s->request, GIT_WINHTTP_AUTH_BASIC, t->url_cred) < 0)
			goto on_error;
	}

	/* We've done everything up to calling WinHttpSendRequest. */

	error = 0;

on_error:
	if (error < 0)
		winhttp_stream_close(s);

	git__free(proxy_url);
	git_buf_free(&buf);
	return error;
}
/*!
 * @brief Prepare a winHTTP request with the given context.
 * @param ctx Pointer to the HTTP transport context to prepare the request from.
 * @param isGet Indication of whether this request is a GET request, otherwise POST is used.
 * @param direction String representing the direction of the communications (for debug).
 * @return An Internet request handle.
 */
static HINTERNET get_request_winhttp(HttpTransportContext *ctx, BOOL isGet, const char *direction)
{
	HINTERNET hReq = NULL;
	DWORD flags = WINHTTP_FLAG_BYPASS_PROXY_CACHE;

	if (ctx->ssl)
	{
		flags |= WINHTTP_FLAG_SECURE;
		dprintf("[%s] Setting secure flag..", direction);
	}

	vdprintf("[%s] opening request on connection %x to %S", direction, ctx->connection, ctx->uri);
	hReq = WinHttpOpenRequest(ctx->connection, isGet ? L"GET" : L"POST", ctx->uri, NULL, NULL, NULL, flags);

	if (hReq == NULL)
	{
		dprintf("[%s] Failed WinHttpOpenRequest: %u", direction, GetLastError());
		SetLastError(ERROR_NOT_FOUND);
		return NULL;
	}

	// if no proxy is set, we should look to see if we can (and should) use the system
	// proxy settings for the given user.
	if (!ctx->proxy)
	{
		if (!ctx->proxy_configured)
		{
			WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieConfig = { 0 };
			if (WinHttpGetIEProxyConfigForCurrentUser(&ieConfig))
			{
				dprintf("[PROXY] Got IE configuration");
				dprintf("[PROXY] AutoDetect: %s", ieConfig.fAutoDetect ? "yes" : "no");
				dprintf("[PROXY] Auto URL: %S", ieConfig.lpszAutoConfigUrl);
				dprintf("[PROXY] Proxy: %S", ieConfig.lpszProxy);
				dprintf("[PROXY] Proxy Bypass: %S", ieConfig.lpszProxyBypass);

				if (ieConfig.lpszAutoConfigUrl || ieConfig.fAutoDetect)
				{
					WINHTTP_AUTOPROXY_OPTIONS autoProxyOpts = { 0 };
					WINHTTP_PROXY_INFO proxyInfo = { 0 };

					if (ieConfig.fAutoDetect)
					{
						dprintf("[PROXY] IE config set to autodetect with DNS or DHCP");

						autoProxyOpts.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
						autoProxyOpts.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
						autoProxyOpts.lpszAutoConfigUrl = 0;
					}
					else if (ieConfig.lpszAutoConfigUrl)
					{
						dprintf("[PROXY] IE config set to autodetect with URL %S", ieConfig.lpszAutoConfigUrl);

						autoProxyOpts.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
						autoProxyOpts.dwAutoDetectFlags = 0;
						autoProxyOpts.lpszAutoConfigUrl = ieConfig.lpszAutoConfigUrl;
					}
					autoProxyOpts.fAutoLogonIfChallenged = TRUE;

					if (WinHttpGetProxyForUrl(ctx->internet, ctx->url, &autoProxyOpts, &proxyInfo))
					{
						ctx->proxy_for_url = malloc(sizeof(WINHTTP_PROXY_INFO));
						memcpy(ctx->proxy_for_url, &proxyInfo, sizeof(WINHTTP_PROXY_INFO));
					}
				}
				else if (ieConfig.lpszProxy)
				{
					WINHTTP_PROXY_INFO* proxyInfo = (WINHTTP_PROXY_INFO*)calloc(1, sizeof(WINHTTP_PROXY_INFO));
					ctx->proxy_for_url = proxyInfo;

					dprintf("[PROXY] IE config set to proxy %S with bypass %S", ieConfig.lpszProxy, ieConfig.lpszProxyBypass);

					proxyInfo->dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
					proxyInfo->lpszProxy = ieConfig.lpszProxy;
					proxyInfo->lpszProxyBypass = ieConfig.lpszProxyBypass;

					// stop the cleanup code from removing these as we're using them behind the scenes and they will
					// be freed later instead.
					ieConfig.lpszProxy = NULL;
					ieConfig.lpszProxyBypass = NULL;;
				}

				if (ieConfig.lpszAutoConfigUrl)
				{
					GlobalFree(ieConfig.lpszAutoConfigUrl);
				}
				if (ieConfig.lpszProxy)
				{
					GlobalFree(ieConfig.lpszProxy);
				}
				if (ieConfig.lpszProxyBypass)
				{
					GlobalFree(ieConfig.lpszProxyBypass);
				}
			}

			// mark as "configured" so we don't attempt to do this horrible PoS mess again.
			ctx->proxy_configured = TRUE;
		}

		if (ctx->proxy_for_url &&
			!WinHttpSetOption(hReq, WINHTTP_OPTION_PROXY, ctx->proxy_for_url, sizeof(WINHTTP_PROXY_INFO)))
		{
			dprintf("[%s] Unable to set proxy options: %u", GetLastError());
		}
	}
	else
	{
		if (ctx->proxy_user)
		{
			dprintf("[%s] Setting proxy username to %S", direction, ctx->proxy_user);
			if (!WinHttpSetOption(hReq, WINHTTP_OPTION_PROXY_USERNAME, ctx->proxy_user, (DWORD)(wcslen(ctx->proxy_user))));
			{
				dprintf("[%s] Failed to set username %u", direction, GetLastError());
			}
		}
		if (ctx->proxy_pass)
		{
			dprintf("[%s] Setting proxy password to %S", direction, ctx->proxy_pass);
			if (!WinHttpSetOption(hReq, WINHTTP_OPTION_PROXY_PASSWORD, ctx->proxy_pass, (DWORD)(wcslen(ctx->proxy_pass))));
			{
				dprintf("[%s] Failed to set password %u", direction, GetLastError());
			}
		}
	}

	if (ctx->ssl)
	{
		flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA
			| SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
			| SECURITY_FLAG_IGNORE_CERT_CN_INVALID
			| SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
		if (!WinHttpSetOption(hReq, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof(flags)))
		{
			dprintf("[%s] failed to set the security flags on the request", direction);
		}
	}

	return hReq;
}
Esempio n. 19
0
static void test_connection_cache( void )
{
    HANDLE ses, con, req;
    DWORD size, status;
    BOOL ret;
    struct info info, *context = &info;

    info.test  = cache_test;
    info.count = sizeof(cache_test) / sizeof(cache_test[0]);
    info.index = 0;
    info.wait = NULL;

    ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
    ok(ses != NULL, "failed to open session %u\n", GetLastError());

    WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );

    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_connect, __LINE__ );
    con = WinHttpConnect( ses, test_winehq, 0, 0 );
    ok(con != NULL, "failed to open a connection %u\n", GetLastError());

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );
    WinHttpCloseHandle( con );
    WinHttpCloseHandle( ses );

    Sleep(2000); /* make sure connection is evicted from cache */

    info.index = 0;

    ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
    ok(ses != NULL, "failed to open session %u\n", GetLastError());

    WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );

    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_connect, __LINE__ );
    con = WinHttpConnect( ses, test_winehq, 0, 0 );
    ok(con != NULL, "failed to open a connection %u\n", GetLastError());

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );
    WinHttpCloseHandle( con );
    WinHttpCloseHandle( ses );

    Sleep(2000); /* make sure connection is evicted from cache */
}
Esempio n. 20
0
static void test_async( void )
{
    HANDLE ses, con, req;
    DWORD size, status;
    BOOL ret;
    struct info info, *context = &info;
    char buffer[1024];

    info.test  = async_test;
    info.count = sizeof(async_test) / sizeof(async_test[0]);
    info.index = 0;
    info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );

    ses = WinHttpOpen( user_agent, 0, NULL, NULL, WINHTTP_FLAG_ASYNC );
    ok(ses != NULL, "failed to open session %u\n", GetLastError());

    WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );

    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_connect, __LINE__ );
    con = WinHttpConnect( ses, test_winehq, 0, 0 );
    ok(con != NULL, "failed to open a connection %u\n", GetLastError());

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    WaitForSingleObject( info.wait, INFINITE );

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    WaitForSingleObject( info.wait, INFINITE );

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_query_data, __LINE__ );
    ret = WinHttpQueryDataAvailable( req, NULL );
    ok(ret, "failed to query data available %u\n", GetLastError());

    WaitForSingleObject( info.wait, INFINITE );

    setup_test( &info, winhttp_read_data, __LINE__ );
    ret = WinHttpReadData( req, buffer, sizeof(buffer), NULL );
    ok(ret, "failed to query data available %u\n", GetLastError());

    WaitForSingleObject( info.wait, INFINITE );

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );
    WinHttpCloseHandle( con );
    WinHttpCloseHandle( ses );

    WaitForSingleObject( info.wait, INFINITE );
    CloseHandle( info.wait );
}
DWORD HTTPGetFile(String url, char * outHtml, unsigned &bufeLen, CTSTR extraHeaders, int *responseCode)
{
	if (NULL == outHtml || 0 == bufeLen)
	{
		return 1;
	}
	unsigned nMaxBufLen = bufeLen;
	bufeLen = 0;
	HINTERNET hSession = NULL;
	HINTERNET hConnect = NULL;
	HINTERNET hRequest = NULL;
	URL_COMPONENTS  urlComponents;
	BOOL secure = FALSE;
	DWORD ret = 1;

	String hostName, path;

	const TCHAR *acceptTypes[] = {
		TEXT("*/*"),
		NULL
	};

	hostName.SetLength(256);
	path.SetLength(1024);

	zero(&urlComponents, sizeof(urlComponents));

	urlComponents.dwStructSize = sizeof(urlComponents);

	urlComponents.lpszHostName = hostName;
	urlComponents.dwHostNameLength = hostName.Length();

	urlComponents.lpszUrlPath = path;
	urlComponents.dwUrlPathLength = path.Length();

	WinHttpCrackUrl(url, 0, 0, &urlComponents);

	if (urlComponents.nPort == 443)
		secure = TRUE;

	hSession = WinHttpOpen(TEXT("ButelLive agent"), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
	if (!hSession)
		goto failure;

	DWORD dwTimeOut = 5000; // ms
	DWORD dwSize = sizeof(DWORD);
	WinHttpSetOption(hSession, WINHTTP_OPTION_CONNECT_TIMEOUT, &dwTimeOut, dwSize);
	WinHttpSetOption(hSession, WINHTTP_OPTION_SEND_TIMEOUT, &dwTimeOut, dwSize);
	WinHttpSetOption(hSession, WINHTTP_OPTION_RECEIVE_TIMEOUT, &dwTimeOut, dwSize);

	hConnect = WinHttpConnect(hSession, hostName, urlComponents.nPort, 0);
	if (!hConnect)
		goto failure;

	hRequest = WinHttpOpenRequest(hConnect, TEXT("Get"), path, NULL, WINHTTP_NO_REFERER, acceptTypes, secure ? WINHTTP_FLAG_SECURE | WINHTTP_FLAG_REFRESH : WINHTTP_FLAG_REFRESH);
	if (!hRequest)
		goto failure;


	BOOL bResults = WinHttpSendRequest(
		hRequest,
		extraHeaders,
		extraHeaders ? -1 : 0,
		NULL,
		0,
		0,
		NULL
		);

	// End the request.
	if (bResults)
		bResults = WinHttpReceiveResponse(hRequest, NULL);
	else
		goto failure;

	TCHAR statusCode[8];
	DWORD statusCodeLen;

	statusCodeLen = sizeof(statusCode);
	if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE, WINHTTP_HEADER_NAME_BY_INDEX, &statusCode, &statusCodeLen, WINHTTP_NO_HEADER_INDEX))
	{
		//ERROR_WINHTTP_HEADER_NOT_FOUND
		int error = GetLastError();
		goto failure;
	}

	*responseCode = wcstoul(statusCode, NULL, 10);

	if (bResults && *responseCode == 200)
	{
		BYTE buffer[16384];
		DWORD dwSize, dwOutSize;
		do
		{
			// Check for available data.
			dwSize = 0;
			if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
				goto failure;

			if (!WinHttpReadData(hRequest, (LPVOID)buffer, dwSize, &dwOutSize))
			{
				goto failure;
			}
			else
			{
				if (!dwOutSize)
					break;

				if (bufeLen + dwOutSize > nMaxBufLen)
				{
					goto failure;
				}
				//strHtml.AppendString((CTSTR)buffer, dwOutSize);
				memcpy(outHtml + bufeLen, buffer, dwOutSize);
				bufeLen += dwOutSize;
				outHtml[bufeLen] = '\0';
			}
		} while (dwSize > 0);
	}
	ret = 0;

failure:
	if (0 != ret)
	{
		DWORD dwError = GetLastError();
		if (dwError != 0)
		{
			ret = dwError;
		}
	}

	if (hSession)
		WinHttpCloseHandle(hSession);
	if (hConnect)
		WinHttpCloseHandle(hConnect);
	if (hRequest)
		WinHttpCloseHandle(hRequest);

	return ret;
}
Esempio n. 22
0
PVIRUSTOTAL_FILE_REPORT_RESULT VirusTotalSendHttpFileReportRequest(
    _In_ PPH_STRING FileHash
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    HANDLE fileHandle = INVALID_HANDLE_VALUE;
    HINTERNET httpSessionHandle = NULL;
    HINTERNET connectHandle = NULL;
    HINTERNET requestHandle = NULL;
    PSTR subRequestBuffer = NULL;
    PPH_STRING phVersion = NULL;
    PPH_STRING userAgent = NULL;
    PPH_STRING urlString = NULL;

    phVersion = PhGetPhVersion();
    userAgent = PhConcatStrings2(L"ProcessHacker_", phVersion->Buffer);

    if (!(httpSessionHandle = WinHttpOpen(
        userAgent->Buffer,
        WindowsVersion >= WINDOWS_8_1 ? WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
        WINHTTP_NO_PROXY_NAME,
        WINHTTP_NO_PROXY_BYPASS,
        0
        )))
    {
        goto CleanupExit;
    }

    if (WindowsVersion >= WINDOWS_8_1)
    {
        WinHttpSetOption(
            httpSessionHandle,
            WINHTTP_OPTION_DECOMPRESSION, 
            &(ULONG){ WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE }, 
            sizeof(ULONG)
            );
    }

    if (!(connectHandle = WinHttpConnect(
        httpSessionHandle,
        L"www.virustotal.com",
        INTERNET_DEFAULT_HTTPS_PORT,
        0
        )))
    {
        goto CleanupExit;
    }

    PPH_BYTES resourceString = VirusTotalGetCachedDbHash();

    urlString = PhFormatString(
        L"%s%s%s%s%S%s%s",
        L"/vtapi",
        L"/v2",
        L"/file",
        L"/report",
        L"?apikey=",
        resourceString->Buffer,
        L"&resource=",
        PhGetString(FileHash)
        );

    PhClearReference(&resourceString);

    if (!(requestHandle = WinHttpOpenRequest(
        connectHandle,
        L"POST",
        PhGetString(urlString),
        NULL,
        WINHTTP_NO_REFERER,
        WINHTTP_DEFAULT_ACCEPT_TYPES,
        WINHTTP_FLAG_SECURE
        )))
    {
        goto CleanupExit;
    }

    if (!WinHttpAddRequestHeaders(requestHandle, L"Content-Type: application/json", -1L, 0))
        goto CleanupExit;

    if (!WinHttpSendRequest(
        requestHandle,
        WINHTTP_NO_ADDITIONAL_HEADERS,
        0,
        WINHTTP_NO_REQUEST_DATA,
        0,
        WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
        0
        ))
    {
        goto CleanupExit;
    }

    if (WinHttpReceiveResponse(requestHandle, NULL))
    {
        BYTE buffer[PAGE_SIZE];
        ULONG allocatedLength;
        ULONG dataLength;
        ULONG returnLength;

        allocatedLength = sizeof(buffer);
        subRequestBuffer = PhAllocate(allocatedLength);
        dataLength = 0;

        while (WinHttpReadData(requestHandle, buffer, PAGE_SIZE, &returnLength))
        {
            if (returnLength == 0)
                break;

            if (allocatedLength < dataLength + returnLength)
            {
                allocatedLength *= 2;
                subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength);
            }

            memcpy(subRequestBuffer + dataLength, buffer, returnLength);
            dataLength += returnLength;
        }

        if (allocatedLength < dataLength + 1)
        {
            allocatedLength++;
            subRequestBuffer = PhReAllocate(subRequestBuffer, allocatedLength);
        }

        subRequestBuffer[dataLength] = 0;
    }

CleanupExit:

    PhClearReference(&urlString);

    if (requestHandle)
        WinHttpCloseHandle(requestHandle);

    if (connectHandle)
        WinHttpCloseHandle(connectHandle);

    if (httpSessionHandle)
        WinHttpCloseHandle(httpSessionHandle);


    PVOID jsonRootObject;
    //PVOID jsonScanObject;
    PVIRUSTOTAL_FILE_REPORT_RESULT result;

    if (!(jsonRootObject = CreateJsonParser(subRequestBuffer)))
        goto CleanupExit;

    if (!GetJsonValueAsUlong(jsonRootObject, "response_code"))
        goto CleanupExit;

    result = PhAllocate(sizeof(VIRUSTOTAL_FILE_REPORT_RESULT));
    memset(result, 0, sizeof(VIRUSTOTAL_FILE_REPORT_RESULT));

    result->Total = PhFormatUInt64(GetJsonValueAsUlong(jsonRootObject, "total"), FALSE);
    result->Positives = PhFormatUInt64(GetJsonValueAsUlong(jsonRootObject, "positives"), FALSE);
    result->Resource = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "resource"));
    result->ScanId = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "scan_id"));
    result->Md5 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "md5"));
    result->Sha1 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "sha1"));
    result->Sha256 = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "sha256"));
    result->ScanDate = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "scan_date"));
    result->Permalink = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "permalink"));
    result->StatusMessage = PhZeroExtendToUtf16(GetJsonValueAsString(jsonRootObject, "verbose_msg"));

    //if (jsonScanObject = JsonGetObject(jsonRootObject, "scans"))
    //{
    //    PPH_LIST jsonArrayList;
    //
    //    if (jsonArrayList = JsonGetObjectArrayList(jsonScanObject))
    //    {
    //        result->ScanResults = PhCreateList(jsonArrayList->Count);
    //
    //        for (ULONG i = 0; i < jsonArrayList->Count; i++)
    //        {
    //            PJSON_ARRAY_LIST_OBJECT object = jsonArrayList->Items[i];
    //            //BOOLEAN detected = GetJsonValueAsBool(object->Entry, "detected") == TRUE;
    //            //PSTR version = GetJsonValueAsString(object->Entry, "version");
    //            //PSTR result = GetJsonValueAsString(object->Entry, "result");
    //            //PSTR update = GetJsonValueAsString(object->Entry, "update");
    //
    //            PhFree(object);
    //        }
    //
    //        PhDereferenceObject(jsonArrayList);
    //    }
    //}

    return result;
}
Esempio n. 23
0
static int winhttp_connect(
	winhttp_subtransport *t)
{
	wchar_t *wide_host;
	int32_t port;
	wchar_t *wide_ua;
	git_buf ua = GIT_BUF_INIT;
	int error = -1;
	int default_timeout = TIMEOUT_INFINITE;
	int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
	DWORD protocols =
		WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
		WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
		WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;

	t->session = NULL;
	t->connection = NULL;

	/* Prepare port */
	if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0)
		return -1;

	/* Prepare host */
	if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) {
		giterr_set(GITERR_OS, "unable to convert host to wide characters");
		return -1;
	}


	if ((error = git_http__user_agent(&ua)) < 0) {
		git__free(wide_host);
		return error;
	}

	if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) {
		giterr_set(GITERR_OS, "unable to convert host to wide characters");
		git__free(wide_host);
		git_buf_free(&ua);
		return -1;
	}

	git_buf_free(&ua);

	/* Establish session */
	t->session = WinHttpOpen(
		wide_ua,
		WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
		WINHTTP_NO_PROXY_NAME,
		WINHTTP_NO_PROXY_BYPASS,
		0);

	if (!t->session) {
		giterr_set(GITERR_OS, "failed to init WinHTTP");
		goto on_error;
	}

	/*
	 * Do a best-effort attempt to enable TLS 1.2 but allow this to
	 * fail; if TLS 1.2 support is not available for some reason,
	 * ignore the failure (it will keep the default protocols).
	 */
	WinHttpSetOption(t->session,
		WINHTTP_OPTION_SECURE_PROTOCOLS,
		&protocols,
		sizeof(protocols));

	if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
		giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP");
		goto on_error;
	}


	/* Establish connection */
	t->connection = WinHttpConnect(
		t->session,
		wide_host,
		(INTERNET_PORT) port,
		0);

	if (!t->connection) {
		giterr_set(GITERR_OS, "failed to connect to host");
		goto on_error;
	}

	if (WinHttpSetStatusCallback(t->connection, winhttp_status, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0) == WINHTTP_INVALID_STATUS_CALLBACK) {
		giterr_set(GITERR_OS, "failed to set status callback");
		goto on_error;
	}

	error = 0;

on_error:
	if (error < 0)
		winhttp_close_connection(t);

	git__free(wide_host);
	git__free(wide_ua);

	return error;
}
Esempio n. 24
0
void WindowsHttpDownloader::InternalConnect(char* append_headers)
{
	WCHAR host_name[1024] = {};
	if (wcslen(_url.lpszHostName) > 1024) {
		SetEvent(_events[EventErr]);
		return;
	}
	wcscpy(host_name, _url.lpszHostName);
	if (wcsstr(host_name, L"/") != NULL)
		*wcsstr(host_name, L"/") = 0;
	if (wcsstr(host_name, L":") != NULL)
		*wcsstr(host_name, L":") = 0;

	_http.connect = WinHttpConnect(_http.session, host_name, _url.nPort, 0);
	if (_http.connect == NULL) {
		SetEvent(_events[EventErr]);
		return;
	}
	SetEvent(_events[EventConnect]);
	if (_abort_download)
		return;

	_http.request = WinHttpOpenRequest(_http.connect, L"GET",
		_url.dwUrlPathLength > 0 ? _url.lpszUrlPath : NULL,
		NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
	if (_http.connect == NULL) {
		SetEvent(_events[EventErr]);
		return;
	}
	if (_abort_download)
		return;

	DWORD temp = WINHTTP_DISABLE_AUTHENTICATION;
	WinHttpSetOption(_http.request, WINHTTP_OPTION_DISABLE_FEATURE, &temp, sizeof(temp));

	int hcount = _user_heads.size();
	for (int i = 0; i < hcount; i++) {
		WCHAR header[MAX_PATH], hvalue[1024];
		header[0] = hvalue[0] = 0;
		auto h = _user_heads.front();
		_user_heads.pop();
		AnsiToUnicode(h.name, header);
		AnsiToUnicode(h.value, hvalue, _countof(hvalue));
		h.Free();
		auto str = (LPWSTR)malloc(4096);
		RtlZeroMemory(str, 4096);
		wcscpy(str, header);
		wcscat(str, L": ");
		wcscat(str, hvalue);
		WinHttpAddRequestHeaders(_http.request, str, -1, WINHTTP_ADDREQ_FLAG_ADD);
		free(str);
	}

	LPWSTR add_headers = NULL;
	if (append_headers) {
		int add_head_len = MultiByteToWideChar(CP_ACP, 0, append_headers, -1, NULL, 0);
		if (add_head_len > 1) {
			add_headers = (LPWSTR)calloc(2, add_head_len);
			if (add_headers)
				MultiByteToWideChar(CP_ACP, 0, append_headers, -1, add_headers, add_head_len + 1);
		}
	}
	if (!WinHttpSendRequest(_http.request,
		add_headers, -1,
		WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) {
		if (add_headers)
			free(add_headers);
		_http.Close();
		SetEvent(_events[EventErr]);
		return;
	}
	if (add_headers)
		free(add_headers);
	SetEvent(_events[EventSendRequest]);
	if (_abort_download)
		return;

	if (!WinHttpReceiveResponse(_http.request, NULL)) {
		_http.Close();
		SetEvent(_events[EventErr]);
		return;
	}

	//status code...
	temp = MAX_PATH;
	WCHAR scode[MAX_PATH] = {};
	WinHttpQueryHeaders(_http.request, WINHTTP_QUERY_STATUS_CODE,
		WINHTTP_HEADER_NAME_BY_INDEX, &scode, &temp, WINHTTP_NO_HEADER_INDEX);
	_http.status_code = wcstol(scode, NULL, 10);

	//headers...
	WinHttpQueryHeaders(_http.request, WINHTTP_QUERY_RAW_HEADERS_CRLF,
		WINHTTP_HEADER_NAME_BY_INDEX, NULL, (LPDWORD)&_recv_headers_zero_size, WINHTTP_NO_HEADER_INDEX);
	_recv_headers = (wchar_t*)calloc(_recv_headers_zero_size, 2);
	if (_recv_headers)
		WinHttpQueryHeaders(_http.request, WINHTTP_QUERY_RAW_HEADERS_CRLF,
		WINHTTP_HEADER_NAME_BY_INDEX, _recv_headers, (LPDWORD)&_recv_headers_zero_size, WINHTTP_NO_HEADER_INDEX);

	WinHttpQueryHeaders(_http.request, WINHTTP_QUERY_RAW_HEADERS,
		WINHTTP_HEADER_NAME_BY_INDEX, NULL, (LPDWORD)&_recv_headers_zero_size, WINHTTP_NO_HEADER_INDEX);
	_recv_headers_zero = (unsigned char*)calloc(_recv_headers_zero_size, 2);
	if (_recv_headers_zero)
		WinHttpQueryHeaders(_http.request, WINHTTP_QUERY_RAW_HEADERS,
		WINHTTP_HEADER_NAME_BY_INDEX, _recv_headers_zero, (LPDWORD)&_recv_headers_zero_size, WINHTTP_NO_HEADER_INDEX);

	SetEvent(_events[EventReceiveResponse]);
	if (_abort_download)
		return;

	if (_http.status_code >= 400)
		SetEvent(_events[EventStatusCode400]);
	else
		InternalDownload();
}
Esempio n. 25
0
// Read URL server
LPSTR SoffidEssoManager::readURL (HINTERNET hSession, const wchar_t* host, int port,
		LPCWSTR path, BOOL allowUnknownCA, size_t *pSize)
{
	BOOL bResults = FALSE;
	HINTERNET hConnect = NULL, hRequest = NULL;

	DWORD dwDownloaded = -1;
	BYTE *buffer = NULL;

	if (debug)
	{
		log("Connecting to %s:%d...\n", host, port);
	}

	hConnect = WinHttpConnect(hSession, host, port, 0);

	if (hConnect)
	{
		if (debug)
		{
			log("Performing request %s...\n", path);
		}

		hRequest = WinHttpOpenRequest(hConnect, L"GET", path, NULL, WINHTTP_NO_REFERER,
				WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
	}

	// Send a request.
	if (hRequest)
	{
		if (debug)
			log("Sending request ...\n");

		WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, NULL, 0);

		if (allowUnknownCA)
		{
			DWORD flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA;
			WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, (LPVOID) &flags,
					sizeof flags);
		}

		bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
				WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
	}

	if (bResults && allowUnknownCA)
	{
		// Agreagar la CA ROOT
		PCERT_CONTEXT context;
		DWORD dwSize = sizeof context;
		BOOL result = WinHttpQueryOption(hRequest, WINHTTP_OPTION_SERVER_CERT_CONTEXT,
				&context, &dwSize);

		if (!result)
		{
			log("Cannot get context\n");
//			notifyError();
		}

		PCCERT_CONTEXT issuerContext = CertFindCertificateInStore(context->hCertStore,
				X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
		HCERTSTORE systemStore = CertOpenStore((LPCSTR) 13, // CERT_STORE_PROV_SYSTEM_REGISTRY_W
				0, (HCRYPTPROV) NULL, (2 << 16) | // CERT_SYSTEM_STORE_LOCAL_MACHINE
						0x1000, // CERT_STORE_MAXIMUM_ALLOWED
				L"ROOT");
		CertAddCertificateContextToStore(systemStore, issuerContext,
				1 /*CERT_STORE_ADD_NEW*/, NULL);

		CertFreeCertificateContext(issuerContext);
		CertFreeCertificateContext(context);
	}

	// End the request.
	if (bResults)
	{
		if (debug)
			log("Waiting for response....\n");

		bResults = WinHttpReceiveResponse(hRequest, NULL);
	}

	// Keep checking for data until there is nothing left.
	DWORD used = 0;
	if (bResults)
	{
		const DWORD chunk = 4096;
		DWORD allocated = 0;
		do
		{
			if (used + chunk > allocated)
			{
				allocated += chunk;
				buffer = (LPBYTE) realloc(buffer, allocated);
			}

			dwDownloaded = 0;
			if (!WinHttpReadData(hRequest, &buffer[used], chunk, &dwDownloaded))
				dwDownloaded = -1;

			else
				used += dwDownloaded;
		} while (dwDownloaded > 0);

		buffer[used] = '\0';
	}

	DWORD dw = GetLastError();
	if (!bResults && debug)
	{
		if (dw == ERROR_WINHTTP_CANNOT_CONNECT)
			log("Error: Cannot connect\n");
		else if (dw == ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
			log("Error: Client CERT required\n");
		else if (dw == ERROR_WINHTTP_CONNECTION_ERROR)
			log("Error: Connection error\n");
		else if (dw == ERROR_WINHTTP_INCORRECT_HANDLE_STATE)
			log("Error: ERROR_WINHTTP_INCORRECT_HANDLE_STATE\n");
		else if (dw == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE)
			log("Error: ERROR_WINHTTP_INCORRECT_HANDLE_TYPE\n");
		else if (dw == ERROR_WINHTTP_INTERNAL_ERROR)
			log("Error: ERROR_WINHTTP_INTERNAL_ERROR\n");
		else if (dw == ERROR_WINHTTP_INVALID_URL)
			log("Error: ERROR_WINHTTP_INVALID_URL\n");
		else if (dw == ERROR_WINHTTP_LOGIN_FAILURE)
			log("Error: ERROR_WINHTTP_LOGIN_FAILURE\n");
		else if (dw == ERROR_WINHTTP_NAME_NOT_RESOLVED)
			log("Error: ERROR_WINHTTP_NAME_NOT_RESOLVED\n");
		else if (dw == ERROR_WINHTTP_OPERATION_CANCELLED)
			log("Error: ERROR_WINHTTP_OPERATION_CANCELLED\n");
		else if (dw == ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW)
			log("Error: ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW\n");
		else if (dw == ERROR_WINHTTP_SECURE_FAILURE)
			log("Error: ERROR_WINHTTP_SECURE_FAILURE\n");
		else if (dw == ERROR_WINHTTP_SHUTDOWN)
			log("Error: ERROR_WINHTTP_SHUTDOWN\n");
		else if (dw == ERROR_WINHTTP_TIMEOUT)
			log("Error: ERROR_WINHTTP_TIMEOUT\n");
		else if (dw == ERROR_WINHTTP_UNRECOGNIZED_SCHEME)
			log("Error: ERROR_WINHTTP_UNRECOGNIZED_SCHEME\n");
		else if (dw == ERROR_NOT_ENOUGH_MEMORY)
			log("Error: ERROR_NOT_ENOUGH_MEMORY\n");
		else if (dw == ERROR_INVALID_PARAMETER)
			log("Error: ERROR_INVALID_PARAMETER\n");
		else if (dw == ERROR_WINHTTP_RESEND_REQUEST)
			log("Error:  ERROR_WINHTTP_RESEND_REQUEST\n");
		else if (dw != ERROR_SUCCESS)
		{
			log("Unkonwn error %d\n", dw);
		}
//		notifyError();
	}

	// Close any open handles.
	if (hRequest)
		WinHttpCloseHandle(hRequest);
	if (hConnect)
		WinHttpCloseHandle(hConnect);
	if (hSession)
		WinHttpCloseHandle(hSession);

	SetLastError(dw);

	if (pSize != NULL)
		*pSize = used;

	return (LPSTR) buffer;
}
Esempio n. 26
0
static BOOL transfer_file_http(BackgroundCopyFileImpl *file, URL_COMPONENTSW *uc,
                               const WCHAR *tmpfile)
{
    BackgroundCopyJobImpl *job = file->owner;
    HANDLE handle;
    HINTERNET ses, con = NULL, req = NULL;
    DWORD flags = (uc->nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0;
    char buf[4096];
    BOOL ret = FALSE;
    DWORD written;

    transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_CONNECTING);

    if (!(ses = WinHttpOpen(NULL, 0, NULL, NULL, WINHTTP_FLAG_ASYNC))) return FALSE;
    WinHttpSetStatusCallback(ses, progress_callback_http, WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS, 0);
    if (!WinHttpSetOption(ses, WINHTTP_OPTION_CONTEXT_VALUE, &file, sizeof(file))) goto done;

    if (!(con = WinHttpConnect(ses, uc->lpszHostName, uc->nPort, 0))) goto done;
    if (!(req = WinHttpOpenRequest(con, NULL, uc->lpszUrlPath, NULL, NULL, NULL, flags))) goto done;
    if (!set_request_credentials(req, job)) goto done;

    if (!(WinHttpSendRequest(req, job->http_options.headers, ~0u, NULL, 0, 0, (DWORD_PTR)file))) goto done;
    if (wait_for_completion(job) || job->error.code) goto done;

    if (!(WinHttpReceiveResponse(req, NULL))) goto done;
    if (wait_for_completion(job) || job->error.code) goto done;

    transitionJobState(job, BG_JOB_STATE_CONNECTING, BG_JOB_STATE_TRANSFERRING);

    handle = CreateFileW(tmpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (handle == INVALID_HANDLE_VALUE) goto done;

    for (;;)
    {
        file->read_size = 0;
        if (!(ret = WinHttpReadData(req, buf, sizeof(buf), NULL))) break;
        if (wait_for_completion(job) || job->error.code)
        {
            ret = FALSE;
            break;
        }
        if (!file->read_size) break;
        if (!(ret = WriteFile(handle, buf, file->read_size, &written, NULL))) break;

        EnterCriticalSection(&job->cs);
        file->fileProgress.BytesTransferred += file->read_size;
        job->jobProgress.BytesTransferred += file->read_size;
        LeaveCriticalSection(&job->cs);
    }

    CloseHandle(handle);

done:
    WinHttpCloseHandle(req);
    WinHttpCloseHandle(con);
    WinHttpCloseHandle(ses);
    if (!ret) DeleteFileW(tmpfile);

    SetEvent(job->done);
    return ret;
}
Esempio n. 27
0
int
__cdecl
wmain(
    int argc,
    WCHAR **argv
)
{
    DWORD dwError = ERROR_SUCCESS;
    HINTERNET hSession = NULL;
    HINTERNET hConnect = NULL;
    HINTERNET hRequest = NULL;
    DWORD dwStatusCode = 0;
    DWORD dwSize = sizeof(dwStatusCode);
    DWORD dwAutoLogonPolicy = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
    PWSTR pwszServerName = NULL;

    if (argc != 2)
    {
        wprintf(L"Usage: %s <servername>\n", argv[0]);
        goto Exit;
    }

    pwszServerName = argv[1];

    // Use WinHttpOpen to obtain a session handle and specify no proxy  
    hSession = WinHttpOpen(USER_AGENT,
                           WINHTTP_ACCESS_TYPE_NO_PROXY,
                           WINHTTP_NO_PROXY_NAME,
                           WINHTTP_NO_PROXY_BYPASS,
                           0);
    if (hSession == NULL)
    {
        dwError = GetLastError();
        wprintf(L"WinHttpOpen failed with error %d\n", dwError);
        goto Exit;
    }

    // Use WinHttpConnect to specify target server and port
    hConnect = WinHttpConnect(hSession,
                              pwszServerName,
                              INTERNET_DEFAULT_HTTP_PORT,
                              0);
    if (hConnect == NULL)
    {
        dwError = GetLastError();
        wprintf(L"WinHttpConnect failed with error %d\n", dwError);
        goto Exit;
    }

    // Use WinHttpOpenRequest to open a GET request and specify taget path
    hRequest = WinHttpOpenRequest(hConnect,
                                  L"GET",
                                  TARGET_PATH,
                                  NULL,
                                  WINHTTP_NO_REFERER,
                                  WINHTTP_DEFAULT_ACCEPT_TYPES,
                                  0);
    if (hRequest == NULL)
    {
        dwError = GetLastError();
        wprintf(L"WinHttpOpenRequest failed with error %d\n", dwError);
        goto Exit;
    }

    // Use WinHttpSetOption to set autologon policy to low level
    // to include the default credentials in a request
    if (!WinHttpSetOption(hRequest,
                          WINHTTP_OPTION_AUTOLOGON_POLICY,
                          &dwAutoLogonPolicy,
                          sizeof(dwAutoLogonPolicy)))
    {
        dwError = GetLastError();
        wprintf(L"WinHttpSetOption failed with error %d\n", dwError);
        goto Exit;
    }

    // Use WinHttpSetCredentials with NULL username and password
    // to use default credentials
    if (!WinHttpSetCredentials(hRequest,
                               WINHTTP_AUTH_TARGET_SERVER,
                               WINHTTP_AUTH_SCHEME_NTLM,
                               NULL,
                               NULL,
                               NULL))
    {
        dwError = GetLastError();
        wprintf(L"WinHttpSetCredentials failed with error %d\n", dwError);
        goto Exit;
    }

    // Use WinHttpSendRequest to send the request and
    // specify no additional headers and request data
    if (!WinHttpSendRequest(hRequest,
                            WINHTTP_NO_ADDITIONAL_HEADERS,
                            0,
                            WINHTTP_NO_REQUEST_DATA, 
                            0,
                            0, 
                            0))
    {
        dwError = GetLastError();
        wprintf(L"WinHttpSendRequest failed with error %d\n", dwError);
        goto Exit;
    }

    // Use WinHttpReceiveResponse to receive the response
    if (!WinHttpReceiveResponse(hRequest,
                                NULL))
    {
        dwError = GetLastError();
        wprintf(L"WinHttpReceiveResponse failed with error %d\n", dwError);
        goto Exit;
    }

    // Use WinHttpQueryHeaders to retrieve the status code
    if (!WinHttpQueryHeaders(hRequest,
                             WINHTTP_QUERY_FLAG_NUMBER |
                             WINHTTP_QUERY_STATUS_CODE,
                             NULL,
                             &dwStatusCode,
                             &dwSize,
                             NULL))
    {
        dwError = GetLastError();
        wprintf(L"WinHttpQueryHeaders failed with error %d\n", dwError);
        goto Exit;
    }

    // Expect to get status code 200
    if(dwStatusCode == 200)  
    {
        wprintf(L"Got expected status code=200\n");
    }
    else
    {
        wprintf(L"Unexpected status code=%d\n", dwStatusCode);
    }

Exit:
    if (hRequest != NULL)
    {
        WinHttpCloseHandle(hRequest);
    }

    if (hConnect != NULL)
    {
        WinHttpCloseHandle(hConnect);
    }

    if (hSession != NULL)
    {
        WinHttpCloseHandle(hSession);
    }

    return dwError;
}
Esempio n. 28
0
DWORD
BeginRequest(
    PWSTR pwszPath,
    PMYCONTEXT *ppContext
    )

/*++

Routine Description:

    Creates and begins a request.

Arguments:

    pwszPath - Supplies the abs_path to use.

    ppContext - Returns a context, caller should use it as follows:
                1. At least one of EndRequest and CancelRequest.
                2. DereferenceContext

Return Value:

    Win32.

--*/

{
    DWORD dwError = ERROR_SUCCESS;
    HINTERNET hRequest = NULL;
    BOOL fLocked = FALSE;
    PCWSTR pwszAcceptTypes[] = {L"*/*", NULL};
    PMYCONTEXT pContext = NULL;

    *ppContext = NULL;

    hRequest = WinHttpOpenRequest(g_hConnect,
                                  L"GET",
                                  pwszPath,
                                  NULL,              // version
                                  NULL,              // referrer
                                  pwszAcceptTypes,
                                  0);                // flags
    if (hRequest == NULL) 
    {
        dwError = GetLastError();
        goto Exit;
    }

    dwError = CreateMyContext(hRequest, &pContext);
    if (dwError != ERROR_SUCCESS)
    {
        goto Exit;
    }

    //
    // pContext now owns hRequest.
    //

    hRequest = NULL;

    dwError = LockRequestHandle(pContext);
    if (dwError != ERROR_SUCCESS)
    {
        goto Exit;
    }

    fLocked = TRUE;

    //
    // Take an extra reference for async callbacks.
    //

    ReferenceContext(pContext);
    if (!WinHttpSetOption(pContext->RequestHandle,
                          WINHTTP_OPTION_CONTEXT_VALUE,
                          &pContext,
                          sizeof(pContext)))
    {
        dwError = GetLastError();

        //
        // Failed to kick off async work, so no async callbacks, so revoke that
        // reference.
        //

        DereferenceContext(pContext);

        printf("WinHttpSetOption WINHTTP_OPTION_CONTEXT_VALUE failed\n");
        goto Exit;
    }


    if (!WinHttpSendRequest(pContext->RequestHandle,
                            NULL,
                            0,
                            NULL,
                            0,
                            0,
                            0)) 
    {
        dwError = GetLastError();
        printf("WinHttpSendRequest failed\n");
        goto Exit;
    }

    UnlockRequestHandle(pContext);
    fLocked = FALSE;

    //
    // Hand off context ownership to caller.
    //

    *ppContext = pContext;
    pContext = NULL;

Exit:

    if (fLocked)
    {
        UnlockRequestHandle(pContext);
        fLocked = FALSE;
    }

    if (pContext != NULL)
    {
        DereferenceContext(pContext);
        pContext = NULL;
    }

    if (hRequest != NULL)
    {
        WinHttpCloseHandle(hRequest);
        hRequest = NULL;
    }

    return dwError;
}
HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
    HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content,
    size_t contentLength, unsigned int* statusCode,
    HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
{
    HTTPAPI_RESULT result;
    if (g_HTTPAPIState != HTTPAPI_INITIALIZED)
    {
        LogError("g_HTTPAPIState not HTTPAPI_INITIALIZED");
        result = HTTPAPI_NOT_INIT;
    }
    else
    {
        HTTP_HANDLE_DATA* handleData = (HTTP_HANDLE_DATA*)handle;

        if ((handleData == NULL) ||
            (relativePath == NULL) ||
            (httpHeadersHandle == NULL))
        {
            result = HTTPAPI_INVALID_ARG;
            LogError("NULL parameter detected (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
        }
        else
        {
            wchar_t* requestTypeString = NULL;

            switch (requestType)
            {
            default:
                break;

            case HTTPAPI_REQUEST_GET:
                requestTypeString = L"GET";
                break;

            case HTTPAPI_REQUEST_POST:
                requestTypeString = L"POST";
                break;

            case HTTPAPI_REQUEST_PUT:
                requestTypeString = L"PUT";
                break;

            case HTTPAPI_REQUEST_DELETE:
                requestTypeString = L"DELETE";
                break;

            case HTTPAPI_REQUEST_PATCH:
                requestTypeString = L"PATCH";
                break;
            }

            if (requestTypeString == NULL)
            {
                result = HTTPAPI_INVALID_ARG;
                LogError("requestTypeString was NULL (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
            }
            else
            {
                const char* headers2;
                headers2 = ConstructHeadersString(httpHeadersHandle);
                if (headers2 != NULL)
                {
                    size_t requiredCharactersForRelativePath = MultiByteToWideChar(CP_ACP, 0, relativePath, -1, NULL, 0);
                    wchar_t* relativePathTemp = (wchar_t*)malloc((requiredCharactersForRelativePath+1) * sizeof(wchar_t));
                    result = HTTPAPI_OK; /*legacy code*/

                    if (relativePathTemp == NULL)
                    {
                        result = HTTPAPI_ALLOC_FAILED;
                        LogError("malloc failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                    }
                    else
                    {
                        if (MultiByteToWideChar(CP_ACP, 0, relativePath, -1, relativePathTemp, (int)requiredCharactersForRelativePath) == 0)
                        {
                            result = HTTPAPI_STRING_PROCESSING_ERROR;
                            LogError("MultiByteToWideChar was 0. (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                        }
                        else
                        {
                            size_t requiredCharactersForHeaders = MultiByteToWideChar(CP_ACP, 0, headers2, -1, NULL, 0);

                            wchar_t* headersTemp = (wchar_t*)malloc((requiredCharactersForHeaders +1) * sizeof(wchar_t) );
                            if (headersTemp == NULL)
                            {
                                result = HTTPAPI_STRING_PROCESSING_ERROR;
                                LogError("MultiByteToWideChar was 0. (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                            }
                            else
                            {
                                if (MultiByteToWideChar(CP_ACP, 0, headers2, -1, headersTemp, (int)requiredCharactersForHeaders) == 0)
                                {
                                    result = HTTPAPI_STRING_PROCESSING_ERROR;
                                    LogError("MultiByteToWideChar was 0(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                }
                                else
                                {
                                    HINTERNET requestHandle = WinHttpOpenRequest(
                                        handleData->ConnectionHandle,
                                        requestTypeString,
                                        relativePathTemp,
                                        NULL,
                                        WINHTTP_NO_REFERER,
                                        WINHTTP_DEFAULT_ACCEPT_TYPES,
                                        WINHTTP_FLAG_SECURE);
                                    if (requestHandle == NULL)
                                    {
                                        result = HTTPAPI_OPEN_REQUEST_FAILED;
                                        LogErrorWinHTTPWithGetLastErrorAsString("WinHttpOpenRequest failed (result = %s).", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                    }
                                    else
                                    {
                                        if ((handleData->x509SchannelHandle!=NULL) && 
                                            !WinHttpSetOption(
                                                requestHandle,
                                                WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
                                                (void*)x509_schannel_get_certificate_context(handleData->x509SchannelHandle),
                                                sizeof(CERT_CONTEXT)
                                        ))
                                        {
                                            LogErrorWinHTTPWithGetLastErrorAsString("unable to WinHttpSetOption");
                                            result = HTTPAPI_SET_X509_FAILURE;
                                        }
                                        else
                                        {
                                            if (WinHttpSetTimeouts(requestHandle,
                                                0,                      /*_In_  int dwResolveTimeout - The initial value is zero, meaning no time-out (infinite). */
                                                60000,                  /*_In_  int dwConnectTimeout, -  The initial value is 60,000 (60 seconds).*/
                                                handleData->timeout,    /*_In_  int dwSendTimeout, -  The initial value is 30,000 (30 seconds).*/
                                                handleData->timeout     /* int dwReceiveTimeout The initial value is 30,000 (30 seconds).*/
                                            ) == FALSE)
                                            {
                                                result = HTTPAPI_SET_TIMEOUTS_FAILED;
                                                LogErrorWinHTTPWithGetLastErrorAsString("WinHttpOpenRequest failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                            }
                                            else
                                            {
                                                DWORD dwSecurityFlags = 0;

                                                if (!WinHttpSetOption(
                                                    requestHandle,
                                                    WINHTTP_OPTION_SECURITY_FLAGS,
                                                    &dwSecurityFlags,
                                                    sizeof(dwSecurityFlags)))
                                                {
                                                    result = HTTPAPI_SET_OPTION_FAILED;
                                                    LogErrorWinHTTPWithGetLastErrorAsString("WinHttpSetOption failed (result = %s).", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                }
                                                else
                                                {
                                                    if (!WinHttpSendRequest(
                                                        requestHandle,
                                                        headersTemp,
                                                        (DWORD)-1L, /*An unsigned long integer value that contains the length, in characters, of the additional headers. If this parameter is -1L ... */
                                                        (void*)content,
                                                        (DWORD)contentLength,
                                                        (DWORD)contentLength,
                                                        0))
                                                    {
                                                        result = HTTPAPI_SEND_REQUEST_FAILED;
                                                        LogErrorWinHTTPWithGetLastErrorAsString("WinHttpSendRequest: (result = %s).", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                    }
                                                    else
                                                    {
                                                        if (!WinHttpReceiveResponse(
                                                            requestHandle,
                                                            0))
                                                        {
                                                            result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
                                                            LogErrorWinHTTPWithGetLastErrorAsString("WinHttpReceiveResponse: (result = %s).", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                        }
                                                        else
                                                        {
                                                            DWORD dwStatusCode = 0;
                                                            DWORD dwBufferLength = sizeof(DWORD);
                                                            DWORD responseBytesAvailable;

                                                            if (!WinHttpQueryHeaders(
                                                                requestHandle,
                                                                WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
                                                                WINHTTP_HEADER_NAME_BY_INDEX,
                                                                &dwStatusCode,
                                                                &dwBufferLength,
                                                                WINHTTP_NO_HEADER_INDEX))
                                                            {
                                                                result = HTTPAPI_QUERY_HEADERS_FAILED;
                                                                LogErrorWinHTTPWithGetLastErrorAsString("WinHttpQueryHeaders failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                            }
                                                            else
                                                            {
                                                                BUFFER_HANDLE useToReadAllResponse = (responseContent != NULL) ? responseContent : BUFFER_new();

                                                                if (statusCode != NULL)
                                                                {
                                                                    *statusCode = dwStatusCode;
                                                                }

                                                                if (useToReadAllResponse == NULL)
                                                                {
                                                                    result = HTTPAPI_ERROR;
                                                                    LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                }
                                                                else
                                                                {

                                                                    int goOnAndReadEverything = 1;
                                                                    do
                                                                    {
                                                                        /*from MSDN: If no data is available and the end of the file has not been reached, one of two things happens. If the session is synchronous, the request waits until data becomes available.*/
                                                                        if (!WinHttpQueryDataAvailable(requestHandle, &responseBytesAvailable))
                                                                        {
                                                                            result = HTTPAPI_QUERY_DATA_AVAILABLE_FAILED;
                                                                            LogErrorWinHTTPWithGetLastErrorAsString("WinHttpQueryDataAvailable failed (result = %s).", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                            goOnAndReadEverything = 0;
                                                                        }
                                                                        else if (responseBytesAvailable == 0)
                                                                        {
                                                                            /*end of the stream, go out*/
                                                                            result = HTTPAPI_OK;
                                                                            goOnAndReadEverything = 0;
                                                                        }
                                                                        else
                                                                        {
                                                                            if (BUFFER_enlarge(useToReadAllResponse, responseBytesAvailable) != 0)
                                                                            {
                                                                                result = HTTPAPI_ERROR;
                                                                                LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                                goOnAndReadEverything = 0;
                                                                            }
                                                                            else
                                                                            {
                                                                                /*Add the read bytes to the response buffer*/
                                                                                size_t bufferSize;
                                                                                const unsigned char* bufferContent;

                                                                                if (BUFFER_content(useToReadAllResponse, &bufferContent) != 0)
                                                                                {
                                                                                    result = HTTPAPI_ERROR;
                                                                                    LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                                    goOnAndReadEverything = 0;
                                                                                }
                                                                                else if (BUFFER_size(useToReadAllResponse, &bufferSize) != 0)
                                                                                {
                                                                                    result = HTTPAPI_ERROR;
                                                                                    LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                                    goOnAndReadEverything = 0;
                                                                                }
                                                                                else
                                                                                {
                                                                                    DWORD bytesReceived;
                                                                                    if (!WinHttpReadData(requestHandle, (LPVOID)(bufferContent + bufferSize - responseBytesAvailable), responseBytesAvailable, &bytesReceived))
                                                                                    {
                                                                                        result = HTTPAPI_READ_DATA_FAILED;
                                                                                        LogErrorWinHTTPWithGetLastErrorAsString("WinHttpReadData failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                                        goOnAndReadEverything = 0;
                                                                                    }
                                                                                    else
                                                                                    {
                                                                                        /*if for some reason bytesReceived is zero If you are using WinHttpReadData synchronously, and the return value is TRUE and the number of bytes read is zero, the transfer has been completed and there are no more bytes to read on the handle.*/
                                                                                        if (bytesReceived == 0)
                                                                                        {
                                                                                            /*end of everything, but this looks like an error still, or a non-conformance between WinHttpQueryDataAvailable and WinHttpReadData*/
                                                                                            result = HTTPAPI_READ_DATA_FAILED;
                                                                                            LogError("bytesReceived was unexpectedly zero (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                                            goOnAndReadEverything = 0;
                                                                                        }
                                                                                        else
                                                                                        {
                                                                                            /*all is fine, keep going*/
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }

                                                                    } while (goOnAndReadEverything != 0);
                                                                }
                                                            }

                                                            if (result == HTTPAPI_OK && responseHeadersHandle != NULL)
                                                            {
                                                                wchar_t* responseHeadersTemp;
                                                                DWORD responseHeadersTempLength = sizeof(responseHeadersTemp);

                                                                (void)WinHttpQueryHeaders(
                                                                    requestHandle,
                                                                    WINHTTP_QUERY_RAW_HEADERS_CRLF,
                                                                    WINHTTP_HEADER_NAME_BY_INDEX,
                                                                    WINHTTP_NO_OUTPUT_BUFFER,
                                                                    &responseHeadersTempLength,
                                                                    WINHTTP_NO_HEADER_INDEX);

                                                                responseHeadersTemp = (wchar_t*)malloc(responseHeadersTempLength + 2);
                                                                if (responseHeadersTemp == NULL)
                                                                {
                                                                    result = HTTPAPI_ALLOC_FAILED;
                                                                    LogError("malloc failed: (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
                                                                }
                                                                else
                                                                {
                                                                    if (WinHttpQueryHeaders(
                                                                        requestHandle,
                                                                        WINHTTP_QUERY_RAW_HEADERS_CRLF,
                                                                        WINHTTP_HEADER_NAME_BY_INDEX,
                                                                        responseHeadersTemp,
                                                                        &responseHeadersTempLength,
                                                                        WINHTTP_NO_HEADER_INDEX))
                                                                    {
                                                                        wchar_t *next_token;
                                                                        wchar_t* token = wcstok_s(responseHeadersTemp, L"\r\n", &next_token);
                                                                        while ((token != NULL) &&
                                                                            (token[0] != L'\0'))
                                                                        {
                                                                            char* tokenTemp;
                                                                            size_t tokenTemp_size;

                                                                            tokenTemp_size = WideCharToMultiByte(CP_ACP, 0, token, -1, NULL, 0, NULL, NULL);
                                                                            if (tokenTemp_size == 0)
                                                                            {
                                                                                LogError("WideCharToMultiByte failed");
                                                                            }
                                                                            else
                                                                            {
                                                                                tokenTemp = (char*)malloc(sizeof(char)*tokenTemp_size);
                                                                                if (tokenTemp == NULL)
                                                                                {
                                                                                    LogError("malloc failed");
                                                                                }
                                                                                else
                                                                                {
                                                                                    if (WideCharToMultiByte(CP_ACP, 0, token, -1, tokenTemp, (int)tokenTemp_size, NULL, NULL) > 0)
                                                                                    {
                                                                                        /*breaking the token in 2 parts: everything before the first ":" and everything after the first ":"*/
                                                                                        /* if there is no such character, then skip it*/
                                                                                        /*if there is a : then replace is by a '\0' and so it breaks the original string in name and value*/

                                                                                        char* whereIsColon = strchr(tokenTemp, ':');
                                                                                        if (whereIsColon != NULL)
                                                                                        {
                                                                                            *whereIsColon = '\0';
                                                                                            if (HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, tokenTemp, whereIsColon + 1) != HTTP_HEADERS_OK)
                                                                                            {
                                                                                                LogError("HTTPHeaders_AddHeaderNameValuePair failed");
                                                                                                result = HTTPAPI_HTTP_HEADERS_FAILED;
                                                                                                break;
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                    else
                                                                                    {
                                                                                        LogError("WideCharToMultiByte failed");
                                                                                    }
                                                                                    free(tokenTemp);
                                                                                }
                                                                            }


                                                                            token = wcstok_s(NULL, L"\r\n", &next_token);
                                                                        }
                                                                    }
                                                                    else
                                                                    {
                                                                        LogError("WinHttpQueryHeaders failed");
                                                                    }

                                                                    free(responseHeadersTemp);
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                        (void)WinHttpCloseHandle(requestHandle);
                                    }
                                }
                                free(headersTemp);
                            }
                        }
                        free(relativePathTemp);
                    }
                    free((void*)headers2);
                }
                else
                {
                    result = HTTPAPI_ALLOC_FAILED; /*likely*/
                    LogError("ConstructHeadersString failed");
                }
            }
        }
    }

    return result;
}