A whole bunch of changes to allow building for W32.
[gnupg.git] / sm / call-dirmngr.c
1 /* call-dirmngr.c - communication with the dromngr 
2  *      Copyright (C) 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h> 
27 #include <time.h>
28 #include <assert.h>
29 #include <ctype.h>
30
31 #include "gpgsm.h"
32 #include <gcrypt.h>
33 #include <assuan.h>
34
35 #include "i18n.h"
36 #include "keydb.h"
37
38 /* The name of the socket for a system daemon.  */
39 #define DEFAULT_SOCKET_NAME "/var/run/dirmngr/socket"
40
41 struct membuf {
42   size_t len;
43   size_t size;
44   char *buf;
45   int out_of_core;
46 };
47
48
49
50 static ASSUAN_CONTEXT dirmngr_ctx = NULL;
51 static int force_pipe_server = 0;
52
53 struct inq_certificate_parm_s {
54   ASSUAN_CONTEXT ctx;
55   ksba_cert_t cert;
56   ksba_cert_t issuer_cert;
57 };
58
59 struct isvalid_status_parm_s {
60   int seen;
61   unsigned char fpr[20];
62 };
63
64
65 struct lookup_parm_s {
66   CTRL ctrl;
67   ASSUAN_CONTEXT ctx;
68   void (*cb)(void *, ksba_cert_t);
69   void *cb_value;
70   struct membuf data;
71   int error;
72 };
73
74 struct run_command_parm_s {
75   ASSUAN_CONTEXT ctx;
76 };
77
78
79 /* A simple implementation of a dynamic buffer.  Use init_membuf() to
80    create a buffer, put_membuf to append bytes and get_membuf to
81    release and return the buffer.  Allocation errors are detected but
82    only returned at the final get_membuf(), this helps not to clutter
83    the code with out of core checks.  */
84
85 static void
86 init_membuf (struct membuf *mb, int initiallen)
87 {
88   mb->len = 0;
89   mb->size = initiallen;
90   mb->out_of_core = 0;
91   mb->buf = xtrymalloc (initiallen);
92   if (!mb->buf)
93       mb->out_of_core = 1;
94 }
95
96 static void
97 put_membuf (struct membuf *mb, const void *buf, size_t len)
98 {
99   if (mb->out_of_core)
100     return;
101
102   if (mb->len + len >= mb->size)
103     {
104       char *p;
105       
106       mb->size += len + 1024;
107       p = xtryrealloc (mb->buf, mb->size);
108       if (!p)
109         {
110           mb->out_of_core = 1;
111           return;
112         }
113       mb->buf = p;
114     }
115   memcpy (mb->buf + mb->len, buf, len);
116   mb->len += len;
117 }
118
119 static void *
120 get_membuf (struct membuf *mb, size_t *len)
121 {
122   char *p;
123
124   if (mb->out_of_core)
125     {
126       xfree (mb->buf);
127       mb->buf = NULL;
128       return NULL;
129     }
130
131   p = mb->buf;
132   *len = mb->len;
133   mb->buf = NULL;
134   mb->out_of_core = 1; /* don't allow a reuse */
135   return p;
136 }
137
138
139
140
141 \f
142 /* Try to connect to the agent via socket or fork it off and work by
143    pipes.  Handle the server's initial greeting */
144 static int
145 start_dirmngr (void)
146 {
147   int rc;
148   char *infostr, *p;
149   ASSUAN_CONTEXT ctx;
150   int try_default = 0;
151
152   if (dirmngr_ctx)
153     return 0; /* fixme: We need a context for each thread or serialize
154                  the access to the dirmngr */
155   /* Note: if you change this to multiple connections, you also need
156      to take care of the implicit option sending caching. */
157
158   infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO");
159   if (opt.prefer_system_dirmngr && !force_pipe_server
160       &&(!infostr || !*infostr))
161     {
162       infostr = DEFAULT_SOCKET_NAME;
163       try_default = 1;
164     }
165   if (!infostr || !*infostr)
166     {
167       const char *pgmname;
168       const char *argv[3];
169       int no_close_list[3];
170       int i;
171
172       if (opt.verbose)
173         log_info (_("no running dirmngr - starting one\n"));
174       
175       if (fflush (NULL))
176         {
177           gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
178           log_error ("error flushing pending output: %s\n", strerror (errno));
179           return tmperr;
180         }
181
182       if (!opt.dirmngr_program || !*opt.dirmngr_program)
183         opt.dirmngr_program = GNUPG_DEFAULT_DIRMNGR;
184       if ( !(pgmname = strrchr (opt.dirmngr_program, '/')))
185         pgmname = opt.dirmngr_program;
186       else
187         pgmname++;
188
189       argv[0] = pgmname;
190       argv[1] = "--server";
191       argv[2] = NULL;
192
193       i=0;
194       if (log_get_fd () != -1)
195         no_close_list[i++] = log_get_fd ();
196       no_close_list[i++] = fileno (stderr);
197       no_close_list[i] = -1;
198
199       /* connect to the agent and perform initial handshaking */
200       rc = assuan_pipe_connect (&ctx, opt.dirmngr_program, (char**)argv,
201                                 no_close_list);
202     }
203   else
204     {
205       int prot;
206       int pid;
207
208       infostr = xstrdup (infostr);
209       if (!try_default && *infostr)
210         {
211           if ( !(p = strchr (infostr, ':')) || p == infostr)
212             {
213               log_error (_("malformed DIRMNGR_INFO environment variable\n"));
214               xfree (infostr);
215               force_pipe_server = 1;
216               return start_dirmngr ();
217             }
218           *p++ = 0;
219           pid = atoi (p);
220           while (*p && *p != ':')
221             p++;
222           prot = *p? atoi (p+1) : 0;
223           if (prot != 1)
224             {
225               log_error (_("dirmngr protocol version %d is not supported\n"),
226                          prot);
227               xfree (infostr);
228               force_pipe_server = 1;
229               return start_dirmngr ();
230             }
231         }
232       else
233         pid = -1;
234
235       rc = assuan_socket_connect (&ctx, infostr, pid);
236       xfree (infostr);
237       if (rc == ASSUAN_Connect_Failed)
238         {
239           log_error (_("can't connect to the dirmngr - trying fall back\n"));
240           force_pipe_server = 1;
241           return start_dirmngr ();
242         }
243     }
244
245   if (rc)
246     {
247       log_error ("can't connect to the dirmngr: %s\n", assuan_strerror (rc));
248       return gpg_error (GPG_ERR_NO_DIRMNGR);
249     }
250   dirmngr_ctx = ctx;
251
252   if (DBG_ASSUAN)
253     log_debug ("connection to dirmngr established\n");
254   return 0;
255 }
256
257
258 \f
259 /* Handle a SENDCERT inquiry. */
260 static AssuanError
261 inq_certificate (void *opaque, const char *line)
262 {
263   struct inq_certificate_parm_s *parm = opaque;
264   AssuanError rc;
265   const unsigned char *der;
266   size_t derlen;
267   int issuer_mode = 0;
268
269   if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))
270     {
271       line += 8;
272     }
273   else if (!strncmp (line, "SENDISSUERCERT", 14)
274            && (line[14] == ' ' || !line[14]))
275     {
276       line += 14;
277       issuer_mode = 1;
278     }
279   else
280     {
281       log_error ("unsupported inquiry `%s'\n", line);
282       return ASSUAN_Inquire_Unknown;
283     }
284
285   if (!*line)
286     { /* Send the current certificate. */
287       der = ksba_cert_get_image (issuer_mode? parm->issuer_cert : parm->cert,
288                                  &derlen);
289       if (!der)
290         rc = ASSUAN_Inquire_Error;
291       else
292         rc = assuan_send_data (parm->ctx, der, derlen);
293     }
294   else if (issuer_mode)
295     {
296       log_error ("sending specific issuer certificate back "
297                  "is not yet implemented\n");
298       rc = ASSUAN_Inquire_Error;
299     }
300   else 
301     { /* Send the given certificate. */
302       int err;
303       ksba_cert_t cert;
304
305
306       err = gpgsm_find_cert (line, &cert);
307       if (err)
308         {
309           log_error ("certificate not found: %s\n", gpg_strerror (err));
310           rc = ASSUAN_Inquire_Error;
311         }
312       else
313         {
314           der = ksba_cert_get_image (cert, &derlen);
315           if (!der)
316             rc = ASSUAN_Inquire_Error;
317           else
318             rc = assuan_send_data (parm->ctx, der, derlen);
319           ksba_cert_release (cert);
320         }
321     }
322
323   return rc; 
324 }
325
326
327 /* Take a 20 byte hexencoded string and put it into the the provided
328    20 byte buffer FPR in binary format. */
329 static int
330 unhexify_fpr (const char *hexstr, unsigned char *fpr)
331 {
332   const char *s;
333   int n;
334
335   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
336     ;
337   if (*s || (n != 40))
338     return 0; /* no fingerprint (invalid or wrong length). */
339   n /= 2;
340   for (s=hexstr, n=0; *s; s += 2, n++)
341     fpr[n] = xtoi_2 (s);
342   return 1; /* okay */
343 }
344
345
346 static assuan_error_t
347 isvalid_status_cb (void *opaque, const char *line)
348 {
349   struct isvalid_status_parm_s *parm = opaque;
350
351   if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24)
352       && (line[24]==' ' || !line[24]))
353     {
354       parm->seen++;
355       if (!line[24] || !unhexify_fpr (line+25, parm->fpr))
356         parm->seen++; /* Bumb it to indicate an error. */
357     }
358   return 0;
359 }
360
361
362
363 \f
364 /* Call the directory manager to check whether the certificate is valid
365    Returns 0 for valid or usually one of the errors:
366
367   GPG_ERR_CERTIFICATE_REVOKED
368   GPG_ERR_NO_CRL_KNOWN
369   GPG_ERR_CRL_TOO_OLD
370
371   With USE_OCSP set to true, the dirmngr is asked to do an OCSP
372   request first.
373  */
374 int
375 gpgsm_dirmngr_isvalid (ctrl_t ctrl,
376                        ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
377 {
378   static int did_options;
379   int rc;
380   char *certid;
381   char line[ASSUAN_LINELENGTH];
382   struct inq_certificate_parm_s parm;
383   struct isvalid_status_parm_s stparm;
384
385
386   rc = start_dirmngr ();
387   if (rc)
388     return rc;
389
390   if (use_ocsp)
391     {
392       certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
393     }
394   else
395     {
396       certid = gpgsm_get_certid (cert);
397       if (!certid)
398         {
399           log_error ("error getting the certificate ID\n");
400           return gpg_error (GPG_ERR_GENERAL);
401         }
402     }
403
404   if (opt.verbose > 1)
405     {
406       char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
407       log_info ("asking dirmngr about %s%s\n", fpr,
408                 use_ocsp? " (using OCSP)":"");
409       xfree (fpr);
410     }
411
412   parm.ctx = dirmngr_ctx;
413   parm.cert = cert;
414   parm.issuer_cert = issuer_cert;
415
416   stparm.seen = 0;
417   memset (stparm.fpr, 0, 20);
418
419   /* FIXME: If --disable-crl-checks has been set, we should pass an
420      option to dirmngr, so that no fallback CRL check is done after an
421      ocsp check. */
422
423   /* It is sufficient to send the options only once because we have
424      one connection per process only. */
425   if (!did_options)
426     {
427       if (opt.force_crl_refresh)
428         assuan_transact (dirmngr_ctx, "OPTION force-crl-refresh=1",
429                          NULL, NULL, NULL, NULL, NULL, NULL);
430       did_options = 1;
431     }
432   snprintf (line, DIM(line)-1, "ISVALID %s", certid);
433   line[DIM(line)-1] = 0;
434   xfree (certid);
435
436   rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
437                         inq_certificate, &parm,
438                         isvalid_status_cb, &stparm);
439   if (opt.verbose > 1)
440     log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
441   rc = map_assuan_err (rc);
442
443   if (!rc && stparm.seen)
444     {
445       /* Need to also check the certificate validity. */
446       if (stparm.seen != 1)
447         {
448           log_error ("communication problem with dirmngr detected\n");
449           rc = gpg_error (GPG_ERR_INV_CRL);
450         }
451       else
452         {
453           KEYDB_HANDLE kh;
454           ksba_cert_t rspcert = NULL;
455
456           /* Fixme: First try to get the certificate from the
457              dirmngr's cache - it should be there. */
458           kh = keydb_new (0);
459           if (!kh)
460             rc = gpg_error (GPG_ERR_ENOMEM);
461           if (!rc)
462             rc = keydb_search_fpr (kh, stparm.fpr);
463           if (!rc)
464             rc = keydb_get_cert (kh, &rspcert);
465           if (rc)
466             {
467               log_error ("unable to find the certificate used "
468                          "by the dirmngr: %s\n", gpg_strerror (rc));
469               rc = gpg_error (GPG_ERR_INV_CRL);
470             }
471           keydb_release (kh);
472
473           if (!rc)
474             {
475               rc = gpgsm_cert_use_ocsp_p (rspcert);
476               if (rc)
477                 rc = gpg_error (GPG_ERR_INV_CRL);
478               else
479                 {
480                   /* Note, the flag = 1: This avoids checking this
481                      certificate over and over again. */
482                   rc = gpgsm_validate_chain (ctrl, rspcert, NULL, 0, NULL, 1);
483                   if (rc)
484                     {
485                       log_error ("invalid certificate used for CRL/OCSP: %s\n",
486                                  gpg_strerror (rc));
487                       rc = gpg_error (GPG_ERR_INV_CRL);
488                     }
489                 }
490             }
491           ksba_cert_release (rspcert);
492         }
493     }
494   return rc;
495 }
496
497
498 \f
499 /* Lookup helpers*/
500 static AssuanError
501 lookup_cb (void *opaque, const void *buffer, size_t length)
502 {
503   struct lookup_parm_s *parm = opaque;
504   size_t len;
505   char *buf;
506   ksba_cert_t cert;
507   int rc;
508
509   if (parm->error)
510     return 0;
511
512   if (buffer)
513     {
514       put_membuf (&parm->data, buffer, length);
515       return 0;
516     }
517   /* END encountered - process what we have */
518   buf = get_membuf (&parm->data, &len);
519   if (!buf)
520     {
521       parm->error = gpg_error (GPG_ERR_ENOMEM);
522       return 0;
523     }
524
525   rc = ksba_cert_new (&cert);
526   if (rc)
527     {
528       parm->error = rc;
529       return 0;
530     }
531   rc = ksba_cert_init_from_mem (cert, buf, len);
532   if (rc)
533     {
534       log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
535     }
536   else
537     {
538       parm->cb (parm->cb_value, cert);
539     }
540
541   ksba_cert_release (cert);
542   init_membuf (&parm->data, 4096);
543   return 0;
544 }
545
546 /* Return a properly escaped pattern from NAMES.  The only error
547    return is NULL to indicate a malloc failure. */
548 static char *
549 pattern_from_strlist (STRLIST names)
550 {
551   STRLIST sl;
552   int n;
553   const char *s;
554   char *pattern, *p;
555
556   for (n=0, sl=names; sl; sl = sl->next)
557     {
558       for (s=sl->d; *s; s++, n++)
559         {
560           if (*s == '%' || *s == ' ' || *s == '+')
561             n += 2;
562         }
563       n++;
564     }
565
566   p = pattern = xtrymalloc (n+1);
567   if (!pattern)
568     return NULL;
569
570   for (n=0, sl=names; sl; sl = sl->next)
571     {
572       for (s=sl->d; *s; s++)
573         {
574           switch (*s)
575             {
576             case '%':
577               *p++ = '%';
578               *p++ = '2';
579               *p++ = '5';
580               break;
581             case ' ':
582               *p++ = '%';
583               *p++ = '2';
584               *p++ = '0';
585               break;
586             case '+':
587               *p++ = '%';
588               *p++ = '2';
589               *p++ = 'B';
590               break;
591             default:
592               *p++ = *s;
593               break;
594             }
595         }
596       *p++ = ' ';
597     }
598   if (p == pattern)
599     *pattern = 0; /* is empty */
600   else
601     p[-1] = '\0'; /* remove trailing blank */
602   
603   return pattern;
604 }
605
606 static AssuanError
607 lookup_status_cb (void *opaque, const char *line)
608 {
609   struct lookup_parm_s *parm = opaque;
610
611   if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
612     {
613       if (parm->ctrl)
614         {
615           for (line +=9; *line == ' '; line++)
616             ;
617           gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
618         }
619     }
620   return 0;
621 }
622
623
624 /* Run the Directroy Managers lookup command using the pattern
625    compiled from the strings given in NAMES.  The caller must provide
626    the callback CB which will be passed cert by cert.  Note that CTRL
627    is optional. */
628 int 
629 gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
630                       void (*cb)(void*, ksba_cert_t), void *cb_value)
631
632   int rc;
633   char *pattern;
634   char line[ASSUAN_LINELENGTH];
635   struct lookup_parm_s parm;
636   size_t len;
637
638   rc = start_dirmngr ();
639   if (rc)
640     return rc;
641
642   pattern = pattern_from_strlist (names);
643   if (!pattern)
644     return OUT_OF_CORE (errno);
645   snprintf (line, DIM(line)-1, "LOOKUP %s", pattern);
646   line[DIM(line)-1] = 0;
647   xfree (pattern);
648
649   parm.ctrl = ctrl;
650   parm.ctx = dirmngr_ctx;
651   parm.cb = cb;
652   parm.cb_value = cb_value;
653   parm.error = 0;
654   init_membuf (&parm.data, 4096);
655
656   rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm,
657                         NULL, NULL, lookup_status_cb, &parm);
658   xfree (get_membuf (&parm.data, &len));
659   if (rc)
660     return map_assuan_err (rc);
661   return parm.error;
662 }
663
664
665 \f
666 /* Run Command helpers*/
667
668 /* Fairly simple callback to write all output of dirmngr to stdout. */
669 static AssuanError
670 run_command_cb (void *opaque, const void *buffer, size_t length)
671 {
672   if (buffer)
673     {
674       if ( fwrite (buffer, length, 1, stdout) != 1 )
675         log_error ("error writing to stdout: %s\n", strerror (errno));
676     }
677   return 0;
678 }
679
680 /* Handle inquiries from the dirmngr COMMAND. */
681 static AssuanError
682 run_command_inq_cb (void *opaque, const char *line)
683 {
684   struct run_command_parm_s *parm = opaque;
685   AssuanError rc = 0;
686
687   if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
688     { /* send the given certificate */
689       int err;
690       ksba_cert_t cert;
691       const unsigned char *der;
692       size_t derlen;
693
694       line += 8;
695       if (!*line)
696         return ASSUAN_Inquire_Error;
697
698       err = gpgsm_find_cert (line, &cert);
699       if (err)
700         {
701           log_error ("certificate not found: %s\n", gpg_strerror (err));
702           rc = ASSUAN_Inquire_Error;
703         }
704       else
705         {
706           der = ksba_cert_get_image (cert, &derlen);
707           if (!der)
708             rc = ASSUAN_Inquire_Error;
709           else
710             rc = assuan_send_data (parm->ctx, der, derlen);
711           ksba_cert_release (cert);
712         }
713     }
714   else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
715     { /* Simply show the message given in the argument. */
716       line += 9;
717       log_info ("dirmngr: %s\n", line);
718     }
719   else
720     {
721       log_error ("unsupported inquiry `%s'\n", line);
722       rc = ASSUAN_Inquire_Unknown;
723     }
724
725   return rc; 
726 }
727
728 static AssuanError
729 run_command_status_cb (void *opaque, const char *line)
730 {
731   if (opt.verbose)
732     {
733       log_info ("dirmngr status: %s\n", line);
734     }
735   return 0;
736 }
737
738
739
740 /* Pass COMMAND to dirmngr and print all output generated by Dirmngr
741    to stdout.  A couple of inquiries are defined (see above).  ARGC
742    arguments in ARGV are given to the Dirmngr.  Spaces, plus and
743    percent characters within the argument strings are percent escaped
744    so that blanks can act as delimiters. */
745 int
746 gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
747                            int argc, char **argv)
748
749   int rc;
750   int i;
751   const char *s;
752   char *line, *p;
753   size_t len;
754   struct run_command_parm_s parm;
755
756   rc = start_dirmngr ();
757   if (rc)
758     return rc;
759
760   parm.ctx = dirmngr_ctx;
761
762   len = strlen (command) + 1;
763   for (i=0; i < argc; i++)
764     len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
765   line = xtrymalloc (len);
766   if (!line)
767     return OUT_OF_CORE (errno);
768
769   p = stpcpy (line, command);
770   for (i=0; i < argc; i++)
771     {
772       *p++ = ' ';
773       for (s=argv[i]; *s; s++)
774         {
775           if (!isascii (*s))
776             *p++ = *s;
777           else if (*s == ' ')
778             *p++ = '+';
779           else if (!isprint (*s) || *s == '+')
780             {
781               sprintf (p, "%%%02X", *s);
782               p += 3;
783             }
784           else
785             *p++ = *s;
786         }
787     }
788   *p = 0;
789
790   rc = assuan_transact (dirmngr_ctx, line,
791                         run_command_cb, NULL,
792                         run_command_inq_cb, &parm,
793                         run_command_status_cb, NULL);
794   xfree (line);
795   log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
796   return map_assuan_err (rc);
797 }