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 2014/06/09 14:00:32 UTC

svn commit: r1601352 - in /subversion/trunk/subversion/bindings/javahl: native/ src/org/apache/subversion/javahl/ src/org/apache/subversion/javahl/callback/ src/org/apache/subversion/javahl/util/

Author: brane
Date: Mon Jun  9 12:00:31 2014
New Revision: 1601352

URL: http://svn.apache.org/r1601352
Log:
Sketch out a utility API for managing credentials from JavaHL.

[in subversion/bindings/javahl]
* src/org/apache/subversion/javahl/SVNUtil.java
  (SVNUtil.Credential): New; abstract base class for credential types.
  (SVNUtil.UsernameCredential,
   SVNUtil.UsernameCredential,
   SVNUtil.SSLServerCertCredential,
   SVNUtil.SSLClientCertPassphraseCredential): New; concrete credentiall types.
  (SVNUtil.getCredential,
   SVNUtil.removeCredential,
   SVNUtil.addCredential,
   SVNUtil.searchCredentials,
   SVNUtil.deleteCredentials): New; credentials management methods.

* src/org/apache/subversion/javahl/callback/AuthnCallback.java
  (AuthnCallback.SSLServerCertFailures.getFailures): New.

* src/org/apache/subversion/javahl/util/ConfigLib.java
  (ConfigLib.getCredential,
   ConfigLib.removeCredential,
   ConfigLib.addCredential,
   ConfigLib.searchCredentials,
   ConfigLib.deleteCredentials): New; credentials management methods.
  (ConfigLib.nativeGetCredential,
   ConfigLib.nativeRemoveCredential,
   ConfigLib.nativeAddCredential,
   ConfigLib.iterateCredentials):
   New; native method declarations for credentials management.

* native/org_apache_subversion_javahl_util_ConfigLib.cpp:
   Reimplement using the new jniwrapper infrastructure.
  (Java_org_apache_subversion_javahl_util_ConfigLib_enableNativeCredentialsStore,
   Java_org_apache_subversion_javahl_util_ConfigLib_disableNativeCredentialsStore,
   Java_org_apache_subversion_javahl_util_ConfigLib_isNativeCredentialsStoreEnabled):
   Change implementation to user jniwrapper.
  (Java_org_apache_subversion_javahl_util_ConfigLib_nativeGetCredential,
   Java_org_apache_subversion_javahl_util_ConfigLib_nativeRemoveCredential,
   Java_org_apache_subversion_javahl_util_ConfigLib_nativeAddCredential,
   Java_org_apache_subversion_javahl_util_ConfigLib_iterateCredentials):
   New; native methods for credentials management.

Modified:
    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

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=1601352&r1=1601351&r2=1601352&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 Mon Jun  9 12:00:31 2014
@@ -26,15 +26,21 @@
 
 #include "../include/org_apache_subversion_javahl_util_ConfigLib.h"
 
-#include "JNIStackElement.h"
-#include "JNIStringHolder.h"
+#include "jniwrapper/jni_stack.hpp"
+
+#include "AuthnCallback.hpp"
+#include "GlobalConfig.h"
+
 #include "JNIUtil.h"
 #include "JNICriticalSection.h"
