~ubuntu-branches/ubuntu/jaunty/gnupg2/jaunty-security

« back to all changes in this revision

Viewing changes to agent/call-pinentry.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
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 3 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, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
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>
 
36
 
 
37
#include "agent.h"
 
38
#include "setenv.h"
 
39
#include "i18n.h"
 
40
 
 
41
#ifdef _POSIX_OPEN_MAX
 
42
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
 
43
#else
 
44
#define MAX_OPEN_FDS 20
 
45
#endif
 
46
 
 
47
 
 
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)
 
53
 
 
54
/* The assuan context of the current pinentry. */
 
55
static assuan_context_t entry_ctx;
 
56
 
 
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;
 
62
 
 
63
/* A mutex used to serialize access to the pinentry. */
 
64
static pth_mutex_t entry_lock;
 
65
 
 
66
/* The thread ID of the popup working thread. */
 
67
static pth_t  popup_tid;
 
68
 
 
69
/* A flag used in communication between the popup working thread and
 
70
   its stop function. */
 
71
static int popup_finished;
 
72
 
 
73
 
 
74
 
 
75
/* Data to be passed to our callbacks, */
 
76
struct entry_parm_s
 
77
{
 
78
  int lines;
 
79
  size_t size;
 
80
  unsigned char *buffer;
 
81
};
 
82
 
 
83
 
 
84
 
 
85
 
 
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)
 
92
{
 
93
  static int initialized;
 
94
 
 
95
  if (!initialized)
 
96
    {
 
97
      if (pth_mutex_init (&entry_lock))
 
98
        initialized = 1;
 
99
    }
 
100
}
 
101
 
 
102
 
 
103
 
 
104
static void
 
105
dump_mutex_state (pth_mutex_t *m)
 
106
{
 
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
 
117
}
 
118
 
 
119
 
 
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)
 
124
{
 
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);
 
130
}
 
131
 
 
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)
 
136
{
 
137
  if (entry_ctx && popup_tid && entry_owner == ctrl)
 
138
    {
 
139
      agent_popup_message_stop (ctrl);
 
140
    }
 
141
}
 
142
 
 
143
 
 
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)
 
150
{
 
151
  assuan_context_t ctx = entry_ctx;
 
152
 
 
153
  entry_ctx = NULL;
 
154
  if (!pth_mutex_release (&entry_lock))
 
155
    {
 
156
      log_error ("failed to release the entry lock\n");
 
157
      if (!rc)
 
158
        rc = gpg_error (GPG_ERR_INTERNAL);
 
159
    }
 
160
  assuan_disconnect (ctx);
 
161
  return rc;
 
162
}
 
163
 
 
164
 
 
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)
 
169
{
 
170
  ctrl_t ctrl = opaque;
 
171
 
 
172
  if (!where)
 
173
    {
 
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 );
 
179
    }
 
180
}
 
181
 
 
182
static int
 
183
getinfo_pid_cb (void *opaque, const void *buffer, size_t length)
 
184
{
 
185
  unsigned long *pid = opaque;
 
186
  char pidbuf[50];
 
187
 
 
188
  /* There is only the pid in the server's response.  */
 
189
  if (length >= sizeof pidbuf)
 
190
    length = sizeof pidbuf -1;
 
191
  if (length)
 
192
    {
 
193
      strncpy (pidbuf, buffer, length);
 
194
      pidbuf[length] = 0;
 
195
      *pid = strtoul (pidbuf, NULL, 10);
 
196
    }
 
197
  return 0;
 
198
}
 
199
 
 
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.
 
203
 */
 
204
static int
 
205
start_pinentry (ctrl_t ctrl)
 
