LCOV - code coverage report
Current view: top level - security/certverifier - OCSPRequestor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 97 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 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             : #include "OCSPRequestor.h"
       8             : 
       9             : #include <limits>
      10             : 
      11             : #include "ScopedNSSTypes.h"
      12             : #include "mozilla/Base64.h"
      13             : #include "mozilla/Casting.h"
      14             : #include "nsIURLParser.h"
      15             : #include "nsNSSCallbacks.h"
      16             : #include "nsNetCID.h"
      17             : #include "nsServiceManagerUtils.h"
      18             : #include "secerr.h"
      19             : 
      20             : extern mozilla::LazyLogModule gCertVerifierLog;
      21             : 
      22             : namespace mozilla {
      23             : 
      24             : void
      25           0 : ReleaseHttpServerSession(nsNSSHttpServerSession* httpServerSession)
      26             : {
      27           0 :   delete httpServerSession;
      28           0 : }
      29             : 
      30             : void
      31           0 : ReleaseHttpRequestSession(nsNSSHttpRequestSession* httpRequestSession)
      32             : {
      33           0 :   httpRequestSession->Release();
      34           0 : }
      35             : 
      36           0 : MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueHTTPServerSession,
      37             :                                       nsNSSHttpServerSession,
      38             :                                       ReleaseHttpServerSession)
      39             : 
      40           0 : MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueHTTPRequestSession,
      41             :                                       nsNSSHttpRequestSession,
      42             :                                       ReleaseHttpRequestSession)
      43             : 
      44             : } // namespace mozilla
      45             : 
      46             : namespace mozilla { namespace psm {
      47             : 
      48             : static nsresult
      49           0 : AppendEscapedBase64Item(const SECItem* encodedRequest, nsACString& path)
      50             : {
      51             :   nsresult rv;
      52             :   nsDependentCSubstring requestAsSubstring(
      53           0 :     BitwiseCast<char*, unsigned char*>(encodedRequest->data),
      54           0 :     encodedRequest->len);
      55           0 :   nsCString base64Request;
      56           0 :   rv = Base64Encode(requestAsSubstring, base64Request);
      57           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
      58           0 :     return rv;
      59             :   }
      60             : 
      61           0 :   MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
      62             :          ("Setting up OCSP GET path, pre path =%s\n",
      63             :           PromiseFlatCString(path).get()));
      64             : 
      65             :   // The path transformation is not a direct url encoding. Three characters
      66             :   // need change '+' -> "%2B", '/' -> "%2F", and '=' -> '%3D'.
      67             :   // http://tools.ietf.org/html/rfc5019#section-5
      68           0 :   base64Request.ReplaceSubstring("+", "%2B");
      69           0 :   base64Request.ReplaceSubstring("/", "%2F");
      70           0 :   base64Request.ReplaceSubstring("=", "%3D");
      71           0 :   path.Append(base64Request);
      72           0 :   return NS_OK;
      73             : }
      74             : 
      75             : Result
      76           0 : DoOCSPRequest(const UniquePLArenaPool& arena, const char* url,
      77             :               const OriginAttributes& originAttributes,
      78             :               const SECItem* encodedRequest, TimeDuration timeout,
      79             :               bool useGET,
      80             :       /*out*/ SECItem*& encodedResponse)
      81             : {
      82           0 :   MOZ_ASSERT(arena.get());
      83           0 :   MOZ_ASSERT(url);
      84           0 :   MOZ_ASSERT(encodedRequest);
      85           0 :   MOZ_ASSERT(encodedRequest->data);
      86           0 :   if (!arena.get() || !url || !encodedRequest || !encodedRequest->data) {
      87           0 :     return Result::FATAL_ERROR_INVALID_ARGS;
      88             :   }
      89           0 :   uint32_t urlLen = strlen(url);
      90           0 :   if (urlLen > static_cast<uint32_t>(std::numeric_limits<int32_t>::max())) {
      91           0 :     return Result::FATAL_ERROR_INVALID_ARGS;
      92             :   }
      93             : 
      94           0 :   nsCOMPtr<nsIURLParser> urlParser = do_GetService(NS_STDURLPARSER_CONTRACTID);
      95           0 :   if (!urlParser) {
      96           0 :     return Result::FATAL_ERROR_LIBRARY_FAILURE;
      97             :   }
      98             : 
      99             :   uint32_t schemePos;
     100             :   int32_t schemeLen;
     101             :   uint32_t authorityPos;
     102             :   int32_t authorityLen;
     103             :   uint32_t pathPos;
     104             :   int32_t pathLen;
     105           0 :   nsresult nsrv = urlParser->ParseURL(url, static_cast<int32_t>(urlLen),
     106             :                                       &schemePos, &schemeLen,
     107             :                                       &authorityPos, &authorityLen,
     108           0 :                                       &pathPos, &pathLen);
     109           0 :   if (NS_FAILED(nsrv)) {
     110           0 :     return Result::ERROR_CERT_BAD_ACCESS_LOCATION;
     111             :   }
     112           0 :   if (schemeLen < 0 || authorityLen < 0) {
     113           0 :     return Result::ERROR_CERT_BAD_ACCESS_LOCATION;
     114             :   }
     115             :   nsAutoCString scheme(url + schemePos,
     116           0 :                        static_cast<nsAutoCString::size_type>(schemeLen));
     117           0 :   if (!scheme.LowerCaseEqualsLiteral("http")) {
     118             :     // We don't support HTTPS to avoid loops. See Bug 92923.
     119             :     // We also in general only support HTTP.
     120           0 :     return Result::ERROR_CERT_BAD_ACCESS_LOCATION;
     121             :   }
     122             : 
     123             :   uint32_t hostnamePos;
     124             :   int32_t hostnameLen;
     125             :   int32_t port;
     126             :   // We ignore user:password sections: if one is present, we send an OCSP
     127             :   // request to the URL as normal without sending the username or password.
     128           0 :   nsrv = urlParser->ParseAuthority(url + authorityPos, authorityLen,
     129             :                                    nullptr, nullptr, nullptr, nullptr,
     130           0 :                                    &hostnamePos, &hostnameLen, &port);
     131           0 :   if (NS_FAILED(nsrv)) {
     132           0 :     return Result::ERROR_CERT_BAD_ACCESS_LOCATION;
     133             :   }
     134           0 :   if (hostnameLen < 0) {
     135           0 :     return Result::ERROR_CERT_BAD_ACCESS_LOCATION;
     136             :   }
     137           0 :   if (port == -1) {
     138           0 :     port = 80;
     139           0 :   } else if (port < 0 || port > 0xffff) {
     140           0 :     return Result::ERROR_CERT_BAD_ACCESS_LOCATION;
     141             :   }
     142             :   nsAutoCString
     143           0 :     hostname(url + authorityPos + hostnamePos,
     144           0 :              static_cast<nsACString::size_type>(hostnameLen));
     145             : 
     146           0 :   nsNSSHttpServerSession* serverSessionPtr = nullptr;
     147           0 :   Result rv = nsNSSHttpInterface::createSessionFcn(
     148           0 :     hostname.BeginReading(), static_cast<uint16_t>(port), &serverSessionPtr);
     149           0 :   if (rv != Success) {
     150           0 :     return rv;
     151             :   }
     152           0 :   UniqueHTTPServerSession serverSession(serverSessionPtr);
     153             : 
     154           0 :   nsAutoCString path;
     155           0 :   if (pathLen > 0) {
     156           0 :     path.Assign(url + pathPos, static_cast<nsAutoCString::size_type>(pathLen));
     157             :   } else {
     158           0 :     path.Assign("/");
     159             :   }
     160           0 :   MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
     161             :          ("Setting up OCSP request: pre all path =%s  pathlen=%d\n", path.get(),
     162             :           pathLen));
     163           0 :   nsAutoCString method("POST");
     164           0 :   if (useGET) {
     165           0 :     method.Assign("GET");
     166           0 :     if (!StringEndsWith(path, NS_LITERAL_CSTRING("/"))) {
     167           0 :       path.Append("/");
     168             :     }
     169           0 :     nsrv = AppendEscapedBase64Item(encodedRequest, path);
     170           0 :     if (NS_WARN_IF(NS_FAILED(nsrv))) {
     171           0 :       return Result::FATAL_ERROR_LIBRARY_FAILURE;
     172             :     }
     173             :   }
     174             : 
     175             :   nsNSSHttpRequestSession* requestSessionPtr;
     176           0 :   rv = nsNSSHttpInterface::createFcn(serverSession.get(), "http", path.get(),
     177             :                                      method.get(), originAttributes, timeout,
     178           0 :                                      &requestSessionPtr);
     179           0 :   if (rv != Success) {
     180           0 :     return rv;
     181             :   }
     182             : 
     183           0 :   UniqueHTTPRequestSession requestSession(requestSessionPtr);
     184             : 
     185           0 :   if (!useGET) {
     186           0 :     rv = nsNSSHttpInterface::setPostDataFcn(
     187             :       requestSession.get(),
     188           0 :       BitwiseCast<char*, unsigned char*>(encodedRequest->data),
     189           0 :       encodedRequest->len, "application/ocsp-request");
     190           0 :     if (rv != Success) {
     191           0 :       return rv;
     192             :     }
     193             :   }
     194             : 
     195             :   uint16_t httpResponseCode;
     196             :   const char* httpResponseData;
     197           0 :   uint32_t httpResponseDataLen = 0; // 0 means any response size is acceptable
     198           0 :   rv = nsNSSHttpInterface::trySendAndReceiveFcn(requestSession.get(), nullptr,
     199             :                                                 &httpResponseCode,
     200             :                                                 nullptr, &httpResponseData,
     201           0 :                                                 &httpResponseDataLen);
     202           0 :   if (rv != Success) {
     203           0 :     return rv;
     204             :   }
     205             : 
     206           0 :   if (httpResponseCode != 200) {
     207           0 :     return Result::ERROR_OCSP_SERVER_ERROR;
     208             :   }
     209             : 
     210           0 :   encodedResponse = SECITEM_AllocItem(arena.get(), nullptr, httpResponseDataLen);
     211           0 :   if (!encodedResponse) {
     212           0 :     return Result::FATAL_ERROR_NO_MEMORY;
     213             :   }
     214             : 
     215           0 :   memcpy(encodedResponse->data, httpResponseData, httpResponseDataLen);
     216           0 :   return Success;
     217             : }
     218             : 
     219             : } } // namespace mozilla::psm

Generated by: LCOV version 1.13