/* This function does NOT expect a DER type and length. */ SECOidTag SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level) { SECOidData *oiddata; char *oidString = NULL; oiddata = SECOID_FindOID(oid); if (oiddata != NULL) { const char *name = oiddata->desc; SECU_Indent(out, level); if (m != NULL) fprintf(out, "%s: ", m); fprintf(out, "%s\n", name); return oiddata->offset; } oidString = CERT_GetOidString(oid); if (oidString) { SECU_Indent(out, level); if (m != NULL) fprintf(out, "%s: ", m); fprintf(out, "%s\n", oidString); PR_smprintf_free(oidString); return SEC_OID_UNKNOWN; } SECU_PrintAsHex(out, oid, m, level); return SEC_OID_UNKNOWN; }
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); }
void SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value, char *msg, int level) { CERTPrivKeyUsagePeriod * prd; PLArenaPool * arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( !arena ) { goto loser; } prd = CERT_DecodePrivKeyUsagePeriodExtension(arena, value); if (!prd) { goto loser; } if (prd->notBefore.data) { SECU_PrintGeneralizedTime(out, &prd->notBefore, "Not Before", level); } if (prd->notAfter.data) { SECU_PrintGeneralizedTime(out, &prd->notAfter, "Not After ", level); } if (!prd->notBefore.data && !prd->notAfter.data) { SECU_Indent(out, level); fprintf(out, "Error: notBefore or notAfter MUST be present.\n"); loser: SECU_PrintAny(out, value, msg, level); } if (arena) { PORT_FreeArena(arena, PR_FALSE); } }
void SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level) { CERTCertificatePolicies *policies = NULL; CERTPolicyInfo **policyInfos; if (msg) { SECU_Indent(out, level); fprintf(out,"%s: \n",msg); level++; } policies = secu_DecodeCertificatePoliciesExtension(value); if (policies == NULL) { SECU_PrintAny(out, value, "Invalid Policy Data", level); return; } policyInfos = policies->policyInfos; while (policyInfos && *policyInfos != NULL) { secu_PrintPolicyInfo(out,*policyInfos,"",level); policyInfos++; } CERT_DestroyCertificatePoliciesExtension(policies); }
static SECStatus secu_PrintPolicyQualifier(FILE *out,CERTPolicyQualifier *policyQualifier, char *msg,int level) { SECStatus rv; SECItem * qualifierValue = &policyQualifier->qualifierValue; SECU_PrintObjectID(out, &policyQualifier->qualifierID , "Policy Qualifier Name", level); if (!qualifierValue->data) { SECU_Indent(out, level); fprintf(out,"Error: missing qualifier\n"); } else switch (policyQualifier->oid) { case SEC_OID_PKIX_USER_NOTICE_QUALIFIER: rv = secu_PrintUserNoticeQualifier(out, qualifierValue, msg, level); if (SECSuccess == rv) break; /* fall through on error */ case SEC_OID_PKIX_CPS_POINTER_QUALIFIER: default: SECU_PrintAny(out, qualifierValue, "Policy Qualifier Data", level); break; } return SECSuccess; }
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_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_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"); } }
/* This expents i->data[0] to be the MSB of the integer. ** if you want to print a DER-encoded integer (with the tag and length) ** call SECU_PrintEncodedInteger(); */ void SECU_PrintInteger(FILE *out, const SECItem *i, const char *m, int level) { int iv; if (!i || !i->len || !i->data) { SECU_Indent(out, level); if (m) { fprintf(out, "%s: (null)\n", m); } else { fprintf(out, "(null)\n"); } } else if (i->len > 4) { SECU_PrintAsHex(out, i, m, level); } else { if (i->type == siUnsignedInteger && *i->data & 0x80) { /* Make sure i->data has zero in the highest bite * if i->data is an unsigned integer */ SECItem tmpI; char data[] = { 0, 0, 0, 0, 0 }; PORT_Memcpy(data + 1, i->data, i->len); tmpI.len = i->len + 1; tmpI.data = (void *)data; iv = DER_GetInteger(&tmpI); } else { iv = DER_GetInteger(i); } SECU_Indent(out, level); if (m) { fprintf(out, "%s: %d (0x%x)\n", m, iv, iv); } else { fprintf(out, "%d (0x%x)\n", iv, iv); } } }
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?) */ }
void SECU_PrintErrMsg(FILE *out, int level, char *progName, char *msg, ...) { va_list args; PRErrorCode err = PORT_GetError(); const char * errString = SECU_Strerror(err); va_start(args, msg); SECU_Indent(out, level); fprintf(out, "%s: ", progName); vfprintf(out, msg, args); if (errString != NULL && PORT_Strlen(errString) > 0) fprintf(out, ": %s\n", errString); else fprintf(out, ": error %d\n", (int)err); va_end(args); }
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_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); }
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_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_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; } }
/* * 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; if (response->statusValue >= ocspResponse_min && response->statusValue <= ocspResponse_max) { fprintf (out_file, "Response Status: %s\n", responseStatusNames[response->statusValue]); } else { fprintf (out_file, "Response Status: other (Status value %d out of defined range)\n", (int)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; }
void SECU_PrintAsHex(FILE *out, const SECItem *data, const char *m, int level) { unsigned i; int column = 0; PRBool isString = PR_TRUE; PRBool isWhiteSpace = PR_TRUE; PRBool printedHex = PR_FALSE; unsigned int limit = 15; if (m) { SECU_Indent(out, level); fprintf(out, "%s:", m); level++; if (wrapEnabled) fprintf(out, "\n"); } if (wrapEnabled) { SECU_Indent(out, level); column = level * INDENT_MULT; } if (!data->len) { fprintf(out, "(empty)\n"); return; } /* take a pass to see if it's all printable. */ for (i = 0; i < data->len; i++) { unsigned char val = data->data[i]; if (!val || !isprint(val)) { isString = PR_FALSE; break; } if (isWhiteSpace && !isspace(val)) { isWhiteSpace = PR_FALSE; } } /* Short values, such as bit strings (which are printed with this ** function) often look like strings, but we want to see the bits. ** so this test assures that short values will be printed in hex, ** perhaps in addition to being printed as strings. ** The threshold size (4 bytes) is arbitrary. */ if (!isString || data->len <= 4) { for (i = 0; i < data->len; i++) { if (i != data->len - 1) { fprintf(out, "%02x:", data->data[i]); column += 3; } else { fprintf(out, "%02x", data->data[i]); column += 2; break; } if (wrapEnabled && (column > 76 || (i % 16 == limit))) { SECU_Newline(out); SECU_Indent(out, level); column = level * INDENT_MULT; limit = i % 16; } } printedHex = PR_TRUE; } if (isString && !isWhiteSpace) { if (printedHex != PR_FALSE) { SECU_Newline(out); SECU_Indent(out, level); column = level * INDENT_MULT; } for (i = 0; i < data->len; i++) { unsigned char val = data->data[i]; if (val) { fprintf(out, "%c", val); column++; } else { column = 77; } if (wrapEnabled && column > 76) { SECU_Newline(out); SECU_Indent(out, level); column = level * INDENT_MULT; } } } if (column != level * INDENT_MULT) { SECU_Newline(out); } }
/* * 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; }