Fix dirmngr problems on CE.
[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 "sysutils.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                 gnupg_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   int saveflag;
709
710   if (opt.batch)
711     return 0; /* fixme: we should return BAD PIN */
712
713   if (!pininfo || pininfo->max_length < 1)
714     return gpg_error (GPG_ERR_INV_VALUE);
715   if (!desc_text && pininfo->min_digits)
716     desc_text = _("Please enter your PIN, so that the secret key "
717                   "can be unlocked for this session");
718   else if (!desc_text)
719     desc_text = _("Please enter your passphrase, so that the secret key "
720                   "can be unlocked for this session");
721
722   if (prompt_text)
723     is_pin = !!strstr (prompt_text, "PIN");
724   else
725     is_pin = desc_text && strstr (desc_text, "PIN");
726
727   rc = start_pinentry (ctrl);
728   if (rc)
729     return rc;
730
731   snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
732   line[DIM(line)-1] = 0;
733   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
734   if (rc)
735     return unlock_pinentry (rc);
736
737   snprintf (line, DIM(line)-1, "SETPROMPT %s",
738             prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
739   line[DIM(line)-1] = 0;
740   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
741   if (rc)
742     return unlock_pinentry (rc);
743
744   /* If a passphrase quality indicator has been requested and a
745      minimum passphrase length has not been disabled, send the command
746      to the pinentry.  */
747   if (pininfo->with_qualitybar && opt.min_passphrase_len )
748     {
749       rc = setup_qualitybar ();
750       if (rc)
751         return unlock_pinentry (rc);
752     }
753
754   if (initial_errtext)
755     { 
756       snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
757       line[DIM(line)-1] = 0;
758       rc = assuan_transact (entry_ctx, line,
759                             NULL, NULL, NULL, NULL, NULL, NULL);
760       if (rc)
761         return unlock_pinentry (rc);
762     }
763
764   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
765     {
766       memset (&parm, 0, sizeof parm);
767       parm.size = pininfo->max_length;
768       *pininfo->pin = 0; /* Reset the PIN. */
769       parm.buffer = (unsigned char*)pininfo->pin;
770
771       if (errtext)
772         { 
773           /* TRANLATORS: The string is appended to an error message in
774              the pinentry.  The %s is the actual error message, the
775              two %d give the current and maximum number of tries. */
776           snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
777                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
778           line[DIM(line)-1] = 0;
779           rc = assuan_transact (entry_ctx, line,
780                                 NULL, NULL, NULL, NULL, NULL, NULL);
781           if (rc)
782             return unlock_pinentry (rc);
783           errtext = NULL;
784         }
785       
786       saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
787       assuan_begin_confidential (entry_ctx);
788       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
789                             inq_quality, entry_ctx, NULL, NULL);
790       assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
791       /* Most pinentries out in the wild return the old Assuan error code
792          for canceled which gets translated to an assuan Cancel error and
793          not to the code for a user cancel.  Fix this here. */
794       if (rc && gpg_err_source (rc)
795           && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
796         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
797
798       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
799         errtext = is_pin? _("PIN too long")
800                         : _("Passphrase too long");
801       else if (rc)
802         return unlock_pinentry (rc);
803
804       if (!errtext && pininfo->min_digits)
805         {
806           /* do some basic checks on the entered PIN. */
807           if (!all_digitsp (pininfo->pin))
808             errtext = _("Invalid characters in PIN");
809           else if (pininfo->max_digits
810                    && strlen (pininfo->pin) > pininfo->max_digits)
811             errtext = _("PIN too long");
812           else if (strlen (pininfo->pin) < pininfo->min_digits)
813             errtext = _("PIN too short");
814         }
815
816       if (!errtext && pininfo->check_cb)
817         {
818           /* More checks by utilizing the optional callback. */
819           pininfo->cb_errtext = NULL;
820           rc = pininfo->check_cb (pininfo);
821           if (rc == -1 && pininfo->cb_errtext)
822             errtext = pininfo->cb_errtext;
823           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
824                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
825             errtext = (is_pin? _("Bad PIN")
826                        : _("Bad Passphrase"));
827           else if (rc)
828             return unlock_pinentry (rc);
829         }
830
831       if (!errtext)
832         return unlock_pinentry (0); /* okay, got a PIN or passphrase */
833     }
834
835   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
836                           : GPG_ERR_BAD_PASSPHRASE));
837 }
838
839
840 \f
841 /* Ask for the passphrase using the supplied arguments.  The returned
842    passphrase needs to be freed by the caller. */
843 int 
844 agent_get_passphrase (ctrl_t ctrl,
845                       char **retpass, const char *desc, const char *prompt,
846                       const char *errtext, int with_qualitybar)
847 {
848
849   int rc;
850   char line[ASSUAN_LINELENGTH];
851   struct entry_parm_s parm;
852   int saveflag;
853
854   *retpass = NULL;
855   if (opt.batch)
856     return gpg_error (GPG_ERR_BAD_PASSPHRASE); 
857
858   rc = start_pinentry (ctrl);
859   if (rc)
860     return rc;
861
862   if (!prompt)
863     prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
864
865
866   if (desc)
867     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
868   else
869     snprintf (line, DIM(line)-1, "RESET");
870   line[DIM(line)-1] = 0;
871   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
872   if (rc)
873     return unlock_pinentry (rc);
874
875   snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
876   line[DIM(line)-1] = 0;
877   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
878   if (rc)
879     return unlock_pinentry (rc);
880
881   if (with_qualitybar && opt.min_passphrase_len)
882     {
883       rc = setup_qualitybar ();
884       if (rc)
885         return unlock_pinentry (rc);
886     }
887
888   if (errtext)
889     {
890       snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
891       line[DIM(line)-1] = 0;
892       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
893       if (rc)
894         return unlock_pinentry (rc);
895     }
896
897   memset (&parm, 0, sizeof parm);
898   parm.size = ASSUAN_LINELENGTH/2 - 5;
899   parm.buffer = gcry_malloc_secure (parm.size+10);
900   if (!parm.buffer)
901     return unlock_pinentry (out_of_core ());
902
903   saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
904   assuan_begin_confidential (entry_ctx);
905   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
906                         inq_quality, entry_ctx, NULL, NULL);
907   assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
908   /* Most pinentries out in the wild return the old Assuan error code
909      for canceled which gets translated to an assuan Cancel error and
910      not to the code for a user cancel.  Fix this here. */
911   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
912     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
913   if (rc)
914     xfree (parm.buffer);
915   else
916     *retpass = parm.buffer;
917   return unlock_pinentry (rc);
918 }
919
920
921 \f
922 /* Pop up the PIN-entry, display the text and the prompt and ask the
923    user to confirm this.  We return 0 for success, ie. the user
924    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
925    other error.  If WITH_CANCEL it true an extra cancel button is
926    displayed to allow the user to easily return a GPG_ERR_CANCELED.
927    if the Pinentry does not support this, the user can still cancel by
928    closing the Pinentry window.  */
929 int 
930 agent_get_confirmation (ctrl_t ctrl,
931                         const char *desc, const char *ok, 
932                         const char *notok, int with_cancel)
933 {
934   int rc;
935   char line[ASSUAN_LINELENGTH];
936
937   rc = start_pinentry (ctrl);
938   if (rc)
939     return rc;
940
941   if (desc)
942     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
943   else
944     snprintf (line, DIM(line)-1, "RESET");
945   line[DIM(line)-1] = 0;
946   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
947   /* Most pinentries out in the wild return the old Assuan error code
948      for canceled which gets translated to an assuan Cancel error and
949      not to the code for a user cancel.  Fix this here. */
950   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
951     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
952
953   if (rc)
954     return unlock_pinentry (rc);
955
956   if (ok)
957     {
958       snprintf (line, DIM(line)-1, "SETOK %s", ok);
959       line[DIM(line)-1] = 0;
960       rc = assuan_transact (entry_ctx,
961                             line, NULL, NULL, NULL, NULL, NULL, NULL);
962       if (rc)
963         return unlock_pinentry (rc);
964     }
965   if (notok)
966     {
967       /* Try to use the newer NOTOK feature if a cancel button is
968          requested.  If no cancel button is requested we keep on using
969          the standard cancel.  */
970       if (with_cancel)
971         {
972           snprintf (line, DIM(line)-1, "SETNOTOK %s", notok);
973           line[DIM(line)-1] = 0;
974           rc = assuan_transact (entry_ctx,
975                                 line, NULL, NULL, NULL, NULL, NULL, NULL);
976         }
977       else
978         rc = GPG_ERR_ASS_UNKNOWN_CMD;
979
980       if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
981         {
982           snprintf (line, DIM(line)-1, "SETCANCEL %s", notok);
983           line[DIM(line)-1] = 0;
984           rc = assuan_transact (entry_ctx, line,
985                                 NULL, NULL, NULL, NULL, NULL, NULL);
986         }
987       if (rc)
988         return unlock_pinentry (rc);
989     }
990
991   rc = assuan_transact (entry_ctx, "CONFIRM",
992                         NULL, NULL, NULL, NULL, NULL, NULL);
993   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
994     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
995
996   return unlock_pinentry (rc);
997 }
998
999
1000 \f
1001 /* Pop up the PINentry, display the text DESC and a button with the
1002    text OK_BTN (which may be NULL to use the default of "OK") and waut
1003    for the user to hit this button.  The return value is not
1004    relevant.  */
1005 int 
1006 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
1007 {
1008   int rc;
1009   char line[ASSUAN_LINELENGTH];
1010
1011   rc = start_pinentry (ctrl);
1012   if (rc)
1013     return rc;
1014
1015   if (desc)
1016     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1017   else
1018     snprintf (line, DIM(line)-1, "RESET");
1019   line[DIM(line)-1] = 0;
1020   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1021   /* Most pinentries out in the wild return the old Assuan error code
1022      for canceled which gets translated to an assuan Cancel error and
1023      not to the code for a user cancel.  Fix this here. */
1024   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1025     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1026
1027   if (rc)
1028     return unlock_pinentry (rc);
1029
1030   if (ok_btn)
1031     {
1032       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1033       line[DIM(line)-1] = 0;
1034       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
1035                             NULL, NULL, NULL);
1036       if (rc)
1037         return unlock_pinentry (rc);
1038     }
1039   
1040   rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
1041                         NULL, NULL, NULL);
1042   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1043     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1044
1045   return unlock_pinentry (rc);
1046 }
1047
1048
1049 /* The thread running the popup message. */
1050 static void *
1051 popup_message_thread (void *arg)
1052 {
1053   (void)arg;
1054
1055   /* We use the --one-button hack instead of the MESSAGE command to
1056      allow the use of old Pinentries.  Those old Pinentries will then
1057      show an additional Cancel button but that is mostly a visual
1058      annoyance. */
1059   assuan_transact (entry_ctx, "CONFIRM --one-button", 
1060                    NULL, NULL, NULL, NULL, NULL, NULL);
1061   popup_finished = 1;
1062   return NULL;
1063 }
1064
1065
1066 /* Pop up a message window similar to the confirm one but keep it open
1067    until agent_popup_message_stop has been called.  It is crucial for
1068    the caller to make sure that the stop function gets called as soon
1069    as the message is not anymore required because the message is
1070    system modal and all other attempts to use the pinentry will fail
1071    (after a timeout). */
1072 int 
1073 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
1074 {
1075   int rc;
1076   char line[ASSUAN_LINELENGTH];
1077   pth_attr_t tattr;
1078
1079   rc = start_pinentry (ctrl);
1080   if (rc)
1081     return rc;
1082
1083   if (desc)
1084     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1085   else
1086     snprintf (line, DIM(line)-1, "RESET");
1087   line[DIM(line)-1] = 0;
1088   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1089   if (rc)
1090     return unlock_pinentry (rc);
1091
1092   if (ok_btn)
1093     {
1094       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1095       line[DIM(line)-1] = 0;
1096       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1097       if (rc)
1098         return unlock_pinentry (rc);
1099     }
1100
1101   tattr = pth_attr_new();
1102   pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
1103   pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
1104   pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
1105
1106   popup_finished = 0;
1107   popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
1108   if (!popup_tid)
1109     {
1110       rc = gpg_error_from_syserror ();
1111       log_error ("error spawning popup message handler: %s\n",
1112                  strerror (errno) );
1113       pth_attr_destroy (tattr);
1114       return unlock_pinentry (rc);
1115     }
1116   pth_attr_destroy (tattr);
1117
1118   return 0;
1119 }
1120
1121 /* Close a popup window. */
1122 void
1123 agent_popup_message_stop (ctrl_t ctrl)
1124 {
1125   int rc;
1126   pid_t pid;
1127
1128   (void)ctrl;
1129
1130   if (!popup_tid || !entry_ctx)
1131     {
1132       log_debug ("agent_popup_message_stop called with no active popup\n");
1133       return; 
1134     }
1135
1136   pid = assuan_get_pid (entry_ctx);
1137   if (pid == (pid_t)(-1))
1138     ; /* No pid available can't send a kill. */
1139   else if (popup_finished)
1140     ; /* Already finished and ready for joining. */
1141 #ifdef HAVE_W32_SYSTEM
1142   /* Older versions of assuan set PID to 0 on Windows to indicate an
1143      invalid value.  */
1144   else if (pid != (pid_t) INVALID_HANDLE_VALUE
1145            && pid != 0)
1146     {
1147       HANDLE process = (HANDLE) pid;
1148       
1149       /* Arbitrary error code.  */
1150       TerminateProcess (process, 1);
1151     }
1152 #else
1153   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1154     { /* The daemon already died.  No need to send a kill.  However
1155          because we already waited for the process, we need to tell
1156          assuan that it should not wait again (done by
1157          unlock_pinentry). */
1158       if (rc == pid)
1159         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1160     }
1161   else if (pid > 0)
1162     kill (pid, SIGKILL);  /* Need to use SIGKILL due to bad
1163                              interaction of SIGINT with Pth. */
1164 #endif
1165
1166   /* Now wait for the thread to terminate. */
1167   rc = pth_join (popup_tid, NULL);
1168   if (!rc)
1169     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1170                strerror (errno));
1171   popup_tid = NULL;
1172   entry_owner = NULL;
1173
1174   /* Now we can close the connection. */
1175   unlock_pinentry (0);
1176 }
1177
1178