aboutsummaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorYue Tao <Yue.Tao@windriver.com>2014-10-22 03:37:28 -0400
committerRichard Purdie <richard.purdie@linuxfoundation.org>2014-11-04 10:19:53 +0000
commit06a33cd00ea11abec1ebe9d5883e44778075ccc6 (patch)
tree69ed9389a6011d7ea1251bbfc2d9c6e6f6b0e326 /meta
parentffc1c58809a2f5fef13484613d1b57c2d4c5ebfb (diff)
downloadopenembedded-core-contrib-06a33cd00ea11abec1ebe9d5883e44778075ccc6.tar.gz
subversion: Security Advisory - subversion - CVE-2014-3522
The Serf RA layer in Apache Subversion 1.4.0 through 1.7.x before 1.7.18 and 1.8.x before 1.8.10 does not properly handle wildcards in the Common Name (CN) or subjectAltName field of the X.509 certificate, which allows man-in-the-middle attackers to spoof servers via a crafted certificate.<a href=http://cwe.mitre.org/data/definitions/297.html target=_blank>CWE-297: Improper Validation of Certificate with Host Mismatch</a> http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-3522 Signed-off-by: Yue Tao <Yue.Tao@windriver.com> Signed-off-by: Jackie Huang <jackie.huang@windriver.com> Signed-off-by: Ross Burton <ross.burton@intel.com>
Diffstat (limited to 'meta')
-rw-r--r--meta/recipes-devtools/subversion/subversion-1.8.9/subversion-CVE-2014-3522.patch444
-rw-r--r--meta/recipes-devtools/subversion/subversion/subversion-CVE-2014-3522.patch439
-rw-r--r--meta/recipes-devtools/subversion/subversion_1.6.15.bb4
-rw-r--r--meta/recipes-devtools/subversion/subversion_1.8.9.bb1
4 files changed, 887 insertions, 1 deletions
diff --git a/meta/recipes-devtools/subversion/subversion-1.8.9/subversion-CVE-2014-3522.patch b/meta/recipes-devtools/subversion/subversion-1.8.9/subversion-CVE-2014-3522.patch
new file mode 100644
index 0000000000..f259e5490a
--- /dev/null
+++ b/meta/recipes-devtools/subversion/subversion-1.8.9/subversion-CVE-2014-3522.patch
@@ -0,0 +1,444 @@
+Upstream-Status: Backport
+
+Signed-off-by: Jackie Huang <jackie.huang@windriver.com>
+
+Index: subversion/include/private/svn_cert.h
+===================================================================
+--- subversion/include/private/svn_cert.h (nonexistent)
++++ subversion/include/private/svn_cert.h (working copy)
+@@ -0,0 +1,68 @@
++/**
++ * @copyright
++ * ====================================================================
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements. See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership. The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License. You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied. See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ * ====================================================================
++ * @endcopyright
++ *
++ * @file svn_cert.h
++ * @brief Implementation of certificate validation functions
++ */
++
++#ifndef SVN_CERT_H
++#define SVN_CERT_H
++
++#include <apr.h>
++
++#include "svn_types.h"
++#include "svn_string.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++
++/* Return TRUE iff @a pattern matches @a hostname as defined
++ * by the matching rules of RFC 6125. In the context of RFC
++ * 6125 the pattern is the domain name portion of the presented
++ * identifier (which comes from the Common Name or a DNSName
++ * portion of the subjectAltName of an X.509 certificate) and
++ * the hostname is the source domain (i.e. the host portion
++ * of the URI the user entered).
++ *
++ * @note With respect to wildcards we only support matching
++ * wildcards in the left-most label and as the only character
++ * in the left-most label (i.e. we support RFC 6125 s. 6.4.3
++ * Rule 1 and 2 but not the optional Rule 3). This may change
++ * in the future.
++ *
++ * @note Subversion does not at current support internationalized
++ * domain names. Both values are presumed to be in NR-LDH label
++ * or A-label form (see RFC 5890 for the definition).
++ *
++ * @since New in 1.9.
++ */
++svn_boolean_t
++svn_cert__match_dns_identity(svn_string_t *pattern, svn_string_t *hostname);
++
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* SVN_CERT_H */
+Index: subversion/libsvn_ra_serf/util.c
+===================================================================
+--- subversion/libsvn_ra_serf/util.c (revision 1615128)
++++ subversion/libsvn_ra_serf/util.c (working copy)
+@@ -28,7 +28,6 @@
+ #define APR_WANT_STRFUNC
+ #include <apr.h>
+ #include <apr_want.h>
+-#include <apr_fnmatch.h>
+
+ #include <serf.h>
+ #include <serf_bucket_types.h>
+@@ -49,6 +48,7 @@
+ #include "private/svn_fspath.h"
+ #include "private/svn_subr_private.h"
+ #include "private/svn_auth_private.h"
++#include "private/svn_cert.h"
+
+ #include "ra_serf.h"
+
+@@ -274,7 +274,6 @@ ssl_server_cert(void *baton, int failures,
+ apr_hash_t *subject = NULL;
+ apr_hash_t *serf_cert = NULL;
+ void *creds;
+- int found_matching_hostname = 0;
+
+ svn_failures = (ssl_convert_serf_failures(failures)
+ | conn->server_cert_failures);
+@@ -286,26 +285,37 @@ ssl_server_cert(void *baton, int failures,
+ ### This should really be handled by serf, which should pass an error
+ for this case, but that has backwards compatibility issues. */
+ apr_array_header_t *san;
++ svn_boolean_t found_san_entry = FALSE;
++ svn_boolean_t found_matching_hostname = FALSE;
++ svn_string_t *actual_hostname =
++ svn_string_create(conn->session->session_url.hostname, scratch_pool);
+
+ serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
+
+ san = svn_hash_gets(serf_cert, "subjectAltName");
+ /* Try to find matching server name via subjectAltName first... */
+- if (san) {
++ if (san)
++ {
+ int i;
+- for (i = 0; i < san->nelts; i++) {
++ found_san_entry = san->nelts > 0;
++ for (i = 0; i < san->nelts; i++)
++ {
+ const char *s = APR_ARRAY_IDX(san, i, const char*);
+- if (apr_fnmatch(s, conn->session->session_url.hostname,
+- APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
+- {
+- found_matching_hostname = 1;
++ svn_string_t *cert_hostname = svn_string_create(s, scratch_pool);
++
++ if (svn_cert__match_dns_identity(cert_hostname, actual_hostname))
++ {
++ found_matching_hostname = TRUE;
+ break;
+- }
+- }
+- }
++ }
++ }
++ }
+
+- /* Match server certificate CN with the hostname of the server */
+- if (!found_matching_hostname)
++ /* Match server certificate CN with the hostname of the server iff
++ * we didn't find any subjectAltName fields and try to match them.
++ * Per RFC 2818 they are authoritative if present and CommonName
++ * should be ignored. */
++ if (!found_matching_hostname && !found_san_entry)
+ {
+ const char *hostname = NULL;
+
+@@ -314,13 +324,20 @@ ssl_server_cert(void *baton, int failures,
+ if (subject)
+ hostname = svn_hash_gets(subject, "CN");
+
+- if (!hostname
+- || apr_fnmatch(hostname, conn->session->session_url.hostname,
+- APR_FNM_PERIOD | APR_FNM_CASE_BLIND) != APR_SUCCESS)
+- {
+- svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
+- }
+- }
++ if (hostname)
++ {
++ svn_string_t *cert_hostname = svn_string_create(hostname,
++ scratch_pool);
++
++ if (svn_cert__match_dns_identity(cert_hostname, actual_hostname))
++ {
++ found_matching_hostname = TRUE;
++ }
++ }
++ }
++
++ if (!found_matching_hostname)
++ svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
+ }
+
+ if (!svn_failures)
+Index: subversion/libsvn_subr/dirent_uri.c
+===================================================================
+--- subversion/libsvn_subr/dirent_uri.c (revision 1615128)
++++ subversion/libsvn_subr/dirent_uri.c (working copy)
+@@ -38,6 +38,7 @@
+
+ #include "dirent_uri.h"
+ #include "private/svn_fspath.h"
++#include "private/svn_cert.h"
+
+ /* The canonical empty path. Can this be changed? Well, change the empty
+ test below and the path library will work, not so sure about the fs/wc
+@@ -2597,3 +2598,81 @@ svn_urlpath__canonicalize(const char *uri,
+ }
+ return uri;
+ }
++
++
++/* -------------- The cert API (see private/svn_cert.h) ------------- */
++
++svn_boolean_t
++svn_cert__match_dns_identity(svn_string_t *pattern, svn_string_t *hostname)
++{
++ apr_size_t pattern_pos = 0, hostname_pos = 0;
++
++ /* support leading wildcards that composed of the only character in the
++ * left-most label. */
++ if (pattern->len >= 2 &&
++ pattern->data[pattern_pos] == '*' &&
++ pattern->data[pattern_pos + 1] == '.')
++ {
++ while (hostname_pos < hostname->len &&
++ hostname->data[hostname_pos] != '.')
++ {
++ hostname_pos++;
++ }
++ /* Assume that the wildcard must match something. Rule 2 says
++ * that *.example.com should not match example.com. If the wildcard
++ * ends up not matching anything then it matches .example.com which
++ * seems to be essentially the same as just example.com */
++ if (hostname_pos == 0)
++ return FALSE;
++
++ pattern_pos++;
++ }
++
++ while (pattern_pos < pattern->len && hostname_pos < hostname->len)
++ {
++ char pattern_c = pattern->data[pattern_pos];
++ char hostname_c = hostname->data[hostname_pos];
++
++ /* fold case as described in RFC 4343.
++ * Note: We actually convert to lowercase, since our URI
++ * canonicalization code converts to lowercase and generally
++ * most certs are issued with lowercase DNS names, meaning
++ * this avoids the fold operation in most cases. The RFC
++ * suggests the opposite transformation, but doesn't require
++ * any specific implementation in any case. It is critical
++ * that this folding be locale independent so you can't use
++ * tolower(). */
++ pattern_c = canonicalize_to_lower(pattern_c);
++ hostname_c = canonicalize_to_lower(hostname_c);
++
++ if (pattern_c != hostname_c)
++ {
++ /* doesn't match */
++ return FALSE;
++ }
++ else
++ {
++ /* characters match so skip both */
++ pattern_pos++;
++ hostname_pos++;
++ }
++ }
++
++ /* ignore a trailing period on the hostname since this has no effect on the
++ * security of the matching. See the following for the long explanation as
++ * to why:
++ * https://bugzilla.mozilla.org/show_bug.cgi?id=134402#c28
++ */
++ if (pattern_pos == pattern->len &&
++ hostname_pos == hostname->len - 1 &&
++ hostname->data[hostname_pos] == '.')
++ hostname_pos++;
++
++ if (pattern_pos != pattern->len || hostname_pos != hostname->len)
++ {
++ /* end didn't match */
++ return FALSE;
++ }
++
++ return TRUE;
++}
+Index: subversion/tests/libsvn_subr/dirent_uri-test.c
+===================================================================
+--- subversion/tests/libsvn_subr/dirent_uri-test.c (revision 1615128)
++++ subversion/tests/libsvn_subr/dirent_uri-test.c (working copy)
+@@ -37,6 +37,7 @@
+ #include "svn_pools.h"
+ #include "svn_dirent_uri.h"
+ #include "private/svn_fspath.h"
++#include "private/svn_cert.h"
+
+ #include "../svn_test.h"
+
+@@ -2714,6 +2715,145 @@ test_fspath_get_longest_ancestor(apr_pool_t *pool)
+ return SVN_NO_ERROR;
+ }
+
++struct cert_match_dns_test {
++ const char *pattern;
++ const char *hostname;
++ svn_boolean_t expected;
++};
++
++static svn_error_t *
++run_cert_match_dns_tests(struct cert_match_dns_test *tests, apr_pool_t *pool)
++{
++ struct cert_match_dns_test *ct;
++ apr_pool_t *iterpool = svn_pool_create(pool);
++
++ for (ct = tests; ct->pattern; ct++)
++ {
++ svn_boolean_t result;
++ svn_string_t *pattern, *hostname;
++
++ svn_pool_clear(iterpool);
++
++ pattern = svn_string_create(ct->pattern, iterpool);
++ hostname = svn_string_create(ct->hostname, iterpool);
++
++ result = svn_cert__match_dns_identity(pattern, hostname);
++ if (result != ct->expected)
++ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
++ "Expected %s but got %s for pattern '%s' on "
++ "hostname '%s'",
++ ct->expected ? "match" : "no match",
++ result ? "match" : "no match",
++ pattern->data, hostname->data);
++
++ }
++
++ svn_pool_destroy(iterpool);
++
++ return SVN_NO_ERROR;
++}
++
++static struct cert_match_dns_test cert_match_dns_tests[] = {
++ { "foo.example.com", "foo.example.com", TRUE }, /* exact match */
++ { "foo.example.com", "FOO.EXAMPLE.COM", TRUE }, /* case differences */
++ { "FOO.EXAMPLE.COM", "foo.example.com", TRUE },
++ { "*.example.com", "FoO.ExAmPlE.CoM", TRUE },
++ { "*.ExAmPlE.CoM", "foo.example.com", TRUE },
++ { "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", TRUE },
++ { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", TRUE },
++ { "foo.example.com", "bar.example.com", FALSE }, /* difference at start */
++ { "foo.example.com", "foo.example.net", FALSE }, /* difference at end */
++ { "foo.example.com", "foo.example.commercial", FALSE }, /* hostname longer */
++ { "foo.example.commercial", "foo.example.com", FALSE }, /* pattern longer */
++ { "foo.example.comcom", "foo.example.com", FALSE }, /* repeated suffix */
++ { "foo.example.com", "foo.example.comcom", FALSE },
++ { "foo.example.com.com", "foo.example.com", FALSE },
++ { "foo.example.com", "foo.example.com.com", FALSE },
++ { "foofoo.example.com", "foo.example.com", FALSE }, /* repeated prefix */
++ { "foo.example.com", "foofoo.example.com", FALSE },
++ { "foo.foo.example.com", "foo.example.com", FALSE },
++ { "foo.example.com", "foo.foo.example.com", FALSE },
++ { "foo.*.example.com", "foo.bar.example.com", FALSE }, /* RFC 6125 s. 6.4.3
++ Rule 1 */
++ { "*.example.com", "foo.example.com", TRUE }, /* RFC 6125 s. 6.4.3 Rule 2 */
++ { "*.example.com", "bar.foo.example.com", FALSE }, /* Rule 2 */
++ { "*.example.com", "example.com", FALSE }, /* Rule 2 */
++ { "*.example.com", ".example.com", FALSE }, /* RFC doesn't say what to do
++ here and a leading period on
++ a hostname doesn't make sense
++ so we'll just reject this. */
++ { "*", "foo.example.com", FALSE }, /* wildcard must be left-most label,
++ implies that there must be more than
++ one label. */
++ { "*", "example.com", FALSE },
++ { "*", "com", FALSE },
++ { "*.example.com", "foo.example.net", FALSE }, /* difference in literal text
++ with a wildcard. */
++ { "*.com", "example.com", TRUE }, /* See Errata ID 3090 for RFC 6125,
++ probably shouldn't allow this but
++ we do for now. */
++ { "*.", "example.com", FALSE }, /* test some dubious 2 character wildcard
++ patterns */
++ { "*.", "example.", TRUE }, /* This one feels questionable */
++ { "*.", "example", FALSE },
++ { "*.", ".", FALSE },
++ { "a", "a", TRUE }, /* check that single letter exact matches work */
++ { "a", "b", FALSE }, /* and single letter not matches shouldn't */
++ { "*.*.com", "foo.example.com", FALSE }, /* unsupported wildcards */
++ { "*.*.com", "example.com", FALSE },
++ { "**.example.com", "foo.example.com", FALSE },
++ { "**.example.com", "example.com", FALSE },
++ { "f*.example.com", "foo.example.com", FALSE },
++ { "f*.example.com", "bar.example.com", FALSE },
++ { "*o.example.com", "foo.example.com", FALSE },
++ { "*o.example.com", "bar.example.com", FALSE },
++ { "f*o.example.com", "foo.example.com", FALSE },
++ { "f*o.example.com", "bar.example.com", FALSE },
++ { "foo.e*.com", "foo.example.com", FALSE },
++ { "foo.*e.com", "foo.example.com", FALSE },
++ { "foo.e*e.com", "foo.example.com", FALSE },
++ { "foo.example.com", "foo.example.com.", TRUE }, /* trailing dot */
++ { "*.example.com", "foo.example.com.", TRUE },
++ { "foo", "foo.", TRUE },
++ { "foo.example.com.", "foo.example.com", FALSE },
++ { "*.example.com.", "foo.example.com", FALSE },
++ { "foo.", "foo", FALSE },
++ { "foo.example.com", "foo.example.com..", FALSE },
++ { "*.example.com", "foo.example.com..", FALSE },
++ { "foo", "foo..", FALSE },
++ { "foo.example.com..", "foo.example.com", FALSE },
++ { "*.example.com..", "foo.example.com", FALSE },
++ { "foo..", "foo", FALSE },
++ { NULL }
++};
++
++static svn_error_t *
++test_cert_match_dns_identity(apr_pool_t *pool)
++{
++ return run_cert_match_dns_tests(cert_match_dns_tests, pool);
++}
++
++/* This test table implements results that should happen if we supported
++ * RFC 6125 s. 6.4.3 Rule 3. We don't so it's expected to fail for now. */
++static struct cert_match_dns_test rule3_tests[] = {
++ { "baz*.example.net", "baz1.example.net", TRUE },
++ { "*baz.example.net", "foobaz.example.net", TRUE },
++ { "b*z.example.net", "buuz.example.net", TRUE },
++ { "b*z.example.net", "bz.example.net", FALSE }, /* presume wildcard can't
++ match nothing */
++ { "baz*.example.net", "baz.example.net", FALSE },
++ { "*baz.example.net", "baz.example.net", FALSE },
++ { "b*z.example.net", "buuzuuz.example.net", TRUE }, /* presume wildcard
++ should be greedy */
++ { NULL }
++};
++
++static svn_error_t *
++test_rule3(apr_pool_t *pool)
++{
++ return run_cert_match_dns_tests(rule3_tests, pool);
++}
++
+
+ /* The test table. */
+
+@@ -2812,5 +2952,9 @@ struct svn_test_descriptor_t test_funcs[] =
+ "test svn_fspath__dirname/basename/split"),
+ SVN_TEST_PASS2(test_fspath_get_longest_ancestor,
+ "test svn_fspath__get_longest_ancestor"),
++ SVN_TEST_PASS2(test_cert_match_dns_identity,
++ "test svn_cert__match_dns_identity"),
++ SVN_TEST_XFAIL2(test_rule3,
++ "test match with RFC 6125 s. 6.4.3 Rule 3"),
+ SVN_TEST_NULL
+ };
diff --git a/meta/recipes-devtools/subversion/subversion/subversion-CVE-2014-3522.patch b/meta/recipes-devtools/subversion/subversion/subversion-CVE-2014-3522.patch
new file mode 100644
index 0000000000..03d5b9710f
--- /dev/null
+++ b/meta/recipes-devtools/subversion/subversion/subversion-CVE-2014-3522.patch
@@ -0,0 +1,439 @@
+Upstream-Status: Backport
+
+Signed-off-by: Yue Tao <yue.tao@windriver.com>
+
+diff --git a/subversion/libsvn_ra_serf/util.c.old b/subversion/libsvn_ra_serf/util.c
+index b6c0141..8b09770 100644
+--- a/subversion/libsvn_ra_serf/util.c.old
++++ b/subversion/libsvn_ra_serf/util.c
+@@ -21,7 +21,6 @@
+ #define APR_WANT_STRFUNC
+ #include <apr.h>
+ #include <apr_want.h>
+-#include <apr_fnmatch.h>
+
+ #include <serf.h>
+ #include <serf_bucket_types.h>
+@@ -30,6 +29,7 @@
+ #include "svn_private_config.h"
+ #include "svn_xml.h"
+ #include "private/svn_dep_compat.h"
++#include "private/svn_cert.h"
+
+ #include "ra_serf.h"
+
+@@ -113,7 +113,12 @@ ssl_server_cert(void *baton, int failures,
+ apr_uint32_t svn_failures;
+ svn_error_t *err;
+ apr_hash_t *issuer, *subject, *serf_cert;
++ apr_array_header_t *san;
+ void *creds;
++ svn_boolean_t found_matching_hostname = FALSE;
++ svn_boolean_t found_san_entry = FALSE;
++ svn_string_t *actual_hostname =
++ svn_string_create(conn->hostname, scratch_pool);
+
+ /* Implicitly approve any non-server certs. */
+ if (serf_ssl_cert_depth(cert) > 0)
+@@ -129,6 +134,7 @@ ssl_server_cert(void *baton, int failures,
+ serf_cert = serf_ssl_cert_certificate(cert, subpool);
+
+ cert_info.hostname = apr_hash_get(subject, "CN", APR_HASH_KEY_STRING);
++ san = apr_hash_get(serf_cert, "subjectAltName", APR_HASH_KEY_STRING);
+ cert_info.fingerprint = apr_hash_get(serf_cert, "sha1", APR_HASH_KEY_STRING);
+ if (! cert_info.fingerprint)
+ cert_info.fingerprint = apr_pstrdup(subpool, "<unknown>");
+@@ -145,16 +145,43 @@ ssl_server_cert(void *baton, int failures,
+
+ svn_failures = ssl_convert_serf_failures(failures);
+
+- /* Match server certificate CN with the hostname of the server */
+- if (cert_info.hostname)
++ /* Try to find matching server name via subjectAltName first... */
++ if (san)
+ {
+- if (apr_fnmatch(cert_info.hostname, conn->hostinfo,
+- APR_FNM_PERIOD) == APR_FNM_NOMATCH)
++ int i;
++ found_san_entry = san->nelts > 0;
++ for (i = 0; i < san->nelts; i++)
+ {
+- svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
++ char *s = APR_ARRAY_IDX(san, i, char*);
++ svn_string_t *cert_hostname = svn_string_create(s, scratch_pool);
++
++ if (svn_cert__match_dns_identity(cert_hostname, actual_hostname))
++ {
++ found_matching_hostname = TRUE;
++ cert_info.hostname = s;
++ break;
++ }
+ }
+ }
+
++ /* Match server certificate CN with the hostname of the server iff
++ * we didn't find any subjectAltName fields and try to match them.
++ * Per RFC 2818 they are authoritative if present and CommonName
++ * should be ignored. */
++ if (!found_matching_hostname && !found_san_entry && cert_info.hostname)
++ {
++ svn_string_t *cert_hostname = svn_string_create(cert_info.hostname,
++ scratch_pool);
++
++ if (svn_cert__match_dns_identity(cert_hostname, actual_hostname))
++ {
++ found_matching_hostname = TRUE;
++ }
++ }
++
++ if (!found_matching_hostname)
++ svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
++
+ svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
+ SVN_AUTH_PARAM_SSL_SERVER_FAILURES,
+ &svn_failures);
+@@ -261,6 +293,10 @@ svn_ra_serf__conn_setup(apr_socket_t *sock,
+ if (!conn->ssl_context)
+ {
+ conn->ssl_context = serf_bucket_ssl_encrypt_context_get(rb);
++
++#if SERF_VERSION_AT_LEAST(1,0,0)
++ serf_ssl_set_hostname(conn->ssl_context, conn->hostinfo);
++#endif
+
+ serf_ssl_client_cert_provider_set(conn->ssl_context,
+ svn_ra_serf__handle_client_cert,
+diff --git a/subversion/libsvn_subr/dirent_uri.c.old b/subversion/libsvn_subr/dirent_uri.c
+index eef99ba..a5f9e7e 100644
+--- a/subversion/libsvn_subr/dirent_uri.c.old
++++ b/subversion/libsvn_subr/dirent_uri.c
+@@ -30,6 +30,7 @@
+ #include "svn_path.h"
+
+ #include "private_uri.h"
++#include "private/svn_cert.h"
+
+ /* The canonical empty path. Can this be changed? Well, change the empty
+ test below and the path library will work, not so sure about the fs/wc
+@@ -1194,3 +1195,81 @@ svn_uri_is_canonical(const char *uri, apr_pool_t *pool)
+
+ return TRUE;
+ }
++
++
++/* -------------- The cert API (see private/svn_cert.h) ------------- */
++
++svn_boolean_t
++svn_cert__match_dns_identity(svn_string_t *pattern, svn_string_t *hostname)
++{
++ apr_size_t pattern_pos = 0, hostname_pos = 0;
++
++ /* support leading wildcards that composed of the only character in the
++ * left-most label. */
++ if (pattern->len >= 2 &&
++ pattern->data[pattern_pos] == '*' &&
++ pattern->data[pattern_pos + 1] == '.')
++ {
++ while (hostname_pos < hostname->len &&
++ hostname->data[hostname_pos] != '.')
++ {
++ hostname_pos++;
++ }
++ /* Assume that the wildcard must match something. Rule 2 says
++ * that *.example.com should not match example.com. If the wildcard
++ * ends up not matching anything then it matches .example.com which
++ * seems to be essentially the same as just example.com */
++ if (hostname_pos == 0)
++ return FALSE;
++
++ pattern_pos++;
++ }
++
++ while (pattern_pos < pattern->len && hostname_pos < hostname->len)
++ {
++ char pattern_c = pattern->data[pattern_pos];
++ char hostname_c = hostname->data[hostname_pos];
++
++ /* fold case as described in RFC 4343.
++ * Note: We actually convert to lowercase, since our URI
++ * canonicalization code converts to lowercase and generally
++ * most certs are issued with lowercase DNS names, meaning
++ * this avoids the fold operation in most cases. The RFC
++ * suggests the opposite transformation, but doesn't require
++ * any specific implementation in any case. It is critical
++ * that this folding be locale independent so you can't use
++ * tolower(). */
++ pattern_c = canonicalize_to_lower(pattern_c);
++ hostname_c = canonicalize_to_lower(hostname_c);
++
++ if (pattern_c != hostname_c)
++ {
++ /* doesn't match */
++ return FALSE;
++ }
++ else
++ {
++ /* characters match so skip both */
++ pattern_pos++;
++ hostname_pos++;
++ }
++ }
++
++ /* ignore a trailing period on the hostname since this has no effect on the
++ * security of the matching. See the following for the long explanation as
++ * to why:
++ * https://bugzilla.mozilla.org/show_bug.cgi?id=134402#c28
++ */
++ if (pattern_pos == pattern->len &&
++ hostname_pos == hostname->len - 1 &&
++ hostname->data[hostname_pos] == '.')
++ hostname_pos++;
++
++ if (pattern_pos != pattern->len || hostname_pos != hostname->len)
++ {
++ /* end didn't match */
++ return FALSE;
++ }
++
++ return TRUE;
++}
+diff --git a/subversion/tests/libsvn_subr/dirent_uri-test.c.old b/subversion/tests/libsvn_subr/dirent_uri-test.c
+index d71d9c1..370b64a 100644
+--- a/subversion/tests/libsvn_subr/dirent_uri-test.c.old
++++ b/subversion/tests/libsvn_subr/dirent_uri-test.c
+@@ -31,6 +31,7 @@
+
+ #include "svn_pools.h"
+ #include "svn_dirent_uri.h"
++#include "private/svn_cert.h"
+
+ #include "../svn_test.h"
+ #include "../../libsvn_subr/private_uri.h"
+@@ -1671,6 +1672,145 @@ test_uri_internal_style(const char **msg,
+ return SVN_NO_ERROR;
+ }
+
++struct cert_match_dns_test {
++ const char *pattern;
++ const char *hostname;
++ svn_boolean_t expected;
++};
++
++static svn_error_t *
++run_cert_match_dns_tests(struct cert_match_dns_test *tests, apr_pool_t *pool)
++{
++ struct cert_match_dns_test *ct;
++ apr_pool_t *iterpool = svn_pool_create(pool);
++
++ for (ct = tests; ct->pattern; ct++)
++ {
++ svn_boolean_t result;
++ svn_string_t *pattern, *hostname;
++
++ svn_pool_clear(iterpool);
++
++ pattern = svn_string_create(ct->pattern, iterpool);
++ hostname = svn_string_create(ct->hostname, iterpool);
++
++ result = svn_cert__match_dns_identity(pattern, hostname);
++ if (result != ct->expected)
++ return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
++ "Expected %s but got %s for pattern '%s' on "
++ "hostname '%s'",
++ ct->expected ? "match" : "no match",
++ result ? "match" : "no match",
++ pattern->data, hostname->data);
++
++ }
++
++ svn_pool_destroy(iterpool);
++
++ return SVN_NO_ERROR;
++}
++
++static struct cert_match_dns_test cert_match_dns_tests[] = {
++ { "foo.example.com", "foo.example.com", TRUE }, /* exact match */
++ { "foo.example.com", "FOO.EXAMPLE.COM", TRUE }, /* case differences */
++ { "FOO.EXAMPLE.COM", "foo.example.com", TRUE },
++ { "*.example.com", "FoO.ExAmPlE.CoM", TRUE },
++ { "*.ExAmPlE.CoM", "foo.example.com", TRUE },
++ { "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", TRUE },
++ { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", TRUE },
++ { "foo.example.com", "bar.example.com", FALSE }, /* difference at start */
++ { "foo.example.com", "foo.example.net", FALSE }, /* difference at end */
++ { "foo.example.com", "foo.example.commercial", FALSE }, /* hostname longer */
++ { "foo.example.commercial", "foo.example.com", FALSE }, /* pattern longer */
++ { "foo.example.comcom", "foo.example.com", FALSE }, /* repeated suffix */
++ { "foo.example.com", "foo.example.comcom", FALSE },
++ { "foo.example.com.com", "foo.example.com", FALSE },
++ { "foo.example.com", "foo.example.com.com", FALSE },
++ { "foofoo.example.com", "foo.example.com", FALSE }, /* repeated prefix */
++ { "foo.example.com", "foofoo.example.com", FALSE },
++ { "foo.foo.example.com", "foo.example.com", FALSE },
++ { "foo.example.com", "foo.foo.example.com", FALSE },
++ { "foo.*.example.com", "foo.bar.example.com", FALSE }, /* RFC 6125 s. 6.4.3
++ Rule 1 */
++ { "*.example.com", "foo.example.com", TRUE }, /* RFC 6125 s. 6.4.3 Rule 2 */
++ { "*.example.com", "bar.foo.example.com", FALSE }, /* Rule 2 */
++ { "*.example.com", "example.com", FALSE }, /* Rule 2 */
++ { "*.example.com", ".example.com", FALSE }, /* RFC doesn't say what to do
++ here and a leading period on
++ a hostname doesn't make sense
++ so we'll just reject this. */
++ { "*", "foo.example.com", FALSE }, /* wildcard must be left-most label,
++ implies that there must be more than
++ one label. */
++ { "*", "example.com", FALSE },
++ { "*", "com", FALSE },
++ { "*.example.com", "foo.example.net", FALSE }, /* difference in literal text
++ with a wildcard. */
++ { "*.com", "example.com", TRUE }, /* See Errata ID 3090 for RFC 6125,
++ probably shouldn't allow this but
++ we do for now. */
++ { "*.", "example.com", FALSE }, /* test some dubious 2 character wildcard
++ patterns */
++ { "*.", "example.", TRUE }, /* This one feels questionable */
++ { "*.", "example", FALSE },
++ { "*.", ".", FALSE },
++ { "a", "a", TRUE }, /* check that single letter exact matches work */
++ { "a", "b", FALSE }, /* and single letter not matches shouldn't */
++ { "*.*.com", "foo.example.com", FALSE }, /* unsupported wildcards */
++ { "*.*.com", "example.com", FALSE },
++ { "**.example.com", "foo.example.com", FALSE },
++ { "**.example.com", "example.com", FALSE },
++ { "f*.example.com", "foo.example.com", FALSE },
++ { "f*.example.com", "bar.example.com", FALSE },
++ { "*o.example.com", "foo.example.com", FALSE },
++ { "*o.example.com", "bar.example.com", FALSE },
++ { "f*o.example.com", "foo.example.com", FALSE },
++ { "f*o.example.com", "bar.example.com", FALSE },
++ { "foo.e*.com", "foo.example.com", FALSE },
++ { "foo.*e.com", "foo.example.com", FALSE },
++ { "foo.e*e.com", "foo.example.com", FALSE },
++ { "foo.example.com", "foo.example.com.", TRUE }, /* trailing dot */
++ { "*.example.com", "foo.example.com.", TRUE },
++ { "foo", "foo.", TRUE },
++ { "foo.example.com.", "foo.example.com", FALSE },
++ { "*.example.com.", "foo.example.com", FALSE },
++ { "foo.", "foo", FALSE },
++ { "foo.example.com", "foo.example.com..", FALSE },
++ { "*.example.com", "foo.example.com..", FALSE },
++ { "foo", "foo..", FALSE },
++ { "foo.example.com..", "foo.example.com", FALSE },
++ { "*.example.com..", "foo.example.com", FALSE },
++ { "foo..", "foo", FALSE },
++ { NULL }
++};
++
++static svn_error_t *
++test_cert_match_dns_identity(apr_pool_t *pool)
++{
++ return run_cert_match_dns_tests(cert_match_dns_tests, pool);
++}
++
++/* This test table implements results that should happen if we supported
++ * RFC 6125 s. 6.4.3 Rule 3. We don't so it's expected to fail for now. */
++static struct cert_match_dns_test rule3_tests[] = {
++ { "baz*.example.net", "baz1.example.net", TRUE },
++ { "*baz.example.net", "foobaz.example.net", TRUE },
++ { "b*z.example.net", "buuz.example.net", TRUE },
++ { "b*z.example.net", "bz.example.net", FALSE }, /* presume wildcard can't
++ match nothing */
++ { "baz*.example.net", "baz.example.net", FALSE },
++ { "*baz.example.net", "baz.example.net", FALSE },
++ { "b*z.example.net", "buuzuuz.example.net", TRUE }, /* presume wildcard
++ should be greedy */
++ { NULL }
++};
++
++static svn_error_t *
++test_rule3(apr_pool_t *pool)
++{
++ return run_cert_match_dns_tests(rule3_tests, pool);
++}
++
+
+ /* The test table. */
+
+@@ -1699,5 +1839,7 @@ struct svn_test_descriptor_t test_funcs[] =
+ SVN_TEST_PASS(test_uri_local_style),
+ SVN_TEST_PASS(test_dirent_internal_style),
+ SVN_TEST_PASS(test_uri_internal_style),
++ SVN_TEST_PASS(test_cert_match_dns_identity),
++ SVN_TEST_XFAIL(test_rule3),
+ SVN_TEST_NULL
+ };
+diff --git a/subversion/include/private/svn_cert.h b/subversion/include/private/svn_cert.h
+new file mode 100644
+index 0000000..32e32a0
+--- /dev/null
++++ b/subversion/include/private/svn_cert.h
+@@ -0,0 +1,68 @@
++/**
++ * @copyright
++ * ====================================================================
++ * Licensed to the Apache Software Foundation (ASF) under one
++ * or more contributor license agreements. See the NOTICE file
++ * distributed with this work for additional information
++ * regarding copyright ownership. The ASF licenses this file
++ * to you under the Apache License, Version 2.0 (the
++ * "License"); you may not use this file except in compliance
++ * with the License. You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing,
++ * software distributed under the License is distributed on an
++ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
++ * KIND, either express or implied. See the License for the
++ * specific language governing permissions and limitations
++ * under the License.
++ * ====================================================================
++ * @endcopyright
++ *
++ * @file svn_cert.h
++ * @brief Implementation of certificate validation functions
++ */
++
++#ifndef SVN_CERT_H
++#define SVN_CERT_H
++
++#include <apr.h>
++
++#include "svn_types.h"
++#include "svn_string.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++
++/* Return TRUE iff @a pattern matches @a hostname as defined
++ * by the matching rules of RFC 6125. In the context of RFC
++ * 6125 the pattern is the domain name portion of the presented
++ * identifier (which comes from the Common Name or a DNSName
++ * portion of the subjectAltName of an X.509 certificate) and
++ * the hostname is the source domain (i.e. the host portion
++ * of the URI the user entered).
++ *
++ * @note With respect to wildcards we only support matching
++ * wildcards in the left-most label and as the only character
++ * in the left-most label (i.e. we support RFC 6125 ยง 6.4.3
++ * Rule 1 and 2 but not the optional Rule 3). This may change
++ * in the future.
++ *
++ * @note Subversion does not at current support internationalized
++ * domain names. Both values are presumed to be in NR-LDH label
++ * or A-label form (see RFC 5890 for the definition).
++ *
++ * @since New in 1.9.
++ */
++svn_boolean_t
++svn_cert__match_dns_identity(svn_string_t *pattern, svn_string_t *hostname);
++
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* SVN_CERT_H */
diff --git a/meta/recipes-devtools/subversion/subversion_1.6.15.bb b/meta/recipes-devtools/subversion/subversion_1.6.15.bb
index 1bc637473b..6680ab6d34 100644
--- a/meta/recipes-devtools/subversion/subversion_1.6.15.bb
+++ b/meta/recipes-devtools/subversion/subversion_1.6.15.bb
@@ -17,7 +17,9 @@ SRC_URI = "http://subversion.tigris.org/downloads/${BPN}-${PV}.tar.bz2 \
file://subversion-CVE-2013-4505.patch \
file://subversion-CVE-2013-1845.patch \
file://subversion-CVE-2013-1847-CVE-2013-1846.patch \
- file://subversion-CVE-2013-4277.patch"
+ file://subversion-CVE-2013-4277.patch \
+ file://subversion-CVE-2014-3522.patch \
+"
SRC_URI[md5sum] = "113fca1d9e4aa389d7dc2b210010fa69"
SRC_URI[sha256sum] = "b2919d603a5f3c19f42e3265c4b930e2376c43b3969b90ef9c42b2f72d5aaa45"
diff --git a/meta/recipes-devtools/subversion/subversion_1.8.9.bb b/meta/recipes-devtools/subversion/subversion_1.8.9.bb
index d134a5352c..e1ab945896 100644
--- a/meta/recipes-devtools/subversion/subversion_1.8.9.bb
+++ b/meta/recipes-devtools/subversion/subversion_1.8.9.bb
@@ -12,6 +12,7 @@ inherit gettext
SRC_URI = "${APACHE_MIRROR}/${BPN}/${BPN}-${PV}.tar.bz2 \
file://libtool2.patch \
file://disable_macos.patch \
+ file://subversion-CVE-2014-3522.patch;striplevel=0 \
"
SRC_URI[md5sum] = "bd495517a760ddd764ce449a891971db"
SRC_URI[sha256sum] = "45d708a5c3ffbef4b2a1044c4716a053e680763743d1f7ba99d0369f6da49e33"