1 /* call-agent.c - divert operations to the agent
2 * Copyright (C) 2001, 2002, 2003 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
21 #if 0 /* lety Emacs display a red warning */
22 #error fixme: this shares a lof of code with the file in ../sm
43 #include "call-agent.h"
49 static ASSUAN_CONTEXT agent_ctx
= NULL
;
50 static int force_pipe_server
= 1; /* FIXME: set this back to 0. */
52 struct cipher_parm_s
{
54 const char *ciphertext
;
58 struct genkey_parm_s
{
66 /* Try to connect to the agent via socket or fork it off and work by
67 pipes. Handle the server's initial greeting */
74 char *dft_display
= NULL
;
75 char *dft_ttyname
= NULL
;
76 char *dft_ttytype
= NULL
;
81 return 0; /* fixme: We need a context for each thread or serialize
82 the access to the agent. */
84 infostr
= force_pipe_server
? NULL
: getenv ("GPG_AGENT_INFO");
85 if (!infostr
|| !*infostr
)
93 log_info (_("no running gpg-agent - starting one\n"));
97 gpg_error_t tmperr
= gpg_error_from_errno (errno
);
98 log_error ("error flushing pending output: %s\n", strerror (errno
));
102 if (!opt
.agent_program
|| !*opt
.agent_program
)
103 opt
.agent_program
= GNUPG_DEFAULT_AGENT
;
104 if ( !(pgmname
= strrchr (opt
.agent_program
, '/')))
105 pgmname
= opt
.agent_program
;
110 argv
[1] = "--server";
114 if (log_get_fd () != -1)
115 no_close_list
[i
++] = log_get_fd ();
116 no_close_list
[i
++] = fileno (stderr
);
117 no_close_list
[i
] = -1;
119 /* connect to the agent and perform initial handshaking */
120 rc
= assuan_pipe_connect (&ctx
, opt
.agent_program
, (char**)argv
,
128 infostr
= xstrdup (infostr
);
129 if ( !(p
= strchr (infostr
, ':')) || p
== infostr
)
131 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
133 force_pipe_server
= 1;
134 return start_agent ();
138 while (*p
&& *p
!= ':')
140 prot
= *p
? atoi (p
+1) : 0;
143 log_error (_("gpg-agent protocol version %d is not supported\n"),
146 force_pipe_server
= 1;
147 return start_agent ();
150 rc
= assuan_socket_connect (&ctx
, infostr
, pid
);
152 if (rc
== ASSUAN_Connect_Failed
)
154 log_error (_("can't connect to the agent - trying fall back\n"));
155 force_pipe_server
= 1;
156 return start_agent ();
162 log_error ("can't connect to the agent: %s\n", assuan_strerror (rc
));
163 return gpg_error (GPG_ERR_NO_AGENT
);
168 log_debug ("connection to agent established\n");
170 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
172 return map_assuan_err (rc
);
175 #warning put this code into common/asshelp.c
178 dft_display
= getenv ("DISPLAY");
179 if (opt
.display
|| dft_display
)
182 if (asprintf (&optstr
, "OPTION display=%s",
183 opt
.display
? opt
.display
: dft_display
) < 0)
184 return gpg_error_from_errno (errno
);
185 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
189 return map_assuan_err (rc
);
193 dft_ttyname
= getenv ("GPG_TTY");
194 if ((!dft_ttyname
|| !*dft_ttyname
) && ttyname (0))
195 dft_ttyname
= ttyname (0);
197 if (opt
.ttyname
|| dft_ttyname
)
200 if (asprintf (&optstr
, "OPTION ttyname=%s",
201 opt
.ttyname
? opt
.ttyname
: dft_ttyname
) < 0)
202 return gpg_error_from_errno (errno
);
203 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
207 return map_assuan_err (rc
);
209 dft_ttytype
= getenv ("TERM");
210 if (opt
.ttytype
|| (dft_ttyname
&& dft_ttytype
))
213 if (asprintf (&optstr
, "OPTION ttytype=%s",
214 opt
.ttyname
? opt
.ttytype
: dft_ttytype
) < 0)
215 return gpg_error_from_errno (errno
);
216 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
220 return map_assuan_err (rc
);
222 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
223 old_lc
= setlocale (LC_CTYPE
, NULL
);
226 old_lc
= strdup (old_lc
);
228 return gpg_error_from_errno (errno
);
231 dft_lc
= setlocale (LC_CTYPE
, "");
233 if (opt
.lc_ctype
|| (dft_ttyname
&& dft_lc
))
236 if (asprintf (&optstr
, "OPTION lc-ctype=%s",
237 opt
.lc_ctype
? opt
.lc_ctype
: dft_lc
) < 0)
238 rc
= gpg_error_from_errno (errno
);
241 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
245 rc
= map_assuan_err (rc
);
248 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
251 setlocale (LC_CTYPE
, old_lc
);
257 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
258 old_lc
= setlocale (LC_MESSAGES
, NULL
);
261 old_lc
= strdup (old_lc
);
263 return gpg_error_from_errno (errno
);
265 dft_lc
= setlocale (LC_MESSAGES
, "");
267 if (opt
.lc_messages
|| (dft_ttyname
&& dft_lc
))
270 if (asprintf (&optstr
, "OPTION lc-messages=%s",
271 opt
.lc_messages
? opt
.lc_messages
: dft_lc
) < 0)
272 rc
= gpg_error_from_errno (errno
);
275 rc
= assuan_transact (agent_ctx
, optstr
, NULL
, NULL
, NULL
, NULL
, NULL
,
279 rc
= map_assuan_err (rc
);
282 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
285 setlocale (LC_MESSAGES
, old_lc
);
294 /* Return a new malloced string by unescaping the string S. Escaping
295 is percent escaping and '+'/space mapping. A binary nul will
296 silently be replaced by a 0xFF. Function returns NULL to indicate
297 an out of memory status. */
299 unescape_status_string (const unsigned char *s
)
303 buffer
= d
= xtrymalloc (strlen (s
)+1);
308 if (*s
== '%' && s
[1] && s
[2])
329 /* Take a 20 byte hexencoded string and put it into the the provided
330 20 byte buffer FPR in binary format. */
332 unhexify_fpr (const char *hexstr
, unsigned char *fpr
)
337 for (s
=hexstr
, n
=0; hexdigitp (s
); s
++, n
++)
340 return 0; /* no fingerprint (invalid or wrong length). */
342 for (s
=hexstr
, n
=0; *s
; s
+= 2, n
++)
347 /* Take the serial number from LINE and return it verbatim in a newly
348 allocated string. We make sure that only hex characters are
351 store_serialno (const char *line
)
356 for (s
=line
; hexdigitp (s
); s
++)
358 p
= xtrymalloc (s
+ 1 - line
);
361 memcpy (p
, line
, s
-line
);
370 /* Handle a KEYPARMS inquiry. Note, we only send the data,
371 assuan_transact takes care of flushing and writing the end */
373 inq_genkey_parms (void *opaque
, const char *keyword
)
375 struct genkey_parm_s
*parm
= opaque
;
378 rc
= assuan_send_data (parm
->ctx
, parm
->sexp
, parm
->sexplen
);
384 /* Call the agent to generate a new key */
386 agent_genkey (KsbaConstSexp keyparms
, KsbaSexp
*r_pubkey
)
389 struct genkey_parm_s gk_parm
;
399 rc
= assuan_transact (agent_ctx
, "RESET", NULL
, NULL
,
400 NULL
, NULL
, NULL
, NULL
);
402 return map_assuan_err (rc
);
404 init_membuf (&data
, 1024);
405 gk_parm
.ctx
= agent_ctx
;
406 gk_parm
.sexp
= keyparms
;
407 gk_parm
.sexplen
= gcry_sexp_canon_len (keyparms
, 0, NULL
, NULL
);
408 if (!gk_parm
.sexplen
)
409 return gpg_error (GPG_ERR_INV_VALUE
);
410 rc
= assuan_transact (agent_ctx
, "GENKEY",
411 membuf_data_cb
, &data
,
412 inq_genkey_parms
, &gk_parm
, NULL
, NULL
);
415 xfree (get_membuf (&data
, &len
));
416 return map_assuan_err (rc
);
418 buf
= get_membuf (&data
, &len
);
420 return gpg_error (GPG_ERR_ENOMEM
);
421 if (!gcry_sexp_canon_len (buf
, len
, NULL
, NULL
))
424 return gpg_error (GPG_ERR_INV_SEXP
);
433 /* Ask the agent whether the corresponding secret key is available for
434 the given keygrip. */
436 agent_havekey (const char *hexkeygrip
)
439 char line
[ASSUAN_LINELENGTH
];
445 if (!hexkeygrip
|| strlen (hexkeygrip
) != 40)
446 return gpg_error (GPG_ERR_INV_VALUE
);
448 snprintf (line
, DIM(line
)-1, "HAVEKEY %s", hexkeygrip
);
449 line
[DIM(line
)-1] = 0;
451 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
452 return map_assuan_err (rc
);
456 /* Release the card info structure INFO. */
458 agent_release_card_info (struct agent_card_info_s
*info
)
463 xfree (info
->serialno
); info
->serialno
= NULL
;
464 xfree (info
->disp_name
); info
->disp_name
= NULL
;
465 xfree (info
->disp_lang
); info
->disp_lang
= NULL
;
466 xfree (info
->pubkey_url
); info
->pubkey_url
= NULL
;
467 xfree (info
->login_data
); info
->login_data
= NULL
;
468 info
->cafpr1valid
= info
->cafpr2valid
= info
->cafpr3valid
= 0;
469 info
->fpr1valid
= info
->fpr2valid
= info
->fpr3valid
= 0;
473 learn_status_cb (void *opaque
, const char *line
)
475 struct agent_card_info_s
*parm
= opaque
;
476 const char *keyword
= line
;
480 for (keywordlen
=0; *line
&& !spacep (line
); line
++, keywordlen
++)
482 while (spacep (line
))
485 if (keywordlen
== 8 && !memcmp (keyword
, "SERIALNO", keywordlen
))
487 xfree (parm
->serialno
);
488 parm
->serialno
= store_serialno (line
);
490 else if (keywordlen
== 9 && !memcmp (keyword
, "DISP-NAME", keywordlen
))
492 xfree (parm
->disp_name
);
493 parm
->disp_name
= unescape_status_string (line
);
495 else if (keywordlen
== 9 && !memcmp (keyword
, "DISP-LANG", keywordlen
))
497 xfree (parm
->disp_lang
);
498 parm
->disp_lang
= unescape_status_string (line
);
500 else if (keywordlen
== 8 && !memcmp (keyword
, "DISP-SEX", keywordlen
))
502 parm
->disp_sex
= *line
== '1'? 1 : *line
== '2' ? 2: 0;
504 else if (keywordlen
== 10 && !memcmp (keyword
, "PUBKEY-URL", keywordlen
))
506 xfree (parm
->pubkey_url
);
507 parm
->pubkey_url
= unescape_status_string (line
);
509 else if (keywordlen
== 10 && !memcmp (keyword
, "LOGIN-DATA", keywordlen
))
511 xfree (parm
->login_data
);
512 parm
->login_data
= unescape_status_string (line
);
514 else if (keywordlen
== 11 && !memcmp (keyword
, "SIG-COUNTER", keywordlen
))
516 parm
->sig_counter
= strtoul (line
, NULL
, 0);
518 else if (keywordlen
== 10 && !memcmp (keyword
, "CHV-STATUS", keywordlen
))
522 buf
= p
= unescape_status_string (line
);
527 parm
->chv1_cached
= atoi (p
);
528 while (*p
&& !spacep (p
))
532 for (i
=0; *p
&& i
< 3; i
++)
534 parm
->chvmaxlen
[i
] = atoi (p
);
535 while (*p
&& !spacep (p
))
540 for (i
=0; *p
&& i
< 3; i
++)
542 parm
->chvretry
[i
] = atoi (p
);
543 while (*p
&& !spacep (p
))
551 else if (keywordlen
== 7 && !memcmp (keyword
, "KEY-FPR", keywordlen
))
553 int no
= atoi (line
);
554 while (*line
&& !spacep (line
))
556 while (spacep (line
))
559 parm
->fpr1valid
= unhexify_fpr (line
, parm
->fpr1
);
561 parm
->fpr2valid
= unhexify_fpr (line
, parm
->fpr2
);
563 parm
->fpr3valid
= unhexify_fpr (line
, parm
->fpr3
);
565 else if (keywordlen
== 6 && !memcmp (keyword
, "CA-FPR", keywordlen
))
567 int no
= atoi (line
);
568 while (*line
&& !spacep (line
))
570 while (spacep (line
))
573 parm
->cafpr1valid
= unhexify_fpr (line
, parm
->cafpr1
);
575 parm
->cafpr2valid
= unhexify_fpr (line
, parm
->cafpr2
);
577 parm
->cafpr3valid
= unhexify_fpr (line
, parm
->cafpr3
);
583 /* Call the agent to learn about a smartcard */
585 agent_learn (struct agent_card_info_s
*info
)
593 memset (info
, 0, sizeof *info
);
594 rc
= assuan_transact (agent_ctx
, "LEARN --send",
595 NULL
, NULL
, NULL
, NULL
,
596 learn_status_cb
, info
);
598 return map_assuan_err (rc
);
601 /* Call the agent to retrieve a data object. This function returns
602 the data in the same structure as used by the learn command. It is
603 allowed to update such a structure using this commmand. */
605 agent_scd_getattr (const char *name
, struct agent_card_info_s
*info
)
608 char line
[ASSUAN_LINELENGTH
];
611 return gpg_error (GPG_ERR_INV_VALUE
);
613 /* We assume that NAME does not need escaping. */
614 if (12 + strlen (name
) > DIM(line
)-1)
615 return gpg_error (GPG_ERR_TOO_LARGE
);
616 stpcpy (stpcpy (line
, "SCD GETATTR "), name
);
622 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
,
623 learn_status_cb
, info
);
625 return map_assuan_err (rc
);
629 /* Send an setattr command to the SCdaemon. */
631 agent_scd_setattr (const char *name
,
632 const unsigned char *value
, size_t valuelen
)
635 char line
[ASSUAN_LINELENGTH
];
638 if (!*name
|| !valuelen
)
639 return gpg_error (GPG_ERR_INV_VALUE
);
641 /* We assume that NAME does not need escaping. */
642 if (12 + strlen (name
) > DIM(line
)-1)
643 return gpg_error (GPG_ERR_TOO_LARGE
);
645 p
= stpcpy (stpcpy (line
, "SCD SETATTR "), name
);
647 for (; valuelen
; value
++, valuelen
--)
649 if (p
>= line
+ DIM(line
)-5 )
650 return gpg_error (GPG_ERR_TOO_LARGE
);
651 if (*value
< ' ' || *value
== '+' || *value
== '%')
653 sprintf (p
, "%%%02X", *value
);
656 else if (*value
== ' ')
667 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
668 return map_assuan_err (rc
);
672 /* Status callback for the SCD GENKEY command. */
674 scd_genkey_cb (void *opaque
, const char *line
)
676 struct agent_card_genkey_s
*parm
= opaque
;
677 const char *keyword
= line
;
681 log_debug ("got status line `%s'\n", line
);
682 for (keywordlen
=0; *line
&& !spacep (line
); line
++, keywordlen
++)
684 while (spacep (line
))
687 if (keywordlen
== 7 && !memcmp (keyword
, "KEY-FPR", keywordlen
))
689 parm
->fprvalid
= unhexify_fpr (line
, parm
->fpr
);
691 if (keywordlen
== 8 && !memcmp (keyword
, "KEY-DATA", keywordlen
))
694 const char *name
= line
;
696 while (*line
&& !spacep (line
))
698 while (spacep (line
))
701 rc
= gcry_mpi_scan (&a
, GCRYMPI_FMT_HEX
, line
, 0, NULL
);
703 log_error ("error parsing received key data: %s\n", gpg_strerror (rc
));
704 else if (*name
== 'n' && spacep (name
+1))
706 else if (*name
== 'e' && spacep (name
+1))
710 log_info ("unknown parameter name in received key data\n");
711 gcry_mpi_release (a
);
714 else if (keywordlen
== 14 && !memcmp (keyword
,"KEY-CREATED-AT", keywordlen
))
716 parm
->created_at
= (u32
)strtoul (line
, NULL
, 10);
722 /* Send a GENKEY command to the SCdaemon. */
724 agent_scd_genkey (struct agent_card_genkey_s
*info
, int keyno
, int force
)
727 char line
[ASSUAN_LINELENGTH
];
733 memset (info
, 0, sizeof *info
);
734 snprintf (line
, DIM(line
)-1, "SCD GENKEY %s%d",
735 force
? "--force ":"", keyno
);
736 line
[DIM(line
)-1] = 0;
738 memset (info
, 0, sizeof *info
);
739 rc
= assuan_transact (agent_ctx
, line
,
740 NULL
, NULL
, NULL
, NULL
,
741 scd_genkey_cb
, info
);
743 return map_assuan_err (rc
);
748 membuf_data_cb (void *opaque
, const void *buffer
, size_t length
)
750 membuf_t
*data
= opaque
;
753 put_membuf (data
, buffer
, length
);
757 /* Send a sign command to the scdaemon via gpg-agent's pass thru
760 agent_scd_pksign (const char *serialno
, int hashalgo
,
761 const unsigned char *indata
, size_t indatalen
,
762 char **r_buf
, size_t *r_buflen
)
765 char *p
, line
[ASSUAN_LINELENGTH
];
769 /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
778 if (indatalen
*2 + 50 > DIM(line
))
779 return gpg_error (GPG_ERR_GENERAL
);
781 sprintf (line
, "SCD SETDATA ");
782 p
= line
+ strlen (line
);
783 for (i
=0; i
< indatalen
; i
++, p
+= 2 )
784 sprintf (p
, "%02X", indata
[i
]);
785 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
787 return map_assuan_err (rc
);
789 init_membuf (&data
, 1024);
791 if (!hashalgo
) /* Temporary test hack. */
792 snprintf (line
, DIM(line
)-1, "SCD PKAUTH %s", serialno
);
795 snprintf (line
, DIM(line
)-1, "SCD PKSIGN %s", serialno
);
796 line
[DIM(line
)-1] = 0;
797 rc
= assuan_transact (agent_ctx
, line
, membuf_data_cb
, &data
,
798 NULL
, NULL
, NULL
, NULL
);
801 xfree (get_membuf (&data
, &len
));
802 return map_assuan_err (rc
);
804 *r_buf
= get_membuf (&data
, r_buflen
);
810 /* Decrypt INDATA of length INDATALEN using the card identified by
811 SERIALNO. Return the plaintext in a nwly allocated buffer stored
812 at the address of R_BUF.
814 Note, we currently support only RSA or more exactly algorithms
815 taking one input data element. */
817 agent_scd_pkdecrypt (const char *serialno
,
818 const unsigned char *indata
, size_t indatalen
,
819 char **r_buf
, size_t *r_buflen
)
822 char *p
, line
[ASSUAN_LINELENGTH
];
831 /* FIXME: use secure memory where appropriate */
832 if (indatalen
*2 + 50 > DIM(line
))
833 return gpg_error (GPG_ERR_GENERAL
);
835 sprintf (line
, "SCD SETDATA ");
836 p
= line
+ strlen (line
);
837 for (i
=0; i
< indatalen
; i
++, p
+= 2 )
838 sprintf (p
, "%02X", indata
[i
]);
839 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
841 return map_assuan_err (rc
);
843 init_membuf (&data
, 1024);
844 snprintf (line
, DIM(line
)-1, "SCD PKDECRYPT %s", serialno
);
845 line
[DIM(line
)-1] = 0;
846 rc
= assuan_transact (agent_ctx
, line
,
847 membuf_data_cb
, &data
,
848 NULL
, NULL
, NULL
, NULL
);
851 xfree (get_membuf (&data
, &len
));
852 return map_assuan_err (rc
);
854 *r_buf
= get_membuf (&data
, r_buflen
);
856 return gpg_error (GPG_ERR_ENOMEM
);
862 /* Change the PIN of an OpenPGP card or reset the retry counter.
863 CHVNO 1: Change the PIN
865 3: Change the admin PIN
866 101: Set a new PIN and reset the retry counter
870 agent_scd_change_pin (int chvno
)
873 char line
[ASSUAN_LINELENGTH
];
874 const char *reset
= "";
884 snprintf (line
, DIM(line
)-1, "SCD PASSWD %s %d", reset
, chvno
);
885 line
[DIM(line
)-1] = 0;
886 rc
= assuan_transact (agent_ctx
, line
, NULL
, NULL
,
887 NULL
, NULL
, NULL
, NULL
);
888 return map_assuan_err (rc
);
892 /* Perform a CHECKPIN operation. SERIALNO should be the serial
893 number of the card - optioanlly followed by the fingerprint;
894 however the fingerprint is ignored here. */
896 agent_scd_checkpin (const char *serialno
)
899 char line
[ASSUAN_LINELENGTH
];
905 snprintf (line
, DIM(line
)-1, "SCD CHECKPIN %s", serialno
);
906 line
[DIM(line
)-1] = 0;
907 return assuan_transact (agent_ctx
, line
,
909 NULL
, NULL
, NULL
, NULL
);