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