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 ();
274 /* Call the scdaemon to do a sign operation using the key identified by
275 the hex string KEYID. */
277 gpgsm_scd_pksign (ctrl_t ctrl
, const char *keyid
, const char *desc
,
278 unsigned char *digest
, size_t digestlen
, int digestalgo
,
279 unsigned char **r_buf
, size_t *r_buflen
)
282 char *p
, line
[ASSUAN_LINELENGTH
];
286 unsigned char *sigbuf
;
293 case GCRY_MD_SHA1
: hashopt
= "--hash=sha1"; break;
294 case GCRY_MD_RMD160
:hashopt
= "--hash=rmd160"; break;
295 case GCRY_MD_MD5
: hashopt
= "--hash=md5"; break;
296 case GCRY_MD_SHA256
:hashopt
= "--hash=sha256"; break;
298 return gpg_error (GPG_ERR_DIGEST_ALGO
);
301 rc
= start_agent (ctrl
);
305 if (digestlen
*2 + 50 > DIM(line
))
306 return gpg_error (GPG_ERR_GENERAL
);
308 p
= stpcpy (line
, "SCD SETDATA " );
309 for (i
=0; i
< digestlen
; i
++, p
+= 2 )
310 sprintf (p
, "%02X", digest
[i
]);
311 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
315 init_membuf (&data
, 1024);
317 snprintf (line
, DIM(line
)-1, "SCD PKSIGN %s %s", hashopt
, keyid
);
318 line
[DIM(line
)-1] = 0;
319 rc
= assuan_transact (agent_ctx
, line
,
320 membuf_data_cb
, &data
, NULL
, NULL
, NULL
, NULL
);
323 xfree (get_membuf (&data
, &len
));
326 sigbuf
= get_membuf (&data
, &sigbuflen
);
328 /* Create an S-expression from it which is formatted like this:
329 "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" Fixme: If a card ever
330 creates non-RSA keys we need to change things. */
331 *r_buflen
= 21 + 11 + sigbuflen
+ 4;
332 p
= xtrymalloc (*r_buflen
);
333 *r_buf
= (unsigned char*)p
;
339 p
= stpcpy (p
, "(7:sig-val(3:rsa(1:s" );
340 sprintf (p
, "%u:", (unsigned int)sigbuflen
);
342 memcpy (p
, sigbuf
, sigbuflen
);
347 assert (gcry_sexp_canon_len (*r_buf
, *r_buflen
, NULL
, NULL
));
354 /* Handle a CIPHERTEXT inquiry. Note, we only send the data,
355 assuan_transact talkes care of flushing and writing the end */
357 inq_ciphertext_cb (void *opaque
, const char *keyword
)
359 struct cipher_parm_s
*parm
= opaque
;
362 assuan_begin_confidential (parm
->ctx
);
363 rc
= assuan_send_data (parm
->ctx
, parm
->ciphertext
, parm
->ciphertextlen
);
364 assuan_end_confidential (parm
->ctx
);
369 /* Call the agent to do a decrypt operation using the key identified by
370 the hex string KEYGRIP. */
372 gpgsm_agent_pkdecrypt (ctrl_t ctrl
, const char *keygrip
, const char *desc
,
373 ksba_const_sexp_t ciphertext
,
374 char **r_buf
, size_t *r_buflen
)
377 char line
[ASSUAN_LINELENGTH
];
379 struct cipher_parm_s cipher_parm
;
381 char *p
, *buf
, *endp
;
382 size_t ciphertextlen
;
384 if (!keygrip
|| strlen(keygrip
) != 40 || !ciphertext
|| !r_buf
|| !r_buflen
)
385 return gpg_error (GPG_ERR_INV_VALUE
);
388 ciphertextlen
= gcry_sexp_canon_len (ciphertext
, 0, NULL
, NULL
);
390 return gpg_error (GPG_ERR_INV_VALUE
);
392 rc
= start_agent (ctrl
);
396 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
400 assert ( DIM(line
) >= 50 );
401 snprintf (line
, DIM(line
)-1, "SETKEY %s", keygrip
);
402 line
[DIM(line
)-1] = 0;
403 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
409 snprintf (line
, DIM(line
)-1, "SETKEYDESC %s", desc
);
410 line
[DIM(line
)-1] = 0;
411 rc
= assuan_transact (agent_ctx
, line
,
412 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
417 init_membuf (&data
, 1024);
418 cipher_parm
.ctx
= agent_ctx
;
419 cipher_parm
.ciphertext
= ciphertext
;
420 cipher_parm
.ciphertextlen
= ciphertextlen
;
421 rc
= assuan_transact (agent_ctx
, "PKDECRYPT",
422 membuf_data_cb
, &data
,
423 inq_ciphertext_cb
, &cipher_parm
, NULL
, NULL
);
426 xfree (get_membuf (&data
, &len
));
430 put_membuf (&data
, "", 1); /* Make sure it is 0 terminated. */
431 buf
= get_membuf (&data
, &len
);
433 return gpg_error (GPG_ERR_ENOMEM
);
434 assert (len
); /* (we forced Nul termination.) */
438 if (len
< 13 || memcmp (buf
, "(5:value", 8) ) /* "(5:valueN:D)\0" */
439 return gpg_error (GPG_ERR_INV_SEXP
);
440 len
-= 11; /* Count only the data of the second part. */
441 p
= buf
+ 8; /* Skip leading parenthesis and the value tag. */
445 /* For compatibility with older gpg-agents handle the old style
446 incomplete S-exps. */
447 len
--; /* Do not count the Nul. */
451 n
= strtoul (p
, &endp
, 10);
452 if (!n
|| *endp
!= ':')
453 return gpg_error (GPG_ERR_INV_SEXP
);
456 return gpg_error (GPG_ERR_INV_SEXP
); /* Oops: Inconsistent S-Exp. */
458 memmove (buf
, endp
, n
);
469 /* Handle a KEYPARMS inquiry. Note, we only send the data,
470 assuan_transact takes care of flushing and writing the end */
472 inq_genkey_parms (void *opaque
, const char *keyword
)
474 struct genkey_parm_s
*parm
= opaque
;
477 rc
= assuan_send_data (parm
->ctx
, parm
->sexp
, parm
->sexplen
);
483 /* Call the agent to generate a newkey */
485 gpgsm_agent_genkey (ctrl_t ctrl
,
486 ksba_const_sexp_t keyparms
, ksba_sexp_t
*r_pubkey
)
489 struct genkey_parm_s gk_parm
;
495 rc
= start_agent (ctrl
);
499 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
503 init_membuf (&data
, 1024);
504 gk_parm
.ctx
= agent_ctx
;
505 gk_parm
.sexp
= keyparms
;
506 gk_parm
.sexplen
= gcry_sexp_canon_len (keyparms
, 0, NULL
, NULL
);
507 if (!gk_parm
.sexplen
)
508 return gpg_error (GPG_ERR_INV_VALUE
);
509 rc
= assuan_transact (agent_ctx
, "GENKEY",
510 membuf_data_cb
, &data
,
511 inq_genkey_parms
, &gk_parm
, NULL
, NULL
);
514 xfree (get_membuf (&data
, &len
));
517 buf
= get_membuf (&data
, &len
);
519 return gpg_error (GPG_ERR_ENOMEM
);
520 if (!gcry_sexp_canon_len (buf
, len
, NULL
, NULL
))
523 return gpg_error (GPG_ERR_INV_SEXP
);
530 /* Call the agent to read the public key part for a given keygrip. If
531 FROMCARD is true, the key is directly read from the current
532 smartcard. In this case HEXKEYGRIP should be the keyID
535 gpgsm_agent_readkey (ctrl_t ctrl
, int fromcard
, const char *hexkeygrip
,
536 ksba_sexp_t
*r_pubkey
)
542 char line
[ASSUAN_LINELENGTH
];
545 rc
= start_agent (ctrl
);
549 rc
= assuan_transact (agent_ctx
, "RESET",NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
553 snprintf (line
, DIM(line
)-1, "%sREADKEY %s",
554 fromcard
? "SCD ":"", hexkeygrip
);
555 line
[DIM(line
)-1] = 0;
557 init_membuf (&data
, 1024);
558 rc
= assuan_transact (agent_ctx
, line
,
559 membuf_data_cb
, &data
,
560 NULL
, NULL
, NULL
, NULL
);
563 xfree (get_membuf (&data
, &len
));
566 buf
= get_membuf (&data
, &len
);
568 return gpg_error (GPG_ERR_ENOMEM
);
569 if (!gcry_sexp_canon_len (buf
, len
, NULL
, NULL
))
572 return gpg_error (GPG_ERR_INV_SEXP
);
581 istrusted_status_cb (void *opaque
, const char *line
)
583 struct rootca_flags_s
*flags
= opaque
;
585 if (!strncmp (line
, "TRUSTLISTFLAG", 13) && (line
[13]==' ' || !line
[13]))
587 for (line
+= 13; *line
== ' '; line
++)
589 if (!strncmp (line
, "relax", 5) && (line
[5] == ' ' || !line
[5]))
597 /* Ask the agent whether the certificate is in the list of trusted
598 keys. ROOTCA_FLAGS is guaranteed to be cleared on error. */
600 gpgsm_agent_istrusted (ctrl_t ctrl
, ksba_cert_t cert
,
601 struct rootca_flags_s
*rootca_flags
)
605 char line
[ASSUAN_LINELENGTH
];
607 memset (rootca_flags
, 0, sizeof *rootca_flags
);
609 rc
= start_agent (ctrl
);
613 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
616 log_error ("error getting the fingerprint\n");
617 return gpg_error (GPG_ERR_GENERAL
);
620 snprintf (line
, DIM(line
)-1, "ISTRUSTED %s", fpr
);
621 line
[DIM(line
)-1] = 0;
624 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
,
625 istrusted_status_cb
, rootca_flags
);
629 /* Ask the agent to mark CERT as a trusted Root-CA one */
631 gpgsm_agent_marktrusted (ctrl_t ctrl
, ksba_cert_t cert
)
635 char line
[ASSUAN_LINELENGTH
];
637 rc
= start_agent (ctrl
);
641 fpr
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
644 log_error ("error getting the fingerprint\n");
645 return gpg_error (GPG_ERR_GENERAL
);
648 dn
= ksba_cert_get_issuer (cert
, 0);
652 return gpg_error (GPG_ERR_GENERAL
);
654 snprintf (line
, DIM(line
)-1, "MARKTRUSTED %s S %s", fpr
, dn
);
655 line
[DIM(line
)-1] = 0;
659 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
665 /* Ask the agent whether the a corresponding secret key is available
666 for the given keygrip */
668 gpgsm_agent_havekey (ctrl_t ctrl
, const char *hexkeygrip
)
671 char line
[ASSUAN_LINELENGTH
];
673 rc
= start_agent (ctrl
);
677 if (!hexkeygrip
|| strlen (hexkeygrip
) != 40)
678 return gpg_error (GPG_ERR_INV_VALUE
);
680 snprintf (line
, DIM(line
)-1, "HAVEKEY %s", hexkeygrip
);
681 line
[DIM(line
)-1] = 0;
683 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
689 learn_cb (void *opaque
, const void *buffer
, size_t length
)
691 struct learn_parm_s
*parm
= opaque
;
702 put_membuf (parm
->data
, buffer
, length
);
705 /* END encountered - process what we have */
706 buf
= get_membuf (parm
->data
, &len
);
709 parm
->error
= gpg_error (GPG_ERR_ENOMEM
);
714 /* FIXME: this should go into import.c */
715 rc
= ksba_cert_new (&cert
);
721 rc
= ksba_cert_init_from_mem (cert
, buf
, len
);
724 log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc
));
725 ksba_cert_release (cert
);
730 rc
= gpgsm_basic_cert_check (cert
);
731 if (gpg_err_code (rc
) == GPG_ERR_MISSING_CERT
)
732 { /* For later use we store it in the ephemeral database. */
733 log_info ("issuer certificate missing - storing as ephemeral\n");
734 keydb_store_cert (cert
, 1, NULL
);
737 log_error ("invalid certificate: %s\n", gpg_strerror (rc
));
742 if (!keydb_store_cert (cert
, 0, &existed
))
744 if (opt
.verbose
> 1 && existed
)
745 log_info ("certificate already in DB\n");
746 else if (opt
.verbose
&& !existed
)
747 log_info ("certificate imported\n");
751 ksba_cert_release (cert
);
752 init_membuf (parm
->data
, 4096);
756 /* Call the agent to learn about a smartcard */
758 gpgsm_agent_learn (ctrl_t ctrl
)
761 struct learn_parm_s learn_parm
;
765 rc
= start_agent (ctrl
);
769 init_membuf (&data
, 4096);
770 learn_parm
.error
= 0;
771 learn_parm
.ctx
= agent_ctx
;
772 learn_parm
.data
= &data
;
773 rc
= assuan_transact (agent_ctx
, "LEARN --send",
774 learn_cb
, &learn_parm
,
775 NULL
, NULL
, NULL
, NULL
);
776 xfree (get_membuf (&data
, &len
));
779 return learn_parm
.error
;
783 /* Ask the agent to change the passphrase of the key identified by
784 HEXKEYGRIP. If DESC is not NULL, display instead of the default
785 description message. */
787 gpgsm_agent_passwd (ctrl_t ctrl
, const char *hexkeygrip
, const char *desc
)
790 char line
[ASSUAN_LINELENGTH
];
792 rc
= start_agent (ctrl
);
796 if (!hexkeygrip
|| strlen (hexkeygrip
) != 40)
797 return gpg_error (GPG_ERR_INV_VALUE
);
801 snprintf (line
, DIM(line
)-1, "SETKEYDESC %s", desc
);
802 line
[DIM(line
)-1] = 0;
803 rc
= assuan_transact (agent_ctx
, line
,
804 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
809 snprintf (line
, DIM(line
)-1, "PASSWD %s", hexkeygrip
);
810 line
[DIM(line
)-1] = 0;
812 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
818 /* Ask the agent to pop up a confirmation dialog with the text DESC
819 and an okay and cancel button. */
821 gpgsm_agent_get_confirmation (ctrl_t ctrl
, const char *desc
)
824 char line
[ASSUAN_LINELENGTH
];
826 rc
= start_agent (ctrl
);
830 snprintf (line
, DIM(line
)-1, "GET_CONFIRMATION %s", desc
);
831 line
[DIM(line
)-1] = 0;
833 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);