Move password repetition from gpg to gpg-agent.
[gnupg.git] / agent / call-pinentry.c
blob86792d8d74cb04f6ce08ce6d0f50a457ff3d74c5
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 (void)ctrl;
415 if (waitseconds > 0)
417 pth_event_t evt;
418 int rc;
420 evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
421 if (!pth_mutex_acquire (&entry_lock, 0, evt))
423 if (pth_event_occurred (evt))
424 rc = gpg_error (GPG_ERR_TIMEOUT);
425 else
426 rc = gpg_error (GPG_ERR_INTERNAL);
427 pth_event_free (evt, PTH_FREE_THIS);
428 return rc;
430 pth_event_free (evt, PTH_FREE_THIS);
432 else
434 if (!pth_mutex_acquire (&entry_lock, 1, NULL))
435 return gpg_error (GPG_ERR_LOCKED);
438 if (!pth_mutex_release (&entry_lock))
439 log_error ("failed to release the entry lock at %d\n", __LINE__);
440 return 0;
444 static int
445 getpin_cb (void *opaque, const void *buffer, size_t length)
447 struct entry_parm_s *parm = opaque;
449 if (!buffer)
450 return 0;
452 /* we expect the pin to fit on one line */
453 if (parm->lines || length >= parm->size)
454 return gpg_error (GPG_ERR_ASS_TOO_MUCH_DATA);
456 /* fixme: we should make sure that the assuan buffer is allocated in
457 secure memory or read the response byte by byte */
458 memcpy (parm->buffer, buffer, length);
459 parm->buffer[length] = 0;
460 parm->lines++;
461 return 0;
465 static int
466 all_digitsp( const char *s)
468 for (; *s && *s >= '0' && *s <= '9'; s++)
470 return !*s;
474 /* Return a new malloced string by unescaping the string S. Escaping
475 is percent escaping and '+'/space mapping. A binary Nul will
476 silently be replaced by a 0xFF. Function returns NULL to indicate
477 an out of memory status. PArsing stops at the end of the string or
478 a white space character. */
479 static char *
480 unescape_passphrase_string (const unsigned char *s)
482 char *buffer, *d;
484 buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
485 if (!buffer)
486 return NULL;
487 while (*s && !spacep (s))
489 if (*s == '%' && s[1] && s[2])
491 s++;
492 *d = xtoi_2 (s);
493 if (!*d)
494 *d = '\xff';
495 d++;
496 s += 2;
498 else if (*s == '+')
500 *d++ = ' ';
501 s++;
503 else
504 *d++ = *s++;
506 *d = 0;
507 return buffer;
511 /* Estimate the quality of the passphrase PW and return a value in the
512 range 0..100. */
513 static int
514 estimate_passphrase_quality (const char *pw)
516 int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
517 int length;
518 const char *s;
520 if (goodlength < 1)
521 return 0;
523 for (length = 0, s = pw; *s; s++)
524 if (!spacep (s))
525 length ++;
527 if (length > goodlength)
528 return 100;
529 return ((length*10) / goodlength)*10;
533 /* Handle the QUALITY inquiry. */
534 static int
535 inq_quality (void *opaque, const char *line)
537 assuan_context_t ctx = opaque;
538 char *pin;
539 int rc;
540 int percent;
541 char numbuf[20];
543 if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
545 line += 7;
546 while (*line == ' ')
547 line++;
549 pin = unescape_passphrase_string (line);
550 if (!pin)
551 rc = gpg_error_from_syserror ();
552 else
554 percent = estimate_passphrase_quality (pin);
555 if (check_passphrase_constraints (NULL, pin, 1))
556 percent = -percent;
557 snprintf (numbuf, sizeof numbuf, "%d", percent);
558 rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
559 xfree (pin);
562 else
564 log_error ("unsupported inquiry `%s' from pinentry\n", line);
565 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
568 return rc;
575 /* Call the Entry and ask for the PIN. We do check for a valid PIN
576 number here and repeat it as long as we have invalid formed
577 numbers. */
579 agent_askpin (ctrl_t ctrl,
580 const char *desc_text, const char *prompt_text,
581 const char *initial_errtext,
582 struct pin_entry_info_s *pininfo)
584 int rc;
585 char line[ASSUAN_LINELENGTH];
586 struct entry_parm_s parm;
587 const char *errtext = NULL;
588 int is_pin = 0;
590 if (opt.batch)
591 return 0; /* fixme: we should return BAD PIN */
593 if (!pininfo || pininfo->max_length < 1)
594 return gpg_error (GPG_ERR_INV_VALUE);
595 if (!desc_text && pininfo->min_digits)
596 desc_text = _("Please enter your PIN, so that the secret key "
597 "can be unlocked for this session");
598 else if (!desc_text)
599 desc_text = _("Please enter your passphrase, so that the secret key "
600 "can be unlocked for this session");
602 if (prompt_text)
603 is_pin = !!strstr (prompt_text, "PIN");
604 else
605 is_pin = desc_text && strstr (desc_text, "PIN");
607 rc = start_pinentry (ctrl);
608 if (rc)
609 return rc;
611 snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
612 line[DIM(line)-1] = 0;
613 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
614 if (rc)
615 return unlock_pinentry (rc);
617 snprintf (line, DIM(line)-1, "SETPROMPT %s",
618 prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
619 line[DIM(line)-1] = 0;
620 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
621 if (rc)
622 return unlock_pinentry (rc);
624 /* If a passphrase quality indicator has been requested and a
625 minimum passphrase length has not been disabled, send the command
626 to the pinentry. */
627 if (pininfo->with_qualitybar && opt.min_passphrase_len )
629 char *tmpstr, *tmpstr2;
630 const char *tooltip;
632 /* TRANSLATORS: This string is displayed by pinentry as the
633 label for the quality bar. */
634 tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
635 snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
636 line[DIM(line)-1] = 0;
637 xfree (tmpstr);
638 rc = assuan_transact (entry_ctx, line,
639 NULL, NULL, NULL, NULL, NULL, NULL);
640 if (rc == 103 /*(Old assuan error code)*/
641 || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
642 ; /* Ignore Unknown Command from old pinentry versions. */
643 else if (rc)
644 return unlock_pinentry (rc);
646 tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
647 if (tmpstr2)
648 tooltip = tmpstr2;
649 else
651 /* TRANSLATORS: This string is a tooltip, shown by pinentry
652 when hovering over the quality bar. Please use an
653 appropriate string to describe what this is about. The
654 length of the tooltip is limited to about 900 characters.
655 If you do not translate this entry, a default english
656 text (see source) will be used. */
657 tooltip = _("pinentry.qualitybar.tooltip");
658 if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
659 tooltip = ("The quality of the text entered above.\n"
660 "Please ask your administrator for "
661 "details about the criteria.");
663 tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
664 xfree (tmpstr2);
665 snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
666 line[DIM(line)-1] = 0;
667 xfree (tmpstr);
668 rc = assuan_transact (entry_ctx, line,
669 NULL, NULL, NULL, NULL, NULL, NULL);
670 if (rc == 103 /*(Old assuan error code)*/
671 || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
672 ; /* Ignore Unknown Command from old pinentry versions. */
673 else if (rc)
674 return unlock_pinentry (rc);
677 if (initial_errtext)
679 snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
680 line[DIM(line)-1] = 0;
681 rc = assuan_transact (entry_ctx, line,
682 NULL, NULL, NULL, NULL, NULL, NULL);
683 if (rc)
684 return unlock_pinentry (rc);
687 for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
689 memset (&parm, 0, sizeof parm);
690 parm.size = pininfo->max_length;
691 *pininfo->pin = 0; /* Reset the PIN. */
692 parm.buffer = (unsigned char*)pininfo->pin;
694 if (errtext)
696 /* TRANLATORS: The string is appended to an error message in
697 the pinentry. The %s is the actual error message, the
698 two %d give the current and maximum number of tries. */
699 snprintf (line, DIM(line)-1, _("SETERROR %s (try %d of %d)"),
700 errtext, pininfo->failed_tries+1, pininfo->max_tries);
701 line[DIM(line)-1] = 0;
702 rc = assuan_transact (entry_ctx, line,
703 NULL, NULL, NULL, NULL, NULL, NULL);
704 if (rc)
705 return unlock_pinentry (rc);
706 errtext = NULL;
709 rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
710 inq_quality, entry_ctx, NULL, NULL);
711 /* Most pinentries out in the wild return the old Assuan error code
712 for canceled which gets translated to an assuan Cancel error and
713 not to the code for a user cancel. Fix this here. */
714 if (rc && gpg_err_source (rc)
715 && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
716 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
718 if (gpg_err_code (rc) == GPG_ERR_ASS_TOO_MUCH_DATA)
719 errtext = is_pin? _("PIN too long")
720 : _("Passphrase too long");
721 else if (rc)
722 return unlock_pinentry (rc);
724 if (!errtext && pininfo->min_digits)
726 /* do some basic checks on the entered PIN. */
727 if (!all_digitsp (pininfo->pin))
728 errtext = _("Invalid characters in PIN");
729 else if (pininfo->max_digits
730 && strlen (pininfo->pin) > pininfo->max_digits)
731 errtext = _("PIN too long");
732 else if (strlen (pininfo->pin) < pininfo->min_digits)
733 errtext = _("PIN too short");
736 if (!errtext && pininfo->check_cb)
738 /* More checks by utilizing the optional callback. */
739 pininfo->cb_errtext = NULL;
740 rc = pininfo->check_cb (pininfo);
741 if (rc == -1 && pininfo->cb_errtext)
742 errtext = pininfo->cb_errtext;
743 else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
744 || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
745 errtext = (is_pin? _("Bad PIN")
746 : _("Bad Passphrase"));
747 else if (rc)
748 return unlock_pinentry (rc);
751 if (!errtext)
752 return unlock_pinentry (0); /* okay, got a PIN or passphrase */
755 return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
756 : GPG_ERR_BAD_PASSPHRASE));
761 /* Ask for the passphrase using the supplied arguments. The returned
762 passphrase needs to be freed by the caller. */
763 int
764 agent_get_passphrase (ctrl_t ctrl,
765 char **retpass, const char *desc, const char *prompt,
766 const char *errtext)
769 int rc;
770 char line[ASSUAN_LINELENGTH];
771 struct entry_parm_s parm;
773 *retpass = NULL;
774 if (opt.batch)
775 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
777 rc = start_pinentry (ctrl);
778 if (rc)
779 return rc;
781 if (!prompt)
782 prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
785 if (desc)
786 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
787 else
788 snprintf (line, DIM(line)-1, "RESET");
789 line[DIM(line)-1] = 0;
790 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
791 if (rc)
792 return unlock_pinentry (rc);
794 snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
795 line[DIM(line)-1] = 0;
796 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
797 if (rc)
798 return unlock_pinentry (rc);
800 if (errtext)
802 snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
803 line[DIM(line)-1] = 0;
804 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
805 if (rc)
806 return unlock_pinentry (rc);
809 memset (&parm, 0, sizeof parm);
810 parm.size = ASSUAN_LINELENGTH/2 - 5;
811 parm.buffer = gcry_malloc_secure (parm.size+10);
812 if (!parm.buffer)
813 return unlock_pinentry (out_of_core ());
815 assuan_begin_confidential (entry_ctx);
816 rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
817 NULL, NULL, NULL, NULL);
818 /* Most pinentries out in the wild return the old Assuan error code
819 for canceled which gets translated to an assuan Cancel error and
820 not to the code for a user cancel. Fix this here. */
821 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
822 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
823 if (rc)
824 xfree (parm.buffer);
825 else
826 *retpass = parm.buffer;
827 return unlock_pinentry (rc);
832 /* Pop up the PIN-entry, display the text and the prompt and ask the
833 user to confirm this. We return 0 for success, ie. the user
834 confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
835 other error. */
836 int
837 agent_get_confirmation (ctrl_t ctrl,
838 const char *desc, const char *ok, const char *cancel)
840 int rc;
841 char line[ASSUAN_LINELENGTH];
843 rc = start_pinentry (ctrl);
844 if (rc)
845 return rc;
847 if (desc)
848 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
849 else
850 snprintf (line, DIM(line)-1, "RESET");
851 line[DIM(line)-1] = 0;
852 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
853 /* Most pinentries out in the wild return the old Assuan error code
854 for canceled which gets translated to an assuan Cancel error and
855 not to the code for a user cancel. Fix this here. */
856 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
857 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
859 if (rc)
860 return unlock_pinentry (rc);
862 if (ok)
864 snprintf (line, DIM(line)-1, "SETOK %s", ok);
865 line[DIM(line)-1] = 0;
866 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
867 if (rc)
868 return unlock_pinentry (rc);
870 if (cancel)
872 snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel);
873 line[DIM(line)-1] = 0;
874 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
875 if (rc)
876 return unlock_pinentry (rc);
879 rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
880 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
881 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
883 return unlock_pinentry (rc);
888 /* Pop up the PINentry, display the text DESC and a button with the
889 text OK_BTN (which may be NULL to use the default of "OK") and waut
890 for the user to hit this button. The return value is not
891 relevant. */
892 int
893 agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
895 int rc;
896 char line[ASSUAN_LINELENGTH];
898 rc = start_pinentry (ctrl);
899 if (rc)
900 return rc;
902 if (desc)
903 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
904 else
905 snprintf (line, DIM(line)-1, "RESET");
906 line[DIM(line)-1] = 0;
907 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
908 /* Most pinentries out in the wild return the old Assuan error code
909 for canceled which gets translated to an assuan Cancel error and
910 not to the code for a user cancel. Fix this here. */
911 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
912 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
914 if (rc)
915 return unlock_pinentry (rc);
917 if (ok_btn)
919 snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
920 line[DIM(line)-1] = 0;
921 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL,
922 NULL, NULL, NULL);
923 if (rc)
924 return unlock_pinentry (rc);
927 rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
928 NULL, NULL, NULL);
929 if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
930 rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);
932 return unlock_pinentry (rc);
936 /* The thread running the popup message. */
937 static void *
938 popup_message_thread (void *arg)
940 (void)arg;
942 /* We use the --one-button hack instead of the MESSAGE command to
943 allow the use of old Pinentries. Those old Pinentries will then
944 show an additional Cancel button but that is mostly a visual
945 annoyance. */
946 assuan_transact (entry_ctx, "CONFIRM --one-button",
947 NULL, NULL, NULL, NULL, NULL, NULL);
948 popup_finished = 1;
949 return NULL;
953 /* Pop up a message window similar to the confirm one but keep it open
954 until agent_popup_message_stop has been called. It is crucial for
955 the caller to make sure that the stop function gets called as soon
956 as the message is not anymore required because the message is
957 system modal and all other attempts to use the pinentry will fail
958 (after a timeout). */
959 int
960 agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
962 int rc;
963 char line[ASSUAN_LINELENGTH];
964 pth_attr_t tattr;
966 rc = start_pinentry (ctrl);
967 if (rc)
968 return rc;
970 if (desc)
971 snprintf (line, DIM(line)-1, "SETDESC %s", desc);
972 else
973 snprintf (line, DIM(line)-1, "RESET");
974 line[DIM(line)-1] = 0;
975 rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
976 if (rc)
977 return unlock_pinentry (rc);
979 if (ok_btn)
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,NULL,NULL,NULL);
984 if (rc)
985 return unlock_pinentry (rc);
988 tattr = pth_attr_new();
989 pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
990 pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
991 pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
993 popup_finished = 0;
994 popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
995 if (!popup_tid)
997 rc = gpg_error_from_syserror ();
998 log_error ("error spawning popup message handler: %s\n",
999 strerror (errno) );
1000 pth_attr_destroy (tattr);
1001 return unlock_pinentry (rc);
1003 pth_attr_destroy (tattr);
1005 return 0;
1008 /* Close a popup window. */
1009 void
1010 agent_popup_message_stop (ctrl_t ctrl)
1012 int rc;
1013 pid_t pid;
1015 (void)ctrl;
1017 if (!popup_tid || !entry_ctx)
1019 log_debug ("agent_popup_message_stop called with no active popup\n");
1020 return;
1023 pid = assuan_get_pid (entry_ctx);
1024 if (pid == (pid_t)(-1))
1025 ; /* No pid available can't send a kill. */
1026 else if (popup_finished)
1027 ; /* Already finished and ready for joining. */
1028 #ifdef HAVE_W32_SYSTEM
1029 /* Older versions of assuan set PID to 0 on Windows to indicate an
1030 invalid value. */
1031 else if (pid != (pid_t) INVALID_HANDLE_VALUE
1032 && pid != 0)
1034 HANDLE process = (HANDLE) pid;
1036 /* Arbitrary error code. */
1037 TerminateProcess (process, 1);
1039 #else
1040 else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
1041 { /* The daemon already died. No need to send a kill. However
1042 because we already waited for the process, we need to tell
1043 assuan that it should not wait again (done by
1044 unlock_pinentry). */
1045 if (rc == pid)
1046 assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
1048 else if (pid > 0)
1049 kill (pid, SIGKILL); /* Need to use SIGKILL due to bad
1050 interaction of SIGINT with Pth. */
1051 #endif
1053 /* Now wait for the thread to terminate. */
1054 rc = pth_join (popup_tid, NULL);
1055 if (!rc)
1056 log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
1057 strerror (errno));
1058 popup_tid = NULL;
1059 entry_owner = NULL;
1061 /* Now we can close the connection. */
1062 unlock_pinentry (0);