52
53
#include "status.h"
55
enum gpga_protocol_codes {
57
GPGA_PROT_GET_VERSION = 1,
58
GPGA_PROT_GET_PASSPHRASE = 2,
59
GPGA_PROT_CLEAR_PASSPHRASE= 3,
60
GPGA_PROT_SHUTDOWN = 4,
64
GPGA_PROT_REPLY_BASE = 0x10000,
65
GPGA_PROT_OKAY = 0x10001,
66
GPGA_PROT_GOT_PASSPHRASE = 0x10002,
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
54
#ifdef ENABLE_AGENT_SUPPORT
56
#endif /*ENABLE_AGENT_SUPPORT*/
81
59
#define buftou32( p ) ((*(byte*)(p) << 24) | (*((byte*)(p)+1)<< 16) | \
195
writen (int fd, const void *buf, size_t nbytes)
198
DWORD nwritten, nleft = nbytes;
202
if (!WriteFile ((HANDLE)write_fd, buf, nleft, &nwritten, NULL))
204
log_error ("write failed: %s\n", w32_strerror (0));
207
/*log_info ("** WriteFile fd=%d nytes=%d nwritten=%d\n",
208
write_fd, nbytes, (int)nwritten);*/
212
buf = (const BYTE *)buf + nwritten;
214
#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
215
/* not implemented */
217
size_t nleft = nbytes;
222
nwritten = write (fd, buf, nleft);
229
log_error ("write() failed: %s\n", strerror (errno));
234
buf = (const char*)buf + nwritten;
243
readn (int fd, void *buf, size_t buflen, size_t *ret_nread)
246
DWORD nread, nleft = buflen;
250
if (!ReadFile ((HANDLE)read_fd, buf, nleft, &nread, NULL))
252
log_error ("read() error: %s\n", w32_strerror (0));
255
if (!nread || GetLastError() == ERROR_BROKEN_PIPE)
257
/*log_info ("** ReadFile fd=%d buflen=%d nread=%d\n",
258
read_fd, buflen, (int)nread);*/
262
buf = (BYTE *)buf + nread;
265
*ret_nread = buflen - nleft;
267
#elif defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
268
/* not implemented */
270
size_t nleft = buflen;
277
nread = read ( fd, buf, nleft );
284
log_error ( "read() error: %s\n", strerror (errno) );
291
buf = (char*)buf + nread;
294
*ret_nread = buflen - nleft;
300
/* read an entire line */
302
readaline (int fd, char *buf, size_t buflen)
304
size_t nleft = buflen;
310
int n = read (fd, buf, nleft);
315
return -1; /* read error */
319
return -1; /* incomplete line */
326
for (; n && *p != '\n'; n--, p++)
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 */
342
#if !defined (__riscos__)
344
#if !defined (_WIN32)
345
/* For the new Assuan protocol we may have to send options */
347
agent_send_option (int fd, const char *name, const char *value)
167
#ifdef ENABLE_AGENT_SUPPORT
168
/* Send one option to the gpg-agent. */
170
agent_send_option (assuan_context_t ctx, const char *name, const char *value)
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));
363
nread = readaline (fd, buf, DIM(buf)-1);
367
if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
175
if (!value || !*value)
176
return 0; /* Avoid sending empty option values. */
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);
185
/* Send all required options to the gpg-agent. */
374
agent_send_all_options (int fd)
187
agent_send_all_options (assuan_context_t ctx)
376
189
char *dft_display = NULL;
377
190
const char *dft_ttyname = NULL;
270
#endif /*ENABLE_AGENT_SUPPORT*/
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.
466
agent_open (int *ret_prot)
475
if ( !(infostr = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
477
|| *infostr == '0') {
478
log_error( _("gpg-agent is not available in this session\n"));
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") );
489
h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent");
491
Sleep(50); /* some time for the server */
492
if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
494
log_error( _("can't get server read FD for the agent\n") );
499
if ( !(p = read_w32_registry_string(NULL, "Software\\GNU\\GnuPG",
501
log_error ( _("can't get server write FD for the agent\n") );
508
if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) {
515
struct sockaddr_un client_addr;
519
if (opt.gpg_agent_info)
520
infostr = m_strdup (opt.gpg_agent_info);
523
infostr = getenv ( "GPG_AGENT_INFO" );
525
log_error (_("gpg-agent is not available in this session\n"));
529
infostr = m_strdup ( infostr );
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"));
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 != ':')
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);
554
if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 ) {
555
log_error ("can't create socket: %s\n", strerror(errno) );
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;
567
if( connect( fd, (struct sockaddr*)&client_addr, len ) == -1 ) {
568
log_error ( _("can't connect to `%s': %s\n"),
569
infostr, strerror (errno) );
578
if ( writen ( fd, "GPGA\0\0\0\x01", 8 ) ) {
583
else { /* assuan based gpg-agent */
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"));
596
if (agent_send_all_options (fd)) {
597
log_error (_("problem with the agent - disabling agent use\n"));
611
agent_close ( int fd )
614
HANDLE h = OpenEvent(EVENT_ALL_ACCESS, FALSE, "gpg_agent");
620
#endif /* !__riscos__ */
281
#ifdef ENABLE_AGENT_SUPPORT
283
agent_open (int try, const char *orig_codeset)
286
assuan_context_t ctx;
291
if (opt.gpg_agent_info)
292
infostr = xstrdup (opt.gpg_agent_info);
295
infostr = getenv ( "GPG_AGENT_INFO" );
296
if (!infostr || !*infostr)
302
bind_textdomain_codeset (PACKAGE, orig_codeset);
303
#endif /*ENABLE_NLS*/
304
log_error (_("gpg-agent is not available in this session\n"));
309
infostr = xstrdup ( infostr );
312
if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
318
bind_textdomain_codeset (PACKAGE, orig_codeset);
319
#endif /*ENABLE_NLS*/
320
log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
328
while (*p && *p != PATHSEP_C)
330
prot = *p? atoi (p+1) : 0;
337
bind_textdomain_codeset (PACKAGE, orig_codeset);
338
#endif /*ENABLE_NLS*/
339
log_error (_("gpg-agent protocol version %d is not supported\n"),
347
rc = assuan_socket_connect (&ctx, infostr, pid);
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));
365
if (agent_send_all_options (ctx))
371
bind_textdomain_codeset (PACKAGE, orig_codeset);
372
#endif /*ENABLE_NLS*/
373
log_error (_("problem with the agent - disabling agent use\n"));
376
assuan_disconnect (ctx);
382
#endif/*ENABLE_AGENT_SUPPORT*/
385
#ifdef ENABLE_AGENT_SUPPORT
387
agent_close (assuan_context_t ctx)
389
assuan_disconnect (ctx);
391
#endif /*ENABLE_AGENT_SUPPORT*/
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
399
percent_plus_escape (char *p, const char *atext)
401
const unsigned char *s;
403
for (s=atext; *s; s++)
405
if (*s < ' ' || *s == '+')
407
sprintf (p, "%%%02X", *s);
418
#endif /*ENABLE_AGENT_SUPPORT*/
421
#ifdef ENABLE_AGENT_SUPPORT
423
/* Object for the agent_okay_cb function. */
424
struct agent_okay_cb_s {
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)
434
struct agent_okay_cb_s *parm = opaque;
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
442
parm->pw = xmalloc_secure (strlen (line)/2+2);
444
for (i=0; hexdigitp (line) && hexdigitp (line+1); line += 2)
445
parm->pw[i++] = xtoi_2 (line);
449
#endif /*ENABLE_AGENT_SUPPORT*/
741
567
atext = m_strdup ( _("Enter passphrase\n") );
744
{ /* old style protocol */
747
n = 4 + 20 + strlen (atext);
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) ) )
753
m_free (atext); atext = NULL;
756
if ( readn ( fd, buf, 12, &nread ) )
761
log_error ( "response from agent too short\n" );
764
n = buftou32 ( buf );
765
reply = buftou32 ( buf + 4 );
766
if ( reply == GPGA_PROT_GOT_PASSPHRASE )
771
if ( nread < 12 || n < 8 )
773
log_error ( "response from agent too short\n" );
776
pwlen = buftou32 ( buf + 8 );
779
if ( pwlen > n || n > 1000 )
781
log_error (_("passphrase too long\n"));
782
/* or protocol error */
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 ) )
794
log_error (_("invalid response from agent\n"));
797
pw[pwlen] = 0; /* make a C String */
800
free_public_key( pk );
803
bind_textdomain_codeset (PACKAGE, orig_codeset);
805
m_free (orig_codeset);
808
else if ( reply == GPGA_PROT_CANCELED )
810
log_info ( _("cancelled by user\n") );
815
log_error ( _("problem with the agent: agent returns 0x%lx\n"),
819
{ /* The new Assuan protocol */
822
const unsigned char *s;
572
struct agent_okay_cb_s okay_cb_parm;
825
574
if (!tryagain_text)
826
575
tryagain_text = "X";
828
577
tryagain_text = _(tryagain_text);
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:"")
584
+ (cacheid? (3*strlen (cacheid)): 0)
585
+ 3*strlen (tryagain_text)
837
587
strcpy (line, "GET_PASSPHRASE ");
839
if (!mode && have_fpr)
589
if (!mode && cacheid)
591
p = percent_plus_escape (p, cacheid);
593
else if (!mode && have_fpr)
841
595
for (i=0; i < 20; i++, p +=2 )
842
596
sprintf (p, "%02X", fpr[i]);
845
*p++ = 'X'; /* no caching */
599
*p++ = 'X'; /* No caching. */
847
for (i=0, s=tryagain_text; *s; s++)
849
if (*s < ' ' || *s == '+')
851
sprintf (p, "%%%02X", *s);
602
p = percent_plus_escape (p, tryagain_text);
861
605
/* The prompt. */
862
606
if (custom_prompt)
864
608
char *tmp = native_to_utf8 (custom_prompt);
865
for (i=0, s=tmp; *s; s++)
867
if (*s < ' ' || *s == '+')
869
sprintf (p, "%%%02X", *s);
609
p = percent_plus_escape (p, tmp);
880
*p++ = 'X'; /* Use the standard prompt */
613
*p++ = 'X'; /* Use the standard prompt. */
883
/* copy description */
884
for (i=0, s= atext; *s; s++)
616
/* Copy description. */
617
percent_plus_escape (p, atext);
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);
625
xfree (atext); atext = NULL;
886
if (*s < ' ' || *s == '+')
888
sprintf (p, "%%%02X", *s);
897
i = writen (fd, line, p - line);
901
m_free (atext); atext = NULL;
904
pw = m_alloc_secure (500);
905
nread = readaline (fd, pw, 499);
909
if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ')
910
{ /* we got a passphrase - convert it back from hex */
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 */
628
assert (okay_cb_parm.pw);
629
pw = okay_cb_parm.pw;
918
632
free_public_key( pk );
919
633
#ifdef ENABLE_NLS
920
634
if (orig_codeset)
921
635
bind_textdomain_codeset (PACKAGE, orig_codeset);
923
m_free (orig_codeset);
637
xfree (orig_codeset);
926
else if (nread > 4 && !memcmp (pw, "ERR ", 4)
927
&& (0xffff & strtoul (&pw[4], NULL, 0)) == 99)
640
else if (rc && (rc & 0xffff) == 99)
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") );
981
691
if (!opt.use_agent)
984
pk = m_alloc_clear ( sizeof *pk );
985
memset (fpr, 0, MAX_FINGERPRINT_LEN );
986
if( !keyid || get_pubkey( pk, keyid ) )
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 ) )
700
goto failure; /* oops: no key for some reason */
705
fingerprint_from_pk( pk, fpr, &dummy );
993
fingerprint_from_pk( pk, fpr, &dummy );
996
if ( (fd = agent_open (&prot)) == -1 )
711
if ( !(ctx = agent_open (0, NULL)) )
1003
u32tobuf (buf+4, GPGA_PROT_CLEAR_PASSPHRASE );
1004
memcpy (buf+8, fpr, 20 );
1005
if ( writen ( fd, buf, 28 ) )
1009
if ( readn ( fd, buf, 8, &nread ) )
1013
log_error ( "response from agent too short\n" );
1017
reply = buftou32 ( buf + 4 );
1018
if ( reply != GPGA_PROT_OKAY && reply != GPGA_PROT_NO_PASSPHRASE )
1020
log_error ( _("problem with the agent: agent returns 0x%lx\n"),
1025
{ /* The assuan protocol */
1029
line = m_alloc (17 + 40 + 2);
1030
strcpy (line, "CLEAR_PASSPHRASE ");
1032
for (i=0; i < 20; i++, p +=2 )
1033
sprintf (p, "%02X", fpr[i]);
1035
i = writen (fd, line, p - line);
1041
nread = readaline (fd, buf, DIM(buf)-1);
1045
if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
720
line = xmalloc (17 + 3*strlen (cacheid) + 2);
721
strcpy (line, "CLEAR_PASSPHRASE ");
723
p = percent_plus_escape (p, cacheid);
727
line = xmalloc (17 + 40 + 2);
728
strcpy (line, "CLEAR_PASSPHRASE ");
730
for (i=0; i < 20; i++, p +=2 )
731
sprintf (p, "%02X", fpr[i]);
735
rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
1049
739
log_error (_("problem with the agent - disabling agent use\n"));
1050
740
opt.use_agent = 0;