gpg,gpgsm: Handle pkdecrypt responses with/without NUL terminators.
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Tue, 23 Jul 2019 14:07:17 +0000 (10:07 -0400)
committerNIIBE Yutaka <gniibe@fsij.org>
Fri, 26 Jul 2019 00:53:33 +0000 (09:53 +0900)
* g10/call-agent.c (agent_pkdecrypt): accept but do not require
NUL-terminated data from the agent.
* sm/call-agent.c (gpgsm_agent_pkdecrypt): accept but do not require
NUL-terminated data from the agent.

GnuPG-bug-id: 4652
Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
g10/call-agent.c
sm/call-agent.c

index d552383..62568fc 100644 (file)
@@ -2323,25 +2323,28 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
       return err;
     }
 
-  put_membuf (&data, "", 1); /* Make sure it is 0 terminated.  */
   buf = get_membuf (&data, &len);
   if (!buf)
     return gpg_error_from_syserror ();
-  log_assert (len); /* (we forced Nul termination.)  */
 
-  if (*buf != '(')
+  if (len == 0 || *buf != '(')
     {
       xfree (buf);
       return gpg_error (GPG_ERR_INV_SEXP);
     }
 
-  if (len < 13 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)\0" */
+  if (len < 12 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)" */
     {
       xfree (buf);
       return gpg_error (GPG_ERR_INV_SEXP);
     }
-  len -= 10;   /* Count only the data of the second part. */
+  while (buf[len-1] == 0)
+    len--;
+  if (buf[len-1] != ')')
+    return gpg_error (GPG_ERR_INV_SEXP);
+  len--; /* Drop the final close-paren. */
   p = buf + 8; /* Skip leading parenthesis and the value tag. */
+  len -= 8;   /* Count only the data of the second part. */
 
   n = strtoul (p, &endp, 10);
   if (!n || *endp != ':')
index b37c2e5..f9069a3 100644 (file)
@@ -477,7 +477,7 @@ gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
 {
   int rc;
   char line[ASSUAN_LINELENGTH];
-   membuf_t data;
+  membuf_t data;
   struct cipher_parm_s cipher_parm;
   size_t n, len;
   char *p, *buf, *endp;
@@ -528,7 +528,7 @@ gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
       return rc;
     }
 
-  put_membuf (&data, "", 1); /* Make sure it is 0 terminated. */
+  put_membuf (&data, "", 1); /* Make sure it is 0 terminated so we can invoke strtoul safely. */
   buf = get_membuf (&data, &len);
   if (!buf)
     return gpg_error (GPG_ERR_ENOMEM);
@@ -538,8 +538,14 @@ gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
     {
       if (len < 13 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)\0" */
         return gpg_error (GPG_ERR_INV_SEXP);
-      len -= 11;   /* Count only the data of the second part. */
+      /* Trim any spurious trailing Nuls: */
+      while (buf[len-1] == 0)
+        len--;
+      if (buf[len-1] != ')')
+        return gpg_error (GPG_ERR_INV_SEXP);
+      len--; /* Drop the final close-paren: */
       p = buf + 8; /* Skip leading parenthesis and the value tag. */
+      len -= 8; /* Count only the data of the second part. */
     }
   else
     {