1 /* call-agent.c - divert operations to the agent
2 * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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 2 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
35 #include "../assuan/assuan.h"
37 #include "keydb.h" /* fixme: Move this to import.c */
39 static ASSUAN_CONTEXT agent_ctx
= NULL
;
40 static int force_pipe_server
= 0;
42 struct cipher_parm_s
{
44 const char *ciphertext
;
48 struct genkey_parm_s
{
69 /* A simple implemnation of a dynamic buffer. Use init_membuf() to
70 create a buffer, put_membuf to append bytes and get_membuf to
71 release and return the buffer. Allocation errors are detected but
72 only returned at the final get_membuf(), this helps not to clutter
73 the code with out of core checks. */
76 init_membuf (struct membuf
*mb
, int initiallen
)
79 mb
->size
= initiallen
;
81 mb
->buf
= xtrymalloc (initiallen
);
87 put_membuf (struct membuf
*mb
, const void *buf
, size_t len
)
92 if (mb
->len
+ len
>= mb
->size
)
96 mb
->size
+= len
+ 1024;
97 p
= xtryrealloc (mb
->buf
, mb
->size
);
105 memcpy (mb
->buf
+ mb
->len
, buf
, len
);
110 get_membuf (struct membuf
*mb
, size_t *len
)
124 mb
->out_of_core
= 1; /* don't allow a reuse */
130 /* Try to connect to the agent via socket or fork it off and work by
131 pipes. Handle the server's initial greeting */
138 char *dft_display
= NULL
;
139 char *dft_ttyname
= NULL
;
140 char *dft_ttytype
= NULL
;
145 return 0; /* fixme: We need a context for each thread or serialize
146 the access to the agent (which is suitable given that
147 the agent is not MT */
149 infostr
= force_pipe_server
? NULL
: getenv ("GPG_AGENT_INFO");
154 log_info (_("no running gpg-agent - starting one\n"));
158 log_error ("error flushing pending output: %s\n", strerror (errno
));
159 return seterr (Write_Error
);
162 if (!opt
.agent_program
|| !*opt
.agent_program
)
163 opt
.agent_program
= "../agent/gpg-agent";
164 if ( !(pgmname
= strrchr (opt
.agent_program
, '/')))
165 pgmname
= opt
.agent_program
;
170 argv
[1] = "--server";
173 /* connect to the agent and perform initial handshaking */
174 rc
= assuan_pipe_connect (&ctx
, opt
.agent_program
, (char**)argv
, 0);
181 infostr
= xstrdup (infostr
);
182 if ( !(p
= strchr (infostr
, ':')) || p
== infostr
)
184 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
186 force_pipe_server
= 1;
187 return start_agent ();
191 while (*p
&& *p
!= ':')
193 prot
= *p
? atoi (p
+1) : 0;
196 log_error (_("gpg-agent protocol version %d is not supported\n"),
199 force_pipe_server
= 1;
200 return start_agent ();
203 rc
= assuan_socket_connect (&ctx
, infostr
, pid
);
205 if (rc
== ASSUAN_Connect_Failed
)
207 log_error (_("can't connect to the agent - trying fall back\n"));
208 force_pipe_server
= 1;
209 return start_agent ();
215 log_error ("can't connect to the agent: %s\n", assuan_strerror (rc
));
216 return seterr (No_Agent
);
221 log_debug ("connection to agent established\n");
223 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
225 return map_assuan_err (rc
);
227 dft_display
= getenv ("DISPLAY");
228 if (opt
.display
|| dft_display
)
231 if (asprintf (&optstr
, "OPTION display=%s",
232 opt
.display
? opt
.display
: dft_display
) < 0)
233 return GNUPG_Out_Of_Core
;
234 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
238 return map_assuan_err (rc
);
240 if (!opt
.ttyname
&& ttyname (1))
241 dft_ttyname
= ttyname (1);
242 if (opt
.ttyname
|| dft_ttyname
)
245 if (asprintf (&optstr
, "OPTION ttyname=%s",
246 opt
.ttyname
? opt
.ttyname
: dft_ttyname
) < 0)
247 return GNUPG_Out_Of_Core
;
248 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
252 return map_assuan_err (rc
);
254 dft_ttytype
= getenv ("TERM");
255 if (!rc
&& (opt
.ttytype
|| (dft_ttyname
&& dft_ttytype
)))
258 if (asprintf (&optstr
, "OPTION ttytype=%s",
259 opt
.ttyname
? opt
.ttytype
: dft_ttytype
) < 0)
260 return GNUPG_Out_Of_Core
;
261 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
265 return map_assuan_err (rc
);
268 old_lc
= setlocale (LC_CTYPE
, NULL
);
269 dft_lc
= setlocale (LC_CTYPE
, "");
271 if (!rc
&& (opt
.lc_ctype
|| (dft_ttyname
&& dft_lc
)))
274 if (asprintf (&optstr
, "OPTION lc-ctype=%s",
275 opt
.lc_ctype
? opt
.lc_ctype
: dft_lc
) < 0)
276 return GNUPG_Out_Of_Core
;
277 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
281 return map_assuan_err (rc
);
285 setlocale (LC_CTYPE
, old_lc
);
288 old_lc
= setlocale (LC_MESSAGES
, NULL
);
289 dft_lc
= setlocale (LC_MESSAGES
, "");
291 if (!rc
&& (opt
.lc_messages
|| (dft_ttyname
&& dft_lc
)))
294 if (asprintf (&optstr
, "OPTION lc-messages=%s",
295 opt
.lc_messages
? opt
.lc_messages
: dft_lc
) < 0)
296 return GNUPG_Out_Of_Core
;
297 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
301 return map_assuan_err (rc
);
305 setlocale (LC_MESSAGES
, old_lc
);
313 membuf_data_cb (void *opaque
, const void *buffer
, size_t length
)
315 struct membuf
*data
= opaque
;
318 put_membuf (data
, buffer
, length
);
325 /* Call the agent to do a sign operation using the key identified by
326 the hex string KEYGRIP. */
328 gpgsm_agent_pksign (const char *keygrip
,
329 unsigned char *digest
, size_t digestlen
, int digestalgo
,
330 char **r_buf
, size_t *r_buflen
)
333 char *p
, line
[ASSUAN_LINELENGTH
];
342 if (digestlen
*2 + 50 > DIM(line
))
343 return seterr (General_Error
);
345 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
347 return map_assuan_err (rc
);
349 snprintf (line
, DIM(line
)-1, "SIGKEY %s", keygrip
);
350 line
[DIM(line
)-1] = 0;
351 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
353 return map_assuan_err (rc
);
355 sprintf (line
, "SETHASH %d ", digestalgo
);
356 p
= line
+ strlen (line
);
357 for (i
=0; i
< digestlen
; i
++, p
+= 2 )
358 sprintf (p
, "%02X", digest
[i
]);
359 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
361 return map_assuan_err (rc
);
363 init_membuf (&data
, 1024);
364 rc
= assuan_transact (agent_ctx
, "PKSIGN",
365 membuf_data_cb
, &data
, NULL
, NULL
, NULL
, NULL
);
368 xfree (get_membuf (&data
, &len
));
369 return map_assuan_err (rc
);
371 *r_buf
= get_membuf (&data
, r_buflen
);
373 if (!gcry_sexp_canon_len (*r_buf
, *r_buflen
, NULL
, NULL
))
375 xfree (*r_buf
); *r_buf
= NULL
;
376 return GNUPG_Invalid_Value
;
379 return *r_buf
? 0 : GNUPG_Out_Of_Core
;
385 /* Handle a CIPHERTEXT inquiry. Note, we only send the data,
386 assuan_transact talkes care of flushing and writing the end */
388 inq_ciphertext_cb (void *opaque
, const char *keyword
)
390 struct cipher_parm_s
*parm
= opaque
;
393 assuan_begin_confidential (parm
->ctx
);
394 rc
= assuan_send_data (parm
->ctx
, parm
->ciphertext
, parm
->ciphertextlen
);
395 assuan_end_confidential (parm
->ctx
);
400 /* Call the agent to do a decrypt operation using the key identified by
401 the hex string KEYGRIP. */
403 gpgsm_agent_pkdecrypt (const char *keygrip
,
404 KsbaConstSexp ciphertext
,
405 char **r_buf
, size_t *r_buflen
)
408 char line
[ASSUAN_LINELENGTH
];
410 struct cipher_parm_s cipher_parm
;
413 size_t ciphertextlen
;
415 if (!keygrip
|| strlen(keygrip
) != 40 || !ciphertext
|| !r_buf
|| !r_buflen
)
416 return GNUPG_Invalid_Value
;
419 ciphertextlen
= gcry_sexp_canon_len (ciphertext
, 0, NULL
, NULL
);
421 return GNUPG_Invalid_Value
;
427 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
429 return map_assuan_err (rc
);
431 assert ( DIM(line
) >= 50 );
432 snprintf (line
, DIM(line
)-1, "SETKEY %s", keygrip
);
433 line
[DIM(line
)-1] = 0;
434 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
436 return map_assuan_err (rc
);
438 init_membuf (&data
, 1024);
439 cipher_parm
.ctx
= agent_ctx
;
440 cipher_parm
.ciphertext
= ciphertext
;
441 cipher_parm
.ciphertextlen
= ciphertextlen
;
442 rc
= assuan_transact (agent_ctx
, "PKDECRYPT",
443 membuf_data_cb
, &data
,
444 inq_ciphertext_cb
, &cipher_parm
, NULL
, NULL
);
447 xfree (get_membuf (&data
, &len
));
448 return map_assuan_err (rc
);
451 put_membuf (&data
, "", 1); /* make sure it is 0 terminated */
452 buf
= get_membuf (&data
, &len
);
454 return seterr (Out_Of_Core
);
455 /* FIXME: We would better a return a full S-exp and not just a part */
457 len
--; /* remove the terminating 0 */
458 n
= strtoul (buf
, &endp
, 10);
459 if (!n
|| *endp
!= ':')
460 return seterr (Invalid_Sexp
);
462 if (endp
-buf
+n
> len
)
463 return seterr (Invalid_Sexp
); /* oops len does not match internal len*/
464 memmove (buf
, endp
, n
);
474 /* Handle a KEYPARMS inquiry. Note, we only send the data,
475 assuan_transact takes care of flushing and writing the end */
477 inq_genkey_parms (void *opaque
, const char *keyword
)
479 struct genkey_parm_s
*parm
= opaque
;
482 rc
= assuan_send_data (parm
->ctx
, parm
->sexp
, parm
->sexplen
);
488 /* Call the agent to generate a newkey */
490 gpgsm_agent_genkey (KsbaConstSexp keyparms
, KsbaSexp
*r_pubkey
)
493 struct genkey_parm_s gk_parm
;
503 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
505 return map_assuan_err (rc
);
507 init_membuf (&data
, 1024);
508 gk_parm
.ctx
= agent_ctx
;
509 gk_parm
.sexp
= keyparms
;
510 gk_parm
.sexplen
= gcry_sexp_canon_len (keyparms
, 0, NULL
, NULL
);
511 if (!gk_parm
.sexplen
)
512 return GNUPG_Invalid_Value
;
513 rc
= assuan_transact (agent_ctx
, "GENKEY",
514 membuf_data_cb
, &data
,
515 inq_genkey_parms
, &gk_parm
, NULL
, NULL
);
518 xfree (get_membuf (&data
, &len
));
519 return map_assuan_err (rc
);
521 buf
= get_membuf (&data
, &len
);
523 return GNUPG_Out_Of_Core
;
524 if (!gcry_sexp_canon_len (buf
, len
, NULL
, NULL
))
527 return GNUPG_Invalid_Sexp
;
534 /* Ask the agent whether the certificate is in the list of trusted
537 gpgsm_agent_istrusted (KsbaCert cert
)
541 char line
[ASSUAN_LINELENGTH
];
547 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
550 log_error ("error getting the fingerprint\n");
551 return seterr (General_Error
);
554 snprintf (line
, DIM(line
)-1, "ISTRUSTED %s", fpr
);
555 line
[DIM(line
)-1] = 0;
558 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
559 return map_assuan_err (rc
);
562 /* Ask the agent to mark CERT as a trusted Root-CA one */
564 gpgsm_agent_marktrusted (KsbaCert cert
)
568 char line
[ASSUAN_LINELENGTH
];
574 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
577 log_error ("error getting the fingerprint\n");
578 return seterr (General_Error
);
581 dn
= ksba_cert_get_issuer (cert
, 0);
585 return seterr (General_Error
);
587 snprintf (line
, DIM(line
)-1, "MARKTRUSTED %s S %s", fpr
, dn
);
588 line
[DIM(line
)-1] = 0;
592 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
593 return map_assuan_err (rc
);
598 /* Ask the agent whether the a corresponding secret key is available
599 for the given keygrip */
601 gpgsm_agent_havekey (const char *hexkeygrip
)
604 char line
[ASSUAN_LINELENGTH
];
610 if (!hexkeygrip
|| strlen (hexkeygrip
) != 40)
611 return GNUPG_Invalid_Value
;
613 snprintf (line
, DIM(line
)-1, "HAVEKEY %s", hexkeygrip
);
614 line
[DIM(line
)-1] = 0;
616 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
617 return map_assuan_err (rc
);
622 learn_cb (void *opaque
, const void *buffer
, size_t length
)
624 struct learn_parm_s
*parm
= opaque
;
635 put_membuf (parm
->data
, buffer
, length
);
638 /* END encountered - process what we have */
639 buf
= get_membuf (parm
->data
, &len
);
642 parm
->error
= GNUPG_Out_Of_Core
;
647 /* FIXME: this should go into import.c */
648 cert
= ksba_cert_new ();
651 parm
->error
= GNUPG_Out_Of_Core
;
654 rc
= ksba_cert_init_from_mem (cert
, buf
, len
);
657 log_error ("failed to parse a certificate: %s\n", ksba_strerror (rc
));
658 ksba_cert_release (cert
);
659 parm
->error
= map_ksba_err (rc
);
663 rc
= gpgsm_basic_cert_check (cert
);
665 log_error ("invalid certificate: %s\n", gnupg_strerror (rc
));
668 if (!keydb_store_cert (cert
))
669 log_error ("certificate imported\n");
672 ksba_cert_release (cert
);
673 init_membuf (parm
->data
, 4096);
677 /* Call the agent to learn about a smartcard */
682 struct learn_parm_s learn_parm
;
690 init_membuf (&data
, 4096);
691 learn_parm
.error
= 0;
692 learn_parm
.ctx
= agent_ctx
;
693 learn_parm
.data
= &data
;
694 rc
= assuan_transact (agent_ctx
, "LEARN --send",
695 learn_cb
, &learn_parm
,
696 NULL
, NULL
, NULL
, NULL
);
697 xfree (get_membuf (&data
, &len
));
699 return map_assuan_err (rc
);
700 return learn_parm
.error
;