~ubuntu-branches/ubuntu/hardy/gnupg/hardy-updates

« back to all changes in this revision

Viewing changes to g10/passphrase.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2005-12-16 16:57:39 UTC
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20051216165739-v0m2d1you6hd8jho
Tags: upstream-1.4.2
ImportĀ upstreamĀ versionĀ 1.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* passphrase.c -  Get a passphrase
2
 
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3
 
 *               2004, 2005 Free Software Foundation, Inc.
 
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 
3
 *               2005 Free Software Foundation, Inc.
4
4
 *
5
5
 * This file is part of GnuPG.
6
6
 *
16
16
 *
17
17
 * You should have received a copy of the GNU General Public License
18
18
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 
20
 * USA.
20
21
 */
21
22
 
22
23
#include <config.h>
50
51
#include "main.h"
51
52
#include "i18n.h"
52
53
#include "status.h"
53
 
 
54
 
 
55
 
enum gpga_protocol_codes {
56
 
    /* Request codes */
57
 
    GPGA_PROT_GET_VERSION     = 1,
58
 
    GPGA_PROT_GET_PASSPHRASE  = 2,
59
 
    GPGA_PROT_CLEAR_PASSPHRASE= 3,
60
 
    GPGA_PROT_SHUTDOWN        = 4,
61
 
    GPGA_PROT_FLUSH           = 5,
62
 
 
63
 
    /* Reply codes */
64
 
    GPGA_PROT_REPLY_BASE     = 0x10000,
65
 
    GPGA_PROT_OKAY           = 0x10001,
66
 
    GPGA_PROT_GOT_PASSPHRASE = 0x10002,
67
 
 
68
 
    /* Error codes */
69
 
    GPGA_PROT_ERROR_BASE     = 0x20000,
70
 
    GPGA_PROT_PROTOCOL_ERROR = 0x20001,
71
 
    GPGA_PROT_INVALID_REQUEST= 0x20002,
72
 
    GPGA_PROT_CANCELED       = 0x20003,    
73
 
    GPGA_PROT_NO_PASSPHRASE  = 0x20004,    
74
 
    GPGA_PROT_BAD_PASSPHRASE = 0x20005,
75
 
    GPGA_PROT_INVALID_DATA   = 0x20006,
76
 
    GPGA_PROT_NOT_IMPLEMENTED= 0x20007,
77
 
    GPGA_PROT_UI_PROBLEM     = 0x20008
78
 
};
 
54
#ifdef ENABLE_AGENT_SUPPORT
 
55
#include "assuan.h"
 
56
#endif /*ENABLE_AGENT_SUPPORT*/
79
57
 
80
58
 
81
59
#define buftou32( p )  ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
95
73
                     *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
96
74
#define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
97
75
 
98
 
 
99
 
 
100
76
static char *fd_passwd = NULL;
101
77
static char *next_pw = NULL;
102
78
static char *last_pw = NULL;
103
79
 
104
 
#if defined (_WIN32)
105
 
static int read_fd = 0;
106
 
static int write_fd = 0;
107
 
#endif
108
 
 
109
80
static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create );
110
81
 
111
82
int
191
162
  fd_passwd = pw;
192
163
}
193
164
 
194
 
static int
195
 
writen (int fd, const void *buf, size_t nbytes)
196
 
{
197
 
#if defined (_WIN32)
198
 
  DWORD nwritten, nleft = nbytes;
199
 
    
200
 
  while (nleft > 0)
201
 
    {
202
 
      if (!WriteFile ((HANDLE)write_fd, buf, nleft, &nwritten, NULL))
203
 
        {
204
 
          log_error ("write failed: %s\n", w32_strerror (0));
205
 
          return -1;
206
 
        }
207
 
      /*log_info ("** WriteFile fd=%d nytes=%d nwritten=%d\n",
208
 
        write_fd, nbytes, (int)nwritten);*/
209
 
      Sleep (100);
210
 
        
211
 
      nleft -= nwritten;
212
 
      buf = (const BYTE *)buf + nwritten;
213
 
    }
214
 
#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
215
 
  /* not implemented */
216
 
#else
217
 
  size_t nleft = nbytes;
218
 
  int nwritten;
219
 
 
220
 
  while (nleft > 0)
221
 
    {
222
 
      nwritten = write (fd, buf, nleft);
223
 
      if (nwritten < 0)
224
 
        {
225
 
          if (errno == EINTR)
226
 
            nwritten = 0;
227
 
          else
228
 
            {
229
 
              log_error ("write() failed: %s\n", strerror (errno));
230
 
              return -1;
231
 
            }
232
 
        }
233
 
      nleft -= nwritten;
234
 
      buf = (const char*)buf + nwritten;
235
 
    }
236
 
#endif
237
 
    
238
 
  return 0;
239
 
}
240
 
 
241
 
 
242
 
static int
243
 
readn (int fd, void *buf, size_t buflen, size_t *ret_nread)
244
 
