[git] Pinentry - branch, master, updated. pinentry-1.0.0-33-g6aafa61

by Daniel Kahn Gillmor cvs at cvs.gnupg.org
Thu Oct 19 09:41:53 CEST 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The standard pinentry collection".

The branch, master has been updated
       via  6aafa61b199ab9091d6c9e190129f2ead2a647c7 (commit)
      from  1f5b351531205214e9513a0aed170660dc822ceb (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 6aafa61b199ab9091d6c9e190129f2ead2a647c7
Author: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
Date:   Sun Feb 5 00:44:12 2017 -0500

    core: Expect (and verify) a uid on "owner" option.
    
    * pinentry/pinentry.h (struct pinentry): Add field 'owner_uid'.
    * pinentry/pinentry.c (pinentry_reset): Handle this new field.
    (get_pid_name_for_uid): New. Atomic check for the base process name
    contingent on process ownership.
    (pinentry_get_title): Only scan for full commandline if the process
    actually belongs to the claimed uid.
    (option_handler): Option "owner" now expects "pid/uid hostname".
    
    --
    
    This requires an update to gpg's use of the "owner" option to emit the
    uid (which will follow shortly).  It is not as atomic as it should be.
    In particular, there's a race condition between reading from
    /proc/PID/status and reading from /proc/PID/cmdline, but it's a much
    smaller race than there was previously.
    
    Werner suggested using a / between pid/uid instead of whitespace.
    
    Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>

diff --git a/pinentry/pinentry.c b/pinentry/pinentry.c
index 2ba4baa..ac3a323 100644
--- a/pinentry/pinentry.c
+++ b/pinentry/pinentry.c
@@ -101,6 +101,7 @@ pinentry_reset (int use_defaults)
   char *default_tt_hide = pinentry.default_tt_hide;
   char *touch_file = pinentry.touch_file;
   unsigned long owner_pid = pinentry.owner_pid;
+  int owner_uid = pinentry.owner_uid;
   char *owner_host = pinentry.owner_host;
 
   /* These options are set from the command line.  Don't reset
@@ -176,6 +177,8 @@ pinentry_reset (int use_defaults)
       pinentry.color_bg = PINENTRY_COLOR_DEFAULT;
       pinentry.color_so = PINENTRY_COLOR_DEFAULT;
       pinentry.color_so_bright = 0;
+
+      pinentry.owner_uid = -1;
     }
   else /* Restore the options.  */
     {
@@ -195,6 +198,7 @@ pinentry_reset (int use_defaults)
       pinentry.default_tt_hide = default_tt_hide;
       pinentry.touch_file = touch_file;
       pinentry.owner_pid = owner_pid;
+      pinentry.owner_uid = owner_uid;
       pinentry.owner_host = owner_host;
 
       pinentry.debug = debug;
@@ -429,6 +433,54 @@ get_cmdline (unsigned long pid)
 }
 
 
+/* Atomically ask the kernel for information about process PID.
+ * Return a malloc'ed copy of the process name as long as the process
+ * uid matches UID.  If it cannot determine that the process has uid
+ * UID, it returns NULL.
+
+ * This is not as informative as get_cmdline, but it verifies that the
+ * process does belong to the user in question.
+ */
+static char *
+get_pid_name_for_uid (unsigned long pid, int uid)
+{
+  char buffer[400];
+  FILE *fp;
+  size_t end, n;
+  char *uidstr;
+
+  snprintf (buffer, sizeof buffer, "/proc/%lu/status", pid);
+  buffer[sizeof buffer - 1] = 0;
+
+  fp = fopen (buffer, "rb");
+  if (!fp)
+    return NULL;
+  n = fread (buffer, 1, sizeof buffer - 1, fp);
+  if (n < sizeof buffer -1 && ferror (fp))
+    {
+      /* Some error occurred.  */
+      fclose (fp);
+      return NULL;
+    }
+  fclose (fp);
+  if (n == 0)
+    return NULL;
+  if (strncmp (buffer, "Name:\t", 6))
+    return NULL;
+  end = strcspn (buffer + 6, "\n") + 6;
+  buffer[end] = 0;
+
+  /* check that uid matches what we expect */
+  uidstr = strstr (buffer + end + 1, "\nUid:\t");
+  if (!uidstr)
+    return NULL;
+  if (atoi (uidstr + 6) != uid)
+    return NULL;
+
+  return strdup (buffer + 6);
+}
+
+
 /* Return a malloced string with the title.  The caller mus free the
  * string.  If no title is available or the title string has an error
  * NULL is returned.  */
@@ -443,16 +495,21 @@ pinentry_get_title (pinentry_t pe)
     {
       char buf[200];
       struct utsname utsbuf;
+      char *pidname = NULL;
       char *cmdline = NULL;
 
       if (pe->owner_host &&
           !uname (&utsbuf) && utsbuf.nodename &&
           !strcmp (utsbuf.nodename, pe->owner_host))
-        cmdline = get_cmdline (pe->owner_pid);
+        {
+          pidname = get_pid_name_for_uid (pe->owner_pid, pe->owner_uid);
+          if (pidname)
+            cmdline = get_cmdline (pe->owner_pid);
+        }
 
-      if (pe->owner_host && cmdline)
+      if (pe->owner_host && (cmdline || pidname))
         snprintf (buf, sizeof buf, "[%lu]@%s (%s)",
-                  pe->owner_pid, pe->owner_host, cmdline);
+                  pe->owner_pid, pe->owner_host, cmdline ? cmdline : pidname);
       else if (pe->owner_host)
         snprintf (buf, sizeof buf, "[%lu]@%s",
                   pe->owner_pid, pe->owner_host);
@@ -460,6 +517,7 @@ pinentry_get_title (pinentry_t pe)
         snprintf (buf, sizeof buf, "[%lu] <unknown host>",
                   pe->owner_pid);
       buf[sizeof buf - 1] = 0;
+      free (pidname);
       free (cmdline);
       title = strdup (buf);
     }
