toolkit/system/windowsproxy/nsWindowsSystemProxySettings.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include <windows.h>
michael@0 7 #include <ras.h>
michael@0 8 #include <wininet.h>
michael@0 9
michael@0 10 #include "mozilla/ArrayUtils.h"
michael@0 11 #include "mozilla/Attributes.h"
michael@0 12 #include "nsISystemProxySettings.h"
michael@0 13 #include "nsIServiceManager.h"
michael@0 14 #include "mozilla/ModuleUtils.h"
michael@0 15 #include "nsPrintfCString.h"
michael@0 16 #include "nsNetUtil.h"
michael@0 17 #include "nsISupportsPrimitives.h"
michael@0 18 #include "nsIURI.h"
michael@0 19
michael@0 20 class nsWindowsSystemProxySettings MOZ_FINAL : public nsISystemProxySettings
michael@0 21 {
michael@0 22 public:
michael@0 23 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 24 NS_DECL_NSISYSTEMPROXYSETTINGS
michael@0 25
michael@0 26 nsWindowsSystemProxySettings() {};
michael@0 27 nsresult Init();
michael@0 28
michael@0 29 private:
michael@0 30 ~nsWindowsSystemProxySettings() {};
michael@0 31
michael@0 32 bool MatchOverride(const nsACString& aHost);
michael@0 33 bool PatternMatch(const nsACString& aHost, const nsACString& aOverride);
michael@0 34 };
michael@0 35
michael@0 36 NS_IMPL_ISUPPORTS(nsWindowsSystemProxySettings, nsISystemProxySettings)
michael@0 37
michael@0 38 NS_IMETHODIMP
michael@0 39 nsWindowsSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
michael@0 40 {
michael@0 41 *aMainThreadOnly = false;
michael@0 42 return NS_OK;
michael@0 43 }
michael@0 44
michael@0 45
michael@0 46 nsresult
michael@0 47 nsWindowsSystemProxySettings::Init()
michael@0 48 {
michael@0 49 return NS_OK;
michael@0 50 }
michael@0 51
michael@0 52 static void SetProxyResult(const char* aType, const nsACString& aHostPort,
michael@0 53 nsACString& aResult)
michael@0 54 {
michael@0 55 aResult.AssignASCII(aType);
michael@0 56 aResult.Append(' ');
michael@0 57 aResult.Append(aHostPort);
michael@0 58 }
michael@0 59
michael@0 60 static void SetProxyResultDirect(nsACString& aResult)
michael@0 61 {
michael@0 62 // For whatever reason, a proxy is not to be used.
michael@0 63 aResult.AssignASCII("DIRECT");
michael@0 64 }
michael@0 65
michael@0 66 static nsresult ReadInternetOption(uint32_t aOption, uint32_t& aFlags,
michael@0 67 nsAString& aValue)
michael@0 68 {
michael@0 69 DWORD connFlags = 0;
michael@0 70 WCHAR connName[RAS_MaxEntryName + 1];
michael@0 71 MOZ_SEH_TRY {
michael@0 72 InternetGetConnectedStateExW(&connFlags, connName,
michael@0 73 mozilla::ArrayLength(connName), 0);
michael@0 74 } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
michael@0 75 return NS_ERROR_FAILURE;
michael@0 76 }
michael@0 77
michael@0 78 INTERNET_PER_CONN_OPTIONW options[2];
michael@0 79 options[0].dwOption = INTERNET_PER_CONN_FLAGS_UI;
michael@0 80 options[1].dwOption = aOption;
michael@0 81
michael@0 82 INTERNET_PER_CONN_OPTION_LISTW list;
michael@0 83 list.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LISTW);
michael@0 84 list.pszConnection = connFlags & INTERNET_CONNECTION_MODEM ?
michael@0 85 connName : nullptr;
michael@0 86 list.dwOptionCount = mozilla::ArrayLength(options);
michael@0 87 list.dwOptionError = 0;
michael@0 88 list.pOptions = options;
michael@0 89
michael@0 90 unsigned long size = sizeof(INTERNET_PER_CONN_OPTION_LISTW);
michael@0 91 if (!InternetQueryOptionW(nullptr, INTERNET_OPTION_PER_CONNECTION_OPTION,
michael@0 92 &list, &size)) {
michael@0 93 if (GetLastError() != ERROR_INVALID_PARAMETER) {
michael@0 94 return NS_ERROR_FAILURE;
michael@0 95 }
michael@0 96 options[0].dwOption = INTERNET_PER_CONN_FLAGS;
michael@0 97 size = sizeof(INTERNET_PER_CONN_OPTION_LISTW);
michael@0 98 MOZ_SEH_TRY {
michael@0 99 if (!InternetQueryOptionW(nullptr,
michael@0 100 INTERNET_OPTION_PER_CONNECTION_OPTION,
michael@0 101 &list, &size)) {
michael@0 102 return NS_ERROR_FAILURE;
michael@0 103 }
michael@0 104 } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
michael@0 105 return NS_ERROR_FAILURE;
michael@0 106 }
michael@0 107 }
michael@0 108
michael@0 109 aFlags = options[0].Value.dwValue;
michael@0 110 aValue.Assign(options[1].Value.pszValue);
michael@0 111 GlobalFree(options[1].Value.pszValue);
michael@0 112
michael@0 113 return NS_OK;
michael@0 114 }
michael@0 115
michael@0 116 bool
michael@0 117 nsWindowsSystemProxySettings::MatchOverride(const nsACString& aHost)
michael@0 118 {
michael@0 119 nsresult rv;
michael@0 120 uint32_t flags = 0;
michael@0 121 nsAutoString buf;
michael@0 122
michael@0 123 rv = ReadInternetOption(INTERNET_PER_CONN_PROXY_BYPASS, flags, buf);
michael@0 124 if (NS_FAILED(rv))
michael@0 125 return false;
michael@0 126
michael@0 127 NS_ConvertUTF16toUTF8 cbuf(buf);
michael@0 128
michael@0 129 nsAutoCString host(aHost);
michael@0 130 int32_t start = 0;
michael@0 131 int32_t end = cbuf.Length();
michael@0 132
michael@0 133 // Windows formats its proxy override list in the form:
michael@0 134 // server;server;server where 'server' is a server name pattern or IP
michael@0 135 // address, or "<local>". "<local>" must be translated to
michael@0 136 // "localhost;127.0.0.1".
michael@0 137 // In a server name pattern, a '*' character matches any substring and
michael@0 138 // all other characters must match themselves; the whole pattern must match
michael@0 139 // the whole hostname.
michael@0 140 while (true) {
michael@0 141 int32_t delimiter = cbuf.FindCharInSet(" ;", start);
michael@0 142 if (delimiter == -1)
michael@0 143 delimiter = end;
michael@0 144
michael@0 145 if (delimiter != start) {
michael@0 146 const nsAutoCString override(Substring(cbuf, start,
michael@0 147 delimiter - start));
michael@0 148 if (override.EqualsLiteral("<local>")) {
michael@0 149 // This override matches local addresses.
michael@0 150 if (host.EqualsLiteral("localhost") ||
michael@0 151 host.EqualsLiteral("127.0.0.1"))
michael@0 152 return true;
michael@0 153 } else if (PatternMatch(host, override)) {
michael@0 154 return true;
michael@0 155 }
michael@0 156 }
michael@0 157
michael@0 158 if (delimiter == end)
michael@0 159 break;
michael@0 160 start = ++delimiter;
michael@0 161 }
michael@0 162
michael@0 163 return false;
michael@0 164 }
michael@0 165
michael@0 166 bool
michael@0 167 nsWindowsSystemProxySettings::PatternMatch(const nsACString& aHost,
michael@0 168 const nsACString& aOverride)
michael@0 169 {
michael@0 170 nsAutoCString host(aHost);
michael@0 171 nsAutoCString override(aOverride);
michael@0 172 int32_t overrideLength = override.Length();
michael@0 173 int32_t tokenStart = 0;
michael@0 174 int32_t offset = 0;
michael@0 175 bool star = false;
michael@0 176
michael@0 177 while (tokenStart < overrideLength) {
michael@0 178 int32_t tokenEnd = override.FindChar('*', tokenStart);
michael@0 179 if (tokenEnd == tokenStart) {
michael@0 180 star = true;
michael@0 181 tokenStart++;
michael@0 182 // If the character following the '*' is a '.' character then skip
michael@0 183 // it so that "*.foo.com" allows "foo.com".
michael@0 184 if (override.FindChar('.', tokenStart) == tokenStart)
michael@0 185 tokenStart++;
michael@0 186 } else {
michael@0 187 if (tokenEnd == -1)
michael@0 188 tokenEnd = overrideLength;
michael@0 189 nsAutoCString token(Substring(override, tokenStart,
michael@0 190 tokenEnd - tokenStart));
michael@0 191 offset = host.Find(token, offset);
michael@0 192 if (offset == -1 || (!star && offset))
michael@0 193 return false;
michael@0 194 star = false;
michael@0 195 tokenStart = tokenEnd;
michael@0 196 offset += token.Length();
michael@0 197 }
michael@0 198 }
michael@0 199
michael@0 200 return (star || (offset == host.Length()));
michael@0 201 }
michael@0 202
michael@0 203 nsresult
michael@0 204 nsWindowsSystemProxySettings::GetPACURI(nsACString& aResult)
michael@0 205 {
michael@0 206 nsresult rv;
michael@0 207 uint32_t flags = 0;
michael@0 208 nsAutoString buf;
michael@0 209
michael@0 210 rv = ReadInternetOption(INTERNET_PER_CONN_AUTOCONFIG_URL, flags, buf);
michael@0 211 if (!(flags & PROXY_TYPE_AUTO_PROXY_URL)) {
michael@0 212 aResult.Truncate();
michael@0 213 return rv;
michael@0 214 }
michael@0 215
michael@0 216 if (NS_SUCCEEDED(rv))
michael@0 217 aResult = NS_ConvertUTF16toUTF8(buf);
michael@0 218 return rv;
michael@0 219 }
michael@0 220
michael@0 221 nsresult
michael@0 222 nsWindowsSystemProxySettings::GetProxyForURI(const nsACString & aSpec,
michael@0 223 const nsACString & aScheme,
michael@0 224 const nsACString & aHost,
michael@0 225 const int32_t aPort,
michael@0 226 nsACString & aResult)
michael@0 227 {
michael@0 228 nsresult rv;
michael@0 229 uint32_t flags = 0;
michael@0 230 nsAutoString buf;
michael@0 231
michael@0 232 rv = ReadInternetOption(INTERNET_PER_CONN_PROXY_SERVER, flags, buf);
michael@0 233 if (NS_FAILED(rv) || !(flags & PROXY_TYPE_PROXY)) {
michael@0 234 SetProxyResultDirect(aResult);
michael@0 235 return NS_OK;
michael@0 236 }
michael@0 237
michael@0 238 if (MatchOverride(aHost)) {
michael@0 239 SetProxyResultDirect(aResult);
michael@0 240 return NS_OK;
michael@0 241 }
michael@0 242
michael@0 243 NS_ConvertUTF16toUTF8 cbuf(buf);
michael@0 244
michael@0 245 nsAutoCString prefix;
michael@0 246 ToLowerCase(aScheme, prefix);
michael@0 247
michael@0 248 prefix.Append('=');
michael@0 249
michael@0 250 nsAutoCString specificProxy;
michael@0 251 nsAutoCString defaultProxy;
michael@0 252 nsAutoCString socksProxy;
michael@0 253 int32_t start = 0;
michael@0 254 int32_t end = cbuf.Length();
michael@0 255
michael@0 256 while (true) {
michael@0 257 int32_t delimiter = cbuf.FindCharInSet(" ;", start);
michael@0 258 if (delimiter == -1)
michael@0 259 delimiter = end;
michael@0 260
michael@0 261 if (delimiter != start) {
michael@0 262 const nsAutoCString proxy(Substring(cbuf, start,
michael@0 263 delimiter - start));
michael@0 264 if (proxy.FindChar('=') == -1) {
michael@0 265 // If a proxy name is listed by itself, it is used as the
michael@0 266 // default proxy for any protocols that do not have a specific
michael@0 267 // proxy specified.
michael@0 268 // (http://msdn.microsoft.com/en-us/library/aa383996%28VS.85%29.aspx)
michael@0 269 defaultProxy = proxy;
michael@0 270 } else if (proxy.Find(prefix) == 0) {
michael@0 271 // To list a proxy for a specific protocol, the string must
michael@0 272 // follow the format "<protocol>=<protocol>://<proxy_name>".
michael@0 273 // (http://msdn.microsoft.com/en-us/library/aa383996%28VS.85%29.aspx)
michael@0 274 specificProxy = Substring(proxy, prefix.Length());
michael@0 275 break;
michael@0 276 } else if (proxy.Find("socks=") == 0) {
michael@0 277 // SOCKS proxy.
michael@0 278 socksProxy = Substring(proxy, 5); // "socks=" length.
michael@0 279 }
michael@0 280 }
michael@0 281
michael@0 282 if (delimiter == end)
michael@0 283 break;
michael@0 284 start = ++delimiter;
michael@0 285 }
michael@0 286
michael@0 287 if (!specificProxy.IsEmpty())
michael@0 288 SetProxyResult("PROXY", specificProxy, aResult); // Protocol-specific proxy.
michael@0 289 else if (!defaultProxy.IsEmpty())
michael@0 290 SetProxyResult("PROXY", defaultProxy, aResult); // Default proxy.
michael@0 291 else if (!socksProxy.IsEmpty())
michael@0 292 SetProxyResult("SOCKS", socksProxy, aResult); // SOCKS proxy.
michael@0 293 else
michael@0 294 SetProxyResultDirect(aResult); // Direct connection.
michael@0 295
michael@0 296 return NS_OK;
michael@0 297 }
michael@0 298
michael@0 299 #define NS_WINDOWSSYSTEMPROXYSERVICE_CID /* 4e22d3ea-aaa2-436e-ada4-9247de57d367 */\
michael@0 300 { 0x4e22d3ea, 0xaaa2, 0x436e, \
michael@0 301 {0xad, 0xa4, 0x92, 0x47, 0xde, 0x57, 0xd3, 0x67 } }
michael@0 302
michael@0 303 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWindowsSystemProxySettings, Init)
michael@0 304 NS_DEFINE_NAMED_CID(NS_WINDOWSSYSTEMPROXYSERVICE_CID);
michael@0 305
michael@0 306 static const mozilla::Module::CIDEntry kSysProxyCIDs[] = {
michael@0 307 { &kNS_WINDOWSSYSTEMPROXYSERVICE_CID, false, nullptr, nsWindowsSystemProxySettingsConstructor },
michael@0 308 { nullptr }
michael@0 309 };
michael@0 310
michael@0 311 static const mozilla::Module::ContractIDEntry kSysProxyContracts[] = {
michael@0 312 { NS_SYSTEMPROXYSETTINGS_CONTRACTID, &kNS_WINDOWSSYSTEMPROXYSERVICE_CID },
michael@0 313 { nullptr }
michael@0 314 };
michael@0 315
michael@0 316 static const mozilla::Module kSysProxyModule = {
michael@0 317 mozilla::Module::kVersion,
michael@0 318 kSysProxyCIDs,
michael@0 319 kSysProxyContracts
michael@0 320 };
michael@0 321
michael@0 322 NSMODULE_DEFN(nsWindowsProxyModule) = &kSysProxyModule;

mercurial