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

[PATCH] Obfuscate auth info

From: Malcolm Rowe <malcolm-svn-dev_at_farside.org.uk>
Date: 2006-10-18 11:29:56 CEST

Hello list,

Background for people not at the summit: We discussed the
regularly-reported problem today about the Subversion client storing
plaintext auth info on Unix, and the response that elicits from users.

We all agreed that scrambling the password wouldn't add any security at
all, but we also had a vague consensus that as long as we made sure that
users didn't think the passwords _were_ encrypted, obfuscating them in
some way might not be objectionable, since not doing so aggravates some
people.

Obfuscating passwords solves two problems:
1. It prevents accidental disclosure (e.g. 'grep -r pony ~', if your
   password is 'i-want-a-pony', your non-malicious sysadmin reading
   it by mistake, that kind of thing).
2. It stops people complaining that "HEY SUBVERSION IS STORING MY PASSWORD IN
   THE CLEAR!!1".

I thought I might take a look at how easy it was to do this, and it
turns out to be really easy, hence the attached patch. I'm far too
tired to actually write a proper log message at the moment, but in the
meantime the code's here if we decide that we want it.

[I want to make it clear that if we decide that we aren't interested in
this feature, I'm quite happy to drop the code in the bin. This is not
an attempt to drive the feature in by saying "Hey, I did all this work,
you've gotta commit it".]

The patch adds a new type of simple provider that just base64's the
password and adds a warning to make it clear that the auth info is not
encrypted. The resulting auth file looks like this:

K 7
comment
V 252
WARNING! This file contains a version of your password that has been
slightly scrambled to avoid accidental disclosure.

The scrambled password is NOT ENCRYPTED in any way, and so you should
take the same care of it as you would your regular password.
K 8
passtype
V 10
obfuscated
K 8
password
V 16
aGFycnlzc2VjcmV0
K 15
svn:realmstring
V 59
<svn://localhost:3691> c5ddb573-1120-0410-ba9b-f45616950c8b
K 8
username
V 5
harry
END

Regards,
Malcolm

Index: subversion/include/svn_auth.h
===================================================================
--- subversion/include/svn_auth.h (revision 21975)
+++ subversion/include/svn_auth.h (working copy)
@@ -701,6 +701,26 @@ svn_auth_get_keychain_simple_provider(sv
 
 #endif /* DARWIN || DOXYGEN */
 
+/**
+ * Create and return @a *provider, an authentication provider of type @c
+ * svn_auth_cred_simple_t that gets/sets information from the user's
+ * ~/.subversion configuration directory. Allocate @a *provider in
+ * @a pool.
+ *
+ * This is like svn_client_get_simple_provider(), except that the
+ * provider will lightly scramble the password before storing it to
+ * disk so that accidental disclosure is harder.
+ *
+ * This provider does @em not encrypt the data in any meaningful way.
+ * To ensure that users are aware of this, it will also add a warning to
+ * the auth file.
+ *
+ * @since New in 1.5.
+ */
+void
+svn_auth_get_obfuscated_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+
 /** Create and return @a *provider, an authentication provider of type @c
  * svn_auth_cred_username_t that gets/sets information from a user's
  * ~/.subversion configuration directory. Allocate @a *provider in
Index: subversion/libsvn_subr/simple_providers.c
===================================================================
--- subversion/libsvn_subr/simple_providers.c (revision 21975)
+++ subversion/libsvn_subr/simple_providers.c (working copy)
@@ -23,6 +23,7 @@
 /*** Includes. ***/
 
 #include <apr_pools.h>
+#include <apr_base64.h>
 #include "svn_auth.h"
 #include "svn_error.h"
 #include "svn_utf.h"
@@ -39,10 +40,12 @@
 #define SVN_AUTH__AUTHFILE_USERNAME_KEY "username"
 #define SVN_AUTH__AUTHFILE_PASSWORD_KEY "password"
 #define SVN_AUTH__AUTHFILE_PASSTYPE_KEY "passtype"
+#define SVN_AUTH__AUTHFILE_COMMENT_KEY "comment"
 
 #define SVN_AUTH__SIMPLE_PASSWORD_TYPE "simple"
 #define SVN_AUTH__WINCRYPT_PASSWORD_TYPE "wincrypt"
 #define SVN_AUTH__KEYCHAIN_PASSWORD_TYPE "keychain"
+#define SVN_AUTH__OBFUSCATED_PASSWORD_TYPE "obfuscated"
 
 
 /* A function that stores PASSWORD (or some encrypted version thereof)
@@ -537,17 +540,12 @@ svn_auth_get_simple_prompt_provider
 
 #ifdef WIN32
 #include <wincrypt.h>
-#include <apr_base64.h>
 
 /* The description string that's combined with unencrypted data by the
    Windows CryptoAPI. Used during decryption to verify that the
    encrypted data were valid. */
 static const WCHAR description[] = L"auth_svn.simple.wincrypt";
 
-/* The password type used by the windows simple auth provider, passed
- into simple_first_creds_helper and simple_save_creds_helper. */
-static const char windows_crypto_type[] = "wincrypt";
-
 /* Dynamically load the address of function NAME in PDLL into
    PFN. Return TRUE if the function name was found, otherwise
    FALSE. Equivalent to dlsym(). */
@@ -877,3 +875,117 @@ svn_auth_get_keychain_simple_provider(sv
 }
 
 #endif /* SVN_HAVE_KEYCHAIN_SERVICES */
+
+/*-----------------------------------------------------------------------*/
+/* Obfuscating simple provider, stores obfuscated passwords in the creds */
+/* file. This does not add any security at all, but does mitigate */
+/* against accidental disclosure. */
+/*-----------------------------------------------------------------------*/
+
+/* Store an obfuscated (base-64) version of PASSWORD in CREDS, together with
+ a note to warn users that the password is not encrypted.
+
+ This function implements password_set_t. */
+static svn_boolean_t
+obfuscated_password_set(apr_hash_t *creds,
+ const char *realmstring,
+ const char *username,
+ const char *password,
+ svn_boolean_t non_interactive,
+ apr_pool_t *pool)
+{
+ size_t len = strlen(password);
+ char *obfuscated = apr_palloc(pool, apr_base64_encode_len(len));
+ apr_base64_encode(obfuscated, password, len);
+ if (!simple_password_set(creds, realmstring, username, obfuscated,
+ non_interactive, pool))
+ return FALSE;
+
+ const char * warning =
+ _("WARNING! This file contains a version of your password that has been\n"
+ "slightly scrambled to avoid accidental disclosure.\n\n"
+ "The scrambled password is NOT ENCRYPTED in any way, and so you should\n"
+ "take the same care of it as you would your regular password.");
+ apr_hash_set(creds, SVN_AUTH__AUTHFILE_COMMENT_KEY, APR_HASH_KEY_STRING,
+ svn_string_create(warning, pool));
+
+ return TRUE;
+}
+
+/* Retrieve an obfuscated password from CREDS.
+ This function implements password_get_t. */
+static svn_boolean_t
+obfuscated_password_get(const char **password,
+ apr_hash_t *creds,
+ const char *realmstring,
+ const char *username,
+ svn_boolean_t non_interactive,
+ apr_pool_t *pool)
+{
+ const char *obfuscated;
+ char *plaintext;
+ size_t len;
+
+ if (!simple_password_get(&obfuscated, creds, realmstring, username,
+ non_interactive, pool))
+ return FALSE;
+
+ len = apr_base64_decode_len(obfuscated);
+ plaintext = apr_palloc(pool, len);
+ apr_base64_decode(plaintext, obfuscated);
+ *password = plaintext;
+
+ return TRUE;
+}
+
+/* Get cached obfuscated credentials from the simple provider's cache. */
+static svn_error_t *
+obfuscated_simple_first_creds(void **credentials,
+ void **iter_baton,
+ void *provider_baton,
+ apr_hash_t *parameters,
+ const char *realmstring,
+ apr_pool_t *pool)
+{
+ return simple_first_creds_helper(credentials,
+ iter_baton, provider_baton,
+ parameters, realmstring,
+ obfuscated_password_get,
+ SVN_AUTH__OBFUSCATED_PASSWORD_TYPE,
+ pool);
+}
+
+/* Save obfuscated credentials to the simple provider's cache. */
+static svn_error_t *
+obfuscated_simple_save_creds(svn_boolean_t *saved,
+ void *credentials,
+ void *provider_baton,
+ apr_hash_t *parameters,
+ const char *realmstring,
+ apr_pool_t *pool)
+{
+ return simple_save_creds_helper(saved, credentials, provider_baton,
+ parameters, realmstring,
+ obfuscated_password_set,
+ SVN_AUTH__OBFUSCATED_PASSWORD_TYPE,
+ pool);
+}
+
+static const svn_auth_provider_t obfuscated_simple_provider = {
+ SVN_AUTH_CRED_SIMPLE,
+ obfuscated_simple_first_creds,
+ NULL,
+ obfuscated_simple_save_creds
+};
+
+
+/* Public API */
+void
+svn_auth_get_obfuscated_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
+
+ po->vtable = &obfuscated_simple_provider;
+ *provider = po;
+}
Index: subversion/libsvn_subr/cmdline.c
===================================================================
--- subversion/libsvn_subr/cmdline.c (revision 21975)
+++ subversion/libsvn_subr/cmdline.c (working copy)
@@ -362,6 +362,8 @@ svn_cmdline_setup_auth_baton(svn_auth_ba
   svn_auth_get_keychain_simple_provider(&provider, pool);
   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
 #endif
+ svn_auth_get_obfuscated_simple_provider(&provider, pool);
+ APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
   svn_auth_get_simple_provider(&provider, pool);
   APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
   svn_auth_get_username_provider(&provider, pool);

  • application/pgp-signature attachment: stored
Received on Wed Oct 18 11:30:17 2006

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