security/certverifier/OCSPRequestor.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "OCSPRequestor.h"
michael@0 8
michael@0 9 #include "nsIURLParser.h"
michael@0 10 #include "nsNSSCallbacks.h"
michael@0 11 #include "nsNetCID.h"
michael@0 12 #include "nsServiceManagerUtils.h"
michael@0 13 #include "pkix/ScopedPtr.h"
michael@0 14 #include "secerr.h"
michael@0 15
michael@0 16 namespace mozilla { namespace psm {
michael@0 17
michael@0 18 using mozilla::pkix::ScopedPtr;
michael@0 19
michael@0 20 void
michael@0 21 ReleaseHttpServerSession(nsNSSHttpServerSession* httpServerSession)
michael@0 22 {
michael@0 23 delete httpServerSession;
michael@0 24 }
michael@0 25 typedef ScopedPtr<nsNSSHttpServerSession, ReleaseHttpServerSession>
michael@0 26 ScopedHTTPServerSession;
michael@0 27
michael@0 28 void
michael@0 29 ReleaseHttpRequestSession(nsNSSHttpRequestSession* httpRequestSession)
michael@0 30 {
michael@0 31 httpRequestSession->Release();
michael@0 32 }
michael@0 33 typedef ScopedPtr<nsNSSHttpRequestSession, ReleaseHttpRequestSession>
michael@0 34 ScopedHTTPRequestSession;
michael@0 35
michael@0 36 SECItem* DoOCSPRequest(PLArenaPool* arena, const char* url,
michael@0 37 const SECItem* encodedRequest, PRIntervalTime timeout)
michael@0 38 {
michael@0 39 nsCOMPtr<nsIURLParser> urlParser = do_GetService(NS_STDURLPARSER_CONTRACTID);
michael@0 40 if (!urlParser) {
michael@0 41 PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
michael@0 42 return nullptr;
michael@0 43 }
michael@0 44
michael@0 45 uint32_t schemePos;
michael@0 46 int32_t schemeLen;
michael@0 47 uint32_t authorityPos;
michael@0 48 int32_t authorityLen;
michael@0 49 uint32_t pathPos;
michael@0 50 int32_t pathLen;
michael@0 51 nsresult rv = urlParser->ParseURL(url, PL_strlen(url),
michael@0 52 &schemePos, &schemeLen,
michael@0 53 &authorityPos, &authorityLen,
michael@0 54 &pathPos, &pathLen);
michael@0 55 if (NS_FAILED(rv)) {
michael@0 56 PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0);
michael@0 57 return nullptr;
michael@0 58 }
michael@0 59 if (schemeLen < 0 || authorityLen < 0) {
michael@0 60 PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0);
michael@0 61 return nullptr;
michael@0 62 }
michael@0 63 nsAutoCString scheme(url + schemePos, schemeLen);
michael@0 64 if (!scheme.LowerCaseEqualsLiteral("http")) {
michael@0 65 // We dont support https:// to avoid loops see Bug 92923
michael@0 66 PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0);
michael@0 67 return nullptr;
michael@0 68 }
michael@0 69
michael@0 70 uint32_t hostnamePos;
michael@0 71 int32_t hostnameLen;
michael@0 72 int32_t port;
michael@0 73 // We do not support urls with user@pass sections in the URL,
michael@0 74 // In cas we find them we will ignore and try to connect with
michael@0 75 rv = urlParser->ParseAuthority(url + authorityPos, authorityLen,
michael@0 76 nullptr, nullptr, nullptr, nullptr,
michael@0 77 &hostnamePos, &hostnameLen, &port);
michael@0 78 if (NS_FAILED(rv)) {
michael@0 79 PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0);
michael@0 80 return nullptr;
michael@0 81 }
michael@0 82 if (hostnameLen < 0) {
michael@0 83 PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0);
michael@0 84 return nullptr;
michael@0 85 }
michael@0 86 if (port == -1) {
michael@0 87 port = 80;
michael@0 88 }
michael@0 89
michael@0 90 nsAutoCString hostname(url + authorityPos + hostnamePos, hostnameLen);
michael@0 91 SEC_HTTP_SERVER_SESSION serverSessionPtr = nullptr;
michael@0 92 if (nsNSSHttpInterface::createSessionFcn(hostname.BeginReading(), port,
michael@0 93 &serverSessionPtr) != SECSuccess) {
michael@0 94 PR_SetError(SEC_ERROR_NO_MEMORY, 0);
michael@0 95 return nullptr;
michael@0 96 }
michael@0 97
michael@0 98 ScopedHTTPServerSession serverSession(
michael@0 99 reinterpret_cast<nsNSSHttpServerSession*>(serverSessionPtr));
michael@0 100 nsAutoCString path;
michael@0 101 if (pathLen > 0) {
michael@0 102 path.Assign(url + pathPos, pathLen);
michael@0 103 } else {
michael@0 104 path.Assign("/");
michael@0 105 }
michael@0 106 SEC_HTTP_REQUEST_SESSION requestSessionPtr;
michael@0 107 if (nsNSSHttpInterface::createFcn(serverSession.get(), "http",
michael@0 108 path.BeginReading(), "POST",
michael@0 109 timeout, &requestSessionPtr)
michael@0 110 != SECSuccess) {
michael@0 111 PR_SetError(SEC_ERROR_NO_MEMORY, 0);
michael@0 112 return nullptr;
michael@0 113 }
michael@0 114
michael@0 115 ScopedHTTPRequestSession requestSession(
michael@0 116 reinterpret_cast<nsNSSHttpRequestSession*>(requestSessionPtr));
michael@0 117 if (nsNSSHttpInterface::setPostDataFcn(requestSession.get(),
michael@0 118 reinterpret_cast<char*>(encodedRequest->data), encodedRequest->len,
michael@0 119 "application/ocsp-request") != SECSuccess) {
michael@0 120 PR_SetError(SEC_ERROR_NO_MEMORY, 0);
michael@0 121 return nullptr;
michael@0 122 }
michael@0 123
michael@0 124 uint16_t httpResponseCode;
michael@0 125 const char* httpResponseData;
michael@0 126 uint32_t httpResponseDataLen = 0; // 0 means any response size is acceptable
michael@0 127 if (nsNSSHttpInterface::trySendAndReceiveFcn(requestSession.get(), nullptr,
michael@0 128 &httpResponseCode, nullptr,
michael@0 129 nullptr, &httpResponseData,
michael@0 130 &httpResponseDataLen)
michael@0 131 != SECSuccess) {
michael@0 132 PR_SetError(SEC_ERROR_OCSP_SERVER_ERROR, 0);
michael@0 133 return nullptr;
michael@0 134 }
michael@0 135
michael@0 136 if (httpResponseCode != 200) {
michael@0 137 PR_SetError(SEC_ERROR_OCSP_SERVER_ERROR, 0);
michael@0 138 return nullptr;
michael@0 139 }
michael@0 140
michael@0 141 SECItem* encodedResponse = SECITEM_AllocItem(arena, nullptr,
michael@0 142 httpResponseDataLen);
michael@0 143 if (!encodedResponse) {
michael@0 144 PR_SetError(SEC_ERROR_NO_MEMORY, 0);
michael@0 145 return nullptr;
michael@0 146 }
michael@0 147
michael@0 148 memcpy(encodedResponse->data, httpResponseData, httpResponseDataLen);
michael@0 149 return encodedResponse;
michael@0 150 }
michael@0 151
michael@0 152 } } // namespace mozilla::psm

mercurial