Пример #1
0
NS_IMETHODIMP
nsNSSCertificateDB::FindCertByEmailAddress(nsISupports *aToken, const char *aEmailAddress, nsIX509Cert **_retval)
{
  nsNSSShutDownPreventionLock locker;
  CERTCertificate *any_cert = CERT_FindCertByNicknameOrEmailAddr(CERT_GetDefaultCertDB(), (char*)aEmailAddress);
  if (!any_cert)
    return NS_ERROR_FAILURE;

  CERTCertificateCleaner certCleaner(any_cert);
    
  // any_cert now contains a cert with the right subject, but it might not have the correct usage
  CERTCertList *certlist = CERT_CreateSubjectCertList(
    nsnull, CERT_GetDefaultCertDB(), &any_cert->derSubject, PR_Now(), PR_TRUE);
  if (!certlist)
    return NS_ERROR_FAILURE;  

  CERTCertListCleaner listCleaner(certlist);

  if (SECSuccess != CERT_FilterCertListByUsage(certlist, certUsageEmailRecipient, PR_FALSE))
    return NS_ERROR_FAILURE;
  
  if (CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist))
    return NS_ERROR_FAILURE;
  
  nsNSSCertificate *nssCert = new nsNSSCertificate(CERT_LIST_HEAD(certlist)->cert);
  if (!nssCert)
    return NS_ERROR_OUT_OF_MEMORY;

  NS_ADDREF(nssCert);
  *_retval = static_cast<nsIX509Cert*>(nssCert);
  return NS_OK;
}
Пример #2
0
CERTCertificate *
CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID)
{
    CERTCertList *list;
    CERTCertificate *cert = NULL;
    CERTCertListNode *node, *head;

    list = CERT_CreateSubjectCertList(NULL, handle, name, 0, PR_FALSE);
    if (list == NULL)
        return NULL;

    node = head = CERT_LIST_HEAD(list);
    if (head) {
        do {
            if (node->cert &&
                SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID)) {
                cert = CERT_DupCertificate(node->cert);
                goto done;
            }
            node = CERT_LIST_NEXT(node);
        } while (node && head != node);
    }
    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
done:
    if (list) {
        CERT_DestroyCertList(list);
    }
    return cert;
}
SECStatus
NSSCertDBTrustDomain::FindPotentialIssuers(
  const SECItem* encodedIssuerName, PRTime time,
  /*out*/ mozilla::pkix::ScopedCERTCertList& results)
{
  // TODO: normalize encodedIssuerName
  // TODO: NSS seems to be ambiguous between "no potential issuers found" and
  // "there was an error trying to retrieve the potential issuers."
  results = CERT_CreateSubjectCertList(nullptr, CERT_GetDefaultCertDB(),
                                       encodedIssuerName, time, true);
  return SECSuccess;
}
Пример #4
0
SECStatus
AppTrustDomain::FindPotentialIssuers(const SECItem* encodedIssuerName,
                                     PRTime time,
                             /*out*/ mozilla::pkix::ScopedCERTCertList& results)
{
  MOZ_ASSERT(mTrustedRoot);
  if (!mTrustedRoot) {
    PR_SetError(PR_INVALID_STATE_ERROR, 0);
    return SECFailure;
  }

  results = CERT_CreateSubjectCertList(nullptr, CERT_GetDefaultCertDB(),
                                       encodedIssuerName, time, true);
  return SECSuccess;
}
Пример #5
0
Result
AppTrustDomain::FindIssuer(Input encodedIssuerName, IssuerChecker& checker,
                           Time)

