certdb.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,329 行 · 第 1/4 页
C
2,329 行
goto loser; } /* * Open the memory resident decoded cert database. */ handle->tempCertDB = dbopen( 0, O_RDWR | O_CREAT, 0600, DB_HASH, 0 ); if ( !handle->tempCertDB ) { goto loser; } handle->dbMon = PR_NewMonitor(); PORT_Assert(handle->dbMon != NULL); handle->spkDigestInfo = NULL; handle->statusConfig = NULL; /* initialize the cert database */ (void) CERT_InitCertDB(handle); return (SECSuccess); loser: PORT_SetError(SEC_ERROR_BAD_DATABASE); if ( handle->permCertDB ) { (* handle->permCertDB->close)(handle->permCertDB); handle->permCertDB = 0; } if ( handle->tempCertDB ) { (* handle->tempCertDB->close)(handle->tempCertDB); handle->tempCertDB = 0; } return(SECFailure);}/* XXX this would probably be okay/better as an xp routine? */static voidsec_lower_string(char *s){ if ( s == NULL ) { return; } while ( *s ) { *s = PORT_Tolower(*s); s++; } return;}/*** Add a domain name to the list of names that the user has explicitly** allowed (despite cert name mismatches) for use with a server cert.*/SECStatusCERT_AddOKDomainName(CERTCertificate *cert, const char *hn){ CERTOKDomainName *domainOK; int newNameLen; if (!hn || !(newNameLen = strlen(hn))) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } domainOK = (CERTOKDomainName *)PORT_ArenaZAlloc(cert->arena, (sizeof *domainOK) + newNameLen); if (!domainOK) return SECFailure; /* error code is already set. */ PORT_Strcpy(domainOK->name, hn); sec_lower_string(domainOK->name); /* put at head of list. */ domainOK->next = cert->domainOK; cert->domainOK = domainOK; return SECSuccess;}/* Make sure that the name of the host we are connecting to matches the * name that is incoded in the common-name component of the certificate * that they are using. */SECStatusCERT_VerifyCertName(CERTCertificate *cert, const char *hn){ char * cn; char * domain; char * hndomain; char * hostname; int regvalid; int match; SECStatus rv; CERTOKDomainName *domainOK; if (!hn || !strlen(hn)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } hostname = PORT_Strdup(hn); if ( hostname == NULL ) { return(SECFailure); } sec_lower_string(hostname); /* if the name is one that the user has already approved, it's OK. */ for (domainOK = cert->domainOK; domainOK; domainOK = domainOK->next) { if (0 == PORT_Strcmp(hostname, domainOK->name)) { PORT_Free(hostname); return SECSuccess; } } /* try the cert extension first, then the common name */ cn = CERT_FindNSStringExtension(cert, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME); if ( cn == NULL ) { cn = CERT_GetCommonName(&cert->subject); } sec_lower_string(cn); if ( cn ) { if ( ( hndomain = PORT_Strchr(hostname, '.') ) == NULL ) { /* No domain in server name */ if ( ( domain = PORT_Strchr(cn, '.') ) != NULL ) { /* there is a domain in the cn string, so chop it off */ *domain = '\0'; } } regvalid = PORT_RegExpValid(cn); if ( regvalid == NON_SXP ) { /* compare entire hostname with cert name */ if ( PORT_Strcmp(hostname, cn) == 0 ) { rv = SECSuccess; goto done; } if ( hndomain ) { /* compare just domain name with cert name */ if ( PORT_Strcmp(hndomain+1, cn) == 0 ) { rv = SECSuccess; goto done; } } PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); rv = SECFailure; goto done; } else { /* try to match the shexp */ match = PORT_RegExpCaseSearch(hostname, cn); if ( match == 0 ) { rv = SECSuccess; } else { PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN); rv = SECFailure; } goto done; } } PORT_SetError(SEC_ERROR_NO_MEMORY); rv = SECFailure;done: /* free the common name */ if ( cn ) { PORT_Free(cn); } if ( hostname ) { PORT_Free(hostname); } return(rv);}PRBoolCERT_CompareCerts(CERTCertificate *c1, CERTCertificate *c2){ SECComparison comp; comp = SECITEM_CompareItem(&c1->derCert, &c2->derCert); if ( comp == SECEqual ) { /* certs are the same */ return(PR_TRUE); } else { return(PR_FALSE); }}static SECStatusStringsEqual(char *s1, char *s2) { if ( ( s1 == NULL ) || ( s2 == NULL ) ) { if ( s1 != s2 ) { /* only one is null */ return(SECFailure); } return(SECSuccess); /* both are null */ } if ( PORT_Strcmp( s1, s2 ) != 0 ) { return(SECFailure); /* not equal */ } return(SECSuccess); /* strings are equal */}PRBoolCERT_CompareCertsForRedirection(CERTCertificate *c1, CERTCertificate *c2){ SECComparison comp; char *c1str, *c2str; SECStatus eq; comp = SECITEM_CompareItem(&c1->derCert, &c2->derCert); if ( comp == SECEqual ) { /* certs are the same */ return(PR_TRUE); } /* check if they are issued by the same CA */ comp = SECITEM_CompareItem(&c1->derIssuer, &c2->derIssuer); if ( comp != SECEqual ) { /* different issuer */ return(PR_FALSE); } /* check country name */ c1str = CERT_GetCountryName(&c1->subject); c2str = CERT_GetCountryName(&c2->subject); eq = StringsEqual(c1str, c2str); PORT_Free(c1str); PORT_Free(c2str); if ( eq != SECSuccess ) { return(PR_FALSE); } /* check locality name */ c1str = CERT_GetLocalityName(&c1->subject); c2str = CERT_GetLocalityName(&c2->subject); eq = StringsEqual(c1str, c2str); PORT_Free(c1str); PORT_Free(c2str); if ( eq != SECSuccess ) { return(PR_FALSE); } /* check state name */ c1str = CERT_GetStateName(&c1->subject); c2str = CERT_GetStateName(&c2->subject); eq = StringsEqual(c1str, c2str); PORT_Free(c1str); PORT_Free(c2str); if ( eq != SECSuccess ) { return(PR_FALSE); } /* check org name */ c1str = CERT_GetOrgName(&c1->subject); c2str = CERT_GetOrgName(&c2->subject); eq = StringsEqual(c1str, c2str); PORT_Free(c1str); PORT_Free(c2str); if ( eq != SECSuccess ) { return(PR_FALSE); }#ifdef NOTDEF /* check orgUnit name */ /* * We need to revisit this and decide which fields should be allowed to be * different */ c1str = CERT_GetOrgUnitName(&c1->subject); c2str = CERT_GetOrgUnitName(&c2->subject); eq = StringsEqual(c1str, c2str); PORT_Free(c1str); PORT_Free(c2str); if ( eq != SECSuccess ) { return(PR_FALSE); }#endif return(PR_TRUE); /* all fields but common name are the same */}/* CERT_CertChainFromCert and CERT_DestroyCertificateList moved to certhigh.c */CERTIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *arena, CERTCertificate *cert){ CERTIssuerAndSN *result; SECStatus rv; if ( arena == NULL ) { arena = cert->arena; } result = (CERTIssuerAndSN*)PORT_ArenaZAlloc(arena, sizeof(*result)); if (result == NULL) { PORT_SetError (SEC_ERROR_NO_MEMORY); return NULL; } rv = SECITEM_CopyItem(arena, &result->derIssuer, &cert->derIssuer); if (rv != SECSuccess) return NULL; rv = CERT_CopyName(arena, &result->issuer, &cert->issuer); if (rv != SECSuccess) return NULL; rv = SECITEM_CopyItem(arena, &result->serialNumber, &cert->serialNumber); if (rv != SECSuccess) return NULL; return result;}char *CERT_MakeCANickname(CERTCertificate *cert){ char *firstname = NULL; char *org = NULL; char *nickname = NULL; int count; CERTCertificate *dummycert; CERTCertDBHandle *handle; handle = cert->dbhandle; nickname = CERT_GetNickName(cert, handle, cert->arena); if (nickname == NULL) { firstname = CERT_GetCommonName(&cert->subject); if ( firstname == NULL ) { firstname = CERT_GetOrgUnitName(&cert->subject); } org = CERT_GetOrgName(&cert->issuer); if ( org == NULL ) { goto loser; } count = 1; while ( 1 ) { if ( firstname ) { if ( count == 1 ) { nickname = PR_smprintf("%s - %s", firstname, org); } else { nickname = PR_smprintf("%s - %s #%d", firstname, org, count); } } else { if ( count == 1 ) { nickname = PR_smprintf("%s", org); } else { nickname = PR_smprintf("%s #%d", org, count); } } if ( nickname == NULL ) { goto loser; } /* look up the nickname to make sure it isn't in use already */ dummycert = CERT_FindCertByNickname(handle, nickname); if ( dummycert == NULL ) { goto done; } /* found a cert, destroy it and loop */ CERT_DestroyCertificate(dummycert); /* free the nickname */ PORT_Free(nickname); count++; } }loser: if ( nickname ) { PORT_Free(nickname); } nickname = ""; done: if ( firstname ) { PORT_Free(firstname); } if ( org ) { PORT_Free(org); } return(nickname);}/* CERT_Import_CAChain moved to certhigh.c */voidCERT_DestroyCrl (CERTSignedCrl *crl){ SEC_DestroyCrl (crl);}/* * Does a cert belong to a CA? We decide based on perm database trust * flags, Netscape Cert Type Extension, and KeyUsage Extension. */PRBoolCERT_IsCACert(CERTCertificate *cert, unsigned int *rettype){ CERTCertTrust *trust; SECStatus rv; unsigned int type; PRBool ret; ret = PR_FALSE; type = 0; if ( cert->isperm ) { trust = cert->trust; if ( ( trust->sslFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) { ret = PR_TRUE; type |= NS_CERT_TYPE_SSL_CA; } if ( ( trust->emailFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) { ret = PR_TRUE; type |= NS_CERT_TYPE_EMAIL_CA; } if ( ( trust->objectSigningFlags & CERTDB_VALID_CA ) == CERTDB_VALID_CA ) { ret = PR_TRUE; type |= NS_CERT_TYPE_OBJECT_SIGNING_CA; } } else { if ( cert->nsCertType & ( NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA | NS_CERT_TYPE_OBJECT_SIGNING_CA ) ) { ret = PR_TRUE; type = (cert->nsCertType & NS_CERT_TYPE_CA); } else { CERTBasicConstraints constraints; rv = CERT_FindBasicConstraintExten(cert, &constraints); if ( rv == SECSuccess ) { if ( constraints.isCA ) { ret = PR_TRUE; type = (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA); } } } /* finally check if it's a FORTEZZA V1 CA */ if (ret == PR_FALSE) { if (fortezzaIsCA(cert)) { ret = PR_TRUE; type = (NS_CERT_TYPE_SSL_CA | NS_CERT_TYPE_EMAIL_CA); } } } if ( rettype != NULL ) { *rettype = type; } return(ret);}/* * is certa newer than certb? If one is expired, pick the other one. */PRBoolCERT_IsNewer(CERTCertificate *certa, CERTCertificate *certb){ int64 notBeforeA, notAfterA, notBeforeB, notAfterB, now; SECStatus rv; PRBool newerbefore, newerafter; rv = CERT_GetCertTimes(certa, ¬BeforeA, ¬AfterA); if ( rv != SECSuccess ) { return(PR_FALSE); } rv = CERT_GetCertTimes(certb, ¬BeforeB, ¬AfterB); if ( rv != SECSuccess ) { return(PR_TRUE); } newerbefore = PR_FALSE; if ( LL_CMP(notBeforeA, >, notBeforeB) ) { newerbefore = PR_TRUE; } newerafter = PR_FALSE; if ( LL_CMP(notAfterA, >, notAfterB) ) { newerafter = PR_TRUE; } if ( newerbefore && newerafter ) { return(PR_TRUE); } if ( ( !newerbefore ) && ( !newerafter ) ) { return(PR_FALSE); } /* get current UTC time */ now = PR_Now(); if ( newerbefore ) { /* cert A was issued after cert B, but expires sooner */ /* if A is expired, then pick B */ if ( LL_CMP(notAfterA, <, now ) ) { return(PR_FALSE); } return(PR_TRUE); } else { /* cert B was issued after cert A, but expires sooner */ /* if B is expired, then pick A */ if ( LL_CMP(notAfterB, <, now ) ) { return(PR_TRUE); } return(PR_FALSE); }}voidCERT_DestroyCertArray(CERTCertificate **certs, unsigned int ncerts){ unsigned int i; if ( certs ) { for ( i = 0; i < ncerts; i++ ) { if ( certs[i] ) { CERT_DestroyCertificate(certs[i]); } } PORT_Free(certs); } return;}char *CERT_FixupEmailAddr(char *emailAddr){ char *retaddr; char *str; if ( emailAddr == NULL ) { return(NULL); } /* copy the string */ str = retaddr = PORT_Strdup(emailAddr); if ( str == NULL ) { return(NULL); } /* make it lower case */ while ( *str ) { *str = tolower( *str ); str++; } return(retaddr);}/*
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?