-#include "GlobalConfig.h"
+
+#include "svn_config.h"
+
+#include "svn_private_config.h"
 
 namespace {
 bool g_ignore_native_credentials = false;
-} // anonymous callback
+} // anonymous namespace
 
 bool GlobalConfig::useNativeCredentialsStore()
 {
@@ -44,29 +50,113 @@ bool GlobalConfig::useNativeCredentialsS
 
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_util_ConfigLib_enableNativeCredentialsStore(
-    JNIEnv* env, jobject jthis)
+    JNIEnv* jenv, jobject jthis)
 {
-  JNIEntry(ConfigLib, enableNativeCredentialsStore);
-
-  JNICriticalSection lock(*JNIUtil::g_configMutex);
-  g_ignore_native_credentials = false;
+  SVN_JAVAHL_JNI_TRY(ConfigLib, enableNativeCredentialsStore)
+    {
+      JNICriticalSection lock(*JNIUtil::g_configMutex);
+      g_ignore_native_credentials = false;
+    }
+  SVN_JAVAHL_JNI_CATCH;
 }
 
 JNIEXPORT void JNICALL
 Java_org_apache_subversion_javahl_util_ConfigLib_disableNativeCredentialsStore(
-    JNIEnv* env, jobject jthis)
+    JNIEnv* jenv, jobject jthis)
 {
-  JNIEntry(ConfigLib, disableNativeCredentialsStore);
-
-  JNICriticalSection lock(*JNIUtil::g_configMutex);
-  g_ignore_native_credentials = true;
+  SVN_JAVAHL_JNI_TRY(ConfigLib, disableNativeCredentialsStore)
+    {
+      JNICriticalSection lock(*JNIUtil::g_configMutex);
+      g_ignore_native_credentials = true;
+    }
+  SVN_JAVAHL_JNI_CATCH;
 }
 
 JNIEXPORT jboolean JNICALL
 Java_org_apache_subversion_javahl_util_ConfigLib_isNativeCredentialsStoreEnabled(
-    JNIEnv* env, jobject jthis)
+    JNIEnv* jenv, jobject jthis)
+{
+  SVN_JAVAHL_JNI_TRY(ConfigLib, isNativeCredentialsStoreEnabled)
+    {
+      return jboolean(GlobalConfig::useNativeCredentialsStore());
+    }
+  SVN_JAVAHL_JNI_CATCH;
+  return JNI_FALSE;
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_util_ConfigLib_nativeGetCredential(
+    JNIEnv* jenv, jobject jthis,
+    jstring jconfig_dir, jstring jcred_kind, jstring jrealm)
+{
+  SVN_JAVAHL_JNI_TRY(ConfigLib, nativeGetCredential)
+    {
+      if (!GlobalConfig::useNativeCredentialsStore())
+        return NULL;
+
+      const Java::Env env(jenv);
+    }
+  SVN_JAVAHL_JNI_CATCH;
+  return NULL;
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_util_ConfigLib_nativeRemoveCredential(
+    JNIEnv* jenv, jobject jthis,
+    jstring jconfig_dir, jstring jcred_kind, jstring jrealm)
 {
-  JNIEntry(ConfigLib, isNativeCredentialsStoreEnabled);
+  SVN_JAVAHL_JNI_TRY(ConfigLib, nativeRemoveCredential)
+    {
+      if (!GlobalConfig::useNativeCredentialsStore())
+        return NULL;
+
+      const Java::Env env(jenv);
+    }
+  SVN_JAVAHL_JNI_CATCH;
+  return NULL;
+}
 
-  return jboolean(GlobalConfig::useNativeCredentialsStore());
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_util_ConfigLib_nativeAddCredential(
+    JNIEnv* jenv, jobject jthis,
+    jstring jconfig_dir, jstring jcred_kind, jstring jrealm,
+    jstring jusername, jstring jpassword,
+    jstring jserver_cert_hostname,
+    jstring jserver_cert_fingerprint,
+    jstring jserver_cert_valid_from,
+    jstring jserver_cert_valid_until,
+    jstring jserver_cert_issuer,
+    jstring jserver_cert_der,
+    jint jserver_cert_failures,
+    jstring jclient_cert_passphrase)
+{
+  SVN_JAVAHL_JNI_TRY(ConfigLib, nativeAddCredential)
+    {
+      if (!GlobalConfig::useNativeCredentialsStore())
+        return NULL;
+
+      const Java::Env env(jenv);
+    }
+  SVN_JAVAHL_JNI_CATCH;
+  return NULL;
+}
+
+
+JNIEXPORT jobject JNICALL
+Java_org_apache_subversion_javahl_util_ConfigLib_iterateCredentials(
+    JNIEnv* jenv, jobject jthis,
+    jboolean jdelete_matching,
+    jstring jconfig_dir, jstring jcred_kind,
+    jstring jrealm_pattern, jstring jusername_pattern,
+    jstring jhostname_pattern, jstring jtext_pattern)
+{
+  SVN_JAVAHL_JNI_TRY(ConfigLib, iterateCredentials)
+    {
+      if (!GlobalConfig::useNativeCredentialsStore())
+        return NULL;
+
+      const Java::Env env(jenv);
+    }
+  SVN_JAVAHL_JNI_CATCH;
+  return NULL;
 }

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=1601352&r1=1601351&r2=1601352&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 Mon Jun  9 12:00:31 2014
@@ -92,6 +92,421 @@ public class SVNUtil
       }
 
     //
+    // Credentials management
+    //
+
+    /**
+     * Generic credential description. Provides default accessors for
+     * concrete implementations.
+     */
+    public static abstract class Credential
+    {
+        /**
+         * Describes the kind of the credential.
+         */
+        public static enum Kind
+        {
+            /** The username for a realm. */
+            username            ("svn.username"),
+
+            /** The username and password for a realm. */
+            simple              ("svn.simple"),
+
+            /** The trusted SSL server certificate for a realm. */
+            sslServer           ("svn.ssl.server"),
+
+            /** The client certificate passphrase for a realm. */
+            sslClientPassphrase ("svn.ssl.client-passphrase");
+
+            private String token;
+
+            Kind(String token)
+            {
+                this.token = token;
+            }
+
+            /** @return the string representation of the enumeration. */
+            public String toString()
+            {
+                return this.token;
+            }
+        }
+
+        /** @return the kind of the credential. */
+        public Kind getKind()
+        {
+            return kind;
+        }
+
+        /** @return the realm that the credential is valid for. */
+        public String getRealm()
+        {
+            return realm;
+        }
+
+        /**
+         * @return the type of the secure store used for the secret
+         * parts of this credential; may be <code>null</code> if the
+         * credential does not contain any secrets bits.
+         */
+        public String getSecureStore()
+        {
+            return store;
+        }
+
+        /**
+         * @return the username associated with the credential, or
+         * <code>null</code>, if there is no username in the concrete
+         * credential type.
+         */
+        public String getUsername()
+        {
+            return null;
+        }
+
+        /**
+         * @return the password associated with the credential, or
+         * <code>null</code>, if there is no password in the concrete
+         * credential type.
+         */
+        public String getPassword()
+        {
+            return null;
+        }
+
+        /**
+         * @return the server certificate info associated with the
+         * credential, or <code>null</code>, if there is no server
+         * certificate in the concrete credential type.
+         */
+        public AuthnCallback.SSLServerCertInfo getServerCertInfo()
+        {
+            return null;
+        }
+
+        /**
+         * @return the accepted server certificate failures associated
+         * with the credential, or <code>null</code>, if there is no
+         * server certificate in the concrete credential type.
+         */
+        public AuthnCallback.SSLServerCertFailures getServerCertFailures()
+        {
+            return null;
+        }
+
+        /**
+         * @return the client certificate passphrase associated with
+         * the credential, or <code>null</code>, if there is no client
+         * certificate in the concrete credential type.
+         */
+        public String getClientCertPassphrase()
+        {
+            return null;
+        }
+
+        /** Protected constructor used by subclasses. */
+        protected Credential(Kind kind, String realm, String store)
+        {
+            this.kind = kind;
+            this.realm = realm;
+            this.store = store;
+        }
+
+        protected Kind kind;
+        protected String realm;
+        protected String store;
+    }
+
+    /**
+     * A credential that defines a username.
+     */
+    public static class UsernameCredential extends Credential
+    {
+        /** Constructs a username credential. */
+        public UsernameCredential(String realm, String username)
+        {
+            super(Kind.username, realm, null);
+            this.username = username;
+        }
+
+        /** @return the username associated with the credential. */
+        public String getUsername()
+        {
+            return username;
+        }
+
+        /** Protected constructor used by subclasses. */
+        protected UsernameCredential(Kind kind, String realm, String store,
+                                     String username)
+        {
+            super(kind, realm, null);
+            this.username = username;
+        }
+
+        /** Protected constructor used by the native implementation. */
+        protected UsernameCredential(String realm, String store,
+                                     String username)
+        {
+            super(Kind.username, realm, store);
+            this.username = username;
+        }
+
+        protected String username;
+    }
+
+    /**
+     * A credential that defines a username and password.
+     */
+    public static class SimpleCredential extends UsernameCredential
+    {
+        /** Constructs a simple credential. */
+        public SimpleCredential(String realm, String username, String password)
+        {
+            super(Kind.simple, realm, null, username);
+            this.password = password;
+        }
+
+        /** @return the password associated with the credential. */
+        public String getPassword()
+        {
+            return password;
+        }
+
+        /** Protected constructor used by the native implementation. */
+        protected SimpleCredential(String realm, String store,
+                                   String username, String password)
+        {
+            super(Kind.simple, realm, store, username);
+            this.password = password;
+        }
+
+        protected String password;
+    }
+
+    /**
+     * A credential that defines a trusted SSL server certificate.
+     */
+    public static class SSLServerCertCredential extends Credential
+    {
+        /** Constructs an SSL server certificate credential. */
+        public SSLServerCertCredential(String realm,
+                                       AuthnCallback.SSLServerCertInfo info,
+                                       AuthnCallback.SSLServerCertFailures failures)
+        {
+            super(Kind.sslServer, realm, null);
+            this.info = info;
+            this.failures = failures;
+        }
+
+        /**
+         * @return the server certificate info associated with the
+         * credential.
+         */
+        public AuthnCallback.SSLServerCertInfo getServerCertInfo()
+        {
+            return info;
+        }
+
+        /**
+         * @return the accepted server certificate failures associated
+         * with the credential.
+         */
+        public AuthnCallback.SSLServerCertFailures getServerCertFailures()
+        {
+            return failures;
+        }
+
+        /** Protected constructor used by the native implementation. */
+        protected SSLServerCertCredential(String realm, String store,
+                                          AuthnCallback.SSLServerCertInfo info,
+                                          AuthnCallback.SSLServerCertFailures failures)
+        {
+            super(Kind.sslServer, realm, store);
+            this.info = info;
+            this.failures = failures;
+        }
+
+        protected AuthnCallback.SSLServerCertInfo info;
+        protected AuthnCallback.SSLServerCertFailures failures;
+    }
+
+    /**
+     * A credential that defines an SSL client certificate passphrase.
+     */
+    public static class SSLClientCertPassphraseCredential extends Credential
+    {
+        /** Constructs an SSL client certificate passphrase credential. */
+        public SSLClientCertPassphraseCredential(String realm, String passprase)
+        {
+            super(Kind.sslClientPassphrase, realm, null);
+            this.passphrase = passphrase;
+        }
+
+        /**
+         * @return the client certificate passphrase associated with
+         * the credential.
+         */
+        public String getClientCertPassphrase()
+        {
+            return passphrase;
+        }
+
+        /** Protected constructor used by the native implementation. */
+        protected SSLClientCertPassphraseCredential(String realm, String store,
+                                                    String passprase)
+        {
+            super(Kind.sslClientPassphrase, realm, store);
+            this.passphrase = passphrase;
+        }
+
+        protected String passphrase;
+    }
+
+    /**
+     * Find a stored credential.
+     * Unlike {@link #searchCredentials}, the the realm name is not
+     * a glob pattern.
+     * <p>
+     * <b>Note:</b> If the native credentials store is disabled, this
+     *              method will always return <code>null</code>.
+     *
+     * @param configDir The path to the configuration directory; if
+     *        <code>null</code>, the default (system-specific) user
+     *        configuration path will be used.
+     * @param kind The kind of the credential; may not be <code>null</code>.
+     * @param realm The realm name; may not be <code>null</code>.
+     * @return the matching credential, or <code>null</code> if not found.
+     */
+    public static Credential getCredential(String configDir,
+                                           Credential.Kind kind,
+                                           String realm)
+        throws ClientException
+    {
+        return configLib.getCredential(configDir, kind, realm);
+    }
+
+    /**
+     * Remove a stored credential.
+     * Unlike {@link #deleteCredentials}, the the realm name is not
+     * a glob pattern.
+     * <p>
+     * <b>Note:</b> If the native credentials store is disabled, this
+     *              method will always return <code>null</code>.
+     *
+     * @param configDir The path to the configuration directory; if
+     *        <code>null</code>, the default (system-specific) user
+     *        configuration path will be used.
+     * @param kind The kind of the credential; may not be <code>null</code>.
+     * @param realm The realm name; may not be <code>null</code>.
+     * @return the deleted credential, or <code>null</code> if not found.
+     */
+    public static Credential removeCredential(String configDir,
+                                              Credential.Kind kind,
+                                              String realm)
+        throws ClientException
+    {
+        return configLib.removeCredential(configDir, kind, realm);
+    }
+
+    /**
+     * Store a new credential, or replace an existing credential.
+     * <p>
+     * <b>Note:</b> If the native credentials store is disabled, this
+     *              method will always return <code>null</code>.
+     *
+     * @param configDir The path to the configuration directory; if
+     *        <code>null</code>, the default (system-specific) user
+     *        configuration path will be used.
+     * @param credential The credential to store.
+     * @param replace If <code>true</code>, any existing matching
+     *        credential will be replaced.
+     *
+     * @return the stored credential. If <code>replace</code> was
+     * <code>false</code>, and a credential with the same kind and
+     * for the same realm exists, it will be returned. If the given
+     * credential was successfully added, the same object reference
+     * will be returned (the calling code can compare reference values
+     * to determine this). Will return <code>null</code> if the
+     * credential could not be stored for any reason.
+     */
+    public static Credential addCredential(String configDir,
+                                           Credential credential,
+                                           boolean replace)
+        throws ClientException
+    {
+        return configLib.addCredential(configDir, credential, replace);
+    }
+
+    /**
+     * Find stored credentials that match the given search criteria.
+     * <p>
+     * <b>Note:</b> If the native credentials store is disabled, this
+     *              method will always return <code>null</code>.
+     *
+     * @param configDir The path to the configuration directory; if
+     *        <code>null</code>, the default (system-specific) user
+     *        configuration path will be used.
+     * @param kind The kind of the credential; if <code>null</code>,
+     *             all matching credential types will be returned.
+     * @param realmPattern A glob pattern for the realm string;
+     *             if <code>null</code>, all realms will be considered;
+     *             otherwise, only those credentials whose realm matches
+     *             the pattern will be returned.
+     * @param usernamePattern A glob pattern for the username;
+     *             if <code>null</code>, all credentials will be considered;
+     *             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 textPattern A glob pattern that must match any textual
+     *             information in a credential, for example, a realm,
+     *             username, certificate details, etc; passwords, passphrases
+     *             and other info considered secret will not be matched;
+     * @return the list of matching credentials.
+     */
+    public static List<Credential>
+        searchCredentials(String configDir,
+                          Credential.Kind kind,
+                          String realmPattern,
+                          String usernamePattern,
+                          String hostnamePattern,
+                          String textPattern)
+        throws ClientException
+    {
+        return configLib.searchCredentials(configDir, kind, realmPattern,
+                                           usernamePattern, hostnamePattern,
+                                           textPattern);
+    }
+
+    /**
+     * Delete stored credentials that match the given search criteria.
+     * The parameters of this method are the same as for
+     * {@link #searchCredentials}.
+     * <p>
+     * <b>Note:</b> If the native credentials store is disabled, this
+     *              method will always return <code>null</code>.
+     *
+     * @return the list of deleted credentials.
+     */
+    public static List<Credential>
+        deleteCredentials(String configDir,
+                          Credential.Kind kind,
+                          String realmPattern,
+                          String usernamePattern,
+                          String hostnamePattern,
+                          String textPattern)
+        throws ClientException
+    {
+        return configLib.deleteCredentials(configDir, kind, realmPattern,
+                                           usernamePattern, hostnamePattern,
+                                           textPattern);
+    }
+
+    //
     // Diff and Merge
     //
     private static final DiffLib diffLib = new DiffLib();

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=1601352&r1=1601351&r2=1601352&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 Mon Jun  9 12:00:31 2014
@@ -197,6 +197,12 @@ public interface AuthnCallback
             return ((failures & OTHER) != 0);
         }
 
