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