[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] Updated SSL server certificate handling

From: Tobias Ringström <tobias_at_ringstrom.mine.nu>
Date: 2003-09-23 21:45:47 CEST

This patch changes the (new) Subversion SSL server certificate handling
to only accept a certificate for a certain hostname and port and a set
of failures. It also makes it possible to accept a certificate that has
an invalid date or hostname permanently.

/Tobias

Log message:
Update the SSL server certificate handling to only permanently accept
a certain certificate for a particular host+port, not for any SSL
connection. It also allows the user to permanently accept/ignore all
SSL errors for a connection.

* subversion/include/svn_auth.h
  (svn_auth_cred_server_ssl_t): Added accepted_failures.

* subversion/libsvn_client/auth.c
  (ssl_server_file_provider_baton_t): Removed cred_kind.
  (server_ssl_file_first_credentials): Verify if current cert is
  trusted for the current realmstring, and the current set of
  failures.
  (server_ssl_file_save_credentials): Store the cert and the
  accepted set of failures in the auth hash.

* subversion/clients/cmdline/prompt.c
  (svn_cl__auth_ssl_server_prompt): Set the accepted_failures
  parameter in the credentials.

* subversion/libsvn_ra_dav/session.c
  (server_ssl_callback): Use the scheme, hostname and port number
  as realmstring.

Index: subversion/include/svn_auth.h
===================================================================
--- subversion/include/svn_auth.h (revision 7160)
+++ subversion/include/svn_auth.h (working copy)
@@ -191,12 +191,14 @@
 /** SSL server verification.
  *
  * If @a trust_permanently is set to true by the provider, the
- * certificate will be trusted permanently.
+ * certificate will be trusted permanently. The member @a
+ * accepted_failures is only valid if @a trust_permanently is true.
  */
 #define SVN_AUTH_CRED_SERVER_SSL "svn.ssl.server"
 typedef struct
 {
   svn_boolean_t trust_permanently;
+ int accepted_failures;
 } svn_auth_cred_server_ssl_t;
 
 
Index: subversion/libsvn_client/auth.c
===================================================================
--- subversion/libsvn_client/auth.c (revision 7160)
+++ subversion/libsvn_client/auth.c (working copy)
@@ -37,6 +37,9 @@
 #include "svn_config.h"
 #include "client.h"
 
+/* The keys that will be stored on disk */
+#define SVN_CLIENT__AUTHFILE_ASCII_CERT_KEY "ascii_cert"
+#define SVN_CLIENT__AUTHFILE_FAILURES_KEY "failures"
 
 /*-----------------------------------------------------------------------*/
 
@@ -437,9 +440,6 @@
 
 /*** SSL file providers. ***/
 typedef struct {
- /* the cred_kind being fetched (see svn_auth.h)*/
- const char *cred_kind;
-
   /* cache: realmstring which identifies the credentials file */
   const char *realmstring;
 } ssl_server_file_provider_baton_t;
@@ -476,6 +476,9 @@
   *credentials = NULL;
   *iter_baton = NULL;
 
+ /* Make sure the save_creds function can get the realmstring */
+ pb->realmstring = apr_pstrdup (pool, realmstring);
+
   /* Check for ignored cert dates */
   if (failures & (SVN_AUTH_SSL_NOTYETVALID | SVN_AUTH_SSL_EXPIRED))
     {
@@ -501,21 +504,36 @@
           failures &= ~SVN_AUTH_SSL_CNMISMATCH;
         }
     }
-
 
- /* Check if this is a permanently accepted cert */
- if (failures & SVN_AUTH_SSL_UNKNOWNCA)
+ /* Check if this is a permanently accepted certificate */
+ config_dir = apr_hash_get (parameters,
+ SVN_AUTH_PARAM_CONFIG_DIR,
+ APR_HASH_KEY_STRING);
+ error = svn_config_read_auth_data (&creds_hash, SVN_AUTH_CRED_SERVER_SSL,
+ pb->realmstring, config_dir, pool);
+ svn_error_clear(error);
+ if (!error && creds_hash)
     {
- pb->realmstring = apr_pstrdup (pool, realmstring);
- config_dir = apr_hash_get (parameters,
- SVN_AUTH_PARAM_CONFIG_DIR,
- APR_HASH_KEY_STRING);
- error = svn_config_read_auth_data (&creds_hash, pb->cred_kind,
- pb->realmstring, config_dir, pool);
- svn_error_clear(error);
- if (!error && creds_hash)
+ svn_string_t *trusted_cert, *this_cert, *failstr;
+ int last_failures;
+
+ trusted_cert = apr_hash_get (creds_hash,
+ SVN_CLIENT__AUTHFILE_ASCII_CERT_KEY,
+ APR_HASH_KEY_STRING);
+ this_cert = svn_string_create(cert_info->ascii_cert, pool);
+ failstr = apr_hash_get (creds_hash,
+ SVN_CLIENT__AUTHFILE_FAILURES_KEY,
+ APR_HASH_KEY_STRING);
+
+ last_failures = atoi(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) &&
+ (failures & ~last_failures) == 0)
         {
- failures &= ~SVN_AUTH_SSL_UNKNOWNCA;
+ failures = 0;
         }
     }
 
