Пример #1
0
nsresult
nsNSSCertificateDB::ImportValidCACerts(int numCACerts, SECItem *CACerts, nsIInterfaceRequestor *ctx)
{
  CERTCertList *certList = NULL;
  SECItem **rawArray;

  // build a CertList for filtering
  certList = CERT_NewCertList();
  if (certList == NULL) {
    return NS_ERROR_FAILURE;
  }

  CERTCertListCleaner listCleaner(certList);

  // get all certs into temp store
  SECStatus srv = SECFailure;
  CERTCertificate **certArray = NULL;

  rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numCACerts);
  if ( !rawArray ) {
    return NS_ERROR_FAILURE;
  }

  for (int i=0; i < numCACerts; i++) {
    rawArray[i] = &CACerts[i];
  }

  srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, numCACerts, rawArray, 
                         &certArray, PR_FALSE, PR_TRUE, NULL);

  PORT_Free(rawArray);
  rawArray = NULL;

  if (srv != SECSuccess) {
    return NS_ERROR_FAILURE;
  }

  for (int i2=0; i2 < numCACerts; i2++) {
    CERTCertificate *cacert = certArray[i2];
    if (cacert)
      cacert = CERT_DupCertificate(cacert);
    if (cacert)
      CERT_AddCertToListTail(certList, cacert);
  }

  CERT_DestroyCertArray(certArray, numCACerts);

  return ImportValidCACertsInList(certList, ctx);
}
Пример #2
0
/*
 * Does a temporary import, which decodes the entire chain and allows
 * CERT_VerifyCert to verify the chain when passed the end certificate
 */
static int crt_tmp_import(CERTCertDBHandle *handle, CERTCertificate ***chain,
						      SECItem *ders,
						      int der_cnt)
{
	if (der_cnt < 1) {
		DBG(DBG_X509, DBG_log("nothing to decode"));
		return 0;
	}

	SECItem **derlist = PORT_Alloc(sizeof(SECItem *) * der_cnt);

	int i;
	int nonroot = 0;

	for (i = 0; i < der_cnt; i++) {
		if (!CERT_IsRootDERCert(&ders[i]))
			derlist[nonroot++] = &ders[i];
	}

	int fin_count = 0;

	if (nonroot < 1) {
		DBG(DBG_X509, DBG_log("nothing to decode"));
	} else {
		SECStatus rv = CERT_ImportCerts(handle, 0, nonroot, derlist,
						chain, PR_FALSE, PR_FALSE, NULL);
		if (rv != SECSuccess || *chain == NULL) {
			DBG(DBG_X509, DBG_log("NSS error decoding certs: %s",
					       nss_err_str(PORT_GetError())));
		} else {
			CERTCertificate **cc;

			for (cc = *chain; fin_count < nonroot && *cc != NULL; cc++) {
				DBG(DBG_X509, DBG_log("decoded %s",
					(*cc)->subjectName));
				fin_count++;
			}
		}
	}

	PORT_Free(derlist);
	return fin_count;
}
Пример #3
0
OSStatus
SecCmsSignedDataImportCerts(SecCmsSignedDataRef sigd, SecKeychainRef keychain,
				SECCertUsage certusage, Boolean keepcerts)
{
    int certcount;
    OSStatus rv;
    int i;

    certcount = SecCmsArrayCount((void **)sigd->rawCerts);

    rv = CERT_ImportCerts(keychain, certusage, certcount, sigd->rawCerts, NULL,
			  keepcerts, PR_FALSE, NULL);

    /* XXX CRL handling */

    if (sigd->signerInfos != NULL) {
	/* fill in all signerinfo's certs */
	for (i = 0; sigd->signerInfos[i] != NULL; i++)
	    (void)SecCmsSignerInfoGetSigningCertificate(sigd->signerInfos[i], keychain);
    }

    return rv;
}
Пример #4
0
SECStatus
NSS_CMSSignedData_ImportCerts(NSSCMSSignedData *sigd, CERTCertDBHandle *certdb,
                              SECCertUsage certusage, PRBool keepcerts)
{
    int certcount;
    CERTCertificate **certArray = NULL;
    CERTCertList *certList = NULL;
    CERTCertListNode *node;
    SECStatus rv;
    SECItem **rawArray;
    int i;
    PRTime now;

    if (!sigd) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    certcount = NSS_CMSArray_Count((void **)sigd->rawCerts);

    /* get the certs in the temp DB */
    rv = CERT_ImportCerts(certdb, certusage, certcount, sigd->rawCerts,
                          &certArray, PR_FALSE, PR_FALSE, NULL);
    if (rv != SECSuccess) {
        goto loser;
    }

    /* save the certs so they don't get destroyed */
    for (i = 0; i < certcount; i++) {
        CERTCertificate *cert = certArray[i];
        if (cert)
            NSS_CMSSignedData_AddTempCertificate(sigd, cert);
    }

    if (!keepcerts) {
        goto done;
    }

    /* build a CertList for filtering */
    certList = CERT_NewCertList();
    if (certList == NULL) {
        rv = SECFailure;
        goto loser;
    }
    for (i = 0; i < certcount; i++) {
        CERTCertificate *cert = certArray[i];
        if (cert)
            cert = CERT_DupCertificate(cert);
        if (cert)
            CERT_AddCertToListTail(certList, cert);
    }

    /* filter out the certs we don't want */
    rv = CERT_FilterCertListByUsage(certList, certusage, PR_FALSE);
    if (rv != SECSuccess) {
        goto loser;
    }

    /* go down the remaining list of certs and verify that they have
     * valid chains, then import them.
     */
    now = PR_Now();
    for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
         node = CERT_LIST_NEXT(node)) {
        CERTCertificateList *certChain;

        if (CERT_VerifyCert(certdb, node->cert,
                            PR_TRUE, certusage, now, NULL, NULL) != SECSuccess) {
            continue;
        }

        certChain = CERT_CertChainFromCert(node->cert, certusage, PR_FALSE);
        if (!certChain) {
            continue;
        }

        /*
         * CertChain returns an array of SECItems, import expects an array of
         * SECItem pointers. Create the SECItem Pointers from the array of
         * SECItems.
         */
        rawArray = (SECItem **)PORT_Alloc(certChain->len * sizeof(SECItem *));
        if (!rawArray) {
            CERT_DestroyCertificateList(certChain);
            continue;
        }
        for (i = 0; i < certChain->len; i++) {
            rawArray[i] = &certChain->certs[i];
        }
        (void)CERT_ImportCerts(certdb, certusage, certChain->len,
                               rawArray, NULL, keepcerts, PR_FALSE, NULL);
        PORT_Free(rawArray);
        CERT_DestroyCertificateList(certChain);
    }

    rv = SECSuccess;

