1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/certverifier/OCSPRequestor.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,152 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "OCSPRequestor.h" 1.11 + 1.12 +#include "nsIURLParser.h" 1.13 +#include "nsNSSCallbacks.h" 1.14 +#include "nsNetCID.h" 1.15 +#include "nsServiceManagerUtils.h" 1.16 +#include "pkix/ScopedPtr.h" 1.17 +#include "secerr.h" 1.18 + 1.19 +namespace mozilla { namespace psm { 1.20 + 1.21 +using mozilla::pkix::ScopedPtr; 1.22 + 1.23 +void 1.24 +ReleaseHttpServerSession(nsNSSHttpServerSession* httpServerSession) 1.25 +{ 1.26 + delete httpServerSession; 1.27 +} 1.28 +typedef ScopedPtr<nsNSSHttpServerSession, ReleaseHttpServerSession> 1.29 + ScopedHTTPServerSession; 1.30 + 1.31 +void 1.32 +ReleaseHttpRequestSession(nsNSSHttpRequestSession* httpRequestSession) 1.33 +{ 1.34 + httpRequestSession->Release(); 1.35 +} 1.36 +typedef ScopedPtr<nsNSSHttpRequestSession, ReleaseHttpRequestSession> 1.37 + ScopedHTTPRequestSession; 1.38 + 1.39 +SECItem* DoOCSPRequest(PLArenaPool* arena, const char* url, 1.40 + const SECItem* encodedRequest, PRIntervalTime timeout) 1.41 +{ 1.42 + nsCOMPtr<nsIURLParser> urlParser = do_GetService(NS_STDURLPARSER_CONTRACTID); 1.43 + if (!urlParser) { 1.44 + PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0); 1.45 + return nullptr; 1.46 + } 1.47 + 1.48 + uint32_t schemePos; 1.49 + int32_t schemeLen; 1.50 + uint32_t authorityPos; 1.51 + int32_t authorityLen; 1.52 + uint32_t pathPos; 1.53 + int32_t pathLen; 1.54 + nsresult rv = urlParser->ParseURL(url, PL_strlen(url), 1.55 + &schemePos, &schemeLen, 1.56 + &authorityPos, &authorityLen, 1.57 + &pathPos, &pathLen); 1.58 + if (NS_FAILED(rv)) { 1.59 + PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); 1.60 + return nullptr; 1.61 + } 1.62 + if (schemeLen < 0 || authorityLen < 0) { 1.63 + PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); 1.64 + return nullptr; 1.65 + } 1.66 + nsAutoCString scheme(url + schemePos, schemeLen); 1.67 + if (!scheme.LowerCaseEqualsLiteral("http")) { 1.68 + // We dont support https:// to avoid loops see Bug 92923 1.69 + PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); 1.70 + return nullptr; 1.71 + } 1.72 + 1.73 + uint32_t hostnamePos; 1.74 + int32_t hostnameLen; 1.75 + int32_t port; 1.76 + // We do not support urls with user@pass sections in the URL, 1.77 + // In cas we find them we will ignore and try to connect with 1.78 + rv = urlParser->ParseAuthority(url + authorityPos, authorityLen, 1.79 + nullptr, nullptr, nullptr, nullptr, 1.80 + &hostnamePos, &hostnameLen, &port); 1.81 + if (NS_FAILED(rv)) { 1.82 + PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); 1.83 + return nullptr; 1.84 + } 1.85 + if (hostnameLen < 0) { 1.86 + PR_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 0); 1.87 + return nullptr; 1.88 + } 1.89 + if (port == -1) { 1.90 + port = 80; 1.91 + } 1.92 + 1.93 + nsAutoCString hostname(url + authorityPos + hostnamePos, hostnameLen); 1.94 + SEC_HTTP_SERVER_SESSION serverSessionPtr = nullptr; 1.95 + if (nsNSSHttpInterface::createSessionFcn(hostname.BeginReading(), port, 1.96 + &serverSessionPtr) != SECSuccess) { 1.97 + PR_SetError(SEC_ERROR_NO_MEMORY, 0); 1.98 + return nullptr; 1.99 + } 1.100 + 1.101 + ScopedHTTPServerSession serverSession( 1.102 + reinterpret_cast<nsNSSHttpServerSession*>(serverSessionPtr)); 1.103 + nsAutoCString path; 1.104 + if (pathLen > 0) { 1.105 + path.Assign(url + pathPos, pathLen); 1.106 + } else { 1.107 + path.Assign("/"); 1.108 + } 1.109 + SEC_HTTP_REQUEST_SESSION requestSessionPtr; 1.110 + if (nsNSSHttpInterface::createFcn(serverSession.get(), "http", 1.111 + path.BeginReading(), "POST", 1.112 + timeout, &requestSessionPtr) 1.113 + != SECSuccess) { 1.114 + PR_SetError(SEC_ERROR_NO_MEMORY, 0); 1.115 + return nullptr; 1.116 + } 1.117 + 1.118 + ScopedHTTPRequestSession requestSession( 1.119 + reinterpret_cast<nsNSSHttpRequestSession*>(requestSessionPtr)); 1.120 + if (nsNSSHttpInterface::setPostDataFcn(requestSession.get(), 1.121 + reinterpret_cast<char*>(encodedRequest->data), encodedRequest->len, 1.122 + "application/ocsp-request") != SECSuccess) { 1.123 + PR_SetError(SEC_ERROR_NO_MEMORY, 0); 1.124 + return nullptr; 1.125 + } 1.126 + 1.127 + uint16_t httpResponseCode; 1.128 + const char* httpResponseData; 1.129 + uint32_t httpResponseDataLen = 0; // 0 means any response size is acceptable 1.130 + if (nsNSSHttpInterface::trySendAndReceiveFcn(requestSession.get(), nullptr, 1.131 + &httpResponseCode, nullptr, 1.132 + nullptr, &httpResponseData, 1.133 + &httpResponseDataLen) 1.134 + != SECSuccess) { 1.135 + PR_SetError(SEC_ERROR_OCSP_SERVER_ERROR, 0); 1.136 + return nullptr; 1.137 + } 1.138 + 1.139 + if (httpResponseCode != 200) { 1.140 + PR_SetError(SEC_ERROR_OCSP_SERVER_ERROR, 0); 1.141 + return nullptr; 1.142 + } 1.143 + 1.144 + SECItem* encodedResponse = SECITEM_AllocItem(arena, nullptr, 1.145 + httpResponseDataLen); 1.146 + if (!encodedResponse) { 1.147 + PR_SetError(SEC_ERROR_NO_MEMORY, 0); 1.148 + return nullptr; 1.149 + } 1.150 + 1.151 + memcpy(encodedResponse->data, httpResponseData, httpResponseDataLen); 1.152 + return encodedResponse; 1.153 +} 1.154 + 1.155 +} } // namespace mozilla::psm