diff --git a/reviewboard/scmtools/svn/__init__.py b/reviewboard/scmtools/svn/__init__.py
index 620cb691339447e10a1ff40efa8181ca948533f1..5e00488bd5e61d34d46ab2f85014c496315305f6 100644
--- a/reviewboard/scmtools/svn/__init__.py
+++ b/reviewboard/scmtools/svn/__init__.py
@@ -75,9 +75,9 @@ class SVNTool(SCMTool):
         # reference the repository, but it will safely go away when needed.
         # The function we pass can access that without causing the leaks
         repository_ref = weakref.ref(repository)
-        self.client.callback_ssl_server_trust_prompt = \
-            lambda trust_dict: \
-            SVNTool._ssl_server_trust_prompt(trust_dict, repository_ref())
+        self.client.set_ssl_server_trust_prompt(
+            lambda trust_dict:
+            SVNTool._ssl_server_trust_prompt(trust_dict, repository_ref()))
 
         # 'svn diff' produces patches which have the revision string localized
         # to their system locale. This is a little ridiculous, but we have to
diff --git a/reviewboard/scmtools/svn/base.py b/reviewboard/scmtools/svn/base.py
index b5de12d762206ed7b2f3bbb8cb8029383c56b33f..138cdfd53cce4efe2ea029ec3c5844f79b85c273 100644
--- a/reviewboard/scmtools/svn/base.py
+++ b/reviewboard/scmtools/svn/base.py
@@ -37,6 +37,9 @@ class Client(object):
     def __init__(self, config_dir, repopath, username=None, password=None):
         self.repopath = repopath
 
+    def set_ssl_server_trust_prompt(self, cb):
+        raise NotImplementedError
+
     @property
     def branches(self):
         """Returns a list of branches.
diff --git a/reviewboard/scmtools/svn/pysvn.py b/reviewboard/scmtools/svn/pysvn.py
index 5f4fb0e4fdb35b243cdb6b4d59dc18b22e66df13..19985995b22e81847766031598352741be2ea88f 100644
--- a/reviewboard/scmtools/svn/pysvn.py
+++ b/reviewboard/scmtools/svn/pysvn.py
@@ -45,6 +45,13 @@ class Client(base.Client):
         if password:
             self.client.set_default_password(six.text_type(password))
 
+    def set_ssl_server_trust_prompt(self, cb):
+        self.client.callback_ssl_server_trust_prompt = cb
+
+    def ssl_trust_prompt(self, trust_dict):
+        if hasattr(self, 'callback_ssl_server_trust_prompt'):
+            return self.callback_ssl_server_trust_prompt(trust_dict)
+
     def _do_on_path(self, cb, path, revision=HEAD):
         if not path:
             raise FileNotFoundError(path, revision)
@@ -301,10 +308,11 @@ class Client(base.Client):
 
         def ssl_server_trust_prompt(trust_dict):
             cert.update(trust_dict.copy())
-            del cert['failures']
+
             if on_failure:
                 return False, 0, False
             else:
+                del cert['failures']
                 return True, trust_dict['failures'], True
 
         self.client.callback_ssl_server_trust_prompt = ssl_server_trust_prompt
@@ -316,3 +324,5 @@ class Client(base.Client):
         except ClientError as e:
             if on_failure:
                 on_failure(e, path, cert)
+
+        return cert
diff --git a/reviewboard/scmtools/svn/subvertpy.py b/reviewboard/scmtools/svn/subvertpy.py
index 41d5495fea617e817477c3a48f42e42f1c8f908c..49b4b37aaa332230846a7c230552fab4d15954b3 100644
--- a/reviewboard/scmtools/svn/subvertpy.py
+++ b/reviewboard/scmtools/svn/subvertpy.py
@@ -38,21 +38,36 @@ class Client(base.Client):
         super(Client, self).__init__(config_dir, repopath, username, password)
         self.repopath = B(self.repopath)
         self.config_dir = B(config_dir)
+
+        self._ssl_trust_prompt_cb = None
+
         auth_providers = [
             ra.get_simple_provider(),
             ra.get_username_provider(),
         ]
+
         if repopath.startswith('https:'):
-            auth_providers.append(
-                ra.get_ssl_server_trust_prompt_provider(self.ssl_trust_prompt))
+            auth_providers += [
+                ra.get_ssl_client_cert_file_provider(),
+                ra.get_ssl_client_cert_pw_file_provider(),
+                ra.get_ssl_server_trust_file_provider(),
+                ra.get_ssl_server_trust_prompt_provider(self.ssl_trust_prompt),
+            ]
+
         self.auth = ra.Auth(auth_providers)
+
         if username:
             self.auth.set_parameter(B('svn:auth:username'), B(username))
+
         if password:
             self.auth.set_parameter(B('svn:auth:password'), B(password))
+
         cfg = get_config(self.config_dir)
         self.client = SVNClient(cfg, auth=self.auth)
 
+    def set_ssl_server_trust_prompt(self, cb):
+        self._ssl_trust_prompt_cb = cb
+
     @property
     def ra(self):
         """Lazily creates the ``RemoteAccess`` object so