{
245
 
#if defined (_WIN32)
246
 
  DWORD nread, nleft = buflen;
247
 
    
248
 
  while (nleft > 0)
249
 
    {
250
 
      if (!ReadFile ((HANDLE)read_fd, buf, nleft, &nread, NULL))
251
 
        {
252
 
          log_error ("read() error: %s\n", w32_strerror (0));
253
 
          return -1;
254
 
        }
255
 
      if (!nread || GetLastError() == ERROR_BROKEN_PIPE)
256
 
        break;
257
 
      /*log_info ("** ReadFile fd=%d buflen=%d nread=%d\n",
258
 
        read_fd, buflen, (int)nread);*/
259
 
      Sleep (100);
260
 
        
261
 
      nleft -= nread;
262
 
      buf = (BYTE *)buf + nread;
263
 
    }           
264
 
  if (ret_nread)
265
 
    *ret_nread = buflen - nleft;
266
 
 
267
 
#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
268
 
  /* not implemented */
269
 
#else
270
 
  size_t nleft = buflen;
271
 
  int nread;
272
 
  char *p;
273
 
  
274
 
  p = buf;
275
 
  while( nleft > 0 )
276
 
    {
277
 
      nread = read ( fd, buf, nleft );
278
 
      if( nread < 0 ) 
279
 
        {
280
 
          if (errno == EINTR)
281
 
            nread = 0;
282
 
          else 
283
 
            {
284
 
              log_error ( "read() error: %s\n", strerror (errno) );
285
 
              return -1;
286
 
            }
287
 
        }
288
 
      else if (!nread)
289
 
        break; /* EOF */
290
 
      nleft -= nread;
291
 
      buf = (char*)buf + nread;
292
 
    }
293
 
  if (ret_nread)
294
 
    *ret_nread = buflen - nleft;
295
 
#endif
296
 
    
297
 
  return 0;
298
 
}
299
 
 
300
 
/* read an entire line */
301
 
static int
302
 
readaline (int fd, char *buf, size_t buflen)
303
 
{
304
 
  size_t nleft = buflen;
305
 
  char *p;
306
 
  int nread = 0;
307
 
 
308
 
  while (nleft > 0)
309
 
    {
310
 
      int n = read (fd, buf, nleft);
311
 
      if (n < 0)
312
 
        {
313
 
          if (errno == EINTR)
314
 
            continue;
315
 
          return -1; /* read error */
316
 
        }
317
 
      else if (!n)
318
 
        {
319
 
          return -1; /* incomplete line */
320
 
        }
321
 
      p = buf;
322
 
      nleft -= n;
323
 
      buf += n;
324
 
      nread += n;
325
 
      
326
 
      for (; n && *p != '\n'; n--, p++)
327
 
        ;
328
 
      if (n)
329
 
        {
330
 
          break; /* at least one full line available - that's enough.
331
 
                    This function is just a temporary hack until we use
332
 
                    the assuna lib in gpg.  So it is okay to forget
333
 
                    about pending bytes */
334
 
        }
335
 
    }
336
 
 
337
 
  return nread; 
338
 
}
339
 
 
340
 
 
341
 
 
342
 
#if !defined (__riscos__)
343
 
 
344
 
#if !defined (_WIN32)
345
 
/* For the new Assuan protocol we may have to send options */
346
 
static int
347
 
agent_send_option (int fd, const char *name, const char *value)
348
 
{
349
 
  char buf[200];
350
 
  int nread;
 
165
 
 
166
 
 
167
#ifdef ENABLE_AGENT_SUPPORT
 
168
/* Send one option to the gpg-agent.  */
 
169
static int
 
170
agent_send_option (assuan_context_t ctx, const char *name, const char *value)
 
171
{
351
172
  char *line;
352
 
  int i; 
353
 
  
354
 
  line = m_alloc (7 + strlen (name) + 1 + strlen (value) + 2);
355
 
  strcpy (stpcpy (stpcpy (stpcpy (
356
 
                     stpcpy (line, "OPTION "), name), "="), value), "\n");
357
 
  i = writen (fd, line, strlen (line));
358
 
  m_free (line);
359
 
  if (i)
360
 
    return -1;
361
 
  
362
 
  /* get response */
363
 
  nread = readaline (fd, buf, DIM(buf)-1);
364
 
  if (nread < 3)
365
 
    return -1;
366
 
  
367
 
  if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n')) 
368
 
    return 0; /* okay */
 
173
  int rc; 
 
174
  
 
175
  if (!value || !*value)
 
176
    return 0; /* Avoid sending empty option values. */
369
177
 
370
 
  return -1;
 
178
  line = xmalloc (7 + strlen (name) + 1 + strlen (value) + 1);
 
179
  strcpy (stpcpy (stpcpy (stpcpy (line, "OPTION "), name), "="), value);
 
180
  rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
 
181
  xfree (line);
 
182
  return rc? -1 : 0;
371
183
}
372
184
 
 
185
/* Send all required options to the gpg-agent.  */
373
186
static int 
374
 
agent_send_all_options (int fd)
 
187
agent_send_all_options (assuan_context_t ctx)
375
188
{
376
189
  char *dft_display = NULL;
377
190
  const char *dft_ttyname = NULL;
383
196
  dft_display = getenv ("DISPLAY");
384
197
  if (opt.display || dft_display)
385
198
    {
386
 
      if (agent_send_option (fd, "display",
 
199
      if (agent_send_option (ctx, "display",
387
200
                             opt.display ? opt.display : dft_display))
388
201
        return -1;
389
202
    }
400
213
    }
401
214
  if (opt.ttyname || dft_ttyname)
402
215
    {
403
 
      if (agent_send_option (fd, "ttyname",
 
216
      if (agent_send_option (ctx, "ttyname",
404
217
                             opt.ttyname ? opt.ttyname : dft_ttyname))
405
218
        return -1;
406
219
    }
408
221
  dft_ttytype = getenv ("TERM");
409
222
  if (opt.ttytype || (dft_ttyname && dft_ttytype))
410
223
    {
411
 
      if (agent_send_option (fd, "ttytype",
 
224
      if (agent_send_option (ctx, "ttytype",
412
225
                             opt.ttyname ? opt.ttytype : dft_ttytype))
413
226
        return -1;
414
227
    }
421
234
#endif
422
235
  if (opt.lc_ctype || (dft_ttyname && dft_lc))
423
236
    {
424
 
      rc = agent_send_option (fd, "lc-ctype",
 
237
      rc = agent_send_option (ctx, "lc-ctype",
425
238
                              opt.lc_ctype ? opt.lc_ctype : dft_lc);
426
239
    }
427
240
#if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
442
255
#endif
443
256
  if (opt.lc_messages || (dft_ttyname && dft_lc))
444
257
    {
445
 
      rc = agent_send_option (fd, "lc-messages",
 
258
      rc = agent_send_option (ctx, "lc-messages",
446
259
                              opt.lc_messages ? opt.lc_messages : dft_lc);
447
260
    }
448
261
#if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
454
267
#endif
455
268
  return rc;
456
269
}
457
 
#endif /*!_WIN32*/
 
270
#endif /*ENABLE_AGENT_SUPPORT*/
458
271
 
459
272
 
460
273
/*
461
 
 * Open a connection to the agent and send the magic string
462
 
 * Returns: -1 on error or an filedescriptor for urther processing
 
274
 * Open a connection to the agent and initializes the connection.
 
275
 * Returns: -1 on error; on success an Assuan context for that
 
276
 * connection is returned.  With TRY set to true, no error messages
 
277
 * are printed and the use of the agent won't get disabled on failure.
 
278
 * If ORIG_CODESET is not NULL, the function will swithc the codeset
 
279
 * back to that one before printing error messages.
463
280
 */
464
 
 
465
 
static int
466
 
agent_open (int *ret_prot)
467
 
{
468
 
#if defined (_WIN32)
469
 
    int fd;
470
 
    char *infostr, *p;
471
 
    HANDLE h;
472
 
    char pidstr[128];
473
 
 
474
 
    *ret_prot = 0;
475
 
    if ( !(infostr = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
476
 
                                              "agentPID")) 
477
 
         || *infostr == '0') {
478
 
        log_error( _("gpg-agent is not available in this session\n"));
479
 
        return -1;
480
 
    }
481
 
    free(infostr);
482
 
    
483
 
    sprintf(pidstr, "%u", (unsigned int)GetCurrentProcessId());
484
 
    if (write_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
485
 
                                  "agentCID", pidstr)) {
486
 
        log_error( _("can't set client pid for the agent\n") );
487
 
        return -1;
488
 
    }
489
 
    h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent");
490
 
    SetEvent(h);
491
 
    Sleep(50); /* some time for the server */ 
492
 
    if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
493
 
                                        "agentReadFD")) ) {
494
 
        log_error( _("can't get server read FD for the agent\n") );
495
 
        return -1;
496
 
    }
497
 
    read_fd = atol(p);
498
 
    free(p);    
499
 
    if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
500
 
                                        "agentWriteFD")) ) {
501
 
        log_error ( _("can't get server write FD for the agent\n") );
502
 
        return -1;
503
 
    }
504
 
    write_fd = atol(p);
505
 
    free(p);
506
 
    fd = 0;
507
 
 
508
 
    if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) {
509
 
        fd = -1;
510
 
    }