@@ -1027,24 +1085,35 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
 
       free (pinentry.owner_host);
       pinentry.owner_host = NULL;
+      pinentry.owner_uid = -1;
+      pinentry.owner_pid = 0;
 
       errno = 0;
       along = strtol (value, &endp, 10);
-      if (along < 0 || errno)
-        pinentry.owner_pid = 0;
-      else
+      if (along && !errno)
         {
           pinentry.owner_pid = (unsigned long)along;
-          while (endp && *endp == ' ')
-            endp++;
           if (*endp)
             {
-              pinentry.owner_host = strdup (endp);
-              if (pinentry.owner_host)
+              errno = 0;
+              if (*endp == '/') { /* we have a uid */
+                endp++;
+                along = strtol (endp, &endp, 10);
+                if (along >= 0 && !errno)
+                  pinentry.owner_uid = (int)along;
+              }
+              if (endp)
                 {
-                  for (endp=pinentry.owner_host; *endp && *endp != ' '; endp++)
-                    ;
-                  *endp = 0;
+                  while (*endp == ' ')
+                    endp++;
+                  if (*endp)
+                    {
+                      pinentry.owner_host = strdup (endp);
+                      for (endp=pinentry.owner_host;
+                           *endp && *endp != ' '; endp++)
+                        ;
+                      *endp = 0;
+                    }
                 }
             }
         }
diff --git a/pinentry/pinentry.h b/pinentry/pinentry.h
index a4447a8..128331c 100644
--- a/pinentry/pinentry.h
+++ b/pinentry/pinentry.h
@@ -98,7 +98,11 @@ struct pinentry
    * which actually triggered the the pinentry.  For example gpg.  */
   unsigned long owner_pid;
 
-  /* The malloced hostname of the owener or NULL.  */
+  /* The numeric uid (user ID) of the owner process or -1 if not
+   * known. */
+  int owner_uid;
+
+  /* The malloced hostname of the owner or NULL.  */
   char *owner_host;
 
   /* The window ID of the parent window over which the pinentry window

-----------------------------------------------------------------------

Summary of changes:
 pinentry/pinentry.c | 95 +++++++++++++++++++++++++++++++++++++++++++++--------
 pinentry/pinentry.h |  6 +++-
 2 files changed, 87 insertions(+), 14 deletions(-)


hooks/post-receive
-- 
The standard pinentry collection
http://git.gnupg.org




More information about the Gnupg-commits mailing list