security/nss/cmd/vfychain/vfychain.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /****************************************************************************
     6  *  Read in a cert chain from one or more files, and verify the chain for
     7  *  some usage.
     8  *                                                                          *
     9  *  This code was modified from other code also kept in the NSS directory.
    10  ****************************************************************************/ 
    12 #include <stdio.h>
    13 #include <string.h>
    15 #if defined(XP_UNIX)
    16 #include <unistd.h>
    17 #endif
    19 #include "prerror.h"
    21 #include "pk11func.h"
    22 #include "seccomon.h"
    23 #include "secutil.h"
    24 #include "secmod.h"
    25 #include "secitem.h"
    26 #include "cert.h"
    27 #include "ocsp.h"
    30 /* #include <stdlib.h> */
    31 /* #include <errno.h> */
    32 /* #include <fcntl.h> */
    33 /* #include <stdarg.h> */
    35 #include "nspr.h"
    36 #include "plgetopt.h"
    37 #include "prio.h"
    38 #include "nss.h"
    40 /* #include "vfyutil.h" */
    42 #define RD_BUF_SIZE (60 * 1024)
    44 int verbose;
    46 secuPWData  pwdata          = { PW_NONE, 0 };
    48 static void
    49 Usage(const char *progName)
    50 {
    51     fprintf(stderr, 
    52 	"Usage: %s [options] [revocation options] certfile "
    53             "[[options] certfile] ...\n"
    54 	"\tWhere options are:\n"
    55 	"\t-a\t\t Following certfile is base64 encoded\n"
    56 	"\t-b YYMMDDHHMMZ\t Validate date (default: now)\n"
    57 	"\t-d directory\t Database directory\n"
    58 	"\t-i number of consecutive verifications\n"
    59 	"\t-f \t\t Enable cert fetching from AIA URL\n"
    60 	"\t-o oid\t\t Set policy OID for cert validation(Format OID.1.2.3)\n"
    61 	"\t-p \t\t Use PKIX Library to validate certificate by calling:\n"
    62 	"\t\t\t   * CERT_VerifyCertificate if specified once,\n"
    63 	"\t\t\t   * CERT_PKIXVerifyCert if specified twice and more.\n"
    64 	"\t-r\t\t Following certfile is raw binary DER (default)\n"
    65         "\t-t\t\t Following cert is explicitly trusted (overrides db trust).\n"
    66 	"\t-u usage \t 0=SSL client, 1=SSL server, 2=SSL StepUp, 3=SSL CA,\n"
    67 	"\t\t\t 4=Email signer, 5=Email recipient, 6=Object signer,\n"
    68 	"\t\t\t 9=ProtectedObjectSigner, 10=OCSP responder, 11=Any CA\n"
    69 	"\t-T\t\t Trust both explicit trust anchors (-t) and the database.\n"
    70 	"\t\t\t (Default is to only trust certificates marked -t, if there are any,\n"
    71 	"\t\t\t or to trust the database if there are certificates marked -t.)\n"
    72 	"\t-v\t\t Verbose mode. Prints root cert subject(double the\n"
    73 	"\t\t\t argument for whole root cert info)\n"
    74 	"\t-w password\t Database password.\n"
    75 	"\t-W pwfile\t Password file.\n\n"
    76         "\tRevocation options for PKIX API(invoked with -pp options) is a\n"
    77         "\tcollection of the following flags:\n"
    78         "\t\t[-g type [-h flags] [-m type [-s flags]] ...] ...\n"
    79         "\tWhere:\n"
    80         "\t-g test type\t Sets status checking test type. Possible values\n"
    81         "\t\t\tare \"leaf\" or \"chain\"\n"
    82         "\t-h test flags\t Sets revocation flags for the test type it\n"
    83         "\t\t\tfollows. Possible flags: \"testLocalInfoFirst\" and\n"
    84         "\t\t\t\"requireFreshInfo\".\n"
    85         "\t-m method type\t Sets method type for the test type it follows.\n"
    86         "\t\t\tPossible types are \"crl\" and \"ocsp\".\n"
    87         "\t-s method flags\t Sets revocation flags for the method it follows.\n"
    88         "\t\t\tPossible types are \"doNotUse\", \"forbidFetching\",\n"
    89         "\t\t\t\"ignoreDefaultSrc\", \"requireInfo\" and \"failIfNoInfo\".\n",
    90         progName);
    91     exit(1);
    92 }
    94 /**************************************************************************
    95 ** 
    96 ** Error and information routines.
    97 **
    98 **************************************************************************/
   100 void
   101 errWarn(char *function)
   102 {
   103     fprintf(stderr, "Error in function %s: %s\n",
   104 		    function, SECU_Strerror(PR_GetError()));
   105 }
   107 void
   108 exitErr(char *function)
   109 {
   110     errWarn(function);
   111     /* Exit gracefully. */
   112     /* ignoring return value of NSS_Shutdown as code exits with 1 anyway*/
   113     (void) NSS_Shutdown();
   114     PR_Cleanup();
   115     exit(1);
   116 }
   118 typedef struct certMemStr {
   119     struct certMemStr * next;
   120     CERTCertificate * cert;
   121 } certMem;
   123 certMem * theCerts;
   124 CERTCertList *trustedCertList;
   126 void
   127 rememberCert(CERTCertificate * cert, PRBool trusted)
   128 {
   129     if (trusted) {
   130         if (!trustedCertList) {
   131             trustedCertList = CERT_NewCertList();
   132         }
   133         CERT_AddCertToListTail(trustedCertList, cert);
   134     } else {
   135         certMem * newCertMem = PORT_ZNew(certMem);
   136         if (newCertMem) {
   137             newCertMem->next = theCerts;
   138             newCertMem->cert = cert;
   139             theCerts = newCertMem;
   140         }
   141     }
   142 }
   144 void
   145 forgetCerts(void)
   146 {
   147     certMem * oldCertMem;
   148     while (theCerts) {
   149 	oldCertMem = theCerts;
   150     	theCerts = theCerts->next;
   151 	CERT_DestroyCertificate(oldCertMem->cert);
   152 	PORT_Free(oldCertMem);
   153     }
   154     if (trustedCertList) {
   155         CERT_DestroyCertList(trustedCertList);
   156     }
   157 }
   160 CERTCertificate *
   161 getCert(const char *name, PRBool isAscii, const char * progName)
   162 {
   163     CERTCertificate * cert;
   164     CERTCertDBHandle *defaultDB;
   165     PRFileDesc*     fd;
   166     SECStatus       rv;
   167     SECItem         item        = {0, NULL, 0};
   169     defaultDB = CERT_GetDefaultCertDB();
   171     /* First, let's try to find the cert in existing DB. */
   172     cert = CERT_FindCertByNicknameOrEmailAddr(defaultDB, name);
   173     if (cert) {
   174         return cert;
   175     }
   177     /* Don't have a cert with name "name" in the DB. Try to
   178      * open a file with such name and get the cert from there.*/
   179     fd = PR_Open(name, PR_RDONLY, 0777); 
   180     if (!fd) {
   181 	PRErrorCode err = PR_GetError();
   182     	fprintf(stderr, "open of %s failed, %d = %s\n", 
   183 	        name, err, SECU_Strerror(err));
   184 	return cert;
   185     }
   187     rv = SECU_ReadDERFromFile(&item, fd, isAscii, PR_FALSE);
   188     PR_Close(fd);
   189     if (rv != SECSuccess) {
   190 	fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName);
   191 	return cert;
   192     }
   194     if (!item.len) { /* file was empty */
   195 	fprintf(stderr, "cert file %s was empty.\n", name);
   196 	return cert;
   197     }
   199     cert = CERT_NewTempCertificate(defaultDB, &item, 
   200                                    NULL     /* nickname */, 
   201                                    PR_FALSE /* isPerm */, 
   202 				   PR_TRUE  /* copyDER */);
   203     if (!cert) {
   204 	PRErrorCode err = PR_GetError();
   205 	fprintf(stderr, "couldn't import %s, %d = %s\n",
   206 	        name, err, SECU_Strerror(err));
   207     }
   208     PORT_Free(item.data);
   209     return cert;
   210 }
   213 #define REVCONFIG_TEST_UNDEFINED      0
   214 #define REVCONFIG_TEST_LEAF           1
   215 #define REVCONFIG_TEST_CHAIN          2
   216 #define REVCONFIG_METHOD_CRL          1
   217 #define REVCONFIG_METHOD_OCSP         2
   219 #define REVCONFIG_TEST_LEAF_STR       "leaf"
   220 #define REVCONFIG_TEST_CHAIN_STR      "chain"
   221 #define REVCONFIG_METHOD_CRL_STR      "crl"
   222 #define REVCONFIG_METHOD_OCSP_STR     "ocsp"
   224 #define REVCONFIG_TEST_TESTLOCALINFOFIRST_STR     "testLocalInfoFirst"
   225 #define REVCONFIG_TEST_REQUIREFRESHINFO_STR       "requireFreshInfo"
   226 #define REVCONFIG_METHOD_DONOTUSEMETHOD_STR       "doNotUse"
   227 #define REVCONFIG_METHOD_FORBIDNETWORKFETCHIN_STR "forbidFetching"
   228 #define REVCONFIG_METHOD_IGNOREDEFAULTSRC_STR     "ignoreDefaultSrc"
   229 #define REVCONFIG_METHOD_REQUIREINFO_STR          "requireInfo"
   230 #define REVCONFIG_METHOD_FAILIFNOINFO_STR         "failIfNoInfo" 
   232 #define REV_METHOD_INDEX_MAX  4
   234 typedef struct RevMethodsStruct {
   235     unsigned int testType;
   236     char *testTypeStr;
   237     unsigned int testFlags;
   238     char *testFlagsStr;
   239     unsigned int methodType;
   240     char *methodTypeStr;
   241     unsigned int methodFlags;
   242     char *methodFlagsStr;
   243 } RevMethods;
   245 RevMethods revMethodsData[REV_METHOD_INDEX_MAX];
   247 SECStatus
   248 parseRevMethodsAndFlags()
   249 {
   250     int i;
   251     unsigned int testType = 0;
   253     for(i = 0;i < REV_METHOD_INDEX_MAX;i++) {
   254         /* testType */
   255         if (revMethodsData[i].testTypeStr) {
   256             char *typeStr = revMethodsData[i].testTypeStr;
   258             testType = 0;
   259             if (!PORT_Strcmp(typeStr, REVCONFIG_TEST_LEAF_STR)) {
   260                 testType = REVCONFIG_TEST_LEAF;
   261             } else if (!PORT_Strcmp(typeStr, REVCONFIG_TEST_CHAIN_STR)) {
   262                 testType = REVCONFIG_TEST_CHAIN;
   263             }
   264         }
   265         if (!testType) {
   266             return SECFailure;
   267         }
   268         revMethodsData[i].testType = testType;
   269         /* testFlags */
   270         if (revMethodsData[i].testFlagsStr) {
   271             char *flagStr = revMethodsData[i].testFlagsStr;
   272             unsigned int testFlags = 0;
   274             if (PORT_Strstr(flagStr, REVCONFIG_TEST_TESTLOCALINFOFIRST_STR)) {
   275                 testFlags |= CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
   276             } 
   277             if (PORT_Strstr(flagStr, REVCONFIG_TEST_REQUIREFRESHINFO_STR)) {
   278                 testFlags |= CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
   279             }
   280             revMethodsData[i].testFlags = testFlags;
   281         }
   282         /* method type */
   283         if (revMethodsData[i].methodTypeStr) {
   284             char *methodStr = revMethodsData[i].methodTypeStr;
   285             unsigned int methodType = 0;
   287             if (!PORT_Strcmp(methodStr, REVCONFIG_METHOD_CRL_STR)) {
   288                 methodType = REVCONFIG_METHOD_CRL;
   289             } else if (!PORT_Strcmp(methodStr, REVCONFIG_METHOD_OCSP_STR)) {
   290                 methodType = REVCONFIG_METHOD_OCSP;
   291             }
   292             if (!methodType) {
   293                 return SECFailure;
   294             }
   295             revMethodsData[i].methodType = methodType;
   296         }
   297         if (!revMethodsData[i].methodType) {
   298             revMethodsData[i].testType = REVCONFIG_TEST_UNDEFINED;
   299             continue;
   300         }
   301         /* method flags */
   302         if (revMethodsData[i].methodFlagsStr) {
   303             char *flagStr = revMethodsData[i].methodFlagsStr;
   304             unsigned int methodFlags = 0;
   306             if (!PORT_Strstr(flagStr, REVCONFIG_METHOD_DONOTUSEMETHOD_STR)) {
   307                 methodFlags |= CERT_REV_M_TEST_USING_THIS_METHOD;
   308             } 
   309             if (PORT_Strstr(flagStr,
   310                             REVCONFIG_METHOD_FORBIDNETWORKFETCHIN_STR)) {
   311                 methodFlags |= CERT_REV_M_FORBID_NETWORK_FETCHING;
   312             }
   313             if (PORT_Strstr(flagStr, REVCONFIG_METHOD_IGNOREDEFAULTSRC_STR)) {
   314                 methodFlags |= CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
   315             }
   316             if (PORT_Strstr(flagStr, REVCONFIG_METHOD_REQUIREINFO_STR)) {
   317                 methodFlags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE;
   318             }
   319             if (PORT_Strstr(flagStr, REVCONFIG_METHOD_FAILIFNOINFO_STR)) {
   320                 methodFlags |= CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO;
   321             }
   322             revMethodsData[i].methodFlags = methodFlags;
   323         } else {
   324             revMethodsData[i].methodFlags |= CERT_REV_M_TEST_USING_THIS_METHOD;
   325         }
   326     }
   327     return SECSuccess;
   328 }
   330 SECStatus
   331 configureRevocationParams(CERTRevocationFlags *flags)
   332 {
   333    int i;
   334    unsigned int testType = REVCONFIG_TEST_UNDEFINED;
   335    static CERTRevocationTests *revTests = NULL;
   336    PRUint64 *revFlags;
   338    for(i = 0;i < REV_METHOD_INDEX_MAX;i++) {
   339        if (revMethodsData[i].testType == REVCONFIG_TEST_UNDEFINED) {
   340            continue;
   341        }
   342        if (revMethodsData[i].testType != testType) {
   343            testType = revMethodsData[i].testType;
   344            if (testType == REVCONFIG_TEST_CHAIN) {
   345                revTests = &flags->chainTests;
   346            } else {
   347                revTests = &flags->leafTests;
   348            }
   349            revTests->number_of_preferred_methods = 0;
   350            revTests->preferred_methods = 0;
   351            revFlags = revTests->cert_rev_flags_per_method;
   352        }
   353        /* Set the number of the methods independently to the max number of
   354         * methods. If method flags are not set it will be ignored due to
   355         * default DO_NOT_USE flag. */
   356        revTests->number_of_defined_methods = cert_revocation_method_count;
   357        revTests->cert_rev_method_independent_flags |=
   358            revMethodsData[i].testFlags;
   359        if (revMethodsData[i].methodType == REVCONFIG_METHOD_CRL) {
   360            revFlags[cert_revocation_method_crl] =
   361                revMethodsData[i].methodFlags;
   362        } else if (revMethodsData[i].methodType == REVCONFIG_METHOD_OCSP) {
   363            revFlags[cert_revocation_method_ocsp] =
   364                revMethodsData[i].methodFlags;
   365        }
   366    }
   367    return SECSuccess;
   368 }
   370 void
   371 freeRevocationMethodData()
   372 {
   373     int i = 0;
   374     for(;i < REV_METHOD_INDEX_MAX;i++) {
   375         if (revMethodsData[i].testTypeStr) {
   376             PORT_Free(revMethodsData[i].testTypeStr);
   377         }
   378         if (revMethodsData[i].testFlagsStr) {
   379             PORT_Free(revMethodsData[i].testFlagsStr);
   380         }
   381         if (revMethodsData[i].methodTypeStr) {
   382             PORT_Free(revMethodsData[i].methodTypeStr);
   383         }
   384         if (revMethodsData[i].methodFlagsStr) {
   385             PORT_Free(revMethodsData[i].methodFlagsStr);
   386         }
   387     }
   388 }
   390 PRBool
   391 isOCSPEnabled()
   392 {
   393     int i;
   395     for(i = 0;i < REV_METHOD_INDEX_MAX;i++) {
   396         if (revMethodsData[i].methodType == REVCONFIG_METHOD_OCSP) {
   397             return PR_TRUE;
   398         }
   399     }
   400     return PR_FALSE;
   401 }
   403 int
   404 main(int argc, char *argv[], char *envp[])
   405 {
   406     char *               certDir      = NULL;
   407     char *               progName     = NULL;
   408     char *               oidStr       = NULL;
   409     CERTCertificate *    cert;
   410     CERTCertificate *    firstCert    = NULL;
   411     CERTCertificate *    issuerCert   = NULL;
   412     CERTCertDBHandle *   defaultDB    = NULL;
   413     PRBool               isAscii      = PR_FALSE;
   414     PRBool               trusted      = PR_FALSE;
   415     SECStatus            secStatus;
   416     SECCertificateUsage  certUsage    = certificateUsageSSLServer;
   417     PLOptState *         optstate;
   418     PRTime               time         = 0;
   419     PLOptStatus          status;
   420     int                  usePkix      = 0;
   421     int                  rv           = 1;
   422     int                  usage;
   423     CERTVerifyLog        log;
   424     CERTCertList        *builtChain = NULL;
   425     PRBool               certFetching = PR_FALSE;
   426     int                  revDataIndex = 0;
   427     PRBool               ocsp_fetchingFailureIsAFailure = PR_TRUE;
   428     PRBool               useDefaultRevFlags = PR_TRUE;
   429     PRBool               onlyTrustAnchors = PR_TRUE;
   430     int                  vfyCounts = 1;
   432     PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
   434     progName = PL_strdup(argv[0]);
   436     optstate = PL_CreateOptState(argc, argv, "ab:c:d:efg:h:i:m:o:prs:tTu:vw:W:");
   437     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
   438 	switch(optstate->option) {
   439 	case  0  : /* positional parameter */  goto breakout;
   440 	case 'a' : isAscii  = PR_TRUE;                        break;
   441 	case 'b' : secStatus = DER_AsciiToTime(&time, optstate->value);
   442 	           if (secStatus != SECSuccess) Usage(progName); break;
   443 	case 'd' : certDir  = PL_strdup(optstate->value);     break;
   444 	case 'e' : ocsp_fetchingFailureIsAFailure = PR_FALSE;  break;
   445 	case 'f' : certFetching = PR_TRUE;                    break;
   446 	case 'g' : 
   447                    if (revMethodsData[revDataIndex].testTypeStr ||
   448                        revMethodsData[revDataIndex].methodTypeStr) {
   449                        revDataIndex += 1;
   450                        if (revDataIndex == REV_METHOD_INDEX_MAX) {
   451                            fprintf(stderr, "Invalid revocation configuration"
   452                                    "specified.\n");
   453                            secStatus = SECFailure;
   454                            break;
   455                        }
   456                    }
   457                    useDefaultRevFlags = PR_FALSE;
   458                    revMethodsData[revDataIndex].
   459                        testTypeStr = PL_strdup(optstate->value); break;
   460 	case 'h' : 
   461                    revMethodsData[revDataIndex].
   462                        testFlagsStr = PL_strdup(optstate->value);break;
   463         case 'i' : vfyCounts = PORT_Atoi(optstate->value);       break;
   464                    break;
   465 	case 'm' : 
   466                    if (revMethodsData[revDataIndex].methodTypeStr) {
   467                        revDataIndex += 1;
   468                        if (revDataIndex == REV_METHOD_INDEX_MAX) {
   469                            fprintf(stderr, "Invalid revocation configuration"
   470                                    "specified.\n");
   471                            secStatus = SECFailure;
   472                            break;
   473                        }
   474                    }
   475                    useDefaultRevFlags = PR_FALSE;
   476                    revMethodsData[revDataIndex].
   477                        methodTypeStr = PL_strdup(optstate->value); break;
   478 	case 'o' : oidStr = PL_strdup(optstate->value);       break;
   479 	case 'p' : usePkix += 1;                              break;
   480 	case 'r' : isAscii  = PR_FALSE;                       break;
   481 	case 's' : 
   482                    revMethodsData[revDataIndex].
   483                        methodFlagsStr = PL_strdup(optstate->value); break;
   484 	case 't' : trusted  = PR_TRUE;                        break;
   485 	case 'T' : onlyTrustAnchors = PR_FALSE;               break;
   486 	case 'u' : usage    = PORT_Atoi(optstate->value);
   487 	           if (usage < 0 || usage > 62) Usage(progName);
   488 		   certUsage = ((SECCertificateUsage)1) << usage; 
   489 		   if (certUsage > certificateUsageHighest) Usage(progName);
   490 		   break;
   491         case 'w':
   492                   pwdata.source = PW_PLAINTEXT;
   493                   pwdata.data = PORT_Strdup(optstate->value);
   494                   break;
   496         case 'W':
   497                   pwdata.source = PW_FROMFILE;
   498                   pwdata.data = PORT_Strdup(optstate->value);
   499                   break;
   500 	case 'v' : verbose++;                                 break;
   501 	default  : Usage(progName);                           break;
   502 	}
   503     }
   504 breakout:
   505     if (status != PL_OPT_OK)
   506 	Usage(progName);
   508     if (usePkix < 2) {
   509         if (oidStr) {
   510             fprintf(stderr, "Policy oid(-o) can be used only with"
   511                     " CERT_PKIXVerifyCert(-pp) function.\n");
   512             Usage(progName);
   513         }
   514         if (trusted) {
   515             fprintf(stderr, "Cert trust flag can be used only with"
   516                     " CERT_PKIXVerifyCert(-pp) function.\n");
   517             Usage(progName);
   518         }
   519         if (!onlyTrustAnchors) {
   520             fprintf(stderr, "Cert trust anchor exclusiveness can be"
   521                     " used only with CERT_PKIXVerifyCert(-pp)"
   522                     " function.\n");
   523         }
   524     }
   526     if (!useDefaultRevFlags && parseRevMethodsAndFlags()) {
   527         fprintf(stderr, "Invalid revocation configuration specified.\n");
   528         goto punt;
   529     }
   531     /* Set our password function callback. */
   532     PK11_SetPasswordFunc(SECU_GetModulePassword);
   534     /* Initialize the NSS libraries. */
   535     if (certDir) {
   536 	secStatus = NSS_Init(certDir);
   537     } else {
   538 	secStatus = NSS_NoDB_Init(NULL);
   540 	/* load the builtins */
   541 	SECMOD_AddNewModule("Builtins", DLL_PREFIX"nssckbi."DLL_SUFFIX, 0, 0);
   542     }
   543     if (secStatus != SECSuccess) {
   544 	exitErr("NSS_Init");
   545     }
   546     SECU_RegisterDynamicOids();
   547     if (isOCSPEnabled()) {
   548         CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
   549         CERT_DisableOCSPDefaultResponder(CERT_GetDefaultCertDB());
   550         if (!ocsp_fetchingFailureIsAFailure) {
   551             CERT_SetOCSPFailureMode(ocspMode_FailureIsNotAVerificationFailure);
   552         }
   553     }
   555     while (status == PL_OPT_OK) {
   556 	switch(optstate->option) {
   557 	default  : Usage(progName);                           break;
   558 	case 'a' : isAscii  = PR_TRUE;                        break;
   559 	case 'r' : isAscii  = PR_FALSE;                       break;
   560 	case 't' : trusted  = PR_TRUE;                       break;
   561 	case  0  : /* positional parameter */
   562             if (usePkix < 2 && trusted) {
   563                 fprintf(stderr, "Cert trust flag can be used only with"
   564                         " CERT_PKIXVerifyCert(-pp) function.\n");
   565                 Usage(progName);
   566             }
   567 	    cert = getCert(optstate->value, isAscii, progName);
   568 	    if (!cert) 
   569 	        goto punt;
   570 	    rememberCert(cert, trusted);
   571 	    if (!firstCert)
   572 	        firstCert = cert;
   573             trusted = PR_FALSE;
   574 	}
   575         status = PL_GetNextOpt(optstate);
   576     }
   577     PL_DestroyOptState(optstate);
   578     if (status == PL_OPT_BAD || !firstCert)
   579 	Usage(progName);
   581     /* Initialize log structure */
   582     log.arena = PORT_NewArena(512);
   583     log.head = log.tail = NULL;
   584     log.count = 0;
   586     do {
   587         if (usePkix < 2) {
   588             /* NOW, verify the cert chain. */
   589             if (usePkix) {
   590                 /* Use old API with libpkix validation lib */
   591                 CERT_SetUsePKIXForValidation(PR_TRUE);
   592             }
   593             if (!time)
   594                 time = PR_Now();
   596             defaultDB = CERT_GetDefaultCertDB();
   597             secStatus = CERT_VerifyCertificate(defaultDB, firstCert, 
   598                                                PR_TRUE /* check sig */,
   599                                                certUsage, 
   600                                                time,
   601                                                &pwdata, /* wincx  */
   602                                                &log, /* error log */
   603                                            NULL);/* returned usages */
   604         } else do {
   605                 static CERTValOutParam cvout[4];
   606                 static CERTValInParam cvin[7];
   607                 SECOidTag oidTag;
   608                 int inParamIndex = 0;
   609                 static PRUint64 revFlagsLeaf[2];
   610                 static PRUint64 revFlagsChain[2];
   611                 static CERTRevocationFlags rev;
   613                 if (oidStr) {
   614                     PLArenaPool *arena;
   615                     SECOidData od;
   616                     memset(&od, 0, sizeof od);
   617                     od.offset = SEC_OID_UNKNOWN;
   618                     od.desc = "User Defined Policy OID";
   619                     od.mechanism = CKM_INVALID_MECHANISM;
   620                     od.supportedExtension = INVALID_CERT_EXTENSION;
   622                     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   623                     if ( !arena ) {
   624                         fprintf(stderr, "out of memory");
   625                         goto punt;
   626                     }
   628                     secStatus = SEC_StringToOID(arena, &od.oid, oidStr, 0);
   629                     if (secStatus != SECSuccess) {
   630                         PORT_FreeArena(arena, PR_FALSE);
   631                         fprintf(stderr, "Can not encode oid: %s(%s)\n", oidStr,
   632                                 SECU_Strerror(PORT_GetError()));
   633                         break;
   634                     }
   636                     oidTag = SECOID_AddEntry(&od);
   637                     PORT_FreeArena(arena, PR_FALSE);
   638                     if (oidTag == SEC_OID_UNKNOWN) {
   639                         fprintf(stderr, "Can not add new oid to the dynamic "
   640                                 "table: %s\n", oidStr);
   641                         secStatus = SECFailure;
   642                         break;
   643                     }
   645                     cvin[inParamIndex].type = cert_pi_policyOID;
   646                     cvin[inParamIndex].value.arraySize = 1;
   647                     cvin[inParamIndex].value.array.oids = &oidTag;
   649                     inParamIndex++;
   650                 }
   652                 if (trustedCertList) {
   653                     cvin[inParamIndex].type = cert_pi_trustAnchors;
   654                     cvin[inParamIndex].value.pointer.chain = trustedCertList;
   656                     inParamIndex++;
   657                 }
   659                 cvin[inParamIndex].type = cert_pi_useAIACertFetch;
   660                 cvin[inParamIndex].value.scalar.b = certFetching;
   661                 inParamIndex++;
   663                 rev.leafTests.cert_rev_flags_per_method = revFlagsLeaf;
   664                 rev.chainTests.cert_rev_flags_per_method = revFlagsChain;
   665                 secStatus = configureRevocationParams(&rev);
   666                 if (secStatus) {
   667                     fprintf(stderr, "Can not config revocation parameters ");
   668                     break;
   669                 }
   671                 cvin[inParamIndex].type = cert_pi_revocationFlags;
   672                 cvin[inParamIndex].value.pointer.revocation = &rev;
   673                 inParamIndex++;
   675                 if (time) {
   676                     cvin[inParamIndex].type = cert_pi_date;
   677                     cvin[inParamIndex].value.scalar.time = time;
   678                     inParamIndex++;
   679                 }
   681                 if (!onlyTrustAnchors) {
   682                     cvin[inParamIndex].type = cert_pi_useOnlyTrustAnchors;
   683                     cvin[inParamIndex].value.scalar.b = onlyTrustAnchors;
   684                     inParamIndex++;
   685                 }
   687                 cvin[inParamIndex].type = cert_pi_end;
   689                 cvout[0].type = cert_po_trustAnchor;
   690                 cvout[0].value.pointer.cert = NULL;
   691                 cvout[1].type = cert_po_certList;
   692                 cvout[1].value.pointer.chain = NULL;
   694                 /* setting pointer to CERTVerifyLog. Initialized structure
   695                  * will be used CERT_PKIXVerifyCert */
   696                 cvout[2].type = cert_po_errorLog;
   697                 cvout[2].value.pointer.log = &log;
   699                 cvout[3].type = cert_po_end;
   701                 secStatus = CERT_PKIXVerifyCert(firstCert, certUsage,
   702                                                 cvin, cvout, &pwdata);
   703                 if (secStatus != SECSuccess) {
   704                     break;
   705                 }
   706                 issuerCert = cvout[0].value.pointer.cert;
   707                 builtChain = cvout[1].value.pointer.chain;
   708             } while (0);
   710         /* Display validation results */
   711         if (secStatus != SECSuccess || log.count > 0) {
   712             CERTVerifyLogNode *node = NULL;
   713             fprintf(stderr, "Chain is bad!\n");
   715             SECU_displayVerifyLog(stderr, &log, verbose); 
   716             /* Have cert refs in the log only in case of failure.
   717              * Destroy them. */
   718             for (node = log.head; node; node = node->next) {
   719                 if (node->cert)
   720                     CERT_DestroyCertificate(node->cert);
   721             }
   722             log.head = log.tail = NULL;
   723             log.count = 0;
   724             rv = 1;
   725         } else {
   726             fprintf(stderr, "Chain is good!\n");
   727             if (issuerCert) {
   728                 if (verbose > 1) {
   729                     rv = SEC_PrintCertificateAndTrust(issuerCert, "Root Certificate",
   730                                                       NULL);
   731                     if (rv != SECSuccess) {
   732                         SECU_PrintError(progName, "problem printing certificate");
   733                     }
   734                 } else if (verbose > 0) {
   735                     SECU_PrintName(stdout, &issuerCert->subject, "Root "
   736                                    "Certificate Subject:", 0);
   737                 }
   738                 CERT_DestroyCertificate(issuerCert);
   739             }
   740             if (builtChain) {
   741                 CERTCertListNode *node;
   742                 int count = 0;
   743                 char buff[256];
   745                 if (verbose) { 
   746                     for(node = CERT_LIST_HEAD(builtChain); !CERT_LIST_END(node, builtChain);
   747                         node = CERT_LIST_NEXT(node), count++ ) {
   748                         sprintf(buff, "Certificate %d Subject", count + 1);
   749                         SECU_PrintName(stdout, &node->cert->subject, buff, 0);
   750                     }
   751                 }
   752                 CERT_DestroyCertList(builtChain);
   753             }
   754             rv = 0;
   755         }
   756     } while (--vfyCounts > 0);
   758     /* Need to destroy CERTVerifyLog arena at the end */
   759     PORT_FreeArena(log.arena, PR_FALSE);
   761 punt:
   762     forgetCerts();
   763     if (NSS_Shutdown() != SECSuccess) {
   764 	SECU_PrintError(progName, "NSS_Shutdown");
   765 	rv = 1;
   766     }
   767     PORT_Free(progName);
   768     PORT_Free(certDir);
   769     PORT_Free(oidStr);
   770     freeRevocationMethodData();
   771     if (pwdata.data) {
   772         PORT_Free(pwdata.data);
   773     }
   774     PL_ArenaFinish();
   775     PR_Cleanup();
   776     return rv;
   777 }

mercurial