/* XXX CRL handling */

done:
    if (sigd->signerInfos != NULL) {
        /* fill in all signerinfo's certs */
        for (i = 0; sigd->signerInfos[i] != NULL; i++)
            (void)NSS_CMSSignerInfo_GetSigningCertificate(
                sigd->signerInfos[i], certdb);
    }

loser:
    /* now free everything */
    if (certArray) {
        CERT_DestroyCertArray(certArray, certcount);
    }
    if (certList) {
        CERT_DestroyCertList(certList);
    }

    return rv;
}
Пример #5
0
nsresult
nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx)
{
  SECItem **rawArray;

  /* filter out the certs we don't want */
  SECStatus srv = CERT_FilterCertListByUsage(certList, certUsageAnyCA, PR_TRUE);
  if (srv != SECSuccess) {
    return NS_ERROR_FAILURE;
  }

  /* go down the remaining list of certs and verify that they have
   * valid chains, if yes, then import.
   */
  PRTime now = PR_Now();
  CERTCertListNode *node;
  for (node = CERT_LIST_HEAD(certList);
       !CERT_LIST_END(node,certList);
       node = CERT_LIST_NEXT(node)) {

    bool alert_and_skip = false;

    if (CERT_VerifyCert(CERT_GetDefaultCertDB(), node->cert, 
        PR_TRUE, certUsageVerifyCA, now, ctx, NULL) != SECSuccess) {
      alert_and_skip = true;
    }

    CERTCertificateList *certChain = nsnull;
    CERTCertificateListCleaner chainCleaner(certChain);

    if (!alert_and_skip) {    
      certChain = CERT_CertChainFromCert(node->cert, certUsageAnyCA, PR_FALSE);
      if (!certChain) {
        alert_and_skip = true;
      }
    }

    if (alert_and_skip) {    
      nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(node->cert);
      DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
      continue;
    }

    /*
     * CertChain returns an array of SECItems, import expects an array of
     * SECItem pointers. Create the SECItem Pointers from the array of
     * SECItems.
     */
    rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *));
    if (!rawArray) {
      continue;
    }
    for (int i=0; i < certChain->len; i++) {
      rawArray[i] = &certChain->certs[i];
    }
    CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, certChain->len, 
                            rawArray,  NULL, PR_TRUE, PR_TRUE, NULL);

    PORT_Free(rawArray);
  }
  
  return NS_OK;
}
Пример #6
0
NS_IMETHODIMP
nsNSSCertificateDB::ImportServerCertificate(PRUint8 * data, PRUint32 length, 
                                            nsIInterfaceRequestor *ctx)