@@ -544,7 +562,8 @@
                                   apr_pool_t *pool)
 {
   ssl_server_file_provider_baton_t *pb = provider_baton;
- const char *ascii_cert = pb->realmstring;
+ svn_auth_cred_server_ssl_t *creds = credentials;
+ const svn_auth_ssl_server_cert_info_t *cert_info;
   apr_hash_t *creds_hash = NULL;
   const char *config_dir;
 
@@ -552,10 +571,23 @@
                              SVN_AUTH_PARAM_CONFIG_DIR,
                              APR_HASH_KEY_STRING);
 
+ cert_info = apr_hash_get (parameters,
+ SVN_AUTH_PARAM_SSL_SERVER_CERT_INFO,
+ APR_HASH_KEY_STRING);
+
   creds_hash = apr_hash_make (pool);
+ apr_hash_set (creds_hash,
+ SVN_CLIENT__AUTHFILE_ASCII_CERT_KEY,
+ APR_HASH_KEY_STRING,
+ svn_string_create (cert_info->ascii_cert, pool));
+ apr_hash_set (creds_hash,
+ SVN_CLIENT__AUTHFILE_FAILURES_KEY,
+ APR_HASH_KEY_STRING,
+ svn_string_createf(pool, "%d", creds->accepted_failures));
+
   SVN_ERR (svn_config_write_auth_data (creds_hash,
- pb->cred_kind,
- ascii_cert,
+ SVN_AUTH_CRED_SERVER_SSL,
+ pb->realmstring,
                                        config_dir,
                                        pool));
   *saved = TRUE;
@@ -668,8 +700,6 @@
   svn_auth_provider_object_t *po = apr_pcalloc (pool, sizeof(*po));
   ssl_server_file_provider_baton_t *pb = apr_pcalloc (pool, sizeof(*pb));
 
- pb->cred_kind = SVN_AUTH_CRED_SERVER_SSL;
-
   po->vtable = &server_ssl_file_provider;
   po->provider_baton = pb;
   *provider = po;
Index: subversion/clients/cmdline/prompt.c
===================================================================
--- subversion/clients/cmdline/prompt.c (revision 7160)
+++ subversion/clients/cmdline/prompt.c (working copy)
@@ -250,6 +250,7 @@
     {
       *cred_p = apr_pcalloc (pool, sizeof (**cred_p));
       (*cred_p)->trust_permanently = TRUE;
+ (*cred_p)->accepted_failures = failures;
     }
   else
     {
Index: subversion/libsvn_ra_dav/session.c
===================================================================
--- subversion/libsvn_ra_dav/session.c (revision 7160)
+++ subversion/libsvn_ra_dav/session.c (working copy)
@@ -127,15 +127,12 @@
   svn_auth_ssl_server_cert_info_t cert_info;
   char fingerprint[NE_SSL_DIGESTLEN];
   char valid_from[NE_SSL_VDATELEN], valid_until[NE_SSL_VDATELEN];
+ const char *portstring = apr_psprintf (ras->pool, "%d", ras->root.port);
+ const char *realmstring;
 
- /* The following is a quick hack to prevent alternate CN hostname
- * spoofing. It will be replaced by a better more secure solution
- * shortly. */
- if ((failures & NE_SSL_UNTRUSTED) &&
- strcmp(ne_ssl_cert_identity(cert), ras->root.host) != 0)
- {
- failures |= NE_SSL_IDMISMATCH;
- }
+ /* Construct the realmstring, e.g. https://svn.collab.net:80 */
+ realmstring = apr_pstrcat(ras->pool, ras->root.scheme, "://",
+ ras->root.host, ":", portstring, NULL);
 
   svn_auth_set_parameter(ras->callbacks->auth_baton,
                          SVN_AUTH_PARAM_SSL_SERVER_FAILURES,
@@ -161,7 +158,7 @@
   apr_pool_create(&pool, ras->pool);
   error = svn_auth_first_credentials(&creds, &state,
                                      SVN_AUTH_CRED_SERVER_SSL,
- ascii_cert,
+ realmstring,
                                      ras->callbacks->auth_baton,
                                      pool);
   if (error || !creds)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Sep 23 21:47:39 2003

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.