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