agent: Tell the Pinentry the client's pid.
[gnupg.git] / agent / call-pinentry.c
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 <assert.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30 #ifndef HAVE_W32_SYSTEM
31 # include <sys/wait.h>
32 # include <sys/types.h>
33 # include <signal.h>
34 #endif
35 #include <npth.h>
36
37 #include "agent.h"
38 #include <assuan.h>
39 #include "sysutils.h"
40 #include "i18n.h"
41
42 #ifdef _POSIX_OPEN_MAX
43 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
44 #else
45 #define MAX_OPEN_FDS 20
46 #endif
47
48
49 /* Because access to the pinentry must be serialized (it is and shall
50    be a global mutually exclusive dialog) we better timeout pending
51    requests after some time.  1 minute seem to be a reasonable
52    time. */
53 #define LOCK_TIMEOUT  (1*60)
54
55 /* The assuan context of the current pinentry. */
56 static assuan_context_t entry_ctx;
57
58 /* The control variable of the connection owning the current pinentry.
59    This is only valid if ENTRY_CTX is not NULL.  Note, that we care
60    only about the value of the pointer and that it should never be
61    dereferenced.  */
62 static ctrl_t entry_owner;
63
64 /* A mutex used to serialize access to the pinentry. */
65 static npth_mutex_t entry_lock;
66
67 /* The thread ID of the popup working thread. */
68 static npth_t  popup_tid;
69
70 /* A flag used in communication between the popup working thread and
71    its stop function. */
72 static int popup_finished;
73
74
75
76 /* Data to be passed to our callbacks, */
77 struct entry_parm_s
78 {
79   int lines;
80   size_t size;
81   unsigned char *buffer;
82 };
83
84
85
86 \f
87 /* This function must be called once to initialize this module.  This
88    has to be done before a second thread is spawned.  We can't do the
89    static initialization because Pth emulation code might not be able
90    to do a static init; in particular, it is not possible for W32. */
91 void
92 initialize_module_call_pinentry (void)
93 {
94   static int initialized;
95
96   if (!initialized)
97     {
98       if (npth_mutex_init (&entry_lock, NULL))
99         initialized = 1;
100     }
101 }
102
103
104
105 /* This function may be called to print infromation pertaining to the
106    current state of this module to the log. */
107 void
108 agent_query_dump_state (void)
109 {
110   log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
111             entry_ctx, (long)assuan_get_pid (entry_ctx), (void*)popup_tid);
112 }
113
114 /* Called to make sure that a popup window owned by the current
115    connection gets closed. */
116 void
117 agent_reset_query (ctrl_t ctrl)
118 {
119   if (entry_ctx && popup_tid && entry_owner == ctrl)
120     {
121       agent_popup_message_stop (ctrl);
122     }
123 }
124
125
126 /* Unlock the pinentry so that another thread can start one and
127    disconnect that pinentry - we do this after the unlock so that a
128    stalled pinentry does not block other threads.  Fixme: We should
129    have a timeout in Assuan for the disconnect operation. */
130 static gpg_error_t
131 unlock_pinentry (gpg_error_t rc)
132 {
133   assuan_context_t ctx = entry_ctx;
134   int err;
135
136   if (rc)
137     {
138       if (DBG_IPC)
139         log_debug ("error calling pinentry: %s <%s>\n",
140                    gpg_strerror (rc), gpg_strsource (rc));
141
142       /* Change the source of the error to pinentry so that the final
143          consumer of the error code knows that the problem is with
144          pinentry.  For backward compatibility we do not do that for
145          some common error codes.  */
146       switch (gpg_err_code (rc))
147         {
148         case GPG_ERR_NO_PIN_ENTRY:
149         case GPG_ERR_CANCELED:
150         case GPG_ERR_FULLY_CANCELED:
151         case GPG_ERR_ASS_UNKNOWN_INQUIRE:
152         case GPG_ERR_ASS_TOO_MUCH_DATA:
153         case GPG_ERR_NO_PASSPHRASE:
154         case GPG_ERR_BAD_PASSPHRASE:
155         case GPG_ERR_BAD_PIN:
156           break;
157
158         default:
159           rc = gpg_err_make (GPG_ERR_SOURCE_PINENTRY, gpg_err_code (rc));
160           break;
161         }
162     }
163
164   entry_ctx = NULL;
165   err = npth_mutex_unlock (&entry_lock);
166   if (err)
167     {
168       log_error ("failed to release the entry lock: %s\n", strerror (err));
169       if (!rc)
170         rc = gpg_error_from_errno (err);
171     }
172   assuan_release (ctx);
173   return rc;
174 }
175
176
177 /* To make sure we leave no secrets in our image after forking of the
178    pinentry, we use this callback. */
179 static void
180 atfork_cb (void *opaque, int where)
181 {
182   ctrl_t ctrl = opaque;
183
184   if (!where)
185     {
186       int iterator = 0;
187       const char *name, *assname, *value;
188
189       gcry_control (GCRYCTL_TERM_SECMEM);
190
191       while ((name = session_env_list_stdenvnames (&iterator, &assname)))
192         {
193           /* For all new envvars (!ASSNAME) and the two medium old
194              ones which do have an assuan name but are conveyed using
195              environment variables, update the environment of the
196              forked process.  */
197           if (!assname
198               || !strcmp (name, "XAUTHORITY")
199               || !strcmp (name, "PINENTRY_USER_DATA"))
200             {
201               value = session_env_getenv (ctrl->session_env, name);
202               if (value)
203                 gnupg_setenv (name, value, 1);
204             }
205         }
206     }
207 }
208
209
210 static gpg_error_t
211 getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
212 {
213   unsigned long *pid = opaque;
214   char pidbuf[50];
215
216   /* There is only the pid in the server's response.  */
217   if (length >= sizeof pidbuf)
218     length = sizeof pidbuf -1;
219   if (length)
220     {
221       strncpy (pidbuf, buffer, length);
222       pidbuf[length] = 0;
223       *pid = strtoul (pidbuf, NULL, 10);
224     }
225   return 0;
226 }
227
228
229 /* Fork off the pin entry if this has not already been done.  Note,
230    that this function must always be used to acquire the lock for the
231    pinentry - we will serialize _all_ pinentry calls.
232  */
233 static gpg_error_t
234 start_pinentry (ctrl_t ctrl)
235 {
236   int rc = 0;
237   const char *full_pgmname;
238   const char *pgmname;
239   assuan_context_t ctx;
240   const char *argv[5];
241   assuan_fd_t no_close_list[3];
242   int i;
243   const char *tmpstr;
244   unsigned long pinentry_pid;
245   const char *value;
246   struct timespec abstime;
247   char *flavor_version;
248   int err;
249
250   npth_clock_gettime (&abstime);
251   abstime.tv_sec += LOCK_TIMEOUT;
252   err = npth_mutex_timedlock (&entry_lock, &abstime);
253   if (err)
254     {
255       if (err == ETIMEDOUT)
256         rc = gpg_error (GPG_ERR_TIMEOUT);
257       else
258         rc = gpg_error_from_errno (rc);
259       log_error (_("failed to acquire the pinentry lock: %s\n"),
260                  gpg_strerror (rc));
261       return rc;
262     }
263
264   entry_owner = ctrl;
265
266   if (entry_ctx)
267     return 0;
268
269   if (opt.verbose)
270     log_info ("starting a new PIN Entry\n");
271
272 #ifdef HAVE_W32_SYSTEM
273   fflush (stdout);
274   fflush (stderr);
275 #endif
276   if (fflush (NULL))
277     {
278 #ifndef HAVE_W32_SYSTEM
279       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
280 #endif
281       log_error ("error flushing pending output: %s\n", strerror (errno));
282       /* At least Windows XP fails here with EBADF.  According to docs
283          and Wine an fflush(NULL) is the same as _flushall.  However
284          the Wine implementaion does not flush stdin,stdout and stderr
285          - see above.  Let's try to ignore the error. */
286 #ifndef HAVE_W32_SYSTEM
287       return unlock_pinentry (tmperr);
288 #endif
289     }
290
291   full_pgmname = opt.pinentry_program;
292   if (!full_pgmname || !*full_pgmname)
293     full_pgmname = gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY);
294   if ( !(pgmname = strrchr (full_pgmname, '/')))
295     pgmname = full_pgmname;
296   else
297     pgmname++;
298
299   /* OS X needs the entire file name in argv[0], so that it can locate
300      the resource bundle.  For other systems we stick to the usual
301      convention of supplying only the name of the program.  */
302 #ifdef __APPLE__
303   argv[0] = full_pgmname;
304 #else /*!__APPLE__*/
305   argv[0] = pgmname;
306 #endif /*__APPLE__*/
307
308   if (!opt.keep_display
309       && (value = session_env_getenv (ctrl->session_env, "DISPLAY")))
310     {
311       argv[1] = "--display";
312       argv[2] = value;
313       argv[3] = NULL;
314     }
315   else
316     argv[1] = NULL;
317
318   i=0;
319   if (!opt.running_detached)
320     {
321       if (log_get_fd () != -1)
322         no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
323       no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
324     }
325   no_close_list[i] = ASSUAN_INVALID_FD;
326
327   rc = assuan_new (&ctx);
328   if (rc)
329     {
330       log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
331       return rc;
332     }
333   /* We don't want to log the pinentry communication to make the logs
334      easier to read.  We might want to add a new debug option to enable
335      pinentry logging.  */
336 #ifdef ASSUAN_NO_LOGGING
337   assuan_set_flag (ctx, ASSUAN_NO_LOGGING, !opt.debug_pinentry);
338 #endif
339
340   /* Connect to the pinentry and perform initial handshaking.  Note
341      that atfork is used to change the environment for pinentry.  We
342      start the server in detached mode to suppress the console window
343      under Windows.  */
344   rc = assuan_pipe_connect (ctx, full_pgmname, argv,
345                             no_close_list, atfork_cb, ctrl,
346                             ASSUAN_PIPE_CONNECT_DETACHED);
347   if (rc)
348     {
349       log_error ("can't connect to the PIN entry module '%s': %s\n",
350                  full_pgmname, gpg_strerror (rc));
351       assuan_release (ctx);
352       return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
353     }
354   entry_ctx = ctx;
355
356   if (DBG_IPC)
357     log_debug ("connection to PIN entry established\n");
358
359   value = session_env_getenv (ctrl->session_env, "PINENTRY_USER_DATA");
360   if (value != NULL)
361     {
362       char *optstr;
363       if (asprintf (&optstr, "OPTION pinentry-user-data=%s", value) < 0 )
364         return unlock_pinentry (out_of_core ());
365       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
366                             NULL);
367       xfree (optstr);
368       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
369         return unlock_pinentry (rc);
370     }
371
372   rc = assuan_transact (entry_ctx,
373                         opt.no_grab? "OPTION no-grab":"OPTION grab",
374                         NULL, NULL, NULL, NULL, NULL, NULL);
375   if (rc)
376     return unlock_pinentry (rc);
377
378   value = session_env_getenv (ctrl->session_env, "GPG_TTY");
379   if (value)
380     {
381       char *optstr;
382       if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
383         return unlock_pinentry (out_of_core ());
384       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
385                             NULL);
386       xfree (optstr);
387       if (rc)
388         return unlock_pinentry (rc);
389     }
390   value = session_env_getenv (ctrl->session_env, "TERM");
391   if (value)
392     {
393       char *optstr;
394       if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
395         return unlock_pinentry (out_of_core ());
396       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
397                             NULL);
398       xfree (optstr);
399       if (rc)
400         return unlock_pinentry (rc);
401     }
402   if (ctrl->lc_ctype)
403     {
404       char *optstr;
405       if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
406         return unlock_pinentry (out_of_core ());
407       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
408                             NULL);
409       xfree (optstr);
410       if (rc)
411         return unlock_pinentry (rc);
412     }
413   if (ctrl->lc_messages)
414     {
415       char *optstr;
416       if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
417         return unlock_pinentry (out_of_core ());
418       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
419                             NULL);
420       xfree (optstr);
421       if (rc)
422         return unlock_pinentry (rc);
423     }
424
425
426   if (opt.allow_external_cache)
427     {
428       /* Indicate to the pinentry that it may read from an external cache.
429
430          It is essential that the pinentry respect this.  If the
431          cached password is not up to date and retry == 1, then, using
432          a version of GPG Agent that doesn't support this, won't issue
433          another pin request and the user won't get a chance to
434          correct the password.  */
435       rc = assuan_transact (entry_ctx, "OPTION allow-external-password-cache",
436                             NULL, NULL, NULL, NULL, NULL, NULL);
437       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
438         return unlock_pinentry (rc);
439     }
440
441   if (opt.allow_emacs_pinentry)
442     {
443       /* Indicate to the pinentry that it may read passphrase through
444          Emacs minibuffer, if possible.  */
445       rc = assuan_transact (entry_ctx, "OPTION allow-emacs-prompt",
446                             NULL, NULL, NULL, NULL, NULL, NULL);
447       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
448         return unlock_pinentry (rc);
449     }
450
451
452   {
453     /* Provide a few default strings for use by the pinentries.  This
454        may help a pinentry to avoid implementing localization code.  */
455     static struct { const char *key, *value; int what; } tbl[] = {
456       /* TRANSLATORS: These are labels for buttons etc used in
457          Pinentries.  An underscore indicates that the next letter
458          should be used as an accelerator.  Double the underscore for
459          a literal one.  The actual to be translated text starts after
460          the second vertical bar.  Note that gpg-agent has been set to
461          utf-8 so that the strings are in the expected encoding.  */
462       { "ok",     N_("|pinentry-label|_OK") },
463       { "cancel", N_("|pinentry-label|_Cancel") },
464       { "yes",    N_("|pinentry-label|_Yes") },
465       { "no",     N_("|pinentry-label|_No") },
466       { "prompt", N_("|pinentry-label|PIN:") },
467       { "pwmngr", N_("|pinentry-label|_Save in password manager"), 1 },
468       { "cf-visi",N_("Do you really want to make your "
469                      "passphrase visible on the screen?") },
470       { "tt-visi",N_("|pinentry-tt|Make passphrase visible") },
471       { "tt-hide",N_("|pinentry-tt|Hide passphrase") },
472       { NULL, NULL}
473     };
474     char *optstr;
475     int idx;
476     const char *s, *s2;
477
478     for (idx=0; tbl[idx].key; idx++)
479       {
480         if (!opt.allow_external_cache && tbl[idx].what == 1)
481           continue;  /* No need for it.  */
482         s = L_(tbl[idx].value);
483         if (*s == '|' && (s2=strchr (s+1,'|')))
484           s = s2+1;
485         if (asprintf (&optstr, "OPTION default-%s=%s", tbl[idx].key, s) < 0 )
486           return unlock_pinentry (out_of_core ());
487         assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
488                          NULL);
489         xfree (optstr);
490       }
491   }
492
493   /* Tell the pinentry that we would prefer that the given character
494      is used as the invisible character by the entry widget.  */
495   if (opt.pinentry_invisible_char)
496     {
497       char *optstr;
498       if ((optstr = xtryasprintf ("OPTION invisible-char=%s",
499                                   opt.pinentry_invisible_char)))
500         {
501           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
502                            NULL);
503           /* We ignore errors because this is just a fancy thing and
504              older pinentries do not support this feature.  */
505           xfree (optstr);
506         }
507     }
508
509   if (opt.pinentry_timeout)
510     {
511       char *optstr;
512       if ((optstr = xtryasprintf ("SETTIMEOUT %lu", opt.pinentry_timeout)))
513         {
514           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
515                            NULL);
516           /* We ignore errors because this is just a fancy thing.  */
517           xfree (optstr);
518         }
519     }
520
521   /* Tell the pinentry the name of a file it shall touch after having
522      messed with the tty.  This is optional and only supported by
523      newer pinentries and thus we do no error checking. */
524   tmpstr = opt.pinentry_touch_file;
525   if (tmpstr && !strcmp (tmpstr, "/dev/null"))
526     tmpstr = NULL;
527   else if (!tmpstr)
528     tmpstr = get_agent_socket_name ();
529   if (tmpstr)
530     {
531       char *optstr;
532
533       if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
534         ;
535       else
536         {
537           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
538                            NULL);
539           xfree (optstr);
540         }
541     }
542
543   /* Tell Pinentry about our client.  */
544   if (ctrl->client_pid)
545     {
546       char *optstr;
547       if ((optstr = xtryasprintf ("OPTION owner=%lu", ctrl->client_pid)))
548         {
549           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
550                            NULL);
551           /* We ignore errors because this is just a fancy thing and
552              older pinentries do not support this feature.  */
553           xfree (optstr);
554         }
555     }
556
557
558   /* Ask the pinentry for its version and flavor and store that as a
559    * string in MB.  This information is useful for helping users to
560    * figure out Pinentry problems.  */
561   {
562     membuf_t mb;
563
564     init_membuf (&mb, 256);
565     if (assuan_transact (entry_ctx, "GETINFO flavor",
566                          put_membuf_cb, &mb, NULL, NULL, NULL, NULL))
567       put_membuf_str (&mb, "unknown");
568     put_membuf_str (&mb, " ");
569     if (assuan_transact (entry_ctx, "GETINFO version",
570                          put_membuf_cb, &mb, NULL, NULL, NULL, NULL))
571       put_membuf_str (&mb, "unknown");
572     put_membuf_str (&mb, " ");
573     if (assuan_transact (entry_ctx, "GETINFO ttyinfo",
574                          put_membuf_cb, &mb, NULL, NULL, NULL, NULL))
575       put_membuf_str (&mb, "? ? ?");
576     put_membuf (&mb, "", 1);
577     flavor_version = get_membuf (&mb, NULL);
578   }
579
580
581   /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
582      it will send the pid back and we will use an inquire to notify
583      our client.  The client may answer the inquiry either with END or
584      with CAN to cancel the pinentry. */
585   rc = assuan_transact (entry_ctx, "GETINFO pid",
586                         getinfo_pid_cb, &pinentry_pid,
587                         NULL, NULL, NULL, NULL);
588   if (rc)
589     {
590       log_info ("You may want to update to a newer pinentry\n");
591       rc = 0;
592     }
593   else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
594     log_error ("pinentry did not return a PID\n");
595   else
596     {
597       rc = agent_inq_pinentry_launched (ctrl, pinentry_pid, flavor_version);
598       if (gpg_err_code (rc) == GPG_ERR_CANCELED
599           || gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
600         return unlock_pinentry (gpg_err_make (GPG_ERR_SOURCE_DEFAULT,
601                                               gpg_err_code (rc)));
602       rc = 0;
603     }
604
605   xfree (flavor_version);
606
607   return 0;
608 }
609
610
611 /* Returns True if the pinentry is currently active. If WAITSECONDS is
612    greater than zero the function will wait for this many seconds
613    before returning.  */
614 int
615 pinentry_active_p (ctrl_t ctrl, int waitseconds)
616 {
617   int err;
618   (void)ctrl;
619
620   if (waitseconds > 0)
621     {
622       struct timespec abstime;
623       int rc;
624
625       npth_clock_gettime (&abstime);
626       abstime.tv_sec += waitseconds;
627       err = npth_mutex_timedlock (&entry_lock, &abstime);
628       if (err)
629         {
630           if (err == ETIMEDOUT)
631             rc = gpg_error (GPG_ERR_TIMEOUT);
632           else
633             rc = gpg_error (GPG_ERR_INTERNAL);
634           return rc;
635         }
636     }
637   else
638     {
639       err = npth_mutex_trylock (&entry_lock);
640       if (err)
641         return gpg_error (GPG_ERR_LOCKED);
642     }
643
644   err = npth_mutex_unlock (&entry_lock);
645   if (err)
646     log_error ("failed to release the entry lock at %d: %s\n", __LINE__,
647                strerror (errno));
648   return 0;
649 }
650
651
652 static gpg_error_t
653 getpin_cb (void *opaque, const void *buffer, size_t length)
654 {
655   struct entry_parm_s *parm = opaque;
656
657   if (!buffer)
658     return 0;
659
660   /* we expect the pin to fit on one line */
661   if (parm->lines || length >= parm->size)
662     return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
663
664   /* fixme: we should make sure that the assuan buffer is allocated in
665      secure memory or read the response byte by byte */
666   memcpy (parm->buffer, buffer, length);
667   parm->buffer[length] = 0;
668   parm->lines++;
669   return 0;
670 }
671
672
673 static int
674 all_digitsp( const char *s)
675 {
676   for (; *s && *s >= '0' && *s <= '9'; s++)
677     ;
678   return !*s;
679 }
680
681
682 /* Return a new malloced string by unescaping the string S.  Escaping
683    is percent escaping and '+'/space mapping.  A binary Nul will
684    silently be replaced by a 0xFF.  Function returns NULL to indicate
685    an out of memory status.  Parsing stops at the end of the string or
686    a white space character. */
687 static char *
688 unescape_passphrase_string (const unsigned char *s)
689 {
690   char *buffer, *d;
691
692   buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
693   if (!buffer)
694     return NULL;
695   while (*s && !spacep (s))
696     {
697       if (*s == '%' && s[1] && s[2])
698         {
699           s++;
700           *d = xtoi_2 (s);
701           if (!*d)
702             *d = '\xff';
703           d++;
704           s += 2;
705         }
706       else if (*s == '+')
707         {
708           *d++ = ' ';
709           s++;
710         }
711       else
712         *d++ = *s++;
713     }
714   *d = 0;
715   return buffer;
716 }
717
718
719 /* Estimate the quality of the passphrase PW and return a value in the
720    range 0..100.  */
721 static int
722 estimate_passphrase_quality (const char *pw)
723 {
724   int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
725   int length;
726   const char *s;
727
728   if (goodlength < 1)
729     return 0;
730
731   for (length = 0, s = pw; *s; s++)
732     if (!spacep (s))
733       length ++;
734
735   if (length > goodlength)
736     return 100;
737   return ((length*10) / goodlength)*10;
738 }
739
740
741 /* Handle the QUALITY inquiry. */
742 static gpg_error_t
743 inq_quality (void *opaque, const char *line)
744 {
745   assuan_context_t ctx = opaque;
746   const char *s;
747   char *pin;
748   int rc;
749   int percent;
750   char numbuf[20];
751
752   if ((s = has_leading_keyword (line, "QUALITY")))
753     {
754       pin = unescape_passphrase_string (s);
755       if (!pin)
756         rc = gpg_error_from_syserror ();
757       else
758         {
759           percent = estimate_passphrase_quality (pin);
760           if (check_passphrase_constraints (NULL, pin, NULL))
761             percent = -percent;
762           snprintf (numbuf, sizeof numbuf, "%d", percent);
763           rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
764           xfree (pin);
765         }
766     }
767   else
768     {
769       log_error ("unsupported inquiry '%s' from pinentry\n", line);
770       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
771     }
772
773   return rc;
774 }
775
776
777 /* Helper for agent_askpin and agent_get_passphrase.  */
778 static gpg_error_t
779 setup_qualitybar (ctrl_t ctrl)
780 {
781   int rc;
782   char line[ASSUAN_LINELENGTH];
783   char *tmpstr, *tmpstr2;
784   const char *tooltip;
785
786   (void)ctrl;
787
788   /* TRANSLATORS: This string is displayed by Pinentry as the label
789      for the quality bar.  */
790   tmpstr = try_percent_escape (L_("Quality:"), "\t\r\n\f\v");
791   snprintf (line, DIM(line), "SETQUALITYBAR %s", tmpstr? tmpstr:"");
792   xfree (tmpstr);
793   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
794   if (rc == 103 /*(Old assuan error code)*/
795       || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
796     ; /* Ignore Unknown Command from old Pinentry versions.  */
797   else if (rc)
798     return rc;
799
800   tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
801   if (tmpstr2)
802     tooltip = tmpstr2;
803   else
804     {
805       /* TRANSLATORS: This string is a tooltip, shown by pinentry when
806          hovering over the quality bar.  Please use an appropriate
807          string to describe what this is about.  The length of the
808          tooltip is limited to about 900 characters.  If you do not
809          translate this entry, a default english text (see source)
810          will be used. */
811       tooltip =  L_("pinentry.qualitybar.tooltip");
812       if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
813         tooltip = ("The quality of the text entered above.\n"
814                    "Please ask your administrator for "
815                    "details about the criteria.");
816     }
817   tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
818   xfree (tmpstr2);
819   snprintf (line, DIM(line), "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
820   xfree (tmpstr);
821   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
822   if (rc == 103 /*(Old assuan error code)*/
823           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
824     ; /* Ignore Unknown Command from old pinentry versions.  */
825   else if (rc)
826     return rc;
827
828   return 0;
829 }
830
831 enum
832   {
833     PINENTRY_STATUS_CLOSE_BUTTON = 1 << 0,
834     PINENTRY_STATUS_PIN_REPEATED = 1 << 8,
835     PINENTRY_STATUS_PASSWORD_FROM_CACHE = 1 << 9
836   };
837
838 /* Check the button_info line for a close action.  Also check for the
839    PIN_REPEATED flag.  */
840 static gpg_error_t
841 pinentry_status_cb (void *opaque, const char *line)
842 {
843   unsigned int *flag = opaque;
844   const char *args;
845
846   if ((args = has_leading_keyword (line, "BUTTON_INFO")))
847     {
848       if (!strcmp (args, "close"))
849         *flag |= PINENTRY_STATUS_CLOSE_BUTTON;
850     }
851   else if (has_leading_keyword (line, "PIN_REPEATED"))
852     {
853       *flag |= PINENTRY_STATUS_PIN_REPEATED;
854     }
855   else if (has_leading_keyword (line, "PASSWORD_FROM_CACHE"))
856     {
857       *flag |= PINENTRY_STATUS_PASSWORD_FROM_CACHE;
858     }
859
860   return 0;
861 }
862
863
864
865 \f
866 /* Call the Entry and ask for the PIN.  We do check for a valid PIN
867    number here and repeat it as long as we have invalid formed
868    numbers.  KEYINFO and CACHE_MODE are used to tell pinentry something
869    about the key. */
870 gpg_error_t
871 agent_askpin (ctrl_t ctrl,
872               const char *desc_text, const char *prompt_text,
873               const char *initial_errtext,
874               struct pin_entry_info_s *pininfo,
875               const char *keyinfo, cache_mode_t cache_mode)
876 {
877   gpg_error_t rc;
878   char line[ASSUAN_LINELENGTH];
879   struct entry_parm_s parm;
880   const char *errtext = NULL;
881   int is_pin = 0;
882   int saveflag;
883   unsigned int pinentry_status;
884
885   if (opt.batch)
886     return 0; /* fixme: we should return BAD PIN */
887
888   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
889     {
890       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
891         return gpg_error (GPG_ERR_CANCELED);
892       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
893         {
894           unsigned char *passphrase;
895           size_t size;
896
897           *pininfo->pin = 0; /* Reset the PIN. */
898           rc = pinentry_loopback(ctrl, "PASSPHRASE", &passphrase, &size,
899                   pininfo->max_length - 1);
900           if (rc)
901             return rc;
902
903           memcpy(&pininfo->pin, passphrase, size);
904           xfree(passphrase);
905           pininfo->pin[size] = 0;
906           if (pininfo->check_cb)
907             {
908               /* More checks by utilizing the optional callback. */
909               pininfo->cb_errtext = NULL;
910               rc = pininfo->check_cb (pininfo);
911             }
912           return rc;
913         }
914       return gpg_error(GPG_ERR_NO_PIN_ENTRY);
915     }
916
917   if (!pininfo || pininfo->max_length < 1)
918     return gpg_error (GPG_ERR_INV_VALUE);
919   if (!desc_text && pininfo->min_digits)
920     desc_text = L_("Please enter your PIN, so that the secret key "
921                    "can be unlocked for this session");
922   else if (!desc_text)
923     desc_text = L_("Please enter your passphrase, so that the secret key "
924                    "can be unlocked for this session");
925
926   if (prompt_text)
927     is_pin = !!strstr (prompt_text, "PIN");
928   else
929     is_pin = desc_text && strstr (desc_text, "PIN");
930
931   rc = start_pinentry (ctrl);
932   if (rc)
933     return rc;
934
935   /* If we have a KEYINFO string and are normal, user, or ssh cache
936      mode, we tell that the Pinentry so it may use it for own caching
937      purposes.  Most pinentries won't have this implemented and thus
938      we do not error out in this case.  */
939   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
940                   || cache_mode == CACHE_MODE_USER
941                   || cache_mode == CACHE_MODE_SSH))
942     snprintf (line, DIM(line), "SETKEYINFO %c/%s",
943               cache_mode == CACHE_MODE_USER? 'u' :
944               cache_mode == CACHE_MODE_SSH? 's' : 'n',
945               keyinfo);
946   else
947     snprintf (line, DIM(line), "SETKEYINFO --clear");
948
949   rc = assuan_transact (entry_ctx, line,
950                         NULL, NULL, NULL, NULL, NULL, NULL);
951   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
952     return unlock_pinentry (rc);
953
954   snprintf (line, DIM(line), "SETDESC %s", desc_text);
955   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
956   if (rc)
957     return unlock_pinentry (rc);
958
959   snprintf (line, DIM(line), "SETPROMPT %s",
960             prompt_text? prompt_text : is_pin? L_("PIN:") : L_("Passphrase:"));
961   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
962   if (rc)
963     return unlock_pinentry (rc);
964
965   /* If a passphrase quality indicator has been requested and a
966      minimum passphrase length has not been disabled, send the command
967      to the pinentry.  */
968   if (pininfo->with_qualitybar && opt.min_passphrase_len )
969     {
970       rc = setup_qualitybar (ctrl);
971       if (rc)
972         return unlock_pinentry (rc);
973     }
974
975   if (initial_errtext)
976     {
977       snprintf (line, DIM(line), "SETERROR %s", initial_errtext);
978       rc = assuan_transact (entry_ctx, line,
979                             NULL, NULL, NULL, NULL, NULL, NULL);
980       if (rc)
981         return unlock_pinentry (rc);
982     }
983
984   if (pininfo->with_repeat)
985     {
986       snprintf (line, DIM(line), "SETREPEATERROR %s",
987                 L_("does not match - try again"));
988       rc = assuan_transact (entry_ctx, line,
989                             NULL, NULL, NULL, NULL, NULL, NULL);
990       if (rc)
991         pininfo->with_repeat = 0; /* Pinentry does not support it.  */
992     }
993   pininfo->repeat_okay = 0;
994
995   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
996     {
997       memset (&parm, 0, sizeof parm);
998       parm.size = pininfo->max_length;
999       *pininfo->pin = 0; /* Reset the PIN. */
1000       parm.buffer = (unsigned char*)pininfo->pin;
1001
1002       if (errtext)
1003         {
1004           /* TRANSLATORS: The string is appended to an error message in
1005              the pinentry.  The %s is the actual error message, the
1006              two %d give the current and maximum number of tries. */
1007           snprintf (line, DIM(line), L_("SETERROR %s (try %d of %d)"),
1008                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
1009           rc = assuan_transact (entry_ctx, line,
1010                                 NULL, NULL, NULL, NULL, NULL, NULL);
1011           if (rc)
1012             return unlock_pinentry (rc);
1013           errtext = NULL;
1014         }
1015
1016       if (pininfo->with_repeat)
1017         {
1018           snprintf (line, DIM(line), "SETREPEAT %s", L_("Repeat:"));
1019           rc = assuan_transact (entry_ctx, line,
1020                                 NULL, NULL, NULL, NULL, NULL, NULL);
1021           if (rc)
1022             return unlock_pinentry (rc);
1023         }
1024
1025       saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
1026       assuan_begin_confidential (entry_ctx);
1027       pinentry_status = 0;
1028       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
1029                             inq_quality, entry_ctx,
1030                             pinentry_status_cb, &pinentry_status);
1031       assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
1032       /* Most pinentries out in the wild return the old Assuan error code
1033          for canceled which gets translated to an assuan Cancel error and
1034          not to the code for a user cancel.  Fix this here. */
1035       if (rc && gpg_err_source (rc)
1036           && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1037         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1038
1039
1040       /* Change error code in case the window close button was clicked
1041          to cancel the operation.  */
1042       if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
1043           && gpg_err_code (rc) == GPG_ERR_CANCELED)
1044         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
1045
1046       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
1047         errtext = is_pin? L_("PIN too long")
1048                         : L_("Passphrase too long");
1049       else if (rc)
1050         return unlock_pinentry (rc);
1051
1052       if (!errtext && pininfo->min_digits)
1053         {
1054           /* do some basic checks on the entered PIN. */
1055           if (!all_digitsp (pininfo->pin))
1056             errtext = L_("Invalid characters in PIN");
1057           else if (pininfo->max_digits
1058                    && strlen (pininfo->pin) > pininfo->max_digits)
1059             errtext = L_("PIN too long");
1060           else if (strlen (pininfo->pin) < pininfo->min_digits)
1061             errtext = L_("PIN too short");
1062         }
1063
1064       if (!errtext && pininfo->check_cb)
1065         {
1066           /* More checks by utilizing the optional callback. */
1067           pininfo->cb_errtext = NULL;
1068           rc = pininfo->check_cb (pininfo);
1069           if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1070               && pininfo->cb_errtext)
1071             errtext = pininfo->cb_errtext;
1072           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1073                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
1074             errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase"));
1075           else if (rc)
1076             return unlock_pinentry (rc);
1077         }
1078
1079       if (!errtext)
1080         {
1081           if (pininfo->with_repeat
1082               && (pinentry_status & PINENTRY_STATUS_PIN_REPEATED))
1083             pininfo->repeat_okay = 1;
1084           return unlock_pinentry (0); /* okay, got a PIN or passphrase */
1085         }
1086
1087       if ((pinentry_status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
1088         /* The password was read from the cache.  Don't count this
1089            against the retry count.  */
1090         pininfo->failed_tries --;
1091     }
1092
1093   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
1094                           : GPG_ERR_BAD_PASSPHRASE));
1095 }
1096
1097
1098 \f
1099 /* Ask for the passphrase using the supplied arguments.  The returned
1100    passphrase needs to be freed by the caller. */
1101 int
1102 agent_get_passphrase (ctrl_t ctrl,
1103                       char **retpass, const char *desc, const char *prompt,
1104                       const char *errtext, int with_qualitybar,
1105                       const char *keyinfo, cache_mode_t cache_mode)
1106 {
1107
1108   int rc;
1109   char line[ASSUAN_LINELENGTH];
1110   struct entry_parm_s parm;
1111   int saveflag;
1112   unsigned int pinentry_status;
1113
1114   *retpass = NULL;
1115   if (opt.batch)
1116     return gpg_error (GPG_ERR_BAD_PASSPHRASE);
1117
1118   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1119     {
1120       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1121         return gpg_error (GPG_ERR_CANCELED);
1122
1123       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
1124         {
1125           size_t size;
1126           size_t len = ASSUAN_LINELENGTH/2;
1127
1128           return pinentry_loopback (ctrl, "PASSPHRASE",
1129                                     (unsigned char **)retpass, &size, len);
1130         }
1131       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1132     }
1133
1134   rc = start_pinentry (ctrl);
1135   if (rc)
1136     return rc;
1137
1138   if (!prompt)
1139     prompt = desc && strstr (desc, "PIN")? L_("PIN:"): L_("Passphrase:");
1140
1141
1142   /* If we have a KEYINFO string and are normal, user, or ssh cache
1143      mode, we tell that the Pinentry so it may use it for own caching
1144      purposes.  Most pinentries won't have this implemented and thus
1145      we do not error out in this case.  */
1146   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1147                   || cache_mode == CACHE_MODE_USER
1148                   || cache_mode == CACHE_MODE_SSH))
1149     snprintf (line, DIM(line), "SETKEYINFO %c/%s",
1150               cache_mode == CACHE_MODE_USER? 'u' :
1151               cache_mode == CACHE_MODE_SSH? 's' : 'n',
1152               keyinfo);
1153   else
1154     snprintf (line, DIM(line), "SETKEYINFO --clear");
1155
1156   rc = assuan_transact (entry_ctx, line,
1157                         NULL, NULL, NULL, NULL, NULL, NULL);
1158   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
1159     return unlock_pinentry (rc);
1160
1161
1162   if (desc)
1163     snprintf (line, DIM(line), "SETDESC %s", desc);
1164   else
1165     snprintf (line, DIM(line), "RESET");
1166   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1167   if (rc)
1168     return unlock_pinentry (rc);
1169
1170   snprintf (line, DIM(line), "SETPROMPT %s", prompt);
1171   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1172   if (rc)
1173     return unlock_pinentry (rc);
1174
1175   if (with_qualitybar && opt.min_passphrase_len)
1176     {
1177       rc = setup_qualitybar (ctrl);
1178       if (rc)
1179         return unlock_pinentry (rc);
1180     }
1181
1182   if (errtext)
1183     {
1184       snprintf (line, DIM(line), "SETERROR %s", errtext);
1185       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1186       if (rc)
1187         return unlock_pinentry (rc);
1188     }
1189
1190   memset (&parm, 0, sizeof parm);
1191   parm.size = ASSUAN_LINELENGTH/2 - 5;
1192   parm.buffer = gcry_malloc_secure (parm.size+10);
1193   if (!parm.buffer)
1194     return unlock_pinentry (out_of_core ());
1195
1196   saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
1197   assuan_begin_confidential (entry_ctx);
1198   pinentry_status = 0;
1199   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
1200                         inq_quality, entry_ctx,
1201                         pinentry_status_cb, &pinentry_status);
1202   assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
1203   /* Most pinentries out in the wild return the old Assuan error code
1204      for canceled which gets translated to an assuan Cancel error and
1205      not to the code for a user cancel.  Fix this here. */
1206   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1207     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1208   /* Change error code in case the window close button was clicked
1209      to cancel the operation.  */
1210   if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
1211       && gpg_err_code (rc) == GPG_ERR_CANCELED)
1212     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
1213
1214   if (rc)
1215     xfree (parm.buffer);
1216   else
1217     *retpass = parm.buffer;
1218   return unlock_pinentry (rc);
1219 }
1220
1221
1222 \f
1223 /* Pop up the PIN-entry, display the text and the prompt and ask the
1224    user to confirm this.  We return 0 for success, ie. the user
1225    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
1226    other error.  If WITH_CANCEL it true an extra cancel button is
1227    displayed to allow the user to easily return a GPG_ERR_CANCELED.
1228    if the Pinentry does not support this, the user can still cancel by
1229    closing the Pinentry window.  */
1230 int
1231 agent_get_confirmation (ctrl_t ctrl,
1232                         const char *desc, const char *ok,
1233                         const char *notok, int with_cancel)
1234 {
1235   int rc;
1236   char line[ASSUAN_LINELENGTH];
1237
1238   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1239     {
1240       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1241         return gpg_error (GPG_ERR_CANCELED);
1242
1243       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1244     }
1245
1246   rc = start_pinentry (ctrl);
1247   if (rc)
1248     return rc;
1249
1250   if (desc)
1251     snprintf (line, DIM(line), "SETDESC %s", desc);
1252   else
1253     snprintf (line, DIM(line), "RESET");
1254   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1255   /* Most pinentries out in the wild return the old Assuan error code
1256      for canceled which gets translated to an assuan Cancel error and
1257      not to the code for a user cancel.  Fix this here. */
1258   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1259     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1260
1261   if (rc)
1262     return unlock_pinentry (rc);
1263
1264   if (ok)
1265     {
1266       snprintf (line, DIM(line), "SETOK %s", ok);
1267       rc = assuan_transact (entry_ctx,
1268                             line, NULL, NULL, NULL, NULL, NULL, NULL);
1269       if (rc)
1270         return unlock_pinentry (rc);
1271     }
1272   if (notok)
1273     {
1274       /* Try to use the newer NOTOK feature if a cancel button is
1275          requested.  If no cancel button is requested we keep on using
1276          the standard cancel.  */
1277       if (with_cancel)
1278         {
1279           snprintf (line, DIM(line), "SETNOTOK %s", notok);
1280           rc = assuan_transact (entry_ctx,
1281                                 line, NULL, NULL, NULL, NULL, NULL, NULL);
1282         }
1283       else
1284         rc = GPG_ERR_ASS_UNKNOWN_CMD;
1285
1286       if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
1287         {
1288           snprintf (line, DIM(line), "SETCANCEL %s", notok);
1289           rc = assuan_transact (entry_ctx, line,
1290                                 NULL, NULL, NULL, NULL, NULL, NULL);
1291         }
1292       if (rc)
1293         return unlock_pinentry (rc);
1294     }
1295
1296   rc = assuan_transact (entry_ctx, "CONFIRM",
1297                         NULL, NULL, NULL, NULL, NULL, NULL);
1298   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1299     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1300
1301   return unlock_pinentry (rc);
1302 }
1303
1304
1305 \f
1306 /* Pop up the PINentry, display the text DESC and a button with the
1307    text OK_BTN (which may be NULL to use the default of "OK") and wait
1308    for the user to hit this button.  The return value is not
1309    relevant.  */
1310 int
1311 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
1312 {
1313   int rc;
1314   char line[ASSUAN_LINELENGTH];
1315
1316   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1317     return gpg_error (GPG_ERR_CANCELED);
1318
1319   rc = start_pinentry (ctrl);
1320   if (rc)
1321     return rc;
1322
1323   if (desc)
1324     snprintf (line, DIM(line), "SETDESC %s", desc);
1325   else
1326     snprintf (line, DIM(line), "RESET");
1327   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1328   /* Most pinentries out in the wild return the old Assuan error code
1329      for canceled which gets translated to an assuan Cancel error and
1330      not to the code for a user cancel.  Fix this here. */
1331   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1332     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1333
1334   if (rc)
1335     return unlock_pinentry (rc);
1336
1337   if (ok_btn)
1338     {
1339       snprintf (line, DIM(line), "SETOK %s", ok_btn);
1340       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
1341                             NULL, NULL, NULL);
1342       if (rc)
1343         return unlock_pinentry (rc);
1344     }
1345
1346   rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
1347                         NULL, NULL, NULL);
1348   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1349     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1350
1351   return unlock_pinentry (rc);
1352 }
1353
1354
1355 /* The thread running the popup message. */
1356 static void *
1357 popup_message_thread (void *arg)
1358 {
1359   (void)arg;
1360
1361   /* We use the --one-button hack instead of the MESSAGE command to
1362      allow the use of old Pinentries.  Those old Pinentries will then
1363      show an additional Cancel button but that is mostly a visual
1364      annoyance. */
1365   assuan_transact (entry_ctx, "CONFIRM --one-button",
1366                    NULL, NULL, NULL, NULL, NULL, NULL);
1367   popup_finished = 1;
1368   return NULL;
1369 }
1370
1371
1372 /* Pop up a message window similar to the confirm one but keep it open
1373    until agent_popup_message_stop has been called.  It is crucial for
1374    the caller to make sure that the stop function gets called as soon
1375    as the message is not anymore required because the message is
1376    system modal and all other attempts to use the pinentry will fail
1377    (after a timeout). */
1378 int
1379 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
1380 {
1381   int rc;
1382   char line[ASSUAN_LINELENGTH];
1383   npth_attr_t tattr;
1384   int err;
1385
1386   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1387     return gpg_error (GPG_ERR_CANCELED);
1388
1389   rc = start_pinentry (ctrl);
1390   if (rc)
1391     return rc;
1392
1393   if (desc)
1394     snprintf (line, DIM(line), "SETDESC %s", desc);
1395   else
1396     snprintf (line, DIM(line), "RESET");
1397   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1398   if (rc)
1399     return unlock_pinentry (rc);
1400
1401   if (ok_btn)
1402     {
1403       snprintf (line, DIM(line), "SETOK %s", ok_btn);
1404       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1405       if (rc)
1406         return unlock_pinentry (rc);
1407     }
1408
1409   err = npth_attr_init (&tattr);
1410   if (err)
1411     return unlock_pinentry (gpg_error_from_errno (err));
1412   npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
1413
1414   popup_finished = 0;
1415   err = npth_create (&popup_tid, &tattr, popup_message_thread, NULL);
1416   npth_attr_destroy (&tattr);
1417   if (err)
1418     {
1419       rc = gpg_error_from_errno (err);
1420       log_error ("error spawning popup message handler: %s\n",
1421                  strerror (err) );
1422       return unlock_pinentry (rc);
1423     }
1424   npth_setname_np (popup_tid, "popup-message");
1425
1426   return 0;
1427 }
1428
1429 /* Close a popup window. */
1430 void
1431 agent_popup_message_stop (ctrl_t ctrl)
1432 {
1433   int rc;
1434   pid_t pid;
1435
1436   (void)ctrl;
1437
1438   if (!popup_tid || !entry_ctx)
1439     {
1440       log_debug ("agent_popup_message_stop called with no active popup\n");
1441       return;
1442     }
1443
1444   pid = assuan_get_pid (entry_ctx);
1445   if (pid == (pid_t)(-1))
1446     ; /* No pid available can't send a kill. */
1447   else if (popup_finished)
1448     ; /* Already finished and ready for joining. */
1449 #ifdef HAVE_W32_SYSTEM
1450   /* Older versions of assuan set PID to 0 on Windows to indicate an
1451      invalid value.  */
1452   else if (pid != (pid_t) INVALID_HANDLE_VALUE
1453            && pid != 0)
1454     {
1455       HANDLE process = (HANDLE) pid;
1456
1457       /* Arbitrary error code.  */
1458       TerminateProcess (process, 1);
1459     }
1460 #else
1461   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1462     { /* The daemon already died.  No need to send a kill.  However
1463          because we already waited for the process, we need to tell
1464          assuan that it should not wait again (done by
1465          unlock_pinentry). */
1466       if (rc == pid)
1467         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1468     }
1469   else if (pid > 0)
1470     kill (pid, SIGINT);
1471 #endif
1472
1473   /* Now wait for the thread to terminate. */
1474   rc = npth_join (popup_tid, NULL);
1475   if (rc)
1476     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1477                strerror (rc));
1478   /* Thread IDs are opaque, but we try our best here by resetting it
1479      to the same content that a static global variable has.  */
1480   memset (&popup_tid, '\0', sizeof (popup_tid));
1481   entry_owner = NULL;
1482
1483   /* Now we can close the connection. */
1484   unlock_pinentry (0);
1485 }
1486
1487 int
1488 agent_clear_passphrase (ctrl_t ctrl,
1489                         const char *keyinfo, cache_mode_t cache_mode)
1490 {
1491   int rc;
1492   char line[ASSUAN_LINELENGTH];
1493
1494   if (! (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1495                      || cache_mode == CACHE_MODE_USER
1496                      || cache_mode == CACHE_MODE_SSH)))
1497     return gpg_error (GPG_ERR_NOT_SUPPORTED);
1498
1499   rc = start_pinentry (ctrl);
1500   if (rc)
1501     return rc;
1502
1503   snprintf (line, DIM(line), "CLEARPASSPHRASE %c/%s",
1504             cache_mode == CACHE_MODE_USER? 'u' :
1505             cache_mode == CACHE_MODE_SSH? 's' : 'n',
1506             keyinfo);
1507   rc = assuan_transact (entry_ctx, line,
1508                         NULL, NULL, NULL, NULL, NULL, NULL);
1509
1510   return unlock_pinentry (rc);
1511 }