206
{
 
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;
 
216
 
 
217
  evt = pth_event (PTH_EVENT_TIME, pth_timeout (LOCK_TIMEOUT, 0));
 
218
  if (!pth_mutex_acquire (&entry_lock, 0, evt))
 
219
    {
 
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;
 
228
    }
 
229
  pth_event_free (evt, PTH_FREE_THIS);
 
230
 
 
231
  entry_owner = ctrl;
 
232
 
 
233
  if (entry_ctx)
 
234
    return 0; 
 
235
 
 
236
  if (opt.verbose)
 
237
    log_info ("starting a new PIN Entry\n");
 
238
 
 
239
#ifdef HAVE_W32_SYSTEM      
 
240
  fflush (stdout);
 
241
  fflush (stderr);
 
242
#endif
 
243
  if (fflush (NULL))
 
244
    {
 
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
 
256
    }
 
257
 
 
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++;
 
265
 
 
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__*/
 
274
 
 
275
  if (ctrl->display && !opt.keep_display)
 
276
    {
 
277
      argv[1] = "--display";
 
278
      argv[2] = ctrl->display;
 
279
      argv[3] = NULL;
 
280
    }
 
281
  else
 
282
    argv[1] = NULL;
 
283
  
 
284
  i=0;
 
285
  if (!opt.running_detached)
 
286
    {
 
287
      if (log_get_fd () != -1)
 
288
        no_close_list[i++] = log_get_fd ();
 
289
      no_close_list[i++] = fileno (stderr);
 
290
    }
 
291
  no_close_list[i] = -1;
 
292
 
 
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)
 
300
    {
 
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));
 
304
    }
 
305
  entry_ctx = ctx;
 
306
 
 
307
  if (DBG_ASSUAN)
 
308
    log_debug ("connection to PIN entry established\n");
 
309
 
 
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)
 
316
    {
 
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
      free (optstr);
 
323
      if (rc)
 
324
        return unlock_pinentry (rc);
 
325
    }
 
326
  if (ctrl->ttytype)
 
327
    {
 
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);
 
335
    }
 
336
  if (ctrl->lc_ctype)
 
337
    {
 
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);
 
345
    }
 
346
  if (ctrl->lc_messages)
 
347
    {
 
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);
 
355
    }
 
356
 
 
357
  
 
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)
 
367
    {
 
368
      char *optstr;
 
369
      
 
370
      if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
 
371
        ;
 
372
      else
 
373
        {
 
374
          assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
 
375
                           NULL);
 
376
          free (optstr);
 
377
        }
 
378
    }
 
379
 
 
380
 
 
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)
 
389
    {
 
390
      log_info ("You may want to update to a newer pinentry\n");
 
391
      rc = 0;
 
392
    }
 
393
  else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
 
394
    log_error ("pinentry did not return a PID\n");
 
395
  else
 
396
    {
 
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;
 
401
    }
 
402
 
 
403
  return 0;
 
404
}
 
405
 
 
406
 
 
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.  */
 
410
int
 
411
pinentry_active_p (ctrl_t ctrl, int waitseconds)
 
412
{
 
413
  if (waitseconds > 0)
 
414
    {
 
415
      pth_event_t evt;
 
416
      int rc;
 
417
 
 
418
      evt = pth_event (PTH_EVENT_TIME, pth_timeout (waitseconds, 0));
 
419
      if (!pth_mutex_acquire (&entry_lock, 0, evt))
 
420
        {
 
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;
 
427
        }
 
428
      pth_event_free (evt, PTH_FREE_THIS);
 
429
    }
 
430
  else
 
431
    {
 
432
      if (!pth_mutex_acquire (&entry_lock, 1, NULL))
 
433
        return gpg_error (GPG_ERR_LOCKED);
 
434
    }
 
435
 
 
436
  if (!pth_mutex_release (&entry_lock))
 
437
    log_error ("failed to release the entry lock at %d\n", __LINE__);
 
438
  return 0;
 
439
}
 
440
 
 
441
 
 
442
static int
 
443
getpin_cb (void *opaque, const void *buffer, size_t length)
 
444
{
 
445
  struct entry_parm_s *parm = opaque;
 
446
 
 
447
  if (!buffer)
 
448
    return 0;
 
449
 
 
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);
 
453
 
 
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;
 
460
}
 
461
 
 
462
 
 
463
static int
 
464
all_digitsp( const char *s)
 
465
{
 
466
  for (; *s && *s >= '0' && *s <= '9'; s++)
 
467
    ;
 
468
  return !*s;
 
469
}  
 
470
 
 
471
 
 
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)
 