511
 
#else /* Posix */
512
 
 
513
 
    int fd;
514
 
    char *infostr, *p;
515
 
    struct sockaddr_un client_addr;
516
 
    size_t len;
517
 
    int prot;
518
 
 
519
 
    if (opt.gpg_agent_info)
520
 
      infostr = m_strdup (opt.gpg_agent_info);
521
 
    else
522
 
      {
523
 
        infostr = getenv ( "GPG_AGENT_INFO" );
524
 
        if ( !infostr ) {
525
 
          log_error (_("gpg-agent is not available in this session\n"));
526
 
          opt.use_agent = 0;
527
 
          return -1;
528
 
        }
529
 
        infostr = m_strdup ( infostr );
530
 
      }
531
 
 
532
 
    if ( !(p = strchr ( infostr, ':')) || p == infostr
533
 
         || (p-infostr)+1 >= sizeof client_addr.sun_path ) {
534
 
        log_error( _("malformed GPG_AGENT_INFO environment variable\n"));
535
 
        m_free (infostr );
536
 
        opt.use_agent = 0;
537
 
        return -1;
538
 
    }
539
 
    *p++ = 0;
540
 
    /* See whether this is the new gpg-agent using the Assuna protocl.
541
 
       This agent identifies itself by have an info string with a
542
 
       version number in the 3rd field. */
543
 
    while (*p && *p != ':')
544
 
      p++;
545
 
    prot = *p? atoi (p+1) : 0;
546
 
    if ( prot < 0 || prot > 1) {
547
 
        log_error (_("gpg-agent protocol version %d is not supported\n"),prot);
548
 
        m_free (infostr );
549
 
        opt.use_agent = 0;
550
 
        return -1;
551
 
    }
552
 
    *ret_prot = prot;
553
 
       
554
 
    if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) {
555
 
        log_error ("can't create socket: %s\n", strerror(errno) );
556
 
        m_free (infostr );
557
 
        opt.use_agent = 0;
558
 
        return -1;
559
 
    }
560
 
    
561
 
    memset( &client_addr, 0, sizeof client_addr );
562
 
    client_addr.sun_family = AF_UNIX;
563
 
    strcpy( client_addr.sun_path, infostr );
564
 
    len = offsetof (struct sockaddr_un, sun_path)
565
 
        + strlen(client_addr.sun_path) + 1;
566
 
    
567
 
    if( connect( fd, (struct sockaddr*)&client_addr, len ) == -1 ) {
568
 
        log_error ( _("can't connect to `%s': %s\n"), 
569
 
                    infostr, strerror (errno) );
570
 
        m_free (infostr );
571
 
        close (fd );
572
 
        opt.use_agent = 0;
573
 
        return -1;
574
 
    }
