diff options
-rw-r--r-- | security/nss/lib/certdb/genname.c | 533 | ||||
-rw-r--r-- | security/nss/lib/certdb/secname.c | 91 |
2 files changed, 327 insertions, 297 deletions
diff --git a/security/nss/lib/certdb/genname.c b/security/nss/lib/certdb/genname.c index a8dcf6dff..94cde971a 100644 --- a/security/nss/lib/certdb/genname.c +++ b/security/nss/lib/certdb/genname.c @@ -433,12 +433,12 @@ cert_DecodeGeneralNames (PRArenaPool *arena, } currentName->l.next = head; currentName->l.prev = tail; - tail = &(currentName->l); - (cert_get_prev_general_name(currentName))->l.next = tail; + tail = head->prev = tail->next = &(currentName->l); encodedGenName++; } - (cert_get_next_general_name(currentName))->l.prev = tail; - return cert_get_next_general_name(currentName); + if (currentName) { + return cert_get_next_general_name(currentName); + } loser: return NULL; } @@ -605,6 +605,7 @@ cert_DecodeNameConstraintSubTree(PRArenaPool *arena, CERTNameConstraint *next = NULL; int i = 0; + PORT_Assert(arena); while (subTree[i] != NULL) { current = cert_DecodeNameConstraint(arena, subTree[i]); if (current == NULL) { @@ -621,14 +622,6 @@ cert_DecodeNameConstraintSubTree(PRArenaPool *arena, first->l.prev = &(current->l); return first; loser: - if (first) { - current = first; - do { - next = cert_get_next_name_constraint(current); - PORT_Free(current); - current = next; - }while (current != first); - } return NULL; } @@ -842,7 +835,7 @@ CERT_AddNameConstraint(CERTNameConstraint *list, SECStatus -CERT_GetNameConstriantByType (CERTNameConstraint *constraints, +CERT_GetNameConstraintByType (CERTNameConstraint *constraints, CERTGeneralNameType type, CERTNameConstraint **returnList, PRArenaPool *arena) @@ -967,41 +960,72 @@ loser: return NULL; } +/* This function does very basic regular expression matching. +** The only wildcard character is "*", which matches any substring. +** constraint is the regular expression. name is to be tested against it. +** return SECSuccess on match, SECFailure otherwise. Does not set error. +*/ static SECStatus -compareNameToConstraint(char *name, char *constraint, PRBool substring) +compareNameToConstraint(const char *name, const char *constraint, int level) { + PRBool substring = PR_FALSE; SECStatus rv; - if (*constraint == '\0' && *name == '\0') { - return SECSuccess; + while (*name == *constraint && *constraint != '\0' && *constraint != '*') { + ++name; + ++constraint; } - if (*constraint == '*') { - return compareNameToConstraint(name, constraint + 1, PR_TRUE); + if (*constraint == '\0' && *name == '\0') + return SECSuccess; + + while (*constraint == '*') { + ++constraint; + substring = PR_TRUE; } - if (substring) { - if (*constraint == '\0') { - return SECSuccess; - } - while (*name != *constraint) { - if (*name == '\0') { - return SECFailure; - } - name++; - } - rv = compareNameToConstraint(name + 1, constraint + 1, PR_FALSE); - if (rv == SECSuccess) { - return rv; - } - name++; - } else { - if (*name == *constraint) { + + if (!substring) + return SECFailure; + + if (*constraint == '\0') + return SECSuccess; + + if (++level > 20) + return SECFailure; /* prevent stack overflow */ + + do { + while (*name != *constraint && *name != '\0') name++; - constraint++; - } else { + if (*name == '\0') return SECFailure; - } - } - return compareNameToConstraint(name, constraint, substring); + + /* recurse */ + rv = compareNameToConstraint(name + 1, constraint + 1, level); + + ++name; + } while (rv != SECSuccess); + return rv; +} + +#define compareN2C(n,c) compareNameToConstraint((n),(c),0) + +/* This isn't right for items containing UCS2 or UCS4. +** Those should be converted to UTF8 rather than merely strncpy'ed. +** But it's not clear that we can tell what the encoding is here. +*/ +static char * +secItem2String(PLArenaPool *arena, SECItem *item) +{ + char * cPtr; + if (arena) + cPtr = PORT_ArenaAlloc(arena, item->len + 1); + else + cPtr = PORT_Alloc(item->len + 1); + if (cPtr) { + if (item->len) + PORT_Strncpy(cPtr, (char *)item->data, item->len); + cPtr[item->len] = '\0'; + } + return cPtr; } SECStatus @@ -1010,234 +1034,247 @@ cert_CompareNameWithConstraints(CERTGeneralName *name, PRBool excluded) { SECStatus rv = SECSuccess; - char *nameString = NULL; - char *constraintString = NULL; + char *nString = NULL; + char *cString = NULL; int start; int end; - int tag; - CERTRDN **nameRDNS, *nameRDN; - CERTRDN **constraintRDNS, *constraintRDN; - CERTAVA **nameAVAS, *nameAVA; - CERTAVA **constraintAVAS, *constraintAVA; + CERTRDN **nRDNs, *nRDN; + CERTAVA **nAVAs, *nAVA; CERTNameConstraint *current; - SECItem *avaValue; - CERTName constraintName; CERTName certName; SECComparison status = SECEqual; - PRArenaPool *certNameArena; - PRArenaPool *constraintNameArena; + PRArenaPool *nArena; + + if (!constraints) + return SECSuccess; + + nArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!nArena) + return SECFailure; certName.arena = NULL; - certName.rdns = NULL; - constraintName.arena = NULL; - constraintName.rdns = NULL; - if (constraints != NULL) { - current = constraints; - if (name->type == certDirectoryName) { - certNameArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - CERT_CopyName(certNameArena, &certName, &name->name.directoryName); - nameRDNS = certName.rdns; - for (;;) { - nameRDN = *nameRDNS++; - nameAVAS = nameRDN->avas; - for(;;) { - nameAVA = *nameAVAS++; - tag = CERT_GetAVATag(nameAVA); - if ( tag == SEC_OID_PKCS9_EMAIL_ADDRESS || - tag == SEC_OID_RFC1274_MAIL) { - avaValue = CERT_DecodeAVAValue(&nameAVA->value); - nameString = (char*)PORT_ZAlloc(avaValue->len + 1); - nameString = PORT_Strncpy(nameString, (char *) avaValue->data, avaValue->len); - start = 0; - while(nameString[start] != '@' && nameString[start + 1] != '\0') { - start++; - } + certName.rdns = NULL; + + /* Phase 1. If the name is a Directory Name, look through all the + ** AVAs in all the RDNs for any that are email addresses. + ** Subject all email addresses to all RFC822 email address constraints. + */ + if (name->type == certDirectoryName) { + rv = CERT_CopyName(nArena, &certName, &name->name.directoryName); + if (rv != SECSuccess) + goto loser; + nRDNs = certName.rdns; + while (nRDNs && *nRDNs) { /* loop over RDNs */ + nRDN = *nRDNs++; + nAVAs = nRDN->avas; + while (nAVAs && *nAVAs) { /* loop over AVAs */ + int tag; + nAVA = *nAVAs++; + tag = CERT_GetAVATag(nAVA); + if ( tag == SEC_OID_PKCS9_EMAIL_ADDRESS || + tag == SEC_OID_RFC1274_MAIL) { /* email AVA */ + SECItem *avaValue; + avaValue = CERT_DecodeAVAValue(&nAVA->value); + if (!avaValue) + goto loser; + nString = secItem2String(nArena, avaValue); + SECITEM_FreeItem(avaValue, PR_TRUE); + if (!nString) + goto loser; + start = 0; + while (nString[start] != '@' && nString[start] != '\0') { + start++; + } + if (nString[start]) start++; - do{ - if (current->name.type == certRFC822Name) { - constraintString = (char*)PORT_ZAlloc(current->name.name.other.len + 1); - constraintString = PORT_Strncpy(constraintString, - (char *) current->name.name.other.data, - current->name.name.other.len); - rv = compareNameToConstraint(nameString + start, constraintString, - PR_FALSE); - - if (constraintString != NULL) { - PORT_Free(constraintString); - constraintString = NULL; - } - if (nameString != NULL) { - PORT_Free(nameString); - nameString = NULL; - } - if (rv == SECSuccess && excluded == PR_TRUE) { + current = constraints; + do { /* loop over constraints */ + if (current->name.type == certRFC822Name) { + cString = + secItem2String(nArena, ¤t->name.name.other); + if (!cString) + goto loser; + rv = compareN2C(nString + start, cString); + if (rv == SECSuccess) { + if (excluded) goto found; - } - if (rv == SECSuccess && excluded == PR_FALSE) { - break; - } + break; /* out of loop over constraints. */ } - current = cert_get_next_name_constraint(current); - } while (current != constraints); - } - if (rv != SECSuccess && excluded == PR_FALSE) { - goto loser; - } - if (*nameAVAS == NULL) { - break; - } - } - if (*nameRDNS == NULL) { - break; + } /* email address constraint */ + current = cert_get_next_name_constraint(current); + } while (current != constraints); /*loop over constraints*/ + } /* handle one email AVA */ + if (rv != SECSuccess && excluded == PR_FALSE) { + goto no_match; } } - } - current = constraints; - do { - switch (name->type) { - case certDNSName: - nameString = (char*)PORT_ZAlloc(name->name.other.len + 1); - nameString = PORT_Strncpy(nameString, (char *) name->name.other.data, - name->name.other.len); - constraintString = (char*)PORT_ZAlloc(current->name.name.other.len + 1); - constraintString = PORT_Strncpy(constraintString, - (char *) current->name.name.other.data, - current->name.name.other.len); - rv = compareNameToConstraint(nameString, constraintString, PR_FALSE); - if (nameString != NULL) { - PORT_Free(nameString); - } - if (constraintString != NULL) { - PORT_Free(constraintString); - } - break; - case certRFC822Name: - nameString = (char*)PORT_ZAlloc(name->name.other.len + 1); - nameString = PORT_Strncpy(nameString, (char *) name->name.other.data, - name->name.other.len); - start = 0; - while(nameString[start] != '@' && nameString[start + 1] != '\0') { - start++; - } + } /* loop over RDNs */ + } /* name->type == certDirectoryName */ + + /* Phase 2. loop over all constratints for this name. */ + current = constraints; + do { + switch (name->type) { + + case certDNSName: + PORT_Assert(name->type == current->name.type); + nString = secItem2String(nArena, &name->name.other); + if (!nString) + goto loser; + cString = secItem2String(nArena, ¤t->name.name.other); + if (!cString) + goto loser; + rv = compareN2C(nString, cString); + break; + + case certRFC822Name: + PORT_Assert(name->type == current->name.type); + nString = secItem2String(nArena, &name->name.other); + if (!nString) + goto loser; + start = 0; + while (nString[start] != '@' && + nString[start] != '\0') { start++; - constraintString = (char*)PORT_ZAlloc(current->name.name.other.len + 1); - constraintString = PORT_Strncpy(constraintString, - (char *) current->name.name.other.data, - current->name.name.other.len); - rv = compareNameToConstraint(nameString + start, constraintString, PR_FALSE); - if (nameString != NULL) { - PORT_Free(nameString); - } - if (constraintString != NULL) { - PORT_Free(constraintString); - } - break; - case certURI: - nameString = (char*)PORT_ZAlloc(name->name.other.len + 1); - nameString = PORT_Strncpy(nameString, (char *) name->name.other.data, - name->name.other.len); - start = 0; - while(PORT_Strncmp(nameString + start, "://", 3) != 0 && - nameString[start + 3] != '\0') { - start++; - } + } + if (nString[start]) + start++; + cString = secItem2String(nArena, ¤t->name.name.other); + if (!cString) + goto loser; + rv = compareN2C(nString + start, cString); + break; + + case certURI: + PORT_Assert(name->type == current->name.type); + nString = secItem2String(nArena, &name->name.other); + if (!nString) + goto loser; + /* XXX This URI hostname parsing is wrong because it doesn't + ** handle user name and password strings that can come + ** before the host name. + */ + start = 0; + while(nString[start] != 0 && + PORT_Strncmp(nString + start, "://", 3) != 0 ) { + start++; + } + if (nString[start]) start +=3; - end = 0; - while(nameString[start + end] != '/' && - nameString[start + end] != '\0') { - end++; - } - nameString[start + end] = '\0'; - constraintString = (char*)PORT_ZAlloc(current->name.name.other.len + 1); - constraintString = PORT_Strncpy(constraintString, - (char *) current->name.name.other.data, - current->name.name.other.len); - rv = compareNameToConstraint(nameString + start, constraintString, PR_FALSE); - if (nameString != NULL) { - PORT_Free(nameString); - } - if (constraintString != NULL) { - PORT_Free(constraintString); + end = 0; + while(nString[start + end] != '/' && + nString[start + end] != ':' && + nString[start + end] != '\0') { + end++; + } + nString[start + end] = '\0'; + cString = secItem2String(nArena, ¤t->name.name.other); + if (!cString) + goto loser; + rv = compareN2C(nString + start, cString); + break; + + case certDirectoryName: + PORT_Assert(current->name.type == certDirectoryName || \ + current->name.type == certRFC822Name); + if (current->name.type == certRFC822Name) + goto next_constraint; /* already handled in phase 1. */ + if (current->name.type == certDirectoryName) { + PRArenaPool *cArena; + CERTRDN **cRDNs, *cRDN; + CERTAVA **cAVAs, *cAVA; + CERTName constraintName; + + constraintName.arena = NULL; + constraintName.rdns = NULL; + + cArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!cArena) + goto loser; + rv = CERT_CopyName(cArena, &constraintName, + ¤t->name.name.directoryName); + if (rv != SECSuccess) { + PORT_FreeArena(cArena, PR_FALSE); + goto loser; } - break; - case certDirectoryName: - if (current->name.type == certDirectoryName) { - constraintNameArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - CERT_CopyName(constraintNameArena, &constraintName, ¤t->name.name.directoryName); - constraintRDNS = constraintName.rdns; - for (;;) { - constraintRDN = *constraintRDNS++; - constraintAVAS = constraintRDN->avas; - for(;;) { - constraintAVA = *constraintAVAS++; - certNameArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - CERT_CopyName(certNameArena, &certName, &name->name.directoryName); - nameRDNS = certName.rdns; - for (;;) { - nameRDN = *nameRDNS++; - nameAVAS = nameRDN->avas++; - for(;;) { - nameAVA = *nameAVAS++; - status = CERT_CompareAVA(constraintAVA, nameAVA); - if (status == SECEqual || *nameAVAS == NULL) { - break; - } - } - if (status == SECEqual || *nameRDNS == NULL) { + cRDNs = constraintName.rdns; + while (cRDNs && *cRDNs) { /* loop over constraint RDNs */ + cRDN = *cRDNs++; + cAVAs = cRDN->avas; + while (cAVAs && *cAVAs) { /* loop over constraint AVAs */ + cAVA = *cAVAs++; + + /* certName was initialized in Phase 1. */ + PORT_Assert(certName.arena != NULL); + + nRDNs = certName.rdns; + while (nRDNs && *nRDNs) { /* loop over name RDNs */ + nRDN = *nRDNs++; + nAVAs = nRDN->avas; + while (nAVAs && *nAVAs) { /* loop over name AVAs */ + nAVA = *nAVAs++; + status = CERT_CompareAVA(cAVA, nAVA); + if (status == SECEqual) break; - } - } - if (status != SECEqual || *constraintAVAS == NULL) { + } /* loop over name AVAs */ + if (status == SECEqual) break; - } - } - if (status != SECEqual || *constraintRDNS == NULL) { + } /* loop over name RDNs */ + if (status != SECEqual) break; - } - } - if (status == SECEqual) { - if (excluded == PR_FALSE) { - goto found; - } else { - goto loser; - } - } - break; - } else if (current->name.type == certRFC822Name) { - current = cert_get_next_name_constraint(current); - continue; - } - default: - /* other types are not supported */ - if (excluded) { - goto found; - } else { - goto loser; + } /* loop over AVAs in constraint */ + if (status != SECEqual) + break; + } /* loop over RDNs in constraint */ + PORT_FreeArena(cArena, PR_FALSE); + if (status == SECEqual) { + if (!excluded) + goto found; + goto no_match; } + break; } - if (rv == SECSuccess && status == SECEqual) { - goto found; - } - current = cert_get_next_name_constraint(current); - } while (current !=constraints); - } else { - goto found; - } -loser: - if (certName.arena) { - CERT_DestroyName(&certName); - } - if (constraintName.arena) { - CERT_DestroyName(&constraintName); - } + goto loser; +#ifdef NOTYET + case certOtherName: /* type 1 */ + case certX400Address: /* type 4 */ + case certEDIPartyName: /* type 6 */ + case certIPAddress: /* type 8 */ + case certRegisterID: /* type 9 */ + PORT_Assert(name->type == current->name.type); + if (name->type == current->name.type && + name->name.other.len == current->name.name.other.len && + !memcmp(name->name.other.data, current->name.name.other.data, + name->name.other.len)) + rv = SECSuccess; + else + rv = SECFailure; + break; +#endif + default: + /* non-standard types are not supported */ + goto loser; + } + if (rv == SECSuccess && status == SECEqual) { + goto found; + } +next_constraint: + current = cert_get_next_name_constraint(current); + } while (current !=constraints); + +no_match: + if (nArena) + PORT_FreeArena(nArena, PR_FALSE); return SECFailure; + +loser: + if (nArena) + PORT_FreeArena(nArena, PR_FALSE); + return excluded ? SECSuccess : SECFailure; + found: - if (certName.arena) { - CERT_DestroyName(&certName); - } - if (constraintName.arena) { - CERT_DestroyName(&constraintName); - } + if (nArena) + PORT_FreeArena(nArena, PR_FALSE); return SECSuccess; } @@ -1268,7 +1305,7 @@ CERT_CompareNameSpace(CERTCertificate *cert, } do { if (constraints->excluded != NULL) { - rv = CERT_GetNameConstriantByType(constraints->excluded, currentName->type, + rv = CERT_GetNameConstraintByType(constraints->excluded, currentName->type, &matchingConstraints, arena); if (rv != SECSuccess) { goto loser; @@ -1282,7 +1319,7 @@ CERT_CompareNameSpace(CERTCertificate *cert, } } if (constraints->permited != NULL) { - rv = CERT_GetNameConstriantByType(constraints->permited, currentName->type, + rv = CERT_GetNameConstraintByType(constraints->permited, currentName->type, &matchingConstraints, arena); if (rv != SECSuccess) { goto loser; diff --git a/security/nss/lib/certdb/secname.c b/security/nss/lib/certdb/secname.c index a508dcb44..63f279bce 100644 --- a/security/nss/lib/certdb/secname.c +++ b/security/nss/lib/certdb/secname.c @@ -67,8 +67,8 @@ CountArray(void **array) return count; } -static void -**AddToArray(PRArenaPool *arena, void **array, void *element) +static void ** +AddToArray(PRArenaPool *arena, void **array, void *element) { unsigned count; void **ap; @@ -96,35 +96,6 @@ static void return array; } -#if 0 -static void -**RemoveFromArray(void **array, void *element) -{ - unsigned count; - void **ap; - int slot; - - /* Look for element */ - ap = array; - if (ap) { - count = 1; /* count the null at the end */ - slot = -1; - for (; *ap; ap++, count++) { - if (*ap == element) { - /* Found it */ - slot = ap - array; - } - } - if (slot >= 0) { - /* Found it. Squish array down */ - PORT_Memmove((void*) (array + slot), (void*) (array + slot + 1), - (count - slot - 1) * sizeof(void*)); - /* Don't bother reallocing the memory */ - } - } - return array; -} -#endif /* 0 */ SECOidTag CERT_GetAVATag(CERTAVA *ava) @@ -217,6 +188,7 @@ SetupAVAValue(PRArenaPool *arena, int valueType, char *value, SECItem *it, case SEC_ASN1_PRINTABLE_STRING: case SEC_ASN1_IA5_STRING: case SEC_ASN1_T61_STRING: + case SEC_ASN1_UTF8_STRING: /* no conversion required */ valueLen = PORT_Strlen(value); break; case SEC_ASN1_UNIVERSAL_STRING: @@ -357,17 +329,27 @@ SECStatus CERT_CopyRDN(PRArenaPool *arena, CERTRDN *to, CERTRDN *from) { CERTAVA **avas, *fava, *tava; - SECStatus rv; + SECStatus rv = SECSuccess; /* Copy each ava from from */ avas = from->avas; - while ((fava = *avas++) != 0) { - tava = CERT_CopyAVA(arena, fava); - if (!tava) return SECFailure; - rv = CERT_AddAVA(arena, to, tava); - if (rv) return rv; + if (avas) { + if (avas[0] == NULL) { + rv = CERT_AddAVA(arena, to, NULL); + return rv; + } + while ((fava = *avas++) != 0) { + tava = CERT_CopyAVA(arena, fava); + if (!tava) { + rv = SECFailure; + break; + } + rv = CERT_AddAVA(arena, to, tava); + if (rv != SECSuccess) + break; + } } - return SECSuccess; + return rv; } /************************************************************************/ @@ -460,27 +442,38 @@ SECStatus CERT_CopyName(PRArenaPool *arena, CERTName *to, CERTName *from) { CERTRDN **rdns, *frdn, *trdn; - SECStatus rv; + SECStatus rv = SECSuccess; - if (!to || !from) + if (!to || !from) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; + } CERT_DestroyName(to); to->arena = arena; /* Copy each rdn from from */ rdns = from->rdns; - while ((frdn = *rdns++) != 0) { - trdn = CERT_CreateRDN(arena, 0); - if ( trdn == NULL ) { - return(SECFailure); + if (rdns) { + if (rdns[0] == NULL) { + rv = CERT_AddRDN(to, NULL); + return rv; + } + while ((frdn = *rdns++) != NULL) { + trdn = CERT_CreateRDN(arena, 0); + if (!trdn) { + rv = SECFailure; + break; + } + rv = CERT_CopyRDN(arena, trdn, frdn); + if (rv != SECSuccess) + break; + rv = CERT_AddRDN(to, trdn); + if (rv != SECSuccess) + break; } - rv = CERT_CopyRDN(arena, trdn, frdn); - if (rv) return rv; - rv = CERT_AddRDN(to, trdn); - if (rv) return rv; } - return SECSuccess; + return rv; } /************************************************************************/ |