+        /** @return the internal bitfield representation of the failures. */
+        public int getFailures()
+        {
+            return failures;
+        }
+
         private static final int NOT_YET_VALID = 0x00000001;
         private static final int EXPIRED       = 0x00000002;
         private static final int CN_MISMATCH   = 0x00000004;

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=1601352&r1=1601351&r2=1601352&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 Mon Jun  9 12:00:31 2014
@@ -23,14 +23,17 @@
 
 package org.apache.subversion.javahl.util;
 
+import org.apache.subversion.javahl.callback.*;
+
 import org.apache.subversion.javahl.SVNUtil;
 import org.apache.subversion.javahl.ClientException;
 import org.apache.subversion.javahl.NativeResources;
 
-import org.apache.subversion.javahl.callback.*;
+import java.util.List;
 
 /**
- * Provides global configuration knobs.
+ * Provides global configuration knobs and
+ * Encapsulates utility functions for authentication credentials management.
  * @since 1.9
  */
 public class ConfigLib
@@ -54,4 +57,118 @@ public class ConfigLib
     /** @see SVNUtil.isNativeCredentialsStoreEnabled */
     public native boolean isNativeCredentialsStoreEnabled()
         throws ClientException;
+
+    //
+    // Credentials management
+    //
+
+    /** @see SVNUtil.getCredential */
+    public SVNUtil.Credential getCredential(String configDir,
+                                            SVNUtil.Credential.Kind kind,
+                                            String realm)
+        throws ClientException
+    {
+        return nativeGetCredential(configDir, kind.toString(), realm);
+    }
+
+    /** @see SVNUtil.removeCredential */
+    public SVNUtil.Credential removeCredential(String configDir,
+                                               SVNUtil.Credential.Kind kind,
+                                               String realm)
+        throws ClientException
+    {
+        return nativeRemoveCredential(configDir, kind.toString(), realm);
+    }
+
+    /** @see SVNUtil.addCredential */
+    public SVNUtil.Credential addCredential(String configDir,
+                                            SVNUtil.Credential credential,
+                                            boolean replace)
+        throws ClientException
+    {
+        final AuthnCallback.SSLServerCertInfo sci = credential.getServerCertInfo();
+        final AuthnCallback.SSLServerCertFailures scf = credential.getServerCertFailures();
+        return nativeAddCredential(configDir,
+                                   credential.getKind().toString(),
+                                   credential.getRealm(),
+                                   credential.getUsername(),
+                                   credential.getPassword(),
+                                   (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),
+                                   credential.getClientCertPassphrase());
+    }
+
+    /** @see SVNUtil.searchCredentials */
+    public List<SVNUtil.Credential>
+        searchCredentials(String configDir,
+                          SVNUtil.Credential.Kind kind,
+                          String realmPattern,
+                          String usernamePattern,
+                          String hostnamePattern,
+                          String textPattern)
+        throws ClientException
+    {
+        return iterateCredentials(
+            false, configDir, kind.toString(), realmPattern,
+            usernamePattern, hostnamePattern, textPattern);
+    }
+
+    /** @see SVNUtil.deleteCredentials */
+    public List<SVNUtil.Credential>
+        deleteCredentials(String configDir,
+                          SVNUtil.Credential.Kind kind,
+                          String realmPattern,
+                          String usernamePattern,
+                          String hostnamePattern,
+                          String textPattern)
+        throws ClientException
+    {
+        return iterateCredentials(
+            true, configDir, kind.toString(), realmPattern,
+            usernamePattern, hostnamePattern, textPattern);
+    }
+
+    private native SVNUtil.Credential
+        nativeGetCredential(String configDir,
+                               String kind,
+                               String realm)
+        throws ClientException;
+
+    private native SVNUtil.Credential
+        nativeRemoveCredential(String configDir,
+                               String kind,
+                               String realm)
+        throws ClientException;
+
+    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;
+
+    private native List<SVNUtil.Credential>
+        iterateCredentials(boolean deleteMatching,
+                           String configDir,
+                           String kind,
+                           String realmPattern,
+                           String usernamePattern,
+                           String hostnamePattern,
+                           String textPattern)
+        throws ClientException;
 }
+