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