Skip to content

Commit

Permalink
Fix several bugs reported in bug 210707.
Browse files Browse the repository at this point in the history
Change loops over RDNs and AVAs to detect NULL pointers.
Change list of attribute type "keywords" to match RFCs and internet
drafts.
Quote attribute values strings that contain adjacent embedded blanks.
Don't quote hex string values.
Always use hex string values when type OID is unrecognized.
  • Loading branch information
nelsonb%netscape.com committed Jun 27, 2003
1 parent addc141 commit feb1697
Showing 1 changed file with 83 additions and 47 deletions.
130 changes: 83 additions & 47 deletions security/nss/lib/certdb/alg1485.c
@@ -1,4 +1,5 @@
/*
/* alg1485.c - implementation of RFCs 1485, 1779 and 2253.
*
* 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
Expand Down Expand Up @@ -38,6 +39,9 @@
#include "secitem.h"
#include "secerr.h"

/* for better RFC 2253 compliance. */
#define NSS_STRICT_RFC_2253_VALUES_ONLY 1

struct NameToKind {
const char * name;
unsigned int maxLen; /* max bytes in UTF8 encoded string value */
Expand All @@ -46,30 +50,41 @@ struct NameToKind {

/* Add new entries to this table, and maybe to function CERT_ParseRFC1485AVA */
static const struct NameToKind name2kinds[] = {
{ "CN", 64, SEC_OID_AVA_COMMON_NAME },
{ "ST", 128, SEC_OID_AVA_STATE_OR_PROVINCE },
{ "OU", 64, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME },
{ "DC", 128, SEC_OID_AVA_DC },
{ "C", 2, SEC_OID_AVA_COUNTRY_NAME },
{ "O", 64, SEC_OID_AVA_ORGANIZATION_NAME },
{ "L", 128, SEC_OID_AVA_LOCALITY },
{ "dnQualifier", 32767, SEC_OID_AVA_DN_QUALIFIER },
{ "E", 128, SEC_OID_PKCS9_EMAIL_ADDRESS },
{ "UID", 256, SEC_OID_RFC1274_UID },
{ "MAIL", 256, SEC_OID_RFC1274_MAIL },
{ "SURNAME", 64, SEC_OID_AVA_SURNAME },
{ "SERIAL", 64, SEC_OID_AVA_SERIAL_NUMBER },
{ "STREET", 128, SEC_OID_AVA_STREET_ADDRESS },
{ "TITLE", 64, SEC_OID_AVA_TITLE },
{ "ADDRESS", 128, SEC_OID_AVA_POSTAL_ADDRESS },
{ "CODE", 40, SEC_OID_AVA_POSTAL_CODE },
{ "BOX", 40, SEC_OID_AVA_POST_OFFICE_BOX },
{ "GIVEN", 64, SEC_OID_AVA_GIVEN_NAME },
{ "INITIALS", 64, SEC_OID_AVA_INITIALS },
{ "GENERATION", 64, SEC_OID_AVA_GENERATION_QUALIFIER },
{ "HOUSE", 64, SEC_OID_AVA_HOUSE_IDENTIFIER },
{ "AKA", 64, SEC_OID_AVA_PSEUDONYM },
{ 0, 256, SEC_OID_UNKNOWN }
/* keywords given in RFC 2253 */
{ "CN", 64, SEC_OID_AVA_COMMON_NAME },
{ "L", 128, SEC_OID_AVA_LOCALITY },
{ "ST", 128, SEC_OID_AVA_STATE_OR_PROVINCE },
{ "O", 64, SEC_OID_AVA_ORGANIZATION_NAME },
{ "OU", 64, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME },
{ "C", 2, SEC_OID_AVA_COUNTRY_NAME },
{ "STREET", 128, SEC_OID_AVA_STREET_ADDRESS },
{ "DC", 128, SEC_OID_AVA_DC },
{ "UID", 256, SEC_OID_RFC1274_UID },

#ifndef NSS_STRICT_RFC_2253_KEYWORDS_ONLY
/* NSS legacy keywords */
{ "dnQualifier", 32767, SEC_OID_AVA_DN_QUALIFIER },
{ "E", 128, SEC_OID_PKCS9_EMAIL_ADDRESS },
{ "MAIL", 256, SEC_OID_RFC1274_MAIL },

#ifndef NSS_LEGACY_KEYWORDS_ONLY
/* values from draft-ietf-ldapbis-user-schema-05 */
{ "SN", 64, SEC_OID_AVA_SURNAME },
{ "serialNumber", 64, SEC_OID_AVA_SERIAL_NUMBER },
{ "title", 64, SEC_OID_AVA_TITLE },
{ "postalAddress", 128, SEC_OID_AVA_POSTAL_ADDRESS },
{ "postalCode", 40, SEC_OID_AVA_POSTAL_CODE },
{ "postOfficeBox", 40, SEC_OID_AVA_POST_OFFICE_BOX },
{ "givenName", 64, SEC_OID_AVA_GIVEN_NAME },
{ "initials", 64, SEC_OID_AVA_INITIALS },
{ "generationQualifier", 64, SEC_OID_AVA_GENERATION_QUALIFIER },
{ "houseIdentifier", 64, SEC_OID_AVA_HOUSE_IDENTIFIER },
#if 0 /* removed. Not yet in any IETF draft or RFC. */
{ "pseudonym", 64, SEC_OID_AVA_PSEUDONYM },
#endif
#endif
#endif
{ 0, 256, SEC_OID_UNKNOWN }
};

#define C_DOUBLE_QUOTE '\042'
Expand Down Expand Up @@ -478,22 +493,25 @@ CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen)
int i, reqLen=0;
char *d = dst;
PRBool needsQuoting = PR_FALSE;
char lastC = 0;

/* need to make an initial pass to determine if quoting is needed */
for (i = 0; i < srclen; i++) {
char c = src[i];
reqLen++;
if (SPECIAL_CHAR(c)) {
if (!needsQuoting && (SPECIAL_CHAR(c) ||
(OPTIONAL_SPACE(c) && OPTIONAL_SPACE(lastC)))) {
/* entirety will need quoting */
needsQuoting = PR_TRUE;
}
if (c == C_DOUBLE_QUOTE || c == C_BACKSLASH) {
/* this char will need escaping */
reqLen++;
}
lastC = c;
}
/* if it begins or ends in optional space it needs quoting */
if (srclen > 0 &&
if (!needsQuoting && srclen > 0 &&
(OPTIONAL_SPACE(src[srclen-1]) || OPTIONAL_SPACE(src[0]))) {
needsQuoting = PR_TRUE;
}
Expand Down Expand Up @@ -584,7 +602,7 @@ get_oid_string(SECItem *oid)
PRUint32 one = PR_MIN(n/40, 2); /* never > 2 */
PRUint32 two = n - one * 40;

a = PR_smprintf("%lu.%lu", one, two);
a = PR_smprintf("OID.%lu.%lu", one, two);
if( (char *)NULL == a ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return (char *)NULL;
Expand Down Expand Up @@ -640,6 +658,7 @@ AppendAVA(stringBuf *bufp, CERTAVA *ava)
SECStatus rv;
SECItem *avaValue = NULL;
char *unknownTag = NULL;
PRBool hexValue = PR_FALSE;
char tmpBuf[384];

tag = CERT_GetAVATag(ava);
Expand All @@ -654,6 +673,9 @@ AppendAVA(stringBuf *bufp, CERTAVA *ava)
}
maxLen = n2k->maxLen;

#ifdef NSS_STRICT_RFC_2253_VALUES_ONLY
if (!unknownTag)
#endif
avaValue = CERT_DecodeAVAValue(&ava->value);
if(!avaValue) {
/* the attribute value is not recognized, get the hex value */
Expand All @@ -662,6 +684,7 @@ AppendAVA(stringBuf *bufp, CERTAVA *ava)
if (unknownTag) PR_smprintf_free(unknownTag);
return SECFailure;
}
hexValue = PR_TRUE;
}

/* Check value length */
Expand All @@ -681,8 +704,18 @@ AppendAVA(stringBuf *bufp, CERTAVA *ava)
if (unknownTag) PR_smprintf_free(unknownTag);
tmpBuf[len++] = '=';

/* escape and quote as necessary */
rv = CERT_RFC1485_EscapeAndQuote(tmpBuf+len, sizeof(tmpBuf)-len,
/* escape and quote as necessary - don't quote hex strings */
if (hexValue) {
/* appent avaValue to tmpBuf */
if (avaValue->len + len + 1 > sizeof tmpBuf) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
rv = SECFailure;
} else {
PORT_Strcpy(tmpBuf+len, (char *)avaValue->data);
rv = SECSuccess;
}
} else
rv = CERT_RFC1485_EscapeAndQuote(tmpBuf+len, sizeof(tmpBuf)-len,
(char *)avaValue->data, avaValue->len);
SECITEM_FreeItem(avaValue, PR_TRUE);
if (rv) return SECFailure;
Expand All @@ -694,12 +727,9 @@ AppendAVA(stringBuf *bufp, CERTAVA *ava)
char *
CERT_NameToAscii(CERTName *name)
{
SECStatus rv;
CERTRDN** rdns;
CERTRDN** lastRdn;
CERTRDN** rdn;
CERTAVA** avas;
CERTAVA* ava;
PRBool first = PR_TRUE;
stringBuf strBuf = { NULL, 0, 0 };

Expand All @@ -717,11 +747,19 @@ CERT_NameToAscii(CERTName *name)
* Loop over name contents in _reverse_ RDN order appending to string
*/
for (rdn = lastRdn; rdn >= rdns; rdn--) {
avas = (*rdn)->avas;
while ((ava = *avas++) != NULL) {
/* Put in comma separator */
CERTAVA** avas = (*rdn)->avas;
CERTAVA* ava;
PRBool newRDN = PR_TRUE;

/*
* XXX Do we need to traverse the AVAs in reverse order, too?
*/
while (avas && (ava = *avas++) != NULL) {
SECStatus rv;
/* Put in comma or plus separator */
if (!first) {
rv = AppendStr(&strBuf, ", ");
/* Use of spaces is deprecated in RFC 2253. */
rv = AppendStr(&strBuf, newRDN ? "," : "+");
if (rv) goto loser;
} else {
first = PR_FALSE;
Expand All @@ -730,10 +768,11 @@ CERT_NameToAscii(CERTName *name)
/* Add in tag type plus value into buf */
rv = AppendAVA(&strBuf, ava);
if (rv) goto loser;
newRDN = PR_FALSE;
}
}
return strBuf.buffer;
loser:
loser:
if (strBuf.buffer) {
PORT_Free(strBuf.buffer);
}
Expand Down Expand Up @@ -779,19 +818,16 @@ CERT_GetNameElement(PRArenaPool *arena, CERTName *name, int wantedTag)
{
CERTRDN** rdns;
CERTRDN *rdn;
CERTAVA** avas;
CERTAVA* ava;
char *buf = 0;
int tag;
SECItem *decodeItem = NULL;

rdns = name->rdns;
while ((rdn = *rdns++) != 0) {
avas = rdn->avas;
while ((ava = *avas++) != 0) {
tag = CERT_GetAVATag(ava);
while (rdns && (rdn = *rdns++) != 0) {
CERTAVA** avas = rdn->avas;
CERTAVA* ava;
while (avas && (ava = *avas++) != 0) {
int tag = CERT_GetAVATag(ava);
if ( tag == wantedTag ) {
decodeItem = CERT_DecodeAVAValue(&ava->value);
SECItem *decodeItem = CERT_DecodeAVAValue(&ava->value);
if(!decodeItem) {
return NULL;
}
Expand Down

0 comments on commit feb1697

Please sign in to comment.