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