Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37039854
en ru br
Репозитории ALT
S:3.93.0-alt1
5.1: 3.12.9.0-alt1.M50P.1
4.1: 3.12.1-alt0.20080628.M41.2
4.0: 3.11.4-alt1
www.altlinux.org/Changes

Группа :: Система/Библиотеки
Пакет: nss

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: nss-3.12.1-CVE-2009-2408.patch
Скачать


Index: mozilla/security/nss/cmd/lib/secutil.c
===================================================================
RCS file: mozilla/security/nss/cmd/lib/secutil.c,v
retrieving revision 1.93
diff -p -u -r1.93 secutil.c
--- mozilla/security/nss/cmd/lib/secutil.c	16 Feb 2009 03:47:16 -0000	1.93
+++ mozilla/security/nss/cmd/lib/secutil.c	14 Mar 2009 04:47:14 -0000
@@ -998,7 +998,6 @@ secu_PrintRawString(FILE *out, SECItem *
 	SECU_Indent(out, level); 
 	column = level*INDENT_MULT;
     }
-    fprintf(out, "\""); column++;
 
     for (i = 0; i < si->len; i++) {
 	unsigned char val = si->data[i];
@@ -1010,7 +1009,6 @@ secu_PrintRawString(FILE *out, SECItem *
 	fprintf(out,"%c", printable[val]); column++;
     }
 
-    fprintf(out, "\""); column++;
     if (column != level*INDENT_MULT || column > 76) {
 	secu_Newline(out);
     }
Index: mozilla/security/nss/lib/certdb/alg1485.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/certdb/alg1485.c,v
retrieving revision 1.31
diff -p -u -r1.31 alg1485.c
--- mozilla/security/nss/lib/certdb/alg1485.c	22 Feb 2009 12:27:33 -0000	1.31
+++ mozilla/security/nss/lib/certdb/alg1485.c	14 Mar 2009 04:47:15 -0000
@@ -111,6 +111,28 @@ static const NameToKind name2kinds[] = {
     { 0,           256, SEC_OID_UNKNOWN                      , 0},
 };
 
+/* Table facilitates conversion of ASCII hex to binary. */
+static const PRInt16 x2b[256] = {
+/* #0x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #1x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #2x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #3x */  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, 
+/* #4x */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #5x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #6x */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #7x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #8x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #9x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #ax */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #bx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #cx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #dx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #ex */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
+/* #fx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+#define IS_HEX(c) (x2b[(PRUint8)(c)] >= 0)
+
 #define C_DOUBLE_QUOTE '\042'
 
 #define C_BACKSLASH '\134'
@@ -140,6 +162,17 @@ static const NameToKind name2kinds[] = {
      ((c) == '=') ||						\
      ((c) == '?'))
 
+/* RFC 2253 says we must escape ",+\"\\<>;=" EXCEPT inside a quoted string.
+ * Inside a quoted string, we only need to escape " and \
+ * We choose to quote strings containing any of those special characters,
+ * so we only need to escape " and \
+ */
+#define NEEDS_ESCAPE(c) \
+    (c == C_DOUBLE_QUOTE || c == C_BACKSLASH)
+
+#define NEEDS_HEX_ESCAPE(c) \
+    ((PRUint8)c < 0x20 || c == 0x7f)
+
 int
 cert_AVAOidTagToMaxLen(SECOidTag tag)
 {
@@ -222,11 +255,12 @@ scanTag(char **pbp, char *endptr, char *
     return SECSuccess;
 }
 
-static SECStatus
+/* Returns the number of bytes in the value. 0 means failure. */
+static int
 scanVal(char **pbp, char *endptr, char *valBuf, int valBufSize)  
 {
     char *bp, *valBufp;
-    int vallen;
+    int vallen = 0;
     PRBool isQuoted;
     
     PORT_Assert(valBufSize > 0);
@@ -235,7 +269,7 @@ scanVal(char **pbp, char *endptr, char *
     skipSpace(pbp, endptr);
     if(*pbp == endptr) {
 	/* nothing left */
-	return SECFailure;
+	return 0;
     }
     
     bp = *pbp;
@@ -250,7 +284,6 @@ scanVal(char **pbp, char *endptr, char *
     }
     
     valBufp = valBuf;
-    vallen = 0;
     while (bp < endptr) {
 	char c = *bp;
 	if (c == C_BACKSLASH) {
@@ -259,7 +292,12 @@ scanVal(char **pbp, char *endptr, char *
 	    if (bp >= endptr) {
 		/* escape charater must appear with paired char */
 		*pbp = bp;
-		return SECFailure;
+		return 0;
+	    }
+	    c = *bp;
+	    if (IS_HEX(c) && (endptr - bp) >= 2 && IS_HEX(bp[1])) {
+		bp++;
+		c = (char)((x2b[(PRUint8)c] << 4) | x2b[(PRUint8)*bp]); 
 	    }
 	} else if (c == '#' && bp == *pbp) {
 	    /* ignore leading #, quotation not required for it. */
@@ -274,27 +312,28 @@ scanVal(char **pbp, char *endptr, char *
         vallen++;
 	if (vallen >= valBufSize) {
 	    *pbp = bp;
-	    return SECFailure;
+	    return 0;
 	}
-	*valBufp++ = *bp++;
+	*valBufp++ = c;
+	bp++;
     }
     
-    /* stip trailing spaces from unquoted values */
+    /* strip trailing spaces from unquoted values */
     if (!isQuoted) {
-	if (valBufp > valBuf) {
-	    valBufp--;
-	    while ((valBufp > valBuf) && OPTIONAL_SPACE(*valBufp)) {
-		valBufp--;
-	    }
-	    valBufp++;
+	while (valBufp > valBuf) {
+	    char c = valBufp[-1];
+	    if (! OPTIONAL_SPACE(c))
+	        break;
+	    --valBufp;
 	}
+	vallen = valBufp - valBuf;
     }
     
     if (isQuoted) {
 	/* insist that we stopped on a double quote */
 	if (*bp != C_DOUBLE_QUOTE) {
 	    *pbp = bp;
-	    return SECFailure;
+	    return 0;
 	}
 	/* skip over the quote and skip optional space */
 	bp++;
@@ -303,37 +342,12 @@ scanVal(char **pbp, char *endptr, char *
     
     *pbp = bp;
     
-    if (valBufp == valBuf) {
-	/* empty value -- not allowed */
-	return SECFailure;
-    }
-    
     /* null-terminate valBuf -- guaranteed at least one space left */
-    *valBufp++ = 0;
+    *valBufp = 0;
     
-    return SECSuccess;
+    return vallen;
 }
 
-static const PRInt16 x2b[256] = 
-{
-/* #0x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #1x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #2x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #3x */  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, 
-/* #4x */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #5x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #6x */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #7x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #8x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #9x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #ax */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #bx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #cx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #dx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #ex */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-/* #fx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-};
-
 /* Caller must set error code upon failure */
 static SECStatus
 hexToBin(PLArenaPool *pool, SECItem * destItem, const char * src, int len)
@@ -379,13 +393,14 @@ ParseRFC1485AVA(PRArenaPool *arena, char
     SECOidTag kind  = SEC_OID_UNKNOWN;
     SECStatus rv    = SECFailure;
     SECItem   derOid = { 0, NULL, 0 };
+    SECItem   derVal = { 0, NULL, 0};
 
     char tagBuf[32];
     char valBuf[384];
 
     PORT_Assert(arena);
-    if (scanTag(pbp, endptr, tagBuf, sizeof(tagBuf)) == SECFailure ||
-	scanVal(pbp, endptr, valBuf, sizeof(valBuf)) == SECFailure) {
+    if (SECSuccess != scanTag(pbp, endptr, tagBuf, sizeof tagBuf) ||
+	!(valLen    = scanVal(pbp, endptr, valBuf, sizeof valBuf))) {
 	goto loser;
     }
 
@@ -423,16 +438,13 @@ ParseRFC1485AVA(PRArenaPool *arena, char
     /* Is this a hex encoding of a DER attribute value ? */
     if ('#' == valBuf[0]) {
     	/* convert attribute value from hex to binary */
-	SECItem  derVal = { 0, NULL, 0};
-	valLen = PORT_Strlen(valBuf+1);
-	rv = hexToBin(arena, &derVal, valBuf + 1, valLen);
+	rv = hexToBin(arena, &derVal, valBuf + 1, valLen - 1);
 	if (rv)
 	    goto loser;
 	a = CERT_CreateAVAFromRaw(arena, &derOid, &derVal);
     } else {
 	if (kind == SEC_OID_UNKNOWN)
 	    goto loser;
-	valLen = PORT_Strlen(valBuf);
 	if (kind == SEC_OID_AVA_COUNTRY_NAME && valLen != 2)
 	    goto loser;
 	if (vt == SEC_ASN1_PRINTABLE_STRING &&
@@ -446,7 +458,9 @@ ParseRFC1485AVA(PRArenaPool *arena, char
 		vt = SEC_ASN1_UTF8_STRING;
 	}
 
-	a = CERT_CreateAVA(arena, kind, vt, (char *)valBuf);
+	derVal.data = valBuf;
+	derVal.len  = valLen;
+	a = CERT_CreateAVAFromSECItem(arena, kind, vt, &derVal);
     }
     return a;
 
@@ -580,10 +594,26 @@ AppendStr(stringBuf *bufp, char *str)
     return SECSuccess;
 }
 
+typedef enum {
+    minimalEscape = 0,		/* only hex escapes, and " and \ */
+    minimalEscapeAndQuote,	/* as above, plus quoting        */
+    fullEscape                  /* no quoting, full escaping     */
+} EQMode;
+
+/* Some characters must be escaped as a hex string, e.g. c -> \nn .
+ * Others must be escaped by preceeding with a '\', e.g. c -> \c , but
+ * there are certain "special characters" that may be handled by either
+ * escaping them, or by enclosing the entire attribute value in quotes.
+ * A NULL value for pEQMode implies selecting minimalEscape mode.
+ * Some callers will do quoting when needed, others will not.
+ * If a caller selects minimalEscapeAndQuote, and the string does not
+ * need quoting, then this function changes it to minimalEscape.
+ */
 static int
-cert_RFC1485_GetRequiredLen(const char *src, int srclen, PRBool *pNeedsQuoting)
+cert_RFC1485_GetRequiredLen(const char *src, int srclen, EQMode *pEQMode)
 {
     int i, reqLen=0;
+    EQMode mode = pEQMode ? *pEQMode : minimalEscape;
     PRBool needsQuoting = PR_FALSE;
     char lastC = 0;
 
@@ -591,70 +621,91 @@ cert_RFC1485_GetRequiredLen(const char *
     for (i = 0; i < srclen; i++) {
 	char c = src[i];
 	reqLen++;
-	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 */
+	if (NEEDS_HEX_ESCAPE(c)) {      /* c -> \xx  */
+	    reqLen += 2;
+	} else if (NEEDS_ESCAPE(c)) {   /* c -> \c   */
 	    reqLen++;
+	} else if (SPECIAL_CHAR(c)) {
+	    if (mode == minimalEscapeAndQuote) /* quoting is allowed */
+		needsQuoting = PR_TRUE; /* entirety will need quoting */
+	    else if (mode == fullEscape)
+	    	reqLen++;               /* MAY escape this character */
+	} else if (OPTIONAL_SPACE(c) && OPTIONAL_SPACE(lastC)) {
+	    if (mode == minimalEscapeAndQuote) /* quoting is allowed */
+		needsQuoting = PR_TRUE; /* entirety will need quoting */
 	}
 	lastC = c;
     }
     /* if it begins or ends in optional space it needs quoting */
-    if (!needsQuoting && srclen > 0 && 
+    if (!needsQuoting && srclen > 0 && mode == minimalEscapeAndQuote && 
 	(OPTIONAL_SPACE(src[srclen-1]) || OPTIONAL_SPACE(src[0]))) {
 	needsQuoting = PR_TRUE;
     }
 
     if (needsQuoting) 
     	reqLen += 2;
-    if (pNeedsQuoting)
-    	*pNeedsQuoting = needsQuoting;
-
+    if (pEQMode && mode == minimalEscapeAndQuote && !needsQuoting)
+    	*pEQMode = minimalEscape;
     return reqLen;
 }
 
-SECStatus
-CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen)
+static const char hexChars[16] = { "0123456789abcdef" };
+
+static SECStatus
+escapeAndQuote(char *dst, int dstlen, char *src, int srclen, EQMode *pEQMode)
 {
     int i, reqLen=0;
-    char *d = dst;
-    PRBool needsQuoting = PR_FALSE;
+    EQMode mode = pEQMode ? *pEQMode : minimalEscape;
 
     /* space for terminal null */
-    reqLen = cert_RFC1485_GetRequiredLen(src, srclen, &needsQuoting) + 1;
+    reqLen = cert_RFC1485_GetRequiredLen(src, srclen, &mode) + 1;
     if (reqLen > dstlen) {
 	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
 	return SECFailure;
     }
 
-    d = dst;
-    if (needsQuoting) *d++ = C_DOUBLE_QUOTE;
+    if (mode == minimalEscapeAndQuote)
+        *dst++ = C_DOUBLE_QUOTE;
     for (i = 0; i < srclen; i++) {
 	char c = src[i];
-	if (c == C_DOUBLE_QUOTE || c == C_BACKSLASH) {
-	    /* escape it */
-	    *d++ = C_BACKSLASH;
+	if (NEEDS_HEX_ESCAPE(c)) {
+	    *dst++ = C_BACKSLASH;
+	    *dst++ = hexChars[ (c >> 4) & 0x0f ];
+	    *dst++ = hexChars[  c       & 0x0f ];
+	} else {
+	    if (NEEDS_ESCAPE(c) || (SPECIAL_CHAR(c) && mode == fullEscape)) {
+		*dst++ = C_BACKSLASH;
+		*dst++ = c;
+	    }
+	    *dst++ = c;
 	}
-	*d++ = c;
     }
-    if (needsQuoting) *d++ = C_DOUBLE_QUOTE;
-    *d++ = 0;
+    if (mode == minimalEscapeAndQuote)
+    	*dst++ = C_DOUBLE_QUOTE;
+    *dst++ = 0;
+    if (pEQMode)
+    	*pEQMode = mode;
     return SECSuccess;
 }
 
+SECStatus
+CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen)
+{
+    EQMode mode = minimalEscapeAndQuote;
+    return escapeAndQuote(dst, dstlen, src, srclen, &mode);
+}
+
+
 /* convert an OID to dotted-decimal representation */
 /* Returns a string that must be freed with PR_smprintf_free(), */
 char *
 CERT_GetOidString(const SECItem *oid)
 {
-    PRUint8 *end;
-    PRUint8 *d;
-    PRUint8 *e;
-    char *a         = NULL;
-    char *b;
+    PRUint8 *stop;   /* points to first byte after OID string */
+    PRUint8 *first;  /* byte of an OID component integer      */
+    PRUint8 *last;   /* byte of an OID component integer      */
+    char *rvString   = NULL;
+    char *prefix     = NULL;
 
 #define MAX_OID_LEN 1024 /* bytes */
 
@@ -663,75 +714,113 @@ CERT_GetOidString(const SECItem *oid)
 	return NULL;
     }
 
-    /* d will point to the next sequence of bytes to decode */
-    d = (PRUint8 *)oid->data;
-    /* end points to one past the legitimate data */
-    end = &d[ oid->len ];
+    /* first will point to the next sequence of bytes to decode */
+    first = (PRUint8 *)oid->data;
+    /* stop points to one past the legitimate data */
+    stop = &first[ oid->len ];
 
     /*
      * Check for our pseudo-encoded single-digit OIDs
      */
-    if( (*d == 0x80) && (2 == oid->len) ) {
+    if ((*first == 0x80) && (2 == oid->len)) {
 	/* Funky encoding.  The second byte is the number */
-	a = PR_smprintf("%lu", (PRUint32)d[1]);
-	if( (char *)NULL == a ) {
+	rvString = PR_smprintf("%lu", (PRUint32)first[1]);
+	if (!rvString) {
 	    PORT_SetError(SEC_ERROR_NO_MEMORY);
-	    return (char *)NULL;
 	}
-	return a;
+	return rvString;
     }
 
-    for( ; d < end; d = &e[1] ) {
+    for (; first < stop; first = last + 1) {
+    	unsigned int bytesBeforeLast;
     
-	for( e = d; e < end; e++ ) {
-	    if( 0 == (*e & 0x80) ) {
+	for (last = first; last < stop; last++) {
+	    if (0 == (*last & 0x80)) {
 		break;
 	    }
 	}
-    
-	if( ((e-d) > 4) || (((e-d) == 4) && (*d & 0x70)) ) {
-	    /* More than a 32-bit number */
-	} else {
+	bytesBeforeLast = (unsigned int)(last - first);
+	if (bytesBeforeLast <= 3U) {        /* 0-28 bit number */
 	    PRUint32 n = 0;
-      
-	    switch( e-d ) {
-	    case 4:
-		n |= ((PRUint32)(e[-4] & 0x0f)) << 28;
-	    case 3:
-		n |= ((PRUint32)(e[-3] & 0x7f)) << 21;
-	    case 2:
-		n |= ((PRUint32)(e[-2] & 0x7f)) << 14;
-	    case 1:
-		n |= ((PRUint32)(e[-1] & 0x7f)) <<  7;
-	    case 0:
-		n |= ((PRUint32)(e[-0] & 0x7f))      ;
+	    PRUint32 c;
+
+#define CGET(i, m) \
+		c  = last[-i] & m; \
+		n |= c << (7 * i)
+
+#define CASE(i, m) \
+	    case i:                      \
+		CGET(i, m);              \
+		if (!n) goto unsupported \
+		/* fall-through */
+
+	    switch (bytesBeforeLast) {
+	    CASE(3, 0x7f);
+	    CASE(2, 0x7f);
+	    CASE(1, 0x7f);
+	    case 0: n |= last[0]; /* most significant bit is zero. */
+		break;
 	    }
       
-	    if( (char *)NULL == a ) {
+	    if (!rvString) {
 		/* This is the first number.. decompose it */
 		PRUint32 one = PR_MIN(n/40, 2); /* never > 2 */
-		PRUint32 two = n - one * 40;
+		PRUint32 two = n - (one * 40);
         
-		a = PR_smprintf("OID.%lu.%lu", one, two);
-		if( (char *)NULL == a ) {
-		    PORT_SetError(SEC_ERROR_NO_MEMORY);
-		    return (char *)NULL;
-		}
+		rvString = PR_smprintf("OID.%lu.%lu", one, two);
 	    } else {
-		b = PR_smprintf("%s.%lu", a, n);
-		if( (char *)NULL == b ) {
-		    PR_smprintf_free(a);
-		    PORT_SetError(SEC_ERROR_NO_MEMORY);
-		    return (char *)NULL;
-		}
+		prefix = rvString;
+		rvString = PR_smprintf("%s.%lu", prefix, n);
+	    }
+	} else if (bytesBeforeLast <= 9U) { /* 29-64 bit number */
+	    PRUint64 n = 0;
+	    PRUint64 c;
+
+	    switch (bytesBeforeLast) {
+	    CASE(9, 0x01);
+	    CASE(8, 0x7f);
+	    CASE(7, 0x7f);
+	    CASE(6, 0x7f);
+	    CASE(5, 0x7f);
+	    CASE(4, 0x7f);
+	    CGET(3, 0x7f);
+	    CGET(2, 0x7f);
+	    CGET(1, 0x7f);
+	        n |= last[0]; /* most significant bit is zero. */
+		break;
+	    }
+      
+	    if (!rvString) {
+		/* This is the first number.. decompose it */
+		PRUint64 one = PR_MIN(n/40, 2); /* never > 2 */
+		PRUint64 two = n - (one * 40);
         
-		PR_smprintf_free(a);
-		a = b;
+		rvString = PR_smprintf("OID.%llu.%llu", one, two);
+	    } else {
+		prefix = rvString;
+		rvString = PR_smprintf("%s.%llu", prefix, n);
+	    }
+	} else {
+	    /* More than a 64-bit number, or not minimal encoding. */
+unsupported:
+	    if (!rvString)
+		rvString = PR_smprintf("OID.UNSUPPORTED");
+	    else {
+		prefix = rvString;
+		rvString = PR_smprintf("%s.UNSUPPORTED", prefix);
 	    }
 	}
-    }
 
-    return a;
+	if (prefix) {
+	    PR_smprintf_free(prefix);
+	    prefix = NULL;
+	}
+	if (!rvString) {
+	    PORT_SetError(SEC_ERROR_NO_MEMORY);
+	    break;
+	}
+    }
+    return rvString;
 }
 
 /* convert DER-encoded hex to a string */
@@ -826,6 +915,7 @@ AppendAVA(stringBuf *bufp, CERTAVA *ava,
     SECStatus    rv;
     unsigned int len;
     int          nameLen, valueLen;
+    EQMode       mode        = minimalEscapeAndQuote;
     NameToKind   n2k         = { NULL, 32767, SEC_OID_UNKNOWN, SEC_ASN1_DS };
     char         tmpBuf[384];
 
@@ -907,7 +997,8 @@ AppendAVA(stringBuf *bufp, CERTAVA *ava,
 
     nameLen  = strlen(tagName);
     valueLen = (useHex ? avaValue->len : 
-            cert_RFC1485_GetRequiredLen(avaValue->data, avaValue->len, NULL));
+		cert_RFC1485_GetRequiredLen(avaValue->data, avaValue->len, 
+					    &mode));
     len = nameLen + valueLen + 2; /* Add 2 for '=' and trailing NUL */
 
     if (len <= sizeof(tmpBuf)) {
@@ -934,8 +1025,8 @@ AppendAVA(stringBuf *bufp, CERTAVA *ava,
 	encodedAVA[nameLen + avaValue->len] = '\0';
 	rv = SECSuccess;
     } else 
-	rv = CERT_RFC1485_EscapeAndQuote(encodedAVA + nameLen, len - nameLen, 
-		    		        (char *)avaValue->data, avaValue->len);
+	rv = escapeAndQuote(encodedAVA + nameLen, len - nameLen, 
+		    	    (char *)avaValue->data, avaValue->len, &mode);
     SECITEM_FreeItem(avaValue, PR_TRUE);
     if (rv == SECSuccess)
 	rv = AppendStr(bufp, encodedAVA);
@@ -990,7 +1081,7 @@ CERT_NameToAsciiInvertible(CERTName *nam
 		first = PR_FALSE;
 	    }
 	    
-	    /* Add in tag type plus value into buf */
+	    /* Add in tag type plus value into strBuf */
 	    rv = AppendAVA(&strBuf, ava, strict);
 	    if (rv) goto loser;
 	    newRDN = PR_FALSE;
@@ -1044,44 +1135,58 @@ loser:
     return(retstr);
 }
 
+static char *
+avaToString(PRArenaPool *arena, CERTAVA *ava)
+{
+    char *    buf       = NULL;
+    SECItem*  avaValue;
+    int       valueLen;
+
+    avaValue = CERT_DecodeAVAValue(&ava->value);
+    if(!avaValue) {
+	return buf;
+    }
+    valueLen = cert_RFC1485_GetRequiredLen(avaValue->data, avaValue->len, 
+					   NULL) + 1;
+    if (arena) {
+	buf = (char *)PORT_ArenaZAlloc(arena, valueLen);
+    } else {
+	buf = (char *)PORT_ZAlloc(valueLen);
+    }
+    if (buf) {
+	SECStatus rv = escapeAndQuote(buf, valueLen, (char *)avaValue->data, 
+	                              avaValue->len, NULL);
+	if (rv != SECSuccess) {
+	    if (!arena)
+		PORT_Free(buf);
+	    buf = NULL;
+	}
+    }
+    SECITEM_FreeItem(avaValue, PR_TRUE);
+    return buf;
+}
+
 /* RDNs are sorted from most general to most specific.
  * This code returns the FIRST one found, the most general one found.
  */
 static char *
 CERT_GetNameElement(PRArenaPool *arena, CERTName *name, int wantedTag)
 {
-    CERTRDN** rdns;
-    CERTRDN *rdn;
-    char *buf = 0;
-    
-    rdns = name->rdns;
+    CERTRDN** rdns = name->rdns;
+    CERTRDN*  rdn;
+    CERTAVA*  ava  = NULL;
+
     while (rdns && (rdn = *rdns++) != 0) {
 	CERTAVA** avas = rdn->avas;
-	CERTAVA*  ava;
 	while (avas && (ava = *avas++) != 0) {
 	    int tag = CERT_GetAVATag(ava);
 	    if ( tag == wantedTag ) {
-		SECItem *decodeItem = CERT_DecodeAVAValue(&ava->value);
-		if(!decodeItem) {
-		    return NULL;
-		}
-		if (arena) {
-		    buf = (char *)PORT_ArenaZAlloc(arena,decodeItem->len + 1);
-		} else {
-		    buf = (char *)PORT_ZAlloc(decodeItem->len + 1);
-		}
-		if ( buf ) {
-		    PORT_Memcpy(buf, decodeItem->data, decodeItem->len);
-		    buf[decodeItem->len] = 0;
-		}
-		SECITEM_FreeItem(decodeItem, PR_TRUE);
-		goto done;
+		avas = NULL;
+		rdns = NULL; /* break out of all loops */
 	    }
 	}
     }
-    
-  done:
-    return buf;
+    return ava ? avaToString(arena, ava) : NULL;
 }
 
 /* RDNs are sorted from most general to most specific.
@@ -1091,12 +1196,10 @@ CERT_GetNameElement(PRArenaPool *arena, 
 static char *
 CERT_GetLastNameElement(PRArenaPool *arena, CERTName *name, int wantedTag)
 {
-    CERTRDN** rdns;
-    CERTRDN *rdn;
-    CERTAVA * lastAva = NULL;
-    char *buf = 0;
+    CERTRDN** rdns    = name->rdns;
+    CERTRDN*  rdn;
+    CERTAVA*  lastAva = NULL;
     
-    rdns = name->rdns;
     while (rdns && (rdn = *rdns++) != 0) {
 	CERTAVA** avas = rdn->avas;
 	CERTAVA*  ava;
@@ -1107,24 +1210,7 @@ CERT_GetLastNameElement(PRArenaPool *are
 	    }
 	}
     }
-
-    if (lastAva) {
-	SECItem *decodeItem = CERT_DecodeAVAValue(&lastAva->value);
-	if(!decodeItem) {
-	    return NULL;
-	}
-	if (arena) {
-	    buf = (char *)PORT_ArenaZAlloc(arena,decodeItem->len + 1);
-	} else {
-	    buf = (char *)PORT_ZAlloc(decodeItem->len + 1);
-	}
-	if ( buf ) {
-	    PORT_Memcpy(buf, decodeItem->data, decodeItem->len);
-	    buf[decodeItem->len] = 0;
-	}
-	SECITEM_FreeItem(decodeItem, PR_TRUE);
-    }    
-    return buf;
+    return lastAva ? avaToString(arena, lastAva) : NULL;
 }
 
 char *
Index: mozilla/security/nss/lib/certdb/certi.h
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/certdb/certi.h,v
retrieving revision 1.27
diff -p -u -r1.27 certi.h
--- mozilla/security/nss/lib/certdb/certi.h	31 Oct 2008 23:02:36 -0000	1.27
+++ mozilla/security/nss/lib/certdb/certi.h	14 Mar 2009 04:47:15 -0000
@@ -249,6 +249,10 @@ extern int cert_AVAOidTagToMaxLen(SECOid
 extern CERTAVA * CERT_CreateAVAFromRaw(PRArenaPool *pool, 
                                const SECItem * OID, const SECItem * value);
 
+/* Make an AVA from binary input specified by SECItem */
+extern CERTAVA * CERT_CreateAVAFromSECItem(PRArenaPool *arena, SECOidTag kind, 
+                                           int valueType, SECItem *value);
+
 /*
  * get a DPCache object for the given issuer subject and dp
  * Automatically creates the cache object if it doesn't exist yet.
Index: mozilla/security/lib/certdb/secname.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/certdb/secname.c,v
retrieving revision 1.24
diff -p -u -r1.24 secname.c
--- mozilla/security/nss/lib/certdb/secname.c	6 Jun 2008 01:15:18 -0000	1.24
+++ mozilla/security/nss/lib/certdb/secname.c	14 Mar 2009 04:47:15 -0000
@@ -149,31 +149,30 @@ SetupAVAType(PRArenaPool *arena, SECOidT
 }
 
 static SECStatus
-SetupAVAValue(PRArenaPool *arena, int valueType, char *value, SECItem *it,
-	      unsigned maxLen)
+SetupAVAValue(PRArenaPool *arena, int valueType, const SECItem *in, 
+              SECItem *out, unsigned maxLen)
 {
+    PRUint8 *value, *cp, *ucs4Val;
     unsigned valueLen, valueLenLen, total;
     unsigned ucs4Len = 0, ucs4MaxLen;
-    unsigned char *cp, *ucs4Val;
 
+    value    = in->data;
+    valueLen = in->len;
     switch (valueType) {
       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:
-	valueLen = PORT_Strlen(value);
 	ucs4MaxLen = valueLen * 6;
-	ucs4Val = (unsigned char *)PORT_ArenaZAlloc(arena, ucs4MaxLen);
-	if(!ucs4Val || !PORT_UCS4_UTF8Conversion(PR_TRUE, 
-	                                (unsigned char *)value, valueLen,
+	ucs4Val = (PRUint8 *)PORT_ArenaZAlloc(arena, ucs4MaxLen);
+	if(!ucs4Val || !PORT_UCS4_UTF8Conversion(PR_TRUE, value, valueLen,
 					ucs4Val, ucs4MaxLen, &ucs4Len)) {
 	    PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	    return SECFailure;
 	}
-	value = (char *)ucs4Val;
+	value = ucs4Val;
 	valueLen = ucs4Len;
     	maxLen *= 4;
 	break;
@@ -189,12 +188,13 @@ SetupAVAValue(PRArenaPool *arena, int va
 
     valueLenLen = DER_LengthLength(valueLen);
     total = 1 + valueLenLen + valueLen;
-    it->data = cp = (unsigned char*) PORT_ArenaAlloc(arena, total);
+    cp = (PRUint8*)PORT_ArenaAlloc(arena, total);
     if (!cp) {
 	return SECFailure;
     }
-    it->len = total;
-    cp = (unsigned char*) DER_StoreHeader(cp, valueType, valueLen);
+    out->data = cp;
+    out->len  = total;
+    cp = (PRUint8 *)DER_StoreHeader(cp, valueType, valueLen);
     PORT_Memcpy(cp, value, valueLen);
     return SECSuccess;
 }
@@ -220,7 +220,8 @@ CERT_CreateAVAFromRaw(PRArenaPool *pool,
 }
 
 CERTAVA *
-CERT_CreateAVA(PRArenaPool *arena, SECOidTag kind, int valueType, char *value)
+CERT_CreateAVAFromSECItem(PRArenaPool *arena, SECOidTag kind, int valueType, 
+                          SECItem *value)
 {
     CERTAVA *ava;
     int rv;
@@ -231,18 +232,29 @@ CERT_CreateAVA(PRArenaPool *arena, SECOi
 	rv = SetupAVAType(arena, kind, &ava->type, &maxLen);
 	if (rv) {
 	    /* Illegal AVA type */
-	    return 0;
+	    return NULL;
 	}
 	rv = SetupAVAValue(arena, valueType, value, &ava->value, maxLen);
 	if (rv) {
 	    /* Illegal value type */
-	    return 0;
+	    return NULL;
 	}
     }
     return ava;
 }
 
 CERTAVA *
+CERT_CreateAVA(PRArenaPool *arena, SECOidTag kind, int valueType, char *value)
+{
+    SECItem item = { siBuffer, NULL, 0 };
+
+    item.data = (PRUint8 *)value;
+    item.len  = PORT_Strlen(value);
+
+    return CERT_CreateAVAFromSECItem(arena, kind, valueType, &item);
+}
+
+CERTAVA *
 CERT_CopyAVA(PRArenaPool *arena, CERTAVA *from)
 {
     CERTAVA *ava;
Index: mozilla/security/nss/lib/certdb/alg1485.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/certdb/alg1485.c,v
retrieving revision 1.32
diff -p -u -r1.32 alg1485.c
--- mozilla/security/nss/lib/certdb/alg1485.c	17 Mar 2009 07:30:10 -0000	1.32
+++ mozilla/security/nss/lib/certdb/alg1485.c	18 Mar 2009 20:54:26 -0000
@@ -675,7 +675,6 @@ escapeAndQuote(char *dst, int dstlen, ch
 	} else {
 	    if (NEEDS_ESCAPE(c) || (SPECIAL_CHAR(c) && mode == fullEscape)) {
 		*dst++ = C_BACKSLASH;
-		*dst++ = c;
 	    }
 	    *dst++ = c;
 	}
Index: mozilla/security/nss/lib/certdb/alg1485.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/certdb/alg1485.c,v
retrieving revision 1.33
diff -p -u -5 -r1.33 alg1485.c
--- mozilla/security/nss/lib/certdb/alg1485.c	18 Mar 2009 23:14:45 -0000	1.33
+++ mozilla/security/nss/lib/certdb/alg1485.c	11 Apr 2009 20:02:35 -0000
@@ -755,13 +755,15 @@ CERT_GetOidString(const SECItem *oid)
 
 	    switch (bytesBeforeLast) {
 	    CASE(3, 0x7f);
 	    CASE(2, 0x7f);
 	    CASE(1, 0x7f);
-	    case 0: n |= last[0]; /* most significant bit is zero. */
+	    CGET(0, 0x7f);
 		break;
 	    }
+	    if (last[0] & 0x80)
+	    	goto unsupported;
       
 	    if (!rvString) {
 		/* This is the first number.. decompose it */
 		PRUint32 one = PR_MIN(n/40, 2); /* never > 2 */
 		PRUint32 two = n - (one * 40);
@@ -783,13 +785,15 @@ CERT_GetOidString(const SECItem *oid)
 	    CASE(5, 0x7f);
 	    CASE(4, 0x7f);
 	    CGET(3, 0x7f);
 	    CGET(2, 0x7f);
 	    CGET(1, 0x7f);
-	        n |= last[0]; /* most significant bit is zero. */
+	    CGET(0, 0x7f);
 		break;
 	    }
+	    if (last[0] & 0x80)
+	    	goto unsupported;
       
 	    if (!rvString) {
 		/* This is the first number.. decompose it */
 		PRUint64 one = PR_MIN(n/40, 2); /* never > 2 */
 		PRUint64 two = n - (one * 40);
Index: mozilla/security/nss/lib/certdb/alg1485.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/certdb/alg1485.c,v
retrieving revision 1.35
diff -p -u -r1.35 alg1485.c
--- mozilla/security/nss/lib/certdb/alg1485.c	12 Apr 2009 04:34:00 -0000	1.35
+++ mozilla/security/nss/lib/certdb/alg1485.c	12 Apr 2009 05:38:39 -0000
@@ -757,7 +757,7 @@ CERT_GetOidString(const SECItem *oid)
 	    CASE(3, 0x7f);
 	    CASE(2, 0x7f);
 	    CASE(1, 0x7f);
-	    CGET(0, 0x7f);
+	    case 0: n |= last[0] & 0x7f;
 		break;
 	    }
 	    if (last[0] & 0x80)
Index: mozilla/security/nss/lib/certdb/cert.h
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/certdb/cert.h,v
retrieving revision 1.75
diff -p -u -r1.75 cert.h
--- mozilla/security/nss/lib/certdb/cert.h	21 Nov 2008 21:02:38 -0000	1.75
+++ mozilla/security/nss/lib/certdb/cert.h	19 Mar 2009 14:39:57 -0000
@@ -174,6 +174,17 @@ extern char *CERT_FormatName (CERTName *
 */
 extern char *CERT_Hexify (SECItem *i, int do_colon);
 
+/*
+** Converts DER string (with explicit length) into zString, if destination 
+** buffer is big enough to receive it.  Does quoting and/or escaping as 
+** specified in RFC 1485.  Input string must be single or multi-byte DER
+** character set, (ASCII, UTF8, or ISO 8851-x) not a wide character set.
+** Returns SECSuccess or SECFailure with error code set. If output buffer
+** is too small, sets error code SEC_ERROR_OUTPUT_LEN.
+*/
+extern SECStatus
+CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen);
+
 /******************************************************************************
  *
  * Certificate handling operations
Index: mozilla/security/nss/lib/certdb/certdb.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/certdb/certdb.c,v
retrieving revision 1.98
diff -p -u -r1.98 certdb.c
--- mozilla/security/nss/lib/certdb/certdb.c	12 Mar 2009 08:53:51 -0000	1.98
+++ mozilla/security/nss/lib/certdb/certdb.c	19 Mar 2009 14:39:57 -0000
@@ -1552,15 +1552,18 @@ cert_VerifySubjectAltName(CERTCertificat
 		** so must copy it.  
 		*/
 		int cnLen = current->name.other.len;
-		if (cnLen + 1 > cnBufLen) {
-		    cnBufLen = cnLen + 1;
+		rv = CERT_RFC1485_EscapeAndQuote(cn, cnBufLen, 
+					    current->name.other.data, cnLen);
+		if (rv != SECSuccess && PORT_GetError == SEC_ERROR_OUTPUT_LEN) {
+		    cnBufLen = cnLen * 3 + 3; /* big enough for worst case */
 		    cn = (char *)PORT_ArenaAlloc(arena, cnBufLen);
 		    if (!cn)
 			goto fail;
+		    rv = CERT_RFC1485_EscapeAndQuote(cn, cnBufLen, 
+					    current->name.other.data, cnLen);
 		}
-		PORT_Memcpy(cn, current->name.other.data, cnLen);
-		cn[cnLen] = 0;
-		rv = cert_TestHostName(cn ,hn);
+		if (rv == SECSuccess)
+		    rv = cert_TestHostName(cn ,hn);
 		if (rv == SECSuccess)
 		    goto finish;
 	    }
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin