Started to implement the audit log feature.
[gnupg.git] / g10 / call-agent.c
1 /* call-agent.c - divert operations to the agent
2  * Copyright (C) 2001, 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h> 
26 #include <time.h>
27 #include <assert.h>
28 #ifdef HAVE_LOCALE_H
29 #include <locale.h>
30 #endif
31 #include <assuan.h>
32
33 #include "gpg.h"
34 #include "util.h"
35 #include "membuf.h"
36 #include "options.h"
37 #include "i18n.h"
38 #include "asshelp.h"
39 #include "call-agent.h"
40
41 #ifndef DBG_ASSUAN
42 # define DBG_ASSUAN 1
43 #endif
44
45 static assuan_context_t agent_ctx = NULL;
46
47 struct cipher_parm_s 
48 {
49   assuan_context_t ctx;
50   const char *ciphertext;
51   size_t ciphertextlen;
52 };
53
54 struct writekey_parm_s
55 {
56   assuan_context_t ctx;
57   const unsigned char *keydata;
58   size_t keydatalen;
59 };
60
61 struct genkey_parm_s 
62 {
63   assuan_context_t ctx;
64   const char *sexp;
65   size_t sexplen;
66 };
67
68
69 \f
70 /* Try to connect to the agent via socket or fork it off and work by
71    pipes.  Handle the server's initial greeting */
72 static int
73 start_agent (void)
74 {
75   if (agent_ctx)
76     return 0; /* Fixme: We need a context for each thread or serialize
77                  the access to the agent. */
78
79   return start_new_gpg_agent (&agent_ctx,
80                               GPG_ERR_SOURCE_DEFAULT,
81                               opt.homedir,
82                               opt.agent_program,
83                               opt.display, opt.ttyname, opt.ttytype,
84                               opt.lc_ctype, opt.lc_messages,
85                               opt.xauthority, opt.pinentry_user_data,
86                               opt.verbose, DBG_ASSUAN,
87                               NULL, NULL);
88 }
89
90
91 /* Return a new malloced string by unescaping the string S.  Escaping
92    is percent escaping and '+'/space mapping.  A binary nul will
93    silently be replaced by a 0xFF.  Function returns NULL to indicate
94    an out of memory status. */
95 static char *
96 unescape_status_string (const unsigned char *s)
97 {
98   char *buffer, *d;
99
100   buffer = d = xtrymalloc (strlen (s)+1);
101   if (!buffer)
102     return NULL;
103   while (*s)
104     {
105       if (*s == '%' && s[1] && s[2])
106         { 
107           s++;
108           *d = xtoi_2 (s);
109           if (!*d)
110             *d = '\xff';
111           d++;
112           s += 2;
113         }
114       else if (*s == '+')
115         {
116           *d++ = ' ';
117           s++;
118         }
119       else
120         *d++ = *s++;
121     }
122   *d = 0; 
123   return buffer;
124 }
125
126 /* Copy the text ATEXT into the buffer P and do plus '+' and percent
127    escaping.  Note that the provided buffer needs to be 3 times the
128    size of ATEXT plus 1.  Returns a pointer to the leading Nul in P. */
129 static char *
130 percent_plus_escape (char *p, const char *atext)
131 {
132   const unsigned char *s;
133
134   for (s=atext; *s; s++)
135     {
136       if (*s < ' ' || *s == '+')
137         {
138           sprintf (p, "%%%02X", *s);
139           p += 3;
140         }
141       else if (*s == ' ')
142         *p++ = '+';
143       else
144         *p++ = *s;
145     }
146   *p = 0;
147   return p;
148 }
149
150 /* Take a 20 byte hexencoded string and put it into the the provided
151    20 byte buffer FPR in binary format. */
152 static int
153 unhexify_fpr (const char *hexstr, unsigned char *fpr)
154 {
155   const char *s;
156   int n;
157
158   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
159     ;
160   if (*s || (n != 40))
161     return 0; /* no fingerprint (invalid or wrong length). */
162   n /= 2;
163   for (s=hexstr, n=0; *s; s += 2, n++)
164     fpr[n] = xtoi_2 (s);
165   return 1; /* okay */
166 }
167
168 /* Take the serial number from LINE and return it verbatim in a newly
169    allocated string.  We make sure that only hex characters are
170    returned. */
171 static char *
172 store_serialno (const char *line)
173 {
174   const char *s;
175   char *p;
176
177   for (s=line; hexdigitp (s); s++)
178     ;
179   p = xtrymalloc (s + 1 - line);
180   if (p)
181     {
182       memcpy (p, line, s-line);
183       p[s-line] = 0;
184     }
185   return p;
186 }
187
188
189 \f
190 /* Release the card info structure INFO. */
191 void
192 agent_release_card_info (struct agent_card_info_s *info)
193 {
194   if (!info)
195     return;
196
197   xfree (info->serialno); info->serialno = NULL;
198   xfree (info->disp_name); info->disp_name = NULL;
199   xfree (info->disp_lang); info->disp_lang = NULL;
200   xfree (info->pubkey_url); info->pubkey_url = NULL;
201   xfree (info->login_data); info->login_data = NULL;
202   info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
203   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
204 }
205
206 static int
207 learn_status_cb (void *opaque, const char *line)
208 {
209   struct agent_card_info_s *parm = opaque;
210   const char *keyword = line;
211   int keywordlen;
212   int i;
213
214   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
215     ;
216   while (spacep (line))
217     line++;
218
219   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
220     {
221       xfree (parm->serialno);
222       parm->serialno = store_serialno (line);
223     }
224   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
225     {
226       xfree (parm->disp_name);
227       parm->disp_name = unescape_status_string (line);
228     }
229   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
230     {
231       xfree (parm->disp_lang);
232       parm->disp_lang = unescape_status_string (line);
233     }
234   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
235     {
236       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
237     }
238   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
239     {
240       xfree (parm->pubkey_url);
241       parm->pubkey_url = unescape_status_string (line);
242     }
243   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
244     {
245       xfree (parm->login_data);
246       parm->login_data = unescape_status_string (line);
247     }
248   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
249     {
250       parm->sig_counter = strtoul (line, NULL, 0);
251     }
252   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
253     {
254       char *p, *buf;
255
256       buf = p = unescape_status_string (line);
257       if (buf)
258         {
259           while (spacep (p))
260             p++;
261           parm->chv1_cached = atoi (p);
262           while (*p && !spacep (p))
263             p++;
264           while (spacep (p))
265             p++;
266           for (i=0; *p && i < 3; i++)
267             {
268               parm->chvmaxlen[i] = atoi (p);
269               while (*p && !spacep (p))
270                 p++;
271               while (spacep (p))
272                 p++;
273             }
274           for (i=0; *p && i < 3; i++)
275             {
276               parm->chvretry[i] = atoi (p);
277               while (*p && !spacep (p))
278                 p++;
279               while (spacep (p))
280                 p++;
281             }
282           xfree (buf);
283         }
284     }
285   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
286     {
287       int no = atoi (line);
288       while (*line && !spacep (line))
289         line++;
290       while (spacep (line))
291         line++;
292       if (no == 1)
293         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
294       else if (no == 2)
295         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
296       else if (no == 3)
297         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
298     }
299   else if (keywordlen == 6 && !memcmp (keyword, "CA-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->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
308       else if (no == 2)
309         parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
310       else if (no == 3)
311         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
312     }
313   
314   return 0;
315 }
316
317 /* Call the agent to learn about a smartcard */
318 int
319 agent_learn (struct agent_card_info_s *info)
320 {
321   int rc;
322
323   rc = start_agent ();
324   if (rc)
325     return rc;
326
327   memset (info, 0, sizeof *info);
328   rc = assuan_transact (agent_ctx, "LEARN --send",
329                         NULL, NULL, NULL, NULL,
330                         learn_status_cb, info);
331   
332   return rc;
333 }
334
335 /* Call the agent to retrieve a data object.  This function returns
336    the data in the same structure as used by the learn command.  It is
337    allowed to update such a structure using this commmand. */
338 int
339 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
340 {
341   int rc;
342   char line[ASSUAN_LINELENGTH];
343
344   if (!*name)
345     return gpg_error (GPG_ERR_INV_VALUE);
346
347   /* We assume that NAME does not need escaping. */
348   if (12 + strlen (name) > DIM(line)-1)
349     return gpg_error (GPG_ERR_TOO_LARGE);
350   stpcpy (stpcpy (line, "SCD GETATTR "), name); 
351
352   rc = start_agent ();
353   if (rc)
354     return rc;
355
356   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
357                         learn_status_cb, info);
358   
359   return rc;
360 }
361
362 \f
363 /* Send an setattr command to the SCdaemon.  SERIALNO is not actually
364    used here but required by gpg 1.4's implementation of this code in
365    cardglue.c. */
366 int
367 agent_scd_setattr (const char *name,
368                    const unsigned char *value, size_t valuelen,
369                    const char *serialno)
370 {
371   int rc;
372   char line[ASSUAN_LINELENGTH];
373   char *p;
374
375   if (!*name || !valuelen)
376     return gpg_error (GPG_ERR_INV_VALUE);
377
378   /* We assume that NAME does not need escaping. */
379   if (12 + strlen (name) > DIM(line)-1)
380     return gpg_error (GPG_ERR_TOO_LARGE);
381       
382   p = stpcpy (stpcpy (line, "SCD SETATTR "), name); 
383   *p++ = ' ';
384   for (; valuelen; value++, valuelen--)
385     {
386       if (p >= line + DIM(line)-5 )
387         return gpg_error (GPG_ERR_TOO_LARGE);
388       if (*value < ' ' || *value == '+' || *value == '%')
389         {
390           sprintf (p, "%%%02X", *value);
391           p += 3;
392         }
393       else if (*value == ' ')
394         *p++ = '+';
395       else
396         *p++ = *value;
397     }
398   *p = 0;
399
400   rc = start_agent ();
401   if (rc)
402     return rc;
403
404   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
405   return rc;
406 }
407
408
409 \f
410 /* Handle a KEYDATA inquiry.  Note, we only send the data,
411    assuan_transact takes care of flushing and writing the end */
412 static assuan_error_t
413 inq_writekey_parms (void *opaque, const char *keyword)
414 {
415   struct writekey_parm_s *parm = opaque; 
416
417   return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
418 }
419
420
421 /* Send a WRITEKEY command to the SCdaemon. */
422 int 
423 agent_scd_writekey (int keyno, const char *serialno,
424                     const unsigned char *keydata, size_t keydatalen)
425 {
426   int rc;
427   char line[ASSUAN_LINELENGTH];
428   struct writekey_parm_s parms;
429
430   rc = start_agent ();
431   if (rc)
432     return rc;
433
434   memset (&parms, 0, sizeof parms);
435
436   snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
437   line[DIM(line)-1] = 0;
438   parms.ctx = agent_ctx;
439   parms.keydata = keydata;
440   parms.keydatalen = keydatalen;
441   
442   rc = assuan_transact (agent_ctx, line, NULL, NULL,
443                         inq_writekey_parms, &parms, NULL, NULL);
444
445   return rc;
446 }
447
448
449
450 \f
451 /* Status callback for the SCD GENKEY command. */
452 static int
453 scd_genkey_cb (void *opaque, const char *line)
454 {
455   struct agent_card_genkey_s *parm = opaque;
456   const char *keyword = line;
457   int keywordlen;
458   gpg_error_t rc;
459
460   log_debug ("got status line `%s'\n", line);
461   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
462     ;
463   while (spacep (line))
464     line++;
465
466   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
467     {
468       parm->fprvalid = unhexify_fpr (line, parm->fpr);
469     }
470   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
471     {
472       gcry_mpi_t a;
473       const char *name = line;
474
475       while (*line && !spacep (line))
476         line++;
477       while (spacep (line))
478         line++;
479
480       rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
481       if (rc)
482         log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
483       else if (*name == 'n' && spacep (name+1))
484         parm->n = a;
485       else if (*name == 'e' && spacep (name+1))
486         parm->e = a;
487       else
488         {
489           log_info ("unknown parameter name in received key data\n");
490           gcry_mpi_release (a);
491         }
492     }
493   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
494     {
495       parm->created_at = (u32)strtoul (line, NULL, 10);
496     }
497
498   return 0;
499 }
500
501 /* Send a GENKEY command to the SCdaemon.  SERIALNO is not used in
502    this implementation.  If CREATEDATE has been given, it will be
503    passed to SCDAEMON so that the key can be created with this
504    timestamp; note the user needs to use the returned timestamp as old
505    versions of scddaemon don't support this option.  */
506 int
507 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
508                   const char *serialno, u32 createtime)
509 {
510   int rc;
511   char line[ASSUAN_LINELENGTH];
512   gnupg_isotime_t tbuf;
513
514   rc = start_agent ();
515   if (rc)
516     return rc;
517
518   if (createtime)
519     epoch2isotime (tbuf, createtime);
520   else
521     *tbuf = 0;
522
523   memset (info, 0, sizeof *info);
524   snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
525             *tbuf? "--timestamp=":"", tbuf,
526             force? "--force":"", 
527             keyno);
528   line[DIM(line)-1] = 0;
529
530   memset (info, 0, sizeof *info);
531   rc = assuan_transact (agent_ctx, line,
532                         NULL, NULL, NULL, NULL,
533                         scd_genkey_cb, info);
534   
535   return rc;
536 }
537
538 \f
539 static int
540 membuf_data_cb (void *opaque, const void *buffer, size_t length)
541 {
542   membuf_t *data = opaque;
543
544   if (buffer)
545     put_membuf (data, buffer, length);
546   return 0;
547 }
548   
549 /* Send a sign command to the scdaemon via gpg-agent's pass thru
550    mechanism. */
551 int
552 agent_scd_pksign (const char *serialno, int hashalgo,
553                   const unsigned char *indata, size_t indatalen,
554                   unsigned char **r_buf, size_t *r_buflen)
555 {
556   int rc, i;
557   char *p, line[ASSUAN_LINELENGTH];
558   membuf_t data;
559   size_t len;
560
561   /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
562
563   *r_buf = NULL;
564   *r_buflen = 0;
565
566   rc = start_agent ();
567   if (rc)
568     return rc;
569
570   if (indatalen*2 + 50 > DIM(line))
571     return gpg_error (GPG_ERR_GENERAL);
572
573   sprintf (line, "SCD SETDATA ");
574   p = line + strlen (line);
575   for (i=0; i < indatalen ; i++, p += 2 )
576     sprintf (p, "%02X", indata[i]);
577   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
578   if (rc)
579     return rc;
580
581   init_membuf (&data, 1024);
582 #if 0
583   if (!hashalgo) /* Temporary test hack. */
584     snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
585   else
586 #endif
587     snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
588               hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
589               serialno);
590   line[DIM(line)-1] = 0;
591   rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
592                         NULL, NULL, NULL, NULL);
593   if (rc)
594     {
595       xfree (get_membuf (&data, &len));
596       return rc;
597     }
598   *r_buf = get_membuf (&data, r_buflen);
599
600   return 0;
601 }
602
603
604 /* Decrypt INDATA of length INDATALEN using the card identified by
605    SERIALNO.  Return the plaintext in a nwly allocated buffer stored
606    at the address of R_BUF. 
607
608    Note, we currently support only RSA or more exactly algorithms
609    taking one input data element. */
610 int
611 agent_scd_pkdecrypt (const char *serialno,
612                      const unsigned char *indata, size_t indatalen,
613                      unsigned char **r_buf, size_t *r_buflen)
614 {
615   int rc, i;
616   char *p, line[ASSUAN_LINELENGTH];
617   membuf_t data;
618   size_t len;
619
620   *r_buf = NULL;
621   rc = start_agent ();
622   if (rc)
623     return rc;
624
625   /* FIXME: use secure memory where appropriate */
626   if (indatalen*2 + 50 > DIM(line))
627     return gpg_error (GPG_ERR_GENERAL);
628
629   sprintf (line, "SCD SETDATA ");
630   p = line + strlen (line);
631   for (i=0; i < indatalen ; i++, p += 2 )
632     sprintf (p, "%02X", indata[i]);
633   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
634   if (rc)
635     return rc;
636
637   init_membuf (&data, 1024);
638   snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
639   line[DIM(line)-1] = 0;
640   rc = assuan_transact (agent_ctx, line,
641                         membuf_data_cb, &data,
642                         NULL, NULL, NULL, NULL);
643   if (rc)
644     {
645       xfree (get_membuf (&data, &len));
646       return rc;
647     }
648   *r_buf = get_membuf (&data, r_buflen);
649   if (!*r_buf)
650     return gpg_error (GPG_ERR_ENOMEM);
651
652   return 0;
653 }
654
655
656 /* Change the PIN of an OpenPGP card or reset the retry counter.
657    CHVNO 1: Change the PIN
658          2: Same as 1
659          3: Change the admin PIN
660        101: Set a new PIN and reset the retry counter
661        102: Same as 101
662    SERIALNO is not used.
663  */
664 int
665 agent_scd_change_pin (int chvno, const char *serialno)
666 {
667   int rc;
668   char line[ASSUAN_LINELENGTH];
669   const char *reset = "";
670
671   if (chvno >= 100)
672     reset = "--reset";
673   chvno %= 100;
674
675   rc = start_agent ();
676   if (rc)
677     return rc;
678
679   snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
680   line[DIM(line)-1] = 0;
681   rc = assuan_transact (agent_ctx, line, NULL, NULL,
682                         NULL, NULL, NULL, NULL);
683   return rc;
684 }
685
686
687 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
688    number of the card - optionally followed by the fingerprint;
689    however the fingerprint is ignored here. */
690 int
691 agent_scd_checkpin  (const char *serialno)
692 {
693   int rc;
694   char line[ASSUAN_LINELENGTH];
695
696   rc = start_agent ();
697   if (rc)
698     return rc;
699
700   snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
701   line[DIM(line)-1] = 0;
702   return assuan_transact (agent_ctx, line,
703                           NULL, NULL,
704                           NULL, NULL, NULL, NULL);
705 }
706
707
708 /* Dummy function, only used by the gpg 1.4 implementation. */
709 void
710 agent_clear_pin_cache (const char *sn)
711 {
712
713 }
714
715
716
717 \f
718 /* Note: All strings shall be UTF-8. On success the caller needs to
719    free the string stored at R_PASSPHRASE. On error NULL will be
720    stored at R_PASSPHRASE and an appropriate fpf error code
721    returned. */
722 gpg_error_t
723 agent_get_passphrase (const char *cache_id,
724                       const char *err_msg,
725                       const char *prompt,
726                       const char *desc_msg,
727                       char **r_passphrase)
728 {
729   int rc;
730   char *line, *p;
731   char cmd[] = "GET_PASSPHRASE --data -- ";
732   membuf_t data;
733
734   *r_passphrase = NULL;
735
736   rc = start_agent ();
737   if (rc)
738     return rc;
739
740   /* We allocate 3 times the needed space for the texts so that
741      there is enough space for escaping. */
742   line = xtrymalloc ( strlen (cmd) + 1
743                       + (cache_id? 3*strlen (cache_id): 1) + 1
744                       + (err_msg?  3*strlen (err_msg): 1) + 1
745                       + (prompt?   3*strlen (prompt): 1) + 1
746                       + (desc_msg? 3*strlen (desc_msg): 1) + 1
747                       + 1);
748   if (!line)
749     return gpg_error_from_syserror ();
750
751   p = stpcpy (line, cmd);
752   if (cache_id && *cache_id)
753     p = percent_plus_escape (p, cache_id);
754   else
755     *p++ = 'X';
756   *p++ = ' ';
757
758   if (err_msg && *err_msg)
759     p = percent_plus_escape (p, err_msg);
760   else
761     *p++ = 'X';
762   *p++ = ' ';
763
764   if (prompt && *prompt)
765     p = percent_plus_escape (p, prompt);
766   else
767     *p++ = 'X'; 
768   *p++ = ' ';
769
770   if (desc_msg && *desc_msg)
771     p = percent_plus_escape (p, desc_msg);
772   else
773     *p++ = 'X';
774   *p = 0;
775
776   init_membuf_secure (&data, 64);
777   rc = assuan_transact (agent_ctx, line, 
778                         membuf_data_cb, &data, NULL, NULL, NULL, NULL);
779
780   if (rc)
781     xfree (get_membuf (&data, NULL));
782   else 
783     {
784       put_membuf (&data, "", 1);
785       *r_passphrase = get_membuf (&data, NULL);
786       if (!*r_passphrase)
787         rc = gpg_error_from_syserror ();
788     }
789   xfree (line);
790   return rc;
791 }
792
793
794 gpg_error_t
795 agent_clear_passphrase (const char *cache_id)
796 {
797   int rc;
798   char line[ASSUAN_LINELENGTH];
799
800   if (!cache_id || !*cache_id)
801     return 0;
802
803   rc = start_agent ();
804   if (rc)
805     return rc;
806
807   snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
808   line[DIM(line)-1] = 0;
809   return assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
810 }