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