You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by cm...@apache.org on 2012/08/03 20:42:46 UTC

svn commit: r1369161 - in /subversion/branches/master-passphrase/subversion: include/private/svn_auth_private.h include/svn_auth.h libsvn_subr/auth.c libsvn_subr/cmdline.c libsvn_subr/masterpass_providers.c

Author: cmpilato
Date: Fri Aug  3 18:42:46 2012
New Revision: 1369161

URL: http://svn.apache.org/viewvc?rev=1369161&view=rev
Log:
On the 'master-passphrase' branch: Add the framework for supporting
the obvious additional platform-specific master passphrase providers.

* subversion/include/private/svn_auth_private.h
  (SVN_AUTH__DEFAULT_PROVIDER_LIST): New #define.

* subversion/include/svn_auth.h
  (svn_auth_master_passphrase_provider_func_t): New function type.
  (svn_auth_get_platform_specific_master_passphrase_providers): New function.

* subversion/libsvn_subr/auth.c
  (SVN__DEFAULT_AUTH_PROVIDER_LIST): Remove.
  (svn_auth_get_platform_specific_client_providers): Use
    SVN_AUTH__DEFAULT_PROVIDER_LIST instead of SVN__DEFAULT_AUTH_PROVIDER_LIST.

* subversion/libsvn_subr/cmdline.c
  (open_auth_store): Add 'cfg' parameter, and now call
    svn_auth_get_platform_specific_master_passphrase_providers() instead
    of explicitly referencing the gpg-agent master passphrase provider.
  (svn_cmdline_create_auth_baton): Update call to open_auth_store().

* subversion/libsvn_subr/masterpass_providers.c
  (get_provider, svn_auth_get_platform_specific_master_passphrase_providers):
    New functions.

Modified:
    subversion/branches/master-passphrase/subversion/include/private/svn_auth_private.h
    subversion/branches/master-passphrase/subversion/include/svn_auth.h
    subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c
    subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c
    subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c

