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