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