a0a1da5c347dec09616a5a1d9e406a5bf5aa41b5
[gnupg.git] / sm / call-agent.c
1 /* call-agent.c - divert operations to the agent
2  *      Copyright (C) 2001, 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 #ifdef HAVE_LOCALE_H
30 #include <locale.h>
31 #endif
32
33 #include "gpgsm.h"
34 #include <gcrypt.h>
35 #include <assuan.h>
36 #include "i18n.h"
37 #include "keydb.h" /* fixme: Move this to import.c */
38 #include "../common/membuf.h"
39
40
41 static ASSUAN_CONTEXT agent_ctx = NULL;
42 static int force_pipe_server = 0;
43
44 struct cipher_parm_s {
45   ASSUAN_CONTEXT ctx;
46   const char *ciphertext;
47   size_t ciphertextlen;
48 };
49
50 struct genkey_parm_s {
51   ASSUAN_CONTEXT ctx;
52   const char *sexp;
53   size_t sexplen;
54 };
55
56 struct learn_parm_s {
57   int error;
58   ASSUAN_CONTEXT ctx;
59   membuf_t *data;
60 };
61
62
63 \f
64 /* Try to connect to the agent via socket or fork it off and work by
65    pipes.  Handle the server's initial greeting */
66 static int
67 start_agent (void)
68 {
69   int rc = 0;
70   char *infostr, *p;
71   ASSUAN_CONTEXT ctx;
72   char *dft_display = NULL;
73   char *dft_ttyname = NULL;
74   char *dft_ttytype = NULL;
75   char *old_lc = NULL;
76   char *dft_lc = NULL;
77
78   if (agent_ctx)
79     return 0; /* fixme: We need a context for each thread or serialize
80                  the access to the agent (which is suitable given that
81                  the agent is not MT. */
82
83   infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
84   if (!infostr || !*infostr)
85     {
86       const char *pgmname;
87       const char *argv[3];
88       int no_close_list[3];
89       int i;
90
91       if (opt.verbose)
92         log_info (_("no running gpg-agent - starting one\n"));
93
94       if (fflush (NULL))
95         {
96           gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
97           log_error ("error flushing pending output: %s\n", strerror (errno));
98           return tmperr;
99         }
100
101       if (!opt.agent_program || !*opt.agent_program)
102         opt.agent_program = GNUPG_DEFAULT_AGENT;
103       if ( !(pgmname = strrchr (opt.agent_program, '/')))
104         pgmname = opt.agent_program;
105       else
106         pgmname++;
107
108       argv[0] = pgmname;
109       argv[1] = "--server";
110       argv[2] = NULL;
111
112       i=0;
113       if (log_get_fd () != -1)
114         no_close_list[i++] = log_get_fd ();
115       no_close_list[i++] = fileno (stderr);
116       no_close_list[i] = -1;
117
118       /* connect to the agent and perform initial handshaking */
119       rc = assuan_pipe_connect (&ctx, opt.agent_program, (char**)argv,
120                                 no_close_list);
121     }
122   else
123     {
124       int prot;
125       int pid;
126
127       infostr = xstrdup (infostr);
128       if ( !(p = strchr (infostr, ':')) || p == infostr)
129         {
130           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
131           xfree (infostr);
132           force_pipe_server = 1;
133           return start_agent ();
134         }
135       *p++ = 0;
136       pid = atoi (p);
137       while (*p && *p != ':')
138         p++;
139       prot = *p? atoi (p+1) : 0;
140       if (prot != 1)
141         {
142           log_error (_("gpg-agent protocol version %d is not supported\n"),
143                      prot);
144           xfree (infostr);
145           force_pipe_server = 1;
146           return start_agent ();
147         }
148
149       rc = assuan_socket_connect (&ctx, infostr, pid);
150       xfree (infostr);
151       if (rc == ASSUAN_Connect_Failed)
152         {
153           log_error (_("can't connect to the agent - trying fall back\n"));
154           force_pipe_server = 1;
155           return start_agent ();
156         }
157     }
158
159   if (rc)
160     {
161       log_error ("can't connect to the agent: %s\n", assuan_strerror (rc));
162       return gpg_error (GPG_ERR_NO_AGENT);
163     }
164   agent_ctx = ctx;
165
166   if (DBG_ASSUAN)
167     log_debug ("connection to agent established\n");
168
169   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
170   if (rc)
171     return map_assuan_err (rc);
172
173   dft_display = getenv ("DISPLAY");
174   if (opt.display || dft_display)
175     {
176       char *optstr;
177       if (asprintf (&optstr, "OPTION display=%s",
178                     opt.display ? opt.display : dft_display) < 0)
179         return OUT_OF_CORE (errno);
180       rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
181                             NULL);
182       free (optstr);
183       if (rc)
184         return map_assuan_err (rc);
185     }
186   if (!opt.ttyname)
187     {
188       dft_ttyname = getenv ("GPG_TTY");
189       if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
190         dft_ttyname = ttyname (0);
191     }
192   if (opt.ttyname || dft_ttyname)
193     {
194       char *optstr;
195       if (asprintf (&optstr, "OPTION ttyname=%s",
196                     opt.ttyname ? opt.ttyname : dft_ttyname) < 0)
197         return OUT_OF_CORE (errno);
198       rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
199                             NULL);
200       free (optstr);
201       if (rc)
202         return map_assuan_err (rc);
203     }
204   dft_ttytype = getenv ("TERM");
205   if (opt.ttytype || (dft_ttyname && dft_ttytype))
206     {
207       char *optstr;
208       if (asprintf (&optstr, "OPTION ttytype=%s",
209                     opt.ttyname ? opt.ttytype : dft_ttytype) < 0)
210         return OUT_OF_CORE (errno);
211       rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
212                             NULL);
213       free (optstr);
214       if (rc)
215         return map_assuan_err (rc);
216     }
217 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
218   old_lc = setlocale (LC_CTYPE, NULL);
219   if (old_lc)
220     {
221       old_lc = strdup (old_lc);
222       if (!old_lc)
223         return OUT_OF_CORE (errno);
224     }
225   dft_lc = setlocale (LC_CTYPE, "");
226 #endif
227   if (opt.lc_ctype || (dft_ttyname && dft_lc))
228     {
229       char *optstr;
230       if (asprintf (&optstr, "OPTION lc-ctype=%s",
231                     opt.lc_ctype ? opt.lc_ctype : dft_lc) < 0)
232         rc = OUT_OF_CORE (errno);
233       else
234         {
235           rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
236                                 NULL);
237           free (optstr);
238           if (rc)
239             rc = map_assuan_err (rc);
240         }
241     }
242 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
243   if (old_lc)
244     {
245       setlocale (LC_CTYPE, old_lc);
246       free (old_lc);
247     }
248 #endif
249   if (rc)
250     return rc;
251 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
252   old_lc = setlocale (LC_MESSAGES, NULL);
253   if (old_lc)
254     {
255       old_lc = strdup (old_lc);
256       if (!old_lc)
257         return OUT_OF_CORE (errno);
258     }
259   dft_lc = setlocale (LC_MESSAGES, "");
260 #endif
261   if (opt.lc_messages || (dft_ttyname && dft_lc))
262     {
263       char *optstr;
264       if (asprintf (&optstr, "OPTION lc-messages=%s",
265                     opt.lc_messages ? opt.lc_messages : dft_lc) < 0)
266         rc = OUT_OF_CORE (errno);
267       else
268         {
269           rc = assuan_transact (agent_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
270                                 NULL);
271           free (optstr);
272           if (rc)
273             rc = map_assuan_err (rc);
274         }
275     }
276 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
277   if (old_lc)
278     {
279       setlocale (LC_MESSAGES, old_lc);
280       free (old_lc);
281     }
282 #endif
283
284   return rc;
285 }
286
287
288 static AssuanError
289 membuf_data_cb (void *opaque, const void *buffer, size_t length)
290 {
291   membuf_t *data = opaque;
292
293   if (buffer)
294     put_membuf (data, buffer, length);
295   return 0;
296 }
297   
298
299
300 \f
301 /* Call the agent to do a sign operation using the key identified by
302    the hex string KEYGRIP. */
303 int
304 gpgsm_agent_pksign (const char *keygrip, const char *desc,
305                     unsigned char *digest, size_t digestlen, int digestalgo,
306                     char **r_buf, size_t *r_buflen )
307 {
308   int rc, i;
309   char *p, line[ASSUAN_LINELENGTH];
310   membuf_t data;
311   size_t len;
312
313   *r_buf = NULL;
314   rc = start_agent ();
315   if (rc)
316     return rc;
317
318   if (digestlen*2 + 50 > DIM(line))
319     return gpg_error (GPG_ERR_GENERAL);
320
321   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
322   if (rc)
323     return map_assuan_err (rc);
324
325   snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
326   line[DIM(line)-1] = 0;
327   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
328   if (rc)
329     return map_assuan_err (rc);
330
331   if (desc)
332     {
333       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
334       line[DIM(line)-1] = 0;
335       rc = assuan_transact (agent_ctx, line,
336                             NULL, NULL, NULL, NULL, NULL, NULL);
337       if (rc)
338         return map_assuan_err (rc);
339     }
340
341   sprintf (line, "SETHASH %d ", digestalgo);
342   p = line + strlen (line);
343   for (i=0; i < digestlen ; i++, p += 2 )
344     sprintf (p, "%02X", digest[i]);
345   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
346   if (rc)
347     return map_assuan_err (rc);
348
349   init_membuf (&data, 1024);
350   rc = assuan_transact (agent_ctx, "PKSIGN",
351                         membuf_data_cb, &data, NULL, NULL, NULL, NULL);
352   if (rc)
353     {
354       xfree (get_membuf (&data, &len));
355       return map_assuan_err (rc);
356     }
357   *r_buf = get_membuf (&data, r_buflen);
358
359   if (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL))
360     {
361       xfree (*r_buf); *r_buf = NULL;
362       return gpg_error (GPG_ERR_INV_VALUE);
363     }
364
365   return *r_buf? 0 : OUT_OF_CORE (errno);
366 }
367
368
369
370 \f
371 /* Handle a CIPHERTEXT inquiry.  Note, we only send the data,
372    assuan_transact talkes care of flushing and writing the end */
373 static AssuanError
374 inq_ciphertext_cb (void *opaque, const char *keyword)
375 {
376   struct cipher_parm_s *parm = opaque; 
377   AssuanError rc;
378
379   assuan_begin_confidential (parm->ctx);
380   rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
381   assuan_end_confidential (parm->ctx);
382   return rc; 
383 }
384
385
386 /* Call the agent to do a decrypt operation using the key identified by
387    the hex string KEYGRIP. */
388 int
389 gpgsm_agent_pkdecrypt (const char *keygrip, const char *desc,
390                        ksba_const_sexp_t ciphertext, 
391                        char **r_buf, size_t *r_buflen )
392 {
393   int rc;
394   char line[ASSUAN_LINELENGTH];
395   membuf_t data;
396   struct cipher_parm_s cipher_parm;
397   size_t n, len;
398   char *buf, *endp;
399   size_t ciphertextlen;
400   
401   if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
402     return gpg_error (GPG_ERR_INV_VALUE);
403   *r_buf = NULL;
404
405   ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL);
406   if (!ciphertextlen)
407     return gpg_error (GPG_ERR_INV_VALUE);
408
409   rc = start_agent ();
410   if (rc)
411     return rc;
412
413   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
414   if (rc)
415     return map_assuan_err (rc);
416
417   assert ( DIM(line) >= 50 );
418   snprintf (line, DIM(line)-1, "SETKEY %s", keygrip);
419   line[DIM(line)-1] = 0;
420   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
421   if (rc)
422     return map_assuan_err (rc);
423
424   if (desc)
425     {
426       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
427       line[DIM(line)-1] = 0;
428       rc = assuan_transact (agent_ctx, line,
429                             NULL, NULL, NULL, NULL, NULL, NULL);
430       if (rc)
431         return map_assuan_err (rc);
432     }
433
434   init_membuf (&data, 1024);
435   cipher_parm.ctx = agent_ctx;
436   cipher_parm.ciphertext = ciphertext;
437   cipher_parm.ciphertextlen = ciphertextlen;
438   rc = assuan_transact (agent_ctx, "PKDECRYPT",
439                         membuf_data_cb, &data,
440                         inq_ciphertext_cb, &cipher_parm, NULL, NULL);
441   if (rc)
442     {
443       xfree (get_membuf (&data, &len));
444       return map_assuan_err (rc);
445     }
446
447   put_membuf (&data, "", 1); /* make sure it is 0 terminated */
448   buf = get_membuf (&data, &len);
449   if (!buf)
450     return gpg_error (GPG_ERR_ENOMEM);
451   /* FIXME: We would better a return a full S-exp and not just a part */
452   assert (len);
453   len--; /* remove the terminating 0 */
454   n = strtoul (buf, &endp, 10);
455   if (!n || *endp != ':')
456     return gpg_error (GPG_ERR_INV_SEXP);
457   endp++;
458   if (endp-buf+n > len)
459     return gpg_error (GPG_ERR_INV_SEXP); /* oops len does not
460                                             match internal len*/
461   memmove (buf, endp, n);
462   *r_buflen = n;
463   *r_buf = buf;
464   return 0;
465 }
466
467
468
469
470 \f
471 /* Handle a KEYPARMS inquiry.  Note, we only send the data,
472    assuan_transact takes care of flushing and writing the end */
473 static AssuanError
474 inq_genkey_parms (void *opaque, const char *keyword)
475 {
476   struct genkey_parm_s *parm = opaque; 
477   AssuanError rc;
478
479   rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
480   return rc; 
481 }
482
483
484 \f
485 /* Call the agent to generate a newkey */
486 int
487 gpgsm_agent_genkey (ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
488 {
489   int rc;
490   struct genkey_parm_s gk_parm;
491   membuf_t data;
492   size_t len;
493   char *buf;
494
495   *r_pubkey = NULL;
496   rc = start_agent ();
497   if (rc)
498     return rc;
499
500   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
501   if (rc)
502     return map_assuan_err (rc);
503
504   init_membuf (&data, 1024);
505   gk_parm.ctx = agent_ctx;
506   gk_parm.sexp = keyparms;
507   gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
508   if (!gk_parm.sexplen)
509     return gpg_error (GPG_ERR_INV_VALUE);
510   rc = assuan_transact (agent_ctx, "GENKEY",
511                         membuf_data_cb, &data, 
512                         inq_genkey_parms, &gk_parm, NULL, NULL);
513   if (rc)
514     {
515       xfree (get_membuf (&data, &len));
516       return map_assuan_err (rc);
517     }
518   buf = get_membuf (&data, &len);
519   if (!buf)
520     return gpg_error (GPG_ERR_ENOMEM);
521   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
522     {
523       xfree (buf);
524       return gpg_error (GPG_ERR_INV_SEXP);
525     }
526   *r_pubkey = buf;
527   return 0;
528 }
529
530 \f
531 /* Ask the agent whether the certificate is in the list of trusted
532    keys */
533 int
534 gpgsm_agent_istrusted (ksba_cert_t cert)
535 {
536   int rc;
537   char *fpr;
538   char line[ASSUAN_LINELENGTH];
539
540   rc = start_agent ();
541   if (rc)
542     return rc;
543
544   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
545   if (!fpr)
546     {
547       log_error ("error getting the fingerprint\n");
548       return gpg_error (GPG_ERR_GENERAL);
549     }
550
551   snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr);
552   line[DIM(line)-1] = 0;
553   xfree (fpr);
554
555   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
556   return map_assuan_err (rc);
557 }
558
559 /* Ask the agent to mark CERT as a trusted Root-CA one */
560 int
561 gpgsm_agent_marktrusted (ksba_cert_t cert)
562 {
563   int rc;
564   char *fpr, *dn;
565   char line[ASSUAN_LINELENGTH];
566
567   rc = start_agent ();
568   if (rc)
569     return rc;
570
571   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
572   if (!fpr)
573     {
574       log_error ("error getting the fingerprint\n");
575       return gpg_error (GPG_ERR_GENERAL);
576     }
577
578   dn = ksba_cert_get_issuer (cert, 0);
579   if (!dn)
580     {
581       xfree (fpr);
582       return gpg_error (GPG_ERR_GENERAL);
583     }
584   snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn);
585   line[DIM(line)-1] = 0;
586   ksba_free (dn);
587   xfree (fpr);
588
589   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
590   return map_assuan_err (rc);
591 }
592
593
594 \f
595 /* Ask the agent whether the a corresponding secret key is available
596    for the given keygrip */
597 int
598 gpgsm_agent_havekey (const char *hexkeygrip)
599 {
600   int rc;
601   char line[ASSUAN_LINELENGTH];
602
603   rc = start_agent ();
604   if (rc)
605     return rc;
606
607   if (!hexkeygrip || strlen (hexkeygrip) != 40)
608     return gpg_error (GPG_ERR_INV_VALUE);
609
610   snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
611   line[DIM(line)-1] = 0;
612
613   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
614   return map_assuan_err (rc);
615 }
616
617 \f
618 static AssuanError
619 learn_cb (void *opaque, const void *buffer, size_t length)
620 {
621   struct learn_parm_s *parm = opaque;
622   size_t len;
623   char *buf;
624   ksba_cert_t cert;
625   int rc;
626
627   if (parm->error)
628     return 0;
629
630   if (buffer)
631     {
632       put_membuf (parm->data, buffer, length);
633       return 0;
634     }
635   /* END encountered - process what we have */
636   buf = get_membuf (parm->data, &len);
637   if (!buf)
638     {
639       parm->error = gpg_error (GPG_ERR_ENOMEM);
640       return 0;
641     }
642
643
644   /* FIXME: this should go into import.c */
645   rc = ksba_cert_new (&cert);
646   if (rc)
647     {
648       parm->error = rc;
649       return 0;
650     }
651   rc = ksba_cert_init_from_mem (cert, buf, len);
652   if (rc)
653     {
654       log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
655       ksba_cert_release (cert);
656       parm->error = rc;
657       return 0;
658     }
659
660   rc = gpgsm_basic_cert_check (cert);
661   if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT)
662     { /* For later use we store it in the ephemeral database. */
663       log_info ("issuer certificate missing - storing as ephemeral\n");
664       keydb_store_cert (cert, 1, NULL);
665     }
666   else if (rc)
667     log_error ("invalid certificate: %s\n", gpg_strerror (rc));
668   else
669     {
670       int existed;
671
672       if (!keydb_store_cert (cert, 0, &existed))
673         {
674           if (opt.verbose > 1 && existed)
675             log_info ("certificate already in DB\n");
676           else if (opt.verbose && !existed)
677             log_info ("certificate imported\n");
678         }
679     }
680
681   ksba_cert_release (cert);
682   init_membuf (parm->data, 4096);
683   return 0;
684 }
685   
686 /* Call the agent to learn about a smartcard */
687 int
688 gpgsm_agent_learn ()
689 {
690   int rc;
691   struct learn_parm_s learn_parm;
692   membuf_t data;
693   size_t len;
694
695   rc = start_agent ();
696   if (rc)
697     return rc;
698
699   init_membuf (&data, 4096);
700   learn_parm.error = 0;
701   learn_parm.ctx = agent_ctx;
702   learn_parm.data = &data;
703   rc = assuan_transact (agent_ctx, "LEARN --send",
704                         learn_cb, &learn_parm, 
705                         NULL, NULL, NULL, NULL);
706   xfree (get_membuf (&data, &len));
707   if (rc)
708     return map_assuan_err (rc);
709   return learn_parm.error;
710 }
711
712 \f
713 /* Ask the agent to change the passphrase of the key identified by HEXKEYGRIP. */
714 int
715 gpgsm_agent_passwd (const char *hexkeygrip)
716 {
717   int rc;
718   char line[ASSUAN_LINELENGTH];
719
720   rc = start_agent ();
721   if (rc)
722     return rc;
723
724   if (!hexkeygrip || strlen (hexkeygrip) != 40)
725     return gpg_error (GPG_ERR_INV_VALUE);
726
727   snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
728   line[DIM(line)-1] = 0;
729
730   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
731   return map_assuan_err (rc);
732 }
733