You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by sv...@apache.org on 2014/02/05 05:05:22 UTC
svn commit: r1564623 - in /subversion/branches/1.8.x: ./ STATUS
subversion/include/private/svn_auth_private.h
subversion/libsvn_ra_serf/util.c subversion/libsvn_subr/auth.c
subversion/libsvn_subr/cmdline.c subversion/libsvn_subr/win32_crypto.c
Author: svn-role
Date: Wed Feb 5 04:05:22 2014
New Revision: 1564623
URL: http://svn.apache.org/r1564623
Log:
Merge the r1534149 group from trunk:
* r1534149, r1535676
In the windows CryptoAPI ssl certificate verification, properly handle
certificates that are only trusted via intermediate authorities.
Justification:
While not strictly a bug, intermediate authorities are getting more
common since recent Certificate Authority incidents.
Notes:
rhuijben: This introduces a new credential type as private API.
Not sure about our strict ABI guarantees here, but this affects
usability of users migrating to cloud platforms, etc.
Votes:
+1: rhuijben, steveking, breser
Modified:
subversion/branches/1.8.x/ (props changed)
subversion/branches/1.8.x/STATUS
subversion/branches/1.8.x/subversion/include/private/svn_auth_private.h
subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c
subversion/branches/1.8.x/subversion/libsvn_subr/auth.c
subversion/branches/1.8.x/subversion/libsvn_subr/cmdline.c
subversion/branches/1.8.x/subversion/libsvn_subr/win32_crypto.c
Propchange: subversion/branches/1.8.x/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1534149,1535676
Modified: subversion/branches/1.8.x/STATUS
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/STATUS?rev=1564623&r1=1564622&r2=1564623&view=diff
==============================================================================
--- subversion/branches/1.8.x/STATUS (original)
+++ subversion/branches/1.8.x/STATUS Wed Feb 5 04:05:22 2014
@@ -249,16 +249,3 @@ Veto-blocked changes:
Approved changes:
=================
-
- * r1534149, r1535676
- In the windows CryptoAPI ssl certificate verification, properly handle
- certificates that are only trusted via intermediate authorities.
- Justification:
- While not strictly a bug, intermediate authorities are getting more
- common since recent Certificate Authority incidents.
- Notes:
- rhuijben: This introduces a new credential type as private API.
- Not sure about our strict ABI guarantees here, but this affects
- usability of users migrating to cloud platforms, etc.
- Votes:
- +1: rhuijben, steveking, breser
Modified: subversion/branches/1.8.x/subversion/include/private/svn_auth_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/include/private/svn_auth_private.h?rev=1564623&r1=1564622&r2=1564623&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/include/private/svn_auth_private.h (original)
+++ subversion/branches/1.8.x/subversion/include/private/svn_auth_private.h Wed Feb 5 04:05:22 2014
@@ -37,6 +37,24 @@
extern "C" {
#endif /* __cplusplus */
+/** SSL server authority verification credential type.
+ *
+ * The followin auth parameters are available to the providers:
+ *
+ * - @c SVN_AUTH_PARAM_SSL_SERVER_FAILURES (@c apr_uint32_t*)
+ * - @c SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO
+ * (@c svn_auth_ssl_server_cert_info_t*)
+ *
+ * The following optional auth parameters are relevant to the providers:
+ *
+ * - @c SVN_AUTH_PARAM_NO_AUTH_CACHE (@c void*)
+ *
+ * @since New in 1.9.
+ */
+#define SVN_AUTH_CRED_SSL_SERVER_AUTHORITY "svn.ssl.server.authority"
+
+
+
/* If you add a password type for a provider which stores
* passwords on disk in encrypted form, remember to update
* svn_auth__simple_save_creds_helper. Otherwise it will be
@@ -213,6 +231,25 @@ svn_auth__ssl_client_cert_pw_set(svn_boo
svn_boolean_t non_interactive,
apr_pool_t *pool);
+#if (defined(WIN32) && !defined(__MINGW32__)) || defined(DOXYGEN)
+/**
+ * Set @a *provider to an authentication provider that implements
+ * ssl authority verification via the Windows CryptoApi.
+ *
+ * This provider automatically validates authority certificates with
+ * the CryptoApi, like Internet Explorer and the Windows network API do.
+ * This allows the rollout of root certificates via Windows Domain
+ * policies, instead of Subversion specific configuration.
+ *
+ * @note This function is only available on Windows.
+ */
+void
+svn_auth__get_windows_ssl_server_authority_provider(
+ svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+#endif
+
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c?rev=1564623&r1=1564622&r2=1564623&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_ra_serf/util.c Wed Feb 5 04:05:22 2014
@@ -48,6 +48,7 @@
#include "private/svn_dep_compat.h"
#include "private/svn_fspath.h"
#include "private/svn_subr_private.h"
+#include "private/svn_auth_private.h"
#include "ra_serf.h"
@@ -269,26 +270,70 @@ ssl_server_cert(void *baton, int failure
svn_auth_iterstate_t *state;
const char *realmstring;
apr_uint32_t svn_failures;
- apr_hash_t *issuer, *subject, *serf_cert;
- apr_array_header_t *san;
+ apr_hash_t *issuer;
+ apr_hash_t *subject = NULL;
+ apr_hash_t *serf_cert = NULL;
void *creds;
int found_matching_hostname = 0;
- /* Implicitly approve any non-server certs. */
- if (serf_ssl_cert_depth(cert) > 0)
+ svn_failures = (ssl_convert_serf_failures(failures)
+ | conn->server_cert_failures);
+
+ if (serf_ssl_cert_depth(cert) == 0)
{
- if (failures)
- conn->server_cert_failures |= ssl_convert_serf_failures(failures);
- return APR_SUCCESS;
+ /* If the depth is 0, the hostname must match the certificate.
+
+ ### 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;
+
+ 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) {
+ int i;
+ 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;
+ break;
+ }
+ }
+ }
+
+ /* Match server certificate CN with the hostname of the server */
+ if (!found_matching_hostname)
+ {
+ const char *hostname = NULL;
+
+ subject = serf_ssl_cert_subject(cert, scratch_pool);
+
+ 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 (!svn_failures)
+ return SVN_NO_ERROR;
+
/* Extract the info from the certificate */
- subject = serf_ssl_cert_subject(cert, scratch_pool);
+ if (! subject)
+ subject = serf_ssl_cert_subject(cert, scratch_pool);
issuer = serf_ssl_cert_issuer(cert, scratch_pool);
- serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
+ if (! serf_cert)
+ serf_cert = serf_ssl_cert_certificate(cert, scratch_pool);
cert_info.hostname = svn_hash_gets(subject, "CN");
- san = svn_hash_gets(serf_cert, "subjectAltName");
cert_info.fingerprint = svn_hash_gets(serf_cert, "sha1");
if (! cert_info.fingerprint)
cert_info.fingerprint = apr_pstrdup(scratch_pool, "<unknown>");
@@ -301,32 +346,56 @@ ssl_server_cert(void *baton, int failure
cert_info.issuer_dname = convert_organisation_to_str(issuer, scratch_pool);
cert_info.ascii_cert = serf_ssl_cert_export(cert, scratch_pool);
- svn_failures = (ssl_convert_serf_failures(failures)
- | conn->server_cert_failures);
+ /* Handle any non-server certs. */
+ if (serf_ssl_cert_depth(cert) > 0)
+ {
+ svn_error_t *err;
- /* Try to find matching server name via subjectAltName first... */
- if (san) {
- int i;
- for (i = 0; i < san->nelts; i++) {
- char *s = APR_ARRAY_IDX(san, i, char*);
- if (apr_fnmatch(s, conn->session->session_url.hostname,
- APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_SUCCESS)
- {
- found_matching_hostname = 1;
- cert_info.hostname = s;
- break;
- }
- }
- }
+ svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
+ SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO,
+ &cert_info);
+
+ svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
+ SVN_AUTH_PARAM_SSL_SERVER_FAILURES,
+ &svn_failures);
+
+ realmstring = apr_psprintf(scratch_pool, "AUTHORITY:%s",
+ cert_info.fingerprint);
+
+ err = svn_auth_first_credentials(&creds, &state,
+ SVN_AUTH_CRED_SSL_SERVER_AUTHORITY,
+ realmstring,
+ conn->session->wc_callbacks->auth_baton,
+ scratch_pool);
- /* Match server certificate CN with the hostname of the server */
- if (!found_matching_hostname && cert_info.hostname)
- {
- if (apr_fnmatch(cert_info.hostname, conn->session->session_url.hostname,
- APR_FNM_PERIOD | APR_FNM_CASE_BLIND) == APR_FNM_NOMATCH)
+ svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
+ SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO, NULL);
+
+ svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
+ SVN_AUTH_PARAM_SSL_SERVER_FAILURES, NULL);
+
+ if (err)
{
- svn_failures |= SVN_AUTH_SSL_CNMISMATCH;
+ if (err->apr_err != SVN_ERR_AUTHN_NO_PROVIDER)
+ return svn_error_trace(err);
+
+ /* No provider registered that handles server authorities */
+ svn_error_clear(err);
+ creds = NULL;
}
+
+ if (creds)
+ {
+ server_creds = creds;
+ SVN_ERR(svn_auth_save_credentials(state, scratch_pool));
+
+ svn_failures &= ~server_creds->accepted_failures;
+ }
+
+ if (svn_failures)
+ conn->server_cert_failures |= svn_failures;
+
+ return APR_SUCCESS;
}
svn_auth_set_parameter(conn->session->wc_callbacks->auth_baton,
Modified: subversion/branches/1.8.x/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_subr/auth.c?rev=1564623&r1=1564622&r2=1564623&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_subr/auth.c Wed Feb 5 04:05:22 2014
@@ -35,6 +35,7 @@
#include "svn_private_config.h"
#include "svn_dso.h"
#include "svn_version.h"
+#include "private/svn_auth_private.h"
#include "private/svn_dep_compat.h"
#include "private/svn_subr_private.h"
@@ -540,6 +541,11 @@ svn_auth_get_platform_specific_provider(
{
svn_auth_get_windows_ssl_server_trust_provider(provider, pool);
}
+ else if (strcmp(provider_name, "windows") == 0 &&
+ strcmp(provider_type, "ssl_server_authority") == 0)
+ {
+ svn_auth__get_windows_ssl_server_authority_provider(provider, pool);
+ }
#endif
}
Modified: subversion/branches/1.8.x/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_subr/cmdline.c?rev=1564623&r1=1564622&r2=1564623&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_subr/cmdline.c Wed Feb 5 04:05:22 2014
@@ -505,7 +505,7 @@ svn_cmdline_create_auth_baton(svn_auth_b
svn_auth_get_username_provider(&provider, pool);
APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
- /* The server-cert, client-cert, and client-cert-password providers. */
+ /* The windows ssl server certificate CRYPTOAPI provider. */
SVN_ERR(svn_auth_get_platform_specific_provider(&provider,
"windows",
"ssl_server_trust",
@@ -514,6 +514,15 @@ svn_cmdline_create_auth_baton(svn_auth_b
if (provider)
APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+ /* The windows ssl authority certificate CRYPTOAPI provider. */
+ SVN_ERR(svn_auth_get_platform_specific_provider(&provider,
+ "windows",
+ "ssl_server_authority",
+ pool));
+
+ if (provider)
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
+
svn_auth_get_ssl_server_trust_file_provider(&provider, pool);
APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
svn_auth_get_ssl_client_cert_file_provider(&provider, pool);
Modified: subversion/branches/1.8.x/subversion/libsvn_subr/win32_crypto.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.8.x/subversion/libsvn_subr/win32_crypto.c?rev=1564623&r1=1564622&r2=1564623&view=diff
==============================================================================
--- subversion/branches/1.8.x/subversion/libsvn_subr/win32_crypto.c (original)
+++ subversion/branches/1.8.x/subversion/libsvn_subr/win32_crypto.c Wed Feb 5 04:05:22 2014
@@ -436,8 +436,9 @@ windows_ssl_server_trust_first_credentia
const char *realmstring,
apr_pool_t *pool)
{
- apr_uint32_t *failures = svn_hash_gets(parameters,
- SVN_AUTH_PARAM_SSL_SERVER_FAILURES);
+ apr_uint32_t *failure_ptr = svn_hash_gets(parameters,
+ SVN_AUTH_PARAM_SSL_SERVER_FAILURES);
+ apr_uint32_t failures = *failure_ptr;
const svn_auth_ssl_server_cert_info_t *cert_info =
svn_hash_gets(parameters, SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO);
@@ -445,7 +446,7 @@ windows_ssl_server_trust_first_credentia
*iter_baton = NULL;
/* We can accept only unknown certificate authority. */
- if (*failures & SVN_AUTH_SSL_UNKNOWNCA)
+ if (failures & SVN_AUTH_SSL_UNKNOWNCA)
{
svn_boolean_t ok;
@@ -455,15 +456,16 @@ windows_ssl_server_trust_first_credentia
if (ok)
{
/* Clear failure flag. */
- *failures &= ~SVN_AUTH_SSL_UNKNOWNCA;
+ failures &= ~SVN_AUTH_SSL_UNKNOWNCA;
}
}
/* If all failures are cleared now, we return the creds */
- if (! *failures)
+ if (! failures)
{
svn_auth_cred_ssl_server_trust_t *creds =
apr_pcalloc(pool, sizeof(*creds));
+ creds->accepted_failures = *failure_ptr & ~failures;
creds->may_save = FALSE; /* No need to save it. */
*credentials = creds;
}
@@ -489,4 +491,24 @@ svn_auth_get_windows_ssl_server_trust_pr
*provider = po;
}
+static const svn_auth_provider_t windows_server_authority_provider = {
+ SVN_AUTH_CRED_SSL_SERVER_AUTHORITY,
+ windows_ssl_server_trust_first_credentials,
+ NULL,
+ NULL,
+};
+
+/* Public API */
+void
+svn_auth__get_windows_ssl_server_authority_provider(
+ svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
+
+ po->vtable = &windows_server_authority_provider;
+ *provider = po;
+}
+
+
#endif /* WIN32 */