Some minor changes and typo fixes.
[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.  An underscore indicates that the next letter
398          should be used as an accelerator.  Double the underscore for
399          a literal one.  The actual to be translated text starts after
400          the second vertical bar.  */
401       { "ok",     N_("|pinentry-label|_OK") },
402       { "cancel", N_("|pinentry-label|_Cancel") },
403       { "prompt", N_("|pinentry-label|PIN:") },
404       { NULL, NULL}
405     };
406     char *optstr;
407     int idx;
408     const char *s, *s2;
409
410     for (idx=0; tbl[idx].key; idx++)
411       {
412         s = _(tbl[idx].value);
413         if (*s == '|' && (s2=strchr (s+1,'|')))
414           s = s2+1;
415         if (asprintf (&optstr, "OPTION default-%s=%s", tbl[idx].key, s) < 0 )
416           return unlock_pinentry (out_of_core ());
417         assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
418                          NULL);
419         xfree (optstr);
420       }
421   }
422
423   
424   /* Tell the pinentry the name of a file it shall touch after having
425      messed with the tty.  This is optional and only supported by
426      newer pinentries and thus we do no error checking. */
427   tmpstr = opt.pinentry_touch_file;
428   if (tmpstr && !strcmp (tmpstr, "/dev/null"))
429     tmpstr = NULL;
430   else if (!tmpstr)
431     tmpstr = get_agent_socket_name ();
432   if (tmpstr)
433     {
434       char *optstr;
435       
436       if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
437         ;
438       else
439         {
440           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
441                            NULL);
442           xfree (optstr);
443         }
444     }
445
446
447   /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
448      it will send the pid back and we will use an inquire to notify
449      our client.  The client may answer the inquiry either with END or
450      with CAN to cancel the pinentry. */
451   rc = assuan_transact (entry_ctx, "GETINFO pid", 
452                         getinfo_pid_cb, &pinentry_pid,
453                         NULL, NULL, NULL, NULL);
454   if (rc)
455     {
456       log_info ("You may want to update to a newer pinentry\n");
457       rc = 0;
458     }
459   else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
460     log_error ("pinentry did not return a PID\n");
461   else
462     {
463       rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
464       if (gpg_err_code (rc) == GPG_ERR_CANCELED)
465         return unlock_pinentry (gpg_error (GPG_ERR_CANCELED));
466       rc = 0;
467     }
468
469   return 0;
470 }
471
472
473 /* Returns True is the pinentry is currently active. If WAITSECONDS is
474    greater than zero the function will wait for this many seconds
475    before returning.  */
476 int
477 pinentry_active_p (ctrl_t ctrl, int waitseconds)
478 {
479   (void)ctrl;
480
481   if (waitseconds > 0)
482     {
483       pth_event_t evt;
484       int rc;
485
486       evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
487       if (!pth_mutex_acquire (&entry_lock, 0, evt))
488         {
489           if (pth_event_occurred (evt))
490             rc = gpg_error (GPG_ERR_TIMEOUT);
491           else
492             rc = gpg_error (GPG_ERR_INTERNAL);
493           pth_event_free (evt, PTH_FREE_THIS);
494           return rc;
495         }
496       pth_event_free (evt, PTH_FREE_THIS);
497     }
498   else
499     {
500       if (!pth_mutex_acquire (&entry_lock, 1, NULL))
501         return gpg_error (GPG_ERR_LOCKED);
502     }
503
504   if (!pth_mutex_release (&entry_lock))
505     log_error ("failed to release the entry lock at %d\n", __LINE__);
506   return 0;
507 }
508
509
510 static gpg_error_t
511 getpin_cb (void *opaque, const void *buffer, size_t length)
512 {
513   struct entry_parm_s *parm = opaque;
514
515   if (!buffer)
516     return 0;
517
518   /* we expect the pin to fit on one line */
519   if (parm->lines || length >= parm->size)
520     return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
521
522   /* fixme: we should make sure that the assuan buffer is allocated in
523      secure memory or read the response byte by byte */
524   memcpy (parm->buffer, buffer, length);
525   parm->buffer[length] = 0;
526   parm->lines++;
527   return 0;
528 }
529
530
531 static int
532 all_digitsp( const char *s)
533 {
534   for (; *s && *s >= '0' && *s <= '9'; s++)
535     ;
536   return !*s;
537 }  
538
539
540 /* Return a new malloced string by unescaping the string S.  Escaping
541    is percent escaping and '+'/space mapping.  A binary Nul will
542    silently be replaced by a 0xFF.  Function returns NULL to indicate
543    an out of memory status.  PArsing stops at the end of the string or
544    a white space character. */
545 static char *
546 unescape_passphrase_string (const unsigned char *s)
547 {
548   char *buffer, *d;
549
550   buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
551   if (!buffer)
552     return NULL;
553   while (*s && !spacep (s))
554     {
555       if (*s == '%' && s[1] && s[2])
556         { 
557           s++;
558           *d = xtoi_2 (s);
559           if (!*d)
560             *d = '\xff';
561           d++;
562           s += 2;
563         }
564       else if (*s == '+')
565         {
566           *d++ = ' ';
567           s++;
568         }
569       else
570         *d++ = *s++;
571     }
572   *d = 0; 
573   return buffer;
574 }
575
576
577 /* Estimate the quality of the passphrase PW and return a value in the
578    range 0..100.  */
579 static int
580 estimate_passphrase_quality (const char *pw)
581 {
582   int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
583   int length;
584   const char *s;
585
586   if (goodlength < 1)
587     return 0;
588
589   for (length = 0, s = pw; *s; s++)
590     if (!spacep (s))
591       length ++;
592
593   if (length > goodlength)
594     return 100;
595   return ((length*10) / goodlength)*10;
596 }
597
598
599 /* Handle the QUALITY inquiry. */
600 static gpg_error_t
601 inq_quality (void *opaque, const char *line)
602 {
603   assuan_context_t ctx = opaque;
604   char *pin;
605   int rc;
606   int percent;
607   char numbuf[20];
608
609   if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
610     {
611       line += 7;
612       while (*line == ' ')
613         line++;
614       
615       pin = unescape_passphrase_string (line);
616       if (!pin)
617         rc = gpg_error_from_syserror ();
618       else
619         {
620           percent = estimate_passphrase_quality (pin);
621           if (check_passphrase_constraints (NULL, pin, 1))
622             percent = -percent;
623           snprintf (numbuf, sizeof numbuf, "%d", percent);
624           rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
625           xfree (pin);
626         }
627     }
628   else
629     {
630       log_error ("unsupported inquiry `%s' from pinentry\n", line);
631       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
632     }
633
634   return rc;
635 }
636
637
638 /* Helper for agent_askpin and agent_get_passphrase.  */
639 static int
640 setup_qualitybar (void)
641 {
642   int rc;
643   char line[ASSUAN_LINELENGTH];
644   char *tmpstr, *tmpstr2;
645   const char *tooltip;
646   
647   /* TRANSLATORS: This string is displayed by Pinentry as the label
648      for the quality bar.  */
649   tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
650   snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
651   line[DIM(line)-1] = 0;
652   xfree (tmpstr);
653   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
654   if (rc == 103 /*(Old assuan error code)*/
655       || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
656     ; /* Ignore Unknown Command from old Pinentry versions.  */
657   else if (rc)
658     return rc;
659   
660   tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
661   if (tmpstr2)
662     tooltip = tmpstr2;
663   else
664     {
665       /* TRANSLATORS: This string is a tooltip, shown by pinentry when
666          hovering over the quality bar.  Please use an appropriate
667          string to describe what this is about.  The length of the
668          tooltip is limited to about 900 characters.  If you do not
669          translate this entry, a default english text (see source)
670          will be used. */
671       tooltip =  _("pinentry.qualitybar.tooltip");
672       if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
673         tooltip = ("The quality of the text entered above.\n"
674                    "Please ask your administrator for "
675                    "details about the criteria.");
676     }
677   tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
678   xfree (tmpstr2);
679   snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
680   line[DIM(line)-1] = 0;
681   xfree (tmpstr);
682   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
683   if (rc == 103 /*(Old assuan error code)*/
684           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
685     ; /* Ignore Unknown Command from old pinentry versions.  */
686   else if (rc)
687     return rc;
688
689   return 0;
690 }
691
692
693 \f
694 /* Call the Entry and ask for the PIN.  We do check for a valid PIN
695    number here and repeat it as long as we have invalid formed
696    numbers. */
697 int
698 agent_askpin (ctrl_t ctrl,
699               const char *desc_text, const char *prompt_text,
700               const char *initial_errtext,
701               struct pin_entry_info_s *pininfo)
702 {
703   int rc;
704   char line[ASSUAN_LINELENGTH];
705   struct entry_parm_s parm;
706   const char *errtext = NULL;
707   int is_pin = 0;
708
709   if (opt.batch)
710     return 0; /* fixme: we should return BAD PIN */
711
712   if (!pininfo || pininfo->max_length < 1)
713     return gpg_error (GPG_ERR_INV_VALUE);
714   if (!desc_text && pininfo->min_digits)
715     desc_text = _("Please enter your PIN, so that the secret key "
716                   "can be unlocked for this session");
717   else if (!desc_text)
718     desc_text = _("Please enter your passphrase, so that the secret key "
719                   "can be unlocked for this session");
720
721   if (prompt_text)
722     is_pin = !!strstr (prompt_text, "PIN");
723   else
724     is_pin = desc_text && strstr (desc_text, "PIN");
725
726   rc = start_pinentry (ctrl);
727   if (rc)
728     return rc;
729
730   snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
731   line[DIM(line)-1] = 0;
732   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
733   if (rc)
734     return unlock_pinentry (rc);
735
736   snprintf (line, DIM(line)-1, "SETPROMPT %s",
737             prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
738   line[DIM(line)-1] = 0;
739   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
740   if (rc)
741     return unlock_pinentry (rc);
742
743   /* If a passphrase quality indicator has been requested and a
744      minimum passphrase length has not been disabled, send the command
745      to the pinentry.  */
746   if (pininfo->with_qualitybar && opt.min_passphrase_len )
747     {
748       rc = setup_qualitybar ();
749       if (rc)
750         return unlock_pinentry (rc);
751     }
752
753   if (initial_errtext)
754     { 
755       snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
756       line[DIM(line)-1] = 0;
757       rc = assuan_transact (entry_ctx, line,
758                             NULL, NULL, NULL, NULL, NULL, NULL);
759       if (rc)
760         return unlock_pinentry (rc);
761     }
762
763   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
764     {
765       memset (&parm, 0, sizeof parm);
766       parm.size = pininfo->max_length;
767       *pininfo->pin = 0; /* Reset the PIN. */
768       parm.buffer = (unsigned char*)pininfo->pin;
769
770       if (errtext)
771         { 
772           /* TRANLATORS: The string is appended to an error message in
773              the pinentry.  The %s is the actual error message, the
774              two %d give the current and maximum number of tries. */
775           snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
776                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
777           line[DIM(line)-1] = 0;
778           rc = assuan_transact (entry_ctx, line,
779                                 NULL, NULL, NULL, NULL, NULL, NULL);
780           if (rc)
781             return unlock_pinentry (rc);
782           errtext = NULL;
783         }
784       
785       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
786                             inq_quality, entry_ctx, NULL, NULL);
787       /* Most pinentries out in the wild return the old Assuan error code
788          for canceled which gets translated to an assuan Cancel error and
789          not to the code for a user cancel.  Fix this here. */
790       if (rc && gpg_err_source (rc)
791           && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
792         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
793
794       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
795         errtext = is_pin? _("PIN too long")
796                         : _("Passphrase too long");
797       else if (rc)
798         return unlock_pinentry (rc);
799
800       if (!errtext && pininfo->min_digits)
801         {
802           /* do some basic checks on the entered PIN. */
803           if (!all_digitsp (pininfo->pin))
804             errtext = _("Invalid characters in PIN");
805           else if (pininfo->max_digits
806                    && strlen (pininfo->pin) > pininfo->max_digits)
807             errtext = _("PIN too long");
808           else if (strlen (pininfo->pin) < pininfo->min_digits)
809             errtext = _("PIN too short");
810         }
811
812       if (!errtext && pininfo->check_cb)
813         {
814           /* More checks by utilizing the optional callback. */
815           pininfo->cb_errtext = NULL;
816           rc = pininfo->check_cb (pininfo);
817           if (rc == -1 && pininfo->cb_errtext)
818             errtext = pininfo->cb_errtext;
819           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
820                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
821             errtext = (is_pin? _("Bad PIN")
822                        : _("Bad Passphrase"));
823           else if (rc)
824             return unlock_pinentry (rc);
825         }
826
827       if (!errtext)
828         return unlock_pinentry (0); /* okay, got a PIN or passphrase */
829     }
830
831   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
832                           : GPG_ERR_BAD_PASSPHRASE));
833 }
834
835
836 \f
837 /* Ask for the passphrase using the supplied arguments.  The returned
838    passphrase needs to be freed by the caller. */
839 int 
840 agent_get_passphrase (ctrl_t ctrl,
841                       char **retpass, const char *desc, const char *prompt,
842                       const char *errtext, int with_qualitybar)
843 {
844
845   int rc;
846   char line[ASSUAN_LINELENGTH];
847   struct entry_parm_s parm;
848
849   *retpass = NULL;
850   if (opt.batch)
851     return gpg_error (GPG_ERR_BAD_PASSPHRASE); 
852
853   rc = start_pinentry (ctrl);
854   if (rc)
855     return rc;
856
857   if (!prompt)
858     prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
859
860
861   if (desc)
862     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
863   else
864     snprintf (line, DIM(line)-1, "RESET");
865   line[DIM(line)-1] = 0;
866   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
867   if (rc)
868     return unlock_pinentry (rc);
869
870   snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
871   line[DIM(line)-1] = 0;
872   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
873   if (rc)
874     return unlock_pinentry (rc);
875
876   if (with_qualitybar && opt.min_passphrase_len)
877     {
878       rc = setup_qualitybar ();
879       if (rc)
880         return unlock_pinentry (rc);
881     }
882
883   if (errtext)
884     {
885       snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
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
892   memset (&parm, 0, sizeof parm);
893   parm.size = ASSUAN_LINELENGTH/2 - 5;
894   parm.buffer = gcry_malloc_secure (parm.size+10);
895   if (!parm.buffer)
896     return unlock_pinentry (out_of_core ());
897
898   assuan_begin_confidential (entry_ctx);
899   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
900                         inq_quality, entry_ctx, NULL, NULL);
901   /* Most pinentries out in the wild return the old Assuan error code
902      for canceled which gets translated to an assuan Cancel error and
903      not to the code for a user cancel.  Fix this here. */
904   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
905     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
906   if (rc)
907     xfree (parm.buffer);
908   else
909     *retpass = parm.buffer;
910   return unlock_pinentry (rc);
911 }
912
913
914 \f
915 /* Pop up the PIN-entry, display the text and the prompt and ask the
916    user to confirm this.  We return 0 for success, ie. the user
917    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
918    other error.  If WITH_CANCEL it true an extra cancel button is
919    displayed to allow the user to easily return a GPG_ERR_CANCELED.
920    if the Pinentry does not support this, the user can still cancel by
921    closing the Pinentry window.  */
922 int 
923 agent_get_confirmation (ctrl_t ctrl,
924                         const char *desc, const char *ok, 
925                         const char *notok, int with_cancel)
926 {
927   int rc;
928   char line[ASSUAN_LINELENGTH];
929
930   rc = start_pinentry (ctrl);
931   if (rc)
932     return rc;
933
934   if (desc)
935     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
936   else
937     snprintf (line, DIM(line)-1, "RESET");
938   line[DIM(line)-1] = 0;
939   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
940   /* Most pinentries out in the wild return the old Assuan error code
941      for canceled which gets translated to an assuan Cancel error and
942      not to the code for a user cancel.  Fix this here. */
943   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
944     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
945
946   if (rc)
947     return unlock_pinentry (rc);
948
949   if (ok)
950     {
951       snprintf (line, DIM(line)-1, "SETOK %s", ok);
952       line[DIM(line)-1] = 0;
953       rc = assuan_transact (entry_ctx,
954                             line, NULL, NULL, NULL, NULL, NULL, NULL);
955       if (rc)
956         return unlock_pinentry (rc);
957     }
958   if (notok)
959     {
960       /* Try to use the newer NOTOK feature if a cancel button is
961          requested.  If no cancel button is requested we keep on using
962          the standard cancel.  */
963       if (with_cancel)
964         {
965           snprintf (line, DIM(line)-1, "SETNOTOK %s", notok);
966           line[DIM(line)-1] = 0;
967           rc = assuan_transact (entry_ctx,
968                                 line, NULL, NULL, NULL, NULL, NULL, NULL);
969         }
970       else
971         rc = GPG_ERR_ASS_UNKNOWN_CMD;
972
973       if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
974         {
975           snprintf (line, DIM(line)-1, "SETCANCEL %s", notok);
976           line[DIM(line)-1] = 0;
977           rc = assuan_transact (entry_ctx, line,
978                                 NULL, NULL, NULL, NULL, NULL, NULL);
979         }
980       if (rc)
981         return unlock_pinentry (rc);
982     }
983
984   rc = assuan_transact (entry_ctx, "CONFIRM",
985                         NULL, NULL, NULL, NULL, NULL, NULL);
986   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
987     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
988
989   return unlock_pinentry (rc);
990 }
991
992
993 \f
994 /* Pop up the PINentry, display the text DESC and a button with the
995    text OK_BTN (which may be NULL to use the default of "OK") and waut
996    for the user to hit this button.  The return value is not
997    relevant.  */
998 int 
999 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
1000 {
1001   int rc;
1002   char line[ASSUAN_LINELENGTH];
1003
1004   rc = start_pinentry (ctrl);
1005   if (rc)
1006     return rc;
1007
1008   if (desc)
1009     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1010   else
1011     snprintf (line, DIM(line)-1, "RESET");
1012   line[DIM(line)-1] = 0;
1013   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1014   /* Most pinentries out in the wild return the old Assuan error code
1015      for canceled which gets translated to an assuan Cancel error and
1016      not to the code for a user cancel.  Fix this here. */
1017   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1018     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1019
1020   if (rc)
1021     return unlock_pinentry (rc);
1022
1023   if (ok_btn)
1024     {
1025       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1026       line[DIM(line)-1] = 0;
1027       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
1028                             NULL, NULL, NULL);
1029       if (rc)
1030         return unlock_pinentry (rc);
1031     }
1032   
1033   rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
1034                         NULL, NULL, NULL);
1035   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1036     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1037
1038   return unlock_pinentry (rc);
1039 }
1040
1041
1042 /* The thread running the popup message. */
1043 static void *
1044 popup_message_thread (void *arg)
1045 {
1046   (void)arg;
1047
1048   /* We use the --one-button hack instead of the MESSAGE command to
1049      allow the use of old Pinentries.  Those old Pinentries will then
1050      show an additional Cancel button but that is mostly a visual
1051      annoyance. */
1052   assuan_transact (entry_ctx, "CONFIRM --one-button", 
1053                    NULL, NULL, NULL, NULL, NULL, NULL);
1054   popup_finished = 1;
1055   return NULL;
1056 }
1057
1058
1059 /* Pop up a message window similar to the confirm one but keep it open
1060    until agent_popup_message_stop has been called.  It is crucial for
1061    the caller to make sure that the stop function gets called as soon
1062    as the message is not anymore required because the message is
1063    system modal and all other attempts to use the pinentry will fail
1064    (after a timeout). */
1065 int 
1066 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
1067 {
1068   int rc;
1069   char line[ASSUAN_LINELENGTH];
1070   pth_attr_t tattr;
1071
1072   rc = start_pinentry (ctrl);
1073   if (rc)
1074     return rc;
1075
1076   if (desc)
1077     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1078   else
1079     snprintf (line, DIM(line)-1, "RESET");
1080   line[DIM(line)-1] = 0;
1081   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1082   if (rc)
1083     return unlock_pinentry (rc);
1084
1085   if (ok_btn)
1086     {
1087       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1088       line[DIM(line)-1] = 0;
1089       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1090       if (rc)
1091         return unlock_pinentry (rc);
1092     }
1093
1094   tattr = pth_attr_new();
1095   pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
1096   pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
1097   pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
1098
1099   popup_finished = 0;
1100   popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
1101   if (!popup_tid)
1102     {
1103       rc = gpg_error_from_syserror ();
1104       log_error ("error spawning popup message handler: %s\n",
1105                  strerror (errno) );
1106       pth_attr_destroy (tattr);
1107       return unlock_pinentry (rc);
1108     }
1109   pth_attr_destroy (tattr);
1110
1111   return 0;
1112 }
1113
1114 /* Close a popup window. */
1115 void
1116 agent_popup_message_stop (ctrl_t ctrl)
1117 {
1118   int rc;
1119   pid_t pid;
1120
1121   (void)ctrl;
1122
1123   if (!popup_tid || !entry_ctx)
1124     {
1125       log_debug ("agent_popup_message_stop called with no active popup\n");
1126       return; 
1127     }
1128
1129   pid = assuan_get_pid (entry_ctx);
1130   if (pid == (pid_t)(-1))
1131     ; /* No pid available can't send a kill. */
1132   else if (popup_finished)
1133     ; /* Already finished and ready for joining. */
1134 #ifdef HAVE_W32_SYSTEM
1135   /* Older versions of assuan set PID to 0 on Windows to indicate an
1136      invalid value.  */
1137   else if (pid != (pid_t) INVALID_HANDLE_VALUE
1138            && pid != 0)
1139     {
1140       HANDLE process = (HANDLE) pid;
1141       
1142       /* Arbitrary error code.  */
1143       TerminateProcess (process, 1);
1144     }
1145 #else
1146   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1147     { /* The daemon already died.  No need to send a kill.  However
1148          because we already waited for the process, we need to tell
1149          assuan that it should not wait again (done by
1150          unlock_pinentry). */
1151       if (rc == pid)
1152         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1153     }
1154   else if (pid > 0)
1155     kill (pid, SIGKILL);  /* Need to use SIGKILL due to bad
1156                              interaction of SIGINT with Pth. */
1157 #endif
1158
1159   /* Now wait for the thread to terminate. */
1160   rc = pth_join (popup_tid, NULL);
1161   if (!rc)
1162     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1163                strerror (errno));
1164   popup_tid = NULL;
1165   entry_owner = NULL;
1166
1167   /* Now we can close the connection. */
1168   unlock_pinentry (0);
1169 }
1170
1171