Proxy* WinHttpIO::getautoproxy() { Proxy* proxy = new Proxy(); proxy->setProxyType(Proxy::NONE); WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyConfig = { 0 }; if (WinHttpGetIEProxyConfigForCurrentUser(&ieProxyConfig) == TRUE) { if (ieProxyConfig.lpszProxy) { string proxyURL; proxy->setProxyType(Proxy::CUSTOM); int len = wcslen(ieProxyConfig.lpszProxy); proxyURL.assign((const char*)ieProxyConfig.lpszProxy, len * sizeof(wchar_t) + 1); // only save one proxy for (int i = 0; i < len; i++) { wchar_t* character = (wchar_t*)(proxyURL.data() + i * sizeof(wchar_t)); if (*character == ' ' || *character == ';') { proxyURL.resize(i*sizeof(wchar_t)); len = i; break; } } // remove protocol prefix, if any for (int i = len - 1; i >= 0; i--) { wchar_t* character = (wchar_t*)(proxyURL.data() + i * sizeof(wchar_t)); if (*character == '/') { proxyURL = proxyURL.substr((i + 1) * sizeof(wchar_t)); break; } } proxy->setProxyURL(&proxyURL); } else if (ieProxyConfig.lpszAutoConfigUrl || ieProxyConfig.fAutoDetect == TRUE) { WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions; if (ieProxyConfig.lpszAutoConfigUrl) { autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL; autoProxyOptions.lpszAutoConfigUrl = ieProxyConfig.lpszAutoConfigUrl; autoProxyOptions.dwAutoDetectFlags = 0; } else { autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; autoProxyOptions.lpszAutoConfigUrl = NULL; autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; } autoProxyOptions.fAutoLogonIfChallenged = TRUE; autoProxyOptions.lpvReserved = NULL; autoProxyOptions.dwReserved = 0; WINHTTP_PROXY_INFO proxyInfo; if (WinHttpGetProxyForUrl(hSession, L"https://g.api.mega.co.nz/", &autoProxyOptions, &proxyInfo)) { if (proxyInfo.lpszProxy) { string proxyURL; proxy->setProxyType(Proxy::CUSTOM); proxyURL.assign((const char*)proxyInfo.lpszProxy, wcslen(proxyInfo.lpszProxy) * sizeof(wchar_t)); proxy->setProxyURL(&proxyURL); } } } } if (ieProxyConfig.lpszProxy) { GlobalFree(ieProxyConfig.lpszProxy); } if (ieProxyConfig.lpszProxyBypass) { GlobalFree(ieProxyConfig.lpszProxyBypass); } if (ieProxyConfig.lpszAutoConfigUrl) { GlobalFree(ieProxyConfig.lpszAutoConfigUrl); } return proxy; }
/*! * @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; }
DWORD ProxyResolver::GetProxyForAutoSettings( _In_ HINTERNET hSession, _In_z_ PCWSTR pwszUrl, _In_opt_z_ PCWSTR pwszAutoConfigUrl, _Outptr_result_maybenull_ PWSTR *ppwszProxy, _Outptr_result_maybenull_ PWSTR *ppwszProxyBypass ) /*++ Routine Description: Uses Auto detection or AutoConfigURL to run WinHttpGetProxyForUrl. Additionally provides autologon by calling once without autologon, which is most performant, and then with autologon if logon fails. Arguments: hSession - The WinHttp session to use for the proxy resolution. pwszUrl - The URL to get the proxy for. pwszAutoConfig - The autoconfig URL or NULL for Autodetection. ppwszProxy - Upon success, the proxy string found for pwszUrl or NULL if no proxy should be used for this URL. Use GlobalFree to free. ppwszProxyBypass - Upon success, the proxy bypass string found for pwszUrl or NULL if there is no proxy bypass for the configuration type. Use GlobalFree to free. Return Value: WIN32 Error codes. The caller should use IsRecoverableAutoProxyError to decide whether execution can continue. --*/ { DWORD dwError = ERROR_SUCCESS; WINHTTP_AUTOPROXY_OPTIONS waoOptions = {}; WINHTTP_PROXY_INFO wpiProxyInfo = {}; *ppwszProxy = NULL; *ppwszProxyBypass = NULL; if (pwszAutoConfigUrl) { waoOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL; waoOptions.lpszAutoConfigUrl = pwszAutoConfigUrl; } else { waoOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; waoOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; } // // First call with no autologon. Autologon prevents the // session (in proc) or autoproxy service (out of proc) from caching // the proxy script. This causes repetitive network traffic, so it is // best not to do autologon unless it is required according to the // result of WinHttpGetProxyForUrl. // This applies to both WinHttpGetProxyForUrl and WinhttpGetProxyForUrlEx. // if (m_fExtendedAPI) { m_hEvent = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS); if (m_hEvent == NULL) { dwError = GetLastError(); goto quit; } dwError = GetProxyForUrlEx(hSession, pwszUrl, &waoOptions); if (dwError != ERROR_WINHTTP_LOGIN_FAILURE) { // // Unless we need to retry with auto-logon exit the function with the // result, on success the proxy list will be stored in m_wprProxyResult // by GetProxyCallBack. // goto quit; } // // Enable autologon if challenged. // waoOptions.fAutoLogonIfChallenged = TRUE; dwError = GetProxyForUrlEx(hSession, pwszUrl, &waoOptions); goto quit; } if (!WinHttpGetProxyForUrl(hSession, pwszUrl, &waoOptions, &wpiProxyInfo)) { dwError = GetLastError(); if (dwError != ERROR_WINHTTP_LOGIN_FAILURE) { goto quit; } // // Enable autologon if challenged. // dwError = ERROR_SUCCESS; waoOptions.fAutoLogonIfChallenged = TRUE; if (!WinHttpGetProxyForUrl(hSession, pwszUrl, &waoOptions, &wpiProxyInfo)) { dwError = GetLastError(); goto quit; } } *ppwszProxy = wpiProxyInfo.lpszProxy; wpiProxyInfo.lpszProxy = NULL; *ppwszProxyBypass = wpiProxyInfo.lpszProxyBypass; wpiProxyInfo.lpszProxyBypass = NULL; quit: if (wpiProxyInfo.lpszProxy) { GlobalFree(wpiProxyInfo.lpszProxy); wpiProxyInfo.lpszProxy = NULL; } if (wpiProxyInfo.lpszProxyBypass) { GlobalFree(wpiProxyInfo.lpszProxyBypass); wpiProxyInfo.lpszProxyBypass = NULL; } return dwError; }
// Detect any proxy configuration settings automatically. // static void windows_detect_autoproxy_settings() { if (log_flags.proxy_debug) { post_sysmon_msg("[proxy] automatic proxy check in progress"); } HINTERNET hWinHttp = NULL; WINHTTP_AUTOPROXY_OPTIONS autoproxy_options; WINHTTP_PROXY_INFO proxy_info; PARSED_URL purl; std::wstring network_test_url; size_t pos; memset(&autoproxy_options, 0, sizeof(autoproxy_options)); memset(&proxy_info, 0, sizeof(proxy_info)); autoproxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; autoproxy_options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; autoproxy_options.fAutoLogonIfChallenged = TRUE; network_test_url = boinc_ascii_to_wide(nvc_config.network_test_url).c_str(); hWinHttp = WinHttpOpen( L"BOINC client", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, NULL ); char msg[1024], buf[1024]; safe_strcpy(msg, "[proxy] "); if (WinHttpGetProxyForUrl(hWinHttp, network_test_url.c_str(), &autoproxy_options, &proxy_info)) { // Apparently there are some conditions where WinHttpGetProxyForUrl can return // success but where proxy_info.lpszProxy is null. Maybe related to UPNP? // // For the time being check to see if proxy_info.lpszProxy is non-null. // if (proxy_info.lpszProxy) { std::string proxy(boinc_wide_to_ascii(std::wstring(proxy_info.lpszProxy))); std::string new_proxy; if (log_flags.proxy_debug) { safe_strcat(msg, "proxy list: "); safe_strcat(msg, proxy.c_str()); } if (!proxy.empty()) { // Trim string if more than one proxy is defined // proxy list is defined as: // ([<scheme>=][<scheme>"://"]<server>[":"<port>]) // Find and erase first delimeter type. pos = proxy.find(';'); if (pos != -1 ) { new_proxy = proxy.erase(pos); proxy = new_proxy; } // Find and erase second delimeter type. pos = proxy.find(' '); if (pos != -1 ) { new_proxy = proxy.erase(pos); proxy = new_proxy; } // Parse the remaining url parse_url(proxy.c_str(), purl); // Store the results for future use. if (0 != strcmp(working_proxy_info.autodetect_server_name, purl.host)) { // Reset clients connection error detection path net_status.need_physical_connection = false; working_proxy_info.autodetect_protocol = purl.protocol; safe_strcpy(working_proxy_info.autodetect_server_name, purl.host); working_proxy_info.autodetect_port = purl.port; } if (log_flags.proxy_debug) { snprintf(buf, sizeof(buf), "proxy detected %s:%d", purl.host, purl.port); safe_strcat(msg, buf); } } } // Clean up if (proxy_info.lpszProxy) GlobalFree(proxy_info.lpszProxy); if (proxy_info.lpszProxyBypass) GlobalFree(proxy_info.lpszProxyBypass); } else { // We can get here if the user is switching from a network that // requires a proxy to one that does not require a proxy. working_proxy_info.autodetect_protocol = 0; safe_strcpy(working_proxy_info.autodetect_server_name, ""); working_proxy_info.autodetect_port = 0; if (log_flags.proxy_debug) { safe_strcat(msg, "no automatic proxy detected"); } } if (hWinHttp) WinHttpCloseHandle(hWinHttp); if (log_flags.proxy_debug) { post_sysmon_msg(msg); } }
/* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":95 */ ((struct __pyx_obj_17_pymfclib_winhttp_WinHTTPSession *)__pyx_v_self)->hInternet = NULL; goto __pyx_L2; } __pyx_L2:; Py_DECREF(__pyx_v_self); } static PyObject *__pyx_f_17_pymfclib_winhttp_14WinHTTPSession_getProxyForUrl(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static PyObject *__pyx_f_17_pymfclib_winhttp_14WinHTTPSession_getProxyForUrl(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { PyObject *__pyx_v_url = 0; PyObject *__pyx_v_configurl = 0; WINHTTP_AUTOPROXY_OPTIONS __pyx_v_autoopt; WINHTTP_PROXY_INFO __pyx_v_proxyinfo; struct __pyx_obj_17_pymfclib_winhttp_ProxyInfo *__pyx_v_ret; PyObject *__pyx_r; int __pyx_1; __pyx_t_17_pymfclib_winhttp_PYMFC_WCHAR *__pyx_2; BOOL __pyx_3; PyObject *__pyx_4 = 0; static char *__pyx_argnames[] = {"url","configurl",0}; if (!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "OO", __pyx_argnames, &__pyx_v_url, &__pyx_v_configurl)) return 0; Py_INCREF(__pyx_v_self); Py_INCREF(__pyx_v_url); Py_INCREF(__pyx_v_configurl); __pyx_v_ret = ((struct __pyx_obj_17_pymfclib_winhttp_ProxyInfo *)Py_None); Py_INCREF(Py_None); /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":102 */ memset((&__pyx_v_autoopt),0,(sizeof(__pyx_v_autoopt))); /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":103 */ memset((&__pyx_v_proxyinfo),0,(sizeof(__pyx_v_proxyinfo))); /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":105 */ __pyx_1 = PyObject_IsTrue(__pyx_v_configurl); if (__pyx_1 < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 105; goto __pyx_L1;} if (__pyx_1) { /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":106 */ __pyx_v_autoopt.dwFlags = (WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL); /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":107 */ __pyx_2 = PyUnicode_AsUnicode(__pyx_v_configurl); if (__pyx_2 == NULL) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 107; goto __pyx_L1;} __pyx_v_autoopt.lpszAutoConfigUrl = __pyx_2; goto __pyx_L2; } /*else*/ { __pyx_v_autoopt.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; } __pyx_L2:; /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":111 */ __pyx_v_autoopt.dwAutoDetectFlags = (WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A); /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":112 */ __pyx_v_autoopt.fAutoLogonIfChallenged = 1; /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":114 */ __pyx_2 = PyUnicode_AsUnicode(__pyx_v_url); if (__pyx_2 == NULL) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 114; goto __pyx_L1;} __pyx_3 = WinHttpGetProxyForUrl(((struct __pyx_obj_17_pymfclib_winhttp_WinHTTPSession *)__pyx_v_self)->hInternet,__pyx_2,(&__pyx_v_autoopt),(&__pyx_v_proxyinfo)); if (__pyx_3) { /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":115 */ __pyx_4 = PyObject_CallObject(((PyObject *)__pyx_ptype_17_pymfclib_winhttp_ProxyInfo), 0); if (!__pyx_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 115; goto __pyx_L1;} Py_DECREF(((PyObject *)__pyx_v_ret)); __pyx_v_ret = ((struct __pyx_obj_17_pymfclib_winhttp_ProxyInfo *)__pyx_4); __pyx_4 = 0; /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":116 */ __pyx_4 = PyInt_FromLong((__pyx_v_proxyinfo.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY)); if (!__pyx_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; goto __pyx_L1;} Py_DECREF(__pyx_v_ret->noproxy); __pyx_v_ret->noproxy = __pyx_4; __pyx_4 = 0; /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":118 */ /*try:*/ { /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":119 */ __pyx_1 = (__pyx_v_proxyinfo.lpszProxy != 0); if (__pyx_1) { __pyx_4 = _fromWideChar(__pyx_v_proxyinfo.lpszProxy); if (!__pyx_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 120; goto __pyx_L5;} Py_DECREF(__pyx_v_ret->proxy); __pyx_v_ret->proxy = __pyx_4; __pyx_4 = 0; goto __pyx_L7; } __pyx_L7:; /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":121 */ __pyx_1 = (__pyx_v_proxyinfo.lpszProxyBypass != 0); if (__pyx_1) { __pyx_4 = _fromWideChar(__pyx_v_proxyinfo.lpszProxyBypass); if (!__pyx_4) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 122; goto __pyx_L5;} Py_DECREF(__pyx_v_ret->proxybypass); __pyx_v_ret->proxybypass = __pyx_4; __pyx_4 = 0; goto __pyx_L8; } __pyx_L8:; } /*finally:*/ { int __pyx_why; PyObject *__pyx_exc_type, *__pyx_exc_value, *__pyx_exc_tb; int __pyx_exc_lineno; __pyx_why = 0; goto __pyx_L6; __pyx_L5: { __pyx_why = 4; Py_XDECREF(__pyx_4); __pyx_4 = 0; PyErr_Fetch(&__pyx_exc_type, &__pyx_exc_value, &__pyx_exc_tb); __pyx_exc_lineno = __pyx_lineno; goto __pyx_L6; } __pyx_L6:; /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":124 */ __pyx_1 = (__pyx_v_proxyinfo.lpszProxy != 0); if (__pyx_1) { GlobalFree(__pyx_v_proxyinfo.lpszProxy); goto __pyx_L10; } __pyx_L10:; /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":126 */ __pyx_1 = (__pyx_v_proxyinfo.lpszProxyBypass != 0); if (__pyx_1) { GlobalFree(__pyx_v_proxyinfo.lpszProxyBypass); goto __pyx_L11; } __pyx_L11:; switch (__pyx_why) { case 4: { PyErr_Restore(__pyx_exc_type, __pyx_exc_value, __pyx_exc_tb); __pyx_lineno = __pyx_exc_lineno; __pyx_exc_type = 0; __pyx_exc_value = 0; __pyx_exc_tb = 0; goto __pyx_L1; } } } /* "c:\src\ip\pymfc\pymfclib\_pymfclib_winhttp.pyx":128 */ Py_INCREF(((PyObject *)__pyx_v_ret)); __pyx_r = ((PyObject *)__pyx_v_ret); goto __pyx_L0; goto __pyx_L3; } __pyx_L3:; __pyx_r = Py_None; Py_INCREF(Py_None); goto __pyx_L0; __pyx_L1:; Py_XDECREF(__pyx_4); __Pyx_AddTraceback("_pymfclib_winhttp.WinHTTPSession.getProxyForUrl"); __pyx_r = 0; __pyx_L0:; Py_DECREF(__pyx_v_ret); Py_DECREF(__pyx_v_self); Py_DECREF(__pyx_v_url); Py_DECREF(__pyx_v_configurl); return __pyx_r; }
// This method will return true if we should keep attempting to use a proxy // or false if the auto proxy determination was to use a direct connection. static bool GetAutoProxiesForURL(string& url, vector<SharedProxy>& proxies) { bool shouldUseProxy = true; WINHTTP_PROXY_INFO autoProxyInfo; ZeroMemory(&autoProxyInfo, sizeof(WINHTTP_PROXY_INFO)); WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions; ZeroMemory(&autoProxyOptions, sizeof(WINHTTP_AUTOPROXY_OPTIONS)); // This type of auto-detection might take several seconds, so // if the user specified an autoconfiguration URL don't do it. // TODO: Maybe we should use this as a fallback later, but it's *very* expensive. if (autoConfigURL.empty() && useProxyAutoConfig) { autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; } if (!autoConfigURL.empty()) { autoProxyOptions.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL; autoProxyOptions.lpszAutoConfigUrl = autoConfigURL.c_str(); } // From Chromium: // Per http://msdn.microsoft.com/en-us/library/aa383153(VS.85).aspx, it is // necessary to first try resolving with fAutoLogonIfChallenged set to false. // Otherwise, we fail over to trying it with a value of true. This way we // get good performance in the case where WinHTTP uses an out-of-process // resolver. This is important for Vista and Win2k3. wstring wideURL = UTF8ToWide(url); autoProxyOptions.fAutoLogonIfChallenged = FALSE; BOOL ok = WinHttpGetProxyForUrl( httpSession.GetHandle(), wideURL.c_str(), &autoProxyOptions, &autoProxyInfo); if (!ok && ERROR_WINHTTP_LOGIN_FAILURE == GetLastError()) { autoProxyOptions.fAutoLogonIfChallenged = TRUE; ok = WinHttpGetProxyForUrl( httpSession.GetHandle(), wideURL.c_str(), &autoProxyOptions, &autoProxyInfo); } if (ok && autoProxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY && autoProxyInfo.lpszProxy) { // Only the first proxy in the list will get a copy of the bypass list. std::string bypassList; if (autoProxyInfo.lpszProxyBypass) { std::wstring bypassW = autoProxyInfo.lpszProxyBypass; bypassList = string(bypassW.begin(), bypassW.end()); } std::wstring proxyListW = autoProxyInfo.lpszProxy; string proxyList = string(proxyListW.begin(), proxyListW.end()); ParseProxyList(proxyList, bypassList, proxies); } else if (ok && autoProxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY) { // The only case in which we do not continue to try using a proxy. // In this case the auto proxy setup told us to use a direct connection. shouldUseProxy = false; } else { // Auto proxy failed, so try another method string error = "Could not get proxy for url="; error.append(url); error.append(": "); error.append(ErrorCodeToString(GetLastError())); Logger::Get("Proxy")->Error(error); } // Always cleanup if (autoProxyInfo.lpszProxy) GlobalFree(autoProxyInfo.lpszProxy); if (autoProxyInfo.lpszProxyBypass) GlobalFree(autoProxyInfo.lpszProxyBypass); return shouldUseProxy; }
// Main entry point int __cdecl wmain() { HRESULT hr = S_OK; WS_ERROR* error = NULL; WS_SERVICE_PROXY* serviceProxy = NULL; WS_HEAP* heap = NULL; WS_ENDPOINT_ADDRESS address = {}; static const WS_STRING serviceUrl = WS_STRING_VALUE(L"http://terraservice.net/TerraService2.asmx"); WS_CHANNEL_PROPERTY channelPropertyArray[4]; WS_ADDRESSING_VERSION addressingVersion = WS_ADDRESSING_VERSION_TRANSPORT; WS_ENVELOPE_VERSION envelopeVersion = WS_ENVELOPE_VERSION_SOAP_1_1; WCHAR* place = NULL; WS_HTTP_PROXY_SETTING_MODE proxySettingMode = WS_HTTP_PROXY_SETTING_MODE_CUSTOM; WS_CUSTOM_HTTP_PROXY customProxy = {}; address.url = serviceUrl; WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions = {}; WINHTTP_PROXY_INFO proxyInfo = {}; HINTERNET session = NULL; channelPropertyArray[0].id = WS_CHANNEL_PROPERTY_ADDRESSING_VERSION; channelPropertyArray[0].value = &addressingVersion; channelPropertyArray[0].valueSize = sizeof(addressingVersion); channelPropertyArray[1].id = WS_CHANNEL_PROPERTY_ENVELOPE_VERSION; channelPropertyArray[1].value = &envelopeVersion; channelPropertyArray[1].valueSize = sizeof(envelopeVersion); channelPropertyArray[2].id = WS_CHANNEL_PROPERTY_HTTP_PROXY_SETTING_MODE; channelPropertyArray[2].value = &proxySettingMode; channelPropertyArray[2].valueSize = sizeof(proxySettingMode); channelPropertyArray[3].id = WS_CHANNEL_PROPERTY_CUSTOM_HTTP_PROXY; channelPropertyArray[3].value = &customProxy; channelPropertyArray[3].valueSize = sizeof(customProxy); // This part illustrates how to setup a HTTP header authentication security binding // against the HTTP proxy server in case it requires authentication. // declare and initialize a default windows credential WS_STRING_WINDOWS_INTEGRATED_AUTH_CREDENTIAL windowsCredential = {}; // zero out the struct windowsCredential.credential.credentialType = WS_STRING_WINDOWS_INTEGRATED_AUTH_CREDENTIAL_TYPE; // set the credential type // for illustration only; usernames and passwords should never be included in source files windowsCredential.username.chars = L"domain\\user"; windowsCredential.username.length = (ULONG)wcslen(windowsCredential.username.chars); windowsCredential.password.chars = L"password"; windowsCredential.password.length = (ULONG)wcslen(windowsCredential.password.chars); // declare and initialize properties to set the authentication scheme to Basic ULONG scheme = WS_HTTP_HEADER_AUTH_SCHEME_NEGOTIATE; ULONG target = WS_HTTP_HEADER_AUTH_TARGET_PROXY; WS_SECURITY_BINDING_PROPERTY httpProxyAuthBindingProperties[2] = { { WS_SECURITY_BINDING_PROPERTY_HTTP_HEADER_AUTH_SCHEME, &scheme, sizeof(scheme) }, { WS_SECURITY_BINDING_PROPERTY_HTTP_HEADER_AUTH_TARGET, &target, sizeof(target) } }; // declare and initialize an HTTP header authentication security binding for the HTTP proxy server WS_HTTP_HEADER_AUTH_SECURITY_BINDING httpProxyAuthBinding = {}; // zero out the struct httpProxyAuthBinding.binding.bindingType = WS_HTTP_HEADER_AUTH_SECURITY_BINDING_TYPE; // set the binding type httpProxyAuthBinding.binding.properties = httpProxyAuthBindingProperties; httpProxyAuthBinding.binding.propertyCount = WsCountOf(httpProxyAuthBindingProperties); httpProxyAuthBinding.clientCredential = &windowsCredential.credential; // declare and initialize the array of all security bindings WS_SECURITY_BINDING* securityBindings[1] = { &httpProxyAuthBinding.binding }; // declare and initialize the security description WS_SECURITY_DESCRIPTION securityDescription = {}; // zero out the struct securityDescription.securityBindings = securityBindings; securityDescription.securityBindingCount = WsCountOf(securityBindings); // Create an error object for storing rich error information hr = WsCreateError( NULL, 0, &error); if (FAILED(hr)) { goto Exit; } // Create a heap to store deserialized data hr = WsCreateHeap( /*maxSize*/ 2048, /*trimSize*/ 512, NULL, 0, &heap, error); if (FAILED(hr)) { goto Exit; } session = WinHttpOpen(L"NWS Example", WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC); if (!session) { hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; } autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_RUN_INPROCESS | WINHTTP_AUTOPROXY_AUTO_DETECT; autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; autoProxyOptions.fAutoLogonIfChallenged = FALSE; WinHttpGetProxyForUrl( session, serviceUrl.chars, &autoProxyOptions, &proxyInfo); if (proxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY) { if (proxyInfo.lpszProxy) { customProxy.servers.chars = proxyInfo.lpszProxy; customProxy.servers.length = (ULONG)wcslen(proxyInfo.lpszProxy); } if (proxyInfo.lpszProxyBypass) { customProxy.bypass.chars = proxyInfo.lpszProxyBypass; customProxy.bypass.length = (ULONG)wcslen(proxyInfo.lpszProxyBypass); } } hr = WsCreateServiceProxy( WS_CHANNEL_TYPE_REQUEST, WS_HTTP_CHANNEL_BINDING, &securityDescription, NULL, 0, channelPropertyArray, WsCountOf(channelPropertyArray), &serviceProxy, error); if (FAILED(hr)) { goto Exit; } // Open channel to address hr = WsOpenServiceProxy( serviceProxy, &address, NULL, error); if (FAILED(hr)) { goto Exit; } for (int i = 0; i < 100; i++) { LonLatPt point = {10.0, 10.0}; hr = TerraServiceSoap_ConvertLonLatPtToNearestPlace( serviceProxy, &point, &place, heap, NULL, 0, NULL, error); if (FAILED(hr)) { goto Exit; } if (place != NULL) { wprintf(L"Place @ Lattitude=%f, Longitutde=%f is %s\n", point.Lon, point.Lat, place); } else { wprintf(L"Could not find any place for Lattitude=%f, Longitutde=%f\n", point.Lon, point.Lat); } fflush(stdout); hr = WsResetHeap( heap, error); if (FAILED(hr)) { goto Exit; } } Exit: if (FAILED(hr)) { // Print out the error PrintError(hr, error); } if (proxyInfo.lpszProxy) { ::GlobalFree(proxyInfo.lpszProxy); } if (proxyInfo.lpszProxyBypass) { ::GlobalFree(proxyInfo.lpszProxyBypass); } if (serviceProxy != NULL) { WsCloseServiceProxy(serviceProxy, NULL, NULL); WsFreeServiceProxy(serviceProxy); } if (!session) { WinHttpCloseHandle(session); } if (heap != NULL) { WsFreeHeap(heap); } if (error != NULL) { WsFreeError(error); } fflush(stdout); return SUCCEEDED(hr) ? 0 : -1; }
static LPWSTR QueryWindowsProxySettings(const url_scheme scheme, LPCSTR host) { LPWSTR proxy = NULL; BOOL auto_detect = TRUE; LPWSTR auto_config_url = NULL; WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxy_config; if (WinHttpGetIEProxyConfigForCurrentUser(&proxy_config)) { proxy = proxy_config.lpszProxy; auto_detect = proxy_config.fAutoDetect; auto_config_url = proxy_config.lpszAutoConfigUrl; GlobalFree(proxy_config.lpszProxyBypass); } if (auto_detect) { LPWSTR old_url = auto_config_url; DWORD flags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; if (WinHttpDetectAutoProxyConfigUrl(flags, &auto_config_url)) GlobalFree(old_url); } if (auto_config_url) { HINTERNET session = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (session) { int size = _snwprintf(NULL, 0, L"%s://%S", UrlSchemeStr(scheme), host) + 1; LPWSTR url = malloc(size * sizeof(WCHAR)); if (url) { _snwprintf(url, size, L"%s://%S", UrlSchemeStr(scheme), host); LPWSTR old_proxy = proxy; WINHTTP_PROXY_INFO proxy_info; WINHTTP_AUTOPROXY_OPTIONS options = { .fAutoLogonIfChallenged = TRUE, .dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL, .lpszAutoConfigUrl = auto_config_url, .dwAutoDetectFlags = 0, .lpvReserved = NULL, .dwReserved = 0 }; if (WinHttpGetProxyForUrl(session, url, &options, &proxy_info)) { GlobalFree(old_proxy); GlobalFree(proxy_info.lpszProxyBypass); proxy = proxy_info.lpszProxy; } free(url); } WinHttpCloseHandle(session); } GlobalFree(auto_config_url); } return proxy; } static VOID ParseProxyString(LPWSTR proxy_str, url_scheme scheme, LPCSTR *type, LPCWSTR *host, LPCWSTR *port) { if (proxy_str == NULL) return; LPCWSTR delim = L"; "; LPWSTR token = wcstok(proxy_str, delim); LPCWSTR scheme_str = UrlSchemeStr(scheme); LPCWSTR socks_str = UrlSchemeStr(SOCKS_URL); /* Token format: [<scheme>=][<scheme>"://"]<server>[":"<port>] */ while (token) { BOOL match = FALSE; LPWSTR eq = wcschr(token, '='); LPWSTR css = wcsstr(token, L"://"); /* * If the token has a <scheme>, test for the one we're looking for. * If we're looking for a https proxy, socks will also do. * If it's a proxy without a <scheme> it's only good for https. */ if (eq || css) { if (wcsbegins(token, scheme_str)) { match = TRUE; } else if (scheme == HTTPS_URL && wcsbegins(token, socks_str)) { match = TRUE; scheme = SOCKS_URL; } } else if (scheme == HTTPS_URL) { match = TRUE; } if (match) { LPWSTR server = token; if (css) server = css + 3; else if (eq) server = eq + 1; /* IPv6 addresses are surrounded by brackets */ LPWSTR port_delim; if (server[0] == '[') { server += 1; LPWSTR end = wcschr(server, ']'); if (end == NULL) continue; *end++ = '\0'; port_delim = (*end == ':' ? end : NULL); } else { port_delim = wcsrchr(server, ':'); if (port_delim) *port_delim = '\0'; } *type = (scheme == HTTPS_URL ? "HTTP" : "SOCKS"); *host = server; if (port_delim) *port = port_delim + 1; else *port = (scheme == HTTPS_URL ? L"80": L"1080"); break; } token = wcstok(NULL, delim); } } /* * Respond to management interface PROXY notifications * Input format: REMOTE_NO,PROTOCOL,HOST */ void OnProxy(connection_t *c, char *line) { LPSTR proto, host; char *pos = strchr(line, ','); if (pos == NULL) return; proto = ++pos; pos = strchr(pos, ','); if (pos == NULL) return; *pos = '\0'; host = ++pos; if (host[0] == '\0') return; LPCSTR type = "NONE"; LPCWSTR addr = L"", port = L""; LPWSTR proxy_str = NULL; if (o.proxy_source == manual) { if (o.proxy_type == http && streq(proto, "TCP")) { type = "HTTP"; addr = o.proxy_http_address; port = o.proxy_http_port; } else if (o.proxy_type == socks) { type = "SOCKS"; addr = o.proxy_socks_address; port = o.proxy_socks_port; } } else if (o.proxy_source == windows) { url_scheme scheme = (streq(proto, "TCP") ? HTTPS_URL : SOCKS_URL); proxy_str = QueryWindowsProxySettings(scheme, host); ParseProxyString(proxy_str, scheme, &type, &addr, &port); } char cmd[128]; snprintf(cmd, sizeof(cmd), "proxy %s %S %S", type, addr, port); cmd[sizeof(cmd) - 1] = '\0'; ManagementCommand(c, cmd, NULL, regular); GlobalFree(proxy_str); }