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