1 /* command-ssh.c - gpg-agent's ssh-agent emulation layer
2 * Copyright (C) 2004, 2005, 2006, 2009 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 3 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, see <http://www.gnu.org/licenses/>.
20 /* Only v2 of the ssh-agent protocol is implemented. */
28 #include <sys/types.h>
41 #define SSH_REQUEST_REQUEST_IDENTITIES 11
42 #define SSH_REQUEST_SIGN_REQUEST 13
43 #define SSH_REQUEST_ADD_IDENTITY 17
44 #define SSH_REQUEST_REMOVE_IDENTITY 18
45 #define SSH_REQUEST_REMOVE_ALL_IDENTITIES 19
46 #define SSH_REQUEST_LOCK 22
47 #define SSH_REQUEST_UNLOCK 23
48 #define SSH_REQUEST_ADD_ID_CONSTRAINED 25
51 #define SSH_OPT_CONSTRAIN_LIFETIME 1
52 #define SSH_OPT_CONSTRAIN_CONFIRM 2
55 #define SSH_RESPONSE_SUCCESS 6
56 #define SSH_RESPONSE_FAILURE 5
57 #define SSH_RESPONSE_IDENTITIES_ANSWER 12
58 #define SSH_RESPONSE_SIGN_RESPONSE 14
60 /* Other constants. */
61 #define SSH_DSA_SIGNATURE_PADDING 20
62 #define SSH_DSA_SIGNATURE_ELEMS 2
63 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0)
66 /* The blurb we put into the header of a newly created control file. */
67 static const char sshcontrolblurb
[] =
68 "# List of allowed ssh keys. Only keys present in this file are used\n"
69 "# in the SSH protocol. The ssh-add tool may add new entries to this\n"
70 "# file to enable them; you may also add them manually. Comment\n"
71 "# lines, like this one, as well as empty lines are ignored. Lines do\n"
72 "# have a certain length limit but this is not serious limitation as\n"
73 "# the format of the entries is fixed and checked by gpg-agent. A\n"
74 "# non-comment line starts with optional white spaces, followed by the\n"
75 "# keygrip of the key given as 40 hex digits, optionally followed by a\n"
76 "# the caching TTL in seconds and another optional field for arbitrary\n"
77 "# flags. Prepend the keygrip with an '!' mark to disable it.\n"
84 /* Return a new uint32 with b0 being the most significant byte and b3
85 being the least significant byte. */
86 #define uint32_construct(b0, b1, b2, b3) \
87 ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3)
96 /* Type for a request handler. */
97 typedef gpg_error_t (*ssh_request_handler_t
) (ctrl_t ctrl
,
101 /* Type, which is used for associating request handlers with the
102 appropriate request IDs. */
103 typedef struct ssh_request_spec
106 ssh_request_handler_t handler
;
107 const char *identifier
;
108 unsigned int secret_input
;
109 } ssh_request_spec_t
;
111 /* Type for "key modifier functions", which are necessary since
112 OpenSSH and GnuPG treat key material slightly different. A key
113 modifier is called right after a new key identity has been received
114 in order to "sanitize" the material. */
115 typedef gpg_error_t (*ssh_key_modifier_t
) (const char *elems
,
118 /* The encoding of a generated signature is dependent on the
119 algorithm; therefore algorithm specific signature encoding
120 functions are necessary. */
121 typedef gpg_error_t (*ssh_signature_encoder_t
) (estream_t signature_blob
,
124 /* Type, which is used for boundling all the algorithm specific
125 information together in a single object. */
126 typedef struct ssh_key_type_spec
128 /* Algorithm identifier as used by OpenSSH. */
129 const char *ssh_identifier
;
131 /* Algorithm identifier as used by GnuPG. */
132 const char *identifier
;
134 /* List of MPI names for secret keys; order matches the one of the
136 const char *elems_key_secret
;
138 /* List of MPI names for public keys; order matches the one of the
140 const char *elems_key_public
;
142 /* List of MPI names for signature data. */
143 const char *elems_signature
;
145 /* List of MPI names for secret keys; order matches the one, which
146 is required by gpg-agent's key access layer. */
147 const char *elems_sexp_order
;
149 /* Key modifier function. Key modifier functions are necessary in
150 order to fix any inconsistencies between the representation of
151 keys on the SSH and on the GnuPG side. */
152 ssh_key_modifier_t key_modifier
;
154 /* Signature encoder function. Signature encoder functions are
155 necessary since the encoding of signatures depends on the used
157 ssh_signature_encoder_t signature_encoder
;
161 } ssh_key_type_spec_t
;
165 static gpg_error_t
ssh_handler_request_identities (ctrl_t ctrl
,
168 static gpg_error_t
ssh_handler_sign_request (ctrl_t ctrl
,
171 static gpg_error_t
ssh_handler_add_identity (ctrl_t ctrl
,
174 static gpg_error_t
ssh_handler_remove_identity (ctrl_t ctrl
,
177 static gpg_error_t
ssh_handler_remove_all_identities (ctrl_t ctrl
,
180 static gpg_error_t
ssh_handler_lock (ctrl_t ctrl
,
183 static gpg_error_t
ssh_handler_unlock (ctrl_t ctrl
,
187 static gpg_error_t
ssh_key_modifier_rsa (const char *elems
, gcry_mpi_t
*mpis
);
188 static gpg_error_t
ssh_signature_encoder_rsa (estream_t signature_blob
,
190 static gpg_error_t
ssh_signature_encoder_dsa (estream_t signature_blob
,
195 /* Global variables. */
198 /* Associating request types with the corresponding request
201 static ssh_request_spec_t request_specs
[] =
203 #define REQUEST_SPEC_DEFINE(id, name, secret_input) \
204 { SSH_REQUEST_##id, ssh_handler_##name, #name, secret_input }
206 REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES
, request_identities
, 1),
207 REQUEST_SPEC_DEFINE (SIGN_REQUEST
, sign_request
, 0),
208 REQUEST_SPEC_DEFINE (ADD_IDENTITY
, add_identity
, 1),
209 REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED
, add_identity
, 1),
210 REQUEST_SPEC_DEFINE (REMOVE_IDENTITY
, remove_identity
, 0),
211 REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES
, remove_all_identities
, 0),
212 REQUEST_SPEC_DEFINE (LOCK
, lock
, 0),
213 REQUEST_SPEC_DEFINE (UNLOCK
, unlock
, 0)
214 #undef REQUEST_SPEC_DEFINE
218 /* Table holding key type specifications. */
219 static ssh_key_type_spec_t ssh_key_types
[] =
222 "ssh-rsa", "rsa", "nedupq", "en", "s", "nedpqu",
223 ssh_key_modifier_rsa
, ssh_signature_encoder_rsa
,
224 SPEC_FLAG_USE_PKCS1V2
227 "ssh-dss", "dsa", "pqgyx", "pqgy", "rs", "pqgyx",
228 NULL
, ssh_signature_encoder_dsa
,
238 General utility functions.
241 /* A secure realloc, i.e. it makes sure to allocate secure memory if A
242 is NULL. This is required because the standard gcry_realloc does
243 not know whether to allocate secure or normal if NULL is passed as
246 realloc_secure (void *a
, size_t n
)
251 p
= gcry_realloc (a
, n
);
253 p
= gcry_malloc_secure (n
);
259 /* Create and return a new C-string from DATA/DATA_N (i.e.: add
260 NUL-termination); return NULL on OOM. */
262 make_cstring (const char *data
, size_t data_n
)
266 s
= xtrymalloc (data_n
+ 1);
269 memcpy (s
, data
, data_n
);
280 Primitive I/O functions.
284 /* Read a byte from STREAM, store it in B. */
286 stream_read_byte (estream_t stream
, unsigned char *b
)
291 ret
= es_fgetc (stream
);
294 if (es_ferror (stream
))
295 err
= gpg_error_from_syserror ();
297 err
= gpg_error (GPG_ERR_EOF
);
309 /* Write the byte contained in B to STREAM. */
311 stream_write_byte (estream_t stream
, unsigned char b
)
316 ret
= es_fputc (b
, stream
);
318 err
= gpg_error_from_syserror ();
325 /* Read a uint32 from STREAM, store it in UINT32. */
327 stream_read_uint32 (estream_t stream
, u32
*uint32
)
329 unsigned char buffer
[4];
334 ret
= es_read (stream
, buffer
, sizeof (buffer
), &bytes_read
);
336 err
= gpg_error_from_syserror ();
339 if (bytes_read
!= sizeof (buffer
))
340 err
= gpg_error (GPG_ERR_EOF
);
345 n
= uint32_construct (buffer
[0], buffer
[1], buffer
[2], buffer
[3]);
354 /* Write the uint32 contained in UINT32 to STREAM. */
356 stream_write_uint32 (estream_t stream
, u32 uint32
)
358 unsigned char buffer
[4];
362 buffer
[0] = uint32
>> 24;
363 buffer
[1] = uint32
>> 16;
364 buffer
[2] = uint32
>> 8;
365 buffer
[3] = uint32
>> 0;
367 ret
= es_write (stream
, buffer
, sizeof (buffer
), NULL
);
369 err
= gpg_error_from_syserror ();
376 /* Read SIZE bytes from STREAM into BUFFER. */
378 stream_read_data (estream_t stream
, unsigned char *buffer
, size_t size
)
384 ret
= es_read (stream
, buffer
, size
, &bytes_read
);
386 err
= gpg_error_from_syserror ();
389 if (bytes_read
!= size
)
390 err
= gpg_error (GPG_ERR_EOF
);
398 /* Write SIZE bytes from BUFFER to STREAM. */
400 stream_write_data (estream_t stream
, const unsigned char *buffer
, size_t size
)
405 ret
= es_write (stream
, buffer
, size
, NULL
);
407 err
= gpg_error_from_syserror ();
414 /* Read a binary string from STREAM into STRING, store size of string
415 in STRING_SIZE; depending on SECURE use secure memory for
418 stream_read_string (estream_t stream
, unsigned int secure
,
419 unsigned char **string
, u32
*string_size
)
422 unsigned char *buffer
= NULL
;
425 /* Read string length. */
426 err
= stream_read_uint32 (stream
, &length
);
430 /* Allocate space. */
432 buffer
= xtrymalloc_secure (length
+ 1);
434 buffer
= xtrymalloc (length
+ 1);
437 err
= gpg_error_from_syserror ();
442 err
= stream_read_data (stream
, buffer
, length
);
446 /* Finalize string object. */
450 *string_size
= length
;
460 /* Read a C-string from STREAM, store copy in STRING. */
462 stream_read_cstring (estream_t stream
, char **string
)
464 unsigned char *buffer
;
467 err
= stream_read_string (stream
, 0, &buffer
, NULL
);
471 *string
= (char *) buffer
;
479 /* Write a binary string from STRING of size STRING_N to STREAM. */
481 stream_write_string (estream_t stream
,
482 const unsigned char *string
, u32 string_n
)
486 err
= stream_write_uint32 (stream
, string_n
);
490 err
= stream_write_data (stream
, string
, string_n
);
497 /* Write a C-string from STRING to STREAM. */
499 stream_write_cstring (estream_t stream
, const char *string
)
503 err
= stream_write_string (stream
,
504 (const unsigned char *) string
, strlen (string
));
509 /* Read an MPI from STREAM, store it in MPINT. Depending on SECURE
510 use secure memory. */
512 stream_read_mpi (estream_t stream
, unsigned int secure
, gcry_mpi_t
*mpint
)
514 unsigned char *mpi_data
;
521 err
= stream_read_string (stream
, secure
, &mpi_data
, &mpi_data_size
);
525 /* To avoid excessive use of secure memory we check that an MPI is
527 if (mpi_data_size
> 520)
529 log_error (_("ssh keys greater than %d bits are not supported\n"), 4096);
530 err
= GPG_ERR_TOO_LARGE
;
534 err
= gcry_mpi_scan (&mpi
, GCRYMPI_FMT_STD
, mpi_data
, mpi_data_size
, NULL
);
547 /* Write the MPI contained in MPINT to STREAM. */
549 stream_write_mpi (estream_t stream
, gcry_mpi_t mpint
)
551 unsigned char *mpi_buffer
;
557 err
= gcry_mpi_aprint (GCRYMPI_FMT_STD
, &mpi_buffer
, &mpi_buffer_n
, mpint
);
561 err
= stream_write_string (stream
, mpi_buffer
, mpi_buffer_n
);
570 /* Copy data from SRC to DST until EOF is reached. */
572 stream_copy (estream_t dst
, estream_t src
)
582 ret
= es_read (src
, buffer
, sizeof (buffer
), &bytes_read
);
583 if (ret
|| (! bytes_read
))
586 err
= gpg_error_from_syserror ();
589 ret
= es_write (dst
, buffer
, bytes_read
, NULL
);
592 err
= gpg_error_from_syserror ();
601 /* Read the content of the file specified by FILENAME into a newly
602 create buffer, which is to be stored in BUFFER; store length of
603 buffer in BUFFER_N. */
605 file_to_buffer (const char *filename
, unsigned char **buffer
, size_t *buffer_n
)
607 unsigned char *buffer_new
;
619 stream
= es_fopen (filename
, "r");
622 err
= gpg_error_from_syserror ();
626 ret
= fstat (es_fileno (stream
), &statbuf
);
629 err
= gpg_error_from_syserror ();
633 buffer_new
= xtrymalloc (statbuf
.st_size
);
636 err
= gpg_error_from_syserror ();
640 err
= stream_read_data (stream
, buffer_new
, statbuf
.st_size
);
644 *buffer
= buffer_new
;
645 *buffer_n
= statbuf
.st_size
;
661 /* Open the ssh control file and create it if not available. With
662 APPEND passed as true the file will be opened in append mode,
663 otherwise in read only mode. On success a file pointer is stored
664 at the address of R_FP. */
666 open_control_file (FILE **r_fp
, int append
)
672 /* Note: As soon as we start to use non blocking functions here
673 (i.e. where Pth might switch threads) we need to employ a
676 fname
= make_filename (opt
.homedir
, "sshcontrol", NULL
);
677 /* FIXME: With "a+" we are not able to check whether this will will
678 be created and thus the blurb needs to be written first. */
679 fp
= fopen (fname
, append
? "a+":"r");
680 if (!fp
&& errno
== ENOENT
)
682 /* Fixme: "x" is a GNU extension. We might want to use the es_
684 fp
= fopen (fname
, "wx");
687 err
= gpg_error (gpg_err_code_from_errno (errno
));
688 log_error (_("can't create `%s': %s\n"), fname
, gpg_strerror (err
));
692 fputs (sshcontrolblurb
, fp
);
694 fp
= fopen (fname
, append
? "a+":"r");
699 err
= gpg_error (gpg_err_code_from_errno (errno
));
700 log_error (_("can't open `%s': %s\n"), fname
, gpg_strerror (err
));
711 /* Search the file at stream FP from the beginning until a matching
712 HEXGRIP is found; return success in this case and store true at
713 DISABLED if the found key has been disabled. If R_TTL is not NULL
714 a specified TTL for that key is stored there. */
716 search_control_file (FILE *fp
, const char *hexgrip
,
717 int *r_disabled
, int *r_ttl
)
720 char *p
, *pend
, line
[256];
723 assert (strlen (hexgrip
) == 40 );
730 if (!fgets (line
, DIM(line
)-1, fp
) )
733 return gpg_error (GPG_ERR_EOF
);
734 return gpg_error (gpg_err_code_from_errno (errno
));
737 if (!*line
|| line
[strlen(line
)-1] != '\n')
739 /* Eat until end of line */
740 while ( (c
=getc (fp
)) != EOF
&& c
!= '\n')
742 return gpg_error (*line
? GPG_ERR_LINE_TOO_LONG
743 : GPG_ERR_INCOMPLETE_LINE
);
746 /* Allow for empty lines and spaces */
747 for (p
=line
; spacep (p
); p
++)
750 while (!*p
|| *p
== '\n' || *p
== '#');
756 for (p
++; spacep (p
); p
++)
760 for (i
=0; hexdigitp (p
) && i
< 40; p
++, i
++)
761 if (hexgrip
[i
] != (*p
>= 'a'? (*p
& 0xdf): *p
))
763 if (i
!= 40 || !(spacep (p
) || *p
== '\n'))
765 log_error ("invalid formatted line in ssh control file\n");
766 return gpg_error (GPG_ERR_BAD_DATA
);
769 ttl
= strtol (p
, &pend
, 10);
771 if (!(spacep (p
) || *p
== '\n') || ttl
< -1)
773 log_error ("invalid TTL value in ssh control file; assuming 0\n");
779 /* Here is the place to parse flags if we need them. */
781 return 0; /* Okay: found it. */
786 /* Add an entry to the control file to mark the key with the keygrip
787 HEXGRIP as usable for SSH; i.e. it will be returned when ssh asks
788 for it. This function is in general used to add a key received
789 through the ssh-add function. We can assume that the user wants to
790 allow ssh using this key. */
792 add_control_entry (ctrl_t ctrl
, const char *hexgrip
, int ttl
)
800 err
= open_control_file (&fp
, 1);
804 err
= search_control_file (fp
, hexgrip
, &disabled
, NULL
);
805 if (err
&& gpg_err_code(err
) == GPG_ERR_EOF
)
808 time_t atime
= time (NULL
);
810 /* Not yet in the file - add it. Because the file has been
811 opened in append mode, we simply need to write to it. */
812 tp
= localtime (&atime
);
813 fprintf (fp
, "# Key added on %04d-%02d-%02d %02d:%02d:%02d\n%s %d\n",
814 1900+tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
,
815 tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
,
824 /* Scan the sshcontrol file and return the TTL. */
826 ttl_from_sshcontrol (const char *hexgrip
)
831 if (!hexgrip
|| strlen (hexgrip
) != 40)
832 return 0; /* Wrong input: Use global default. */
834 if (open_control_file (&fp
, 0))
835 return 0; /* Error: Use the global default TTL. */
837 if (search_control_file (fp
, hexgrip
, &disabled
, &ttl
)
839 ttl
= 0; /* Use the global default if not found or disabled. */
856 /* Free the list of MPIs MPI_LIST. */
858 mpint_list_free (gcry_mpi_t
*mpi_list
)
864 for (i
= 0; mpi_list
[i
]; i
++)
865 gcry_mpi_release (mpi_list
[i
]);
870 /* Receive key material MPIs from STREAM according to KEY_SPEC;
871 depending on SECRET expect a public key or secret key. The newly
872 allocated list of MPIs is stored in MPI_LIST. Returns usual error
875 ssh_receive_mpint_list (estream_t stream
, int secret
,
876 ssh_key_type_spec_t key_spec
, gcry_mpi_t
**mpi_list
)
878 unsigned int elems_public_n
;
879 const char *elems_public
;
880 unsigned int elems_n
;
891 elems
= key_spec
.elems_key_secret
;
893 elems
= key_spec
.elems_key_public
;
894 elems_n
= strlen (elems
);
896 elems_public
= key_spec
.elems_key_public
;
897 elems_public_n
= strlen (elems_public
);
899 mpis
= xtrycalloc (elems_n
+ 1, sizeof *mpis
);
902 err
= gpg_error_from_syserror ();
907 for (i
= 0; i
< elems_n
; i
++)
910 elem_is_secret
= ! strchr (elems_public
, elems
[i
]);
911 err
= stream_read_mpi (stream
, elem_is_secret
, &mpis
[i
]);
923 mpint_list_free (mpis
);
930 /* Key modifier function for RSA. */
932 ssh_key_modifier_rsa (const char *elems
, gcry_mpi_t
*mpis
)
938 if (strcmp (elems
, "nedupq"))
939 /* Modifying only necessary for secret keys. */
946 if (gcry_mpi_cmp (p
, q
) > 0)
948 /* P shall be smaller then Q! Swap primes. iqmp becomes u. */
956 /* U needs to be recomputed. */
957 gcry_mpi_invm (u
, p
, q
);
964 /* Signature encoder function for RSA. */
966 ssh_signature_encoder_rsa (estream_t signature_blob
, gcry_mpi_t
*mpis
)
975 err
= gcry_mpi_aprint (GCRYMPI_FMT_USG
, &data
, &data_n
, s
);
979 err
= stream_write_string (signature_blob
, data
, data_n
);
988 /* Signature encoder function for DSA. */
990 ssh_signature_encoder_dsa (estream_t signature_blob
, gcry_mpi_t
*mpis
)
992 unsigned char buffer
[SSH_DSA_SIGNATURE_PADDING
* SSH_DSA_SIGNATURE_ELEMS
];
1000 for (i
= 0; i
< 2; i
++)
1002 err
= gcry_mpi_aprint (GCRYMPI_FMT_USG
, &data
, &data_n
, mpis
[i
]);
1006 if (data_n
> SSH_DSA_SIGNATURE_PADDING
)
1008 err
= gpg_error (GPG_ERR_INTERNAL
); /* FIXME? */
1012 memset (buffer
+ (i
* SSH_DSA_SIGNATURE_PADDING
), 0,
1013 SSH_DSA_SIGNATURE_PADDING
- data_n
);
1014 memcpy (buffer
+ (i
* SSH_DSA_SIGNATURE_PADDING
)
1015 + (SSH_DSA_SIGNATURE_PADDING
- data_n
), data
, data_n
);
1023 err
= stream_write_string (signature_blob
, buffer
, sizeof (buffer
));
1037 /* This function constructs a new S-Expression for the key identified
1038 by the KEY_SPEC, SECRET, MPIS and COMMENT, which is to be stored in
1039 *SEXP. Returns usual error code. */
1041 sexp_key_construct (gcry_sexp_t
*sexp
,
1042 ssh_key_type_spec_t key_spec
, int secret
,
1043 gcry_mpi_t
*mpis
, const char *comment
)
1045 const char *key_identifier
[] = { "public-key", "private-key" };
1046 gcry_sexp_t sexp_new
;
1047 char *sexp_template
;
1048 size_t sexp_template_n
;
1060 elems
= key_spec
.elems_sexp_order
;
1062 elems
= key_spec
.elems_key_public
;
1063 elems_n
= strlen (elems
);
1066 Calculate size for sexp_template_n:
1068 "(%s(%s<mpis>)(comment%s))" -> 20 + sizeof (<mpis>).
1073 sexp_template_n
= 20 + (elems_n
* 5);
1074 sexp_template
= xtrymalloc (sexp_template_n
);
1075 if (! sexp_template
)
1077 err
= gpg_error_from_syserror ();
1081 /* Key identifier, algorithm identifier, mpis, comment. */
1082 arg_list
= xtrymalloc (sizeof (*arg_list
) * (2 + elems_n
+ 1));
1085 err
= gpg_error_from_syserror ();
1090 arg_list
[i
++] = &key_identifier
[secret
];
1091 arg_list
[i
++] = &key_spec
.identifier
;
1094 sexp_template_n
= 0;
1095 sexp_template_n
= sprintf (sexp_template
+ sexp_template_n
, "(%%s(%%s");
1096 for (i
= 0; i
< elems_n
; i
++)
1098 sexp_template_n
+= sprintf (sexp_template
+ sexp_template_n
, "(%c%%m)",
1102 for (j
= 0; j
< elems_n
; j
++)
1103 if (key_spec
.elems_key_secret
[j
] == elems
[i
])
1108 arg_list
[i
+ 2] = &mpis
[j
];
1110 sexp_template_n
+= sprintf (sexp_template
+ sexp_template_n
,
1113 arg_list
[i
+ 2] = &comment
;
1115 err
= gcry_sexp_build_array (&sexp_new
, NULL
, sexp_template
, arg_list
);
1124 xfree (sexp_template
);
1129 /* This functions breaks up the key contained in the S-Expression SEXP
1130 according to KEY_SPEC. The MPIs are bundled in a newly create
1131 list, which is to be stored in MPIS; a newly allocated string
1132 holding the comment will be stored in COMMENT; SECRET will be
1133 filled with a boolean flag specifying what kind of key it is.
1134 Returns usual error code. */
1136 sexp_key_extract (gcry_sexp_t sexp
,
1137 ssh_key_type_spec_t key_spec
, int *secret
,
1138 gcry_mpi_t
**mpis
, char **comment
)
1141 gcry_sexp_t value_list
;
1142 gcry_sexp_t value_pair
;
1143 gcry_sexp_t comment_list
;
1151 gcry_mpi_t
*mpis_new
;
1157 comment_list
= NULL
;
1161 data
= gcry_sexp_nth_data (sexp
, 0, &data_n
);
1164 err
= gpg_error (GPG_ERR_INV_SEXP
);
1168 if ((data_n
== 10 && !strncmp (data
, "public-key", 10))
1169 || (data_n
== 21 && !strncmp (data
, "protected-private-key", 21))
1170 || (data_n
== 20 && !strncmp (data
, "shadowed-private-key", 20)))
1173 elems
= key_spec
.elems_key_public
;
1175 else if (data_n
== 11 && !strncmp (data
, "private-key", 11))
1178 elems
= key_spec
.elems_key_secret
;
1182 err
= gpg_error (GPG_ERR_INV_SEXP
);
1186 elems_n
= strlen (elems
);
1187 mpis_new
= xtrycalloc (elems_n
+ 1, sizeof *mpis_new
);
1190 err
= gpg_error_from_syserror ();
1194 value_list
= gcry_sexp_find_token (sexp
, key_spec
.identifier
, 0);
1197 err
= gpg_error (GPG_ERR_INV_SEXP
);
1201 for (i
= 0; i
< elems_n
; i
++)
1203 value_pair
= gcry_sexp_find_token (value_list
, elems
+ i
, 1);
1206 err
= gpg_error (GPG_ERR_INV_SEXP
);
1210 /* Note that we need to use STD format; i.e. prepend a 0x00 to
1211 indicate a positive number if the high bit is set. */
1212 mpi
= gcry_sexp_nth_mpi (value_pair
, 1, GCRYMPI_FMT_STD
);
1215 err
= gpg_error (GPG_ERR_INV_SEXP
);
1219 gcry_sexp_release (value_pair
);
1225 /* We do not require a comment sublist to be present here. */
1229 comment_list
= gcry_sexp_find_token (sexp
, "comment", 0);
1231 data
= gcry_sexp_nth_data (comment_list
, 1, &data_n
);
1238 comment_new
= make_cstring (data
, data_n
);
1241 err
= gpg_error_from_syserror ();
1246 *secret
= is_secret
;
1248 *comment
= comment_new
;
1252 gcry_sexp_release (value_list
);
1253 gcry_sexp_release (value_pair
);
1254 gcry_sexp_release (comment_list
);
1258 xfree (comment_new
);
1259 mpint_list_free (mpis_new
);
1265 /* Extract the car from SEXP, and create a newly created C-string
1266 which is to be stored in IDENTIFIER. */
1268 sexp_extract_identifier (gcry_sexp_t sexp
, char **identifier
)
1270 char *identifier_new
;
1271 gcry_sexp_t sublist
;
1276 identifier_new
= NULL
;
1279 sublist
= gcry_sexp_nth (sexp
, 1);
1282 err
= gpg_error (GPG_ERR_INV_SEXP
);
1286 data
= gcry_sexp_nth_data (sublist
, 0, &data_n
);
1289 err
= gpg_error (GPG_ERR_INV_SEXP
);
1293 identifier_new
= make_cstring (data
, data_n
);
1294 if (! identifier_new
)
1296 err
= gpg_err_code_from_errno (errno
);
1300 *identifier
= identifier_new
;
1304 gcry_sexp_release (sublist
);
1317 /* Search for a key specification entry. If SSH_NAME is not NULL,
1318 search for an entry whose "ssh_name" is equal to SSH_NAME;
1319 otherwise, search for an entry whose "name" is equal to NAME.
1320 Store found entry in SPEC on success, return error otherwise. */
1322 ssh_key_type_lookup (const char *ssh_name
, const char *name
,
1323 ssh_key_type_spec_t
*spec
)
1328 for (i
= 0; i
< DIM (ssh_key_types
); i
++)
1329 if ((ssh_name
&& (! strcmp (ssh_name
, ssh_key_types
[i
].ssh_identifier
)))
1330 || (name
&& (! strcmp (name
, ssh_key_types
[i
].identifier
))))
1333 if (i
== DIM (ssh_key_types
))
1334 err
= gpg_error (GPG_ERR_NOT_FOUND
);
1337 *spec
= ssh_key_types
[i
];
1344 /* Receive a key from STREAM, according to the key specification given
1345 as KEY_SPEC. Depending on SECRET, receive a secret or a public
1346 key. If READ_COMMENT is true, receive a comment string as well.
1347 Constructs a new S-Expression from received data and stores it in
1348 KEY_NEW. Returns zero on success or an error code. */
1350 ssh_receive_key (estream_t stream
, gcry_sexp_t
*key_new
, int secret
,
1351 int read_comment
, ssh_key_type_spec_t
*key_spec
)
1357 ssh_key_type_spec_t spec
;
1358 gcry_mpi_t
*mpi_list
;
1366 err
= stream_read_cstring (stream
, &key_type
);
1370 err
= ssh_key_type_lookup (key_type
, NULL
, &spec
);
1374 err
= ssh_receive_mpint_list (stream
, secret
, spec
, &mpi_list
);
1380 err
= stream_read_cstring (stream
, &comment
);
1386 elems
= spec
.elems_key_secret
;
1388 elems
= spec
.elems_key_public
;
1390 if (spec
.key_modifier
)
1392 err
= (*spec
.key_modifier
) (elems
, mpi_list
);
1397 err
= sexp_key_construct (&key
, spec
, secret
, mpi_list
, comment
);
1407 mpint_list_free (mpi_list
);
1415 /* Converts a key of type TYPE, whose key material is given in MPIS,
1416 into a newly created binary blob, which is to be stored in
1417 BLOB/BLOB_SIZE. Returns zero on success or an error code. */
1419 ssh_convert_key_to_blob (unsigned char **blob
, size_t *blob_size
,
1420 const char *type
, gcry_mpi_t
*mpis
)
1422 unsigned char *blob_new
;
1423 long int blob_size_new
;
1435 stream
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
1438 err
= gpg_error_from_syserror ();
1442 err
= stream_write_cstring (stream
, type
);
1446 for (i
= 0; mpis
[i
] && (! err
); i
++)
1447 err
= stream_write_mpi (stream
, mpis
[i
]);
1451 blob_size_new
= es_ftell (stream
);
1452 if (blob_size_new
== -1)
1454 err
= gpg_error_from_syserror ();
1458 err
= es_fseek (stream
, 0, SEEK_SET
);
1462 blob_new
= xtrymalloc (blob_size_new
);
1465 err
= gpg_error_from_syserror ();
1469 err
= stream_read_data (stream
, blob_new
, blob_size_new
);
1474 *blob_size
= blob_size_new
;
1487 /* Write the public key KEY_PUBLIC to STREAM in SSH key format. If
1488 OVERRIDE_COMMENT is not NULL, it will be used instead of the
1489 comment stored in the key. */
1491 ssh_send_key_public (estream_t stream
, gcry_sexp_t key_public
,
1492 const char *override_comment
)
1494 ssh_key_type_spec_t spec
;
1495 gcry_mpi_t
*mpi_list
;
1498 unsigned char *blob
;
1507 err
= sexp_extract_identifier (key_public
, &key_type
);
1511 err
= ssh_key_type_lookup (NULL
, key_type
, &spec
);
1515 err
= sexp_key_extract (key_public
, spec
, NULL
, &mpi_list
, &comment
);
1519 err
= ssh_convert_key_to_blob (&blob
, &blob_n
,
1520 spec
.ssh_identifier
, mpi_list
);
1524 err
= stream_write_string (stream
, blob
, blob_n
);
1528 err
= stream_write_cstring (stream
,
1529 override_comment
? override_comment
: comment
);
1533 mpint_list_free (mpi_list
);
1541 /* Read a public key out of BLOB/BLOB_SIZE according to the key
1542 specification given as KEY_SPEC, storing the new key in KEY_PUBLIC.
1543 Returns zero on success or an error code. */
1545 ssh_read_key_public_from_blob (unsigned char *blob
, size_t blob_size
,
1546 gcry_sexp_t
*key_public
,
1547 ssh_key_type_spec_t
*key_spec
)
1549 estream_t blob_stream
;
1554 blob_stream
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
1557 err
= gpg_error_from_syserror ();
1561 err
= stream_write_data (blob_stream
, blob
, blob_size
);
1565 err
= es_fseek (blob_stream
, 0, SEEK_SET
);
1569 err
= ssh_receive_key (blob_stream
, key_public
, 0, 0, key_spec
);
1574 es_fclose (blob_stream
);
1581 /* This function calculates the key grip for the key contained in the
1582 S-Expression KEY and writes it to BUFFER, which must be large
1583 enough to hold it. Returns usual error code. */
1585 ssh_key_grip (gcry_sexp_t key
, unsigned char *buffer
)
1587 if (!gcry_pk_get_keygrip (key
, buffer
))
1588 return gpg_error (GPG_ERR_INTERNAL
);
1593 /* Converts the secret key KEY_SECRET into a public key, storing it in
1594 KEY_PUBLIC. SPEC is the according key specification. Returns zero
1595 on success or an error code. */
1597 key_secret_to_public (gcry_sexp_t
*key_public
,
1598 ssh_key_type_spec_t spec
, gcry_sexp_t key_secret
)
1608 err
= sexp_key_extract (key_secret
, spec
, &is_secret
, &mpis
, &comment
);
1612 err
= sexp_key_construct (key_public
, spec
, 0, mpis
, comment
);
1616 mpint_list_free (mpis
);
1623 /* Check whether a smartcard is available and whether it has a usable
1624 key. Store a copy of that key at R_PK and return 0. If no key is
1625 available store NULL at R_PK and return an error code. If CARDSN
1626 is not NULL, a string with the serial number of the card will be
1627 a malloced and stored there. */
1629 card_key_available (ctrl_t ctrl
, gcry_sexp_t
*r_pk
, char **cardsn
)
1633 char *serialno
= NULL
;
1634 unsigned char *pkbuf
;
1637 unsigned char grip
[20];
1643 /* First see whether a card is available and whether the application
1645 err
= agent_card_getattr (ctrl
, "$AUTHKEYID", &authkeyid
);
1646 if ( gpg_err_code (err
) == GPG_ERR_CARD_REMOVED
)
1648 /* Ask for the serial number to reset the card. */
1649 err
= agent_card_serialno (ctrl
, &serialno
);
1653 log_info (_("error getting serial number of card: %s\n"),
1654 gpg_strerror (err
));
1657 log_info (_("detected card with S/N: %s\n"), serialno
);
1658 err
= agent_card_getattr (ctrl
, "$AUTHKEYID", &authkeyid
);
1662 log_error (_("error getting default authentication keyID of card: %s\n"),
1663 gpg_strerror (err
));
1668 /* Get the S/N if we don't have it yet. Use the fast getattr method. */
1669 if (!serialno
&& (err
= agent_card_getattr (ctrl
, "SERIALNO", &serialno
)) )
1671 log_error (_("error getting serial number of card: %s\n"),
1672 gpg_strerror (err
));
1677 /* Read the public key. */
1678 err
= agent_card_readkey (ctrl
, authkeyid
, &pkbuf
);
1682 log_info (_("no suitable card key found: %s\n"), gpg_strerror (err
));
1688 pkbuflen
= gcry_sexp_canon_len (pkbuf
, 0, NULL
, NULL
);
1689 err
= gcry_sexp_sscan (&s_pk
, NULL
, (char*)pkbuf
, pkbuflen
);
1692 log_error ("failed to build S-Exp from received card key: %s\n",
1693 gpg_strerror (err
));
1700 err
= ssh_key_grip (s_pk
, grip
);
1703 log_debug ("error computing keygrip from received card key: %s\n",
1704 gcry_strerror (err
));
1706 gcry_sexp_release (s_pk
);
1712 if ( agent_key_available (grip
) )
1714 /* (Shadow)-key is not available in our key storage. */
1715 unsigned char *shadow_info
;
1718 shadow_info
= make_shadow_info (serialno
, authkeyid
);
1721 err
= gpg_error_from_syserror ();
1723 gcry_sexp_release (s_pk
);
1728 err
= agent_shadow_key (pkbuf
, shadow_info
, &tmp
);
1729 xfree (shadow_info
);
1732 log_error (_("shadowing the key failed: %s\n"), gpg_strerror (err
));
1734 gcry_sexp_release (s_pk
);
1741 pkbuflen
= gcry_sexp_canon_len (pkbuf
, 0, NULL
, NULL
);
1744 err
= agent_write_private_key (grip
, pkbuf
, pkbuflen
, 0);
1747 log_error (_("error writing key: %s\n"), gpg_strerror (err
));
1749 gcry_sexp_release (s_pk
);
1760 /* If the card handler is able to return a short serialnumber,
1761 use that one, else use the complete serialno. */
1762 if (!agent_card_getattr (ctrl
, "$DISPSERIALNO", &dispsn
))
1764 *cardsn
= xtryasprintf ("cardno:%s", dispsn
);
1768 *cardsn
= xtryasprintf ("cardno:%s", serialno
);
1771 err
= gpg_error_from_syserror ();
1773 gcry_sexp_release (s_pk
);
1792 Request handler. Each handler is provided with a CTRL context, a
1793 REQUEST object and a RESPONSE object. The actual request is to be
1794 read from REQUEST, the response needs to be written to RESPONSE.
1799 /* Handler for the "request_identities" command. */
1801 ssh_handler_request_identities (ctrl_t ctrl
,
1802 estream_t request
, estream_t response
)
1805 ssh_key_type_spec_t spec
;
1806 struct dirent
*dir_entry
;
1807 char *key_directory
;
1808 size_t key_directory_n
;
1810 unsigned char *buffer
;
1813 estream_t key_blobs
;
1814 gcry_sexp_t key_secret
;
1815 gcry_sexp_t key_public
;
1819 FILE *ctrl_fp
= NULL
;
1821 gpg_error_t ret_err
;
1825 /* Prepare buffer stream. */
1827 key_directory
= NULL
;
1837 key_blobs
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
1840 err
= gpg_error_from_syserror ();
1844 /* Open key directory. */
1845 key_directory
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, NULL
);
1846 if (! key_directory
)
1848 err
= gpg_err_code_from_errno (errno
);
1851 key_directory_n
= strlen (key_directory
);
1853 key_path
= xtrymalloc (key_directory_n
+ 46);
1856 err
= gpg_err_code_from_errno (errno
);
1860 sprintf (key_path
, "%s/", key_directory
);
1861 sprintf (key_path
+ key_directory_n
+ 41, ".key");
1863 dir
= opendir (key_directory
);
1866 err
= gpg_err_code_from_errno (errno
);
1872 /* First check whether a key is currently available in the card
1873 reader - this should be allowed even without being listed in
1876 if (!card_key_available (ctrl
, &key_public
, &cardsn
))
1878 err
= ssh_send_key_public (key_blobs
, key_public
, cardsn
);
1879 gcry_sexp_release (key_public
);
1889 /* Then look at all the registered an allowed keys. */
1892 /* Fixme: We should better iterate over the control file and check
1893 whether the key file is there. This is better in resepct to
1894 performance if tehre are a lot of key sin our key storage. */
1895 /* FIXME: make sure that buffer gets deallocated properly. */
1896 err
= open_control_file (&ctrl_fp
, 0);
1900 while ( (dir_entry
= readdir (dir
)) )
1902 if ((strlen (dir_entry
->d_name
) == 44)
1903 && (! strncmp (dir_entry
->d_name
+ 40, ".key", 4)))
1908 /* We do only want to return keys listed in our control
1910 strncpy (hexgrip
, dir_entry
->d_name
, 40);
1912 if ( strlen (hexgrip
) != 40 )
1914 if (search_control_file (ctrl_fp
, hexgrip
, &disabled
, NULL
)
1918 strncpy (key_path
+ key_directory_n
+ 1, dir_entry
->d_name
, 40);
1920 /* Read file content. */
1921 err
= file_to_buffer (key_path
, &buffer
, &buffer_n
);
1925 err
= gcry_sexp_sscan (&key_secret
, NULL
, (char*)buffer
, buffer_n
);
1932 err
= sexp_extract_identifier (key_secret
, &key_type
);
1936 err
= ssh_key_type_lookup (NULL
, key_type
, &spec
);
1943 err
= key_secret_to_public (&key_public
, spec
, key_secret
);
1947 gcry_sexp_release (key_secret
);
1950 err
= ssh_send_key_public (key_blobs
, key_public
, NULL
);
1954 gcry_sexp_release (key_public
);
1961 ret
= es_fseek (key_blobs
, 0, SEEK_SET
);
1964 err
= gpg_error_from_syserror ();
1970 /* Send response. */
1972 gcry_sexp_release (key_secret
);
1973 gcry_sexp_release (key_public
);
1977 ret_err
= stream_write_byte (response
, SSH_RESPONSE_IDENTITIES_ANSWER
);
1980 ret_err
= stream_write_uint32 (response
, key_counter
);
1983 ret_err
= stream_copy (response
, key_blobs
);
1989 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
1996 es_fclose (key_blobs
);
2003 xfree (key_directory
);
2012 /* This function hashes the data contained in DATA of size DATA_N
2013 according to the message digest algorithm specified by MD_ALGORITHM
2014 and writes the message digest to HASH, which needs to large enough
2017 data_hash (unsigned char *data
, size_t data_n
,
2018 int md_algorithm
, unsigned char *hash
)
2020 gcry_md_hash_buffer (md_algorithm
, hash
, data
, data_n
);
2025 /* This function signs the data contained in CTRL, stores the created
2026 signature in newly allocated memory in SIG and it's size in SIG_N;
2027 SIG_ENCODER is the signature encoder to use. */
2029 data_sign (ctrl_t ctrl
, ssh_signature_encoder_t sig_encoder
,
2030 unsigned char **sig
, size_t *sig_n
)
2033 gcry_sexp_t signature_sexp
= NULL
;
2034 estream_t stream
= NULL
;
2035 gcry_sexp_t valuelist
= NULL
;
2036 gcry_sexp_t sublist
= NULL
;
2037 gcry_mpi_t sig_value
= NULL
;
2038 unsigned char *sig_blob
= NULL
;
2039 size_t sig_blob_n
= 0;
2040 char *identifier
= NULL
;
2041 const char *identifier_raw
;
2042 size_t identifier_n
;
2043 ssh_key_type_spec_t spec
;
2048 gcry_mpi_t
*mpis
= NULL
;
2053 ctrl
->use_auth_call
= 1;
2054 err
= agent_pksign_do (ctrl
,
2055 _("Please enter the passphrase "
2056 "for the ssh key%0A %c"), &signature_sexp
,
2057 CACHE_MODE_SSH
, ttl_from_sshcontrol
);
2058 ctrl
->use_auth_call
= 0;
2062 valuelist
= gcry_sexp_nth (signature_sexp
, 1);
2065 err
= gpg_error (GPG_ERR_INV_SEXP
);
2069 stream
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
2072 err
= gpg_error_from_syserror ();
2076 identifier_raw
= gcry_sexp_nth_data (valuelist
, 0, &identifier_n
);
2077 if (! identifier_raw
)
2079 err
= gpg_error (GPG_ERR_INV_SEXP
);
2083 identifier
= make_cstring (identifier_raw
, identifier_n
);
2086 err
= gpg_error_from_syserror ();
2090 err
= ssh_key_type_lookup (NULL
, identifier
, &spec
);
2094 err
= stream_write_cstring (stream
, spec
.ssh_identifier
);
2098 elems
= spec
.elems_signature
;
2099 elems_n
= strlen (elems
);
2101 mpis
= xtrycalloc (elems_n
+ 1, sizeof *mpis
);
2104 err
= gpg_error_from_syserror ();
2108 for (i
= 0; i
< elems_n
; i
++)
2110 sublist
= gcry_sexp_find_token (valuelist
, spec
.elems_signature
+ i
, 1);
2113 err
= gpg_error (GPG_ERR_INV_SEXP
);
2117 sig_value
= gcry_sexp_nth_mpi (sublist
, 1, GCRYMPI_FMT_USG
);
2120 err
= gpg_error (GPG_ERR_INTERNAL
); /* FIXME? */
2123 gcry_sexp_release (sublist
);
2126 mpis
[i
] = sig_value
;
2131 err
= (*sig_encoder
) (stream
, mpis
);
2135 sig_blob_n
= es_ftell (stream
);
2136 if (sig_blob_n
== -1)
2138 err
= gpg_error_from_syserror ();
2142 sig_blob
= xtrymalloc (sig_blob_n
);
2145 err
= gpg_error_from_syserror ();
2149 ret
= es_fseek (stream
, 0, SEEK_SET
);
2152 err
= gpg_error_from_syserror ();
2156 err
= stream_read_data (stream
, sig_blob
, sig_blob_n
);
2161 *sig_n
= sig_blob_n
;
2170 gcry_sexp_release (valuelist
);
2171 gcry_sexp_release (signature_sexp
);
2172 gcry_sexp_release (sublist
);
2173 mpint_list_free (mpis
);
2179 /* Handler for the "sign_request" command. */
2181 ssh_handler_sign_request (ctrl_t ctrl
, estream_t request
, estream_t response
)
2184 ssh_key_type_spec_t spec
;
2185 unsigned char hash
[MAX_DIGEST_LEN
];
2186 unsigned int hash_n
;
2187 unsigned char key_grip
[20];
2188 unsigned char *key_blob
;
2190 unsigned char *data
;
2196 gpg_error_t ret_err
;
2205 err
= stream_read_string (request
, 0, &key_blob
, &key_blob_size
);
2209 err
= ssh_read_key_public_from_blob (key_blob
, key_blob_size
, &key
, &spec
);
2213 /* Receive data to sign. */
2214 err
= stream_read_string (request
, 0, &data
, &data_size
);
2219 err
= stream_read_uint32 (request
, &flags
);
2224 hash_n
= gcry_md_get_algo_dlen (GCRY_MD_SHA1
);
2227 err
= gpg_error (GPG_ERR_INTERNAL
);
2230 err
= data_hash (data
, data_size
, GCRY_MD_SHA1
, hash
);
2234 /* Calculate key grip. */
2235 err
= ssh_key_grip (key
, key_grip
);
2241 ctrl
->digest
.algo
= GCRY_MD_SHA1
;
2242 memcpy (ctrl
->digest
.value
, hash
, hash_n
);
2243 ctrl
->digest
.valuelen
= hash_n
;
2244 ctrl
->digest
.raw_value
= ! (spec
.flags
& SPEC_FLAG_USE_PKCS1V2
);
2245 ctrl
->have_keygrip
= 1;
2246 memcpy (ctrl
->keygrip
, key_grip
, 20);
2248 err
= data_sign (ctrl
, spec
.signature_encoder
, &sig
, &sig_n
);
2256 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SIGN_RESPONSE
);
2259 ret_err
= stream_write_string (response
, sig
, sig_n
);
2265 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2272 gcry_sexp_release (key
);
2280 /* This function extracts the comment contained in the key
2281 S-Expression KEY and stores a copy in COMMENT. Returns usual error
2284 ssh_key_extract_comment (gcry_sexp_t key
, char **comment
)
2286 gcry_sexp_t comment_list
;
2292 comment_list
= gcry_sexp_find_token (key
, "comment", 0);
2295 err
= gpg_error (GPG_ERR_INV_SEXP
);
2299 data
= gcry_sexp_nth_data (comment_list
, 1, &data_n
);
2302 err
= gpg_error (GPG_ERR_INV_SEXP
);
2306 comment_new
= make_cstring (data
, data_n
);
2309 err
= gpg_error_from_syserror ();
2313 *comment
= comment_new
;
2318 gcry_sexp_release (comment_list
);
2323 /* This function converts the key contained in the S-Expression KEY
2324 into a buffer, which is protected by the passphrase PASSPHRASE.
2325 Returns usual error code. */
2327 ssh_key_to_protected_buffer (gcry_sexp_t key
, const char *passphrase
,
2328 unsigned char **buffer
, size_t *buffer_n
)
2330 unsigned char *buffer_new
;
2331 unsigned int buffer_new_n
;
2335 buffer_new_n
= gcry_sexp_sprint (key
, GCRYSEXP_FMT_CANON
, NULL
, 0);
2336 buffer_new
= xtrymalloc_secure (buffer_new_n
);
2339 err
= gpg_error_from_syserror ();
2343 gcry_sexp_sprint (key
, GCRYSEXP_FMT_CANON
, buffer_new
, buffer_new_n
);
2344 /* FIXME: guarantee? */
2346 err
= agent_protect (buffer_new
, passphrase
, buffer
, buffer_n
);
2357 /* Callback function to compare the first entered PIN with the one
2358 currently being entered. */
2360 reenter_compare_cb (struct pin_entry_info_s
*pi
)
2362 const char *pin1
= pi
->check_cb_arg
;
2364 if (!strcmp (pin1
, pi
->pin
))
2365 return 0; /* okay */
2369 /* Store the ssh KEY into our local key storage and protect it after
2370 asking for a passphrase. Cache that passphrase. TTL is the
2371 maximum caching time for that key. If the key already exists in
2372 our key storage, don't do anything. When entering a new key also
2373 add an entry to the sshcontrol file. */
2375 ssh_identity_register (ctrl_t ctrl
, gcry_sexp_t key
, int ttl
)
2378 unsigned char key_grip_raw
[20];
2380 unsigned char *buffer
= NULL
;
2382 char *description
= NULL
;
2383 const char *description2
= _("Please re-enter this passphrase");
2384 char *comment
= NULL
;
2385 const char *initial_errtext
= NULL
;
2387 struct pin_entry_info_s
*pi
= NULL
, *pi2
;
2389 err
= ssh_key_grip (key
, key_grip_raw
);
2393 /* Check whether the key is already in our key storage. Don't do
2395 if ( !agent_key_available (key_grip_raw
) )
2396 goto out
; /* Yes, key is available. */
2399 err
= ssh_key_extract_comment (key
, &comment
);
2403 if ( asprintf (&description
,
2404 _("Please enter a passphrase to protect"
2405 " the received secret key%%0A"
2407 "within gpg-agent's key storage"),
2408 comment
? comment
: "?") < 0)
2410 err
= gpg_error_from_syserror ();
2415 pi
= gcry_calloc_secure (2, sizeof (*pi
) + 100 + 1);
2418 err
= gpg_error_from_syserror ();
2421 pi2
= pi
+ (sizeof *pi
+ 100 + 1);
2422 pi
->max_length
= 100;
2424 pi2
->max_length
= 100;
2426 pi2
->check_cb
= reenter_compare_cb
;
2427 pi2
->check_cb_arg
= pi
->pin
;
2430 err
= agent_askpin (ctrl
, description
, NULL
, initial_errtext
, pi
);
2431 initial_errtext
= NULL
;
2435 /* Unless the passphrase is empty, ask to confirm it. */
2436 if (pi
->pin
&& *pi
->pin
)
2438 err
= agent_askpin (ctrl
, description2
, NULL
, NULL
, pi2
);
2440 { /* The re-entered one did not match and the user did not
2442 initial_errtext
= _("does not match - try again");
2447 err
= ssh_key_to_protected_buffer (key
, pi
->pin
, &buffer
, &buffer_n
);
2451 /* Store this key to our key storage. */
2452 err
= agent_write_private_key (key_grip_raw
, buffer
, buffer_n
, 0);
2456 /* Cache this passphrase. */
2457 for (i
= 0; i
< 20; i
++)
2458 sprintf (key_grip
+ 2 * i
, "%02X", key_grip_raw
[i
]);
2460 err
= agent_put_cache (key_grip
, CACHE_MODE_SSH
, pi
->pin
, ttl
);
2464 /* And add an entry to the sshcontrol file. */
2465 err
= add_control_entry (ctrl
, key_grip
, ttl
);
2469 if (pi
&& pi
->max_length
)
2470 wipememory (pi
->pin
, pi
->max_length
);
2474 xfree (description
);
2480 /* This function removes the key contained in the S-Expression KEY
2481 from the local key storage, in case it exists there. Returns usual
2482 error code. FIXME: this function is a stub. */
2484 ssh_identity_drop (gcry_sexp_t key
)
2486 unsigned char key_grip
[21] = { 0 };
2489 err
= ssh_key_grip (key
, key_grip
);
2493 key_grip
[sizeof (key_grip
) - 1] = 0;
2495 /* FIXME: What to do here - forgetting the passphrase or deleting
2496 the key from key cache? */
2503 /* Handler for the "add_identity" command. */
2505 ssh_handler_add_identity (ctrl_t ctrl
, estream_t request
, estream_t response
)
2507 gpg_error_t ret_err
;
2519 err
= ssh_receive_key (request
, &key
, 1, 1, NULL
);
2525 err
= stream_read_byte (request
, &b
);
2526 if (gpg_err_code (err
) == GPG_ERR_EOF
)
2534 case SSH_OPT_CONSTRAIN_LIFETIME
:
2538 err
= stream_read_uint32 (request
, &n
);
2544 case SSH_OPT_CONSTRAIN_CONFIRM
:
2551 /* FIXME: log/bad? */
2558 /* FIXME: are constraints used correctly? */
2560 err
= ssh_identity_register (ctrl
, key
, ttl
);
2564 gcry_sexp_release (key
);
2567 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2569 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2574 /* Handler for the "remove_identity" command. */
2576 ssh_handler_remove_identity (ctrl_t ctrl
,
2577 estream_t request
, estream_t response
)
2579 unsigned char *key_blob
;
2582 gpg_error_t ret_err
;
2592 err
= stream_read_string (request
, 0, &key_blob
, &key_blob_size
);
2596 err
= ssh_read_key_public_from_blob (key_blob
, key_blob_size
, &key
, NULL
);
2600 err
= ssh_identity_drop (key
);
2605 gcry_sexp_release (key
);
2608 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2610 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2615 /* FIXME: stub function. Actually useful? */
2617 ssh_identities_remove_all (void)
2623 /* FIXME: shall we remove _all_ cache entries or only those
2624 registered through the ssh emulation? */
2629 /* Handler for the "remove_all_identities" command. */
2631 ssh_handler_remove_all_identities (ctrl_t ctrl
,
2632 estream_t request
, estream_t response
)
2634 gpg_error_t ret_err
;
2640 err
= ssh_identities_remove_all ();
2643 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2645 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2650 /* Lock agent? FIXME: stub function. */
2657 log_error ("ssh-agent's lock command is not implemented\n");
2663 /* Unock agent? FIXME: stub function. */
2669 log_error ("ssh-agent's unlock command is not implemented\n");
2675 /* Handler for the "lock" command. */
2677 ssh_handler_lock (ctrl_t ctrl
, estream_t request
, estream_t response
)
2679 gpg_error_t ret_err
;
2688 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2690 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2695 /* Handler for the "unlock" command. */
2697 ssh_handler_unlock (ctrl_t ctrl
, estream_t request
, estream_t response
)
2699 gpg_error_t ret_err
;
2705 err
= ssh_unlock ();
2708 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2710 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2717 /* Return the request specification for the request identified by TYPE
2718 or NULL in case the requested request specification could not be
2720 static ssh_request_spec_t
*
2721 request_spec_lookup (int type
)
2723 ssh_request_spec_t
*spec
;
2726 for (i
= 0; i
< DIM (request_specs
); i
++)
2727 if (request_specs
[i
].type
== type
)
2729 if (i
== DIM (request_specs
))
2732 log_info ("ssh request %u is not supported\n", type
);
2736 spec
= request_specs
+ i
;
2741 /* Process a single request. The request is read from and the
2742 response is written to STREAM_SOCK. Uses CTRL as context. Returns
2743 zero in case of success, non zero in case of failure. */
2745 ssh_request_process (ctrl_t ctrl
, estream_t stream_sock
)
2747 ssh_request_spec_t
*spec
;
2750 unsigned char request_type
;
2754 unsigned char *request_data
;
2755 u32 request_data_size
;
2758 request_data
= NULL
;
2763 /* Create memory streams for request/response data. The entire
2764 request will be stored in secure memory, since it might contain
2765 secret key material. The response does not have to be stored in
2766 secure memory, since we never give out secret keys.
2768 Note: we only have little secure memory, but there is NO
2769 possibility of DoS here; only trusted clients are allowed to
2770 connect to the agent. What could happen is that the agent
2771 returns out-of-secure-memory errors on requests in case the
2772 agent's owner floods his own agent with many large messages.
2775 /* Retrieve request. */
2776 err
= stream_read_string (stream_sock
, 1, &request_data
, &request_data_size
);
2780 if (opt
.verbose
> 1)
2781 log_info ("received ssh request of length %u\n",
2782 (unsigned int)request_data_size
);
2784 if (! request_data_size
)
2788 /* Broken request; FIXME. */
2791 request_type
= request_data
[0];
2792 spec
= request_spec_lookup (request_type
);
2797 /* Unknown request; FIXME. */
2800 if (spec
->secret_input
)
2801 request
= es_mopen (NULL
, 0, 0, 1, realloc_secure
, gcry_free
, "r+");
2803 request
= es_mopen (NULL
, 0, 0, 1, gcry_realloc
, gcry_free
, "r+");
2806 err
= gpg_error_from_syserror ();
2809 ret
= es_setvbuf (request
, NULL
, _IONBF
, 0);
2812 err
= gpg_error_from_syserror ();
2815 err
= stream_write_data (request
, request_data
+ 1, request_data_size
- 1);
2818 es_rewind (request
);
2820 response
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
2823 err
= gpg_error_from_syserror ();
2828 log_info ("ssh request handler for %s (%u) started\n",
2829 spec
->identifier
, spec
->type
);
2831 err
= (*spec
->handler
) (ctrl
, request
, response
);
2836 log_info ("ssh request handler for %s (%u) failed: %s\n",
2837 spec
->identifier
, spec
->type
, gpg_strerror (err
));
2839 log_info ("ssh request handler for %s (%u) ready\n",
2840 spec
->identifier
, spec
->type
);
2849 response_size
= es_ftell (response
);
2850 if (opt
.verbose
> 1)
2851 log_info ("sending ssh response of length %u\n",
2852 (unsigned int)response_size
);
2854 err
= es_fseek (response
, 0, SEEK_SET
);
2861 err
= stream_write_uint32 (stream_sock
, response_size
);
2868 err
= stream_copy (stream_sock
, response
);
2872 err
= es_fflush (stream_sock
);
2878 if (err
&& es_feof (stream_sock
))
2879 log_error ("error occured while processing request: %s\n",
2880 gpg_strerror (err
));
2884 if (opt
.verbose
> 1)
2885 log_info ("sending ssh error response\n");
2886 err
= stream_write_uint32 (stream_sock
, 1);
2889 err
= stream_write_byte (stream_sock
, SSH_RESPONSE_FAILURE
);
2897 es_fclose (request
);
2899 es_fclose (response
);
2900 xfree (request_data
); /* FIXME? */
2905 /* Start serving client on SOCK_CLIENT. */
2907 start_command_handler_ssh (ctrl_t ctrl
, gnupg_fd_t sock_client
)
2909 estream_t stream_sock
= NULL
;
2910 gpg_error_t err
= 0;
2913 /* Because the ssh protocol does not send us information about the
2914 the current TTY setting, we resort here to use those from startup
2915 or those explictly set. */
2917 static const char *names
[] =
2918 {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL
};
2922 for (idx
=0; !err
&& names
[idx
]; idx
++)
2923 if (!session_env_getenv (ctrl
->session_env
, names
[idx
])
2924 && (value
= session_env_getenv (opt
.startup_env
, names
[idx
])))
2925 err
= session_env_setenv (ctrl
->session_env
, names
[idx
], value
);
2927 if (!err
&& !ctrl
->lc_ctype
&& opt
.startup_lc_ctype
)
2928 if (!(ctrl
->lc_ctype
= xtrystrdup (opt
.startup_lc_ctype
)))
2929 err
= gpg_error_from_syserror ();
2931 if (!err
&& !ctrl
->lc_messages
&& opt
.startup_lc_messages
)
2932 if (!(ctrl
->lc_messages
= xtrystrdup (opt
.startup_lc_messages
)))
2933 err
= gpg_error_from_syserror ();
2937 log_error ("error setting default session environment: %s\n",
2938 gpg_strerror (err
));
2944 /* Create stream from socket. */
2945 stream_sock
= es_fdopen (FD2INT(sock_client
), "r+");
2948 err
= gpg_error_from_syserror ();
2949 log_error (_("failed to create stream from socket: %s\n"),
2950 gpg_strerror (err
));
2953 /* We have to disable the estream buffering, because the estream
2954 core doesn't know about secure memory. */
2955 ret
= es_setvbuf (stream_sock
, NULL
, _IONBF
, 0);
2958 err
= gpg_error_from_syserror ();
2959 log_error ("failed to disable buffering "
2960 "on socket stream: %s\n", gpg_strerror (err
));
2964 /* Main processing loop. */
2965 while ( !ssh_request_process (ctrl
, stream_sock
) )
2967 /* Check wether we have reached EOF before trying to read
2971 c
= es_fgetc (stream_sock
);
2974 es_ungetc (c
, stream_sock
);
2977 /* Reset the SCD in case it has been used. */
2978 agent_reset_scd (ctrl
);
2983 es_fclose (stream_sock
);