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