The big Assuan error code removal.
[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, 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 (gpg_err_code (rc) == GPG_ERR_ASS_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", gpg_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 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 int
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 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 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 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 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 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 ();
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 int
279 inq_ciphertext_cb (void *opaque, const char *keyword)
280 {
281   struct cipher_parm_s *parm = opaque; 
282   int 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 *p, *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 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 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 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 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   assert (len); /* (we forced Nul termination.)  */
357
358   if (*buf == '(')
359     {
360       if (len < 13 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)\0" */
361         return gpg_error (GPG_ERR_INV_SEXP);
362       len -= 11;   /* Count only the data of the second part. */
363       p = buf + 8; /* Skip leading parenthesis and the value tag. */
364     }
365   else
366     {
367       /* For compatibility with older gpg-agents handle the old style
368          incomplete S-exps. */
369       len--;      /* Do not count the Nul. */
370       p = buf;
371     }
372
373   n = strtoul (p, &endp, 10);
374   if (!n || *endp != ':')
375     return gpg_error (GPG_ERR_INV_SEXP);
376   endp++;
377   if (endp-p+n > len)
378     return gpg_error (GPG_ERR_INV_SEXP); /* Oops: Inconsistent S-Exp. */
379   
380   memmove (buf, endp, n);
381
382   *r_buflen = n;
383   *r_buf = buf;
384   return 0;
385 }
386
387
388
389
390 \f
391 /* Handle a KEYPARMS inquiry.  Note, we only send the data,
392    assuan_transact takes care of flushing and writing the end */
393 static int
394 inq_genkey_parms (void *opaque, const char *keyword)
395 {
396   struct genkey_parm_s *parm = opaque; 
397   int rc;
398
399   rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
400   return rc; 
401 }
402
403
404 \f
405 /* Call the agent to generate a newkey */
406 int
407 gpgsm_agent_genkey (ctrl_t ctrl,
408                     ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
409 {
410   int rc;
411   struct genkey_parm_s gk_parm;
412   membuf_t data;
413   size_t len;
414   unsigned char *buf;
415
416   *r_pubkey = NULL;
417   rc = start_agent (ctrl);
418   if (rc)
419     return rc;
420
421   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
422   if (rc)
423     return rc;
424
425   init_membuf (&data, 1024);
426   gk_parm.ctx = agent_ctx;
427   gk_parm.sexp = keyparms;
428   gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
429   if (!gk_parm.sexplen)
430     return gpg_error (GPG_ERR_INV_VALUE);
431   rc = assuan_transact (agent_ctx, "GENKEY",
432                         membuf_data_cb, &data, 
433                         inq_genkey_parms, &gk_parm, NULL, NULL);
434   if (rc)
435     {
436       xfree (get_membuf (&data, &len));
437       return rc;
438     }
439   buf = get_membuf (&data, &len);
440   if (!buf)
441     return gpg_error (GPG_ERR_ENOMEM);
442   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
443     {
444       xfree (buf);
445       return gpg_error (GPG_ERR_INV_SEXP);
446     }
447   *r_pubkey = buf;
448   return 0;
449 }
450
451 \f
452 /* Call the agent to read the public key part for a given keygrip.  */
453 int
454 gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip,
455                      ksba_sexp_t *r_pubkey)
456 {
457   int rc;
458   membuf_t data;
459   size_t len;
460   unsigned char *buf;
461   char line[ASSUAN_LINELENGTH];
462
463   *r_pubkey = NULL;
464   rc = start_agent (ctrl);
465   if (rc)
466     return rc;
467
468   rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
469   if (rc)
470     return rc;
471
472   snprintf (line, DIM(line)-1, "READKEY %s", hexkeygrip);
473   line[DIM(line)-1] = 0;
474
475   init_membuf (&data, 1024);
476   rc = assuan_transact (agent_ctx, line,
477                         membuf_data_cb, &data, 
478                         NULL, NULL, NULL, NULL);
479   if (rc)
480     {
481       xfree (get_membuf (&data, &len));
482       return rc;
483     }
484   buf = get_membuf (&data, &len);
485   if (!buf)
486     return gpg_error (GPG_ERR_ENOMEM);
487   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
488     {
489       xfree (buf);
490       return gpg_error (GPG_ERR_INV_SEXP);
491     }
492   *r_pubkey = buf;
493   return 0;
494 }
495
496 \f
497 /* Ask the agent whether the certificate is in the list of trusted
498    keys */
499 int
500 gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert)
501 {
502   int rc;
503   char *fpr;
504   char line[ASSUAN_LINELENGTH];
505
506   rc = start_agent (ctrl);
507   if (rc)
508     return rc;
509
510   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
511   if (!fpr)
512     {
513       log_error ("error getting the fingerprint\n");
514       return gpg_error (GPG_ERR_GENERAL);
515     }
516
517   snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr);
518   line[DIM(line)-1] = 0;
519   xfree (fpr);
520
521   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
522   return rc;
523 }
524
525 /* Ask the agent to mark CERT as a trusted Root-CA one */
526 int
527 gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
528 {
529   int rc;
530   char *fpr, *dn;
531   char line[ASSUAN_LINELENGTH];
532
533   rc = start_agent (ctrl);
534   if (rc)
535     return rc;
536
537   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
538   if (!fpr)
539     {
540       log_error ("error getting the fingerprint\n");
541       return gpg_error (GPG_ERR_GENERAL);
542     }
543
544   dn = ksba_cert_get_issuer (cert, 0);
545   if (!dn)
546     {
547       xfree (fpr);
548       return gpg_error (GPG_ERR_GENERAL);
549     }
550   snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn);
551   line[DIM(line)-1] = 0;
552   ksba_free (dn);
553   xfree (fpr);
554
555   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
556   return rc;
557 }
558
559
560 \f
561 /* Ask the agent whether the a corresponding secret key is available
562    for the given keygrip */
563 int
564 gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
565 {
566   int rc;
567   char line[ASSUAN_LINELENGTH];
568
569   rc = start_agent (ctrl);
570   if (rc)
571     return rc;
572
573   if (!hexkeygrip || strlen (hexkeygrip) != 40)
574     return gpg_error (GPG_ERR_INV_VALUE);
575
576   snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
577   line[DIM(line)-1] = 0;
578
579   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
580   return rc;
581 }
582
583 \f
584 static int
585 learn_cb (void *opaque, const void *buffer, size_t length)
586 {
587   struct learn_parm_s *parm = opaque;
588   size_t len;
589   char *buf;
590   ksba_cert_t cert;
591   int rc;
592
593   if (parm->error)
594     return 0;
595
596   if (buffer)
597     {
598       put_membuf (parm->data, buffer, length);
599       return 0;
600     }
601   /* END encountered - process what we have */
602   buf = get_membuf (parm->data, &len);
603   if (!buf)
604     {
605       parm->error = gpg_error (GPG_ERR_ENOMEM);
606       return 0;
607     }
608
609
610   /* FIXME: this should go into import.c */
611   rc = ksba_cert_new (&cert);
612   if (rc)
613     {
614       parm->error = rc;
615       return 0;
616     }
617   rc = ksba_cert_init_from_mem (cert, buf, len);
618   if (rc)
619     {
620       log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
621       ksba_cert_release (cert);
622       parm->error = rc;
623       return 0;
624     }
625
626   rc = gpgsm_basic_cert_check (cert);
627   if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT)
628     { /* For later use we store it in the ephemeral database. */
629       log_info ("issuer certificate missing - storing as ephemeral\n");
630       keydb_store_cert (cert, 1, NULL);
631     }
632   else if (rc)
633     log_error ("invalid certificate: %s\n", gpg_strerror (rc));
634   else
635     {
636       int existed;
637
638       if (!keydb_store_cert (cert, 0, &existed))
639         {
640           if (opt.verbose > 1 && existed)
641             log_info ("certificate already in DB\n");
642           else if (opt.verbose && !existed)
643             log_info ("certificate imported\n");
644         }
645     }
646
647   ksba_cert_release (cert);
648   init_membuf (parm->data, 4096);
649   return 0;
650 }
651   
652 /* Call the agent to learn about a smartcard */
653 int
654 gpgsm_agent_learn (ctrl_t ctrl)
655 {
656   int rc;
657   struct learn_parm_s learn_parm;
658   membuf_t data;
659   size_t len;
660
661   rc = start_agent (ctrl);
662   if (rc)
663     return rc;
664
665   init_membuf (&data, 4096);
666   learn_parm.error = 0;
667   learn_parm.ctx = agent_ctx;
668   learn_parm.data = &data;
669   rc = assuan_transact (agent_ctx, "LEARN --send",
670                         learn_cb, &learn_parm, 
671                         NULL, NULL, NULL, NULL);
672   xfree (get_membuf (&data, &len));
673   if (rc)
674     return rc;
675   return learn_parm.error;
676 }
677
678 \f
679 /* Ask the agent to change the passphrase of the key identified by
680    HEXKEYGRIP. If DESC is not NULL, display instead of the default
681    description message. */
682 int
683 gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
684 {
685   int rc;
686   char line[ASSUAN_LINELENGTH];
687
688   rc = start_agent (ctrl);
689   if (rc)
690     return rc;
691
692   if (!hexkeygrip || strlen (hexkeygrip) != 40)
693     return gpg_error (GPG_ERR_INV_VALUE);
694
695   if (desc)
696     {
697       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
698       line[DIM(line)-1] = 0;
699       rc = assuan_transact (agent_ctx, line,
700                             NULL, NULL, NULL, NULL, NULL, NULL);
701       if (rc)
702         return rc;
703     }
704
705   snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
706   line[DIM(line)-1] = 0;
707
708   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
709   return rc;
710 }
711
712
713 \f
714 /* Ask the agent to pop up a confirmation dialog with the text DESC
715    and an okay and cancel button.  */
716 gpg_error_t
717 gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc)
718 {
719   int rc;
720   char line[ASSUAN_LINELENGTH];
721
722   rc = start_agent (ctrl);
723   if (rc)
724     return rc;
725
726   snprintf (line, DIM(line)-1, "GET_CONFIRMATION %s", desc);
727   line[DIM(line)-1] = 0;
728
729   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
730   return rc;
731 }