1 /* call-agent.c - divert operations to the agent
2 * Copyright (C) 2001, 2002, 2003, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
39 #include "keydb.h" /* fixme: Move this to import.c */
40 #include "../common/membuf.h"
43 static assuan_context_t agent_ctx
= NULL
;
44 static int force_pipe_server
= 0;
49 const unsigned char *ciphertext
;
56 const unsigned char *sexp
;
69 /* Try to connect to the agent via socket or fork it off and work by
70 pipes. Handle the server's initial greeting */
72 start_agent (ctrl_t ctrl
)
79 return 0; /* fixme: We need a context for each thread or serialize
80 the access to the agent (which is suitable given that
81 the agent is not MT. */
83 infostr
= force_pipe_server
? NULL
: getenv ("GPG_AGENT_INFO");
84 if (!infostr
|| !*infostr
)
92 /* First check whether we can connect at the standard
94 sockname
= make_filename (opt
.homedir
, "S.gpg-agent", NULL
);
95 rc
= assuan_socket_connect (&ctx
, sockname
, 0);
100 /* With no success start a new server. */
102 log_info (_("no running gpg-agent - starting one\n"));
104 gpgsm_status (ctrl
, STATUS_PROGRESS
, "starting_agent ? 0 0");
108 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
109 log_error ("error flushing pending output: %s\n",
114 if (!opt
.agent_program
|| !*opt
.agent_program
)
115 opt
.agent_program
= GNUPG_DEFAULT_AGENT
;
116 if ( !(pgmname
= strrchr (opt
.agent_program
, '/')))
117 pgmname
= opt
.agent_program
;
122 argv
[1] = "--server";
126 if (log_get_fd () != -1)
127 no_close_list
[i
++] = log_get_fd ();
128 no_close_list
[i
++] = fileno (stderr
);
129 no_close_list
[i
] = -1;
131 /* Connect to the agent and perform initial handshaking. */
132 rc
= assuan_pipe_connect (&ctx
, opt
.agent_program
, argv
,
141 infostr
= xstrdup (infostr
);
142 if ( !(p
= strchr (infostr
, PATHSEP_C
)) || p
== infostr
)
144 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
146 force_pipe_server
= 1;
147 return start_agent (ctrl
);
151 while (*p
&& *p
!= PATHSEP_C
)
153 prot
= *p
? atoi (p
+1) : 0;
156 log_error (_("gpg-agent protocol version %d is not supported\n"),
159 force_pipe_server
= 1;
160 return start_agent (ctrl
);
163 rc
= assuan_socket_connect (&ctx
, infostr
, pid
);
165 if (gpg_err_code (rc
) == GPG_ERR_ASS_CONNECT_FAILED
)
167 log_error (_("can't connect to the agent - trying fall back\n"));
168 force_pipe_server
= 1;
169 return start_agent (ctrl
);
175 log_error ("can't connect to the agent: %s\n", gpg_strerror (rc
));
176 return gpg_error (GPG_ERR_NO_AGENT
);
181 log_debug ("connection to agent established\n");
183 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
187 return send_pinentry_environment (agent_ctx
, GPG_ERR_SOURCE_DEFAULT
,
188 opt
.display
, opt
.ttyname
, opt
.ttytype
,
189 opt
.lc_ctype
, opt
.lc_messages
);
194 membuf_data_cb (void *opaque
, const void *buffer
, size_t length
)
196 membuf_t
*data
= opaque
;
199 put_membuf (data
, buffer
, length
);
206 /* Call the agent to do a sign operation using the key identified by
207 the hex string KEYGRIP. */
209 gpgsm_agent_pksign (ctrl_t ctrl
, const char *keygrip
, const char *desc
,
210 unsigned char *digest
, size_t digestlen
, int digestalgo
,
211 unsigned char **r_buf
, size_t *r_buflen
)
214 char *p
, line
[ASSUAN_LINELENGTH
];
219 rc
= start_agent (ctrl
);
223 if (digestlen
*2 + 50 > DIM(line
))
224 return gpg_error (GPG_ERR_GENERAL
);
226 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
230 snprintf (line
, DIM(line
)-1, "SIGKEY %s", keygrip
);
231 line
[DIM(line
)-1] = 0;
232 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
238 snprintf (line
, DIM(line
)-1, "SETKEYDESC %s", desc
);
239 line
[DIM(line
)-1] = 0;
240 rc
= assuan_transact (agent_ctx
, line
,
241 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
246 sprintf (line
, "SETHASH %d ", digestalgo
);
247 p
= line
+ strlen (line
);
248 for (i
=0; i
< digestlen
; i
++, p
+= 2 )
249 sprintf (p
, "%02X", digest
[i
]);
250 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
254 init_membuf (&data
, 1024);
255 rc
= assuan_transact (agent_ctx
, "PKSIGN",
256 membuf_data_cb
, &data
, NULL
, NULL
, NULL
, NULL
);
259 xfree (get_membuf (&data
, &len
));
262 *r_buf
= get_membuf (&data
, r_buflen
);
264 if (!gcry_sexp_canon_len (*r_buf
, *r_buflen
, NULL
, NULL
))
266 xfree (*r_buf
); *r_buf
= NULL
;
267 return gpg_error (GPG_ERR_INV_VALUE
);
270 return *r_buf
? 0 : out_of_core ();
276 /* Handle a CIPHERTEXT inquiry. Note, we only send the data,
277 assuan_transact talkes care of flushing and writing the end */
279 inq_ciphertext_cb (void *opaque
, const char *keyword
)
281 struct cipher_parm_s
*parm
= opaque
;
284 assuan_begin_confidential (parm
->ctx
);
285 rc
= assuan_send_data (parm
->ctx
, parm
->ciphertext
, parm
->ciphertextlen
);
286 assuan_end_confidential (parm
->ctx
);
291 /* Call the agent to do a decrypt operation using the key identified by
292 the hex string KEYGRIP. */
294 gpgsm_agent_pkdecrypt (ctrl_t ctrl
, const char *keygrip
, const char *desc
,
295 ksba_const_sexp_t ciphertext
,
296 char **r_buf
, size_t *r_buflen
)
299 char line
[ASSUAN_LINELENGTH
];
301 struct cipher_parm_s cipher_parm
;
303 char *p
, *buf
, *endp
;
304 size_t ciphertextlen
;
306 if (!keygrip
|| strlen(keygrip
) != 40 || !ciphertext
|| !r_buf
|| !r_buflen
)
307 return gpg_error (GPG_ERR_INV_VALUE
);
310 ciphertextlen
= gcry_sexp_canon_len (ciphertext
, 0, NULL
, NULL
);
312 return gpg_error (GPG_ERR_INV_VALUE
);
314 rc
= start_agent (ctrl
);
318 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
322 assert ( DIM(line
) >= 50 );
323 snprintf (line
, DIM(line
)-1, "SETKEY %s", keygrip
);
324 line
[DIM(line
)-1] = 0;
325 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
331 snprintf (line
, DIM(line
)-1, "SETKEYDESC %s", desc
);
332 line
[DIM(line
)-1] = 0;
333 rc
= assuan_transact (agent_ctx
, line
,
334 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
339 init_membuf (&data
, 1024);
340 cipher_parm
.ctx
= agent_ctx
;
341 cipher_parm
.ciphertext
= ciphertext
;
342 cipher_parm
.ciphertextlen
= ciphertextlen
;
343 rc
= assuan_transact (agent_ctx
, "PKDECRYPT",
344 membuf_data_cb
, &data
,
345 inq_ciphertext_cb
, &cipher_parm
, NULL
, NULL
);
348 xfree (get_membuf (&data
, &len
));
352 put_membuf (&data
, "", 1); /* Make sure it is 0 terminated. */
353 buf
= get_membuf (&data
, &len
);
355 return gpg_error (GPG_ERR_ENOMEM
);
356 assert (len
); /* (we forced Nul termination.) */
360 if (len
< 13 || memcmp (buf
, "(5:value", 8) ) /* "(5:valueN:D)\0" */
361 return gpg_error (GPG_ERR_INV_SEXP
);
362 len
-= 11; /* Count only the data of the second part. */
363 p
= buf
+ 8; /* Skip leading parenthesis and the value tag. */
367 /* For compatibility with older gpg-agents handle the old style
368 incomplete S-exps. */
369 len
--; /* Do not count the Nul. */
373 n
= strtoul (p
, &endp
, 10);
374 if (!n
|| *endp
!= ':')
375 return gpg_error (GPG_ERR_INV_SEXP
);
378 return gpg_error (GPG_ERR_INV_SEXP
); /* Oops: Inconsistent S-Exp. */
380 memmove (buf
, endp
, n
);
391 /* Handle a KEYPARMS inquiry. Note, we only send the data,
392 assuan_transact takes care of flushing and writing the end */
394 inq_genkey_parms (void *opaque
, const char *keyword
)
396 struct genkey_parm_s
*parm
= opaque
;
399 rc
= assuan_send_data (parm
->ctx
, parm
->sexp
, parm
->sexplen
);
405 /* Call the agent to generate a newkey */
407 gpgsm_agent_genkey (ctrl_t ctrl
,
408 ksba_const_sexp_t keyparms
, ksba_sexp_t
*r_pubkey
)
411 struct genkey_parm_s gk_parm
;
417 rc
= start_agent (ctrl
);
421 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
425 init_membuf (&data
, 1024);
426 gk_parm
.ctx
= agent_ctx
;
427 gk_parm
.sexp
= keyparms
;
428 gk_parm
.sexplen
= gcry_sexp_canon_len (keyparms
, 0, NULL
, NULL
);
429 if (!gk_parm
.sexplen
)
430 return gpg_error (GPG_ERR_INV_VALUE
);
431 rc
= assuan_transact (agent_ctx
, "GENKEY",
432 membuf_data_cb
, &data
,
433 inq_genkey_parms
, &gk_parm
, NULL
, NULL
);
436 xfree (get_membuf (&data
, &len
));
439 buf
= get_membuf (&data
, &len
);
441 return gpg_error (GPG_ERR_ENOMEM
);
442 if (!gcry_sexp_canon_len (buf
, len
, NULL
, NULL
))
445 return gpg_error (GPG_ERR_INV_SEXP
);
452 /* Call the agent to read the public key part for a given keygrip. */
454 gpgsm_agent_readkey (ctrl_t ctrl
, const char *hexkeygrip
,
455 ksba_sexp_t
*r_pubkey
)
461 char line
[ASSUAN_LINELENGTH
];
464 rc
= start_agent (ctrl
);
468 rc
= assuan_transact (agent_ctx
, "RESET",NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
472 snprintf (line
, DIM(line
)-1, "READKEY %s", hexkeygrip
);
473 line
[DIM(line
)-1] = 0;
475 init_membuf (&data
, 1024);
476 rc
= assuan_transact (agent_ctx
, line
,
477 membuf_data_cb
, &data
,
478 NULL
, NULL
, NULL
, NULL
);
481 xfree (get_membuf (&data
, &len
));
484 buf
= get_membuf (&data
, &len
);
486 return gpg_error (GPG_ERR_ENOMEM
);
487 if (!gcry_sexp_canon_len (buf
, len
, NULL
, NULL
))
490 return gpg_error (GPG_ERR_INV_SEXP
);
497 /* Ask the agent whether the certificate is in the list of trusted
500 gpgsm_agent_istrusted (ctrl_t ctrl
, ksba_cert_t cert
)
504 char line
[ASSUAN_LINELENGTH
];
506 rc
= start_agent (ctrl
);
510 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
513 log_error ("error getting the fingerprint\n");
514 return gpg_error (GPG_ERR_GENERAL
);
517 snprintf (line
, DIM(line
)-1, "ISTRUSTED %s", fpr
);
518 line
[DIM(line
)-1] = 0;
521 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
525 /* Ask the agent to mark CERT as a trusted Root-CA one */
527 gpgsm_agent_marktrusted (ctrl_t ctrl
, ksba_cert_t cert
)
531 char line
[ASSUAN_LINELENGTH
];
533 rc
= start_agent (ctrl
);
537 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
540 log_error ("error getting the fingerprint\n");
541 return gpg_error (GPG_ERR_GENERAL
);
544 dn
= ksba_cert_get_issuer (cert
, 0);
548 return gpg_error (GPG_ERR_GENERAL
);
550 snprintf (line
, DIM(line
)-1, "MARKTRUSTED %s S %s", fpr
, dn
);
551 line
[DIM(line
)-1] = 0;
555 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
561 /* Ask the agent whether the a corresponding secret key is available
562 for the given keygrip */
564 gpgsm_agent_havekey (ctrl_t ctrl
, const char *hexkeygrip
)
567 char line
[ASSUAN_LINELENGTH
];
569 rc
= start_agent (ctrl
);
573 if (!hexkeygrip
|| strlen (hexkeygrip
) != 40)
574 return gpg_error (GPG_ERR_INV_VALUE
);
576 snprintf (line
, DIM(line
)-1, "HAVEKEY %s", hexkeygrip
);
577 line
[DIM(line
)-1] = 0;
579 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
585 learn_cb (void *opaque
, const void *buffer
, size_t length
)
587 struct learn_parm_s
*parm
= opaque
;
598 put_membuf (parm
->data
, buffer
, length
);
601 /* END encountered - process what we have */
602 buf
= get_membuf (parm
->data
, &len
);
605 parm
->error
= gpg_error (GPG_ERR_ENOMEM
);
610 /* FIXME: this should go into import.c */
611 rc
= ksba_cert_new (&cert
);
617 rc
= ksba_cert_init_from_mem (cert
, buf
, len
);
620 log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc
));
621 ksba_cert_release (cert
);
626 rc
= gpgsm_basic_cert_check (cert
);
627 if (gpg_err_code (rc
) == GPG_ERR_MISSING_CERT
)
628 { /* For later use we store it in the ephemeral database. */
629 log_info ("issuer certificate missing - storing as ephemeral\n");
630 keydb_store_cert (cert
, 1, NULL
);
633 log_error ("invalid certificate: %s\n", gpg_strerror (rc
));
638 if (!keydb_store_cert (cert
, 0, &existed
))
640 if (opt
.verbose
> 1 && existed
)
641 log_info ("certificate already in DB\n");
642 else if (opt
.verbose
&& !existed
)
643 log_info ("certificate imported\n");
647 ksba_cert_release (cert
);
648 init_membuf (parm
->data
, 4096);
652 /* Call the agent to learn about a smartcard */
654 gpgsm_agent_learn (ctrl_t ctrl
)
657 struct learn_parm_s learn_parm
;
661 rc
= start_agent (ctrl
);
665 init_membuf (&data
, 4096);
666 learn_parm
.error
= 0;
667 learn_parm
.ctx
= agent_ctx
;
668 learn_parm
.data
= &data
;
669 rc
= assuan_transact (agent_ctx
, "LEARN --send",
670 learn_cb
, &learn_parm
,
671 NULL
, NULL
, NULL
, NULL
);
672 xfree (get_membuf (&data
, &len
));
675 return learn_parm
.error
;
679 /* Ask the agent to change the passphrase of the key identified by
680 HEXKEYGRIP. If DESC is not NULL, display instead of the default
681 description message. */
683 gpgsm_agent_passwd (ctrl_t ctrl
, const char *hexkeygrip
, const char *desc
)
686 char line
[ASSUAN_LINELENGTH
];
688 rc
= start_agent (ctrl
);
692 if (!hexkeygrip
|| strlen (hexkeygrip
) != 40)
693 return gpg_error (GPG_ERR_INV_VALUE
);
697 snprintf (line
, DIM(line
)-1, "SETKEYDESC %s", desc
);
698 line
[DIM(line
)-1] = 0;
699 rc
= assuan_transact (agent_ctx
, line
,
700 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
705 snprintf (line
, DIM(line
)-1, "PASSWD %s", hexkeygrip
);
706 line
[DIM(line
)-1] = 0;
708 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
714 /* Ask the agent to pop up a confirmation dialog with the text DESC
715 and an okay and cancel button. */
717 gpgsm_agent_get_confirmation (ctrl_t ctrl
, const char *desc
)
720 char line
[ASSUAN_LINELENGTH
];
722 rc
= start_agent (ctrl
);
726 snprintf (line
, DIM(line
)-1, "GET_CONFIRMATION %s", desc
);
727 line
[DIM(line
)-1] = 0;
729 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);