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
)
108 log_printf ("unknown under W32");
110 if (!(m
->mx_state
& PTH_MUTEX_INITIALIZED
))
111 log_printf ("not_initialized");
112 else if (!(m
->mx_state
& PTH_MUTEX_LOCKED
))
113 log_printf ("not_locked");
115 log_printf ("locked tid=0x%lx count=%lu", (long)m
->mx_owner
, m
->mx_count
);
120 /* This function may be called to print infromation pertaining to the
121 current state of this module to the log. */
123 agent_query_dump_state (void)
125 log_info ("agent_query_dump_state: entry_lock=");
126 dump_mutex_state (&entry_lock
);
128 log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
129 entry_ctx
, (long)assuan_get_pid (entry_ctx
), popup_tid
);
132 /* Called to make sure that a popup window owned by the current
133 connection gets closed. */
135 agent_reset_query (ctrl_t ctrl
)
137 if (entry_ctx
&& popup_tid
&& entry_owner
== ctrl
)
139 agent_popup_message_stop (ctrl
);
144 /* Unlock the pinentry so that another thread can start one and
145 disconnect that pinentry - we do this after the unlock so that a
146 stalled pinentry does not block other threads. Fixme: We should
147 have a timeout in Assuan for the disconnect operation. */
149 unlock_pinentry (int rc
)
151 assuan_context_t ctx
= entry_ctx
;
154 if (!pth_mutex_release (&entry_lock
))
156 log_error ("failed to release the entry lock\n");
158 rc
= gpg_error (GPG_ERR_INTERNAL
);
160 assuan_disconnect (ctx
);
165 /* To make sure we leave no secrets in our image after forking of the
166 pinentry, we use this callback. */
168 atfork_cb (void *opaque
, int where
)
170 ctrl_t ctrl
= opaque
;
174 gcry_control (GCRYCTL_TERM_SECMEM
);
175 if (ctrl
->xauthority
)
176 setenv ("XAUTHORITY", ctrl
->xauthority
, 1);
177 if (ctrl
->pinentry_user_data
)
178 setenv ("PINENTRY_USER_DATA", ctrl
->pinentry_user_data
, 1 );
183 getinfo_pid_cb (void *opaque
, const void *buffer
, size_t length
)
185 unsigned long *pid
= opaque
;
188 /* There is only the pid in the server's response. */
189 if (length
>= sizeof pidbuf
)
190 length
= sizeof pidbuf
-1;
193 strncpy (pidbuf
, buffer
, length
);
195 *pid
= strtoul (pidbuf
, NULL
, 10);
200 /* Fork off the pin entry if this has not already been done. Note,
201 that this function must always be used to aquire the lock for the
202 pinentry - we will serialize _all_ pinentry calls.
205 start_pinentry (ctrl_t ctrl
)
209 assuan_context_t ctx
;
211 int no_close_list
[3];
215 unsigned long pinentry_pid
;
217 evt
= pth_event (PTH_EVENT_TIME
, pth_timeout (LOCK_TIMEOUT
, 0));
218 if (!pth_mutex_acquire (&entry_lock
, 0, evt
))
220 if (pth_event_occurred (evt
))
221 rc
= gpg_error (GPG_ERR_TIMEOUT
);
223 rc
= gpg_error (GPG_ERR_INTERNAL
);
224 pth_event_free (evt
, PTH_FREE_THIS
);
225 log_error (_("failed to acquire the pinentry lock: %s\n"),
229 pth_event_free (evt
, PTH_FREE_THIS
);
237 log_info ("starting a new PIN Entry\n");
239 #ifdef HAVE_W32_SYSTEM
245 #ifndef HAVE_W32_SYSTEM
246 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
248 log_error ("error flushing pending output: %s\n", strerror (errno
));
249 /* At least Windows XP fails here with EBADF. According to docs
250 and Wine an fflush(NULL) is the same as _flushall. However
251 the Wime implementaion does not flush stdin,stdout and stderr
252 - see above. Lets try to ignore the error. */
253 #ifndef HAVE_W32_SYSTEM
254 return unlock_pinentry (tmperr
);
258 if (!opt
.pinentry_program
|| !*opt
.pinentry_program
)
259 opt
.pinentry_program
= gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY
);
260 pgmname
= opt
.pinentry_program
;
261 if ( !(pgmname
= strrchr (opt
.pinentry_program
, '/')))
262 pgmname
= opt
.pinentry_program
;
266 /* OS X needs the entire file name in argv[0], so that it can locate
267 the resource bundle. For other systems we stick to the usual
268 convention of supplying only the name of the program. */
270 argv
[0] = opt
.pinentry_program
;
275 if (ctrl
->display
&& !opt
.keep_display
)
277 argv
[1] = "--display";
278 argv
[2] = ctrl
->display
;
285 if (!opt
.running_detached
)
287 if (log_get_fd () != -1)
288 no_close_list
[i
++] = log_get_fd ();
289 no_close_list
[i
++] = fileno (stderr
);
291 no_close_list
[i
] = -1;
293 /* Connect to the pinentry and perform initial handshaking. Note
294 that atfork is used to change the environment for pinentry. We
295 start the server in detached mode to suppress the console window
297 rc
= assuan_pipe_connect_ext (&ctx
, opt
.pinentry_program
, argv
,
298 no_close_list
, atfork_cb
, ctrl
, 128);
301 log_error ("can't connect to the PIN entry module: %s\n",
303 return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY
));
308 log_debug ("connection to PIN entry established\n");
310 rc
= assuan_transact (entry_ctx
,
311 opt
.no_grab
? "OPTION no-grab":"OPTION grab",
312 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
314 return unlock_pinentry (rc
);
318 if (asprintf (&optstr
, "OPTION ttyname=%s", ctrl
->ttyname
) < 0 )
319 return unlock_pinentry (out_of_core ());
320 rc
= assuan_transact (entry_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
324 return unlock_pinentry (rc
);
329 if (asprintf (&optstr
, "OPTION ttytype=%s", ctrl
->ttytype
) < 0 )
330 return unlock_pinentry (out_of_core ());
331 rc
= assuan_transact (entry_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
334 return unlock_pinentry (rc
);
339 if (asprintf (&optstr
, "OPTION lc-ctype=%s", ctrl
->lc_ctype
) < 0 )
340 return unlock_pinentry (out_of_core ());
341 rc
= assuan_transact (entry_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
344 return unlock_pinentry (rc
);
346 if (ctrl
->lc_messages
)
349 if (asprintf (&optstr
, "OPTION lc-messages=%s", ctrl
->lc_messages
) < 0 )
350 return unlock_pinentry (out_of_core ());
351 rc
= assuan_transact (entry_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
354 return unlock_pinentry (rc
);
358 /* Tell the pinentry the name of a file it shall touch after having
359 messed with the tty. This is optional and only supported by
360 newer pinentries and thus we do no error checking. */
361 tmpstr
= opt
.pinentry_touch_file
;
362 if (tmpstr
&& !strcmp (tmpstr
, "/dev/null"))
365 tmpstr
= get_agent_socket_name ();
370 if (asprintf (&optstr
, "OPTION touch-file=%s", tmpstr
) < 0 )
374 assuan_transact (entry_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
381 /* Now ask the Pinentry for its PID. If the Pinentry is new enough
382 it will send the pid back and we will use an inquire to notify
383 our client. The client may answer the inquiry either with END or
384 with CAN to cancel the pinentry. */
385 rc
= assuan_transact (entry_ctx
, "GETINFO pid",
386 getinfo_pid_cb
, &pinentry_pid
,
387 NULL
, NULL
, NULL
, NULL
);
390 log_info ("You may want to update to a newer pinentry\n");
393 else if (!rc
&& (pid_t
)pinentry_pid
== (pid_t
)(-1))
394 log_error ("pinentry did not return a PID\n");
397 rc
= agent_inq_pinentry_launched (ctrl
, pinentry_pid
);
398 if (gpg_err_code (rc
) == GPG_ERR_CANCELED
)
399 return unlock_pinentry (gpg_error (GPG_ERR_CANCELED
));
407 /* Returns True is the pinentry is currently active. If WAITSECONDS is
408 greater than zero the function will wait for this many seconds
411 pinentry_active_p (ctrl_t ctrl
, int waitseconds
)
418 evt
= pth_event (PTH_EVENT_TIME
, pth_timeout (waitseconds
, 0));
419 if (!pth_mutex_acquire (&entry_lock
, 0, evt
))
421 if (pth_event_occurred (evt
))
422 rc
= gpg_error (GPG_ERR_TIMEOUT
);
424 rc
= gpg_error (GPG_ERR_INTERNAL
);
425 pth_event_free (evt
, PTH_FREE_THIS
);
428 pth_event_free (evt
, PTH_FREE_THIS
);
432 if (!pth_mutex_acquire (&entry_lock
, 1, NULL
))
433 return gpg_error (GPG_ERR_LOCKED
);
436 if (!pth_mutex_release (&entry_lock
))
437 log_error ("failed to release the entry lock at %d\n", __LINE__
);
443 getpin_cb (void *opaque
, const void *buffer
, size_t length
)
445 struct entry_parm_s
*parm
= opaque
;
450 /* we expect the pin to fit on one line */
451 if (parm
->lines
|| length
>= parm
->size
)
452 return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA
);
454 /* fixme: we should make sure that the assuan buffer is allocated in
455 secure memory or read the response byte by byte */
456 memcpy (parm
->buffer
, buffer
, length
);
457 parm
->buffer
[length
] = 0;
464 all_digitsp( const char *s
)
466 for (; *s
&& *s
>= '0' && *s
<= '9'; s
++)
472 /* Return a new malloced string by unescaping the string S. Escaping
473 is percent escaping and '+'/space mapping. A binary Nul will
474 silently be replaced by a 0xFF. Function returns NULL to indicate
475 an out of memory status. PArsing stops at the end of the string or
476 a white space character. */
478 unescape_passphrase_string (const unsigned char *s
)
482 buffer
= d
= xtrymalloc_secure (strlen ((const char*)s
)+1);
485 while (*s
&& !spacep (s
))
487 if (*s
== '%' && s
[1] && s
[2])
509 /* Estimate the quality of the passphrase PW and return a value in the
512 estimate_passphrase_quality (const char *pw
)
514 int goodlength
= opt
.min_passphrase_len
+ opt
.min_passphrase_len
/3;
521 for (length
= 0, s
= pw
; *s
; s
++)
525 if (length
> goodlength
)
527 return ((length
*10) / goodlength
)*10;
531 /* Handle the QUALITY inquiry. */
533 inq_quality (void *opaque
, const char *line
)
535 assuan_context_t ctx
= opaque
;
541 if (!strncmp (line
, "QUALITY", 7) && (line
[7] == ' ' || !line
[7]))
547 pin
= unescape_passphrase_string (line
);
549 rc
= gpg_error_from_syserror ();
552 percent
= estimate_passphrase_quality (pin
);
553 if (check_passphrase_constraints (NULL
, pin
, 1))
555 snprintf (numbuf
, sizeof numbuf
, "%d", percent
);
556 rc
= assuan_send_data (ctx
, numbuf
, strlen (numbuf
));
562 log_error ("unsupported inquiry `%s' from pinentry\n", line
);
563 rc
= gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE
);
573 /* Call the Entry and ask for the PIN. We do check for a valid PIN
574 number here and repeat it as long as we have invalid formed
577 agent_askpin (ctrl_t ctrl
,
578 const char *desc_text
, const char *prompt_text
,
579 const char *initial_errtext
,
580 struct pin_entry_info_s
*pininfo
)
583 char line
[ASSUAN_LINELENGTH
];
584 struct entry_parm_s parm
;
585 const char *errtext
= NULL
;
589 return 0; /* fixme: we should return BAD PIN */
591 if (!pininfo
|| pininfo
->max_length
< 1)
592 return gpg_error (GPG_ERR_INV_VALUE
);
593 if (!desc_text
&& pininfo
->min_digits
)
594 desc_text
= _("Please enter your PIN, so that the secret key "
595 "can be unlocked for this session");
597 desc_text
= _("Please enter your passphrase, so that the secret key "
598 "can be unlocked for this session");
601 is_pin
= !!strstr (prompt_text
, "PIN");
603 is_pin
= desc_text
&& strstr (desc_text
, "PIN");
605 rc
= start_pinentry (ctrl
);
609 snprintf (line
, DIM(line
)-1, "SETDESC %s", desc_text
);
610 line
[DIM(line
)-1] = 0;
611 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
613 return unlock_pinentry (rc
);
615 snprintf (line
, DIM(line
)-1, "SETPROMPT %s",
616 prompt_text
? prompt_text
: is_pin
? "PIN:" : "Passphrase:");
617 line
[DIM(line
)-1] = 0;
618 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
620 return unlock_pinentry (rc
);
622 /* If a passphrase quality indicator has been requested and a
623 minimum passphrase length has not been disabled, send the command
625 if (pininfo
->with_qualitybar
&& opt
.min_passphrase_len
)
627 char *tmpstr
, *tmpstr2
;
630 /* TRANSLATORS: This string is displayed by pinentry as the
631 label for the quality bar. */
632 tmpstr
= try_percent_escape (_("Quality:"), "\t\r\n\f\v");
633 snprintf (line
, DIM(line
)-1, "SETQUALITYBAR %s", tmpstr
? tmpstr
:"");
634 line
[DIM(line
)-1] = 0;
636 rc
= assuan_transact (entry_ctx
, line
,
637 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
638 if (rc
== 103 /*(Old assuan error code)*/
639 || gpg_err_code (rc
) == GPG_ERR_ASS_UNKNOWN_CMD
)
640 ; /* Ignore Unknown Command from old pinentry versions. */
642 return unlock_pinentry (rc
);
644 tmpstr2
= gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
649 /* TRANSLATORS: This string is a tooltip, shown by pinentry
650 when hovering over the quality bar. Please use an
651 appropriate string to describe what this is about. The
652 length of the tooltip is limited to about 900 characters.
653 If you do not translate this entry, a default english
654 text (see source) will be used. */
655 tooltip
= _("pinentry.qualitybar.tooltip");
656 if (!strcmp ("pinentry.qualitybar.tooltip", tooltip
))
657 tooltip
= ("The quality of the text entered above.\n"
658 "Please ask your administrator for "
659 "details about the criteria.");
661 tmpstr
= try_percent_escape (tooltip
, "\t\r\n\f\v");
663 snprintf (line
, DIM(line
)-1, "SETQUALITYBAR_TT %s", tmpstr
? tmpstr
:"");
664 line
[DIM(line
)-1] = 0;
666 rc
= assuan_transact (entry_ctx
, line
,
667 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
668 if (rc
== 103 /*(Old assuan error code)*/
669 || gpg_err_code (rc
) == GPG_ERR_ASS_UNKNOWN_CMD
)
670 ; /* Ignore Unknown Command from old pinentry versions. */
672 return unlock_pinentry (rc
);
677 snprintf (line
, DIM(line
)-1, "SETERROR %s", initial_errtext
);
678 line
[DIM(line
)-1] = 0;
679 rc
= assuan_transact (entry_ctx
, line
,
680 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
682 return unlock_pinentry (rc
);
685 for (;pininfo
->failed_tries
< pininfo
->max_tries
; pininfo
->failed_tries
++)
687 memset (&parm
, 0, sizeof parm
);
688 parm
.size
= pininfo
->max_length
;
689 *pininfo
->pin
= 0; /* Reset the PIN. */
690 parm
.buffer
= (unsigned char*)pininfo
->pin
;
694 /* TRANLATORS: The string is appended to an error message in
695 the pinentry. The %s is the actual error message, the
696 two %d give the current and maximum number of tries. */
697 snprintf (line
, DIM(line
)-1, _("SETERROR %s (try %d of %d)"),
698 errtext
, pininfo
->failed_tries
+1, pininfo
->max_tries
);
699 line
[DIM(line
)-1] = 0;
700 rc
= assuan_transact (entry_ctx
, line
,
701 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
703 return unlock_pinentry (rc
);
707 rc
= assuan_transact (entry_ctx
, "GETPIN", getpin_cb
, &parm
,
708 inq_quality
, entry_ctx
, NULL
, NULL
);
709 /* Most pinentries out in the wild return the old Assuan error code
710 for canceled which gets translated to an assuan Cancel error and
711 not to the code for a user cancel. Fix this here. */
712 if (rc
&& gpg_err_source (rc
)
713 && gpg_err_code (rc
) == GPG_ERR_ASS_CANCELED
)
714 rc
= gpg_err_make (gpg_err_source (rc
), GPG_ERR_CANCELED
);
716 if (gpg_err_code (rc
) == GPG_ERR_ASS_TOO_MUCH_DATA
)
717 errtext
= is_pin
? _("PIN too long")
718 : _("Passphrase too long");
720 return unlock_pinentry (rc
);
722 if (!errtext
&& pininfo
->min_digits
)
724 /* do some basic checks on the entered PIN. */
725 if (!all_digitsp (pininfo
->pin
))
726 errtext
= _("Invalid characters in PIN");
727 else if (pininfo
->max_digits
728 && strlen (pininfo
->pin
) > pininfo
->max_digits
)
729 errtext
= _("PIN too long");
730 else if (strlen (pininfo
->pin
) < pininfo
->min_digits
)
731 errtext
= _("PIN too short");
734 if (!errtext
&& pininfo
->check_cb
)
736 /* More checks by utilizing the optional callback. */
737 pininfo
->cb_errtext
= NULL
;
738 rc
= pininfo
->check_cb (pininfo
);
739 if (rc
== -1 && pininfo
->cb_errtext
)
740 errtext
= pininfo
->cb_errtext
;
741 else if (gpg_err_code (rc
) == GPG_ERR_BAD_PASSPHRASE
742 || gpg_err_code (rc
) == GPG_ERR_BAD_PIN
)
743 errtext
= (is_pin
? _("Bad PIN")
744 : _("Bad Passphrase"));
746 return unlock_pinentry (rc
);
750 return unlock_pinentry (0); /* okay, got a PIN or passphrase */
753 return unlock_pinentry (gpg_error (pininfo
->min_digits
? GPG_ERR_BAD_PIN
754 : GPG_ERR_BAD_PASSPHRASE
));
759 /* Ask for the passphrase using the supplied arguments. The returned
760 passphrase needs to be freed by the caller. */
762 agent_get_passphrase (ctrl_t ctrl
,
763 char **retpass
, const char *desc
, const char *prompt
,
768 char line
[ASSUAN_LINELENGTH
];
769 struct entry_parm_s parm
;
773 return gpg_error (GPG_ERR_BAD_PASSPHRASE
);
775 rc
= start_pinentry (ctrl
);
780 prompt
= desc
&& strstr (desc
, "PIN")? "PIN": _("Passphrase");
784 snprintf (line
, DIM(line
)-1, "SETDESC %s", desc
);
786 snprintf (line
, DIM(line
)-1, "RESET");
787 line
[DIM(line
)-1] = 0;
788 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
790 return unlock_pinentry (rc
);
792 snprintf (line
, DIM(line
)-1, "SETPROMPT %s", prompt
);
793 line
[DIM(line
)-1] = 0;
794 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
796 return unlock_pinentry (rc
);
800 snprintf (line
, DIM(line
)-1, "SETERROR %s", errtext
);
801 line
[DIM(line
)-1] = 0;
802 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
804 return unlock_pinentry (rc
);
807 memset (&parm
, 0, sizeof parm
);
808 parm
.size
= ASSUAN_LINELENGTH
/2 - 5;
809 parm
.buffer
= gcry_malloc_secure (parm
.size
+10);
811 return unlock_pinentry (out_of_core ());
813 assuan_begin_confidential (entry_ctx
);
814 rc
= assuan_transact (entry_ctx
, "GETPIN", getpin_cb
, &parm
,
815 NULL
, NULL
, NULL
, NULL
);
816 /* Most pinentries out in the wild return the old Assuan error code
817 for canceled which gets translated to an assuan Cancel error and
818 not to the code for a user cancel. Fix this here. */
819 if (rc
&& gpg_err_source (rc
) && gpg_err_code (rc
) == GPG_ERR_ASS_CANCELED
)
820 rc
= gpg_err_make (gpg_err_source (rc
), GPG_ERR_CANCELED
);
824 *retpass
= parm
.buffer
;
825 return unlock_pinentry (rc
);
830 /* Pop up the PIN-entry, display the text and the prompt and ask the
831 user to confirm this. We return 0 for success, ie. the user
832 confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
835 agent_get_confirmation (ctrl_t ctrl
,
836 const char *desc
, const char *ok
, const char *cancel
)
839 char line
[ASSUAN_LINELENGTH
];
841 rc
= start_pinentry (ctrl
);
846 snprintf (line
, DIM(line
)-1, "SETDESC %s", desc
);
848 snprintf (line
, DIM(line
)-1, "RESET");
849 line
[DIM(line
)-1] = 0;
850 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
851 /* Most pinentries out in the wild return the old Assuan error code
852 for canceled which gets translated to an assuan Cancel error and
853 not to the code for a user cancel. Fix this here. */
854 if (rc
&& gpg_err_source (rc
) && gpg_err_code (rc
) == GPG_ERR_ASS_CANCELED
)
855 rc
= gpg_err_make (gpg_err_source (rc
), GPG_ERR_CANCELED
);
858 return unlock_pinentry (rc
);
862 snprintf (line
, DIM(line
)-1, "SETOK %s", ok
);
863 line
[DIM(line
)-1] = 0;
864 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
866 return unlock_pinentry (rc
);
870 snprintf (line
, DIM(line
)-1, "SETCANCEL %s", cancel
);
871 line
[DIM(line
)-1] = 0;
872 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
874 return unlock_pinentry (rc
);
877 rc
= assuan_transact (entry_ctx
, "CONFIRM", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
878 if (rc
&& gpg_err_source (rc
) && gpg_err_code (rc
) == GPG_ERR_ASS_CANCELED
)
879 rc
= gpg_err_make (gpg_err_source (rc
), GPG_ERR_CANCELED
);
881 return unlock_pinentry (rc
);
886 /* Pop up the PINentry, display the text DESC and a button with the
887 text OK_BTN (which may be NULL to use the default of "OK") and waut
888 for the user to hit this button. The return value is not
891 agent_show_message (ctrl_t ctrl
, const char *desc
, const char *ok_btn
)
894 char line
[ASSUAN_LINELENGTH
];
896 rc
= start_pinentry (ctrl
);
901 snprintf (line
, DIM(line
)-1, "SETDESC %s", desc
);
903 snprintf (line
, DIM(line
)-1, "RESET");
904 line
[DIM(line
)-1] = 0;
905 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
906 /* Most pinentries out in the wild return the old Assuan error code
907 for canceled which gets translated to an assuan Cancel error and
908 not to the code for a user cancel. Fix this here. */
909 if (rc
&& gpg_err_source (rc
) && gpg_err_code (rc
) == GPG_ERR_ASS_CANCELED
)
910 rc
= gpg_err_make (gpg_err_source (rc
), GPG_ERR_CANCELED
);
913 return unlock_pinentry (rc
);
917 snprintf (line
, DIM(line
)-1, "SETOK %s", ok_btn
);
918 line
[DIM(line
)-1] = 0;
919 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
,
922 return unlock_pinentry (rc
);
925 rc
= assuan_transact (entry_ctx
, "CONFIRM --one-button", NULL
, NULL
, NULL
,
927 if (rc
&& gpg_err_source (rc
) && gpg_err_code (rc
) == GPG_ERR_ASS_CANCELED
)
928 rc
= gpg_err_make (gpg_err_source (rc
), GPG_ERR_CANCELED
);
930 return unlock_pinentry (rc
);
934 /* The thread running the popup message. */
936 popup_message_thread (void *arg
)
938 /* We use the --one-button hack instead of the MESSAGE command to
939 allow the use of old Pinentries. Those old Pinentries will then
940 show an additional Cancel button but that is mostly a visual
942 assuan_transact (entry_ctx
, "CONFIRM --one-button",
943 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
949 /* Pop up a message window similar to the confirm one but keep it open
950 until agent_popup_message_stop has been called. It is crucial for
951 the caller to make sure that the stop function gets called as soon
952 as the message is not anymore required because the message is
953 system modal and all other attempts to use the pinentry will fail
954 (after a timeout). */
956 agent_popup_message_start (ctrl_t ctrl
, const char *desc
, const char *ok_btn
)
959 char line
[ASSUAN_LINELENGTH
];
962 rc
= start_pinentry (ctrl
);
967 snprintf (line
, DIM(line
)-1, "SETDESC %s", desc
);
969 snprintf (line
, DIM(line
)-1, "RESET");
970 line
[DIM(line
)-1] = 0;
971 rc
= assuan_transact (entry_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
973 return unlock_pinentry (rc
);
977 snprintf (line
, DIM(line
)-1, "SETOK %s", ok_btn
);
978 line
[DIM(line
)-1] = 0;
979 rc
= assuan_transact (entry_ctx
, line
, NULL
,NULL
,NULL
,NULL
,NULL
,NULL
);
981 return unlock_pinentry (rc
);
984 tattr
= pth_attr_new();
985 pth_attr_set (tattr
, PTH_ATTR_JOINABLE
, 1);
986 pth_attr_set (tattr
, PTH_ATTR_STACK_SIZE
, 256*1024);
987 pth_attr_set (tattr
, PTH_ATTR_NAME
, "popup-message");
990 popup_tid
= pth_spawn (tattr
, popup_message_thread
, NULL
);
993 rc
= gpg_error_from_syserror ();
994 log_error ("error spawning popup message handler: %s\n",
996 pth_attr_destroy (tattr
);
997 return unlock_pinentry (rc
);
999 pth_attr_destroy (tattr
);
1004 /* Close a popup window. */
1006 agent_popup_message_stop (ctrl_t ctrl
)
1011 if (!popup_tid
|| !entry_ctx
)
1013 log_debug ("agent_popup_message_stop called with no active popup\n");
1017 pid
= assuan_get_pid (entry_ctx
);
1018 if (pid
== (pid_t
)(-1))
1019 ; /* No pid available can't send a kill. */
1020 else if (popup_finished
)
1021 ; /* Already finished and ready for joining. */
1022 #ifdef HAVE_W32_SYSTEM
1023 /* Older versions of assuan set PID to 0 on Windows to indicate an
1025 else if (pid
!= (pid_t
) INVALID_HANDLE_VALUE
1028 HANDLE process
= (HANDLE
) pid
;
1030 /* Arbitrary error code. */
1031 TerminateProcess (process
, 1);
1034 else if (pid
&& ((rc
=waitpid (pid
, NULL
, WNOHANG
))==-1 || (rc
== pid
)) )
1035 { /* The daemon already died. No need to send a kill. However
1036 because we already waited for the process, we need to tell
1037 assuan that it should not wait again (done by
1038 unlock_pinentry). */
1040 assuan_set_flag (entry_ctx
, ASSUAN_NO_WAITPID
, 1);
1043 kill (pid
, SIGKILL
); /* Need to use SIGKILL due to bad
1044 interaction of SIGINT with Pth. */
1047 /* Now wait for the thread to terminate. */
1048 rc
= pth_join (popup_tid
, NULL
);
1050 log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1055 /* Now we can close the connection. */
1056 unlock_pinentry (0);