You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2015/01/30 03:21:17 UTC

svn commit: r1655909 - in /subversion/trunk: ./ notes/ subversion/bindings/javahl/native/ subversion/bindings/javahl/native/jniwrapper/ subversion/bindings/javahl/src/org/apache/subversion/javahl/ subversion/bindings/javahl/src/org/apache/subversion/ja...

Author: breser
Date: Fri Jan 30 02:21:16 2015
New Revision: 1655909

URL: http://svn.apache.org/r1655909
Log:
Merge the svn-auth-x509 branch to trunk.

This adds an X.509 parser which we use to display certificates via the auth
command rather than storing the details provided by serf from a connection.

* LICENSE,
  NOTICE: Note that the X.509 parser is based on the parser from TropicSSL.

* build.conf
  (libsvn_subr): Add svn_x509.h header to msvc-export.
  (x509-test, __ALL_TESTS__): Add C tests for X.509 parser.

* subversion/include/private/svn_utf_private.h
  (svn_utf__encode_ucs4_string, svn_utf__utf16_to_utf8,
   svn_utf__utf32_to_utf8): New functions for converting various Unicode
     character encodings needed by the X.509 parser.

* subversion/include/svn_x509.h: New header.

* subversion/include/svn_error_codes.h
  (SVN_ERR_X509_CATEGORY_START): New category for errors from X.509 parser.
  (SVN_ERR_ASN1_OUT_OF_DATA, SVN_ERR_ASN1_UNEXPECTED_TAG,
   SVN_ERR_ASN1_INVALID_LENGTH, SVN_ERR_ASN1_LENGTH_MISMATCH,
   SVN_ERR_ASN1_INVALID_DATA, SVN_ERR_X509_FEATURE_UNAVAILABLE,
   SVN_ERR_X509_CERT_INVALID_PEM, SVN_ERR_X509_CERT_INVALID_FORMAT,
   SVN_ERR_X509_CERT_INVALID_VERSION, SVN_ERR_X509_CERT_INVALID_SERIAL,
   SVN_ERR_X509_CERT_INVALID_ALG, SVN_ERR_X509_CERT_INVALID_NAME,
   SVN_ERR_X509_CERT_INVALID_DATE, SVN_ERR_X509_CERT_INVALID_PUBKEY,
   SVN_ERR_X509_CERT_INVALID_SIGNATURE, SVN_ERR_X509_CERT_INVALID_EXTENSIONS,
   SVN_ERR_X509_CERT_UNKNOWN_VERSION, SVN_ERR_X509_CERT_UNKNOWN_PK_ALG,
   SVN_ERR_X509_CERT_SIG_MISMATCH, SVN_ERR_X509_CERT_VERIFY_FAILED):
    New error codes.

* subversion/include/svn_config.h
  (SVN_CONFIG_AUTHN_HOSTNAME_KEY, SVN_CONFIG_AUTHN_FINGERPRINT_KEY,
   SVN_CONFIG_AUTHN_VALID_FROM_KEY, SVN_CONFIG_AUTHN_VALID_UNTIL_KEY,
   SVN_CONFIG_AUTHN_ISSUER_DN_KEY): Remove constants used as keys for
    storing parsed certificate info in authn files.

* subversion/libsvn_subr/x509parse.c,
  subversion/libsvn_subr/x509info.c,
  subversion/include/x509.h: New files for implementing the X.509 parser.

* subversion/libsvn_subr/ssl_server_trust_providers.c
  (ssl_server_trust_file_first_credentials,
   ssl_server_trust_file_save_credentials): Don't store/retrive parsed
    details of X.509 certificates.

* subversion/libsvn_subr/utf.c
  (membuf_insert_ucs4, svn_utf__utf16_to_utf8, svn_utf__utf32_to_utf8):
    New functions to implement Unicode conversions.

* subversion/libsvn_subr/utf8proc.c
  (encode_ucs4_string): Convert to the private function ...
  (svn_utf__encode_ucs4_string): New function.
  (svn_utf__glob): Update caller.

* subversion/svn/auth-cmd.c
  (match_credential): Remove code to match the hostname/fingerprint since
    the data isn't stored.
  (show_cert): New function to drive the X.509 parser and then display
    the certificate to the user.
  (list_credential): Use show_cert().

* subversion/tests/libsvn_subr/utf-test.c
  (test_utf_conversions, test_funcs): Add tests for new unicode character
    set conversions.

* subversion/tests/libsvn_subr/x509-test.c: Add tests for X.509 parser.

[in subverison/bindings/javahl]
* native/jniwrapper/jni_base.cpp,
  native/jniwrapper/jni_exception.hpp:
    Add IllegalArgumentException exeption.

* native/AuthnCallback.cpp,
  native/AuthnCallback.hpp,
  src/org/apache/subversion/javahl/callback/AuthnCallback.java:
  (AuthnCallback::SSLServerCertInfo): Update the getters and constructor to
    reflect the info available from the X.509 parser.

* native/org_apache_subversion_javahl_util_ConfigLib.cpp
  (build_credential): Update to feed AuthnCallback::SSLServerCertInfo the info
    that is available.
  (Java_org_apache_subversion_javahl_util_ConfigLib_nativeSearchCredentials):
    Update the searching of the certificates to parse the certificate rather
    than depending on the stored data.

* src/org/apache/subversion/javahl/SVNUtil.java
  (SVNUtil.searchCredentials): Update hostnamePattern documentation.

* native/Promper.cpp
  (Prompter::dispatch_ssl_server_trust_prompt): Update to reflect changes
    to SSLServerCertInfo.

* src/org/apache/subversion/javahl/util/ConfigLib.java: Remove some commented
    out code.

* tests/org/apache/subversion/javahl/UtilTests.java
  (util_cred_ssl_server, testCredentials): Update tests as needed.


Added:
    subversion/trunk/subversion/include/svn_x509.h
      - copied unchanged from r1655900, subversion/branches/svn-auth-x509/subversion/include/svn_x509.h
    subversion/trunk/subversion/libsvn_subr/x509.h
      - copied unchanged from r1655900, subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509.h
    subversion/trunk/subversion/libsvn_subr/x509info.c
      - copied unchanged from r1655900, subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509info.c
    subversion/trunk/subversion/libsvn_subr/x509parse.c
      - copied unchanged from r1655900, subversion/branches/svn-auth-x509/subversion/libsvn_subr/x509parse.c
    subversion/trunk/subversion/tests/libsvn_subr/x509-test.c
      - copied unchanged from r1655900, subversion/branches/svn-auth-x509/subversion/tests/libsvn_subr/x509-test.c
Modified:
    subversion/trunk/   (props changed)
    subversion/trunk/LICENSE
    subversion/trunk/NOTICE
    subversion/trunk/build.conf
    subversion/trunk/notes/   (props changed)
    subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.cpp
    subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.hpp
    subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp
    subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp
    subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/AuthnCallback.java
    subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java
    subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
    subversion/trunk/subversion/include/private/svn_utf_private.h
    subversion/trunk/subversion/include/svn_config.h
    subversion/trunk/subversion/include/svn_error_codes.h
    subversion/trunk/subversion/libsvn_fs_x/   (props changed)
    subversion/trunk/subversion/libsvn_subr/ssl_server_trust_providers.c
    subversion/trunk/subversion/libsvn_subr/utf.c
    subversion/trunk/subversion/libsvn_subr/utf8proc.c
    subversion/trunk/subversion/svn/auth-cmd.c
    subversion/trunk/subversion/tests/libsvn_fs_x/   (props changed)
    subversion/trunk/subversion/tests/libsvn_subr/utf-test.c

Propchange: subversion/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Jan 30 02:21:16 2015
@@ -67,6 +67,7 @@
 /subversion/branches/revprop-caching-ng:1620597,1620599
 /subversion/branches/revprop-packing:1143907,1143971,1143997,1144017,1144499,1144568,1146145
 /subversion/branches/subtree-mergeinfo:876734-878766
+/subversion/branches/svn-auth-x509:1603509-1655900
 /subversion/branches/svn-mergeinfo-enhancements:870119-870195,870197-870288
 /subversion/branches/svn-patch-improvements:918519-934609
 /subversion/branches/svn_mutex:1141683-1182099

Modified: subversion/trunk/LICENSE
URL: http://svn.apache.org/viewvc/subversion/trunk/LICENSE?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/LICENSE (original)
+++ subversion/trunk/LICENSE Fri Jan 30 02:21:16 2015
@@ -332,3 +332,37 @@ For the (modified) utf8proc library in s
   Unicode and the Unicode logo are trademarks of Unicode, Inc., and may be
   registered in some jurisdictions. All other trademarks and registered
   trademarks mentioned herein are the property of their respective owners.
+
+For the files subversion/libsvn_subr/x509parse.c and
+subversion/libsvn_subr/x509.h
+
+ *  Based on XySSL: Copyright (C) 2006-2008   Christophe Devine
+ *
+ *  Copyright (C) 2009  Paul Bakker <polarssl_maintainer at polarssl dot org>
+ *
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *    * Neither the names of PolarSSL or XySSL nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ *  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Modified: subversion/trunk/NOTICE
URL: http://svn.apache.org/viewvc/subversion/trunk/NOTICE?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/NOTICE (original)
+++ subversion/trunk/NOTICE Fri Jan 30 02:21:16 2015
@@ -22,4 +22,7 @@ modifications by Spyglass Inc., Carnegie
 Bell Communications Research, Inc (Bellcore).
 
 This product includes software developed by Public Software Group e. V.
