app-openpgp changes
[gnupg.git] / agent / call-pinentry.c
blob41fe6f40913a6ee3c942dfe78af34ffb1ff5f948
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 gcry_control (GCRYCTL_TERM_SECMEM);
176 if (ctrl->xauthority)
177 setenv ("XAUTHORITY", ctrl->xauthority, 1);
178 if (ctrl->pinentry_user_data)
179 setenv ("PINENTRY_USER_DATA", ctrl->pinentry_user_data, 1 );
183 static int
184 getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
186 unsigned long *pid = opaque;
187 char pidbuf[50];
189 /* There is only the pid in the server's response. */
190 if (length >= sizeof pidbuf)
191 length = sizeof pidbuf -1;
192 if (length)
194 strncpy (pidbuf, buffer, length);
195 pidbuf[length] = 0;
196 *pid = strtoul (pidbuf, NULL, 10);
198 return 0;
201 /* Fork off the pin entry if this has not already been done. Note,
202 that this function must always be used to aquire the lock for the
203 pinentry - we will serialize _all_ pinentry calls.
205 static int
206 start_pinentry (ctrl_t ctrl)
208 int rc;
209 const char *pgmname;
210 assuan_context_t ctx;
211 const char *argv[5];
212 int no_close_list[3];
213 int i;
214 pth_event_t evt;
215 const char *tmpstr;
216 unsigned long pinentry_pid;
218 evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
219 if (!pth_mutex_acquire (&entry_lock, 0, evt))
221 if (pth_event_occurred (evt))
222 rc = gpg_error (GPG_ERR_TIMEOUT);
223 else
224 rc = gpg_error (GPG_ERR_INTERNAL);
225 pth_event_free (evt, PTH_FREE_THIS);
226 log_error (_("failed to acquire the pinentry lock: %s\n"),
227 gpg_strerror (rc));
228 return rc;
230 pth_event_free (evt, PTH_FREE_THIS);
232 entry_owner = ctrl;
234 if (entry_ctx)
235 return 0;
237 if (opt.verbose)
238 log_info ("starting a new PIN Entry\n");
240 #ifdef HAVE_W32_SYSTEM
241 fflush (stdout);
242 fflush (stderr);
243 #endif
244 if (fflush (NULL))
246 #ifndef HAVE_W32_SYSTEM
247 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
248 #endif
249 log_error ("error flushing pending output: %s\n", strerror (errno));
250 /* At least Windows XP fails here with EBADF. According to docs
251 and Wine an fflush(NULL) is the same as _flushall. However
252 the Wime implementaion does not flush stdin,stdout and stderr
253 - see above. Lets try to ignore the error. */
254 #ifndef HAVE_W32_SYSTEM
255 return unlock_pinentry (tmperr);
256 #endif
259 if (!opt.pinentry_program || !*opt.pinentry_program)
260 opt.pinentry_program = gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY);
261 pgmname = opt.pinentry_program;
262 if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
263 pgmname = opt.pinentry_program;
264 else
265 pgmname++;
267 /* OS X needs the entire file name in argv[0], so that it can locate
268 the resource bundle. For other systems we stick to the usual
269 convention of supplying only the name of the program. */
270 #ifdef __APPLE__
271 argv[0] = opt.pinentry_program;
272 #else /*!__APPLE__*/
273 argv[0] = pgmname;
274 #endif /*__APPLE__*/
276 if (ctrl->display && !opt.keep_display)
278 argv[1] = "--display";
279 argv[2] = ctrl->display;
280 argv[3] = NULL;
282 else
283 argv[1] = NULL;
285 i=0;
286 if (!opt.running_detached)
288 if (log_get_fd () != -1)
289 no_close_list[i++] = log_get_fd ();
290 no_close_list[i++] = fileno (stderr);
292 no_close_list[i] = -1;
294 /* Connect to the pinentry and perform initial handshaking. Note
295 that atfork is used to change the environment for pinentry. We
296 start the server in detached mode to suppress the console window
297 under Windows. */
298 rc = assuan_pipe_connect_ext (&ctx, opt.pinentry_program, argv,
299 no_close_list, atfork_cb, ctrl, 128);
300 if (rc)
302 log_error ("can't connect to the PIN entry module: %s\n",
303 gpg_strerror (rc));
304 return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
306 entry_ctx = ctx;
308 if (DBG_ASSUAN)
309 log_debug ("connection to PIN entry established\n");
311 rc = assuan_transact (entry_ctx,
312 opt.no_grab? "OPTION no-grab":"OPTION grab",
313 NULL, NULL, NULL, NULL, NULL, NULL);
314 if (rc)
315 return unlock_pinentry (rc);
316 if (ctrl->ttyname)
318 char *optstr;
319 if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
320 return unlock_pinentry (out_of_core ());
321 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
322 NULL);
323 xfree (optstr);
324 if (rc)
325 return unlock_pinentry (rc);
327 if (ctrl->ttytype)
329 char *optstr;
330 if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
331 return unlock_pinentry (out_of_core ());
332 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
333 NULL);
334 if (rc)
335 return unlock_pinentry (rc);
337 if (ctrl->lc_ctype)
339 char *optstr;
340 if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
341 return unlock_pinentry (out_of_core ());
342 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
343 NULL);
344 if (rc)
345 return unlock_pinentry (rc);
347 if (ctrl->lc_messages)
349 char *optstr;
350 if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
351 return unlock_pinentry (out_of_core ());
352 rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
353 NULL);
354 if (rc)
355 return unlock_pinentry (rc);
359 /* Tell the pinentry the name of a file it shall touch after having
360 messed with the tty. This is optional and only supported by
361 newer pinentries and thus we do no error checking. */
362 tmpstr = opt.pinentry_touch_file;
363 if (tmpstr && !strcmp (tmpstr, "/dev/null"))
364 tmpstr = NULL;
365 else if (!tmpstr)
366 tmpstr = get_agent_socket_name ();
367 if (tmpstr)
369 char *optstr;
371 if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
373 else
375 assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
376 NULL);
377 xfree (optstr);
382 /* Now ask the Pinentry for its PID. If the Pinentry is new enough
383 it will send the pid back and we will use an inquire to notify
384 our client. The client may answer the inquiry either with END or
385 with CAN to cancel the pinentry. */
386 rc = assuan_transact (entry_ctx, "GETINFO pid",
387 getinfo_pid_cb, &pinentry_pid,
388 NULL, NULL, NULL, NULL);
389 if (rc)
391 log_info ("You may want to update to a newer pinentry\n");
392 rc = 0;
394 else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
395 log_error ("pinentry did not return a PID\n");
396 else
398 rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
399 if (gpg_err_code (rc) == GPG_ERR_CANCELED)
400 return unlock_pinentry (gpg_error (GPG_ERR_CANCELED));
401 rc = 0;
404 return 0;
408 /* Returns True is the pinentry is currently active. If WAITSECONDS is
409 greater than zero the function will wait for this many seconds
410 before returning. */
412 pinentry_active_p (ctrl_t ctrl, int waitseconds)
414 (void)ctrl;
416 if (waitseconds > 0)
418 pth_event_t evt;
419 int rc;
421 evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
422 if (!pth_mutex_acquire (&entry_lock, 0, evt))
424 if (pth_event_occurred (evt))
425 rc = gpg_error (GPG_ERR_TIMEOUT);
426 else
427 rc = gpg_error (GPG_ERR_INTERNAL);
428 pth_event_free (evt, PTH_FREE_THIS);
429 return rc;
431 pth_event_free (evt, PTH_FREE_THIS);
433 else
435 if (!pth_mutex_acquire (&entry_lock, 1, NULL))
436 return gpg_error (GPG_ERR_LOCKED);
439 if (!pth_mutex_release (&entry_lock))
440 log_error ("failed to release the entry lock at %d\n", __LINE__);
441 return 0;
445 static int
446 getpin_cb (void *opaque, const void *buffer, size_t length)
448 struct entry_parm_s *parm = opaque;
450 if (!buffer)
451 return 0;
453 /* we expect the pin to fit on one line */
454 if (parm->lines || length >= parm->size)
455 return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
457 /* fixme: we should make sure that the assuan buffer is allocated in
458 secure memory or read the response byte by byte */
459 memcpy (parm->buffer, buffer, length);
460 parm->buffer[length] = 0;
461 parm->lines++;
462 return 0;
466 static int
467 all_digitsp( const char *s)
469 for (; *s && *s >= '0' && *s <= '9'; s++)
471 return !*s;
475 /* Return a new malloced string by unescaping the string S. Escaping
476 is percent escaping and '+'/space mapping. A binary Nul will
477 silently be replaced by a 0xFF. Function returns NULL to indicate
478 an out of memory status. PArsing stops at the end of the string or
479 a white space character. */
480 static char *
481 unescape_passphrase_string (const unsigned char *s)
483 char *buffer, *d;
485 buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
486 if (!buffer)
487 return NULL;
488 while (*s && !spacep (s))
490 if (*s == '%' && s[1] && s[2])
492 s++;
493 *d = xtoi_2 (s);
494 if (!*d)
495 *d = '\xff';
496 d++;
497 s += 2;
499 else if (*s == '+')
501 *d++ = ' ';
502 s++;
504 else
505 *d++ = *s++;
507 *d = 0;
508 return buffer;
512 /* Estimate the quality of the passphrase PW and return a value in the
513 range 0..100. */
514 static int
515 estimate_passphrase_quality (const char *pw)
517 int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
518 int length;
519 const char *s;
521 if (goodlength < 1)
522 return 0;
524 for (length = 0, s = pw; *s; s++)
525 if (!spacep (s))
526 length ++;
528 if (length > goodlength)
529 return 100;
530 return ((length*10) / goodlength)*10;
534 /* Handle the QUALITY inquiry. */
535 static int
536 inq_quality (void *opaque, const char *line)
538 assuan_context_t ctx = opaque;
539 char *pin;
540 int rc;
541 int percent;
542 char numbuf[20];
544 if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
546 line += 7;
547 while (*line == ' ')
548 line++;
550 pin = unescape_passphrase_string (line);
551 if (!pin)
552 rc = gpg_error_from_syserror ();
553 else
555 percent = estimate_passphrase_quality (pin);
556 if (check_passphrase_constraints (NULL, pin, 1))
557 percent = -percent;
558 snprintf (numbuf, sizeof numbuf, "%d", percent);
559 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
560 xfree (pin);
563 else
565 log_error ("unsupported inquiry `%s' from pinentry\n", line);
566 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
569 return rc;
573 /* Helper for agent_askpin and agent_get_passphrase. */
574 static int
575 setup_qualitybar (void)
577 int rc;
578 char line[ASSUAN_LINELENGTH];
579 char *tmpstr, *tmpstr2;
580 const char *tooltip;
582 /* TRANSLATORS: This string is displayed by Pinentry as the label
583 for the quality bar. */
584 tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
585 snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
586 line[DIM(line)-1] = 0;
587 xfree (tmpstr);
588 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
589 if (rc == 103 /*(Old assuan error code)*/
590 || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
591 ; /* Ignore Unknown Command from old Pinentry versions. */
592 else if (rc)
593 return rc;
595 tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
596 if (tmpstr2)
597 tooltip = tmpstr2;
598 else
600 /* TRANSLATORS: This string is a tooltip, shown by pinentry when
601 hovering over the quality bar. Please use an appropriate
602 string to describe what this is about. The length of the
603 tooltip is limited to about 900 characters. If you do not
604 translate this entry, a default english text (see source)
605 will be used. */
606 tooltip = _("pinentry.qualitybar.tooltip");
607 if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
608 tooltip = ("The quality of the text entered above.\n"
609 "Please ask your administrator for "
610 "details about the criteria.");
612 tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
613 xfree (tmpstr2);
614 snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %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 return 0;
629 /* Call the Entry and ask for the PIN. We do check for a valid PIN
630 number here and repeat it as long as we have invalid formed
631 numbers. */
633 agent_askpin (ctrl_t ctrl,
634 const char *desc_text, const char *prompt_text,
635 const char *initial_errtext,
636 struct pin_entry_info_s *pininfo)
638 int rc;
639 char line[ASSUAN_LINELENGTH];
640 struct entry_parm_s parm;
641 const char *errtext = NULL;
642 int is_pin = 0;
644 if (opt.batch)
645 return 0; /* fixme: we should return BAD PIN */
647 if (!pininfo || pininfo->max_length < 1)
648 return gpg_error (GPG_ERR_INV_VALUE);
649 if (!desc_text && pininfo->min_digits)
650 desc_text = _("Please enter your PIN, so that the secret key "
651 "can be unlocked for this session");
652 else if (!desc_text)
653 desc_text = _("Please enter your passphrase, so that the secret key "
654 "can be unlocked for this session");
656 if (prompt_text)
657 is_pin = !!strstr (prompt_text, "PIN");
658 else
659 is_pin = desc_text && strstr (desc_text, "PIN");
661 rc = start_pinentry (ctrl);
662 if (rc)
663 return rc;
665 snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
666 line[DIM(line)-1] = 0;
667 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
668 if (rc)
669 return unlock_pinentry (rc);
671 snprintf (line, DIM(line)-1, "SETPROMPT %s",
672 prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
673 line[DIM(line)-1] = 0;
674 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
675 if (rc)
676 return unlock_pinentry (rc);
678 /* If a passphrase quality indicator has been requested and a
679 minimum passphrase length has not been disabled, send the command
680 to the pinentry. */
681 if (pininfo->with_qualitybar && opt.min_passphrase_len )
683 rc = setup_qualitybar ();
684 if (rc)
685 return unlock_pinentry (rc);
688 if (initial_errtext)
690 snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
691 line[DIM(line)-1] = 0;
692 rc = assuan_transact (entry_ctx, line,
693 NULL, NULL, NULL, NULL, NULL, NULL);
694 if (rc)
695 return unlock_pinentry (rc);
698 for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
700 memset (&parm, 0, sizeof parm);
701 parm.size = pininfo->max_length;
702 *pininfo->pin = 0; /* Reset the PIN. */
703 parm.buffer = (unsigned char*)pininfo->pin;
705 if (errtext)
707 /* TRANLATORS: The string is appended to an error message in
708 the pinentry. The %s is the actual error message, the
709 two %d give the current and maximum number of tries. */
710 snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
711 errtext, pininfo->failed_tries+1, pininfo->max_tries);
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);
717 errtext = NULL;
720 rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
721 inq_quality, entry_ctx, NULL, NULL);
722 /* Most pinentries out in the wild return the old Assuan error code
723 for canceled which gets translated to an assuan Cancel error and
724 not to the code for a user cancel. Fix this here. */
725 if (rc && gpg_err_source (rc)
726 && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
727 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
729 if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
730 errtext = is_pin? _("PIN too long")
731 : _("Passphrase too long");
732 else if (rc)
733 return unlock_pinentry (rc);
735 if (!errtext && pininfo->min_digits)
737 /* do some basic checks on the entered PIN. */
738 if (!all_digitsp (pininfo->pin))
739 errtext = _("Invalid characters in PIN");
740 else if (pininfo->max_digits
741 && strlen (pininfo->pin) > pininfo->max_digits)
742 errtext = _("PIN too long");
743 else if (strlen (pininfo->pin) < pininfo->min_digits)
744 errtext = _("PIN too short");
747 if (!errtext && pininfo->check_cb)
749 /* More checks by utilizing the optional callback. */
750 pininfo->cb_errtext = NULL;
751 rc = pininfo->check_cb (pininfo);
752 if (rc == -1 && pininfo->cb_errtext)
753 errtext = pininfo->cb_errtext;
754 else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
755 || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
756 errtext = (is_pin? _("Bad PIN")
757 : _("Bad Passphrase"));
758 else if (rc)
759 return unlock_pinentry (rc);
762 if (!errtext)
763 return unlock_pinentry (0); /* okay, got a PIN or passphrase */
766 return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
767 : GPG_ERR_BAD_PASSPHRASE));
772 /* Ask for the passphrase using the supplied arguments. The returned
773 passphrase needs to be freed by the caller. */
774 int
775 agent_get_passphrase (ctrl_t ctrl,
776 char **retpass, const char *desc, const char *prompt,
777 const char *errtext, int with_qualitybar)
780 int rc;
781 char line[ASSUAN_LINELENGTH];
782 struct entry_parm_s parm;
784 *retpass = NULL;
785 if (opt.batch)
786 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
788 rc = start_pinentry (ctrl);
789 if (rc)
790 return rc;
792 if (!prompt)
793 prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
796 if (desc)
797 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
798 else
799 snprintf (line, DIM(line)-1, "RESET");
800 line[DIM(line)-1] = 0;
801 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
802 if (rc)
803 return unlock_pinentry (rc);
805 snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
806 line[DIM(line)-1] = 0;
807 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
808 if (rc)
809 return unlock_pinentry (rc);
811 if (with_qualitybar && opt.min_passphrase_len)
813 rc = setup_qualitybar ();
814 if (rc)
815 return unlock_pinentry (rc);
818 if (errtext)
820 snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
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);
827 memset (&parm, 0, sizeof parm);
828 parm.size = ASSUAN_LINELENGTH/2 - 5;
829 parm.buffer = gcry_malloc_secure (parm.size+10);
830 if (!parm.buffer)
831 return unlock_pinentry (out_of_core ());
833 assuan_begin_confidential (entry_ctx);
834 rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
835 inq_quality, entry_ctx, NULL, NULL);
836 /* Most pinentries out in the wild return the old Assuan error code
837 for canceled which gets translated to an assuan Cancel error and
838 not to the code for a user cancel. Fix this here. */
839 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
840 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
841 if (rc)
842 xfree (parm.buffer);
843 else
844 *retpass = parm.buffer;
845 return unlock_pinentry (rc);
850 /* Pop up the PIN-entry, display the text and the prompt and ask the
851 user to confirm this. We return 0 for success, ie. the user
852 confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
853 other error. */
854 int
855 agent_get_confirmation (ctrl_t ctrl,
856 const char *desc, const char *ok, const char *cancel)
858 int rc;
859 char line[ASSUAN_LINELENGTH];
861 rc = start_pinentry (ctrl);
862 if (rc)
863 return rc;
865 if (desc)
866 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
867 else
868 snprintf (line, DIM(line)-1, "RESET");
869 line[DIM(line)-1] = 0;
870 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
871 /* Most pinentries out in the wild return the old Assuan error code
872 for canceled which gets translated to an assuan Cancel error and
873 not to the code for a user cancel. Fix this here. */
874 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
875 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
877 if (rc)
878 return unlock_pinentry (rc);
880 if (ok)
882 snprintf (line, DIM(line)-1, "SETOK %s", ok);
883 line[DIM(line)-1] = 0;
884 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
885 if (rc)
886 return unlock_pinentry (rc);
888 if (cancel)
890 snprintf (line, DIM(line)-1, "SETNOTOK %s", cancel);
891 line[DIM(line)-1] = 0;
892 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
893 if (gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
895 snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel);
896 line[DIM(line)-1] = 0;
897 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
899 if (rc)
900 return unlock_pinentry (rc);
903 rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
904 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
905 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
907 return unlock_pinentry (rc);
912 /* Pop up the PINentry, display the text DESC and a button with the
913 text OK_BTN (which may be NULL to use the default of "OK") and waut
914 for the user to hit this button. The return value is not
915 relevant. */
916 int
917 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
919 int rc;
920 char line[ASSUAN_LINELENGTH];
922 rc = start_pinentry (ctrl);
923 if (rc)
924 return rc;
926 if (desc)
927 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
928 else
929 snprintf (line, DIM(line)-1, "RESET");
930 line[DIM(line)-1] = 0;
931 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
932 /* Most pinentries out in the wild return the old Assuan error code
933 for canceled which gets translated to an assuan Cancel error and
934 not to the code for a user cancel. Fix this here. */
935 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
936 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
938 if (rc)
939 return unlock_pinentry (rc);
941 if (ok_btn)
943 snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
944 line[DIM(line)-1] = 0;
945 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
946 NULL, NULL, NULL);
947 if (rc)
948 return unlock_pinentry (rc);
951 rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
952 NULL, NULL, NULL);
953 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
954 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
956 return unlock_pinentry (rc);
960 /* The thread running the popup message. */
961 static void *
962 popup_message_thread (void *arg)
964 (void)arg;
966 /* We use the --one-button hack instead of the MESSAGE command to
967 allow the use of old Pinentries. Those old Pinentries will then
968 show an additional Cancel button but that is mostly a visual
969 annoyance. */
970 assuan_transact (entry_ctx, "CONFIRM --one-button",
971 NULL, NULL, NULL, NULL, NULL, NULL);
972 popup_finished = 1;
973 return NULL;
977 /* Pop up a message window similar to the confirm one but keep it open
978 until agent_popup_message_stop has been called. It is crucial for
979 the caller to make sure that the stop function gets called as soon
980 as the message is not anymore required because the message is
981 system modal and all other attempts to use the pinentry will fail
982 (after a timeout). */
983 int
984 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
986 int rc;
987 char line[ASSUAN_LINELENGTH];
988 pth_attr_t tattr;
990 rc = start_pinentry (ctrl);
991 if (rc)
992 return rc;
994 if (desc)
995 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
996 else
997 snprintf (line, DIM(line)-1, "RESET");
998 line[DIM(line)-1] = 0;
999 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1000 if (rc)
1001 return unlock_pinentry (rc);
1003 if (ok_btn)
1005 snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
1006 line[DIM(line)-1] = 0;
1007 rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
1008 if (rc)
1009 return unlock_pinentry (rc);
1012 tattr = pth_attr_new();
1013 pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
1014 pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
1015 pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
1017 popup_finished = 0;
1018 popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
1019 if (!popup_tid)
1021 rc = gpg_error_from_syserror ();
1022 log_error ("error spawning popup message handler: %s\n",
1023 strerror (errno) );
1024 pth_attr_destroy (tattr);
1025 return unlock_pinentry (rc);
1027 pth_attr_destroy (tattr);
1029 return 0;
1032 /* Close a popup window. */
1033 void
1034 agent_popup_message_stop (ctrl_t ctrl)
1036 int rc;
1037 pid_t pid;
1039 (void)ctrl;
1041 if (!popup_tid || !entry_ctx)
1043 log_debug ("agent_popup_message_stop called with no active popup\n");
1044 return;
1047 pid = assuan_get_pid (entry_ctx);
1048 if (pid == (pid_t)(-1))
1049 ; /* No pid available can't send a kill. */
1050 else if (popup_finished)
1051 ; /* Already finished and ready for joining. */
1052 #ifdef HAVE_W32_SYSTEM
1053 /* Older versions of assuan set PID to 0 on Windows to indicate an
1054 invalid value. */
1055 else if (pid != (pid_t) INVALID_HANDLE_VALUE
1056 && pid != 0)
1058 HANDLE process = (HANDLE) pid;
1060 /* Arbitrary error code. */
1061 TerminateProcess (process, 1);
1063 #else
1064 else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1065 { /* The daemon already died. No need to send a kill. However
1066 because we already waited for the process, we need to tell
1067 assuan that it should not wait again (done by
1068 unlock_pinentry). */
1069 if (rc == pid)
1070 assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1072 else if (pid > 0)
1073 kill (pid, SIGKILL); /* Need to use SIGKILL due to bad
1074 interaction of SIGINT with Pth. */
1075 #endif
1077 /* Now wait for the thread to terminate. */
1078 rc = pth_join (popup_tid, NULL);
1079 if (!rc)
1080 log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1081 strerror (errno));
1082 popup_tid = NULL;
1083 entry_owner = NULL;
1085 /* Now we can close the connection. */
1086 unlock_pinentry (0);