diff options
Diffstat (limited to 'security/nss/cmd/ocspclnt/ocspclnt.c')
-rw-r--r-- | security/nss/cmd/ocspclnt/ocspclnt.c | 1219 |
1 files changed, 0 insertions, 1219 deletions
diff --git a/security/nss/cmd/ocspclnt/ocspclnt.c b/security/nss/cmd/ocspclnt/ocspclnt.c deleted file mode 100644 index a5a1448c6..000000000 --- a/security/nss/cmd/ocspclnt/ocspclnt.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -/* - * Test program for client-side OCSP. - * - * $Id$ - */ - -#include "secutil.h" -#include "nspr.h" -#include "plgetopt.h" -#include "nss.h" -#include "cert.h" -#include "ocsp.h" -#include "xconst.h" /* - * XXX internal header file; needed to get at - * cert_DecodeAuthInfoAccessExtension -- would be - * nice to not need this, but that would require - * better/different APIs. - */ - -#ifndef NO_PP /* - * Compile with this every once in a while to be - * sure that no dependencies on it get added - * outside of the pretty-printing routines. - */ -#include "ocspti.h" /* internals for pretty-printing routines *only* */ -#endif /* NO_PP */ - -#define DEFAULT_DB_DIR "~/.netscape" - - -static void -synopsis (char *program_name) -{ - PRFileDesc *pr_stderr; - - pr_stderr = PR_STDERR; - PR_fprintf (pr_stderr, "Usage:"); - PR_fprintf (pr_stderr, - "\t%s -p [-d <dir>]\n", - program_name); - PR_fprintf (pr_stderr, - "\t%s -P [-d <dir>]\n", - program_name); - PR_fprintf (pr_stderr, - "\t%s -r <name> [-L] [-s <name>] [-d <dir>]\n", - program_name); - PR_fprintf (pr_stderr, - "\t%s -R <name> [-l <location>] [-s <name>] [-d <dir>]\n", - program_name); - PR_fprintf (pr_stderr, - "\t%s -S <name> [-l <location> -t <name>]\n", - program_name); - PR_fprintf (pr_stderr, - "\t\t [-s <name>] [-w <time>] [-d <dir>]\n"); - PR_fprintf (pr_stderr, - "\t%s -V <name> -u <usage> [-l <location> -t <name>]\n", - program_name); - PR_fprintf (pr_stderr, - "\t\t [-s <name>] [-w <time>] [-d <dir>]\n"); -} - - -static void -short_usage (char *program_name) -{ - PR_fprintf (PR_STDERR, - "Type %s -H for more detailed descriptions\n", - program_name); - synopsis (program_name); -} - - -static void -long_usage (char *program_name) -{ - PRFileDesc *pr_stderr; - - pr_stderr = PR_STDERR; - synopsis (program_name); - PR_fprintf (pr_stderr, "\nCommands (must specify exactly one):\n"); - PR_fprintf (pr_stderr, - " %-13s Pretty-print a binary request read from stdin\n", - "-p"); - PR_fprintf (pr_stderr, - " %-13s Pretty-print a binary response read from stdin\n", - "-P"); - PR_fprintf (pr_stderr, - " %-13s Create a request for cert \"nickname\" on stdout\n", - "-r nickname"); - PR_fprintf (pr_stderr, - " %-13s Get response for cert \"nickname\", dump to stdout\n", - "-R nickname"); - PR_fprintf (pr_stderr, - " %-13s Get status for cert \"nickname\"\n", - "-S nickname"); - PR_fprintf (pr_stderr, - " %-13s Fully verify cert \"nickname\", w/ status check\n", - "-V nickname"); - PR_fprintf (pr_stderr, "Options:\n"); - PR_fprintf (pr_stderr, - " %-13s Add the service locator extension to the request\n", - "-L"); - PR_fprintf (pr_stderr, - " %-13s Find security databases in \"dbdir\" (default %s)\n", - "-d dbdir", DEFAULT_DB_DIR); - PR_fprintf (pr_stderr, - " %-13s Use \"location\" as URL of responder\n", - "-l location"); - PR_fprintf (pr_stderr, - " %-13s Trust cert \"nickname\" as response signer\n", - "-t nickname"); - PR_fprintf (pr_stderr, - " %-13s Sign requests with cert \"nickname\"\n", - "-s nickname"); - PR_fprintf (pr_stderr, - " %-13s Type of certificate usage for verification:\n", - "-u usage"); - PR_fprintf (pr_stderr, - "%-17s c SSL Client\n", ""); - PR_fprintf (pr_stderr, - "%-17s s SSL Server\n", ""); - PR_fprintf (pr_stderr, - "%-17s e Email Recipient\n", ""); - PR_fprintf (pr_stderr, - "%-17s E Email Signer\n", ""); - PR_fprintf (pr_stderr, - "%-17s S Object Signer\n", ""); - PR_fprintf (pr_stderr, - "%-17s C CA\n", ""); - PR_fprintf (pr_stderr, - " %-13s Validity time (default current time), one of:\n", - "-w time"); - PR_fprintf (pr_stderr, - "%-17s %-25s (GMT)\n", "", "YYMMDDhhmm[ss]Z"); - PR_fprintf (pr_stderr, - "%-17s %-25s (later than GMT)\n", "", "YYMMDDhhmm[ss]+hhmm"); - PR_fprintf (pr_stderr, - "%-17s %-25s (earlier than GMT)\n", "", "YYMMDDhhmm[ss]-hhmm"); -} - - -/* - * XXX This is a generic function that would probably make a good - * replacement for SECU_DER_Read (which is not at all specific to DER, - * despite its name), but that requires fixing all of the tools... - * Still, it should be done, whenenver I/somebody has the time. - * (Also, consider whether this actually belongs in the security - * library itself, not just in the command library.) - * - * This function takes an open file (a PRFileDesc *) and reads the - * entire file into a SECItem. (Obviously, the file is intended to - * be small enough that such a thing is advisable.) Both the SECItem - * and the buffer it points to are allocated from the heap; the caller - * is expected to free them. ("SECITEM_FreeItem(item, PR_TRUE)") - */ -static SECItem * -read_file_into_item (PRFileDesc *in_file, SECItemType si_type) -{ - PRStatus prv; - SECItem *item; - PRFileInfo file_info; - PRInt32 bytes_read; - - prv = PR_GetOpenFileInfo (in_file, &file_info); - if (prv != PR_SUCCESS) - return NULL; - - if (file_info.size == 0) { - /* XXX Need a better error; just grabbed this one for expediency. */ - PORT_SetError (SEC_ERROR_INPUT_LEN); - return NULL; - } - - if (file_info.size > 0xffff) { /* I think this is too big. */ - PORT_SetError (SEC_ERROR_NO_MEMORY); - return NULL; - } - - item = PORT_Alloc (sizeof (SECItem)); - if (item == NULL) - return NULL; - - item->type = si_type; - item->len = (unsigned int) file_info.size; - item->data = PORT_Alloc ((size_t)item->len); - if (item->data == NULL) - goto loser; - - bytes_read = PR_Read (in_file, item->data, (PRInt32) item->len); - if (bytes_read < 0) { - /* Something went wrong; error is already set for us. */ - goto loser; - } else if (bytes_read == 0) { - /* Something went wrong; we read nothing. But no system/nspr error. */ - /* XXX Need to set an error here. */ - goto loser; - } else if (item->len != (unsigned int)bytes_read) { - /* Something went wrong; we read less (or more!?) than we expected. */ - /* XXX Need to set an error here. */ - goto loser; - } - - return item; - -loser: - SECITEM_FreeItem (item, PR_TRUE); - return NULL; -} - - -/* - * Create a DER-encoded OCSP request (for the certificate whose nickname - * is "name") and dump it out. - */ -static SECStatus -create_request (FILE *out_file, CERTCertDBHandle *handle, const char *cert_name, - PRBool add_service_locator, PRBool add_acceptable_responses) -{ - CERTCertificate *cert = NULL; - CERTCertList *certs = NULL; - CERTOCSPRequest *request = NULL; - int64 now = PR_Now(); - SECItem *encoding = NULL; - SECStatus rv = SECFailure; - - if (handle == NULL || cert_name == NULL) - goto loser; - - cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name); - if (cert == NULL) - goto loser; - - /* - * We need to create a list of one. - */ - certs = CERT_NewCertList(); - if (certs == NULL) - goto loser; - - if (CERT_AddCertToListTail (certs, cert) != SECSuccess) - goto loser; - - /* - * Now that cert is included in the list, we need to be careful - * that we do not try to destroy it twice. This will prevent that. - */ - cert = NULL; - - request = CERT_CreateOCSPRequest (certs, now, add_service_locator, NULL); - if (request == NULL) - goto loser; - - if (add_acceptable_responses) { - rv = CERT_AddOCSPAcceptableResponses(request, - SEC_OID_PKIX_OCSP_BASIC_RESPONSE); - if (rv != SECSuccess) - goto loser; - } - - encoding = CERT_EncodeOCSPRequest (NULL, request, NULL); - if (encoding == NULL) - goto loser; - - if (fwrite (encoding->data, encoding->len, 1, out_file) != 1) - goto loser; - - rv = SECSuccess; - -loser: - if (encoding != NULL) - SECITEM_FreeItem(encoding, PR_TRUE); - if (request != NULL) - CERT_DestroyOCSPRequest(request); - if (certs != NULL) - CERT_DestroyCertList (certs); - if (cert != NULL) - CERT_DestroyCertificate (cert); - - return rv; -} - - -/* - * Create a DER-encoded OCSP request (for the certificate whose nickname is - * "cert_name"), then get and dump a corresponding response. The responder - * location is either specified explicitly (as "responder_url") or found - * via the AuthorityInfoAccess URL in the cert. - */ -static SECStatus -dump_response (FILE *out_file, CERTCertDBHandle *handle, const char *cert_name, - const char *responder_url) -{ - CERTCertificate *cert = NULL; - CERTCertList *certs = NULL; - char *loc = NULL; - int64 now = PR_Now(); - SECItem *response = NULL; - SECStatus rv = SECFailure; - PRBool includeServiceLocator; - - if (handle == NULL || cert_name == NULL) - goto loser; - - cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name); - if (cert == NULL) - goto loser; - - if (responder_url != NULL) { - loc = (char *) responder_url; - includeServiceLocator = PR_TRUE; - } else { - loc = CERT_GetOCSPAuthorityInfoAccessLocation (cert); - if (loc == NULL) - goto loser; - includeServiceLocator = PR_FALSE; - } - - /* - * We need to create a list of one. - */ - certs = CERT_NewCertList(); - if (certs == NULL) - goto loser; - - if (CERT_AddCertToListTail (certs, cert) != SECSuccess) - goto loser; - - /* - * Now that cert is included in the list, we need to be careful - * that we do not try to destroy it twice. This will prevent that. - */ - cert = NULL; - - response = CERT_GetEncodedOCSPResponse (NULL, certs, loc, now, - includeServiceLocator, - NULL, NULL, NULL); - if (response == NULL) - goto loser; - - if (fwrite (response->data, response->len, 1, out_file) != 1) - goto loser; - - rv = SECSuccess; - -loser: - if (response != NULL) - SECITEM_FreeItem (response, PR_TRUE); - if (certs != NULL) - CERT_DestroyCertList (certs); - if (loc != NULL && loc != responder_url) - PORT_Free (loc); - if (cert != NULL) - CERT_DestroyCertificate (cert); - - return rv; -} - - -/* - * Get the status for the specified certificate (whose nickname is "cert_name"). - * Directly use the OCSP function rather than doing a full verification. - */ -static SECStatus -get_cert_status (FILE *out_file, CERTCertDBHandle *handle, - const char *cert_name, int64 verify_time) -{ - CERTCertificate *cert = NULL; - SECStatus rv = SECFailure; - - if (handle == NULL || cert_name == NULL) - goto loser; - - cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name); - if (cert == NULL) - goto loser; - - rv = CERT_CheckOCSPStatus (handle, cert, verify_time, NULL); - - fprintf (out_file, "Check of certificate \"%s\" ", cert_name); - if (rv == SECSuccess) { - fprintf (out_file, "succeeded.\n"); - } else { - const char *error_string = SECU_Strerror(PORT_GetError()); - fprintf (out_file, "failed. Reason:\n"); - if (error_string != NULL && PORT_Strlen(error_string) > 0) - fprintf (out_file, "%s\n", error_string); - else - fprintf (out_file, "Unknown\n"); - } - - rv = SECSuccess; - -loser: - if (cert != NULL) - CERT_DestroyCertificate (cert); - - return rv; -} - - -/* - * Verify the specified certificate (whose nickname is "cert_name"). - * OCSP is already turned on, so we just need to call the standard - * certificate verification API and let it do all the work. - */ -static SECStatus -verify_cert (FILE *out_file, CERTCertDBHandle *handle, const char *cert_name, - SECCertUsage cert_usage, int64 verify_time) -{ - CERTCertificate *cert = NULL; - SECStatus rv = SECFailure; - - if (handle == NULL || cert_name == NULL) - goto loser; - - cert = CERT_FindCertByNicknameOrEmailAddr (handle, (char *) cert_name); - if (cert == NULL) - goto loser; - - rv = CERT_VerifyCert (handle, cert, PR_TRUE, cert_usage, verify_time, - NULL, NULL); - - fprintf (out_file, "Verification of certificate \"%s\" ", cert_name); - if (rv == SECSuccess) { - fprintf (out_file, "succeeded.\n"); - } else { - const char *error_string = SECU_Strerror(PORT_GetError()); - fprintf (out_file, "failed. Reason:\n"); - if (error_string != NULL && PORT_Strlen(error_string) > 0) - fprintf (out_file, "%s\n", error_string); - else - fprintf (out_file, "Unknown\n"); - } - - rv = SECSuccess; - -loser: - if (cert != NULL) - CERT_DestroyCertificate (cert); - - return rv; -} - - -#ifdef NO_PP - -static SECStatus -print_request (FILE *out_file, SECItem *data) -{ - fprintf (out_file, "Cannot pretty-print request compiled with NO_PP.\n"); - return SECSuccess; -} - -static SECStatus -print_response (FILE *out_file, SECItem *data, CERTCertDBHandle *handle) -{ - fprintf (out_file, "Cannot pretty-print response compiled with NO_PP.\n"); - return SECSuccess; -} - -#else /* NO_PP */ - -static void -print_ocsp_version (FILE *out_file, SECItem *version, int level) -{ - if (version->len > 0) { - SECU_PrintInteger (out_file, version, "Version", level); - } else { - SECU_Indent (out_file, level); - fprintf (out_file, "Version: DEFAULT\n"); - } -} - - -static void -print_ocsp_cert_id (FILE *out_file, CERTOCSPCertID *cert_id, int level) -{ - SECU_Indent (out_file, level); - fprintf (out_file, "Cert ID:\n"); - level++; - - SECU_PrintAlgorithmID (out_file, &(cert_id->hashAlgorithm), - "Hash Algorithm", level); - SECU_PrintAsHex (out_file, &(cert_id->issuerNameHash), - "Issuer Name Hash", level); - SECU_PrintAsHex (out_file, &(cert_id->issuerKeyHash), - "Issuer Key Hash", level); - SECU_PrintInteger (out_file, &(cert_id->serialNumber), - "Serial Number", level); - /* XXX lookup the cert; if found, print something nice (nickname?) */ -} - - -static void -print_raw_certificates (FILE *out_file, SECItem **raw_certs, int level) -{ - SECItem *raw_cert; - int i = 0; - char cert_label[50]; - - SECU_Indent (out_file, level); - - if (raw_certs == NULL) { - fprintf (out_file, "No Certificates.\n"); - return; - } - - fprintf (out_file, "Certificate List:\n"); - while ((raw_cert = raw_certs[i++]) != NULL) { - sprintf (cert_label, "Certificate (%d)", i); - (void) SECU_PrintSignedData (out_file, raw_cert, cert_label, level + 1, - SECU_PrintCertificate); - } -} - - -static void -print_ocsp_extensions (FILE *out_file, CERTCertExtension **extensions, - char *msg, int level) -{ - if (extensions) { - SECU_PrintExtensions (out_file, extensions, msg, level); - } else { - SECU_Indent (out_file, level); - fprintf (out_file, "No %s\n", msg); - } -} - - -static void -print_single_request (FILE *out_file, ocspSingleRequest *single, int level) -{ - print_ocsp_cert_id (out_file, single->reqCert, level); - print_ocsp_extensions (out_file, single->singleRequestExtensions, - "Single Request Extensions", level); -} - - -/* - * Decode the DER/BER-encoded item "data" as an OCSP request - * and pretty-print the subfields. - */ -static SECStatus -print_request (FILE *out_file, SECItem *data) -{ - CERTOCSPRequest *request; - ocspTBSRequest *tbsRequest; - int level = 0; - - PORT_Assert (out_file != NULL); - PORT_Assert (data != NULL); - if (out_file == NULL || data == NULL) { - PORT_SetError (SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - request = CERT_DecodeOCSPRequest (data); - if (request == NULL || request->tbsRequest == NULL) - return SECFailure; - - tbsRequest = request->tbsRequest; - - fprintf (out_file, "TBS Request:\n"); - level++; - - print_ocsp_version (out_file, &(tbsRequest->version), level); - - /* - * XXX Probably should be an interface to get the signer name - * without looking inside the tbsRequest at all. - */ - if (tbsRequest->requestorName != NULL) { - SECU_Indent (out_file, level); - fprintf (out_file, "XXX print the requestorName\n"); - } else { - SECU_Indent (out_file, level); - fprintf (out_file, "No Requestor Name.\n"); - } - - if (tbsRequest->requestList != NULL) { - int i; - - for (i = 0; tbsRequest->requestList[i] != NULL; i++) { - SECU_Indent (out_file, level); - fprintf (out_file, "Request %d:\n", i); - print_single_request (out_file, tbsRequest->requestList[i], - level + 1); - } - } else { - fprintf (out_file, "Request list is empty.\n"); - } - - print_ocsp_extensions (out_file, tbsRequest->requestExtensions, - "Request Extensions", level); - - if (request->optionalSignature != NULL) { - ocspSignature *whole_sig; - SECItem rawsig; - - fprintf (out_file, "Signature:\n"); - - whole_sig = request->optionalSignature; - SECU_PrintAlgorithmID (out_file, &(whole_sig->signatureAlgorithm), - "Signature Algorithm", level); - - rawsig = whole_sig->signature; - DER_ConvertBitString (&rawsig); - SECU_PrintAsHex (out_file, &rawsig, "Signature", level); - - print_raw_certificates (out_file, whole_sig->derCerts, level); - - fprintf (out_file, "XXX verify the sig and print result\n"); - } else { - fprintf (out_file, "No Signature\n"); - } - - CERT_DestroyOCSPRequest (request); - return SECSuccess; -} - - -static void -print_revoked_info (FILE *out_file, ocspRevokedInfo *revoked_info, int level) -{ - SECU_PrintGeneralizedTime (out_file, &(revoked_info->revocationTime), - "Revocation Time", level); - - if (revoked_info->revocationReason != NULL) { - SECU_PrintAsHex (out_file, revoked_info->revocationReason, - "Revocation Reason", level); - } else { - SECU_Indent (out_file, level); - fprintf (out_file, "No Revocation Reason.\n"); - } -} - - -static void -print_cert_status (FILE *out_file, ocspCertStatus *status, int level) -{ - SECU_Indent (out_file, level); - fprintf (out_file, "Status: "); - - switch (status->certStatusType) { - case ocspCertStatus_good: - fprintf (out_file, "Cert is good.\n"); - break; - case ocspCertStatus_revoked: - fprintf (out_file, "Cert has been revoked.\n"); - print_revoked_info (out_file, status->certStatusInfo.revokedInfo, - level + 1); - break; - case ocspCertStatus_unknown: - fprintf (out_file, "Cert is unknown to responder.\n"); - break; - default: - fprintf (out_file, "Unrecognized status.\n"); - break; - } -} - - -static void -print_single_response (FILE *out_file, CERTOCSPSingleResponse *single, - int level) -{ - print_ocsp_cert_id (out_file, single->certID, level); - - print_cert_status (out_file, single->certStatus, level); - - SECU_PrintGeneralizedTime (out_file, &(single->thisUpdate), - "This Update", level); - - if (single->nextUpdate != NULL) { - SECU_PrintGeneralizedTime (out_file, single->nextUpdate, - "Next Update", level); - } else { - SECU_Indent (out_file, level); - fprintf (out_file, "No Next Update\n"); - } - - print_ocsp_extensions (out_file, single->singleExtensions, - "Single Response Extensions", level); -} - - -static void -print_responder_id (FILE *out_file, ocspResponderID *responderID, int level) -{ - SECU_Indent (out_file, level); - fprintf (out_file, "Responder ID "); - - switch (responderID->responderIDType) { - case ocspResponderID_byName: - fprintf (out_file, "(byName):\n"); - SECU_PrintName (out_file, &(responderID->responderIDValue.name), - "Name", level + 1); - break; - case ocspResponderID_byKey: - fprintf (out_file, "(byKey):\n"); - SECU_PrintAsHex (out_file, &(responderID->responderIDValue.keyHash), - "Key Hash", level + 1); - break; - default: - fprintf (out_file, "Unrecognized Responder ID Type\n"); - break; - } -} - - -static void -print_response_data (FILE *out_file, ocspResponseData *responseData, int level) -{ - SECU_Indent (out_file, level); - fprintf (out_file, "Response Data:\n"); - level++; - - print_ocsp_version (out_file, &(responseData->version), level); - - print_responder_id (out_file, responseData->responderID, level); - - SECU_PrintGeneralizedTime (out_file, &(responseData->producedAt), - "Produced At", level); - - if (responseData->responses != NULL) { - int i; - - for (i = 0; responseData->responses[i] != NULL; i++) { - SECU_Indent (out_file, level); - fprintf (out_file, "Response %d:\n", i); - print_single_response (out_file, responseData->responses[i], - level + 1); - } - } else { - fprintf (out_file, "Response list is empty.\n"); - } - - print_ocsp_extensions (out_file, responseData->responseExtensions, - "Response Extensions", level); -} - - -static void -print_basic_response (FILE *out_file, ocspBasicOCSPResponse *basic, int level) -{ - SECItem rawsig; - - SECU_Indent (out_file, level); - fprintf (out_file, "Basic OCSP Response:\n"); - level++; - - print_response_data (out_file, basic->tbsResponseData, level); - - SECU_PrintAlgorithmID (out_file, - &(basic->responseSignature.signatureAlgorithm), - "Signature Algorithm", level); - - rawsig = basic->responseSignature.signature; - DER_ConvertBitString (&rawsig); - SECU_PrintAsHex (out_file, &rawsig, "Signature", level); - - print_raw_certificates (out_file, basic->responseSignature.derCerts, level); -} - - -/* - * Note this must match (exactly) the enumeration ocspResponseStatus. - */ -static char *responseStatusNames[] = { - "successful (Response has valid confirmations)", - "malformedRequest (Illegal confirmation request)", - "internalError (Internal error in issuer)", - "tryLater (Try again later)", - "unused ((4) is not used)", - "sigRequired (Must sign the request)", - "unauthorized (Request unauthorized)", - "other (Status value out of defined range)" -}; - -/* - * Decode the DER/BER-encoded item "data" as an OCSP response - * and pretty-print the subfields. - */ -static SECStatus -print_response (FILE *out_file, SECItem *data, CERTCertDBHandle *handle) -{ - CERTOCSPResponse *response; - int level = 0; - - PORT_Assert (out_file != NULL); - PORT_Assert (data != NULL); - if (out_file == NULL || data == NULL) { - PORT_SetError (SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - response = CERT_DecodeOCSPResponse (data); - if (response == NULL) - return SECFailure; - - PORT_Assert (response->statusValue <= ocspResponse_other); - fprintf (out_file, "Response Status: %s\n", - responseStatusNames[response->statusValue]); - - if (response->statusValue == ocspResponse_successful) { - ocspResponseBytes *responseBytes = response->responseBytes; - SECStatus sigStatus; - CERTCertificate *signerCert = NULL; - - PORT_Assert (responseBytes != NULL); - - level++; - fprintf (out_file, "Response Bytes:\n"); - SECU_PrintObjectID (out_file, &(responseBytes->responseType), - "Response Type", level); - switch (response->responseBytes->responseTypeTag) { - case SEC_OID_PKIX_OCSP_BASIC_RESPONSE: - print_basic_response (out_file, - responseBytes->decodedResponse.basic, - level); - break; - default: - SECU_Indent (out_file, level); - fprintf (out_file, "Unknown response syntax\n"); - break; - } - - sigStatus = CERT_VerifyOCSPResponseSignature (response, handle, - NULL, &signerCert, NULL); - SECU_Indent (out_file, level); - fprintf (out_file, "Signature verification "); - if (sigStatus != SECSuccess) { - fprintf (out_file, "failed: %s\n", SECU_Strerror (PORT_GetError())); - } else { - fprintf (out_file, "succeeded.\n"); - if (signerCert != NULL) { - SECU_PrintName (out_file, &signerCert->subject, "Signer", - level); - CERT_DestroyCertificate (signerCert); - } else { - SECU_Indent (out_file, level); - fprintf (out_file, "No signer cert returned?\n"); - } - } - } else { - SECU_Indent (out_file, level); - fprintf (out_file, "Unsuccessful response, no more information.\n"); - } - - CERT_DestroyOCSPResponse (response); - return SECSuccess; -} - -#endif /* NO_PP */ - - -static SECStatus -cert_usage_from_char (const char *cert_usage_str, SECCertUsage *cert_usage) -{ - PORT_Assert (cert_usage_str != NULL); - PORT_Assert (cert_usage != NULL); - - if (PORT_Strlen (cert_usage_str) != 1) - return SECFailure; - - switch (*cert_usage_str) { - case 'c': - *cert_usage = certUsageSSLClient; - break; - case 's': - *cert_usage = certUsageSSLServer; - break; - case 'e': - *cert_usage = certUsageEmailRecipient; - break; - case 'E': - *cert_usage = certUsageEmailSigner; - break; - case 'S': - *cert_usage = certUsageObjectSigner; - break; - case 'C': - *cert_usage = certUsageVerifyCA; - break; - default: - return SECFailure; - } - - return SECSuccess; -} - - -int -main (int argc, char **argv) -{ - int retval; - char *program_name; - PRFileDesc *in_file; - FILE *out_file; /* not PRFileDesc until SECU accepts it */ - int crequest, dresponse; - int prequest, presponse; - int ccert, vcert; - const char *db_dir, *date_str, *cert_usage_str, *name; - const char *responder_name, *responder_url, *signer_name; - PRBool add_acceptable_responses, add_service_locator; - SECItem *data = NULL; - PLOptState *optstate; - SECStatus rv; - CERTCertDBHandle *handle = NULL; - SECCertUsage cert_usage; - int64 verify_time; - - retval = -1; /* what we return/exit with on error */ - - program_name = PL_strrchr(argv[0], '/'); - program_name = program_name ? (program_name + 1) : argv[0]; - - in_file = PR_STDIN; - out_file = stdout; - - crequest = 0; - dresponse = 0; - prequest = 0; - presponse = 0; - ccert = 0; - vcert = 0; - - db_dir = NULL; - date_str = NULL; - cert_usage_str = NULL; - name = NULL; - responder_name = NULL; - responder_url = NULL; - signer_name = NULL; - - add_acceptable_responses = PR_FALSE; - add_service_locator = PR_FALSE; - - optstate = PL_CreateOptState (argc, argv, "AHLPR:S:V:d:l:pr:s:t:u:w:"); - if (optstate == NULL) { - SECU_PrintError (program_name, "PL_CreateOptState failed"); - return retval; - } - - while (PL_GetNextOpt (optstate) == PL_OPT_OK) { - switch (optstate->option) { - case '?': - short_usage (program_name); - return retval; - - case 'A': - add_acceptable_responses = PR_TRUE; - break; - - case 'H': - long_usage (program_name); - return retval; - - case 'L': - add_service_locator = PR_TRUE; - break; - - case 'P': - presponse = 1; - break; - - case 'R': - dresponse = 1; - name = optstate->value; - break; - - case 'S': - ccert = 1; - name = optstate->value; - break; - - case 'V': - vcert = 1; - name = optstate->value; - break; - - case 'd': - db_dir = optstate->value; - break; - - case 'l': - responder_url = optstate->value; - break; - - case 'p': - prequest = 1; - break; - - case 'r': - crequest = 1; - name = optstate->value; - break; - - case 's': - signer_name = optstate->value; - break; - - case 't': - responder_name = optstate->value; - break; - - case 'u': - cert_usage_str = optstate->value; - break; - - case 'w': - date_str = optstate->value; - break; - } - } - - if ((crequest + dresponse + prequest + presponse + ccert + vcert) != 1) { - PR_fprintf (PR_STDERR, "%s: must specify exactly one command\n\n", - program_name); - short_usage (program_name); - return retval; - } - - if (vcert) { - if (cert_usage_str == NULL) { - PR_fprintf (PR_STDERR, "%s: verification requires cert usage\n\n", - program_name); - short_usage (program_name); - return retval; - } - - rv = cert_usage_from_char (cert_usage_str, &cert_usage); - if (rv != SECSuccess) { - PR_fprintf (PR_STDERR, "%s: invalid cert usage (\"%s\")\n\n", - program_name, cert_usage_str); - long_usage (program_name); - return retval; - } - } - - if (ccert + vcert) { - if (responder_url != NULL || responder_name != NULL) { - /* - * To do a full status check, both the URL and the cert name - * of the responder must be specified if either one is. - */ - if (responder_url == NULL || responder_name == NULL) { - if (responder_url == NULL) - PR_fprintf (PR_STDERR, - "%s: must also specify responder location\n\n", - program_name); - else - PR_fprintf (PR_STDERR, - "%s: must also specify responder name\n\n", - program_name); - short_usage (program_name); - return retval; - } - } - - if (date_str != NULL) { - rv = DER_AsciiToTime (&verify_time, (char *) date_str); - if (rv != SECSuccess) { - SECU_PrintError (program_name, "error converting time string"); - PR_fprintf (PR_STDERR, "\n"); - long_usage (program_name); - return retval; - } - } else { - verify_time = PR_Now(); - } - } - - retval = -2; /* errors change from usage to runtime */ - - /* - * Initialize the NSPR and Security libraries. - */ - PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); - db_dir = SECU_ConfigDirectory (db_dir); - rv = NSS_Init (db_dir); - if (rv != SECSuccess) { - SECU_PrintError (program_name, "NSS_Init failed"); - goto prdone; - } - - if (prequest + presponse) { - data = read_file_into_item (in_file, siBuffer); - if (data == NULL) { - SECU_PrintError (program_name, "problem reading input"); - goto nssdone; - } - } - - if (crequest + dresponse + presponse + ccert + vcert) { - handle = CERT_GetDefaultCertDB(); - if (handle == NULL) { - SECU_PrintError (program_name, "problem getting certdb handle"); - goto nssdone; - } - - /* - * It would be fine to do the enable for all of these commands, - * but this way we check that everything but an overall verify - * can be done without it. That is, that the individual pieces - * work on their own. - */ - if (vcert) { - rv = CERT_EnableOCSPChecking (handle); - if (rv != SECSuccess) { - SECU_PrintError (program_name, "error enabling OCSP checking"); - goto nssdone; - } - } - - if ((ccert + vcert) && (responder_name != NULL)) { - rv = CERT_SetOCSPDefaultResponder (handle, responder_url, - responder_name); - if (rv != SECSuccess) { - SECU_PrintError (program_name, - "error setting default responder"); - goto nssdone; - } - - rv = CERT_EnableOCSPDefaultResponder (handle); - if (rv != SECSuccess) { - SECU_PrintError (program_name, - "error enabling default responder"); - goto nssdone; - } - } - } - -#define NOTYET(opt) \ - { \ - PR_fprintf (PR_STDERR, "%s not yet working\n", opt); \ - exit (-1); \ - } - - if (crequest) { - if (signer_name != NULL) { - NOTYET("-s"); - } - rv = create_request (out_file, handle, name, add_service_locator, - add_acceptable_responses); - } else if (dresponse) { - if (signer_name != NULL) { - NOTYET("-s"); - } - rv = dump_response (out_file, handle, name, responder_url); - } else if (prequest) { - rv = print_request (out_file, data); - } else if (presponse) { - rv = print_response (out_file, data, handle); - } else if (ccert) { - if (signer_name != NULL) { - NOTYET("-s"); - } - rv = get_cert_status (out_file, handle, name, verify_time); - } else if (vcert) { - if (signer_name != NULL) { - NOTYET("-s"); - } - rv = verify_cert (out_file, handle, name, cert_usage, verify_time); - } - - if (rv != SECSuccess) - SECU_PrintError (program_name, "error performing requested operation"); - else - retval = 0; - -nssdone: - if (data != NULL) { - SECITEM_FreeItem (data, PR_TRUE); - } - - if (handle != NULL) { - (void) CERT_DisableOCSPChecking (handle); - } - - NSS_Shutdown (); - -prdone: - PR_Cleanup (); - return retval; -} |