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