Add readcert command.
[gnupg.git] / g10 / call-agent.c
1 /* call-agent.c - Divert GPG operations to the agent.
2  * Copyright (C) 2001, 2002, 2003, 2006, 2007, 
3  *               2008 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 #include <assuan.h>
33
34 #include "gpg.h"
35 #include "util.h"
36 #include "membuf.h"
37 #include "options.h"
38 #include "i18n.h"
39 #include "asshelp.h"
40 #include "sysutils.h"
41 #include "call-agent.h"
42
43 #ifndef DBG_ASSUAN
44 # define DBG_ASSUAN 1
45 #endif
46
47 static assuan_context_t agent_ctx = NULL;
48
49 struct cipher_parm_s 
50 {
51   assuan_context_t ctx;
52   const char *ciphertext;
53   size_t ciphertextlen;
54 };
55
56 struct writecert_parm_s
57 {
58   assuan_context_t ctx;
59   const unsigned char *certdata;
60   size_t certdatalen;
61 };
62
63 struct writekey_parm_s
64 {
65   assuan_context_t ctx;
66   const unsigned char *keydata;
67   size_t keydatalen;
68 };
69
70 struct genkey_parm_s 
71 {
72   assuan_context_t ctx;
73   const char *sexp;
74   size_t sexplen;
75 };
76
77
78 \f
79 /* Try to connect to the agent via socket or fork it off and work by
80    pipes.  Handle the server's initial greeting */
81 static int
82 start_agent (void)
83 {
84   int rc;
85
86   if (agent_ctx)
87     return 0; /* Fixme: We need a context for each thread or serialize
88                  the access to the agent. */
89
90   rc = start_new_gpg_agent (&agent_ctx,
91                             GPG_ERR_SOURCE_DEFAULT,
92                             opt.homedir,
93                             opt.agent_program,
94                             opt.display, opt.ttyname, opt.ttytype,
95                             opt.lc_ctype, opt.lc_messages,
96                             opt.xauthority, opt.pinentry_user_data,
97                             opt.verbose, DBG_ASSUAN,
98                             NULL, NULL);
99   if (!rc)
100     {
101       /* Tell the agent that we support Pinentry notifications.  No
102          error checking so that it will work also with older
103          agents.  */
104       assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
105                        NULL, NULL, NULL, NULL, NULL, NULL);
106     }
107
108   return rc;
109 }
110
111
112 /* Return a new malloced string by unescaping the string S.  Escaping
113    is percent escaping and '+'/space mapping.  A binary nul will
114    silently be replaced by a 0xFF.  Function returns NULL to indicate
115    an out of memory status. */
116 static char *
117 unescape_status_string (const unsigned char *s)
118 {
119   return percent_plus_unescape (s, 0xff);
120 }
121
122
123 /* Take a 20 byte hexencoded string and put it into the the provided
124    20 byte buffer FPR in binary format. */
125 static int
126 unhexify_fpr (const char *hexstr, unsigned char *fpr)
127 {
128   const char *s;
129   int n;
130
131   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
132     ;
133   if (*s || (n != 40))
134     return 0; /* no fingerprint (invalid or wrong length). */
135   n /= 2;
136   for (s=hexstr, n=0; *s; s += 2, n++)
137     fpr[n] = xtoi_2 (s);
138   return 1; /* okay */
139 }
140
141 /* Take the serial number from LINE and return it verbatim in a newly
142    allocated string.  We make sure that only hex characters are
143    returned. */
144 static char *
145 store_serialno (const char *line)
146 {
147   const char *s;
148   char *p;
149
150   for (s=line; hexdigitp (s); s++)
151     ;
152   p = xtrymalloc (s + 1 - line);
153   if (p)
154     {
155       memcpy (p, line, s-line);
156       p[s-line] = 0;
157     }
158   return p;
159 }
160
161
162 \f
163 /* This is a dummy data line callback.  */
164 static int
165 dummy_data_cb (void *opaque, const void *buffer, size_t length)
166 {
167   (void)opaque;
168   (void)buffer;
169   (void)length;
170   return 0;
171 }
172
173
174 /* This is the default inquiry callback.  It mainly handles the
175    Pinentry notifications.  */
176 static int
177 default_inq_cb (void *opaque, const char *line)
178 {
179   (void)opaque;
180
181   if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
182     {
183       /* There is no working server mode yet thus we use
184          AllowSetForegroundWindow window right here.  We might want to
185          do this anyway in case gpg is called on the console. */
186       gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
187       /* We do not pass errors to avoid breaking other code.  */
188     }
189   else
190     log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
191
192   return 0;
193 }
194
195
196
197 /* Release the card info structure INFO. */
198 void
199 agent_release_card_info (struct agent_card_info_s *info)
200 {
201   if (!info)
202     return;
203
204   xfree (info->serialno); info->serialno = NULL;
205   xfree (info->apptype); info->apptype = NULL;
206   xfree (info->disp_name); info->disp_name = NULL;
207   xfree (info->disp_lang); info->disp_lang = NULL;
208   xfree (info->pubkey_url); info->pubkey_url = NULL;
209   xfree (info->login_data); info->login_data = NULL;
210   info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
211   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
212 }
213
214 static int
215 learn_status_cb (void *opaque, const char *line)
216 {
217   struct agent_card_info_s *parm = opaque;
218   const char *keyword = line;
219   int keywordlen;
220   int i;
221
222   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
223     ;
224   while (spacep (line))
225     line++;
226
227   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
228     {
229       xfree (parm->serialno);
230       parm->serialno = store_serialno (line);
231       parm->is_v2 = (strlen (parm->serialno) >= 16 
232                      && xtoi_2 (parm->serialno+12) >= 2 );
233     }
234   else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
235     {
236       xfree (parm->apptype);
237       parm->apptype = unescape_status_string (line);
238     }
239   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
240     {
241       xfree (parm->disp_name);
242       parm->disp_name = unescape_status_string (line);
243     }
244   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
245     {
246       xfree (parm->disp_lang);
247       parm->disp_lang = unescape_status_string (line);
248     }
249   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
250     {
251       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
252     }
253   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
254     {
255       xfree (parm->pubkey_url);
256       parm->pubkey_url = unescape_status_string (line);
257     }
258   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
259     {
260       xfree (parm->login_data);
261       parm->login_data = unescape_status_string (line);
262     }
263   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
264     {
265       parm->sig_counter = strtoul (line, NULL, 0);
266     }
267   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
268     {
269       char *p, *buf;
270
271       buf = p = unescape_status_string (line);
272       if (buf)
273         {
274           while (spacep (p))
275             p++;
276           parm->chv1_cached = atoi (p);
277           while (*p && !spacep (p))
278             p++;
279           while (spacep (p))
280             p++;
281           for (i=0; *p && i < 3; i++)
282             {
283               parm->chvmaxlen[i] = atoi (p);
284               while (*p && !spacep (p))
285                 p++;
286               while (spacep (p))
287                 p++;
288             }
289           for (i=0; *p && i < 3; i++)
290             {
291               parm->chvretry[i] = atoi (p);
292               while (*p && !spacep (p))
293                 p++;
294               while (spacep (p))
295                 p++;
296             }
297           xfree (buf);
298         }
299     }
300   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
301     {
302       int no = atoi (line);
303       while (*line && !spacep (line))
304         line++;
305       while (spacep (line))
306         line++;
307       if (no == 1)
308         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
309       else if (no == 2)
310         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
311       else if (no == 3)
312         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
313     }
314   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
315     {
316       int no = atoi (line);
317       while (*line && !spacep (line))
318         line++;
319       while (spacep (line))
320         line++;
321       if (no == 1)
322         parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
323       else if (no == 2)
324         parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
325       else if (no == 3)
326         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
327     }
328   else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
329     {
330       int keyno, algo, nbits;
331
332       sscanf (line, "%d %d %d", &keyno, &algo, &nbits);
333       keyno--;
334       if (keyno >= 0 && keyno < DIM (parm->key_attr))
335         {
336           parm->key_attr[keyno].algo = algo;
337           parm->key_attr[keyno].nbits = nbits;
338         }
339     }
340
341   return 0;
342 }
343
344 /* Call the agent to learn about a smartcard */
345 int
346 agent_learn (struct agent_card_info_s *info)
347 {
348   int rc;
349
350   rc = start_agent ();
351   if (rc)
352     return rc;
353
354   memset (info, 0, sizeof *info);
355   rc = assuan_transact (agent_ctx, "LEARN --send",
356                         dummy_data_cb, NULL, default_inq_cb, NULL,
357                         learn_status_cb, info);
358   /* Also try to get the key attributes.  */
359   if (!rc)
360     agent_scd_getattr ("KEY-ATTR", info);
361   
362   return rc;
363 }
364
365 /* Call the agent to retrieve a data object.  This function returns
366    the data in the same structure as used by the learn command.  It is
367    allowed to update such a structure using this commmand. */
368 int
369 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
370 {
371   int rc;
372   char line[ASSUAN_LINELENGTH];
373
374   if (!*name)
375     return gpg_error (GPG_ERR_INV_VALUE);
376
377   /* We assume that NAME does not need escaping. */
378   if (12 + strlen (name) > DIM(line)-1)
379     return gpg_error (GPG_ERR_TOO_LARGE);
380   stpcpy (stpcpy (line, "SCD GETATTR "), name); 
381
382   rc = start_agent ();
383   if (rc)
384     return rc;
385
386   rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
387                         learn_status_cb, info);
388   
389   return rc;
390 }
391
392 \f
393 /* Send an setattr command to the SCdaemon.  SERIALNO is not actually
394    used here but required by gpg 1.4's implementation of this code in
395    cardglue.c. */
396 int
397 agent_scd_setattr (const char *name,
398                    const unsigned char *value, size_t valuelen,
399                    const char *serialno)
400 {
401   int rc;
402   char line[ASSUAN_LINELENGTH];
403   char *p;
404
405   (void)serialno;
406
407   if (!*name || !valuelen)
408     return gpg_error (GPG_ERR_INV_VALUE);
409
410   /* We assume that NAME does not need escaping. */
411   if (12 + strlen (name) > DIM(line)-1)
412     return gpg_error (GPG_ERR_TOO_LARGE);
413       
414   p = stpcpy (stpcpy (line, "SCD SETATTR "), name); 
415   *p++ = ' ';
416   for (; valuelen; value++, valuelen--)
417     {
418       if (p >= line + DIM(line)-5 )
419         return gpg_error (GPG_ERR_TOO_LARGE);
420       if (*value < ' ' || *value == '+' || *value == '%')
421         {
422           sprintf (p, "%%%02X", *value);
423           p += 3;
424         }
425       else if (*value == ' ')
426         *p++ = '+';
427       else
428         *p++ = *value;
429     }
430   *p = 0;
431
432   rc = start_agent ();
433   if (rc)
434     return rc;
435
436   rc = assuan_transact (agent_ctx, line, NULL, NULL, 
437                         default_inq_cb, NULL, NULL, NULL);
438   return rc;
439 }
440
441
442 \f
443 /* Handle a CERTDATA inquiry.  Note, we only send the data,
444    assuan_transact takes care of flushing and writing the END
445    command. */
446 static int
447 inq_writecert_parms (void *opaque, const char *line)
448 {
449   int rc;
450   struct writecert_parm_s *parm = opaque; 
451
452   if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
453     {
454       rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
455     }
456   else
457     rc = default_inq_cb (opaque, line);
458
459   return rc;
460 }
461
462
463 /* Send a WRITECERT command to the SCdaemon. */
464 int 
465 agent_scd_writecert (const char *certidstr,
466                      const unsigned char *certdata, size_t certdatalen)
467 {
468   int rc;
469   char line[ASSUAN_LINELENGTH];
470   struct writecert_parm_s parms;
471
472   rc = start_agent ();
473   if (rc)
474     return rc;
475
476   memset (&parms, 0, sizeof parms);
477
478   snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
479   line[DIM(line)-1] = 0;
480   parms.ctx = agent_ctx;
481   parms.certdata = certdata;
482   parms.certdatalen = certdatalen;
483   
484   rc = assuan_transact (agent_ctx, line, NULL, NULL,
485                         inq_writecert_parms, &parms, NULL, NULL);
486
487   return rc;
488 }
489
490
491 \f
492 /* Handle a KEYDATA inquiry.  Note, we only send the data,
493    assuan_transact takes care of flushing and writing the end */
494 static int
495 inq_writekey_parms (void *opaque, const char *line)
496 {
497   int rc;
498   struct writekey_parm_s *parm = opaque; 
499
500   if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
501     {
502       rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
503     }
504   else
505     rc = default_inq_cb (opaque, line);
506
507   return rc;
508 }
509
510
511 /* Send a WRITEKEY command to the SCdaemon. */
512 int 
513 agent_scd_writekey (int keyno, const char *serialno,
514                     const unsigned char *keydata, size_t keydatalen)
515 {
516   int rc;
517   char line[ASSUAN_LINELENGTH];
518   struct writekey_parm_s parms;
519
520   (void)serialno;
521
522   rc = start_agent ();
523   if (rc)
524     return rc;
525
526   memset (&parms, 0, sizeof parms);
527
528   snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
529   line[DIM(line)-1] = 0;
530   parms.ctx = agent_ctx;
531   parms.keydata = keydata;
532   parms.keydatalen = keydatalen;
533   
534   rc = assuan_transact (agent_ctx, line, NULL, NULL,
535                         inq_writekey_parms, &parms, NULL, NULL);
536
537   return rc;
538 }
539
540
541 \f
542 /* Status callback for the SCD GENKEY command. */
543 static int
544 scd_genkey_cb (void *opaque, const char *line)
545 {
546   struct agent_card_genkey_s *parm = opaque;
547   const char *keyword = line;
548   int keywordlen;
549   gpg_error_t rc;
550
551   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
552     ;
553   while (spacep (line))
554     line++;
555
556   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
557     {
558       parm->fprvalid = unhexify_fpr (line, parm->fpr);
559     }
560   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
561     {
562       gcry_mpi_t a;
563       const char *name = line;
564
565       while (*line && !spacep (line))
566         line++;
567       while (spacep (line))
568         line++;
569
570       rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
571       if (rc)
572         log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
573       else if (*name == 'n' && spacep (name+1))
574         parm->n = a;
575       else if (*name == 'e' && spacep (name+1))
576         parm->e = a;
577       else
578         {
579           log_info ("unknown parameter name in received key data\n");
580           gcry_mpi_release (a);
581         }
582     }
583   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
584     {
585       parm->created_at = (u32)strtoul (line, NULL, 10);
586     }
587
588   return 0;
589 }
590
591 /* Send a GENKEY command to the SCdaemon.  SERIALNO is not used in
592    this implementation.  If CREATEDATE has been given, it will be
593    passed to SCDAEMON so that the key can be created with this
594    timestamp; note the user needs to use the returned timestamp as old
595    versions of scddaemon don't support this option.  */
596 int
597 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
598                   const char *serialno, u32 createtime)
599 {
600   int rc;
601   char line[ASSUAN_LINELENGTH];
602   gnupg_isotime_t tbuf;
603
604   (void)serialno;
605
606   rc = start_agent ();
607   if (rc)
608     return rc;
609
610   if (createtime)
611     epoch2isotime (tbuf, createtime);
612   else
613     *tbuf = 0;
614
615   memset (info, 0, sizeof *info);
616   snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
617             *tbuf? "--timestamp=":"", tbuf,
618             force? "--force":"", 
619             keyno);
620   line[DIM(line)-1] = 0;
621
622   memset (info, 0, sizeof *info);
623   rc = assuan_transact (agent_ctx, line,
624                         NULL, NULL, default_inq_cb, NULL,
625                         scd_genkey_cb, info);
626   
627   return rc;
628 }
629
630 \f
631 static int
632 membuf_data_cb (void *opaque, const void *buffer, size_t length)
633 {
634   membuf_t *data = opaque;
635
636   if (buffer)
637     put_membuf (data, buffer, length);
638   return 0;
639 }
640   
641 /* Send a sign command to the scdaemon via gpg-agent's pass thru
642    mechanism. */
643 int
644 agent_scd_pksign (const char *serialno, int hashalgo,
645                   const unsigned char *indata, size_t indatalen,
646                   unsigned char **r_buf, size_t *r_buflen)
647 {
648   int rc, i;
649   char *p, line[ASSUAN_LINELENGTH];
650   membuf_t data;
651   size_t len;
652
653   /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
654
655   *r_buf = NULL;
656   *r_buflen = 0;
657
658   rc = start_agent ();
659   if (rc)
660     return rc;
661
662   if (indatalen*2 + 50 > DIM(line))
663     return gpg_error (GPG_ERR_GENERAL);
664
665   /* Send the serialno command to initialize the connection. We don't
666      care about the data returned.  If the card has already been
667      initialized, this is a very fast command.  We request the openpgp
668      card because that is what we expect. */
669   rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
670                         NULL, NULL, NULL, NULL, NULL, NULL);
671   if (rc)
672     return rc;
673
674   sprintf (line, "SCD SETDATA ");
675   p = line + strlen (line);
676   for (i=0; i < indatalen ; i++, p += 2 )
677     sprintf (p, "%02X", indata[i]);
678   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
679   if (rc)
680     return rc;
681
682   init_membuf (&data, 1024);
683 #if 0
684   if (!hashalgo) /* Temporary test hack. */
685     snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
686   else
687 #endif
688     snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
689               hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
690               serialno);
691   line[DIM(line)-1] = 0;
692   rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
693                         default_inq_cb, NULL, NULL, NULL);
694   if (rc)
695     {
696       xfree (get_membuf (&data, &len));
697       return rc;
698     }
699   *r_buf = get_membuf (&data, r_buflen);
700
701   return 0;
702 }
703
704
705 /* Decrypt INDATA of length INDATALEN using the card identified by
706    SERIALNO.  Return the plaintext in a nwly allocated buffer stored
707    at the address of R_BUF. 
708
709    Note, we currently support only RSA or more exactly algorithms
710    taking one input data element. */
711 int
712 agent_scd_pkdecrypt (const char *serialno,
713                      const unsigned char *indata, size_t indatalen,
714                      unsigned char **r_buf, size_t *r_buflen)
715 {
716   int rc, i;
717   char *p, line[ASSUAN_LINELENGTH];
718   membuf_t data;
719   size_t len;
720
721   *r_buf = NULL;
722   rc = start_agent ();
723   if (rc)
724     return rc;
725
726   /* FIXME: use secure memory where appropriate */
727   if (indatalen*2 + 50 > DIM(line))
728     return gpg_error (GPG_ERR_GENERAL);
729
730   /* Send the serialno command to initialize the connection. We don't
731      care about the data returned.  If the card has already been
732      initialized, this is a very fast command.  We request the openpgp
733      card because that is what we expect. */
734   rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
735                         NULL, NULL, NULL, NULL, NULL, NULL);
736   if (rc)
737     return rc;
738
739   sprintf (line, "SCD SETDATA ");
740   p = line + strlen (line);
741   for (i=0; i < indatalen ; i++, p += 2 )
742     sprintf (p, "%02X", indata[i]);
743   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
744   if (rc)
745     return rc;
746
747   init_membuf (&data, 1024);
748   snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
749   line[DIM(line)-1] = 0;
750   rc = assuan_transact (agent_ctx, line,
751                         membuf_data_cb, &data,
752                         default_inq_cb, NULL, NULL, NULL);
753   if (rc)
754     {
755       xfree (get_membuf (&data, &len));
756       return rc;
757     }
758   *r_buf = get_membuf (&data, r_buflen);
759   if (!*r_buf)
760     return gpg_error (GPG_ERR_ENOMEM);
761
762   return 0;
763 }
764
765
766 \f
767 /* Send a READCERT command to the SCdaemon. */
768 int 
769 agent_scd_readcert (const char *certidstr,
770                     void **r_buf, size_t *r_buflen)
771 {
772   int rc;
773   char line[ASSUAN_LINELENGTH];
774   membuf_t data;
775   size_t len;
776
777   *r_buf = NULL;
778   rc = start_agent ();
779   if (rc)
780     return rc;
781
782   init_membuf (&data, 2048);
783
784   snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
785   line[DIM(line)-1] = 0;
786   rc = assuan_transact (agent_ctx, line,
787                         membuf_data_cb, &data,
788                         default_inq_cb, NULL, NULL, NULL);
789   if (rc)
790     {
791       xfree (get_membuf (&data, &len));
792       return rc;
793     }
794   *r_buf = get_membuf (&data, r_buflen);
795   if (!*r_buf)
796     return gpg_error (GPG_ERR_ENOMEM);
797
798   return 0;
799 }
800
801
802 \f
803 /* Change the PIN of an OpenPGP card or reset the retry counter.
804    CHVNO 1: Change the PIN
805          2: For v1 cards: Same as 1.
806             For v2 cards: Reset the PIN using the Reset Code.
807          3: Change the admin PIN
808        101: Set a new PIN and reset the retry counter
809        102: For v1 cars: Same as 101.
810             For v2 cards: Set a new Reset Code.
811    SERIALNO is not used.
812  */
813 int
814 agent_scd_change_pin (int chvno, const char *serialno)
815 {
816   int rc;
817   char line[ASSUAN_LINELENGTH];
818   const char *reset = "";
819
820   (void)serialno;
821
822   if (chvno >= 100)
823     reset = "--reset";
824   chvno %= 100;
825
826   rc = start_agent ();
827   if (rc)
828     return rc;
829
830   snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
831   line[DIM(line)-1] = 0;
832   rc = assuan_transact (agent_ctx, line, NULL, NULL,
833                         default_inq_cb, NULL, NULL, NULL);
834   return rc;
835 }
836
837
838 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
839    number of the card - optionally followed by the fingerprint;
840    however the fingerprint is ignored here. */
841 int
842 agent_scd_checkpin  (const char *serialno)
843 {
844   int rc;
845   char line[ASSUAN_LINELENGTH];
846
847   rc = start_agent ();
848   if (rc)
849     return rc;
850
851   snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
852   line[DIM(line)-1] = 0;
853   return assuan_transact (agent_ctx, line,
854                           NULL, NULL,
855                           default_inq_cb, NULL, NULL, NULL);
856 }
857
858
859 /* Dummy function, only used by the gpg 1.4 implementation. */
860 void
861 agent_clear_pin_cache (const char *sn)
862 {
863   (void)sn;
864 }
865
866
867
868 \f
869 /* Note: All strings shall be UTF-8. On success the caller needs to
870    free the string stored at R_PASSPHRASE. On error NULL will be
871    stored at R_PASSPHRASE and an appropriate fpf error code
872    returned. */
873 gpg_error_t
874 agent_get_passphrase (const char *cache_id,
875                       const char *err_msg,
876                       const char *prompt,
877                       const char *desc_msg,
878                       int repeat,
879                       int check,
880                       char **r_passphrase)
881 {
882   int rc;
883   char line[ASSUAN_LINELENGTH];
884   char *arg1 = NULL;
885   char *arg2 = NULL;  
886   char *arg3 = NULL; 
887   char *arg4 = NULL;
888   membuf_t data;
889
890   *r_passphrase = NULL;
891
892   rc = start_agent ();
893   if (rc)
894     return rc;
895
896   /* Check that the gpg-agent understands the repeat option.  */
897   if (assuan_transact (agent_ctx, 
898                        "GETINFO cmd_has_option GET_PASSPHRASE repeat",
899                        NULL, NULL, NULL, NULL, NULL, NULL))
900     return gpg_error (GPG_ERR_NOT_SUPPORTED);
901
902   if (cache_id && *cache_id)
903     if (!(arg1 = percent_plus_escape (cache_id)))
904       goto no_mem;
905   if (err_msg && *err_msg)
906     if (!(arg2 = percent_plus_escape (err_msg)))
907       goto no_mem;
908   if (prompt && *prompt)
909     if (!(arg3 = percent_plus_escape (prompt)))
910       goto no_mem;
911   if (desc_msg && *desc_msg)
912     if (!(arg4 = percent_plus_escape (desc_msg)))
913       goto no_mem;
914
915   snprintf (line, DIM(line)-1, 
916             "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s", 
917             repeat, 
918             check? " --check --qualitybar":"",
919             arg1? arg1:"X",
920             arg2? arg2:"X",
921             arg3? arg3:"X",
922             arg4? arg4:"X");
923   line[DIM(line)-1] = 0;
924   xfree (arg1);
925   xfree (arg2);
926   xfree (arg3);
927   xfree (arg4);
928
929   init_membuf_secure (&data, 64);
930   rc = assuan_transact (agent_ctx, line, 
931                         membuf_data_cb, &data,
932                         default_inq_cb, NULL, NULL, NULL);
933
934   if (rc)
935     xfree (get_membuf (&data, NULL));
936   else 
937     {
938       put_membuf (&data, "", 1);
939       *r_passphrase = get_membuf (&data, NULL);
940       if (!*r_passphrase)
941         rc = gpg_error_from_syserror ();
942     }
943   return rc;
944  no_mem:
945   rc = gpg_error_from_syserror ();
946   xfree (arg1);
947   xfree (arg2);
948   xfree (arg3);
949   xfree (arg4);
950   return rc;
951 }
952
953
954 gpg_error_t
955 agent_clear_passphrase (const char *cache_id)
956 {
957   int rc;
958   char line[ASSUAN_LINELENGTH];
959
960   if (!cache_id || !*cache_id)
961     return 0;
962
963   rc = start_agent ();
964   if (rc)
965     return rc;
966
967   snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
968   line[DIM(line)-1] = 0;
969   return assuan_transact (agent_ctx, line, NULL, NULL,
970                           default_inq_cb, NULL, NULL, NULL);
971 }