-under a permissive license, see LICENSE.
\ No newline at end of file
+under a permissive license, see LICENSE.
+
+This software contains code derived from TropicSSL under a BSD 3-Clause
+license, see LICENSE.

Modified: subversion/trunk/build.conf
URL: http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Fri Jan 30 02:21:16 2015
@@ -372,7 +372,7 @@ msvc-export =
         svn_error.h svn_hash.h svn_io.h svn_iter.h svn_md5.h svn_mergeinfo.h 
         svn_nls.h svn_opt.h svn_path.h svn_pools.h svn_props.h svn_quoprint.h 
         svn_sorts.h svn_string.h svn_subst.h svn_time.h svn_types.h svn_user.h
-        svn_utf.h svn_version.h svn_xml.h 
+        svn_utf.h svn_version.h svn_xml.h svn_x509.h
         private\svn_atomic.h private\svn_cache.h private\svn_cmdline_private.h
         private\svn_debug.h private\svn_error_private.h private\svn_fspath.h
         private\svn_log.h private\svn_mergeinfo_private.h
@@ -1124,6 +1124,15 @@ sources = translate-test.c
 install = test
 libs = libsvn_test libsvn_subr apriconv apr
 
+[x509-test]
+description = Test x509 parser
+type = exe
+path = subversion/tests/libsvn_subr
+sources = x509-test.c
+install = test
+libs = libsvn_test libsvn_subr apriconv apr
+
+
 # ----------------------------------------------------------------------------
 # Tests for libsvn_delta
 
@@ -1490,7 +1499,7 @@ libs = __ALL__
        conflict-data-test db-test pristine-store-test entries-compat-test
        op-depth-test dirent_uri-test wc-queries-test wc-test
        auth-test
-       parse-diff-test
+       parse-diff-test x509-test
 
 [__MORE__]
 type = project

Propchange: subversion/trunk/notes/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Jan 30 02:21:16 2015
@@ -25,6 +25,7 @@
 /subversion/branches/ra_serf-digest-authn/notes:875693-876404
 /subversion/branches/reintegrate-improvements/notes:873853-874164
 /subversion/branches/subtree-mergeinfo/notes:876734-878766
+/subversion/branches/svn-auth-x509/notes:1603509-1655900
 /subversion/branches/svn-mergeinfo-enhancements/notes:870119-870195,870197-870288
 /subversion/branches/svn-patch-improvements/notes:918519-934609
 /subversion/branches/svnpatch-diff/notes:865738-876477

Modified: subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.cpp?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.cpp Fri Jan 30 02:21:16 2015
@@ -21,10 +21,19 @@
  * @endcopyright
  */
 
+#include "svn_base64.h"
+#include "svn_x509.h"
+
 #include "jniwrapper/jni_stack.hpp"
+#include "jniwrapper/jni_exception.hpp"
+#include "jniwrapper/jni_string.hpp"
+#include "jniwrapper/jni_array.hpp"
+#include "jniwrapper/jni_list.hpp"
 
 #include "AuthnCallback.hpp"
 
+#include "svn_private_config.h"
+
 namespace JavaHL {
 
 // Class JavaHL::AuthnCallback
@@ -176,30 +185,75 @@ AuthnCallback::SSLServerCertInfo::ClassI
   : ::Java::Object::ClassImpl(env, cls),
     m_mid_ctor(env.GetMethodID(cls, "<init>",
                                "(Ljava/lang/String;"
-                               "Ljava/lang/String;"
-                               "Ljava/lang/String;"
-                               "Ljava/lang/String;"
-                               "Ljava/lang/String;"
+                               "Ljava/lang/String;JJ[B"
+                               "Ljava/util/List;"
                                "Ljava/lang/String;)V"))
 {}
 
 AuthnCallback::SSLServerCertInfo::ClassImpl::~ClassImpl() {}
 
 AuthnCallback::SSLServerCertInfo::SSLServerCertInfo(
-    ::Java::Env env,
-    const ::Java::String& hostname,
-    const ::Java::String& fingerprint,
-    const ::Java::String& validFrom,
-    const ::Java::String& validUntil,
-    const ::Java::String& issuer,
-    const ::Java::String& der)
+    ::Java::Env env, const char* ascii_cert)
   : ::Java::Object(env,
                    ::Java::ClassCache::get_authn_ssl_server_cert_info(env))
 {
+  SVN::Pool pool;
+
+  /* Convert header-less PEM to DER by undoing base64 encoding. */
+  const svn_string_t cert_string = { ascii_cert, strlen(ascii_cert) };
+  const svn_string_t* der = svn_base64_decode_string(&cert_string,
+                                                     pool.getPool());
+
+  svn_x509_certinfo_t *certinfo;
+  SVN_JAVAHL_CHECK(env, svn_x509_parse_cert(&certinfo, der->data, der->len,
+                                            pool.getPool(), pool.getPool()));
+
+  const ::Java::String subject(
+      env, svn_x509_certinfo_get_subject(certinfo, pool.getPool()));
+  const ::Java::String issuer(
+      env, svn_x509_certinfo_get_issuer(certinfo, pool.getPool()));
+  const ::Java::String cert(env, ascii_cert);
+  const jlong valid_from =
+    (jlong(svn_x509_certinfo_get_valid_from(certinfo)) + 500) / 1000;
+  const jlong valid_to =
+    (jlong(svn_x509_certinfo_get_valid_to(certinfo)) + 500) / 1000;
+
+  const svn_checksum_t* digest = svn_x509_certinfo_get_digest(certinfo);
+  jsize digest_size;
+  switch (digest->kind)
+    {
+    case svn_checksum_sha1:
+      digest_size = 160 / 8;
+      break;
+
+    case svn_checksum_md5:
+      digest_size = 128 / 8;
+      break;
+
+    default:
+      digest_size = 0;          // Initialize this to avoid compiler warnings
+      ::Java::IllegalArgumentException(env).raise(
+          _("Unknown certificate digest type"));
+    }
+  const ::Java::ByteArray fingerprint(env, digest->digest, digest_size);
+
+  jobject jhostnames = NULL;
+  const apr_array_header_t* hostnames =
+    svn_x509_certinfo_get_hostnames(certinfo);
+  if (hostnames)
+    {
+      ::Java::MutableList< ::Java::String> hn(env, hostnames->nelts);
+      for (int i = 0; i < hostnames->nelts; ++i)
+        hn.add(::Java::String(env, APR_ARRAY_IDX(hostnames, i, const char*)));
+      jhostnames = hn.get();
+    }
+
   set_this(env.NewObject(get_class(), impl().m_mid_ctor,
-                         hostname.get(), fingerprint.get(),
-                         validFrom.get(), validUntil.get(),
-                         issuer.get(), der.get()));
+                         subject.get(), issuer.get(),
+                         valid_from, valid_to,
+                         fingerprint.get(),
+                         jhostnames,
+                         cert.get()));
 }
 
 

Modified: subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.hpp?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.hpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/AuthnCallback.hpp Fri Jan 30 02:21:16 2015
@@ -153,13 +153,7 @@ public:
     /**
      * Creates and initializes a wrapped object;
      */
-    explicit SSLServerCertInfo(::Java::Env env,
-                               const ::Java::String& hostname,
-                               const ::Java::String& fingerprint,
-                               const ::Java::String& validFrom,
-                               const ::Java::String& validUntil,
-                               const ::Java::String& issuer,
-                               const ::Java::String& der);
+    explicit SSLServerCertInfo(::Java::Env env, const char* ascii_cert);
 
   private:
     /**

Modified: subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/Prompter.cpp Fri Jan 30 02:21:16 2015
@@ -325,14 +325,7 @@ svn_error_t *Prompter::dispatch_ssl_serv
       authn.ssl_server_trust_prompt(
           ::Java::String(env, realm),
           ::JavaHL::AuthnCallback::SSLServerCertFailures(env, jint(failures)),
-          ::JavaHL::AuthnCallback::SSLServerCertInfo(
-              env,
-              ::Java::String(env, cert_info->hostname),
-              ::Java::String(env, cert_info->fingerprint),
-              ::Java::String(env, cert_info->valid_from),
-              ::Java::String(env, cert_info->valid_until),
-              ::Java::String(env, cert_info->issuer_dname),
-              ::Java::String(env, cert_info->ascii_cert)),
+          ::JavaHL::AuthnCallback::SSLServerCertInfo(env, cert_info->ascii_cert),
           may_save));
   if (!result.get())
     return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,

Modified: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp Fri Jan 30 02:21:16 2015
@@ -329,6 +329,8 @@ const char* const IndexOutOfBoundsExcept
 const char* const IOException::m_class_name =
   "java/io/IOException";
 
+const char* const IllegalArgumentException::m_class_name =
+  "java/lang/IllegalArgumentException";
 
 // Implementation of jni_stack.hpp
 

Modified: subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/jniwrapper/jni_exception.hpp Fri Jan 30 02:21:16 2015
@@ -286,6 +286,25 @@ private:
   static const char* const m_class_name;
 };
 
+/**
+ * Generator class for exceptions of type @c java.lang.IllegalArgumentException.
+ *
+ * @since New in 1.9.
+ */
+class IllegalArgumentException : public Exception
+{
+public:
+  /**
+   * Constructs an exception generator object.
+   */
+  explicit IllegalArgumentException(Env env)
+    : Exception(env, m_class_name)
+    {}
+
+private:
+  static const char* const m_class_name;
+};
+
 } // namespace Java
 
 #endif // SVN_JAVAHL_JNIWRAPPER_ENV_HPP

