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