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