Sophie

Sophie

distrib > Mandriva > 2009.1 > x86_64 > by-pkgid > e7f854c7f1514285c4f4ff5c808c3926 > files > 4

libneon0.26-0.26.4-6.2mdv2009.1.src.rpm

diff -r b27f0c82a840 src/ne_openssl.c
--- a/src/ne_openssl.c	Wed Sep 02 13:25:47 2009 -0300
+++ b/src/ne_openssl.c	Wed Sep 02 14:13:06 2009 -0300
@@ -215,23 +215,20 @@ void ne_ssl_cert_validity_time(const ne_
 /* Return non-zero if hostname from certificate (cn) matches hostname
  * used for session (hostname).  (Wildcard matching is no longer
  * mandated by RFC3280, but certs are deployed which use wildcards) */
-static int match_hostname(char *cn, const char *hostname)
+static int match_hostname(const char *cn, size_t cnlen, const char *hostname)
 {
     const char *dot;
-    NE_DEBUG(NE_DBG_SSL, "Match %s on %s...\n", cn, hostname);
-    dot = strchr(hostname, '.');
-    if (dot == NULL) {
-	char *pnt = strchr(cn, '.');
-	/* hostname is not fully-qualified; unqualify the cn. */
-	if (pnt != NULL) {
-	    *pnt = '\0';
-	}
+
+    NE_DEBUG(NE_DBG_SSL, "ssl: Match common name '%s' against '%s'\n",
+             cn, hostname);
+
+    if (strncmp(cn, "*.", 2) == 0 && cnlen > 2
+        && (dot = strchr(hostname, '.')) != NULL) {
+       hostname = dot + 1;
+       cn += 2;
+       cnlen -= 2;
     }
-    else if (strncmp(cn, "*.", 2) == 0) {
-	hostname = dot + 1;
-	cn += 2;
-    }
-    return !ne_strcasecmp(cn, hostname);
+    return cnlen == strlen(hostname) && !ne_strcasecmp(cn, hostname);
 }
 
 /* Check certificate identity.  Returns zero if identity matches; 1 if
@@ -255,7 +252,7 @@ static int check_identity(const char *ho
 	    if (nm->type == GEN_DNS) {
 		char *name = dup_ia5string(nm->d.ia5);
                 if (identity && !found) *identity = ne_strdup(name);
-		match = match_hostname(name, hostname);
+		match = match_hostname(name, nm->d.ia5->length, hostname);
 		ne_free(name);
 		found = 1;
             } else if (nm->type == GEN_IPADD) {
@@ -314,7 +311,7 @@ static int check_identity(const char *ho
             return -1;
         }
         if (identity) *identity = ne_strdup(cname->data);
-        match = match_hostname(cname->data, hostname);
+        match = match_hostname(cname->data, cname->length, hostname);
         ne_buffer_destroy(cname);
     }
 
diff -r b27f0c82a840 src/ne_string.c
--- a/src/ne_string.c	Wed Sep 02 13:25:47 2009 -0300
+++ b/src/ne_string.c	Wed Sep 02 14:13:06 2009 -0300
@@ -36,10 +36,10 @@
 
 #include <stdio.h>
 
-#include <ctype.h> /* for isprint() etc in ne_strclean() */
-
 #include "ne_alloc.h"
 #include "ne_string.h"
+/* hack for 0.28.x backport of ne_strnqdup, ne_buffer_qappend */
+#include "ne_private.h"
 
 char *ne_token(char **str, char separator)
 {
@@ -239,6 +239,98 @@ void ne_buffer_altered(ne_buffer *buf)
     buf->used = strlen(buf->data) + 1;
 }
 
+/* ascii_quote[n] gives the number of bytes needed by
+ * ne_buffer_qappend() to append character 'n'. */
+static const unsigned char ascii_quote[256] = {
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+};
+
+static const char hex_chars[16] = "0123456789ABCDEF";
+
+/* Return the expected number of bytes needed to append the string
+ * beginning at byte 's', where 'send' points to the last byte after
+ * 's'. */ 
+static size_t qappend_count(const unsigned char *s, const unsigned char *send)
+{
+    const unsigned char *p;
+    size_t ret;
+    
+    for (p = s, ret = 0; p < send; p++) {
+        ret += ascii_quote[*p];
+    }
+
+    return ret;
+}       
+
+/* Append the string 's', up to but not including 'send', to string
+ * 'dest', quoting along the way.  Returns pointer to NUL. */
+static char *quoted_append(char *dest, const unsigned char *s, 
+                           const unsigned char *send)
+{
+    const unsigned char *p;
+    char *q = dest;
+
+    for (p = s; p < send; p++) {
+        if (ascii_quote[*p] == 1) {
+            *q++ = *p;
+        }
+        else {
+            *q++ = '\\';
+            *q++ = 'x';
+            *q++ = hex_chars[(*p >> 4) & 0x0f];
+            *q++ = hex_chars[*p & 0x0f];
+        }
+    }
+
+    /* NUL terminate after the last character */
+    *q = '\0';
+    
+    return q;
+}
+
+void ne__buffer_qappend(ne_buffer *buf, const unsigned char *data, size_t len)
+{
+    const unsigned char *dend = data + len;
+    char *q, *qs;
+
+    ne_buffer_grow(buf, buf->used + qappend_count(data, dend));
+
+    /* buf->used >= 1, so this is safe. */
+    qs = buf->data + buf->used - 1;
+
+    q = quoted_append(qs, data, dend);
+    
+    /* used already accounts for a NUL, so increment by number of
+     * characters appended, *before* the NUL. */
+    buf->used += q - qs;
+}
+
+char *ne__strnqdup(const unsigned char *data, size_t len)
+{
+    const unsigned char *dend = data + len;
+    char *dest = malloc(qappend_count(data, dend) + 1);
+
+    quoted_append(dest, data, dend);
+
+    return dest;
+}
+
+
 static const char b64_alphabet[] =  
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     "abcdefghijklmnopqrstuvwxyz"
@@ -332,11 +424,50 @@ size_t ne_unbase64(const char *data, uns
     return outp - *out;
 }
 
+/* Character map array; ascii_clean[n] = isprint(n) ? n : 0x20.  Used
+ * by ne_strclean as a locale-independent isprint(). */
+static const unsigned char ascii_clean[256] = {
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 
+    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 
+    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
+    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
+    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 
+    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 
+    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 
+    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
+    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
+    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
+};
+
 char *ne_strclean(char *str)
 {
-    char *pnt;
-    for (pnt = str; *pnt; pnt++)
-        if (iscntrl(*pnt) || !isprint(*pnt)) *pnt = ' ';
+    unsigned char *pnt;
+
+    for (pnt = (unsigned char *)str; *pnt; pnt++)
+        *pnt = (char)ascii_clean[*pnt];
+
     return str;
 }
 
diff -r b27f0c82a840 src/ne_xml.c
--- a/src/ne_xml.c	Wed Sep 02 13:25:47 2009 -0300
+++ b/src/ne_xml.c	Wed Sep 02 14:13:06 2009 -0300
@@ -405,6 +405,28 @@ static void end_element(void *userdata, 
     destroy_element(elm);
 }
 
+#if defined(HAVE_EXPAT) && XML_MAJOR_VERSION > 1
+/* Stop the parser if an entity declaration is hit. */
+static void entity_declaration(void *userData, const XML_Char *entityName,
+                              int is_parameter_entity, const XML_Char *value,
+                              int value_length, const XML_Char *base,
+                              const XML_Char *systemId, const XML_Char *publicId,
+                              const XML_Char *notationName)
+{
+    ne_xml_parser *parser = userData;
+    
+    NE_DEBUG(NE_DBG_XMLPARSE, "XML: entity declaration [%s]. Failing.\n",
+             entityName);
+
+    XML_StopParser(parser->parser, XML_FALSE);
+}
+#elif defined(HAVE_EXPAT)
+/* A noop default_handler. */
+static void default_handler(void *userData, const XML_Char *s, int len)
+{
+}
+#endif
+
 /* Find a namespace definition for 'prefix' in given element, where
  * length of prefix is 'pfxlen'.  Returns the URI or NULL. */
 static const char *resolve_nspace(const struct element *elm, 
@@ -443,14 +465,34 @@ ne_xml_parser *ne_xml_create(void)
     XML_SetCharacterDataHandler(p->parser, char_data);
     XML_SetUserData(p->parser, (void *) p);
     XML_SetXmlDeclHandler(p->parser, decl_handler);
+
+    /* Prevent the "billion laughs" attack against expat by disabling
+     * internal entity expansion.  With 2.x, forcibly stop the parser
+     * if an entity is declared - this is safer and a more obvious
+     * failure mode.  With older versions, installing a noop
+     * DefaultHandler means that internal entities will be expanded as
+     * the empty string, which is also sufficient to prevent the
+     * attack. */
+#if XML_MAJOR_VERSION > 1
+    XML_SetEntityDeclHandler(p->parser, entity_declaration);
 #else
+    XML_SetDefaultHandler(p->parser, default_handler);
+#endif
+
+#else /* HAVE_LIBXML */
     p->parser = xmlCreatePushParserCtxt(&sax_handler, 
 					(void *)p, NULL, 0, NULL);
     if (p->parser == NULL) {
 	abort();
     }
+#if LIBXML_VERSION < 20602
     p->parser->replaceEntities = 1;
+#else
+    /* Enable expansion of entities, and disable network access. */
+    xmlCtxtUseOptions(p->parser, XML_PARSE_NOENT | XML_PARSE_NONET);
 #endif
+
+#endif /* HAVE_LIBXML || HAVE_EXPAT */
     return p;
 }