Modified: subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/org_apache_subversion_javahl_util_ConfigLib.cpp Fri Jan 30 02:21:16 2015
@@ -41,8 +41,10 @@
 #include "JNICriticalSection.h"
 
 #include "svn_auth.h"
+#include "svn_base64.h"
 #include "svn_config.h"
 #include "svn_hash.h"
+#include "svn_x509.h"
 
 #include "svn_private_config.h"
 
@@ -140,41 +142,14 @@ jobject build_credential(Java::Env env,
   else if (0 == strcmp(cred_kind, SVN_AUTH_CRED_SSL_SERVER_TRUST))
     {
       entry = static_cast<svn_string_t*>(
-          svn_hash_gets(cred, SVN_CONFIG_AUTHN_HOSTNAME_KEY));
-      const char* hostname = (entry ? entry->data : NULL);
-
-      entry = static_cast<svn_string_t*>(
-          svn_hash_gets(cred, SVN_CONFIG_AUTHN_FINGERPRINT_KEY));
-      const char* fingerprint = (entry ? entry->data : NULL);
-
-      entry = static_cast<svn_string_t*>(
-          svn_hash_gets(cred, SVN_CONFIG_AUTHN_VALID_FROM_KEY));
-      const char* valid_from = (entry ? entry->data : NULL);
-
-      entry = static_cast<svn_string_t*>(
-          svn_hash_gets(cred, SVN_CONFIG_AUTHN_VALID_UNTIL_KEY));
-      const char* valid_until = (entry ? entry->data : NULL);
-
-      entry = static_cast<svn_string_t*>(
-          svn_hash_gets(cred, SVN_CONFIG_AUTHN_ISSUER_DN_KEY));
-      const char* issuer = (entry ? entry->data : NULL);
-
-      entry = static_cast<svn_string_t*>(
           svn_hash_gets(cred, SVN_CONFIG_AUTHN_ASCII_CERT_KEY));
-      const char* der = (entry ? entry->data : NULL);
+      const char* ascii_cert = (entry ? entry->data : NULL);
 
       entry = static_cast<svn_string_t*>(
           svn_hash_gets(cred, SVN_CONFIG_AUTHN_FAILURES_KEY));
       jint failflags = (!entry ? 0 : jint(apr_atoi64(entry->data)));
 
-      info = JavaHL::AuthnCallback
-        ::SSLServerCertInfo(env,
-                            Java::String(env, hostname),
-                            Java::String(env, fingerprint),
-                            Java::String(env, valid_from),
-                            Java::String(env, valid_until),
-                            Java::String(env, issuer),
-                            Java::String(env, der)).get();
+      info = JavaHL::AuthnCallback::SSLServerCertInfo(env, ascii_cert).get();
       failures = JavaHL::AuthnCallback
         ::SSLServerCertFailures(env, failflags).get();
     }
@@ -370,6 +345,19 @@ Java_org_apache_subversion_javahl_util_C
         const ::Java::Env m_env;
         ::Java::MutableList<JavaHL::Credential> m_credentials;
 
+        bool match_array(const char* pattern,
+                         const apr_array_header_t* hostnames)
+          {
+            for (int i = 0; i < hostnames->nelts; ++i)
+              {
+                const char* const hostname =
+                  APR_ARRAY_IDX(hostnames, i, const char*);
+                if (!apr_fnmatch(pattern, hostname, 0))
+                  return true;
+              }
+            return false;
+          }
+
       public:
         explicit Callback(::Java::Env ctor_env,
                           const char* ctor_cred_kind,
@@ -411,25 +399,41 @@ Java_org_apache_subversion_javahl_util_C
                 svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_PASSTYPE_KEY));
             const char* const store = (entry ? entry->data : NULL);
 
-            entry = static_cast<svn_string_t*>(
-                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_HOSTNAME_KEY));
-            const char* const hostname = (entry ? entry->data : NULL);
-
-            entry = static_cast<svn_string_t*>(
-                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_FINGERPRINT_KEY));
-            const char* const fingerprint = (entry ? entry->data : NULL);
+            const svn_string_t* ascii_cert = static_cast<svn_string_t*>(
+                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_ASCII_CERT_KEY));
 
-            entry = static_cast<svn_string_t*>(
-                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_VALID_FROM_KEY));
-            const char* const valid_from = (entry ? entry->data : NULL);
-
-            entry = static_cast<svn_string_t*>(
-                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_VALID_UNTIL_KEY));
-            const char* const valid_until = (entry ? entry->data : NULL);
-
-            entry = static_cast<svn_string_t*>(
-                svn_hash_gets(cb_cred_hash, SVN_CONFIG_AUTHN_ISSUER_DN_KEY));
-            const char* const issuer = (entry ? entry->data : NULL);
+            /* Parsed certificate data. */
+            const char* subject = NULL;
+            const char* issuer = NULL;
+            const char* fingerprint = NULL;
+            const apr_array_header_t* hostnames = NULL;
+
+            if (ascii_cert)
+              {
+                const svn_string_t* const der =
+                  svn_base64_decode_string(ascii_cert, cb_scratch_pool);
+                svn_x509_certinfo_t* certinfo;
+                svn_error_t* err = svn_x509_parse_cert(
+                    &certinfo, der->data, der->len,
+                    cb_scratch_pool, cb_scratch_pool);
+                if (err)
+                  {
+                    // Ignore credentials that can't be parsed.
+                    svn_error_clear(err);
+                    return SVN_NO_ERROR;
+                  }
+                else
+                  {
+                    subject = svn_x509_certinfo_get_subject(
+                        certinfo, cb_scratch_pool);
+                    issuer = svn_x509_certinfo_get_issuer(
+                        certinfo, cb_scratch_pool);
+                    fingerprint = svn_checksum_to_cstring_display(
+                        svn_x509_certinfo_get_digest(certinfo),
+                        cb_scratch_pool);
+                    hostnames = svn_x509_certinfo_get_hostnames(certinfo);
+                  }
+              }
 
             bool match = (m_realm_pattern
                           && !apr_fnmatch(m_realm_pattern, cb_realmstring, 0));
@@ -441,8 +445,8 @@ Java_org_apache_subversion_javahl_util_C
 
             if (!match && m_hostname_pattern)
               match = (match
-                       || (hostname
-                           && !apr_fnmatch(m_hostname_pattern, hostname, 0)));
+                       || (hostnames
+                           &&  match_array(m_hostname_pattern, hostnames)));
 
             if (!match && m_text_pattern)
               match = (match
@@ -450,16 +454,14 @@ Java_org_apache_subversion_javahl_util_C
                            && !apr_fnmatch(m_text_pattern, username, 0))
                        || (store
                            && !apr_fnmatch(m_text_pattern, store, 0))
-                       || (hostname
-                           && !apr_fnmatch(m_text_pattern, hostname, 0))
+                       || (subject
+                           && !apr_fnmatch(m_text_pattern, subject, 0))
+                       || (issuer
+                           && !apr_fnmatch(m_text_pattern, issuer, 0))
                        || (fingerprint
                            && !apr_fnmatch(m_text_pattern, fingerprint, 0))