Modified: subversion/branches/master-passphrase/subversion/include/private/svn_auth_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/include/private/svn_auth_private.h?rev=1369161&r1=1369160&r2=1369161&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/private/svn_auth_private.h (original)
+++ subversion/branches/master-passphrase/subversion/include/private/svn_auth_private.h Fri Aug  3 18:42:46 2012
@@ -48,6 +48,13 @@ extern "C" {
 #define SVN_AUTH__GNOME_KEYRING_PASSWORD_TYPE      "gnome-keyring"
 #define SVN_AUTH__GPG_AGENT_PASSWORD_TYPE          "gpg-agent"
 
+/* Default ordered list of available third-party password storage
+ * providers.
+ */
+#define SVN_AUTH__DEFAULT_PROVIDER_LIST \
+         "gnome-keyring,kwallet,keychain,gpg-agent,windows-cryptoapi"
+
+
 /* A function that stores in *PASSWORD (potentially after decrypting it)
    the user's password.  It might be obtained directly from CREDS, or
    from an external store, using REALMSTRING and USERNAME as keys.

Modified: subversion/branches/master-passphrase/subversion/include/svn_auth.h
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/include/svn_auth.h?rev=1369161&r1=1369160&r2=1369161&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/include/svn_auth.h (original)
+++ subversion/branches/master-passphrase/subversion/include/svn_auth.h Fri Aug  3 18:42:46 2012
@@ -900,6 +900,7 @@ svn_auth_get_platform_specific_client_pr
   svn_config_t *config,
   apr_pool_t *pool);
 
+
 #if (defined(WIN32) && !defined(__MINGW32__)) || defined(DOXYGEN)
 /**
  * Set @a *provider to an authentication provider of type @c
@@ -1310,6 +1311,34 @@ svn_auth_get_ssl_client_cert_pw_prompt_p
   apr_pool_t *pool);
 
 
+
+/*** Master Passphrase Providers ***/
+
+/** Master passphrase providers are unique in Subversion in that they
+ * are used with a unique svn_auth_baton_t which is not the same auth
+ * baton used for other provider types ("simple", "username", etc.).
+ */
+
+/** A function returning a master passphrase provider. */
+typedef void (*svn_auth_master_passphrase_provider_func_t)(
+  svn_auth_provider_object_t **provider,
+  apr_pool_t *pool);
+
+/** Set @a *providers to an array of @c svn_auth_provider_object_t
+ * master passphrase providers appropriate for the client platform and
+ * which honor the allowed, ordered providers specified via the
+ * 'password-stores' option @a config.  Allocate providers from @a
+ * pool.
+ *
+ * @since New in 1.8.
+ */
+svn_error_t *
+svn_auth_get_platform_specific_master_passphrase_providers(
+  apr_array_header_t **providers,
+  svn_config_t *config,
+  apr_pool_t *pool);
+
+
 /** Set @a *provider to an authentication provider of type @c
  * svn_auth_cred_master_passphrase_t, allocated in @a pool.
  *

Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c?rev=1369161&r1=1369160&r2=1369161&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/auth.c Fri Aug  3 18:42:46 2012
@@ -34,6 +34,7 @@
 #include "svn_private_config.h"
 #include "svn_dso.h"
 #include "svn_version.h"
+#include "private/svn_auth_private.h"
 
 /* AN OVERVIEW
    ===========
@@ -523,9 +524,6 @@ svn_auth_get_platform_specific_client_pr
   apr_array_header_t *password_stores;
   int i;
 
-#define SVN__DEFAULT_AUTH_PROVIDER_LIST \
-         "gnome-keyring,kwallet,keychain,gpg-agent,windows-cryptoapi"
-
   if (config)
     {
       svn_config_get
@@ -533,11 +531,11 @@ svn_auth_get_platform_specific_client_pr
          &password_stores_config_option,
          SVN_CONFIG_SECTION_AUTH,
          SVN_CONFIG_OPTION_PASSWORD_STORES,
-         SVN__DEFAULT_AUTH_PROVIDER_LIST);
+         SVN_AUTH__DEFAULT_PROVIDER_LIST);
     }
   else
     {
-      password_stores_config_option = SVN__DEFAULT_AUTH_PROVIDER_LIST;
+      password_stores_config_option = SVN_AUTH__DEFAULT_PROVIDER_LIST;
     }
 
   *providers = apr_array_make(pool, 12, sizeof(svn_auth_provider_object_t *));

Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c?rev=1369161&r1=1369160&r2=1369161&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/cmdline.c Fri Aug  3 18:42:46 2012
@@ -450,6 +450,7 @@ ssl_trust_unknown_server_cert
 /* Instantiate and open an auth store. */
 static svn_error_t *
 open_auth_store(svn_auth__store_t **auth_store_p,
+                svn_config_t *cfg,
                 const char *config_dir,
                 svn_boolean_t use_master_password,
                 svn_boolean_t no_auth_cache,
@@ -473,16 +474,10 @@ open_auth_store(svn_auth__store_t **auth
 
       /* Build an authentication baton with the relevant master
          passphrase providers. */
-      mp_providers = apr_array_make(pool, 1, 
-                                    sizeof(svn_auth_provider_object_t *));
       if (! non_interactive)
         {
-#if !defined(WIN32) || defined(DOXYGEN)
-          /* ### FIXME!!  This should be done by code that inspects
-             and honors the 'password-stores' configuration setting! */
-          svn_auth_get_gpg_agent_master_passphrase_provider(&provider, pool);
-          APR_ARRAY_PUSH(mp_providers, svn_auth_provider_object_t *) = provider;
-#endif /* !defined(WIN32) || defined(DOXYGEN) */
+          SVN_ERR(svn_auth_get_platform_specific_master_passphrase_providers(
+              &mp_providers, cfg, pool));
           svn_auth_get_master_passphrase_prompt_provider(
               &provider, svn_cmdline_auth_master_passphrase_prompt,
               pb, 3, pool);
@@ -689,7 +684,7 @@ svn_cmdline_create_auth_baton(svn_auth_b
 #endif /* SVN_HAVE_GNOME_KEYRING */
 
   /* Open the appropriate auth store, and cache it in the auth baton. */
-  SVN_ERR(open_auth_store(&auth_store, config_dir, use_master_password,
+  SVN_ERR(open_auth_store(&auth_store, cfg, config_dir, use_master_password,
                           (no_auth_cache || ! store_auth_creds_val),
                           non_interactive, pb, pool));
   svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_AUTH_STORE, auth_store);

Modified: subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c
URL: http://svn.apache.org/viewvc/subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c?rev=1369161&r1=1369160&r2=1369161&view=diff
==============================================================================
--- subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c (original)
+++ subversion/branches/master-passphrase/subversion/libsvn_subr/masterpass_providers.c Fri Aug  3 18:42:46 2012
@@ -28,6 +28,8 @@
 #include "svn_error.h"
 #include "svn_config.h"
 #include "svn_string.h"
+#include "svn_dso.h"
+#include "svn_version.h"
 #include "auth_store.h"
 
 #include "private/svn_auth_private.h"
@@ -149,3 +151,163 @@ void svn_auth_get_master_passphrase_prom
   po->provider_baton = pb;
   *provider = po;
 }
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Platform-specific providers                                           */
+/*-----------------------------------------------------------------------*/
+
+/* Set *PROVIDER to the master passphrase provider known by
+   PROVIDER_NAME, if available for the plaform; set it to NULL
+   otherwise.  */
+static svn_error_t *
+get_provider(svn_auth_provider_object_t **provider,
+             const char *provider_name,
+             apr_pool_t *pool)
+{
+  *provider = NULL;
+
+  if (apr_strnatcmp(provider_name, "gnome_keyring") == 0 ||
+      apr_strnatcmp(provider_name, "kwallet") == 0)
+    {
+#if (defined(SVN_HAVE_GNOME_KEYRING) || defined(SVN_HAVE_KWALLET))
+      apr_dso_handle_t *dso;
+      apr_dso_handle_sym_t provider_func_symbol, version_func_symbol;
+      const char *provider_func_name, *version_func_name;
+      const char *library_label, *library_name;
+
+      library_name = apr_psprintf(pool, "libsvn_auth_%s-%d.so.0",
+                                  provider_name, SVN_VER_MAJOR);
+      library_label = apr_psprintf(pool, "svn_%s", provider_name);
+      provider_func_name = 
+        apr_psprintf(pool,
+                     "svn_auth__get_%s_master_passphrase_provider",
+                     provider_name);
+      version_func_name = 
+        apr_psprintf(pool, "svn_auth_%s_version", provider_name);
+      SVN_ERR(svn_dso_load(&dso, library_name));
+      if (dso)
+        {
+          if (apr_dso_sym(&version_func_symbol, dso, version_func_name) == 0)
+            {
+              svn_version_func_t version_func = version_func_symbol;
+              svn_version_checklist_t check_list[2];
+
+              check_list[0].label = library_label;
+              check_list[0].version_query = version_func;
+              check_list[1].label = NULL;
+              check_list[1].version_query = NULL;
+              SVN_ERR(svn_ver_check_list(svn_subr_version(), check_list));
+            }
+          if (apr_dso_sym(&provider_func_symbol, dso, provider_func_name) == 0)
+            {
+              svn_auth_master_passphrase_provider_func_t provider_func =
+                provider_func_symbol;
+              provider_func(provider, pool);
+            }
+        }
+#endif /* defined(SVN_HAVE_GNOME_KEYRING) || defined(SVN_HAVE_KWALLET) */
+    }
+  else if (strcmp(provider_name, "gpg_agent") == 0)
+    {
+#if defined(SVN_HAVE_GPG_AGENT)
+      svn_auth_get_gpg_agent_master_passphrase_provider(provider, pool);
+#endif /* defined(SVN_HAVE_GPG_AGENT) */
+    }
+  else if (strcmp(provider_name, "keychain") == 0)
+    {
+#ifdef SVN_HAVE_KEYCHAIN_SERVICES
+      svn_auth_get_keychain_master_passphrase_provider(provider, pool);
+#endif /* SVN_HAVE_KEYCHAIN_SERVICES */
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+/* If provider P is non-NULL, add it to the providers LIST. */
+#define SVN__MAYBE_ADD_PROVIDER(list,p)                        \
+  { if (p) APR_ARRAY_PUSH(list,                                \
+                          svn_auth_provider_object_t *) = p; }
+
+svn_error_t *
+svn_auth_get_platform_specific_master_passphrase_providers(
+  apr_array_header_t **providers,
+  svn_config_t *config,
+  apr_pool_t *pool)
+{
+  svn_auth_provider_object_t *provider;
+  const char *password_stores_config_option = SVN_AUTH__DEFAULT_PROVIDER_LIST;
+  apr_array_header_t *password_stores;
+  int i;
+
+  /* Initialize our output. */
+  *providers = apr_array_make(pool, 12, sizeof(svn_auth_provider_object_t *));
+
+  if (config)
+    {
+      svn_config_get(config, &password_stores_config_option,
+                     SVN_CONFIG_SECTION_AUTH,
+                     SVN_CONFIG_OPTION_PASSWORD_STORES,
+                     SVN_AUTH__DEFAULT_PROVIDER_LIST);
+    }
+
+  password_stores = svn_cstring_split(password_stores_config_option,
+                                      " ,", TRUE, pool);
+  for (i = 0; i < password_stores->nelts; i++)
+    {
+      const char *password_store = APR_ARRAY_IDX(password_stores, i,
+                                                 const char *);
+
+      /* GNOME Keyring */
+      if (apr_strnatcmp(password_store, "gnome-keyring") == 0)
+        {
+#if 0
+          SVN_ERR(get_provider(&provider, "gnome_keyring", pool));
+          SVN__MAYBE_ADD_PROVIDER(*providers, provider);
+#endif
+          continue;
+        }
+
+      /* GPG-Agent */
+      if (apr_strnatcmp(password_store, "gpg-agent") == 0)
+        {
+          SVN_ERR(get_provider(&provider, "gpg_agent", pool));
+          SVN__MAYBE_ADD_PROVIDER(*providers, provider);
+          continue;
+        }
+
+      /* KWallet */
+      if (apr_strnatcmp(password_store, "kwallet") == 0)
+        {
+#if 0
+          SVN_ERR(get_provider(&provider, "kwallet", pool));
+          SVN__MAYBE_ADD_PROVIDER(*providers, provider);
+#endif
+          continue;
+        }
+
+      /* Keychain */
+      if (apr_strnatcmp(password_store, "keychain") == 0)
+        {
+#if 0
+          SVN_ERR(get_provider(&provider, "keychain", pool));
+          SVN__MAYBE_ADD_PROVIDER(*providers, provider);
+#endif
+          continue;
+        }
+
+      /* Windows (no master passphrase provider for this platform) */
+      if (apr_strnatcmp(password_store, "windows-cryptoapi") == 0)
+        continue;
+
+      return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
+                               _("Invalid config: unknown password store '%s'"),
+                               password_store);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+#undef SVN__MAYBE_ADD_PROVIDER