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