mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1005142 - Part 1/2 - Add OCSP get capabilities to OCSPRequestor. r=keeler
--HG-- extra : rebase_source : ee4a86bf02a466a31de8b0b6cd7ce375a7f28c6d
This commit is contained in:
parent
6fe994703a
commit
f051695b8d
@ -374,8 +374,10 @@ CertVerifier::MozillaPKIXVerifyCert(
|
||||
: !mOCSPStrict ? NSSCertDBTrustDomain::FetchOCSPForDVSoftFail
|
||||
: NSSCertDBTrustDomain::FetchOCSPForDVHardFail;
|
||||
|
||||
SECStatus rv;
|
||||
ocsp_get_config ocspGETConfig = mOCSPGETEnabled ? ocsp_get_enabled
|
||||
: ocsp_get_disabled;
|
||||
|
||||
SECStatus rv;
|
||||
// TODO(bug 970750): anyExtendedKeyUsage
|
||||
// TODO: encipherOnly/decipherOnly
|
||||
// S/MIME Key Usage: http://tools.ietf.org/html/rfc3850#section-4.4.2
|
||||
@ -390,7 +392,7 @@ CertVerifier::MozillaPKIXVerifyCert(
|
||||
// XXX: We don't really have a trust bit for SSL client authentication so
|
||||
// just use trustEmail as it is the closest alternative.
|
||||
NSSCertDBTrustDomain trustDomain(trustEmail, ocspFetching, mOCSPCache,
|
||||
pinArg);
|
||||
pinArg, ocspGETConfig);
|
||||
rv = BuildCertChain(trustDomain, cert, time,
|
||||
EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
|
||||
KeyPurposeId::id_kp_clientAuth,
|
||||
@ -415,7 +417,7 @@ CertVerifier::MozillaPKIXVerifyCert(
|
||||
ocspFetching == NSSCertDBTrustDomain::NeverFetchOCSP
|
||||
? NSSCertDBTrustDomain::LocalOnlyOCSPForEV
|
||||
: NSSCertDBTrustDomain::FetchOCSPForEV,
|
||||
mOCSPCache, pinArg, &callbackContainer);
|
||||
mOCSPCache, pinArg, ocspGETConfig, &callbackContainer);
|
||||
rv = BuildCertChainForOneKeyUsage(trustDomain, cert, time,
|
||||
KU_DIGITAL_SIGNATURE, // ECDHE/DHE
|
||||
KU_KEY_ENCIPHERMENT, // RSA
|
||||
@ -441,7 +443,8 @@ CertVerifier::MozillaPKIXVerifyCert(
|
||||
|
||||
// Now try non-EV.
|
||||
NSSCertDBTrustDomain trustDomain(trustSSL, ocspFetching, mOCSPCache,
|
||||
pinArg, &callbackContainer);
|
||||
pinArg, ocspGETConfig,
|
||||
&callbackContainer);
|
||||
rv = BuildCertChainForOneKeyUsage(trustDomain, cert, time,
|
||||
KU_DIGITAL_SIGNATURE, // ECDHE/DHE
|
||||
KU_KEY_ENCIPHERMENT, // RSA
|
||||
@ -454,7 +457,7 @@ CertVerifier::MozillaPKIXVerifyCert(
|
||||
|
||||
case certificateUsageSSLCA: {
|
||||
NSSCertDBTrustDomain trustDomain(trustSSL, ocspFetching, mOCSPCache,
|
||||
pinArg);
|
||||
pinArg, ocspGETConfig);
|
||||
rv = BuildCertChain(trustDomain, cert, time, EndEntityOrCA::MustBeCA,
|
||||
KU_KEY_CERT_SIGN, KeyPurposeId::id_kp_serverAuth,
|
||||
CertPolicyId::anyPolicy,
|
||||
@ -464,7 +467,7 @@ CertVerifier::MozillaPKIXVerifyCert(
|
||||
|
||||
case certificateUsageEmailSigner: {
|
||||
NSSCertDBTrustDomain trustDomain(trustEmail, ocspFetching, mOCSPCache,
|
||||
pinArg);
|
||||
pinArg, ocspGETConfig);
|
||||
rv = BuildCertChain(trustDomain, cert, time,
|
||||
EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
|
||||
KeyPurposeId::id_kp_emailProtection,
|
||||
@ -478,7 +481,7 @@ CertVerifier::MozillaPKIXVerifyCert(
|
||||
// usage it is trying to verify for, and base its algorithm choices
|
||||
// based on the result of the verification(s).
|
||||
NSSCertDBTrustDomain trustDomain(trustEmail, ocspFetching, mOCSPCache,
|
||||
pinArg);
|
||||
pinArg, ocspGETConfig);
|
||||
rv = BuildCertChainForOneKeyUsage(trustDomain, cert, time,
|
||||
KU_KEY_ENCIPHERMENT, // RSA
|
||||
KU_KEY_AGREEMENT, // ECDH/DH
|
||||
@ -491,7 +494,7 @@ CertVerifier::MozillaPKIXVerifyCert(
|
||||
|
||||
case certificateUsageObjectSigner: {
|
||||
NSSCertDBTrustDomain trustDomain(trustObjectSigning, ocspFetching,
|
||||
mOCSPCache, pinArg);
|
||||
mOCSPCache, pinArg, ocspGETConfig);
|
||||
rv = BuildCertChain(trustDomain, cert, time,
|
||||
EndEntityOrCA::MustBeEndEntity, KU_DIGITAL_SIGNATURE,
|
||||
KeyPurposeId::id_kp_codeSigning,
|
||||
@ -520,20 +523,20 @@ CertVerifier::MozillaPKIXVerifyCert(
|
||||
}
|
||||
|
||||
NSSCertDBTrustDomain sslTrust(trustSSL, ocspFetching, mOCSPCache,
|
||||
pinArg);
|
||||
pinArg, ocspGETConfig);
|
||||
rv = BuildCertChain(sslTrust, cert, time, endEntityOrCA,
|
||||
keyUsage, eku, CertPolicyId::anyPolicy,
|
||||
stapledOCSPResponse, builtChain);
|
||||
if (rv == SECFailure && PR_GetError() == SEC_ERROR_UNKNOWN_ISSUER) {
|
||||
NSSCertDBTrustDomain emailTrust(trustEmail, ocspFetching, mOCSPCache,
|
||||
pinArg);
|
||||
pinArg, ocspGETConfig);
|
||||
rv = BuildCertChain(emailTrust, cert, time, endEntityOrCA, keyUsage,
|
||||
eku, CertPolicyId::anyPolicy,
|
||||
stapledOCSPResponse, builtChain);
|
||||
if (rv == SECFailure && SEC_ERROR_UNKNOWN_ISSUER) {
|
||||
NSSCertDBTrustDomain objectSigningTrust(trustObjectSigning,
|
||||
ocspFetching, mOCSPCache,
|
||||
pinArg);
|
||||
pinArg, ocspGETConfig);
|
||||
rv = BuildCertChain(objectSigningTrust, cert, time, endEntityOrCA,
|
||||
keyUsage, eku, CertPolicyId::anyPolicy,
|
||||
stapledOCSPResponse, builtChain);
|
||||
|
@ -44,11 +44,13 @@ NSSCertDBTrustDomain::NSSCertDBTrustDomain(SECTrustType certDBTrustType,
|
||||
OCSPFetching ocspFetching,
|
||||
OCSPCache& ocspCache,
|
||||
void* pinArg,
|
||||
CertVerifier::ocsp_get_config ocspGETConfig,
|
||||
CERTChainVerifyCallback* checkChainCallback)
|
||||
: mCertDBTrustType(certDBTrustType)
|
||||
, mOCSPFetching(ocspFetching)
|
||||
, mOCSPCache(ocspCache)
|
||||
, mPinArg(pinArg)
|
||||
, mOCSPGetConfig(ocspGETConfig)
|
||||
, mCheckChainCallback(checkChainCallback)
|
||||
{
|
||||
}
|
||||
@ -338,7 +340,8 @@ NSSCertDBTrustDomain::CheckRevocation(
|
||||
}
|
||||
|
||||
response = DoOCSPRequest(arena.get(), url.get(), request,
|
||||
OCSPFetchingTypeToTimeoutTime(mOCSPFetching));
|
||||
OCSPFetchingTypeToTimeoutTime(mOCSPFetching),
|
||||
mOCSPGetConfig == CertVerifier::ocsp_get_enabled);
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
};
|
||||
NSSCertDBTrustDomain(SECTrustType certDBTrustType, OCSPFetching ocspFetching,
|
||||
OCSPCache& ocspCache, void* pinArg,
|
||||
CertVerifier::ocsp_get_config ocspGETConfig,
|
||||
CERTChainVerifyCallback* checkChainCallback = nullptr);
|
||||
|
||||
virtual SECStatus FindPotentialIssuers(
|
||||
@ -95,6 +96,7 @@ private:
|
||||
const OCSPFetching mOCSPFetching;
|
||||
OCSPCache& mOCSPCache; // non-owning!
|
||||
void* mPinArg; // non-owning!
|
||||
const CertVerifier::ocsp_get_config mOCSPGetConfig;
|
||||
CERTChainVerifyCallback* mCheckChainCallback; // non-owning!
|
||||
};
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "OCSPRequestor.h"
|
||||
|
||||
#include "mozilla/Base64.h"
|
||||
#include "nsIURLParser.h"
|
||||
#include "nsNSSCallbacks.h"
|
||||
#include "nsNetCID.h"
|
||||
@ -13,6 +14,10 @@
|
||||
#include "pkix/ScopedPtr.h"
|
||||
#include "secerr.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* gCertVerifierLog;
|
||||
#endif
|
||||
|
||||
namespace mozilla { namespace psm {
|
||||
|
||||
using mozilla::pkix::ScopedPtr;
|
||||
@ -33,8 +38,36 @@ ReleaseHttpRequestSession(nsNSSHttpRequestSession* httpRequestSession)
|
||||
typedef ScopedPtr<nsNSSHttpRequestSession, ReleaseHttpRequestSession>
|
||||
ScopedHTTPRequestSession;
|
||||
|
||||
SECItem* DoOCSPRequest(PLArenaPool* arena, const char* url,
|
||||
const SECItem* encodedRequest, PRIntervalTime timeout)
|
||||
static nsresult
|
||||
AppendEscapedBase64Item(const SECItem* encodedRequest, nsACString& path)
|
||||
{
|
||||
nsresult rv;
|
||||
nsDependentCSubstring requestAsSubstring(
|
||||
reinterpret_cast<const char*>(encodedRequest->data), encodedRequest->len);
|
||||
nsCString base64Request;
|
||||
rv = Base64Encode(requestAsSubstring, base64Request);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
|
||||
("Setting up OCSP GET path, pre path =%s\n",
|
||||
PromiseFlatCString(path).get()));
|
||||
|
||||
// The path transformation is not a direct url encoding. Three characters
|
||||
// need change '+' -> "%2B", '/' -> "%2F", and '=' -> '%3D'.
|
||||
// http://tools.ietf.org/html/rfc5019#section-5
|
||||
base64Request.ReplaceSubstring("+", "%2B");
|
||||
base64Request.ReplaceSubstring("/", "%2F");
|
||||
base64Request.ReplaceSubstring("=", "%3D");
|
||||
path.Append(base64Request);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SECItem*
|
||||
DoOCSPRequest(PLArenaPool* arena, const char* url,
|
||||
const SECItem* encodedRequest, PRIntervalTime timeout,
|
||||
bool useGET)
|
||||
{
|
||||
nsCOMPtr<nsIURLParser> urlParser = do_GetService(NS_STDURLPARSER_CONTRACTID);
|
||||
if (!urlParser) {
|
||||
@ -86,39 +119,56 @@ SECItem* DoOCSPRequest(PLArenaPool* arena, const char* url,
|
||||
if (port == -1) {
|
||||
port = 80;
|
||||
}
|
||||
|
||||
nsAutoCString hostname(url + authorityPos + hostnamePos, hostnameLen);
|
||||
|
||||
SEC_HTTP_SERVER_SESSION serverSessionPtr = nullptr;
|
||||
if (nsNSSHttpInterface::createSessionFcn(hostname.BeginReading(), port,
|
||||
&serverSessionPtr) != SECSuccess) {
|
||||
PR_SetError(SEC_ERROR_NO_MEMORY, 0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedHTTPServerSession serverSession(
|
||||
reinterpret_cast<nsNSSHttpServerSession*>(serverSessionPtr));
|
||||
|
||||
nsAutoCString path;
|
||||
if (pathLen > 0) {
|
||||
path.Assign(url + pathPos, pathLen);
|
||||
} else {
|
||||
path.Assign("/");
|
||||
}
|
||||
SEC_HTTP_REQUEST_SESSION requestSessionPtr;
|
||||
PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
|
||||
("Setting up OCSP request: pre all path =%s pathlen=%d\n", path.get(),
|
||||
pathLen));
|
||||
nsAutoCString method("POST");
|
||||
if (useGET) {
|
||||
method.Assign("GET");
|
||||
if (!StringEndsWith(path, NS_LITERAL_CSTRING("/"))) {
|
||||
path.Append("/");
|
||||
}
|
||||
nsresult rv = AppendEscapedBase64Item(encodedRequest, path);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SEC_HTTP_REQUEST_SESSION requestSessionPtr = nullptr;
|
||||
if (nsNSSHttpInterface::createFcn(serverSession.get(), "http",
|
||||
path.BeginReading(), "POST",
|
||||
path.get(), method.get(),
|
||||
timeout, &requestSessionPtr)
|
||||
!= SECSuccess) {
|
||||
PR_SetError(SEC_ERROR_NO_MEMORY, 0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedHTTPRequestSession requestSession(
|
||||
reinterpret_cast<nsNSSHttpRequestSession*>(requestSessionPtr));
|
||||
if (nsNSSHttpInterface::setPostDataFcn(requestSession.get(),
|
||||
reinterpret_cast<char*>(encodedRequest->data), encodedRequest->len,
|
||||
"application/ocsp-request") != SECSuccess) {
|
||||
PR_SetError(SEC_ERROR_NO_MEMORY, 0);
|
||||
return nullptr;
|
||||
|
||||
if (!useGET) {
|
||||
if (nsNSSHttpInterface::setPostDataFcn(requestSession.get(),
|
||||
reinterpret_cast<char*>(encodedRequest->data), encodedRequest->len,
|
||||
"application/ocsp-request") != SECSuccess) {
|
||||
PR_SetError(SEC_ERROR_NO_MEMORY, 0);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t httpResponseCode;
|
||||
|
@ -7,13 +7,15 @@
|
||||
#ifndef mozilla_psm_OCSPRequestor_h
|
||||
#define mozilla_psm_OCSPRequestor_h
|
||||
|
||||
#include "CertVerifier.h"
|
||||
#include "secmodt.h"
|
||||
|
||||
namespace mozilla { namespace psm {
|
||||
|
||||
// The memory returned is owned by the given arena.
|
||||
SECItem* DoOCSPRequest(PLArenaPool* arena, const char* url,
|
||||
const SECItem* encodedRequest, PRIntervalTime timeout);
|
||||
const SECItem* encodedRequest, PRIntervalTime timeout,
|
||||
bool useGET);
|
||||
|
||||
} } // namespace mozilla::psm
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user