Preparing an interim release
[gnupg.git] / agent / query.c
1 /* query.c - fork of the pinentry to query stuff from the user
2  * Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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 2 of the License, or
9  * (at your option) any later version.
10  *
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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30 #ifndef HAVE_W32_SYSTEM
31 #include <sys/wait.h>
32 #endif
33 #include <pth.h>
34
35 #include "agent.h"
36 #include "i18n.h"
37 #include <assuan.h>
38
39 #ifdef _POSIX_OPEN_MAX
40 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
41 #else
42 #define MAX_OPEN_FDS 20
43 #endif
44
45
46 /* Because access to the pinentry must be serialized (it is and shall
47    be a global mutual dialog) we should better timeout further
48    requests after some time.  2 minutes seem to be a reasonable
49    time. */
50 #define LOCK_TIMEOUT  (1*60)
51
52 /* The assuan context of the current pinentry. */
53 static assuan_context_t entry_ctx;
54
55 /* The control variable of the connection owning the current pinentry.
56    This is only valid if ENTRY_CTX is not NULL.  Note, that we care
57    only about the value of the pointer and that it should never be
58    dereferenced.  */
59 static ctrl_t entry_owner;
60
61 /* A mutex used to serialize access to the pinentry. */
62 static pth_mutex_t entry_lock;
63
64 /* The thread ID of the popup working thread. */
65 static pth_t  popup_tid;
66
67 /* A flag used in communication between the popup working thread and
68    its stop function. */
69 static int popup_finished;
70
71
72
73 /* Data to be passed to our callbacks, */
74 struct entry_parm_s
75 {
76   int lines;
77   size_t size;
78   unsigned char *buffer;
79 };
80
81
82
83 \f
84 /* This function must be called once to initialize this module.  This
85    has to be done before a second thread is spawned.  We can't do the
86    static initialization because Pth emulation code might not be able
87    to do a static init; in particular, it is not possible for W32. */
88 void
89 initialize_module_query (void)
90 {
91   static int initialized;
92
93   if (!initialized)
94     {
95       if (pth_mutex_init (&entry_lock))
96         initialized = 1;
97     }
98 }
99
100
101
102 static void
103 dump_mutex_state (pth_mutex_t *m)
104 {
105   if (!(m->mx_state & PTH_MUTEX_INITIALIZED))
106     log_printf ("not_initialized");
107   else if (!(m->mx_state & PTH_MUTEX_LOCKED))
108     log_printf ("not_locked");
109   else
110     log_printf ("locked tid=0x%lx count=%lu", (long)m->mx_owner, m->mx_count);
111 }
112
113
114 /* This function may be called to print infromation pertaining to the
115    current state of this module to the log. */
116 void
117 agent_query_dump_state (void)
118 {
119   log_info ("agent_query_dump_state: entry_lock=");
120   dump_mutex_state (&entry_lock);
121   log_printf ("\n");
122   log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n",
123             entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid);
124 }
125
126 /* Called to make sure that a popup window owned by the current
127    connection gets closed. */
128 void
129 agent_reset_query (ctrl_t ctrl)
130 {
131   if (entry_ctx && popup_tid && entry_owner == ctrl)
132     {
133       agent_popup_message_stop (ctrl);
134     }
135 }
136
137
138 /* Unlock the pinentry so that another thread can start one and
139    disconnect that pinentry - we do this after the unlock so that a
140    stalled pinentry does not block other threads.  Fixme: We should
141    have a timeout in Assuan for the disconnect operation. */
142 static int 
143 unlock_pinentry (int rc)
144 {
145   assuan_context_t ctx = entry_ctx;
146
147   entry_ctx = NULL;
148   if (!pth_mutex_release (&entry_lock))
149     {
150       log_error ("failed to release the entry lock\n");
151       if (!rc)
152         rc = gpg_error (GPG_ERR_INTERNAL);
153     }
154   assuan_disconnect (ctx);
155   return rc;
156 }
157
158
159 /* To make sure we leave no secrets in our image after forking of the
160    pinentry, we use this callback. */
161 static void
162 atfork_cb (void *opaque, int where)
163 {
164   if (!where)
165     gcry_control (GCRYCTL_TERM_SECMEM);
166 }
167
168
169 /* Fork off the pin entry if this has not already been done.  Note,
170    that this function must always be used to aquire the lock for the
171    pinentry - we will serialize _all_ pinentry calls.
172  */
173 static int
174 start_pinentry (ctrl_t ctrl)
175 {
176   int rc;
177   const char *pgmname;
178   ASSUAN_CONTEXT ctx;
179   const char *argv[5];
180   int no_close_list[3];
181   int i;
182   pth_event_t evt;
183
184   evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
185   if (!pth_mutex_acquire (&entry_lock, 0, evt))
186     {
187       if (pth_event_occurred (evt))
188         rc = gpg_error (GPG_ERR_TIMEOUT);
189       else
190         rc = gpg_error (GPG_ERR_INTERNAL);
191       pth_event_free (evt, PTH_FREE_THIS);
192       log_error (_("failed to acquire the pinentry lock: %s\n"),
193                  gpg_strerror (rc));
194       return rc;
195     }
196   pth_event_free (evt, PTH_FREE_THIS);
197
198   entry_owner = ctrl;
199
200   if (entry_ctx)
201     return 0; 
202
203   if (opt.verbose)
204     log_info ("starting a new PIN Entry\n");
205       
206   if (fflush (NULL))
207     {
208       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
209       log_error ("error flushing pending output: %s\n", strerror (errno));
210       return unlock_pinentry (tmperr);
211     }
212
213   if (!opt.pinentry_program || !*opt.pinentry_program)
214     opt.pinentry_program = GNUPG_DEFAULT_PINENTRY;
215   if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
216     pgmname = opt.pinentry_program;
217   else
218     pgmname++;
219
220   argv[0] = pgmname;
221   if (ctrl->display && !opt.keep_display)
222     {
223       argv[1] = "--display";
224       argv[2] = ctrl->display;
225       argv[3] = NULL;
226     }
227   else
228     argv[1] = NULL;
229   
230   i=0;
231   if (!opt.running_detached)
232     {
233       if (log_get_fd () != -1)
234         no_close_list[i++] = log_get_fd ();
235       no_close_list[i++] = fileno (stderr);
236     }
237   no_close_list[i] = -1;
238
239   /* Connect to the pinentry and perform initial handshaking */
240   rc = assuan_pipe_connect2 (&ctx, opt.pinentry_program, (char**)argv,
241                              no_close_list, atfork_cb, NULL);
242   if (rc)
243     {
244       log_error ("can't connect to the PIN entry module: %s\n",
245                  assuan_strerror (rc));
246       return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
247     }
248   entry_ctx = ctx;
249
250   if (DBG_ASSUAN)
251     log_debug ("connection to PIN entry established\n");
252
253   rc = assuan_transact (entry_ctx, 
254                         opt.no_grab? "OPTION no-grab":"OPTION grab",
255                         NULL, NULL, NULL, NULL, NULL, NULL);
256   if (rc)
257     return unlock_pinentry (map_assuan_err (rc));
258   if (ctrl->ttyname)
259     {
260       char *optstr;
261       if (asprintf (&optstr, "OPTION ttyname=%s", ctrl->ttyname) < 0 )
262         return unlock_pinentry (out_of_core ());
263       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
264                             NULL);
265       free (optstr);
266       if (rc)
267         return unlock_pinentry (map_assuan_err (rc));
268     }
269   if (ctrl->ttytype)
270     {
271       char *optstr;
272       if (asprintf (&optstr, "OPTION ttytype=%s", ctrl->ttytype) < 0 )
273         return unlock_pinentry (out_of_core ());
274       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
275                             NULL);
276       if (rc)
277         return unlock_pinentry (map_assuan_err (rc));
278     }
279   if (ctrl->lc_ctype)
280     {
281       char *optstr;
282       if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
283         return unlock_pinentry (out_of_core ());
284       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
285                             NULL);
286       if (rc)
287         return unlock_pinentry (map_assuan_err (rc));
288     }
289   if (ctrl->lc_messages)
290     {
291       char *optstr;
292       if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
293         return unlock_pinentry (out_of_core ());
294       rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
295                             NULL);
296       if (rc)
297         return unlock_pinentry (map_assuan_err (rc));
298     }
299   return 0;
300 }
301
302
303 static AssuanError
304 getpin_cb (void *opaque, const void *buffer, size_t length)
305 {
306   struct entry_parm_s *parm = opaque;
307
308   if (!buffer)
309     return 0;
310
311   /* we expect the pin to fit on one line */
312   if (parm->lines || length >= parm->size)
313     return ASSUAN_Too_Much_Data;
314
315   /* fixme: we should make sure that the assuan buffer is allocated in
316      secure memory or read the response byte by byte */
317   memcpy (parm->buffer, buffer, length);
318   parm->buffer[length] = 0;
319   parm->lines++;
320   return 0;
321 }
322
323
324 static int
325 all_digitsp( const char *s)
326 {
327   for (; *s && *s >= '0' && *s <= '9'; s++)
328     ;
329   return !*s;
330 }  
331
332
333 \f
334 /* Call the Entry and ask for the PIN.  We do check for a valid PIN
335    number here and repeat it as long as we have invalid formed
336    numbers. */
337 int
338 agent_askpin (ctrl_t ctrl,
339               const char *desc_text, const char *prompt_text,
340               const char *initial_errtext,
341               struct pin_entry_info_s *pininfo)
342 {
343   int rc;
344   char line[ASSUAN_LINELENGTH];
345   struct entry_parm_s parm;
346   const char *errtext = NULL;
347   int is_pin = 0;
348
349   if (opt.batch)
350     return 0; /* fixme: we should return BAD PIN */
351
352   if (!pininfo || pininfo->max_length < 1)
353     return gpg_error (GPG_ERR_INV_VALUE);
354   if (!desc_text && pininfo->min_digits)
355     desc_text = _("Please enter your PIN, so that the secret key "
356                   "can be unlocked for this session");
357   else if (!desc_text)
358     desc_text = _("Please enter your passphrase, so that the secret key "
359                   "can be unlocked for this session");
360
361   if (prompt_text)
362     is_pin = !!strstr (prompt_text, "PIN");
363   else
364     is_pin = desc_text && strstr (desc_text, "PIN");
365
366   rc = start_pinentry (ctrl);
367   if (rc)
368     return rc;
369
370   snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
371   line[DIM(line)-1] = 0;
372   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
373   if (rc)
374     return unlock_pinentry (map_assuan_err (rc));
375
376   snprintf (line, DIM(line)-1, "SETPROMPT %s",
377             prompt_text? prompt_text : is_pin? "PIN:" : "Passphrase:");
378   line[DIM(line)-1] = 0;
379   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
380   if (rc)
381     return unlock_pinentry (map_assuan_err (rc));
382
383
384   if (initial_errtext)
385     { 
386       snprintf (line, DIM(line)-1, "SETERROR %s", initial_errtext);
387       line[DIM(line)-1] = 0;
388       rc = assuan_transact (entry_ctx, line,
389                             NULL, NULL, NULL, NULL, NULL, NULL);
390       if (rc)
391         return unlock_pinentry (map_assuan_err (rc));
392     }
393
394   for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
395     {
396       memset (&parm, 0, sizeof parm);
397       parm.size = pininfo->max_length;
398       parm.buffer = (unsigned char*)pininfo->pin;
399
400       if (errtext)
401         { 
402           /* fixme: should we show the try count? It must be translated */
403           snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)",
404                     errtext, pininfo->failed_tries+1, pininfo->max_tries);
405           line[DIM(line)-1] = 0;
406           rc = assuan_transact (entry_ctx, line,
407                                 NULL, NULL, NULL, NULL, NULL, NULL);
408           if (rc)
409             return unlock_pinentry (map_assuan_err (rc));
410           errtext = NULL;
411         }
412       
413       rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
414                             NULL, NULL, NULL, NULL);
415       if (rc == ASSUAN_Too_Much_Data)
416         errtext = is_pin? _("PIN too long")
417                         : _("Passphrase too long");
418       else if (rc)
419         return unlock_pinentry (map_assuan_err (rc));
420
421       if (!errtext && pininfo->min_digits)
422         {
423           /* do some basic checks on the entered PIN. */
424           if (!all_digitsp (pininfo->pin))
425             errtext = _("Invalid characters in PIN");
426           else if (pininfo->max_digits
427                    && strlen (pininfo->pin) > pininfo->max_digits)
428             errtext = _("PIN too long");
429           else if (strlen (pininfo->pin) < pininfo->min_digits)
430             errtext = _("PIN too short");
431         }
432
433       if (!errtext && pininfo->check_cb)
434         {
435           /* More checks by utilizing the optional callback. */
436           pininfo->cb_errtext = NULL;
437           rc = pininfo->check_cb (pininfo);
438           if (rc == -1 && pininfo->cb_errtext)
439             errtext = pininfo->cb_errtext;
440           else if (gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
441                    || gpg_err_code (rc) == GPG_ERR_BAD_PIN)
442             errtext = (is_pin? _("Bad PIN")
443                        : _("Bad Passphrase"));
444           else if (rc)
445             return unlock_pinentry (map_assuan_err (rc));
446         }
447
448       if (!errtext)
449         return unlock_pinentry (0); /* okay, got a PIN or passphrase */
450     }
451
452   return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
453                           : GPG_ERR_BAD_PASSPHRASE));
454 }
455
456
457 \f
458 /* Ask for the passphrase using the supplied arguments.  The
459    passphrase is returned in RETPASS as an hex encoded string to be
460    freed by the caller */
461 int 
462 agent_get_passphrase (ctrl_t ctrl,
463                       char **retpass, const char *desc, const char *prompt,
464                       const char *errtext)
465 {
466
467   int rc;
468   char line[ASSUAN_LINELENGTH];
469   struct entry_parm_s parm;
470   unsigned char *p;
471   char *hexstring;
472   int i;
473
474   *retpass = NULL;
475   if (opt.batch)
476     return gpg_error (GPG_ERR_BAD_PASSPHRASE); 
477
478   rc = start_pinentry (ctrl);
479   if (rc)
480     return rc;
481
482   if (!prompt)
483     prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
484
485
486   if (desc)
487     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
488   else
489     snprintf (line, DIM(line)-1, "RESET");
490   line[DIM(line)-1] = 0;
491   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
492   if (rc)
493     return unlock_pinentry (map_assuan_err (rc));
494
495   snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
496   line[DIM(line)-1] = 0;
497   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
498   if (rc)
499     return unlock_pinentry (map_assuan_err (rc));
500
501   if (errtext)
502     {
503       snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
504       line[DIM(line)-1] = 0;
505       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
506       if (rc)
507         return unlock_pinentry (map_assuan_err (rc));
508     }
509
510   memset (&parm, 0, sizeof parm);
511   parm.size = ASSUAN_LINELENGTH/2 - 5;
512   parm.buffer = gcry_malloc_secure (parm.size+10);
513   if (!parm.buffer)
514     return unlock_pinentry (out_of_core ());
515
516   assuan_begin_confidential (entry_ctx);
517   rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
518   if (rc)
519     {
520       xfree (parm.buffer);
521       return unlock_pinentry (map_assuan_err (rc));
522     }
523   
524   hexstring = gcry_malloc_secure (strlen ((char*)parm.buffer)*2+1);
525   if (!hexstring)
526     {
527       gpg_error_t tmperr = out_of_core ();
528       xfree (parm.buffer);
529       return unlock_pinentry (tmperr);
530     }
531
532   for (i=0, p=parm.buffer; *p; p++, i += 2)
533     sprintf (hexstring+i, "%02X", *p);
534   
535   xfree (parm.buffer);
536   *retpass = hexstring;
537   return unlock_pinentry (0);
538 }
539
540
541 \f
542 /* Pop up the PIN-entry, display the text and the prompt and ask the
543    user to confirm this.  We return 0 for success, ie. the user
544    confirmed it, GPG_ERR_NOT_CONFIRMED for what the text says or an
545    other error. */
546 int 
547 agent_get_confirmation (ctrl_t ctrl,
548                         const char *desc, const char *ok, const char *cancel)
549 {
550   int rc;
551   char line[ASSUAN_LINELENGTH];
552
553   rc = start_pinentry (ctrl);
554   if (rc)
555     return rc;
556
557   if (desc)
558     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
559   else
560     snprintf (line, DIM(line)-1, "RESET");
561   line[DIM(line)-1] = 0;
562   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
563   if (rc)
564     return unlock_pinentry (map_assuan_err (rc));
565
566   if (ok)
567     {
568       snprintf (line, DIM(line)-1, "SETOK %s", ok);
569       line[DIM(line)-1] = 0;
570       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
571       if (rc)
572         return unlock_pinentry (map_assuan_err (rc));
573     }
574   if (cancel)
575     {
576       snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel);
577       line[DIM(line)-1] = 0;
578       rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
579       if (rc)
580         return unlock_pinentry (map_assuan_err (rc));
581     }
582
583   rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
584   return unlock_pinentry (map_assuan_err (rc));
585 }
586
587
588 /* The thread running the popup message. */
589 static void *
590 popup_message_thread (void *arg)
591 {
592   assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
593   popup_finished = 1;
594   return NULL;
595 }
596
597
598 /* Pop up a message window similar to the confirm one but keep it open
599    until agent_popup_message_stop has been called.  It is crucial for
600    the caller to make sure that the stop function gets called as soon
601    as the message is not anymore required becuase the message is
602    system modal and all other attempts to use the pinentry will fail
603    (after a timeout). */
604 int 
605 agent_popup_message_start (ctrl_t ctrl, const char *desc,
606                            const char *ok_btn, const char *cancel_btn)
607 {
608   int rc;
609   char line[ASSUAN_LINELENGTH];
610   pth_attr_t tattr;
611
612   rc = start_pinentry (ctrl);
613   if (rc)
614     return rc;
615
616   if (desc)
617     snprintf (line, DIM(line)-1, "SETDESC %s", desc);
618   else
619     snprintf (line, DIM(line)-1, "RESET");
620   line[DIM(line)-1] = 0;
621   rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
622   if (rc)
623     return unlock_pinentry (map_assuan_err (rc));
624
625   if (ok_btn)
626     {
627       snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
628       line[DIM(line)-1] = 0;
629       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
630       if (rc)
631         return unlock_pinentry (map_assuan_err (rc));
632     }
633   if (cancel_btn)
634     {
635       snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel_btn);
636       line[DIM(line)-1] = 0;
637       rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
638       if (rc)
639         return unlock_pinentry (map_assuan_err (rc));
640     }
641
642   tattr = pth_attr_new();
643   pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
644   pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
645   pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");
646
647   popup_finished = 0;
648   popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
649   if (!popup_tid)
650     {
651       rc = gpg_error_from_errno (errno);
652       log_error ("error spawning popup message handler: %s\n",
653                  strerror (errno) );
654       pth_attr_destroy (tattr);
655       return unlock_pinentry (rc);
656     }
657   pth_attr_destroy (tattr);
658
659   return 0;
660 }
661
662 /* Close a popup window. */
663 void
664 agent_popup_message_stop (ctrl_t ctrl)
665 {
666   int rc;
667   pid_t pid;
668
669   if (!popup_tid || !entry_ctx)
670     {
671       log_debug ("agent_popup_message_stop called with no active popup\n");
672       return; 
673     }
674
675   pid = assuan_get_pid (entry_ctx);
676   if (pid == (pid_t)(-1))
677     ; /* No pid available can't send a kill. */
678   else if (popup_finished)
679     ; /* Already finished and ready for joining. */
680   else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
681     { /* The daemon already died.  No need to send a kill.  However
682          because we already waited for the process, we need to tell
683          assuan that it should not wait again (done by
684          unlock_pinentry). */
685       if (rc == pid)
686         assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
687     }
688   else
689     kill (pid, SIGINT);
690
691   /* Now wait for the thread to terminate. */
692   rc = pth_join (popup_tid, NULL);
693   if (!rc)
694     log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
695                strerror (errno));
696   popup_tid = NULL;
697   entry_owner = NULL;
698
699   /* Now we can close the connection. */
700   unlock_pinentry (0);
701 }
702
703