{
  MOZ_ASSERT(mTrustedRoot);
  if (!mTrustedRoot) {
    return Result::FATAL_ERROR_INVALID_STATE;
  }

  // TODO(bug 1035418): If/when mozilla::pkix relaxes the restriction that
  // FindIssuer must only pass certificates with a matching subject name to
  // checker.Check, we can stop using CERT_CreateSubjectCertList and instead
  // use logic like this:
  //
  // 1. First, try the trusted trust anchor.
  // 2. Secondly, iterate through the certificates that were stored in the CMS
  //    message, passing each one to checker.Check.
  SECItem encodedIssuerNameSECItem =
    UnsafeMapInputToSECItem(encodedIssuerName);
  UniqueCERTCertList
    candidates(CERT_CreateSubjectCertList(nullptr, CERT_GetDefaultCertDB(),
                                          &encodedIssuerNameSECItem, 0,
                                          false));
  if (candidates) {
    for (CERTCertListNode* n = CERT_LIST_HEAD(candidates);
         !CERT_LIST_END(n, candidates); n = CERT_LIST_NEXT(n)) {
      Input certDER;
      Result rv = certDER.Init(n->cert->derCert.data, n->cert->derCert.len);
      if (rv != Success) {
        continue; // probably too big
      }

      bool keepGoing;
      rv = checker.Check(certDER, nullptr/*additionalNameConstraints*/,
                         keepGoing);
      if (rv != Success) {
        return rv;
      }
      if (!keepGoing) {
        break;
      }
    }
  }

  return Success;
}
SECStatus
NSSCertDBTrustDomain::FindPotentialIssuers(
  const SECItem* encodedIssuerName, PRTime time,
  /*out*/ insanity::pkix::ScopedCERTCertList& results)
{
  // TODO: normalize encodedIssuerName
  // TODO: NSS seems to be ambiguous between "no potential issuers found" and
  // "there was an error trying to retrieve the potential issuers."
  results = CERT_CreateSubjectCertList(nullptr, CERT_GetDefaultCertDB(),
                                       encodedIssuerName, time, true);
  if (!results) {
    // NSS sometimes returns this unhelpful error code upon failing to find any
    // candidate certificates.
    if (PR_GetError() == SEC_ERROR_BAD_DATABASE) {
      PR_SetError(SEC_ERROR_UNKNOWN_ISSUER, 0);
    }
    return SECFailure;
  }

  return SECSuccess;
}
Пример #7
0
SECStatus
AppTrustDomain::FindPotentialIssuers(const SECItem* encodedIssuerName,
                                     PRTime time,
                                     /*out*/ insanity::pkix::ScopedCERTCertList& results)
{
    MOZ_ASSERT(mTrustedRoot);
    if (!mTrustedRoot) {
        PR_SetError(PR_INVALID_STATE_ERROR, 0);
        return SECFailure;
    }

    results = CERT_CreateSubjectCertList(nullptr, CERT_GetDefaultCertDB(),
                                         encodedIssuerName, time, true);
    if (!results) {
        // NSS sometimes returns this unhelpful error code upon failing to find any
        // candidate certificates.
        if (PR_GetError() == SEC_ERROR_BAD_DATABASE) {
            PR_SetError(SEC_ERROR_UNKNOWN_ISSUER, 0);
        }
        return SECFailure;
    }

    return SECSuccess;
}
Пример #8
0
int
__pmSecureServerInit(void)
{
    const PRUint16 *cipher;
    SECStatus secsts;
    int pathSpecified;
    int sts = 0;

    PM_INIT_LOCKS();
    PM_LOCK(secureserver_lock);

    /* Only attempt this once. */
    if (secure_server.initialized)
	goto done;
    secure_server.initialized = 1;

    if (PR_Initialized() != PR_TRUE)
	PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);

    /* Configure optional (cmdline) password file in case DB locked */
    PK11_SetPasswordFunc(certificate_database_password);

    /*
     * Configure location of the NSS database with a sane default.
     * For servers, we default to the shared (sql) system-wide database.
     * If command line db specified, pass it directly through - allowing
     * any old database format, at the users discretion.
     */
    if (!secure_server.database_path[0]) {
	const char *path;
	pathSpecified = 0;
	path = serverdb(secure_server.database_path, MAXPATHLEN, "sql:");

	/* this is the default case on some platforms, so no log spam */
	if (access(path, R_OK|X_OK) < 0) {
	    if (pmDebugOptions.context)
		pmNotifyErr(LOG_INFO,
			      "Cannot access system security database: %s",
			      secure_server.database_path);
	    sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	    secure_server.init_failed = 1;
	    goto done;
	}
    }
    else
	pathSpecified = 1;

    /*
     * pmproxy acts as both a client and server. Since the
     * server init path happens first, the db previously
     * got opened readonly.  Instead try to open RW.
     * Fallback if there is an error.
     */

    secsts = NSS_InitReadWrite(secure_server.database_path);

    if( secsts != SECSuccess )
    	secsts = NSS_Init(secure_server.database_path);

    if (secsts != SECSuccess && !pathSpecified) {
	/* fallback, older versions of NSS do not support sql: */
	serverdb(secure_server.database_path, MAXPATHLEN, "");
	secsts = NSS_Init(secure_server.database_path);
    }

    if (secsts != SECSuccess) {
	pmNotifyErr(LOG_ERR, "Cannot setup certificate DB (%s): %s",
			secure_server.database_path,
			pmErrStr(__pmSecureSocketsError(PR_GetError())));
	sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	secure_server.init_failed = 1;
	goto done;
    }

    /* Some NSS versions don't do this correctly in NSS_SetDomesticPolicy. */
    for (cipher = SSL_GetImplementedCiphers(); *cipher != 0; ++cipher)
	SSL_CipherPolicySet(*cipher, SSL_ALLOWED);

    /* Configure SSL session cache for multi-process server, using defaults */
    secsts = SSL_ConfigMPServerSIDCache(1, 0, 0, NULL);
    if (secsts != SECSuccess) {
	pmNotifyErr(LOG_ERR, "Unable to configure SSL session ID cache: %s",
		pmErrStr(__pmSecureSocketsError(PR_GetError())));
	sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	secure_server.init_failed = 1;
	goto done;
    } else {
	secure_server.ssl_session_cache_setup = 1;
    }

    /*
     * Iterate over any/all PCP Collector nickname certificates,
     * seeking one valid certificate.  No-such-nickname is not an
     * error (not configured by admin at all) but anything else is.
     */
    CERTCertList *certlist;
    CERTCertDBHandle *nssdb = CERT_GetDefaultCertDB();
    CERTCertificate *dbcert = PK11_FindCertFromNickname(secure_server.cert_nickname, NULL);

    if (dbcert) {
	PRTime now = PR_Now();
	SECItem *name = &dbcert->derSubject;
	CERTCertListNode *node;

	certlist = CERT_CreateSubjectCertList(NULL, nssdb, name, now, PR_FALSE);
	if (certlist) {
	    for (node = CERT_LIST_HEAD(certlist);
		 !CERT_LIST_END(node, certlist);
		 node = CERT_LIST_NEXT (node)) {
		if (pmDebugOptions.context)
		    __pmDumpCertificate(stderr, secure_server.cert_nickname, node->cert);
		if (!__pmValidCertificate(nssdb, node->cert, now))
		    continue;
		secure_server.certificate_verified = 1;
		break;
	    }
	    CERT_DestroyCertList(certlist);
	}

	if (secure_server.certificate_verified) {
	    secure_server.certificate_KEA = NSS_FindCertKEAType(dbcert);
	    secure_server.private_key = PK11_FindKeyByAnyCert(dbcert, NULL);
	    if (!secure_server.private_key) {
		pmNotifyErr(LOG_ERR, "Unable to extract %s private key",
				secure_server.cert_nickname);
		CERT_DestroyCertificate(dbcert);
		secure_server.certificate_verified = 0;
		sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
		secure_server.init_failed = 1;
		goto done;
	    }
	} else {
	    pmNotifyErr(LOG_ERR, "Unable to find a valid %s", secure_server.cert_nickname);
	    CERT_DestroyCertificate(dbcert);
	    sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	    secure_server.init_failed = 1;
	    goto done;
	}
    }

    if (! secure_server.certificate_verified) {
	if (pmDebugOptions.context) {
	    pmNotifyErr(LOG_INFO, "No valid %s in security database: %s",
			  secure_server.cert_nickname, secure_server.database_path);
	}
	sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	secure_server.init_failed = 1;
	goto done;
    }

    secure_server.certificate = dbcert;
    secure_server.init_failed = 0;
    sts = 0;