{
  nsNSSShutDownPreventionLock locker;
  SECStatus srv = SECFailure;
  nsresult nsrv = NS_OK;
  CERTCertificate * cert;
  SECItem **rawCerts = nsnull;
  int numcerts;
  int i;
  nsNSSCertTrust trust;
  char *serverNickname = nsnull;
 
  PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  if (!arena)
    return NS_ERROR_OUT_OF_MEMORY;

  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
  if (!certCollection) {
    PORT_FreeArena(arena, PR_FALSE);
    return NS_ERROR_FAILURE;
  }
  cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection->rawCerts,
                          (char *)NULL, PR_FALSE, PR_TRUE);
  if (!cert) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }
  numcerts = certCollection->numcerts;
  rawCerts = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
  if ( !rawCerts ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  for ( i = 0; i < numcerts; i++ ) {
    rawCerts[i] = &certCollection->rawCerts[i];
  }

  serverNickname = nsNSSCertificate::defaultServerNickname(cert);
  srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageSSLServer,
             numcerts, rawCerts, NULL, PR_TRUE, PR_FALSE,
             serverNickname);
  PR_FREEIF(serverNickname);
  if ( srv != SECSuccess ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  trust.SetValidServerPeer();
  srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust.GetTrust());
  if ( srv != SECSuccess ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }
loser:
  PORT_Free(rawCerts);
  if (cert)
    CERT_DestroyCertificate(cert);
  if (arena) 
    PORT_FreeArena(arena, PR_TRUE);
  return nsrv;
}
Пример #7
0
/*
 *  [noscript] void importEmailCertificates(in charPtr data, in unsigned long length,
 *                                     in nsIInterfaceRequestor ctx);
 */
NS_IMETHODIMP
nsNSSCertificateDB::ImportEmailCertificate(PRUint8 * data, PRUint32 length, 
                                       nsIInterfaceRequestor *ctx)

{
  nsNSSShutDownPreventionLock locker;
  SECStatus srv = SECFailure;
  nsresult nsrv = NS_OK;
  CERTCertDBHandle *certdb;
  CERTCertificate **certArray = NULL;
  CERTCertList *certList = NULL;
  CERTCertListNode *node;
  PRTime now;
  SECCertUsage certusage;
  SECItem **rawArray;
  int numcerts;
  int i;
 
  PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  if (!arena)
    return NS_ERROR_OUT_OF_MEMORY;

  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
  if (!certCollection) {
    PORT_FreeArena(arena, PR_FALSE);
    return NS_ERROR_FAILURE;
  }

  certdb = CERT_GetDefaultCertDB();
  certusage = certUsageEmailRecipient;

  numcerts = certCollection->numcerts;

  rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
  if ( !rawArray ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  for (i=0; i < numcerts; i++) {
    rawArray[i] = &certCollection->rawCerts[i];
  }

  srv = CERT_ImportCerts(certdb, certusage, numcerts, rawArray, 
                         &certArray, PR_FALSE, PR_FALSE, NULL);

  PORT_Free(rawArray);
  rawArray = NULL;

  if (srv != SECSuccess) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  // build a CertList for filtering
  certList = CERT_NewCertList();
  if (certList == NULL) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }
  for (i=0; i < numcerts; i++) {
    CERTCertificate *cert = certArray[i];
    if (cert)
      cert = CERT_DupCertificate(cert);
    if (cert)
      CERT_AddCertToListTail(certList, cert);
  }

  /* go down the remaining list of certs and verify that they have
   * valid chains, then import them.
   */
  now = PR_Now();
  for (node = CERT_LIST_HEAD(certList);
       !CERT_LIST_END(node,certList);
       node = CERT_LIST_NEXT(node)) {

    bool alert_and_skip = false;

    if (!node->cert) {
      continue;
    }

    if (CERT_VerifyCert(certdb, node->cert, 
        PR_TRUE, certusage, now, ctx, NULL) != SECSuccess) {
      alert_and_skip = true;
    }

    CERTCertificateList *certChain = nsnull;
    CERTCertificateListCleaner chainCleaner(certChain);

    if (!alert_and_skip) {
      certChain = CERT_CertChainFromCert(node->cert, certusage, PR_FALSE);
      if (!certChain) {
        alert_and_skip = true;
      }
    }

    if (alert_and_skip) {    
      nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(node->cert);
      DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
      continue;
    }

    /*
     * CertChain returns an array of SECItems, import expects an array of
     * SECItem pointers. Create the SECItem Pointers from the array of
     * SECItems.
     */
    rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *));
    if (!rawArray) {
      continue;
    }
    for (i=0; i < certChain->len; i++) {
      rawArray[i] = &certChain->certs[i];
    }
    CERT_ImportCerts(certdb, certusage, certChain->len, 
                            rawArray,  NULL, PR_TRUE, PR_FALSE, NULL);

    CERT_SaveSMimeProfile(node->cert, NULL, NULL);

    PORT_Free(rawArray);
  }

