[w32] gpg-agent is now started automagically by gpgsm.
[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 "membuf.h"
41 #include "exechelp.h"
42
43
44 static assuan_context_t agent_ctx = NULL;
45 static int force_pipe_server = 0;
46
47 struct cipher_parm_s
48 {
49   assuan_context_t ctx;
50   const unsigned char *ciphertext;
51   size_t ciphertextlen;
52 };
53
54 struct genkey_parm_s
55 {
56   assuan_context_t ctx;
57   const unsigned char *sexp;
58   size_t sexplen;
59 };
60
61 struct learn_parm_s
62 {
63   int error;
64   assuan_context_t ctx;
65   membuf_t *data;
66 };
67
68
69 \f
70 /* Try to connect to the agent via socket or fork it off and work by
71    pipes.  Handle the server's initial greeting */
72 static int
73 start_agent (ctrl_t ctrl)
74 {
75   int rc = 0;
76   char *infostr, *p;
77   assuan_context_t ctx;
78
79   if (agent_ctx)
80     return 0; /* fixme: We need a context for each thread or serialize
81                  the access to the agent (which is suitable given that
82                  the agent is not MT. */
83
84   infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
85   if (!infostr || !*infostr)
86     {
87       char *sockname;
88
89       /* First check whether we can connect at the standard
90          socket.  */
91       sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
92       rc = assuan_socket_connect (&ctx, sockname, 0);
93
94       if (rc)
95         {
96           /* With no success start a new server.  */
97           if (opt.verbose)
98             log_info (_("no running gpg-agent - starting one\n"));
99           
100           gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0");
101           
102           if (fflush (NULL))
103             {
104               gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
105               log_error ("error flushing pending output: %s\n",
106                          strerror (errno));
107               xfree (sockname);
108               return tmperr;
109             }
110           
111           if (!opt.agent_program || !*opt.agent_program)
112             opt.agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT);
113
114 #ifdef HAVE_W32_SYSTEM
115           {
116             /* Under Windows we start the server in daemon mode.  This
117                is because the default is to use the standard socket
118                and thus there is no need for the GPG_AGENT_INFO
119                envvar.  This is possible as we don't have a real unix
120                domain socket but use a plain file and thus there is no
121                need to care about non-local file systems. */
122             const char *argv[3];
123
124             /* The --no-reuse-standard option makes sure that we don't
125                start a second instance of a agent in case another
126                process has started one in the meantime.  */
127             argv[0] = "--daemon";
128             argv[1] = "--no-reuse-standard-socket"; 
129             argv[2] = NULL;  
130
131             rc = gnupg_spawn_process_detached (opt.agent_program, argv, NULL);
132             if (rc)
133               log_debug ("failed to start agent `%s': %s\n",
134                          opt.agent_program, gpg_strerror (rc));
135             else
136               {
137                 /* Give the agent some time to prepare itself. */
138                 gnupg_sleep (3);
139                 /* Now try again to connect the agent.  */
140                 rc = assuan_socket_connect (&ctx, sockname, 0);
141               }
142           }
143 #else /*!HAVE_W32_SYSTEM*/
144           {
145             const char *pgmname;
146             const char *argv[3];
147             int no_close_list[3];
148             int i;
149
150             if ( !(pgmname = strrchr (opt.agent_program, '/')))
151               pgmname = opt.agent_program;
152             else
153               pgmname++;
154             
155             argv[0] = pgmname;
156             argv[1] = "--server";
157             argv[2] = NULL;
158             
159             i=0;
160             if (log_get_fd () != -1)
161               no_close_list[i++] = log_get_fd ();
162             no_close_list[i++] = fileno (stderr);
163             no_close_list[i] = -1;
164             
165             /* Connect to the agent and perform initial handshaking. */
166             rc = assuan_pipe_connect (&ctx, opt.agent_program, argv,
167                                       no_close_list);
168           }
169 #endif /*!HAVE_W32_SYSTEM*/
170         }
171       xfree (sockname);
172     }
173   else
174     {
175       int prot;
176       int pid;
177
178       infostr = xstrdup (infostr);
179       if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
180         {
181           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
182           xfree (infostr);
183           force_pipe_server = 1;
184           return start_agent (ctrl);
185         }
186       *p++ = 0;
187       pid = atoi (p);
188       while (*p && *p != PATHSEP_C)
189         p++;
190       prot = *p? atoi (p+1) : 0;
191       if (prot != 1)
192         {
193           log_error (_("gpg-agent protocol version %d is not supported\n"),
194                      prot);
195           xfree (infostr);
196           force_pipe_server = 1;
197           return start_agent (ctrl);
198         }
199
200       rc = assuan_socket_connect (&ctx, infostr, pid);
201       xfree (infostr);
202       if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
203         {
204           log_info (_("can't connect to the agent - trying fall back\n"));
205           force_pipe_server = 1;
206           return start_agent (ctrl);
207         }
208     }
209
210   if (rc)
211     {
212       log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
213       return gpg_error (GPG_ERR_NO_AGENT);
214     }
215   agent_ctx = ctx;
216
217   if (DBG_ASSUAN)
218     log_debug ("connection to agent established\n");
219
220   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
221   if (rc)
222     return rc;
223
224   return send_pinentry_environment (agent_ctx, GPG_ERR_SOURCE_DEFAULT,
225                                     opt.display, opt.ttyname, opt.ttytype,
226                                     opt.lc_ctype, opt.lc_messages);
227 }
228
229
230 static int
231 membuf_data_cb (void *opaque, const void *buffer, size_t length)
232 {
233   membuf_t *data = opaque;
234
235   if (buffer)
236     put_membuf (data, buffer, length);
237   return 0;
238 }
239   
240
241
242 \f
243 /* Call the agent to do a sign operation using the key identified by
244    the hex string KEYGRIP. */
245 int
246 gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
247                     unsigned char *digest, size_t digestlen, int digestalgo,
248                     unsigned char **r_buf, size_t *r_buflen )
249 {
250   int rc, i;
251   char *p, line[ASSUAN_LINELENGTH];
252   membuf_t data;
253   size_t len;
254
255   *r_buf = NULL;
256   rc = start_agent (ctrl);
257   if (rc)
258     return rc;
259
260   if (digestlen*2 + 50 > DIM(line))
261     return gpg_error (GPG_ERR_GENERAL);
262
263   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
264   if (rc)
265     return rc;
266
267   snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
268   line[DIM(line)-1] = 0;
269   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
270   if (rc)
271     return rc;
272
273   if (desc)
274     {
275       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
276       line[DIM(line)-1] = 0;
277       rc = assuan_transact (agent_ctx, line,
278                             NULL, NULL, NULL, NULL, NULL, NULL);
279       if (rc)
280         return rc;
281     }
282
283   sprintf (line, "SETHASH %d ", digestalgo);
284   p = line + strlen (line);
285   for (i=0; i < digestlen ; i++, p += 2 )
286     sprintf (p, "%02X", digest[i]);
287   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
288   if (rc)
289     return rc;
290
291   init_membuf (&data, 1024);
292   rc = assuan_transact (agent_ctx, "PKSIGN",
293                         membuf_data_cb, &data, NULL, NULL, NULL, NULL);
294   if (rc)
295     {
296       xfree (get_membuf (&data, &len));
297       return rc;
298     }
299   *r_buf = get_membuf (&data, r_buflen);
300
301   if (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL))
302     {
303       xfree (*r_buf); *r_buf = NULL;
304       return gpg_error (GPG_ERR_INV_VALUE);
305     }
306
307   return *r_buf? 0 : out_of_core ();
308 }
309
310
311 /* Call the scdaemon to do a sign operation using the key identified by
312    the hex string KEYID. */
313 int
314 gpgsm_scd_pksign (ctrl_t ctrl, const char *keyid, const char *desc,
315                   unsigned char *digest, size_t digestlen, int digestalgo,
316                   unsigned char **r_buf, size_t *r_buflen )
317 {
318   int rc, i;
319   char *p, line[ASSUAN_LINELENGTH];
320   membuf_t data;
321   size_t len;
322   const char *hashopt;
323   unsigned char *sigbuf;
324   size_t sigbuflen;
325
326   *r_buf = NULL;
327
328   switch(digestalgo)
329     {
330     case GCRY_MD_SHA1:  hashopt = "--hash=sha1"; break;
331     case GCRY_MD_RMD160:hashopt = "--hash=rmd160"; break;
332     case GCRY_MD_MD5:   hashopt = "--hash=md5"; break;
333     case GCRY_MD_SHA256:hashopt = "--hash=sha256"; break;
334     default: 
335       return gpg_error (GPG_ERR_DIGEST_ALGO);
336     }
337
338   rc = start_agent (ctrl);
339   if (rc)
340     return rc;
341
342   if (digestlen*2 + 50 > DIM(line))
343     return gpg_error (GPG_ERR_GENERAL);
344
345   p = stpcpy (line, "SCD SETDATA " );
346   for (i=0; i < digestlen ; i++, p += 2 )
347     sprintf (p, "%02X", digest[i]);
348   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
349   if (rc)
350     return rc;
351
352   init_membuf (&data, 1024);
353
354   snprintf (line, DIM(line)-1, "SCD PKSIGN %s %s", hashopt, keyid);
355   line[DIM(line)-1] = 0;
356   rc = assuan_transact (agent_ctx, line,
357                         membuf_data_cb, &data, NULL, NULL, NULL, NULL);
358   if (rc)
359     {
360       xfree (get_membuf (&data, &len));
361       return rc;
362     }
363   sigbuf = get_membuf (&data, &sigbuflen);
364
365   /* Create an S-expression from it which is formatted like this:
366      "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" Fixme: If a card ever
367      creates non-RSA keys we need to change things. */
368   *r_buflen = 21 + 11 + sigbuflen + 4;
369   p = xtrymalloc (*r_buflen);
370   *r_buf = (unsigned char*)p;
371   if (!p)
372     {
373       xfree (sigbuf);
374       return 0;
375     }
376   p = stpcpy (p, "(7:sig-val(3:rsa(1:s" );
377   sprintf (p, "%u:", (unsigned int)sigbuflen);
378   p += strlen (p);
379   memcpy (p, sigbuf, sigbuflen);
380   p += sigbuflen;
381   strcpy (p, ")))");
382   xfree (sigbuf);
383
384   assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
385   return  0;
386 }
387
388
389
390 \f
391 /* Handle a CIPHERTEXT inquiry.  Note, we only send the data,
392    assuan_transact talkes care of flushing and writing the end */
393 static int
394 inq_ciphertext_cb (void *opaque, const char *keyword)
395 {
396   struct cipher_parm_s *parm = opaque; 
397   int rc;
398
399   assuan_begin_confidential (parm->ctx);
400   rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
401   assuan_end_confidential (parm->ctx);
402   return rc; 
403 }
404
405
406 /* Call the agent to do a decrypt operation using the key identified by
407    the hex string KEYGRIP. */
408 int
409 gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
410                        ksba_const_sexp_t ciphertext, 
411                        char **r_buf, size_t *r_buflen )
412 {
413   int rc;
414   char line[ASSUAN_LINELENGTH];
415   membuf_t data;
416   struct cipher_parm_s cipher_parm;
417   size_t n, len;
418   char *p, *buf, *endp;
419   size_t ciphertextlen;
420   
421   if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
422     return gpg_error (GPG_ERR_INV_VALUE);
423   *r_buf = NULL;
424
425   ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL);
426   if (!ciphertextlen)
427     return gpg_error (GPG_ERR_INV_VALUE);
428
429   rc = start_agent (ctrl);
430   if (rc)
431     return rc;
432
433   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
434   if (rc)
435     return rc;
436
437   assert ( DIM(line) >= 50 );
438   snprintf (line, DIM(line)-1, "SETKEY %s", keygrip);
439   line[DIM(line)-1] = 0;
440   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
441   if (rc)
442     return rc;
443
444   if (desc)
445     {
446       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
447       line[DIM(line)-1] = 0;
448       rc = assuan_transact (agent_ctx, line,
449                             NULL, NULL, NULL, NULL, NULL, NULL);
450       if (rc)
451         return rc;
452     }
453
454   init_membuf (&data, 1024);
455   cipher_parm.ctx = agent_ctx;
456   cipher_parm.ciphertext = ciphertext;
457   cipher_parm.ciphertextlen = ciphertextlen;
458   rc = assuan_transact (agent_ctx, "PKDECRYPT",
459                         membuf_data_cb, &data,
460                         inq_ciphertext_cb, &cipher_parm, NULL, NULL);
461   if (rc)
462     {
463       xfree (get_membuf (&data, &len));
464       return rc;
465     }
466
467   put_membuf (&data, "", 1); /* Make sure it is 0 terminated. */
468   buf = get_membuf (&data, &len);
469   if (!buf)
470     return gpg_error (GPG_ERR_ENOMEM);
471   assert (len); /* (we forced Nul termination.)  */
472
473   if (*buf == '(')
474     {
475       if (len < 13 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)\0" */
476         return gpg_error (GPG_ERR_INV_SEXP);
477       len -= 11;   /* Count only the data of the second part. */
478       p = buf + 8; /* Skip leading parenthesis and the value tag. */
479     }
480   else
481     {
482       /* For compatibility with older gpg-agents handle the old style
483          incomplete S-exps. */
484       len--;      /* Do not count the Nul. */
485       p = buf;
486     }
487
488   n = strtoul (p, &endp, 10);
489   if (!n || *endp != ':')
490     return gpg_error (GPG_ERR_INV_SEXP);
491   endp++;
492   if (endp-p+n > len)
493     return gpg_error (GPG_ERR_INV_SEXP); /* Oops: Inconsistent S-Exp. */
494   
495   memmove (buf, endp, n);
496
497   *r_buflen = n;
498   *r_buf = buf;
499   return 0;
500 }
501
502
503
504
505 \f
506 /* Handle a KEYPARMS inquiry.  Note, we only send the data,
507    assuan_transact takes care of flushing and writing the end */
508 static int
509 inq_genkey_parms (void *opaque, const char *keyword)
510 {
511   struct genkey_parm_s *parm = opaque; 
512   int rc;
513
514   rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
515   return rc; 
516 }
517
518
519 \f
520 /* Call the agent to generate a newkey */
521 int
522 gpgsm_agent_genkey (ctrl_t ctrl,
523                     ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
524 {
525   int rc;
526   struct genkey_parm_s gk_parm;
527   membuf_t data;
528   size_t len;
529   unsigned char *buf;
530
531   *r_pubkey = NULL;
532   rc = start_agent (ctrl);
533   if (rc)
534     return rc;
535
536   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
537   if (rc)
538     return rc;
539
540   init_membuf (&data, 1024);
541   gk_parm.ctx = agent_ctx;
542   gk_parm.sexp = keyparms;
543   gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
544   if (!gk_parm.sexplen)
545     return gpg_error (GPG_ERR_INV_VALUE);
546   rc = assuan_transact (agent_ctx, "GENKEY",
547                         membuf_data_cb, &data, 
548                         inq_genkey_parms, &gk_parm, NULL, NULL);
549   if (rc)
550     {
551       xfree (get_membuf (&data, &len));
552       return rc;
553     }
554   buf = get_membuf (&data, &len);
555   if (!buf)
556     return gpg_error (GPG_ERR_ENOMEM);
557   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
558     {
559       xfree (buf);
560       return gpg_error (GPG_ERR_INV_SEXP);
561     }
562   *r_pubkey = buf;
563   return 0;
564 }
565
566 \f
567 /* Call the agent to read the public key part for a given keygrip.  If
568    FROMCARD is true, the key is directly read from the current
569    smartcard. In this case HEXKEYGRIP should be the keyID
570    (e.g. OPENPGP.3). */
571 int
572 gpgsm_agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
573                      ksba_sexp_t *r_pubkey)
574 {
575   int rc;
576   membuf_t data;
577   size_t len;
578   unsigned char *buf;
579   char line[ASSUAN_LINELENGTH];
580
581   *r_pubkey = NULL;
582   rc = start_agent (ctrl);
583   if (rc)
584     return rc;
585
586   rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
587   if (rc)
588     return rc;
589
590   snprintf (line, DIM(line)-1, "%sREADKEY %s",
591             fromcard? "SCD ":"", hexkeygrip);
592   line[DIM(line)-1] = 0;
593
594   init_membuf (&data, 1024);
595   rc = assuan_transact (agent_ctx, line,
596                         membuf_data_cb, &data, 
597                         NULL, NULL, NULL, NULL);
598   if (rc)
599     {
600       xfree (get_membuf (&data, &len));
601       return rc;
602     }
603   buf = get_membuf (&data, &len);
604   if (!buf)
605     return gpg_error (GPG_ERR_ENOMEM);
606   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
607     {
608       xfree (buf);
609       return gpg_error (GPG_ERR_INV_SEXP);
610     }
611   *r_pubkey = buf;
612   return 0;
613 }
614
615 \f
616
617 static int
618 istrusted_status_cb (void *opaque, const char *line)
619 {
620   struct rootca_flags_s *flags = opaque;
621
622   if (!strncmp (line, "TRUSTLISTFLAG", 13) && (line[13]==' ' || !line[13]))
623     {
624       for (line += 13; *line == ' '; line++)
625         ;
626       if (!strncmp (line, "relax", 5) && (line[5] == ' ' || !line[5]))
627         flags->relax = 1;
628     }
629   return 0;
630 }
631
632
633
634 /* Ask the agent whether the certificate is in the list of trusted
635    keys.  ROOTCA_FLAGS is guaranteed to be cleared on error. */
636 int
637 gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert,
638                        struct rootca_flags_s *rootca_flags)
639 {
640   int rc;
641   char *fpr;
642   char line[ASSUAN_LINELENGTH];
643
644   memset (rootca_flags, 0, sizeof *rootca_flags);
645
646   rc = start_agent (ctrl);
647   if (rc)
648     return rc;
649
650   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
651   if (!fpr)
652     {
653       log_error ("error getting the fingerprint\n");
654       return gpg_error (GPG_ERR_GENERAL);
655     }
656
657   snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr);
658   line[DIM(line)-1] = 0;
659   xfree (fpr);
660
661   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
662                         istrusted_status_cb, rootca_flags);
663   return rc;
664 }
665
666 /* Ask the agent to mark CERT as a trusted Root-CA one */
667 int
668 gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
669 {
670   int rc;
671   char *fpr, *dn;
672   char line[ASSUAN_LINELENGTH];
673
674   rc = start_agent (ctrl);
675   if (rc)
676     return rc;
677
678   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
679   if (!fpr)
680     {
681       log_error ("error getting the fingerprint\n");
682       return gpg_error (GPG_ERR_GENERAL);
683     }
684
685   dn = ksba_cert_get_issuer (cert, 0);
686   if (!dn)
687     {
688       xfree (fpr);
689       return gpg_error (GPG_ERR_GENERAL);
690     }
691   snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn);
692   line[DIM(line)-1] = 0;
693   ksba_free (dn);
694   xfree (fpr);
695
696   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
697   return rc;
698 }
699
700
701 \f
702 /* Ask the agent whether the a corresponding secret key is available
703    for the given keygrip */
704 int
705 gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
706 {
707   int rc;
708   char line[ASSUAN_LINELENGTH];
709
710   rc = start_agent (ctrl);
711   if (rc)
712     return rc;
713
714   if (!hexkeygrip || strlen (hexkeygrip) != 40)
715     return gpg_error (GPG_ERR_INV_VALUE);
716
717   snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
718   line[DIM(line)-1] = 0;
719
720   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
721   return rc;
722 }
723
724 \f
725 static int
726 learn_cb (void *opaque, const void *buffer, size_t length)
727 {
728   struct learn_parm_s *parm = opaque;
729   size_t len;
730   char *buf;
731   ksba_cert_t cert;
732   int rc;
733
734   if (parm->error)
735     return 0;
736
737   if (buffer)
738     {
739       put_membuf (parm->data, buffer, length);
740       return 0;
741     }
742   /* END encountered - process what we have */
743   buf = get_membuf (parm->data, &len);
744   if (!buf)
745     {
746       parm->error = gpg_error (GPG_ERR_ENOMEM);
747       return 0;
748     }
749
750
751   /* FIXME: this should go into import.c */
752   rc = ksba_cert_new (&cert);
753   if (rc)
754     {
755       parm->error = rc;
756       return 0;
757     }
758   rc = ksba_cert_init_from_mem (cert, buf, len);
759   if (rc)
760     {
761       log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
762       ksba_cert_release (cert);
763       parm->error = rc;
764       return 0;
765     }
766
767   rc = gpgsm_basic_cert_check (cert);
768   if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT)
769     { /* For later use we store it in the ephemeral database. */
770       log_info ("issuer certificate missing - storing as ephemeral\n");
771       keydb_store_cert (cert, 1, NULL);
772     }
773   else if (rc)
774     log_error ("invalid certificate: %s\n", gpg_strerror (rc));
775   else
776     {
777       int existed;
778
779       if (!keydb_store_cert (cert, 0, &existed))
780         {
781           if (opt.verbose > 1 && existed)
782             log_info ("certificate already in DB\n");
783           else if (opt.verbose && !existed)
784             log_info ("certificate imported\n");
785         }
786     }
787
788   ksba_cert_release (cert);
789   init_membuf (parm->data, 4096);
790   return 0;
791 }
792   
793 /* Call the agent to learn about a smartcard */
794 int
795 gpgsm_agent_learn (ctrl_t ctrl)
796 {
797   int rc;
798   struct learn_parm_s learn_parm;
799   membuf_t data;
800   size_t len;
801
802   rc = start_agent (ctrl);
803   if (rc)
804     return rc;
805
806   init_membuf (&data, 4096);
807   learn_parm.error = 0;
808   learn_parm.ctx = agent_ctx;
809   learn_parm.data = &data;
810   rc = assuan_transact (agent_ctx, "LEARN --send",
811                         learn_cb, &learn_parm, 
812                         NULL, NULL, NULL, NULL);
813   xfree (get_membuf (&data, &len));
814   if (rc)
815     return rc;
816   return learn_parm.error;
817 }
818
819 \f
820 /* Ask the agent to change the passphrase of the key identified by
821    HEXKEYGRIP. If DESC is not NULL, display instead of the default
822    description message. */
823 int
824 gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
825 {
826   int rc;
827   char line[ASSUAN_LINELENGTH];
828
829   rc = start_agent (ctrl);
830   if (rc)
831     return rc;
832
833   if (!hexkeygrip || strlen (hexkeygrip) != 40)
834     return gpg_error (GPG_ERR_INV_VALUE);
835
836   if (desc)
837     {
838       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
839       line[DIM(line)-1] = 0;
840       rc = assuan_transact (agent_ctx, line,
841                             NULL, NULL, NULL, NULL, NULL, NULL);
842       if (rc)
843         return rc;
844     }
845
846   snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
847   line[DIM(line)-1] = 0;
848
849   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
850   return rc;
851 }
852
853
854 \f
855 /* Ask the agent to pop up a confirmation dialog with the text DESC
856    and an okay and cancel button.  */
857 gpg_error_t
858 gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc)
859 {
860   int rc;
861   char line[ASSUAN_LINELENGTH];
862
863   rc = start_agent (ctrl);
864   if (rc)
865     return rc;
866
867   snprintf (line, DIM(line)-1, "GET_CONFIRMATION %s", desc);
868   line[DIM(line)-1] = 0;
869
870   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
871   return rc;
872 }