agent/
[gnupg.git] / sm / call-agent.c
1 /* call-agent.c - Divert GPGSM operations to the agent
2  * Copyright (C) 2001, 2002, 2003, 2005, 2007,
3  *               2008, 2009 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
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 "membuf.h"
40
41
42 static assuan_context_t agent_ctx = NULL;
43
44
45 struct cipher_parm_s
46 {
47   ctrl_t ctrl;
48   assuan_context_t ctx;
49   const unsigned char *ciphertext;
50   size_t ciphertextlen;
51 };
52
53 struct genkey_parm_s
54 {
55   ctrl_t ctrl;
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   ctrl_t ctrl;
65   assuan_context_t ctx;
66   membuf_t *data;
67 };
68
69
70 \f
71 /* Try to connect to the agent via socket or fork it off and work by
72    pipes.  Handle the server's initial greeting */
73 static int
74 start_agent (ctrl_t ctrl)
75 {
76   int rc;
77
78   if (agent_ctx)
79     rc = 0;      /* fixme: We need a context for each thread or
80                     serialize the access to the agent (which is
81                     suitable given that the agent is not MT. */
82   else
83     {
84       rc = start_new_gpg_agent (&agent_ctx,
85                                 GPG_ERR_SOURCE_DEFAULT,
86                                 opt.homedir,
87                                 opt.agent_program,
88                                 opt.lc_ctype, opt.lc_messages,
89                                 opt.session_env,
90                                 opt.verbose, DBG_ASSUAN,
91                                 gpgsm_status2, ctrl);
92       
93       if (!rc)
94         {
95           /* Tell the agent that we support Pinentry notifications.  No
96              error checking so that it will work also with older
97              agents.  */
98           assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
99                            NULL, NULL, NULL, NULL, NULL, NULL);
100         }
101     }
102
103   if (!ctrl->agent_seen)
104     {
105       ctrl->agent_seen = 1;
106       audit_log_ok (ctrl->audit, AUDIT_AGENT_READY, rc);
107     }
108
109   return rc;
110 }
111
112
113
114 static gpg_error_t
115 membuf_data_cb (void *opaque, const void *buffer, size_t length)
116 {
117   membuf_t *data = opaque;
118
119   if (buffer)
120     put_membuf (data, buffer, length);
121   return 0;
122 }
123   
124
125 /* This is the default inquiry callback.  It mainly handles the
126    Pinentry notifications.  */
127 static gpg_error_t
128 default_inq_cb (void *opaque, const char *line)
129 {
130   gpg_error_t err;
131   ctrl_t ctrl = opaque;
132
133   if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
134     {
135       err = gpgsm_proxy_pinentry_notify (ctrl, line);
136       if (err)
137         log_error (_("failed to proxy %s inquiry to client\n"), 
138                    "PINENTRY_LAUNCHED");
139       /* We do not pass errors to avoid breaking other code.  */
140     }
141   else
142     log_error ("ignoring gpg-agent inquiry `%s'\n", line);
143
144   return 0;
145 }
146
147
148
149 \f
150 /* Call the agent to do a sign operation using the key identified by
151    the hex string KEYGRIP. */
152 int
153 gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
154                     unsigned char *digest, size_t digestlen, int digestalgo,
155                     unsigned char **r_buf, size_t *r_buflen )
156 {
157   int rc, i;
158   char *p, line[ASSUAN_LINELENGTH];
159   membuf_t data;
160   size_t len;
161
162   *r_buf = NULL;
163   rc = start_agent (ctrl);
164   if (rc)
165     return rc;
166
167   if (digestlen*2 + 50 > DIM(line))
168     return gpg_error (GPG_ERR_GENERAL);
169
170   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
171   if (rc)
172     return rc;
173
174   snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
175   line[DIM(line)-1] = 0;
176   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
177   if (rc)
178     return rc;
179
180   if (desc)
181     {
182       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
183       line[DIM(line)-1] = 0;
184       rc = assuan_transact (agent_ctx, line,
185                             NULL, NULL, NULL, NULL, NULL, NULL);
186       if (rc)
187         return rc;
188     }
189
190   sprintf (line, "SETHASH %d ", digestalgo);
191   p = line + strlen (line);
192   for (i=0; i < digestlen ; i++, p += 2 )
193     sprintf (p, "%02X", digest[i]);
194   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
195   if (rc)
196     return rc;
197
198   init_membuf (&data, 1024);
199   rc = assuan_transact (agent_ctx, "PKSIGN",
200                         membuf_data_cb, &data, default_inq_cb, ctrl,
201                         NULL, NULL);
202   if (rc)
203     {
204       xfree (get_membuf (&data, &len));
205       return rc;
206     }
207   *r_buf = get_membuf (&data, r_buflen);
208
209   if (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL))
210     {
211       xfree (*r_buf); *r_buf = NULL;
212       return gpg_error (GPG_ERR_INV_VALUE);
213     }
214
215   return *r_buf? 0 : out_of_core ();
216 }
217
218
219 /* Call the scdaemon to do a sign operation using the key identified by
220    the hex string KEYID. */
221 int
222 gpgsm_scd_pksign (ctrl_t ctrl, const char *keyid, const char *desc,
223                   unsigned char *digest, size_t digestlen, int digestalgo,
224                   unsigned char **r_buf, size_t *r_buflen )
225 {
226   int rc, i;
227   char *p, line[ASSUAN_LINELENGTH];
228   membuf_t data;
229   size_t len;
230   const char *hashopt;
231   unsigned char *sigbuf;
232   size_t sigbuflen;
233
234   (void)desc;
235
236   *r_buf = NULL;
237
238   switch(digestalgo)
239     {
240     case GCRY_MD_SHA1:  hashopt = "--hash=sha1"; break;
241     case GCRY_MD_RMD160:hashopt = "--hash=rmd160"; break;
242     case GCRY_MD_MD5:   hashopt = "--hash=md5"; break;
243     case GCRY_MD_SHA256:hashopt = "--hash=sha256"; break;
244     default: 
245       return gpg_error (GPG_ERR_DIGEST_ALGO);
246     }
247
248   rc = start_agent (ctrl);
249   if (rc)
250     return rc;
251
252   if (digestlen*2 + 50 > DIM(line))
253     return gpg_error (GPG_ERR_GENERAL);
254
255   p = stpcpy (line, "SCD SETDATA " );
256   for (i=0; i < digestlen ; i++, p += 2 )
257     sprintf (p, "%02X", digest[i]);
258   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
259   if (rc)
260     return rc;
261
262   init_membuf (&data, 1024);
263
264   snprintf (line, DIM(line)-1, "SCD PKSIGN %s %s", hashopt, keyid);
265   line[DIM(line)-1] = 0;
266   rc = assuan_transact (agent_ctx, line,
267                         membuf_data_cb, &data, default_inq_cb, ctrl,
268                         NULL, NULL);
269   if (rc)
270     {
271       xfree (get_membuf (&data, &len));
272       return rc;
273     }
274   sigbuf = get_membuf (&data, &sigbuflen);
275
276   /* Create an S-expression from it which is formatted like this:
277      "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" Fixme: If a card ever
278      creates non-RSA keys we need to change things. */
279   *r_buflen = 21 + 11 + sigbuflen + 4;
280   p = xtrymalloc (*r_buflen);
281   *r_buf = (unsigned char*)p;
282   if (!p)
283     {
284       xfree (sigbuf);
285       return 0;
286     }
287   p = stpcpy (p, "(7:sig-val(3:rsa(1:s" );
288   sprintf (p, "%u:", (unsigned int)sigbuflen);
289   p += strlen (p);
290   memcpy (p, sigbuf, sigbuflen);
291   p += sigbuflen;
292   strcpy (p, ")))");
293   xfree (sigbuf);
294
295   assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
296   return  0;
297 }
298
299
300
301 \f
302 /* Handle a CIPHERTEXT inquiry.  Note, we only send the data,
303    assuan_transact talkes care of flushing and writing the end */
304 static gpg_error_t
305 inq_ciphertext_cb (void *opaque, const char *line)
306 {
307   struct cipher_parm_s *parm = opaque; 
308   int rc;
309
310   if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10]))
311     {
312       assuan_begin_confidential (parm->ctx);
313       rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
314       assuan_end_confidential (parm->ctx);
315     }
316   else
317     rc = default_inq_cb (parm->ctrl, line);
318
319   return rc; 
320 }
321
322
323 /* Call the agent to do a decrypt operation using the key identified by
324    the hex string KEYGRIP. */
325 int
326 gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
327                        ksba_const_sexp_t ciphertext, 
328                        char **r_buf, size_t *r_buflen )
329 {
330   int rc;
331   char line[ASSUAN_LINELENGTH];
332    membuf_t data;
333   struct cipher_parm_s cipher_parm;
334   size_t n, len;
335   char *p, *buf, *endp;
336   size_t ciphertextlen;
337   
338   if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
339     return gpg_error (GPG_ERR_INV_VALUE);
340   *r_buf = NULL;
341
342   ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL);
343   if (!ciphertextlen)
344     return gpg_error (GPG_ERR_INV_VALUE);
345
346   rc = start_agent (ctrl);
347   if (rc)
348     return rc;
349
350   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
351   if (rc)
352     return rc;
353
354   assert ( DIM(line) >= 50 );
355   snprintf (line, DIM(line)-1, "SETKEY %s", keygrip);
356   line[DIM(line)-1] = 0;
357   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
358   if (rc)
359     return rc;
360
361   if (desc)
362     {
363       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
364       line[DIM(line)-1] = 0;
365       rc = assuan_transact (agent_ctx, line,
366                             NULL, NULL, NULL, NULL, NULL, NULL);
367       if (rc)
368         return rc;
369     }
370
371   init_membuf (&data, 1024);
372   cipher_parm.ctrl = ctrl;
373   cipher_parm.ctx = agent_ctx;
374   cipher_parm.ciphertext = ciphertext;
375   cipher_parm.ciphertextlen = ciphertextlen;
376   rc = assuan_transact (agent_ctx, "PKDECRYPT",
377                         membuf_data_cb, &data,
378                         inq_ciphertext_cb, &cipher_parm, NULL, NULL);
379   if (rc)
380     {
381       xfree (get_membuf (&data, &len));
382       return rc;
383     }
384
385   put_membuf (&data, "", 1); /* Make sure it is 0 terminated. */
386   buf = get_membuf (&data, &len);
387   if (!buf)
388     return gpg_error (GPG_ERR_ENOMEM);
389   assert (len); /* (we forced Nul termination.)  */
390
391   if (*buf == '(')
392     {
393       if (len < 13 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)\0" */
394         return gpg_error (GPG_ERR_INV_SEXP);
395       len -= 11;   /* Count only the data of the second part. */
396       p = buf + 8; /* Skip leading parenthesis and the value tag. */
397     }
398   else
399     {
400       /* For compatibility with older gpg-agents handle the old style
401          incomplete S-exps. */
402       len--;      /* Do not count the Nul. */
403       p = buf;
404     }
405
406   n = strtoul (p, &endp, 10);
407   if (!n || *endp != ':')
408     return gpg_error (GPG_ERR_INV_SEXP);
409   endp++;
410   if (endp-p+n > len)
411     return gpg_error (GPG_ERR_INV_SEXP); /* Oops: Inconsistent S-Exp. */
412   
413   memmove (buf, endp, n);
414
415   *r_buflen = n;
416   *r_buf = buf;
417   return 0;
418 }
419
420
421
422
423 \f
424 /* Handle a KEYPARMS inquiry.  Note, we only send the data,
425    assuan_transact takes care of flushing and writing the end */
426 static gpg_error_t
427 inq_genkey_parms (void *opaque, const char *line)
428 {
429   struct genkey_parm_s *parm = opaque; 
430   int rc;
431
432   if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8]))
433     {
434       rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
435     }
436   else
437     rc = default_inq_cb (parm->ctrl, line);
438
439   return rc; 
440 }
441
442
443 \f
444 /* Call the agent to generate a newkey */
445 int
446 gpgsm_agent_genkey (ctrl_t ctrl,
447                     ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
448 {
449   int rc;
450   struct genkey_parm_s gk_parm;
451   membuf_t data;
452   size_t len;
453   unsigned char *buf;
454
455   *r_pubkey = NULL;
456   rc = start_agent (ctrl);
457   if (rc)
458     return rc;
459
460   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
461   if (rc)
462     return rc;
463
464   init_membuf (&data, 1024);
465   gk_parm.ctrl = ctrl;
466   gk_parm.ctx = agent_ctx;
467   gk_parm.sexp = keyparms;
468   gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
469   if (!gk_parm.sexplen)
470     return gpg_error (GPG_ERR_INV_VALUE);
471   rc = assuan_transact (agent_ctx, "GENKEY",
472                         membuf_data_cb, &data, 
473                         inq_genkey_parms, &gk_parm, NULL, NULL);
474   if (rc)
475     {
476       xfree (get_membuf (&data, &len));
477       return rc;
478     }
479   buf = get_membuf (&data, &len);
480   if (!buf)
481     return gpg_error (GPG_ERR_ENOMEM);
482   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
483     {
484       xfree (buf);
485       return gpg_error (GPG_ERR_INV_SEXP);
486     }
487   *r_pubkey = buf;
488   return 0;
489 }
490
491 \f
492 /* Call the agent to read the public key part for a given keygrip.  If
493    FROMCARD is true, the key is directly read from the current
494    smartcard. In this case HEXKEYGRIP should be the keyID
495    (e.g. OPENPGP.3). */
496 int
497 gpgsm_agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
498                      ksba_sexp_t *r_pubkey)
499 {
500   int rc;
501   membuf_t data;
502   size_t len;
503   unsigned char *buf;
504   char line[ASSUAN_LINELENGTH];
505
506   *r_pubkey = NULL;
507   rc = start_agent (ctrl);
508   if (rc)
509     return rc;
510
511   rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
512   if (rc)
513     return rc;
514
515   snprintf (line, DIM(line)-1, "%sREADKEY %s",
516             fromcard? "SCD ":"", hexkeygrip);
517   line[DIM(line)-1] = 0;
518
519   init_membuf (&data, 1024);
520   rc = assuan_transact (agent_ctx, line,
521                         membuf_data_cb, &data, 
522                         default_inq_cb, ctrl, NULL, NULL);
523   if (rc)
524     {
525       xfree (get_membuf (&data, &len));
526       return rc;
527     }
528   buf = get_membuf (&data, &len);
529   if (!buf)
530     return gpg_error (GPG_ERR_ENOMEM);
531   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
532     {
533       xfree (buf);
534       return gpg_error (GPG_ERR_INV_SEXP);
535     }
536   *r_pubkey = buf;
537   return 0;
538 }
539
540
541 \f
542 /* Take the serial number from LINE and return it verbatim in a newly
543    allocated string.  We make sure that only hex characters are
544    returned. */
545 static char *
546 store_serialno (const char *line)
547 {
548   const char *s;
549   char *p;
550
551   for (s=line; hexdigitp (s); s++)
552     ;
553   p = xtrymalloc (s + 1 - line);
554   if (p)
555     {
556       memcpy (p, line, s-line);
557       p[s-line] = 0;
558     }
559   return p;
560 }
561
562
563 /* Callback for the gpgsm_agent_serialno fucntion.  */
564 static gpg_error_t
565 scd_serialno_status_cb (void *opaque, const char *line)
566 {
567   char **r_serialno = opaque;
568   const char *keyword = line;
569   int keywordlen;
570
571   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
572     ;
573   while (spacep (line))
574     line++;
575
576   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
577     {
578       xfree (*r_serialno);
579       *r_serialno = store_serialno (line);
580     }
581
582   return 0;
583 }
584
585
586 /* Call the agent to read the serial number of the current card.  */
587 int
588 gpgsm_agent_scd_serialno (ctrl_t ctrl, char **r_serialno)
589 {
590   int rc;
591   char *serialno = NULL;
592  
593   *r_serialno = NULL;
594   rc = start_agent (ctrl);
595   if (rc)
596     return rc;
597
598   rc = assuan_transact (agent_ctx, "SCD SERIALNO",
599                         NULL, NULL,
600                         default_inq_cb, ctrl,
601                         scd_serialno_status_cb, &serialno);
602   if (!rc && !serialno)
603     rc = gpg_error (GPG_ERR_INTERNAL);
604   if (rc)
605     {
606       xfree (serialno);
607       return rc;
608     }
609   *r_serialno = serialno;
610   return 0;
611 }
612
613
614 \f
615 /* Callback for the gpgsm_agent_serialno fucntion.  */
616 static gpg_error_t
617 scd_keypairinfo_status_cb (void *opaque, const char *line)
618 {
619   strlist_t *listaddr = opaque;
620   const char *keyword = line;
621   int keywordlen;
622   strlist_t sl;
623   char *p;
624
625   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
626     ;
627   while (spacep (line))
628     line++;
629
630   if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
631     {
632       sl = append_to_strlist (listaddr, line);
633       p = sl->d;
634       /* Make sure that we only have two tokes so that future
635          extensions of the format won't change the format expected by
636          the caller.  */
637       while (*p && !spacep (p))
638         p++;
639       if (*p)
640         {
641           while (spacep (p))
642             p++;
643           while (*p && !spacep (p))
644             p++;
645           *p = 0;
646         }
647     }
648
649   return 0;
650 }
651
652
653 /* Call the agent to read the keypairinfo lines of the current card.
654    The list is returned as a string made up of the keygrip, a space
655    and the keyid.  */
656 int
657 gpgsm_agent_scd_keypairinfo (ctrl_t ctrl, strlist_t *r_list)
658 {
659   int rc;
660   strlist_t list = NULL;
661  
662   *r_list = NULL;
663   rc = start_agent (ctrl);
664   if (rc)
665     return rc;
666
667   rc = assuan_transact (agent_ctx, "SCD LEARN --force",
668                         NULL, NULL,
669                         default_inq_cb, ctrl,
670                         scd_keypairinfo_status_cb, &list);
671   if (!rc && !list)
672     rc = gpg_error (GPG_ERR_NO_DATA);
673   if (rc)
674     {
675       free_strlist (list);
676       return rc;
677     }
678   *r_list = list;
679   return 0;
680 }
681
682
683 \f
684 static gpg_error_t
685 istrusted_status_cb (void *opaque, const char *line)
686 {
687   struct rootca_flags_s *flags = opaque;
688
689   if (!strncmp (line, "TRUSTLISTFLAG", 13) && (line[13]==' ' || !line[13]))
690     {
691       for (line += 13; *line == ' '; line++)
692         ;
693       if (!strncmp (line, "relax", 5) && (line[5] == ' ' || !line[5]))
694         flags->relax = 1;
695       else if (!strncmp (line, "cm", 2) && (line[2] == ' ' || !line[2]))
696         flags->chain_model = 1;
697     }
698   return 0;
699 }
700
701
702
703 /* Ask the agent whether the certificate is in the list of trusted
704    keys.  The certificate is either specified by the CERT object or by
705    the fingerprint HEXFPR.  ROOTCA_FLAGS is guaranteed to be cleared
706    on error. */
707 int
708 gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert, const char *hexfpr,
709                        struct rootca_flags_s *rootca_flags)
710 {
711   int rc;
712   char line[ASSUAN_LINELENGTH];
713
714   memset (rootca_flags, 0, sizeof *rootca_flags);
715
716   if (cert && hexfpr)
717     return gpg_error (GPG_ERR_INV_ARG);
718
719   rc = start_agent (ctrl);
720   if (rc)
721     return rc;
722
723   if (hexfpr)
724     {
725       snprintf (line, DIM(line)-1, "ISTRUSTED %s", hexfpr);
726       line[DIM(line)-1] = 0;
727     }
728   else
729     {
730       char *fpr;
731
732       fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
733       if (!fpr)
734         {
735           log_error ("error getting the fingerprint\n");
736           return gpg_error (GPG_ERR_GENERAL);
737         }
738       
739       snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr);
740       line[DIM(line)-1] = 0;
741       xfree (fpr);
742     }
743
744   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
745                         istrusted_status_cb, rootca_flags);
746   if (!rc)
747     rootca_flags->valid = 1;
748   return rc;
749 }
750
751 /* Ask the agent to mark CERT as a trusted Root-CA one */
752 int
753 gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
754 {
755   int rc;
756   char *fpr, *dn, *dnfmt;
757   char line[ASSUAN_LINELENGTH];
758
759   rc = start_agent (ctrl);
760   if (rc)
761     return rc;
762
763   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
764   if (!fpr)
765     {
766       log_error ("error getting the fingerprint\n");
767       return gpg_error (GPG_ERR_GENERAL);
768     }
769
770   dn = ksba_cert_get_issuer (cert, 0);
771   if (!dn)
772     {
773       xfree (fpr);
774       return gpg_error (GPG_ERR_GENERAL);
775     }
776   dnfmt = gpgsm_format_name2 (dn, 0);
777   xfree (dn);
778   if (!dnfmt)
779     return gpg_error_from_syserror ();
780   snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dnfmt);
781   line[DIM(line)-1] = 0;
782   ksba_free (dnfmt);
783   xfree (fpr);
784
785   rc = assuan_transact (agent_ctx, line, NULL, NULL,
786                         default_inq_cb, ctrl, NULL, NULL);
787   return rc;
788 }
789
790
791 \f
792 /* Ask the agent whether the a corresponding secret key is available
793    for the given keygrip */
794 int
795 gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
796 {
797   int rc;
798   char line[ASSUAN_LINELENGTH];
799
800   rc = start_agent (ctrl);
801   if (rc)
802     return rc;
803
804   if (!hexkeygrip || strlen (hexkeygrip) != 40)
805     return gpg_error (GPG_ERR_INV_VALUE);
806
807   snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
808   line[DIM(line)-1] = 0;
809
810   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
811   return rc;
812 }
813
814 \f
815 static gpg_error_t
816 learn_status_cb (void *opaque, const char *line)
817 {
818   struct learn_parm_s *parm = opaque;
819
820   /* Pass progress data to the caller.  */
821   if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
822     {
823       if (parm->ctrl)
824         {
825           for (line += 8; *line == ' '; line++)
826             ;
827           if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
828             return gpg_error (GPG_ERR_ASS_CANCELED);
829         }
830     }
831   return 0;
832 }
833
834 static gpg_error_t
835 learn_cb (void *opaque, const void *buffer, size_t length)
836 {
837   struct learn_parm_s *parm = opaque;
838   size_t len;
839   char *buf;
840   ksba_cert_t cert;
841   int rc;
842
843   if (parm->error)
844     return 0;
845
846   if (buffer)
847     {
848       put_membuf (parm->data, buffer, length);
849       return 0;
850     }
851   /* END encountered - process what we have */
852   buf = get_membuf (parm->data, &len);
853   if (!buf)
854     {
855       parm->error = gpg_error (GPG_ERR_ENOMEM);
856       return 0;
857     }
858
859   if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, "learncard C 0 0"))
860     return gpg_error (GPG_ERR_ASS_CANCELED);
861
862   /* FIXME: this should go into import.c */
863   rc = ksba_cert_new (&cert);
864   if (rc)
865     {
866       parm->error = rc;
867       return 0;
868     }
869   rc = ksba_cert_init_from_mem (cert, buf, len);
870   if (rc)
871     {
872       log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
873       ksba_cert_release (cert);
874       parm->error = rc;
875       return 0;
876     }
877
878   /* We do not store a certifciate with missing issuers as ephemeral
879      because we can assume that the --learn-card command has been used
880      on purpose.  */
881   rc = gpgsm_basic_cert_check (parm->ctrl, cert);
882   if (rc && gpg_err_code (rc) != GPG_ERR_MISSING_CERT)
883     log_error ("invalid certificate: %s\n", gpg_strerror (rc));
884   else
885     {
886       int existed;
887
888       if (!keydb_store_cert (cert, 0, &existed))
889         {
890           if (opt.verbose > 1 && existed)
891             log_info ("certificate already in DB\n");
892           else if (opt.verbose && !existed)
893             log_info ("certificate imported\n");
894         }
895     }
896
897   ksba_cert_release (cert);
898   init_membuf (parm->data, 4096);
899   return 0;
900 }
901   
902 /* Call the agent to learn about a smartcard */
903 int
904 gpgsm_agent_learn (ctrl_t ctrl)
905 {
906   int rc;
907   struct learn_parm_s learn_parm;
908   membuf_t data;
909   size_t len;
910
911   rc = start_agent (ctrl);
912   if (rc)
913     return rc;
914
915   init_membuf (&data, 4096);
916   learn_parm.error = 0;
917   learn_parm.ctrl = ctrl;
918   learn_parm.ctx = agent_ctx;
919   learn_parm.data = &data;
920   rc = assuan_transact (agent_ctx, "LEARN --send",
921                         learn_cb, &learn_parm, 
922                         NULL, NULL, 
923                         learn_status_cb, &learn_parm);
924   xfree (get_membuf (&data, &len));
925   if (rc)
926     return rc;
927   return learn_parm.error;
928 }
929
930 \f
931 /* Ask the agent to change the passphrase of the key identified by
932    HEXKEYGRIP. If DESC is not NULL, display instead of the default
933    description message. */
934 int
935 gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
936 {
937   int rc;
938   char line[ASSUAN_LINELENGTH];
939
940   rc = start_agent (ctrl);
941   if (rc)
942     return rc;
943
944   if (!hexkeygrip || strlen (hexkeygrip) != 40)
945     return gpg_error (GPG_ERR_INV_VALUE);
946
947   if (desc)
948     {
949       snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
950       line[DIM(line)-1] = 0;
951       rc = assuan_transact (agent_ctx, line,
952                             NULL, NULL, NULL, NULL, NULL, NULL);
953       if (rc)
954         return rc;
955     }
956
957   snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
958   line[DIM(line)-1] = 0;
959
960   rc = assuan_transact (agent_ctx, line, NULL, NULL,
961                         default_inq_cb, ctrl, NULL, NULL);
962   return rc;
963 }
964
965
966 \f
967 /* Ask the agent to pop up a confirmation dialog with the text DESC
968    and an okay and cancel button.  */
969 gpg_error_t
970 gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc)
971 {
972   int rc;
973   char line[ASSUAN_LINELENGTH];
974
975   rc = start_agent (ctrl);
976   if (rc)
977     return rc;
978
979   snprintf (line, DIM(line)-1, "GET_CONFIRMATION %s", desc);
980   line[DIM(line)-1] = 0;
981
982   rc = assuan_transact (agent_ctx, line, NULL, NULL,
983                         default_inq_cb, ctrl, NULL, NULL);
984   return rc;
985 }
986
987
988 \f
989 /* Return 0 if the agent is alive.  This is useful to make sure that
990    an agent has been started. */
991 gpg_error_t
992 gpgsm_agent_send_nop (ctrl_t ctrl)
993 {
994   int rc;
995
996   rc = start_agent (ctrl);
997   if (!rc)
998     rc = assuan_transact (agent_ctx, "NOP",
999                           NULL, NULL, NULL, NULL, NULL, NULL);
1000   return rc;
1001 }
1002
1003
1004 \f
1005 static gpg_error_t
1006 keyinfo_status_cb (void *opaque, const char *line)
1007 {
1008   char **serialno = opaque;
1009   const char *s, *s2;
1010
1011   if (!strncmp (line, "KEYINFO ", 8) && !*serialno)
1012     {
1013       s = strchr (line+8, ' ');
1014       if (s && s[1] == 'T' && s[2] == ' ' && s[3])
1015         {
1016           s += 3;
1017           s2 = strchr (s, ' ');
1018           if ( s2 > s )
1019             {
1020               *serialno = xtrymalloc ((s2 - s)+1);
1021               if (*serialno)
1022                 {
1023                   memcpy (*serialno, s, s2 - s);
1024                   (*serialno)[s2 - s] = 0;
1025                 }
1026             }
1027         }
1028     }
1029   return 0;
1030 }
1031
1032 /* Return the serial number for a secret key.  If the returned serial
1033    number is NULL, the key is not stored on a smartcard.  Caller needs
1034    to free R_SERIALNO.  */
1035 gpg_error_t
1036 gpgsm_agent_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
1037 {
1038   gpg_error_t err;
1039   char line[ASSUAN_LINELENGTH];
1040   char *serialno = NULL;
1041
1042   *r_serialno = NULL;
1043
1044   err = start_agent (ctrl);
1045   if (err)
1046     return err;
1047
1048   if (!hexkeygrip || strlen (hexkeygrip) != 40)
1049     return gpg_error (GPG_ERR_INV_VALUE);
1050
1051   snprintf (line, DIM(line)-1, "KEYINFO %s", hexkeygrip);
1052   line[DIM(line)-1] = 0;
1053
1054   err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
1055                          keyinfo_status_cb, &serialno);
1056   if (!err && serialno)
1057     {
1058       /* Sanity check for bad characters.  */
1059       if (strpbrk (serialno, ":\n\r"))
1060         err = GPG_ERR_INV_VALUE;
1061     }
1062   if (err)
1063     xfree (serialno);
1064   else
1065     *r_serialno = serialno;
1066   return err;
1067 }
1068