mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
bug 700693 - OCSP stapling testing r=bsmith
This commit is contained in:
parent
67c9526728
commit
316600ee29
@ -4,8 +4,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['src', 'public']
|
||||
TEST_DIRS += ['tests']
|
||||
DIRS += ['src', 'public', 'tests']
|
||||
|
||||
MODULE = 'pipnss'
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "sechash.h"
|
||||
#include "secpkcs7.h"
|
||||
#include "prerror.h"
|
||||
#include "ocsp.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -96,6 +97,9 @@ MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTName,
|
||||
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTCertNicknames,
|
||||
CERTCertNicknames,
|
||||
CERT_FreeNicknames)
|
||||
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTOCSPCertID,
|
||||
CERTOCSPCertID,
|
||||
CERT_DestroyOCSPCertID)
|
||||
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedCERTSubjectPublicKeyInfo,
|
||||
CERTSubjectPublicKeyInfo,
|
||||
SECKEY_DestroySubjectPublicKeyInfo)
|
||||
|
@ -4,6 +4,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['unit']
|
||||
TEST_DIRS += ['mochitest']
|
||||
|
||||
MODULE = 'pipnss'
|
||||
|
@ -7,9 +7,10 @@
|
||||
const { 'classes': Cc, 'interfaces': Ci, 'utils': Cu, 'results': Cr } = Components;
|
||||
|
||||
let { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
|
||||
let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
|
||||
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm"); // XXX: tempScope?
|
||||
Cu.import("resource://gre/modules/Services.jsm"); // XXX: tempScope?
|
||||
let gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc);
|
||||
|
||||
function readFile(file) {
|
||||
let fstream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
@ -25,3 +26,10 @@ function addCertFromFile(certdb, filename, trustString) {
|
||||
let der = readFile(certFile);
|
||||
certdb.addCert(der, trustString, null);
|
||||
}
|
||||
|
||||
function getXPCOMStatusFromNSS(offset) {
|
||||
let nssErrorsService = Cc["@mozilla.org/nss_errors_service;1"]
|
||||
.getService(Ci.nsINSSErrorsService);
|
||||
let statusNSS = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE + offset;
|
||||
return nssErrorsService.getXPCOMFromNSSError(statusNSS);
|
||||
}
|
||||
|
10
security/manager/ssl/tests/unit/moz.build
Normal file
10
security/manager/ssl/tests/unit/moz.build
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['test_ocsp_stapling']
|
||||
|
||||
MODULE = 'pipnss'
|
||||
|
211
security/manager/ssl/tests/unit/test_ocsp_stapling.js
Normal file
211
security/manager/ssl/tests/unit/test_ocsp_stapling.js
Normal file
@ -0,0 +1,211 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// In which we connect to a number of domains (as faked by a server running
|
||||
// locally) with and without OCSP stapling enabled to determine that good
|
||||
// things happen and bad things don't.
|
||||
|
||||
let { Promise } = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let { HttpServer } = Cu.import("resource://testing-common/httpd.js", {});
|
||||
|
||||
let gOCSPServerProcess = null;
|
||||
let gHttpServer = null;
|
||||
|
||||
const REMOTE_PORT = 8443;
|
||||
const CALLBACK_PORT = 8444;
|
||||
|
||||
function Connection(aHost) {
|
||||
this.host = aHost;
|
||||
let threadManager = Cc["@mozilla.org/thread-manager;1"]
|
||||
.getService(Ci.nsIThreadManager);
|
||||
this.thread = threadManager.currentThread;
|
||||
this.defer = Promise.defer();
|
||||
let sts = Cc["@mozilla.org/network/socket-transport-service;1"]
|
||||
.getService(Ci.nsISocketTransportService);
|
||||
this.transport = sts.createTransport(["ssl"], 1, aHost, REMOTE_PORT, null);
|
||||
this.transport.setEventSink(this, this.thread);
|
||||
this.inputStream = null;
|
||||
this.outputStream = null;
|
||||
this.connected = false;
|
||||
}
|
||||
|
||||
Connection.prototype = {
|
||||
// nsITransportEventSink
|
||||
onTransportStatus: function(aTransport, aStatus, aProgress, aProgressMax) {
|
||||
if (!this.connected && aStatus == Ci.nsISocketTransport.STATUS_CONNECTED_TO) {
|
||||
this.connected = true;
|
||||
this.outputStream.asyncWait(this, 0, 0, this.thread);
|
||||
}
|
||||
},
|
||||
|
||||
// nsIInputStreamCallback
|
||||
onInputStreamReady: function(aStream) {
|
||||
try {
|
||||
// this will throw if the stream has been closed by an error
|
||||
let str = NetUtil.readInputStreamToString(aStream, aStream.available());
|
||||
do_check_eq(str, "0");
|
||||
this.inputStream.close();
|
||||
this.inputStream = null;
|
||||
this.outputStream.close();
|
||||
this.outputStream = null;
|
||||
this.transport = null;
|
||||
this.defer.resolve(Cr.NS_OK);
|
||||
} catch (e) {
|
||||
this.defer.resolve(e.result);
|
||||
}
|
||||
},
|
||||
|
||||
// nsIOutputStreamCallback
|
||||
onOutputStreamReady: function(aStream) {
|
||||
let sslSocketControl = this.transport.securityInfo
|
||||
.QueryInterface(Ci.nsISSLSocketControl);
|
||||
sslSocketControl.proxyStartSSL();
|
||||
this.outputStream.write("0", 1);
|
||||
let inStream = this.transport.openInputStream(0, 0, 0)
|
||||
.QueryInterface(Ci.nsIAsyncInputStream);
|
||||
this.inputStream = inStream;
|
||||
this.inputStream.asyncWait(this, 0, 0, this.thread);
|
||||
},
|
||||
|
||||
go: function() {
|
||||
this.outputStream = this.transport.openOutputStream(0, 0, 0)
|
||||
.QueryInterface(Ci.nsIAsyncOutputStream);
|
||||
return this.defer.promise;
|
||||
}
|
||||
};
|
||||
|
||||
/* Returns a promise to connect to aHost that resolves to the result of that
|
||||
* connection */
|
||||
function connectTo(aHost) {
|
||||
Services.prefs.setCharPref("network.dns.localDomains", aHost);
|
||||
let connection = new Connection(aHost);
|
||||
return connection.go();
|
||||
}
|
||||
|
||||
function add_connection_test(aHost, aExpectedResult, aStaplingEnabled) {
|
||||
add_test(function() {
|
||||
Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling",
|
||||
aStaplingEnabled);
|
||||
do_test_pending();
|
||||
connectTo(aHost).then(function(aResult) {
|
||||
do_check_eq(aResult, aExpectedResult);
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
gOCSPServerProcess.kill();
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
addCertFromFile(certdb, "test_ocsp_stapling/ocsp-ca.der", "CTu,u,u");
|
||||
|
||||
let directoryService = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties);
|
||||
let envSvc = Cc["@mozilla.org/process/environment;1"]
|
||||
.getService(Ci.nsIEnvironment);
|
||||
let greDir = directoryService.get("GreD", Ci.nsIFile);
|
||||
envSvc.set("DYLD_LIBRARY_PATH", greDir.path);
|
||||
envSvc.set("LD_LIBRARY_PATH", greDir.path);
|
||||
envSvc.set("OCSP_SERVER_DEBUG_LEVEL", "3");
|
||||
envSvc.set("OCSP_SERVER_CALLBACK_PORT", CALLBACK_PORT);
|
||||
|
||||
gHttpServer = new HttpServer();
|
||||
gHttpServer.registerPathHandler("/", handleServerCallback);
|
||||
gHttpServer.start(CALLBACK_PORT);
|
||||
|
||||
let serverBin = directoryService.get("CurProcD", Ci.nsILocalFile);
|
||||
serverBin.append("OCSPStaplingServer" + (gIsWindows ? ".exe" : ""));
|
||||
// If we're testing locally, the above works. If not, the server executable
|
||||
// is in another location.
|
||||
if (!serverBin.exists()) {
|
||||
serverBin = directoryService.get("CurWorkD", Ci.nsILocalFile);
|
||||
while (serverBin.path.indexOf("xpcshell") != -1) {
|
||||
serverBin = serverBin.parent;
|
||||
}
|
||||
serverBin.append("bin");
|
||||
serverBin.append("OCSPStaplingServer" + (gIsWindows ? ".exe" : ""));
|
||||
}
|
||||
do_check_true(serverBin.exists());
|
||||
gOCSPServerProcess = Cc["@mozilla.org/process/util;1"]
|
||||
.createInstance(Ci.nsIProcess);
|
||||
gOCSPServerProcess.init(serverBin);
|
||||
let ocspCertDir = directoryService.get("CurWorkD", Ci.nsILocalFile);
|
||||
ocspCertDir.append("test_ocsp_stapling");
|
||||
do_check_true(ocspCertDir.exists());
|
||||
gOCSPServerProcess.run(false, [ocspCertDir.path], 1);
|
||||
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function handleServerCallback(aRequest, aResponse) {
|
||||
aResponse.write("OK!");
|
||||
aResponse.seizePower();
|
||||
aResponse.finish();
|
||||
run_test_body();
|
||||
}
|
||||
|
||||
function run_test_body() {
|
||||
// In the absence of OCSP stapling, these should actually all work.
|
||||
add_connection_test("ocsp-stapling-good.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-revoked.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-good-other-ca.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-malformed.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-srverr.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-trylater.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-needssig.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-unauthorized.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-unknown.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-good-other.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-none.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-expired.example.com", Cr.NS_OK, false);
|
||||
add_connection_test("ocsp-stapling-expired-fresh-ca.example.com", Cr.NS_OK, false);
|
||||
// Now test OCSP stapling
|
||||
// The following error codes are defined in security/nss/lib/util/SECerrs.h
|
||||
add_connection_test("ocsp-stapling-good.example.com", Cr.NS_OK, true);
|
||||
// SEC_ERROR_REVOKED_CERTIFICATE = SEC_ERROR_BASE + 12
|
||||
add_connection_test("ocsp-stapling-revoked.example.com", getXPCOMStatusFromNSS(12), true);
|
||||
// This stapled response is from a CA that is untrusted and did not issue
|
||||
// the server's certificate.
|
||||
// SEC_ERROR_BAD_DATABASE = SEC_ERROR_BASE + 18
|
||||
add_connection_test("ocsp-stapling-good-other-ca.example.com", getXPCOMStatusFromNSS(18), true);
|
||||
// Now add that CA to the trusted database. It still should not be able
|
||||
// to sign for the ocsp response.
|
||||
add_test(function() {
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
addCertFromFile(certdb, "test_ocsp_stapling/ocsp-other-ca.der", "CTu,u,u");
|
||||
run_next_test();
|
||||
});
|
||||
// SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE = (SEC_ERROR_BASE + 130)
|
||||
add_connection_test("ocsp-stapling-good-other-ca.example.com", getXPCOMStatusFromNSS(130), true);
|
||||
// SEC_ERROR_OCSP_MALFORMED_REQUEST = (SEC_ERROR_BASE + 120)
|
||||
add_connection_test("ocsp-stapling-malformed.example.com", getXPCOMStatusFromNSS(120), true);
|
||||
// SEC_ERROR_OCSP_SERVER_ERROR = (SEC_ERROR_BASE + 121)
|
||||
add_connection_test("ocsp-stapling-srverr.example.com", getXPCOMStatusFromNSS(121), true);
|
||||
// SEC_ERROR_OCSP_TRY_SERVER_LATER = (SEC_ERROR_BASE + 122)
|
||||
add_connection_test("ocsp-stapling-trylater.example.com", getXPCOMStatusFromNSS(122), true);
|
||||
// SEC_ERROR_OCSP_REQUEST_NEEDS_SIG = (SEC_ERROR_BASE + 123)
|
||||
add_connection_test("ocsp-stapling-needssig.example.com", getXPCOMStatusFromNSS(123), true);
|
||||
// SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST = (SEC_ERROR_BASE + 124)
|
||||
add_connection_test("ocsp-stapling-unauthorized.example.com", getXPCOMStatusFromNSS(124), true);
|
||||
// SEC_ERROR_OCSP_UNKNOWN_CERT = (SEC_ERROR_BASE + 126)
|
||||
add_connection_test("ocsp-stapling-unknown.example.com", getXPCOMStatusFromNSS(126), true);
|
||||
add_connection_test("ocsp-stapling-good-other.example.com", getXPCOMStatusFromNSS(126), true);
|
||||
// SEC_ERROR_OCSP_MALFORMED_RESPONSE = (SEC_ERROR_BASE + 129)
|
||||
add_connection_test("ocsp-stapling-none.example.com", getXPCOMStatusFromNSS(129), true);
|
||||
// SEC_ERROR_OCSP_OLD_RESPONSE = (SEC_ERROR_BASE + 132)
|
||||
add_connection_test("ocsp-stapling-expired.example.com", getXPCOMStatusFromNSS(132), true);
|
||||
add_connection_test("ocsp-stapling-expired-fresh-ca.example.com", getXPCOMStatusFromNSS(132), true);
|
||||
do_register_cleanup(function() { gHttpServer.stop(cleanup); });
|
||||
run_next_test();
|
||||
do_test_finished();
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
# vim: noexpandtab ts=8 sw=8
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = @relativesrcdir@
|
||||
FAIL_ON_WARNINGS := 1
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
CPPSRCS = \
|
||||
OCSPStaplingServer.cpp \
|
||||
$(NULL)
|
||||
|
||||
SIMPLE_PROGRAMS := $(CPPSRCS:.cpp=$(BIN_SUFFIX))
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
LIBS = \
|
||||
$(NSPR_LIBS) \
|
||||
$(NSS_LIBS) \
|
||||
$(MOZALLOC_LIB) \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += $(TK_CFLAGS)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
@ -0,0 +1,589 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This is a standalone server that delivers various stapled OCSP responses.
|
||||
// The client is expected to connect, initiate an SSL handshake (with SNI
|
||||
// to indicate which "server" to connect to), and verify the OCSP response.
|
||||
// If all is good, the client then sends one encrypted byte and receives that
|
||||
// same byte back.
|
||||
// This server also has the ability to "call back" another process waiting on
|
||||
// it. That is, when the server is all set up and ready to receive connections,
|
||||
// it will connect to a specified port and issue a simple HTTP request.
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ScopedNSSTypes.h"
|
||||
#include "nspr.h"
|
||||
#include "nss.h"
|
||||
#include "ocsp.h"
|
||||
#include "ocspt.h"
|
||||
#include "plarenas.h"
|
||||
#include "prenv.h"
|
||||
#include "prerror.h"
|
||||
#include "prnetdb.h"
|
||||
#include "prtime.h"
|
||||
#include "ssl.h"
|
||||
#include "secerr.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define LISTEN_PORT 8443
|
||||
#define DEBUG_ERRORS 1
|
||||
#define DEBUG_WARNINGS 2
|
||||
#define DEBUG_VERBOSE 3
|
||||
|
||||
uint32_t gDebugLevel = 0;
|
||||
uint32_t gCallbackPort = 0;
|
||||
|
||||
enum OCSPStapleResponseType
|
||||
{
|
||||
OSRTNull = 0,
|
||||
OSRTGood, // the certificate is good
|
||||
OSRTRevoked, // the certificate has been revoked
|
||||
OSRTUnknown, // the responder doesn't know if the cert is good
|
||||
OSRTGoodOtherCert, // the response references a different certificate
|
||||
OSRTGoodOtherCA, // the wrong CA has signed the response
|
||||
OSRTExpired, // the signature on the response has expired
|
||||
OSRTExpiredFreshCA, // fresh signature, but old validity period
|
||||
OSRTNone, // no stapled response
|
||||
OSRTMalformed, // the response from the responder was malformed
|
||||
OSRTSrverr, // the response indicates there was a server error
|
||||
OSRTTryLater, // the responder replied with "try again later"
|
||||
OSRTNeedsSig, // the response needs a signature
|
||||
OSRTUnauthorized // the responder is not authorized for this certificate
|
||||
};
|
||||
|
||||
struct OCSPHost
|
||||
{
|
||||
const char *mHostName;
|
||||
const char *mCertName;
|
||||
OCSPStapleResponseType mOSRT;
|
||||
};
|
||||
|
||||
const OCSPHost sOCSPHosts[] =
|
||||
{
|
||||
{ "ocsp-stapling-good.example.com", "good", OSRTGood },
|
||||
{ "ocsp-stapling-revoked.example.com", "revoked", OSRTRevoked },
|
||||
{ "ocsp-stapling-unknown.example.com", "unknown", OSRTUnknown },
|
||||
{ "ocsp-stapling-good-other.example.com", "good-other", OSRTGoodOtherCert },
|
||||
{ "ocsp-stapling-good-other-ca.example.com", "good-otherCA", OSRTGoodOtherCA },
|
||||
{ "ocsp-stapling-expired.example.com", "expired", OSRTExpired },
|
||||
{ "ocsp-stapling-expired-fresh-ca.example.com", "expired-freshCA", OSRTExpiredFreshCA },
|
||||
{ "ocsp-stapling-none.example.com", "none", OSRTNone },
|
||||
{ "ocsp-stapling-malformed.example.com", "malformed", OSRTMalformed },
|
||||
{ "ocsp-stapling-srverr.example.com", "srverr", OSRTSrverr },
|
||||
{ "ocsp-stapling-trylater.example.com", "trylater", OSRTTryLater },
|
||||
{ "ocsp-stapling-needssig.example.com", "needssig", OSRTNeedsSig },
|
||||
{ "ocsp-stapling-unauthorized.example.com", "unauthorized", OSRTUnauthorized },
|
||||
{ nullptr, nullptr, OSRTNull }
|
||||
};
|
||||
|
||||
struct Connection
|
||||
{
|
||||
const OCSPHost *mHost;
|
||||
PRFileDesc *mSocket;
|
||||
char mByte;
|
||||
|
||||
Connection(PRFileDesc *aSocket);
|
||||
~Connection();
|
||||
};
|
||||
|
||||
Connection::Connection(PRFileDesc *aSocket)
|
||||
: mHost(nullptr)
|
||||
, mSocket(aSocket)
|
||||
, mByte(0)
|
||||
{}
|
||||
|
||||
Connection::~Connection()
|
||||
{
|
||||
if (mSocket) {
|
||||
PR_Close(mSocket);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintPRError(const char *aPrefix)
|
||||
{
|
||||
const char *err = PR_ErrorToName(PR_GetError());
|
||||
if (err) {
|
||||
if (gDebugLevel >= DEBUG_ERRORS) {
|
||||
fprintf(stderr, "%s: %s\n", aPrefix, err);
|
||||
}
|
||||
} else {
|
||||
if (gDebugLevel >= DEBUG_ERRORS) {
|
||||
fprintf(stderr, "%s\n", aPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
SendAll(PRFileDesc *aSocket, const char *aData, size_t aDataLen)
|
||||
{
|
||||
if (gDebugLevel >= DEBUG_VERBOSE) {
|
||||
fprintf(stderr, "sending '%s'\n", aData);
|
||||
}
|
||||
|
||||
while (aDataLen > 0) {
|
||||
int32_t bytesSent = PR_Send(aSocket, aData, aDataLen, 0,
|
||||
PR_INTERVAL_NO_TIMEOUT);
|
||||
if (bytesSent == -1) {
|
||||
PrintPRError("PR_Send failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aDataLen -= bytesSent;
|
||||
aData += bytesSent;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ReplyToRequest(Connection *aConn)
|
||||
{
|
||||
// For debugging purposes, SendAll can print out what it's sending.
|
||||
// So, any strings we give to it to send need to be null-terminated.
|
||||
char buf[2] = { aConn->mByte, 0 };
|
||||
return SendAll(aConn->mSocket, buf, 1);
|
||||
}
|
||||
|
||||
const OCSPHost *
|
||||
GetOcspHost(const char *aServerName)
|
||||
{
|
||||
const OCSPHost *host = sOCSPHosts;
|
||||
while (host->mHostName != nullptr &&
|
||||
strcmp(host->mHostName, aServerName) != 0) {
|
||||
host++;
|
||||
}
|
||||
|
||||
if (!host->mHostName) {
|
||||
fprintf(stderr, "host '%s' not in pre-defined list\n", aServerName);
|
||||
MOZ_CRASH();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SetupTLS(Connection *aConn, PRFileDesc *aModelSocket)
|
||||
{
|
||||
PRFileDesc *sslSocket = SSL_ImportFD(aModelSocket, aConn->mSocket);
|
||||
if (!sslSocket) {
|
||||
PrintPRError("SSL_ImportFD failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
aConn->mSocket = sslSocket;
|
||||
|
||||
SSL_OptionSet(sslSocket, SSL_SECURITY, true);
|
||||
SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, false);
|
||||
SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_SERVER, true);
|
||||
|
||||
SSL_ResetHandshake(sslSocket, /* asServer */ 1);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ReadRequest(Connection *aConn)
|
||||
{
|
||||
int32_t bytesRead = PR_Recv(aConn->mSocket, &aConn->mByte, 1, 0,
|
||||
PR_INTERVAL_NO_TIMEOUT);
|
||||
if (bytesRead < 1) {
|
||||
PrintPRError("PR_Recv failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
} else {
|
||||
if (gDebugLevel >= DEBUG_VERBOSE) {
|
||||
fprintf(stderr, "read '0x%hhx'\n", aConn->mByte);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HandleConnection(PRFileDesc *aSocket, PRFileDesc *aModelSocket)
|
||||
{
|
||||
Connection conn(aSocket);
|
||||
nsresult rv = SetupTLS(&conn, aModelSocket);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = ReadRequest(&conn);
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = ReplyToRequest(&conn);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DoCallback()
|
||||
{
|
||||
ScopedPRFileDesc socket(PR_NewTCPSocket());
|
||||
if (!socket) {
|
||||
PrintPRError("PR_NewTCPSocket failed");
|
||||
return;
|
||||
}
|
||||
|
||||
PRNetAddr addr;
|
||||
PR_InitializeNetAddr(PR_IpAddrLoopback, gCallbackPort, &addr);
|
||||
if (PR_Connect(socket, &addr, PR_INTERVAL_NO_TIMEOUT) != PR_SUCCESS) {
|
||||
PrintPRError("PR_Connect failed");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *request = "GET / HTTP/1.0\r\n\r\n";
|
||||
SendAll(socket, request, strlen(request));
|
||||
char buf[4096];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
int32_t bytesRead = PR_Recv(socket, buf, sizeof(buf) - 1, 0,
|
||||
PR_INTERVAL_NO_TIMEOUT);
|
||||
if (bytesRead < 1) {
|
||||
PrintPRError("PR_Recv failed");
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
bytesRead = PR_Recv(socket, buf, sizeof(buf) - 1, 0, PR_INTERVAL_NO_TIMEOUT);
|
||||
if (bytesRead < 1) {
|
||||
PrintPRError("PR_Recv failed");
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
}
|
||||
|
||||
SECItemArray *
|
||||
GetOCSPResponseForType(OCSPStapleResponseType aOSRT, CERTCertificate *aCert,
|
||||
PLArenaPool *aArena)
|
||||
{
|
||||
PRTime now = PR_Now();
|
||||
ScopedCERTOCSPCertID id(CERT_CreateOCSPCertID(aCert, now));
|
||||
if (!id) {
|
||||
PrintPRError("CERT_CreateOCSPCertID failed");
|
||||
return nullptr;
|
||||
}
|
||||
PRTime nextUpdate = now + 10 * PR_USEC_PER_SEC;
|
||||
PRTime oneDay = 60*60*24 * (PRTime)PR_USEC_PER_SEC;
|
||||
PRTime expiredTime = now - oneDay;
|
||||
PRTime oldNow = now - (8 * oneDay);
|
||||
PRTime oldNextUpdate = oldNow + 10 * PR_USEC_PER_SEC;
|
||||
ScopedCERTCertificate othercert(PK11_FindCertFromNickname("good", nullptr));
|
||||
ScopedCERTOCSPCertID otherid(CERT_CreateOCSPCertID(othercert, now));
|
||||
if (!otherid) {
|
||||
PrintPRError("CERT_CreateOCSPCertID failed");
|
||||
return nullptr;
|
||||
}
|
||||
CERTOCSPSingleResponse *sr = nullptr;
|
||||
switch (aOSRT) {
|
||||
case OSRTGood:
|
||||
case OSRTGoodOtherCA:
|
||||
sr = CERT_CreateOCSPSingleResponseGood(aArena, id, now, &nextUpdate);
|
||||
if (!sr) {
|
||||
PrintPRError("CERT_CreateOCSPSingleResponseGood failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTRevoked:
|
||||
sr = CERT_CreateOCSPSingleResponseRevoked(aArena, id, now, &nextUpdate,
|
||||
expiredTime, nullptr);
|
||||
if (!sr) {
|
||||
PrintPRError("CERT_CreateOCSPSingleResponseRevoked failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTUnknown:
|
||||
sr = CERT_CreateOCSPSingleResponseUnknown(aArena, id, now, &nextUpdate);
|
||||
if (!sr) {
|
||||
PrintPRError("CERT_CreateOCSPSingleResponseUnknown failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTExpired:
|
||||
case OSRTExpiredFreshCA:
|
||||
sr = CERT_CreateOCSPSingleResponseGood(aArena, id, oldNow, &oldNextUpdate);
|
||||
if (!sr) {
|
||||
PrintPRError("CERT_CreateOCSPSingleResponseGood failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTGoodOtherCert:
|
||||
sr = CERT_CreateOCSPSingleResponseGood(aArena, otherid, now, &nextUpdate);
|
||||
if (!sr) {
|
||||
PrintPRError("CERT_CreateOCSPSingleResponseGood failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTNone:
|
||||
case OSRTMalformed:
|
||||
case OSRTSrverr:
|
||||
case OSRTTryLater:
|
||||
case OSRTNeedsSig:
|
||||
case OSRTUnauthorized:
|
||||
break;
|
||||
default:
|
||||
if (gDebugLevel >= DEBUG_ERRORS) {
|
||||
fprintf(stderr, "bad ocsp response type: %d\n", aOSRT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ScopedCERTCertificate ca;
|
||||
if (aOSRT == OSRTGoodOtherCA) {
|
||||
ca = PK11_FindCertFromNickname("otherCA", nullptr);
|
||||
if (!ca) {
|
||||
PrintPRError("PK11_FindCertFromNickname failed");
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
// XXX CERT_FindCertIssuer uses the old, deprecated path-building logic
|
||||
ca = CERT_FindCertIssuer(aCert, now, certUsageSSLCA);
|
||||
if (!ca) {
|
||||
PrintPRError("CERT_FindCertIssuer failed");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PRTime signTime = now;
|
||||
if (aOSRT == OSRTExpired) {
|
||||
signTime = oldNow;
|
||||
}
|
||||
|
||||
CERTOCSPSingleResponse **responses;
|
||||
SECItem *response = nullptr;
|
||||
switch (aOSRT) {
|
||||
case OSRTMalformed:
|
||||
response = CERT_CreateEncodedOCSPErrorResponse(
|
||||
aArena, SEC_ERROR_OCSP_MALFORMED_REQUEST);
|
||||
if (!response) {
|
||||
PrintPRError("CERT_CreateEncodedOCSPErrorResponse failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTSrverr:
|
||||
response = CERT_CreateEncodedOCSPErrorResponse(
|
||||
aArena, SEC_ERROR_OCSP_SERVER_ERROR);
|
||||
if (!response) {
|
||||
PrintPRError("CERT_CreateEncodedOCSPErrorResponse failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTTryLater:
|
||||
response = CERT_CreateEncodedOCSPErrorResponse(
|
||||
aArena, SEC_ERROR_OCSP_TRY_SERVER_LATER);
|
||||
if (!response) {
|
||||
PrintPRError("CERT_CreateEncodedOCSPErrorResponse failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTNeedsSig:
|
||||
response = CERT_CreateEncodedOCSPErrorResponse(
|
||||
aArena, SEC_ERROR_OCSP_REQUEST_NEEDS_SIG);
|
||||
if (!response) {
|
||||
PrintPRError("CERT_CreateEncodedOCSPErrorResponse failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTUnauthorized:
|
||||
response = CERT_CreateEncodedOCSPErrorResponse(
|
||||
aArena, SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST);
|
||||
if (!response) {
|
||||
PrintPRError("CERT_CreateEncodedOCSPErrorResponse failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
case OSRTNone:
|
||||
break;
|
||||
default:
|
||||
// responses is contained in aArena and will be freed when aArena is
|
||||
responses = PORT_ArenaNewArray(aArena, CERTOCSPSingleResponse *, 2);
|
||||
if (!responses) {
|
||||
PrintPRError("PORT_ArenaNewArray failed");
|
||||
return nullptr;
|
||||
}
|
||||
responses[0] = sr;
|
||||
responses[1] = nullptr;
|
||||
response = CERT_CreateEncodedOCSPSuccessResponse(
|
||||
aArena, ca, ocspResponderID_byName, signTime, responses, nullptr);
|
||||
if (!response) {
|
||||
PrintPRError("CERT_CreateEncodedOCSPSuccessResponse failed");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
SECItemArray *arr = SECITEM_AllocArray(aArena, nullptr, 1);
|
||||
arr->items[0].data = response ? response->data : nullptr;
|
||||
arr->items[0].len = response ? response->len : 0;
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
int32_t
|
||||
DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
|
||||
uint32_t aSrvNameArrSize, void *aArg)
|
||||
{
|
||||
const OCSPHost *host = nullptr;
|
||||
for (uint32_t i = 0; i < aSrvNameArrSize; i++) {
|
||||
host = GetOcspHost((const char *)aSrvNameArr[i].data);
|
||||
if (host) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!host) {
|
||||
return SSL_SNI_SEND_ALERT;
|
||||
}
|
||||
|
||||
if (gDebugLevel >= DEBUG_VERBOSE) {
|
||||
fprintf(stderr, "found pre-defined host '%s'\n", host->mHostName);
|
||||
}
|
||||
|
||||
ScopedCERTCertificate cert(PK11_FindCertFromNickname(host->mCertName, nullptr));
|
||||
if (!cert) {
|
||||
PrintPRError("PK11_FindCertFromNickname failed");
|
||||
return SSL_SNI_SEND_ALERT;
|
||||
}
|
||||
|
||||
ScopedSECKEYPrivateKey key(PK11_FindKeyByAnyCert(cert, nullptr));
|
||||
if (!key) {
|
||||
PrintPRError("PK11_FindKeyByAnyCert failed");
|
||||
return SSL_SNI_SEND_ALERT;
|
||||
}
|
||||
|
||||
SSLKEAType certKEA = NSS_FindCertKEAType(cert);
|
||||
|
||||
if (SSL_ConfigSecureServer(aFd, cert, key, certKEA) != SECSuccess) {
|
||||
PrintPRError("SSL_ConfigSecureServer failed");
|
||||
return SSL_SNI_SEND_ALERT;
|
||||
}
|
||||
|
||||
PLArenaPool arena;
|
||||
PL_InitArenaPool(&arena, "OCSP response", 1024, 0);
|
||||
// response is contained by the arena - finishing the arena will free it
|
||||
SECItemArray *response = GetOCSPResponseForType(host->mOSRT, cert, &arena);
|
||||
if (!response) {
|
||||
PL_FinishArenaPool(&arena);
|
||||
return SSL_SNI_SEND_ALERT;
|
||||
}
|
||||
// SSL_SetStapledOCSPResponses makes a deep copy of response
|
||||
SECStatus st = SSL_SetStapledOCSPResponses(aFd, response, certKEA);
|
||||
PL_FinishArenaPool(&arena);
|
||||
if (st != SECSuccess) {
|
||||
PrintPRError("SSL_SetStapledOCSPResponses failed");
|
||||
return SSL_SNI_SEND_ALERT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
StartServer()
|
||||
{
|
||||
ScopedPRFileDesc serverSocket(PR_NewTCPSocket());
|
||||
if (!serverSocket) {
|
||||
PrintPRError("PR_NewTCPSocket failed");
|
||||
return;
|
||||
}
|
||||
|
||||
PRSocketOptionData socketOption;
|
||||
socketOption.option = PR_SockOpt_Reuseaddr;
|
||||
socketOption.value.reuse_addr = true;
|
||||
PR_SetSocketOption(serverSocket, &socketOption);
|
||||
|
||||
PRNetAddr serverAddr;
|
||||
PR_InitializeNetAddr(PR_IpAddrLoopback, LISTEN_PORT, &serverAddr);
|
||||
if (PR_Bind(serverSocket, &serverAddr) != PR_SUCCESS) {
|
||||
PrintPRError("PR_Bind failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PR_Listen(serverSocket, 1) != PR_SUCCESS) {
|
||||
PrintPRError("PR_Listen failed");
|
||||
return;
|
||||
}
|
||||
|
||||
ScopedPRFileDesc rawModelSocket(PR_NewTCPSocket());
|
||||
if (!rawModelSocket) {
|
||||
PrintPRError("PR_NewTCPSocket failed for rawModelSocket");
|
||||
return;
|
||||
}
|
||||
|
||||
ScopedPRFileDesc modelSocket(SSL_ImportFD(nullptr, rawModelSocket.forget()));
|
||||
if (!modelSocket) {
|
||||
PrintPRError("SSL_ImportFD of rawModelSocket failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (SECSuccess != SSL_SNISocketConfigHook(modelSocket, DoSNISocketConfig,
|
||||
nullptr)) {
|
||||
PrintPRError("SSL_SNISocketConfigHook failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// We have to configure the server with a certificate, but it's not one
|
||||
// we're actually going to end up using. In the SNI callback, we pick
|
||||
// the right certificate for the connection.
|
||||
ScopedCERTCertificate cert(PK11_FindCertFromNickname("localhost", nullptr));
|
||||
if (!cert) {
|
||||
PrintPRError("PK11_FindCertFromNickname failed");
|
||||
return;
|
||||
}
|
||||
|
||||
ScopedSECKEYPrivateKey key(PK11_FindKeyByAnyCert(cert, nullptr));
|
||||
if (!key) {
|
||||
PrintPRError("PK11_FindKeyByAnyCert failed");
|
||||
return;
|
||||
}
|
||||
|
||||
SSLKEAType certKEA = NSS_FindCertKEAType(cert);
|
||||
|
||||
if (SSL_ConfigSecureServer(modelSocket, cert, key, certKEA) != SECSuccess) {
|
||||
PrintPRError("SSL_ConfigSecureServer failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gCallbackPort != 0) {
|
||||
DoCallback();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
PRNetAddr clientAddr;
|
||||
PRFileDesc *clientSocket = PR_Accept(serverSocket, &clientAddr,
|
||||
PR_INTERVAL_NO_TIMEOUT);
|
||||
HandleConnection(clientSocket, modelSocket);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *debugLevel = PR_GetEnv("OCSP_SERVER_DEBUG_LEVEL");
|
||||
if (debugLevel) {
|
||||
gDebugLevel = atoi(debugLevel);
|
||||
}
|
||||
|
||||
const char *callbackPort = PR_GetEnv("OCSP_SERVER_CALLBACK_PORT");
|
||||
if (callbackPort) {
|
||||
gCallbackPort = atoi(callbackPort);
|
||||
}
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s <NSS DB directory>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (NSS_Init(argv[1]) != SECSuccess) {
|
||||
PrintPRError("NSS_Init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (NSS_SetDomesticPolicy() != SECSuccess) {
|
||||
PrintPRError("NSS_SetDomesticPolicy failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (SSL_ConfigServerSessionIDCache(0, 0, 0, nullptr) != SECSuccess) {
|
||||
PrintPRError("SSL_ConfigServerSessionIDCache failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
StartServer();
|
||||
|
||||
return 0;
|
||||
}
|
BIN
security/manager/ssl/tests/unit/test_ocsp_stapling/cert8.db
Normal file
BIN
security/manager/ssl/tests/unit/test_ocsp_stapling/cert8.db
Normal file
Binary file not shown.
117
security/manager/ssl/tests/unit/test_ocsp_stapling/gen_ocsp_certs.sh
Executable file
117
security/manager/ssl/tests/unit/test_ocsp_stapling/gen_ocsp_certs.sh
Executable file
@ -0,0 +1,117 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# Usage: ./gen_ocsp_certs.sh <path to objdir> <output directory>
|
||||
# e.g. (from the root of mozilla-central)
|
||||
# `./security/manager/ssl/tests/unit/test_ocsp_stapling/gen_ocsp_certs.sh \
|
||||
# obj-x86_64-unknown-linux-gnu/ \
|
||||
# security/manager/ssl/tests/unit/test_ocsp_stapling/`
|
||||
#
|
||||
# NB: This will cause the following files to be overwritten if they are in
|
||||
# the output directory:
|
||||
# cert8.db, key3.db, secmod.db, ocsp-ca.der, ocsp-other-ca.der
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "Usage: `basename ${0}` <path to objdir> <output directory>"
|
||||
exit $E_BADARGS
|
||||
fi
|
||||
|
||||
OBJDIR=${1}
|
||||
OUTPUT_DIR=${2}
|
||||
RUN_MOZILLA="$OBJDIR/dist/bin/run-mozilla.sh"
|
||||
CERTUTIL="$OBJDIR/dist/bin/certutil"
|
||||
|
||||
function check_retval {
|
||||
retval=$?
|
||||
if [ "$retval" -ne 0 ]; then
|
||||
echo "failed..."
|
||||
exit "$retval"
|
||||
fi
|
||||
}
|
||||
|
||||
NOISE_FILE=`mktemp`
|
||||
echo "running \"dd if=/dev/urandom of="$NOISE_FILE" bs=1024 count=8\""
|
||||
dd if=/dev/urandom of="$NOISE_FILE" bs=1024 count=1
|
||||
check_retval
|
||||
PASSWORD_FILE=`mktemp`
|
||||
|
||||
function cleanup {
|
||||
rm -f "$NOISE_FILE" "$PASSWORD_FILE"
|
||||
}
|
||||
|
||||
if [ ! -f "$RUN_MOZILLA" ]; then
|
||||
echo "Could not find run-mozilla.sh at \'$RUN_MOZILLA\'"
|
||||
exit $E_BADARGS
|
||||
fi
|
||||
|
||||
if [ ! -f "$CERTUTIL" ]; then
|
||||
echo "Could not find certutil at \'$CERTUTIL\'"
|
||||
exit $E_BADARGS
|
||||
fi
|
||||
|
||||
if [ ! -d "$OUTPUT_DIR" ]; then
|
||||
echo "Could not find output directory at \'$OUTPUT_DIR\'"
|
||||
exit $E_BADARGS
|
||||
fi
|
||||
|
||||
if [ -f "$OUTPUT_DIR/cert8.db" -o -f "$OUTPUT_DIR/key3.db" -o -f "$OUTPUT_DIR/secmod.db" ]; then
|
||||
echo "Found pre-existing NSS DBs. Clobbering old OCSP certs."
|
||||
rm -f "$OUTPUT_DIR/cert8.db" "$OUTPUT_DIR/key3.db" "$OUTPUT_DIR/secmod.db"
|
||||
fi
|
||||
echo "running \"$RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -N -f $PASSWORD_FILE\""
|
||||
$RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -N -f $PASSWORD_FILE
|
||||
check_retval
|
||||
|
||||
COMMON_ARGS="-v 360 -w -1 -2 -z $NOISE_FILE"
|
||||
|
||||
function make_CA {
|
||||
CA_RESPONSES="y\n0\ny"
|
||||
NICKNAME="${1}"
|
||||
SUBJECT="${2}"
|
||||
DERFILE="${3}"
|
||||
|
||||
check_retval
|
||||
echo "running 'echo -e \"$CA_RESPONSES\" | $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -S -n $NICKNAME -s \"$SUBJECT\" -t CTu,u,u -x $COMMON_ARGS'"
|
||||
echo -e "$CA_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -S -n $NICKNAME -s "$SUBJECT" -t CTu,u,u -x $COMMON_ARGS
|
||||
check_retval
|
||||
echo "running \"$RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -L -n $NICKNAME -r > $OUTPUT_DIR/$DERFILE\""
|
||||
$RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -L -n $NICKNAME -r > $OUTPUT_DIR/$DERFILE
|
||||
check_retval
|
||||
}
|
||||
|
||||
SERIALNO=1
|
||||
|
||||
function make_cert {
|
||||
CERT_RESPONSES="n\n\ny"
|
||||
NICKNAME="${1}"
|
||||
SUBJECT="${2}"
|
||||
CA="${3}"
|
||||
|
||||
echo "running 'echo -e \"$CERT_RESPONSES\" | $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -S -s \"$SUBJECT\" -n $NICKNAME -c $CA -t Pu,u,u -m $SERIALNO $COMMON_ARGS'"
|
||||
echo -e "$CERT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -S -s "$SUBJECT" -n $NICKNAME -c $CA -t Pu,u,u -m $SERIALNO $COMMON_ARGS
|
||||
check_retval
|
||||
SERIALNO=$(($SERIALNO + 1))
|
||||
}
|
||||
|
||||
make_CA ocspTestCA 'CN=OCSP stapling test CA' ocsp-ca.der
|
||||
make_CA otherCA 'CN=OCSP other test CA' ocsp-other-ca.der
|
||||
|
||||
make_cert localhost 'CN=localhost' ocspTestCA
|
||||
make_cert good 'CN=ocsp-stapling-good.example.com' ocspTestCA
|
||||
make_cert revoked 'CN=ocsp-stapling-revoked.example.com' ocspTestCA
|
||||
make_cert unknown 'CN=ocsp-stapling-unknown.example.com' ocspTestCA
|
||||
make_cert good-other 'CN=ocsp-stapling-good-other.example.com' ocspTestCA
|
||||
make_cert good-otherCA 'CN=ocsp-stapling-good-other-ca.example.com' ocspTestCA
|
||||
make_cert expired 'CN=ocsp-stapling-expired.example.com' ocspTestCA
|
||||
make_cert expired-freshCA 'CN=ocsp-stapling-expired-fresh-ca.example.com' ocspTestCA
|
||||
make_cert none 'CN=ocsp-stapling-none.example.com' ocspTestCA
|
||||
make_cert malformed 'CN=ocsp-stapling-malformed.example.com' ocspTestCA
|
||||
make_cert srverr 'CN=ocsp-stapling-srverr.example.com' ocspTestCA
|
||||
make_cert trylater 'CN=ocsp-stapling-trylater.example.com' ocspTestCA
|
||||
make_cert needssig 'CN=ocsp-stapling-needssig.example.com' ocspTestCA
|
||||
make_cert unauthorized 'CN=ocsp-stapling-unauthorized.example.com' ocspTestCA
|
||||
|
||||
cleanup
|
BIN
security/manager/ssl/tests/unit/test_ocsp_stapling/key3.db
Normal file
BIN
security/manager/ssl/tests/unit/test_ocsp_stapling/key3.db
Normal file
Binary file not shown.
@ -0,0 +1,8 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MODULE = 'pipnss'
|
||||
|
BIN
security/manager/ssl/tests/unit/test_ocsp_stapling/ocsp-ca.der
Normal file
BIN
security/manager/ssl/tests/unit/test_ocsp_stapling/ocsp-ca.der
Normal file
Binary file not shown.
Binary file not shown.
BIN
security/manager/ssl/tests/unit/test_ocsp_stapling/secmod.db
Normal file
BIN
security/manager/ssl/tests/unit/test_ocsp_stapling/secmod.db
Normal file
Binary file not shown.
@ -16,3 +16,4 @@ skip-if = os == "android"
|
||||
skip-if = os == "android"
|
||||
[test_sts_preloadlist_perwindowpb.js]
|
||||
[test_sts_preloadlist_selfdestruct.js]
|
||||
[test_ocsp_stapling.js]
|
||||
|
@ -125,6 +125,7 @@ TEST_HARNESS_BINS := \
|
||||
ssltunnel$(BIN_SUFFIX) \
|
||||
certutil$(BIN_SUFFIX) \
|
||||
pk12util$(BIN_SUFFIX) \
|
||||
OCSPStaplingServer$(BIN_SUFFIX) \
|
||||
fix_stack_using_bpsyms.py \
|
||||
$(NULL)
|
||||
|
||||
|
@ -507,6 +507,7 @@ NO_PKG_FILES += \
|
||||
ssltunnel* \
|
||||
certutil* \
|
||||
pk12util* \
|
||||
OCSPStaplingServer* \
|
||||
winEmbed.exe \
|
||||
chrome/chrome.rdf \
|
||||
chrome/app-chrome.manifest \
|
||||
|
Loading…
Reference in New Issue
Block a user