LCOV - code coverage report
Current view: top level - netwerk/protocol/http - nsHttpConnectionInfo.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 65 161 40.4 %
Date: 2017-07-14 16:53:18 Functions: 7 12 58.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set sw=4 ts=8 et tw=80 : */
       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             : 
       7             : // HttpLog.h should generally be included first
       8             : #include "HttpLog.h"
       9             : 
      10             : // Log on level :5, instead of default :4.
      11             : #undef LOG
      12             : #define LOG(args) LOG5(args)
      13             : #undef LOG_ENABLED
      14             : #define LOG_ENABLED() LOG5_ENABLED()
      15             : 
      16             : #include "nsHttpConnectionInfo.h"
      17             : #include "mozilla/net/DNS.h"
      18             : #include "prnetdb.h"
      19             : #include "nsICryptoHash.h"
      20             : #include "nsComponentManagerUtils.h"
      21             : #include "nsIProtocolProxyService.h"
      22             : 
      23             : static nsresult
      24           0 : SHA256(const char* aPlainText, nsAutoCString& aResult)
      25             : {
      26             :   static nsICryptoHash* hasher = nullptr;
      27             :   nsresult rv;
      28           0 :   if (!hasher) {
      29           0 :     rv = CallCreateInstance("@mozilla.org/security/hash;1", &hasher);
      30           0 :     if (NS_FAILED(rv)) {
      31           0 :       LOG(("nsHttpDigestAuth: no crypto hash!\n"));
      32           0 :       return rv;
      33             :     }
      34             :   }
      35             : 
      36           0 :   rv = hasher->Init(nsICryptoHash::SHA256);
      37           0 :   NS_ENSURE_SUCCESS(rv, rv);
      38             : 
      39           0 :   rv = hasher->Update((unsigned char*) aPlainText, strlen(aPlainText));
      40           0 :   NS_ENSURE_SUCCESS(rv, rv);
      41             : 
      42           0 :   rv = hasher->Finish(false, aResult);
      43           0 :   return rv;
      44             : }
      45             : 
      46             : namespace mozilla {
      47             : namespace net {
      48             : 
      49           8 : nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &originHost,
      50             :                                            int32_t originPort,
      51             :                                            const nsACString &npnToken,
      52             :                                            const nsACString &username,
      53             :                                            nsProxyInfo *proxyInfo,
      54             :                                            const OriginAttributes &originAttributes,
      55           8 :                                            bool endToEndSSL)
      56           8 :     : mRoutedPort(443)
      57             : {
      58           8 :     Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes, endToEndSSL);
      59           8 : }
      60             : 
      61           0 : nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &originHost,
      62             :                                            int32_t originPort,
      63             :                                            const nsACString &npnToken,
      64             :                                            const nsACString &username,
      65             :                                            nsProxyInfo *proxyInfo,
      66             :                                            const OriginAttributes &originAttributes,
      67             :                                            const nsACString &routedHost,
      68           0 :                                            int32_t routedPort)
      69             : {
      70           0 :     mEndToEndSSL = true; // so DefaultPort() works
      71           0 :     mRoutedPort = routedPort == -1 ? DefaultPort() : routedPort;
      72             : 
      73           0 :     if (!originHost.Equals(routedHost) || (originPort != routedPort)) {
      74           0 :         mRoutedHost = routedHost;
      75             :     }
      76           0 :     Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes, true);
      77           0 : }
      78             : 
      79             : void
      80           8 : nsHttpConnectionInfo::Init(const nsACString &host, int32_t port,
      81             :                            const nsACString &npnToken,
      82             :                            const nsACString &username,
      83             :                            nsProxyInfo* proxyInfo,
      84             :                            const OriginAttributes &originAttributes,
      85             :                            bool e2eSSL)
      86             : {
      87           8 :     LOG(("Init nsHttpConnectionInfo @%p\n", this));
      88             : 
      89           8 :     mUsername = username;
      90           8 :     mProxyInfo = proxyInfo;
      91           8 :     mEndToEndSSL = e2eSSL;
      92           8 :     mUsingConnect = false;
      93           8 :     mNPNToken = npnToken;
      94           8 :     mOriginAttributes = originAttributes;
      95             : 
      96           8 :     mUsingHttpsProxy = (proxyInfo && proxyInfo->IsHTTPS());
      97           8 :     mUsingHttpProxy = mUsingHttpsProxy || (proxyInfo && proxyInfo->IsHTTP());
      98             : 
      99           8 :     if (mUsingHttpProxy) {
     100           0 :         mUsingConnect = mEndToEndSSL;  // SSL always uses CONNECT
     101           0 :         uint32_t resolveFlags = 0;
     102           0 :         if (NS_SUCCEEDED(mProxyInfo->GetResolveFlags(&resolveFlags)) &&
     103           0 :             resolveFlags & nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL) {
     104           0 :             mUsingConnect = true;
     105             :         }
     106             :     }
     107             : 
     108           8 :     SetOriginServer(host, port);
     109           8 : }
     110             : 
     111             : void
     112           0 : nsHttpConnectionInfo::SetNetworkInterfaceId(const nsACString& aNetworkInterfaceId)
     113             : {
     114           0 :     mNetworkInterfaceId = aNetworkInterfaceId;
     115           0 :     BuildHashKey();
     116           0 : }
     117             : 
     118           8 : void nsHttpConnectionInfo::BuildHashKey()
     119             : {
     120             :     //
     121             :     // build hash key:
     122             :     //
     123             :     // the hash key uniquely identifies the connection type.  two connections
     124             :     // are "equal" if they end up talking the same protocol to the same server
     125             :     // and are both used for anonymous or non-anonymous connection only;
     126             :     // anonymity of the connection is setup later from nsHttpChannel::AsyncOpen
     127             :     // where we know we use anonymous connection (LOAD_ANONYMOUS load flag)
     128             :     //
     129             : 
     130             :     const char *keyHost;
     131             :     int32_t keyPort;
     132             : 
     133           8 :     if (mUsingHttpProxy && !mUsingConnect) {
     134           0 :         keyHost = ProxyHost();
     135           0 :         keyPort = ProxyPort();
     136             :     } else {
     137           8 :         keyHost = Origin();
     138           8 :         keyPort = OriginPort();
     139             :     }
     140             : 
     141             :     // The hashkey has 4 fields followed by host connection info
     142             :     // byte 0 is P/T/. {P,T} for Plaintext/TLS Proxy over HTTP
     143             :     // byte 1 is S/. S is for end to end ssl such as https:// uris
     144             :     // byte 2 is A/. A is for an anonymous channel (no cookies, etc..)
     145             :     // byte 3 is P/. P is for a private browising channel
     146             :     // byte 4 is I/. I is for insecure scheme on TLS for http:// uris
     147             :     // byte 5 is X/. X is for disallow_spdy flag
     148             :     // byte 6 is C/. C is for be Conservative
     149             : 
     150           8 :     mHashKey.AssignLiteral(".......");
     151           8 :     mHashKey.Append(keyHost);
     152           8 :     if (!mNetworkInterfaceId.IsEmpty()) {
     153           0 :         mHashKey.Append('(');
     154           0 :         mHashKey.Append(mNetworkInterfaceId);
     155           0 :         mHashKey.Append(')');
     156             :     }
     157           8 :     mHashKey.Append(':');
     158           8 :     mHashKey.AppendInt(keyPort);
     159           8 :     if (!mUsername.IsEmpty()) {
     160           0 :         mHashKey.Append('[');
     161           0 :         mHashKey.Append(mUsername);
     162           0 :         mHashKey.Append(']');
     163             :     }
     164             : 
     165           8 :     if (mUsingHttpsProxy) {
     166           0 :         mHashKey.SetCharAt('T', 0);
     167           8 :     } else if (mUsingHttpProxy) {
     168           0 :         mHashKey.SetCharAt('P', 0);
     169             :     }
     170           8 :     if (mEndToEndSSL) {
     171           0 :         mHashKey.SetCharAt('S', 1);
     172             :     }
     173             : 
     174             :     // NOTE: for transparent proxies (e.g., SOCKS) we need to encode the proxy
     175             :     // info in the hash key (this ensures that we will continue to speak the
     176             :     // right protocol even if our proxy preferences change).
     177             :     //
     178             :     // NOTE: for SSL tunnels add the proxy information to the cache key.
     179             :     // We cannot use the proxy as the host parameter (as we do for non SSL)
     180             :     // because this is a single host tunnel, but we need to include the proxy
     181             :     // information so that a change in proxy config will mean this connection
     182             :     // is not reused
     183             : 
     184             :     // NOTE: Adding the username and the password provides a means to isolate
     185             :     // keep-alive to the URL bar domain as well: If the username is the URL bar
     186             :     // domain, keep-alive connections are not reused by resources bound to
     187             :     // different URL bar domains as the respective hash keys are not matching.
     188             : 
     189          16 :     if ((!mUsingHttpProxy && ProxyHost()) ||
     190           8 :         (mUsingHttpProxy && mUsingConnect)) {
     191           0 :         mHashKey.AppendLiteral(" (");
     192           0 :         mHashKey.Append(ProxyType());
     193           0 :         mHashKey.Append(':');
     194           0 :         mHashKey.Append(ProxyHost());
     195           0 :         mHashKey.Append(':');
     196           0 :         mHashKey.AppendInt(ProxyPort());
     197           0 :         mHashKey.Append(')');
     198           0 :         mHashKey.Append('[');
     199           0 :         mHashKey.Append(ProxyUsername());
     200           0 :         mHashKey.Append(':');
     201           0 :         const char* password = ProxyPassword();
     202           0 :         if (strlen(password) > 0) {
     203           0 :             nsAutoCString digestedPassword;
     204           0 :             nsresult rv = SHA256(password, digestedPassword);
     205           0 :             if (rv == NS_OK) {
     206           0 :                 mHashKey.Append(digestedPassword);
     207             :             }
     208             :         }
     209           0 :         mHashKey.Append(']');
     210             :     }
     211             : 
     212           8 :     if(!mRoutedHost.IsEmpty()) {
     213           0 :         mHashKey.AppendLiteral(" <ROUTE-via ");
     214           0 :         mHashKey.Append(mRoutedHost);
     215           0 :         mHashKey.Append(':');
     216           0 :         mHashKey.AppendInt(mRoutedPort);
     217           0 :         mHashKey.Append('>');
     218             :     }
     219             : 
     220           8 :     if (!mNPNToken.IsEmpty()) {
     221           0 :         mHashKey.AppendLiteral(" {NPN-TOKEN ");
     222           0 :         mHashKey.Append(mNPNToken);
     223           0 :         mHashKey.AppendLiteral("}");
     224             :     }
     225             : 
     226          16 :     nsAutoCString originAttributes;
     227           8 :     mOriginAttributes.CreateSuffix(originAttributes);
     228           8 :     mHashKey.Append(originAttributes);
     229           8 : }
     230             : 
     231             : void
     232           8 : nsHttpConnectionInfo::SetOriginServer(const nsACString &host, int32_t port)
     233             : {
     234           8 :     mOrigin = host;
     235           8 :     mOriginPort = port == -1 ? DefaultPort() : port;
     236           8 :     BuildHashKey();
     237           8 : }
     238             : 
     239             : nsHttpConnectionInfo*
     240           2 : nsHttpConnectionInfo::Clone() const
     241             : {
     242             :     nsHttpConnectionInfo *clone;
     243           2 :     if (mRoutedHost.IsEmpty()) {
     244           4 :         clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername, mProxyInfo,
     245           6 :                                          mOriginAttributes, mEndToEndSSL);
     246             :     } else {
     247           0 :         MOZ_ASSERT(mEndToEndSSL);
     248           0 :         clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername, mProxyInfo,
     249           0 :                                          mOriginAttributes, mRoutedHost, mRoutedPort);
     250             :     }
     251             : 
     252           2 :     if (!mNetworkInterfaceId.IsEmpty()) {
     253           0 :         clone->SetNetworkInterfaceId(mNetworkInterfaceId);
     254             :     }
     255             : 
     256             :     // Make sure the anonymous, insecure-scheme, and private flags are transferred
     257           2 :     clone->SetAnonymous(GetAnonymous());
     258           2 :     clone->SetPrivate(GetPrivate());
     259           2 :     clone->SetInsecureScheme(GetInsecureScheme());
     260           2 :     clone->SetNoSpdy(GetNoSpdy());
     261           2 :     clone->SetBeConservative(GetBeConservative());
     262           2 :     MOZ_ASSERT(clone->Equals(this));
     263             : 
     264           2 :     return clone;
     265             : }
     266             : 
     267             : void
     268           0 : nsHttpConnectionInfo::CloneAsDirectRoute(nsHttpConnectionInfo **outCI)
     269             : {
     270           0 :     if (mRoutedHost.IsEmpty()) {
     271           0 :         *outCI = Clone();
     272           0 :         return;
     273             :     }
     274             : 
     275             :     RefPtr<nsHttpConnectionInfo> clone =
     276             :         new nsHttpConnectionInfo(mOrigin, mOriginPort,
     277           0 :                                  EmptyCString(), mUsername, mProxyInfo,
     278           0 :                                  mOriginAttributes, mEndToEndSSL);
     279             :     // Make sure the anonymous, insecure-scheme, and private flags are transferred
     280           0 :     clone->SetAnonymous(GetAnonymous());
     281           0 :     clone->SetPrivate(GetPrivate());
     282           0 :     clone->SetInsecureScheme(GetInsecureScheme());
     283           0 :     clone->SetNoSpdy(GetNoSpdy());
     284           0 :     clone->SetBeConservative(GetBeConservative());
     285           0 :     if (!mNetworkInterfaceId.IsEmpty()) {
     286           0 :         clone->SetNetworkInterfaceId(mNetworkInterfaceId);
     287             :     }
     288           0 :     clone.forget(outCI);
     289             : }
     290             : 
     291             : nsresult
     292           0 : nsHttpConnectionInfo::CreateWildCard(nsHttpConnectionInfo **outParam)
     293             : {
     294             :     // T???mozilla.org:443 (https:proxy.ducksong.com:3128) [specifc form]
     295             :     // TS??*:0 (https:proxy.ducksong.com:3128)   [wildcard form]
     296             : 
     297           0 :     if (!mUsingHttpsProxy) {
     298           0 :         MOZ_ASSERT(false);
     299             :         return NS_ERROR_NOT_IMPLEMENTED;
     300             :     }
     301             : 
     302           0 :     RefPtr<nsHttpConnectionInfo> clone;
     303           0 :     clone = new nsHttpConnectionInfo(NS_LITERAL_CSTRING("*"), 0,
     304             :                                      mNPNToken, mUsername, mProxyInfo,
     305           0 :                                      mOriginAttributes, true);
     306             :     // Make sure the anonymous and private flags are transferred!
     307           0 :     clone->SetAnonymous(GetAnonymous());
     308           0 :     clone->SetPrivate(GetPrivate());
     309           0 :     clone.forget(outParam);
     310           0 :     return NS_OK;
     311             : }
     312             : 
     313             : bool
     314           3 : nsHttpConnectionInfo::UsingProxy()
     315             : {
     316           3 :     if (!mProxyInfo)
     317           3 :         return false;
     318           0 :     return !mProxyInfo->IsDirect();
     319             : }
     320             : 
     321             : bool
     322           5 : nsHttpConnectionInfo::HostIsLocalIPLiteral() const
     323             : {
     324             :     PRNetAddr prAddr;
     325             :     // If the host/proxy host is not an IP address literal, return false.
     326           5 :     if (ProxyHost()) {
     327           0 :         if (PR_StringToNetAddr(ProxyHost(), &prAddr) != PR_SUCCESS) {
     328           0 :           return false;
     329             :         }
     330           5 :     } else if (PR_StringToNetAddr(Origin(), &prAddr) != PR_SUCCESS) {
     331           4 :         return false;
     332             :     }
     333             :     NetAddr netAddr;
     334           1 :     PRNetAddrToNetAddr(&prAddr, &netAddr);
     335           1 :     return IsIPAddrLocal(&netAddr);
     336             : }
     337             : 
     338             : } // namespace net
     339             : } // namespace mozilla

Generated by: LCOV version 1.13