done:
    PM_UNLOCK(secureserver_lock);
    return sts;
}
/*
 * Find all user certificates that match the given criteria.
 * 
 *	"handle" - database to search
 *	"usage" - certificate usage to match
 *	"oneCertPerName" - if set then only return the "best" cert per
 *			name
 *	"validOnly" - only return certs that are curently valid
 *	"proto_win" - window handle passed to pkcs11
 */
CERTCertList *
CERT_FindUserCertsByUsage(CERTCertDBHandle *handle,
			  SECCertUsage usage,
			  PRBool oneCertPerName,
			  PRBool validOnly,
			  void *proto_win)
{
    CERTCertNicknames *nicknames = NULL;
    char **nnptr;
    int nn;
    CERTCertificate *cert = NULL;
    CERTCertList *certList = NULL;
    SECStatus rv;
    int64 time;
    CERTCertListNode *node = NULL;
    CERTCertListNode *freenode = NULL;
    int n;
    
    time = PR_Now();
    
    nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER,
				      proto_win);
    
    if ( ( nicknames == NULL ) || ( nicknames->numnicknames == 0 ) ) {
	goto loser;
    }

    nnptr = nicknames->nicknames;
    nn = nicknames->numnicknames;

    while ( nn > 0 ) {
	cert = NULL;
	/* use the pk11 call so that we pick up any certs on tokens,
	 * which may require login
	 */
	if ( proto_win != NULL ) {
	    cert = PK11_FindCertFromNickname(*nnptr,proto_win);
	}

	/* Sigh, It turns out if the cert is already in the temp db, because
	 * it's in the perm db, then the nickname lookup doesn't work.
	 * since we already have the cert here, though, than we can just call
	 * CERT_CreateSubjectCertList directly. For those cases where we didn't
	 * find the cert in pkcs #11 (because we didn't have a password arg,
	 * or because the nickname is for a peer, server, or CA cert, then we
	 * go look the cert up.
	 */
	if (cert == NULL) { 
	    cert = CERT_FindCertByNickname(handle,*nnptr);
	}

	if ( cert != NULL ) {
	   /* collect certs for this nickname, sorting them into the list */
	    certList = CERT_CreateSubjectCertList(certList, handle, 
				&cert->derSubject, time, validOnly);

	    CERT_FilterCertListForUserCerts(certList);
	
	    /* drop the extra reference */
	    CERT_DestroyCertificate(cert);
	}
	
	nnptr++;
	nn--;
    }

    /* remove certs with incorrect usage */
    rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);

    if ( rv != SECSuccess ) {
	goto loser;
    }

    /* remove any extra certs for each name */
    if ( oneCertPerName ) {
	PRBool *flags;

	nn = nicknames->numnicknames;
	nnptr = nicknames->nicknames;
	
	flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn);
	if ( flags == NULL ) {
	    goto loser;
	}
	
	node = CERT_LIST_HEAD(certList);
	
	/* treverse all certs in the list */
	while ( !CERT_LIST_END(node, certList) ) {

	    /* find matching nickname index */
	    for ( n = 0; n < nn; n++ ) {
		if ( CERT_MatchNickname(nnptr[n], node->cert->nickname) ) {
		    /* We found a match.  If this is the first one, then
		     * set the flag and move on to the next cert.  If this
		     * is not the first one then delete it from the list.
		     */
		    if ( flags[n] ) {
			/* We have already seen a cert with this nickname,
			 * so delete this one.
			 */
			freenode = node;
			node = CERT_LIST_NEXT(node);
			CERT_RemoveCertListNode(freenode);
		    } else {
			/* keep the first cert for each nickname, but set the
			 * flag so we know to delete any others with the same
			 * nickname.
			 */
			flags[n] = PR_TRUE;
			node = CERT_LIST_NEXT(node);
		    }
		    break;
		}
	    }
	    if ( n == nn ) {
		/* if we get here it means that we didn't find a matching
		 * nickname, which should not happen.
		 */
		PORT_Assert(0);
		node = CERT_LIST_NEXT(node);
	    }
	}
	PORT_Free(flags);
    }

    goto done;
    
