Started to implement the audit log feature.
[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;
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       /* TRANSLATORS: This string is a tooltip, shown by pinentry when
599          hovering over the quality bar.  Please use an appropriate
600          string to describe what this is about.  The length of the
601          tooltip is limited to about 900 characters.  If you do not
602          translate this entry, a default english text (see source)
603          will be used. */
604       tooltip =  _("pinentry.qualitybar.tooltip");
605       if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
606         tooltip = ("The quality of the text entered above.\n"
607                    "Please ask your administrator for "
608                    "details about the criteria.");
609       /* Fixme: As soon as we have the extended error reporting
610          facility (audit log), we can use a user specified helptext if
611          that has been configured. */
612       tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
613       snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
614       line[DIM(line)-1] = 0;
615       xfree (tmpstr);
616       rc = assuan_transact (entry_ctx, line,
617                             NULL, NULL, NULL, NULL, NULL, NULL);
618       if (rc == 103 /*(Old assuan error code)*/
619           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
620         ; /* Ignore Unknown Command from old pinentry versions.  */
621       else if (rc)
622         return unlock_pinentry (rc);
623     }
624
625   if (initial_errtext)
626     { 
627       snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
628       line[DIM(line)-1] = 0;
629       rc = assuan_transact (entry_ctx, line,
630                             NULL, NULL, NULL, NULL, NULL, NULL);
631       if (rc)
632         return unlock_pinentry (rc);
633     }
634
635   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
636     {
637       memset (&parm, 0, sizeof parm);
638       parm.size = pininfo->max_length;
639       *pininfo->pin = 0; /* Reset the PIN. */
640       parm.buffer = (unsigned char*)pininfo->pin;
641
642       if (errtext)
643         { 
644           /* TRANLATORS: The string is appended to an error message in
645              the pinentry.  The %s is the actual error message, the
646              two %d give the current and maximum number of tries. */
647           snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
648                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
649           line[DIM(line)-1] = 0;
650           rc = assuan_transact (entry_ctx, line,
651                                 NULL, NULL, NULL, NULL, NULL, NULL);
652           if (rc)
653             return unlock_pinentry (rc);
654           errtext = NULL;
655         }
656       
657       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
658                             inq_quality, entry_ctx, NULL, NULL);
659       /* Most pinentries out in the wild return the old Assuan error code
660          for canceled which gets translated to an assuan Cancel error and
661          not to the code for a user cancel.  Fix this here. */
662       if (rc && gpg_err_source (rc)
663           && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
664         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
665
666       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
667         errtext = is_pin? _("PIN too long")
668                         : _("Passphrase too long");
669       else if (rc)
670         return unlock_pinentry (rc);
671
672       if (!errtext && pininfo->min_digits)
673         {
674           /* do some basic checks on the entered PIN. */
675           if (!all_digitsp (pininfo->pin))
676             errtext = _("Invalid characters in PIN");
677           else if (pininfo->max_digits
678                    && strlen (pininfo->pin) > pininfo->max_digits)
679             errtext = _("PIN too long");
680           else if (strlen (pininfo->pin) < pininfo->min_digits)
681             errtext = _("PIN too short");
682         }
683
684       if (!errtext && pininfo->check_cb)
685         {
686           /* More checks by utilizing the optional callback. */
687           pininfo->cb_errtext = NULL;
688           rc = pininfo->check_cb (pininfo);
689           if (rc == -1 && pininfo->cb_errtext)
690             errtext = pininfo->cb_errtext;
691           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
692                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
693             errtext = (is_pin? _("Bad PIN")
694                        : _("Bad Passphrase"));
695           else if (rc)
696             return unlock_pinentry (rc);
697         }
698
699       if (!errtext)
700         return unlock_pinentry (0); /* okay, got a PIN or passphrase */
701     }
702
703   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
704                           : GPG_ERR_BAD_PASSPHRASE));
705 }
706
707
708 \f
709 /* Ask for the passphrase using the supplied arguments.  The returned
710    passphrase needs to be freed by the caller. */
711 int 
712 agent_get_passphrase (ctrl_t ctrl,
713                       char **retpass, const char *desc, const char *prompt,
714                       const char *errtext)
715 {
716
717   int rc;
718   char line[ASSUAN_LINELENGTH];
719   struct entry_parm_s parm;
720
721   *retpass = NULL;
722   if (opt.batch)
723     return gpg_error (GPG_ERR_BAD_PASSPHRASE); 
724
725   rc = start_pinentry (ctrl);
726   if (rc)
727     return rc;
728
729   if (!prompt)
730     prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
731
732
733   if (desc)
734     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
735   else
736     snprintf (line, DIM(line)-1, "RESET");
737   line[DIM(line)-1] = 0;
738   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
739   if (rc)
740     return unlock_pinentry (rc);
741
742   snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
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   if (errtext)
749     {
750       snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
751       line[DIM(line)-1] = 0;
752       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
753       if (rc)
754         return unlock_pinentry (rc);
755     }
756
757   memset (&parm, 0, sizeof parm);
758   parm.size = ASSUAN_LINELENGTH/2 - 5;
759   parm.buffer = gcry_malloc_secure (parm.size+10);
760   if (!parm.buffer)
761     return unlock_pinentry (out_of_core ());
762
763   assuan_begin_confidential (entry_ctx);
764   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
765                         NULL, NULL, NULL, NULL);
766   /* Most pinentries out in the wild return the old Assuan error code
767      for canceled which gets translated to an assuan Cancel error and
768      not to the code for a user cancel.  Fix this here. */
769   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
770     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
771   if (rc)
772     xfree (parm.buffer);
773   else
774     *retpass = parm.buffer;
775   return unlock_pinentry (rc);
776 }
777
778
779 \f
780 /* Pop up the PIN-entry, display the text and the prompt and ask the
781    user to confirm this.  We return 0 for success, ie. the user
782    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
783    other error. */
784 int 
785 agent_get_confirmation (ctrl_t ctrl,
786                         const char *desc, const char *ok, const char *cancel)
787 {
788   int rc;
789   char line[ASSUAN_LINELENGTH];
790
791   rc = start_pinentry (ctrl);
792   if (rc)
793     return rc;
794
795   if (desc)
796     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
797   else
798     snprintf (line, DIM(line)-1, "RESET");
799   line[DIM(line)-1] = 0;
800   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
801   /* Most pinentries out in the wild return the old Assuan error code
802      for canceled which gets translated to an assuan Cancel error and
803      not to the code for a user cancel.  Fix this here. */
804   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
805     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
806
807   if (rc)
808     return unlock_pinentry (rc);
809
810   if (ok)
811     {
812       snprintf (line, DIM(line)-1, "SETOK %s", ok);
813       line[DIM(line)-1] = 0;
814       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
815       if (rc)
816         return unlock_pinentry (rc);
817     }
818   if (cancel)
819     {
820       snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel);
821       line[DIM(line)-1] = 0;
822       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
823       if (rc)
824         return unlock_pinentry (rc);
825     }
826
827   rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
828   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
829     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
830
831   return unlock_pinentry (rc);
832 }
833
834
835 \f
836 /* Pop up the PINentry, display the text DESC and a button with the
837    text OK_BTN (which may be NULL to use the default of "OK") and waut
838    for the user to hit this button.  The return value is not
839    relevant.  */
840 int 
841 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
842 {
843   int rc;
844   char line[ASSUAN_LINELENGTH];
845
846   rc = start_pinentry (ctrl);
847   if (rc)
848     return rc;
849
850   if (desc)
851     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
852   else
853     snprintf (line, DIM(line)-1, "RESET");
854   line[DIM(line)-1] = 0;
855   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
856   /* Most pinentries out in the wild return the old Assuan error code
857      for canceled which gets translated to an assuan Cancel error and
858      not to the code for a user cancel.  Fix this here. */
859   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
860     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
861
862   if (rc)
863     return unlock_pinentry (rc);
864
865   if (ok_btn)
866     {
867       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
868       line[DIM(line)-1] = 0;
869       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
870                             NULL, NULL, NULL);
871       if (rc)
872         return unlock_pinentry (rc);
873     }
874   
875   rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
876                         NULL, NULL, NULL);
877   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
878     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
879
880   return unlock_pinentry (rc);
881 }
882
883
884 /* The thread running the popup message. */
885 static void *
886 popup_message_thread (void *arg)
887 {
888   /* We use the --one-button hack instead of the MESSAGE command to
889      allow the use of old Pinentries.  Those old Pinentries will then
890      show an additional Cancel button but that is mostly a visual
891      annoyance. */
892   assuan_transact (entry_ctx, "CONFIRM --one-button", 
893                    NULL, NULL, NULL, NULL, NULL, NULL);
894   popup_finished = 1;
895   return NULL;
896 }
897
898
899 /* Pop up a message window similar to the confirm one but keep it open
900    until agent_popup_message_stop has been called.  It is crucial for
901    the caller to make sure that the stop function gets called as soon
902    as the message is not anymore required because the message is
903    system modal and all other attempts to use the pinentry will fail
904    (after a timeout). */
905 int 
906 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
907 {
908   int rc;
909   char line[ASSUAN_LINELENGTH];
910   pth_attr_t tattr;
911
912   rc = start_pinentry (ctrl);
913   if (rc)
914     return rc;
915
916   if (desc)
917     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
918   else
919     snprintf (line, DIM(line)-1, "RESET");
920   line[DIM(line)-1] = 0;
921   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
922   if (rc)
923     return unlock_pinentry (rc);
924
925   if (ok_btn)
926     {
927       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
928       line[DIM(line)-1] = 0;
929       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
930       if (rc)
931         return unlock_pinentry (rc);
932     }
933
934   tattr = pth_attr_new();
935   pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
936   pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
937   pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
938
939   popup_finished = 0;
940   popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
941   if (!popup_tid)
942     {
943       rc = gpg_error_from_syserror ();
944       log_error ("error spawning popup message handler: %s\n",
945                  strerror (errno) );
946       pth_attr_destroy (tattr);
947       return unlock_pinentry (rc);
948     }
949   pth_attr_destroy (tattr);
950
951   return 0;
952 }
953
954 /* Close a popup window. */
955 void
956 agent_popup_message_stop (ctrl_t ctrl)
957 {
958   int rc;
959   pid_t pid;
960
961   if (!popup_tid || !entry_ctx)
962     {
963       log_debug ("agent_popup_message_stop called with no active popup\n");
964       return; 
965     }
966
967   pid = assuan_get_pid (entry_ctx);
968   if (pid == (pid_t)(-1))
969     ; /* No pid available can't send a kill. */
970   else if (popup_finished)
971     ; /* Already finished and ready for joining. */
972 #ifdef HAVE_W32_SYSTEM
973   /* Older versions of assuan set PID to 0 on Windows to indicate an
974      invalid value.  */
975   else if (pid != (pid_t) INVALID_HANDLE_VALUE
976            && pid != 0)
977     {
978       HANDLE process = (HANDLE) pid;
979       
980       /* Arbitrary error code.  */
981       TerminateProcess (process, 1);
982     }
983 #else
984   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
985     { /* The daemon already died.  No need to send a kill.  However
986          because we already waited for the process, we need to tell
987          assuan that it should not wait again (done by
988          unlock_pinentry). */
989       if (rc == pid)
990         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
991     }
992   else if (pid > 0)
993     kill (pid, SIGKILL);  /* Need to use SIGKILL due to bad
994                              interaction of SIGINT with Pth. */
995 #endif
996
997   /* Now wait for the thread to terminate. */
998   rc = pth_join (popup_tid, NULL);
999   if (!rc)
1000     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1001                strerror (errno));
1002   popup_tid = NULL;
1003   entry_owner = NULL;
1004
1005   /* Now we can close the connection. */
1006   unlock_pinentry (0);
1007 }
1008
1009