gpg: More diagnostics for a launched pinentry.
[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 #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 store 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_str (&mb, " ");
559     if (assuan_transact (entry_ctx, "GETINFO ttyinfo",
560                          put_membuf_cb, &mb, NULL, NULL, NULL, NULL))
561       put_membuf_str (&mb, "? ? ?");
562     put_membuf (&mb, "", 1);
563     flavor_version = get_membuf (&mb, NULL);
564   }
565
566
567   /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
568      it will send the pid back and we will use an inquire to notify
569      our client.  The client may answer the inquiry either with END or
570      with CAN to cancel the pinentry. */
571   rc = assuan_transact (entry_ctx, "GETINFO pid",
572                         getinfo_pid_cb, &pinentry_pid,
573                         NULL, NULL, NULL, NULL);
574   if (rc)
575     {
576       log_info ("You may want to update to a newer pinentry\n");
577       rc = 0;
578     }
579   else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
580     log_error ("pinentry did not return a PID\n");
581   else
582     {
583       rc = agent_inq_pinentry_launched (ctrl, pinentry_pid, flavor_version);
584       if (gpg_err_code (rc) == GPG_ERR_CANCELED
585           || gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
586         return unlock_pinentry (gpg_err_make (GPG_ERR_SOURCE_DEFAULT,
587                                               gpg_err_code (rc)));
588       rc = 0;
589     }
590
591   xfree (flavor_version);
592
593   return 0;
594 }
595
596
597 /* Returns True if the pinentry is currently active. If WAITSECONDS is
598    greater than zero the function will wait for this many seconds
599    before returning.  */
600 int
601 pinentry_active_p (ctrl_t ctrl, int waitseconds)
602 {
603   int err;
604   (void)ctrl;
605
606   if (waitseconds > 0)
607     {
608       struct timespec abstime;
609       int rc;
610
611       npth_clock_gettime (&abstime);
612       abstime.tv_sec += waitseconds;
613       err = npth_mutex_timedlock (&entry_lock, &abstime);
614       if (err)
615         {
616           if (err == ETIMEDOUT)
617             rc = gpg_error (GPG_ERR_TIMEOUT);
618           else
619             rc = gpg_error (GPG_ERR_INTERNAL);
620           return rc;
621         }
622     }
623   else
624     {
625       err = npth_mutex_trylock (&entry_lock);
626       if (err)
627         return gpg_error (GPG_ERR_LOCKED);
628     }
629
630   err = npth_mutex_unlock (&entry_lock);
631   if (err)
632     log_error ("failed to release the entry lock at %d: %s\n", __LINE__,
633                strerror (errno));
634   return 0;
635 }
636
637
638 static gpg_error_t
639 getpin_cb (void *opaque, const void *buffer, size_t length)
640 {
641   struct entry_parm_s *parm = opaque;
642
643   if (!buffer)
644     return 0;
645
646   /* we expect the pin to fit on one line */
647   if (parm->lines || length >= parm->size)
648     return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
649
650   /* fixme: we should make sure that the assuan buffer is allocated in
651      secure memory or read the response byte by byte */
652   memcpy (parm->buffer, buffer, length);
653   parm->buffer[length] = 0;
654   parm->lines++;
655   return 0;
656 }
657
658
659 static int
660 all_digitsp( const char *s)
661 {
662   for (; *s && *s >= '0' && *s <= '9'; s++)
663     ;
664   return !*s;
665 }
666
667
668 /* Return a new malloced string by unescaping the string S.  Escaping
669    is percent escaping and '+'/space mapping.  A binary Nul will
670    silently be replaced by a 0xFF.  Function returns NULL to indicate
671    an out of memory status.  Parsing stops at the end of the string or
672    a white space character. */
673 static char *
674 unescape_passphrase_string (const unsigned char *s)
675 {
676   char *buffer, *d;
677
678   buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
679   if (!buffer)
680     return NULL;
681   while (*s && !spacep (s))
682     {
683       if (*s == '%' && s[1] && s[2])
684         {
685           s++;
686           *d = xtoi_2 (s);
687           if (!*d)
688             *d = '\xff';
689           d++;
690           s += 2;
691         }
692       else if (*s == '+')
693         {
694           *d++ = ' ';
695           s++;
696         }
697       else
698         *d++ = *s++;
699     }
700   *d = 0;
701   return buffer;
702 }
703
704
705 /* Estimate the quality of the passphrase PW and return a value in the
706    range 0..100.  */
707 static int
708 estimate_passphrase_quality (const char *pw)
709 {
710   int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
711   int length;
712   const char *s;
713
714   if (goodlength < 1)
715     return 0;
716
717   for (length = 0, s = pw; *s; s++)
718     if (!spacep (s))
719       length ++;
720
721   if (length > goodlength)
722     return 100;
723   return ((length*10) / goodlength)*10;
724 }
725
726
727 /* Handle the QUALITY inquiry. */
728 static gpg_error_t
729 inq_quality (void *opaque, const char *line)
730 {
731   assuan_context_t ctx = opaque;
732   const char *s;
733   char *pin;
734   int rc;
735   int percent;
736   char numbuf[20];
737
738   if ((s = has_leading_keyword (line, "QUALITY")))
739     {
740       pin = unescape_passphrase_string (s);
741       if (!pin)
742         rc = gpg_error_from_syserror ();
743       else
744         {
745           percent = estimate_passphrase_quality (pin);
746           if (check_passphrase_constraints (NULL, pin, NULL))
747             percent = -percent;
748           snprintf (numbuf, sizeof numbuf, "%d", percent);
749           rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
750           xfree (pin);
751         }
752     }
753   else
754     {
755       log_error ("unsupported inquiry '%s' from pinentry\n", line);
756       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
757     }
758
759   return rc;
760 }
761
762
763 /* Helper for agent_askpin and agent_get_passphrase.  */
764 static gpg_error_t
765 setup_qualitybar (ctrl_t ctrl)
766 {
767   int rc;
768   char line[ASSUAN_LINELENGTH];
769   char *tmpstr, *tmpstr2;
770   const char *tooltip;
771
772   (void)ctrl;
773
774   /* TRANSLATORS: This string is displayed by Pinentry as the label
775      for the quality bar.  */
776   tmpstr = try_percent_escape (L_("Quality:"), "\t\r\n\f\v");
777   snprintf (line, DIM(line), "SETQUALITYBAR %s", tmpstr? tmpstr:"");
778   xfree (tmpstr);
779   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
780   if (rc == 103 /*(Old assuan error code)*/
781       || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
782     ; /* Ignore Unknown Command from old Pinentry versions.  */
783   else if (rc)
784     return rc;
785
786   tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
787   if (tmpstr2)
788     tooltip = tmpstr2;
789   else
790     {
791       /* TRANSLATORS: This string is a tooltip, shown by pinentry when
792          hovering over the quality bar.  Please use an appropriate
793          string to describe what this is about.  The length of the
794          tooltip is limited to about 900 characters.  If you do not
795          translate this entry, a default english text (see source)
796          will be used. */
797       tooltip =  L_("pinentry.qualitybar.tooltip");
798       if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
799         tooltip = ("The quality of the text entered above.\n"
800                    "Please ask your administrator for "
801                    "details about the criteria.");
802     }
803   tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
804   xfree (tmpstr2);
805   snprintf (line, DIM(line), "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
806   xfree (tmpstr);
807   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
808   if (rc == 103 /*(Old assuan error code)*/
809           || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
810     ; /* Ignore Unknown Command from old pinentry versions.  */
811   else if (rc)
812     return rc;
813
814   return 0;
815 }
816
817 enum
818   {
819     PINENTRY_STATUS_CLOSE_BUTTON = 1 << 0,
820     PINENTRY_STATUS_PIN_REPEATED = 1 << 8,
821     PINENTRY_STATUS_PASSWORD_FROM_CACHE = 1 << 9
822   };
823
824 /* Check the button_info line for a close action.  Also check for the
825    PIN_REPEATED flag.  */
826 static gpg_error_t
827 pinentry_status_cb (void *opaque, const char *line)
828 {
829   unsigned int *flag = opaque;
830   const char *args;
831
832   if ((args = has_leading_keyword (line, "BUTTON_INFO")))
833     {
834       if (!strcmp (args, "close"))
835         *flag |= PINENTRY_STATUS_CLOSE_BUTTON;
836     }
837   else if (has_leading_keyword (line, "PIN_REPEATED"))
838     {
839       *flag |= PINENTRY_STATUS_PIN_REPEATED;
840     }
841   else if (has_leading_keyword (line, "PASSWORD_FROM_CACHE"))
842     {
843       *flag |= PINENTRY_STATUS_PASSWORD_FROM_CACHE;
844     }
845
846   return 0;
847 }
848
849
850
851 \f
852 /* Call the Entry and ask for the PIN.  We do check for a valid PIN
853    number here and repeat it as long as we have invalid formed
854    numbers.  KEYINFO and CACHE_MODE are used to tell pinentry something
855    about the key. */
856 gpg_error_t
857 agent_askpin (ctrl_t ctrl,
858               const char *desc_text, const char *prompt_text,
859               const char *initial_errtext,
860               struct pin_entry_info_s *pininfo,
861               const char *keyinfo, cache_mode_t cache_mode)
862 {
863   gpg_error_t rc;
864   char line[ASSUAN_LINELENGTH];
865   struct entry_parm_s parm;
866   const char *errtext = NULL;
867   int is_pin = 0;
868   int saveflag;
869   unsigned int pinentry_status;
870
871   if (opt.batch)
872     return 0; /* fixme: we should return BAD PIN */
873
874   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
875     {
876       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
877         return gpg_error (GPG_ERR_CANCELED);
878       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
879         {
880           unsigned char *passphrase;
881           size_t size;
882
883           *pininfo->pin = 0; /* Reset the PIN. */
884           rc = pinentry_loopback(ctrl, "PASSPHRASE", &passphrase, &size,
885                   pininfo->max_length - 1);
886           if (rc)
887             return rc;
888
889           memcpy(&pininfo->pin, passphrase, size);
890           xfree(passphrase);
891           pininfo->pin[size] = 0;
892           if (pininfo->check_cb)
893             {
894               /* More checks by utilizing the optional callback. */
895               pininfo->cb_errtext = NULL;
896               rc = pininfo->check_cb (pininfo);
897             }
898           return rc;
899         }
900       return gpg_error(GPG_ERR_NO_PIN_ENTRY);
901     }
902
903   if (!pininfo || pininfo->max_length < 1)
904     return gpg_error (GPG_ERR_INV_VALUE);
905   if (!desc_text && pininfo->min_digits)
906     desc_text = L_("Please enter your PIN, so that the secret key "
907                    "can be unlocked for this session");
908   else if (!desc_text)
909     desc_text = L_("Please enter your passphrase, so that the secret key "
910                    "can be unlocked for this session");
911
912   if (prompt_text)
913     is_pin = !!strstr (prompt_text, "PIN");
914   else
915     is_pin = desc_text && strstr (desc_text, "PIN");
916
917   rc = start_pinentry (ctrl);
918   if (rc)
919     return rc;
920
921   /* If we have a KEYINFO string and are normal, user, or ssh cache
922      mode, we tell that the Pinentry so it may use it for own caching
923      purposes.  Most pinentries won't have this implemented and thus
924      we do not error out in this case.  */
925   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
926                   || cache_mode == CACHE_MODE_USER
927                   || cache_mode == CACHE_MODE_SSH))
928     snprintf (line, DIM(line), "SETKEYINFO %c/%s",
929               cache_mode == CACHE_MODE_USER? 'u' :
930               cache_mode == CACHE_MODE_SSH? 's' : 'n',
931               keyinfo);
932   else
933     snprintf (line, DIM(line), "SETKEYINFO --clear");
934
935   rc = assuan_transact (entry_ctx, line,
936                         NULL, NULL, NULL, NULL, NULL, NULL);
937   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
938     return unlock_pinentry (rc);
939
940   snprintf (line, DIM(line), "SETDESC %s", desc_text);
941   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
942   if (rc)
943     return unlock_pinentry (rc);
944
945   snprintf (line, DIM(line), "SETPROMPT %s",
946             prompt_text? prompt_text : is_pin? L_("PIN:") : L_("Passphrase:"));
947   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
948   if (rc)
949     return unlock_pinentry (rc);
950
951   /* If a passphrase quality indicator has been requested and a
952      minimum passphrase length has not been disabled, send the command
953      to the pinentry.  */
954   if (pininfo->with_qualitybar && opt.min_passphrase_len )
955     {
956       rc = setup_qualitybar (ctrl);
957       if (rc)
958         return unlock_pinentry (rc);
959     }
960
961   if (initial_errtext)
962     {
963       snprintf (line, DIM(line), "SETERROR %s", initial_errtext);
964       rc = assuan_transact (entry_ctx, line,
965                             NULL, NULL, NULL, NULL, NULL, NULL);
966       if (rc)
967         return unlock_pinentry (rc);
968     }
969
970   if (pininfo->with_repeat)
971     {
972       snprintf (line, DIM(line), "SETREPEATERROR %s",
973                 L_("does not match - try again"));
974       rc = assuan_transact (entry_ctx, line,
975                             NULL, NULL, NULL, NULL, NULL, NULL);
976       if (rc)
977         pininfo->with_repeat = 0; /* Pinentry does not support it.  */
978     }
979   pininfo->repeat_okay = 0;
980
981   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
982     {
983       memset (&parm, 0, sizeof parm);
984       parm.size = pininfo->max_length;
985       *pininfo->pin = 0; /* Reset the PIN. */
986       parm.buffer = (unsigned char*)pininfo->pin;
987
988       if (errtext)
989         {
990           /* TRANSLATORS: The string is appended to an error message in
991              the pinentry.  The %s is the actual error message, the
992              two %d give the current and maximum number of tries. */
993           snprintf (line, DIM(line), L_("SETERROR %s (try %d of %d)"),
994                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
995           rc = assuan_transact (entry_ctx, line,
996                                 NULL, NULL, NULL, NULL, NULL, NULL);
997           if (rc)
998             return unlock_pinentry (rc);
999           errtext = NULL;
1000         }
1001
1002       if (pininfo->with_repeat)
1003         {
1004           snprintf (line, DIM(line), "SETREPEAT %s", L_("Repeat:"));
1005           rc = assuan_transact (entry_ctx, line,
1006                                 NULL, NULL, NULL, NULL, NULL, NULL);
1007           if (rc)
1008             return unlock_pinentry (rc);
1009         }
1010
1011       saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
1012       assuan_begin_confidential (entry_ctx);
1013       pinentry_status = 0;
1014       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
1015                             inq_quality, entry_ctx,
1016                             pinentry_status_cb, &pinentry_status);
1017       assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
1018       /* Most pinentries out in the wild return the old Assuan error code
1019          for canceled which gets translated to an assuan Cancel error and
1020          not to the code for a user cancel.  Fix this here. */
1021       if (rc && gpg_err_source (rc)
1022           && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1023         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1024
1025
1026       /* Change error code in case the window close button was clicked
1027          to cancel the operation.  */
1028       if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
1029           && gpg_err_code (rc) == GPG_ERR_CANCELED)
1030         rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
1031
1032       if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
1033         errtext = is_pin? L_("PIN too long")
1034                         : L_("Passphrase too long");
1035       else if (rc)
1036         return unlock_pinentry (rc);
1037
1038       if (!errtext && pininfo->min_digits)
1039         {
1040           /* do some basic checks on the entered PIN. */
1041           if (!all_digitsp (pininfo->pin))
1042             errtext = L_("Invalid characters in PIN");
1043           else if (pininfo->max_digits
1044                    && strlen (pininfo->pin) > pininfo->max_digits)
1045             errtext = L_("PIN too long");
1046           else if (strlen (pininfo->pin) < pininfo->min_digits)
1047             errtext = L_("PIN too short");
1048         }
1049
1050       if (!errtext && pininfo->check_cb)
1051         {
1052           /* More checks by utilizing the optional callback. */
1053           pininfo->cb_errtext = NULL;
1054           rc = pininfo->check_cb (pininfo);
1055           if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1056               && pininfo->cb_errtext)
1057             errtext = pininfo->cb_errtext;
1058           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
1059                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
1060             errtext = (is_pin? L_("Bad PIN") : L_("Bad Passphrase"));
1061           else if (rc)
1062             return unlock_pinentry (rc);
1063         }
1064
1065       if (!errtext)
1066         {
1067           if (pininfo->with_repeat
1068               && (pinentry_status & PINENTRY_STATUS_PIN_REPEATED))
1069             pininfo->repeat_okay = 1;
1070           return unlock_pinentry (0); /* okay, got a PIN or passphrase */
1071         }
1072
1073       if ((pinentry_status & PINENTRY_STATUS_PASSWORD_FROM_CACHE))
1074         /* The password was read from the cache.  Don't count this
1075            against the retry count.  */
1076         pininfo->failed_tries --;
1077     }
1078
1079   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
1080                           : GPG_ERR_BAD_PASSPHRASE));
1081 }
1082
1083
1084 \f
1085 /* Ask for the passphrase using the supplied arguments.  The returned
1086    passphrase needs to be freed by the caller. */
1087 int
1088 agent_get_passphrase (ctrl_t ctrl,
1089                       char **retpass, const char *desc, const char *prompt,
1090                       const char *errtext, int with_qualitybar,
1091                       const char *keyinfo, cache_mode_t cache_mode)
1092 {
1093
1094   int rc;
1095   char line[ASSUAN_LINELENGTH];
1096   struct entry_parm_s parm;
1097   int saveflag;
1098   unsigned int pinentry_status;
1099
1100   *retpass = NULL;
1101   if (opt.batch)
1102     return gpg_error (GPG_ERR_BAD_PASSPHRASE);
1103
1104   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1105     {
1106       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1107         return gpg_error (GPG_ERR_CANCELED);
1108
1109       if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
1110         {
1111           size_t size;
1112           size_t len = ASSUAN_LINELENGTH/2;
1113
1114           return pinentry_loopback (ctrl, "PASSPHRASE",
1115                                     (unsigned char **)retpass, &size, len);
1116         }
1117       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1118     }
1119
1120   rc = start_pinentry (ctrl);
1121   if (rc)
1122     return rc;
1123
1124   if (!prompt)
1125     prompt = desc && strstr (desc, "PIN")? L_("PIN:"): L_("Passphrase:");
1126
1127
1128   /* If we have a KEYINFO string and are normal, user, or ssh cache
1129      mode, we tell that the Pinentry so it may use it for own caching
1130      purposes.  Most pinentries won't have this implemented and thus
1131      we do not error out in this case.  */
1132   if (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1133                   || cache_mode == CACHE_MODE_USER
1134                   || cache_mode == CACHE_MODE_SSH))
1135     snprintf (line, DIM(line), "SETKEYINFO %c/%s",
1136               cache_mode == CACHE_MODE_USER? 'u' :
1137               cache_mode == CACHE_MODE_SSH? 's' : 'n',
1138               keyinfo);
1139   else
1140     snprintf (line, DIM(line), "SETKEYINFO --clear");
1141
1142   rc = assuan_transact (entry_ctx, line,
1143                         NULL, NULL, NULL, NULL, NULL, NULL);
1144   if (rc && gpg_err_code (rc) != GPG_ERR_ASS_UNKNOWN_CMD)
1145     return unlock_pinentry (rc);
1146
1147
1148   if (desc)
1149     snprintf (line, DIM(line), "SETDESC %s", desc);
1150   else
1151     snprintf (line, DIM(line), "RESET");
1152   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1153   if (rc)
1154     return unlock_pinentry (rc);
1155
1156   snprintf (line, DIM(line), "SETPROMPT %s", prompt);
1157   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1158   if (rc)
1159     return unlock_pinentry (rc);
1160
1161   if (with_qualitybar && opt.min_passphrase_len)
1162     {
1163       rc = setup_qualitybar (ctrl);
1164       if (rc)
1165         return unlock_pinentry (rc);
1166     }
1167
1168   if (errtext)
1169     {
1170       snprintf (line, DIM(line), "SETERROR %s", errtext);
1171       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1172       if (rc)
1173         return unlock_pinentry (rc);
1174     }
1175
1176   memset (&parm, 0, sizeof parm);
1177   parm.size = ASSUAN_LINELENGTH/2 - 5;
1178   parm.buffer = gcry_malloc_secure (parm.size+10);
1179   if (!parm.buffer)
1180     return unlock_pinentry (out_of_core ());
1181
1182   saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
1183   assuan_begin_confidential (entry_ctx);
1184   pinentry_status = 0;
1185   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
1186                         inq_quality, entry_ctx,
1187                         pinentry_status_cb, &pinentry_status);
1188   assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
1189   /* Most pinentries out in the wild return the old Assuan error code
1190      for canceled which gets translated to an assuan Cancel error and
1191      not to the code for a user cancel.  Fix this here. */
1192   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1193     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1194   /* Change error code in case the window close button was clicked
1195      to cancel the operation.  */
1196   if ((pinentry_status & PINENTRY_STATUS_CLOSE_BUTTON)
1197       && gpg_err_code (rc) == GPG_ERR_CANCELED)
1198     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);
1199
1200   if (rc)
1201     xfree (parm.buffer);
1202   else
1203     *retpass = parm.buffer;
1204   return unlock_pinentry (rc);
1205 }
1206
1207
1208 \f
1209 /* Pop up the PIN-entry, display the text and the prompt and ask the
1210    user to confirm this.  We return 0 for success, ie. the user
1211    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
1212    other error.  If WITH_CANCEL it true an extra cancel button is
1213    displayed to allow the user to easily return a GPG_ERR_CANCELED.
1214    if the Pinentry does not support this, the user can still cancel by
1215    closing the Pinentry window.  */
1216 int
1217 agent_get_confirmation (ctrl_t ctrl,
1218                         const char *desc, const char *ok,
1219                         const char *notok, int with_cancel)
1220 {
1221   int rc;
1222   char line[ASSUAN_LINELENGTH];
1223
1224   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1225     {
1226       if (ctrl->pinentry_mode == PINENTRY_MODE_CANCEL)
1227         return gpg_error (GPG_ERR_CANCELED);
1228
1229       return gpg_error (GPG_ERR_NO_PIN_ENTRY);
1230     }
1231
1232   rc = start_pinentry (ctrl);
1233   if (rc)
1234     return rc;
1235
1236   if (desc)
1237     snprintf (line, DIM(line), "SETDESC %s", desc);
1238   else
1239     snprintf (line, DIM(line), "RESET");
1240   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1241   /* Most pinentries out in the wild return the old Assuan error code
1242      for canceled which gets translated to an assuan Cancel error and
1243      not to the code for a user cancel.  Fix this here. */
1244   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1245     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1246
1247   if (rc)
1248     return unlock_pinentry (rc);
1249
1250   if (ok)
1251     {
1252       snprintf (line, DIM(line), "SETOK %s", ok);
1253       rc = assuan_transact (entry_ctx,
1254                             line, NULL, NULL, NULL, NULL, NULL, NULL);
1255       if (rc)
1256         return unlock_pinentry (rc);
1257     }
1258   if (notok)
1259     {
1260       /* Try to use the newer NOTOK feature if a cancel button is
1261          requested.  If no cancel button is requested we keep on using
1262          the standard cancel.  */
1263       if (with_cancel)
1264         {
1265           snprintf (line, DIM(line), "SETNOTOK %s", notok);
1266           rc = assuan_transact (entry_ctx,
1267                                 line, NULL, NULL, NULL, NULL, NULL, NULL);
1268         }
1269       else
1270         rc = GPG_ERR_ASS_UNKNOWN_CMD;
1271
1272       if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
1273         {
1274           snprintf (line, DIM(line), "SETCANCEL %s", notok);
1275           rc = assuan_transact (entry_ctx, line,
1276                                 NULL, NULL, NULL, NULL, NULL, NULL);
1277         }
1278       if (rc)
1279         return unlock_pinentry (rc);
1280     }
1281
1282   rc = assuan_transact (entry_ctx, "CONFIRM",
1283                         NULL, NULL, NULL, NULL, NULL, NULL);
1284   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1285     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1286
1287   return unlock_pinentry (rc);
1288 }
1289
1290
1291 \f
1292 /* Pop up the PINentry, display the text DESC and a button with the
1293    text OK_BTN (which may be NULL to use the default of "OK") and wait
1294    for the user to hit this button.  The return value is not
1295    relevant.  */
1296 int
1297 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
1298 {
1299   int rc;
1300   char line[ASSUAN_LINELENGTH];
1301
1302   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1303     return gpg_error (GPG_ERR_CANCELED);
1304
1305   rc = start_pinentry (ctrl);
1306   if (rc)
1307     return rc;
1308
1309   if (desc)
1310     snprintf (line, DIM(line), "SETDESC %s", desc);
1311   else
1312     snprintf (line, DIM(line), "RESET");
1313   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1314   /* Most pinentries out in the wild return the old Assuan error code
1315      for canceled which gets translated to an assuan Cancel error and
1316      not to the code for a user cancel.  Fix this here. */
1317   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1318     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1319
1320   if (rc)
1321     return unlock_pinentry (rc);
1322
1323   if (ok_btn)
1324     {
1325       snprintf (line, DIM(line), "SETOK %s", ok_btn);
1326       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
1327                             NULL, NULL, NULL);
1328       if (rc)
1329         return unlock_pinentry (rc);
1330     }
1331
1332   rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
1333                         NULL, NULL, NULL);
1334   if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1335     rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1336
1337   return unlock_pinentry (rc);
1338 }
1339
1340
1341 /* The thread running the popup message. */
1342 static void *
1343 popup_message_thread (void *arg)
1344 {
1345   (void)arg;
1346
1347   /* We use the --one-button hack instead of the MESSAGE command to
1348      allow the use of old Pinentries.  Those old Pinentries will then
1349      show an additional Cancel button but that is mostly a visual
1350      annoyance. */
1351   assuan_transact (entry_ctx, "CONFIRM --one-button",
1352                    NULL, NULL, NULL, NULL, NULL, NULL);
1353   popup_finished = 1;
1354   return NULL;
1355 }
1356
1357
1358 /* Pop up a message window similar to the confirm one but keep it open
1359    until agent_popup_message_stop has been called.  It is crucial for
1360    the caller to make sure that the stop function gets called as soon
1361    as the message is not anymore required because the message is
1362    system modal and all other attempts to use the pinentry will fail
1363    (after a timeout). */
1364 int
1365 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
1366 {
1367   int rc;
1368   char line[ASSUAN_LINELENGTH];
1369   npth_attr_t tattr;
1370   int err;
1371
1372   if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
1373     return gpg_error (GPG_ERR_CANCELED);
1374
1375   rc = start_pinentry (ctrl);
1376   if (rc)
1377     return rc;
1378
1379   if (desc)
1380     snprintf (line, DIM(line), "SETDESC %s", desc);
1381   else
1382     snprintf (line, DIM(line), "RESET");
1383   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1384   if (rc)
1385     return unlock_pinentry (rc);
1386
1387   if (ok_btn)
1388     {
1389       snprintf (line, DIM(line), "SETOK %s", ok_btn);
1390       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1391       if (rc)
1392         return unlock_pinentry (rc);
1393     }
1394
1395   err = npth_attr_init (&tattr);
1396   if (err)
1397     return unlock_pinentry (gpg_error_from_errno (err));
1398   npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);
1399
1400   popup_finished = 0;
1401   err = npth_create (&popup_tid, &tattr, popup_message_thread, NULL);
1402   npth_attr_destroy (&tattr);
1403   if (err)
1404     {
1405       rc = gpg_error_from_errno (err);
1406       log_error ("error spawning popup message handler: %s\n",
1407                  strerror (err) );
1408       return unlock_pinentry (rc);
1409     }
1410   npth_setname_np (popup_tid, "popup-message");
1411
1412   return 0;
1413 }
1414
1415 /* Close a popup window. */
1416 void
1417 agent_popup_message_stop (ctrl_t ctrl)
1418 {
1419   int rc;
1420   pid_t pid;
1421
1422   (void)ctrl;
1423
1424   if (!popup_tid || !entry_ctx)
1425     {
1426       log_debug ("agent_popup_message_stop called with no active popup\n");
1427       return;
1428     }
1429
1430   pid = assuan_get_pid (entry_ctx);
1431   if (pid == (pid_t)(-1))
1432     ; /* No pid available can't send a kill. */
1433   else if (popup_finished)
1434     ; /* Already finished and ready for joining. */
1435 #ifdef HAVE_W32_SYSTEM
1436   /* Older versions of assuan set PID to 0 on Windows to indicate an
1437      invalid value.  */
1438   else if (pid != (pid_t) INVALID_HANDLE_VALUE
1439            && pid != 0)
1440     {
1441       HANDLE process = (HANDLE) pid;
1442
1443       /* Arbitrary error code.  */
1444       TerminateProcess (process, 1);
1445     }
1446 #else
1447   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1448     { /* The daemon already died.  No need to send a kill.  However
1449          because we already waited for the process, we need to tell
1450          assuan that it should not wait again (done by
1451          unlock_pinentry). */
1452       if (rc == pid)
1453         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1454     }
1455   else if (pid > 0)
1456     kill (pid, SIGINT);
1457 #endif
1458
1459   /* Now wait for the thread to terminate. */
1460   rc = npth_join (popup_tid, NULL);
1461   if (rc)
1462     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1463                strerror (rc));
1464   /* Thread IDs are opaque, but we try our best here by resetting it
1465      to the same content that a static global variable has.  */
1466   memset (&popup_tid, '\0', sizeof (popup_tid));
1467   entry_owner = NULL;
1468
1469   /* Now we can close the connection. */
1470   unlock_pinentry (0);
1471 }
1472
1473 int
1474 agent_clear_passphrase (ctrl_t ctrl,
1475                         const char *keyinfo, cache_mode_t cache_mode)
1476 {
1477   int rc;
1478   char line[ASSUAN_LINELENGTH];
1479
1480   if (! (keyinfo && (cache_mode == CACHE_MODE_NORMAL
1481                      || cache_mode == CACHE_MODE_USER
1482                      || cache_mode == CACHE_MODE_SSH)))
1483     return gpg_error (GPG_ERR_NOT_SUPPORTED);
1484
1485   rc = start_pinentry (ctrl);
1486   if (rc)
1487     return rc;
1488
1489   snprintf (line, DIM(line), "CLEARPASSPHRASE %c/%s",
1490             cache_mode == CACHE_MODE_USER? 'u' :
1491             cache_mode == CACHE_MODE_SSH? 's' : 'n',
1492             keyinfo);
1493   rc = assuan_transact (entry_ctx, line,
1494                         NULL, NULL, NULL, NULL, NULL, NULL);
1495
1496   return unlock_pinentry (rc);
1497 }