479
{
 
480
  char *buffer, *d;
 
481
 
 
482
  buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
 
483
  if (!buffer)
 
484
    return NULL;
 
485
  while (*s && !spacep (s))
 
486
    {
 
487
      if (*s == '%' && s[1] && s[2])
 
488
        { 
 
489
          s++;
 
490
          *d = xtoi_2 (s);
 
491
          if (!*d)
 
492
            *d = '\xff';
 
493
          d++;
 
494
          s += 2;
 
495
        }
 
496
      else if (*s == '+')
 
497
        {
 
498
          *d++ = ' ';
 
499
          s++;
 
500
        }
 
501
      else
 
502
        *d++ = *s++;
 
503
    }
 
504
  *d = 0; 
 
505
  return buffer;
 
506
}
 
507
 
 
508
 
 
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)
 
513
{
 
514
  int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
 
515
  int length;
 
516
  const char *s;
 
517
 
 
518
  if (goodlength < 1)
 
519
    return 0;
 
520
 
 
521
  for (length = 0, s = pw; *s; s++)
 
522
    if (!spacep (s))
 
523
      length ++;
 
524
 
 
525
  if (length > goodlength)
 
526
    return 100;
 
527
  return ((length*10) / goodlength)*10;
 
528
}
 
529
 
 
530
 
 
531
/* Handle the QUALITY inquiry. */
 
532
static int
 
533
inq_quality (void *opaque, const char *line)
 
534
{
 
535
  assuan_context_t ctx = opaque;
 
536
  char *pin;
 
537
  int rc;
 
538
  int percent;
 
539
  char numbuf[20];
 
540
 
 
541
  if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
 
542
    {
 
543
      line += 7;
 
544
      while (*line == ' ')
 
545
        line++;
 
546
      
 
547
      pin = unescape_passphrase_string (line);
 
548
      if (!pin)
 
549
        rc = gpg_error_from_syserror ();
 
550
      else
 
551
        {
 
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);
 
558
        }
 
559
    }
 
560
  else
 
561
    {
 
562
      log_error ("unsupported inquiry `%s' from pinentry\n", line);
 
563
      rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
 
564
    }
 
565
 
 
566
  return rc;
 
567
}
 
568
 
 
569
 
 
570
 
 
571
 
 
572
 
 
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. */
 
576
int
 
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)
 
581
{
 
582
  int rc;
 
583
  char line[ASSUAN_LINELENGTH];
 
584
  struct entry_parm_s parm;
 
585
  const char *errtext = NULL;
 
586
  int is_pin = 0;
 
587
 
 
588
  if (opt.batch)
 
589
    return 0; /* fixme: we should return BAD PIN */
 
590
 
 
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");
 
599
 
 
600
  if (prompt_text)
 
601
    is_pin = !!strstr (prompt_text, "PIN");
 
602
  else
 
603
    is_pin = desc_text && strstr (desc_text, "PIN");
 
604
 
 
605
  rc = start_pinentry (ctrl);
 
606
  if (rc)
 
607
    return rc;
 
608
 
 
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);
 
614
 
 
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);
 
621
 
 
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 )
 
626
    {
 
627
      char *tmpstr, *tmpstr2;
 
628
      const char *tooltip;
 
629
 
 
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);
 
643
 
 
644
      tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
 
645
      if (tmpstr2)
 
646
        tooltip = tmpstr2;
 
647
      else
 
648
        {
 
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.");
 
660
        }
 
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);
 
673
    }
 
674
 
 
675
  if (initial_errtext)
 
676
    { 
 
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);
 
683
    }
 
684
 
 
685
  for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
 
686
    {
 
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;
 
691
 
 
692
      if (errtext)
 
693
        { 
 
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;
 
705
        }
 
706
      
 
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);
 
715
 
 
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);
 
721
 
 
722
      if (!errtext && pininfo->min_digits)
 
723
        {
 
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");
 
732
        }
 
733
 
 
734
      if (!errtext && pininfo->check_cb)
 
735
        {
 
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);
 
747
        }
 
748
 
 
749
      if (!errtext)
 
750
        return unlock_pinentry (0); /* okay, got a PIN or passphrase */
 
751
    }
 
752
 
 
753
  return unlock_pinentry (gpg_error (pininfo->min_digits? GPG_ERR_BAD_PIN
 
754
                          : GPG_ERR_BAD_PASSPHRASE));
 