575
 
    m_free (infostr);
576
 
 
577
 
    if (!prot) {
578
 
        if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) {
579
 
          close (fd);
580
 
          fd = -1;
581
 
        }
582
 
    }
583
 
    else { /* assuan based gpg-agent */
584
 
      char line[200];
585
 
      int nread;
586
 
 
587
 
      nread = readaline (fd, line, DIM(line));
588
 
      if (nread < 3 || !(line[0] == 'O' && line[1] == 'K'
589
 
                         && (line[2] == '\n' || line[2] == ' ')) ) {
590
 
        log_error ( _("communication problem with gpg-agent\n"));
591
 
        close (fd );
592
 
        opt.use_agent = 0;
593
 
        return -1;
594
 
      }
595
 
 
596
 
      if (agent_send_all_options (fd)) {
597
 
        log_error (_("problem with the agent - disabling agent use\n"));
598
 
        close (fd);
599
 
        opt.use_agent = 0;
600
 
        return -1;
601
 
      }
602
 
        
603
 
    }
604
 
#endif
605
 
 
606
 
    return fd;
607
 
}
608
 
 
609
 
 
610
 
static void
611
 
agent_close ( int fd )
612
 
{
613
 
#if defined (_WIN32)
614
 
    HANDLE h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent");
615
 
    ResetEvent(h);
616
 
#else
617
 
    close (fd);
618
 
#endif
619
 
}
620
 
#endif /* !__riscos__ */
 
281
#ifdef ENABLE_AGENT_SUPPORT
 
282
assuan_context_t
 
283
agent_open (int try, const char *orig_codeset)
 
284
{
 
285
  int rc;
 
286
  assuan_context_t ctx;
 
287
  char *infostr, *p;
 
288
  int prot;
 
289
  int pid;
 
290
 
 
291
  if (opt.gpg_agent_info)
 
292
    infostr = xstrdup (opt.gpg_agent_info);
 
293
  else
 
294
    {
 
295
      infostr = getenv ( "GPG_AGENT_INFO" );
 
296
      if (!infostr || !*infostr) 
 
297
        {
 
298
          if (!try)
 
299
            {
 
300
#ifdef ENABLE_NLS
 
301
              if (orig_codeset)
 
302
                bind_textdomain_codeset (PACKAGE, orig_codeset);
 
303
#endif /*ENABLE_NLS*/
 
304
              log_error (_("gpg-agent is not available in this session\n"));
 
305
              opt.use_agent = 0;
 
306
            }
 
307
          return NULL;
 
308
        }
 
309
      infostr = xstrdup ( infostr );
 
310
    }
 
311
  
 
312
  if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
 
313
    {
 
314
      if (!try)
 
315
        {
 
316
#ifdef ENABLE_NLS
 
317
          if (orig_codeset)
 
318
            bind_textdomain_codeset (PACKAGE, orig_codeset);
 
319
#endif /*ENABLE_NLS*/
 
320
          log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
 
321
          opt.use_agent = 0;
 
322
        }
 
323
      xfree (infostr);
 
324
      return NULL;
 
325
    }
 
326
  *p++ = 0;
 
327
  pid = atoi (p);
 
328
  while (*p && *p != PATHSEP_C)
 
329
    p++;
 
330
  prot = *p? atoi (p+1) : 0;
 
331
  if (prot != 1)
 
332
    {
 
333
      if (!try)
 
334
        {
 
335
#ifdef ENABLE_NLS
 
336
          if (orig_codeset)
 
337
            bind_textdomain_codeset (PACKAGE, orig_codeset);
 
338
#endif /*ENABLE_NLS*/
 
339
          log_error (_("gpg-agent protocol version %d is not supported\n"),
 
340
                     prot);
 
341
          opt.use_agent = 0;
 
342
        }
 
343
      xfree (infostr);
 
344
      return NULL;
 
345
    }
 
346
     
 
347
  rc = assuan_socket_connect (&ctx, infostr, pid);
 
348
  if (rc)
 
349
    {
 
350
      if (!try)
 
351
        {
 
352
#ifdef ENABLE_NLS
 
353
          if (orig_codeset)
 
354
            bind_textdomain_codeset (PACKAGE, orig_codeset);
 
355
#endif /*ENABLE_NLS*/
 
356
          log_error ( _("can't connect to `%s': %s\n"), 
 
357
                      infostr, assuan_strerror (rc));
 
358
          opt.use_agent = 0;
 
359
        }
 
360
      xfree (infostr );
 
361
      return NULL;
 
362
    }
 
363
  xfree (infostr);
 
364
 
 
365
  if (agent_send_all_options (ctx))
 
366
    {
 
367
      if (!try)
 
368
        {
 
369
#ifdef ENABLE_NLS
 
370
          if (orig_codeset)
 
371
            bind_textdomain_codeset (PACKAGE, orig_codeset);
 
372
#endif /*ENABLE_NLS*/
 
373
          log_error (_("problem with the agent - disabling agent use\n"));
 
374
          opt.use_agent = 0;
 
375
        }
 
376
      assuan_disconnect (ctx);
 
377
      return NULL;
 
378
    }
 
379
 
 
380
  return ctx;
 
381
}
 
382
#endif/*ENABLE_AGENT_SUPPORT*/
 
383
 
 
384
 
 
385
#ifdef ENABLE_AGENT_SUPPORT
 
386
void
 
387
agent_close (assuan_context_t ctx)
 
388
{
 
389
  assuan_disconnect (ctx);
 
390
}
 
391
#endif /*ENABLE_AGENT_SUPPORT*/
 