loser:
    if ( certList != NULL ) {
	CERT_DestroyCertList(certList);
	certList = NULL;
    }

done:
    if ( nicknames != NULL ) {
	CERT_FreeNicknames(nicknames);
    }

    return(certList);
}
/*
 * Find a user certificate that matchs the given criteria.
 * 
 *	"handle" - database to search
 *	"nickname" - nickname to match
 *	"usage" - certificate usage to match
 *	"validOnly" - only return certs that are curently valid
 *	"proto_win" - window handle passed to pkcs11
 */
CERTCertificate *
CERT_FindUserCertByUsage(CERTCertDBHandle *handle,
			 const char *nickname,
			 SECCertUsage usage,
			 PRBool validOnly,
			 void *proto_win)
{
    CERTCertificate *cert = NULL;
    CERTCertList *certList = NULL;
    SECStatus rv;
    int64 time;
    
    time = PR_Now();
    
    /* use the pk11 call so that we pick up any certs on tokens,
     * which may require login
     */
    /* XXX - why is this restricted? */
    if ( proto_win != NULL ) {
	cert = PK11_FindCertFromNickname(nickname,proto_win);
    }


    /* sigh, There are still problems find smart cards from the temp
     * db. This will get smart cards working again. The real fix
     * is to make sure we can search the temp db by their token nickname.
     */
    if (cert == NULL) {
	cert = CERT_FindCertByNickname(handle,nickname);
    }

    if ( cert != NULL ) {
	unsigned int requiredKeyUsage;
	unsigned int requiredCertType;

	rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE,
					&requiredKeyUsage, &requiredCertType);
	if ( rv != SECSuccess ) {
	    /* drop the extra reference */
	    CERT_DestroyCertificate(cert);
	    cert = NULL;
	    goto loser;
	}
	/* If we already found the right cert, just return it */
	if ( (!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE)
	      == secCertTimeValid) &&
	     (CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) &&
	     (cert->nsCertType & requiredCertType) &&
	      CERT_IsUserCert(cert) ) {
	    return(cert);
	}

 	/* collect certs for this nickname, sorting them into the list */
	certList = CERT_CreateSubjectCertList(certList, handle, 
					&cert->derSubject, time, validOnly);

	CERT_FilterCertListForUserCerts(certList);

	/* drop the extra reference */
	CERT_DestroyCertificate(cert);
	cert = NULL;
    }
	
    if ( certList == NULL ) {
	goto loser;
    }
    
    /* remove certs with incorrect usage */
    rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE);

    if ( rv != SECSuccess ) {
	goto loser;
    }

    if ( ! CERT_LIST_END(CERT_LIST_HEAD(certList), certList) ) {
	cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
    }
    
