certhigh.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,101 行 · 第 1/2 页

C
1,101
字号
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "nspr.h"#include "secerr.h"#include "secasn1.h"#include "seccomon.h"#include "pk11func.h"#include "certdb.h"#include "certt.h"#include "cert.h"#include "certxutl.h"/* * 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);		    /* 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 ( PORT_Strcmp(nnptr[n], node->cert->nickname) == 0 ) {		    /* 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,			 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 ) { 	/* collect certs for this nickname, sorting them into the list */	certList = CERT_CreateSubjectCertList(certList, handle, 					&cert->derSubject, time, validOnly);	/* 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);}CERTCertList *CERT_MatchUserCert(CERTCertDBHandle *handle,		   SECCertUsage usage,		   int nCANames, char **caNames,		   void *proto_win){    CERTCertList *certList = NULL;    SECStatus rv;    certList = CERT_FindUserCertsByUsage(handle, usage, PR_TRUE, PR_TRUE,					 proto_win);    if ( certList == NULL ) {	goto loser;    }        rv = CERT_FilterCertListByCANames(certList, nCANames, caNames, usage);    if ( rv != SECSuccess ) {	goto loser;    }        goto done;    loser:    if ( certList != NULL ) {	CERT_DestroyCertList(certList);	certList = NULL;    }done:    return(certList);}typedef struct stringNode {    struct stringNode *next;    char *string;} stringNode;    static SECStatusCollectNicknames( CERTCertificate *cert, SECItem *k, void *data){    CERTCertNicknames *names;    PRBool saveit = PR_FALSE;    CERTCertTrust *trust;    stringNode *node;    int len;        names = (CERTCertNicknames *)data;        if ( cert->nickname ) {	trust = cert->trust;		switch(names->what) {	  case SEC_CERT_NICKNAMES_ALL:	    if ( ( trust->sslFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||	      ( trust->emailFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ||	      ( trust->objectSigningFlags & (CERTDB_VALID_CA|CERTDB_VALID_PEER) ) ) {		saveit = PR_TRUE;	    }	    	    break;	  case SEC_CERT_NICKNAMES_USER:	    if ( ( trust->sslFlags & CERTDB_USER ) ||		( trust->emailFlags & CERTDB_USER ) ||		( trust->objectSigningFlags & CERTDB_USER ) ) {		saveit = PR_TRUE;	    }	    	    break;	  case SEC_CERT_NICKNAMES_SERVER:	    if ( trust->sslFlags & CERTDB_VALID_PEER ) {		saveit = PR_TRUE;	    }	    	    break;	  case SEC_CERT_NICKNAMES_CA:	    if ( ( ( trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) ||		( ( trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) ||		( ( trust->objectSigningFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) ) {		saveit = PR_TRUE;	    }	    break;	}    }    /* traverse the list of collected nicknames and make sure we don't make     * a duplicate     */    if ( saveit ) {	node = (stringNode *)names->head;	while ( node != NULL ) {	    if ( PORT_Strcmp(cert->nickname, node->string) == 0 ) { 		/* if the string matches, then don't save this one */		saveit = PR_FALSE;		break;	    }	    node = node->next;	}    }    if ( saveit ) {		/* allocate the node */	node = (stringNode*)PORT_ArenaAlloc(names->arena, sizeof(stringNode));	if ( node == NULL ) {	    return(SECFailure);	}	/* copy the string */	len = PORT_Strlen(cert->nickname) + 1;	node->string = (char*)PORT_ArenaAlloc(names->arena, len);	if ( node->string == NULL ) {	    return(SECFailure);	}	PORT_Memcpy(node->string, cert->nickname, len);	/* link it into the list */	node->next = (stringNode *)names->head;	names->head = (void *)node;	/* bump the count */	names->numnicknames++;    }        return(SECSuccess);}CERTCertNicknames *CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx){    PRArenaPool *arena;    CERTCertNicknames *names;    int i;    SECStatus rv;    stringNode *node;        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( arena == NULL ) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return(NULL);    }        names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));    if ( names == NULL ) {	goto loser;    }    names->arena = arena;    names->head = NULL;    names->numnicknames = 0;    names->nicknames = NULL;    names->what = what;    names->totallen = 0;        rv = SEC_TraversePermCerts(handle, CollectNicknames, (void *)names);    if ( rv ) {	goto loser;    }    if ( wincx != NULL ) {	rv = PK11_TraverseSlotCerts(CollectNicknames, (void *)names, wincx);	if ( rv ) {	    goto loser;	}    }    if ( names->numnicknames ) {	names->nicknames = (char**)PORT_ArenaAlloc(arena,					 names->numnicknames * sizeof(char *));	if ( names->nicknames == NULL ) {	    goto loser;	}    	node = (stringNode *)names->head;		for ( i = 0; i < names->numnicknames; i++ ) {	    PORT_Assert(node != NULL);	    	    names->nicknames[i] = node->string;	    names->totallen += PORT_Strlen(node->string);	    node = node->next;	}	PORT_Assert(node == NULL);    }    return(names);    loser:    PORT_FreeArena(arena, PR_FALSE);    return(NULL);}voidCERT_FreeNicknames(CERTCertNicknames *nicknames){    PORT_FreeArena(nicknames->arena, PR_FALSE);        return;}/* [ FROM pcertdb.c ] */typedef struct dnameNode {    struct dnameNode *next;    SECItem name;} dnameNode;voidCERT_FreeDistNames(CERTDistNames *names){    PORT_FreeArena(names->arena, PR_FALSE);        return;}static SECStatusCollectDistNames( CERTCertificate *cert, SECItem *k, void *data){    CERTDistNames *names;    PRBool saveit = PR_FALSE;    CERTCertTrust *trust;    dnameNode *node;    int len;        names = (CERTDistNames *)data;        if ( cert->trust ) {	trust = cert->trust;		/* only collect names of CAs trusted for issuing SSL clients */	if ( ( trust->sslFlags &	      ( CERTDB_VALID_CA | CERTDB_TRUSTED_CLIENT_CA ) ) ==	       ( CERTDB_VALID_CA | CERTDB_TRUSTED_CLIENT_CA ) ) {	    saveit = PR_TRUE;	}    }    if ( saveit ) {	/* allocate the node */	node = (dnameNode*)PORT_ArenaAlloc(names->arena, sizeof(dnameNode));	if ( node == NULL ) {	    return(SECFailure);	}	/* copy the name */	node->name.len = len = cert->derSubject.len;	node->name.type = siBuffer;	node->name.data = (unsigned char*)PORT_ArenaAlloc(names->arena, len);	if ( node->name.data == NULL ) {	    return(SECFailure);	}	PORT_Memcpy(node->name.data, cert->derSubject.data, len);	/* link it into the list */	node->next = (dnameNode *)names->head;	names->head = (void *)node;	/* bump the count */	names->nnames++;    }        return(SECSuccess);}/* * Return all of the CAs that are "trusted" for SSL. */CERTDistNames *CERT_GetSSLCACerts(CERTCertDBHandle *handle){    PRArenaPool *arena;    CERTDistNames *names;    int i;    SECStatus rv;    dnameNode *node;        /* allocate an arena to use */    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);    if ( arena == NULL ) {	PORT_SetError(SEC_ERROR_NO_MEMORY);	return(NULL);    }    

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?