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