392
 
 
393
 
 
394
/* Copy the text ATEXT into the buffer P and do plus '+' and percent
 
395
   escaping.  Note that the provided buffer needs to be 3 times the
 
396
   size of ATEXT plus 1.  Returns a pointer to the leading Nul in P. */
 
397
#ifdef ENABLE_AGENT_SUPPORT
 
398
static char *
 
399
percent_plus_escape (char *p, const char *atext)
 
400
{
 
401
  const unsigned char *s;
 
402
 
 
403
  for (s=atext; *s; s++)
 
404
    {
 
405
      if (*s < ' ' || *s == '+')
 
406
        {
 
407
          sprintf (p, "%%%02X", *s);
 
408
          p += 3;
 
409
        }
 
410
      else if (*s == ' ')
 
411
        *p++ = '+';
 
412
      else
 
413
        *p++ = *s;
 
414
    }
 
415
  *p = 0;
 
416
  return p;
 
417
}
 
418
#endif /*ENABLE_AGENT_SUPPORT*/
 
419
 
 
420
 
 
421
#ifdef ENABLE_AGENT_SUPPORT
 
422
 
 
423
/* Object for the agent_okay_cb function.  */
 
424
struct agent_okay_cb_s {
 
425
  char *pw;
 
426
};
 
427
 
 
428
/* A callback used to get the passphrase from the okay line.  See
 
429
   agent-get_passphrase for details.  LINE is the rest of the OK
 
430
   status line without leading white spaces. */
 
431
static assuan_error_t
 
432
agent_okay_cb (void *opaque, const char *line)
 
433
 
434
  struct agent_okay_cb_s *parm = opaque;
 
435
  int i;
 
436
 
 
437
  /* Note: If the malloc below fails we won't be able to wipe the
 
438
     memory at LINE given the current implementation of the Assuan
 
439
     code. There is no easy ay around this w/o adding a lot of more
 
440
     memory function code to allow wiping arbitrary stuff on memory
 
441
     failure. */
 
442
  parm->pw = xmalloc_secure (strlen (line)/2+2);
 
443
  
 
444
  for (i=0; hexdigitp (line) && hexdigitp (line+1); line += 2)
 
445
    parm->pw[i++] = xtoi_2 (line);
 
446
  parm->pw[i] = 0; 
 
447
  return 0;
 
448
}
 
449
#endif /*ENABLE_AGENT_SUPPORT*/
621
450
 
622
451
 
623
452
 
629
458
 *
630
459
 * Note that TRYAGAIN_TEXT must not be translated.  If canceled is not
631
460
 * NULL, the function does set it to 1 if the user canceled the
632
 
 * operation.
 
461
 * operation.  If CACHEID is not NULL, it will be used as the cacheID
 
462
 * for the gpg-agent; if is NULL and a key fingerprint can be
 
463
 * computed, this will be used as the cacheid.
633
464
 */
634
465
static char *
635
 
agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
 
466
agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
 
467
                       const char *tryagain_text,
636
468
                       const char *custom_description,
637
469
                       const char *custom_prompt, int *canceled)
638
470
{
639
 
#if defined(__riscos__)
640
 
  return NULL;
641
 
#else
642
 
  size_t n;
 
471
#ifdef ENABLE_AGENT_SUPPORT
643
472
  char *atext = NULL;
644
 
  char buf[50];
645
 
  int fd = -1;
646
 
  u32 reply;
 
473
  assuan_context_t ctx = NULL;
647
474
  char *pw = NULL;
648
475
  PKT_public_key *pk = m_alloc_clear( sizeof *pk );
649
476
  byte fpr[MAX_FINGERPRINT_LEN];
650
477
  int have_fpr = 0;
651
 
  int prot;
652
478
  char *orig_codeset = NULL;
653
479
 
654
480
  if (canceled)
667
493
    }
668
494
  
669
495
#ifdef ENABLE_NLS
670
 
  /* The Assuan agent protol requires us to transmit utf-8 strings */
 
496
  /* The Assuan agent protocol requires us to transmit utf-8 strings */
671
497
  orig_codeset = bind_textdomain_codeset (PACKAGE, NULL);
672
498
#ifdef HAVE_LANGINFO_CODESET
673
499
  if (!orig_codeset)
681
507
    }
682
508
#endif
683
509
 
684
 
  if ( (fd = agent_open (&prot)) == -1 ) 
 
510
  if ( !(ctx = agent_open (0, orig_codeset)) ) 
685
511
    goto failure;
686
512
 
687
513
  if (custom_description)
740
566
  else
741
567
    atext = m_strdup ( _("Enter passphrase\n") );
742
568
                
743
 
  if (!prot)
