1 /* simple-pwquery.c - A simple password query client for gpg-agent
2 * Copyright (C) 2002, 2004, 2007 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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/>.
20 /* This module is intended as a standalone client implementation to
21 gpg-agent's GET_PASSPHRASE command. In particular it does not use
22 the Assuan library and can only cope with an already running
23 gpg-agent. Some stuff is configurable in the header file. */
33 #ifdef HAVE_W32_SYSTEM
36 #include <sys/socket.h>
42 #ifdef HAVE_W32_SYSTEM
43 #include "../jnlib/w32-afunix.h"
47 #define SIMPLE_PWQUERY_IMPLEMENTATION 1
48 #include "simple-pwquery.h"
50 #if defined(SPWQ_USE_LOGGING) && !defined(HAVE_JNLIB_LOGGING)
51 # undef SPWQ_USE_LOGGING
58 #if !defined (hexdigitp) && !defined (xtoi_2)
59 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
60 #define hexdigitp(a) (digitp (a) \
61 || (*(a) >= 'A' && *(a) <= 'F') \
62 || (*(a) >= 'a' && *(a) <= 'f'))
63 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
64 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
65 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
69 /* Name of the socket to be used if GPG_AGENT_INFO has not been
70 set. No default socket is used if this is NULL. */
71 static char *default_gpg_agent_info
;
80 my_stpcpy(char *a
,const char *b
)
88 #define stpcpy(a,b) my_stpcpy((a), (b))
93 /* Write NBYTES of BUF to file descriptor FD. */
95 writen (int fd
, const void *buf
, size_t nbytes
)
97 size_t nleft
= nbytes
;
102 #ifdef HAVE_W32_SYSTEM
103 nwritten
= send (fd
, buf
, nleft
, 0);
105 nwritten
= write (fd
, buf
, nleft
);
112 #ifdef SPWQ_USE_LOGGING
113 log_error ("write failed: %s\n", strerror (errno
));
115 return SPWQ_IO_ERROR
;
119 buf
= (const char*)buf
+ nwritten
;
126 /* Read an entire line and return number of bytes read. */
128 readline (int fd
, char *buf
, size_t buflen
)
130 size_t nleft
= buflen
;
136 #ifdef HAVE_W32_SYSTEM
137 int n
= recv (fd
, buf
, nleft
, 0);
139 int n
= read (fd
, buf
, nleft
);
145 return -(SPWQ_IO_ERROR
);
149 return -(SPWQ_PROTOCOL_ERROR
); /* incomplete line */
156 for (; n
&& *p
!= '\n'; n
--, p
++)
160 break; /* At least one full line available - that's enough.
161 This function is just a simple implementation, so
162 it is okay to forget about pending bytes. */
170 /* Send an option to the agent */
172 agent_send_option (int fd
, const char *name
, const char *value
)
179 line
= spwq_malloc (7 + strlen (name
) + 1 + strlen (value
) + 2);
181 return SPWQ_OUT_OF_CORE
;
182 strcpy (stpcpy (stpcpy (stpcpy (
183 stpcpy (line
, "OPTION "), name
), "="), value
), "\n");
184 i
= writen (fd
, line
, strlen (line
));
190 nread
= readline (fd
, buf
, DIM(buf
)-1);
194 return SPWQ_PROTOCOL_ERROR
;
196 if (buf
[0] == 'O' && buf
[1] == 'K' && (buf
[2] == ' ' || buf
[2] == '\n'))
199 return SPWQ_ERR_RESPONSE
;
203 /* Send all available options to the agent. */
205 agent_send_all_options (int fd
)
207 char *dft_display
= NULL
;
208 char *dft_ttyname
= NULL
;
209 char *dft_ttytype
= NULL
;
210 char *dft_xauthority
= NULL
;
211 char *dft_pinentry_user_data
= NULL
;
214 dft_display
= getenv ("DISPLAY");
217 if ((rc
= agent_send_option (fd
, "display", dft_display
)))
221 dft_ttyname
= getenv ("GPG_TTY");
222 #ifndef HAVE_W32_SYSTEM
223 if ((!dft_ttyname
|| !*dft_ttyname
) && ttyname (0))
224 dft_ttyname
= ttyname (0);
226 if (dft_ttyname
&& *dft_ttyname
)
228 if ((rc
=agent_send_option (fd
, "ttyname", dft_ttyname
)))
232 dft_ttytype
= getenv ("TERM");
233 if (dft_ttyname
&& dft_ttytype
)
235 if ((rc
= agent_send_option (fd
, "ttytype", dft_ttytype
)))
239 #if defined(HAVE_SETLOCALE)
244 #if defined(LC_CTYPE)
245 old_lc
= setlocale (LC_CTYPE
, NULL
);
248 char *p
= spwq_malloc (strlen (old_lc
)+1);
250 return SPWQ_OUT_OF_CORE
;
254 dft_lc
= setlocale (LC_CTYPE
, "");
255 if (dft_ttyname
&& dft_lc
)
256 rc
= agent_send_option (fd
, "lc-ctype", dft_lc
);
259 setlocale (LC_CTYPE
, old_lc
);
266 #if defined(LC_MESSAGES)
267 old_lc
= setlocale (LC_MESSAGES
, NULL
);
270 char *p
= spwq_malloc (strlen (old_lc
)+1);
272 return SPWQ_OUT_OF_CORE
;
276 dft_lc
= setlocale (LC_MESSAGES
, "");
277 if (dft_ttyname
&& dft_lc
)
278 rc
= agent_send_option (fd
, "lc-messages", dft_lc
);
281 setlocale (LC_MESSAGES
, old_lc
);
288 #endif /*HAVE_SETLOCALE*/
290 /* Send the XAUTHORITY variable. */
291 dft_xauthority
= getenv ("XAUTHORITY");
294 /* We ignore errors here because older gpg-agents don't support
296 agent_send_option (fd
, "xauthority", dft_xauthority
);
299 /* Send the PINENTRY_USER_DATA variable. */
300 dft_pinentry_user_data
= getenv ("PINENTRY_USER_DATA");
301 if (dft_pinentry_user_data
)
303 /* We ignore errors here because older gpg-agents don't support
305 agent_send_option (fd
, "pinentry-user-data", dft_pinentry_user_data
);
313 /* Try to open a connection to the agent, send all options and return
314 the file descriptor for the connection. Return -1 in case of
317 agent_open (int *rfd
)
322 struct sockaddr_un client_addr
;
329 infostr
= getenv ( "GPG_AGENT_INFO" );
330 if ( !infostr
|| !*infostr
)
331 infostr
= default_gpg_agent_info
;
332 if ( !infostr
|| !*infostr
)
334 #ifdef SPWQ_USE_LOGGING
335 log_error (_("gpg-agent is not available in this session\n"));
337 return SPWQ_NO_AGENT
;
339 p
= spwq_malloc (strlen (infostr
)+1);
341 return SPWQ_OUT_OF_CORE
;
345 if ( !(p
= strchr ( infostr
, PATHSEP_C
)) || p
== infostr
346 || (p
-infostr
)+1 >= sizeof client_addr
.sun_path
)
348 #ifdef SPWQ_USE_LOGGING
349 log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
351 return SPWQ_NO_AGENT
;
355 while (*p
&& *p
!= PATHSEP_C
)
357 prot
= *p
? atoi (p
+1) : 0;
360 #ifdef SPWQ_USE_LOGGING
361 log_error (_("gpg-agent protocol version %d is not supported\n"),prot
);
363 return SPWQ_PROTOCOL_ERROR
;
366 #ifdef HAVE_W32_SYSTEM
367 fd
= _w32_sock_new (AF_UNIX
, SOCK_STREAM
, 0);
369 fd
= socket (AF_UNIX
, SOCK_STREAM
, 0);
373 #ifdef SPWQ_USE_LOGGING
374 log_error ("can't create socket: %s\n", strerror(errno
) );
376 return SPWQ_SYS_ERROR
;
379 memset (&client_addr
, 0, sizeof client_addr
);
380 client_addr
.sun_family
= AF_UNIX
;
381 strcpy (client_addr
.sun_path
, infostr
);
382 len
= (offsetof (struct sockaddr_un
, sun_path
)
383 + strlen(client_addr
.sun_path
) + 1);
385 #ifdef HAVE_W32_SYSTEM
386 rc
= _w32_sock_connect (fd
, (struct sockaddr
*)&client_addr
, len
);
388 rc
= connect (fd
, (struct sockaddr
*)&client_addr
, len
);
392 #ifdef SPWQ_USE_LOGGING
393 log_error ( _("can't connect to `%s': %s\n"), infostr
, strerror (errno
));
396 return SPWQ_IO_ERROR
;
399 nread
= readline (fd
, line
, DIM(line
));
400 if (nread
< 3 || !(line
[0] == 'O' && line
[1] == 'K'
401 && (line
[2] == '\n' || line
[2] == ' ')) )
403 #ifdef SPWQ_USE_LOGGING
404 log_error ( _("communication problem with gpg-agent\n"));
407 return SPWQ_PROTOCOL_ERROR
;
410 rc
= agent_send_all_options (fd
);
413 #ifdef SPWQ_USE_LOGGING
414 log_error (_("problem setting the gpg-agent options\n"));
425 /* Copy text to BUFFER and escape as required. Return a pointer to
426 the end of the new buffer. Note that BUFFER must be large enough
427 to keep the entire text; allocataing it 3 times the size of TEXT
430 copy_and_escape (char *buffer
, const char *text
)
433 const unsigned char *s
= (unsigned char *)text
;
439 if (s
[i
] < ' ' || s
[i
] == '+')
441 sprintf (p
, "%%%02X", s
[i
]);
444 else if (s
[i
] == ' ')
453 /* Set the name of the default socket to NAME. */
455 simple_pw_set_socket (const char *name
)
457 spwq_free (default_gpg_agent_info
);
460 default_gpg_agent_info
= spwq_malloc (strlen (name
) + 4 + 1);
461 if (!default_gpg_agent_info
)
462 return SPWQ_OUT_OF_CORE
;
463 /* We don't know the PID thus we use 0. */
464 strcpy (stpcpy (default_gpg_agent_info
, name
),
465 PATHSEP_S
"0" PATHSEP_S
"1");
468 default_gpg_agent_info
= NULL
;
474 /* Ask the gpg-agent for a passphrase and present the user with a
475 DESCRIPTION, a PROMPT and optionally with a TRYAGAIN extra text.
476 If a CACHEID is not NULL it is used to locate the passphrase in in
477 the cache and store it under this ID. If OPT_CHECK is true
478 gpg-agent is asked to apply some checks on the passphrase security.
479 If ERRORCODE is not NULL it should point a variable receiving an
480 errorcode; this error code might be 0 if the user canceled the
481 operation. The function returns NULL to indicate an error. */
483 simple_pwquery (const char *cacheid
,
484 const char *tryagain
,
486 const char *description
,
497 rc
= agent_open (&fd
);
512 /* We allocate 3 times the needed space so that there is enough
513 space for escaping. */
514 line
= spwq_malloc (15 + 10
515 + 3*strlen (cacheid
) + 1
516 + 3*strlen (tryagain
) + 1
517 + 3*strlen (prompt
) + 1
518 + 3*strlen (description
) + 1
522 rc
= SPWQ_OUT_OF_CORE
;
525 strcpy (line
, "GET_PASSPHRASE ");
528 p
= stpcpy (p
, "--check ");
529 p
= copy_and_escape (p
, cacheid
);
531 p
= copy_and_escape (p
, tryagain
);
533 p
= copy_and_escape (p
, prompt
);
535 p
= copy_and_escape (p
, description
);
537 rc
= writen (fd
, line
, p
- line
);
544 pw
= spwq_secure_malloc (500);
545 nread
= readline (fd
, pw
, 499);
553 rc
= SPWQ_PROTOCOL_ERROR
;
557 if (pw
[0] == 'O' && pw
[1] == 'K' && pw
[2] == ' ')
558 { /* we got a passphrase - convert it back from hex */
561 for (i
=3; i
< nread
&& hexdigitp (pw
+i
); i
+=2)
562 pw
[pwlen
++] = xtoi_2 (pw
+i
);
563 pw
[pwlen
] = 0; /* make a C String */
567 else if ((nread
> 7 && !memcmp (pw
, "ERR 111", 7)
568 && (pw
[7] == ' ' || pw
[7] == '\n') )
569 || ((nread
> 4 && !memcmp (pw
, "ERR ", 4)
570 && (strtoul (pw
+4, NULL
, 0) & 0xffff) == 99)) )
572 /* 111 is the old Assuan code for canceled which might still
573 be in use by old installations. 99 is GPG_ERR_CANCELED as
574 used by modern gpg-agents; 0xffff is used to mask out the
576 #ifdef SPWQ_USE_LOGGING
577 log_info (_("canceled by user\n") );
579 *errorcode
= 0; /* Special error code to indicate Cancel. */
581 else if (nread
> 4 && !memcmp (pw
, "ERR ", 4))
583 switch ( (strtoul (pw
+4, NULL
, 0) & 0xffff) )
585 case 85: rc
= SPWQ_NO_PIN_ENTRY
; break;
586 default: rc
= SPWQ_GENERAL_ERROR
; break;
591 #ifdef SPWQ_USE_LOGGING
592 log_error (_("problem with the agent\n"));
594 rc
= SPWQ_ERR_RESPONSE
;
603 spwq_secure_free (pw
);
608 /* Ask the gpg-agent to clear the passphrase for the cache ID CACHEID. */
610 simple_pwclear (const char *cacheid
)
615 /* We need not more than 50 characters for the command and the
617 if (strlen (cacheid
) * 3 > sizeof (line
) - 50)
618 return SPWQ_PROTOCOL_ERROR
;
620 strcpy (line
, "CLEAR_PASSPHRASE ");
622 p
= copy_and_escape (p
, cacheid
);
626 return simple_query (line
);
630 /* Perform the simple query QUERY (which must be new-line and 0
631 terminated) and return the error code. */
633 simple_query (const char *query
)
640 rc
= agent_open (&fd
);
644 rc
= writen (fd
, query
, strlen (query
));
649 nread
= readline (fd
, response
, 499);
657 rc
= SPWQ_PROTOCOL_ERROR
;
661 if (response
[0] == 'O' && response
[1] == 'K')
662 /* OK, do nothing. */;
663 else if ((nread
> 7 && !memcmp (response
, "ERR 111", 7)
664 && (response
[7] == ' ' || response
[7] == '\n') )
665 || ((nread
> 4 && !memcmp (response
, "ERR ", 4)
666 && (strtoul (response
+4, NULL
, 0) & 0xffff) == 99)) )
668 /* 111 is the old Assuan code for canceled which might still
669 be in use by old installations. 99 is GPG_ERR_CANCELED as
670 used by modern gpg-agents; 0xffff is used to mask out the
672 #ifdef SPWQ_USE_LOGGING
673 log_info (_("canceled by user\n") );
678 #ifdef SPWQ_USE_LOGGING
679 log_error (_("problem with the agent\n"));
681 rc
= SPWQ_ERR_RESPONSE
;