loser:
    if ( certList != NULL ) {
	CERT_DestroyCertList(certList);
    }

    return(cert);
}
Пример #11
0
int FileCertExport_main(int argc, char * argv[])
{
    CERTCertListNode *node;
    
    SECStatus rv = 0;
    
    /*初始化数据库*/
    rv = NSS_InitReadWrite(GetSystemDBDir());
    
    
    if (SECSuccess != rv) {
        printf("初始化数据库失败\n");
        
        return -1;
    }
    
    CERTCertList * certs = NULL;
    
    
    CERTCertDBHandle *certHandle;
    
    certHandle = CERT_GetDefaultCertDB();
    
    CERTCertificate *the_cert;
    /*用nickname查找数据库证书*/
    
    char * nickname = "BCDEF";/*nickname*/
    
    the_cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, nickname);
    
    if (NULL == the_cert) {
        printf("nickname为%s证书未找到",nickname);
    }
    
    
    certs = CERT_CreateSubjectCertList(NULL, certHandle, &the_cert->derSubject,
                                       PR_Now(), PR_FALSE);
    
    /*导出cert的文件名称*/
    char * tempCertPath = malloc(255);
    
    memset(tempCertPath, 0, 255);
    strcpy(tempCertPath, GetSystemDBDir());
    
    strcat(tempCertPath, "11111out_2.cer");
    
    FILE * fileOUT = fopen(tempCertPath, "w+b");
    
    if (NULL == fileOUT) {
        printf("%s文件打开失败\n",tempCertPath);
        
        return -1;
    }
    
	CERT_DestroyCertificate(the_cert);
	if (!certs) {
	    return SECFailure;
	}
	for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
         node = CERT_LIST_NEXT(node)) {
	    the_cert = node->cert;
	    /* now get the subjectList that matches this cert */
        SECItem data;
        

        
	    data.data = the_cert->derCert.data;
	    data.len = the_cert->derCert.len;
	    {
            PRInt32 numBytes = fwrite(data.data,data.len,1,fileOUT);
            if (numBytes != (PRInt32) data.len) {
                rv = SECFailure;
            }
            rv = SECSuccess;
	    } 
	    if (rv != SECSuccess) {
            break;
	    }
	}
    
    fclose(fileOUT);
    
    printf("Export Cert SUCCESS!\n");
    
    if (certs) {
        CERT_DestroyCertList(certs);
    }
    
    rv = NSS_Shutdown();
    
    return rv;
}