Imported Upstream version 2.1.11
[platform/upstream/gpg2.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 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 /* Fork off the pin entry if this has not already been done.  Note,
229    that this function must always be used to acquire the lock for the
230    pinentry - we will serialize _all_ pinentry calls.
231  */
232 static gpg_error_t
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   /* Tell the pinentry that we would prefer that the given character
479      is used as the invisible character by the entry widget.  */
480   if (opt.pinentry_invisible_char)
481     {
482       char *optstr;
483       if ((optstr = xtryasprintf ("OPTION invisible-char=%s",
484                                   opt.pinentry_invisible_char)))
485         {
486           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
487                            NULL);
488           /* We ignore errors because this is just a fancy thing and
489              older pinentries do not support this feature.  */
490           xfree (optstr);
491         }
492     }
493
494   if (opt.pinentry_timeout)
495     {
496       char *optstr;
497       if ((optstr = xtryasprintf ("SETTIMEOUT %lu", opt.pinentry_timeout)))
498         {
499           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
500                            NULL);
501           /* We ignore errors because this is just a fancy thing.  */
502           xfree (optstr);
503         }
504     }
505
506   /* Tell the pinentry the name of a file it shall touch after having
507      messed with the tty.  This is optional and only supported by
508      newer pinentries and thus we do no error checking. */
509   tmpstr = opt.pinentry_touch_file;
510   if (tmpstr && !strcmp (tmpstr, "/dev/null"))
511     tmpstr = NULL;
512   else if (!tmpstr)
513     tmpstr = get_agent_socket_name ();
514   if (tmpstr)
515     {
516       char *optstr;
517
518       if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
519         ;
520       else
521         {
522           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
523                            NULL);
524           xfree (optstr);
525         }
526     }
527
528
529   /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
530      it will send the pid back and we will use an inquire to notify
531      our client.  The client may answer the inquiry either with END or
532      with CAN to cancel the pinentry. */
533   rc = assuan_transact (entry_ctx, "GETINFO pid",
534                         getinfo_pid_cb, &pinentry_pid,
535                         NULL, NULL, NULL, NULL);
536   if (rc)
537     {
538       log_info ("You may want to update to a newer pinentry\n");
539       rc = 0;
540     }
541   else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
542     log_error ("pinentry did not return a PID\n");
543   else
544     {
545       rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
546       if (gpg_err_code (rc) == GPG_ERR_CANCELED
547           || gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
548         return unlock_pinentry (gpg_err_make (GPG_ERR_SOURCE_DEFAULT,
549                                               gpg_err_code (rc)));
550       rc = 0;
551     }
552
553   return 0;
554 }
555
556
557 /* Returns True if the pinentry is currently active. If WAITSECONDS is
558    greater than zero the function will wait for this many seconds
559    before returning.  */
560 int
561 pinentry_active_p (ctrl_t ctrl, int waitseconds)
562 {
563   int err;
564   (void)ctrl;
565
566   if (waitseconds > 0)
567     {
568       struct timespec abstime;
569       int rc;
570
571       npth_clock_gettime (&abstime);
572       abstime.tv_sec += waitseconds;
573       err = npth_mutex_timedlock (&entry_lock, &abstime);
574       if (err)
575         {
576           if (err == ETIMEDOUT)
577             rc = gpg_error (GPG_ERR_TIMEOUT);
578           else
579             rc = gpg_error (GPG_ERR_INTERNAL);
580           return rc;
581         }
582     }
583   else
584     {
585       err = npth_mutex_trylock (&entry_lock);
586       if (err)
587         return gpg_error (GPG_ERR_LOCKED);
588     }
589
590   err = npth_mutex_unlock (&entry_lock);
591   if (err)
592     log_error ("failed to release the entry lock at %d: %s\n", __LINE__,
593                strerror (errno));
594   return 0;
595 }
596
597
598 static gpg_error_t
599 getpin_cb (void *opaque, const void *buffer, size_t length)
600 {
601   struct entry_parm_s *parm = opaque;
602
603   if (!buffer)
604     return 0;
605
606   /* we expect the pin to fit on one line */
607   if (parm->lines || length >= parm->size)
608     return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
609
610   /* fixme: we should make sure that the assuan buffer is allocated in
611      secure memory or read the response byte by byte */
612   memcpy (parm->buffer, buffer, length);
613   parm->buffer[length] = 0;
614   parm->lines++;
615   return 0;
616 }
617
618
619 static int
620 all_digitsp( const char *s)
621 {
622   for (; *s && *s >= '0' && *s <= '9'; s++)
623     ;
624   return !*s;
625 }
626
627
628 /* Return a new malloced string by unescaping the string S.  Escaping
629    is percent escaping and '+'/space mapping.  A binary Nul will
630    silently be replaced by a 0xFF.  Function returns NULL to indicate
631    an out of memory status.  Parsing stops at the end of the string or
632    a white space character. */
633 static char *
634 unescape_passphrase_string (const unsigned char *s)
635 {
636   char *buffer, *d;
637
638   buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
639   if (!buffer)
640     return NULL;
641   while (*s && !spacep (s))
642     {
643       if (*s == '%' && s[1] && s[2])
644         {
645           s++;
646           *d = xtoi_2 (s);
647           if (!*d)
648             *d = '\xff';
649           d++;
650           s += 2;
651         }
652       else if (*s == '+')
653         {
654           *d++ = ' ';
655           s++;
656         }
657       else
658         *d++ = *s++;
659     }
660   *d = 0;
661   return buffer;
662 }
663
664
665 /* Estimate the quality of the passphrase PW and return a value in the
666    range 0..100.  */
667 static int
668 estimate_passphrase_quality (const char *pw)
669 {
670   int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
671   int length;
672   const char *s;
673
674   if (goodlength < 1)
675     return 0;
676
677   for (length = 0, s = pw; *s; s++)
678     if (!spacep (s))
679       length ++;
680
681   if (length > goodlength)
682     return 100;
683   return ((length*10) / goodlength)*10;
684 }
685
686
687 /* Handle the QUALITY inquiry. */
688 static gpg_error_t
689 inq_quality (void *opaque, const char *line)
690 {
691   assuan_context_t ctx = opaque;
692   const char *s;
693   char *pin;
694   int rc;
695   int percent;
696   char numbuf[20];
697
698   if ((s = has_leading_keyword (line, "QUALITY")))
699     {
700       pin = unescape_passphrase_string (s);
701       if (!pin)
702         rc = gpg_error_from_syserror ();
703       else
704         {
705           percent = estimate_passphrase_quality (pin);
706           if (check_passphrase_constraints (NULL, pin, NULL))
707             percent = -percent;
708           snprintf (numbuf, sizeof numbuf, "%d", percent);
709           rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
710           xfree (pin);
711         }
712     }
713   else
714     {
715       log_error ("unsupported inquiry '%s' from pinentry\n", line);
716       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
717     }
718
719   return rc;
720 }
721
722
723 /* Helper for agent_askpin and agent_get_passphrase.  */
724 static gpg_error_t
725 setup_qualitybar (ctrl_t ctrl)
726 {
727   int rc;
728   char line[ASSUAN_LINELENGTH];
729   char *tmpstr, *tmpstr2;
730   const char *tooltip;
731
732   (void)ctrl;
733
734   /* TRANSLATORS: This string is displayed by Pinentry as the label
735      for the quality bar.  */
736   tmpstr = try_percent_escape (L_("Quality:"), "\t\r\n\f\v");
737   snprintf (line, DIM(line)-1, "SETQUALITYBAR %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   tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
748   if (tmpstr2)
749     tooltip = tmpstr2;
750   else
751     {
752       /* TRANSLATORS: This string is a tooltip, shown by pinentry when
753          hovering over the quality bar.  Please use an appropriate
754          string to describe what this is about.  The length of the
755          tooltip is limited to about 900 characters.  If you do not
756          translate this entry, a default english text (see source)
757          will be used. */
758       tooltip =  L_("pinentry.qualitybar.tooltip");
759       if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
760         tooltip = ("The quality of the text entered above.\n"
761                    "Please ask your administrator for "
762                    "details about the criteria.");
763     }
764   tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
765   xfree (tmpstr2);
766   snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
767   line[DIM(line)-1] = 0;
768   xfree (tmpstr);
769   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
770   if (rc == 103 /*(Old assuan error code)*/
771           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
772     ; /* Ignore Unknown Command from old pinentry versions.  */
773   else if (rc)
774     return rc;
775
776   return 0;
777 }
778
779 enum
780   {
781     PINENTRY_STATUS_CLOSE_BUTTON = 1 << 0,
782     PINENTRY_STATUS_PIN_REPEATED = 1 << 8,
783     PINENTRY_STATUS_PASSWORD_FROM_CACHE = 1 << 9
784   };
785
786 /* Check the button_info line for a close action.  Also check for the
787    PIN_REPEATED flag.  */
788 static gpg_error_t
789 pinentry_status_cb (void *opaque, const char *line)
790 {
791   unsigned int *flag = opaque;
792   const char *args;
793
794   if ((args = has_leading_keyword (line, "BUTTON_INFO")))
795     {
796       if (!strcmp (args, "close"))
797         *flag |= PINENTRY_STATUS_CLOSE_BUTTON;
798     }
799   else if (has_leading_keyword (line, "PIN_REPEATED"))
800     {
801       *flag |= PINENTRY_STATUS_PIN_REPEATED;
802     }
803   else if (has_leading_keyword (line, "PASSWORD_FROM_CACHE"))
804     {
805       *flag |= PINENTRY_STATUS_PASSWORD_FROM_CACHE;
806     }
807
808   return 0;
809 }
810
811
812
813 \f
814 /* Call the Entry and ask for the PIN.  We do check for a valid PIN
815    number here and repeat it as long as we have invalid formed
816    numbers.  KEYINFO and CACHE_MODE are used to tell pinentry something
817    about the key. */
818 gpg_error_t
819 agent_askpin (ctrl_t ctrl,
820               const char *desc_text, const char *prompt_text,
821               const char *initial_errtext,
822               struct pin_entry_info_s *pininfo,
823               const char *keyinfo, cache_mode_t cache_mode)
824 {
825   gpg_error_t rc;
826   char line[ASSUAN_LINELENGTH];
827   struct entry_parm_s parm;
828   const char *errtext = NULL;
829   int is_pin = 0;
830   int saveflag;
831   unsigned int pinentry_status;
832
833   if (opt.batch)
834     return 0; /* fixme: we should return BAD PIN */
835
836   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
837     {
838       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
839         return gpg_error (GPG_ERR_CANCELED);
840       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
841         {
842           unsigned char *passphrase;
843           size_t size;
844
845           *pininfo->pin = 0; /* Reset the PIN. */
846           rc = pinentry_loopback(ctrl, "PASSPHRASE", &passphrase, &size,
847                   pininfo->max_length - 1);
848           if (rc)
849             return rc;
850
851           memcpy(&pininfo->pin, passphrase, size);
852           xfree(passphrase);
853           pininfo->pin[size] = 0;
854           if (pininfo->check_cb)
855             {
856               /* More checks by utilizing the optional callback. */
857               pininfo->cb_errtext = NULL;
858               rc = pininfo->check_cb (pininfo);
859             }
860           return rc;
861         }
862       return gpg_error(GPG_ERR_NO_PIN_ENTRY);
863     }
864
865   if (!pininfo || pininfo->max_length < 1)
866     return gpg_error (GPG_ERR_INV_VALUE);
867   if (!desc_text && pininfo->min_digits)
868     desc_text = L_("Please enter your PIN, so that the secret key "
869                    "can be unlocked for this session");
870   else if (!desc_text)
871     desc_text = L_("Please enter your passphrase, so that the secret key "
872                    "can be unlocked for this session");
873
874   if (prompt_text)
875     is_pin = !!strstr (prompt_text, "PIN");
876   else
877     is_pin = desc_text && strstr (desc_text, "PIN");
878
879   rc = start_pinentry (ctrl);
880   if (rc)
881     return rc;
882
883   /* If we have a KEYINFO string and are normal, user, or ssh cache
884      mode, we tell that the Pinentry so it may use it for own caching
885      purposes.  Most pinentries won't have this implemented and thus
886      we do not error out in this case.  */
887   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
888                   || cache_mode == CACHE_MODE_USER
889                   || cache_mode == CACHE_MODE_SSH))
890     snprintf (line, DIM(line)-1, "SETKEYINFO %c/%s",
891               cache_mode == CACHE_MODE_USER? 'u' :
892               cache_mode == CACHE_MODE_SSH? 's' : 'n',
893               keyinfo);
894   else
895     snprintf (line, DIM(line)-1, "SETKEYINFO --clear");
896
897   rc = assuan_transact (entry_ctx, line,
898                         NULL, NULL, NULL, NULL, NULL, NULL);
899   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
900     return unlock_pinentry (rc);
901
902   snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
903   line[DIM(line)-1] = 0;
904   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
905   if (rc)
906     return unlock_pinentry (rc);
907
908   snprintf (line, DIM(line)-1, "SETPROMPT %s",
909             prompt_text? prompt_text : is_pin? L_("PIN:") : L_("Passphrase:"));
910   line[DIM(line)-1] = 0;
911   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
912   if (rc)
913     return unlock_pinentry (rc);
914
915   /* If a passphrase quality indicator has been requested and a
916      minimum passphrase length has not been disabled, send the command
917      to the pinentry.  */
918   if (pininfo->with_qualitybar && opt.min_passphrase_len )
919     {
920       rc = setup_qualitybar (ctrl);
921       if (rc)
922         return unlock_pinentry (rc);
923     }
924
925   if (initial_errtext)
926     {
927       snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
928       line[DIM(line)-1] = 0;
929       rc = assuan_transact (entry_ctx, line,
930                             NULL, NULL, NULL, NULL, NULL, NULL);
931       if (rc)
932         return unlock_pinentry (rc);
933     }
934
935   if (pininfo->with_repeat)
936     {
937       snprintf (line, DIM(line)-1, "SETREPEATERROR %s",
938                 L_("does not match - try again"));
939       line[DIM(line)-1] = 0;
940       rc = assuan_transact (entry_ctx, line,
941                             NULL, NULL, NULL, NULL, NULL, NULL);
942       if (rc)
943         pininfo->with_repeat = 0; /* Pinentry does not support it.  */
944     }
945   pininfo->repeat_okay = 0;
946
947   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
948     {
949       memset (&parm, 0, sizeof parm);
950       parm.size = pininfo->max_length;
951       *pininfo->pin = 0; /* Reset the PIN. */
952       parm.buffer = (unsigned char*)pininfo->pin;
953
954       if (errtext)
955         {
956           /* TRANSLATORS: The string is appended to an error message in
957              the pinentry.  The %s is the actual error message, the
958              two %d give the current and maximum number of tries. */
959           snprintf (line, DIM(line)-1, L_("SETERROR %s (try %d of %d)"),
960                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
961           line[DIM(line)-1] = 0;
962           rc = assuan_transact (entry_ctx, line,
963                                 NULL, NULL, NULL, NULL, NULL, NULL);
964           if (rc)
965             return unlock_pinentry (rc);
966           errtext = NULL;
967         }
968
969       if (pininfo->with_repeat)
970         {
971           snprintf (line, DIM(line)-1, "SETREPEAT %s", L_("Repeat:"));
972           line[DIM(line)-1] = 0;
973           rc = assuan_transact (entry_ctx, line,
974                                 NULL, NULL, NULL, NULL, NULL, NULL);
975           if (rc)
976             return unlock_pinentry (rc);
977         }
978
979       saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
980       assuan_begin_confidential (entry_ctx);
981       pinentry_status = 0;
982       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
983                             inq_quality, entry_ctx,
984                             pinentry_status_cb, &pinentry_status);
985       assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
986       /* Most pinentries out in the wild return the old Assuan error code
987          for canceled which gets translated to an assuan Cancel error and
988          not to the code for a user cancel.  Fix this here. */
989       if (rc && gpg_err_source (rc)
990           && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
991         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
992
993
994       /* Change error code in case the window close button was clicked
995          to cancel the operation.  */
996       if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
997           && gpg_err_code (rc) == GPG_ERR_CANCELED)
998         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
999
1000       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
1001         errtext = is_pin? L_("PIN too long")
1002                         : L_("Passphrase too long");
1003       else if (rc)
1004         return unlock_pinentry (rc);
1005
1006       if (!errtext && pininfo->min_digits)
1007         {
1008           /* do some basic checks on the entered PIN. */
1009           if (!all_digitsp (pininfo->pin))
1010             errtext = L_("Invalid characters in PIN");
1011           else if (pininfo->max_digits
1012                    && strlen (pininfo->pin) > pininfo->max_digits)
1013             errtext = L_("PIN too long");
1014           else if (strlen (pininfo->pin) < pininfo->min_digits)
1015             errtext = L_("PIN too short");
1016         }
1017
1018       if (!errtext && pininfo->check_cb)
1019         {
1020           /* More checks by utilizing the optional callback. */
1021           pininfo->cb_errtext = NULL;
1022           rc = pininfo->check_cb (pininfo);
1023           if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1024               && pininfo->cb_errtext)
1025             errtext = pininfo->cb_errtext;
1026           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1027                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
1028             errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase"));
1029           else if (rc)
1030             return unlock_pinentry (rc);
1031         }
1032
1033       if (!errtext)
1034         {
1035           if (pininfo->with_repeat
1036               && (pinentry_status & PINENTRY_STATUS_PIN_REPEATED))
1037             pininfo->repeat_okay = 1;
1038           return unlock_pinentry (0); /* okay, got a PIN or passphrase */
1039         }
1040
1041       if ((pinentry_status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
1042         /* The password was read from the cache.  Don't count this
1043            against the retry count.  */
1044         pininfo->failed_tries --;
1045     }
1046
1047   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
1048                           : GPG_ERR_BAD_PASSPHRASE));
1049 }
1050
1051
1052 \f
1053 /* Ask for the passphrase using the supplied arguments.  The returned
1054    passphrase needs to be freed by the caller. */
1055 int
1056 agent_get_passphrase (ctrl_t ctrl,
1057                       char **retpass, const char *desc, const char *prompt,
1058                       const char *errtext, int with_qualitybar,
1059                       const char *keyinfo, cache_mode_t cache_mode)
1060 {
1061
1062   int rc;
1063   char line[ASSUAN_LINELENGTH];
1064   struct entry_parm_s parm;
1065   int saveflag;
1066   unsigned int pinentry_status;
1067
1068   *retpass = NULL;
1069   if (opt.batch)
1070     return gpg_error (GPG_ERR_BAD_PASSPHRASE);
1071
1072   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1073     {
1074       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1075         return gpg_error (GPG_ERR_CANCELED);
1076
1077       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
1078         {
1079           size_t size;
1080           size_t len = ASSUAN_LINELENGTH/2;
1081
1082           return pinentry_loopback (ctrl, "PASSPHRASE",
1083                                     (unsigned char **)retpass, &size, len);
1084         }
1085       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1086     }
1087
1088   rc = start_pinentry (ctrl);
1089   if (rc)
1090     return rc;
1091
1092   if (!prompt)
1093     prompt = desc && strstr (desc, "PIN")? L_("PIN:"): L_("Passphrase:");
1094
1095
1096   /* If we have a KEYINFO string and are normal, user, or ssh cache
1097      mode, we tell that the Pinentry so it may use it for own caching
1098      purposes.  Most pinentries won't have this implemented and thus
1099      we do not error out in this case.  */
1100   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1101                   || cache_mode == CACHE_MODE_USER
1102                   || cache_mode == CACHE_MODE_SSH))
1103     snprintf (line, DIM(line)-1, "SETKEYINFO %c/%s",
1104               cache_mode == CACHE_MODE_USER? 'u' :
1105               cache_mode == CACHE_MODE_SSH? 's' : 'n',
1106               keyinfo);
1107   else
1108     snprintf (line, DIM(line)-1, "SETKEYINFO --clear");
1109
1110   rc = assuan_transact (entry_ctx, line,
1111                         NULL, NULL, NULL, NULL, NULL, NULL);
1112   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
1113     return unlock_pinentry (rc);
1114
1115
1116   if (desc)
1117     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1118   else
1119     snprintf (line, DIM(line)-1, "RESET");
1120   line[DIM(line)-1] = 0;
1121   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1122   if (rc)
1123     return unlock_pinentry (rc);
1124
1125   snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
1126   line[DIM(line)-1] = 0;
1127   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1128   if (rc)
1129     return unlock_pinentry (rc);
1130
1131   if (with_qualitybar && opt.min_passphrase_len)
1132     {
1133       rc = setup_qualitybar (ctrl);
1134       if (rc)
1135         return unlock_pinentry (rc);
1136     }
1137
1138   if (errtext)
1139     {
1140       snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
1141       line[DIM(line)-1] = 0;
1142       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1143       if (rc)
1144         return unlock_pinentry (rc);
1145     }
1146
1147   memset (&parm, 0, sizeof parm);
1148   parm.size = ASSUAN_LINELENGTH/2 - 5;
1149   parm.buffer = gcry_malloc_secure (parm.size+10);
1150   if (!parm.buffer)
1151     return unlock_pinentry (out_of_core ());
1152
1153   saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
1154   assuan_begin_confidential (entry_ctx);
1155   pinentry_status = 0;
1156   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
1157                         inq_quality, entry_ctx,
1158                         pinentry_status_cb, &pinentry_status);
1159   assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
1160   /* Most pinentries out in the wild return the old Assuan error code
1161      for canceled which gets translated to an assuan Cancel error and
1162      not to the code for a user cancel.  Fix this here. */
1163   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1164     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1165   /* Change error code in case the window close button was clicked
1166      to cancel the operation.  */
1167   if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
1168       && gpg_err_code (rc) == GPG_ERR_CANCELED)
1169     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
1170
1171   if (rc)
1172     xfree (parm.buffer);
1173   else
1174     *retpass = parm.buffer;
1175   return unlock_pinentry (rc);
1176 }
1177
1178
1179 \f
1180 /* Pop up the PIN-entry, display the text and the prompt and ask the
1181    user to confirm this.  We return 0 for success, ie. the user
1182    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
1183    other error.  If WITH_CANCEL it true an extra cancel button is
1184    displayed to allow the user to easily return a GPG_ERR_CANCELED.
1185    if the Pinentry does not support this, the user can still cancel by
1186    closing the Pinentry window.  */
1187 int
1188 agent_get_confirmation (ctrl_t ctrl,
1189                         const char *desc, const char *ok,
1190                         const char *notok, int with_cancel)
1191 {
1192   int rc;
1193   char line[ASSUAN_LINELENGTH];
1194
1195   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1196     {
1197       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1198         return gpg_error (GPG_ERR_CANCELED);
1199
1200       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1201     }
1202
1203   rc = start_pinentry (ctrl);
1204   if (rc)
1205     return rc;
1206
1207   if (desc)
1208     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1209   else
1210     snprintf (line, DIM(line)-1, "RESET");
1211   line[DIM(line)-1] = 0;
1212   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1213   /* Most pinentries out in the wild return the old Assuan error code
1214      for canceled which gets translated to an assuan Cancel error and
1215      not to the code for a user cancel.  Fix this here. */
1216   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1217     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1218
1219   if (rc)
1220     return unlock_pinentry (rc);
1221
1222   if (ok)
1223     {
1224       snprintf (line, DIM(line)-1, "SETOK %s", ok);
1225       line[DIM(line)-1] = 0;
1226       rc = assuan_transact (entry_ctx,
1227                             line, NULL, NULL, NULL, NULL, NULL, NULL);
1228       if (rc)
1229         return unlock_pinentry (rc);
1230     }
1231   if (notok)
1232     {
1233       /* Try to use the newer NOTOK feature if a cancel button is
1234          requested.  If no cancel button is requested we keep on using
1235          the standard cancel.  */
1236       if (with_cancel)
1237         {
1238           snprintf (line, DIM(line)-1, "SETNOTOK %s", notok);
1239           line[DIM(line)-1] = 0;
1240           rc = assuan_transact (entry_ctx,
1241                                 line, NULL, NULL, NULL, NULL, NULL, NULL);
1242         }
1243       else
1244         rc = GPG_ERR_ASS_UNKNOWN_CMD;
1245
1246       if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
1247         {
1248           snprintf (line, DIM(line)-1, "SETCANCEL %s", notok);
1249           line[DIM(line)-1] = 0;
1250           rc = assuan_transact (entry_ctx, line,
1251                                 NULL, NULL, NULL, NULL, NULL, NULL);
1252         }
1253       if (rc)
1254         return unlock_pinentry (rc);
1255     }
1256
1257   rc = assuan_transact (entry_ctx, "CONFIRM",
1258                         NULL, NULL, NULL, NULL, NULL, NULL);
1259   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1260     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1261
1262   return unlock_pinentry (rc);
1263 }
1264
1265
1266 \f
1267 /* Pop up the PINentry, display the text DESC and a button with the
1268    text OK_BTN (which may be NULL to use the default of "OK") and wait
1269    for the user to hit this button.  The return value is not
1270    relevant.  */
1271 int
1272 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
1273 {
1274   int rc;
1275   char line[ASSUAN_LINELENGTH];
1276
1277   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1278     return gpg_error (GPG_ERR_CANCELED);
1279
1280   rc = start_pinentry (ctrl);
1281   if (rc)
1282     return rc;
1283
1284   if (desc)
1285     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1286   else
1287     snprintf (line, DIM(line)-1, "RESET");
1288   line[DIM(line)-1] = 0;
1289   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1290   /* Most pinentries out in the wild return the old Assuan error code
1291      for canceled which gets translated to an assuan Cancel error and
1292      not to the code for a user cancel.  Fix this here. */
1293   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1294     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1295
1296   if (rc)
1297     return unlock_pinentry (rc);
1298
1299   if (ok_btn)
1300     {
1301       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1302       line[DIM(line)-1] = 0;
1303       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
1304                             NULL, NULL, NULL);
1305       if (rc)
1306         return unlock_pinentry (rc);
1307     }
1308
1309   rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
1310                         NULL, NULL, NULL);
1311   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1312     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1313
1314   return unlock_pinentry (rc);
1315 }
1316
1317
1318 /* The thread running the popup message. */
1319 static void *
1320 popup_message_thread (void *arg)
1321 {
1322   (void)arg;
1323
1324   /* We use the --one-button hack instead of the MESSAGE command to
1325      allow the use of old Pinentries.  Those old Pinentries will then
1326      show an additional Cancel button but that is mostly a visual
1327      annoyance. */
1328   assuan_transact (entry_ctx, "CONFIRM --one-button",
1329                    NULL, NULL, NULL, NULL, NULL, NULL);
1330   popup_finished = 1;
1331   return NULL;
1332 }
1333
1334
1335 /* Pop up a message window similar to the confirm one but keep it open
1336    until agent_popup_message_stop has been called.  It is crucial for
1337    the caller to make sure that the stop function gets called as soon
1338    as the message is not anymore required because the message is
1339    system modal and all other attempts to use the pinentry will fail
1340    (after a timeout). */
1341 int
1342 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
1343 {
1344   int rc;
1345   char line[ASSUAN_LINELENGTH];
1346   npth_attr_t tattr;
1347   int err;
1348
1349   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1350     return gpg_error (GPG_ERR_CANCELED);
1351
1352   rc = start_pinentry (ctrl);
1353   if (rc)
1354     return rc;
1355
1356   if (desc)
1357     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1358   else
1359     snprintf (line, DIM(line)-1, "RESET");
1360   line[DIM(line)-1] = 0;
1361   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1362   if (rc)
1363     return unlock_pinentry (rc);
1364
1365   if (ok_btn)
1366     {
1367       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1368       line[DIM(line)-1] = 0;
1369       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1370       if (rc)
1371         return unlock_pinentry (rc);
1372     }
1373
1374   err = npth_attr_init (&tattr);
1375   if (err)
1376     return unlock_pinentry (gpg_error_from_errno (err));
1377   npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
1378
1379   popup_finished = 0;
1380   err = npth_create (&popup_tid, &tattr, popup_message_thread, NULL);
1381   npth_attr_destroy (&tattr);
1382   if (err)
1383     {
1384       rc = gpg_error_from_errno (err);
1385       log_error ("error spawning popup message handler: %s\n",
1386                  strerror (err) );
1387       return unlock_pinentry (rc);
1388     }
1389   npth_setname_np (popup_tid, "popup-message");
1390
1391   return 0;
1392 }
1393
1394 /* Close a popup window. */
1395 void
1396 agent_popup_message_stop (ctrl_t ctrl)
1397 {
1398   int rc;
1399   pid_t pid;
1400
1401   (void)ctrl;
1402
1403   if (!popup_tid || !entry_ctx)
1404     {
1405       log_debug ("agent_popup_message_stop called with no active popup\n");
1406       return;
1407     }
1408
1409   pid = assuan_get_pid (entry_ctx);
1410   if (pid == (pid_t)(-1))
1411     ; /* No pid available can't send a kill. */
1412   else if (popup_finished)
1413     ; /* Already finished and ready for joining. */
1414 #ifdef HAVE_W32_SYSTEM
1415   /* Older versions of assuan set PID to 0 on Windows to indicate an
1416      invalid value.  */
1417   else if (pid != (pid_t) INVALID_HANDLE_VALUE
1418            && pid != 0)
1419     {
1420       HANDLE process = (HANDLE) pid;
1421
1422       /* Arbitrary error code.  */
1423       TerminateProcess (process, 1);
1424     }
1425 #else
1426   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1427     { /* The daemon already died.  No need to send a kill.  However
1428          because we already waited for the process, we need to tell
1429          assuan that it should not wait again (done by
1430          unlock_pinentry). */
1431       if (rc == pid)
1432         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1433     }
1434   else if (pid > 0)
1435     kill (pid, SIGINT);
1436 #endif
1437
1438   /* Now wait for the thread to terminate. */
1439   rc = npth_join (popup_tid, NULL);
1440   if (rc)
1441     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1442                strerror (rc));
1443   /* Thread IDs are opaque, but we try our best here by resetting it
1444      to the same content that a static global variable has.  */
1445   memset (&popup_tid, '\0', sizeof (popup_tid));
1446   entry_owner = NULL;
1447
1448   /* Now we can close the connection. */
1449   unlock_pinentry (0);
1450 }
1451
1452 int
1453 agent_clear_passphrase (ctrl_t ctrl,
1454                         const char *keyinfo, cache_mode_t cache_mode)
1455 {
1456   int rc;
1457   char line[ASSUAN_LINELENGTH];
1458
1459   if (! (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1460                      || cache_mode == CACHE_MODE_USER
1461                      || cache_mode == CACHE_MODE_SSH)))
1462     return gpg_error (GPG_ERR_NOT_SUPPORTED);
1463
1464   rc = start_pinentry (ctrl);
1465   if (rc)
1466     return rc;
1467
1468   snprintf (line, DIM(line)-1, "CLEARPASSPHRASE %c/%s",
1469             cache_mode == CACHE_MODE_USER? 'u' :
1470             cache_mode == CACHE_MODE_SSH? 's' : 'n',
1471             keyinfo);
1472   rc = assuan_transact (entry_ctx, line,
1473                         NULL, NULL, NULL, NULL, NULL, NULL);
1474
1475   return unlock_pinentry (rc);
1476 }