michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "signtool.h" michael@0: #include "pk11func.h" michael@0: #include "certdb.h" michael@0: michael@0: static int num_trav_certs = 0; michael@0: static SECStatus cert_trav_callback(CERTCertificate *cert, SECItem *k, michael@0: void *data); michael@0: michael@0: /********************************************************************* michael@0: * michael@0: * L i s t C e r t s michael@0: */ michael@0: int michael@0: ListCerts(char *key, int list_certs) michael@0: { michael@0: int failed = 0; michael@0: SECStatus rv; michael@0: char *ugly_list; michael@0: CERTCertDBHandle * db; michael@0: michael@0: CERTCertificate * cert; michael@0: CERTVerifyLog errlog; michael@0: michael@0: errlog.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); michael@0: if ( errlog.arena == NULL) { michael@0: out_of_memory(); michael@0: } michael@0: errlog.head = NULL; michael@0: errlog.tail = NULL; michael@0: errlog.count = 0; michael@0: michael@0: ugly_list = PORT_ZAlloc (16); michael@0: michael@0: if (ugly_list == NULL) { michael@0: out_of_memory(); michael@0: } michael@0: michael@0: *ugly_list = 0; michael@0: michael@0: db = CERT_GetDefaultCertDB(); michael@0: michael@0: if (list_certs == 2) { michael@0: PR_fprintf(outputFD, "\nS Certificates\n"); michael@0: PR_fprintf(outputFD, "- ------------\n"); michael@0: } else { michael@0: PR_fprintf(outputFD, "\nObject signing certificates\n"); michael@0: PR_fprintf(outputFD, "---------------------------------------\n"); michael@0: } michael@0: michael@0: num_trav_certs = 0; michael@0: michael@0: /* Traverse ALL tokens in all slots, authenticating to them all */ michael@0: rv = PK11_TraverseSlotCerts(cert_trav_callback, (void * )&list_certs, michael@0: &pwdata); michael@0: michael@0: if (rv) { michael@0: PR_fprintf(outputFD, "**Traverse of ALL slots & tokens failed**\n"); michael@0: return - 1; michael@0: } michael@0: michael@0: if (num_trav_certs == 0) { michael@0: PR_fprintf(outputFD, michael@0: "You don't appear to have any object signing certificates.\n"); michael@0: } michael@0: michael@0: if (list_certs == 2) { michael@0: PR_fprintf(outputFD, "- ------------\n"); michael@0: } else { michael@0: PR_fprintf(outputFD, "---------------------------------------\n"); michael@0: } michael@0: michael@0: if (list_certs == 1) { michael@0: PR_fprintf(outputFD, michael@0: "For a list including CA's, use \"%s -L\"\n", PROGRAM_NAME); michael@0: } michael@0: michael@0: if (list_certs == 2) { michael@0: PR_fprintf(outputFD, michael@0: "Certificates that can be used to sign objects have *'s to " michael@0: "their left.\n"); michael@0: } michael@0: michael@0: if (key) { michael@0: /* Do an analysis of the given cert */ michael@0: michael@0: cert = PK11_FindCertFromNickname(key, &pwdata); michael@0: michael@0: if (cert) { michael@0: PR_fprintf(outputFD, michael@0: "\nThe certificate with nickname \"%s\" was found:\n", michael@0: cert->nickname); michael@0: PR_fprintf(outputFD, "\tsubject name: %s\n", cert->subjectName); michael@0: PR_fprintf(outputFD, "\tissuer name: %s\n", cert->issuerName); michael@0: michael@0: PR_fprintf(outputFD, "\n"); michael@0: michael@0: rv = CERT_CertTimesValid (cert); michael@0: if (rv != SECSuccess) { michael@0: PR_fprintf(outputFD, "**This certificate is expired**\n"); michael@0: } else { michael@0: PR_fprintf(outputFD, "This certificate is not expired.\n"); michael@0: } michael@0: michael@0: rv = CERT_VerifyCert (db, cert, PR_TRUE, michael@0: certUsageObjectSigner, PR_Now(), &pwdata, &errlog); michael@0: michael@0: if (rv != SECSuccess) { michael@0: failed = 1; michael@0: if (errlog.count > 0) { michael@0: PR_fprintf(outputFD, michael@0: "**Certificate validation failed for the " michael@0: "following reason(s):**\n"); michael@0: } else { michael@0: PR_fprintf(outputFD, "**Certificate validation failed**"); michael@0: } michael@0: } else { michael@0: PR_fprintf(outputFD, "This certificate is valid.\n"); michael@0: } michael@0: displayVerifyLog(&errlog); michael@0: michael@0: michael@0: } else { michael@0: failed = 1; michael@0: PR_fprintf(outputFD, michael@0: "The certificate with nickname \"%s\" was NOT FOUND\n", key); michael@0: } michael@0: } michael@0: michael@0: if (errlog.arena != NULL) { michael@0: PORT_FreeArena(errlog.arena, PR_FALSE); michael@0: } michael@0: michael@0: if (failed) { michael@0: return - 1; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: michael@0: /******************************************************************** michael@0: * michael@0: * c e r t _ t r a v _ c a l l b a c k michael@0: */ michael@0: static SECStatus michael@0: cert_trav_callback(CERTCertificate *cert, SECItem *k, void *data) michael@0: { michael@0: int list_certs = 1; michael@0: char *name; michael@0: michael@0: if (data) { michael@0: list_certs = *((int * )data); michael@0: } michael@0: michael@0: #define LISTING_USER_SIGNING_CERTS (list_certs == 1) michael@0: #define LISTING_ALL_CERTS (list_certs == 2) michael@0: michael@0: name = cert->nickname; michael@0: if (name) { michael@0: int isSigningCert; michael@0: michael@0: isSigningCert = cert->nsCertType & NS_CERT_TYPE_OBJECT_SIGNING; michael@0: if (!isSigningCert && LISTING_USER_SIGNING_CERTS) michael@0: return (SECSuccess); michael@0: michael@0: /* Display this name or email address */ michael@0: num_trav_certs++; michael@0: michael@0: if (LISTING_ALL_CERTS) { michael@0: PR_fprintf(outputFD, "%s ", isSigningCert ? "*" : " "); michael@0: } michael@0: PR_fprintf(outputFD, "%s\n", name); michael@0: michael@0: if (LISTING_USER_SIGNING_CERTS) { michael@0: int rv = SECFailure; michael@0: if (rv) { michael@0: CERTCertificate * issuerCert; michael@0: issuerCert = CERT_FindCertIssuer(cert, PR_Now(), michael@0: certUsageObjectSigner); michael@0: if (issuerCert) { michael@0: if (issuerCert->nickname && issuerCert->nickname[0]) { michael@0: PR_fprintf(outputFD, " Issued by: %s\n", michael@0: issuerCert->nickname); michael@0: rv = SECSuccess; michael@0: } michael@0: CERT_DestroyCertificate(issuerCert); michael@0: } michael@0: } michael@0: if (rv && cert->issuerName && cert->issuerName[0]) { michael@0: PR_fprintf(outputFD, " Issued by: %s \n", cert->issuerName); michael@0: } michael@0: { michael@0: char *expires; michael@0: expires = DER_TimeChoiceDayToAscii(&cert->validity.notAfter); michael@0: if (expires) { michael@0: PR_fprintf(outputFD, " Expires: %s\n", expires); michael@0: PORT_Free(expires); michael@0: } michael@0: } michael@0: michael@0: rv = CERT_VerifyCertNow (cert->dbhandle, cert, michael@0: PR_TRUE, certUsageObjectSigner, &pwdata); michael@0: michael@0: if (rv != SECSuccess) { michael@0: rv = PORT_GetError(); michael@0: PR_fprintf(outputFD, michael@0: " ++ Error ++ THIS CERTIFICATE IS NOT VALID (%s)\n", michael@0: secErrorString(rv)); michael@0: } michael@0: } michael@0: } michael@0: michael@0: return (SECSuccess); michael@0: } michael@0: michael@0: