1 /* call-pinentry.c - Spawn the pinentry to query stuff from the user
2  * Copyright (C) 2001, 2002, 2004, 2007, 2008,
3  *               2010  Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #ifndef HAVE_W32_SYSTEM
30 # include <sys/wait.h>
31 # include <sys/types.h>
32 # include <signal.h>
33 # include <sys/utsname.h>
34 #endif
35 #include <npth.h>
36 
37 #include "agent.h"
38 #include <assuan.h>
39 #include "../common/sysutils.h"
40 #include "../common/i18n.h"
41 #include "../common/zb32.h"
42 
43 #ifdef _POSIX_OPEN_MAX
44 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
45 #else
46 #define MAX_OPEN_FDS 20
47 #endif
48 
49 
50 /* Because access to the pinentry must be serialized (it is and shall
51    be a global mutually exclusive dialog) we better timeout pending
52    requests after some time.  1 minute seem to be a reasonable
53    time. */
54 #define LOCK_TIMEOUT  (1*60)
55 
56 /* Define the number of bits to use for a generated pin.  The
57  * passphrase will be rendered as zbase32 which results for 150 bits
58  * in a string of 30 characters.  That fits nicely into the 5
59  * character blocking which pinentry can do.  128 bits would actually
60  * be sufficient but can't be formatted nicely. */
61 #define DEFAULT_GENPIN_BITS 150
62 
63 /* The assuan context of the current pinentry. */
64 static assuan_context_t entry_ctx;
65 
66 /* A list of features of the current pinentry.  */
67 static struct
68 {
69   /* The Pinentry support RS+US tabbing.  This means that a RS (0x1e)
70    * starts a new tabbing block in which a US (0x1f) followed by a
71    * colon marks a colon.  A pinentry can use this to pretty print
72    * name value pairs.  */
73   unsigned int tabbing:1;
74 } entry_features;
75 
76 
77 /* A mutex used to serialize access to the pinentry. */
78 static npth_mutex_t entry_lock;
79 
80 /* The thread ID of the popup working thread. */
81 static npth_t  popup_tid;
82 
83 /* A flag used in communication between the popup working thread and
84    its stop function. */
85 static int popup_finished;
86 
87 
88 
89 /* Data to be passed to our callbacks, */
90 struct entry_parm_s
91 {
92   int lines;
93   size_t size;
94   unsigned char *buffer;
95   int status;
96   unsigned int constraints_flags;
97 };
98 
99 
100 
101 
102 /* This function must be called once to initialize this module.  This
103    has to be done before a second thread is spawned.  We can't do the
104    static initialization because Pth emulation code might not be able
105    to do a static init; in particular, it is not possible for W32. */
106 void
initialize_module_call_pinentry(void)107 initialize_module_call_pinentry (void)
108 {
109   static int initialized;
110   int err;
111 
112   if (!initialized)
113     {
114       err = npth_mutex_init (&entry_lock, NULL);
115       if (err)
116 	log_fatal ("error initializing mutex: %s\n", strerror (err));
117 
118       initialized = 1;
119     }
120 }
121 
122 
123 
124 /* This function may be called to print information pertaining to the
125    current state of this module to the log. */
126 void
agent_query_dump_state(void)127 agent_query_dump_state (void)
128 {
129   log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
130             entry_ctx, (long)assuan_get_pid (entry_ctx), (void*)popup_tid);
131 }
132 
133 /* Called to make sure that a popup window owned by the current
134    connection gets closed. */
135 void
agent_reset_query(ctrl_t ctrl)136 agent_reset_query (ctrl_t ctrl)
137 {
138   if (entry_ctx && popup_tid && ctrl->pinentry_active)
139     {
140       agent_popup_message_stop (ctrl);
141     }
142 }
143 
144 
145 /* Unlock the pinentry so that another thread can start one and
146    disconnect that pinentry - we do this after the unlock so that a
147    stalled pinentry does not block other threads.  Fixme: We should
148    have a timeout in Assuan for the disconnect operation. */
149 static gpg_error_t
unlock_pinentry(ctrl_t ctrl,gpg_error_t rc)150 unlock_pinentry (ctrl_t ctrl, gpg_error_t rc)
151 {
152   assuan_context_t ctx = entry_ctx;
153   int err;
154 
155   if (rc)
156     {
157       if (DBG_IPC)
158         log_debug ("error calling pinentry: %s <%s>\n",
159                    gpg_strerror (rc), gpg_strsource (rc));
160 
161       /* Change the source of the error to pinentry so that the final
162          consumer of the error code knows that the problem is with
163          pinentry.  For backward compatibility we do not do that for
164          some common error codes.  */
165       switch (gpg_err_code (rc))
166         {
167         case GPG_ERR_NO_PIN_ENTRY:
168         case GPG_ERR_CANCELED:
169         case GPG_ERR_FULLY_CANCELED:
170         case GPG_ERR_ASS_UNKNOWN_INQUIRE:
171         case GPG_ERR_ASS_TOO_MUCH_DATA:
172         case GPG_ERR_NO_PASSPHRASE:
173         case GPG_ERR_BAD_PASSPHRASE:
174         case GPG_ERR_BAD_PIN:
175           break;
176 
177         case GPG_ERR_CORRUPTED_PROTECTION:
178           /* This comes from gpg-agent.  */
179           break;
180 
181         default:
182           rc = gpg_err_make (GPG_ERR_SOURCE_PINENTRY, gpg_err_code (rc));
183           break;
184         }
185     }
186 
187   if (--ctrl->pinentry_active == 0)
188     {
189       entry_ctx = NULL;
190       err = npth_mutex_unlock (&entry_lock);
191       if (err)
192         {
193           log_error ("failed to release the entry lock: %s\n", strerror (err));
194           if (!rc)
195             rc = gpg_error_from_errno (err);
196         }
197       assuan_release (ctx);
198     }
199   return rc;
200 }
201 
202 
203 /* Helper for at_fork_cb which can also be called by the parent to
204  * show which envvars will be set.  */
205 static void
atfork_core(ctrl_t ctrl,int debug_mode)206 atfork_core (ctrl_t ctrl, int debug_mode)
207 {
208   int iterator = 0;
209   const char *name, *assname, *value;
210 
211   while ((name = session_env_list_stdenvnames (&iterator, &assname)))
212     {
213       /* For all new envvars (!ASSNAME) and the two medium old ones
214        * which do have an assuan name but are conveyed using
215        * environment variables, update the environment of the forked
216        * process.  We also pass DISPLAY despite that --display is also
217        * used when exec-ing the pinentry.  The reason is that for
218        * example the qt5ct tool does not have any arguments and thus
219        * relies on the DISPLAY envvar.  The use case here is a global
220        * envvar like "QT_QPA_PLATFORMTHEME=qt5ct" which for example is
221        * useful when using the Qt pinentry under GNOME or XFCE.
222        */
223       if (!assname
224           || (!opt.keep_display && !strcmp (name, "DISPLAY"))
225           || !strcmp (name, "XAUTHORITY")
226           || !strcmp (name, "PINENTRY_USER_DATA"))
227         {
228           value = session_env_getenv (ctrl->session_env, name);
229           if (value)
230             {
231               if (debug_mode)
232                 log_debug ("pinentry: atfork used setenv(%s,%s)\n",name,value);
233               else
234                 gnupg_setenv (name, value, 1);
235             }
236         }
237     }
238 }
239 
240 
241 /* To make sure we leave no secrets in our image after forking of the
242    pinentry, we use this callback. */
243 static void
atfork_cb(void * opaque,int where)244 atfork_cb (void *opaque, int where)
245 {
246   ctrl_t ctrl = opaque;
247 
248   if (!where)
249     {
250       gcry_control (GCRYCTL_TERM_SECMEM);
251       atfork_core (ctrl, 0);
252     }
253 }
254 
255 
256 /* Status line callback for the FEATURES status.  */
257 static gpg_error_t
getinfo_features_cb(void * opaque,const char * line)258 getinfo_features_cb (void *opaque, const char *line)
259 {
260   const char *args;
261   char **tokens;
262   int i;
263 
264   (void)opaque;
265 
266   if ((args = has_leading_keyword (line, "FEATURES")))
267     {
268       tokens = strtokenize (args, " ");
269       if (!tokens)
270         return gpg_error_from_syserror ();
271       for (i=0; tokens[i]; i++)
272         if (!strcmp (tokens[i], "tabbing"))
273           entry_features.tabbing = 1;
274       xfree (tokens);
275     }
276 
277   return 0;
278 }
279 
280 
281 static gpg_error_t
getinfo_pid_cb(void * opaque,const void * buffer,size_t length)282 getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
283 {
284   unsigned long *pid = opaque;
285   char pidbuf[50];
286 
287   /* There is only the pid in the server's response.  */
288   if (length >= sizeof pidbuf)
289     length = sizeof pidbuf -1;
290   if (length)
291     {
292       strncpy (pidbuf, buffer, length);
293       pidbuf[length] = 0;
294       *pid = strtoul (pidbuf, NULL, 10);
295     }
296   return 0;
297 }
298 
299 
300 /* Fork off the pin entry if this has not already been done.  Note,
301    that this function must always be used to acquire the lock for the
302    pinentry - we will serialize _all_ pinentry calls.
303  */
304 static gpg_error_t
start_pinentry(ctrl_t ctrl)305 start_pinentry (ctrl_t ctrl)
306 {
307   int rc = 0;
308   const char *full_pgmname;
309   const char *pgmname;
310   assuan_context_t ctx;
311   const char *argv[5];
312   assuan_fd_t no_close_list[3];
313   int i;
314   const char *tmpstr;
315   unsigned long pinentry_pid;
316   const char *value;
317   struct timespec abstime;
318   char *flavor_version;
319   int err;
320 
321   if (ctrl->pinentry_active)
322     {
323       /* It's trying to use pinentry recursively.  In this situation,
324          the thread holds ENTRY_LOCK already.  */
325       ctrl->pinentry_active++;
326       return 0;
327     }
328 
329   npth_clock_gettime (&abstime);
330   abstime.tv_sec += LOCK_TIMEOUT;
331   err = npth_mutex_timedlock (&entry_lock, &abstime);
332   if (err)
333     {
334       if (err == ETIMEDOUT)
335 	rc = gpg_error (GPG_ERR_TIMEOUT);
336       else
337 	rc = gpg_error_from_errno (rc);
338       log_error (_("failed to acquire the pinentry lock: %s\n"),
339                  gpg_strerror (rc));
340       return rc;
341     }
342 
343   if (entry_ctx)
344     return 0;
345 
346   if (opt.verbose)
347     log_info ("starting a new PIN Entry\n");
348 
349 #ifdef HAVE_W32_SYSTEM
350   fflush (stdout);
351   fflush (stderr);
352 #endif
353   if (fflush (NULL))
354     {
355 #ifndef HAVE_W32_SYSTEM
356       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
357 #endif
358       log_error ("error flushing pending output: %s\n", strerror (errno));
359       /* At least Windows XP fails here with EBADF.  According to docs
360          and Wine an fflush(NULL) is the same as _flushall.  However
361          the Wine implementation does not flush stdin,stdout and stderr
362          - see above.  Let's try to ignore the error. */
363 #ifndef HAVE_W32_SYSTEM
364       return unlock_pinentry (ctrl, tmperr);
365 #endif
366     }
367 
368   full_pgmname = opt.pinentry_program;
369   if (!full_pgmname || !*full_pgmname)
370     full_pgmname = gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY);
371   if ( !(pgmname = strrchr (full_pgmname, '/')))
372     pgmname = full_pgmname;
373   else
374     pgmname++;
375 
376   /* OS X needs the entire file name in argv[0], so that it can locate
377      the resource bundle.  For other systems we stick to the usual
378      convention of supplying only the name of the program.  */
379 #ifdef __APPLE__
380   argv[0] = full_pgmname;
381 #else /*!__APPLE__*/
382   argv[0] = pgmname;
383 #endif /*__APPLE__*/
384 
385   if (!opt.keep_display
386       && (value = session_env_getenv (ctrl->session_env, "DISPLAY")))
387     {
388       argv[1] = "--display";
389       argv[2] = value;
390       argv[3] = NULL;
391     }
392   else
393     argv[1] = NULL;
394 
395   i=0;
396   if (!opt.running_detached)
397     {
398       if (log_get_fd () != -1)
399         no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
400       no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
401     }
402   no_close_list[i] = ASSUAN_INVALID_FD;
403 
404   rc = assuan_new (&ctx);
405   if (rc)
406     {
407       log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
408       return rc;
409     }
410 
411   ctrl->pinentry_active = 1;
412   entry_ctx = ctx;
413 
414   /* We don't want to log the pinentry communication to make the logs
415      easier to read.  We might want to add a new debug option to enable
416      pinentry logging.  */
417 #ifdef ASSUAN_NO_LOGGING
418   assuan_set_flag (ctx, ASSUAN_NO_LOGGING, !opt.debug_pinentry);
419 #endif
420 
421   /* Connect to the pinentry and perform initial handshaking.  Note
422      that atfork is used to change the environment for pinentry.  We
423      start the server in detached mode to suppress the console window
424      under Windows.  */
425   rc = assuan_pipe_connect (entry_ctx, full_pgmname, argv,
426 			    no_close_list, atfork_cb, ctrl,
427 			    ASSUAN_PIPE_CONNECT_DETACHED);
428   if (rc)
429     {
430       log_error ("can't connect to the PIN entry module '%s': %s\n",
431                  full_pgmname, gpg_strerror (rc));
432       return unlock_pinentry (ctrl, gpg_error (GPG_ERR_NO_PIN_ENTRY));
433     }
434 
435   if (DBG_IPC)
436     log_debug ("connection to PIN entry established\n");
437 
438   if (opt.debug_pinentry)
439     atfork_core (ctrl, 1); /* Just show the envvars set after the fork.  */
440 
441   value = session_env_getenv (ctrl->session_env, "PINENTRY_USER_DATA");
442   if (value != NULL)
443     {
444       char *optstr;
445       if (asprintf (&optstr, "OPTION pinentry-user-data=%s", value) < 0 )
446         return unlock_pinentry (ctrl, out_of_core ());
447       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
448 			    NULL);
449       xfree (optstr);
450       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
451         return unlock_pinentry (ctrl, rc);
452     }
453 
454   rc = assuan_transact (entry_ctx,
455                         opt.no_grab? "OPTION no-grab":"OPTION grab",
456                         NULL, NULL, NULL, NULL, NULL, NULL);
457   if (rc)
458     {
459       if (gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED
460           || gpg_err_code (rc) == GPG_ERR_UNKNOWN_OPTION)
461         {
462           if (opt.verbose)
463             log_info ("Option no-grab/grab is ignored by pinentry.\n");
464           /* Keep going even if the feature is not supported.  */
465         }
466       else
467         return unlock_pinentry (ctrl, rc);
468     }
469 
470   value = session_env_getenv (ctrl->session_env, "GPG_TTY");
471   if (value)
472     {
473       char *optstr;
474       if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
475         return unlock_pinentry (ctrl, out_of_core ());
476       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
477 			    NULL);
478       xfree (optstr);
479       if (rc)
480         return unlock_pinentry (ctrl, rc);
481     }
482   value = session_env_getenv (ctrl->session_env, "TERM");
483   if (value && *value)
484     {
485       char *optstr;
486       if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
487         return unlock_pinentry (ctrl, out_of_core ());
488       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
489 			    NULL);
490       xfree (optstr);
491       if (rc)
492         return unlock_pinentry (ctrl, rc);
493     }
494   if (ctrl->lc_ctype)
495     {
496       char *optstr;
497       if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
498         return unlock_pinentry (ctrl, out_of_core ());
499       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
500 			    NULL);
501       xfree (optstr);
502       if (rc)
503         return unlock_pinentry (ctrl, rc);
504     }
505   if (ctrl->lc_messages)
506     {
507       char *optstr;
508       if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
509         return unlock_pinentry (ctrl, out_of_core ());
510       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
511 			    NULL);
512       xfree (optstr);
513       if (rc)
514         return unlock_pinentry (ctrl, rc);
515     }
516 
517 
518   if (opt.allow_external_cache)
519     {
520       /* Indicate to the pinentry that it may read from an external cache.
521 
522          It is essential that the pinentry respect this.  If the
523          cached password is not up to date and retry == 1, then, using
524          a version of GPG Agent that doesn't support this, won't issue
525          another pin request and the user won't get a chance to
526          correct the password.  */
527       rc = assuan_transact (entry_ctx, "OPTION allow-external-password-cache",
528                             NULL, NULL, NULL, NULL, NULL, NULL);
529       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
530         return unlock_pinentry (ctrl, rc);
531     }
532 
533   if (opt.allow_emacs_pinentry)
534     {
535       /* Indicate to the pinentry that it may read passphrase through
536 	 Emacs minibuffer, if possible.  */
537       rc = assuan_transact (entry_ctx, "OPTION allow-emacs-prompt",
538                             NULL, NULL, NULL, NULL, NULL, NULL);
539       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
540         return unlock_pinentry (ctrl, rc);
541     }
542 
543 
544   {
545     /* Provide a few default strings for use by the pinentries.  This
546      * may help a pinentry to avoid implementing localization code.
547      * Note that gpg-agent has been set to utf-8 so that the strings
548      * are in the expected encoding.  */
549     static const struct { const char *key, *value; int what; } tbl[] = {
550       /* TRANSLATORS: These are labels for buttons etc as used in
551        * Pinentries.  In your translation copy the text before the
552        * second vertical bar verbatim; translate only the following
553        * text.  An underscore indicates that the next letter should be
554        * used as an accelerator.  Double the underscore to have
555        * pinentry display a literal underscore.   */
556       { "ok",     N_("|pinentry-label|_OK") },
557       { "cancel", N_("|pinentry-label|_Cancel") },
558       { "yes",    N_("|pinentry-label|_Yes") },
559       { "no",     N_("|pinentry-label|_No") },
560       { "prompt", N_("|pinentry-label|PIN:") },
561       { "pwmngr", N_("|pinentry-label|_Save in password manager"), 1 },
562       { "cf-visi",N_("Do you really want to make your "
563                      "passphrase visible on the screen?") },
564       { "tt-visi",N_("|pinentry-tt|Make passphrase visible") },
565       { "tt-hide",N_("|pinentry-tt|Hide passphrase") },
566       { "capshint", N_("Caps Lock is on") },
567       { NULL, NULL}
568     };
569     char *optstr;
570     int idx;
571     const char *s, *s2;
572 
573     for (idx=0; tbl[idx].key; idx++)
574       {
575         if (!opt.allow_external_cache && tbl[idx].what == 1)
576           continue;  /* No need for it.  */
577         s = L_(tbl[idx].value);
578         if (*s == '|' && (s2=strchr (s+1,'|')))
579           s = s2+1;
580         if (asprintf (&optstr, "OPTION default-%s=%s", tbl[idx].key, s) < 0 )
581           return unlock_pinentry (ctrl, out_of_core ());
582         assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
583                          NULL);
584         xfree (optstr);
585       }
586   }
587 
588   /* Tell the pinentry that we would prefer that the given character
589      is used as the invisible character by the entry widget.  */
590   if (opt.pinentry_invisible_char)
591     {
592       char *optstr;
593       if ((optstr = xtryasprintf ("OPTION invisible-char=%s",
594                                   opt.pinentry_invisible_char)))
595         {
596           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
597                            NULL);
598           /* We ignore errors because this is just a fancy thing and
599              older pinentries do not support this feature.  */
600           xfree (optstr);
601         }
602     }
603 
604   if (opt.pinentry_timeout)
605     {
606       char *optstr;
607       if ((optstr = xtryasprintf ("SETTIMEOUT %lu", opt.pinentry_timeout)))
608         {
609           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
610                            NULL);
611           /* We ignore errors because this is just a fancy thing.  */
612           xfree (optstr);
613         }
614     }
615 
616   /* Tell the pinentry the name of a file it shall touch after having
617      messed with the tty.  This is optional and only supported by
618      newer pinentries and thus we do no error checking. */
619   tmpstr = opt.pinentry_touch_file;
620   if (tmpstr && !strcmp (tmpstr, "/dev/null"))
621     tmpstr = NULL;
622   else if (!tmpstr)
623     tmpstr = get_agent_socket_name ();
624   if (tmpstr)
625     {
626       char *optstr;
627 
628       if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
629         ;
630       else
631         {
632           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
633                            NULL);
634           xfree (optstr);
635         }
636     }
637 
638   /* Tell Pinentry about our client.  */
639   if (ctrl->client_pid)
640     {
641       char *optstr;
642       const char *nodename = "";
643 
644 #ifndef HAVE_W32_SYSTEM
645       struct utsname utsbuf;
646       if (!uname (&utsbuf))
647         nodename = utsbuf.nodename;
648 #endif /*!HAVE_W32_SYSTEM*/
649 
650       if ((optstr = xtryasprintf ("OPTION owner=%lu/%d %s",
651                                   ctrl->client_pid, ctrl->client_uid,
652                                   nodename)))
653         {
654           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
655                            NULL);
656           /* We ignore errors because this is just a fancy thing and
657              older pinentries do not support this feature.  */
658           xfree (optstr);
659         }
660     }
661 
662 
663   /* Ask the pinentry for its version and flavor and store that as a
664    * string in MB.  This information is useful for helping users to
665    * figure out Pinentry problems.  Note that "flavor" may also return
666    * a status line with the features; we use a dedicated handler for
667    * that.  */
668   {
669     membuf_t mb;
670 
671     init_membuf (&mb, 256);
672     if (assuan_transact (entry_ctx, "GETINFO flavor",
673                          put_membuf_cb, &mb,
674                          NULL, NULL,
675                          getinfo_features_cb, NULL))
676       put_membuf_str (&mb, "unknown");
677     put_membuf_str (&mb, " ");
678     if (assuan_transact (entry_ctx, "GETINFO version",
679                          put_membuf_cb, &mb, NULL, NULL, NULL, NULL))
680       put_membuf_str (&mb, "unknown");
681     put_membuf_str (&mb, " ");
682     if (assuan_transact (entry_ctx, "GETINFO ttyinfo",
683                          put_membuf_cb, &mb, NULL, NULL, NULL, NULL))
684       put_membuf_str (&mb, "? ? ?");
685     put_membuf (&mb, "", 1);
686     flavor_version = get_membuf (&mb, NULL);
687   }
688 
689 
690   /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
691      it will send the pid back and we will use an inquire to notify
692      our client.  The client may answer the inquiry either with END or
693      with CAN to cancel the pinentry. */
694   rc = assuan_transact (entry_ctx, "GETINFO pid",
695                         getinfo_pid_cb, &pinentry_pid,
696                         NULL, NULL, NULL, NULL);
697   if (rc)
698     {
699       log_info ("You may want to update to a newer pinentry\n");
700       rc = 0;
701     }
702   else if (!rc && pinentry_pid == (unsigned long)(-1L))
703     log_error ("pinentry did not return a PID\n");
704   else
705     {
706       rc = agent_inq_pinentry_launched (ctrl, pinentry_pid, flavor_version);
707       if (gpg_err_code (rc) == GPG_ERR_CANCELED
708           || gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
709         return unlock_pinentry (ctrl, gpg_err_make (GPG_ERR_SOURCE_DEFAULT,
710                                                     gpg_err_code (rc)));
711       rc = 0;
712     }
713 
714   xfree (flavor_version);
715 
716   return rc;
717 }
718 
719 
720 /* Returns True if the pinentry is currently active. If WAITSECONDS is
721    greater than zero the function will wait for this many seconds
722    before returning.  */
723 int
pinentry_active_p(ctrl_t ctrl,int waitseconds)724 pinentry_active_p (ctrl_t ctrl, int waitseconds)
725 {
726   int err;
727   (void)ctrl;
728 
729   if (waitseconds > 0)
730     {
731       struct timespec abstime;
732       int rc;
733 
734       npth_clock_gettime (&abstime);
735       abstime.tv_sec += waitseconds;
736       err = npth_mutex_timedlock (&entry_lock, &abstime);
737       if (err)
738         {
739           if (err == ETIMEDOUT)
740             rc = gpg_error (GPG_ERR_TIMEOUT);
741           else
742             rc = gpg_error (GPG_ERR_INTERNAL);
743           return rc;
744         }
745     }
746   else
747     {
748       err = npth_mutex_trylock (&entry_lock);
749       if (err)
750         return gpg_error (GPG_ERR_LOCKED);
751     }
752 
753   err = npth_mutex_unlock (&entry_lock);
754   if (err)
755     log_error ("failed to release the entry lock at %d: %s\n", __LINE__,
756 	       strerror (errno));
757   return 0;
758 }
759 
760 
761 static gpg_error_t
getpin_cb(void * opaque,const void * buffer,size_t length)762 getpin_cb (void *opaque, const void *buffer, size_t length)
763 {
764   struct entry_parm_s *parm = opaque;
765 
766   if (!buffer)
767     return 0;
768 
769   /* we expect the pin to fit on one line */
770   if (parm->lines || length >= parm->size)
771     return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
772 
773   /* fixme: we should make sure that the assuan buffer is allocated in
774      secure memory or read the response byte by byte */
775   memcpy (parm->buffer, buffer, length);
776   parm->buffer[length] = 0;
777   parm->lines++;
778   return 0;
779 }
780 
781 
782 static int
all_digitsp(const char * s)783 all_digitsp( const char *s)
784 {
785   for (; *s && *s >= '0' && *s <= '9'; s++)
786     ;
787   return !*s;
788 }
789 
790 
791 /* Return a new malloced string by unescaping the string S.  Escaping
792    is percent escaping and '+'/space mapping.  A binary Nul will
793    silently be replaced by a 0xFF.  Function returns NULL to indicate
794    an out of memory status.  Parsing stops at the end of the string or
795    a white space character. */
796 static char *
unescape_passphrase_string(const unsigned char * s)797 unescape_passphrase_string (const unsigned char *s)
798 {
799   char *buffer, *d;
800 
801   buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
802   if (!buffer)
803     return NULL;
804   while (*s && !spacep (s))
805     {
806       if (*s == '%' && s[1] && s[2])
807         {
808           s++;
809           *d = xtoi_2 (s);
810           if (!*d)
811             *d = '\xff';
812           d++;
813           s += 2;
814         }
815       else if (*s == '+')
816         {
817           *d++ = ' ';
818           s++;
819         }
820       else
821         *d++ = *s++;
822     }
823   *d = 0;
824   return buffer;
825 }
826 
827 
828 /* Estimate the quality of the passphrase PW and return a value in the
829    range 0..100.  */
830 static int
estimate_passphrase_quality(const char * pw)831 estimate_passphrase_quality (const char *pw)
832 {
833   int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
834   int length;
835   const char *s;
836 
837   if (goodlength < 1)
838     return 0;
839 
840   for (length = 0, s = pw; *s; s++)
841     if (!spacep (s))
842       length ++;
843 
844   if (length > goodlength)
845     return 100;
846   return ((length*10) / goodlength)*10;
847 }
848 
849 
850 /* Generate a random passphrase in zBase32 encoding (RFC-6189) to be
851  * used by Pinentry to suggest a passphrase.  */
852 static char *
generate_pin(void)853 generate_pin (void)
854 {
855   unsigned int nbits = opt.min_passphrase_len * 8;
856   size_t nbytes;
857   void *rand;
858   char *generated;
859 
860   if (nbits < 128)
861     nbits = DEFAULT_GENPIN_BITS;
862 
863   nbytes = (nbits + 7) / 8;
864 
865   rand = gcry_random_bytes_secure (nbytes, GCRY_STRONG_RANDOM);
866   if (!rand)
867     {
868       log_error ("failed to generate random pin\n");
869       return NULL;
870     }
871 
872   generated = zb32_encode (rand, nbits);
873   gcry_free (rand);
874   return generated;
875 }
876 
877 
878 /* Handle inquiries. */
879 struct inq_cb_parm_s
880 {
881   assuan_context_t ctx;
882   unsigned int flags;  /* CHECK_CONSTRAINTS_... */
883   int genpinhash_valid;
884   char genpinhash[32]; /* Hash of the last generated pin.  */
885 };
886 
887 
888 /* Return true if PIN is indentical to the last generated pin.  */
889 static int
is_generated_pin(struct inq_cb_parm_s * parm,const char * pin)890 is_generated_pin (struct inq_cb_parm_s *parm, const char *pin)
891 {
892   char hashbuf[32];
893 
894   if (!parm->genpinhash_valid)
895     return 0;
896   if (!*pin)
897     return 0;
898   /* Note that we compare the hash so that we do not need to save the
899    * generated PIN longer than needed. */
900   gcry_md_hash_buffer (GCRY_MD_SHA256, hashbuf, pin, strlen (pin));
901 
902   if (!memcmp (hashbuf, parm->genpinhash, 32))
903     return 1; /* yes, it is the same.  */
904 
905   return 0;
906 }
907 
908 
909 static gpg_error_t
inq_cb(void * opaque,const char * line)910 inq_cb (void *opaque, const char *line)
911 {
912   struct inq_cb_parm_s *parm = opaque;
913   gpg_error_t err;
914   const char *s;
915   char *pin;
916 
917   if ((s = has_leading_keyword (line, "QUALITY")))
918     {
919       char numbuf[20];
920       int percent;
921 
922       pin = unescape_passphrase_string (s);
923       if (!pin)
924         err = gpg_error_from_syserror ();
925       else
926         {
927           percent = estimate_passphrase_quality (pin);
928           if (check_passphrase_constraints (NULL, pin, parm->flags, NULL))
929             percent = -percent;
930           snprintf (numbuf, sizeof numbuf, "%d", percent);
931           err = assuan_send_data (parm->ctx, numbuf, strlen (numbuf));
932           xfree (pin);
933         }
934     }
935   else if ((s = has_leading_keyword (line, "CHECKPIN")))
936     {
937       char *errtext = NULL;
938       size_t errtextlen;
939 
940       if (!opt.enforce_passphrase_constraints)
941         {
942           log_error ("unexpected inquiry 'CHECKPIN' without enforced "
943                      "passphrase constraints\n");
944           err = gpg_error (GPG_ERR_ASS_UNEXPECTED_CMD);
945           goto leave;
946         }
947 
948       pin = unescape_passphrase_string (s);
949       if (!pin)
950         err = gpg_error_from_syserror ();
951       else
952         {
953           if (!is_generated_pin (parm, pin)
954               && check_passphrase_constraints (NULL, pin,parm->flags, &errtext))
955             {
956               if (errtext)
957                 {
958                   /* Unescape the percent-escaped errtext because
959                      assuan_send_data escapes it again. */
960                   errtextlen = percent_unescape_inplace (errtext, 0);
961                   err = assuan_send_data (parm->ctx, errtext, errtextlen);
962                 }
963               else
964                 {
965                   log_error ("passphrase check failed without error text\n");
966                   err = gpg_error (GPG_ERR_GENERAL);
967                 }
968             }
969           else
970             {
971               err = assuan_send_data (parm->ctx, NULL, 0);
972             }
973           xfree (errtext);
974           xfree (pin);
975         }
976     }
977   else if ((s = has_leading_keyword (line, "GENPIN")))
978     {
979       int wasconf;
980 
981       parm->genpinhash_valid = 0;
982       pin = generate_pin ();
983       if (!pin)
984         {
985           log_error ("failed to generate a passphrase\n");
986           err = gpg_error (GPG_ERR_GENERAL);
987           goto leave;
988         }
989       wasconf = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
990       assuan_begin_confidential (parm->ctx);
991       err = assuan_send_data (parm->ctx, pin, strlen (pin));
992       if (!wasconf)
993         assuan_end_confidential (parm->ctx);
994       gcry_md_hash_buffer (GCRY_MD_SHA256, parm->genpinhash, pin, strlen (pin));
995       parm->genpinhash_valid = 1;
996       xfree (pin);
997     }
998   else
999     {
1000       log_error ("unsupported inquiry '%s' from pinentry\n", line);
1001       err = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
1002     }
1003 
1004  leave:
1005   return err;
1006 }
1007 
1008 
1009 /* Helper to setup pinentry for genpin action. */
1010 static gpg_error_t
setup_genpin(ctrl_t ctrl)1011 setup_genpin (ctrl_t ctrl)
1012 {
1013   gpg_error_t err;
1014   char line[ASSUAN_LINELENGTH];
1015   char *tmpstr, *tmpstr2;
1016   const char *tooltip;
1017 
1018   (void)ctrl;
1019 
1020   /* TRANSLATORS: This string is displayed by Pinentry as the label
1021      for generating a passphrase.  */
1022   tmpstr = try_percent_escape (L_("Suggest"), "\t\r\n\f\v");
1023   snprintf (line, DIM(line), "SETGENPIN %s", tmpstr? tmpstr:"");
1024   xfree (tmpstr);
1025   err = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1026   if (gpg_err_code (err) == 103 /*(Old assuan error code)*/
1027       || gpg_err_code (err) == GPG_ERR_ASS_UNKNOWN_CMD)
1028     ; /* Ignore Unknown Command from old Pinentry versions.  */
1029   else if (err)
1030     return err;
1031 
1032   tmpstr2 = gnupg_get_help_string ("pinentry.genpin.tooltip", 0);
1033   if (tmpstr2)
1034     tooltip = tmpstr2;
1035   else
1036     {
1037       /* TRANSLATORS: This string is a tooltip, shown by pinentry when
1038          hovering over the generate button.  Please use an appropriate
1039          string to describe what this is about.  The length of the
1040          tooltip is limited to about 900 characters.  If you do not
1041          translate this entry, a default English text (see source)
1042          will be used.  The strcmp thingy is there to detect a
1043          non-translated string.  */
1044       tooltip = L_("pinentry.genpin.tooltip");
1045       if (!strcmp ("pinentry.genpin.tooltip", tooltip))
1046         tooltip = "Suggest a random passphrase.";
1047     }
1048   tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
1049   xfree (tmpstr2);
1050   snprintf (line, DIM(line), "SETGENPIN_TT %s", tmpstr? tmpstr:"");
1051   xfree (tmpstr);
1052   err = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1053   if (gpg_err_code (err) == 103 /*(Old assuan error code)*/
1054           || gpg_err_code (err) == GPG_ERR_ASS_UNKNOWN_CMD)
1055     ; /* Ignore Unknown Command from old pinentry versions.  */
1056   else if (err)
1057     return err;
1058 
1059   return 0;
1060 }
1061 
1062 
1063 /* Helper to setup pinentry for formatted passphrase. */
1064 static gpg_error_t
setup_formatted_passphrase(ctrl_t ctrl)1065 setup_formatted_passphrase (ctrl_t ctrl)
1066 {
1067   static const struct { const char *key, *help_id, *value; } tbl[] = {
1068     /* TRANSLATORS: This is a text shown by pinentry if the option
1069         for formatted passphrase is enabled.  The length is
1070         limited to about 900 characters.  */
1071     { "hint",  "pinentry.formatted_passphrase.hint",
1072       N_("Note: The blanks are not part of the passphrase.") },
1073     { NULL, NULL }
1074   };
1075 
1076   gpg_error_t rc;
1077   char line[ASSUAN_LINELENGTH];
1078   int idx;
1079   char *tmpstr;
1080   const char *s;
1081   char *escapedstr;
1082 
1083   (void)ctrl;
1084 
1085   if (opt.pinentry_formatted_passphrase)
1086     {
1087       snprintf (line, DIM(line), "OPTION formatted-passphrase");
1088       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL,
1089                             NULL);
1090       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
1091         return rc;
1092 
1093       for (idx=0; tbl[idx].key; idx++)
1094         {
1095           tmpstr = gnupg_get_help_string (tbl[idx].help_id, 0);
1096           if (tmpstr)
1097             s = tmpstr;
1098           else
1099             s = L_(tbl[idx].value);
1100           escapedstr = try_percent_escape (s, "\t\r\n\f\v");
1101           xfree (tmpstr);
1102           if (escapedstr && *escapedstr)
1103             {
1104               snprintf (line, DIM(line), "OPTION formatted-passphrase-%s=%s",
1105                         tbl[idx].key, escapedstr);
1106               rc = assuan_transact (entry_ctx, line,
1107                                     NULL, NULL, NULL, NULL, NULL, NULL);
1108             }
1109           else
1110             rc = 0;
1111           xfree (escapedstr);
1112           if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
1113             return rc;
1114         }
1115     }
1116 
1117   return 0;
1118 }
1119 
1120 
1121 /* Helper to setup pinentry for enforced passphrase constraints. */
1122 static gpg_error_t
setup_enforced_constraints(ctrl_t ctrl)1123 setup_enforced_constraints (ctrl_t ctrl)
1124 {
1125   static const struct { const char *key, *help_id, *value; } tbl[] = {
1126     { "hint-short", "pinentry.constraints.hint.short", NULL },
1127     { "hint-long",  "pinentry.constraints.hint.long", NULL },
1128     /* TRANSLATORS: This is a text shown by pinentry as title of a dialog
1129        telling the user that the entered new passphrase does not satisfy
1130        the passphrase constraints.  Please keep it short. */
1131     { "error-title", NULL, N_("Passphrase Not Allowed") },
1132     { NULL, NULL }
1133   };
1134 
1135   gpg_error_t rc;
1136   char line[ASSUAN_LINELENGTH];
1137   int idx;
1138   char *tmpstr;
1139   const char *s;
1140   char *escapedstr;
1141 
1142   (void)ctrl;
1143 
1144   if (opt.enforce_passphrase_constraints)
1145     {
1146       snprintf (line, DIM(line), "OPTION constraints-enforce");
1147       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL,
1148                             NULL);
1149       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
1150         return rc;
1151 
1152       for (idx=0; tbl[idx].key; idx++)
1153         {
1154           tmpstr = gnupg_get_help_string (tbl[idx].help_id, 0);
1155           if (tmpstr)
1156             s = tmpstr;
1157           else if (tbl[idx].value)
1158             s = L_(tbl[idx].value);
1159           else
1160             {
1161               log_error ("no help string found for %s\n", tbl[idx].help_id);
1162               continue;
1163             }
1164           escapedstr = try_percent_escape (s, "\t\r\n\f\v");
1165           xfree (tmpstr);
1166           if (escapedstr && *escapedstr)
1167             {
1168               snprintf (line, DIM(line), "OPTION constraints-%s=%s",
1169                         tbl[idx].key, escapedstr);
1170               rc = assuan_transact (entry_ctx, line,
1171                                     NULL, NULL, NULL, NULL, NULL, NULL);
1172             }
1173           else
1174             rc = 0;  /* Ignore an empty string (would give an IPC error).  */
1175           xfree (escapedstr);
1176           if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
1177             return rc;
1178         }
1179     }
1180 
1181   return 0;
1182 }
1183 
1184 
1185 /* Helper for agent_askpin and agent_get_passphrase.  */
1186 static gpg_error_t
setup_qualitybar(ctrl_t ctrl)1187 setup_qualitybar (ctrl_t ctrl)
1188 {
1189   int rc;
1190   char line[ASSUAN_LINELENGTH];
1191   char *tmpstr, *tmpstr2;
1192   const char *tooltip;
1193 
1194   (void)ctrl;
1195 
1196   /* TRANSLATORS: This string is displayed by Pinentry as the label
1197      for the quality bar.  */
1198   tmpstr = try_percent_escape (L_("Quality:"), "\t\r\n\f\v");
1199   snprintf (line, DIM(line), "SETQUALITYBAR %s", tmpstr? tmpstr:"");
1200   xfree (tmpstr);
1201   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1202   if (rc == 103 /*(Old assuan error code)*/
1203       || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
1204     ; /* Ignore Unknown Command from old Pinentry versions.  */
1205   else if (rc)
1206     return rc;
1207 
1208   tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
1209   if (tmpstr2)
1210     tooltip = tmpstr2;
1211   else
1212     {
1213       /* TRANSLATORS: This string is a tooltip, shown by pinentry when
1214          hovering over the quality bar.  Please use an appropriate
1215          string to describe what this is about.  The length of the
1216          tooltip is limited to about 900 characters.  If you do not
1217          translate this entry, a default english text (see source)
1218          will be used. */
1219       tooltip =  L_("pinentry.qualitybar.tooltip");
1220       if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
1221         tooltip = ("The quality of the text entered above.\n"
1222                    "Please ask your administrator for "
1223                    "details about the criteria.");
1224     }
1225   tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
1226   xfree (tmpstr2);
1227   snprintf (line, DIM(line), "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
1228   xfree (tmpstr);
1229   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1230   if (rc == 103 /*(Old assuan error code)*/
1231           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
1232     ; /* Ignore Unknown Command from old pinentry versions.  */
1233   else if (rc)
1234     return rc;
1235 
1236   return 0;
1237 }
1238 
1239 /* Check the button_info line for a close action.  Also check for the
1240    PIN_REPEATED flag.  */
1241 static gpg_error_t
pinentry_status_cb(void * opaque,const char * line)1242 pinentry_status_cb (void *opaque, const char *line)
1243 {
1244   unsigned int *flag = opaque;
1245   const char *args;
1246 
1247   if ((args = has_leading_keyword (line, "BUTTON_INFO")))
1248     {
1249       if (!strcmp (args, "close"))
1250         *flag |= PINENTRY_STATUS_CLOSE_BUTTON;
1251     }
1252   else if (has_leading_keyword (line, "PIN_REPEATED"))
1253     {
1254       *flag |= PINENTRY_STATUS_PIN_REPEATED;
1255     }
1256   else if (has_leading_keyword (line, "PASSWORD_FROM_CACHE"))
1257     {
1258       *flag |= PINENTRY_STATUS_PASSWORD_FROM_CACHE;
1259     }
1260 
1261   return 0;
1262 }
1263 
1264 
1265 /* Build a SETDESC command line.  This is a dedicated function so that
1266  * it can remove control characters which are not supported by the
1267  * current Pinentry.  */
1268 static void
build_cmd_setdesc(char * line,size_t linelen,const char * desc)1269 build_cmd_setdesc (char *line, size_t linelen, const char *desc)
1270 {
1271   char *src, *dst;
1272 
1273   snprintf (line, linelen, "SETDESC %s", desc);
1274   if (!entry_features.tabbing)
1275     {
1276       /* Remove RS and US.  */
1277       for (src=dst=line; *src; src++)
1278         if (!strchr ("\x1e\x1f", *src))
1279           *dst++ = *src;
1280       *dst = 0;
1281     }
1282 }
1283 
1284 
1285 
1286 /* Watch the socket's EOF condition, while checking finish of
1287    foreground thread.  When EOF condition is detected, terminate
1288    the pinentry process behind the assuan pipe.
1289  */
1290 static void *
watch_sock(void * arg)1291 watch_sock (void *arg)
1292 {
1293   pid_t pid = assuan_get_pid (entry_ctx);
1294 
1295   while (1)
1296     {
1297       int err;
1298       fd_set fdset;
1299       struct timeval timeout = { 0, 500000 };
1300       gnupg_fd_t sock = *(gnupg_fd_t *)arg;
1301 
1302       if (sock == GNUPG_INVALID_FD)
1303         return NULL;
1304 
1305       FD_ZERO (&fdset);
1306       FD_SET (FD2INT (sock), &fdset);
1307       err = npth_select (FD2INT (sock)+1, &fdset, NULL, NULL, &timeout);
1308 
1309       if (err < 0)
1310         {
1311           if (errno == EINTR)
1312             continue;
1313           else
1314             return NULL;
1315         }
1316 
1317       /* Possibly, it's EOF.  */
1318       if (err > 0)
1319         break;
1320     }
1321 
1322   if (pid == (pid_t)(-1))
1323     ; /* No pid available can't send a kill. */
1324 #ifdef HAVE_W32_SYSTEM
1325   /* Older versions of assuan set PID to 0 on Windows to indicate an
1326      invalid value.  */
1327   else if (pid != (pid_t) INVALID_HANDLE_VALUE && pid != 0)
1328     TerminateProcess ((HANDLE)pid, 1);
1329 #else
1330   else if (pid > 0)
1331     kill (pid, SIGINT);
1332 #endif
1333 
1334   return NULL;
1335 }
1336 
1337 
1338 static gpg_error_t
watch_sock_start(gnupg_fd_t * sock_p,npth_t * thread_p)1339 watch_sock_start (gnupg_fd_t *sock_p, npth_t *thread_p)
1340 {
1341   npth_attr_t tattr;
1342   int err;
1343 
1344   err = npth_attr_init (&tattr);
1345   if (err)
1346     {
1347       log_error ("do_getpin: error npth_attr_init: %s\n", strerror (err));
1348       return gpg_error_from_errno (err);
1349     }
1350   npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
1351 
1352   err = npth_create (thread_p, &tattr, watch_sock, sock_p);
1353   npth_attr_destroy (&tattr);
1354   if (err)
1355     {
1356       log_error ("do_getpin: error spawning thread: %s\n", strerror (err));
1357       return gpg_error_from_errno (err);
1358     }
1359 
1360   return 0;
1361 }
1362 
1363 static void
watch_sock_end(gnupg_fd_t * sock_p,npth_t * thread_p)1364 watch_sock_end (gnupg_fd_t *sock_p, npth_t *thread_p)
1365 {
1366   int err;
1367 
1368   *sock_p = GNUPG_INVALID_FD;
1369   err = npth_join (*thread_p, NULL);
1370   if (err)
1371     log_error ("watch_sock_end: error joining thread: %s\n", strerror (err));
1372 }
1373 
1374 
1375 /* Ask pinentry to get a pin by "GETPIN" command, spawning a thread
1376    detecting the socket's EOF.
1377  */
1378 static gpg_error_t
do_getpin(ctrl_t ctrl,struct entry_parm_s * parm)1379 do_getpin (ctrl_t ctrl, struct entry_parm_s *parm)
1380 {
1381   gpg_error_t rc;
1382   gnupg_fd_t sock_watched = ctrl->thread_startup.fd;
1383   npth_t thread;
1384   int wasconf;
1385   struct inq_cb_parm_s inq_cb_parm;
1386 
1387   rc = watch_sock_start (&sock_watched, &thread);
1388   if (rc)
1389     return rc;
1390 
1391   inq_cb_parm.ctx = entry_ctx;
1392   inq_cb_parm.flags = parm->constraints_flags;
1393   inq_cb_parm.genpinhash_valid = 0;
1394 
1395   wasconf = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
1396   assuan_begin_confidential (entry_ctx);
1397   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, parm,
1398                         inq_cb, &inq_cb_parm,
1399                         pinentry_status_cb, &parm->status);
1400   if (!wasconf)
1401     assuan_end_confidential (entry_ctx);
1402 
1403   if (!rc && parm->buffer && is_generated_pin (&inq_cb_parm, parm->buffer))
1404     parm->status |= PINENTRY_STATUS_PASSWORD_GENERATED;
1405   else
1406     parm->status &= ~PINENTRY_STATUS_PASSWORD_GENERATED;
1407 
1408   /* Most pinentries out in the wild return the old Assuan error code
1409      for canceled which gets translated to an assuan Cancel error and
1410      not to the code for a user cancel.  Fix this here. */
1411   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1412     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1413   /* Change error code in case the window close button was clicked
1414      to cancel the operation.  */
1415   if ((parm->status & PINENTRY_STATUS_CLOSE_BUTTON)
1416       && gpg_err_code (rc) == GPG_ERR_CANCELED)
1417     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
1418 
1419   watch_sock_end (&sock_watched, &thread);
1420 
1421   return rc;
1422 }
1423 
1424 /* Call the Entry and ask for the PIN.  We do check for a valid PIN
1425    number here and repeat it as long as we have invalid formed
1426    numbers.  KEYINFO and CACHE_MODE are used to tell pinentry something
1427    about the key. */
1428 gpg_error_t
agent_askpin(ctrl_t ctrl,const char * desc_text,const char * prompt_text,const char * initial_errtext,struct pin_entry_info_s * pininfo,const char * keyinfo,cache_mode_t cache_mode)1429 agent_askpin (ctrl_t ctrl,
1430               const char *desc_text, const char *prompt_text,
1431               const char *initial_errtext,
1432               struct pin_entry_info_s *pininfo,
1433               const char *keyinfo, cache_mode_t cache_mode)
1434 {
1435   gpg_error_t rc;
1436   char line[ASSUAN_LINELENGTH];
1437   struct entry_parm_s parm;
1438   const char *errtext = NULL;
1439   int is_pin = 0;
1440   int is_generated;
1441 
1442   if (opt.batch)
1443     return 0; /* fixme: we should return BAD PIN */
1444 
1445   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1446     {
1447       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1448         return gpg_error (GPG_ERR_CANCELED);
1449       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
1450         {
1451 	  unsigned char *passphrase;
1452 	  size_t size;
1453 
1454 	  *pininfo->pin = 0; /* Reset the PIN. */
1455 	  rc = pinentry_loopback (ctrl, "PASSPHRASE", &passphrase, &size,
1456                                   pininfo->max_length - 1);
1457 	  if (rc)
1458 	    return rc;
1459 
1460 	  memcpy(&pininfo->pin, passphrase, size);
1461 	  xfree(passphrase);
1462 	  pininfo->pin[size] = 0;
1463 	  if (pininfo->check_cb)
1464 	    {
1465 	      /* More checks by utilizing the optional callback. */
1466 	      pininfo->cb_errtext = NULL;
1467 	      rc = pininfo->check_cb (pininfo);
1468 	    }
1469 	  return rc;
1470 	}
1471       return gpg_error(GPG_ERR_NO_PIN_ENTRY);
1472     }
1473 
1474   if (!pininfo || pininfo->max_length < 1)
1475     return gpg_error (GPG_ERR_INV_VALUE);
1476   if (!desc_text && pininfo->min_digits)
1477     desc_text = L_("Please enter your PIN, so that the secret key "
1478                    "can be unlocked for this session");
1479   else if (!desc_text)
1480     desc_text = L_("Please enter your passphrase, so that the secret key "
1481                    "can be unlocked for this session");
1482 
1483   if (prompt_text)
1484     is_pin = !!strstr (prompt_text, "PIN");
1485   else
1486     is_pin = desc_text && strstr (desc_text, "PIN");
1487 
1488   rc = start_pinentry (ctrl);
1489   if (rc)
1490     return rc;
1491 
1492   /* If we have a KEYINFO string and are normal, user, or ssh cache
1493      mode, we tell that the Pinentry so it may use it for own caching
1494      purposes.  Most pinentries won't have this implemented and thus
1495      we do not error out in this case.  */
1496   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1497                   || cache_mode == CACHE_MODE_USER
1498                   || cache_mode == CACHE_MODE_SSH))
1499     snprintf (line, DIM(line), "SETKEYINFO %c/%s",
1500 	      cache_mode == CACHE_MODE_USER? 'u' :
1501 	      cache_mode == CACHE_MODE_SSH? 's' : 'n',
1502 	      keyinfo);
1503   else
1504     snprintf (line, DIM(line), "SETKEYINFO --clear");
1505 
1506   rc = assuan_transact (entry_ctx, line,
1507 			NULL, NULL, NULL, NULL, NULL, NULL);
1508   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
1509     return unlock_pinentry (ctrl, rc);
1510 
1511   build_cmd_setdesc (line, DIM(line), desc_text);
1512   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1513   if (rc)
1514     return unlock_pinentry (ctrl, rc);
1515 
1516   snprintf (line, DIM(line), "SETPROMPT %s",
1517             prompt_text? prompt_text : is_pin? L_("PIN:") : L_("Passphrase:"));
1518   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1519   if (rc)
1520     return unlock_pinentry (ctrl, rc);
1521 
1522   /* If a passphrase quality indicator has been requested and a
1523      minimum passphrase length has not been disabled, send the command
1524      to the pinentry.  */
1525   if (pininfo->with_qualitybar && opt.min_passphrase_len )
1526     {
1527       rc = setup_qualitybar (ctrl);
1528       if (rc)
1529         return unlock_pinentry (ctrl, rc);
1530     }
1531 
1532   if (initial_errtext)
1533     {
1534       snprintf (line, DIM(line), "SETERROR %s", initial_errtext);
1535       rc = assuan_transact (entry_ctx, line,
1536                             NULL, NULL, NULL, NULL, NULL, NULL);
1537       if (rc)
1538         return unlock_pinentry (ctrl, rc);
1539     }
1540 
1541   if (pininfo->with_repeat)
1542     {
1543       snprintf (line, DIM(line), "SETREPEATERROR %s",
1544                 L_("does not match - try again"));
1545       rc = assuan_transact (entry_ctx, line,
1546                             NULL, NULL, NULL, NULL, NULL, NULL);
1547       if (rc)
1548         pininfo->with_repeat = 0; /* Pinentry does not support it.  */
1549     }
1550   pininfo->repeat_okay = 0;
1551   pininfo->status = 0;
1552 
1553   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
1554     {
1555       memset (&parm, 0, sizeof parm);
1556       parm.size = pininfo->max_length;
1557       *pininfo->pin = 0; /* Reset the PIN. */
1558       parm.buffer = (unsigned char*)pininfo->pin;
1559       parm.constraints_flags = pininfo->constraints_flags;
1560 
1561       if (errtext)
1562         {
1563           /* TRANSLATORS: The string is appended to an error message in
1564              the pinentry.  The %s is the actual error message, the
1565              two %d give the current and maximum number of tries. */
1566           snprintf (line, DIM(line), L_("SETERROR %s (try %d of %d)"),
1567                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
1568           rc = assuan_transact (entry_ctx, line,
1569                                 NULL, NULL, NULL, NULL, NULL, NULL);
1570           if (rc)
1571             return unlock_pinentry (ctrl, rc);
1572           errtext = NULL;
1573         }
1574 
1575       if (pininfo->with_repeat)
1576         {
1577           snprintf (line, DIM(line), "SETREPEAT %s", L_("Repeat:"));
1578           rc = assuan_transact (entry_ctx, line,
1579                                 NULL, NULL, NULL, NULL, NULL, NULL);
1580           if (rc)
1581             return unlock_pinentry (ctrl, rc);
1582         }
1583 
1584       rc = do_getpin (ctrl, &parm);
1585       pininfo->status = parm.status;
1586       is_generated = !!(parm.status & PINENTRY_STATUS_PASSWORD_GENERATED);
1587 
1588       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
1589         errtext = is_pin? L_("PIN too long")
1590                         : L_("Passphrase too long");
1591       else if (rc)
1592         return unlock_pinentry (ctrl, rc);
1593 
1594       if (!errtext && pininfo->min_digits && !is_generated)
1595         {
1596           /* do some basic checks on the entered PIN. */
1597           if (!all_digitsp (pininfo->pin))
1598             errtext = L_("Invalid characters in PIN");
1599           else if (pininfo->max_digits
1600                    && strlen (pininfo->pin) > pininfo->max_digits)
1601             errtext = L_("PIN too long");
1602           else if (strlen (pininfo->pin) < pininfo->min_digits)
1603             errtext = L_("PIN too short");
1604         }
1605 
1606       if (!errtext && pininfo->check_cb && !is_generated)
1607         {
1608           /* More checks by utilizing the optional callback. */
1609           pininfo->cb_errtext = NULL;
1610           rc = pininfo->check_cb (pininfo);
1611           /* When pinentry cache causes an error, return now.  */
1612           if (rc
1613               && (pininfo->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
1614             return unlock_pinentry (ctrl, rc);
1615 
1616           if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE)
1617             {
1618               if (pininfo->cb_errtext)
1619                 errtext = pininfo->cb_errtext;
1620               else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1621                        || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
1622                 errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase"));
1623             }
1624           else if (rc)
1625             return unlock_pinentry (ctrl, rc);
1626         }
1627 
1628       if (!errtext)
1629         {
1630           if (pininfo->with_repeat
1631               && (pininfo->status & PINENTRY_STATUS_PIN_REPEATED))
1632             pininfo->repeat_okay = 1;
1633           return unlock_pinentry (ctrl, 0); /* okay, got a PIN or passphrase */
1634         }
1635 
1636       if ((pininfo->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
1637         {
1638           /* The password was read from the cache.  Don't count this
1639              against the retry count.  */
1640           pininfo->failed_tries --;
1641         }
1642     }
1643 
1644   return unlock_pinentry (ctrl, gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
1645                           : GPG_ERR_BAD_PASSPHRASE));
1646 }
1647 
1648 
1649 
1650 /* Ask for the passphrase using the supplied arguments.  The returned
1651    passphrase needs to be freed by the caller.  PININFO is optional
1652    and can be used to have constraints checking while the pinentry
1653    dialog is open (like what we do in agent_askpin).  This is very
1654    similar to agent_askpin and we should eventually merge the two
1655    functions. */
1656 int
agent_get_passphrase(ctrl_t ctrl,char ** retpass,const char * desc,const char * prompt,const char * errtext,int with_qualitybar,const char * keyinfo,cache_mode_t cache_mode,struct pin_entry_info_s * pininfo)1657 agent_get_passphrase (ctrl_t ctrl,
1658                       char **retpass, const char *desc, const char *prompt,
1659                       const char *errtext, int with_qualitybar,
1660 		      const char *keyinfo, cache_mode_t cache_mode,
1661                       struct pin_entry_info_s *pininfo)
1662 {
1663   int rc;
1664   int is_pin;
1665   int is_generated;
1666   char line[ASSUAN_LINELENGTH];
1667   struct entry_parm_s parm;
1668 
1669   *retpass = NULL;
1670   if (opt.batch)
1671     return gpg_error (GPG_ERR_BAD_PASSPHRASE);
1672 
1673   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1674     {
1675       unsigned char *passphrase;
1676       size_t size;
1677 
1678       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1679         return gpg_error (GPG_ERR_CANCELED);
1680 
1681       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK && pininfo)
1682         {
1683 	  *pininfo->pin = 0; /* Reset the PIN. */
1684 	  rc = pinentry_loopback (ctrl, "PASSPHRASE",
1685                                   &passphrase, &size,
1686                                   pininfo->max_length - 1);
1687           if (rc)
1688             return rc;
1689 
1690 	  memcpy (&pininfo->pin, passphrase, size);
1691           wipememory (passphrase, size);
1692 	  xfree (passphrase);
1693 	  pininfo->pin[size] = 0;
1694 	  if (pininfo->check_cb)
1695 	    {
1696 	      /* More checks by utilizing the optional callback. */
1697 	      pininfo->cb_errtext = NULL;
1698 	      rc = pininfo->check_cb (pininfo);
1699 	    }
1700 	  return rc;
1701 
1702         }
1703       else if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
1704         {
1705           /* Legacy variant w/o PININFO.  */
1706 	  return pinentry_loopback (ctrl, "PASSPHRASE",
1707 				    (unsigned char **)retpass, &size,
1708                                     MAX_PASSPHRASE_LEN);
1709         }
1710 
1711       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1712     }
1713 
1714   rc = start_pinentry (ctrl);
1715   if (rc)
1716     return rc;
1717 
1718   /* Set IS_PIN and if needed a default prompt.  */
1719   if (prompt)
1720     is_pin = !!strstr (prompt, "PIN");
1721   else
1722     {
1723       is_pin = desc && strstr (desc, "PIN");
1724       prompt = is_pin? L_("PIN:"): L_("Passphrase:");
1725     }
1726 
1727   /* If we have a KEYINFO string and are normal, user, or ssh cache
1728      mode, we tell that the Pinentry so it may use it for own caching
1729      purposes.  Most pinentries won't have this implemented and thus
1730      we do not error out in this case.  */
1731   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1732                   || cache_mode == CACHE_MODE_USER
1733                   || cache_mode == CACHE_MODE_SSH))
1734     snprintf (line, DIM(line), "SETKEYINFO %c/%s",
1735 	      cache_mode == CACHE_MODE_USER? 'u' :
1736 	      cache_mode == CACHE_MODE_SSH? 's' : 'n',
1737 	      keyinfo);
1738   else
1739     snprintf (line, DIM(line), "SETKEYINFO --clear");
1740 
1741   rc = assuan_transact (entry_ctx, line,
1742 			NULL, NULL, NULL, NULL, NULL, NULL);
1743   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
1744     return unlock_pinentry (ctrl, rc);
1745 
1746   if (desc)
1747     build_cmd_setdesc (line, DIM(line), desc);
1748   else
1749     snprintf (line, DIM(line), "RESET");
1750   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1751   if (rc)
1752     return unlock_pinentry (ctrl, rc);
1753 
1754   snprintf (line, DIM(line), "SETPROMPT %s", prompt);
1755   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1756   if (rc)
1757     return unlock_pinentry (ctrl, rc);
1758 
1759   if ((with_qualitybar || (pininfo && pininfo->with_qualitybar))
1760        && opt.min_passphrase_len)
1761     {
1762       rc = setup_qualitybar (ctrl);
1763       if (rc)
1764         return unlock_pinentry (ctrl, rc);
1765     }
1766 
1767   if (errtext)
1768     {
1769       snprintf (line, DIM(line), "SETERROR %s", errtext);
1770       rc = assuan_transact (entry_ctx, line,
1771                             NULL, NULL, NULL, NULL, NULL, NULL);
1772       if (rc)
1773         return unlock_pinentry (ctrl, rc);
1774     }
1775 
1776   rc = setup_formatted_passphrase (ctrl);
1777   if (rc)
1778     return unlock_pinentry (ctrl, rc);
1779 
1780   if (!pininfo)
1781     {
1782       /* Legacy method without PININFO.  */
1783       memset (&parm, 0, sizeof parm);
1784       parm.size = ASSUAN_LINELENGTH/2 - 5;
1785       parm.buffer = gcry_malloc_secure (parm.size+10);
1786       if (!parm.buffer)
1787         return unlock_pinentry (ctrl, out_of_core ());
1788 
1789       rc = do_getpin (ctrl, &parm);
1790       if (rc)
1791         xfree (parm.buffer);
1792       else
1793         *retpass = parm.buffer;
1794       return unlock_pinentry (ctrl, rc);
1795     }
1796 
1797   /* We got PININFO.  */
1798 
1799   if (pininfo->with_repeat)
1800     {
1801       snprintf (line, DIM(line), "SETREPEATERROR %s",
1802                 L_("does not match - try again"));
1803       rc = assuan_transact (entry_ctx, line,
1804                             NULL, NULL, NULL, NULL, NULL, NULL);
1805       if (rc)
1806         pininfo->with_repeat = 0; /* Pinentry does not support it.  */
1807 
1808       (void)setup_genpin (ctrl);
1809 
1810       rc = setup_enforced_constraints (ctrl);
1811       if (rc)
1812         return unlock_pinentry (ctrl, rc);
1813     }
1814   pininfo->repeat_okay = 0;
1815   pininfo->status = 0;
1816 
1817   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
1818     {
1819       memset (&parm, 0, sizeof parm);
1820       parm.constraints_flags = pininfo->constraints_flags;
1821       parm.size = pininfo->max_length;
1822       parm.buffer = (unsigned char*)pininfo->pin;
1823       *pininfo->pin = 0; /* Reset the PIN. */
1824 
1825       if (errtext)
1826         {
1827           /* TRANSLATORS: The string is appended to an error message in
1828              the pinentry.  The %s is the actual error message, the
1829              two %d give the current and maximum number of tries. */
1830           snprintf (line, DIM(line), L_("SETERROR %s (try %d of %d)"),
1831                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
1832           rc = assuan_transact (entry_ctx, line,
1833                                 NULL, NULL, NULL, NULL, NULL, NULL);
1834           if (rc)
1835             return unlock_pinentry (ctrl, rc);
1836           errtext = NULL;
1837         }
1838 
1839       if (pininfo->with_repeat)
1840         {
1841           snprintf (line, DIM(line), "SETREPEAT %s", L_("Repeat:"));
1842           rc = assuan_transact (entry_ctx, line,
1843                                 NULL, NULL, NULL, NULL, NULL, NULL);
1844           if (rc)
1845             return unlock_pinentry (ctrl, rc);
1846         }
1847 
1848       rc = do_getpin (ctrl, &parm);
1849       pininfo->status = parm.status;
1850       is_generated = !!(parm.status & PINENTRY_STATUS_PASSWORD_GENERATED);
1851 
1852       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
1853         errtext = is_pin? L_("PIN too long")
1854                         : L_("Passphrase too long");
1855       else if (rc)
1856         return unlock_pinentry (ctrl, rc);
1857 
1858       if (!errtext && pininfo->min_digits && !is_generated)
1859         {
1860           /* do some basic checks on the entered PIN. */
1861           if (!all_digitsp (pininfo->pin))
1862             errtext = L_("Invalid characters in PIN");
1863           else if (pininfo->max_digits
1864                    && strlen (pininfo->pin) > pininfo->max_digits)
1865             errtext = L_("PIN too long");
1866           else if (strlen (pininfo->pin) < pininfo->min_digits)
1867             errtext = L_("PIN too short");
1868         }
1869 
1870       if (!errtext && pininfo->check_cb && !is_generated)
1871         {
1872           /* More checks by utilizing the optional callback. */
1873           pininfo->cb_errtext = NULL;
1874           rc = pininfo->check_cb (pininfo);
1875           /* When pinentry cache causes an error, return now.  */
1876           if (rc && (pininfo->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
1877             return unlock_pinentry (ctrl, rc);
1878 
1879           if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE)
1880             {
1881               if (pininfo->cb_errtext)
1882                 errtext = pininfo->cb_errtext;
1883               else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1884                        || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
1885                 errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase"));
1886             }
1887           else if (rc)
1888             return unlock_pinentry (ctrl, rc);
1889         }
1890 
1891       if (!errtext)
1892         {
1893           if (pininfo->with_repeat
1894               && (pininfo->status & PINENTRY_STATUS_PIN_REPEATED))
1895             pininfo->repeat_okay = 1;
1896           return unlock_pinentry (ctrl, 0); /* okay, got a PIN or passphrase */
1897         }
1898 
1899       if ((pininfo->status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
1900         {
1901           /* The password was read from the Pinentry's own cache.
1902              Don't count this against the retry count.  */
1903           pininfo->failed_tries--;
1904         }
1905     }
1906 
1907   return unlock_pinentry (ctrl, gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
1908                           : GPG_ERR_BAD_PASSPHRASE));
1909 }
1910 
1911 
1912 
1913 /* Pop up the PIN-entry, display the text and the prompt and ask the
1914    user to confirm this.  We return 0 for success, ie. the user
1915    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
1916    other error.  If WITH_CANCEL it true an extra cancel button is
1917    displayed to allow the user to easily return a GPG_ERR_CANCELED.
1918    if the Pinentry does not support this, the user can still cancel by
1919    closing the Pinentry window.  */
1920 int
agent_get_confirmation(ctrl_t ctrl,const char * desc,const char * ok,const char * notok,int with_cancel)1921 agent_get_confirmation (ctrl_t ctrl,
1922                         const char *desc, const char *ok,
1923                         const char *notok, int with_cancel)
1924 {
1925   int rc;
1926   char line[ASSUAN_LINELENGTH];
1927 
1928   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1929     {
1930       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1931         return gpg_error (GPG_ERR_CANCELED);
1932 
1933       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
1934         return pinentry_loopback_confirm (ctrl, desc, 1, ok, notok);
1935 
1936       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1937     }
1938 
1939   rc = start_pinentry (ctrl);
1940   if (rc)
1941     return rc;
1942 
1943   if (desc)
1944     build_cmd_setdesc (line, DIM(line), desc);
1945   else
1946     snprintf (line, DIM(line), "RESET");
1947   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1948   /* Most pinentries out in the wild return the old Assuan error code
1949      for canceled which gets translated to an assuan Cancel error and
1950      not to the code for a user cancel.  Fix this here. */
1951   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1952     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1953 
1954   if (rc)
1955     return unlock_pinentry (ctrl, rc);
1956 
1957   if (ok)
1958     {
1959       snprintf (line, DIM(line), "SETOK %s", ok);
1960       rc = assuan_transact (entry_ctx,
1961                             line, NULL, NULL, NULL, NULL, NULL, NULL);
1962       if (rc)
1963         return unlock_pinentry (ctrl, rc);
1964     }
1965   if (notok)
1966     {
1967       /* Try to use the newer NOTOK feature if a cancel button is
1968          requested.  If no cancel button is requested we keep on using
1969          the standard cancel.  */
1970       if (with_cancel)
1971         {
1972           snprintf (line, DIM(line), "SETNOTOK %s", notok);
1973           rc = assuan_transact (entry_ctx,
1974                                 line, NULL, NULL, NULL, NULL, NULL, NULL);
1975         }
1976       else
1977         rc = GPG_ERR_ASS_UNKNOWN_CMD;
1978 
1979       if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
1980 	{
1981 	  snprintf (line, DIM(line), "SETCANCEL %s", notok);
1982 	  rc = assuan_transact (entry_ctx, line,
1983                                 NULL, NULL, NULL, NULL, NULL, NULL);
1984 	}
1985       if (rc)
1986         return unlock_pinentry (ctrl, rc);
1987     }
1988 
1989   {
1990     gnupg_fd_t sock_watched = ctrl->thread_startup.fd;
1991     npth_t thread;
1992 
1993     rc = watch_sock_start (&sock_watched, &thread);
1994     if (!rc)
1995       {
1996         rc = assuan_transact (entry_ctx, "CONFIRM",
1997                               NULL, NULL, NULL, NULL, NULL, NULL);
1998         if (rc && gpg_err_source (rc)
1999             && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
2000           rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
2001 
2002         watch_sock_end (&sock_watched, &thread);
2003       }
2004 
2005     return unlock_pinentry (ctrl, rc);
2006   }
2007 }
2008 
2009 
2010 
2011 /* The thread running the popup message. */
2012 static void *
popup_message_thread(void * arg)2013 popup_message_thread (void *arg)
2014 {
2015   gpg_error_t rc;
2016   gnupg_fd_t sock_watched = *(gnupg_fd_t *)arg;
2017   npth_t thread;
2018 
2019   rc = watch_sock_start (&sock_watched, &thread);
2020   if (rc)
2021     return NULL;
2022 
2023   /* We use the --one-button hack instead of the MESSAGE command to
2024      allow the use of old Pinentries.  Those old Pinentries will then
2025      show an additional Cancel button but that is mostly a visual
2026      annoyance. */
2027   assuan_transact (entry_ctx, "CONFIRM --one-button",
2028                    NULL, NULL, NULL, NULL, NULL, NULL);
2029   watch_sock_end (&sock_watched, &thread);
2030   popup_finished = 1;
2031   return NULL;
2032 }
2033 
2034 
2035 /* Pop up a message window similar to the confirm one but keep it open
2036    until agent_popup_message_stop has been called.  It is crucial for
2037    the caller to make sure that the stop function gets called as soon
2038    as the message is not anymore required because the message is
2039    system modal and all other attempts to use the pinentry will fail
2040    (after a timeout). */
2041 int
agent_popup_message_start(ctrl_t ctrl,const char * desc,const char * ok_btn)2042 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
2043 {
2044   int rc;
2045   char line[ASSUAN_LINELENGTH];
2046   npth_attr_t tattr;
2047   int err;
2048 
2049   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
2050     {
2051       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
2052         return gpg_error (GPG_ERR_CANCELED);
2053 
2054       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
2055         return pinentry_loopback_confirm (ctrl, desc, 0, ok_btn, NULL);
2056 
2057       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
2058     }
2059 
2060   rc = start_pinentry (ctrl);
2061   if (rc)
2062     return rc;
2063 
2064   if (desc)
2065     build_cmd_setdesc (line, DIM(line), desc);
2066   else
2067     snprintf (line, DIM(line), "RESET");
2068   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
2069   if (rc)
2070     return unlock_pinentry (ctrl, rc);
2071 
2072   if (ok_btn)
2073     {
2074       snprintf (line, DIM(line), "SETOK %s", ok_btn);
2075       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
2076       if (rc)
2077         return unlock_pinentry (ctrl, rc);
2078     }
2079 
2080   err = npth_attr_init (&tattr);
2081   if (err)
2082     return unlock_pinentry (ctrl, gpg_error_from_errno (err));
2083   npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
2084 
2085   popup_finished = 0;
2086   err = npth_create (&popup_tid, &tattr, popup_message_thread,
2087                      &ctrl->thread_startup.fd);
2088   npth_attr_destroy (&tattr);
2089   if (err)
2090     {
2091       rc = gpg_error_from_errno (err);
2092       log_error ("error spawning popup message handler: %s\n",
2093                  strerror (err) );
2094       return unlock_pinentry (ctrl, rc);
2095     }
2096   npth_setname_np (popup_tid, "popup-message");
2097 
2098   return 0;
2099 }
2100 
2101 /* Close a popup window. */
2102 void
agent_popup_message_stop(ctrl_t ctrl)2103 agent_popup_message_stop (ctrl_t ctrl)
2104 {
2105   int rc;
2106   pid_t pid;
2107 
2108   (void)ctrl;
2109 
2110   if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
2111     return;
2112 
2113   if (!popup_tid || !entry_ctx)
2114     {
2115       log_debug ("agent_popup_message_stop called with no active popup\n");
2116       return;
2117     }
2118 
2119   pid = assuan_get_pid (entry_ctx);
2120   if (pid == (pid_t)(-1))
2121     ; /* No pid available can't send a kill. */
2122   else if (popup_finished)
2123     ; /* Already finished and ready for joining. */
2124 #ifdef HAVE_W32_SYSTEM
2125   /* Older versions of assuan set PID to 0 on Windows to indicate an
2126      invalid value.  */
2127   else if (pid != (pid_t) INVALID_HANDLE_VALUE
2128 	   && pid != 0)
2129     {
2130       HANDLE process = (HANDLE) pid;
2131 
2132       /* Arbitrary error code.  */
2133       TerminateProcess (process, 1);
2134     }
2135 #else
2136   else if (pid > 0)
2137     kill (pid, SIGINT);
2138 #endif
2139 
2140   /* Now wait for the thread to terminate. */
2141   rc = npth_join (popup_tid, NULL);
2142   if (rc)
2143     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
2144                strerror (rc));
2145   /* Thread IDs are opaque, but we try our best here by resetting it
2146      to the same content that a static global variable has.  */
2147   memset (&popup_tid, '\0', sizeof (popup_tid));
2148 
2149   /* Now we can close the connection. */
2150   unlock_pinentry (ctrl, 0);
2151 }
2152 
2153 int
agent_clear_passphrase(ctrl_t ctrl,const char * keyinfo,cache_mode_t cache_mode)2154 agent_clear_passphrase (ctrl_t ctrl,
2155 			const char *keyinfo, cache_mode_t cache_mode)
2156 {
2157   int rc;
2158   char line[ASSUAN_LINELENGTH];
2159 
2160   if (! (keyinfo && (cache_mode == CACHE_MODE_NORMAL
2161 		     || cache_mode == CACHE_MODE_USER
2162 		     || cache_mode == CACHE_MODE_SSH)))
2163     return gpg_error (GPG_ERR_NOT_SUPPORTED);
2164 
2165   rc = start_pinentry (ctrl);
2166   if (rc)
2167     return rc;
2168 
2169   snprintf (line, DIM(line), "CLEARPASSPHRASE %c/%s",
2170 	    cache_mode == CACHE_MODE_USER? 'u' :
2171 	    cache_mode == CACHE_MODE_SSH? 's' : 'n',
2172 	    keyinfo);
2173   rc = assuan_transact (entry_ctx, line,
2174 			NULL, NULL, NULL, NULL, NULL, NULL);
2175 
2176   return unlock_pinentry (ctrl, rc);
2177 }
2178