Marcus Brinkmann <marcus@g10code.com>
[gnupg.git] / agent / call-pinentry.c
blobea18d43ddec2969c38dd6e53b631e302b0b76544
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 log_printf ("unknown under W32");
109 #else
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");
114 else
115 log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
116 #endif
120 /* This function may be called to print infromation pertaining to the
121 current state of this module to the log. */
122 void
123 agent_query_dump_state (void)
125 log_info ("agent_query_dump_state: entry_lock=");
126 dump_mutex_state (&entry_lock);
127 log_printf ("\n");
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. */
134 void
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. */
148 static int
149 unlock_pinentry (int rc)
151 assuan_context_t ctx = entry_ctx;
153 entry_ctx = NULL;
154 if (!pth_mutex_release (&entry_lock))
156 log_error ("failed to release the entry lock\n");
157 if (!rc)
158 rc = gpg_error (GPG_ERR_INTERNAL);
160 assuan_disconnect (ctx);
161 return rc;
165 /* To make sure we leave no secrets in our image after forking of the
166 pinentry, we use this callback. */
167 static void
168 atfork_cb (void *opaque, int where)
170 ctrl_t ctrl = opaque;
172 if (!where)
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 );
182 static int
183 getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
185 unsigned long *pid = opaque;
186 char pidbuf[50];
188 /* There is only the pid in the server's response. */
189 if (length >= sizeof pidbuf)
190 length = sizeof pidbuf -1;
191 if (length)
193 strncpy (pidbuf, buffer, length);
194 pidbuf[length] = 0;
195 *pid = strtoul (pidbuf, NULL, 10);
197 return 0;
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.
204 static int
205 start_pinentry (ctrl_t ctrl)
207 int rc;
208 const char *pgmname;
209 assuan_context_t ctx;
210 const char *argv[5];
211 int no_close_list[3];
212 int i;
213 pth_event_t evt;
214 const char *tmpstr;
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);
222 else
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"),
226 gpg_strerror (rc));
227 return rc;
229 pth_event_free (evt, PTH_FREE_THIS);
231 entry_owner = ctrl;
233 if (entry_ctx)
234 return 0;
236 if (opt.verbose)
237 log_info ("starting a new PIN Entry\n");
239 #ifdef HAVE_W32_SYSTEM
240 fflush (stdout);
241 fflush (stderr);
242 #endif
243 if (fflush (NULL))
245 #ifndef HAVE_W32_SYSTEM
246 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
247 #endif
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);
255 #endif
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;
263 else
264 pgmname++;
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. */
269 #ifdef __APPLE__
270 argv[0] = opt.pinentry_program;
271 #else /*!__APPLE__*/
272 argv[0] = pgmname;
273 #endif /*__APPLE__*/
275 if (ctrl->display && !opt.keep_display)
277 argv[1] = "--display";
278 argv[2] = ctrl->display;
279 argv[3] = NULL;
281 else
282 argv[1] = NULL;
284 i=0;
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
296 under Windows. */
297 rc = assuan_pipe_connect_ext (&ctx, opt.pinentry_program, argv,
298 no_close_list, atfork_cb, ctrl, 128);
299 if (rc)
301 log_error ("can't connect to the PIN entry module: %s\n",
302 gpg_strerror (rc));
303 return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
305 entry_ctx = ctx;
307 if (DBG_ASSUAN)
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);
313 if (rc)
314 return unlock_pinentry (rc);
315 if (ctrl->ttyname)
317 char *optstr;
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,
321 NULL);
322 xfree (optstr);
323 if (rc)
324 return unlock_pinentry (rc);
326 if (ctrl->ttytype)
328 char *optstr;
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,
332 NULL);
333 if (rc)
334 return unlock_pinentry (rc);
336 if (ctrl->lc_ctype)
338 char *optstr;
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,
342 NULL);
343 if (rc)
344 return unlock_pinentry (rc);
346 if (ctrl->lc_messages)
348 char *optstr;
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,
352 NULL);
353 if (rc)
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"))
363 tmpstr = NULL;
364 else if (!tmpstr)
365 tmpstr = get_agent_socket_name ();
366 if (tmpstr)
368 char *optstr;
370 if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
372 else
374 assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
375 NULL);
376 xfree (optstr);
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);
388 if (rc)
390 log_info ("You may want to update to a newer pinentry\n");
391 rc = 0;
393 else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
394 log_error ("pinentry did not return a PID\n");
395 else
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));
400 rc = 0;
403 return 0;
407 /* Returns True is the pinentry is currently active. If WAITSECONDS is
408 greater than zero the function will wait for this many seconds
409 before returning. */
411 pinentry_active_p (ctrl_t ctrl, int waitseconds)
413 if (waitseconds > 0)
415 pth_event_t evt;
416 int rc;
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);
423 else
424 rc = gpg_error (GPG_ERR_INTERNAL);
425 pth_event_free (evt, PTH_FREE_THIS);
426 return rc;
428 pth_event_free (evt, PTH_FREE_THIS);
430 else
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__);
438 return 0;
442 static int
443 getpin_cb (void *opaque, const void *buffer, size_t length)
445 struct entry_parm_s *parm = opaque;
447 if (!buffer)
448 return 0;
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;
458 parm->lines++;
459 return 0;
463 static int
464 all_digitsp( const char *s)
466 for (; *s && *s >= '0' && *s <= '9'; s++)
468 return !*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. */
477 static char *
478 unescape_passphrase_string (const unsigned char *s)
480 char *buffer, *d;
482 buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
483 if (!buffer)
484 return NULL;
485 while (*s && !spacep (s))
487 if (*s == '%' && s[1] && s[2])
489 s++;
490 *d = xtoi_2 (s);
491 if (!*d)
492 *d = '\xff';
493 d++;
494 s += 2;
496 else if (*s == '+')
498 *d++ = ' ';
499 s++;
501 else
502 *d++ = *s++;
504 *d = 0;
505 return buffer;
509 /* Estimate the quality of the passphrase PW and return a value in the
510 range 0..100. */
511 static int
512 estimate_passphrase_quality (const char *pw)
514 int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
515 int length;
516 const char *s;
518 if (goodlength < 1)
519 return 0;
521 for (length = 0, s = pw; *s; s++)
522 if (!spacep (s))
523 length ++;
525 if (length > goodlength)
526 return 100;
527 return ((length*10) / goodlength)*10;
531 /* Handle the QUALITY inquiry. */
532 static int
533 inq_quality (void *opaque, const char *line)
535 assuan_context_t ctx = opaque;
536 char *pin;
537 int rc;
538 int percent;
539 char numbuf[20];
541 if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
543 line += 7;
544 while (*line == ' ')
545 line++;
547 pin = unescape_passphrase_string (line);
548 if (!pin)
549 rc = gpg_error_from_syserror ();
550 else
552 percent = estimate_passphrase_quality (pin);
553 if (check_passphrase_constraints (NULL, pin, 1))
554 percent = -percent;
555 snprintf (numbuf, sizeof numbuf, "%d", percent);
556 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
557 xfree (pin);
560 else
562 log_error ("unsupported inquiry `%s' from pinentry\n", line);
563 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
566 return rc;
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
575 numbers. */
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)
582 int rc;
583 char line[ASSUAN_LINELENGTH];
584 struct entry_parm_s parm;
585 const char *errtext = NULL;
586 int is_pin = 0;
588 if (opt.batch)
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");
596 else if (!desc_text)
597 desc_text = _("Please enter your passphrase, so that the secret key "
598 "can be unlocked for this session");
600 if (prompt_text)
601 is_pin = !!strstr (prompt_text, "PIN");
602 else
603 is_pin = desc_text && strstr (desc_text, "PIN");
605 rc = start_pinentry (ctrl);
606 if (rc)
607 return rc;
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);
612 if (rc)
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);
619 if (rc)
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
624 to the pinentry. */
625 if (pininfo->with_qualitybar && opt.min_passphrase_len )
627 char *tmpstr, *tmpstr2;
628 const char *tooltip;
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;
635 xfree (tmpstr);
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. */
641 else if (rc)
642 return unlock_pinentry (rc);
644 tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
645 if (tmpstr2)
646 tooltip = tmpstr2;
647 else
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");
662 xfree (tmpstr2);
663 snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
664 line[DIM(line)-1] = 0;
665 xfree (tmpstr);
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. */
671 else if (rc)
672 return unlock_pinentry (rc);
675 if (initial_errtext)
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);
681 if (rc)
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;
692 if (errtext)
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);
702 if (rc)
703 return unlock_pinentry (rc);
704 errtext = NULL;
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");
719 else if (rc)
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"));
745 else if (rc)
746 return unlock_pinentry (rc);
749 if (!errtext)
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. */
761 int
762 agent_get_passphrase (ctrl_t ctrl,
763 char **retpass, const char *desc, const char *prompt,
764 const char *errtext)
767 int rc;
768 char line[ASSUAN_LINELENGTH];
769 struct entry_parm_s parm;
771 *retpass = NULL;
772 if (opt.batch)
773 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
775 rc = start_pinentry (ctrl);
776 if (rc)
777 return rc;
779 if (!prompt)
780 prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
783 if (desc)
784 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
785 else
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);
789 if (rc)
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);
795 if (rc)
796 return unlock_pinentry (rc);
798 if (errtext)
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);
803 if (rc)
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);
810 if (!parm.buffer)
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);
821 if (rc)
822 xfree (parm.buffer);
823 else
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
833 other error. */
834 int
835 agent_get_confirmation (ctrl_t ctrl,
836 const char *desc, const char *ok, const char *cancel)
838 int rc;
839 char line[ASSUAN_LINELENGTH];
841 rc = start_pinentry (ctrl);
842 if (rc)
843 return rc;
845 if (desc)
846 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
847 else
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);
857 if (rc)
858 return unlock_pinentry (rc);
860 if (ok)
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);
865 if (rc)
866 return unlock_pinentry (rc);
868 if (cancel)
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);
873 if (rc)
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
889 relevant. */
890 int
891 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
893 int rc;
894 char line[ASSUAN_LINELENGTH];
896 rc = start_pinentry (ctrl);
897 if (rc)
898 return rc;
900 if (desc)
901 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
902 else
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);
912 if (rc)
913 return unlock_pinentry (rc);
915 if (ok_btn)
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,
920 NULL, NULL, NULL);
921 if (rc)
922 return unlock_pinentry (rc);
925 rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
926 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. */
935 static void *
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
941 annoyance. */
942 assuan_transact (entry_ctx, "CONFIRM --one-button",
943 NULL, NULL, NULL, NULL, NULL, NULL);
944 popup_finished = 1;
945 return 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). */
955 int
956 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
958 int rc;
959 char line[ASSUAN_LINELENGTH];
960 pth_attr_t tattr;
962 rc = start_pinentry (ctrl);
963 if (rc)
964 return rc;
966 if (desc)
967 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
968 else
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);
972 if (rc)
973 return unlock_pinentry (rc);
975 if (ok_btn)
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);
980 if (rc)
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");
989 popup_finished = 0;
990 popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
991 if (!popup_tid)
993 rc = gpg_error_from_syserror ();
994 log_error ("error spawning popup message handler: %s\n",
995 strerror (errno) );
996 pth_attr_destroy (tattr);
997 return unlock_pinentry (rc);
999 pth_attr_destroy (tattr);
1001 return 0;
1004 /* Close a popup window. */
1005 void
1006 agent_popup_message_stop (ctrl_t ctrl)
1008 int rc;
1009 pid_t pid;
1011 if (!popup_tid || !entry_ctx)
1013 log_debug ("agent_popup_message_stop called with no active popup\n");
1014 return;
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
1024 invalid value. */
1025 else if (pid != (pid_t) INVALID_HANDLE_VALUE
1026 && pid != 0)
1028 HANDLE process = (HANDLE) pid;
1030 /* Arbitrary error code. */
1031 TerminateProcess (process, 1);
1033 #else
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). */
1039 if (rc == pid)
1040 assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1042 else if (pid > 0)
1043 kill (pid, SIGKILL); /* Need to use SIGKILL due to bad
1044 interaction of SIGINT with Pth. */
1045 #endif
1047 /* Now wait for the thread to terminate. */
1048 rc = pth_join (popup_tid, NULL);
1049 if (!rc)
1050 log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1051 strerror (errno));
1052 popup_tid = NULL;
1053 entry_owner = NULL;
1055 /* Now we can close the connection. */
1056 unlock_pinentry (0);