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 + -
显示快捷键?