Merge branch 'master' into key-storage-work
[gnupg.git] / common / simple-pwquery.c
1 /* simple-pwquery.c - A simple password query client for gpg-agent
2  *      Copyright (C) 2002, 2004, 2007 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 /* 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. */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 #include <stdlib.h>
29 #include <stddef.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #ifdef HAVE_W32_SYSTEM
34 #include <winsock2.h>
35 #else
36 #include <sys/socket.h>
37 #include <sys/un.h>
38 #endif
39 #ifdef HAVE_LOCALE_H
40 #include <locale.h>
41 #endif
42
43 #define JNLIB_NEED_AFLOCAL
44 #include "../common/mischelp.h"
45 #ifdef HAVE_W32_SYSTEM
46 #include "../common/w32-afunix.h"
47 #endif
48
49
50 #define SIMPLE_PWQUERY_IMPLEMENTATION 1
51 #include "simple-pwquery.h"
52
53 #if defined(SPWQ_USE_LOGGING) && !defined(HAVE_JNLIB_LOGGING)
54 # undef SPWQ_USE_LOGGING
55 #endif
56
57 #ifndef _
58 #define _(a) (a)
59 #endif
60
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))
69 #endif
70
71
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;
75
76
77
78
79 \f
80
81 #ifndef HAVE_STPCPY
82 static char *
83 my_stpcpy(char *a,const char *b)
84 {
85     while( *b )
86         *a++ = *b++;
87     *a = 0;
88
89     return (char*)a;
90 }
91 #define stpcpy(a,b)  my_stpcpy((a), (b))
92 #endif
93
94
95
96 /* Write NBYTES of BUF to file descriptor FD. */
97 static int
98 writen (int fd, const void *buf, size_t nbytes)
99 {
100   size_t nleft = nbytes;
101   int nwritten;
102
103   while (nleft > 0)
104     {
105 #ifdef HAVE_W32_SYSTEM
106       nwritten = send (fd, buf, nleft, 0);
107 #else
108       nwritten = write (fd, buf, nleft);
109 #endif
110       if (nwritten < 0)
111         {
112           if (errno == EINTR)
113             nwritten = 0;
114           else {
115 #ifdef SPWQ_USE_LOGGING
116             log_error ("write failed: %s\n", strerror (errno));
117 #endif
118             return SPWQ_IO_ERROR;
119           }
120         }
121       nleft -= nwritten;
122       buf = (const char*)buf + nwritten;
123     }
124
125   return 0;
126 }
127
128
129 /* Read an entire line and return number of bytes read. */
130 static int
131 readline (int fd, char *buf, size_t buflen)
132 {
133   size_t nleft = buflen;
134   char *p;
135   int nread = 0;
136
137   while (nleft > 0)
138     {
139 #ifdef HAVE_W32_SYSTEM
140       int n = recv (fd, buf, nleft, 0);
141 #else
142       int n = read (fd, buf, nleft);
143 #endif
144       if (n < 0)
145         {
146           if (errno == EINTR)
147             continue;
148           return -(SPWQ_IO_ERROR);
149         }
150       else if (!n)
151         {
152           return -(SPWQ_PROTOCOL_ERROR); /* incomplete line */
153         }
154       p = buf;
155       nleft -= n;
156       buf += n;
157       nread += n;
158
159       for (; n && *p != '\n'; n--, p++)
160         ;
161       if (n)
162         {
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.  */
166         }
167     }
168
169   return nread;
170 }
171
172
173 /* Send an option to the agent */
174 static int
175 agent_send_option (int fd, const char *name, const char *value)
176 {
177   char buf[200];
178   int nread;
179   char *line;
180   int i;
181
182   line = spwq_malloc (7 + strlen (name) + 1 + strlen (value) + 2);
183   if (!line)
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));
188   spwq_free (line);
189   if (i)
190     return i;
191
192   /* get response */
193   nread = readline (fd, buf, DIM(buf)-1);
194   if (nread < 0)
195     return -nread;
196   if (nread < 3)
197     return SPWQ_PROTOCOL_ERROR;
198
199   if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
200     return 0; /* okay */
201
202   return SPWQ_ERR_RESPONSE;
203 }
204
205
206 /* Send all available options to the agent. */
207 static int
208 agent_send_all_options (int fd)
209 {
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;
215   int rc = 0;
216
217   dft_display = getenv ("DISPLAY");
218   if (dft_display)
219     {
220       if ((rc = agent_send_option (fd, "display", dft_display)))
221         return rc;
222     }
223
224   dft_ttyname = getenv ("GPG_TTY");
225 #if !defined(HAVE_W32_SYSTEM) && !defined(HAVE_BROKEN_TTYNAME)
226   if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
227     dft_ttyname = ttyname (0);
228 #endif
229   if (dft_ttyname && *dft_ttyname)
230     {
231       if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
232         return rc;
233     }
234
235   dft_ttytype = getenv ("TERM");
236   if (dft_ttyname && dft_ttytype)
237     {
238       if ((rc = agent_send_option (fd, "ttytype", dft_ttytype)))
239         return rc;
240     }
241
242 #if defined(HAVE_SETLOCALE)
243   {
244     char *old_lc = NULL;
245     char *dft_lc = NULL;
246
247 #if defined(LC_CTYPE)
248     old_lc = setlocale (LC_CTYPE, NULL);
249     if (old_lc)
250       {
251         char *p = spwq_malloc (strlen (old_lc)+1);
252         if (!p)
253           return SPWQ_OUT_OF_CORE;
254         strcpy (p, old_lc);
255         old_lc = p;
256       }
257     dft_lc = setlocale (LC_CTYPE, "");
258     if (dft_ttyname && dft_lc)
259       rc = agent_send_option (fd, "lc-ctype", dft_lc);
260     if (old_lc)
261       {
262         setlocale (LC_CTYPE, old_lc);
263         spwq_free (old_lc);
264       }
265     if (rc)
266       return rc;
267 #endif
268
269 #if defined(LC_MESSAGES)
270     old_lc = setlocale (LC_MESSAGES, NULL);
271     if (old_lc)
272       {
273         char *p = spwq_malloc (strlen (old_lc)+1);
274         if (!p)
275           return SPWQ_OUT_OF_CORE;
276         strcpy (p, old_lc);
277         old_lc = p;
278       }
279     dft_lc = setlocale (LC_MESSAGES, "");
280     if (dft_ttyname && dft_lc)
281       rc = agent_send_option (fd, "lc-messages", dft_lc);
282     if (old_lc)
283       {
284         setlocale (LC_MESSAGES, old_lc);
285         spwq_free (old_lc);
286       }
287     if (rc)
288       return rc;
289 #endif
290   }
291 #endif /*HAVE_SETLOCALE*/
292
293   /* Send the XAUTHORITY variable.  */
294   dft_xauthority = getenv ("XAUTHORITY");
295   if (dft_xauthority)
296     {
297       /* We ignore errors here because older gpg-agents don't support
298          this option.  */
299       agent_send_option (fd, "xauthority", dft_xauthority);
300     }
301
302   /* Send the PINENTRY_USER_DATA variable.  */
303   dft_pinentry_user_data = getenv ("PINENTRY_USER_DATA");
304   if (dft_pinentry_user_data)
305     {
306       /* We ignore errors here because older gpg-agents don't support
307          this option.  */
308       agent_send_option (fd, "pinentry-user-data", dft_pinentry_user_data);
309     }
310
311   return 0;
312 }
313
314
315
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
318    error. */
319 static int
320 agent_open (int *rfd)
321 {
322   int rc;
323   int fd;
324   char *infostr, *p;
325   struct sockaddr_un client_addr;
326   size_t len;
327   int prot;
328   char line[200];
329   int nread;
330
331   *rfd = -1;
332   infostr = getenv ( "GPG_AGENT_INFO" );
333   if ( !infostr || !*infostr )
334     infostr = default_gpg_agent_info;
335   if ( !infostr || !*infostr )
336     {
337 #ifdef SPWQ_USE_LOGGING
338       log_error (_("gpg-agent is not available in this session\n"));
339 #endif
340       return SPWQ_NO_AGENT;
341     }
342   p = spwq_malloc (strlen (infostr)+1);
343   if (!p)
344     return SPWQ_OUT_OF_CORE;
345   strcpy (p, infostr);
346   infostr = p;
347
348   if ( !(p = strchr ( infostr, PATHSEP_C)) || p == infostr
349        || (p-infostr)+1 >= sizeof client_addr.sun_path )
350     {
351 #ifdef SPWQ_USE_LOGGING
352       log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
353 #endif
354       return SPWQ_NO_AGENT;
355     }
356   *p++ = 0;
357
358   while (*p && *p != PATHSEP_C)
359     p++;
360   prot = *p? atoi (p+1) : 0;
361   if ( prot != 1)
362     {
363 #ifdef SPWQ_USE_LOGGING
364       log_error (_("gpg-agent protocol version %d is not supported\n"),prot);
365 #endif
366       return SPWQ_PROTOCOL_ERROR;
367     }
368
369 #ifdef HAVE_W32_SYSTEM
370   fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0);
371 #else
372   fd = socket (AF_UNIX, SOCK_STREAM, 0);
373 #endif
374   if (fd == -1)
375     {
376 #ifdef SPWQ_USE_LOGGING
377       log_error ("can't create socket: %s\n", strerror(errno) );
378 #endif
379       return SPWQ_SYS_ERROR;
380     }
381
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);
386
387 #ifdef HAVE_W32_SYSTEM
388   rc = _w32_sock_connect (fd, (struct sockaddr*)&client_addr, len );
389 #else
390   rc = connect (fd, (struct sockaddr*)&client_addr, len );
391 #endif
392   if (rc == -1)
393     {
394 #ifdef SPWQ_USE_LOGGING
395       log_error ( _("can't connect to '%s': %s\n"), infostr, strerror (errno));
396 #endif
397       close (fd );
398       return SPWQ_IO_ERROR;
399     }
400
401   nread = readline (fd, line, DIM(line));
402   if (nread < 3 || !(line[0] == 'O' && line[1] == 'K'
403                      && (line[2] == '\n' || line[2] == ' ')) )
404     {
405 #ifdef SPWQ_USE_LOGGING
406       log_error ( _("communication problem with gpg-agent\n"));
407 #endif
408       close (fd );
409       return SPWQ_PROTOCOL_ERROR;
410     }
411
412   rc = agent_send_all_options (fd);
413   if (rc)
414     {
415 #ifdef SPWQ_USE_LOGGING
416       log_error (_("problem setting the gpg-agent options\n"));
417 #endif
418       close (fd);
419       return rc;
420     }
421
422   *rfd = fd;
423   return 0;
424 }
425
426
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
430    is sufficient. */
431 static char *
432 copy_and_escape (char *buffer, const char *text)
433 {
434   int i;
435   const unsigned char *s = (unsigned char *)text;
436   char *p = buffer;
437
438
439   for (i=0; s[i]; i++)
440     {
441       if (s[i] < ' ' || s[i] == '+')
442         {
443           sprintf (p, "%%%02X", s[i]);
444           p += 3;
445         }
446       else if (s[i] == ' ')
447         *p++ = '+';
448       else
449         *p++ = s[i];
450     }
451   return p;
452 }
453
454
455 /* Set the name of the default socket to NAME.  */
456 int
457 simple_pw_set_socket (const char *name)
458 {
459   spwq_free (default_gpg_agent_info);
460   if (name)
461     {
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");
468     }
469   else
470     default_gpg_agent_info = NULL;
471
472   return 0;
473 }
474
475
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.  */
484 char *
485 simple_pwquery (const char *cacheid,
486                 const char *tryagain,
487                 const char *prompt,
488                 const char *description,
489                 int opt_check,
490                 int *errorcode)
491 {
492   int fd = -1;
493   int nread;
494   char *result = NULL;
495   char *pw = NULL;
496   char *p;
497   int rc, i;
498
499   rc = agent_open (&fd);
500   if (rc)
501     goto leave;
502
503   if (!cacheid)
504     cacheid = "X";
505   if (!tryagain)
506     tryagain = "X";
507   if (!prompt)
508     prompt = "X";
509   if (!description)
510     description = "X";
511
512   {
513     char *line;
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
521                         + 2);
522     if (!line)
523       {
524         rc = SPWQ_OUT_OF_CORE;
525         goto leave;
526       }
527     strcpy (line, "GET_PASSPHRASE ");
528     p = line+15;
529     if (opt_check)
530       p = stpcpy (p, "--check ");
531     p = copy_and_escape (p, cacheid);
532     *p++ = ' ';
533     p = copy_and_escape (p, tryagain);
534     *p++ = ' ';
535     p = copy_and_escape (p, prompt);
536     *p++ = ' ';
537     p = copy_and_escape (p, description);
538     *p++ = '\n';
539     rc = writen (fd, line, p - line);
540     spwq_free (line);
541     if (rc)
542       goto leave;
543   }
544
545   /* get response */
546   pw = spwq_secure_malloc (500);
547   nread = readline (fd, pw, 499);
548   if (nread < 0)
549     {
550       rc = -nread;
551       goto leave;
552     }
553   if (nread < 3)
554     {
555       rc = SPWQ_PROTOCOL_ERROR;
556       goto leave;
557     }
558
559   if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ')
560     { /* we got a passphrase - convert it back from hex */
561       size_t pwlen = 0;
562
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 */
566       result = pw;
567       pw = NULL;
568     }
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)) )
573     {
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
577          error source.  */
578 #ifdef SPWQ_USE_LOGGING
579       log_info (_("canceled by user\n") );
580 #endif
581       *errorcode = 0; /* Special error code to indicate Cancel. */
582     }
583   else if (nread > 4 && !memcmp (pw, "ERR ", 4))
584     {
585       switch ( (strtoul (pw+4, NULL, 0) & 0xffff) )
586         {
587         case 85: rc = SPWQ_NO_PIN_ENTRY;  break;
588         default: rc = SPWQ_GENERAL_ERROR; break;
589         }
590     }
591   else
592     {
593 #ifdef SPWQ_USE_LOGGING
594       log_error (_("problem with the agent\n"));
595 #endif
596       rc = SPWQ_ERR_RESPONSE;
597     }
598
599  leave:
600   if (errorcode)
601     *errorcode = rc;
602   if (fd != -1)
603     close (fd);
604   if (pw)
605     spwq_secure_free (pw);
606   return result;
607 }
608
609
610 /* Ask the gpg-agent to clear the passphrase for the cache ID CACHEID.  */
611 int
612 simple_pwclear (const char *cacheid)
613 {
614   char line[500];
615   char *p;
616
617   /* We need not more than 50 characters for the command and the
618      terminating nul.  */
619   if (strlen (cacheid) * 3 > sizeof (line) - 50)
620     return SPWQ_PROTOCOL_ERROR;
621
622   strcpy (line, "CLEAR_PASSPHRASE ");
623   p = line + 17;
624   p = copy_and_escape (p, cacheid);
625   *p++ = '\n';
626   *p++ = '\0';
627
628   return simple_query (line);
629 }
630
631
632 /* Perform the simple query QUERY (which must be new-line and 0
633    terminated) and return the error code.  */
634 int
635 simple_query (const char *query)
636 {
637   int fd = -1;
638   int nread;
639   char response[500];
640   int rc;
641
642   rc = agent_open (&fd);
643   if (rc)
644     goto leave;
645
646   rc = writen (fd, query, strlen (query));
647   if (rc)
648     goto leave;
649
650   /* get response */
651   nread = readline (fd, response, 499);
652   if (nread < 0)
653     {
654       rc = -nread;
655       goto leave;
656     }
657   if (nread < 3)
658     {
659       rc = SPWQ_PROTOCOL_ERROR;
660       goto leave;
661     }
662
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)) )
669     {
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
673          error source.  */
674 #ifdef SPWQ_USE_LOGGING
675       log_info (_("canceled by user\n") );
676 #endif
677     }
678   else
679     {
680 #ifdef SPWQ_USE_LOGGING
681       log_error (_("problem with the agent\n"));
682 #endif
683       rc = SPWQ_ERR_RESPONSE;
684     }
685
686  leave:
687   if (fd != -1)
688     close (fd);
689   return rc;
690 }