nsProtocolProxyService.cpp 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* vim:set ts=4 sw=4 sts=4 et: */
  3. /* This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. #include "mozilla/ArrayUtils.h"
  7. #include "mozilla/Attributes.h"
  8. #include "nsProtocolProxyService.h"
  9. #include "nsProxyInfo.h"
  10. #include "nsIClassInfoImpl.h"
  11. #include "nsIIOService.h"
  12. #include "nsIObserverService.h"
  13. #include "nsIProtocolHandler.h"
  14. #include "nsIProtocolProxyCallback.h"
  15. #include "nsIChannel.h"
  16. #include "nsICancelable.h"
  17. #include "nsIDNSService.h"
  18. #include "nsPIDNSService.h"
  19. #include "nsIScriptSecurityManager.h"
  20. #include "nsIPrefService.h"
  21. #include "nsIPrefBranch.h"
  22. #include "nsThreadUtils.h"
  23. #include "nsSOCKSIOLayer.h"
  24. #include "nsString.h"
  25. #include "nsNetUtil.h"
  26. #include "nsNetCID.h"
  27. #include "plstr.h"
  28. #include "prnetdb.h"
  29. #include "nsPACMan.h"
  30. #include "nsProxyRelease.h"
  31. #include "mozilla/Mutex.h"
  32. #include "mozilla/CondVar.h"
  33. #include "nsISystemProxySettings.h"
  34. #include "nsINetworkLinkService.h"
  35. #include "nsIHttpChannelInternal.h"
  36. #include "mozilla/Logging.h"
  37. #include "mozilla/Tokenizer.h"
  38. //----------------------------------------------------------------------------
  39. namespace mozilla {
  40. namespace net {
  41. extern const char kProxyType_HTTP[];
  42. extern const char kProxyType_HTTPS[];
  43. extern const char kProxyType_SOCKS[];
  44. extern const char kProxyType_SOCKS4[];
  45. extern const char kProxyType_SOCKS5[];
  46. extern const char kProxyType_DIRECT[];
  47. #undef LOG
  48. #define LOG(args) MOZ_LOG(gProxyLog, LogLevel::Debug, args)
  49. //----------------------------------------------------------------------------
  50. #define PROXY_PREF_BRANCH "network.proxy"
  51. #define PROXY_PREF(x) PROXY_PREF_BRANCH "." x
  52. #define WPAD_URL "http://wpad/wpad.dat"
  53. //----------------------------------------------------------------------------
  54. // This structure is intended to be allocated on the stack
  55. struct nsProtocolInfo {
  56. nsAutoCString scheme;
  57. uint32_t flags;
  58. int32_t defaultPort;
  59. };
  60. //----------------------------------------------------------------------------
  61. // Return the channel's proxy URI, or if it doesn't exist, the
  62. // channel's main URI.
  63. static nsresult
  64. GetProxyURI(nsIChannel *channel, nsIURI **aOut)
  65. {
  66. nsresult rv = NS_OK;
  67. nsCOMPtr<nsIURI> proxyURI;
  68. nsCOMPtr<nsIHttpChannelInternal> httpChannel(do_QueryInterface(channel));
  69. if (httpChannel) {
  70. rv = httpChannel->GetProxyURI(getter_AddRefs(proxyURI));
  71. }
  72. if (!proxyURI) {
  73. rv = channel->GetURI(getter_AddRefs(proxyURI));
  74. }
  75. if (NS_FAILED(rv)) {
  76. return rv;
  77. }
  78. proxyURI.forget(aOut);
  79. return NS_OK;
  80. }
  81. //-----------------------------------------------------------------------------
  82. // The nsPACManCallback portion of this implementation should be run
  83. // on the main thread - so call nsPACMan::AsyncGetProxyForURI() with
  84. // a true mainThreadResponse parameter.
  85. class nsAsyncResolveRequest final : public nsIRunnable
  86. , public nsPACManCallback
  87. , public nsICancelable
  88. {
  89. public:
  90. NS_DECL_THREADSAFE_ISUPPORTS
  91. nsAsyncResolveRequest(nsProtocolProxyService *pps, nsIChannel *channel,
  92. uint32_t aResolveFlags,
  93. nsIProtocolProxyCallback *callback)
  94. : mStatus(NS_OK)
  95. , mDispatched(false)
  96. , mResolveFlags(aResolveFlags)
  97. , mPPS(pps)
  98. , mXPComPPS(pps)
  99. , mChannel(channel)
  100. , mCallback(callback)
  101. {
  102. NS_ASSERTION(mCallback, "null callback");
  103. }
  104. private:
  105. ~nsAsyncResolveRequest()
  106. {
  107. if (!NS_IsMainThread()) {
  108. // these xpcom pointers might need to be proxied back to the
  109. // main thread to delete safely, but if this request had its
  110. // callbacks called normally they will all be null and this is a nop
  111. if (mChannel) {
  112. NS_ReleaseOnMainThread(mChannel.forget());
  113. }
  114. if (mCallback) {
  115. NS_ReleaseOnMainThread(mCallback.forget());
  116. }
  117. if (mProxyInfo) {
  118. NS_ReleaseOnMainThread(mProxyInfo.forget());
  119. }
  120. if (mXPComPPS) {
  121. NS_ReleaseOnMainThread(mXPComPPS.forget());
  122. }
  123. }
  124. }
  125. public:
  126. void SetResult(nsresult status, nsIProxyInfo *pi)
  127. {
  128. mStatus = status;
  129. mProxyInfo = pi;
  130. }
  131. NS_IMETHOD Run() override
  132. {
  133. if (mCallback)
  134. DoCallback();
  135. return NS_OK;
  136. }
  137. NS_IMETHOD Cancel(nsresult reason) override
  138. {
  139. NS_ENSURE_ARG(NS_FAILED(reason));
  140. // If we've already called DoCallback then, nothing more to do.
  141. if (!mCallback)
  142. return NS_OK;
  143. SetResult(reason, nullptr);
  144. return DispatchCallback();
  145. }
  146. nsresult DispatchCallback()
  147. {
  148. if (mDispatched) // Only need to dispatch once
  149. return NS_OK;
  150. nsresult rv = NS_DispatchToCurrentThread(this);
  151. if (NS_FAILED(rv))
  152. NS_WARNING("unable to dispatch callback event");
  153. else {
  154. mDispatched = true;
  155. return NS_OK;
  156. }
  157. mCallback = nullptr; // break possible reference cycle
  158. return rv;
  159. }
  160. private:
  161. // Called asynchronously, so we do not need to post another PLEvent
  162. // before calling DoCallback.
  163. void OnQueryComplete(nsresult status,
  164. const nsCString &pacString,
  165. const nsCString &newPACURL) override
  166. {
  167. // If we've already called DoCallback then, nothing more to do.
  168. if (!mCallback)
  169. return;
  170. // Provided we haven't been canceled...
  171. if (mStatus == NS_OK) {
  172. mStatus = status;
  173. mPACString = pacString;
  174. mPACURL = newPACURL;
  175. }
  176. // In the cancelation case, we may still have another PLEvent in
  177. // the queue that wants to call DoCallback. No need to wait for
  178. // it, just run the callback now.
  179. DoCallback();
  180. }
  181. void DoCallback()
  182. {
  183. bool pacAvailable = true;
  184. if (mStatus == NS_ERROR_NOT_AVAILABLE && !mProxyInfo) {
  185. // If the PAC service is not avail (e.g. failed pac load
  186. // or shutdown) then we will be going direct. Make that
  187. // mapping now so that any filters are still applied.
  188. mPACString = NS_LITERAL_CSTRING("DIRECT;");
  189. mStatus = NS_OK;
  190. LOG(("pac not available, use DIRECT\n"));
  191. pacAvailable = false;
  192. }
  193. // Generate proxy info from the PAC string if appropriate
  194. if (NS_SUCCEEDED(mStatus) && !mProxyInfo && !mPACString.IsEmpty()) {
  195. mPPS->ProcessPACString(mPACString, mResolveFlags,
  196. getter_AddRefs(mProxyInfo));
  197. nsCOMPtr<nsIURI> proxyURI;
  198. GetProxyURI(mChannel, getter_AddRefs(proxyURI));
  199. // Now apply proxy filters
  200. nsProtocolInfo info;
  201. mStatus = mPPS->GetProtocolInfo(proxyURI, &info);
  202. if (NS_SUCCEEDED(mStatus))
  203. mPPS->ApplyFilters(mChannel, info, mProxyInfo);
  204. else
  205. mProxyInfo = nullptr;
  206. if(pacAvailable) {
  207. // if !pacAvailable, it was already logged above
  208. LOG(("pac thread callback %s\n", mPACString.get()));
  209. }
  210. if (NS_SUCCEEDED(mStatus))
  211. mPPS->MaybeDisableDNSPrefetch(mProxyInfo);
  212. mCallback->OnProxyAvailable(this, mChannel, mProxyInfo, mStatus);
  213. }
  214. else if (NS_SUCCEEDED(mStatus) && !mPACURL.IsEmpty()) {
  215. LOG(("pac thread callback indicates new pac file load\n"));
  216. nsCOMPtr<nsIURI> proxyURI;
  217. GetProxyURI(mChannel, getter_AddRefs(proxyURI));
  218. // trigger load of new pac url
  219. nsresult rv = mPPS->ConfigureFromPAC(mPACURL, false);
  220. if (NS_SUCCEEDED(rv)) {
  221. // now that the load is triggered, we can resubmit the query
  222. RefPtr<nsAsyncResolveRequest> newRequest =
  223. new nsAsyncResolveRequest(mPPS, mChannel, mResolveFlags,
  224. mCallback);
  225. rv = mPPS->mPACMan->AsyncGetProxyForURI(proxyURI,
  226. newRequest,
  227. true);
  228. }
  229. if (NS_FAILED(rv))
  230. mCallback->OnProxyAvailable(this, mChannel, nullptr, rv);
  231. // do not call onproxyavailable() in SUCCESS case - the newRequest will
  232. // take care of that
  233. }
  234. else {
  235. LOG(("pac thread callback did not provide information %X\n", mStatus));
  236. if (NS_SUCCEEDED(mStatus))
  237. mPPS->MaybeDisableDNSPrefetch(mProxyInfo);
  238. mCallback->OnProxyAvailable(this, mChannel, mProxyInfo, mStatus);
  239. }
  240. // We are on the main thread now and don't need these any more so
  241. // release them to avoid having to proxy them back to the main thread
  242. // in the dtor
  243. mCallback = nullptr; // in case the callback holds an owning ref to us
  244. mPPS = nullptr;
  245. mXPComPPS = nullptr;
  246. mChannel = nullptr;
  247. mProxyInfo = nullptr;
  248. }
  249. private:
  250. nsresult mStatus;
  251. nsCString mPACString;
  252. nsCString mPACURL;
  253. bool mDispatched;
  254. uint32_t mResolveFlags;
  255. nsProtocolProxyService *mPPS;
  256. nsCOMPtr<nsIProtocolProxyService> mXPComPPS;
  257. nsCOMPtr<nsIChannel> mChannel;
  258. nsCOMPtr<nsIProtocolProxyCallback> mCallback;
  259. nsCOMPtr<nsIProxyInfo> mProxyInfo;
  260. };
  261. NS_IMPL_ISUPPORTS(nsAsyncResolveRequest, nsICancelable, nsIRunnable)
  262. //----------------------------------------------------------------------------
  263. #define IS_ASCII_SPACE(_c) ((_c) == ' ' || (_c) == '\t')
  264. //
  265. // apply mask to address (zeros out excluded bits).
  266. //
  267. // NOTE: we do the byte swapping here to minimize overall swapping.
  268. //
  269. static void
  270. proxy_MaskIPv6Addr(PRIPv6Addr &addr, uint16_t mask_len)
  271. {
  272. if (mask_len == 128)
  273. return;
  274. if (mask_len > 96) {
  275. addr.pr_s6_addr32[3] = PR_htonl(
  276. PR_ntohl(addr.pr_s6_addr32[3]) & (~0L << (128 - mask_len)));
  277. }
  278. else if (mask_len > 64) {
  279. addr.pr_s6_addr32[3] = 0;
  280. addr.pr_s6_addr32[2] = PR_htonl(
  281. PR_ntohl(addr.pr_s6_addr32[2]) & (~0L << (96 - mask_len)));
  282. }
  283. else if (mask_len > 32) {
  284. addr.pr_s6_addr32[3] = 0;
  285. addr.pr_s6_addr32[2] = 0;
  286. addr.pr_s6_addr32[1] = PR_htonl(
  287. PR_ntohl(addr.pr_s6_addr32[1]) & (~0L << (64 - mask_len)));
  288. }
  289. else {
  290. addr.pr_s6_addr32[3] = 0;
  291. addr.pr_s6_addr32[2] = 0;
  292. addr.pr_s6_addr32[1] = 0;
  293. addr.pr_s6_addr32[0] = PR_htonl(
  294. PR_ntohl(addr.pr_s6_addr32[0]) & (~0L << (32 - mask_len)));
  295. }
  296. }
  297. static void
  298. proxy_GetStringPref(nsIPrefBranch *aPrefBranch,
  299. const char *aPref,
  300. nsCString &aResult)
  301. {
  302. nsXPIDLCString temp;
  303. nsresult rv = aPrefBranch->GetCharPref(aPref, getter_Copies(temp));
  304. if (NS_FAILED(rv))
  305. aResult.Truncate();
  306. else {
  307. aResult.Assign(temp);
  308. // all of our string prefs are hostnames, so we should remove any
  309. // whitespace characters that the user might have unknowingly entered.
  310. aResult.StripWhitespace();
  311. }
  312. }
  313. static void
  314. proxy_GetIntPref(nsIPrefBranch *aPrefBranch,
  315. const char *aPref,
  316. int32_t &aResult)
  317. {
  318. int32_t temp;
  319. nsresult rv = aPrefBranch->GetIntPref(aPref, &temp);
  320. if (NS_FAILED(rv))
  321. aResult = -1;
  322. else
  323. aResult = temp;
  324. }
  325. static void
  326. proxy_GetBoolPref(nsIPrefBranch *aPrefBranch,
  327. const char *aPref,
  328. bool &aResult)
  329. {
  330. bool temp;
  331. nsresult rv = aPrefBranch->GetBoolPref(aPref, &temp);
  332. if (NS_FAILED(rv))
  333. aResult = false;
  334. else
  335. aResult = temp;
  336. }
  337. //----------------------------------------------------------------------------
  338. static const int32_t PROXYCONFIG_DIRECT4X = 3;
  339. static const int32_t PROXYCONFIG_COUNT = 6;
  340. NS_IMPL_ADDREF(nsProtocolProxyService)
  341. NS_IMPL_RELEASE(nsProtocolProxyService)
  342. NS_IMPL_CLASSINFO(nsProtocolProxyService, nullptr, nsIClassInfo::SINGLETON,
  343. NS_PROTOCOLPROXYSERVICE_CID)
  344. // NS_IMPL_QUERY_INTERFACE_CI with the nsProtocolProxyService QI change
  345. NS_INTERFACE_MAP_BEGIN(nsProtocolProxyService)
  346. NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyService)
  347. NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyService2)
  348. NS_INTERFACE_MAP_ENTRY(nsIObserver)
  349. if ( aIID.Equals(NS_GET_IID(nsProtocolProxyService)) ) foundInterface = static_cast<nsIProtocolProxyService2*>(this); else
  350. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIProtocolProxyService)
  351. NS_IMPL_QUERY_CLASSINFO(nsProtocolProxyService)
  352. NS_INTERFACE_MAP_END
  353. NS_IMPL_CI_INTERFACE_GETTER(nsProtocolProxyService,
  354. nsIProtocolProxyService,
  355. nsIProtocolProxyService2)
  356. nsProtocolProxyService::nsProtocolProxyService()
  357. : mFilterLocalHosts(false)
  358. , mFilters(nullptr)
  359. , mProxyConfig(PROXYCONFIG_DIRECT)
  360. , mHTTPProxyPort(-1)
  361. , mFTPProxyPort(-1)
  362. , mHTTPSProxyPort(-1)
  363. , mSOCKSProxyPort(-1)
  364. , mSOCKSProxyVersion(4)
  365. , mSOCKSProxyRemoteDNS(false)
  366. , mProxyOverTLS(true)
  367. , mPACMan(nullptr)
  368. , mSessionStart(PR_Now())
  369. , mFailedProxyTimeout(30 * 60) // 30 minute default
  370. {
  371. }
  372. nsProtocolProxyService::~nsProtocolProxyService()
  373. {
  374. // These should have been cleaned up in our Observe method.
  375. NS_ASSERTION(mHostFiltersArray.Length() == 0 && mFilters == nullptr &&
  376. mPACMan == nullptr, "what happened to xpcom-shutdown?");
  377. }
  378. // nsProtocolProxyService methods
  379. nsresult
  380. nsProtocolProxyService::Init()
  381. {
  382. // failure to access prefs is non-fatal
  383. nsCOMPtr<nsIPrefBranch> prefBranch =
  384. do_GetService(NS_PREFSERVICE_CONTRACTID);
  385. if (prefBranch) {
  386. // monitor proxy prefs
  387. prefBranch->AddObserver(PROXY_PREF_BRANCH, this, false);
  388. // read all prefs
  389. PrefsChanged(prefBranch, nullptr);
  390. }
  391. nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
  392. if (obs) {
  393. // register for shutdown notification so we can clean ourselves up
  394. // properly.
  395. obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
  396. obs->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
  397. }
  398. return NS_OK;
  399. }
  400. // ReloadNetworkPAC() checks if there's a non-networked PAC in use then avoids
  401. // to call ReloadPAC()
  402. nsresult
  403. nsProtocolProxyService::ReloadNetworkPAC()
  404. {
  405. nsCOMPtr<nsIPrefBranch> prefs =
  406. do_GetService(NS_PREFSERVICE_CONTRACTID);
  407. if (!prefs) {
  408. return NS_OK;
  409. }
  410. int32_t type;
  411. nsresult rv = prefs->GetIntPref(PROXY_PREF("type"), &type);
  412. if (NS_FAILED(rv)) {
  413. return NS_OK;
  414. }
  415. if (type == PROXYCONFIG_PAC) {
  416. nsXPIDLCString pacSpec;
  417. prefs->GetCharPref(PROXY_PREF("autoconfig_url"),
  418. getter_Copies(pacSpec));
  419. if (!pacSpec.IsEmpty()) {
  420. nsCOMPtr<nsIURI> pacURI;
  421. rv = NS_NewURI(getter_AddRefs(pacURI), pacSpec);
  422. if(!NS_SUCCEEDED(rv)) {
  423. return rv;
  424. }
  425. nsProtocolInfo pac;
  426. rv = GetProtocolInfo(pacURI, &pac);
  427. if(!NS_SUCCEEDED(rv)) {
  428. return rv;
  429. }
  430. if (!pac.scheme.EqualsLiteral("file") &&
  431. !pac.scheme.EqualsLiteral("data")) {
  432. LOG((": received network changed event, reload PAC"));
  433. ReloadPAC();
  434. }
  435. }
  436. } else if ((type == PROXYCONFIG_WPAD) || (type == PROXYCONFIG_SYSTEM)) {
  437. ReloadPAC();
  438. }
  439. return NS_OK;
  440. }
  441. NS_IMETHODIMP
  442. nsProtocolProxyService::Observe(nsISupports *aSubject,
  443. const char *aTopic,
  444. const char16_t *aData)
  445. {
  446. if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
  447. // cleanup
  448. if (mHostFiltersArray.Length() > 0) {
  449. mHostFiltersArray.Clear();
  450. }
  451. if (mFilters) {
  452. delete mFilters;
  453. mFilters = nullptr;
  454. }
  455. if (mPACMan) {
  456. mPACMan->Shutdown();
  457. mPACMan = nullptr;
  458. }
  459. nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
  460. if (obs) {
  461. obs->RemoveObserver(this, NS_NETWORK_LINK_TOPIC);
  462. obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
  463. }
  464. } else if (strcmp(aTopic, NS_NETWORK_LINK_TOPIC) == 0) {
  465. nsCString converted = NS_ConvertUTF16toUTF8(aData);
  466. const char *state = converted.get();
  467. if (!strcmp(state, NS_NETWORK_LINK_DATA_CHANGED)) {
  468. ReloadNetworkPAC();
  469. }
  470. }
  471. else {
  472. NS_ASSERTION(strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0,
  473. "what is this random observer event?");
  474. nsCOMPtr<nsIPrefBranch> prefs = do_QueryInterface(aSubject);
  475. if (prefs)
  476. PrefsChanged(prefs, NS_LossyConvertUTF16toASCII(aData).get());
  477. }
  478. return NS_OK;
  479. }
  480. void
  481. nsProtocolProxyService::PrefsChanged(nsIPrefBranch *prefBranch,
  482. const char *pref)
  483. {
  484. nsresult rv = NS_OK;
  485. bool reloadPAC = false;
  486. nsXPIDLCString tempString;
  487. if (!pref || !strcmp(pref, PROXY_PREF("type"))) {
  488. int32_t type = -1;
  489. rv = prefBranch->GetIntPref(PROXY_PREF("type"), &type);
  490. if (NS_SUCCEEDED(rv)) {
  491. // bug 115720 - for ns4.x backwards compatibility
  492. if (type == PROXYCONFIG_DIRECT4X) {
  493. type = PROXYCONFIG_DIRECT;
  494. // Reset the type so that the dialog looks correct, and we
  495. // don't have to handle this case everywhere else
  496. // I'm paranoid about a loop of some sort - only do this
  497. // if we're enumerating all prefs, and ignore any error
  498. if (!pref)
  499. prefBranch->SetIntPref(PROXY_PREF("type"), type);
  500. } else if (type >= PROXYCONFIG_COUNT) {
  501. LOG(("unknown proxy type: %lu; assuming direct\n", type));
  502. type = PROXYCONFIG_DIRECT;
  503. }
  504. mProxyConfig = type;
  505. reloadPAC = true;
  506. }
  507. if (mProxyConfig == PROXYCONFIG_SYSTEM) {
  508. mSystemProxySettings = do_GetService(NS_SYSTEMPROXYSETTINGS_CONTRACTID);
  509. if (!mSystemProxySettings)
  510. mProxyConfig = PROXYCONFIG_DIRECT;
  511. ResetPACThread();
  512. } else {
  513. if (mSystemProxySettings) {
  514. mSystemProxySettings = nullptr;
  515. ResetPACThread();
  516. }
  517. }
  518. }
  519. if (!pref || !strcmp(pref, PROXY_PREF("http")))
  520. proxy_GetStringPref(prefBranch, PROXY_PREF("http"), mHTTPProxyHost);
  521. if (!pref || !strcmp(pref, PROXY_PREF("http_port")))
  522. proxy_GetIntPref(prefBranch, PROXY_PREF("http_port"), mHTTPProxyPort);
  523. if (!pref || !strcmp(pref, PROXY_PREF("ssl")))
  524. proxy_GetStringPref(prefBranch, PROXY_PREF("ssl"), mHTTPSProxyHost);
  525. if (!pref || !strcmp(pref, PROXY_PREF("ssl_port")))
  526. proxy_GetIntPref(prefBranch, PROXY_PREF("ssl_port"), mHTTPSProxyPort);
  527. if (!pref || !strcmp(pref, PROXY_PREF("ftp")))
  528. proxy_GetStringPref(prefBranch, PROXY_PREF("ftp"), mFTPProxyHost);
  529. if (!pref || !strcmp(pref, PROXY_PREF("ftp_port")))
  530. proxy_GetIntPref(prefBranch, PROXY_PREF("ftp_port"), mFTPProxyPort);
  531. if (!pref || !strcmp(pref, PROXY_PREF("socks")))
  532. proxy_GetStringPref(prefBranch, PROXY_PREF("socks"), mSOCKSProxyTarget);
  533. if (!pref || !strcmp(pref, PROXY_PREF("socks_port")))
  534. proxy_GetIntPref(prefBranch, PROXY_PREF("socks_port"), mSOCKSProxyPort);
  535. if (!pref || !strcmp(pref, PROXY_PREF("socks_version"))) {
  536. int32_t version;
  537. proxy_GetIntPref(prefBranch, PROXY_PREF("socks_version"), version);
  538. // make sure this preference value remains sane
  539. if (version == 5)
  540. mSOCKSProxyVersion = 5;
  541. else
  542. mSOCKSProxyVersion = 4;
  543. }
  544. if (!pref || !strcmp(pref, PROXY_PREF("socks_remote_dns")))
  545. proxy_GetBoolPref(prefBranch, PROXY_PREF("socks_remote_dns"),
  546. mSOCKSProxyRemoteDNS);
  547. if (!pref || !strcmp(pref, PROXY_PREF("proxy_over_tls"))) {
  548. proxy_GetBoolPref(prefBranch, PROXY_PREF("proxy_over_tls"),
  549. mProxyOverTLS);
  550. }
  551. if (!pref || !strcmp(pref, PROXY_PREF("failover_timeout")))
  552. proxy_GetIntPref(prefBranch, PROXY_PREF("failover_timeout"),
  553. mFailedProxyTimeout);
  554. if (!pref || !strcmp(pref, PROXY_PREF("no_proxies_on"))) {
  555. rv = prefBranch->GetCharPref(PROXY_PREF("no_proxies_on"),
  556. getter_Copies(tempString));
  557. if (NS_SUCCEEDED(rv))
  558. LoadHostFilters(tempString);
  559. }
  560. // We're done if not using something that could give us a PAC URL
  561. // (PAC, WPAD or System)
  562. if (mProxyConfig != PROXYCONFIG_PAC && mProxyConfig != PROXYCONFIG_WPAD &&
  563. mProxyConfig != PROXYCONFIG_SYSTEM)
  564. return;
  565. // OK, we need to reload the PAC file if:
  566. // 1) network.proxy.type changed, or
  567. // 2) network.proxy.autoconfig_url changed and PAC is configured
  568. if (!pref || !strcmp(pref, PROXY_PREF("autoconfig_url")))
  569. reloadPAC = true;
  570. if (reloadPAC) {
  571. tempString.Truncate();
  572. if (mProxyConfig == PROXYCONFIG_PAC) {
  573. prefBranch->GetCharPref(PROXY_PREF("autoconfig_url"),
  574. getter_Copies(tempString));
  575. if (mPACMan && !mPACMan->IsPACURI(tempString)) {
  576. LOG(("PAC Thread URI Changed - Reset Pac Thread"));
  577. ResetPACThread();
  578. }
  579. } else if (mProxyConfig == PROXYCONFIG_WPAD) {
  580. // We diverge from the WPAD spec here in that we don't walk the
  581. // hosts's FQDN, stripping components until we hit a TLD. Doing so
  582. // is dangerous in the face of an incomplete list of TLDs, and TLDs
  583. // get added over time. We could consider doing only a single
  584. // substitution of the first component, if that proves to help
  585. // compatibility.
  586. tempString.AssignLiteral(WPAD_URL);
  587. } else if (mSystemProxySettings) {
  588. // Get System Proxy settings if available
  589. mSystemProxySettings->GetPACURI(tempString);
  590. }
  591. if (!tempString.IsEmpty())
  592. ConfigureFromPAC(tempString, false);
  593. }
  594. }
  595. bool
  596. nsProtocolProxyService::CanUseProxy(nsIURI *aURI, int32_t defaultPort)
  597. {
  598. if (mHostFiltersArray.Length() == 0)
  599. return true;
  600. int32_t port;
  601. nsAutoCString host;
  602. nsresult rv = aURI->GetAsciiHost(host);
  603. if (NS_FAILED(rv) || host.IsEmpty())
  604. return false;
  605. rv = aURI->GetPort(&port);
  606. if (NS_FAILED(rv))
  607. return false;
  608. if (port == -1)
  609. port = defaultPort;
  610. PRNetAddr addr;
  611. bool is_ipaddr = (PR_StringToNetAddr(host.get(), &addr) == PR_SUCCESS);
  612. PRIPv6Addr ipv6;
  613. if (is_ipaddr) {
  614. // convert parsed address to IPv6
  615. if (addr.raw.family == PR_AF_INET) {
  616. // convert to IPv4-mapped address
  617. PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &ipv6);
  618. }
  619. else if (addr.raw.family == PR_AF_INET6) {
  620. // copy the address
  621. memcpy(&ipv6, &addr.ipv6.ip, sizeof(PRIPv6Addr));
  622. }
  623. else {
  624. NS_WARNING("unknown address family");
  625. return true; // allow proxying
  626. }
  627. }
  628. // Don't use proxy for local hosts (plain hostname, no dots)
  629. if ((!is_ipaddr && mFilterLocalHosts && !host.Contains('.')) ||
  630. host.EqualsLiteral("127.0.0.1") ||
  631. host.EqualsLiteral("::1")) {
  632. LOG(("Not using proxy for this local host [%s]!\n", host.get()));
  633. return false; // don't allow proxying
  634. }
  635. int32_t index = -1;
  636. while (++index < int32_t(mHostFiltersArray.Length())) {
  637. HostInfo *hinfo = mHostFiltersArray[index];
  638. if (is_ipaddr != hinfo->is_ipaddr)
  639. continue;
  640. if (hinfo->port && hinfo->port != port)
  641. continue;
  642. if (is_ipaddr) {
  643. // generate masked version of target IPv6 address
  644. PRIPv6Addr masked;
  645. memcpy(&masked, &ipv6, sizeof(PRIPv6Addr));
  646. proxy_MaskIPv6Addr(masked, hinfo->ip.mask_len);
  647. // check for a match
  648. if (memcmp(&masked, &hinfo->ip.addr, sizeof(PRIPv6Addr)) == 0)
  649. return false; // proxy disallowed
  650. }
  651. else {
  652. uint32_t host_len = host.Length();
  653. uint32_t filter_host_len = hinfo->name.host_len;
  654. if (host_len >= filter_host_len) {
  655. //
  656. // compare last |filter_host_len| bytes of target hostname.
  657. //
  658. const char *host_tail = host.get() + host_len - filter_host_len;
  659. if (!PL_strncasecmp(host_tail, hinfo->name.host, filter_host_len)) {
  660. // If the tail of the host string matches the filter
  661. if (filter_host_len > 0 && hinfo->name.host[0] == '.') {
  662. // If the filter was of the form .foo.bar.tld, all such
  663. // matches are correct
  664. return false; // proxy disallowed
  665. }
  666. // abc-def.example.org should not match def.example.org
  667. // however, *.def.example.org should match .def.example.org
  668. // We check that the filter doesn't start with a `.`. If it does,
  669. // then the strncasecmp above should suffice. If it doesn't,
  670. // then we should only consider it a match if the strncasecmp happened
  671. // at a subdomain boundary
  672. if (host_len > filter_host_len && *(host_tail - 1) == '.') {
  673. // If the host was something.foo.bar.tld and the filter
  674. // was foo.bar.tld, it's still a match.
  675. // the character right before the tail must be a
  676. // `.` for this to work
  677. return false; // proxy disallowed
  678. }
  679. if (host_len == filter_host_len) {
  680. // If the host and filter are of the same length,
  681. // they should match
  682. return false; // proxy disallowed
  683. }
  684. }
  685. }
  686. }
  687. }
  688. return true;
  689. }
  690. // kProxyType\* may be referred to externally in
  691. // nsProxyInfo in order to compare by string pointer
  692. const char kProxyType_HTTP[] = "http";
  693. const char kProxyType_HTTPS[] = "https";
  694. const char kProxyType_PROXY[] = "proxy";
  695. const char kProxyType_SOCKS[] = "socks";
  696. const char kProxyType_SOCKS4[] = "socks4";
  697. const char kProxyType_SOCKS5[] = "socks5";
  698. const char kProxyType_DIRECT[] = "direct";
  699. const char *
  700. nsProtocolProxyService::ExtractProxyInfo(const char *start,
  701. uint32_t aResolveFlags,
  702. nsProxyInfo **result)
  703. {
  704. *result = nullptr;
  705. uint32_t flags = 0;
  706. // see BNF in ProxyAutoConfig.h and notes in nsISystemProxySettings.idl
  707. // find end of proxy info delimiter
  708. const char *end = start;
  709. while (*end && *end != ';') ++end;
  710. // find end of proxy type delimiter
  711. const char *sp = start;
  712. while (sp < end && *sp != ' ' && *sp != '\t') ++sp;
  713. uint32_t len = sp - start;
  714. const char *type = nullptr;
  715. switch (len) {
  716. case 4:
  717. if (PL_strncasecmp(start, kProxyType_HTTP, 5) == 0) {
  718. type = kProxyType_HTTP;
  719. }
  720. break;
  721. case 5:
  722. if (PL_strncasecmp(start, kProxyType_PROXY, 5) == 0) {
  723. type = kProxyType_HTTP;
  724. } else if (PL_strncasecmp(start, kProxyType_SOCKS, 5) == 0) {
  725. type = kProxyType_SOCKS4; // assume v4 for 4x compat
  726. } else if (PL_strncasecmp(start, kProxyType_HTTPS, 5) == 0) {
  727. type = kProxyType_HTTPS;
  728. }
  729. break;
  730. case 6:
  731. if (PL_strncasecmp(start, kProxyType_DIRECT, 6) == 0)
  732. type = kProxyType_DIRECT;
  733. else if (PL_strncasecmp(start, kProxyType_SOCKS4, 6) == 0)
  734. type = kProxyType_SOCKS4;
  735. else if (PL_strncasecmp(start, kProxyType_SOCKS5, 6) == 0)
  736. // map "SOCKS5" to "socks" to match contract-id of registered
  737. // SOCKS-v5 socket provider.
  738. type = kProxyType_SOCKS;
  739. break;
  740. }
  741. if (type) {
  742. const char *host = nullptr, *hostEnd = nullptr;
  743. int32_t port = -1;
  744. // If it's a SOCKS5 proxy, do name resolution on the server side.
  745. // We could use this with SOCKS4a servers too, but they might not
  746. // support it.
  747. if (type == kProxyType_SOCKS || mSOCKSProxyRemoteDNS)
  748. flags |= nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST;
  749. // extract host:port
  750. start = sp;
  751. while ((*start == ' ' || *start == '\t') && start < end)
  752. start++;
  753. // port defaults
  754. if (type == kProxyType_HTTP) {
  755. port = 80;
  756. } else if (type == kProxyType_HTTPS) {
  757. port = 443;
  758. } else {
  759. port = 1080;
  760. }
  761. nsProxyInfo *pi = new nsProxyInfo();
  762. pi->mType = type;
  763. pi->mFlags = flags;
  764. pi->mResolveFlags = aResolveFlags;
  765. pi->mTimeout = mFailedProxyTimeout;
  766. // www.foo.com:8080 and http://www.foo.com:8080
  767. nsDependentCSubstring maybeURL(start, end - start);
  768. nsCOMPtr<nsIURI> pacURI;
  769. nsAutoCString urlHost;
  770. if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(pacURI), maybeURL)) &&
  771. NS_SUCCEEDED(pacURI->GetAsciiHost(urlHost)) &&
  772. !urlHost.IsEmpty()) {
  773. // http://www.example.com:8080
  774. pi->mHost = urlHost;
  775. int32_t tPort;
  776. if (NS_SUCCEEDED(pacURI->GetPort(&tPort)) && tPort != -1) {
  777. port = tPort;
  778. }
  779. pi->mPort = port;
  780. }
  781. else {
  782. // www.example.com:8080
  783. if (start < end) {
  784. host = start;
  785. hostEnd = strchr(host, ':');
  786. if (!hostEnd || hostEnd > end) {
  787. hostEnd = end;
  788. // no port, so assume default
  789. }
  790. else {
  791. port = atoi(hostEnd + 1);
  792. }
  793. }
  794. // YES, it is ok to specify a null proxy host.
  795. if (host) {
  796. pi->mHost.Assign(host, hostEnd - host);
  797. pi->mPort = port;
  798. }
  799. }
  800. NS_ADDREF(*result = pi);
  801. }
  802. while (*end == ';' || *end == ' ' || *end == '\t')
  803. ++end;
  804. return end;
  805. }
  806. void
  807. nsProtocolProxyService::GetProxyKey(nsProxyInfo *pi, nsCString &key)
  808. {
  809. key.AssignASCII(pi->mType);
  810. if (!pi->mHost.IsEmpty()) {
  811. key.Append(' ');
  812. key.Append(pi->mHost);
  813. key.Append(':');
  814. key.AppendInt(pi->mPort);
  815. }
  816. }
  817. uint32_t
  818. nsProtocolProxyService::SecondsSinceSessionStart()
  819. {
  820. PRTime now = PR_Now();
  821. // get time elapsed since session start
  822. int64_t diff = now - mSessionStart;
  823. // convert microseconds to seconds
  824. diff /= PR_USEC_PER_SEC;
  825. // return converted 32 bit value
  826. return uint32_t(diff);
  827. }
  828. void
  829. nsProtocolProxyService::EnableProxy(nsProxyInfo *pi)
  830. {
  831. nsAutoCString key;
  832. GetProxyKey(pi, key);
  833. mFailedProxies.Remove(key);
  834. }
  835. void
  836. nsProtocolProxyService::DisableProxy(nsProxyInfo *pi)
  837. {
  838. nsAutoCString key;
  839. GetProxyKey(pi, key);
  840. uint32_t dsec = SecondsSinceSessionStart();
  841. // Add timeout to interval (this is the time when the proxy can
  842. // be tried again).
  843. dsec += pi->mTimeout;
  844. // NOTE: The classic codebase would increase the timeout value
  845. // incrementally each time a subsequent failure occurred.
  846. // We could do the same, but it would require that we not
  847. // remove proxy entries in IsProxyDisabled or otherwise
  848. // change the way we are recording disabled proxies.
  849. // Simpler is probably better for now, and at least the
  850. // user can tune the timeout setting via preferences.
  851. LOG(("DisableProxy %s %d\n", key.get(), dsec));
  852. // If this fails, oh well... means we don't have enough memory
  853. // to remember the failed proxy.
  854. mFailedProxies.Put(key, dsec);
  855. }
  856. bool
  857. nsProtocolProxyService::IsProxyDisabled(nsProxyInfo *pi)
  858. {
  859. nsAutoCString key;
  860. GetProxyKey(pi, key);
  861. uint32_t val;
  862. if (!mFailedProxies.Get(key, &val))
  863. return false;
  864. uint32_t dsec = SecondsSinceSessionStart();
  865. // if time passed has exceeded interval, then try proxy again.
  866. if (dsec > val) {
  867. mFailedProxies.Remove(key);
  868. return false;
  869. }
  870. return true;
  871. }
  872. nsresult
  873. nsProtocolProxyService::SetupPACThread()
  874. {
  875. if (mPACMan)
  876. return NS_OK;
  877. mPACMan = new nsPACMan();
  878. bool mainThreadOnly;
  879. nsresult rv;
  880. if (mSystemProxySettings &&
  881. NS_SUCCEEDED(mSystemProxySettings->GetMainThreadOnly(&mainThreadOnly)) &&
  882. !mainThreadOnly) {
  883. rv = mPACMan->Init(mSystemProxySettings);
  884. }
  885. else {
  886. rv = mPACMan->Init(nullptr);
  887. }
  888. if (NS_FAILED(rv))
  889. mPACMan = nullptr;
  890. return rv;
  891. }
  892. nsresult
  893. nsProtocolProxyService::ResetPACThread()
  894. {
  895. if (!mPACMan)
  896. return NS_OK;
  897. mPACMan->Shutdown();
  898. mPACMan = nullptr;
  899. return SetupPACThread();
  900. }
  901. nsresult
  902. nsProtocolProxyService::ConfigureFromPAC(const nsCString &spec,
  903. bool forceReload)
  904. {
  905. SetupPACThread();
  906. if (mPACMan->IsPACURI(spec) && !forceReload)
  907. return NS_OK;
  908. mFailedProxies.Clear();
  909. return mPACMan->LoadPACFromURI(spec);
  910. }
  911. void
  912. nsProtocolProxyService::ProcessPACString(const nsCString &pacString,
  913. uint32_t aResolveFlags,
  914. nsIProxyInfo **result)
  915. {
  916. if (pacString.IsEmpty()) {
  917. *result = nullptr;
  918. return;
  919. }
  920. const char *proxies = pacString.get();
  921. nsProxyInfo *pi = nullptr, *first = nullptr, *last = nullptr;
  922. while (*proxies) {
  923. proxies = ExtractProxyInfo(proxies, aResolveFlags, &pi);
  924. if (pi && (pi->mType == kProxyType_HTTPS) && !mProxyOverTLS) {
  925. delete pi;
  926. pi = nullptr;
  927. }
  928. if (pi) {
  929. if (last) {
  930. NS_ASSERTION(last->mNext == nullptr, "leaking nsProxyInfo");
  931. last->mNext = pi;
  932. }
  933. else
  934. first = pi;
  935. last = pi;
  936. }
  937. }
  938. *result = first;
  939. }
  940. // nsIProtocolProxyService2
  941. NS_IMETHODIMP
  942. nsProtocolProxyService::ReloadPAC()
  943. {
  944. nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
  945. if (!prefs)
  946. return NS_OK;
  947. int32_t type;
  948. nsresult rv = prefs->GetIntPref(PROXY_PREF("type"), &type);
  949. if (NS_FAILED(rv))
  950. return NS_OK;
  951. nsXPIDLCString pacSpec;
  952. if (type == PROXYCONFIG_PAC)
  953. prefs->GetCharPref(PROXY_PREF("autoconfig_url"), getter_Copies(pacSpec));
  954. else if (type == PROXYCONFIG_WPAD)
  955. pacSpec.AssignLiteral(WPAD_URL);
  956. if (!pacSpec.IsEmpty())
  957. ConfigureFromPAC(pacSpec, true);
  958. return NS_OK;
  959. }
  960. // When sync interface is removed this can go away too
  961. // The nsPACManCallback portion of this implementation should be run
  962. // off the main thread, because it uses a condvar for signaling and
  963. // the main thread is blocking on that condvar -
  964. // so call nsPACMan::AsyncGetProxyForURI() with
  965. // a false mainThreadResponse parameter.
  966. class nsAsyncBridgeRequest final : public nsPACManCallback
  967. {
  968. NS_DECL_THREADSAFE_ISUPPORTS
  969. nsAsyncBridgeRequest()
  970. : mMutex("nsDeprecatedCallback")
  971. , mCondVar(mMutex, "nsDeprecatedCallback")
  972. , mStatus(NS_OK)
  973. , mCompleted(false)
  974. {
  975. }
  976. void OnQueryComplete(nsresult status,
  977. const nsCString &pacString,
  978. const nsCString &newPACURL) override
  979. {
  980. MutexAutoLock lock(mMutex);
  981. mCompleted = true;
  982. mStatus = status;
  983. mPACString = pacString;
  984. mPACURL = newPACURL;
  985. mCondVar.Notify();
  986. }
  987. void Lock() { mMutex.Lock(); }
  988. void Unlock() { mMutex.Unlock(); }
  989. void Wait() { mCondVar.Wait(PR_SecondsToInterval(3)); }
  990. private:
  991. ~nsAsyncBridgeRequest()
  992. {
  993. }
  994. friend class nsProtocolProxyService;
  995. Mutex mMutex;
  996. CondVar mCondVar;
  997. nsresult mStatus;
  998. nsCString mPACString;
  999. nsCString mPACURL;
  1000. bool mCompleted;
  1001. };
  1002. NS_IMPL_ISUPPORTS0(nsAsyncBridgeRequest)
  1003. // nsProtocolProxyService
  1004. nsresult
  1005. nsProtocolProxyService::DeprecatedBlockingResolve(nsIChannel *aChannel,
  1006. uint32_t aFlags,
  1007. nsIProxyInfo **retval)
  1008. {
  1009. NS_ENSURE_ARG_POINTER(aChannel);
  1010. nsCOMPtr<nsIURI> uri;
  1011. nsresult rv = GetProxyURI(aChannel, getter_AddRefs(uri));
  1012. if (NS_FAILED(rv)) return rv;
  1013. nsProtocolInfo info;
  1014. rv = GetProtocolInfo(uri, &info);
  1015. if (NS_FAILED(rv))
  1016. return rv;
  1017. nsCOMPtr<nsIProxyInfo> pi;
  1018. bool usePACThread;
  1019. // SystemProxySettings and PAC files can block the main thread
  1020. // but if neither of them are in use, we can just do the work
  1021. // right here and directly invoke the callback
  1022. rv = Resolve_Internal(aChannel, info, aFlags,
  1023. &usePACThread, getter_AddRefs(pi));
  1024. if (NS_FAILED(rv))
  1025. return rv;
  1026. if (!usePACThread || !mPACMan) {
  1027. ApplyFilters(aChannel, info, pi);
  1028. pi.forget(retval);
  1029. return NS_OK;
  1030. }
  1031. // Use the PAC thread to do the work, so we don't have to reimplement that
  1032. // code, but block this thread on that completion.
  1033. RefPtr<nsAsyncBridgeRequest> ctx = new nsAsyncBridgeRequest();
  1034. ctx->Lock();
  1035. if (NS_SUCCEEDED(mPACMan->AsyncGetProxyForURI(uri, ctx, false))) {
  1036. // this can really block the main thread, so cap it at 3 seconds
  1037. ctx->Wait();
  1038. }
  1039. ctx->Unlock();
  1040. if (!ctx->mCompleted)
  1041. return NS_ERROR_FAILURE;
  1042. if (NS_FAILED(ctx->mStatus))
  1043. return ctx->mStatus;
  1044. // pretty much duplicate real DoCallback logic
  1045. // Generate proxy info from the PAC string if appropriate
  1046. if (!ctx->mPACString.IsEmpty()) {
  1047. LOG(("sync pac thread callback %s\n", ctx->mPACString.get()));
  1048. ProcessPACString(ctx->mPACString, 0, getter_AddRefs(pi));
  1049. ApplyFilters(aChannel, info, pi);
  1050. pi.forget(retval);
  1051. return NS_OK;
  1052. }
  1053. if (!ctx->mPACURL.IsEmpty()) {
  1054. NS_WARNING("sync pac thread callback indicates new pac file load\n");
  1055. // This is a problem and is one of the reasons this blocking interface
  1056. // is deprecated. The main loop needs to spin to make this reload happen. So
  1057. // we are going to kick off the reload and return an error - it will work
  1058. // next time. Because this sync interface is only used in the java plugin it
  1059. // is extremely likely that the pac file has already been loaded anyhow.
  1060. rv = ConfigureFromPAC(ctx->mPACURL, false);
  1061. if (NS_FAILED(rv))
  1062. return rv;
  1063. return NS_ERROR_NOT_AVAILABLE;
  1064. }
  1065. *retval = nullptr;
  1066. return NS_OK;
  1067. }
  1068. nsresult
  1069. nsProtocolProxyService::AsyncResolveInternal(nsIChannel *channel, uint32_t flags,
  1070. nsIProtocolProxyCallback *callback,
  1071. nsICancelable **result,
  1072. bool isSyncOK)
  1073. {
  1074. NS_ENSURE_ARG_POINTER(channel);
  1075. NS_ENSURE_ARG_POINTER(callback);
  1076. nsCOMPtr<nsIURI> uri;
  1077. nsresult rv = GetProxyURI(channel, getter_AddRefs(uri));
  1078. if (NS_FAILED(rv)) return rv;
  1079. *result = nullptr;
  1080. RefPtr<nsAsyncResolveRequest> ctx =
  1081. new nsAsyncResolveRequest(this, channel, flags, callback);
  1082. nsProtocolInfo info;
  1083. rv = GetProtocolInfo(uri, &info);
  1084. if (NS_FAILED(rv))
  1085. return rv;
  1086. nsCOMPtr<nsIProxyInfo> pi;
  1087. bool usePACThread;
  1088. // SystemProxySettings and PAC files can block the main thread
  1089. // but if neither of them are in use, we can just do the work
  1090. // right here and directly invoke the callback
  1091. rv = Resolve_Internal(channel, info, flags,
  1092. &usePACThread, getter_AddRefs(pi));
  1093. if (NS_FAILED(rv))
  1094. return rv;
  1095. if (!usePACThread || !mPACMan) {
  1096. // we can do it locally
  1097. ApplyFilters(channel, info, pi);
  1098. ctx->SetResult(NS_OK, pi);
  1099. if (isSyncOK) {
  1100. ctx->Run();
  1101. return NS_OK;
  1102. }
  1103. rv = ctx->DispatchCallback();
  1104. if (NS_SUCCEEDED(rv))
  1105. ctx.forget(result);
  1106. return rv;
  1107. }
  1108. // else kick off a PAC thread query
  1109. rv = mPACMan->AsyncGetProxyForURI(uri, ctx, true);
  1110. if (NS_SUCCEEDED(rv))
  1111. ctx.forget(result);
  1112. return rv;
  1113. }
  1114. // nsIProtocolProxyService
  1115. NS_IMETHODIMP
  1116. nsProtocolProxyService::AsyncResolve2(nsIChannel *channel, uint32_t flags,
  1117. nsIProtocolProxyCallback *callback,
  1118. nsICancelable **result)
  1119. {
  1120. return AsyncResolveInternal(channel, flags, callback, result, true);
  1121. }
  1122. NS_IMETHODIMP
  1123. nsProtocolProxyService::AsyncResolve(nsISupports *channelOrURI, uint32_t flags,
  1124. nsIProtocolProxyCallback *callback,
  1125. nsICancelable **result)
  1126. {
  1127. nsresult rv;
  1128. // Check if we got a channel:
  1129. nsCOMPtr<nsIChannel> channel = do_QueryInterface(channelOrURI);
  1130. if (!channel) {
  1131. nsCOMPtr<nsIURI> uri = do_QueryInterface(channelOrURI);
  1132. if (!uri) {
  1133. return NS_ERROR_NO_INTERFACE;
  1134. }
  1135. nsCOMPtr<nsIScriptSecurityManager> secMan(
  1136. do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
  1137. NS_ENSURE_SUCCESS(rv, rv);
  1138. nsCOMPtr<nsIPrincipal> systemPrincipal;
  1139. rv = secMan->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
  1140. NS_ENSURE_SUCCESS(rv, rv);
  1141. // creating a temporary channel from the URI which is not
  1142. // used to perform any network loads, hence its safe to
  1143. // use systemPrincipal as the loadingPrincipal.
  1144. rv = NS_NewChannel(getter_AddRefs(channel),
  1145. uri,
  1146. systemPrincipal,
  1147. nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
  1148. nsIContentPolicy::TYPE_OTHER);
  1149. NS_ENSURE_SUCCESS(rv, rv);
  1150. }
  1151. return AsyncResolveInternal(channel, flags, callback, result, false);
  1152. }
  1153. NS_IMETHODIMP
  1154. nsProtocolProxyService::NewProxyInfo(const nsACString &aType,
  1155. const nsACString &aHost,
  1156. int32_t aPort,
  1157. uint32_t aFlags,
  1158. uint32_t aFailoverTimeout,
  1159. nsIProxyInfo *aFailoverProxy,
  1160. nsIProxyInfo **aResult)
  1161. {
  1162. return NewProxyInfoWithAuth(aType, aHost, aPort,
  1163. EmptyCString(), EmptyCString(),
  1164. aFlags, aFailoverTimeout,
  1165. aFailoverProxy, aResult);
  1166. }
  1167. NS_IMETHODIMP
  1168. nsProtocolProxyService::NewProxyInfoWithAuth(const nsACString &aType,
  1169. const nsACString &aHost,
  1170. int32_t aPort,
  1171. const nsACString &aUsername,
  1172. const nsACString &aPassword,
  1173. uint32_t aFlags,
  1174. uint32_t aFailoverTimeout,
  1175. nsIProxyInfo *aFailoverProxy,
  1176. nsIProxyInfo **aResult)
  1177. {
  1178. static const char *types[] = {
  1179. kProxyType_HTTP,
  1180. kProxyType_HTTPS,
  1181. kProxyType_SOCKS,
  1182. kProxyType_SOCKS4,
  1183. kProxyType_DIRECT
  1184. };
  1185. // resolve type; this allows us to avoid copying the type string into each
  1186. // proxy info instance. we just reference the string literals directly :)
  1187. const char *type = nullptr;
  1188. for (uint32_t i = 0; i < ArrayLength(types); ++i) {
  1189. if (aType.LowerCaseEqualsASCII(types[i])) {
  1190. type = types[i];
  1191. break;
  1192. }
  1193. }
  1194. NS_ENSURE_TRUE(type, NS_ERROR_INVALID_ARG);
  1195. // We have only implemented username/password for SOCKS proxies.
  1196. if ((!aUsername.IsEmpty() || !aPassword.IsEmpty()) &&
  1197. !aType.LowerCaseEqualsASCII(kProxyType_SOCKS) &&
  1198. !aType.LowerCaseEqualsASCII(kProxyType_SOCKS4)) {
  1199. return NS_ERROR_NOT_IMPLEMENTED;
  1200. }
  1201. return NewProxyInfo_Internal(type, aHost, aPort,
  1202. aUsername, aPassword,
  1203. aFlags, aFailoverTimeout,
  1204. aFailoverProxy, 0, aResult);
  1205. }
  1206. NS_IMETHODIMP
  1207. nsProtocolProxyService::GetFailoverForProxy(nsIProxyInfo *aProxy,
  1208. nsIURI *aURI,
  1209. nsresult aStatus,
  1210. nsIProxyInfo **aResult)
  1211. {
  1212. // We only support failover when a PAC file is configured, either
  1213. // directly or via system settings
  1214. if (mProxyConfig != PROXYCONFIG_PAC && mProxyConfig != PROXYCONFIG_WPAD &&
  1215. mProxyConfig != PROXYCONFIG_SYSTEM)
  1216. return NS_ERROR_NOT_AVAILABLE;
  1217. // Verify that |aProxy| is one of our nsProxyInfo objects.
  1218. nsCOMPtr<nsProxyInfo> pi = do_QueryInterface(aProxy);
  1219. NS_ENSURE_ARG(pi);
  1220. // OK, the QI checked out. We can proceed.
  1221. // Remember that this proxy is down.
  1222. DisableProxy(pi);
  1223. // NOTE: At this point, we might want to prompt the user if we have
  1224. // not already tried going DIRECT. This is something that the
  1225. // classic codebase supported; however, IE6 does not prompt.
  1226. if (!pi->mNext)
  1227. return NS_ERROR_NOT_AVAILABLE;
  1228. LOG(("PAC failover from %s %s:%d to %s %s:%d\n",
  1229. pi->mType, pi->mHost.get(), pi->mPort,
  1230. pi->mNext->mType, pi->mNext->mHost.get(), pi->mNext->mPort));
  1231. NS_ADDREF(*aResult = pi->mNext);
  1232. return NS_OK;
  1233. }
  1234. nsresult
  1235. nsProtocolProxyService::InsertFilterLink(FilterLink *link, uint32_t position)
  1236. {
  1237. if (!mFilters) {
  1238. mFilters = link;
  1239. return NS_OK;
  1240. }
  1241. // insert into mFilters in sorted order
  1242. FilterLink *last = nullptr;
  1243. for (FilterLink *iter = mFilters; iter; iter = iter->next) {
  1244. if (position < iter->position) {
  1245. if (last) {
  1246. link->next = last->next;
  1247. last->next = link;
  1248. }
  1249. else {
  1250. link->next = mFilters;
  1251. mFilters = link;
  1252. }
  1253. return NS_OK;
  1254. }
  1255. last = iter;
  1256. }
  1257. // our position is equal to or greater than the last link in the list
  1258. last->next = link;
  1259. return NS_OK;
  1260. }
  1261. NS_IMETHODIMP
  1262. nsProtocolProxyService::RegisterFilter(nsIProtocolProxyFilter *filter,
  1263. uint32_t position)
  1264. {
  1265. UnregisterFilter(filter); // remove this filter if we already have it
  1266. FilterLink *link = new FilterLink(position, filter);
  1267. if (!link) {
  1268. return NS_ERROR_OUT_OF_MEMORY;
  1269. }
  1270. return InsertFilterLink(link, position);
  1271. }
  1272. NS_IMETHODIMP
  1273. nsProtocolProxyService::RegisterChannelFilter(nsIProtocolProxyChannelFilter *channelFilter,
  1274. uint32_t position)
  1275. {
  1276. UnregisterChannelFilter(channelFilter); // remove this filter if we already have it
  1277. FilterLink *link = new FilterLink(position, channelFilter);
  1278. if (!link) {
  1279. return NS_ERROR_OUT_OF_MEMORY;
  1280. }
  1281. return InsertFilterLink(link, position);
  1282. }
  1283. nsresult
  1284. nsProtocolProxyService::RemoveFilterLink(nsISupports* givenObject)
  1285. {
  1286. FilterLink *last = nullptr;
  1287. for (FilterLink *iter = mFilters; iter; iter = iter->next) {
  1288. nsCOMPtr<nsISupports> object = do_QueryInterface(iter->filter);
  1289. nsCOMPtr<nsISupports> object2 = do_QueryInterface(iter->channelFilter);
  1290. if (object == givenObject || object2 == givenObject) {
  1291. if (last)
  1292. last->next = iter->next;
  1293. else
  1294. mFilters = iter->next;
  1295. iter->next = nullptr;
  1296. delete iter;
  1297. return NS_OK;
  1298. }
  1299. last = iter;
  1300. }
  1301. // No need to throw an exception in this case.
  1302. return NS_OK;
  1303. }
  1304. NS_IMETHODIMP
  1305. nsProtocolProxyService::UnregisterFilter(nsIProtocolProxyFilter *filter) {
  1306. // QI to nsISupports so we can safely test object identity.
  1307. nsCOMPtr<nsISupports> givenObject = do_QueryInterface(filter);
  1308. return RemoveFilterLink(givenObject);
  1309. }
  1310. NS_IMETHODIMP
  1311. nsProtocolProxyService::UnregisterChannelFilter(nsIProtocolProxyChannelFilter *channelFilter) {
  1312. // QI to nsISupports so we can safely test object identity.
  1313. nsCOMPtr<nsISupports> givenObject = do_QueryInterface(channelFilter);
  1314. return RemoveFilterLink(givenObject);
  1315. }
  1316. NS_IMETHODIMP
  1317. nsProtocolProxyService::GetProxyConfigType(uint32_t* aProxyConfigType)
  1318. {
  1319. *aProxyConfigType = mProxyConfig;
  1320. return NS_OK;
  1321. }
  1322. void
  1323. nsProtocolProxyService::LoadHostFilters(const nsACString& aFilters)
  1324. {
  1325. // check to see the owners flag? /!?/ TODO
  1326. if (mHostFiltersArray.Length() > 0) {
  1327. mHostFiltersArray.Clear();
  1328. }
  1329. if (aFilters.IsEmpty()) {
  1330. return;
  1331. }
  1332. //
  1333. // filter = ( host | domain | ipaddr ["/" mask] ) [":" port]
  1334. // filters = filter *( "," LWS filter)
  1335. //
  1336. // Reset mFilterLocalHosts - will be set to true if "<local>" is in pref string
  1337. mFilterLocalHosts = false;
  1338. mozilla::Tokenizer t(aFilters);
  1339. mozilla::Tokenizer::Token token;
  1340. bool eof = false;
  1341. // while (*filters) {
  1342. while (!eof) {
  1343. // skip over spaces and ,
  1344. t.SkipWhites();
  1345. while (t.CheckChar(',')) {
  1346. t.SkipWhites();
  1347. }
  1348. nsAutoCString portStr;
  1349. nsAutoCString hostStr;
  1350. nsAutoCString maskStr;
  1351. t.Record();
  1352. bool parsingIPv6 = false;
  1353. bool parsingPort = false;
  1354. bool parsingMask = false;
  1355. while (t.Next(token)) {
  1356. if (token.Equals(mozilla::Tokenizer::Token::EndOfFile())) {
  1357. eof = true;
  1358. break;
  1359. }
  1360. if (token.Equals(mozilla::Tokenizer::Token::Char(',')) ||
  1361. token.Type() == mozilla::Tokenizer::TOKEN_WS) {
  1362. break;
  1363. }
  1364. if (token.Equals(mozilla::Tokenizer::Token::Char('['))) {
  1365. parsingIPv6 = true;
  1366. continue;
  1367. }
  1368. if (!parsingIPv6 && token.Equals(mozilla::Tokenizer::Token::Char(':'))) {
  1369. // Port is starting. Claim the previous as host.
  1370. if (parsingMask) {
  1371. t.Claim(maskStr);
  1372. } else {
  1373. t.Claim(hostStr);
  1374. }
  1375. t.Record();
  1376. parsingPort = true;
  1377. continue;
  1378. } else if (token.Equals(mozilla::Tokenizer::Token::Char('/'))) {
  1379. t.Claim(hostStr);
  1380. t.Record();
  1381. parsingMask = true;
  1382. continue;
  1383. } else if (token.Equals(mozilla::Tokenizer::Token::Char(']'))) {
  1384. parsingIPv6 = false;
  1385. continue;
  1386. }
  1387. }
  1388. if (!parsingPort && !parsingMask) {
  1389. t.Claim(hostStr);
  1390. } else if (parsingPort) {
  1391. t.Claim(portStr);
  1392. } else if (parsingMask) {
  1393. t.Claim(maskStr);
  1394. } else {
  1395. NS_WARNING("Could not parse this rule");
  1396. continue;
  1397. }
  1398. if (hostStr.IsEmpty()) {
  1399. continue;
  1400. }
  1401. // If the current host filter is "<local>", then all local (i.e.
  1402. // no dots in the hostname) hosts should bypass the proxy
  1403. if (hostStr.EqualsIgnoreCase("<local>")) {
  1404. mFilterLocalHosts = true;
  1405. LOG(("loaded filter for local hosts "
  1406. "(plain host names, no dots)\n"));
  1407. // Continue to next host filter;
  1408. continue;
  1409. }
  1410. // For all other host filters, create HostInfo object and add to list
  1411. HostInfo *hinfo = new HostInfo();
  1412. nsresult rv = NS_OK;
  1413. int32_t port = portStr.ToInteger(&rv);
  1414. if (NS_FAILED(rv)) {
  1415. port = 0;
  1416. }
  1417. hinfo->port = port;
  1418. int32_t maskLen = maskStr.ToInteger(&rv);
  1419. if (NS_FAILED(rv)) {
  1420. maskLen = 128;
  1421. }
  1422. // PR_StringToNetAddr can't parse brackets enclosed IPv6
  1423. nsAutoCString addrString = hostStr;
  1424. if (hostStr.First() == '[' && hostStr.Last() == ']') {
  1425. addrString = Substring(hostStr, 1, hostStr.Length() - 2);
  1426. }
  1427. PRNetAddr addr;
  1428. if (PR_StringToNetAddr(addrString.get(), &addr) == PR_SUCCESS) {
  1429. hinfo->is_ipaddr = true;
  1430. hinfo->ip.family = PR_AF_INET6; // we always store address as IPv6
  1431. hinfo->ip.mask_len = maskLen;
  1432. if (hinfo->ip.mask_len == 0) {
  1433. NS_WARNING("invalid mask");
  1434. goto loser;
  1435. }
  1436. if (addr.raw.family == PR_AF_INET) {
  1437. // convert to IPv4-mapped address
  1438. PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &hinfo->ip.addr);
  1439. // adjust mask_len accordingly
  1440. if (hinfo->ip.mask_len <= 32)
  1441. hinfo->ip.mask_len += 96;
  1442. }
  1443. else if (addr.raw.family == PR_AF_INET6) {
  1444. // copy the address
  1445. memcpy(&hinfo->ip.addr, &addr.ipv6.ip, sizeof(PRIPv6Addr));
  1446. }
  1447. else {
  1448. NS_WARNING("unknown address family");
  1449. goto loser;
  1450. }
  1451. // apply mask to IPv6 address
  1452. proxy_MaskIPv6Addr(hinfo->ip.addr, hinfo->ip.mask_len);
  1453. }
  1454. else {
  1455. nsAutoCString host;
  1456. if (hostStr.First() == '*') {
  1457. host = Substring(hostStr, 1);
  1458. } else {
  1459. host = hostStr;
  1460. }
  1461. if (host.IsEmpty()) {
  1462. hinfo->name.host = nullptr;
  1463. goto loser;
  1464. }
  1465. hinfo->name.host_len = host.Length();
  1466. hinfo->is_ipaddr = false;
  1467. hinfo->name.host = ToNewCString(host);
  1468. if (!hinfo->name.host)
  1469. goto loser;
  1470. }
  1471. //#define DEBUG_DUMP_FILTERS
  1472. #ifdef DEBUG_DUMP_FILTERS
  1473. printf("loaded filter[%zu]:\n", mHostFiltersArray.Length());
  1474. printf(" is_ipaddr = %u\n", hinfo->is_ipaddr);
  1475. printf(" port = %u\n", hinfo->port);
  1476. printf(" host = %s\n", hostStr.get());
  1477. if (hinfo->is_ipaddr) {
  1478. printf(" ip.family = %x\n", hinfo->ip.family);
  1479. printf(" ip.mask_len = %u\n", hinfo->ip.mask_len);
  1480. PRNetAddr netAddr;
  1481. PR_SetNetAddr(PR_IpAddrNull, PR_AF_INET6, 0, &netAddr);
  1482. memcpy(&netAddr.ipv6.ip, &hinfo->ip.addr, sizeof(hinfo->ip.addr));
  1483. char buf[256];
  1484. PR_NetAddrToString(&netAddr, buf, sizeof(buf));
  1485. printf(" ip.addr = %s\n", buf);
  1486. }
  1487. else {
  1488. printf(" name.host = %s\n", hinfo->name.host);
  1489. }
  1490. #endif
  1491. mHostFiltersArray.AppendElement(hinfo);
  1492. hinfo = nullptr;
  1493. loser:
  1494. delete hinfo;
  1495. }
  1496. }
  1497. nsresult
  1498. nsProtocolProxyService::GetProtocolInfo(nsIURI *uri, nsProtocolInfo *info)
  1499. {
  1500. NS_PRECONDITION(uri, "URI is null");
  1501. NS_PRECONDITION(info, "info is null");
  1502. nsresult rv;
  1503. rv = uri->GetScheme(info->scheme);
  1504. if (NS_FAILED(rv))
  1505. return rv;
  1506. nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv);
  1507. if (NS_FAILED(rv))
  1508. return rv;
  1509. nsCOMPtr<nsIProtocolHandler> handler;
  1510. rv = ios->GetProtocolHandler(info->scheme.get(), getter_AddRefs(handler));
  1511. if (NS_FAILED(rv))
  1512. return rv;
  1513. rv = handler->DoGetProtocolFlags(uri, &info->flags);
  1514. if (NS_FAILED(rv))
  1515. return rv;
  1516. rv = handler->GetDefaultPort(&info->defaultPort);
  1517. return rv;
  1518. }
  1519. nsresult
  1520. nsProtocolProxyService::NewProxyInfo_Internal(const char *aType,
  1521. const nsACString &aHost,
  1522. int32_t aPort,
  1523. const nsACString &aUsername,
  1524. const nsACString &aPassword,
  1525. uint32_t aFlags,
  1526. uint32_t aFailoverTimeout,
  1527. nsIProxyInfo *aFailoverProxy,
  1528. uint32_t aResolveFlags,
  1529. nsIProxyInfo **aResult)
  1530. {
  1531. if (aPort <= 0)
  1532. aPort = -1;
  1533. nsCOMPtr<nsProxyInfo> failover;
  1534. if (aFailoverProxy) {
  1535. failover = do_QueryInterface(aFailoverProxy);
  1536. NS_ENSURE_ARG(failover);
  1537. }
  1538. nsProxyInfo *proxyInfo = new nsProxyInfo();
  1539. if (!proxyInfo)
  1540. return NS_ERROR_OUT_OF_MEMORY;
  1541. proxyInfo->mType = aType;
  1542. proxyInfo->mHost = aHost;
  1543. proxyInfo->mPort = aPort;
  1544. proxyInfo->mUsername = aUsername;
  1545. proxyInfo->mPassword = aPassword;
  1546. proxyInfo->mFlags = aFlags;
  1547. proxyInfo->mResolveFlags = aResolveFlags;
  1548. proxyInfo->mTimeout = aFailoverTimeout == UINT32_MAX
  1549. ? mFailedProxyTimeout : aFailoverTimeout;
  1550. failover.swap(proxyInfo->mNext);
  1551. NS_ADDREF(*aResult = proxyInfo);
  1552. return NS_OK;
  1553. }
  1554. nsresult
  1555. nsProtocolProxyService::Resolve_Internal(nsIChannel *channel,
  1556. const nsProtocolInfo &info,
  1557. uint32_t flags,
  1558. bool *usePACThread,
  1559. nsIProxyInfo **result)
  1560. {
  1561. NS_ENSURE_ARG_POINTER(channel);
  1562. nsresult rv = SetupPACThread();
  1563. if (NS_FAILED(rv))
  1564. return rv;
  1565. *usePACThread = false;
  1566. *result = nullptr;
  1567. if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
  1568. return NS_OK; // Can't proxy this (filters may not override)
  1569. nsCOMPtr<nsIURI> uri;
  1570. rv = GetProxyURI(channel, getter_AddRefs(uri));
  1571. if (NS_FAILED(rv)) return rv;
  1572. // See bug #586908.
  1573. // Avoid endless loop if |uri| is the current PAC-URI. Returning OK
  1574. // here means that we will not use a proxy for this connection.
  1575. if (mPACMan && mPACMan->IsPACURI(uri))
  1576. return NS_OK;
  1577. // If proxies are enabled and this host:port combo is supposed to use a
  1578. // proxy, check for a proxy.
  1579. if ((mProxyConfig == PROXYCONFIG_DIRECT) ||
  1580. !CanUseProxy(uri, info.defaultPort)) {
  1581. return NS_OK;
  1582. }
  1583. bool mainThreadOnly;
  1584. if (mSystemProxySettings &&
  1585. mProxyConfig == PROXYCONFIG_SYSTEM &&
  1586. NS_SUCCEEDED(mSystemProxySettings->GetMainThreadOnly(&mainThreadOnly)) &&
  1587. !mainThreadOnly) {
  1588. *usePACThread = true;
  1589. return NS_OK;
  1590. }
  1591. if (mSystemProxySettings && mProxyConfig == PROXYCONFIG_SYSTEM) {
  1592. // If the system proxy setting implementation is not threadsafe (e.g
  1593. // linux gconf), we'll do it inline here. Such implementations promise
  1594. // not to block
  1595. nsAutoCString PACURI;
  1596. nsAutoCString pacString;
  1597. if (NS_SUCCEEDED(mSystemProxySettings->GetPACURI(PACURI)) &&
  1598. !PACURI.IsEmpty()) {
  1599. // There is a PAC URI configured. If it is unchanged, then
  1600. // just execute the PAC thread. If it is changed then load
  1601. // the new value
  1602. if (mPACMan && mPACMan->IsPACURI(PACURI)) {
  1603. // unchanged
  1604. *usePACThread = true;
  1605. return NS_OK;
  1606. }
  1607. ConfigureFromPAC(PACURI, false);
  1608. return NS_OK;
  1609. }
  1610. nsAutoCString spec;
  1611. nsAutoCString host;
  1612. nsAutoCString scheme;
  1613. int32_t port = -1;
  1614. uri->GetAsciiSpec(spec);
  1615. uri->GetAsciiHost(host);
  1616. uri->GetScheme(scheme);
  1617. uri->GetPort(&port);
  1618. // now try the system proxy settings for this particular url
  1619. if (NS_SUCCEEDED(mSystemProxySettings->
  1620. GetProxyForURI(spec, scheme, host, port,
  1621. pacString))) {
  1622. ProcessPACString(pacString, 0, result);
  1623. return NS_OK;
  1624. }
  1625. }
  1626. // if proxies are enabled and this host:port combo is supposed to use a
  1627. // proxy, check for a proxy.
  1628. if (mProxyConfig == PROXYCONFIG_DIRECT ||
  1629. (mProxyConfig == PROXYCONFIG_MANUAL &&
  1630. !CanUseProxy(uri, info.defaultPort)))
  1631. return NS_OK;
  1632. // Proxy auto config magic...
  1633. if (mProxyConfig == PROXYCONFIG_PAC || mProxyConfig == PROXYCONFIG_WPAD) {
  1634. // Do not query PAC now.
  1635. *usePACThread = true;
  1636. return NS_OK;
  1637. }
  1638. // If we aren't in manual proxy configuration mode then we don't
  1639. // want to honor any manual specific prefs that might be still set
  1640. if (mProxyConfig != PROXYCONFIG_MANUAL)
  1641. return NS_OK;
  1642. // proxy info values for manual configuration mode
  1643. const char *type = nullptr;
  1644. const nsACString *host = nullptr;
  1645. int32_t port = -1;
  1646. uint32_t proxyFlags = 0;
  1647. if ((flags & RESOLVE_PREFER_SOCKS_PROXY) &&
  1648. !mSOCKSProxyTarget.IsEmpty() &&
  1649. (IsHostLocalTarget(mSOCKSProxyTarget) || mSOCKSProxyPort > 0)) {
  1650. host = &mSOCKSProxyTarget;
  1651. if (mSOCKSProxyVersion == 4)
  1652. type = kProxyType_SOCKS4;
  1653. else
  1654. type = kProxyType_SOCKS;
  1655. port = mSOCKSProxyPort;
  1656. if (mSOCKSProxyRemoteDNS)
  1657. proxyFlags |= nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST;
  1658. }
  1659. else if ((flags & RESOLVE_PREFER_HTTPS_PROXY) &&
  1660. !mHTTPSProxyHost.IsEmpty() && mHTTPSProxyPort > 0) {
  1661. host = &mHTTPSProxyHost;
  1662. type = kProxyType_HTTP;
  1663. port = mHTTPSProxyPort;
  1664. }
  1665. else if (!mHTTPProxyHost.IsEmpty() && mHTTPProxyPort > 0 &&
  1666. ((flags & RESOLVE_IGNORE_URI_SCHEME) ||
  1667. info.scheme.EqualsLiteral("http"))) {
  1668. host = &mHTTPProxyHost;
  1669. type = kProxyType_HTTP;
  1670. port = mHTTPProxyPort;
  1671. }
  1672. else if (!mHTTPSProxyHost.IsEmpty() && mHTTPSProxyPort > 0 &&
  1673. !(flags & RESOLVE_IGNORE_URI_SCHEME) &&
  1674. info.scheme.EqualsLiteral("https")) {
  1675. host = &mHTTPSProxyHost;
  1676. type = kProxyType_HTTP;
  1677. port = mHTTPSProxyPort;
  1678. }
  1679. else if (!mFTPProxyHost.IsEmpty() && mFTPProxyPort > 0 &&
  1680. !(flags & RESOLVE_IGNORE_URI_SCHEME) &&
  1681. info.scheme.EqualsLiteral("ftp")) {
  1682. host = &mFTPProxyHost;
  1683. type = kProxyType_HTTP;
  1684. port = mFTPProxyPort;
  1685. }
  1686. else if (!mSOCKSProxyTarget.IsEmpty() &&
  1687. (IsHostLocalTarget(mSOCKSProxyTarget) || mSOCKSProxyPort > 0)) {
  1688. host = &mSOCKSProxyTarget;
  1689. if (mSOCKSProxyVersion == 4)
  1690. type = kProxyType_SOCKS4;
  1691. else
  1692. type = kProxyType_SOCKS;
  1693. port = mSOCKSProxyPort;
  1694. if (mSOCKSProxyRemoteDNS)
  1695. proxyFlags |= nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST;
  1696. }
  1697. if (type) {
  1698. rv = NewProxyInfo_Internal(type, *host, port,
  1699. EmptyCString(), EmptyCString(),
  1700. proxyFlags, UINT32_MAX, nullptr, flags,
  1701. result);
  1702. if (NS_FAILED(rv))
  1703. return rv;
  1704. }
  1705. return NS_OK;
  1706. }
  1707. void
  1708. nsProtocolProxyService::MaybeDisableDNSPrefetch(nsIProxyInfo *aProxy)
  1709. {
  1710. // Disable Prefetch in the DNS service if a proxy is in use.
  1711. if (!aProxy)
  1712. return;
  1713. nsCOMPtr<nsProxyInfo> pi = do_QueryInterface(aProxy);
  1714. if (!pi ||
  1715. !pi->mType ||
  1716. pi->mType == kProxyType_DIRECT)
  1717. return;
  1718. nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
  1719. if (!dns)
  1720. return;
  1721. nsCOMPtr<nsPIDNSService> pdns = do_QueryInterface(dns);
  1722. if (!pdns)
  1723. return;
  1724. // We lose the prefetch optimization for the life of the dns service.
  1725. pdns->SetPrefetchEnabled(false);
  1726. }
  1727. void
  1728. nsProtocolProxyService::ApplyFilters(nsIChannel *channel,
  1729. const nsProtocolInfo &info,
  1730. nsIProxyInfo **list)
  1731. {
  1732. if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY))
  1733. return;
  1734. // We prune the proxy list prior to invoking each filter. This may be
  1735. // somewhat inefficient, but it seems like a good idea since we want each
  1736. // filter to "see" a valid proxy list.
  1737. nsCOMPtr<nsIProxyInfo> result;
  1738. for (FilterLink *iter = mFilters; iter; iter = iter->next) {
  1739. PruneProxyInfo(info, list);
  1740. nsresult rv = NS_OK;
  1741. if (iter->filter) {
  1742. nsCOMPtr<nsIURI> uri;
  1743. rv = GetProxyURI(channel, getter_AddRefs(uri));
  1744. if (uri) {
  1745. rv = iter->filter->ApplyFilter(this, uri, *list,
  1746. getter_AddRefs(result));
  1747. }
  1748. } else if (iter->channelFilter) {
  1749. rv = iter->channelFilter->ApplyFilter(this, channel, *list,
  1750. getter_AddRefs(result));
  1751. }
  1752. if (NS_FAILED(rv))
  1753. continue;
  1754. result.swap(*list);
  1755. }
  1756. PruneProxyInfo(info, list);
  1757. }
  1758. void
  1759. nsProtocolProxyService::PruneProxyInfo(const nsProtocolInfo &info,
  1760. nsIProxyInfo **list)
  1761. {
  1762. if (!*list)
  1763. return;
  1764. nsProxyInfo *head = nullptr;
  1765. CallQueryInterface(*list, &head);
  1766. if (!head) {
  1767. NS_NOTREACHED("nsIProxyInfo must QI to nsProxyInfo");
  1768. return;
  1769. }
  1770. NS_RELEASE(*list);
  1771. // Pruning of disabled proxies works like this:
  1772. // - If all proxies are disabled, return the full list
  1773. // - Otherwise, remove the disabled proxies.
  1774. //
  1775. // Pruning of disallowed proxies works like this:
  1776. // - If the protocol handler disallows the proxy, then we disallow it.
  1777. // Start by removing all disallowed proxies if required:
  1778. if (!(info.flags & nsIProtocolHandler::ALLOWS_PROXY_HTTP)) {
  1779. nsProxyInfo *last = nullptr, *iter = head;
  1780. while (iter) {
  1781. if ((iter->Type() == kProxyType_HTTP) ||
  1782. (iter->Type() == kProxyType_HTTPS)) {
  1783. // reject!
  1784. if (last)
  1785. last->mNext = iter->mNext;
  1786. else
  1787. head = iter->mNext;
  1788. nsProxyInfo *next = iter->mNext;
  1789. iter->mNext = nullptr;
  1790. iter->Release();
  1791. iter = next;
  1792. } else {
  1793. last = iter;
  1794. iter = iter->mNext;
  1795. }
  1796. }
  1797. if (!head)
  1798. return;
  1799. }
  1800. // Now, scan to see if all remaining proxies are disabled. If so, then
  1801. // we'll just bail and return them all. Otherwise, we'll go and prune the
  1802. // disabled ones.
  1803. bool allDisabled = true;
  1804. nsProxyInfo *iter;
  1805. for (iter = head; iter; iter = iter->mNext) {
  1806. if (!IsProxyDisabled(iter)) {
  1807. allDisabled = false;
  1808. break;
  1809. }
  1810. }
  1811. if (allDisabled)
  1812. LOG(("All proxies are disabled, so trying all again"));
  1813. else {
  1814. // remove any disabled proxies.
  1815. nsProxyInfo *last = nullptr;
  1816. for (iter = head; iter; ) {
  1817. if (IsProxyDisabled(iter)) {
  1818. // reject!
  1819. nsProxyInfo *reject = iter;
  1820. iter = iter->mNext;
  1821. if (last)
  1822. last->mNext = iter;
  1823. else
  1824. head = iter;
  1825. reject->mNext = nullptr;
  1826. NS_RELEASE(reject);
  1827. continue;
  1828. }
  1829. // since we are about to use this proxy, make sure it is not on
  1830. // the disabled proxy list. we'll add it back to that list if
  1831. // we have to (in GetFailoverForProxy).
  1832. //
  1833. // XXX(darin): It might be better to do this as a final pass.
  1834. //
  1835. EnableProxy(iter);
  1836. last = iter;
  1837. iter = iter->mNext;
  1838. }
  1839. }
  1840. // if only DIRECT was specified then return no proxy info, and we're done.
  1841. if (head && !head->mNext && head->mType == kProxyType_DIRECT)
  1842. NS_RELEASE(head);
  1843. *list = head; // Transfer ownership
  1844. }
  1845. } // namespace net
  1846. } // namespace mozilla