Fix bug#1122.
[gnupg.git] / agent / call-pinentry.c
blob5e9685f61560dea5543904d89bccc7dd4c62af37
1 /* call-pinentry.c - fork of the pinentry to query stuff from the user
2 * Copyright (C) 2001, 2002, 2004, 2007, 2008 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <assert.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #ifndef HAVE_W32_SYSTEM
30 # include <sys/wait.h>
31 # include <sys/types.h>
32 # include <signal.h>
33 #endif
34 #include <pth.h>
35 #include <assuan.h>
37 #include "agent.h"
38 #include "setenv.h"
39 #include "i18n.h"
41 #ifdef _POSIX_OPEN_MAX
42 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
43 #else
44 #define MAX_OPEN_FDS 20
45 #endif
48 /* Because access to the pinentry must be serialized (it is and shall
49 be a global mutual dialog) we should better timeout further
50 requests after some time. 2 minutes seem to be a reasonable
51 time. */
52 #define LOCK_TIMEOUT (1*60)
54 /* The assuan context of the current pinentry. */
55 static assuan_context_t entry_ctx;
57 /* The control variable of the connection owning the current pinentry.
58 This is only valid if ENTRY_CTX is not NULL. Note, that we care
59 only about the value of the pointer and that it should never be
60 dereferenced. */
61 static ctrl_t entry_owner;
63 /* A mutex used to serialize access to the pinentry. */
64 static pth_mutex_t entry_lock;
66 /* The thread ID of the popup working thread. */
67 static pth_t popup_tid;
69 /* A flag used in communication between the popup working thread and
70 its stop function. */
71 static int popup_finished;
75 /* Data to be passed to our callbacks, */
76 struct entry_parm_s
78 int lines;
79 size_t size;
80 unsigned char *buffer;
86 /* This function must be called once to initialize this module. This
87 has to be done before a second thread is spawned. We can't do the
88 static initialization because Pth emulation code might not be able
89 to do a static init; in particular, it is not possible for W32. */
90 void
91 initialize_module_call_pinentry (void)
93 static int initialized;
95 if (!initialized)
97 if (pth_mutex_init (&entry_lock))
98 initialized = 1;
104 static void
105 dump_mutex_state (pth_mutex_t *m)
107 #ifdef _W32_PTH_H
108 (void)m;
109 log_printf ("unknown under W32");
110 #else
111 if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
112 log_printf ("not_initialized");
113 else if (!(m->mx_state & PTH_MUTEX_LOCKED))
114 log_printf ("not_locked");
115 else
116 log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
117 #endif
121 /* This function may be called to print infromation pertaining to the
122 current state of this module to the log. */
123 void
124 agent_query_dump_state (void)
126 log_info ("agent_query_dump_state: entry_lock=");
127 dump_mutex_state (&entry_lock);
128 log_printf ("\n");
129 log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
130 entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid);
133 /* Called to make sure that a popup window owned by the current
134 connection gets closed. */
135 void
136 agent_reset_query (ctrl_t ctrl)
138 if (entry_ctx && popup_tid && entry_owner == ctrl)
140 agent_popup_message_stop (ctrl);
145 /* Unlock the pinentry so that another thread can start one and
146 disconnect that pinentry - we do this after the unlock so that a
147 stalled pinentry does not block other threads. Fixme: We should
148 have a timeout in Assuan for the disconnect operation. */
149 static int
150 unlock_pinentry (int rc)
152 assuan_context_t ctx = entry_ctx;
154 entry_ctx = NULL;
155 if (!pth_mutex_release (&entry_lock))
157 log_error ("failed to release the entry lock\n");
158 if (!rc)
159 rc = gpg_error (GPG_ERR_INTERNAL);
161 assuan_disconnect (ctx);
162 return rc;
166 /* To make sure we leave no secrets in our image after forking of the
167 pinentry, we use this callback. */
168 static void
169 atfork_cb (void *opaque, int where)
171 ctrl_t ctrl = opaque;
173 if (!where)
175 int iterator = 0;
176 const char *name, *assname, *value;
178 gcry_control (GCRYCTL_TERM_SECMEM);
180 while ((name = session_env_list_stdenvnames (&iterator, &assname)))
182 /* For all new envvars (!ASSNAME) and the two medium old
183 ones which do have an assuan name but are conveyed using
184 environment variables, update the environment of the
185 forked process. */
186 if (!assname
187 || !strcmp (name, "XAUTHORITY")
188 || !strcmp (name, "PINENTRY_USER_DATA"))
190 value = session_env_getenv (ctrl->session_env, name);
191 if (value)
192 setenv (name, value, 1);
199 static int
200 getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
202 unsigned long *pid = opaque;
203 char pidbuf[50];
205 /* There is only the pid in the server's response. */
206 if (length >= sizeof pidbuf)
207 length = sizeof pidbuf -1;
208 if (length)
210 strncpy (pidbuf, buffer, length);
211 pidbuf[length] = 0;
212 *pid = strtoul (pidbuf, NULL, 10);
214 return 0;
217 /* Fork off the pin entry if this has not already been done. Note,
218 that this function must always be used to aquire the lock for the
219 pinentry - we will serialize _all_ pinentry calls.
221 static int
222 start_pinentry (ctrl_t ctrl)
224 int rc;
225 const char *pgmname;
226 assuan_context_t ctx;
227 const char *argv[5];
228 int no_close_list[3];
229 int i;
230 pth_event_t evt;
231 const char *tmpstr;
232 unsigned long pinentry_pid;
233 const char *value;
235 evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
236 if (!pth_mutex_acquire (&entry_lock, 0, evt))
238 if (pth_event_occurred (evt))
239 rc = gpg_error (GPG_ERR_TIMEOUT);
240 else
241 rc = gpg_error (GPG_ERR_INTERNAL);
242 pth_event_free (evt, PTH_FREE_THIS);
243 log_error (_("failed to acquire the pinentry lock: %s\n"),
244 gpg_strerror (rc));
245 return rc;
247 pth_event_free (evt, PTH_FREE_THIS);
249 entry_owner = ctrl;
251 if (entry_ctx)
252 return 0;
254 if (opt.verbose)
255 log_info ("starting a new PIN Entry\n");
257 #ifdef HAVE_W32_SYSTEM
258 fflush (stdout);
259 fflush (stderr);
260 #endif
261 if (fflush (NULL))
263 #ifndef HAVE_W32_SYSTEM
264 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
265 #endif
266 log_error ("error flushing pending output: %s\n", strerror (errno));
267 /* At least Windows XP fails here with EBADF. According to docs
268 and Wine an fflush(NULL) is the same as _flushall. However
269 the Wime implementaion does not flush stdin,stdout and stderr
270 - see above. Lets try to ignore the error. */
271 #ifndef HAVE_W32_SYSTEM
272 return unlock_pinentry (tmperr);
273 #endif
276 if (!opt.pinentry_program || !*opt.pinentry_program)
277 opt.pinentry_program = gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY);
278 pgmname = opt.pinentry_program;
279 if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
280 pgmname = opt.pinentry_program;
281 else
282 pgmname++;
284 /* OS X needs the entire file name in argv[0], so that it can locate
285 the resource bundle. For other systems we stick to the usual
286 convention of supplying only the name of the program. */
287 #ifdef __APPLE__
288 argv[0] = opt.pinentry_program;
289 #else /*!__APPLE__*/
290 argv[0] = pgmname;
291 #endif /*__APPLE__*/
293 if (!opt.keep_display
294 && (value = session_env_getenv (ctrl->session_env, "DISPLAY")))
296 argv[1] = "--display";
297 argv[2] = value;
298 argv[3] = NULL;
300 else
301 argv[1] = NULL;
303 i=0;
304 if (!opt.running_detached)
306 if (log_get_fd () != -1)
307 no_close_list[i++] = log_get_fd ();
308 no_close_list[i++] = fileno (stderr);
310 no_close_list[i] = -1;
312 /* Connect to the pinentry and perform initial handshaking. Note
313 that atfork is used to change the environment for pinentry. We
314 start the server in detached mode to suppress the console window
315 under Windows. */
316 rc = assuan_pipe_connect_ext (&ctx, opt.pinentry_program, argv,
317 no_close_list, atfork_cb, ctrl, 128);
318 if (rc)
320 log_error ("can't connect to the PIN entry module: %s\n",
321 gpg_strerror (rc));
322 return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
324 entry_ctx = ctx;
326 if (DBG_ASSUAN)
327 log_debug ("connection to PIN entry established\n");
329 rc = assuan_transact (entry_ctx,
330 opt.no_grab? "OPTION no-grab":"OPTION grab",
331 NULL, NULL, NULL, NULL, NULL, NULL);
332 if (rc)
333 return unlock_pinentry (rc);
335 value = session_env_getenv (ctrl->session_env, "GPG_TTY");
336 if (value)
338 char *optstr;
339 if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
340 return unlock_pinentry (out_of_core ());
341 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
342 NULL);
343 xfree (optstr);
344 if (rc)
345 return unlock_pinentry (rc);
347 value = session_env_getenv (ctrl->session_env, "TERM");
348 if (value)
350 char *optstr;
351 if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
352 return unlock_pinentry (out_of_core ());
353 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
354 NULL);
355 if (rc)
356 return unlock_pinentry (rc);
358 if (ctrl->lc_ctype)
360 char *optstr;
361 if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
362 return unlock_pinentry (out_of_core ());
363 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
364 NULL);
365 if (rc)
366 return unlock_pinentry (rc);
368 if (ctrl->lc_messages)
370 char *optstr;
371 if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
372 return unlock_pinentry (out_of_core ());
373 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
374 NULL);
375 if (rc)
376 return unlock_pinentry (rc);
380 /* Tell the pinentry the name of a file it shall touch after having
381 messed with the tty. This is optional and only supported by
382 newer pinentries and thus we do no error checking. */
383 tmpstr = opt.pinentry_touch_file;
384 if (tmpstr && !strcmp (tmpstr, "/dev/null"))
385 tmpstr = NULL;
386 else if (!tmpstr)
387 tmpstr = get_agent_socket_name ();
388 if (tmpstr)
390 char *optstr;
392 if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
394 else
396 assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
397 NULL);
398 xfree (optstr);
403 /* Now ask the Pinentry for its PID. If the Pinentry is new enough
404 it will send the pid back and we will use an inquire to notify
405 our client. The client may answer the inquiry either with END or
406 with CAN to cancel the pinentry. */
407 rc = assuan_transact (entry_ctx, "GETINFO pid",
408 getinfo_pid_cb, &pinentry_pid,
409 NULL, NULL, NULL, NULL);
410 if (rc)
412 log_info ("You may want to update to a newer pinentry\n");
413 rc = 0;
415 else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
416 log_error ("pinentry did not return a PID\n");
417 else
419 rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
420 if (gpg_err_code (rc) == GPG_ERR_CANCELED)
421 return unlock_pinentry (gpg_error (GPG_ERR_CANCELED));
422 rc = 0;
425 return 0;
429 /* Returns True is the pinentry is currently active. If WAITSECONDS is
430 greater than zero the function will wait for this many seconds
431 before returning. */
433 pinentry_active_p (ctrl_t ctrl, int waitseconds)
435 (void)ctrl;
437 if (waitseconds > 0)
439 pth_event_t evt;
440 int rc;
442 evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
443 if (!pth_mutex_acquire (&entry_lock, 0, evt))
445 if (pth_event_occurred (evt))
446 rc = gpg_error (GPG_ERR_TIMEOUT);
447 else
448 rc = gpg_error (GPG_ERR_INTERNAL);
449 pth_event_free (evt, PTH_FREE_THIS);
450 return rc;
452 pth_event_free (evt, PTH_FREE_THIS);
454 else
456 if (!pth_mutex_acquire (&entry_lock, 1, NULL))
457 return gpg_error (GPG_ERR_LOCKED);
460 if (!pth_mutex_release (&entry_lock))
461 log_error ("failed to release the entry lock at %d\n", __LINE__);
462 return 0;
466 static int
467 getpin_cb (void *opaque, const void *buffer, size_t length)
469 struct entry_parm_s *parm = opaque;
471 if (!buffer)
472 return 0;
474 /* we expect the pin to fit on one line */
475 if (parm->lines || length >= parm->size)
476 return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
478 /* fixme: we should make sure that the assuan buffer is allocated in
479 secure memory or read the response byte by byte */
480 memcpy (parm->buffer, buffer, length);
481 parm->buffer[length] = 0;
482 parm->lines++;
483 return 0;
487 static int
488 all_digitsp( const char *s)
490 for (; *s && *s >= '0' && *s <= '9'; s++)
492 return !*s;
496 /* Return a new malloced string by unescaping the string S. Escaping
497 is percent escaping and '+'/space mapping. A binary Nul will
498 silently be replaced by a 0xFF. Function returns NULL to indicate
499 an out of memory status. PArsing stops at the end of the string or
500 a white space character. */
501 static char *
502 unescape_passphrase_string (const unsigned char *s)
504 char *buffer, *d;
506 buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
507 if (!buffer)
508 return NULL;
509 while (*s && !spacep (s))
511 if (*s == '%' && s[1] && s[2])
513 s++;
514 *d = xtoi_2 (s);
515 if (!*d)
516 *d = '\xff';
517 d++;
518 s += 2;
520 else if (*s == '+')
522 *d++ = ' ';
523 s++;
525 else
526 *d++ = *s++;
528 *d = 0;
529 return buffer;
533 /* Estimate the quality of the passphrase PW and return a value in the
534 range 0..100. */
535 static int
536 estimate_passphrase_quality (const char *pw)
538 int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
539 int length;
540 const char *s;
542 if (goodlength < 1)
543 return 0;
545 for (length = 0, s = pw; *s; s++)
546 if (!spacep (s))
547 length ++;
549 if (length > goodlength)
550 return 100;
551 return ((length*10) / goodlength)*10;
555 /* Handle the QUALITY inquiry. */
556 static int
557 inq_quality (void *opaque, const char *line)
559 assuan_context_t ctx = opaque;
560 char *pin;
561 int rc;
562 int percent;
563 char numbuf[20];
565 if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
567 line += 7;
568 while (*line == ' ')
569 line++;
571 pin = unescape_passphrase_string (line);
572 if (!pin)
573 rc = gpg_error_from_syserror ();
574 else
576 percent = estimate_passphrase_quality (pin);
577 if (check_passphrase_constraints (NULL, pin, 1))
578 percent = -percent;
579 snprintf (numbuf, sizeof numbuf, "%d", percent);
580 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
581 xfree (pin);
584 else
586 log_error ("unsupported inquiry `%s' from pinentry\n", line);
587 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
590 return rc;
594 /* Helper for agent_askpin and agent_get_passphrase. */
595 static int
596 setup_qualitybar (void)
598 int rc;
599 char line[ASSUAN_LINELENGTH];
600 char *tmpstr, *tmpstr2;
601 const char *tooltip;
603 /* TRANSLATORS: This string is displayed by Pinentry as the label
604 for the quality bar. */
605 tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
606 snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
607 line[DIM(line)-1] = 0;
608 xfree (tmpstr);
609 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
610 if (rc == 103 /*(Old assuan error code)*/
611 || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
612 ; /* Ignore Unknown Command from old Pinentry versions. */
613 else if (rc)
614 return rc;
616 tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
617 if (tmpstr2)
618 tooltip = tmpstr2;
619 else
621 /* TRANSLATORS: This string is a tooltip, shown by pinentry when
622 hovering over the quality bar. Please use an appropriate
623 string to describe what this is about. The length of the
624 tooltip is limited to about 900 characters. If you do not
625 translate this entry, a default english text (see source)
626 will be used. */
627 tooltip = _("pinentry.qualitybar.tooltip");
628 if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
629 tooltip = ("The quality of the text entered above.\n"
630 "Please ask your administrator for "
631 "details about the criteria.");
633 tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
634 xfree (tmpstr2);
635 snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
636 line[DIM(line)-1] = 0;
637 xfree (tmpstr);
638 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
639 if (rc == 103 /*(Old assuan error code)*/
640 || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
641 ; /* Ignore Unknown Command from old pinentry versions. */
642 else if (rc)
643 return rc;
645 return 0;
650 /* Call the Entry and ask for the PIN. We do check for a valid PIN
651 number here and repeat it as long as we have invalid formed
652 numbers. */
654 agent_askpin (ctrl_t ctrl,
655 const char *desc_text, const char *prompt_text,
656 const char *initial_errtext,
657 struct pin_entry_info_s *pininfo)
659 int rc;
660 char line[ASSUAN_LINELENGTH];
661 struct entry_parm_s parm;
662 const char *errtext = NULL;
663 int is_pin = 0;
665 if (opt.batch)
666 return 0; /* fixme: we should return BAD PIN */
668 if (!pininfo || pininfo->max_length < 1)
669 return gpg_error (GPG_ERR_INV_VALUE);
670 if (!desc_text && pininfo->min_digits)
671 desc_text = _("Please enter your PIN, so that the secret key "
672 "can be unlocked for this session");
673 else if (!desc_text)
674 desc_text = _("Please enter your passphrase, so that the secret key "
675 "can be unlocked for this session");
677 if (prompt_text)
678 is_pin = !!strstr (prompt_text, "PIN");
679 else
680 is_pin = desc_text && strstr (desc_text, "PIN");
682 rc = start_pinentry (ctrl);
683 if (rc)
684 return rc;
686 snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
687 line[DIM(line)-1] = 0;
688 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
689 if (rc)
690 return unlock_pinentry (rc);
692 snprintf (line, DIM(line)-1, "SETPROMPT %s",
693 prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
694 line[DIM(line)-1] = 0;
695 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
696 if (rc)
697 return unlock_pinentry (rc);
699 /* If a passphrase quality indicator has been requested and a
700 minimum passphrase length has not been disabled, send the command
701 to the pinentry. */
702 if (pininfo->with_qualitybar && opt.min_passphrase_len )
704 rc = setup_qualitybar ();
705 if (rc)
706 return unlock_pinentry (rc);
709 if (initial_errtext)
711 snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
712 line[DIM(line)-1] = 0;
713 rc = assuan_transact (entry_ctx, line,
714 NULL, NULL, NULL, NULL, NULL, NULL);
715 if (rc)
716 return unlock_pinentry (rc);
719 for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
721 memset (&parm, 0, sizeof parm);
722 parm.size = pininfo->max_length;
723 *pininfo->pin = 0; /* Reset the PIN. */
724 parm.buffer = (unsigned char*)pininfo->pin;
726 if (errtext)
728 /* TRANLATORS: The string is appended to an error message in
729 the pinentry. The %s is the actual error message, the
730 two %d give the current and maximum number of tries. */
731 snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
732 errtext, pininfo->failed_tries+1, pininfo->max_tries);
733 line[DIM(line)-1] = 0;
734 rc = assuan_transact (entry_ctx, line,
735 NULL, NULL, NULL, NULL, NULL, NULL);
736 if (rc)
737 return unlock_pinentry (rc);
738 errtext = NULL;
741 rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
742 inq_quality, entry_ctx, NULL, NULL);
743 /* Most pinentries out in the wild return the old Assuan error code
744 for canceled which gets translated to an assuan Cancel error and
745 not to the code for a user cancel. Fix this here. */
746 if (rc && gpg_err_source (rc)
747 && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
748 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
750 if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
751 errtext = is_pin? _("PIN too long")
752 : _("Passphrase too long");
753 else if (rc)
754 return unlock_pinentry (rc);
756 if (!errtext && pininfo->min_digits)
758 /* do some basic checks on the entered PIN. */
759 if (!all_digitsp (pininfo->pin))
760 errtext = _("Invalid characters in PIN");
761 else if (pininfo->max_digits
762 && strlen (pininfo->pin) > pininfo->max_digits)
763 errtext = _("PIN too long");
764 else if (strlen (pininfo->pin) < pininfo->min_digits)
765 errtext = _("PIN too short");
768 if (!errtext && pininfo->check_cb)
770 /* More checks by utilizing the optional callback. */
771 pininfo->cb_errtext = NULL;
772 rc = pininfo->check_cb (pininfo);
773 if (rc == -1 && pininfo->cb_errtext)
774 errtext = pininfo->cb_errtext;
775 else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
776 || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
777 errtext = (is_pin? _("Bad PIN")
778 : _("Bad Passphrase"));
779 else if (rc)
780 return unlock_pinentry (rc);
783 if (!errtext)
784 return unlock_pinentry (0); /* okay, got a PIN or passphrase */
787 return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
788 : GPG_ERR_BAD_PASSPHRASE));
793 /* Ask for the passphrase using the supplied arguments. The returned
794 passphrase needs to be freed by the caller. */
795 int
796 agent_get_passphrase (ctrl_t ctrl,
797 char **retpass, const char *desc, const char *prompt,
798 const char *errtext, int with_qualitybar)
801 int rc;
802 char line[ASSUAN_LINELENGTH];
803 struct entry_parm_s parm;
805 *retpass = NULL;
806 if (opt.batch)
807 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
809 rc = start_pinentry (ctrl);
810 if (rc)
811 return rc;
813 if (!prompt)
814 prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
817 if (desc)
818 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
819 else
820 snprintf (line, DIM(line)-1, "RESET");
821 line[DIM(line)-1] = 0;
822 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
823 if (rc)
824 return unlock_pinentry (rc);
826 snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
827 line[DIM(line)-1] = 0;
828 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
829 if (rc)
830 return unlock_pinentry (rc);
832 if (with_qualitybar && opt.min_passphrase_len)
834 rc = setup_qualitybar ();
835 if (rc)
836 return unlock_pinentry (rc);
839 if (errtext)
841 snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
842 line[DIM(line)-1] = 0;
843 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
844 if (rc)
845 return unlock_pinentry (rc);
848 memset (&parm, 0, sizeof parm);
849 parm.size = ASSUAN_LINELENGTH/2 - 5;
850 parm.buffer = gcry_malloc_secure (parm.size+10);
851 if (!parm.buffer)
852 return unlock_pinentry (out_of_core ());
854 assuan_begin_confidential (entry_ctx);
855 rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
856 inq_quality, entry_ctx, NULL, NULL);
857 /* Most pinentries out in the wild return the old Assuan error code
858 for canceled which gets translated to an assuan Cancel error and
859 not to the code for a user cancel. Fix this here. */
860 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
861 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
862 if (rc)
863 xfree (parm.buffer);
864 else
865 *retpass = parm.buffer;
866 return unlock_pinentry (rc);
871 /* Pop up the PIN-entry, display the text and the prompt and ask the
872 user to confirm this. We return 0 for success, ie. the user
873 confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
874 other error. If WITH_CANCEL it true an extra cancel button is
875 displayed to allow the user to easily return a GPG_ERR_CANCELED.
876 if the Pinentry does not support this, the user can still cancel by
877 closing the Pinentry window. */
878 int
879 agent_get_confirmation (ctrl_t ctrl,
880 const char *desc, const char *ok,
881 const char *notok, int with_cancel)
883 int rc;
884 char line[ASSUAN_LINELENGTH];
886 rc = start_pinentry (ctrl);
887 if (rc)
888 return rc;
890 if (desc)
891 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
892 else
893 snprintf (line, DIM(line)-1, "RESET");
894 line[DIM(line)-1] = 0;
895 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
896 /* Most pinentries out in the wild return the old Assuan error code
897 for canceled which gets translated to an assuan Cancel error and
898 not to the code for a user cancel. Fix this here. */
899 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
900 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
902 if (rc)
903 return unlock_pinentry (rc);
905 if (ok)
907 snprintf (line, DIM(line)-1, "SETOK %s", ok);
908 line[DIM(line)-1] = 0;
909 rc = assuan_transact (entry_ctx,
910 line, NULL, NULL, NULL, NULL, NULL, NULL);
911 if (rc)
912 return unlock_pinentry (rc);
914 if (notok)
916 /* Try to use the newer NOTOK feature if a cancel button is
917 requested. If no cacnel button is requested we keep on using
918 the standard cancel. */
919 if (with_cancel)
921 snprintf (line, DIM(line)-1, "SETNOTOK %s", notok);
922 line[DIM(line)-1] = 0;
923 rc = assuan_transact (entry_ctx,
924 line, NULL, NULL, NULL, NULL, NULL, NULL);
926 else
927 rc = GPG_ERR_ASS_UNKNOWN_CMD;
929 if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
931 snprintf (line, DIM(line)-1, "SETCANCEL %s", notok);
932 line[DIM(line)-1] = 0;
933 rc = assuan_transact (entry_ctx, line,
934 NULL, NULL, NULL, NULL, NULL, NULL);
936 if (rc)
937 return unlock_pinentry (rc);
940 rc = assuan_transact (entry_ctx, "CONFIRM",
941 NULL, NULL, NULL, NULL, NULL, NULL);
942 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
943 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
945 return unlock_pinentry (rc);
950 /* Pop up the PINentry, display the text DESC and a button with the
951 text OK_BTN (which may be NULL to use the default of "OK") and waut
952 for the user to hit this button. The return value is not
953 relevant. */
954 int
955 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
957 int rc;
958 char line[ASSUAN_LINELENGTH];
960 rc = start_pinentry (ctrl);
961 if (rc)
962 return rc;
964 if (desc)
965 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
966 else
967 snprintf (line, DIM(line)-1, "RESET");
968 line[DIM(line)-1] = 0;
969 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
970 /* Most pinentries out in the wild return the old Assuan error code
971 for canceled which gets translated to an assuan Cancel error and
972 not to the code for a user cancel. Fix this here. */
973 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
974 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
976 if (rc)
977 return unlock_pinentry (rc);
979 if (ok_btn)
981 snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
982 line[DIM(line)-1] = 0;
983 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
984 NULL, NULL, NULL);
985 if (rc)
986 return unlock_pinentry (rc);
989 rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
990 NULL, NULL, NULL);
991 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
992 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
994 return unlock_pinentry (rc);
998 /* The thread running the popup message. */
999 static void *
1000 popup_message_thread (void *arg)
1002 (void)arg;
1004 /* We use the --one-button hack instead of the MESSAGE command to
1005 allow the use of old Pinentries. Those old Pinentries will then
1006 show an additional Cancel button but that is mostly a visual
1007 annoyance. */
1008 assuan_transact (entry_ctx, "CONFIRM --one-button",
1009 NULL, NULL, NULL, NULL, NULL, NULL);
1010 popup_finished = 1;
1011 return NULL;
1015 /* Pop up a message window similar to the confirm one but keep it open
1016 until agent_popup_message_stop has been called. It is crucial for
1017 the caller to make sure that the stop function gets called as soon
1018 as the message is not anymore required because the message is
1019 system modal and all other attempts to use the pinentry will fail
1020 (after a timeout). */
1021 int
1022 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
1024 int rc;
1025 char line[ASSUAN_LINELENGTH];
1026 pth_attr_t tattr;
1028 rc = start_pinentry (ctrl);
1029 if (rc)
1030 return rc;
1032 if (desc)
1033 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1034 else
1035 snprintf (line, DIM(line)-1, "RESET");
1036 line[DIM(line)-1] = 0;
1037 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1038 if (rc)
1039 return unlock_pinentry (rc);
1041 if (ok_btn)
1043 snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1044 line[DIM(line)-1] = 0;
1045 rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1046 if (rc)
1047 return unlock_pinentry (rc);
1050 tattr = pth_attr_new();
1051 pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
1052 pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
1053 pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
1055 popup_finished = 0;
1056 popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
1057 if (!popup_tid)
1059 rc = gpg_error_from_syserror ();
1060 log_error ("error spawning popup message handler: %s\n",
1061 strerror (errno) );
1062 pth_attr_destroy (tattr);
1063 return unlock_pinentry (rc);
1065 pth_attr_destroy (tattr);
1067 return 0;
1070 /* Close a popup window. */
1071 void
1072 agent_popup_message_stop (ctrl_t ctrl)
1074 int rc;
1075 pid_t pid;
1077 (void)ctrl;
1079 if (!popup_tid || !entry_ctx)
1081 log_debug ("agent_popup_message_stop called with no active popup\n");
1082 return;
1085 pid = assuan_get_pid (entry_ctx);
1086 if (pid == (pid_t)(-1))
1087 ; /* No pid available can't send a kill. */
1088 else if (popup_finished)
1089 ; /* Already finished and ready for joining. */
1090 #ifdef HAVE_W32_SYSTEM
1091 /* Older versions of assuan set PID to 0 on Windows to indicate an
1092 invalid value. */
1093 else if (pid != (pid_t) INVALID_HANDLE_VALUE
1094 && pid != 0)
1096 HANDLE process = (HANDLE) pid;
1098 /* Arbitrary error code. */
1099 TerminateProcess (process, 1);
1101 #else
1102 else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1103 { /* The daemon already died. No need to send a kill. However
1104 because we already waited for the process, we need to tell
1105 assuan that it should not wait again (done by
1106 unlock_pinentry). */
1107 if (rc == pid)
1108 assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1110 else if (pid > 0)
1111 kill (pid, SIGKILL); /* Need to use SIGKILL due to bad
1112 interaction of SIGINT with Pth. */
1113 #endif
1115 /* Now wait for the thread to terminate. */
1116 rc = pth_join (popup_tid, NULL);
1117 if (!rc)
1118 log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1119 strerror (errno));
1120 popup_tid = NULL;
1121 entry_owner = NULL;
1123 /* Now we can close the connection. */
1124 unlock_pinentry (0);