Fix bug #1053
[gnupg.git] / agent / call-pinentry.c
1 /* call-pinentry.c - fork of the pinentry to query stuff from the user
2  * Copyright (C) 2001, 2002, 2004, 2007, 2008 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <assert.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #ifndef HAVE_W32_SYSTEM
30 # include <sys/wait.h>
31 # include <sys/types.h>
32 # include <signal.h>
33 #endif
34 #include <pth.h>
35 #include <assuan.h>
36
37 #include "agent.h"
38 #include "setenv.h"
39 #include "i18n.h"
40
41 #ifdef _POSIX_OPEN_MAX
42 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
43 #else
44 #define MAX_OPEN_FDS 20
45 #endif
46
47
48 /* Because access to the pinentry must be serialized (it is and shall
49    be a global mutual dialog) we should better timeout further
50    requests after some time.  2 minutes seem to be a reasonable
51    time. */
52 #define LOCK_TIMEOUT  (1*60)
53
54 /* The assuan context of the current pinentry. */
55 static assuan_context_t entry_ctx;
56
57 /* The control variable of the connection owning the current pinentry.
58    This is only valid if ENTRY_CTX is not NULL.  Note, that we care
59    only about the value of the pointer and that it should never be
60    dereferenced.  */
61 static ctrl_t entry_owner;
62
63 /* A mutex used to serialize access to the pinentry. */
64 static pth_mutex_t entry_lock;
65
66 /* The thread ID of the popup working thread. */
67 static pth_t  popup_tid;
68
69 /* A flag used in communication between the popup working thread and
70    its stop function. */
71 static int popup_finished;
72
73
74
75 /* Data to be passed to our callbacks, */
76 struct entry_parm_s
77 {
78   int lines;
79   size_t size;
80   unsigned char *buffer;
81 };
82
83
84
85 \f
86 /* This function must be called once to initialize this module.  This
87    has to be done before a second thread is spawned.  We can't do the
88    static initialization because Pth emulation code might not be able
89    to do a static init; in particular, it is not possible for W32. */
90 void
91 initialize_module_call_pinentry (void)
92 {
93   static int initialized;
94
95   if (!initialized)
96     {
97       if (pth_mutex_init (&entry_lock))
98         initialized = 1;
99     }
100 }
101
102
103
104 static void
105 dump_mutex_state (pth_mutex_t *m)
106 {
107 #ifdef _W32_PTH_H
108   (void)m;
109   log_printf ("unknown under W32");
110 #else
111   if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
112     log_printf ("not_initialized");
113   else if (!(m->mx_state & PTH_MUTEX_LOCKED))
114     log_printf ("not_locked");
115   else
116     log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
117 #endif
118 }
119
120
121 /* This function may be called to print infromation pertaining to the
122    current state of this module to the log. */
123 void
124 agent_query_dump_state (void)
125 {
126   log_info ("agent_query_dump_state: entry_lock=");
127   dump_mutex_state (&entry_lock);
128   log_printf ("\n");
129   log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
130             entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid);
131 }
132
133 /* Called to make sure that a popup window owned by the current
134    connection gets closed. */
135 void
136 agent_reset_query (ctrl_t ctrl)
137 {
138   if (entry_ctx && popup_tid && entry_owner == ctrl)
139     {
140       agent_popup_message_stop (ctrl);
141     }
142 }
143
144
145 /* Unlock the pinentry so that another thread can start one and
146    disconnect that pinentry - we do this after the unlock so that a
147    stalled pinentry does not block other threads.  Fixme: We should
148    have a timeout in Assuan for the disconnect operation. */
149 static int 
150 unlock_pinentry (int rc)
151 {
152   assuan_context_t ctx = entry_ctx;
153
154   entry_ctx = NULL;
155   if (!pth_mutex_release (&entry_lock))
156     {
157       log_error ("failed to release the entry lock\n");
158       if (!rc)
159         rc = gpg_error (GPG_ERR_INTERNAL);
160     }
161   assuan_disconnect (ctx);
162   return rc;
163 }
164
165
166 /* To make sure we leave no secrets in our image after forking of the
167    pinentry, we use this callback. */
168 static void
169 atfork_cb (void *opaque, int where)
170 {
171   ctrl_t ctrl = opaque;
172
173   if (!where)
174     {
175       gcry_control (GCRYCTL_TERM_SECMEM);
176       if (ctrl->xauthority)
177         setenv ("XAUTHORITY", ctrl->xauthority, 1);
178       if (ctrl->pinentry_user_data)
179         setenv ("PINENTRY_USER_DATA", ctrl->pinentry_user_data, 1 );
180     }
181 }
182
183 static int
184 getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
185 {
186   unsigned long *pid = opaque;
187   char pidbuf[50];
188
189   /* There is only the pid in the server's response.  */
190   if (length >= sizeof pidbuf)
191     length = sizeof pidbuf -1;
192   if (length)
193     {
194       strncpy (pidbuf, buffer, length);
195       pidbuf[length] = 0;
196       *pid = strtoul (pidbuf, NULL, 10);
197     }
198   return 0;
199 }
200
201 /* Fork off the pin entry if this has not already been done.  Note,
202    that this function must always be used to aquire the lock for the
203    pinentry - we will serialize _all_ pinentry calls.
204  */
205 static int
206 start_pinentry (ctrl_t ctrl)
207 {
208   int rc;
209   const char *pgmname;
210   assuan_context_t ctx;
211   const char *argv[5];
212   int no_close_list[3];
213   int i;
214   pth_event_t evt;
215   const char *tmpstr;
216   unsigned long pinentry_pid;
217
218   evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
219   if (!pth_mutex_acquire (&entry_lock, 0, evt))
220     {
221       if (pth_event_occurred (evt))
222         rc = gpg_error (GPG_ERR_TIMEOUT);
223       else
224         rc = gpg_error (GPG_ERR_INTERNAL);
225       pth_event_free (evt, PTH_FREE_THIS);
226       log_error (_("failed to acquire the pinentry lock: %s\n"),
227                  gpg_strerror (rc));
228       return rc;
229     }
230   pth_event_free (evt, PTH_FREE_THIS);
231
232   entry_owner = ctrl;
233
234   if (entry_ctx)
235     return 0; 
236
237   if (opt.verbose)
238     log_info ("starting a new PIN Entry\n");
239
240 #ifdef HAVE_W32_SYSTEM      
241   fflush (stdout);
242   fflush (stderr);
243 #endif
244   if (fflush (NULL))
245     {
246 #ifndef HAVE_W32_SYSTEM
247       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
248 #endif
249       log_error ("error flushing pending output: %s\n", strerror (errno));
250       /* At least Windows XP fails here with EBADF.  According to docs
251          and Wine an fflush(NULL) is the same as _flushall.  However
252          the Wime implementaion does not flush stdin,stdout and stderr
253          - see above.  Lets try to ignore the error. */
254 #ifndef HAVE_W32_SYSTEM
255       return unlock_pinentry (tmperr);
256 #endif
257     }
258
259   if (!opt.pinentry_program || !*opt.pinentry_program)
260     opt.pinentry_program = gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY);
261     pgmname = opt.pinentry_program;
262   if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
263     pgmname = opt.pinentry_program;
264   else
265     pgmname++;
266
267   /* OS X needs the entire file name in argv[0], so that it can locate
268      the resource bundle.  For other systems we stick to the usual
269      convention of supplying only the name of the program.  */
270 #ifdef __APPLE__
271   argv[0] = opt.pinentry_program;
272 #else /*!__APPLE__*/
273   argv[0] = pgmname;
274 #endif /*__APPLE__*/
275
276   if (ctrl->display && !opt.keep_display)
277     {
278       argv[1] = "--display";
279       argv[2] = ctrl->display;
280       argv[3] = NULL;
281     }
282   else
283     argv[1] = NULL;
284   
285   i=0;
286   if (!opt.running_detached)
287     {
288       if (log_get_fd () != -1)
289         no_close_list[i++] = log_get_fd ();
290       no_close_list[i++] = fileno (stderr);
291     }
292   no_close_list[i] = -1;
293
294   /* Connect to the pinentry and perform initial handshaking.  Note
295      that atfork is used to change the environment for pinentry.  We
296      start the server in detached mode to suppress the console window
297      under Windows.  */
298   rc = assuan_pipe_connect_ext (&ctx, opt.pinentry_program, argv,
299                                 no_close_list, atfork_cb, ctrl, 128);
300   if (rc)
301     {
302       log_error ("can't connect to the PIN entry module: %s\n",
303                  gpg_strerror (rc));
304       return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
305     }
306   entry_ctx = ctx;
307
308   if (DBG_ASSUAN)
309     log_debug ("connection to PIN entry established\n");
310
311   rc = assuan_transact (entry_ctx, 
312                         opt.no_grab? "OPTION no-grab":"OPTION grab",
313                         NULL, NULL, NULL, NULL, NULL, NULL);
314   if (rc)
315     return unlock_pinentry (rc);
316   if (ctrl->ttyname)
317     {
318       char *optstr;
319       if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
320         return unlock_pinentry (out_of_core ());
321       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
322                             NULL);
323       xfree (optstr);
324       if (rc)
325         return unlock_pinentry (rc);
326     }
327   if (ctrl->ttytype)
328     {
329       char *optstr;
330       if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
331         return unlock_pinentry (out_of_core ());
332       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
333                             NULL);
334       if (rc)
335         return unlock_pinentry (rc);
336     }
337   if (ctrl->lc_ctype)
338     {
339       char *optstr;
340       if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
341         return unlock_pinentry (out_of_core ());
342       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
343                             NULL);
344       if (rc)
345         return unlock_pinentry (rc);
346     }
347   if (ctrl->lc_messages)
348     {
349       char *optstr;
350       if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
351         return unlock_pinentry (out_of_core ());
352       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
353                             NULL);
354       if (rc)
355         return unlock_pinentry (rc);
356     }
357
358   
359   /* Tell the pinentry the name of a file it shall touch after having
360      messed with the tty.  This is optional and only supported by
361      newer pinentries and thus we do no error checking. */
362   tmpstr = opt.pinentry_touch_file;
363   if (tmpstr && !strcmp (tmpstr, "/dev/null"))
364     tmpstr = NULL;
365   else if (!tmpstr)
366     tmpstr = get_agent_socket_name ();
367   if (tmpstr)
368     {
369       char *optstr;
370       
371       if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
372         ;
373       else
374         {
375           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
376                            NULL);
377           xfree (optstr);
378         }
379     }
380
381
382   /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
383      it will send the pid back and we will use an inquire to notify
384      our client.  The client may answer the inquiry either with END or
385      with CAN to cancel the pinentry. */
386   rc = assuan_transact (entry_ctx, "GETINFO pid", 
387                         getinfo_pid_cb, &pinentry_pid,
388                         NULL, NULL, NULL, NULL);
389   if (rc)
390     {
391       log_info ("You may want to update to a newer pinentry\n");
392       rc = 0;
393     }
394   else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
395     log_error ("pinentry did not return a PID\n");
396   else
397     {
398       rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
399       if (gpg_err_code (rc) == GPG_ERR_CANCELED)
400         return unlock_pinentry (gpg_error (GPG_ERR_CANCELED));
401       rc = 0;
402     }
403
404   return 0;
405 }
406
407
408 /* Returns True is the pinentry is currently active. If WAITSECONDS is
409    greater than zero the function will wait for this many seconds
410    before returning.  */
411 int
412 pinentry_active_p (ctrl_t ctrl, int waitseconds)
413 {
414   (void)ctrl;
415
416   if (waitseconds > 0)
417     {
418       pth_event_t evt;
419       int rc;
420
421       evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
422       if (!pth_mutex_acquire (&entry_lock, 0, evt))
423         {
424           if (pth_event_occurred (evt))
425             rc = gpg_error (GPG_ERR_TIMEOUT);
426           else
427             rc = gpg_error (GPG_ERR_INTERNAL);
428           pth_event_free (evt, PTH_FREE_THIS);
429           return rc;
430         }
431       pth_event_free (evt, PTH_FREE_THIS);
432     }
433   else
434     {
435       if (!pth_mutex_acquire (&entry_lock, 1, NULL))
436         return gpg_error (GPG_ERR_LOCKED);
437     }
438
439   if (!pth_mutex_release (&entry_lock))
440     log_error ("failed to release the entry lock at %d\n", __LINE__);
441   return 0;
442 }
443
444
445 static int
446 getpin_cb (void *opaque, const void *buffer, size_t length)
447 {
448   struct entry_parm_s *parm = opaque;
449
450   if (!buffer)
451     return 0;
452
453   /* we expect the pin to fit on one line */
454   if (parm->lines || length >= parm->size)
455     return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
456
457   /* fixme: we should make sure that the assuan buffer is allocated in
458      secure memory or read the response byte by byte */
459   memcpy (parm->buffer, buffer, length);
460   parm->buffer[length] = 0;
461   parm->lines++;
462   return 0;
463 }
464
465
466 static int
467 all_digitsp( const char *s)
468 {
469   for (; *s && *s >= '0' && *s <= '9'; s++)
470     ;
471   return !*s;
472 }  
473
474
475 /* Return a new malloced string by unescaping the string S.  Escaping
476    is percent escaping and '+'/space mapping.  A binary Nul will
477    silently be replaced by a 0xFF.  Function returns NULL to indicate
478    an out of memory status.  PArsing stops at the end of the string or
479    a white space character. */
480 static char *
481 unescape_passphrase_string (const unsigned char *s)
482 {
483   char *buffer, *d;
484
485   buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
486   if (!buffer)
487     return NULL;
488   while (*s && !spacep (s))
489     {
490       if (*s == '%' && s[1] && s[2])
491         { 
492           s++;
493           *d = xtoi_2 (s);
494           if (!*d)
495             *d = '\xff';
496           d++;
497           s += 2;
498         }
499       else if (*s == '+')
500         {
501           *d++ = ' ';
502           s++;
503         }
504       else
505         *d++ = *s++;
506     }
507   *d = 0; 
508   return buffer;
509 }
510
511
512 /* Estimate the quality of the passphrase PW and return a value in the
513    range 0..100.  */
514 static int
515 estimate_passphrase_quality (const char *pw)
516 {
517   int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
518   int length;
519   const char *s;
520
521   if (goodlength < 1)
522     return 0;
523
524   for (length = 0, s = pw; *s; s++)
525     if (!spacep (s))
526       length ++;
527
528   if (length > goodlength)
529     return 100;
530   return ((length*10) / goodlength)*10;
531 }
532
533
534 /* Handle the QUALITY inquiry. */
535 static int
536 inq_quality (void *opaque, const char *line)
537 {
538   assuan_context_t ctx = opaque;
539   char *pin;
540   int rc;
541   int percent;
542   char numbuf[20];
543
544   if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
545     {
546       line += 7;
547       while (*line == ' ')
548         line++;
549       
550       pin = unescape_passphrase_string (line);
551       if (!pin)
552         rc = gpg_error_from_syserror ();
553       else
554         {
555           percent = estimate_passphrase_quality (pin);
556           if (check_passphrase_constraints (NULL, pin, 1))
557             percent = -percent;
558           snprintf (numbuf, sizeof numbuf, "%d", percent);
559           rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
560           xfree (pin);
561         }
562     }
563   else
564     {
565       log_error ("unsupported inquiry `%s' from pinentry\n", line);
566       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
567     }
568
569   return rc;
570 }
571
572
573 /* Helper for agent_askpin and agent_get_passphrase.  */
574 static int
575 setup_qualitybar (void)
576 {
577   int rc;
578   char line[ASSUAN_LINELENGTH];
579   char *tmpstr, *tmpstr2;
580   const char *tooltip;
581   
582   /* TRANSLATORS: This string is displayed by Pinentry as the label
583      for the quality bar.  */
584   tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
585   snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
586   line[DIM(line)-1] = 0;
587   xfree (tmpstr);
588   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
589   if (rc == 103 /*(Old assuan error code)*/
590       || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
591     ; /* Ignore Unknown Command from old Pinentry versions.  */
592   else if (rc)
593     return rc;
594   
595   tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
596   if (tmpstr2)
597     tooltip = tmpstr2;
598   else
599     {
600       /* TRANSLATORS: This string is a tooltip, shown by pinentry when
601          hovering over the quality bar.  Please use an appropriate
602          string to describe what this is about.  The length of the
603          tooltip is limited to about 900 characters.  If you do not
604          translate this entry, a default english text (see source)
605          will be used. */
606       tooltip =  _("pinentry.qualitybar.tooltip");
607       if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
608         tooltip = ("The quality of the text entered above.\n"
609                    "Please ask your administrator for "
610                    "details about the criteria.");
611     }
612   tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
613   xfree (tmpstr2);
614   snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
615   line[DIM(line)-1] = 0;
616   xfree (tmpstr);
617   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
618   if (rc == 103 /*(Old assuan error code)*/
619           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
620     ; /* Ignore Unknown Command from old pinentry versions.  */
621   else if (rc)
622     return rc;
623
624   return 0;
625 }
626
627
628 \f
629 /* Call the Entry and ask for the PIN.  We do check for a valid PIN
630    number here and repeat it as long as we have invalid formed
631    numbers. */
632 int
633 agent_askpin (ctrl_t ctrl,
634               const char *desc_text, const char *prompt_text,
635               const char *initial_errtext,
636               struct pin_entry_info_s *pininfo)
637 {
638   int rc;
639   char line[ASSUAN_LINELENGTH];
640   struct entry_parm_s parm;
641   const char *errtext = NULL;
642   int is_pin = 0;
643
644   if (opt.batch)
645     return 0; /* fixme: we should return BAD PIN */
646
647   if (!pininfo || pininfo->max_length < 1)
648     return gpg_error (GPG_ERR_INV_VALUE);
649   if (!desc_text && pininfo->min_digits)
650     desc_text = _("Please enter your PIN, so that the secret key "
651                   "can be unlocked for this session");
652   else if (!desc_text)
653     desc_text = _("Please enter your passphrase, so that the secret key "
654                   "can be unlocked for this session");
655
656   if (prompt_text)
657     is_pin = !!strstr (prompt_text, "PIN");
658   else
659     is_pin = desc_text && strstr (desc_text, "PIN");
660
661   rc = start_pinentry (ctrl);
662   if (rc)
663     return rc;
664
665   snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
666   line[DIM(line)-1] = 0;
667   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
668   if (rc)
669     return unlock_pinentry (rc);
670
671   snprintf (line, DIM(line)-1, "SETPROMPT %s",
672             prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
673   line[DIM(line)-1] = 0;
674   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
675   if (rc)
676     return unlock_pinentry (rc);
677
678   /* If a passphrase quality indicator has been requested and a
679      minimum passphrase length has not been disabled, send the command
680      to the pinentry.  */
681   if (pininfo->with_qualitybar && opt.min_passphrase_len )
682     {
683       rc = setup_qualitybar ();
684       if (rc)
685         return unlock_pinentry (rc);
686     }
687
688   if (initial_errtext)
689     { 
690       snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
691       line[DIM(line)-1] = 0;
692       rc = assuan_transact (entry_ctx, line,
693                             NULL, NULL, NULL, NULL, NULL, NULL);
694       if (rc)
695         return unlock_pinentry (rc);
696     }
697
698   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
699     {
700       memset (&parm, 0, sizeof parm);
701       parm.size = pininfo->max_length;
702       *pininfo->pin = 0; /* Reset the PIN. */
703       parm.buffer = (unsigned char*)pininfo->pin;
704
705       if (errtext)
706         { 
707           /* TRANLATORS: The string is appended to an error message in
708              the pinentry.  The %s is the actual error message, the
709              two %d give the current and maximum number of tries. */
710           snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
711                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
712           line[DIM(line)-1] = 0;
713           rc = assuan_transact (entry_ctx, line,
714                                 NULL, NULL, NULL, NULL, NULL, NULL);
715           if (rc)
716             return unlock_pinentry (rc);
717           errtext = NULL;
718         }
719       
720       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
721                             inq_quality, entry_ctx, NULL, NULL);
722       /* Most pinentries out in the wild return the old Assuan error code
723          for canceled which gets translated to an assuan Cancel error and
724          not to the code for a user cancel.  Fix this here. */
725       if (rc && gpg_err_source (rc)
726           && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
727         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
728
729       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
730         errtext = is_pin? _("PIN too long")
731                         : _("Passphrase too long");
732       else if (rc)
733         return unlock_pinentry (rc);
734
735       if (!errtext && pininfo->min_digits)
736         {
737           /* do some basic checks on the entered PIN. */
738           if (!all_digitsp (pininfo->pin))
739             errtext = _("Invalid characters in PIN");
740           else if (pininfo->max_digits
741                    && strlen (pininfo->pin) > pininfo->max_digits)
742             errtext = _("PIN too long");
743           else if (strlen (pininfo->pin) < pininfo->min_digits)
744             errtext = _("PIN too short");
745         }
746
747       if (!errtext && pininfo->check_cb)
748         {
749           /* More checks by utilizing the optional callback. */
750           pininfo->cb_errtext = NULL;
751           rc = pininfo->check_cb (pininfo);
752           if (rc == -1 && pininfo->cb_errtext)
753             errtext = pininfo->cb_errtext;
754           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
755                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
756             errtext = (is_pin? _("Bad PIN")
757                        : _("Bad Passphrase"));
758           else if (rc)
759             return unlock_pinentry (rc);
760         }
761
762       if (!errtext)
763         return unlock_pinentry (0); /* okay, got a PIN or passphrase */
764     }
765
766   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
767                           : GPG_ERR_BAD_PASSPHRASE));
768 }
769
770
771 \f
772 /* Ask for the passphrase using the supplied arguments.  The returned
773    passphrase needs to be freed by the caller. */
774 int 
775 agent_get_passphrase (ctrl_t ctrl,
776                       char **retpass, const char *desc, const char *prompt,
777                       const char *errtext, int with_qualitybar)
778 {
779
780   int rc;
781   char line[ASSUAN_LINELENGTH];
782   struct entry_parm_s parm;
783
784   *retpass = NULL;
785   if (opt.batch)
786     return gpg_error (GPG_ERR_BAD_PASSPHRASE); 
787
788   rc = start_pinentry (ctrl);
789   if (rc)
790     return rc;
791
792   if (!prompt)
793     prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
794
795
796   if (desc)
797     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
798   else
799     snprintf (line, DIM(line)-1, "RESET");
800   line[DIM(line)-1] = 0;
801   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
802   if (rc)
803     return unlock_pinentry (rc);
804
805   snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
806   line[DIM(line)-1] = 0;
807   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
808   if (rc)
809     return unlock_pinentry (rc);
810
811   if (with_qualitybar && opt.min_passphrase_len)
812     {
813       rc = setup_qualitybar ();
814       if (rc)
815         return unlock_pinentry (rc);
816     }
817
818   if (errtext)
819     {
820       snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
821       line[DIM(line)-1] = 0;
822       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
823       if (rc)
824         return unlock_pinentry (rc);
825     }
826
827   memset (&parm, 0, sizeof parm);
828   parm.size = ASSUAN_LINELENGTH/2 - 5;
829   parm.buffer = gcry_malloc_secure (parm.size+10);
830   if (!parm.buffer)
831     return unlock_pinentry (out_of_core ());
832
833   assuan_begin_confidential (entry_ctx);
834   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
835                         inq_quality, entry_ctx, NULL, NULL);
836   /* Most pinentries out in the wild return the old Assuan error code
837      for canceled which gets translated to an assuan Cancel error and
838      not to the code for a user cancel.  Fix this here. */
839   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
840     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
841   if (rc)
842     xfree (parm.buffer);
843   else
844     *retpass = parm.buffer;
845   return unlock_pinentry (rc);
846 }
847
848
849 \f
850 /* Pop up the PIN-entry, display the text and the prompt and ask the
851    user to confirm this.  We return 0 for success, ie. the user
852    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
853    other error. */
854 int 
855 agent_get_confirmation (ctrl_t ctrl,
856                         const char *desc, const char *ok, const char *cancel)
857 {
858   int rc;
859   char line[ASSUAN_LINELENGTH];
860
861   rc = start_pinentry (ctrl);
862   if (rc)
863     return rc;
864
865   if (desc)
866     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
867   else
868     snprintf (line, DIM(line)-1, "RESET");
869   line[DIM(line)-1] = 0;
870   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
871   /* Most pinentries out in the wild return the old Assuan error code
872      for canceled which gets translated to an assuan Cancel error and
873      not to the code for a user cancel.  Fix this here. */
874   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
875     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
876
877   if (rc)
878     return unlock_pinentry (rc);
879
880   if (ok)
881     {
882       snprintf (line, DIM(line)-1, "SETOK %s", ok);
883       line[DIM(line)-1] = 0;
884       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
885       if (rc)
886         return unlock_pinentry (rc);
887     }
888   if (cancel)
889     {
890       snprintf (line, DIM(line)-1, "SETNOTOK %s", cancel);
891       line[DIM(line)-1] = 0;
892       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
893       if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
894         {
895           snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel);
896           line[DIM(line)-1] = 0;
897           rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
898         }
899       if (rc)
900         return unlock_pinentry (rc);
901     }
902
903   rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
904   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
905     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
906
907   return unlock_pinentry (rc);
908 }
909
910
911 \f
912 /* Pop up the PINentry, display the text DESC and a button with the
913    text OK_BTN (which may be NULL to use the default of "OK") and waut
914    for the user to hit this button.  The return value is not
915    relevant.  */
916 int 
917 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
918 {
919   int rc;
920   char line[ASSUAN_LINELENGTH];
921
922   rc = start_pinentry (ctrl);
923   if (rc)
924     return rc;
925
926   if (desc)
927     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
928   else
929     snprintf (line, DIM(line)-1, "RESET");
930   line[DIM(line)-1] = 0;
931   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
932   /* Most pinentries out in the wild return the old Assuan error code
933      for canceled which gets translated to an assuan Cancel error and
934      not to the code for a user cancel.  Fix this here. */
935   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
936     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
937
938   if (rc)
939     return unlock_pinentry (rc);
940
941   if (ok_btn)
942     {
943       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
944       line[DIM(line)-1] = 0;
945       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
946                             NULL, NULL, NULL);
947       if (rc)
948         return unlock_pinentry (rc);
949     }
950   
951   rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
952                         NULL, NULL, NULL);
953   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
954     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
955
956   return unlock_pinentry (rc);
957 }
958
959
960 /* The thread running the popup message. */
961 static void *
962 popup_message_thread (void *arg)
963 {
964   (void)arg;
965
966   /* We use the --one-button hack instead of the MESSAGE command to
967      allow the use of old Pinentries.  Those old Pinentries will then
968      show an additional Cancel button but that is mostly a visual
969      annoyance. */
970   assuan_transact (entry_ctx, "CONFIRM --one-button", 
971                    NULL, NULL, NULL, NULL, NULL, NULL);
972   popup_finished = 1;
973   return NULL;
974 }
975
976
977 /* Pop up a message window similar to the confirm one but keep it open
978    until agent_popup_message_stop has been called.  It is crucial for
979    the caller to make sure that the stop function gets called as soon
980    as the message is not anymore required because the message is
981    system modal and all other attempts to use the pinentry will fail
982    (after a timeout). */
983 int 
984 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
985 {
986   int rc;
987   char line[ASSUAN_LINELENGTH];
988   pth_attr_t tattr;
989
990   rc = start_pinentry (ctrl);
991   if (rc)
992     return rc;
993
994   if (desc)
995     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
996   else
997     snprintf (line, DIM(line)-1, "RESET");
998   line[DIM(line)-1] = 0;
999   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1000   if (rc)
1001     return unlock_pinentry (rc);
1002
1003   if (ok_btn)
1004     {
1005       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1006       line[DIM(line)-1] = 0;
1007       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1008       if (rc)
1009         return unlock_pinentry (rc);
1010     }
1011
1012   tattr = pth_attr_new();
1013   pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
1014   pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
1015   pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
1016
1017   popup_finished = 0;
1018   popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
1019   if (!popup_tid)
1020     {
1021       rc = gpg_error_from_syserror ();
1022       log_error ("error spawning popup message handler: %s\n",
1023                  strerror (errno) );
1024       pth_attr_destroy (tattr);
1025       return unlock_pinentry (rc);
1026     }
1027   pth_attr_destroy (tattr);
1028
1029   return 0;
1030 }
1031
1032 /* Close a popup window. */
1033 void
1034 agent_popup_message_stop (ctrl_t ctrl)
1035 {
1036   int rc;
1037   pid_t pid;
1038
1039   (void)ctrl;
1040
1041   if (!popup_tid || !entry_ctx)
1042     {
1043       log_debug ("agent_popup_message_stop called with no active popup\n");
1044       return; 
1045     }
1046
1047   pid = assuan_get_pid (entry_ctx);
1048   if (pid == (pid_t)(-1))
1049     ; /* No pid available can't send a kill. */
1050   else if (popup_finished)
1051     ; /* Already finished and ready for joining. */
1052 #ifdef HAVE_W32_SYSTEM
1053   /* Older versions of assuan set PID to 0 on Windows to indicate an
1054      invalid value.  */
1055   else if (pid != (pid_t) INVALID_HANDLE_VALUE
1056            && pid != 0)
1057     {
1058       HANDLE process = (HANDLE) pid;
1059       
1060       /* Arbitrary error code.  */
1061       TerminateProcess (process, 1);
1062     }
1063 #else
1064   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1065     { /* The daemon already died.  No need to send a kill.  However
1066          because we already waited for the process, we need to tell
1067          assuan that it should not wait again (done by
1068          unlock_pinentry). */
1069       if (rc == pid)
1070         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1071     }
1072   else if (pid > 0)
1073     kill (pid, SIGKILL);  /* Need to use SIGKILL due to bad
1074                              interaction of SIGINT with Pth. */
1075 #endif
1076
1077   /* Now wait for the thread to terminate. */
1078   rc = pth_join (popup_tid, NULL);
1079   if (!rc)
1080     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1081                strerror (errno));
1082   popup_tid = NULL;
1083   entry_owner = NULL;
1084
1085   /* Now we can close the connection. */
1086   unlock_pinentry (0);
1087 }
1088
1089