loser:
  if (certArray) {
    CERT_DestroyCertArray(certArray, numcerts);
  }
  if (certList) {
    CERT_DestroyCertList(certList);
  }
  if (arena) 
    PORT_FreeArena(arena, PR_TRUE);
  return nsrv;
}
Пример #8
0
int main(int argc, char *argv[])
{
	int opt;
	long fin = 0;
	int use_pkix = 0;
	SECStatus rv;
	char pbuf[1024];
	PRBool crlcheck = PR_FALSE;
	PRBool ocspcheck = PR_FALSE;
	PRBool strict = PR_FALSE;
	CERTCertDBHandle *handle = NULL;
	CERTCertificate **certout = NULL;
	CERTVerifyLog vfy_log;
	CERTVerifyLog vfy_log2;
	CERTVerifyLog *cur_log;
	CERTValOutParam *pkixout = NULL;

	SECItem c1;
	SECItem c2;
	SECItem *certs[2];
	certs[0] = &c1;
	certs[1] = &c2;

	int numcerts = 0;
	while ((opt = getopt(argc, argv, "u:d:e:pn:s:coSr")) != -1) {
		switch(opt) {
			/* usage type */
		case 'u':
			set_usage(optarg);
			break;
		case 'd':
			db_dir = optarg;
			break;
		case 's':
			sub_file = optarg;
			break;
		case 'c':
			crlcheck = PR_TRUE;
			break;
		case 'o':
			ocspcheck = PR_TRUE;
			break;
		case 'S':
			strict = PR_TRUE;
			break;
		case 'e':
			end_file = optarg;
			break;
		case 'p':
			use_pkix = 1;
			break;
		case 'n':
			rightca_nick = optarg;
			break;
		case 'r':
			retry_verify = PR_TRUE;
			break;
		default:
			print_usage();
			break;
		}
	}

	if (db_dir == NULL)
		db_dir = "testfiles/";
	if (end_file == NULL)
		end_file = "testfiles/end.pem";

	get_file(certs[numcerts++], end_file);

	if (sub_file != NULL) {
		get_file(certs[numcerts++], sub_file);
	}

	snprintf(pbuf, sizeof(pbuf), "sql:%s", db_dir);
	if (NSS_Initialize(pbuf, "", "", "secmod.db", 0x1) != SECSuccess) {
		printf("NSS_Initialize failed %d\n", PORT_GetError());
		exit(-1);
	}

	if ((handle = CERT_GetDefaultCertDB()) == NULL) {
		printf("NULL handle\n");
		exit(-1);
	}
	if (ocspcheck) {
		CERT_EnableOCSPChecking(handle);
		CERT_DisableOCSPDefaultResponder(handle);
		if (strict)
			CERT_SetOCSPFailureMode(ocspMode_FailureIsNotAVerificationFailure);
	}

	rv = CERT_ImportCerts(handle, 0, numcerts, certs, &certout, PR_FALSE,
							 PR_FALSE, NULL);
	if (rv != SECSuccess) {
		printf("CERT_ImportCerts failed %d\n", PORT_GetError());
		exit(-1);
	}
	vfy_log.count = 0;
	vfy_log.head = NULL;
	vfy_log.tail = NULL;
	vfy_log.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);

	vfy_log2.count = 0;
	vfy_log2.head = NULL;
	vfy_log2.tail = NULL;
	vfy_log2.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);

	if (use_pkix) {
		int in_idx = 0;
		CERTValInParam cvin[7];
		CERTValOutParam cvout[3];
		CERTCertList *trustcl = NULL;
		CERTRevocationFlags rev;
		PRUint64 revFlagsLeaf[2] = { 0, 0 };
		PRUint64 revFlagsChain[2] = { 0, 0 };

		zero(&cvin);	/* ??? is this reasonable? */
		zero(&cvout);	/* ??? is this reasonable? */
		zero(&rev);	/* ??? is this reasonable? */

		if (rightca_nick == NULL)
			rightca_nick = "root";

		if ((trustcl = get_trust_certlist(handle, rightca_nick)) == NULL) {
			printf("Couldn't find trust anchor\n");
			exit(-1);
		}

		cvin[in_idx].type = cert_pi_useAIACertFetch;
		cvin[in_idx++].value.scalar.b = PR_TRUE;
		cvin[in_idx].type = cert_pi_revocationFlags;
		cvin[in_idx++].value.pointer.revocation = &rev;
		cvin[in_idx].type = cert_pi_trustAnchors;
		cvin[in_idx++].value.pointer.chain = trustcl;
		cvin[in_idx].type = cert_pi_useOnlyTrustAnchors;
		cvin[in_idx++].value.scalar.b = PR_TRUE;

		set_rev_per_meth(&rev, revFlagsLeaf, revFlagsChain);
		set_rev_params(&rev, crlcheck, ocspcheck, strict);
		cvin[in_idx].type = cert_pi_end;

		cvout[0].type = cert_po_errorLog;
		cvout[0].value.pointer.log = &vfy_log;
		cur_log = &vfy_log;
		cvout[1].type = cert_po_certList;
		cvout[1].value.pointer.chain = NULL;
		cvout[2].type = cert_po_end;
		pkixout = &cvout[0];

pkixredo:
		rv = CERT_PKIXVerifyCert(*certout, pkixusage, cvin, cvout,
				NULL);

		//CERT_DestroyCertList(trustcl);

	} else {
		cur_log = &vfy_log;
vfyredo:
		rv = CERT_VerifyCert(handle, *certout, PR_TRUE, usage, PR_Now(),
								       NULL,
								       cur_log);
	}

	if (rv != SECSuccess || cur_log->count > 0) {
		if (cur_log->count > 0 && cur_log->head != NULL) {
			fin = err_stat(cur_log->head);
		} else {
			fin = PORT_GetError();
		}
		if (fin == SEC_ERROR_INADEQUATE_KEY_USAGE) {
			printf("SEC_ERROR_INADEQUATE_KEY_USAGE : Certificate key usage inadequate for attempted operation.\n"
				);
		} else if (fin == SEC_ERROR_INADEQUATE_CERT_TYPE) {
			printf("SEC_ERROR_INADEQUATE_CERT_TYPE : Certificate type not approved for application.\n"
				);
		} else {
			printf("OTHER : %ld", fin);
		}
	}
	if ((fin == SEC_ERROR_INADEQUATE_CERT_TYPE ||
			fin == SEC_ERROR_INADEQUATE_KEY_USAGE) &&
					 retry_verify && !retried) {
		printf("Retrying verification\n");
		fin = 0;
		retried = PR_TRUE;
		if (use_pkix) {
			pkixout[0].value.pointer.log = &vfy_log2;
			cur_log = &vfy_log2;
			pkixout[1].value.pointer.chain = NULL;
			if (pkixusage == certificateUsageSSLClient) {
				pkixusage = certificateUsageSSLServer;
			} else {
				pkixusage = certificateUsageSSLClient;
			}
			goto pkixredo;
		} else {
			if (usage == certUsageSSLClient) {
				usage = certUsageSSLServer;
			} else {
				usage = certUsageSSLClient;
			}
			goto vfyredo;
		}
	}

	PORT_FreeArena(vfy_log.arena, PR_FALSE);
	PORT_FreeArena(vfy_log2.arena, PR_FALSE);
	NSS_Shutdown();
	exit(fin == 0 ? 0 : 1);
}