You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/07/08 16:29:04 UTC

svn commit: r1500762 - /subversion/trunk/subversion/libsvn_subr/gpg_agent.c

Author: stsp
Date: Mon Jul  8 14:29:04 2013
New Revision: 1500762

URL: http://svn.apache.org/r1500762
Log:
Prevent the GPG Agent password store from overriding other password stores
even though no usable GPG agent is running.

* subversion/libsvn_subr/gpg_agent.c
  (find_running_gpg_agent): New helper function that finds a running GPG Agent.
   This code was split out from the upper half of ...
  (password_get_gpg_agent): ... this function.
  (password_set_gpg_agent): Don't unconditionally set *done to TRUE. While it
   is correct that we don't need to explicitly store the password in the agent,
   this function must check whether a usable GPG agent exists. Otherwise,
   users might be left with no usable password store, since the gpg-agent
   store wrongly claims that the password was saved, when it actually wasn't.

Modified:
    subversion/trunk/subversion/libsvn_subr/gpg_agent.c

Modified: subversion/trunk/subversion/libsvn_subr/gpg_agent.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/gpg_agent.c?rev=1500762&r1=1500761&r2=1500762&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/gpg_agent.c (original)
+++ subversion/trunk/subversion/libsvn_subr/gpg_agent.c Mon Jul  8 14:29:04 2013
@@ -156,42 +156,28 @@ send_option(int sd, char *buf, size_t n,
   return (strncmp(buf, "OK", 2) == 0);
 }
 
-/* Implementation of svn_auth__password_get_t that retrieves the password
-   from gpg-agent */
+
+/* Locate a running GPG Agent, and return an open file descriptor
+ * for communication with the agent in *NEW_SD. If no running agent
+ * can be found, set *NEW_SD to -1. */
 static svn_error_t *
-password_get_gpg_agent(svn_boolean_t *done,
-                       const char **password,
-                       apr_hash_t *creds,
-                       const char *realmstring,
-                       const char *username,
-                       apr_hash_t *parameters,
-                       svn_boolean_t non_interactive,
-                       apr_pool_t *pool)
+find_running_gpg_agent(int *new_sd, apr_pool_t *pool)
 {
-  int sd;
+  char *buffer;
   char *gpg_agent_info = NULL;
+  const char *socket_name = NULL;
+  const char *request = NULL;
   const char *p = NULL;
   char *ep = NULL;
-  char *buffer;
-
-  apr_array_header_t *socket_details;
-  const char *request = NULL;
-  const char *cache_id = NULL;
-  struct sockaddr_un addr;
-  const char *tty_name;
-  const char *tty_type;
-  const char *lc_ctype;
-  const char *display;
-  const char *socket_name = NULL;
-  svn_checksum_t *digest = NULL;
-  char *password_prompt;
-  char *realm_prompt;
+  int sd;
 
-  *done = FALSE;
+  *new_sd = -1;
 
   gpg_agent_info = getenv("GPG_AGENT_INFO");
   if (gpg_agent_info != NULL)
     {
+      apr_array_header_t *socket_details;
+
       socket_details = svn_cstring_split(gpg_agent_info, ":", TRUE,
                                          pool);
       socket_name = APR_ARRAY_IDX(socket_details, 0, const char *);
@@ -201,6 +187,8 @@ password_get_gpg_agent(svn_boolean_t *do
 
   if (socket_name != NULL)
     {
+      struct sockaddr_un addr;
+
       addr.sun_family = AF_UNIX;
       strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path) - 1);
       addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
@@ -273,6 +261,44 @@ password_get_gpg_agent(svn_boolean_t *do
       return SVN_NO_ERROR;
     }
 
+  *new_sd = sd;
+  return SVN_NO_ERROR;
+}
+
+/* Implementation of svn_auth__password_get_t that retrieves the password
+   from gpg-agent */
+static svn_error_t *
+password_get_gpg_agent(svn_boolean_t *done,
+                       const char **password,
+                       apr_hash_t *creds,
+                       const char *realmstring,
+                       const char *username,
+                       apr_hash_t *parameters,
+                       svn_boolean_t non_interactive,
+                       apr_pool_t *pool)
+{
+  int sd;
+  const char *p = NULL;
+  char *ep = NULL;
+  char *buffer;
+  const char *request = NULL;
+  const char *cache_id = NULL;
+  const char *tty_name;
+  const char *tty_type;
+  const char *lc_ctype;
+  const char *display;
+  svn_checksum_t *digest = NULL;
+  char *password_prompt;
+  char *realm_prompt;
+
+  *done = FALSE;
+
+  SVN_ERR(find_running_gpg_agent(&sd, pool));
+  if (sd == -1)
+    return SVN_NO_ERROR;
+
+  buffer = apr_palloc(pool, BUFFER_SIZE);
+
   /* Send TTY_NAME to the gpg-agent daemon. */
   tty_name = getenv("GPG_TTY");
   if (tty_name != NULL)
@@ -388,8 +414,8 @@ password_get_gpg_agent(svn_boolean_t *do
    password in GPG Agent if that's how this particular integration
    worked.  But it isn't.  GPG Agent stores the password provided by
    the user via the pinentry program immediately upon its provision
-   (and regardless of its accuracy as passwords go), so there's
-   nothing really to do here.  */
+   (and regardless of its accuracy as passwords go), so we just need
+   to check if a usable GPG Agent exists. */
 static svn_error_t *
 password_set_gpg_agent(svn_boolean_t *done,
                        apr_hash_t *creds,
@@ -400,7 +426,21 @@ password_set_gpg_agent(svn_boolean_t *do
                        svn_boolean_t non_interactive,
                        apr_pool_t *pool)
 {
-  *done = TRUE;
+  int sd;
+  const char *tty_name;
+
+  *done = FALSE;
+
+  SVN_ERR(find_running_gpg_agent(&sd, pool));
+  if (sd == -1)
+    return SVN_NO_ERROR;
+
+  close(sd);
+
+  /* Also ensure that GPG_TTY is set in the evironment.
+   * If it isn't set the user won't be prompted by the agent. */
+  tty_name = getenv("GPG_TTY");
+  *done = (tty_name != NULL);
 
   return SVN_NO_ERROR;
 }