Hello community,

here is the log from the commit of package libserf for openSUSE:Factory checked 
in at 2014-08-13 08:49:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libserf (Old)
 and      /work/SRC/openSUSE:Factory/.libserf.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libserf"

Changes:
--------
--- /work/SRC/openSUSE:Factory/libserf/libserf.changes  2014-06-10 
14:39:19.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.libserf.new/libserf.changes     2014-08-13 
08:49:17.000000000 +0200
@@ -1,0 +2,10 @@
+Mon Aug 11 16:07:48 UTC 2014 - [email protected]
+
+- Serf 1.3.7
+  Serf may not provide the full value for fields contained in X.509
+  certificates.  Allowing for clients to potentially improperly
+  accept certificates. 
+  * Handle NUL bytes in fields of an X.509 certificate.
+    [bnc#890510] [CVE-2014-3504]
+
+-------------------------------------------------------------------

Old:
----
  serf-1.3.6.tar.bz2

New:
----
  serf-1.3.7.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libserf.spec ++++++
--- /var/tmp/diff_new_pack.up1HJq/_old  2014-08-13 08:49:18.000000000 +0200
+++ /var/tmp/diff_new_pack.up1HJq/_new  2014-08-13 08:49:18.000000000 +0200
@@ -23,7 +23,7 @@
 %define minor  3
 %define SHLIBVER %{major}.%{minor}.0
 Name:           libserf
-Version:        1.3.6
+Version:        1.3.7
 Release:        0
 Summary:        High-Performance Asynchronous HTTP Client Library
 License:        Apache-2.0

++++++ serf-1.3.6.tar.bz2 -> serf-1.3.7.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.6/CHANGES new/serf-1.3.7/CHANGES
--- old/serf-1.3.6/CHANGES      2014-06-09 18:05:27.000000000 +0200
+++ new/serf-1.3.7/CHANGES      2014-08-11 17:17:02.000000000 +0200
@@ -1,8 +1,11 @@
-Serf 1.3.6 [2014-06-09, from /tags/1.3.6, rxxxx]
+Serf 1.3.7 [2014-08-11, from /tags/1.3.7, r2411]
+  Handle NUL bytes in fields of an X.509 certificate. (r2393, r2399)
+
+Serf 1.3.6 [2014-06-09, from /tags/1.3.6, r2372]
   Revert r2319 from serf 1.3.5: this change was making serf call 
handle_response
     multiple times in case of an error response, leading to unexpected 
behavior.
 
-Serf 1.3.5 [2014-04-27, from /tags/1.3.5, rxxxx]
+Serf 1.3.5 [2014-04-27, from /tags/1.3.5, r2355]
   Fix issue #125: no reverse lookup during Negotiate authentication for 
proxies.
   Fix a crash caused by incorrect reuse of the ssltunnel CONNECT request 
(r2316)
   Cancel request if response parsing failed + authn callback set (r2319)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.6/buckets/ssl_buckets.c 
new/serf-1.3.7/buckets/ssl_buckets.c
--- old/serf-1.3.6/buckets/ssl_buckets.c        2014-02-04 20:41:14.000000000 
+0100
+++ new/serf-1.3.7/buckets/ssl_buckets.c        2014-08-06 04:24:00.000000000 
+0200
@@ -202,6 +202,8 @@
 };
 
 static void disable_compression(serf_ssl_context_t *ssl_ctx);
+static char *
+    pstrdup_escape_nul_bytes(const char *buf, int len, apr_pool_t *pool);
 
 #if SSL_VERBOSE
 /* Log all ssl alerts that we receive from the server. */
@@ -427,6 +429,85 @@
 #endif
 };
 
