63919dd1f312a736df45cf97b676233ec74a8c95
[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
492 \f
493 /* Handle a KEYDATA inquiry.  Note, we only send the data,
494    assuan_transact takes care of flushing and writing the end */
495 static int
496 inq_writekey_parms (void *opaque, const char *line)
497 {
498   int rc;
499   struct writekey_parm_s *parm = opaque; 
500
501   if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
502     {
503       rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
504     }
505   else
506     rc = default_inq_cb (opaque, line);
507
508   return rc;
509 }
510
511
512 /* Send a WRITEKEY command to the SCdaemon. */
513 int 
514 agent_scd_writekey (int keyno, const char *serialno,
515                     const unsigned char *keydata, size_t keydatalen)
516 {
517   int rc;
518   char line[ASSUAN_LINELENGTH];
519   struct writekey_parm_s parms;
520
521   (void)serialno;
522
523   rc = start_agent ();
524   if (rc)
525     return rc;
526
527   memset (&parms, 0, sizeof parms);
528
529   snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
530   line[DIM(line)-1] = 0;
531   parms.ctx = agent_ctx;
532   parms.keydata = keydata;
533   parms.keydatalen = keydatalen;
534   
535   rc = assuan_transact (agent_ctx, line, NULL, NULL,
536                         inq_writekey_parms, &parms, NULL, NULL);
537
538   return rc;
539 }
540
541
542
543 \f
544 /* Status callback for the SCD GENKEY command. */
545 static int
546 scd_genkey_cb (void *opaque, const char *line)
547 {
548   struct agent_card_genkey_s *parm = opaque;
549   const char *keyword = line;
550   int keywordlen;
551   gpg_error_t rc;
552
553   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
554     ;
555   while (spacep (line))
556     line++;
557
558   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
559     {
560       parm->fprvalid = unhexify_fpr (line, parm->fpr);
561     }
562   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
563     {
564       gcry_mpi_t a;
565       const char *name = line;
566
567       while (*line && !spacep (line))
568         line++;
569       while (spacep (line))
570         line++;
571
572       rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
573       if (rc)
574         log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
575       else if (*name == 'n' && spacep (name+1))
576         parm->n = a;
577       else if (*name == 'e' && spacep (name+1))
578         parm->e = a;
579       else
580         {
581           log_info ("unknown parameter name in received key data\n");
582           gcry_mpi_release (a);
583         }
584     }
585   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
586     {
587       parm->created_at = (u32)strtoul (line, NULL, 10);
588     }
589
590   return 0;
591 }
592
593 /* Send a GENKEY command to the SCdaemon.  SERIALNO is not used in
594    this implementation.  If CREATEDATE has been given, it will be
595    passed to SCDAEMON so that the key can be created with this
596    timestamp; note the user needs to use the returned timestamp as old
597    versions of scddaemon don't support this option.  */
598 int
599 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
600                   const char *serialno, u32 createtime)
601 {
602   int rc;
603   char line[ASSUAN_LINELENGTH];
604   gnupg_isotime_t tbuf;
605
606   (void)serialno;
607
608   rc = start_agent ();
609   if (rc)
610     return rc;
611
612   if (createtime)
613     epoch2isotime (tbuf, createtime);
614   else
615     *tbuf = 0;
616
617   memset (info, 0, sizeof *info);
618   snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
619             *tbuf? "--timestamp=":"", tbuf,
620             force? "--force":"", 
621             keyno);
622   line[DIM(line)-1] = 0;
623
624   memset (info, 0, sizeof *info);
625   rc = assuan_transact (agent_ctx, line,
626                         NULL, NULL, default_inq_cb, NULL,
627                         scd_genkey_cb, info);
628   
629   return rc;
630 }
631
632 \f
633 static int
634 membuf_data_cb (void *opaque, const void *buffer, size_t length)
635 {
636   membuf_t *data = opaque;
637
638   if (buffer)
639     put_membuf (data, buffer, length);
640   return 0;
641 }
642   
643 /* Send a sign command to the scdaemon via gpg-agent's pass thru
644    mechanism. */
645 int
646 agent_scd_pksign (const char *serialno, int hashalgo,
647                   const unsigned char *indata, size_t indatalen,
648                   unsigned char **r_buf, size_t *r_buflen)
649 {
650   int rc, i;
651   char *p, line[ASSUAN_LINELENGTH];
652   membuf_t data;
653   size_t len;
654
655   /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
656
657   *r_buf = NULL;
658   *r_buflen = 0;
659
660   rc = start_agent ();
661   if (rc)
662     return rc;
663
664   if (indatalen*2 + 50 > DIM(line))
665     return gpg_error (GPG_ERR_GENERAL);
666
667   /* Send the serialno command to initialize the connection. We don't
668      care about the data returned.  If the card has already been
669      initialized, this is a very fast command.  We request the openpgp
670      card because that is what we expect. */
671   rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
672                         NULL, NULL, NULL, NULL, NULL, NULL);
673   if (rc)
674     return rc;
675
676   sprintf (line, "SCD SETDATA ");
677   p = line + strlen (line);
678   for (i=0; i < indatalen ; i++, p += 2 )
679     sprintf (p, "%02X", indata[i]);
680   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
681   if (rc)
682     return rc;
683
684   init_membuf (&data, 1024);
685 #if 0
686   if (!hashalgo) /* Temporary test hack. */
687     snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
688   else
689 #endif
690     snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
691               hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
692               serialno);
693   line[DIM(line)-1] = 0;
694   rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
695                         default_inq_cb, NULL, NULL, NULL);
696   if (rc)
697     {
698       xfree (get_membuf (&data, &len));
699       return rc;
700     }
701   *r_buf = get_membuf (&data, r_buflen);
702
703   return 0;
704 }
705
706
707 /* Decrypt INDATA of length INDATALEN using the card identified by
708    SERIALNO.  Return the plaintext in a nwly allocated buffer stored
709    at the address of R_BUF. 
710
711    Note, we currently support only RSA or more exactly algorithms
712    taking one input data element. */
713 int
714 agent_scd_pkdecrypt (const char *serialno,
715                      const unsigned char *indata, size_t indatalen,
716                      unsigned char **r_buf, size_t *r_buflen)
717 {
718   int rc, i;
719   char *p, line[ASSUAN_LINELENGTH];
720   membuf_t data;
721   size_t len;
722
723   *r_buf = NULL;
724   rc = start_agent ();
725   if (rc)
726     return rc;
727
728   /* FIXME: use secure memory where appropriate */
729   if (indatalen*2 + 50 > DIM(line))
730     return gpg_error (GPG_ERR_GENERAL);
731
732   /* Send the serialno command to initialize the connection. We don't
733      care about the data returned.  If the card has already been
734      initialized, this is a very fast command.  We request the openpgp
735      card because that is what we expect. */
736   rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
737                         NULL, NULL, NULL, NULL, NULL, NULL);
738   if (rc)
739     return rc;
740
741   sprintf (line, "SCD SETDATA ");
742   p = line + strlen (line);
743   for (i=0; i < indatalen ; i++, p += 2 )
744     sprintf (p, "%02X", indata[i]);
745   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
746   if (rc)
747     return rc;
748
749   init_membuf (&data, 1024);
750   snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
751   line[DIM(line)-1] = 0;
752   rc = assuan_transact (agent_ctx, line,
753                         membuf_data_cb, &data,
754                         default_inq_cb, NULL, NULL, NULL);
755   if (rc)
756     {
757       xfree (get_membuf (&data, &len));
758       return rc;
759     }
760   *r_buf = get_membuf (&data, r_buflen);
761   if (!*r_buf)
762     return gpg_error (GPG_ERR_ENOMEM);
763
764   return 0;
765 }
766
767
768 /* Change the PIN of an OpenPGP card or reset the retry counter.
769    CHVNO 1: Change the PIN
770          2: For v1 cards: Same as 1.
771             For v2 cards: Reset the PIN using the Reset Code.
772          3: Change the admin PIN
773        101: Set a new PIN and reset the retry counter
774        102: For v1 cars: Same as 101.
775             For v2 cards: Set a new Reset Code.
776    SERIALNO is not used.
777  */
778 int
779 agent_scd_change_pin (int chvno, const char *serialno)
780 {
781   int rc;
782   char line[ASSUAN_LINELENGTH];
783   const char *reset = "";
784
785   (void)serialno;
786
787   if (chvno >= 100)
788     reset = "--reset";
789   chvno %= 100;
790
791   rc = start_agent ();
792   if (rc)
793     return rc;
794
795   snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
796   line[DIM(line)-1] = 0;
797   rc = assuan_transact (agent_ctx, line, NULL, NULL,
798                         default_inq_cb, NULL, NULL, NULL);
799   return rc;
800 }
801
802
803 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
804    number of the card - optionally followed by the fingerprint;
805    however the fingerprint is ignored here. */
806 int
807 agent_scd_checkpin  (const char *serialno)
808 {
809   int rc;
810   char line[ASSUAN_LINELENGTH];
811
812   rc = start_agent ();
813   if (rc)
814     return rc;
815
816   snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
817   line[DIM(line)-1] = 0;
818   return assuan_transact (agent_ctx, line,
819                           NULL, NULL,
820                           default_inq_cb, NULL, NULL, NULL);
821 }
822
823
824 /* Dummy function, only used by the gpg 1.4 implementation. */
825 void
826 agent_clear_pin_cache (const char *sn)
827 {
828   (void)sn;
829 }
830
831
832
833 \f
834 /* Note: All strings shall be UTF-8. On success the caller needs to
835    free the string stored at R_PASSPHRASE. On error NULL will be
836    stored at R_PASSPHRASE and an appropriate fpf error code
837    returned. */
838 gpg_error_t
839 agent_get_passphrase (const char *cache_id,
840                       const char *err_msg,
841                       const char *prompt,
842                       const char *desc_msg,
843                       int repeat,
844                       int check,
845                       char **r_passphrase)
846 {
847   int rc;
848   char line[ASSUAN_LINELENGTH];
849   char *arg1 = NULL;
850   char *arg2 = NULL;  
851   char *arg3 = NULL; 
852   char *arg4 = NULL;
853   membuf_t data;
854
855   *r_passphrase = NULL;
856
857   rc = start_agent ();
858   if (rc)
859     return rc;
860
861   /* Check that the gpg-agent understands the repeat option.  */
862   if (assuan_transact (agent_ctx, 
863                        "GETINFO cmd_has_option GET_PASSPHRASE repeat",
864                        NULL, NULL, NULL, NULL, NULL, NULL))
865     return gpg_error (GPG_ERR_NOT_SUPPORTED);
866
867   if (cache_id && *cache_id)
868     if (!(arg1 = percent_plus_escape (cache_id)))
869       goto no_mem;
870   if (err_msg && *err_msg)
871     if (!(arg2 = percent_plus_escape (err_msg)))
872       goto no_mem;
873   if (prompt && *prompt)
874     if (!(arg3 = percent_plus_escape (prompt)))
875       goto no_mem;
876   if (desc_msg && *desc_msg)
877     if (!(arg4 = percent_plus_escape (desc_msg)))
878       goto no_mem;
879
880   snprintf (line, DIM(line)-1, 
881             "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s", 
882             repeat, 
883             check? " --check --qualitybar":"",
884             arg1? arg1:"X",
885             arg2? arg2:"X",
886             arg3? arg3:"X",
887             arg4? arg4:"X");
888   line[DIM(line)-1] = 0;
889   xfree (arg1);
890   xfree (arg2);
891   xfree (arg3);
892   xfree (arg4);
893
894   init_membuf_secure (&data, 64);
895   rc = assuan_transact (agent_ctx, line, 
896                         membuf_data_cb, &data,
897                         default_inq_cb, NULL, NULL, NULL);
898
899   if (rc)
900     xfree (get_membuf (&data, NULL));
901   else 
902     {
903       put_membuf (&data, "", 1);
904       *r_passphrase = get_membuf (&data, NULL);
905       if (!*r_passphrase)
906         rc = gpg_error_from_syserror ();
907     }
908   return rc;
909  no_mem:
910   rc = gpg_error_from_syserror ();
911   xfree (arg1);
912   xfree (arg2);
913   xfree (arg3);
914   xfree (arg4);
915   return rc;
916 }
917
918
919 gpg_error_t
920 agent_clear_passphrase (const char *cache_id)
921 {
922   int rc;
923   char line[ASSUAN_LINELENGTH];
924
925   if (!cache_id || !*cache_id)
926     return 0;
927
928   rc = start_agent ();
929   if (rc)
930     return rc;
931
932   snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
933   line[DIM(line)-1] = 0;
934   return assuan_transact (agent_ctx, line, NULL, NULL,
935                           default_inq_cb, NULL, NULL, NULL);
936 }