744
 
    { /* old style protocol */
745
 
      size_t nread;
746
 
 
747
 
      n = 4 + 20 + strlen (atext);
748
 
      u32tobuf (buf, n );
749
 
      u32tobuf (buf+4, GPGA_PROT_GET_PASSPHRASE );
750
 
      memcpy (buf+8, fpr, 20 );
751
 
      if ( writen ( fd, buf, 28 ) || writen ( fd, atext, strlen (atext) ) ) 
752
 
        goto failure;
753
 
      m_free (atext); atext = NULL;
754
 
      
755
 
      /* get response */
756
 
      if ( readn ( fd, buf, 12, &nread ) ) 
757
 
        goto failure;
758
 
      
759
 
      if ( nread < 8 ) 
760
 
        {
761
 
          log_error ( "response from agent too short\n" );
762
 
          goto failure;
763
 
        }
764
 
      n = buftou32 ( buf );
765
 
      reply = buftou32 ( buf + 4 );
766
 
      if ( reply == GPGA_PROT_GOT_PASSPHRASE ) 
767
 
        {
768
 
          size_t pwlen;
769
 
          size_t nn;
770
 
          
771
 
          if ( nread < 12 || n < 8 ) 
772
 
            {
773
 
              log_error ( "response from agent too short\n" );
774
 
              goto failure;
775
 
            }
776
 
          pwlen = buftou32 ( buf + 8 );
777
 
          nread -= 12;
778
 
          n -= 8;
779
 
          if ( pwlen > n || n > 1000 ) 
780
 
            {
781
 
              log_error (_("passphrase too long\n"));
782
 
              /* or protocol error */
783
 
              goto failure;
784
 
            }
785
 
          /* we read the whole block in one chunk to give no hints
786
 
           * on how long the passhrase actually is - this wastes some bytes
787
 
           * but because we already have this padding we should not loosen
788
 
           * this by issuing 2 read calls */
789
 
          pw = m_alloc_secure ( n+1 );
790
 
          if ( readn ( fd, pw, n, &nn ) )
791
 
            goto failure;
792
 
          if ( n != nn ) 
793
 
            {
794
 
              log_error (_("invalid response from agent\n"));
795
 
              goto failure;           
796
 
            }
797
 
          pw[pwlen] = 0; /* make a C String */
798
 
          agent_close (fd);
799
 
          if (pk)
800
 
            free_public_key( pk );
801
 
#ifdef ENABLE_NLS
802
 
          if (orig_codeset)
803
 
            bind_textdomain_codeset (PACKAGE, orig_codeset);
804
 
#endif
805
 
          m_free (orig_codeset);
806
 
          return pw;
807
 
        }
808
 
      else if ( reply == GPGA_PROT_CANCELED ) 
809
 
        {
810
 
          log_info ( _("cancelled by user\n") );
811
 
          if (canceled)
812
 
            *canceled = 1;
813
 
        }
814
 
      else 
815
 
        log_error ( _("problem with the agent: agent returns 0x%lx\n"),
816
 
                    (ulong)reply );
817
 
    }
818
 
  else
819
 
    { /* The new Assuan protocol */
820
 
      int nread;
 
569
  { 
821
570
      char *line, *p;
822
 
      const unsigned char *s;
823
 
      int i; 
 
571
      int i, rc; 
 
572
      struct agent_okay_cb_s okay_cb_parm;
824
573
 
825
574
      if (!tryagain_text)
826
575
        tryagain_text = "X";
827
576
      else
828
577
        tryagain_text = _(tryagain_text);
829
578
 
830
 
      /* We allocate 2 time the needed space for atext so that there
831
 
         is enough space for escaping */
832
 
      line = m_alloc (15 + 46 
833
 
                      + 3*strlen (tryagain_text)
 
579
      /* We allocate 23 times the needed space for thye texts so that
 
580
         there is enough space for escaping. */
 
581
      line = xmalloc (15 + 46 
834
582
                      + 3*strlen (atext)
835
583
                      + 3*strlen (custom_prompt? custom_prompt:"")
836
 
                      + 2);
 
584
                      + (cacheid? (3*strlen (cacheid)): 0)
 
585
                      + 3*strlen (tryagain_text)
 
586
                      + 1);
837
587
      strcpy (line, "GET_PASSPHRASE ");
838
588
      p = line+15;
839
 
      if (!mode && have_fpr)
 
589
      if (!mode && cacheid)
 
590
        {
 
591
          p = percent_plus_escape (p, cacheid);
 
592
        }
 
593
      else if (!mode && have_fpr)
840
594
        {
841
595
          for (i=0; i < 20; i++, p +=2 )
842
596
            sprintf (p, "%02X", fpr[i]);
843
597
        }
844
598
      else
845
 
        *p++ = 'X'; /* no caching */
 
599
        *p++ = 'X'; /* No caching. */
846
600
      *p++ = ' ';
847
 
      for (i=0, s=tryagain_text; *s; s++)
848
 
        {
849
 
          if (*s < ' ' || *s == '+')
850
 
            {
851
 
              sprintf (p, "%%%02X", *s);
852
 
              p += 3;
853
 
            }
854
 
          else if (*s == ' ')
855
 
            *p++ = '+';
856
 
          else
857
 
            *p++ = *s;
858
 
        }
 
601
 
 
602
      p = percent_plus_escape (p, tryagain_text);
859
603
      *p++ = ' ';
860
604
 
861
605
      /* The prompt.  */
862
606
      if (custom_prompt)
863
607
        {
864
608
          char *tmp = native_to_utf8 (custom_prompt);
865
 
          for (i=0, s=tmp; *s; s++)
866
 
            {
867
 
              if (*s < ' ' || *s == '+')
868
 
                {
869
 
                  sprintf (p, "%%%02X", *s);
870
 
                  p += 3;
871
 
                }
872
 
              else if (*s == ' ')
873
 
                *p++ = '+';
874
 
              else
875
 
                *p++ = *s;
876
 
            }
 
609
          p = percent_plus_escape (p, tmp);
877
610
          xfree (tmp);
878
611
        }
879
612
      else
880
 
        *p++ = 'X'; /* Use the standard prompt */
881
 
 
 
613
        *p++ = 'X'; /* Use the standard prompt. */
882
614
      *p++ = ' ';
883
 
      /* copy description */
884
 
      for (i=0, s= atext; *s; s++)
 
615
 
 
616
      /* Copy description. */
 
617
      percent_plus_escape (p, atext);
 
618
 
 
619
      /* Call gpg-agent.  */
 
620
      memset (&okay_cb_parm, 0, sizeof okay_cb_parm);
 
621
      rc = assuan_transact2 (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL,
 
622
                             agent_okay_cb, &okay_cb_parm);
 
623
 
 
624
      xfree (line);
 
625
      xfree (atext); atext = NULL;
 
626
      if (!rc)
885
627
        {
886
 
          if (*s < ' ' || *s == '+')
887
 
            {
888
 
              sprintf (p, "%%%02X", *s);
889
 
              p += 3;
890
 
            }
891
 
          else if (*s == ' ')
892
 
            *p++ = '+';
893
 
          else
894
 
            *p++ = *s;
895
 
        }
896
 
      *p++ = '\n';
897
 
      i = writen (fd, line, p - line);
898
 
      m_free (line);
899
 
      if (i)
900
 
        goto failure;
901
 
      m_free (atext); atext = NULL;
902
 
      
903
 
      /* get response */
904
 
      pw = m_alloc_secure (500);
905
 
      nread = readaline (fd, pw, 499);
906
 
      if (nread < 3)
907
 
        goto failure;
908
 
      
909
 
      if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ') 
910
 
        { /* we got a passphrase - convert it back from hex */
911
 
          size_t pwlen = 0;
912
 
 
913
 
          for (i=3; i < nread && hexdigitp (pw+i); i+=2)
914
 
            pw[pwlen++] = xtoi_2 (pw+i);
915
 
          pw[pwlen] = 0; /* make a C String */
916
 
          agent_close (fd);
 
628
          assert (okay_cb_parm.pw);
 
629
          pw = okay_cb_parm.pw;
 
630
          agent_close (ctx);
917
631
          if (pk)
918
632
            free_public_key( pk );
919
633
#ifdef ENABLE_NLS
920
634
          if (orig_codeset)
921
635
            bind_textdomain_codeset (PACKAGE, orig_codeset);
922
636
#endif
923
 
          m_free (orig_codeset);
 
637
          xfree (orig_codeset);
924
638
          return pw;
925
639
        }
926
 
      else if (nread > 4 && !memcmp (pw, "ERR ", 4)
927
 
               && (0xffff & strtoul (&pw[4], NULL, 0)) == 99)
 
640
      else if (rc && (rc & 0xffff) == 99)
928
641
        {
929
 
          /* 99 is GPG_ERR_CANCELED.  FIXME: Check tail and overflow,
930
 
             and use gpg-error.  */
 
642
          /* 99 is GPG_ERR_CANCELED. */
931
643
          log_info (_("cancelled by user\n") );
932
644
          if (canceled)
933
645
            *canceled = 1;
937
649
          log_error (_("problem with the agent - disabling agent use\n"));
938
650
          opt.use_agent = 0;
939
651
        }
940
 
    }
 
652
  }