+typedef enum san_copy_t {
+    EscapeNulAndCopy = 0,
+    ErrorOnNul = 1,
+} san_copy_t;
+
+
+static apr_status_t
+get_subject_alt_names(apr_array_header_t **san_arr, X509 *ssl_cert,
+                      san_copy_t copy_action, apr_pool_t *pool)
+{
+    STACK_OF(GENERAL_NAME) *names;
+
+    /* assert: copy_action == ErrorOnNul || (san_arr && pool) */
+
+    if (san_arr) {
+        *san_arr = NULL;
+    }
+
+    /* Get subjectAltNames */
+    names = X509_get_ext_d2i(ssl_cert, NID_subject_alt_name, NULL, NULL);
+    if (names) {
+        int names_count = sk_GENERAL_NAME_num(names);
+        int name_idx;
+
+        if (san_arr)
+            *san_arr = apr_array_make(pool, names_count, sizeof(char*));
+        for (name_idx = 0; name_idx < names_count; name_idx++) {
+            char *p = NULL;
+            GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, name_idx);
+
+            switch (nm->type) {
+                case GEN_DNS:
+                    if (copy_action == ErrorOnNul &&
+                        strlen(nm->d.ia5->data) != nm->d.ia5->length)
+                        return SERF_ERROR_SSL_CERT_FAILED;
+                    if (san_arr && *san_arr)
+                        p = pstrdup_escape_nul_bytes((const char 
*)nm->d.ia5->data,
+                                                     nm->d.ia5->length,
+                                                     pool);
+                    break;
+                default:
+                    /* Don't know what to do - skip. */
+                    break;
+            }
+
+            if (p) {
+                APR_ARRAY_PUSH(*san_arr, char*) = p;
+            }
+        }
+        sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
+    }
+    
+    return APR_SUCCESS;
+}
+
+static apr_status_t validate_cert_hostname(X509 *server_cert, apr_pool_t *pool)
+{
+    char buf[1024];
+    int length;
+    apr_status_t ret;
+
+    ret = get_subject_alt_names(NULL, server_cert, ErrorOnNul, NULL);
+    if (ret) {
+      return ret;
+    } else {
+        /* Fail if the subject's CN field contains \0 characters. */
+        X509_NAME *subject = X509_get_subject_name(server_cert);
+        if (!subject)
+            return SERF_ERROR_SSL_CERT_FAILED;
+
+        length = X509_NAME_get_text_by_NID(subject, NID_commonName, buf, 1024);
+        if (length != -1)
+            if (strlen(buf) != length)
+                return SERF_ERROR_SSL_CERT_FAILED;
+    }
+
+    return APR_SUCCESS;
+}
+
 static int
 validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
 {
@@ -435,6 +516,7 @@
     X509 *server_cert;
     int err, depth;
     int failures = 0;
+    apr_status_t status;
 
     ssl = X509_STORE_CTX_get_ex_data(store_ctx,
                                      SSL_get_ex_data_X509_STORE_CTX_idx());
@@ -475,6 +557,11 @@
         }
     }
 
+    /* Validate hostname */
+    status = validate_cert_hostname(server_cert, ctx->pool);
+    if (status)
+        failures |= SERF_SSL_CERT_UNKNOWN_FAILURE;
+
     /* Check certificate expiry dates. */
     if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
         failures |= SERF_SSL_CERT_NOTYETVALID;
@@ -485,7 +572,6 @@
 
     if (ctx->server_cert_callback &&
         (depth == 0 || failures)) {
-        apr_status_t status;
         serf_ssl_certificate_t *cert;
         apr_pool_t *subpool;
 
@@ -512,7 +598,6 @@
 
     if (ctx->server_cert_chain_callback
         && (depth == 0 || failures)) {
-        apr_status_t status;
         STACK_OF(X509) *chain;
         const serf_ssl_certificate_t **certs;
         int certs_len;
@@ -1461,7 +1546,50 @@
 
 /* Functions to read a serf_ssl_certificate structure. */
 
-/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). */
+/* Takes a counted length string and escapes any NUL bytes so that
+ * it can be used as a C string.  NUL bytes are escaped as 3 characters
+ * "\00" (that's a literal backslash).
+ * The returned string is allocated in POOL.
+ */
+static char *
+pstrdup_escape_nul_bytes(const char *buf, int len, apr_pool_t *pool)
+{
+    int i, nul_count = 0;
+    char *ret;
+
+    /* First determine if there are any nul bytes in the string. */
+    for (i = 0; i < len; i++) {
+        if (buf[i] == '\0')
+            nul_count++;
+    }
+
+    if (nul_count == 0) {
+        /* There aren't so easy case to just copy the string */
+        ret = apr_pstrdup(pool, buf);
+    } else {
+        /* There are so we have to replace nul bytes with escape codes
+         * Proper length is the length of the original string, plus
+         * 2 times the number of nulls (for two digit hex code for
+         * the value) + the trailing null. */
+        char *pos;
+        ret = pos = apr_palloc(pool, len + 2 * nul_count + 1);
+        for (i = 0; i < len; i++) {
+            if (buf[i] != '\0') {
+                *(pos++) = buf[i];
+            } else {
+                *(pos++) = '\\';
+                *(pos++) = '0';
+                *(pos++) = '0';
+            }
+        }
+        *pos = '\0';
+    }
+
+    return ret;
+}
+
+/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). Any NUL bytes in
+   these fields in the certificate will be escaped as \00. */
 static apr_hash_t *
 convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
 {
@@ -1474,37 +1602,44 @@
                                     NID_commonName,
                                     buf, 1024);
     if (ret != -1)
