common: Change a string to a simlar one to ease translation.
[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.  This is a kludge to keep on using
73    the existsing code despite that we only support a standard socket.  */
74 static char *default_gpg_agent_info;
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   char *dft_xauthority = NULL;
213   char *dft_pinentry_user_data = NULL;
214   int rc = 0;
215
216   dft_display = getenv ("DISPLAY");
217   if (dft_display)
218     {
219       if ((rc = agent_send_option (fd, "display", dft_display)))
220         return rc;
221     }
222
223   dft_ttyname = getenv ("GPG_TTY");
224 #if !defined(HAVE_W32_SYSTEM) && !defined(HAVE_BROKEN_TTYNAME)
225   if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
226     dft_ttyname = ttyname (0);
227 #endif
228   if (dft_ttyname && *dft_ttyname)
229     {
230       if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
231         return rc;
232     }
233
234   dft_ttytype = getenv ("TERM");
235   if (dft_ttyname && dft_ttytype)
236     {
237       if ((rc = agent_send_option (fd, "ttytype", dft_ttytype)))
238         return rc;
239     }
240
241 #if defined(HAVE_SETLOCALE)
242   {
243     char *old_lc = NULL;
244     char *dft_lc = NULL;
245
246 #if defined(LC_CTYPE)
247     old_lc = setlocale (LC_CTYPE, NULL);
248     if (old_lc)
249       {
250         char *p = spwq_malloc (strlen (old_lc)+1);
251         if (!p)
252           return SPWQ_OUT_OF_CORE;
253         strcpy (p, old_lc);
254         old_lc = p;
255       }
256     dft_lc = setlocale (LC_CTYPE, "");
257     if (dft_ttyname && dft_lc)
258       rc = agent_send_option (fd, "lc-ctype", dft_lc);
259     if (old_lc)
260       {
261         setlocale (LC_CTYPE, old_lc);
262         spwq_free (old_lc);
263       }
264     if (rc)
265       return rc;
266 #endif
267
268 #if defined(LC_MESSAGES)
269     old_lc = setlocale (LC_MESSAGES, NULL);
270     if (old_lc)
271       {
272         char *p = spwq_malloc (strlen (old_lc)+1);
273         if (!p)
274           return SPWQ_OUT_OF_CORE;
275         strcpy (p, old_lc);
276         old_lc = p;
277       }
278     dft_lc = setlocale (LC_MESSAGES, "");
279     if (dft_ttyname && dft_lc)
280       rc = agent_send_option (fd, "lc-messages", dft_lc);
281     if (old_lc)
282       {
283         setlocale (LC_MESSAGES, old_lc);
284         spwq_free (old_lc);
285       }
286     if (rc)
287       return rc;
288 #endif
289   }
290 #endif /*HAVE_SETLOCALE*/
291
292   /* Send the XAUTHORITY variable.  */
293   dft_xauthority = getenv ("XAUTHORITY");
294   if (dft_xauthority)
295     {
296       /* We ignore errors here because older gpg-agents don't support
297          this option.  */
298       agent_send_option (fd, "xauthority", dft_xauthority);
299     }
300
301   /* Send the PINENTRY_USER_DATA variable.  */
302   dft_pinentry_user_data = getenv ("PINENTRY_USER_DATA");
303   if (dft_pinentry_user_data)
304     {
305       /* We ignore errors here because older gpg-agents don't support
306          this option.  */
307       agent_send_option (fd, "pinentry-user-data", dft_pinentry_user_data);
308     }
309
310   return 0;
311 }
312
313
314
315 /* Try to open a connection to the agent, send all options and return
316    the file descriptor for the connection.  Return -1 in case of
317    error. */
318 static int
319 agent_open (int *rfd)
320 {
321   int rc;
322   int fd;
323   char *infostr, *p;
324   struct sockaddr_un client_addr;
325   size_t len;
326   char line[200];
327   int nread;
328
329   *rfd = -1;
330   infostr = default_gpg_agent_info;
331   if ( !infostr || !*infostr )
332     {
333 #ifdef SPWQ_USE_LOGGING
334       log_error (_("no gpg-agent running in this session\n"));
335 #endif
336       return SPWQ_NO_AGENT;
337     }
338   p = spwq_malloc (strlen (infostr)+1);
339   if (!p)
340     return SPWQ_OUT_OF_CORE;
341   strcpy (p, infostr);
342   infostr = p;
343
344   if ( !(p = strchr ( infostr, PATHSEP_C)) || p == infostr
345        || (p-infostr)+1 >= sizeof client_addr.sun_path )
346     {
347       return SPWQ_NO_AGENT;
348     }
349   *p++ = 0;
350
351   while (*p && *p != PATHSEP_C)
352     p++;
353
354 #ifdef HAVE_W32_SYSTEM
355   fd = _w32_sock_new (AF_UNIX, SOCK_STREAM, 0);
356 #else
357   fd = socket (AF_UNIX, SOCK_STREAM, 0);
358 #endif
359   if (fd == -1)
360     {
361 #ifdef SPWQ_USE_LOGGING
362       log_error ("can't create socket: %s\n", strerror(errno) );
363 #endif
364       return SPWQ_SYS_ERROR;
365     }
366
367   memset (&client_addr, 0, sizeof client_addr);
368   client_addr.sun_family = AF_UNIX;
369   strcpy (client_addr.sun_path, infostr);
370   len = SUN_LEN (&client_addr);
371
372 #ifdef HAVE_W32_SYSTEM
373   rc = _w32_sock_connect (fd, (struct sockaddr*)&client_addr, len );
374 #else
375   rc = connect (fd, (struct sockaddr*)&client_addr, len );
376 #endif
377   if (rc == -1)
378     {
379 #ifdef SPWQ_USE_LOGGING
380       log_error ( _("can't connect to '%s': %s\n"), infostr, strerror (errno));
381 #endif
382       close (fd );
383       return SPWQ_IO_ERROR;
384     }
385
386   nread = readline (fd, line, DIM(line));
387   if (nread < 3 || !(line[0] == 'O' && line[1] == 'K'
388                      && (line[2] == '\n' || line[2] == ' ')) )
389     {
390 #ifdef SPWQ_USE_LOGGING
391       log_error ( _("communication problem with gpg-agent\n"));
392 #endif
393       close (fd );
394       return SPWQ_PROTOCOL_ERROR;
395     }
396
397   rc = agent_send_all_options (fd);
398   if (rc)
399     {
400 #ifdef SPWQ_USE_LOGGING
401       log_error (_("problem setting the gpg-agent options\n"));
402 #endif
403       close (fd);
404       return rc;
405     }
406
407   *rfd = fd;
408   return 0;
409 }
410
411
412 /* Copy text to BUFFER and escape as required.  Return a pointer to
413    the end of the new buffer.  Note that BUFFER must be large enough
414    to keep the entire text; allocataing it 3 times the size of TEXT
415    is sufficient. */
416 static char *
417 copy_and_escape (char *buffer, const char *text)
418 {
419   int i;
420   const unsigned char *s = (unsigned char *)text;
421   char *p = buffer;
422
423
424   for (i=0; s[i]; i++)
425     {
426       if (s[i] < ' ' || s[i] == '+')
427         {
428           sprintf (p, "%%%02X", s[i]);
429           p += 3;
430         }
431       else if (s[i] == ' ')
432         *p++ = '+';
433       else
434         *p++ = s[i];
435     }
436   return p;
437 }
438
439
440 /* Set the name of the default socket to NAME.  */
441 int
442 simple_pw_set_socket (const char *name)
443 {
444   spwq_free (default_gpg_agent_info);
445   if (name)
446     {
447       default_gpg_agent_info = spwq_malloc (strlen (name) + 4 + 1);
448       if (!default_gpg_agent_info)
449         return SPWQ_OUT_OF_CORE;
450       /* We don't know the PID thus we use 0.  */
451       strcpy (stpcpy (default_gpg_agent_info, name),
452               PATHSEP_S "0" PATHSEP_S "1");
453     }
454   else
455     default_gpg_agent_info = NULL;
456
457   return 0;
458 }
459
460
461 /* Ask the gpg-agent for a passphrase and present the user with a
462    DESCRIPTION, a PROMPT and optionally with a TRYAGAIN extra text.
463    If a CACHEID is not NULL it is used to locate the passphrase in in
464    the cache and store it under this ID.  If OPT_CHECK is true
465    gpg-agent is asked to apply some checks on the passphrase security.
466    If ERRORCODE is not NULL it should point a variable receiving an
467    errorcode; this error code might be 0 if the user canceled the
468    operation.  The function returns NULL to indicate an error.  */
469 char *
470 simple_pwquery (const char *cacheid,
471                 const char *tryagain,
472                 const char *prompt,
473                 const char *description,
474                 int opt_check,
475                 int *errorcode)
476 {
477   int fd = -1;
478   int nread;
479   char *result = NULL;
480   char *pw = NULL;
481   char *p;
482   int rc, i;
483
484   rc = agent_open (&fd);
485   if (rc)
486     goto leave;
487
488   if (!cacheid)
489     cacheid = "X";
490   if (!tryagain)
491     tryagain = "X";
492   if (!prompt)
493     prompt = "X";
494   if (!description)
495     description = "X";
496
497   {
498     char *line;
499     /* We allocate 3 times the needed space so that there is enough
500        space for escaping. */
501     line = spwq_malloc (15 + 10
502                         + 3*strlen (cacheid) + 1
503                         + 3*strlen (tryagain) + 1
504                         + 3*strlen (prompt) + 1
505                         + 3*strlen (description) + 1
506                         + 2);
507     if (!line)
508       {
509         rc = SPWQ_OUT_OF_CORE;
510         goto leave;
511       }
512     strcpy (line, "GET_PASSPHRASE ");
513     p = line+15;
514     if (opt_check)
515       p = stpcpy (p, "--check ");
516     p = copy_and_escape (p, cacheid);
517     *p++ = ' ';
518     p = copy_and_escape (p, tryagain);
519     *p++ = ' ';
520     p = copy_and_escape (p, prompt);
521     *p++ = ' ';
522     p = copy_and_escape (p, description);
523     *p++ = '\n';
524     rc = writen (fd, line, p - line);
525     spwq_free (line);
526     if (rc)
527       goto leave;
528   }
529
530   /* get response */
531   pw = spwq_secure_malloc (500);
532   nread = readline (fd, pw, 499);
533   if (nread < 0)
534     {
535       rc = -nread;
536       goto leave;
537     }
538   if (nread < 3)
539     {
540       rc = SPWQ_PROTOCOL_ERROR;
541       goto leave;
542     }
543
544   if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ')
545     { /* we got a passphrase - convert it back from hex */
546       size_t pwlen = 0;
547
548       for (i=3; i < nread && hexdigitp (pw+i); i+=2)
549         pw[pwlen++] = xtoi_2 (pw+i);
550       pw[pwlen] = 0; /* make a C String */
551       result = pw;
552       pw = NULL;
553     }
554   else if ((nread > 7 && !memcmp (pw, "ERR 111", 7)
555             && (pw[7] == ' ' || pw[7] == '\n') )
556            || ((nread > 4 && !memcmp (pw, "ERR ", 4)
557                 && (strtoul (pw+4, NULL, 0) & 0xffff) == 99)) )
558     {
559       /* 111 is the old Assuan code for canceled which might still
560          be in use by old installations. 99 is GPG_ERR_CANCELED as
561          used by modern gpg-agents; 0xffff is used to mask out the
562          error source.  */
563 #ifdef SPWQ_USE_LOGGING
564       log_info (_("canceled by user\n") );
565 #endif
566       *errorcode = 0; /* Special error code to indicate Cancel. */
567     }
568   else if (nread > 4 && !memcmp (pw, "ERR ", 4))
569     {
570       switch ( (strtoul (pw+4, NULL, 0) & 0xffff) )
571         {
572         case 85: rc = SPWQ_NO_PIN_ENTRY;  break;
573         default: rc = SPWQ_GENERAL_ERROR; break;
574         }
575     }
576   else
577     {
578 #ifdef SPWQ_USE_LOGGING
579       log_error (_("problem with the agent\n"));
580 #endif
581       rc = SPWQ_ERR_RESPONSE;
582     }
583
584  leave:
585   if (errorcode)
586     *errorcode = rc;
587   if (fd != -1)
588     close (fd);
589   if (pw)
590     spwq_secure_free (pw);
591   return result;
592 }
593
594
595 /* Ask the gpg-agent to clear the passphrase for the cache ID CACHEID.  */
596 int
597 simple_pwclear (const char *cacheid)
598 {
599   char line[500];
600   char *p;
601
602   /* We need not more than 50 characters for the command and the
603      terminating nul.  */
604   if (strlen (cacheid) * 3 > sizeof (line) - 50)
605     return SPWQ_PROTOCOL_ERROR;
606
607   strcpy (line, "CLEAR_PASSPHRASE ");
608   p = line + 17;
609   p = copy_and_escape (p, cacheid);
610   *p++ = '\n';
611   *p++ = '\0';
612
613   return simple_query (line);
614 }
615
616
617 /* Perform the simple query QUERY (which must be new-line and 0
618    terminated) and return the error code.  */
619 int
620 simple_query (const char *query)
621 {
622   int fd = -1;
623   int nread;
624   char response[500];
625   int rc;
626
627   rc = agent_open (&fd);
628   if (rc)
629     goto leave;
630
631   rc = writen (fd, query, strlen (query));
632   if (rc)
633     goto leave;
634
635   /* get response */
636   nread = readline (fd, response, 499);
637   if (nread < 0)
638     {
639       rc = -nread;
640       goto leave;
641     }
642   if (nread < 3)
643     {
644       rc = SPWQ_PROTOCOL_ERROR;
645       goto leave;
646     }
647
648   if (response[0] == 'O' && response[1] == 'K')
649     /* OK, do nothing.  */;
650   else if ((nread > 7 && !memcmp (response, "ERR 111", 7)
651             && (response[7] == ' ' || response[7] == '\n') )
652            || ((nread > 4 && !memcmp (response, "ERR ", 4)
653                 && (strtoul (response+4, NULL, 0) & 0xffff) == 99)) )
654     {
655       /* 111 is the old Assuan code for canceled which might still
656          be in use by old installations. 99 is GPG_ERR_CANCELED as
657          used by modern gpg-agents; 0xffff is used to mask out the
658          error source.  */
659 #ifdef SPWQ_USE_LOGGING
660       log_info (_("canceled by user\n") );
661 #endif
662     }
663   else
664     {
665 #ifdef SPWQ_USE_LOGGING
666       log_error (_("problem with the agent\n"));
667 #endif
668       rc = SPWQ_ERR_RESPONSE;
669     }
670
671  leave:
672   if (fd != -1)
673     close (fd);
674   return rc;
675 }