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