chiark / gitweb /
Import gnupg2_2.1.17.orig.tar.bz2
[gnupg2.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 <https://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 <npth.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 mutually exclusive dialog) we better timeout pending
51    requests after some time.  1 minute 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 npth_mutex_t entry_lock;
66
67 /* The thread ID of the popup working thread. */
68 static npth_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 (npth_mutex_init (&entry_lock, NULL))
99         initialized = 1;
100     }
101 }
102
103
104
105 /* This function may be called to print infromation pertaining to the
106    current state of this module to the log. */
107 void
108 agent_query_dump_state (void)
109 {
110   log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
111             entry_ctx, (long)assuan_get_pid (entry_ctx), (void*)popup_tid);
112 }
113
114 /* Called to make sure that a popup window owned by the current
115    connection gets closed. */
116 void
117 agent_reset_query (ctrl_t ctrl)
118 {
119   if (entry_ctx && popup_tid && entry_owner == ctrl)
120     {
121       agent_popup_message_stop (ctrl);
122     }
123 }
124
125
126 /* Unlock the pinentry so that another thread can start one and
127    disconnect that pinentry - we do this after the unlock so that a
128    stalled pinentry does not block other threads.  Fixme: We should
129    have a timeout in Assuan for the disconnect operation. */
130 static gpg_error_t
131 unlock_pinentry (gpg_error_t rc)
132 {
133   assuan_context_t ctx = entry_ctx;
134   int err;
135
136   if (rc)
137     {
138       if (DBG_IPC)
139         log_debug ("error calling pinentry: %s <%s>\n",
140                    gpg_strerror (rc), gpg_strsource (rc));
141
142       /* Change the source of the error to pinentry so that the final
143          consumer of the error code knows that the problem is with
144          pinentry.  For backward compatibility we do not do that for
145          some common error codes.  */
146       switch (gpg_err_code (rc))
147         {
148         case GPG_ERR_NO_PIN_ENTRY:
149         case GPG_ERR_CANCELED:
150         case GPG_ERR_FULLY_CANCELED:
151         case GPG_ERR_ASS_UNKNOWN_INQUIRE:
152         case GPG_ERR_ASS_TOO_MUCH_DATA:
153         case GPG_ERR_NO_PASSPHRASE:
154         case GPG_ERR_BAD_PASSPHRASE:
155         case GPG_ERR_BAD_PIN:
156           break;
157
158         default:
159           rc = gpg_err_make (GPG_ERR_SOURCE_PINENTRY, gpg_err_code (rc));
160           break;
161         }
162     }
163
164   entry_ctx = NULL;
165   err = npth_mutex_unlock (&entry_lock);
166   if (err)
167     {
168       log_error ("failed to release the entry lock: %s\n", strerror (err));
169       if (!rc)
170         rc = gpg_error_from_errno (err);
171     }
172   assuan_release (ctx);
173   return rc;
174 }
175
176
177 /* To make sure we leave no secrets in our image after forking of the
178    pinentry, we use this callback. */
179 static void
180 atfork_cb (void *opaque, int where)
181 {
182   ctrl_t ctrl = opaque;
183
184   if (!where)
185     {
186       int iterator = 0;
187       const char *name, *assname, *value;
188
189       gcry_control (GCRYCTL_TERM_SECMEM);
190
191       while ((name = session_env_list_stdenvnames (&iterator, &assname)))
192         {
193           /* For all new envvars (!ASSNAME) and the two medium old
194              ones which do have an assuan name but are conveyed using
195              environment variables, update the environment of the
196              forked process.  */
197           if (!assname
198               || !strcmp (name, "XAUTHORITY")
199               || !strcmp (name, "PINENTRY_USER_DATA"))
200             {
201               value = session_env_getenv (ctrl->session_env, name);
202               if (value)
203                 gnupg_setenv (name, value, 1);
204             }
205         }
206     }
207 }
208
209
210 static gpg_error_t
211 getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
212 {
213   unsigned long *pid = opaque;
214   char pidbuf[50];
215
216   /* There is only the pid in the server's response.  */
217   if (length >= sizeof pidbuf)
218     length = sizeof pidbuf -1;
219   if (length)
220     {
221       strncpy (pidbuf, buffer, length);
222       pidbuf[length] = 0;
223       *pid = strtoul (pidbuf, NULL, 10);
224     }
225   return 0;
226 }
227
228
229 /* Fork off the pin entry if this has not already been done.  Note,
230    that this function must always be used to acquire the lock for the
231    pinentry - we will serialize _all_ pinentry calls.
232  */
233 static gpg_error_t
234 start_pinentry (ctrl_t ctrl)
235 {
236   int rc = 0;
237   const char *full_pgmname;
238   const char *pgmname;
239   assuan_context_t ctx;
240   const char *argv[5];
241   assuan_fd_t no_close_list[3];
242   int i;
243   const char *tmpstr;
244   unsigned long pinentry_pid;
245   const char *value;
246   struct timespec abstime;
247   char *flavor_version;
248   int err;
249
250   npth_clock_gettime (&abstime);
251   abstime.tv_sec += LOCK_TIMEOUT;
252   err = npth_mutex_timedlock (&entry_lock, &abstime);
253   if (err)
254     {
255       if (err == ETIMEDOUT)
256         rc = gpg_error (GPG_ERR_TIMEOUT);
257       else
258         rc = gpg_error_from_errno (rc);
259       log_error (_("failed to acquire the pinentry lock: %s\n"),
260                  gpg_strerror (rc));
261       return rc;
262     }
263
264   entry_owner = ctrl;
265
266   if (entry_ctx)
267     return 0;
268
269   if (opt.verbose)
270     log_info ("starting a new PIN Entry\n");
271
272 #ifdef HAVE_W32_SYSTEM
273   fflush (stdout);
274   fflush (stderr);
275 #endif
276   if (fflush (NULL))
277     {
278 #ifndef HAVE_W32_SYSTEM
279       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
280 #endif
281       log_error ("error flushing pending output: %s\n", strerror (errno));
282       /* At least Windows XP fails here with EBADF.  According to docs
283          and Wine an fflush(NULL) is the same as _flushall.  However
284          the Wine implementaion does not flush stdin,stdout and stderr
285          - see above.  Let's try to ignore the error. */
286 #ifndef HAVE_W32_SYSTEM
287       return unlock_pinentry (tmperr);
288 #endif
289     }
290
291   full_pgmname = opt.pinentry_program;
292   if (!full_pgmname || !*full_pgmname)
293     full_pgmname = gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY);
294   if ( !(pgmname = strrchr (full_pgmname, '/')))
295     pgmname = full_pgmname;
296   else
297     pgmname++;
298
299   /* OS X needs the entire file name in argv[0], so that it can locate
300      the resource bundle.  For other systems we stick to the usual
301      convention of supplying only the name of the program.  */
302 #ifdef __APPLE__
303   argv[0] = full_pgmname;
304 #else /*!__APPLE__*/
305   argv[0] = pgmname;
306 #endif /*__APPLE__*/
307
308   if (!opt.keep_display
309       && (value = session_env_getenv (ctrl->session_env, "DISPLAY")))
310     {
311       argv[1] = "--display";
312       argv[2] = value;
313       argv[3] = NULL;
314     }
315   else
316     argv[1] = NULL;
317
318   i=0;
319   if (!opt.running_detached)
320     {
321       if (log_get_fd () != -1)
322         no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
323       no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
324     }
325   no_close_list[i] = ASSUAN_INVALID_FD;
326
327   rc = assuan_new (&ctx);
328   if (rc)
329     {
330       log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
331       return rc;
332     }
333   /* We don't want to log the pinentry communication to make the logs
334      easier to read.  We might want to add a new debug option to enable
335      pinentry logging.  */
336 #ifdef ASSUAN_NO_LOGGING
337   assuan_set_flag (ctx, ASSUAN_NO_LOGGING, !opt.debug_pinentry);
338 #endif
339
340   /* Connect to the pinentry and perform initial handshaking.  Note
341      that atfork is used to change the environment for pinentry.  We
342      start the server in detached mode to suppress the console window
343      under Windows.  */
344   rc = assuan_pipe_connect (ctx, full_pgmname, argv,
345                             no_close_list, atfork_cb, ctrl,
346                             ASSUAN_PIPE_CONNECT_DETACHED);
347   if (rc)
348     {
349       log_error ("can't connect to the PIN entry module '%s': %s\n",
350                  full_pgmname, gpg_strerror (rc));
351       assuan_release (ctx);
352       return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
353     }
354   entry_ctx = ctx;
355
356   if (DBG_IPC)
357     log_debug ("connection to PIN entry established\n");
358
359   value = session_env_getenv (ctrl->session_env, "PINENTRY_USER_DATA");
360   if (value != NULL)
361     {
362       char *optstr;
363       if (asprintf (&optstr, "OPTION pinentry-user-data=%s", value) < 0 )
364         return unlock_pinentry (out_of_core ());
365       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
366                             NULL);
367       xfree (optstr);
368       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
369         return unlock_pinentry (rc);
370     }
371
372   rc = assuan_transact (entry_ctx,
373                         opt.no_grab? "OPTION no-grab":"OPTION grab",
374                         NULL, NULL, NULL, NULL, NULL, NULL);
375   if (rc)
376     return unlock_pinentry (rc);
377
378   value = session_env_getenv (ctrl->session_env, "GPG_TTY");
379   if (value)
380     {
381       char *optstr;
382       if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
383         return unlock_pinentry (out_of_core ());
384       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
385                             NULL);
386       xfree (optstr);
387       if (rc)
388         return unlock_pinentry (rc);
389     }
390   value = session_env_getenv (ctrl->session_env, "TERM");
391   if (value)
392     {
393       char *optstr;
394       if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
395         return unlock_pinentry (out_of_core ());
396       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
397                             NULL);
398       xfree (optstr);
399       if (rc)
400         return unlock_pinentry (rc);
401     }
402   if (ctrl->lc_ctype)
403     {
404       char *optstr;
405       if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
406         return unlock_pinentry (out_of_core ());
407       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
408                             NULL);
409       xfree (optstr);
410       if (rc)
411         return unlock_pinentry (rc);
412     }
413   if (ctrl->lc_messages)
414     {
415       char *optstr;
416       if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
417         return unlock_pinentry (out_of_core ());
418       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
419                             NULL);
420       xfree (optstr);
421       if (rc)
422         return unlock_pinentry (rc);
423     }
424
425
426   if (opt.allow_external_cache)
427     {
428       /* Indicate to the pinentry that it may read from an external cache.
429
430          It is essential that the pinentry respect this.  If the
431          cached password is not up to date and retry == 1, then, using
432          a version of GPG Agent that doesn't support this, won't issue
433          another pin request and the user won't get a chance to
434          correct the password.  */
435       rc = assuan_transact (entry_ctx, "OPTION allow-external-password-cache",
436                             NULL, NULL, NULL, NULL, NULL, NULL);
437       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
438         return unlock_pinentry (rc);
439     }
440
441   if (opt.allow_emacs_pinentry)
442     {
443       /* Indicate to the pinentry that it may read passphrase through
444          Emacs minibuffer, if possible.  */
445       rc = assuan_transact (entry_ctx, "OPTION allow-emacs-prompt",
446                             NULL, NULL, NULL, NULL, NULL, NULL);
447       if (rc && gpg_err_code (rc) != GPG_ERR_UNKNOWN_OPTION)
448         return unlock_pinentry (rc);
449     }
450
451
452   {
453     /* Provide a few default strings for use by the pinentries.  This
454        may help a pinentry to avoid implementing localization code.  */
455     static struct { const char *key, *value; int what; } tbl[] = {
456       /* TRANSLATORS: These are labels for buttons etc used in
457          Pinentries.  An underscore indicates that the next letter
458          should be used as an accelerator.  Double the underscore for
459          a literal one.  The actual to be translated text starts after
460          the second vertical bar.  Note that gpg-agent has been set to
461          utf-8 so that the strings are in the expected encoding.  */
462       { "ok",     N_("|pinentry-label|_OK") },
463       { "cancel", N_("|pinentry-label|_Cancel") },
464       { "yes",    N_("|pinentry-label|_Yes") },
465       { "no",     N_("|pinentry-label|_No") },
466       { "prompt", N_("|pinentry-label|PIN:") },
467       { "pwmngr", N_("|pinentry-label|_Save in password manager"), 1 },
468       { "cf-visi",N_("Do you really want to make your "
469                      "passphrase visible on the screen?") },
470       { "tt-visi",N_("|pinentry-tt|Make passphrase visible") },
471       { "tt-hide",N_("|pinentry-tt|Hide passphrase") },
472       { NULL, NULL}
473     };
474     char *optstr;
475     int idx;
476     const char *s, *s2;
477
478     for (idx=0; tbl[idx].key; idx++)
479       {
480         if (!opt.allow_external_cache && tbl[idx].what == 1)
481           continue;  /* No need for it.  */
482         s = L_(tbl[idx].value);
483         if (*s == '|' && (s2=strchr (s+1,'|')))
484           s = s2+1;
485         if (asprintf (&optstr, "OPTION default-%s=%s", tbl[idx].key, s) < 0 )
486           return unlock_pinentry (out_of_core ());
487         assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
488                          NULL);
489         xfree (optstr);
490       }
491   }
492
493   /* Tell the pinentry that we would prefer that the given character
494      is used as the invisible character by the entry widget.  */
495   if (opt.pinentry_invisible_char)
496     {
497       char *optstr;
498       if ((optstr = xtryasprintf ("OPTION invisible-char=%s",
499                                   opt.pinentry_invisible_char)))
500         {
501           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
502                            NULL);
503           /* We ignore errors because this is just a fancy thing and
504              older pinentries do not support this feature.  */
505           xfree (optstr);
506         }
507     }
508
509   if (opt.pinentry_timeout)
510     {
511       char *optstr;
512       if ((optstr = xtryasprintf ("SETTIMEOUT %lu", opt.pinentry_timeout)))
513         {
514           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
515                            NULL);
516           /* We ignore errors because this is just a fancy thing.  */
517           xfree (optstr);
518         }
519     }
520
521   /* Tell the pinentry the name of a file it shall touch after having
522      messed with the tty.  This is optional and only supported by
523      newer pinentries and thus we do no error checking. */
524   tmpstr = opt.pinentry_touch_file;
525   if (tmpstr && !strcmp (tmpstr, "/dev/null"))
526     tmpstr = NULL;
527   else if (!tmpstr)
528     tmpstr = get_agent_socket_name ();
529   if (tmpstr)
530     {
531       char *optstr;
532
533       if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
534         ;
535       else
536         {
537           assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
538                            NULL);
539           xfree (optstr);
540         }
541     }
542
543
544   /* Ask the pinentry for its version and flavor and streo that as a
545    * string in MB.  This information is useful for helping users to
546    * figure out Pinentry problems.  */
547   {
548     membuf_t mb;
549
550     init_membuf (&mb, 256);
551     if (assuan_transact (entry_ctx, "GETINFO flavor",
552                          put_membuf_cb, &mb, NULL, NULL, NULL, NULL))
553       put_membuf_str (&mb, "unknown");
554     put_membuf_str (&mb, " ");
555     if (assuan_transact (entry_ctx, "GETINFO version",
556                          put_membuf_cb, &mb, NULL, NULL, NULL, NULL))
557       put_membuf_str (&mb, "unknown");
558     put_membuf (&mb, "", 1);
559     flavor_version = get_membuf (&mb, NULL);
560   }
561
562
563   /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
564      it will send the pid back and we will use an inquire to notify
565      our client.  The client may answer the inquiry either with END or
566      with CAN to cancel the pinentry. */
567   rc = assuan_transact (entry_ctx, "GETINFO pid",
568                         getinfo_pid_cb, &pinentry_pid,
569                         NULL, NULL, NULL, NULL);
570   if (rc)
571     {
572       log_info ("You may want to update to a newer pinentry\n");
573       rc = 0;
574     }
575   else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
576     log_error ("pinentry did not return a PID\n");
577   else
578     {
579       rc = agent_inq_pinentry_launched (ctrl, pinentry_pid, flavor_version);
580       if (gpg_err_code (rc) == GPG_ERR_CANCELED
581           || gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
582         return unlock_pinentry (gpg_err_make (GPG_ERR_SOURCE_DEFAULT,
583                                               gpg_err_code (rc)));
584       rc = 0;
585     }
586
587   xfree (flavor_version);
588
589   return 0;
590 }
591
592
593 /* Returns True if the pinentry is currently active. If WAITSECONDS is
594    greater than zero the function will wait for this many seconds
595    before returning.  */
596 int
597 pinentry_active_p (ctrl_t ctrl, int waitseconds)
598 {
599   int err;
600   (void)ctrl;
601
602   if (waitseconds > 0)
603     {
604       struct timespec abstime;
605       int rc;
606
607       npth_clock_gettime (&abstime);
608       abstime.tv_sec += waitseconds;
609       err = npth_mutex_timedlock (&entry_lock, &abstime);
610       if (err)
611         {
612           if (err == ETIMEDOUT)
613             rc = gpg_error (GPG_ERR_TIMEOUT);
614           else
615             rc = gpg_error (GPG_ERR_INTERNAL);
616           return rc;
617         }
618     }
619   else
620     {
621       err = npth_mutex_trylock (&entry_lock);
622       if (err)
623         return gpg_error (GPG_ERR_LOCKED);
624     }
625
626   err = npth_mutex_unlock (&entry_lock);
627   if (err)
628     log_error ("failed to release the entry lock at %d: %s\n", __LINE__,
629                strerror (errno));
630   return 0;
631 }
632
633
634 static gpg_error_t
635 getpin_cb (void *opaque, const void *buffer, size_t length)
636 {
637   struct entry_parm_s *parm = opaque;
638
639   if (!buffer)
640     return 0;
641
642   /* we expect the pin to fit on one line */
643   if (parm->lines || length >= parm->size)
644     return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
645
646   /* fixme: we should make sure that the assuan buffer is allocated in
647      secure memory or read the response byte by byte */
648   memcpy (parm->buffer, buffer, length);
649   parm->buffer[length] = 0;
650   parm->lines++;
651   return 0;
652 }
653
654
655 static int
656 all_digitsp( const char *s)
657 {
658   for (; *s && *s >= '0' && *s <= '9'; s++)
659     ;
660   return !*s;
661 }
662
663
664 /* Return a new malloced string by unescaping the string S.  Escaping
665    is percent escaping and '+'/space mapping.  A binary Nul will
666    silently be replaced by a 0xFF.  Function returns NULL to indicate
667    an out of memory status.  Parsing stops at the end of the string or
668    a white space character. */
669 static char *
670 unescape_passphrase_string (const unsigned char *s)
671 {
672   char *buffer, *d;
673
674   buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
675   if (!buffer)
676     return NULL;
677   while (*s && !spacep (s))
678     {
679       if (*s == '%' && s[1] && s[2])
680         {
681           s++;
682           *d = xtoi_2 (s);
683           if (!*d)
684             *d = '\xff';
685           d++;
686           s += 2;
687         }
688       else if (*s == '+')
689         {
690           *d++ = ' ';
691           s++;
692         }
693       else
694         *d++ = *s++;
695     }
696   *d = 0;
697   return buffer;
698 }
699
700
701 /* Estimate the quality of the passphrase PW and return a value in the
702    range 0..100.  */
703 static int
704 estimate_passphrase_quality (const char *pw)
705 {
706   int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
707   int length;
708   const char *s;
709
710   if (goodlength < 1)
711     return 0;
712
713   for (length = 0, s = pw; *s; s++)
714     if (!spacep (s))
715       length ++;
716
717   if (length > goodlength)
718     return 100;
719   return ((length*10) / goodlength)*10;
720 }
721
722
723 /* Handle the QUALITY inquiry. */
724 static gpg_error_t
725 inq_quality (void *opaque, const char *line)
726 {
727   assuan_context_t ctx = opaque;
728   const char *s;
729   char *pin;
730   int rc;
731   int percent;
732   char numbuf[20];
733
734   if ((s = has_leading_keyword (line, "QUALITY")))
735     {
736       pin = unescape_passphrase_string (s);
737       if (!pin)
738         rc = gpg_error_from_syserror ();
739       else
740         {
741           percent = estimate_passphrase_quality (pin);
742           if (check_passphrase_constraints (NULL, pin, NULL))
743             percent = -percent;
744           snprintf (numbuf, sizeof numbuf, "%d", percent);
745           rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
746           xfree (pin);
747         }
748     }
749   else
750     {
751       log_error ("unsupported inquiry '%s' from pinentry\n", line);
752       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
753     }
754
755   return rc;
756 }
757
758
759 /* Helper for agent_askpin and agent_get_passphrase.  */
760 static gpg_error_t
761 setup_qualitybar (ctrl_t ctrl)
762 {
763   int rc;
764   char line[ASSUAN_LINELENGTH];
765   char *tmpstr, *tmpstr2;
766   const char *tooltip;
767
768   (void)ctrl;
769
770   /* TRANSLATORS: This string is displayed by Pinentry as the label
771      for the quality bar.  */
772   tmpstr = try_percent_escape (L_("Quality:"), "\t\r\n\f\v");
773   snprintf (line, DIM(line), "SETQUALITYBAR %s", tmpstr? tmpstr:"");
774   xfree (tmpstr);
775   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
776   if (rc == 103 /*(Old assuan error code)*/
777       || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
778     ; /* Ignore Unknown Command from old Pinentry versions.  */
779   else if (rc)
780     return rc;
781
782   tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
783   if (tmpstr2)
784     tooltip = tmpstr2;
785   else
786     {
787       /* TRANSLATORS: This string is a tooltip, shown by pinentry when
788          hovering over the quality bar.  Please use an appropriate
789          string to describe what this is about.  The length of the
790          tooltip is limited to about 900 characters.  If you do not
791          translate this entry, a default english text (see source)
792          will be used. */
793       tooltip =  L_("pinentry.qualitybar.tooltip");
794       if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
795         tooltip = ("The quality of the text entered above.\n"
796                    "Please ask your administrator for "
797                    "details about the criteria.");
798     }
799   tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
800   xfree (tmpstr2);
801   snprintf (line, DIM(line), "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
802   xfree (tmpstr);
803   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
804   if (rc == 103 /*(Old assuan error code)*/
805           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
806     ; /* Ignore Unknown Command from old pinentry versions.  */
807   else if (rc)
808     return rc;
809
810   return 0;
811 }
812
813 enum
814   {
815     PINENTRY_STATUS_CLOSE_BUTTON = 1 << 0,
816     PINENTRY_STATUS_PIN_REPEATED = 1 << 8,
817     PINENTRY_STATUS_PASSWORD_FROM_CACHE = 1 << 9
818   };
819
820 /* Check the button_info line for a close action.  Also check for the
821    PIN_REPEATED flag.  */
822 static gpg_error_t
823 pinentry_status_cb (void *opaque, const char *line)
824 {
825   unsigned int *flag = opaque;
826   const char *args;
827
828   if ((args = has_leading_keyword (line, "BUTTON_INFO")))
829     {
830       if (!strcmp (args, "close"))
831         *flag |= PINENTRY_STATUS_CLOSE_BUTTON;
832     }
833   else if (has_leading_keyword (line, "PIN_REPEATED"))
834     {
835       *flag |= PINENTRY_STATUS_PIN_REPEATED;
836     }
837   else if (has_leading_keyword (line, "PASSWORD_FROM_CACHE"))
838     {
839       *flag |= PINENTRY_STATUS_PASSWORD_FROM_CACHE;
840     }
841
842   return 0;
843 }
844
845
846
847 \f
848 /* Call the Entry and ask for the PIN.  We do check for a valid PIN
849    number here and repeat it as long as we have invalid formed
850    numbers.  KEYINFO and CACHE_MODE are used to tell pinentry something
851    about the key. */
852 gpg_error_t
853 agent_askpin (ctrl_t ctrl,
854               const char *desc_text, const char *prompt_text,
855               const char *initial_errtext,
856               struct pin_entry_info_s *pininfo,
857               const char *keyinfo, cache_mode_t cache_mode)
858 {
859   gpg_error_t rc;
860   char line[ASSUAN_LINELENGTH];
861   struct entry_parm_s parm;
862   const char *errtext = NULL;
863   int is_pin = 0;
864   int saveflag;
865   unsigned int pinentry_status;
866
867   if (opt.batch)
868     return 0; /* fixme: we should return BAD PIN */
869
870   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
871     {
872       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
873         return gpg_error (GPG_ERR_CANCELED);
874       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
875         {
876           unsigned char *passphrase;
877           size_t size;
878
879           *pininfo->pin = 0; /* Reset the PIN. */
880           rc = pinentry_loopback(ctrl, "PASSPHRASE", &passphrase, &size,
881                   pininfo->max_length - 1);
882           if (rc)
883             return rc;
884
885           memcpy(&pininfo->pin, passphrase, size);
886           xfree(passphrase);
887           pininfo->pin[size] = 0;
888           if (pininfo->check_cb)
889             {
890               /* More checks by utilizing the optional callback. */
891               pininfo->cb_errtext = NULL;
892               rc = pininfo->check_cb (pininfo);
893             }
894           return rc;
895         }
896       return gpg_error(GPG_ERR_NO_PIN_ENTRY);
897     }
898
899   if (!pininfo || pininfo->max_length < 1)
900     return gpg_error (GPG_ERR_INV_VALUE);
901   if (!desc_text && pininfo->min_digits)
902     desc_text = L_("Please enter your PIN, so that the secret key "
903                    "can be unlocked for this session");
904   else if (!desc_text)
905     desc_text = L_("Please enter your passphrase, so that the secret key "
906                    "can be unlocked for this session");
907
908   if (prompt_text)
909     is_pin = !!strstr (prompt_text, "PIN");
910   else
911     is_pin = desc_text && strstr (desc_text, "PIN");
912
913   rc = start_pinentry (ctrl);
914   if (rc)
915     return rc;
916
917   /* If we have a KEYINFO string and are normal, user, or ssh cache
918      mode, we tell that the Pinentry so it may use it for own caching
919      purposes.  Most pinentries won't have this implemented and thus
920      we do not error out in this case.  */
921   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
922                   || cache_mode == CACHE_MODE_USER
923                   || cache_mode == CACHE_MODE_SSH))
924     snprintf (line, DIM(line), "SETKEYINFO %c/%s",
925               cache_mode == CACHE_MODE_USER? 'u' :
926               cache_mode == CACHE_MODE_SSH? 's' : 'n',
927               keyinfo);
928   else
929     snprintf (line, DIM(line), "SETKEYINFO --clear");
930
931   rc = assuan_transact (entry_ctx, line,
932                         NULL, NULL, NULL, NULL, NULL, NULL);
933   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
934     return unlock_pinentry (rc);
935
936   snprintf (line, DIM(line), "SETDESC %s", desc_text);
937   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
938   if (rc)
939     return unlock_pinentry (rc);
940
941   snprintf (line, DIM(line), "SETPROMPT %s",
942             prompt_text? prompt_text : is_pin? L_("PIN:") : L_("Passphrase:"));
943   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
944   if (rc)
945     return unlock_pinentry (rc);
946
947   /* If a passphrase quality indicator has been requested and a
948      minimum passphrase length has not been disabled, send the command
949      to the pinentry.  */
950   if (pininfo->with_qualitybar && opt.min_passphrase_len )
951     {
952       rc = setup_qualitybar (ctrl);
953       if (rc)
954         return unlock_pinentry (rc);
955     }
956
957   if (initial_errtext)
958     {
959       snprintf (line, DIM(line), "SETERROR %s", initial_errtext);
960       rc = assuan_transact (entry_ctx, line,
961                             NULL, NULL, NULL, NULL, NULL, NULL);
962       if (rc)
963         return unlock_pinentry (rc);
964     }
965
966   if (pininfo->with_repeat)
967     {
968       snprintf (line, DIM(line), "SETREPEATERROR %s",
969                 L_("does not match - try again"));
970       rc = assuan_transact (entry_ctx, line,
971                             NULL, NULL, NULL, NULL, NULL, NULL);
972       if (rc)
973         pininfo->with_repeat = 0; /* Pinentry does not support it.  */
974     }
975   pininfo->repeat_okay = 0;
976
977   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
978     {
979       memset (&parm, 0, sizeof parm);
980       parm.size = pininfo->max_length;
981       *pininfo->pin = 0; /* Reset the PIN. */
982       parm.buffer = (unsigned char*)pininfo->pin;
983
984       if (errtext)
985         {
986           /* TRANSLATORS: The string is appended to an error message in
987              the pinentry.  The %s is the actual error message, the
988              two %d give the current and maximum number of tries. */
989           snprintf (line, DIM(line), L_("SETERROR %s (try %d of %d)"),
990                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
991           rc = assuan_transact (entry_ctx, line,
992                                 NULL, NULL, NULL, NULL, NULL, NULL);
993           if (rc)
994             return unlock_pinentry (rc);
995           errtext = NULL;
996         }
997
998       if (pininfo->with_repeat)
999         {
1000           snprintf (line, DIM(line), "SETREPEAT %s", L_("Repeat:"));
1001           rc = assuan_transact (entry_ctx, line,
1002                                 NULL, NULL, NULL, NULL, NULL, NULL);
1003           if (rc)
1004             return unlock_pinentry (rc);
1005         }
1006
1007       saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
1008       assuan_begin_confidential (entry_ctx);
1009       pinentry_status = 0;
1010       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
1011                             inq_quality, entry_ctx,
1012                             pinentry_status_cb, &pinentry_status);
1013       assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
1014       /* Most pinentries out in the wild return the old Assuan error code
1015          for canceled which gets translated to an assuan Cancel error and
1016          not to the code for a user cancel.  Fix this here. */
1017       if (rc && gpg_err_source (rc)
1018           && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1019         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1020
1021
1022       /* Change error code in case the window close button was clicked
1023          to cancel the operation.  */
1024       if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
1025           && gpg_err_code (rc) == GPG_ERR_CANCELED)
1026         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
1027
1028       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
1029         errtext = is_pin? L_("PIN too long")
1030                         : L_("Passphrase too long");
1031       else if (rc)
1032         return unlock_pinentry (rc);
1033
1034       if (!errtext && pininfo->min_digits)
1035         {
1036           /* do some basic checks on the entered PIN. */
1037           if (!all_digitsp (pininfo->pin))
1038             errtext = L_("Invalid characters in PIN");
1039           else if (pininfo->max_digits
1040                    && strlen (pininfo->pin) > pininfo->max_digits)
1041             errtext = L_("PIN too long");
1042           else if (strlen (pininfo->pin) < pininfo->min_digits)
1043             errtext = L_("PIN too short");
1044         }
1045
1046       if (!errtext && pininfo->check_cb)
1047         {
1048           /* More checks by utilizing the optional callback. */
1049           pininfo->cb_errtext = NULL;
1050           rc = pininfo->check_cb (pininfo);
1051           if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1052               && pininfo->cb_errtext)
1053             errtext = pininfo->cb_errtext;
1054           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1055                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
1056             errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase"));
1057           else if (rc)
1058             return unlock_pinentry (rc);
1059         }
1060
1061       if (!errtext)
1062         {
1063           if (pininfo->with_repeat
1064               && (pinentry_status & PINENTRY_STATUS_PIN_REPEATED))
1065             pininfo->repeat_okay = 1;
1066           return unlock_pinentry (0); /* okay, got a PIN or passphrase */
1067         }
1068
1069       if ((pinentry_status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
1070         /* The password was read from the cache.  Don't count this
1071            against the retry count.  */
1072         pininfo->failed_tries --;
1073     }
1074
1075   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
1076                           : GPG_ERR_BAD_PASSPHRASE));
1077 }
1078
1079
1080 \f
1081 /* Ask for the passphrase using the supplied arguments.  The returned
1082    passphrase needs to be freed by the caller. */
1083 int
1084 agent_get_passphrase (ctrl_t ctrl,
1085                       char **retpass, const char *desc, const char *prompt,
1086                       const char *errtext, int with_qualitybar,
1087                       const char *keyinfo, cache_mode_t cache_mode)
1088 {
1089
1090   int rc;
1091   char line[ASSUAN_LINELENGTH];
1092   struct entry_parm_s parm;
1093   int saveflag;
1094   unsigned int pinentry_status;
1095
1096   *retpass = NULL;
1097   if (opt.batch)
1098     return gpg_error (GPG_ERR_BAD_PASSPHRASE);
1099
1100   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1101     {
1102       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1103         return gpg_error (GPG_ERR_CANCELED);
1104
1105       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
1106         {
1107           size_t size;
1108           size_t len = ASSUAN_LINELENGTH/2;
1109
1110           return pinentry_loopback (ctrl, "PASSPHRASE",
1111                                     (unsigned char **)retpass, &size, len);
1112         }
1113       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1114     }
1115
1116   rc = start_pinentry (ctrl);
1117   if (rc)
1118     return rc;
1119
1120   if (!prompt)
1121     prompt = desc && strstr (desc, "PIN")? L_("PIN:"): L_("Passphrase:");
1122
1123
1124   /* If we have a KEYINFO string and are normal, user, or ssh cache
1125      mode, we tell that the Pinentry so it may use it for own caching
1126      purposes.  Most pinentries won't have this implemented and thus
1127      we do not error out in this case.  */
1128   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1129                   || cache_mode == CACHE_MODE_USER
1130                   || cache_mode == CACHE_MODE_SSH))
1131     snprintf (line, DIM(line), "SETKEYINFO %c/%s",
1132               cache_mode == CACHE_MODE_USER? 'u' :
1133               cache_mode == CACHE_MODE_SSH? 's' : 'n',
1134               keyinfo);
1135   else
1136     snprintf (line, DIM(line), "SETKEYINFO --clear");
1137
1138   rc = assuan_transact (entry_ctx, line,
1139                         NULL, NULL, NULL, NULL, NULL, NULL);
1140   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
1141     return unlock_pinentry (rc);
1142
1143
1144   if (desc)
1145     snprintf (line, DIM(line), "SETDESC %s", desc);
1146   else
1147     snprintf (line, DIM(line), "RESET");
1148   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1149   if (rc)
1150     return unlock_pinentry (rc);
1151
1152   snprintf (line, DIM(line), "SETPROMPT %s", prompt);
1153   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1154   if (rc)
1155     return unlock_pinentry (rc);
1156
1157   if (with_qualitybar && opt.min_passphrase_len)
1158     {
1159       rc = setup_qualitybar (ctrl);
1160       if (rc)
1161         return unlock_pinentry (rc);
1162     }
1163
1164   if (errtext)
1165     {
1166       snprintf (line, DIM(line), "SETERROR %s", errtext);
1167       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1168       if (rc)
1169         return unlock_pinentry (rc);
1170     }
1171
1172   memset (&parm, 0, sizeof parm);
1173   parm.size = ASSUAN_LINELENGTH/2 - 5;
1174   parm.buffer = gcry_malloc_secure (parm.size+10);
1175   if (!parm.buffer)
1176     return unlock_pinentry (out_of_core ());
1177
1178   saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
1179   assuan_begin_confidential (entry_ctx);
1180   pinentry_status = 0;
1181   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
1182                         inq_quality, entry_ctx,
1183                         pinentry_status_cb, &pinentry_status);
1184   assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
1185   /* Most pinentries out in the wild return the old Assuan error code
1186      for canceled which gets translated to an assuan Cancel error and
1187      not to the code for a user cancel.  Fix this here. */
1188   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1189     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1190   /* Change error code in case the window close button was clicked
1191      to cancel the operation.  */
1192   if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
1193       && gpg_err_code (rc) == GPG_ERR_CANCELED)
1194     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
1195
1196   if (rc)
1197     xfree (parm.buffer);
1198   else
1199     *retpass = parm.buffer;
1200   return unlock_pinentry (rc);
1201 }
1202
1203
1204 \f
1205 /* Pop up the PIN-entry, display the text and the prompt and ask the
1206    user to confirm this.  We return 0 for success, ie. the user
1207    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
1208    other error.  If WITH_CANCEL it true an extra cancel button is
1209    displayed to allow the user to easily return a GPG_ERR_CANCELED.
1210    if the Pinentry does not support this, the user can still cancel by
1211    closing the Pinentry window.  */
1212 int
1213 agent_get_confirmation (ctrl_t ctrl,
1214                         const char *desc, const char *ok,
1215                         const char *notok, int with_cancel)
1216 {
1217   int rc;
1218   char line[ASSUAN_LINELENGTH];
1219
1220   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1221     {
1222       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1223         return gpg_error (GPG_ERR_CANCELED);
1224
1225       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1226     }
1227
1228   rc = start_pinentry (ctrl);
1229   if (rc)
1230     return rc;
1231
1232   if (desc)
1233     snprintf (line, DIM(line), "SETDESC %s", desc);
1234   else
1235     snprintf (line, DIM(line), "RESET");
1236   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1237   /* Most pinentries out in the wild return the old Assuan error code
1238      for canceled which gets translated to an assuan Cancel error and
1239      not to the code for a user cancel.  Fix this here. */
1240   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1241     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1242
1243   if (rc)
1244     return unlock_pinentry (rc);
1245
1246   if (ok)
1247     {
1248       snprintf (line, DIM(line), "SETOK %s", ok);
1249       rc = assuan_transact (entry_ctx,
1250                             line, NULL, NULL, NULL, NULL, NULL, NULL);
1251       if (rc)
1252         return unlock_pinentry (rc);
1253     }
1254   if (notok)
1255     {
1256       /* Try to use the newer NOTOK feature if a cancel button is
1257          requested.  If no cancel button is requested we keep on using
1258          the standard cancel.  */
1259       if (with_cancel)
1260         {
1261           snprintf (line, DIM(line), "SETNOTOK %s", notok);
1262           rc = assuan_transact (entry_ctx,
1263                                 line, NULL, NULL, NULL, NULL, NULL, NULL);
1264         }
1265       else
1266         rc = GPG_ERR_ASS_UNKNOWN_CMD;
1267
1268       if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
1269         {
1270           snprintf (line, DIM(line), "SETCANCEL %s", notok);
1271           rc = assuan_transact (entry_ctx, line,
1272                                 NULL, NULL, NULL, NULL, NULL, NULL);
1273         }
1274       if (rc)
1275         return unlock_pinentry (rc);
1276     }
1277
1278   rc = assuan_transact (entry_ctx, "CONFIRM",
1279                         NULL, NULL, NULL, NULL, NULL, NULL);
1280   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1281     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1282
1283   return unlock_pinentry (rc);
1284 }
1285
1286
1287 \f
1288 /* Pop up the PINentry, display the text DESC and a button with the
1289    text OK_BTN (which may be NULL to use the default of "OK") and wait
1290    for the user to hit this button.  The return value is not
1291    relevant.  */
1292 int
1293 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
1294 {
1295   int rc;
1296   char line[ASSUAN_LINELENGTH];
1297
1298   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1299     return gpg_error (GPG_ERR_CANCELED);
1300
1301   rc = start_pinentry (ctrl);
1302   if (rc)
1303     return rc;
1304
1305   if (desc)
1306     snprintf (line, DIM(line), "SETDESC %s", desc);
1307   else
1308     snprintf (line, DIM(line), "RESET");
1309   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1310   /* Most pinentries out in the wild return the old Assuan error code
1311      for canceled which gets translated to an assuan Cancel error and
1312      not to the code for a user cancel.  Fix this here. */
1313   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1314     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1315
1316   if (rc)
1317     return unlock_pinentry (rc);
1318
1319   if (ok_btn)
1320     {
1321       snprintf (line, DIM(line), "SETOK %s", ok_btn);
1322       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
1323                             NULL, NULL, NULL);
1324       if (rc)
1325         return unlock_pinentry (rc);
1326     }
1327
1328   rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
1329                         NULL, NULL, NULL);
1330   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1331     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1332
1333   return unlock_pinentry (rc);
1334 }
1335
1336
1337 /* The thread running the popup message. */
1338 static void *
1339 popup_message_thread (void *arg)
1340 {
1341   (void)arg;
1342
1343   /* We use the --one-button hack instead of the MESSAGE command to
1344      allow the use of old Pinentries.  Those old Pinentries will then
1345      show an additional Cancel button but that is mostly a visual
1346      annoyance. */
1347   assuan_transact (entry_ctx, "CONFIRM --one-button",
1348                    NULL, NULL, NULL, NULL, NULL, NULL);
1349   popup_finished = 1;
1350   return NULL;
1351 }
1352
1353
1354 /* Pop up a message window similar to the confirm one but keep it open
1355    until agent_popup_message_stop has been called.  It is crucial for
1356    the caller to make sure that the stop function gets called as soon
1357    as the message is not anymore required because the message is
1358    system modal and all other attempts to use the pinentry will fail
1359    (after a timeout). */
1360 int
1361 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
1362 {
1363   int rc;
1364   char line[ASSUAN_LINELENGTH];
1365   npth_attr_t tattr;
1366   int err;
1367
1368   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1369     return gpg_error (GPG_ERR_CANCELED);
1370
1371   rc = start_pinentry (ctrl);
1372   if (rc)
1373     return rc;
1374
1375   if (desc)
1376     snprintf (line, DIM(line), "SETDESC %s", desc);
1377   else
1378     snprintf (line, DIM(line), "RESET");
1379   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1380   if (rc)
1381     return unlock_pinentry (rc);
1382
1383   if (ok_btn)
1384     {
1385       snprintf (line, DIM(line), "SETOK %s", ok_btn);
1386       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1387       if (rc)
1388         return unlock_pinentry (rc);
1389     }
1390
1391   err = npth_attr_init (&tattr);
1392   if (err)
1393     return unlock_pinentry (gpg_error_from_errno (err));
1394   npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
1395
1396   popup_finished = 0;
1397   err = npth_create (&popup_tid, &tattr, popup_message_thread, NULL);
1398   npth_attr_destroy (&tattr);
1399   if (err)
1400     {
1401       rc = gpg_error_from_errno (err);
1402       log_error ("error spawning popup message handler: %s\n",
1403                  strerror (err) );
1404       return unlock_pinentry (rc);
1405     }
1406   npth_setname_np (popup_tid, "popup-message");
1407
1408   return 0;
1409 }
1410
1411 /* Close a popup window. */
1412 void
1413 agent_popup_message_stop (ctrl_t ctrl)
1414 {
1415   int rc;
1416   pid_t pid;
1417
1418   (void)ctrl;
1419
1420   if (!popup_tid || !entry_ctx)
1421     {
1422       log_debug ("agent_popup_message_stop called with no active popup\n");
1423       return;
1424     }
1425
1426   pid = assuan_get_pid (entry_ctx);
1427   if (pid == (pid_t)(-1))
1428     ; /* No pid available can't send a kill. */
1429   else if (popup_finished)
1430     ; /* Already finished and ready for joining. */
1431 #ifdef HAVE_W32_SYSTEM
1432   /* Older versions of assuan set PID to 0 on Windows to indicate an
1433      invalid value.  */
1434   else if (pid != (pid_t) INVALID_HANDLE_VALUE
1435            && pid != 0)
1436     {
1437       HANDLE process = (HANDLE) pid;
1438
1439       /* Arbitrary error code.  */
1440       TerminateProcess (process, 1);
1441     }
1442 #else
1443   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1444     { /* The daemon already died.  No need to send a kill.  However
1445          because we already waited for the process, we need to tell
1446          assuan that it should not wait again (done by
1447          unlock_pinentry). */
1448       if (rc == pid)
1449         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1450     }
1451   else if (pid > 0)
1452     kill (pid, SIGINT);
1453 #endif
1454
1455   /* Now wait for the thread to terminate. */
1456   rc = npth_join (popup_tid, NULL);
1457   if (rc)
1458     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1459                strerror (rc));
1460   /* Thread IDs are opaque, but we try our best here by resetting it
1461      to the same content that a static global variable has.  */
1462   memset (&popup_tid, '\0', sizeof (popup_tid));
1463   entry_owner = NULL;
1464
1465   /* Now we can close the connection. */
1466   unlock_pinentry (0);
1467 }
1468
1469 int
1470 agent_clear_passphrase (ctrl_t ctrl,
1471                         const char *keyinfo, cache_mode_t cache_mode)
1472 {
1473   int rc;
1474   char line[ASSUAN_LINELENGTH];
1475
1476   if (! (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1477                      || cache_mode == CACHE_MODE_USER
1478                      || cache_mode == CACHE_MODE_SSH)))
1479     return gpg_error (GPG_ERR_NOT_SUPPORTED);
1480
1481   rc = start_pinentry (ctrl);
1482   if (rc)
1483     return rc;
1484
1485   snprintf (line, DIM(line), "CLEARPASSPHRASE %c/%s",
1486             cache_mode == CACHE_MODE_USER? 'u' :
1487             cache_mode == CACHE_MODE_SSH? 's' : 'n',
1488             keyinfo);
1489   rc = assuan_transact (entry_ctx, line,
1490                         NULL, NULL, NULL, NULL, NULL, NULL);
1491
1492   return unlock_pinentry (rc);
1493 }