#include <security_cdsa_utils/cuFileIo.h>
#include <utilLib/common.h>
#include <clAppUtils/clutils.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Security/cssm.h>
#include <clAppUtils/BlobList.h>
#include <clAppUtils/certVerify.h>
#include "script.h"
static void usage(char **argv)
{
printf("Usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" -c certFileName [...]\n");
printf(" -C rootCertFileName [...]\n");
printf(" -r crlFileName [...]\n");
printf(" -d certDbName\n");
printf(" -D crlDlDbName\n");
printf(" -s (use system anchor certs)\n");
printf(" -g (use Trust Settings)\n");
printf(" -i (implicit anchors)\n");
printf(" -l=loopCount (default = 1)\n");
printf(" -f (leaf cert is a CA)\n");
printf(" -w(rite CRLs to dlDbName)\n");
printf("Policy options:\n");
printf(" -y ssl|smime|swuSign|codeSign|pkgSign|resourceSign|iChat|pkinitServer|\n"
" pkinitClient|IPSec\n");
printf(" -h sslHostName (implies SSL policy; default is basic)\n");
printf(" -t SSL client side (implies SSL policy, default is server side)\n");
printf(" -E senderEmail (implies SMIME policy unless iChat is specified)\n");
printf("Revocation options:\n");
printf(" -R revocationPolicy (crl|ocsp|both|none); default = none\n");
printf(" -a (allow certs unverified by CRL or OCSP)\n");
printf(" -A (require CRL verification if present in cert\n");
printf(" -4 (require CRL verification for all certs)\n");
printf(" -Q (require OCSP if present in cert)\n");
printf(" -5 (require OCSP verification for all certs)\n");
printf(" -u responderURI\n");
printf(" -U responderCert\n");
printf(" -H (OCSP cache disable)\n");
printf(" -W (network OCSP disable)\n");
printf(" -o generate OCSP nonce\n");
printf(" -O require nonce in OCSP response\n");
printf("Misc. options:\n");
printf(" -n (no network fetch of CRLs)\n");
printf(" -N (no network fetch of certs)\n");
printf(" -k keyUsage (In HEX starting with 0x)\n");
printf(" -T verifyTime (in CSSM_TIMESTRING format, like 20041217154316)\n");
printf(" -e=expectedError (default is CSSM_OK)\n");
printf(" -S scriptFile\n");
printf(" -p (print script variable names)\n");
printf(" -P (pause after each script test)\n");
printf(" -v (verbose)\n");
printf(" -q (quiet)\n");
printf(" -L (silent)\n");
exit(1);
}
static void gatherFiles(
BlobList &blobList,
char **argv,
int argc,
int &currArg)
{
if((currArg == argc) || (argv[currArg][0] == '-')) {
usage(argv);
}
while(currArg<argc) {
char *argp = argv[currArg];
if(argp[0] == '-') {
currArg--;
return;
}
int rtn = blobList.addFile(argv[currArg]);
if(rtn) {
exit(1);
}
currArg++;
}
return;
}
int main(int argc, char **argv)
{
BlobList certs;
BlobList roots;
BlobList crls;
int rtn;
CSSM_DL_HANDLE dlHand;
int loop;
int arg;
char *argp;
CSSM_DL_DB_HANDLE_PTR crlDbHandPtr = NULL;
CSSM_DL_DB_LIST dlDbList;
CSSM_DL_DB_HANDLE dlDbHandles[2];
CSSM_RETURN crtn;
CSSM_RETURN silent = CSSM_FALSE;
CSSM_BOOL scriptPause = CSSM_FALSE;
CertVerifyArgs vfyArgs;
memset(&vfyArgs, 0, sizeof(vfyArgs));
vfyArgs.version = CERT_VFY_ARGS_VERS;
vfyArgs.certs = &certs;
vfyArgs.roots = &roots;
vfyArgs.crls = &crls;
vfyArgs.crlNetFetchEnable = CSSM_TRUE;
vfyArgs.certNetFetchEnable = CSSM_TRUE;
int loops = 1;
const char *crlDbName = NULL;
const char *certDbName = NULL;
char *scriptFile = NULL;
if(argc < 2) {
usage(argv);
}
for(arg=1; arg<argc; arg++) {
argp = argv[arg];
if(argp[0] != '-') {
usage(argv);
}
switch(argp[1]) {
case 'l':
loops = atoi(&argp[3]);
break;
case 'r':
arg++;
gatherFiles(crls, argv, argc, arg);
break;
case 'c':
arg++;
gatherFiles(certs, argv, argc, arg);
break;
case 'C':
arg++;
gatherFiles(roots, argv, argc, arg);
break;
case 'v':
vfyArgs.verbose = CSSM_TRUE;
break;
case 'q':
vfyArgs.quiet = CSSM_TRUE;
break;
case 's':
vfyArgs.useSystemAnchors = CSSM_TRUE;
break;
case 'g':
vfyArgs.useTrustSettings = CSSM_TRUE;
break;
case 'i':
vfyArgs.implicitAnchors = CSSM_TRUE;
break;
case 'a':
vfyArgs.allowUnverified = CSSM_TRUE;
break;
case 'e':
vfyArgs.expectedErrStr = &argp[3];
break;
case 'n':
vfyArgs.crlNetFetchEnable = CSSM_FALSE;
break;
case 'N':
vfyArgs.certNetFetchEnable = CSSM_FALSE;
break;
case 'f':
vfyArgs.leafCertIsCA = CSSM_TRUE;
break;
case 'd':
arg++;
if(arg == argc) {
usage(argv);
}
certDbName = argv[arg];
break;
case 'D':
arg++;
if(arg == argc) {
usage(argv);
}
crlDbName = argv[arg];
break;
case 'S':
arg++;
if(arg == argc) {
usage(argv);
}
scriptFile = argv[arg];
break;
case 'h':
arg++;
if(arg == argc) {
usage(argv);
}
vfyArgs.sslHost= argv[arg];
vfyArgs.vfyPolicy = CVP_SSL;
break;
case 'E':
arg++;
if(arg == argc) {
usage(argv);
}
if(vfyArgs.vfyPolicy == CVP_Basic) {
vfyArgs.vfyPolicy = CVP_SMIME;
}
vfyArgs.senderEmail = argv[arg];
break;
case 'k':
arg++;
if(arg == argc) {
usage(argv);
}
vfyArgs.intendedKeyUse = hexToBin(argv[arg]);
break;
case 't':
vfyArgs.sslClient = CSSM_TRUE;
vfyArgs.vfyPolicy = CVP_SSL;
break;
case 'y':
arg++;
if(arg == argc) {
usage(argv);
}
argp = argv[arg];
if(parsePolicyString(argp, &vfyArgs.vfyPolicy)) {
printf("Bogus policyValue (%s)\n", argp);
printPolicyStrings();
exit(1);
}
break;
case 'R':
arg++;
if(arg == argc) {
usage(argv);
}
argp = argv[arg];
if(!strcmp(argp, "none")) {
vfyArgs.revokePolicy = CRP_None;
}
else if(!strcmp(argp, "crl")) {
vfyArgs.revokePolicy = CRP_CRL;
}
else if(!strcmp(argp, "ocsp")) {
vfyArgs.revokePolicy = CRP_OCSP;
}
else if(!strcmp(argp, "both")) {
vfyArgs.revokePolicy = CRP_CRL_OCSP;
}
else {
usage(argv);
}
break;
case 'u':
arg++;
if(arg == argc) {
usage(argv);
}
vfyArgs.responderURI = argv[arg];
break;
case 'U':
if(readFile(argv[arg], (unsigned char **)vfyArgs.responderCert,
&vfyArgs.responderCertLen)) {
printf("***Error reading responderCert from %s. Aborting.\n",
argv[arg]);
exit(1);
}
break;
case 'H':
vfyArgs.disableCache = CSSM_TRUE;
break;
case 'W':
vfyArgs.disableOcspNet = CSSM_TRUE;
break;
case 'Q':
vfyArgs.requireOcspIfPresent = CSSM_TRUE;
break;
case '5':
vfyArgs.requireOcspForAll = CSSM_TRUE;
break;
case 'o':
vfyArgs.generateOcspNonce = CSSM_TRUE;
break;
case 'O':
vfyArgs.requireOcspRespNonce = CSSM_TRUE;
break;
case 'A':
vfyArgs.requireCrlIfPresent = CSSM_TRUE;
break;
case '4':
vfyArgs.requireCrlForAll = CSSM_TRUE;
break;
case 'T':
arg++;
if(arg == argc) {
usage(argv);
}
vfyArgs.vfyTime = argv[arg];
break;
case 'p':
printScriptVars();
exit(0);
case 'P':
scriptPause = CSSM_TRUE;
break;
case 'L':
silent = CSSM_TRUE; vfyArgs.quiet = CSSM_TRUE; break;
default:
usage(argv);
}
}
if((vfyArgs.responderCert != NULL) || (vfyArgs.responderURI != NULL)) {
switch(vfyArgs.revokePolicy) {
case CRP_None:
vfyArgs.revokePolicy = CRP_OCSP;
break;
case CRP_OCSP:
case CRP_CRL_OCSP:
break;
case CRP_CRL:
printf("*** OCSP options (responderURI, responderCert) only valid "
"with OCSP policy\n");
usage(argv);
}
}
vfyArgs.clHand = clStartup();
if(vfyArgs.clHand == CSSM_INVALID_HANDLE) {
return 1;
}
vfyArgs.tpHand = tpStartup();
if(vfyArgs.tpHand == CSSM_INVALID_HANDLE) {
return 1;
}
vfyArgs.cspHand = cspStartup();
if(vfyArgs.cspHand == CSSM_INVALID_HANDLE) {
return 1;
}
dlHand = dlStartup();
if(dlHand == CSSM_INVALID_HANDLE) {
return 1;
}
if(!silent) {
testStartBanner("certcrl", argc, argv);
}
if(scriptFile) {
ScriptVars vars;
vars.allowUnverified = vfyArgs.allowUnverified;
vars.requireCrlIfPresent = vfyArgs.requireCrlIfPresent;
vars.requireOcspIfPresent = vfyArgs.requireOcspIfPresent;
vars.crlNetFetchEnable = vfyArgs.crlNetFetchEnable;
vars.certNetFetchEnable = vfyArgs.certNetFetchEnable;
vars.useSystemAnchors = vfyArgs.useSystemAnchors;
vars.useTrustSettings = vfyArgs.useTrustSettings;
vars.leafCertIsCA = vfyArgs.leafCertIsCA;
vars.cacheDisable = vfyArgs.disableCache;
vars.ocspNetFetchDisable = vfyArgs.disableOcspNet;
vars.requireCrlForAll = vfyArgs.requireCrlForAll;
vars.requireOcspForAll = vfyArgs.requireOcspForAll;
return runScript(scriptFile, vfyArgs.tpHand, vfyArgs.clHand,
vfyArgs.cspHand, dlHand,
&vars, vfyArgs.quiet, vfyArgs.verbose, scriptPause);
}
dlDbList.NumHandles = 0;
dlDbList.DLDBHandle = &dlDbHandles[0];
dlDbList.DLDBHandle[0].DLHandle = dlHand;
dlDbList.DLDBHandle[1].DLHandle = dlHand;
if(certDbName != NULL) {
crtn = CSSM_DL_DbOpen(dlHand,
certDbName,
NULL, CSSM_DB_ACCESS_READ,
NULL, NULL, &dlDbList.DLDBHandle[0].DBHandle);
if(crtn) {
printError("CSSM_DL_DbOpen", crtn);
printf("***Error opening DB %s. Aborting.\n", certDbName);
return 1;
}
dlDbList.NumHandles++;
vfyArgs.dlDbList = &dlDbList;
}
if(crlDbName != NULL) {
vfyArgs.crlDlDb = &dlDbList.DLDBHandle[dlDbList.NumHandles];
crtn = CSSM_DL_DbOpen(dlHand,
crlDbName,
NULL, CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE,
NULL, NULL, &crlDbHandPtr->DBHandle);
if(crtn) {
printError("CSSM_DL_DbOpen", crtn);
printf("***Error opening DB %s. Aborting.\n", crlDbName);
return 1;
}
dlDbList.NumHandles++;
vfyArgs.dlDbList = &dlDbList;
}
for(loop=0; loop<loops; loop++) {
rtn = certVerify(&vfyArgs);
if(rtn) {
break;
}
if(loops != 1) {
fpurge(stdin);
printf("CR to continue, q to quit: ");
char c = getchar();
if(c == 'q') {
break;
}
}
}
return rtn;
}