941
653
      
942
654
        
943
655
 failure:
944
656
#ifdef ENABLE_NLS
945
657
  if (orig_codeset)
946
 
    bind_textdomain_codeset (PACKAGE, orig_codeset);
 
658
    {
 
659
      bind_textdomain_codeset (PACKAGE, orig_codeset);
 
660
      xfree (orig_codeset);
 
661
    }
947
662
#endif
948
 
  m_free (atext);
949
 
  if ( fd != -1 )
950
 
    agent_close (fd);
951
 
  m_free (pw );
 
663
  xfree (atext);
 
664
  agent_close (ctx);
 
665
  xfree (pw );
952
666
  if (pk)
953
667
    free_public_key( pk );
954
 
  
 
668
 
 
669
#endif /*ENABLE_AGENT_SUPPORT*/
 
670
 
955
671
  return NULL;
956
 
#endif /* Posix or W32 */
957
672
}
958
673
 
 
674
 
959
675
/*
960
 
 * Clear the cached passphrase
 
676
 * Clear the cached passphrase.  If CACHEID is not NULL, it will be
 
677
 * used instead of a cache ID derived from KEYID.
961
678
 */
962
679
void
963
 
passphrase_clear_cache ( u32 *keyid, int algo )
 
680
passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
964
681
{
965
 
#if defined(__riscos__)
966
 
  return ;
967
 
#else
968
 
  size_t n;
969
 
  char buf[200];
970
 
  int fd = -1;
971
 
  size_t nread;
972
 
  u32 reply;
 
682
#ifdef ENABLE_AGENT_SUPPORT
 
683
  assuan_context_t ctx = NULL;
973
684
  PKT_public_key *pk;
974
685
  byte fpr[MAX_FINGERPRINT_LEN];
975
 
  int prot;
976
686
  
977
687
#if MAX_FINGERPRINT_LEN < 20
978
688
#error agent needs a 20 byte fingerprint
981
691
  if (!opt.use_agent)
982
692
    return;
983
693
  
984
 
  pk = m_alloc_clear ( sizeof *pk );
985
 
  memset (fpr, 0, MAX_FINGERPRINT_LEN );
986
 
  if( !keyid || get_pubkey( pk, keyid ) )
 
694
  if (!cacheid)
987
695
    {
988
 
      goto failure; /* oops: no key for some reason */
 
696
      pk = xcalloc (1, sizeof *pk);
 
697
      memset (fpr, 0, MAX_FINGERPRINT_LEN );
 
698
      if( !keyid || get_pubkey( pk, keyid ) )
 
699
        {
 
700
          goto failure; /* oops: no key for some reason */
 
701
        }
 
702
  
 
703
      {
 
704
        size_t dummy;
 
705
        fingerprint_from_pk( pk, fpr, &dummy );
 
706
      }
989
707
    }
990
 
  
991
 
  {
992
 
    size_t dummy;
993
 
    fingerprint_from_pk( pk, fpr, &dummy );
994
 
  }
 
708
  else
 
709
    pk = NULL;
995
710
    
996
 
  if ( (fd = agent_open (&prot)) == -1 ) 
 
711
  if ( !(ctx = agent_open (0, NULL)) ) 
997
712
    goto failure;
998
713
 
999
 
  if (!prot)
1000
 
    {
1001
 
      n = 4 + 20;
1002
 
      u32tobuf (buf, n );
1003
 
      u32tobuf (buf+4, GPGA_PROT_CLEAR_PASSPHRASE );
1004
 
      memcpy (buf+8, fpr, 20 );
1005
 
      if ( writen ( fd, buf, 28 ) )  
1006
 
        goto failure;
1007
 
      
1008
 
      /* get response */
1009
 
      if ( readn ( fd, buf, 8, &nread ) ) 
1010
 
        goto failure;
1011
 
      
1012
 
      if ( nread < 8 ) {
1013
 
        log_error ( "response from agent too short\n" );
1014
 
        goto failure;
1015
 
      }
1016
 
      
1017
 
      reply = buftou32 ( buf + 4 );
1018
 
      if ( reply != GPGA_PROT_OKAY && reply != GPGA_PROT_NO_PASSPHRASE )
1019
 
        {
1020
 
          log_error ( _("problem with the agent: agent returns 0x%lx\n"),
1021
 
                      (ulong)reply );
1022
 
        }
1023
 
    }
1024
 
  else 
1025
 
    { /* The assuan protocol */
 
714
  { 
1026
715
      char *line, *p;
1027
 
      int i; 
1028
 
 
1029
 
      line = m_alloc (17 + 40 + 2);
1030
 
      strcpy (line, "CLEAR_PASSPHRASE ");
1031
 
      p = line+17;
1032
 
      for (i=0; i < 20; i++, p +=2 )
1033
 
        sprintf (p, "%02X", fpr[i]);
1034
 
      *p++ = '\n';
1035
 
      i = writen (fd, line, p - line);
1036
 
      m_free (line);
1037
 
      if (i)
1038
 
        goto failure;
1039
 
      
1040
 
      /* get response */
1041
 
      nread = readaline (fd, buf, DIM(buf)-1);
1042
 
      if (nread < 3)
1043
 
        goto failure;
1044
 
      
1045
 
      if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n')) 
1046
 
        ;
1047
 
      else 
 
716
      int i, rc; 
 
717
 
 
718
      if (cacheid)
 
719
        {
 
720
          line = xmalloc (17 + 3*strlen (cacheid) + 2);
 
721
          strcpy (line, "CLEAR_PASSPHRASE ");
 
722
          p = line+17;
 
723
          p = percent_plus_escape (p, cacheid);
 
724
        }
 
725
      else
 
726
        {
 
727
          line = xmalloc (17 + 40 + 2);
 
728
          strcpy (line, "CLEAR_PASSPHRASE ");
 
729
          p = line+17;
 
730
          for (i=0; i < 20; i++, p +=2 )
 
731
            sprintf (p, "%02X", fpr[i]);
 
732
        }
 
733
      *p = 0;
 
734
 
 
735
      rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
 
736
      xfree (line);
 
737
      if (rc)
1048
738
        {
1049
739
          log_error (_("problem with the agent - disabling agent use\n"));
1050
740
          opt.use_agent = 0;
1052
742
    }
1053
743
        
1054
744
 failure:
1055
 
  if (fd != -1)
1056
 
    agent_close (fd);
 
745
  agent_close (ctx);
1057
746
  if (pk)
1058
747
    free_public_key( pk );
1059
 
#endif /* Posix or W32 */
 
748
#endif /*ENABLE_AGENT_SUPPORT*/
1060
749
}
1061
750
 
1062
751
 
1067
756
ask_passphrase (const char *description,
1068
757
                const char *tryagain_text,
1069
758
                const char *promptid,
1070
 
                const char *prompt, int *canceled)
 
759
                const char *prompt,
 
760
                const char *cacheid, int *canceled)
1071
761
{
1072
762
  char *pw = NULL;
1073
763
  
1075
765
    *canceled = 0;
1076
766
 
1077
767
  if (!opt.batch && description)
1078
 
    tty_printf ("\n%s\n",description);
 
768
    {
 
769
      if (strchr (description, '%'))
 
770
        {
 
771
          char *tmp = unescape_percent_string (description);
 
772
          tty_printf ("\n%s\n", tmp);
 
773
          xfree (tmp);
 
774
        }
 
775
      else
 
776
        tty_printf ("\n%s\n",description);
 
777
    }
1079
778
               
1080
779
 agent_died:
1081
780
  if ( opt.use_agent ) 
1082
781
    {
1083
 
      pw = agent_get_passphrase (NULL, 0,
 
782
      pw = agent_get_passphrase (NULL, 0, cacheid,
1084
783
                                 tryagain_text, description, prompt,
1085
784
                                 canceled );
1086
785
      if (!pw)
1224
923
    }
1225
924
    else if ( opt.use_agent ) {
1226
925
      /* Divert to the gpg-agent. */
1227
 
        pw = agent_get_passphrase ( keyid, mode == 2? 1: 0,
 
926
        pw = agent_get_passphrase ( keyid, mode == 2? 1: 0, NULL,
1228
927
                                    tryagain_text, NULL, NULL, canceled );
1229
928
        if (!pw)
1230
929
          {
1233
932
            pw = m_strdup ("");
1234
933
          }
1235
934
        if( *pw && mode == 2 ) {
1236
 
          char *pw2 = agent_get_passphrase ( keyid, 2, NULL, NULL,
 
935
            char *pw2 = agent_get_passphrase ( keyid, 2, NULL, NULL, NULL,
1237
936
                                               NULL, canceled );
1238
937
            if (!pw2)
1239
938
              {