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