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