-        apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+        apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING,
+                     pstrdup_escape_nul_bytes(buf, ret, pool));
     ret = X509_NAME_get_text_by_NID(org,
                                     NID_pkcs9_emailAddress,
                                     buf, 1024);
     if (ret != -1)
-        apr_hash_set(tgt, "E", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+        apr_hash_set(tgt, "E", APR_HASH_KEY_STRING,
+                     pstrdup_escape_nul_bytes(buf, ret, pool));
     ret = X509_NAME_get_text_by_NID(org,
                                     NID_organizationalUnitName,
                                     buf, 1024);
     if (ret != -1)
-        apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+        apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING,
+                     pstrdup_escape_nul_bytes(buf, ret, pool));
     ret = X509_NAME_get_text_by_NID(org,
                                     NID_organizationName,
                                     buf, 1024);
     if (ret != -1)
-        apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+        apr_hash_set(tgt, "O", APR_HASH_KEY_STRING,
+                     pstrdup_escape_nul_bytes(buf, ret, pool));
     ret = X509_NAME_get_text_by_NID(org,
                                     NID_localityName,
                                     buf, 1024);
     if (ret != -1)
-        apr_hash_set(tgt, "L", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+        apr_hash_set(tgt, "L", APR_HASH_KEY_STRING,
+                     pstrdup_escape_nul_bytes(buf, ret, pool));
     ret = X509_NAME_get_text_by_NID(org,
                                     NID_stateOrProvinceName,
                                     buf, 1024);
     if (ret != -1)
-        apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+        apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING,
+                     pstrdup_escape_nul_bytes(buf, ret, pool));
     ret = X509_NAME_get_text_by_NID(org,
                                     NID_countryName,
                                     buf, 1024);
     if (ret != -1)
-        apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
+        apr_hash_set(tgt, "C", APR_HASH_KEY_STRING,
+                     pstrdup_escape_nul_bytes(buf, ret, pool));
 
     return tgt;
 }
@@ -1550,7 +1685,7 @@
     unsigned int md_size, i;
     unsigned char md[EVP_MAX_MD_SIZE];
     BIO *bio;
-    STACK_OF(GENERAL_NAME) *names;
+    apr_array_header_t *san_arr;
 
     /* sha1 fingerprint */
     if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) {
@@ -1595,32 +1730,8 @@
     BIO_free(bio);
 
     /* Get subjectAltNames */
-    names = X509_get_ext_d2i(cert->ssl_cert, NID_subject_alt_name, NULL, NULL);
-    if (names) {
-        int names_count = sk_GENERAL_NAME_num(names);
-
-        apr_array_header_t *san_arr = apr_array_make(pool, names_count,
-                                                     sizeof(char*));
+    if (!get_subject_alt_names(&san_arr, cert->ssl_cert, EscapeNulAndCopy, 
pool))
         apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr);
-        for (i = 0; i < names_count; i++) {
-            char *p = NULL;
-            GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, i);
-
-            switch (nm->type) {
-            case GEN_DNS:
-                p = apr_pstrmemdup(pool, (const char *)nm->d.ia5->data,
-                                   nm->d.ia5->length);
-                break;
-            default:
-                /* Don't know what to do - skip. */
-                break;
-            }
-            if (p) {
-                APR_ARRAY_PUSH(san_arr, char*) = p;
-            }
-        }
-        sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
-    }
 
     return tgt;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/serf-1.3.6/serf.h new/serf-1.3.7/serf.h
--- old/serf-1.3.6/serf.h       2014-06-07 09:44:30.000000000 +0200
+++ new/serf-1.3.7/serf.h       2014-08-04 20:11:28.000000000 +0200
@@ -1062,7 +1062,7 @@
 /* Version info */
 #define SERF_MAJOR_VERSION 1
 #define SERF_MINOR_VERSION 3
-#define SERF_PATCH_VERSION 6
+#define SERF_PATCH_VERSION 7
 
 /* Version number string */
 #define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to