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>
43 #define JNLIB_NEED_AFLOCAL
44 #include "../jnlib/mischelp.h"
45 #ifdef HAVE_W32_SYSTEM
46 #include "../jnlib/w32-afunix.h"
50 #define SIMPLE_PWQUERY_IMPLEMENTATION 1
51 #include "simple-pwquery.h"
53 #if defined(SPWQ_USE_LOGGING) && !defined(HAVE_JNLIB_LOGGING)
54 # undef SPWQ_USE_LOGGING
61 #if !defined (hexdigitp) && !defined (xtoi_2)
62 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
63 #define hexdigitp(a) (digitp (a) \
64 || (*(a) >= 'A' && *(a) <= 'F') \
65 || (*(a) >= 'a' && *(a) <= 'f'))
66 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
67 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
68 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
72 /* Name of the socket to be used if GPG_AGENT_INFO has not been
73 set. No default socket is used if this is NULL. */
74 static char *default_gpg_agent_info
;
83 my_stpcpy(char *a
,const char *b
)
91 #define stpcpy(a,b) my_stpcpy((a), (b))
96 /* Write NBYTES of BUF to file descriptor FD. */
98 writen (int fd
, const void *buf
, size_t nbytes
)
100 size_t nleft
= nbytes
;
105 #ifdef HAVE_W32_SYSTEM
106 nwritten
= send (fd
, buf
, nleft
, 0);
108 nwritten
= write (fd
, buf
, nleft
);
115 #ifdef SPWQ_USE_LOGGING
116 log_error ("write failed: %s\n", strerror (errno
));
118 return SPWQ_IO_ERROR
;
122 buf
= (const char*)buf
+ nwritten
;
129 /* Read an entire line and return number of bytes read. */
131 readline (int fd
, char *buf
, size_t buflen
)
133 size_t nleft
= buflen
;
139 #ifdef HAVE_W32_SYSTEM
140 int n
= recv (fd
, buf
, nleft
, 0);
142 int n
= read (fd
, buf
, nleft
);
148 return -(SPWQ_IO_ERROR
);
152 return -(SPWQ_PROTOCOL_ERROR
); /* incomplete line */
159 for (; n
&& *p
!= '\n'; n
--, p
++)
163 break; /* At least one full line available - that's enough.
164 This function is just a simple implementation, so
165 it is okay to forget about pending bytes. */
173 /* Send an option to the agent */
175 agent_send_option (int fd
, const char *name
, const char *value
)
182 line
= spwq_malloc (7 + strlen (name
) + 1 + strlen (value
) + 2);
184 return SPWQ_OUT_OF_CORE
;
185 strcpy (stpcpy (stpcpy (stpcpy (
186 stpcpy (line
, "OPTION "), name
), "="), value
), "\n");
187 i
= writen (fd
, line
, strlen (line
));
193 nread
= readline (fd
, buf
, DIM(buf
)-1);
197 return SPWQ_PROTOCOL_ERROR
;
199 if (buf
[0] == 'O' && buf
[1] == 'K' && (buf
[2] == ' ' || buf
[2] == '\n'))
202 return SPWQ_ERR_RESPONSE
;
206 /* Send all available options to the agent. */
208 agent_send_all_options (int fd
)
210 char *dft_display
= NULL
;
211 char *dft_ttyname
= NULL
;
212 char *dft_ttytype
= NULL
;
213 char *dft_xauthority
= NULL
;
214 char *dft_pinentry_user_data
= NULL
;
217 dft_display
= getenv ("DISPLAY");
220 if ((rc
= agent_send_option (fd
, "display", dft_display
)))
224 dft_ttyname
= getenv ("GPG_TTY");
225 #ifndef HAVE_W32_SYSTEM
226 if ((!dft_ttyname
|| !*dft_ttyname
) && ttyname (0))
227 dft_ttyname
= ttyname (0);
229 if (dft_ttyname
&& *dft_ttyname
)
231 if ((rc
=agent_send_option (fd
, "ttyname", dft_ttyname
)))
235 dft_ttytype
= getenv ("TERM");
236 if (dft_ttyname
&& dft_ttytype
)
238 if ((rc
= agent_send_option (fd
, "ttytype", dft_ttytype
)))
242 #if defined(HAVE_SETLOCALE)
247 #if defined(LC_CTYPE)
248 old_lc
= setlocale (LC_CTYPE
, NULL
);
251 char *p
= spwq_malloc (strlen (old_lc
)+1);
253 return SPWQ_OUT_OF_CORE
;
257 dft_lc
= setlocale (LC_CTYPE
, "");
258 if (dft_ttyname
&& dft_lc
)
259 rc
= agent_send_option (fd
, "lc-ctype", dft_lc
);
262 setlocale (LC_CTYPE
, old_lc
);
269 #if defined(LC_MESSAGES)
270 old_lc
= setlocale (LC_MESSAGES
, NULL
);
273 char *p
= spwq_malloc (strlen (old_lc
)+1);
275 return SPWQ_OUT_OF_CORE
;
279 dft_lc
= setlocale (LC_MESSAGES
, "");
280 if (dft_ttyname
&& dft_lc
)
281 rc
= agent_send_option (fd
, "lc-messages", dft_lc
);
284 setlocale (LC_MESSAGES
, old_lc
);
291 #endif /*HAVE_SETLOCALE*/
293 /* Send the XAUTHORITY variable. */
294 dft_xauthority
= getenv ("XAUTHORITY");
297 /* We ignore errors here because older gpg-agents don't support
299 agent_send_option (fd
, "xauthority", dft_xauthority
);
302 /* Send the PINENTRY_USER_DATA variable. */
303 dft_pinentry_user_data
= getenv ("PINENTRY_USER_DATA");
304 if (dft_pinentry_user_data
)
306 /* We ignore errors here because older gpg-agents don't support
308 agent_send_option (fd
, "pinentry-user-data", dft_pinentry_user_data
);
316 /* Try to open a connection to the agent, send all options and return
317 the file descriptor for the connection. Return -1 in case of
320 agent_open (int *rfd
)
325 struct sockaddr_un client_addr
;
332 infostr
= getenv ( "GPG_AGENT_INFO" );
333 if ( !infostr
|| !*infostr
)
334 infostr
= default_gpg_agent_info
;
335 if ( !infostr
|| !*infostr
)
337 #ifdef SPWQ_USE_LOGGING
338 log_error (_("gpg-agent is not available in this session\n"));
340 return SPWQ_NO_AGENT
;
342 p
= spwq_malloc (strlen (infostr
)+1);
344 return SPWQ_OUT_OF_CORE
;
348 if ( !(p
= strchr ( infostr
, PATHSEP_C
)) || p
== infostr
349 || (p
-infostr
)+1 >= sizeof client_addr
.sun_path
)
351 #ifdef SPWQ_USE_LOGGING
352 log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
354 return SPWQ_NO_AGENT
;
358 while (*p
&& *p
!= PATHSEP_C
)
360 prot
= *p
? atoi (p
+1) : 0;
363 #ifdef SPWQ_USE_LOGGING
364 log_error (_("gpg-agent protocol version %d is not supported\n"),prot
);
366 return SPWQ_PROTOCOL_ERROR
;
369 #ifdef HAVE_W32_SYSTEM
370 fd
= _w32_sock_new (AF_UNIX
, SOCK_STREAM
, 0);
372 fd
= socket (AF_UNIX
, SOCK_STREAM
, 0);
376 #ifdef SPWQ_USE_LOGGING
377 log_error ("can't create socket: %s\n", strerror(errno
) );
379 return SPWQ_SYS_ERROR
;
382 memset (&client_addr
, 0, sizeof client_addr
);
383 client_addr
.sun_family
= AF_UNIX
;
384 strcpy (client_addr
.sun_path
, infostr
);
385 len
= SUN_LEN (&client_addr
);
387 #ifdef HAVE_W32_SYSTEM
388 rc
= _w32_sock_connect (fd
, (struct sockaddr
*)&client_addr
, len
);
390 rc
= connect (fd
, (struct sockaddr
*)&client_addr
, len
);
394 #ifdef SPWQ_USE_LOGGING
395 log_error ( _("can't connect to `%s': %s\n"), infostr
, strerror (errno
));
398 return SPWQ_IO_ERROR
;
401 nread
= readline (fd
, line
, DIM(line
));
402 if (nread
< 3 || !(line
[0] == 'O' && line
[1] == 'K'
403 && (line
[2] == '\n' || line
[2] == ' ')) )
405 #ifdef SPWQ_USE_LOGGING
406 log_error ( _("communication problem with gpg-agent\n"));
409 return SPWQ_PROTOCOL_ERROR
;
412 rc
= agent_send_all_options (fd
);
415 #ifdef SPWQ_USE_LOGGING
416 log_error (_("problem setting the gpg-agent options\n"));
427 /* Copy text to BUFFER and escape as required. Return a pointer to
428 the end of the new buffer. Note that BUFFER must be large enough
429 to keep the entire text; allocataing it 3 times the size of TEXT
432 copy_and_escape (char *buffer
, const char *text
)
435 const unsigned char *s
= (unsigned char *)text
;
441 if (s
[i
] < ' ' || s
[i
] == '+')
443 sprintf (p
, "%%%02X", s
[i
]);
446 else if (s
[i
] == ' ')
455 /* Set the name of the default socket to NAME. */
457 simple_pw_set_socket (const char *name
)
459 spwq_free (default_gpg_agent_info
);
462 default_gpg_agent_info
= spwq_malloc (strlen (name
) + 4 + 1);
463 if (!default_gpg_agent_info
)
464 return SPWQ_OUT_OF_CORE
;
465 /* We don't know the PID thus we use 0. */
466 strcpy (stpcpy (default_gpg_agent_info
, name
),
467 PATHSEP_S
"0" PATHSEP_S
"1");
470 default_gpg_agent_info
= NULL
;
476 /* Ask the gpg-agent for a passphrase and present the user with a
477 DESCRIPTION, a PROMPT and optionally with a TRYAGAIN extra text.
478 If a CACHEID is not NULL it is used to locate the passphrase in in
479 the cache and store it under this ID. If OPT_CHECK is true
480 gpg-agent is asked to apply some checks on the passphrase security.
481 If ERRORCODE is not NULL it should point a variable receiving an
482 errorcode; this error code might be 0 if the user canceled the
483 operation. The function returns NULL to indicate an error. */
485 simple_pwquery (const char *cacheid
,
486 const char *tryagain
,
488 const char *description
,
499 rc
= agent_open (&fd
);
514 /* We allocate 3 times the needed space so that there is enough
515 space for escaping. */
516 line
= spwq_malloc (15 + 10
517 + 3*strlen (cacheid
) + 1
518 + 3*strlen (tryagain
) + 1
519 + 3*strlen (prompt
) + 1
520 + 3*strlen (description
) + 1
524 rc
= SPWQ_OUT_OF_CORE
;
527 strcpy (line
, "GET_PASSPHRASE ");
530 p
= stpcpy (p
, "--check ");
531 p
= copy_and_escape (p
, cacheid
);
533 p
= copy_and_escape (p
, tryagain
);
535 p
= copy_and_escape (p
, prompt
);
537 p
= copy_and_escape (p
, description
);
539 rc
= writen (fd
, line
, p
- line
);
546 pw
= spwq_secure_malloc (500);
547 nread
= readline (fd
, pw
, 499);
555 rc
= SPWQ_PROTOCOL_ERROR
;
559 if (pw
[0] == 'O' && pw
[1] == 'K' && pw
[2] == ' ')
560 { /* we got a passphrase - convert it back from hex */
563 for (i
=3; i
< nread
&& hexdigitp (pw
+i
); i
+=2)
564 pw
[pwlen
++] = xtoi_2 (pw
+i
);
565 pw
[pwlen
] = 0; /* make a C String */
569 else if ((nread
> 7 && !memcmp (pw
, "ERR 111", 7)
570 && (pw
[7] == ' ' || pw
[7] == '\n') )
571 || ((nread
> 4 && !memcmp (pw
, "ERR ", 4)
572 && (strtoul (pw
+4, NULL
, 0) & 0xffff) == 99)) )
574 /* 111 is the old Assuan code for canceled which might still
575 be in use by old installations. 99 is GPG_ERR_CANCELED as
576 used by modern gpg-agents; 0xffff is used to mask out the
578 #ifdef SPWQ_USE_LOGGING
579 log_info (_("canceled by user\n") );
581 *errorcode
= 0; /* Special error code to indicate Cancel. */
583 else if (nread
> 4 && !memcmp (pw
, "ERR ", 4))
585 switch ( (strtoul (pw
+4, NULL
, 0) & 0xffff) )
587 case 85: rc
= SPWQ_NO_PIN_ENTRY
; break;
588 default: rc
= SPWQ_GENERAL_ERROR
; break;
593 #ifdef SPWQ_USE_LOGGING
594 log_error (_("problem with the agent\n"));
596 rc
= SPWQ_ERR_RESPONSE
;
605 spwq_secure_free (pw
);
610 /* Ask the gpg-agent to clear the passphrase for the cache ID CACHEID. */
612 simple_pwclear (const char *cacheid
)
617 /* We need not more than 50 characters for the command and the
619 if (strlen (cacheid
) * 3 > sizeof (line
) - 50)
620 return SPWQ_PROTOCOL_ERROR
;
622 strcpy (line
, "CLEAR_PASSPHRASE ");
624 p
= copy_and_escape (p
, cacheid
);
628 return simple_query (line
);
632 /* Perform the simple query QUERY (which must be new-line and 0
633 terminated) and return the error code. */
635 simple_query (const char *query
)
642 rc
= agent_open (&fd
);
646 rc
= writen (fd
, query
, strlen (query
));
651 nread
= readline (fd
, response
, 499);
659 rc
= SPWQ_PROTOCOL_ERROR
;
663 if (response
[0] == 'O' && response
[1] == 'K')
664 /* OK, do nothing. */;
665 else if ((nread
> 7 && !memcmp (response
, "ERR 111", 7)
666 && (response
[7] == ' ' || response
[7] == '\n') )
667 || ((nread
> 4 && !memcmp (response
, "ERR ", 4)
668 && (strtoul (response
+4, NULL
, 0) & 0xffff) == 99)) )
670 /* 111 is the old Assuan code for canceled which might still
671 be in use by old installations. 99 is GPG_ERR_CANCELED as
672 used by modern gpg-agents; 0xffff is used to mask out the
674 #ifdef SPWQ_USE_LOGGING
675 log_info (_("canceled by user\n") );
680 #ifdef SPWQ_USE_LOGGING
681 log_error (_("problem with the agent\n"));
683 rc
= SPWQ_ERR_RESPONSE
;