-                       || (valid_from
-                           && !apr_fnmatch(m_text_pattern, valid_from, 0))
-                       || (valid_until
-                           && !apr_fnmatch(m_text_pattern, valid_until, 0))
-                       || (issuer
-                           && !apr_fnmatch(m_text_pattern, issuer, 0)));
+                       || (hostnames
+                           && match_array(m_text_pattern, hostnames)));
 
             if (match)
               m_credentials.add(

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java Fri Jan 30 02:21:16 2015
@@ -466,11 +466,12 @@ public class SVNUtil
      *             otherwise, only those credentials that have a username,
      *             and where the username matches the pattern, will be
      *             returned.
-     * @param hostnamePattern A glob pattern for the hostname (CN) of
-     *             a server certificate; if <code>null</code>, all credntials
-     *             will be considered; otherwise, only those credentials
-     *             that have a server certificate with a hostname that
-     *             matches the pattern will be returned.
+     * @param hostnamePattern A glob pattern for the hostnames of a
+     *             server certificate; if <code>null</code>, all
+     *             credntials will be considered; otherwise, only
+     *             those credentials that have a server certificate
+     *             with a hostname that matches the pattern will be
+     *             returned.
      * @param textPattern A glob pattern that must match any textual
      *             information in a credential, for example, a realm,
      *             username, certificate details, etc; passwords, passphrases

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/AuthnCallback.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/AuthnCallback.java?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/AuthnCallback.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/AuthnCallback.java Fri Jan 30 02:21:16 2015
@@ -23,6 +23,8 @@
 
 package org.apache.subversion.javahl.callback;
 
+import java.util.Date;
+import java.util.List;
 import java.util.logging.Logger;
 
 /**
@@ -243,74 +245,84 @@ public interface AuthnCallback
         private static final long serialVersionUID = 1L;
 
         /**
-         * @return The primary CN of the certificate.
+         * @return The subject of the certificate.
          */
-        public String getHostname()
+        public String getSubject()
         {
-            return hostname;
+            return subject;
         }
 
         /**
-         * @return The text representation of the certificate fingerprint.
+         * @return The certificate issuer.
          */
-        public String getFingerprint()
+        public String getIssuer()
         {
-            return fingerprint;
+            return issuer;
         }
 
         /**
-         * @return The text represent representation of the date from
-         *         which the certificate is valid.
+         * @return The from which the certificate is valid.
          */
-        public String getValidFrom()
+        public Date getValidFrom()
         {
             return validFrom;
         }
 
         /**
-         * @return The text represent representation of the date after
-         *         which the certificate is no longer valid.
+         * @return The date after which the certificate is no longer valid.
          */
-        public String getValidUntil()
+        public Date getValidTo()
         {
-            return validUntil;
+            return validTo;
         }
 
         /**
-         * @return The DN of the certificate issuer.
+         * @return The certificate fingerprint.
          */
-        public String getIssuer()
+        public byte[] getFingerprint()
         {
-            return issuer;
+            return fingerprint;
         }
 
         /**
-         * @return the Base64-encoded DER representation of the certificate.
+         * @return A list of host names that the certificate represents.
          */
-        public String getDER()
+        public List<String> getHostnames()
         {
-            return der;
+            return hostnames;
+        }
+
+        /**
+         * @return the Base64-encoded raw certificate data.
+         */
+        public String getCert()
+        {
+            return asciiCert;
         }
 
         /* This private constructor is used by the native implementation. */
-        private SSLServerCertInfo(String hostname, String fingerprint,
-                                  String validFrom, String validUntil,
-                                  String issuer, String der)
+        private SSLServerCertInfo(String subject, String issuer,
+                                  long validFrom, long validTo,
+                                  byte[] fingerprint,
+                                  List<String> hostnames,
+                                  String asciiCert)
         {
-            this.hostname = hostname;
-            this.fingerprint = fingerprint;
-            this.validFrom = validFrom;
-            this.validUntil = validUntil;
+            this.subject = subject;
             this.issuer = issuer;
-            this.der = der;
+            this.validFrom = new Date(validFrom);
+            this.validTo = new Date(validTo);
+            this.fingerprint = fingerprint;
+            this.hostnames = hostnames;
+            this.asciiCert = asciiCert;
         }
 
-        private String hostname;
-        private String fingerprint;
-        private String validFrom;
-        private String validUntil;
+        private String subject;
         private String issuer;
-        private String der;
+        private Date validFrom;
+        private Date validTo;
+        private byte[] fingerprint;
+        private List<String> hostnames;
+        private String asciiCert;
     }
 
     /**

Modified: subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java (original)
+++ subversion/trunk/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java Fri Jan 30 02:21:16 2015
@@ -81,48 +81,6 @@ public class ConfigLib
         return nativeRemoveCredential(configDir, kind.toString(), realm);
     }
 
-    ///** @see SVNUtil.addCredential */
-    //public SVNUtil.Credential addCredential(String configDir,
-    //                                        SVNUtil.Credential credential,
-    //                                        boolean replace)
-    //    throws ClientException, SubversionException
-    //{
-    //    final SVNUtil.Credential.Kind kind = credential.getKind();
-    //
-    //    final String username =
-    //        ((kind == SVNUtil.Credential.Kind.username
-    //          || kind == SVNUtil.Credential.Kind.simple)
-    //         ? credential.getUsername() : null);
-    //
-    //    final String password =
-    //        (kind == SVNUtil.Credential.Kind.simple
-    //         ? credential.getPassword() : null);
-    //
-    //    final AuthnCallback.SSLServerCertInfo sci =
-    //        (kind == SVNUtil.Credential.Kind.sslServer
-    //         ? credential.getServerCertInfo() : null);
-    //
-    //    final AuthnCallback.SSLServerCertFailures scf =
-    //        (kind == SVNUtil.Credential.Kind.sslServer
-    //         ? credential.getServerCertFailures() : null);
-    //
-    //    final String passphrase =
-    //        (kind == SVNUtil.Credential.Kind.sslClientPassphrase
-    //         ? credential.getClientCertPassphrase() : null);
-    //
-    //    return nativeAddCredential(configDir, kind.toString(),
-    //                               credential.getRealm(),
-    //                               username, password,
-    //                               (sci != null ? sci.getHostname() : null),
-    //                               (sci != null ? sci.getFingerprint() : null),
-    //                               (sci != null ? sci.getValidFrom() : null),
-    //                               (sci != null ? sci.getValidUntil() : null),
-    //                               (sci != null ? sci.getIssuer() : null),
-    //                               (sci != null ? sci.getDER() : null),
-    //                               (scf != null ? scf.getFailures() : 0),
-    //                               passphrase);
-    //}
-
     /** @see SVNUtil.searchCredentials */
     public List<SVNUtil.Credential>
         searchCredentials(String configDir,
@@ -151,22 +109,6 @@ public class ConfigLib
                                String realm)
         throws ClientException, SubversionException;
 
-    //private native SVNUtil.Credential
-    //    nativeAddCredential(String configDir,
-    //                        String kind,
-    //                        String realm,
-    //                        String username,
-    //                        String password,
-    //                        String serverCertHostname,
-    //                        String serverCertFingerprint,
-    //                        String serverCertValidFrom,
-    //                        String serverCertValidUntil,
-    //                        String serverCertIssuer,
-    //                        String serverCertDER,
-    //                        int serverCertFailures,
-    //                        String clientCertPassphrase)
-    //    throws ClientException, SubversionException;
-
     private native List<SVNUtil.Credential>
         nativeSearchCredentials(String configDir,
                                 String kind,

Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java (original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/UtilTests.java Fri Jan 30 02:21:16 2015
@@ -627,16 +627,41 @@ public class UtilTests extends SVNTests
     private static final String util_cred_ssl_server =
         "K 10\n" +
         "ascii_cert\n" +
-        "V 12\n" +
-        "NotTelling==\n" +
+        "V 1616\n" +
+        "MIIEtzCCA5+gAwIBAgIQWGBOrapkezd+BWVsAtmtmTANBgkqhkiG9w0BAQsFADA8" +
+        "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMVGhhd3RlLCBJbmMuMRYwFAYDVQQDEw1U" +
+        "aGF3dGUgU1NMIENBMB4XDTE0MDQxMTAwMDAwMFoXDTE2MDQwNzIzNTk1OVowgYsx" +
+        "CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxQLRm9yZXN0" +
+        "IEhpbGwxIzAhBgNVBAoUGkFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRcwFQYD" +
+        "VQQLFA5JbmZyYXN0cnVjdHVyZTEVMBMGA1UEAxQMKi5hcGFjaGUub3JnMIIBIjAN" +
+        "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Tq4mH+stRoxe4xth8tUCgLt+P4L" +
+        "D/JWZz4a2IecaaAk57vIlTxEyP16fUShUfxVJnD0KV11zv2qaEUXNaA6hKd4H/oB" +
+        "u2OyGev+quRM+aFCjWqASkXt7fLGsIkHAwP3XwBVBpARbcXJeCjCBxqaYrQqS8LT" +
+        "wfPUD9eYncGlQ+ixb3Bosy7TmkWKeLsRdS90cAO/rdgQ8OI7kLT/1tr5GpF9RmXo" +
+        "RnVqMP+U0zGd/BNNSneg7emb7TxLzxeMKZ7QbF4MZi8RRN11spvx8/f92CiYrGGu" +
+        "y67VdOGPaomYc+VZ2syLwduHGK40ADrEK3+MQpsRFB0dM08j9bhpr5A44wIDAQAB" +
+        "o4IBYzCCAV8wFwYDVR0RBBAwDoIMKi5hcGFjaGUub3JnMAkGA1UdEwQCMAAwQgYD" +
+        "VR0gBDswOTA3BgpghkgBhvhFAQc2MCkwJwYIKwYBBQUHAgEWG2h0dHBzOi8vd3d3" +
+        "LnRoYXd0ZS5jb20vY3BzLzAOBgNVHQ8BAf8EBAMCBaAwHwYDVR0jBBgwFoAUp6KD" +
+        "uzRFQD381TBPErk+oQGf9tswOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL3N2ci1v" +
+        "di1jcmwudGhhd3RlLmNvbS9UaGF3dGVPVi5jcmwwHQYDVR0lBBYwFAYIKwYBBQUH" +
+        "AwEGCCsGAQUFBwMCMGkGCCsGAQUFBwEBBF0wWzAiBggrBgEFBQcwAYYWaHR0cDov" +
+        "L29jc3AudGhhd3RlLmNvbTA1BggrBgEFBQcwAoYpaHR0cDovL3N2ci1vdi1haWEu" +
+        "dGhhd3RlLmNvbS9UaGF3dGVPVi5jZXIwDQYJKoZIhvcNAQELBQADggEBAF52BLvl" +
+        "x5or9/aO7+cPhxuPxwiNRgbvHdCakD7n8vzjNyct9fKp6/XxB6GQiTZ0nZPJOyIu" +
+        "Pi1QDLKOXvaPeLKDBilL/+mrn/ev3s/aRQSrUsieKDoQnqtmlxEHc/T3+Ni/RZob" +
+        "PD4GzPuNKpK3BIc0fk/95T8R1DjBSQ5/clvkzOKtcl3VffAwnHiE9TZx9js7kZwO" +
+        "b9nOKX8DFao3EpQcS7qn63Ibzbq5A6ry8ZNRQSIJK/xlCAWoyUd1uxnqGFnus8wb" +
+        "9RVZJQe8YvyytBjgbE3QjnfPOxoEJA3twupnPmH+OCTM6V3TZqpRZj/sZ5rtIQ++" +
+        "hI5FdJWUWVSgnSw=\n" +
         "K 8\n" +
         "failures\n" +
         "V 1\n" +
         "8\n" +
         "K 15\n" +
         "svn:realmstring\n" +
-        "V 27\n" +
-        "https://svn.example.com:443\n" +
+        "V 26\n" +
+        "https://svn.apache.org:443\n" +
         "END\n";
 
     private static final String util_cred_ssl_client_passphrase =
@@ -717,9 +742,12 @@ public class UtilTests extends SVNTests
         /* one SSL server trust credential */
         cred = SVNUtil.getCredential(configDir,
                                      SVNUtil.Credential.Kind.sslServer,
-                                     "https://svn.example.com:443");
+                                     "https://svn.apache.org:443");
         assertNotNull(cred);
-        assertEquals(cred.getServerCertInfo().getDER(), "NotTelling==");
+        assertEquals(cred.getServerCertInfo().getSubject(),
+                     "C=US, ST=Maryland, L=Forest Hill, " +
+                     "O=Apache Software Foundation, OU=Infrastructure, " +
+                     "CN=*.apache.org");
 
         /* one SSL client passphrase credential */
         cred = SVNUtil.getCredential(configDir,
@@ -764,10 +792,16 @@ public class UtilTests extends SVNTests
         assertNotNull(creds);
         assertEquals(creds.size(), 2);
 
+        /* search with match on subvject */
+        creds = SVNUtil.searchCredentials(configDir, null,
+                                          null, null, "\\*.apache.org", null);
+        assertNotNull(creds);
+        assertEquals(creds.size(), 1);
+
         /* search with match on realm */
         creds = SVNUtil.searchCredentials(configDir, null,
                                           "*example*", null, null, null);
         assertNotNull(creds);
-        assertEquals(creds.size(), 4);
+        assertEquals(creds.size(), 3);
     }
 }

