[scd] Memory leak fix.
[gnupg.git] / agent / call-pinentry.c
blob172a88914a6dd9cc799f125885e513824f873d1f
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>
36 #include "agent.h"
37 #include <assuan.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_release (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 gpg_error_t
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 rc = assuan_new (&ctx);
313 if (rc)
315 log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
316 return rc;
319 /* Connect to the pinentry and perform initial handshaking. Note
320 that atfork is used to change the environment for pinentry. We
321 start the server in detached mode to suppress the console window
322 under Windows. */
323 rc = assuan_pipe_connect_ext (ctx, opt.pinentry_program, argv,
324 no_close_list, atfork_cb, ctrl, 128);
325 if (rc)
327 log_error ("can't connect to the PIN entry module: %s\n",
328 gpg_strerror (rc));
329 assuan_release (ctx);
330 return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
332 entry_ctx = ctx;
334 if (DBG_ASSUAN)
335 log_debug ("connection to PIN entry established\n");
337 rc = assuan_transact (entry_ctx,
338 opt.no_grab? "OPTION no-grab":"OPTION grab",
339 NULL, NULL, NULL, NULL, NULL, NULL);
340 if (rc)
341 return unlock_pinentry (rc);
343 value = session_env_getenv (ctrl->session_env, "GPG_TTY");
344 if (value)
346 char *optstr;
347 if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
348 return unlock_pinentry (out_of_core ());
349 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
350 NULL);
351 xfree (optstr);
352 if (rc)
353 return unlock_pinentry (rc);
355 value = session_env_getenv (ctrl->session_env, "TERM");
356 if (value)
358 char *optstr;
359 if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
360 return unlock_pinentry (out_of_core ());
361 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
362 NULL);
363 if (rc)
364 return unlock_pinentry (rc);
366 if (ctrl->lc_ctype)
368 char *optstr;
369 if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
370 return unlock_pinentry (out_of_core ());
371 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
372 NULL);
373 if (rc)
374 return unlock_pinentry (rc);
376 if (ctrl->lc_messages)
378 char *optstr;
379 if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
380 return unlock_pinentry (out_of_core ());
381 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
382 NULL);
383 if (rc)
384 return unlock_pinentry (rc);
388 /* Tell the pinentry the name of a file it shall touch after having
389 messed with the tty. This is optional and only supported by
390 newer pinentries and thus we do no error checking. */
391 tmpstr = opt.pinentry_touch_file;
392 if (tmpstr && !strcmp (tmpstr, "/dev/null"))
393 tmpstr = NULL;
394 else if (!tmpstr)
395 tmpstr = get_agent_socket_name ();
396 if (tmpstr)
398 char *optstr;
400 if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
402 else
404 assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
405 NULL);
406 xfree (optstr);
411 /* Now ask the Pinentry for its PID. If the Pinentry is new enough
412 it will send the pid back and we will use an inquire to notify
413 our client. The client may answer the inquiry either with END or
414 with CAN to cancel the pinentry. */
415 rc = assuan_transact (entry_ctx, "GETINFO pid",
416 getinfo_pid_cb, &pinentry_pid,
417 NULL, NULL, NULL, NULL);
418 if (rc)
420 log_info ("You may want to update to a newer pinentry\n");
421 rc = 0;
423 else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
424 log_error ("pinentry did not return a PID\n");
425 else
427 rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
428 if (gpg_err_code (rc) == GPG_ERR_CANCELED)
429 return unlock_pinentry (gpg_error (GPG_ERR_CANCELED));
430 rc = 0;
433 return 0;
437 /* Returns True is the pinentry is currently active. If WAITSECONDS is
438 greater than zero the function will wait for this many seconds
439 before returning. */
441 pinentry_active_p (ctrl_t ctrl, int waitseconds)
443 (void)ctrl;
445 if (waitseconds > 0)
447 pth_event_t evt;
448 int rc;
450 evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
451 if (!pth_mutex_acquire (&entry_lock, 0, evt))
453 if (pth_event_occurred (evt))
454 rc = gpg_error (GPG_ERR_TIMEOUT);
455 else
456 rc = gpg_error (GPG_ERR_INTERNAL);
457 pth_event_free (evt, PTH_FREE_THIS);
458 return rc;
460 pth_event_free (evt, PTH_FREE_THIS);
462 else
464 if (!pth_mutex_acquire (&entry_lock, 1, NULL))
465 return gpg_error (GPG_ERR_LOCKED);
468 if (!pth_mutex_release (&entry_lock))
469 log_error ("failed to release the entry lock at %d\n", __LINE__);
470 return 0;
474 static gpg_error_t
475 getpin_cb (void *opaque, const void *buffer, size_t length)
477 struct entry_parm_s *parm = opaque;
479 if (!buffer)
480 return 0;
482 /* we expect the pin to fit on one line */
483 if (parm->lines || length >= parm->size)
484 return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
486 /* fixme: we should make sure that the assuan buffer is allocated in
487 secure memory or read the response byte by byte */
488 memcpy (parm->buffer, buffer, length);
489 parm->buffer[length] = 0;
490 parm->lines++;
491 return 0;
495 static int
496 all_digitsp( const char *s)
498 for (; *s && *s >= '0' && *s <= '9'; s++)
500 return !*s;
504 /* Return a new malloced string by unescaping the string S. Escaping
505 is percent escaping and '+'/space mapping. A binary Nul will
506 silently be replaced by a 0xFF. Function returns NULL to indicate
507 an out of memory status. PArsing stops at the end of the string or
508 a white space character. */
509 static char *
510 unescape_passphrase_string (const unsigned char *s)
512 char *buffer, *d;
514 buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
515 if (!buffer)
516 return NULL;
517 while (*s && !spacep (s))
519 if (*s == '%' && s[1] && s[2])
521 s++;
522 *d = xtoi_2 (s);
523 if (!*d)
524 *d = '\xff';
525 d++;
526 s += 2;
528 else if (*s == '+')
530 *d++ = ' ';
531 s++;
533 else
534 *d++ = *s++;
536 *d = 0;
537 return buffer;
541 /* Estimate the quality of the passphrase PW and return a value in the
542 range 0..100. */
543 static int
544 estimate_passphrase_quality (const char *pw)
546 int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
547 int length;
548 const char *s;
550 if (goodlength < 1)
551 return 0;
553 for (length = 0, s = pw; *s; s++)
554 if (!spacep (s))
555 length ++;
557 if (length > goodlength)
558 return 100;
559 return ((length*10) / goodlength)*10;
563 /* Handle the QUALITY inquiry. */
564 static gpg_error_t
565 inq_quality (void *opaque, const char *line)
567 assuan_context_t ctx = opaque;
568 char *pin;
569 int rc;
570 int percent;
571 char numbuf[20];
573 if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
575 line += 7;
576 while (*line == ' ')
577 line++;
579 pin = unescape_passphrase_string (line);
580 if (!pin)
581 rc = gpg_error_from_syserror ();
582 else
584 percent = estimate_passphrase_quality (pin);
585 if (check_passphrase_constraints (NULL, pin, 1))
586 percent = -percent;
587 snprintf (numbuf, sizeof numbuf, "%d", percent);
588 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
589 xfree (pin);
592 else
594 log_error ("unsupported inquiry `%s' from pinentry\n", line);
595 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
598 return rc;
602 /* Helper for agent_askpin and agent_get_passphrase. */
603 static int
604 setup_qualitybar (void)
606 int rc;
607 char line[ASSUAN_LINELENGTH];
608 char *tmpstr, *tmpstr2;
609 const char *tooltip;
611 /* TRANSLATORS: This string is displayed by Pinentry as the label
612 for the quality bar. */
613 tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
614 snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
615 line[DIM(line)-1] = 0;
616 xfree (tmpstr);
617 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
618 if (rc == 103 /*(Old assuan error code)*/
619 || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
620 ; /* Ignore Unknown Command from old Pinentry versions. */
621 else if (rc)
622 return rc;
624 tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
625 if (tmpstr2)
626 tooltip = tmpstr2;
627 else
629 /* TRANSLATORS: This string is a tooltip, shown by pinentry when
630 hovering over the quality bar. Please use an appropriate
631 string to describe what this is about. The length of the
632 tooltip is limited to about 900 characters. If you do not
633 translate this entry, a default english text (see source)
634 will be used. */
635 tooltip = _("pinentry.qualitybar.tooltip");
636 if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
637 tooltip = ("The quality of the text entered above.\n"
638 "Please ask your administrator for "
639 "details about the criteria.");
641 tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
642 xfree (tmpstr2);
643 snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
644 line[DIM(line)-1] = 0;
645 xfree (tmpstr);
646 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
647 if (rc == 103 /*(Old assuan error code)*/
648 || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
649 ; /* Ignore Unknown Command from old pinentry versions. */
650 else if (rc)
651 return rc;
653 return 0;
658 /* Call the Entry and ask for the PIN. We do check for a valid PIN
659 number here and repeat it as long as we have invalid formed
660 numbers. */
662 agent_askpin (ctrl_t ctrl,
663 const char *desc_text, const char *prompt_text,
664 const char *initial_errtext,
665 struct pin_entry_info_s *pininfo)
667 int rc;
668 char line[ASSUAN_LINELENGTH];
669 struct entry_parm_s parm;
670 const char *errtext = NULL;
671 int is_pin = 0;
673 if (opt.batch)
674 return 0; /* fixme: we should return BAD PIN */
676 if (!pininfo || pininfo->max_length < 1)
677 return gpg_error (GPG_ERR_INV_VALUE);
678 if (!desc_text && pininfo->min_digits)
679 desc_text = _("Please enter your PIN, so that the secret key "
680 "can be unlocked for this session");
681 else if (!desc_text)
682 desc_text = _("Please enter your passphrase, so that the secret key "
683 "can be unlocked for this session");
685 if (prompt_text)
686 is_pin = !!strstr (prompt_text, "PIN");
687 else
688 is_pin = desc_text && strstr (desc_text, "PIN");
690 rc = start_pinentry (ctrl);
691 if (rc)
692 return rc;
694 snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
695 line[DIM(line)-1] = 0;
696 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
697 if (rc)
698 return unlock_pinentry (rc);
700 snprintf (line, DIM(line)-1, "SETPROMPT %s",
701 prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
702 line[DIM(line)-1] = 0;
703 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
704 if (rc)
705 return unlock_pinentry (rc);
707 /* If a passphrase quality indicator has been requested and a
708 minimum passphrase length has not been disabled, send the command
709 to the pinentry. */
710 if (pininfo->with_qualitybar && opt.min_passphrase_len )
712 rc = setup_qualitybar ();
713 if (rc)
714 return unlock_pinentry (rc);
717 if (initial_errtext)
719 snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
720 line[DIM(line)-1] = 0;
721 rc = assuan_transact (entry_ctx, line,
722 NULL, NULL, NULL, NULL, NULL, NULL);
723 if (rc)
724 return unlock_pinentry (rc);
727 for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
729 memset (&parm, 0, sizeof parm);
730 parm.size = pininfo->max_length;
731 *pininfo->pin = 0; /* Reset the PIN. */
732 parm.buffer = (unsigned char*)pininfo->pin;
734 if (errtext)
736 /* TRANLATORS: The string is appended to an error message in
737 the pinentry. The %s is the actual error message, the
738 two %d give the current and maximum number of tries. */
739 snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
740 errtext, pininfo->failed_tries+1, pininfo->max_tries);
741 line[DIM(line)-1] = 0;
742 rc = assuan_transact (entry_ctx, line,
743 NULL, NULL, NULL, NULL, NULL, NULL);
744 if (rc)
745 return unlock_pinentry (rc);
746 errtext = NULL;
749 rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
750 inq_quality, entry_ctx, NULL, NULL);
751 /* Most pinentries out in the wild return the old Assuan error code
752 for canceled which gets translated to an assuan Cancel error and
753 not to the code for a user cancel. Fix this here. */
754 if (rc && gpg_err_source (rc)
755 && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
756 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
758 if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
759 errtext = is_pin? _("PIN too long")
760 : _("Passphrase too long");
761 else if (rc)
762 return unlock_pinentry (rc);
764 if (!errtext && pininfo->min_digits)
766 /* do some basic checks on the entered PIN. */
767 if (!all_digitsp (pininfo->pin))
768 errtext = _("Invalid characters in PIN");
769 else if (pininfo->max_digits
770 && strlen (pininfo->pin) > pininfo->max_digits)
771 errtext = _("PIN too long");
772 else if (strlen (pininfo->pin) < pininfo->min_digits)
773 errtext = _("PIN too short");
776 if (!errtext && pininfo->check_cb)
778 /* More checks by utilizing the optional callback. */
779 pininfo->cb_errtext = NULL;
780 rc = pininfo->check_cb (pininfo);
781 if (rc == -1 && pininfo->cb_errtext)
782 errtext = pininfo->cb_errtext;
783 else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
784 || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
785 errtext = (is_pin? _("Bad PIN")
786 : _("Bad Passphrase"));
787 else if (rc)
788 return unlock_pinentry (rc);
791 if (!errtext)
792 return unlock_pinentry (0); /* okay, got a PIN or passphrase */
795 return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
796 : GPG_ERR_BAD_PASSPHRASE));
801 /* Ask for the passphrase using the supplied arguments. The returned
802 passphrase needs to be freed by the caller. */
803 int
804 agent_get_passphrase (ctrl_t ctrl,
805 char **retpass, const char *desc, const char *prompt,
806 const char *errtext, int with_qualitybar)
809 int rc;
810 char line[ASSUAN_LINELENGTH];
811 struct entry_parm_s parm;
813 *retpass = NULL;
814 if (opt.batch)
815 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
817 rc = start_pinentry (ctrl);
818 if (rc)
819 return rc;
821 if (!prompt)
822 prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
825 if (desc)
826 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
827 else
828 snprintf (line, DIM(line)-1, "RESET");
829 line[DIM(line)-1] = 0;
830 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
831 if (rc)
832 return unlock_pinentry (rc);
834 snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
835 line[DIM(line)-1] = 0;
836 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
837 if (rc)
838 return unlock_pinentry (rc);
840 if (with_qualitybar && opt.min_passphrase_len)
842 rc = setup_qualitybar ();
843 if (rc)
844 return unlock_pinentry (rc);
847 if (errtext)
849 snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
850 line[DIM(line)-1] = 0;
851 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
852 if (rc)
853 return unlock_pinentry (rc);
856 memset (&parm, 0, sizeof parm);
857 parm.size = ASSUAN_LINELENGTH/2 - 5;
858 parm.buffer = gcry_malloc_secure (parm.size+10);
859 if (!parm.buffer)
860 return unlock_pinentry (out_of_core ());
862 assuan_begin_confidential (entry_ctx);
863 rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
864 inq_quality, entry_ctx, NULL, NULL);
865 /* Most pinentries out in the wild return the old Assuan error code
866 for canceled which gets translated to an assuan Cancel error and
867 not to the code for a user cancel. Fix this here. */
868 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
869 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
870 if (rc)
871 xfree (parm.buffer);
872 else
873 *retpass = parm.buffer;
874 return unlock_pinentry (rc);
879 /* Pop up the PIN-entry, display the text and the prompt and ask the
880 user to confirm this. We return 0 for success, ie. the user
881 confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
882 other error. If WITH_CANCEL it true an extra cancel button is
883 displayed to allow the user to easily return a GPG_ERR_CANCELED.
884 if the Pinentry does not support this, the user can still cancel by
885 closing the Pinentry window. */
886 int
887 agent_get_confirmation (ctrl_t ctrl,
888 const char *desc, const char *ok,
889 const char *notok, int with_cancel)
891 int rc;
892 char line[ASSUAN_LINELENGTH];
894 rc = start_pinentry (ctrl);
895 if (rc)
896 return rc;
898 if (desc)
899 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
900 else
901 snprintf (line, DIM(line)-1, "RESET");
902 line[DIM(line)-1] = 0;
903 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
904 /* Most pinentries out in the wild return the old Assuan error code
905 for canceled which gets translated to an assuan Cancel error and
906 not to the code for a user cancel. Fix this here. */
907 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
908 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
910 if (rc)
911 return unlock_pinentry (rc);
913 if (ok)
915 snprintf (line, DIM(line)-1, "SETOK %s", ok);
916 line[DIM(line)-1] = 0;
917 rc = assuan_transact (entry_ctx,
918 line, NULL, NULL, NULL, NULL, NULL, NULL);
919 if (rc)
920 return unlock_pinentry (rc);
922 if (notok)
924 /* Try to use the newer NOTOK feature if a cancel button is
925 requested. If no cacnel button is requested we keep on using
926 the standard cancel. */
927 if (with_cancel)
929 snprintf (line, DIM(line)-1, "SETNOTOK %s", notok);
930 line[DIM(line)-1] = 0;
931 rc = assuan_transact (entry_ctx,
932 line, NULL, NULL, NULL, NULL, NULL, NULL);
934 else
935 rc = GPG_ERR_ASS_UNKNOWN_CMD;
937 if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
939 snprintf (line, DIM(line)-1, "SETCANCEL %s", notok);
940 line[DIM(line)-1] = 0;
941 rc = assuan_transact (entry_ctx, line,
942 NULL, NULL, NULL, NULL, NULL, NULL);
944 if (rc)
945 return unlock_pinentry (rc);
948 rc = assuan_transact (entry_ctx, "CONFIRM",
949 NULL, NULL, NULL, NULL, NULL, NULL);
950 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
951 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
953 return unlock_pinentry (rc);
958 /* Pop up the PINentry, display the text DESC and a button with the
959 text OK_BTN (which may be NULL to use the default of "OK") and waut
960 for the user to hit this button. The return value is not
961 relevant. */
962 int
963 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
965 int rc;
966 char line[ASSUAN_LINELENGTH];
968 rc = start_pinentry (ctrl);
969 if (rc)
970 return rc;
972 if (desc)
973 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
974 else
975 snprintf (line, DIM(line)-1, "RESET");
976 line[DIM(line)-1] = 0;
977 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
978 /* Most pinentries out in the wild return the old Assuan error code
979 for canceled which gets translated to an assuan Cancel error and
980 not to the code for a user cancel. Fix this here. */
981 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
982 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
984 if (rc)
985 return unlock_pinentry (rc);
987 if (ok_btn)
989 snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
990 line[DIM(line)-1] = 0;
991 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
992 NULL, NULL, NULL);
993 if (rc)
994 return unlock_pinentry (rc);
997 rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
998 NULL, NULL, NULL);
999 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
1000 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
1002 return unlock_pinentry (rc);
1006 /* The thread running the popup message. */
1007 static void *
1008 popup_message_thread (void *arg)
1010 (void)arg;
1012 /* We use the --one-button hack instead of the MESSAGE command to
1013 allow the use of old Pinentries. Those old Pinentries will then
1014 show an additional Cancel button but that is mostly a visual
1015 annoyance. */
1016 assuan_transact (entry_ctx, "CONFIRM --one-button",
1017 NULL, NULL, NULL, NULL, NULL, NULL);
1018 popup_finished = 1;
1019 return NULL;
1023 /* Pop up a message window similar to the confirm one but keep it open
1024 until agent_popup_message_stop has been called. It is crucial for
1025 the caller to make sure that the stop function gets called as soon
1026 as the message is not anymore required because the message is
1027 system modal and all other attempts to use the pinentry will fail
1028 (after a timeout). */
1029 int
1030 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
1032 int rc;
1033 char line[ASSUAN_LINELENGTH];
1034 pth_attr_t tattr;
1036 rc = start_pinentry (ctrl);
1037 if (rc)
1038 return rc;
1040 if (desc)
1041 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
1042 else
1043 snprintf (line, DIM(line)-1, "RESET");
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);
1049 if (ok_btn)
1051 snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1052 line[DIM(line)-1] = 0;
1053 rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1054 if (rc)
1055 return unlock_pinentry (rc);
1058 tattr = pth_attr_new();
1059 pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
1060 pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
1061 pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
1063 popup_finished = 0;
1064 popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
1065 if (!popup_tid)
1067 rc = gpg_error_from_syserror ();
1068 log_error ("error spawning popup message handler: %s\n",
1069 strerror (errno) );
1070 pth_attr_destroy (tattr);
1071 return unlock_pinentry (rc);
1073 pth_attr_destroy (tattr);
1075 return 0;
1078 /* Close a popup window. */
1079 void
1080 agent_popup_message_stop (ctrl_t ctrl)
1082 int rc;
1083 pid_t pid;
1085 (void)ctrl;
1087 if (!popup_tid || !entry_ctx)
1089 log_debug ("agent_popup_message_stop called with no active popup\n");
1090 return;
1093 pid = assuan_get_pid (entry_ctx);
1094 if (pid == (pid_t)(-1))
1095 ; /* No pid available can't send a kill. */
1096 else if (popup_finished)
1097 ; /* Already finished and ready for joining. */
1098 #ifdef HAVE_W32_SYSTEM
1099 /* Older versions of assuan set PID to 0 on Windows to indicate an
1100 invalid value. */
1101 else if (pid != (pid_t) INVALID_HANDLE_VALUE
1102 && pid != 0)
1104 HANDLE process = (HANDLE) pid;
1106 /* Arbitrary error code. */
1107 TerminateProcess (process, 1);
1109 #else
1110 else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1111 { /* The daemon already died. No need to send a kill. However
1112 because we already waited for the process, we need to tell
1113 assuan that it should not wait again (done by
1114 unlock_pinentry). */
1115 if (rc == pid)
1116 assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1118 else if (pid > 0)
1119 kill (pid, SIGKILL); /* Need to use SIGKILL due to bad
1120 interaction of SIGINT with Pth. */
1121 #endif
1123 /* Now wait for the thread to terminate. */
1124 rc = pth_join (popup_tid, NULL);
1125 if (!rc)
1126 log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1127 strerror (errno));
1128 popup_tid = NULL;
1129 entry_owner = NULL;
1131 /* Now we can close the connection. */
1132 unlock_pinentry (0);