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