Modified: subversion/trunk/subversion/include/private/svn_utf_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_utf_private.h?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_utf_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_utf_private.h Fri Jan 30 02:21:16 2015
@@ -159,6 +159,23 @@ svn_utf__normalize(const char **result,
 svn_boolean_t
 svn_utf__is_normalized(const char *string, apr_pool_t *scratch_pool);
 
+/* Encode an UCS-4 string to UTF-8, placing the result into BUFFER.
+ * While utf8proc does have a similar function, it does more checking
+ * and processing than we want here; this function does not attempt
+ * any normalizations but just encodes the individual code points.
+ * The encoded string will always be NUL-terminated.
+ *
+ * Return the length of the result (excluding the NUL terminator) in
+ * *result_length.
+ *
+ * A returned error indicates that a codepoint is invalid.
+ */
+svn_error_t *
+svn_utf__encode_ucs4_string(svn_membuf_t *buffer,
+                            const apr_int32_t *ucs4str,
+                            apr_size_t length,
+                            apr_size_t *result_length);
+
 /* Pattern matching similar to the the SQLite LIKE and GLOB
  * operators. PATTERN, KEY and ESCAPE must all point to UTF-8
  * strings. Furthermore, ESCAPE, if provided, must be a character from
@@ -191,6 +208,48 @@ svn_utf__glob(svn_boolean_t *match,
 const char *
 svn_utf__utf8proc_version(void);
 
+/* Convert an UTF-16 (or UCS-2) string to UTF-8, returning the pointer
+ * in RESULT. If BIG_ENDIAN is set, then UTF16STR is big-endian;
+ * otherwise, it's little-endian.
+ *
+ * If UTF16LEN is SVN_UTF__UNKNOWN_LENGTH, then UTF16STR must be
+ * terminated with a zero; otherwise, it is the number of 16-bit codes
+ * to convert, and the source string may contain NUL values.
+ *
+ * Allocate RESULT in RESULT_POOL and use SCRATCH_POOL for
+ * intermediate allocation.
+ *
+ * This function combines UTF-16 surrogate pairs into single code
+ * points, but will leave single lead or trail surrogates unchanged.
+ */
+svn_error_t *
+svn_utf__utf16_to_utf8(const svn_string_t **result,
+                       const apr_uint16_t *utf16str,
+                       apr_size_t utf16len,
+                       svn_boolean_t big_endian,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool);
+
+/* Convert an UTF-32 string to UTF-8, returning the pointer in
+ * RESULT. If BIG_ENDIAN is set, then UTF32STR is big-endian;
+ * otherwise, it's little-endian.
+ *
+ * If UTF32LEN is SVN_UTF__UNKNOWN_LENGTH, then UTF32STR must be
+ * terminated with a zero; otherwise, it is the number of 32-bit codes
+ * to convert, and the source string may contain NUL values.
+ *
+ * Allocate RESULT in RESULT_POOL and use SCRATCH_POOL for
+ * intermediate allocation.
+ */
+svn_error_t *
+svn_utf__utf32_to_utf8(const svn_string_t **result,
+                       const apr_int32_t *utf32str,
+                       apr_size_t utf32len,
+                       svn_boolean_t big_endian,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/trunk/subversion/include/svn_config.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_config.h?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_config.h (original)
+++ subversion/trunk/subversion/include/svn_config.h Fri Jan 30 02:21:16 2015
@@ -731,31 +731,6 @@ svn_config_ensure(const char *config_dir
  */
 #define SVN_CONFIG_AUTHN_FAILURES_KEY           "failures"
 
-/** A hash-key for a hostname, such as hostnames in SSL certificates.
- * @since New in 1.9.
- */
-#define SVN_CONFIG_AUTHN_HOSTNAME_KEY           "hostname"
-
-/** A hash-key for a fingerprint, such as fingerprints in SSL certificates.
- * @since New in 1.9.
- */
-#define SVN_CONFIG_AUTHN_FINGERPRINT_KEY        "fingerprint"
-
-/** A hash-key for a valid-from date, such as dates in SSL certificates.
- * @since New in 1.9.
- */
-#define SVN_CONFIG_AUTHN_VALID_FROM_KEY         "valid_from"
-
-/** A hash-key for a valid-to date, such as dates in SSL certificates.
- * @since New in 1.9.
- */
-#define SVN_CONFIG_AUTHN_VALID_UNTIL_KEY        "valid_until"
-
-/** A hash-key for an issuer distinguished name, such as issuer names
- * in SSL certificates.
- * @since New in 1.9.
- */
-#define SVN_CONFIG_AUTHN_ISSUER_DN_KEY        "issuer_dn"
 
 /** @} */
 

Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Fri Jan 30 02:21:16 2015
@@ -150,6 +150,8 @@ extern "C" {
                                          + (22 * SVN_ERR_CATEGORY_SIZE))
 #define SVN_ERR_MALFUNC_CATEGORY_START  (APR_OS_START_USERERR \
                                          + (23 * SVN_ERR_CATEGORY_SIZE))
+#define SVN_ERR_X509_CATEGORY_START     (APR_OS_START_USERERR \
+                                         + (24 * SVN_ERR_CATEGORY_SIZE))
 
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
@@ -1617,6 +1619,90 @@ SVN_ERROR_START
              SVN_ERR_MALFUNC_CATEGORY_START + 1,
              "No non-tracing links found in the error chain")
 
+  /* X509 parser errors.
+   * Names of these error codes are based on tropicssl error codes.
+   * @since New in 1.9 */
+
+  SVN_ERRDEF(SVN_ERR_ASN1_OUT_OF_DATA,
+             SVN_ERR_X509_CATEGORY_START + 0,
+             "Unexpected end of ASN1 data")
+
+  SVN_ERRDEF(SVN_ERR_ASN1_UNEXPECTED_TAG,
+             SVN_ERR_X509_CATEGORY_START + 1,
+             "Unexpected ASN1 tag")
+
+  SVN_ERRDEF(SVN_ERR_ASN1_INVALID_LENGTH,
+             SVN_ERR_X509_CATEGORY_START + 2,
+             "Invalid ASN1 length")
+
+  SVN_ERRDEF(SVN_ERR_ASN1_LENGTH_MISMATCH,
+             SVN_ERR_X509_CATEGORY_START + 3,
+             "ASN1 length mismatch")
+
+  SVN_ERRDEF(SVN_ERR_ASN1_INVALID_DATA,
+             SVN_ERR_X509_CATEGORY_START + 4,
+             "Invalid ASN1 data")
+
+  SVN_ERRDEF(SVN_ERR_X509_FEATURE_UNAVAILABLE,
+             SVN_ERR_X509_CATEGORY_START + 5,
+             "Unavailable X509 feature")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_PEM,
+             SVN_ERR_X509_CATEGORY_START + 6,
+             "Invalid PEM certificate")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_FORMAT,
+             SVN_ERR_X509_CATEGORY_START + 7,
+             "Invalid certificate format")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_VERSION,
+             SVN_ERR_X509_CATEGORY_START + 8,
+             "Invalid certificate version")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_SERIAL,
+             SVN_ERR_X509_CATEGORY_START + 9,
+             "Invalid certificate serial number")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_ALG,
+             SVN_ERR_X509_CATEGORY_START + 10,
+             "Found invalid algorithm in certificate")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_NAME,
+             SVN_ERR_X509_CATEGORY_START + 11,
+             "Found invalid name in certificate")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_DATE,
+             SVN_ERR_X509_CATEGORY_START + 12,
+             "Found invalid date in certificate")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_PUBKEY,
+             SVN_ERR_X509_CATEGORY_START + 13,
+             "Found invalid public key in certificate")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_SIGNATURE,
+             SVN_ERR_X509_CATEGORY_START + 14,
+             "Found invalid signature in certificate")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_INVALID_EXTENSIONS,
+             SVN_ERR_X509_CATEGORY_START + 15,
+             "Found invalid extensions in certificate")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_UNKNOWN_VERSION,
+             SVN_ERR_X509_CATEGORY_START + 16,
+             "Unknown certificate version")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_UNKNOWN_PK_ALG,
+             SVN_ERR_X509_CATEGORY_START + 17,
+             "Certificate uses unknown public key algorithm")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_SIG_MISMATCH,
+             SVN_ERR_X509_CATEGORY_START + 18,
+             "Certificate signature mismatch")
+
+  SVN_ERRDEF(SVN_ERR_X509_CERT_VERIFY_FAILED,
+             SVN_ERR_X509_CATEGORY_START + 19,
+             "Certficate verification failed")
+
 SVN_ERROR_END
 
 