755
}
 
756
 
 
757
 
 
758
 
 
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)
 
765
{
 
766
 
 
767
  int rc;
 
768
  char line[ASSUAN_LINELENGTH];
 
769
  struct entry_parm_s parm;
 
770
 
 
771
  *retpass = NULL;
 
772
  if (opt.batch)
 
773
    return gpg_error (GPG_ERR_BAD_PASSPHRASE); 
 
774
 
 
775
  rc = start_pinentry (ctrl);
 
776
  if (rc)
 
777
    return rc;
 
778
 
 
779
  if (!prompt)
 
780
    prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
 
781
 
 
782
 
 
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);
 
791
 
 
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);
 
797
 
 
798
  if (errtext)
 
799
    {
 
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);
 
805
    }
 
806
 
 
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 ());
 
812
 
 
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);
 
826
}
 
827
 
 
828
 
 
829
 
 
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)
 
837
{
 
838
  int rc;
 
839
  char line[ASSUAN_LINELENGTH];
 
840
 
 
841
  rc = start_pinentry (ctrl);
 
842
  if (rc)
 
843
    return rc;
 
844
 
 
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);
 
856
 
 
857
  if (rc)
 
858
    return unlock_pinentry (rc);
 
859
 
 
860
  if (ok)
 
861
    {
 
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);
 
867
    }
 
868
  if (cancel)
 
869
    {
 
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);
 
875
    }
 
876
 
 
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);
 
880
 
 
881
  return unlock_pinentry (rc);
 
882
}
 
883
 
 
884
 
 
885
 
 
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)
 
892
{
 
893
  int rc;
 
894
  char line[ASSUAN_LINELENGTH];
 
895
 
 
896
  rc = start_pinentry (ctrl);
 
897
  if (rc)
 
898
    return rc;
 
899
 
 
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);
 
911
 
 
912
  if (rc)
 
913
    return unlock_pinentry (rc);
 
914
 
 
915
  if (ok_btn)
 
916
    {
 
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);
 
923
    }
 
924
  
 
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);
 
929
 
 
930
  return unlock_pinentry (rc);
 
931
}
 
932
 
 
933
 
 
934
/* The thread running the popup message. */
 
935
static void *
 
936
popup_message_thread (void *arg)
 
937
{
 
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;
 
946
}
 
947
 
 
948
 
 
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)
 
957
{
 
958
  int rc;
 
959
  char line[ASSUAN_LINELENGTH];
 
960
  pth_attr_t tattr;
 
961
 
 
962
  rc = start_pinentry (ctrl);
 
963
  if (rc)
 
964
    return rc;
 
965
 
 
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);
 
974
 
 
975
  if (ok_btn)
 
976
    {
 
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);
 
982
    }
 
983
 
 
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");
 
988
 
 
989
  popup_finished = 0;
 
990
  popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
 
991
  if (!popup_tid)
 
992
    {
 
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);
 
998
    }
 
999
  pth_attr_destroy (tattr);
 
1000
 
 
1001
  return 0;
 
1002
}
 
1003
 
 
1004
/* Close a popup window. */
 
1005
void
 
1006
agent_popup_message_stop (ctrl_t ctrl)
 
1007
{
 
1008
  int rc;
 
1009
  pid_t pid;
 
1010
 
 
1011
  if (!popup_tid || !entry_ctx)
 
1012
    {
 
1013
      log_debug ("agent_popup_message_stop called with no active popup\n");
 
1014
      return; 
 
1015
    }
 
1016
 
 
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)
 
1027
    {
 
1028
      HANDLE process = (HANDLE) pid;
 
1029
      
 
1030
      /* Arbitrary error code.  */
 
1031
      TerminateProcess (process, 1);
 
1032
    }
 
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);
 
1041
    }
 
1042
  else if (pid > 0)
 
1043
    kill (pid, SIGKILL);  /* Need to use SIGKILL due to bad
 
1044
                             interaction of SIGINT with Pth. */
 
1045
#endif
 
1046
 
 
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;
 
1054
 
 
1055
  /* Now we can close the connection. */
 
1056
  unlock_pinentry (0);
 
1057
}
 
1058
 
 
1059