@@ -246,7 +261,7 @@ class Client(base.Client):
                           issuer_dname, ascii_cert)
         :return: (accepted_failures, may_save)
         """
-        if hasattr(self, 'callback_ssl_server_trust_prompt'):
+        if self._ssl_trust_prompt_cb:
             trust_dict = {
                 'realm': realm,
                 'failures': failures,
@@ -256,36 +271,10 @@ class Client(base.Client):
                 'valid_until': certinfo[3],
                 'issuer_dname': certinfo[4],
             }
-            return self.callback_ssl_server_trust_prompt(trust_dict)[1:]
+            return self._trust_prompt_cb(trust_dict)[1:]
         else:
             return None
 
-    def _accept_trust_prompt(self, realm, failures, certinfo, may_save):
-        """
-        Callback for ``subvertpy.ra.get_ssl_server_trust_prompt_provider``.
-        ``may_save`` indicates whether to save the cert info for
-        subsequent requests.
-
-        USED ONLY FOR ``accept_ssl_certificate``.
-
-        :param certinfo: (hostname, fingerprint, valid_from, valid_until,
-                            issuer_dname, ascii_cert)
-        :return: (accepted_failures, may_save)
-        """
-        self._accept_cert.update({
-            'realm': realm,
-            'failures': failures,
-            'hostname': certinfo[0],
-            'finger_print': certinfo[1],
-            'valid_from': certinfo[2],
-            'valid_until': certinfo[3],
-            'issuer_dname': certinfo[4],
-        })
-        if self._accept_on_failure:
-            return None
-        else:
-            return failures, True
-
     def accept_ssl_certificate(self, path, on_failure=None):
         """If the repository uses SSL, this method is used to determine whether
         the SSL certificate can be automatically accepted.
@@ -297,20 +286,42 @@ class Client(base.Client):
 
             void on_failure(e:Exception, path:str, cert:dict)
         """
-        self._accept_cert = {}
-        self._accept_on_failure = on_failure
+        cert = {}
+
+        def _accept_trust_prompt(realm, failures, certinfo, may_save):
+            cert.update({
+                'realm': realm,
+                'failures': failures,
+                'hostname': certinfo[0],
+                'finger_print': certinfo[1],
+                'valid_from': certinfo[2],
+                'valid_until': certinfo[3],
+                'issuer_dname': certinfo[4],
+            })
+
+            if on_failure:
+                return 0, False
+            else:
+                del cert['failures']
+                return failures, True
 
         auth = ra.Auth([
             ra.get_simple_provider(),
             ra.get_username_provider(),
-            ra.get_ssl_server_trust_prompt_provider(self._accept_trust_prompt),
+            ra.get_ssl_client_cert_file_provider(),
+            ra.get_ssl_client_cert_pw_file_provider(),
+            ra.get_ssl_server_trust_file_provider(),
+            ra.get_ssl_server_trust_prompt_provider(_accept_trust_prompt),
         ])
         cfg = get_config(self.config_dir)
         client = SVNClient(cfg, auth)
+
         try:
             info = client.info(path)
             logging.debug('SVN: Got repository information for %s: %s' %
                           (path, info))
         except SubversionException as e:
             if on_failure:
-                on_failure(e, path, self._accept_cert)
+                on_failure(e, path, cert)
+
+        return cert
