common: Include <gpg-error.h>.
[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 GNUPG_COMMON_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 #ifndef _
54 #define _(a) (a)
55 #endif
56
57 #if !defined (hexdigitp) && !defined (xtoi_2)
58 #define digitp(p)   (*(p) >= '0' && *(p) <= '9')
59 #define hexdigitp(a) (digitp (a)                     \
60                       || (*(a) >= 'A' && *(a) <= 'F')  \
61                       || (*(a) >= 'a' && *(a) <= 'f'))
62 #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
63                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
64 #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
65 #endif
66
67
68 /* Name of the socket to be used.  This is a kludge to keep on using
69    the existsing code despite that we only support a standard socket.  */
70 static char *default_gpg_agent_info;
71
72
73
74 \f
75
76 #ifndef HAVE_STPCPY
77 static char *
78 my_stpcpy(char *a,const char *b)
79 {
80     while( *b )
81         *a++ = *b++;
82     *a = 0;
83
84     return (char*)a;
85 }
86 #define stpcpy(a,b)  my_stpcpy((a), (b))
87 #endif
88
89
90
91 /* Write NBYTES of BUF to file descriptor FD. */
92 static int
93 writen (int fd, const void *buf, size_t nbytes)
94 {
95   size_t nleft = nbytes;
96   int nwritten;
97
98   while (nleft > 0)
99     {
100 #ifdef HAVE_W32_SYSTEM
101       nwritten = send (fd, buf, nleft, 0);
102 #else
103       nwritten = write (fd, buf, nleft);
104 #endif
105       if (nwritten < 0)
106         {
107           if (errno == EINTR)
108             nwritten = 0;
109           else {
110 #ifdef SPWQ_USE_LOGGING
111             log_error ("write failed: %s\n", strerror (errno));
112 #endif
113             return SPWQ_IO_ERROR;
114           }
115         }
116       nleft -= nwritten;
117       buf = (const char*)buf + nwritten;
118     }
119
120   return 0;
121 }
122
123
124 /* Read an entire line and return number of bytes read. */
125 static int
126 readline (int fd, char *buf, size_t buflen)
127 {
128   size_t nleft = buflen;
129   char *p;
130   int nread = 0;
131
132   while (nleft > 0)
133     {
134 #ifdef HAVE_W32_SYSTEM
135       int n = recv (fd, buf, nleft, 0);
136 #else
137       int n = read (fd, buf, nleft);
138 #endif
139       if (n < 0)
140         {
141           if (errno == EINTR)
142             continue;
143           return -(SPWQ_IO_ERROR);
144         }
145       else if (!n)
146         {
147           return -(SPWQ_PROTOCOL_ERROR); /* incomplete line */
148         }
149       p = buf;
150       nleft -= n;
151       buf += n;
152       nread += n;
153
154       for (; n && *p != '\n'; n--, p++)
155         ;
156       if (n)
157         {
158           break; /* At least one full line available - that's enough.
159                     This function is just a simple implementation, so
160                     it is okay to forget about pending bytes.  */
161         }
162     }
163
164   return nread;
165 }
166
167
168 /* Send an option to the agent */
169 static int
170 agent_send_option (int fd, const char *name, const char *value)
171 {
172   char buf[200];
173   int nread;
174   char *line;
175   int i;
176
177   line = spwq_malloc (7 + strlen (name) + 1 + strlen (value) + 2);
178   if (!line)
179     return SPWQ_OUT_OF_CORE;
180   strcpy (stpcpy (stpcpy (stpcpy (
181                      stpcpy (line, "OPTION "), name), "="), value), "\n");
182   i = writen (fd, line, strlen (line));
183   spwq_free (line);
184   if (i)
185     return i;
186
187   /* get response */
188   nread = readline (fd, buf, DIM(buf)-1);
189   if (nread < 0)
190     return -nread;
191   if (nread < 3)
192     return SPWQ_PROTOCOL_ERROR;
193
194   if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
195     return 0; /* okay */
196
197   return SPWQ_ERR_RESPONSE;
198 }
199
200
201 /* Send all available options to the agent. */
202 static int
203 agent_send_all_options (int fd)
204 {
205   char *dft_display = NULL;
206   char *dft_ttyname = NULL;
207   char *dft_ttytype = NULL;
208   char *dft_xauthority = NULL;
209   char *dft_pinentry_user_data = NULL;
210   int rc = 0;
211
212   dft_display = getenv ("DISPLAY");
213   if (dft_display)
214     {
215       if ((rc = agent_send_option (fd, "display", dft_display)))
216         return rc;
217     }
218
219   dft_ttyname = getenv ("GPG_TTY");
220 #if !defined(HAVE_W32_SYSTEM) && !defined(HAVE_BROKEN_TTYNAME)
221   if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
222     dft_ttyname = ttyname (0);
223 #endif
224   if (dft_ttyname && *dft_ttyname)
225     {
226       if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
227         return rc;
228     }
229
230   dft_ttytype = getenv ("TERM");
231   if (dft_ttyname && dft_ttytype)
232     {
233       if ((rc = agent_send_option (fd, "ttytype", dft_ttytype)))
234         return rc;
235     }
236
237 #if defined(HAVE_SETLOCALE)
238   {
239     char *old_lc = NULL;
240     char *dft_lc = NULL;
241
242 #if defined(LC_CTYPE)
243     old_lc = setlocale (LC_CTYPE, NULL);
244     if (old_lc)
245       {
246         char *p = spwq_malloc (strlen (old_lc)+1);
247         if (!p)
248           return SPWQ_OUT_OF_CORE;
249         strcpy (p, old_lc);
250         old_lc = p;
251       }
252     dft_lc = setlocale (LC_CTYPE, "");
253     if (dft_ttyname && dft_lc)
254       rc = agent_send_option (fd, "lc-ctype", dft_lc);
255     if (old_lc)
256       {
257         setlocale (LC_CTYPE, old_lc);
258         spwq_free (old_lc);
259       }
260     if (rc)
261       return rc;
262 #endif
263
264 #if defined(LC_MESSAGES)
265     old_lc = setlocale (LC_MESSAGES, NULL);
266     if (old_lc)
267       {
268         char *p = spwq_malloc (strlen (old_lc)+1);
269         if (!p)
270           return SPWQ_OUT_OF_CORE;
271         strcpy (p, old_lc);
272         old_lc = p;
273       }
274     dft_lc = setlocale (LC_MESSAGES, "");
275     if (dft_ttyname && dft_lc)
276       rc = agent_send_option (fd, "lc-messages", dft_lc);
277     if (old_lc)
278       {
279         setlocale (LC_MESSAGES, old_lc);
280         spwq_free (old_lc);
281       }
282     if (rc)
283       return rc;
284 #endif
285   }
286 #endif /*HAVE_SETLOCALE*/
287
288   /* Send the XAUTHORITY variable.  */
289   dft_xauthority = getenv ("XAUTHORITY");
290   if (dft_xauthority)
291     {
292       /* We ignore errors here because older gpg-agents don't support
293          this option.  */
294       agent_send_option (fd, "xauthority", dft_xauthority);
295     }
296
297   /* Send the PINENTRY_USER_DATA variable.  */
298   dft_pinentry_user_data = getenv ("PINENTRY_USER_DATA");
299   if (dft_pinentry_user_data)
300     {
301       /* We ignore errors here because older gpg-agents don't support
302          this option.  */
303       agent_send_option (fd, "pinentry-user-data", dft_pinentry_user_data);
304     }
305
306   return 0;
307 }
308
309
310
311 /* Try to open a connection to the agent, send all options and return
312    the file descriptor for the connection.  Return -1 in case of
313    error. */
314 static int
315 agent_open (int *rfd)
316 {
317   int rc;
318   int fd;
319   char *infostr, *p;
320   struct sockaddr_un client_addr;
321   size_t len;
322   char line[200];
323   int nread;
324
325   *rfd = -1;
326   infostr = default_gpg_agent_info;
327   if ( !infostr || !*infostr )
328     {
329 #ifdef SPWQ_USE_LOGGING
330       log_error (_("no gpg-agent running in this session\n"));
331 #endif
332       return SPWQ_NO_AGENT;
333     }
334   p = spwq_malloc (strlen (infostr)+1);
335   if (!p)
336     return SPWQ_OUT_OF_CORE;
337   strcpy (p, infostr);
338   infostr = p;
339
340   if ( !(p = strchr ( infostr, PATHSEP_C)) || p == infostr
341        || (p-infostr)+1 >= sizeof client_addr.sun_path )
342     {
343       return SPWQ_NO_AGENT;
344     }
345   *p++ = 0;
346
347   while (*p && *p != PATHSEP_C)
348     p++;
349
350 #ifdef HAVE_W32_SYSTEM
351   fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0);
352 #else
353   fd = socket (AF_UNIX, SOCK_STREAM, 0);
354 #endif
355   if (fd == -1)
356     {
357 #ifdef SPWQ_USE_LOGGING
358       log_error ("can't create socket: %s\n", strerror(errno) );
359 #endif
360       return SPWQ_SYS_ERROR;
361     }
362
363   memset (&client_addr, 0, sizeof client_addr);
364   client_addr.sun_family = AF_UNIX;
365   strcpy (client_addr.sun_path, infostr);
366   len = SUN_LEN (&client_addr);
367
368 #ifdef HAVE_W32_SYSTEM
369   rc = _w32_sock_connect (fd, (struct sockaddr*)&client_addr, len );
370 #else
371   rc = connect (fd, (struct sockaddr*)&client_addr, len );
372 #endif
373   if (rc == -1)
374     {
375 #ifdef SPWQ_USE_LOGGING
376       log_error ( _("can't connect to '%s': %s\n"), infostr, strerror (errno));
377 #endif
378       close (fd );
379       return SPWQ_IO_ERROR;
380     }
381
382   nread = readline (fd, line, DIM(line));
383   if (nread < 3 || !(line[0] == 'O' && line[1] == 'K'
384                      && (line[2] == '\n' || line[2] == ' ')) )
385     {
386 #ifdef SPWQ_USE_LOGGING
387       log_error ( _("communication problem with gpg-agent\n"));
388 #endif
389       close (fd );
390       return SPWQ_PROTOCOL_ERROR;
391     }
392
393   rc = agent_send_all_options (fd);
394   if (rc)
395     {
396 #ifdef SPWQ_USE_LOGGING
397       log_error (_("problem setting the gpg-agent options\n"));
398 #endif
399       close (fd);
400       return rc;
401     }
402
403   *rfd = fd;
404   return 0;
405 }
406
407
408 /* Copy text to BUFFER and escape as required.  Return a pointer to
409    the end of the new buffer.  Note that BUFFER must be large enough
410    to keep the entire text; allocataing it 3 times the size of TEXT
411    is sufficient. */
412 static char *
413 copy_and_escape (char *buffer, const char *text)
414 {
415   int i;
416   const unsigned char *s = (unsigned char *)text;
417   char *p = buffer;
418
419
420   for (i=0; s[i]; i++)
421     {
422       if (s[i] < ' ' || s[i] == '+')
423         {
424           sprintf (p, "%%%02X", s[i]);
425           p += 3;
426         }
427       else if (s[i] == ' ')
428         *p++ = '+';
429       else
430         *p++ = s[i];
431     }
432   return p;
433 }
434
435
436 /* Set the name of the default socket to NAME.  */
437 int
438 simple_pw_set_socket (const char *name)
439 {
440   spwq_free (default_gpg_agent_info);
441   if (name)
442     {
443       default_gpg_agent_info = spwq_malloc (strlen (name) + 4 + 1);
444       if (!default_gpg_agent_info)
445         return SPWQ_OUT_OF_CORE;
446       /* We don't know the PID thus we use 0.  */
447       strcpy (stpcpy (default_gpg_agent_info, name),
448               PATHSEP_S "0" PATHSEP_S "1");
449     }
450   else
451     default_gpg_agent_info = NULL;
452
453   return 0;
454 }
455
456
457 /* Ask the gpg-agent for a passphrase and present the user with a
458    DESCRIPTION, a PROMPT and optionally with a TRYAGAIN extra text.
459    If a CACHEID is not NULL it is used to locate the passphrase in in
460    the cache and store it under this ID.  If OPT_CHECK is true
461    gpg-agent is asked to apply some checks on the passphrase security.
462    If ERRORCODE is not NULL it should point a variable receiving an
463    errorcode; this error code might be 0 if the user canceled the
464    operation.  The function returns NULL to indicate an error.  */
465 char *
466 simple_pwquery (const char *cacheid,
467                 const char *tryagain,
468                 const char *prompt,
469                 const char *description,
470                 int opt_check,
471                 int *errorcode)
472 {
473   int fd = -1;
474   int nread;
475   char *result = NULL;
476   char *pw = NULL;
477   char *p;
478   int rc, i;
479
480   rc = agent_open (&fd);
481   if (rc)
482     goto leave;
483
484   if (!cacheid)
485     cacheid = "X";
486   if (!tryagain)
487     tryagain = "X";
488   if (!prompt)
489     prompt = "X";
490   if (!description)
491     description = "X";
492
493   {
494     char *line;
495     /* We allocate 3 times the needed space so that there is enough
496        space for escaping. */
497     line = spwq_malloc (15 + 10
498                         + 3*strlen (cacheid) + 1
499                         + 3*strlen (tryagain) + 1
500                         + 3*strlen (prompt) + 1
501                         + 3*strlen (description) + 1
502                         + 2);
503     if (!line)
504       {
505         rc = SPWQ_OUT_OF_CORE;
506         goto leave;
507       }
508     strcpy (line, "GET_PASSPHRASE ");
509     p = line+15;
510     if (opt_check)
511       p = stpcpy (p, "--check ");
512     p = copy_and_escape (p, cacheid);
513     *p++ = ' ';
514     p = copy_and_escape (p, tryagain);
515     *p++ = ' ';
516     p = copy_and_escape (p, prompt);
517     *p++ = ' ';
518     p = copy_and_escape (p, description);
519     *p++ = '\n';
520     rc = writen (fd, line, p - line);
521     spwq_free (line);
522     if (rc)
523       goto leave;
524   }
525
526   /* get response */
527   pw = spwq_secure_malloc (500);
528   nread = readline (fd, pw, 499);
529   if (nread < 0)
530     {
531       rc = -nread;
532       goto leave;
533     }
534   if (nread < 3)
535     {
536       rc = SPWQ_PROTOCOL_ERROR;
537       goto leave;
538     }
539
540   if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ')
541     { /* we got a passphrase - convert it back from hex */
542       size_t pwlen = 0;
543
544       for (i=3; i < nread && hexdigitp (pw+i); i+=2)
545         pw[pwlen++] = xtoi_2 (pw+i);
546       pw[pwlen] = 0; /* make a C String */
547       result = pw;
548       pw = NULL;
549     }
550   else if ((nread > 7 && !memcmp (pw, "ERR 111", 7)
551             && (pw[7] == ' ' || pw[7] == '\n') )
552            || ((nread > 4 && !memcmp (pw, "ERR ", 4)
553                 && (strtoul (pw+4, NULL, 0) & 0xffff) == 99)) )
554     {
555       /* 111 is the old Assuan code for canceled which might still
556          be in use by old installations. 99 is GPG_ERR_CANCELED as
557          used by modern gpg-agents; 0xffff is used to mask out the
558          error source.  */
559 #ifdef SPWQ_USE_LOGGING
560       log_info (_("canceled by user\n") );
561 #endif
562       *errorcode = 0; /* Special error code to indicate Cancel. */
563     }
564   else if (nread > 4 && !memcmp (pw, "ERR ", 4))
565     {
566       switch ( (strtoul (pw+4, NULL, 0) & 0xffff) )
567         {
568         case 85: rc = SPWQ_NO_PIN_ENTRY;  break;
569         default: rc = SPWQ_GENERAL_ERROR; break;
570         }
571     }
572   else
573     {
574 #ifdef SPWQ_USE_LOGGING
575       log_error (_("problem with the agent\n"));
576 #endif
577       rc = SPWQ_ERR_RESPONSE;
578     }
579
580  leave:
581   if (errorcode)
582     *errorcode = rc;
583   if (fd != -1)
584     close (fd);
585   if (pw)
586     spwq_secure_free (pw);
587   return result;
588 }
589
590
591 /* Ask the gpg-agent to clear the passphrase for the cache ID CACHEID.  */
592 int
593 simple_pwclear (const char *cacheid)
594 {
595   char line[500];
596   char *p;
597
598   /* We need not more than 50 characters for the command and the
599      terminating nul.  */
600   if (strlen (cacheid) * 3 > sizeof (line) - 50)
601     return SPWQ_PROTOCOL_ERROR;
602
603   strcpy (line, "CLEAR_PASSPHRASE ");
604   p = line + 17;
605   p = copy_and_escape (p, cacheid);
606   *p++ = '\n';
607   *p++ = '\0';
608
609   return simple_query (line);
610 }
611
612
613 /* Perform the simple query QUERY (which must be new-line and 0
614    terminated) and return the error code.  */
615 int
616 simple_query (const char *query)
617 {
618   int fd = -1;
619   int nread;
620   char response[500];
621   int rc;
622
623   rc = agent_open (&fd);
624   if (rc)
625     goto leave;
626
627   rc = writen (fd, query, strlen (query));
628   if (rc)
629     goto leave;
630
631   /* get response */
632   nread = readline (fd, response, 499);
633   if (nread < 0)
634     {
635       rc = -nread;
636       goto leave;
637     }
638   if (nread < 3)
639     {
640       rc = SPWQ_PROTOCOL_ERROR;
641       goto leave;
642     }
643
644   if (response[0] == 'O' && response[1] == 'K')
645     /* OK, do nothing.  */;
646   else if ((nread > 7 && !memcmp (response, "ERR 111", 7)
647             && (response[7] == ' ' || response[7] == '\n') )
648            || ((nread > 4 && !memcmp (response, "ERR ", 4)
649                 && (strtoul (response+4, NULL, 0) & 0xffff) == 99)) )
650     {
651       /* 111 is the old Assuan code for canceled which might still
652          be in use by old installations. 99 is GPG_ERR_CANCELED as
653          used by modern gpg-agents; 0xffff is used to mask out the
654          error source.  */
655 #ifdef SPWQ_USE_LOGGING
656       log_info (_("canceled by user\n") );
657 #endif
658     }
659   else
660     {
661 #ifdef SPWQ_USE_LOGGING
662       log_error (_("problem with the agent\n"));
663 #endif
664       rc = SPWQ_ERR_RESPONSE;
665     }
666
667  leave:
668   if (fd != -1)
669     close (fd);
670   return rc;
671 }