2008-01-15 Marcus Brinkmann <marcus@g10code.de>
[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.  We
275      start the server in detached mode to suppress the console window
276      under Windows.  */
277   rc = assuan_pipe_connect_ext (&ctx, opt.pinentry_program, argv,
278                                 no_close_list, atfork_cb, ctrl, 128);
279   if (rc)
280     {
281       log_error ("can't connect to the PIN entry module: %s\n",
282                  gpg_strerror (rc));
283       return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
284     }
285   entry_ctx = ctx;
286
287   if (DBG_ASSUAN)
288     log_debug ("connection to PIN entry established\n");
289
290   rc = assuan_transact (entry_ctx, 
291                         opt.no_grab? "OPTION no-grab":"OPTION grab",
292                         NULL, NULL, NULL, NULL, NULL, NULL);
293   if (rc)
294     return unlock_pinentry (rc);
295   if (ctrl->ttyname)
296     {
297       char *optstr;
298       if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
299         return unlock_pinentry (out_of_core ());
300       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
301                             NULL);
302       free (optstr);
303       if (rc)
304         return unlock_pinentry (rc);
305     }
306   if (ctrl->ttytype)
307     {
308       char *optstr;
309       if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
310         return unlock_pinentry (out_of_core ());
311       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
312                             NULL);
313       if (rc)
314         return unlock_pinentry (rc);
315     }
316   if (ctrl->lc_ctype)
317     {
318       char *optstr;
319       if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
320         return unlock_pinentry (out_of_core ());
321       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
322                             NULL);
323       if (rc)
324         return unlock_pinentry (rc);
325     }
326   if (ctrl->lc_messages)
327     {
328       char *optstr;
329       if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 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
337   
338   /* Tell the pinentry the name of a file it shall touch after having
339      messed with the tty.  This is optional and only supported by
340      newer pinentries and thus we do no error checking. */
341   tmpstr = opt.pinentry_touch_file;
342   if (tmpstr && !strcmp (tmpstr, "/dev/null"))
343     tmpstr = NULL;
344   else if (!tmpstr)
345     tmpstr = get_agent_socket_name ();
346   if (tmpstr)
347     {
348       char *optstr;
349       
350       if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
351         ;
352       else
353         {
354           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
355                            NULL);
356           free (optstr);
357         }
358     }
359
360   return 0;
361 }
362
363 /* Returns True is the pinentry is currently active. If WAITSECONDS is
364    greater than zero the function will wait for this many seconds
365    before returning.  */
366 int
367 pinentry_active_p (ctrl_t ctrl, int waitseconds)
368 {
369   if (waitseconds > 0)
370     {
371       pth_event_t evt;
372       int rc;
373
374       evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
375       if (!pth_mutex_acquire (&entry_lock, 0, evt))
376         {
377           if (pth_event_occurred (evt))
378             rc = gpg_error (GPG_ERR_TIMEOUT);
379           else
380             rc = gpg_error (GPG_ERR_INTERNAL);
381           pth_event_free (evt, PTH_FREE_THIS);
382           return rc;
383         }
384       pth_event_free (evt, PTH_FREE_THIS);
385     }
386   else
387     {
388       if (!pth_mutex_acquire (&entry_lock, 1, NULL))
389         return gpg_error (GPG_ERR_LOCKED);
390     }
391
392   if (!pth_mutex_release (&entry_lock))
393     log_error ("failed to release the entry lock at %d\n", __LINE__);
394   return 0;
395 }
396
397
398 static int
399 getpin_cb (void *opaque, const void *buffer, size_t length)
400 {
401   struct entry_parm_s *parm = opaque;
402
403   if (!buffer)
404     return 0;
405
406   /* we expect the pin to fit on one line */
407   if (parm->lines || length >= parm->size)
408     return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
409
410   /* fixme: we should make sure that the assuan buffer is allocated in
411      secure memory or read the response byte by byte */
412   memcpy (parm->buffer, buffer, length);
413   parm->buffer[length] = 0;
414   parm->lines++;
415   return 0;
416 }
417
418
419 static int
420 all_digitsp( const char *s)
421 {
422   for (; *s && *s >= '0' && *s <= '9'; s++)
423     ;
424   return !*s;
425 }  
426
427
428 /* Return a new malloced string by unescaping the string S.  Escaping
429    is percent escaping and '+'/space mapping.  A binary Nul will
430    silently be replaced by a 0xFF.  Function returns NULL to indicate
431    an out of memory status.  PArsing stops at the end of the string or
432    a white space character. */
433 static char *
434 unescape_passphrase_string (const unsigned char *s)
435 {
436   char *buffer, *d;
437
438   buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
439   if (!buffer)
440     return NULL;
441   while (*s && !spacep (s))
442     {
443       if (*s == '%' && s[1] && s[2])
444         { 
445           s++;
446           *d = xtoi_2 (s);
447           if (!*d)
448             *d = '\xff';
449           d++;
450           s += 2;
451         }
452       else if (*s == '+')
453         {
454           *d++ = ' ';
455           s++;
456         }
457       else
458         *d++ = *s++;
459     }
460   *d = 0; 
461   return buffer;
462 }
463
464
465 /* Estimate the quality of the passphrase PW and return a value in the
466    range 0..100.  */
467 static int
468 estimate_passphrase_quality (const char *pw)
469 {
470   int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
471   int length;
472   const char *s;
473
474   if (goodlength < 1)
475     return 0;
476
477   for (length = 0, s = pw; *s; s++)
478     if (!spacep (s))
479       length ++;
480
481   if (length > goodlength)
482     return 100;
483   return ((length*10) / goodlength)*10;
484 }
485
486
487 /* Handle the QUALITY inquiry. */
488 static int
489 inq_quality (void *opaque, const char *line)
490 {
491   assuan_context_t ctx = opaque;
492   char *pin;
493   int rc;
494   int percent;
495   char numbuf[20];
496
497   if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
498     {
499       line += 7;
500       while (*line == ' ')
501         line++;
502       
503       pin = unescape_passphrase_string (line);
504       if (!pin)
505         rc = gpg_error_from_syserror ();
506       else
507         {
508           percent = estimate_passphrase_quality (pin);
509           if (check_passphrase_constraints (NULL, pin, 1))
510             percent = -percent;
511           snprintf (numbuf, sizeof numbuf, "%d", percent);
512           rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
513           xfree (pin);
514         }
515     }
516   else
517     {
518       log_error ("unsupported inquiry `%s' from pinentry\n", line);
519       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
520     }
521
522   return rc;
523 }
524
525
526
527
528 \f
529 /* Call the Entry and ask for the PIN.  We do check for a valid PIN
530    number here and repeat it as long as we have invalid formed
531    numbers. */
532 int
533 agent_askpin (ctrl_t ctrl,
534               const char *desc_text, const char *prompt_text,
535               const char *initial_errtext,
536               struct pin_entry_info_s *pininfo)
537 {
538   int rc;
539   char line[ASSUAN_LINELENGTH];
540   struct entry_parm_s parm;
541   const char *errtext = NULL;
542   int is_pin = 0;
543
544   if (opt.batch)
545     return 0; /* fixme: we should return BAD PIN */
546
547   if (!pininfo || pininfo->max_length < 1)
548     return gpg_error (GPG_ERR_INV_VALUE);
549   if (!desc_text && pininfo->min_digits)
550     desc_text = _("Please enter your PIN, so that the secret key "
551                   "can be unlocked for this session");
552   else if (!desc_text)
553     desc_text = _("Please enter your passphrase, so that the secret key "
554                   "can be unlocked for this session");
555
556   if (prompt_text)
557     is_pin = !!strstr (prompt_text, "PIN");
558   else
559     is_pin = desc_text && strstr (desc_text, "PIN");
560
561   rc = start_pinentry (ctrl);
562   if (rc)
563     return rc;
564
565   snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
566   line[DIM(line)-1] = 0;
567   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
568   if (rc)
569     return unlock_pinentry (rc);
570
571   snprintf (line, DIM(line)-1, "SETPROMPT %s",
572             prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
573   line[DIM(line)-1] = 0;
574   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
575   if (rc)
576     return unlock_pinentry (rc);
577
578   /* If a passphrase quality indicator has been requested and a
579      minimum passphrase length has not been disabled, send the command
580      to the pinentry.  */
581   if (pininfo->with_qualitybar && opt.min_passphrase_len )
582     {
583       char *tmpstr, *tmpstr2;
584       const char *tooltip;
585
586       /* TRANSLATORS: This string is displayed by pinentry as the
587          label for the quality bar.  */
588       tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
589       snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
590       line[DIM(line)-1] = 0;
591       xfree (tmpstr);
592       rc = assuan_transact (entry_ctx, line,
593                             NULL, NULL, NULL, NULL, NULL, NULL);
594       if (rc == 103 /*(Old assuan error code)*/
595           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
596         ; /* Ignore Unknown Command from old pinentry versions.  */
597       else if (rc)
598         return unlock_pinentry (rc);
599
600       tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
601       if (tmpstr2)
602         tooltip = tmpstr2;
603       else
604         {
605           /* TRANSLATORS: This string is a tooltip, shown by pinentry
606              when hovering over the quality bar.  Please use an
607              appropriate string to describe what this is about.  The
608              length of the tooltip is limited to about 900 characters.
609              If you do not translate this entry, a default english
610              text (see source) will be used. */
611           tooltip =  _("pinentry.qualitybar.tooltip");
612           if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
613             tooltip = ("The quality of the text entered above.\n"
614                        "Please ask your administrator for "
615                        "details about the criteria.");
616         }
617       tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
618       xfree (tmpstr2);
619       snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
620       line[DIM(line)-1] = 0;
621       xfree (tmpstr);
622       rc = assuan_transact (entry_ctx, line,
623                             NULL, NULL, NULL, NULL, NULL, NULL);
624       if (rc == 103 /*(Old assuan error code)*/
625           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
626         ; /* Ignore Unknown Command from old pinentry versions.  */
627       else if (rc)
628         return unlock_pinentry (rc);
629     }
630
631   if (initial_errtext)
632     { 
633       snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
634       line[DIM(line)-1] = 0;
635       rc = assuan_transact (entry_ctx, line,
636                             NULL, NULL, NULL, NULL, NULL, NULL);
637       if (rc)
638         return unlock_pinentry (rc);
639     }
640
641   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
642     {
643       memset (&parm, 0, sizeof parm);
644       parm.size = pininfo->max_length;
645       *pininfo->pin = 0; /* Reset the PIN. */
646       parm.buffer = (unsigned char*)pininfo->pin;
647
648       if (errtext)
649         { 
650           /* TRANLATORS: The string is appended to an error message in
651              the pinentry.  The %s is the actual error message, the
652              two %d give the current and maximum number of tries. */
653           snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
654                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
655           line[DIM(line)-1] = 0;
656           rc = assuan_transact (entry_ctx, line,
657                                 NULL, NULL, NULL, NULL, NULL, NULL);
658           if (rc)
659             return unlock_pinentry (rc);
660           errtext = NULL;
661         }
662       
663       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
664                             inq_quality, entry_ctx, NULL, NULL);
665       /* Most pinentries out in the wild return the old Assuan error code
666          for canceled which gets translated to an assuan Cancel error and
667          not to the code for a user cancel.  Fix this here. */
668       if (rc && gpg_err_source (rc)
669           && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
670         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
671
672       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
673         errtext = is_pin? _("PIN too long")
674                         : _("Passphrase too long");
675       else if (rc)
676         return unlock_pinentry (rc);
677
678       if (!errtext && pininfo->min_digits)
679         {
680           /* do some basic checks on the entered PIN. */
681           if (!all_digitsp (pininfo->pin))
682             errtext = _("Invalid characters in PIN");
683           else if (pininfo->max_digits
684                    && strlen (pininfo->pin) > pininfo->max_digits)
685             errtext = _("PIN too long");
686           else if (strlen (pininfo->pin) < pininfo->min_digits)
687             errtext = _("PIN too short");
688         }
689
690       if (!errtext && pininfo->check_cb)
691         {
692           /* More checks by utilizing the optional callback. */
693           pininfo->cb_errtext = NULL;
694           rc = pininfo->check_cb (pininfo);
695           if (rc == -1 && pininfo->cb_errtext)
696             errtext = pininfo->cb_errtext;
697           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
698                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
699             errtext = (is_pin? _("Bad PIN")
700                        : _("Bad Passphrase"));
701           else if (rc)
702             return unlock_pinentry (rc);
703         }
704
705       if (!errtext)
706         return unlock_pinentry (0); /* okay, got a PIN or passphrase */
707     }
708
709   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
710                           : GPG_ERR_BAD_PASSPHRASE));
711 }
712
713
714 \f
715 /* Ask for the passphrase using the supplied arguments.  The returned
716    passphrase needs to be freed by the caller. */
717 int 
718 agent_get_passphrase (ctrl_t ctrl,
719                       char **retpass, const char *desc, const char *prompt,
720                       const char *errtext)
721 {
722
723   int rc;
724   char line[ASSUAN_LINELENGTH];
725   struct entry_parm_s parm;
726
727   *retpass = NULL;
728   if (opt.batch)
729     return gpg_error (GPG_ERR_BAD_PASSPHRASE); 
730
731   rc = start_pinentry (ctrl);
732   if (rc)
733     return rc;
734
735   if (!prompt)
736     prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
737
738
739   if (desc)
740     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
741   else
742     snprintf (line, DIM(line)-1, "RESET");
743   line[DIM(line)-1] = 0;
744   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
745   if (rc)
746     return unlock_pinentry (rc);
747
748   snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
749   line[DIM(line)-1] = 0;
750   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
751   if (rc)
752     return unlock_pinentry (rc);
753
754   if (errtext)
755     {
756       snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
757       line[DIM(line)-1] = 0;
758       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
759       if (rc)
760         return unlock_pinentry (rc);
761     }
762
763   memset (&parm, 0, sizeof parm);
764   parm.size = ASSUAN_LINELENGTH/2 - 5;
765   parm.buffer = gcry_malloc_secure (parm.size+10);
766   if (!parm.buffer)
767     return unlock_pinentry (out_of_core ());
768
769   assuan_begin_confidential (entry_ctx);
770   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
771                         NULL, NULL, NULL, NULL);
772   /* Most pinentries out in the wild return the old Assuan error code
773      for canceled which gets translated to an assuan Cancel error and
774      not to the code for a user cancel.  Fix this here. */
775   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
776     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
777   if (rc)
778     xfree (parm.buffer);
779   else
780     *retpass = parm.buffer;
781   return unlock_pinentry (rc);
782 }
783
784
785 \f
786 /* Pop up the PIN-entry, display the text and the prompt and ask the
787    user to confirm this.  We return 0 for success, ie. the user
788    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
789    other error. */
790 int 
791 agent_get_confirmation (ctrl_t ctrl,
792                         const char *desc, const char *ok, const char *cancel)
793 {
794   int rc;
795   char line[ASSUAN_LINELENGTH];
796
797   rc = start_pinentry (ctrl);
798   if (rc)
799     return rc;
800
801   if (desc)
802     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
803   else
804     snprintf (line, DIM(line)-1, "RESET");
805   line[DIM(line)-1] = 0;
806   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
807   /* Most pinentries out in the wild return the old Assuan error code
808      for canceled which gets translated to an assuan Cancel error and
809      not to the code for a user cancel.  Fix this here. */
810   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
811     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
812
813   if (rc)
814     return unlock_pinentry (rc);
815
816   if (ok)
817     {
818       snprintf (line, DIM(line)-1, "SETOK %s", ok);
819       line[DIM(line)-1] = 0;
820       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
821       if (rc)
822         return unlock_pinentry (rc);
823     }
824   if (cancel)
825     {
826       snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel);
827       line[DIM(line)-1] = 0;
828       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
829       if (rc)
830         return unlock_pinentry (rc);
831     }
832
833   rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
834   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
835     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
836
837   return unlock_pinentry (rc);
838 }
839
840
841 \f
842 /* Pop up the PINentry, display the text DESC and a button with the
843    text OK_BTN (which may be NULL to use the default of "OK") and waut
844    for the user to hit this button.  The return value is not
845    relevant.  */
846 int 
847 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
848 {
849   int rc;
850   char line[ASSUAN_LINELENGTH];
851
852   rc = start_pinentry (ctrl);
853   if (rc)
854     return rc;
855
856   if (desc)
857     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
858   else
859     snprintf (line, DIM(line)-1, "RESET");
860   line[DIM(line)-1] = 0;
861   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
862   /* Most pinentries out in the wild return the old Assuan error code
863      for canceled which gets translated to an assuan Cancel error and
864      not to the code for a user cancel.  Fix this here. */
865   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
866     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
867
868   if (rc)
869     return unlock_pinentry (rc);
870
871   if (ok_btn)
872     {
873       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
874       line[DIM(line)-1] = 0;
875       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
876                             NULL, NULL, NULL);
877       if (rc)
878         return unlock_pinentry (rc);
879     }
880   
881   rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
882                         NULL, NULL, NULL);
883   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
884     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
885
886   return unlock_pinentry (rc);
887 }
888
889
890 /* The thread running the popup message. */
891 static void *
892 popup_message_thread (void *arg)
893 {
894   /* We use the --one-button hack instead of the MESSAGE command to
895      allow the use of old Pinentries.  Those old Pinentries will then
896      show an additional Cancel button but that is mostly a visual
897      annoyance. */
898   assuan_transact (entry_ctx, "CONFIRM --one-button", 
899                    NULL, NULL, NULL, NULL, NULL, NULL);
900   popup_finished = 1;
901   return NULL;
902 }
903
904
905 /* Pop up a message window similar to the confirm one but keep it open
906    until agent_popup_message_stop has been called.  It is crucial for
907    the caller to make sure that the stop function gets called as soon
908    as the message is not anymore required because the message is
909    system modal and all other attempts to use the pinentry will fail
910    (after a timeout). */
911 int 
912 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
913 {
914   int rc;
915   char line[ASSUAN_LINELENGTH];
916   pth_attr_t tattr;
917
918   rc = start_pinentry (ctrl);
919   if (rc)
920     return rc;
921
922   if (desc)
923     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
924   else
925     snprintf (line, DIM(line)-1, "RESET");
926   line[DIM(line)-1] = 0;
927   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
928   if (rc)
929     return unlock_pinentry (rc);
930
931   if (ok_btn)
932     {
933       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
934       line[DIM(line)-1] = 0;
935       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
936       if (rc)
937         return unlock_pinentry (rc);
938     }
939
940   tattr = pth_attr_new();
941   pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
942   pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
943   pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
944
945   popup_finished = 0;
946   popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
947   if (!popup_tid)
948     {
949       rc = gpg_error_from_syserror ();
950       log_error ("error spawning popup message handler: %s\n",
951                  strerror (errno) );
952       pth_attr_destroy (tattr);
953       return unlock_pinentry (rc);
954     }
955   pth_attr_destroy (tattr);
956
957   return 0;
958 }
959
960 /* Close a popup window. */
961 void
962 agent_popup_message_stop (ctrl_t ctrl)
963 {
964   int rc;
965   pid_t pid;
966
967   if (!popup_tid || !entry_ctx)
968     {
969       log_debug ("agent_popup_message_stop called with no active popup\n");
970       return; 
971     }
972
973   pid = assuan_get_pid (entry_ctx);
974   if (pid == (pid_t)(-1))
975     ; /* No pid available can't send a kill. */
976   else if (popup_finished)
977     ; /* Already finished and ready for joining. */
978 #ifdef HAVE_W32_SYSTEM
979   /* Older versions of assuan set PID to 0 on Windows to indicate an
980      invalid value.  */
981   else if (pid != (pid_t) INVALID_HANDLE_VALUE
982            && pid != 0)
983     {
984       HANDLE process = (HANDLE) pid;
985       
986       /* Arbitrary error code.  */
987       TerminateProcess (process, 1);
988     }
989 #else
990   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
991     { /* The daemon already died.  No need to send a kill.  However
992          because we already waited for the process, we need to tell
993          assuan that it should not wait again (done by
994          unlock_pinentry). */
995       if (rc == pid)
996         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
997     }
998   else if (pid > 0)
999     kill (pid, SIGKILL);  /* Need to use SIGKILL due to bad
1000                              interaction of SIGINT with Pth. */
1001 #endif
1002
1003   /* Now wait for the thread to terminate. */
1004   rc = pth_join (popup_tid, NULL);
1005   if (!rc)
1006     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1007                strerror (errno));
1008   popup_tid = NULL;
1009   entry_owner = NULL;
1010
1011   /* Now we can close the connection. */
1012   unlock_pinentry (0);
1013 }
1014
1015