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/>.
29 #ifndef HAVE_W32_SYSTEM
30 # include <sys/wait.h>
31 # include <sys/types.h>
41 #ifdef _POSIX_OPEN_MAX
42 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
44 #define MAX_OPEN_FDS 20
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
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
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
71 static int popup_finished
;
75 /* Data to be passed to our callbacks, */
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. */
91 initialize_module_call_pinentry (void)
93 static int initialized
;
97 if (pth_mutex_init (&entry_lock
))
105 dump_mutex_state (pth_mutex_t
*m
)
109 log_printf ("unknown under W32");
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");
116 log_printf ("locked tid=0x%lx count=%lu", (long)m
->mx_owner
, m
->mx_count
);
121 /* This function may be called to print infromation pertaining to the
122 current state of this module to the log. */
124 agent_query_dump_state (void)
126 log_info ("agent_query_dump_state: entry_lock=");
127 dump_mutex_state (&entry_lock
);
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. */
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. */
150 unlock_pinentry (int rc
)
152 assuan_context_t ctx
= entry_ctx
;
155 if (!pth_mutex_release (&entry_lock
))
157 log_error ("failed to release the entry lock\n");
159 rc
= gpg_error (GPG_ERR_INTERNAL
);
161 assuan_disconnect (ctx
);
166 /* To make sure we leave no secrets in our image after forking of the
167 pinentry, we use this callback. */
169 atfork_cb (void *opaque
, int where
)
171 ctrl_t ctrl
= opaque
;
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
187 || !strcmp (name
, "XAUTHORITY")
188 || !strcmp (name
, "PINENTRY_USER_DATA"))
190 value
= session_env_getenv (ctrl
->session_env
, name
);
192 setenv (name
, value
, 1);
200 getinfo_pid_cb (void *opaque
, const void *buffer
, size_t length
)
202 unsigned long *pid
= opaque
;
205 /* There is only the pid in the server's response. */
206 if (length
>= sizeof pidbuf
)
207 length
= sizeof pidbuf
-1;
210 strncpy (pidbuf
, buffer
, length
);
212 *pid
= strtoul (pidbuf
, NULL
, 10);
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.
222 start_pinentry (ctrl_t ctrl
)
226 assuan_context_t ctx
;
228 int no_close_list
[3];
232 unsigned long pinentry_pid
;
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
);
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"),
247 pth_event_free (evt
, PTH_FREE_THIS
);
255 log_info ("starting a new PIN Entry\n");
257 #ifdef HAVE_W32_SYSTEM
263 #ifndef HAVE_W32_SYSTEM
264 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
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
);
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
;
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. */
288 argv
[0] = opt
.pinentry_program
;
293 if (!opt
.keep_display
294 && (value
= session_env_getenv (ctrl
->session_env
, "DISPLAY")))
296 argv
[1] = "--display";
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
316 rc
= assuan_pipe_connect_ext (&ctx
, opt
.pinentry_program
, argv
,
317 no_close_list
, atfork_cb
, ctrl
, 128);
320 log_error ("can't connect to the PIN entry module: %s\n",
322 return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY
));
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
);
333 return unlock_pinentry (rc
);
335 value
= session_env_getenv (ctrl
->session_env
, "GPG_TTY");
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
,
345 return unlock_pinentry (rc
);
347 value
= session_env_getenv (ctrl
->session_env
, "TERM");
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
,
356 return unlock_pinentry (rc
);
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
,
366 return unlock_pinentry (rc
);
368 if (ctrl
->lc_messages
)
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
,
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"))
387 tmpstr
= get_agent_socket_name ();
392 if (asprintf (&optstr
, "OPTION touch-file=%s", tmpstr
) < 0 )
396 assuan_transact (entry_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
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
);
412 log_info ("You may want to update to a newer pinentry\n");
415 else if (!rc
&& (pid_t
)pinentry_pid
== (pid_t
)(-1))
416 log_error ("pinentry did not return a PID\n");
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
));
429 /* Returns True is the pinentry is currently active. If WAITSECONDS is
430 greater than zero the function will wait for this many seconds
433 pinentry_active_p (ctrl_t ctrl
, int waitseconds
)
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
);
448 rc
= gpg_error (GPG_ERR_INTERNAL
);
449 pth_event_free (evt
, PTH_FREE_THIS
);
452 pth_event_free (evt
, PTH_FREE_THIS
);
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__
);
467 getpin_cb (void *opaque
, const void *buffer
, size_t length
)
469 struct entry_parm_s
*parm
= opaque
;
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;
488 all_digitsp( const char *s
)
490 for (; *s
&& *s
>= '0' && *s
<= '9'; 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. */
502 unescape_passphrase_string (const unsigned char *s
)
506 buffer
= d
= xtrymalloc_secure (strlen ((const char*)s
)+1);
509 while (*s
&& !spacep (s
))
511 if (*s
== '%' && s
[1] && s
[2])
533 /* Estimate the quality of the passphrase PW and return a value in the
536 estimate_passphrase_quality (const char *pw
)
538 int goodlength
= opt
.min_passphrase_len
+ opt
.min_passphrase_len
/3;
545 for (length
= 0, s
= pw
; *s
; s
++)
549 if (length
> goodlength
)
551 return ((length
*10) / goodlength
)*10;
555 /* Handle the QUALITY inquiry. */
557 inq_quality (void *opaque
, const char *line
)
559 assuan_context_t ctx
= opaque
;
565 if (!strncmp (line
, "QUALITY", 7) && (line
[7] == ' ' || !line
[7]))
571 pin
= unescape_passphrase_string (line
);
573 rc
= gpg_error_from_syserror ();
576 percent
= estimate_passphrase_quality (pin
);
577 if (check_passphrase_constraints (NULL
, pin
, 1))
579 snprintf (numbuf
, sizeof numbuf
, "%d", percent
);
580 rc
= assuan_send_data (ctx
, numbuf
, strlen (numbuf
));
586 log_error ("unsupported inquiry `%s' from pinentry\n", line
);
587 rc
= gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE
);
594 /* Helper for agent_askpin and agent_get_passphrase. */
596 setup_qualitybar (void)
599 char line
[ASSUAN_LINELENGTH
];
600 char *tmpstr
, *tmpstr2
;
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;
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. */
616 tmpstr2
= gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
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)
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");
635 snprintf (line
, DIM(line
)-1, "SETQUALITYBAR_TT %s", tmpstr
? tmpstr
:"");
636 line
[DIM(line
)-1] = 0;
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. */
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
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
)
660 char line
[ASSUAN_LINELENGTH
];
661 struct entry_parm_s parm
;
662 const char *errtext
= NULL
;
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");
674 desc_text
= _("Please enter your passphrase, so that the secret key "
675 "can be unlocked for this session");
678 is_pin
= !!strstr (prompt_text
, "PIN");
680 is_pin
= desc_text
&& strstr (desc_text
, "PIN");
682 rc
= start_pinentry (ctrl
);
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
);
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
);
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
702 if (pininfo
->with_qualitybar
&& opt
.min_passphrase_len
)
704 rc
= setup_qualitybar ();
706 return unlock_pinentry (rc
);
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
);
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
;
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
);
737 return unlock_pinentry (rc
);
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");
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"));
780 return unlock_pinentry (rc
);
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. */
796 agent_get_passphrase (ctrl_t ctrl
,
797 char **retpass
, const char *desc
, const char *prompt
,
798 const char *errtext
, int with_qualitybar
)
802 char line
[ASSUAN_LINELENGTH
];
803 struct entry_parm_s parm
;
807 return gpg_error (GPG_ERR_BAD_PASSPHRASE
);
809 rc
= start_pinentry (ctrl
);
814 prompt
= desc
&& strstr (desc
, "PIN")? "PIN": _("Passphrase");
818 snprintf (line
, DIM(line
)-1, "SETDESC %s", desc
);
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
);
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
);
830 return unlock_pinentry (rc
);
832 if (with_qualitybar
&& opt
.min_passphrase_len
)
834 rc
= setup_qualitybar ();
836 return unlock_pinentry (rc
);
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
);
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);
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
);
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. */
879 agent_get_confirmation (ctrl_t ctrl
,
880 const char *desc
, const char *ok
,
881 const char *notok
, int with_cancel
)
884 char line
[ASSUAN_LINELENGTH
];
886 rc
= start_pinentry (ctrl
);
891 snprintf (line
, DIM(line
)-1, "SETDESC %s", desc
);
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
);
903 return unlock_pinentry (rc
);
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
);
912 return unlock_pinentry (rc
);
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. */
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
);
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
);
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
955 agent_show_message (ctrl_t ctrl
, const char *desc
, const char *ok_btn
)
958 char line
[ASSUAN_LINELENGTH
];
960 rc
= start_pinentry (ctrl
);
965 snprintf (line
, DIM(line
)-1, "SETDESC %s", desc
);
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
);
977 return unlock_pinentry (rc
);
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
,
986 return unlock_pinentry (rc
);
989 rc
= assuan_transact (entry_ctx
, "CONFIRM --one-button", 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. */
1000 popup_message_thread (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
1008 assuan_transact (entry_ctx
, "CONFIRM --one-button",
1009 NULL
, NULL
, NULL
, NULL
, NULL
, 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). */
1022 agent_popup_message_start (ctrl_t ctrl
, const char *desc
, const char *ok_btn
)
1025 char line
[ASSUAN_LINELENGTH
];
1028 rc
= start_pinentry (ctrl
);
1033 snprintf (line
, DIM(line
)-1, "SETDESC %s", desc
);
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
);
1039 return unlock_pinentry (rc
);
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
);
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");
1056 popup_tid
= pth_spawn (tattr
, popup_message_thread
, NULL
);
1059 rc
= gpg_error_from_syserror ();
1060 log_error ("error spawning popup message handler: %s\n",
1062 pth_attr_destroy (tattr
);
1063 return unlock_pinentry (rc
);
1065 pth_attr_destroy (tattr
);
1070 /* Close a popup window. */
1072 agent_popup_message_stop (ctrl_t ctrl
)
1079 if (!popup_tid
|| !entry_ctx
)
1081 log_debug ("agent_popup_message_stop called with no active popup\n");
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
1093 else if (pid
!= (pid_t
) INVALID_HANDLE_VALUE
1096 HANDLE process
= (HANDLE
) pid
;
1098 /* Arbitrary error code. */
1099 TerminateProcess (process
, 1);
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). */
1108 assuan_set_flag (entry_ctx
, ASSUAN_NO_WAITPID
, 1);
1111 kill (pid
, SIGKILL
); /* Need to use SIGKILL due to bad
1112 interaction of SIGINT with Pth. */
1115 /* Now wait for the thread to terminate. */
1116 rc
= pth_join (popup_tid
, NULL
);
1118 log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1123 /* Now we can close the connection. */
1124 unlock_pinentry (0);