gecko-dev/security/nss/cmd/ocspresp/ocspresp.c

252 строки
7.3 KiB
C

/* 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/. */
/*
* ocspresp - self test for OCSP response creation
*/
#include "nspr.h"
#include "secutil.h"
#include "secpkcs7.h"
#include "cert.h"
#include "certdb.h"
#include "nss.h"
#include "pk11func.h"
#include "cryptohi.h"
#include "ocsp.h"
#if defined(XP_UNIX)
#include <unistd.h>
#endif
#include <stdio.h>
#include <string.h>
secuPWData pwdata = { PW_NONE, 0 };
static PRBool
getCaAndSubjectCert(CERTCertDBHandle *certHandle,
const char *caNick, const char *eeNick,
CERTCertificate **outCA, CERTCertificate **outCert)
{
*outCA = CERT_FindCertByNickname(certHandle, caNick);
*outCert = CERT_FindCertByNickname(certHandle, eeNick);
return *outCA && *outCert;
}
static SECItem *
encode(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca)
{
SECItem *response;
PRTime now = PR_Now();
PRTime nextUpdate;
CERTOCSPSingleResponse **responses;
CERTOCSPSingleResponse *sr;
if (!arena)
return NULL;
nextUpdate = now + 10 * PR_USEC_PER_SEC; /* in the future */
sr = CERT_CreateOCSPSingleResponseGood(arena, cid, now, &nextUpdate);
/* meaning of value 2: one entry + one end marker */
responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2);
if (responses == NULL)
return NULL;
responses[0] = sr;
responses[1] = NULL;
response = CERT_CreateEncodedOCSPSuccessResponse(
arena, ca, ocspResponderID_byName, now, responses, &pwdata);
return response;
}
static SECItem *
encodeRevoked(PLArenaPool *arena, CERTOCSPCertID *cid, CERTCertificate *ca)
{
SECItem *response;
PRTime now = PR_Now();
PRTime revocationTime;
CERTOCSPSingleResponse **responses;
CERTOCSPSingleResponse *sr;
if (!arena)
return NULL;
revocationTime = now - 10 * PR_USEC_PER_SEC; /* in the past */
sr = CERT_CreateOCSPSingleResponseRevoked(arena, cid, now, NULL,
revocationTime, NULL);
/* meaning of value 2: one entry + one end marker */
responses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse *, 2);
if (responses == NULL)
return NULL;
responses[0] = sr;
responses[1] = NULL;
response = CERT_CreateEncodedOCSPSuccessResponse(
arena, ca, ocspResponderID_byName, now, responses, &pwdata);
return response;
}
int
Usage(void)
{
PRFileDesc *pr_stderr = PR_STDERR;
PR_fprintf(pr_stderr, "ocspresp runs an internal selftest for OCSP response creation");
PR_fprintf(pr_stderr, "Usage:");
PR_fprintf(pr_stderr,
"\tocspresp <dbdir> <CA-nick> <EE-nick> [-p <pass>] [-f <file>]\n");
PR_fprintf(pr_stderr,
"\tdbdir: Find security databases in \"dbdir\"\n");
PR_fprintf(pr_stderr,
"\tCA-nick: nickname of a trusted CA certificate with private key\n");
PR_fprintf(pr_stderr,
"\tEE-nick: nickname of a entity cert issued by CA\n");
PR_fprintf(pr_stderr,
"\t-p: a password for db\n");
PR_fprintf(pr_stderr,
"\t-f: a filename containing the password for db\n");
return -1;
}
int
main(int argc, char **argv)
{
SECStatus rv;
int retval = -1;
CERTCertDBHandle *certHandle = NULL;
CERTCertificate *caCert = NULL, *cert = NULL;
CERTOCSPCertID *cid = NULL;
PLArenaPool *arena = NULL;
PRTime now = PR_Now();
SECItem *encoded = NULL;
CERTOCSPResponse *decoded = NULL;
SECItem *encodedRev = NULL;
CERTOCSPResponse *decodedRev = NULL;
SECItem *encodedFail = NULL;
CERTOCSPResponse *decodedFail = NULL;
CERTCertificate *obtainedSignerCert = NULL;
if (argc != 4 && argc != 6) {
return Usage();
}
if (argc == 6) {
if (!strcmp(argv[4], "-p")) {
pwdata.source = PW_PLAINTEXT;
pwdata.data = PORT_Strdup(argv[5]);
} else if (!strcmp(argv[4], "-f")) {
pwdata.source = PW_FROMFILE;
pwdata.data = PORT_Strdup(argv[5]);
} else
return Usage();
}
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
/*rv = NSS_Init(SECU_ConfigDirectory(NULL));*/
rv = NSS_Init(argv[1]);
if (rv != SECSuccess) {
SECU_PrintPRandOSError(argv[0]);
goto loser;
}
PK11_SetPasswordFunc(SECU_GetModulePassword);
certHandle = CERT_GetDefaultCertDB();
if (!certHandle)
goto loser;
if (!getCaAndSubjectCert(certHandle, argv[2], argv[3], &caCert, &cert))
goto loser;
cid = CERT_CreateOCSPCertID(cert, now);
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
encoded = encode(arena, cid, caCert);
PORT_Assert(encoded);
decoded = CERT_DecodeOCSPResponse(encoded);
PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decoded));
PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decoded, certHandle, &pwdata,
&obtainedSignerCert, caCert));
PORT_CheckSuccess(CERT_GetOCSPStatusForCertID(certHandle, decoded, cid,
obtainedSignerCert, now));
CERT_DestroyCertificate(obtainedSignerCert);
encodedRev = encodeRevoked(arena, cid, caCert);
PORT_Assert(encodedRev);
decodedRev = CERT_DecodeOCSPResponse(encodedRev);
PORT_CheckSuccess(CERT_GetOCSPResponseStatus(decodedRev));
PORT_CheckSuccess(CERT_VerifyOCSPResponseSignature(decodedRev, certHandle, &pwdata,
&obtainedSignerCert, caCert));
#ifdef DEBUG
{
SECStatus rv = CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid,
obtainedSignerCert, now);
PORT_Assert(rv == SECFailure);
PORT_Assert(PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE);
}
#else
(void)CERT_GetOCSPStatusForCertID(certHandle, decodedRev, cid,
obtainedSignerCert, now);
#endif
CERT_DestroyCertificate(obtainedSignerCert);
encodedFail = CERT_CreateEncodedOCSPErrorResponse(
arena, SEC_ERROR_OCSP_TRY_SERVER_LATER);
PORT_Assert(encodedFail);
decodedFail = CERT_DecodeOCSPResponse(encodedFail);
#ifdef DEBUG
{
SECStatus rv = CERT_GetOCSPResponseStatus(decodedFail);
PORT_Assert(rv == SECFailure);
PORT_Assert(PORT_GetError() == SEC_ERROR_OCSP_TRY_SERVER_LATER);
}
#else
(void)CERT_GetOCSPResponseStatus(decodedFail);
#endif
retval = 0;
loser:
if (retval != 0)
SECU_PrintError(argv[0], "tests failed");
if (cid)
CERT_DestroyOCSPCertID(cid);
if (cert)
CERT_DestroyCertificate(cert);
if (caCert)
CERT_DestroyCertificate(caCert);
if (arena)
PORT_FreeArena(arena, PR_FALSE);
if (decoded)
CERT_DestroyOCSPResponse(decoded);
if (decodedRev)
CERT_DestroyOCSPResponse(decodedRev);
if (decodedFail)
CERT_DestroyOCSPResponse(decodedFail);
if (pwdata.data) {
PORT_Free(pwdata.data);
}
if (NSS_Shutdown() != SECSuccess) {
SECU_PrintError(argv[0], "NSS shutdown:");
if (retval == 0)
retval = -2;
}
return retval;
}