Propchange: subversion/trunk/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Jan 30 02:21:16 2015
@@ -68,6 +68,7 @@
 /subversion/branches/revprop-caching-ng/subversion/libsvn_fs_x:1620597
 /subversion/branches/revprop-packing/subversion/libsvn_fs_x:1143907,1143971,1143997,1144017,1144499,1144568,1146145
 /subversion/branches/subtree-mergeinfo/subversion/libsvn_fs_x:876734-878766
+/subversion/branches/svn-auth-x509/subversion/libsvn_fs_x:1603509-1655900
 /subversion/branches/svn-mergeinfo-enhancements/subversion/libsvn_fs_x:870119-870195,870197-870288
 /subversion/branches/svn-patch-improvements/subversion/libsvn_fs_x:918519-934609
 /subversion/branches/svn_mutex/subversion/libsvn_fs_x:1141683-1182099

Modified: subversion/trunk/subversion/libsvn_subr/ssl_server_trust_providers.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/ssl_server_trust_providers.c?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/ssl_server_trust_providers.c (original)
+++ subversion/trunk/subversion/libsvn_subr/ssl_server_trust_providers.c Fri Jan 30 02:21:16 2015
@@ -74,57 +74,13 @@ ssl_server_trust_file_first_credentials(
       if (failstr)
         SVN_ERR(svn_cstring_atoui(&last_failures, failstr->data));
 
+      /* If the cert is trusted and there are no new failures, we
+       * accept it by clearing all failures. */
       if (trusted_cert &&
-          svn_string_compare(this_cert, trusted_cert))
+          svn_string_compare(this_cert, trusted_cert) &&
+          (*failures & ~last_failures) == 0)
         {
-          svn_boolean_t save_cert = FALSE;
-
-          /* If the cert is trusted and there are no new failures, we
-           * accept it by clearing all failures. */
-          if ((*failures & ~last_failures) == 0)
-            {
-              *failures = 0;
-            }
-
-          /* If the on-disk cert info is lacking new-in-1.9 human-readable
-             info, add the info now and save the cert. */
-          if (!svn_hash_gets(creds_hash, SVN_CONFIG_AUTHN_HOSTNAME_KEY))
-            {
-              svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_HOSTNAME_KEY,
-                            svn_string_create(cert_info->hostname, pool));
-              save_cert = TRUE;
-            }
-          if (!svn_hash_gets(creds_hash, SVN_CONFIG_AUTHN_FINGERPRINT_KEY))
-            {
-              svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_FINGERPRINT_KEY,
-                            svn_string_create(cert_info->fingerprint, pool));
-              save_cert = TRUE;
-            }
-          if (!svn_hash_gets(creds_hash, SVN_CONFIG_AUTHN_VALID_FROM_KEY))
-            {
-              svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_VALID_FROM_KEY,
-                            svn_string_create(cert_info->valid_from, pool));
-              save_cert = TRUE;
-            }
-          if (!svn_hash_gets(creds_hash, SVN_CONFIG_AUTHN_VALID_UNTIL_KEY))
-            {
-              svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_VALID_UNTIL_KEY,
-                            svn_string_create(cert_info->valid_until, pool));
-              save_cert = TRUE;
-            }
-          if (!svn_hash_gets(creds_hash, SVN_CONFIG_AUTHN_ISSUER_DN_KEY))
-            {
-              svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_ISSUER_DN_KEY,
-                            svn_string_create(cert_info->issuer_dname, pool));
-              save_cert = TRUE;
-            }
-
-          if (save_cert)
-            SVN_ERR(svn_config_write_auth_data(creds_hash,
-                                               SVN_AUTH_CRED_SSL_SERVER_TRUST,
-                                               realmstring,
-                                               config_dir,
-                                               pool));
+          *failures = 0;
         }
     }
 
@@ -167,16 +123,6 @@ ssl_server_trust_file_save_credentials(s
   svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_FAILURES_KEY,
                 svn_string_createf(pool, "%lu",
                                    (unsigned long)creds->accepted_failures));
-  svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_HOSTNAME_KEY,
-                svn_string_create(cert_info->hostname, pool));
-  svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_FINGERPRINT_KEY,
-                svn_string_create(cert_info->fingerprint, pool));
-  svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_VALID_FROM_KEY,
-                svn_string_create(cert_info->valid_from, pool));
-  svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_VALID_UNTIL_KEY,
-                svn_string_create(cert_info->valid_until, pool));
-  svn_hash_sets(creds_hash, SVN_CONFIG_AUTHN_ISSUER_DN_KEY,
-                svn_string_create(cert_info->issuer_dname, pool));
 
   SVN_ERR(svn_config_write_auth_data(creds_hash,
                                      SVN_AUTH_CRED_SSL_SERVER_TRUST,

Modified: subversion/trunk/subversion/libsvn_subr/utf.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/utf.c?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/utf.c (original)
+++ subversion/trunk/subversion/libsvn_subr/utf.c Fri Jan 30 02:21:16 2015
@@ -1016,6 +1016,161 @@ svn_utf_cstring_from_utf8_string(const c
 }
 
 
+/* Insert the given UCS-4 VALUE into BUF at the given OFFSET. */
+static void
+membuf_insert_ucs4(svn_membuf_t *buf, apr_size_t offset, apr_int32_t value)
+{
+  svn_membuf__resize(buf, (offset + 1) * sizeof(value));
+  ((apr_int32_t*)buf->data)[offset] = value;
+}
+
+/* TODO: Use compiler intrinsics for byte swaps. */
+#define SWAP_SHORT(x)  ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff))
+#define SWAP_LONG(x)   ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8)    \
+                        | (((x) >> 8) & 0xff00) | (((x) >> 24) & 0xff))
+
+#define IS_UTF16_LEAD_SURROGATE(c)   ((c) >= 0xd800 && (c) <= 0xdbff)
+#define IS_UTF16_TRAIL_SURROGATE(c)  ((c) >= 0xdc00 && (c) <= 0xdfff)
+
+svn_error_t *
+svn_utf__utf16_to_utf8(const svn_string_t **result,
+                       const apr_uint16_t *utf16str,
+                       apr_size_t utf16len,
+                       svn_boolean_t big_endian,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  static const apr_uint16_t endiancheck = 0xa55a;
+  const svn_boolean_t arch_big_endian =
+    (((const char*)&endiancheck)[sizeof(endiancheck) - 1] == '\x5a');
+  const svn_boolean_t swap_order = (!big_endian != !arch_big_endian);
+
+  apr_uint16_t lead_surrogate;
+  apr_size_t length;
+  apr_size_t offset;
+  svn_membuf_t ucs4buf;
+  svn_membuf_t resultbuf;
+  svn_string_t *res;
+
+  if (utf16len == SVN_UTF__UNKNOWN_LENGTH)
+    {
+      const apr_uint16_t *endp = utf16str;
+      while (*endp++)
+        ;
+      utf16len = (endp - utf16str);
+    }
+
+  svn_membuf__create(&ucs4buf, utf16len * sizeof(apr_int32_t), scratch_pool);
+
+  for (lead_surrogate = 0, length = 0, offset = 0;
+       offset < utf16len; ++offset)
+    {
+      const apr_uint16_t code =
+        (swap_order ? SWAP_SHORT(utf16str[offset]) : utf16str[offset]);
+
+      if (lead_surrogate)
+        {
+          if (IS_UTF16_TRAIL_SURROGATE(code))
+            {
+              /* Combine the lead and trail currogates into a 32-bit code. */
+              membuf_insert_ucs4(&ucs4buf, length++,
+                                 (0x010000
+                                  + (((lead_surrogate & 0x03ff) << 10)
+                                     | (code & 0x03ff))));
+              lead_surrogate = 0;
+              continue;
+            }
+          else
+            {
+              /* If we didn't find a surrogate pair, just dump the
+                 lead surrogate into the stream. */
+              membuf_insert_ucs4(&ucs4buf, length++, lead_surrogate);
+              lead_surrogate = 0;
+            }
+        }
+
+      if ((offset + 1) < utf16len && IS_UTF16_LEAD_SURROGATE(code))
+        {
+          /* Store a lead surrogate that is followed by at least one
+             code for the next iteration. */
+          lead_surrogate = code;
+          continue;
+        }
+      else
+        membuf_insert_ucs4(&ucs4buf, length++, code);
+    }
+
+  /* Convert the UCS-4 buffer to UTF-8, assuming an average of 2 bytes
+     per code point for encoding. The buffer will grow as
+     necessary. */
+  svn_membuf__create(&resultbuf, length * 2, result_pool);
+  SVN_ERR(svn_utf__encode_ucs4_string(
+              &resultbuf, ucs4buf.data, length, &length));
+
+  res = apr_palloc(result_pool, sizeof(*res));
+  res->data = resultbuf.data;
+  res->len = length;
+  *result = res;
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_utf__utf32_to_utf8(const svn_string_t **result,
+                       const apr_int32_t *utf32str,
+                       apr_size_t utf32len,
+                       svn_boolean_t big_endian,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  static const apr_int32_t endiancheck = 0xa5cbbc5a;
+  const svn_boolean_t arch_big_endian =
+    (((const char*)&endiancheck)[sizeof(endiancheck) - 1] == '\x5a');
+  const svn_boolean_t swap_order = (!big_endian != !arch_big_endian);
+
+  apr_size_t length;
+  svn_membuf_t resultbuf;
+  svn_string_t *res;
+
+  if (utf32len == SVN_UTF__UNKNOWN_LENGTH)
+    {
+      const apr_int32_t *endp = utf32str;
+      while (*endp++)
+        ;
+      utf32len = (endp - utf32str);
+    }
+
+  if (swap_order)
+    {
+      apr_size_t offset;
+      svn_membuf_t ucs4buf;
+
+      svn_membuf__create(&ucs4buf, utf32len * sizeof(apr_int32_t),
+                         scratch_pool);
+
+      for (offset = 0; offset < utf32len; ++offset)
+        {
+          const apr_int32_t code = SWAP_LONG(utf32str[offset]);
+          membuf_insert_ucs4(&ucs4buf, offset, code);
+        }
+      utf32str = ucs4buf.data;
+    }
+
+  /* Convert the UCS-4 buffer to UTF-8, assuming an average of 2 bytes
+     per code point for encoding. The buffer will grow as
+     necessary. */
+  svn_membuf__create(&resultbuf, utf32len * 2, result_pool);
+  SVN_ERR(svn_utf__encode_ucs4_string(
+              &resultbuf, utf32str, utf32len, &length));
+
+  res = apr_palloc(result_pool, sizeof(*res));
+  res->data = resultbuf.data;
+  res->len = length;
+  *result = res;
+  return SVN_NO_ERROR;
+}
+
+
 #ifdef WIN32
 
 

Modified: subversion/trunk/subversion/libsvn_subr/utf8proc.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/utf8proc.c?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/utf8proc.c (original)
+++ subversion/trunk/subversion/libsvn_subr/utf8proc.c Fri Jan 30 02:21:16 2015
@@ -218,20 +218,14 @@ encode_ucs4(svn_membuf_t *buffer, apr_in
   return SVN_NO_ERROR;
 }
 
-/* Decode an UCS-4 string to UTF-8, placing the result into BUFFER.
- * While utf8proc does have a similar function, it does more checking
- * and processing than we want here. Return the length of the result
- * (excluding the NUL terminator) in *result_length.
- *
- * A returned error indicates that the codepoint is invalid.
- */
-static svn_error_t *
-encode_ucs4_string(svn_membuf_t *buffer,
-                   apr_int32_t *ucs4str, apr_size_t len,
-                   apr_size_t *result_length)
+svn_error_t *
+svn_utf__encode_ucs4_string(svn_membuf_t *buffer,
+                            const apr_int32_t *ucs4str,
+                            apr_size_t length,
+                            apr_size_t *result_length)
 {
   *result_length = 0;
-  while (len-- > 0)
+  while (length-- > 0)
     SVN_ERR(encode_ucs4(buffer, *ucs4str++, result_length));
   svn_membuf__resize(buffer, *result_length + 1);
   ((char*)buffer->data)[*result_length] = '\0';
@@ -262,8 +256,8 @@ svn_utf__glob(svn_boolean_t *match,
      because apr_fnmatch can't handle it.*/
   SVN_ERR(decompose_normalized(&tempbuf_len, pattern, pattern_len, temp_buf));
   if (!sql_like)
-    SVN_ERR(encode_ucs4_string(pattern_buf, temp_buf->data, tempbuf_len,
-                               &patternbuf_len));
+    SVN_ERR(svn_utf__encode_ucs4_string(pattern_buf, temp_buf->data,
+                                        tempbuf_len, &patternbuf_len));
   else
     {
       /* Convert a LIKE pattern to a GLOB pattern that apr_fnmatch can use. */
@@ -338,8 +332,8 @@ svn_utf__glob(svn_boolean_t *match,
 
   /* Now normalize the string */
   SVN_ERR(decompose_normalized(&tempbuf_len, string, string_len, temp_buf));
-  SVN_ERR(encode_ucs4_string(string_buf, temp_buf->data,
-                             tempbuf_len, &tempbuf_len));
+  SVN_ERR(svn_utf__encode_ucs4_string(string_buf, temp_buf->data,
+                                      tempbuf_len, &tempbuf_len));
 
   *match = !apr_fnmatch(pattern_buf->data, string_buf->data, 0);
   return SVN_NO_ERROR;

Modified: subversion/trunk/subversion/svn/auth-cmd.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/auth-cmd.c?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/auth-cmd.c (original)
+++ subversion/trunk/subversion/svn/auth-cmd.c Fri Jan 30 02:21:16 2015
@@ -41,6 +41,9 @@
 #include "svn_config.h"
 #include "svn_auth.h"
 #include "svn_sorts.h"
+#include "svn_base64.h"
+#include "svn_x509.h"
+#include "svn_time.h"
 
 #include "private/svn_cmdline_private.h"
 #include "private/svn_token.h"
@@ -150,9 +153,6 @@ match_credential(svn_boolean_t *match,
                 continue; /* don't match secrets */
               else if (strcmp(key, SVN_CONFIG_AUTHN_ASCII_CERT_KEY) == 0)
                 continue; /* don't match base64 data */
-              else if (strcmp(key, SVN_CONFIG_AUTHN_HOSTNAME_KEY) == 0 ||
-                       strcmp(key, SVN_CONFIG_AUTHN_FINGERPRINT_KEY) == 0)
-                *match = match_pattern(pattern, value->data, TRUE, iterpool);
               else
                 *match = match_pattern(pattern, value->data, FALSE, iterpool);
 
@@ -168,6 +168,63 @@ match_credential(svn_boolean_t *match,
 }
 
 static svn_error_t *
+show_cert(const svn_string_t *pem_cert, apr_pool_t *scratch_pool)
+{
+  const svn_string_t *der_cert;
+  svn_x509_certinfo_t *certinfo;
+  const apr_array_header_t *hostnames;
+  svn_error_t *err;
+
+  /* Convert header-less PEM to DER by undoing base64 encoding. */
+  der_cert = svn_base64_decode_string(pem_cert, scratch_pool);
+
+  err = svn_x509_parse_cert(&certinfo, der_cert->data, der_cert->len,
+                            scratch_pool, scratch_pool);
+  if (err)
+    {
+      /* Just display X.509 parsing errors as warnings and continue */
+      svn_handle_warning2(stderr, err, "svn: ");
+      svn_error_clear(err);
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(svn_cmdline_printf(scratch_pool, _("Subject: %s\n"),
+                             svn_x509_certinfo_get_subject(certinfo, scratch_pool)));
+  SVN_ERR(svn_cmdline_printf(scratch_pool, _("Valid from: %s\n"),
+                             svn_time_to_human_cstring(
+                                 svn_x509_certinfo_get_valid_from(certinfo),
+                                 scratch_pool)));
+  SVN_ERR(svn_cmdline_printf(scratch_pool, _("Valid until: %s\n"),
+                             svn_time_to_human_cstring(
+                                 svn_x509_certinfo_get_valid_to(certinfo),
+                                 scratch_pool)));
+  SVN_ERR(svn_cmdline_printf(scratch_pool, _("Issuer: %s\n"),
+                             svn_x509_certinfo_get_issuer(certinfo, scratch_pool)));
+  SVN_ERR(svn_cmdline_printf(scratch_pool, _("Fingerprint: %s\n"),
+                             svn_checksum_to_cstring_display(
+                                 svn_x509_certinfo_get_digest(certinfo),
+                                 scratch_pool)));
+
+  hostnames = svn_x509_certinfo_get_hostnames(certinfo);
+  if (hostnames && !apr_is_empty_array(hostnames))
+    {
+      int i;
+      svn_stringbuf_t *buf = svn_stringbuf_create_empty(scratch_pool);
+      for (i = 0; i < hostnames->nelts; ++i)
+        {
+          const char *hostname = APR_ARRAY_IDX(hostnames, i, const char*);
+          if (i > 0)
+            svn_stringbuf_appendbytes(buf, ", ", 2);
+          svn_stringbuf_appendbytes(buf, hostname, strlen(hostname));
+        }
+      SVN_ERR(svn_cmdline_printf(scratch_pool, _("Hostnames: %s\n"),
+                                 buf->data));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
 list_credential(const char *cred_kind,
                 const char *realmstring,
                 apr_array_header_t *cred_items,
@@ -188,7 +245,7 @@ list_credential(const char *cred_kind,
       svn_sort__item_t item;
       const char *key;
       svn_string_t *value;
-      
+
       svn_pool_clear(iterpool);
       item = APR_ARRAY_IDX(cred_items, i, svn_sort__item_t);
       key = item.key;
@@ -218,20 +275,7 @@ list_credential(const char *cred_kind,
       else if (strcmp(key, SVN_CONFIG_AUTHN_USERNAME_KEY) == 0)
         SVN_ERR(svn_cmdline_printf(iterpool, _("Username: %s\n"), value->data));
       else if (strcmp(key, SVN_CONFIG_AUTHN_ASCII_CERT_KEY) == 0)
-        continue; /* don't show data which is not human-readable */
-      else if (strcmp(key, SVN_CONFIG_AUTHN_HOSTNAME_KEY) == 0)
-        SVN_ERR(svn_cmdline_printf(iterpool, _("Hostname: %s\n"), value->data));
-      else if (strcmp(key, SVN_CONFIG_AUTHN_VALID_FROM_KEY) == 0)
-        SVN_ERR(svn_cmdline_printf(iterpool, _("Valid from: %s\n"),
-                                   value->data));
-      else if (strcmp(key, SVN_CONFIG_AUTHN_VALID_UNTIL_KEY) == 0)
-        SVN_ERR(svn_cmdline_printf(iterpool, _("Valid until: %s\n"),
-                                   value->data));
-      else if (strcmp(key, SVN_CONFIG_AUTHN_ISSUER_DN_KEY) == 0)
-        SVN_ERR(svn_cmdline_printf(iterpool, _("Issuer: %s\n"), value->data));
-      else if (strcmp(key, SVN_CONFIG_AUTHN_FINGERPRINT_KEY) == 0)
-        SVN_ERR(svn_cmdline_printf(iterpool, _("Fingerprint: %s\n"),
-                                   value->data));
+       SVN_ERR(show_cert(value, iterpool));
       else if (strcmp(key, SVN_CONFIG_AUTHN_FAILURES_KEY) == 0)
         SVN_ERR(show_cert_failures(value->data, iterpool));
       else

Propchange: subversion/trunk/subversion/tests/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Jan 30 02:21:16 2015
@@ -62,6 +62,7 @@
 /subversion/branches/revprop-cache/subversion/tests/libsvn_fs_x:1298521-1326293
 /subversion/branches/revprop-packing/subversion/tests/libsvn_fs_x:1143907,1143971,1143997,1144017,1144499,1144568,1146145
 /subversion/branches/subtree-mergeinfo/subversion/tests/libsvn_fs_x:876734-878766
+/subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs_x:1603509-1655900
 /subversion/branches/svn-mergeinfo-enhancements/subversion/tests/libsvn_fs_x:870119-870195,870197-870288
 /subversion/branches/svn-patch-improvements/subversion/tests/libsvn_fs_x:918519-934609
 /subversion/branches/svn_mutex/subversion/tests/libsvn_fs_x:1141683-1182099

Modified: subversion/trunk/subversion/tests/libsvn_subr/utf-test.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_subr/utf-test.c?rev=1655909&r1=1655908&r2=1655909&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_subr/utf-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_subr/utf-test.c Fri Jan 30 02:21:16 2015
@@ -737,6 +737,92 @@ test_utf_is_normalized(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+
+static svn_error_t *
+test_utf_conversions(apr_pool_t *pool)
+{
+  static const struct cvt_test_t
+  {
+    svn_boolean_t sixteenbit;
+    svn_boolean_t bigendian;
+    const char *source;
+    const char *result;
+  } tests[] = {
+
+#define UTF_32_LE FALSE, FALSE
+#define UTF_32_BE FALSE, TRUE
+#define UTF_16_LE TRUE, FALSE
+#define UTF_16_BE TRUE, TRUE
+
+    /* Normal character conversion */
+    { UTF_32_LE, "t\0\0\0" "e\0\0\0" "s\0\0\0" "t\0\0\0" "\0\0\0\0", "test" },
+    { UTF_32_BE, "\0\0\0t" "\0\0\0e" "\0\0\0s" "\0\0\0t" "\0\0\0\0", "test" },
+    { UTF_16_LE, "t\0" "e\0" "s\0" "t\0" "\0\0", "test" },
+    { UTF_16_BE, "\0t" "\0e" "\0s" "\0t" "\0\0", "test" },
+
+    /* Valid surrogate pairs */
+    { UTF_16_LE, "\x00\xD8" "\x00\xDC" "\0\0", "\xf0\x90\x80\x80" }, /* U+010000 */
+    { UTF_16_LE, "\x34\xD8" "\x1E\xDD" "\0\0", "\xf0\x9d\x84\x9e" }, /* U+01D11E */
+    { UTF_16_LE, "\xFF\xDB" "\xFD\xDF" "\0\0", "\xf4\x8f\xbf\xbd" }, /* U+10FFFD */
+
+    { UTF_16_BE, "\xD8\x00" "\xDC\x00" "\0\0", "\xf0\x90\x80\x80" }, /* U+010000 */
+    { UTF_16_BE, "\xD8\x34" "\xDD\x1E" "\0\0", "\xf0\x9d\x84\x9e" }, /* U+01D11E */
+    { UTF_16_BE, "\xDB\xFF" "\xDF\xFD" "\0\0", "\xf4\x8f\xbf\xbd" }, /* U+10FFFD */
+
+    /* Swapped, single and trailing surrogate pairs */
+    { UTF_16_LE, "*\0" "\x00\xDC" "\x00\xD8" "*\0\0\0", "*\xed\xb0\x80" "\xed\xa0\x80*" },
+    { UTF_16_LE, "*\0" "\x1E\xDD" "*\0\0\0", "*\xed\xb4\x9e*" },
+    { UTF_16_LE, "*\0" "\xFF\xDB" "*\0\0\0", "*\xed\xaf\xbf*" },
+    { UTF_16_LE, "\x1E\xDD" "\0\0", "\xed\xb4\x9e" },
+    { UTF_16_LE, "\xFF\xDB" "\0\0", "\xed\xaf\xbf" },
+
+    { UTF_16_BE, "\0*" "\xDC\x00" "\xD8\x00" "\0*\0\0", "*\xed\xb0\x80" "\xed\xa0\x80*" },
+    { UTF_16_BE, "\0*" "\xDD\x1E" "\0*\0\0", "*\xed\xb4\x9e*" },
+    { UTF_16_BE, "\0*" "\xDB\xFF" "\0*\0\0", "*\xed\xaf\xbf*" },
+    { UTF_16_BE, "\xDD\x1E" "\0\0", "\xed\xb4\x9e" },
+    { UTF_16_BE, "\xDB\xFF" "\0\0", "\xed\xaf\xbf" },
+
+#undef UTF_32_LE
+#undef UTF_32_BE
+#undef UTF_16_LE
+#undef UTF_16_BE
+
+    { 0 }
+  };
+
+  const struct cvt_test_t *tc;
+  const svn_string_t *result;
+  int i;
+
+  for (i = 1, tc = tests; tc->source; ++tc, ++i)
+    {
+      if (tc->sixteenbit)
+        SVN_ERR(svn_utf__utf16_to_utf8(&result, (const void*)tc->source,
+                                       SVN_UTF__UNKNOWN_LENGTH,
+                                       tc->bigendian, pool, pool));
+      else
+        SVN_ERR(svn_utf__utf32_to_utf8(&result, (const void*)tc->source,
+                                       SVN_UTF__UNKNOWN_LENGTH,
+                                       tc->bigendian, pool, pool));
+      SVN_ERR_ASSERT(0 == strcmp(result->data, tc->result));
+    }
+
+  /* Test counted strings with NUL characters */
+  SVN_ERR(svn_utf__utf16_to_utf8(
+              &result, (void*)("x\0" "\0\0" "y\0" "*\0"), 3,
+              FALSE, pool, pool));
+  SVN_ERR_ASSERT(0 == memcmp(result->data, "x\0y", 3));
+
+  SVN_ERR(svn_utf__utf32_to_utf8(
+              &result,
+              (void*)("\0\0\0x" "\0\0\0\0" "\0\0\0y" "\0\0\0*"), 3,
+              TRUE, pool, pool));
+  SVN_ERR_ASSERT(0 == memcmp(result->data, "x\0y", 3));
+
+  return SVN_NO_ERROR;
+}
+
+
 
 /* The test table.  */
 
@@ -761,6 +847,8 @@ static struct svn_test_descriptor_t test
                    "test svn_utf__fuzzy_escape"),
     SVN_TEST_PASS2(test_utf_is_normalized,
                    "test svn_utf__is_normalized"),
+    SVN_TEST_PASS2(test_utf_conversions,
+                   "test svn_utf__utf{16,32}_to_utf8"),
     SVN_TEST_NULL
   };