1 /* command-ssh.c - gpg-agent's ssh-agent emulation layer
2 * Copyright (C) 2004, 2005, 2006 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,
22 /* Only v2 of the ssh-agent protocol is implemented. */
30 #include <sys/types.h>
43 #define SSH_REQUEST_REQUEST_IDENTITIES 11
44 #define SSH_REQUEST_SIGN_REQUEST 13
45 #define SSH_REQUEST_ADD_IDENTITY 17
46 #define SSH_REQUEST_REMOVE_IDENTITY 18
47 #define SSH_REQUEST_REMOVE_ALL_IDENTITIES 19
48 #define SSH_REQUEST_LOCK 22
49 #define SSH_REQUEST_UNLOCK 23
50 #define SSH_REQUEST_ADD_ID_CONSTRAINED 25
53 #define SSH_OPT_CONSTRAIN_LIFETIME 1
54 #define SSH_OPT_CONSTRAIN_CONFIRM 2
57 #define SSH_RESPONSE_SUCCESS 6
58 #define SSH_RESPONSE_FAILURE 5
59 #define SSH_RESPONSE_IDENTITIES_ANSWER 12
60 #define SSH_RESPONSE_SIGN_RESPONSE 14
62 /* Other constants. */
63 #define SSH_DSA_SIGNATURE_PADDING 20
64 #define SSH_DSA_SIGNATURE_ELEMS 2
65 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0)
68 /* The blurb we put into the header of a newly created control file. */
69 static const char sshcontrolblurb
[] =
70 "# List of allowed ssh keys. Only keys present in this file are used\n"
71 "# in the SSH protocol. The ssh-add tool may add new entries to this\n"
72 "# file to enable them; you may also add them manually. Comment\n"
73 "# lines, like this one, as well as empty lines are ignored. Lines do\n"
74 "# have a certain length limit but this is not serious limitation as\n"
75 "# the format of the entries is fixed and checked by gpg-agent. A\n"
76 "# non-comment line starts with optional white spaces, followed by the\n"
77 "# keygrip of the key given as 40 hex digits, optionally followed by a\n"
78 "# the caching TTL in seconds and another optional field for arbitrary\n"
79 "# flags. Prepend the keygrip with an '!' mark to disable it.\n"
86 /* Return a new uint32 with b0 being the most significant byte and b3
87 being the least significant byte. */
88 #define uint32_construct(b0, b1, b2, b3) \
89 ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3)
98 /* Type for a request handler. */
99 typedef gpg_error_t (*ssh_request_handler_t
) (ctrl_t ctrl
,
103 /* Type, which is used for associating request handlers with the
104 appropriate request IDs. */
105 typedef struct ssh_request_spec
108 ssh_request_handler_t handler
;
109 const char *identifier
;
110 unsigned int secret_input
;
111 } ssh_request_spec_t
;
113 /* Type for "key modifier functions", which are necessary since
114 OpenSSH and GnuPG treat key material slightly different. A key
115 modifier is called right after a new key identity has been received
116 in order to "sanitize" the material. */
117 typedef gpg_error_t (*ssh_key_modifier_t
) (const char *elems
,
120 /* The encoding of a generated signature is dependent on the
121 algorithm; therefore algorithm specific signature encoding
122 functions are necessary. */
123 typedef gpg_error_t (*ssh_signature_encoder_t
) (estream_t signature_blob
,
126 /* Type, which is used for boundling all the algorithm specific
127 information together in a single object. */
128 typedef struct ssh_key_type_spec
130 /* Algorithm identifier as used by OpenSSH. */
131 const char *ssh_identifier
;
133 /* Algorithm identifier as used by GnuPG. */
134 const char *identifier
;
136 /* List of MPI names for secret keys; order matches the one of the
138 const char *elems_key_secret
;
140 /* List of MPI names for public keys; order matches the one of the
142 const char *elems_key_public
;
144 /* List of MPI names for signature data. */
145 const char *elems_signature
;
147 /* List of MPI names for secret keys; order matches the one, which
148 is required by gpg-agent's key access layer. */
149 const char *elems_sexp_order
;
151 /* Key modifier function. Key modifier functions are necessary in
152 order to fix any inconsistencies between the representation of
153 keys on the SSH and on the GnuPG side. */
154 ssh_key_modifier_t key_modifier
;
156 /* Signature encoder function. Signature encoder functions are
157 necessary since the encoding of signatures depends on the used
159 ssh_signature_encoder_t signature_encoder
;
163 } ssh_key_type_spec_t
;
167 static gpg_error_t
ssh_handler_request_identities (ctrl_t ctrl
,
170 static gpg_error_t
ssh_handler_sign_request (ctrl_t ctrl
,
173 static gpg_error_t
ssh_handler_add_identity (ctrl_t ctrl
,
176 static gpg_error_t
ssh_handler_remove_identity (ctrl_t ctrl
,
179 static gpg_error_t
ssh_handler_remove_all_identities (ctrl_t ctrl
,
182 static gpg_error_t
ssh_handler_lock (ctrl_t ctrl
,
185 static gpg_error_t
ssh_handler_unlock (ctrl_t ctrl
,
189 static gpg_error_t
ssh_key_modifier_rsa (const char *elems
, gcry_mpi_t
*mpis
);
190 static gpg_error_t
ssh_signature_encoder_rsa (estream_t signature_blob
,
192 static gpg_error_t
ssh_signature_encoder_dsa (estream_t signature_blob
,
197 /* Global variables. */
200 /* Associating request types with the corresponding request
203 static ssh_request_spec_t request_specs
[] =
205 #define REQUEST_SPEC_DEFINE(id, name, secret_input) \
206 { SSH_REQUEST_##id, ssh_handler_##name, #name, secret_input }
208 REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES
, request_identities
, 1),
209 REQUEST_SPEC_DEFINE (SIGN_REQUEST
, sign_request
, 0),
210 REQUEST_SPEC_DEFINE (ADD_IDENTITY
, add_identity
, 1),
211 REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED
, add_identity
, 1),
212 REQUEST_SPEC_DEFINE (REMOVE_IDENTITY
, remove_identity
, 0),
213 REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES
, remove_all_identities
, 0),
214 REQUEST_SPEC_DEFINE (LOCK
, lock
, 0),
215 REQUEST_SPEC_DEFINE (UNLOCK
, unlock
, 0)
216 #undef REQUEST_SPEC_DEFINE
220 /* Table holding key type specifications. */
221 static ssh_key_type_spec_t ssh_key_types
[] =
224 "ssh-rsa", "rsa", "nedupq", "en", "s", "nedpqu",
225 ssh_key_modifier_rsa
, ssh_signature_encoder_rsa
,
226 SPEC_FLAG_USE_PKCS1V2
229 "ssh-dss", "dsa", "pqgyx", "pqgy", "rs", "pqgyx",
230 NULL
, ssh_signature_encoder_dsa
,
240 General utility functions.
243 /* A secure realloc, i.e. it makes sure to allocate secure memory if A
244 is NULL. This is required because the standard gcry_realloc does
245 not know whether to allocate secure or normal if NULL is passed as
248 realloc_secure (void *a
, size_t n
)
253 p
= gcry_realloc (a
, n
);
255 p
= gcry_malloc_secure (n
);
261 /* Create and return a new C-string from DATA/DATA_N (i.e.: add
262 NUL-termination); return NULL on OOM. */
264 make_cstring (const char *data
, size_t data_n
)
268 s
= xtrymalloc (data_n
+ 1);
271 memcpy (s
, data
, data_n
);
282 Primitive I/O functions.
286 /* Read a byte from STREAM, store it in B. */
288 stream_read_byte (estream_t stream
, unsigned char *b
)
293 ret
= es_fgetc (stream
);
296 if (es_ferror (stream
))
297 err
= gpg_error_from_syserror ();
299 err
= gpg_error (GPG_ERR_EOF
);
311 /* Write the byte contained in B to STREAM. */
313 stream_write_byte (estream_t stream
, unsigned char b
)
318 ret
= es_fputc (b
, stream
);
320 err
= gpg_error_from_syserror ();
327 /* Read a uint32 from STREAM, store it in UINT32. */
329 stream_read_uint32 (estream_t stream
, u32
*uint32
)
331 unsigned char buffer
[4];
336 ret
= es_read (stream
, buffer
, sizeof (buffer
), &bytes_read
);
338 err
= gpg_error_from_syserror ();
341 if (bytes_read
!= sizeof (buffer
))
342 err
= gpg_error (GPG_ERR_EOF
);
347 n
= uint32_construct (buffer
[0], buffer
[1], buffer
[2], buffer
[3]);
356 /* Write the uint32 contained in UINT32 to STREAM. */
358 stream_write_uint32 (estream_t stream
, u32 uint32
)
360 unsigned char buffer
[4];
364 buffer
[0] = uint32
>> 24;
365 buffer
[1] = uint32
>> 16;
366 buffer
[2] = uint32
>> 8;
367 buffer
[3] = uint32
>> 0;
369 ret
= es_write (stream
, buffer
, sizeof (buffer
), NULL
);
371 err
= gpg_error_from_syserror ();
378 /* Read SIZE bytes from STREAM into BUFFER. */
380 stream_read_data (estream_t stream
, unsigned char *buffer
, size_t size
)
386 ret
= es_read (stream
, buffer
, size
, &bytes_read
);
388 err
= gpg_error_from_syserror ();
391 if (bytes_read
!= size
)
392 err
= gpg_error (GPG_ERR_EOF
);
400 /* Write SIZE bytes from BUFFER to STREAM. */
402 stream_write_data (estream_t stream
, const unsigned char *buffer
, size_t size
)
407 ret
= es_write (stream
, buffer
, size
, NULL
);
409 err
= gpg_error_from_syserror ();
416 /* Read a binary string from STREAM into STRING, store size of string
417 in STRING_SIZE; depending on SECURE use secure memory for
420 stream_read_string (estream_t stream
, unsigned int secure
,
421 unsigned char **string
, u32
*string_size
)
424 unsigned char *buffer
;
429 /* Read string length. */
430 err
= stream_read_uint32 (stream
, &length
);
434 /* Allocate space. */
436 buffer
= xtrymalloc_secure (length
+ 1);
438 buffer
= xtrymalloc (length
+ 1);
441 err
= gpg_error_from_syserror ();
446 err
= stream_read_data (stream
, buffer
, length
);
450 /* Finalize string object. */
454 *string_size
= length
;
464 /* Read a C-string from STREAM, store copy in STRING. */
466 stream_read_cstring (estream_t stream
, char **string
)
468 unsigned char *buffer
;
471 err
= stream_read_string (stream
, 0, &buffer
, NULL
);
475 *string
= (char *) buffer
;
483 /* Write a binary string from STRING of size STRING_N to STREAM. */
485 stream_write_string (estream_t stream
,
486 const unsigned char *string
, u32 string_n
)
490 err
= stream_write_uint32 (stream
, string_n
);
494 err
= stream_write_data (stream
, string
, string_n
);
501 /* Write a C-string from STRING to STREAM. */
503 stream_write_cstring (estream_t stream
, const char *string
)
507 err
= stream_write_string (stream
,
508 (const unsigned char *) string
, strlen (string
));
513 /* Read an MPI from STREAM, store it in MPINT. Depending on SECURE
514 use secure memory. */
516 stream_read_mpi (estream_t stream
, unsigned int secure
, gcry_mpi_t
*mpint
)
518 unsigned char *mpi_data
;
525 err
= stream_read_string (stream
, secure
, &mpi_data
, &mpi_data_size
);
529 /* To avoid excessive use of secure memory we check that an MPI is
531 if (mpi_data_size
> 520)
533 log_error (_("ssh keys greater than %d bits are not supported\n"), 4096);
534 err
= GPG_ERR_TOO_LARGE
;
538 err
= gcry_mpi_scan (&mpi
, GCRYMPI_FMT_STD
, mpi_data
, mpi_data_size
, NULL
);
551 /* Write the MPI contained in MPINT to STREAM. */
553 stream_write_mpi (estream_t stream
, gcry_mpi_t mpint
)
555 unsigned char *mpi_buffer
;
561 err
= gcry_mpi_aprint (GCRYMPI_FMT_STD
, &mpi_buffer
, &mpi_buffer_n
, mpint
);
565 err
= stream_write_string (stream
, mpi_buffer
, mpi_buffer_n
);
574 /* Copy data from SRC to DST until EOF is reached. */
576 stream_copy (estream_t dst
, estream_t src
)
586 ret
= es_read (src
, buffer
, sizeof (buffer
), &bytes_read
);
587 if (ret
|| (! bytes_read
))
590 err
= gpg_error_from_syserror ();
593 ret
= es_write (dst
, buffer
, bytes_read
, NULL
);
596 err
= gpg_error_from_syserror ();
605 /* Read the content of the file specified by FILENAME into a newly
606 create buffer, which is to be stored in BUFFER; store length of
607 buffer in BUFFER_N. */
609 file_to_buffer (const char *filename
, unsigned char **buffer
, size_t *buffer_n
)
611 unsigned char *buffer_new
;
623 stream
= es_fopen (filename
, "r");
626 err
= gpg_error_from_syserror ();
630 ret
= fstat (es_fileno (stream
), &statbuf
);
633 err
= gpg_error_from_syserror ();
637 buffer_new
= xtrymalloc (statbuf
.st_size
);
640 err
= gpg_error_from_syserror ();
644 err
= stream_read_data (stream
, buffer_new
, statbuf
.st_size
);
648 *buffer
= buffer_new
;
649 *buffer_n
= statbuf
.st_size
;
665 /* Open the ssh control file and create it if not available. With
666 APPEND passed as true the file will be opened in append mode,
667 otherwise in read only mode. On success a file pointer is stored
668 at the address of R_FP. */
670 open_control_file (FILE **r_fp
, int append
)
676 /* Note: As soon as we start to use non blocking functions here
677 (i.e. where Pth might switch threads) we need to employ a
680 fname
= make_filename (opt
.homedir
, "sshcontrol", NULL
);
681 /* FIXME: With "a+" we are not able to check whether this will will
682 be created and thus the blurb needs to be written first. */
683 fp
= fopen (fname
, append
? "a+":"r");
684 if (!fp
&& errno
== ENOENT
)
686 /* Fixme: "x" is a GNU extension. We might want to use the es_
688 fp
= fopen (fname
, "wx");
691 err
= gpg_error (gpg_err_code_from_errno (errno
));
692 log_error (_("can't create `%s': %s\n"), fname
, gpg_strerror (err
));
696 fputs (sshcontrolblurb
, fp
);
698 fp
= fopen (fname
, append
? "a+":"r");
703 err
= gpg_error (gpg_err_code_from_errno (errno
));
704 log_error (_("can't open `%s': %s\n"), fname
, gpg_strerror (err
));
715 /* Search the file at stream FP from the beginning until a matching
716 HEXGRIP is found; return success in this case and store true at
717 DISABLED if the found key has been disabled. */
719 search_control_file (FILE *fp
, const char *hexgrip
, int *disabled
)
724 assert (strlen (hexgrip
) == 40 );
731 if (!fgets (line
, DIM(line
)-1, fp
) )
734 return gpg_error (GPG_ERR_EOF
);
735 return gpg_error (gpg_err_code_from_errno (errno
));
738 if (!*line
|| line
[strlen(line
)-1] != '\n')
740 /* Eat until end of line */
741 while ( (c
=getc (fp
)) != EOF
&& c
!= '\n')
743 return gpg_error (*line
? GPG_ERR_LINE_TOO_LONG
744 : GPG_ERR_INCOMPLETE_LINE
);
747 /* Allow for empty lines and spaces */
748 for (p
=line
; spacep (p
); p
++)
751 while (!*p
|| *p
== '\n' || *p
== '#');
757 for (p
++; spacep (p
); p
++)
761 for (i
=0; hexdigitp (p
) && i
< 40; p
++, i
++)
762 if (hexgrip
[i
] != (*p
>= 'a'? (*p
& 0xdf): *p
))
764 if (i
!= 40 || !(spacep (p
) || *p
== '\n'))
766 log_error ("invalid formatted line in ssh control file\n");
767 return gpg_error (GPG_ERR_BAD_DATA
);
770 /* Fixme: Get TTL and flags. */
772 return 0; /* Okay: found it. */
777 /* Add an entry to the control file to mark the key with the keygrip
778 HEXGRIP as usable for SSH; i.e. it will be returned when ssh asks
779 for it. This function is in general used to add a key received
780 through the ssh-add function. We can assume that the user wants to
781 allow ssh using this key. */
783 add_control_entry (ctrl_t ctrl
, const char *hexgrip
, int ttl
)
789 err
= open_control_file (&fp
, 1);
793 err
= search_control_file (fp
, hexgrip
, &disabled
);
794 if (err
&& gpg_err_code(err
) == GPG_ERR_EOF
)
797 time_t atime
= time (NULL
);
799 /* Not yet in the file - add it. Becuase the file has been
800 opened in append mode, we simply need to write to it. */
801 tp
= localtime (&atime
);
802 fprintf (fp
, "# Key added on %04d-%02d-%02d %02d:%02d:%02d\n%s %d\n",
803 1900+tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
,
804 tp
->tm_hour
, tp
->tm_min
, tp
->tm_sec
,
822 /* Free the list of MPIs MPI_LIST. */
824 mpint_list_free (gcry_mpi_t
*mpi_list
)
830 for (i
= 0; mpi_list
[i
]; i
++)
831 gcry_mpi_release (mpi_list
[i
]);
836 /* Receive key material MPIs from STREAM according to KEY_SPEC;
837 depending on SECRET expect a public key or secret key. The newly
838 allocated list of MPIs is stored in MPI_LIST. Returns usual error
841 ssh_receive_mpint_list (estream_t stream
, int secret
,
842 ssh_key_type_spec_t key_spec
, gcry_mpi_t
**mpi_list
)
844 unsigned int elems_public_n
;
845 const char *elems_public
;
846 unsigned int elems_n
;
857 elems
= key_spec
.elems_key_secret
;
859 elems
= key_spec
.elems_key_public
;
860 elems_n
= strlen (elems
);
862 elems_public
= key_spec
.elems_key_public
;
863 elems_public_n
= strlen (elems_public
);
865 mpis
= xtrycalloc (elems_n
+ 1, sizeof *mpis
);
868 err
= gpg_error_from_syserror ();
873 for (i
= 0; i
< elems_n
; i
++)
876 elem_is_secret
= ! strchr (elems_public
, elems
[i
]);
877 err
= stream_read_mpi (stream
, elem_is_secret
, &mpis
[i
]);
889 mpint_list_free (mpis
);
896 /* Key modifier function for RSA. */
898 ssh_key_modifier_rsa (const char *elems
, gcry_mpi_t
*mpis
)
904 if (strcmp (elems
, "nedupq"))
905 /* Modifying only necessary for secret keys. */
912 if (gcry_mpi_cmp (p
, q
) > 0)
914 /* P shall be smaller then Q! Swap primes. iqmp becomes u. */
922 /* U needs to be recomputed. */
923 gcry_mpi_invm (u
, p
, q
);
930 /* Signature encoder function for RSA. */
932 ssh_signature_encoder_rsa (estream_t signature_blob
, gcry_mpi_t
*mpis
)
941 err
= gcry_mpi_aprint (GCRYMPI_FMT_USG
, &data
, &data_n
, s
);
945 err
= stream_write_string (signature_blob
, data
, data_n
);
954 /* Signature encoder function for DSA. */
956 ssh_signature_encoder_dsa (estream_t signature_blob
, gcry_mpi_t
*mpis
)
958 unsigned char buffer
[SSH_DSA_SIGNATURE_PADDING
* SSH_DSA_SIGNATURE_ELEMS
];
966 for (i
= 0; i
< 2; i
++)
968 err
= gcry_mpi_aprint (GCRYMPI_FMT_USG
, &data
, &data_n
, mpis
[i
]);
972 if (data_n
> SSH_DSA_SIGNATURE_PADDING
)
974 err
= gpg_error (GPG_ERR_INTERNAL
); /* FIXME? */
978 memset (buffer
+ (i
* SSH_DSA_SIGNATURE_PADDING
), 0,
979 SSH_DSA_SIGNATURE_PADDING
- data_n
);
980 memcpy (buffer
+ (i
* SSH_DSA_SIGNATURE_PADDING
)
981 + (SSH_DSA_SIGNATURE_PADDING
- data_n
), data
, data_n
);
989 err
= stream_write_string (signature_blob
, buffer
, sizeof (buffer
));
1003 /* This function constructs a new S-Expression for the key identified
1004 by the KEY_SPEC, SECRET, MPIS and COMMENT, which is to be stored in
1005 *SEXP. Returns usual error code. */
1007 sexp_key_construct (gcry_sexp_t
*sexp
,
1008 ssh_key_type_spec_t key_spec
, int secret
,
1009 gcry_mpi_t
*mpis
, const char *comment
)
1011 const char *key_identifier
[] = { "public-key", "private-key" };
1012 gcry_sexp_t sexp_new
;
1013 char *sexp_template
;
1014 size_t sexp_template_n
;
1026 elems
= key_spec
.elems_sexp_order
;
1028 elems
= key_spec
.elems_key_public
;
1029 elems_n
= strlen (elems
);
1032 Calculate size for sexp_template_n:
1034 "(%s(%s<mpis>)(comment%s))" -> 20 + sizeof (<mpis>).
1039 sexp_template_n
= 20 + (elems_n
* 5);
1040 sexp_template
= xtrymalloc (sexp_template_n
);
1041 if (! sexp_template
)
1043 err
= gpg_error_from_syserror ();
1047 /* Key identifier, algorithm identifier, mpis, comment. */
1048 arg_list
= xtrymalloc (sizeof (*arg_list
) * (2 + elems_n
+ 1));
1051 err
= gpg_error_from_syserror ();
1056 arg_list
[i
++] = &key_identifier
[secret
];
1057 arg_list
[i
++] = &key_spec
.identifier
;
1060 sexp_template_n
= 0;
1061 sexp_template_n
= sprintf (sexp_template
+ sexp_template_n
, "(%%s(%%s");
1062 for (i
= 0; i
< elems_n
; i
++)
1064 sexp_template_n
+= sprintf (sexp_template
+ sexp_template_n
, "(%c%%m)",
1068 for (j
= 0; j
< elems_n
; j
++)
1069 if (key_spec
.elems_key_secret
[j
] == elems
[i
])
1074 arg_list
[i
+ 2] = &mpis
[j
];
1076 sexp_template_n
+= sprintf (sexp_template
+ sexp_template_n
,
1079 arg_list
[i
+ 2] = &comment
;
1081 err
= gcry_sexp_build_array (&sexp_new
, NULL
, sexp_template
, arg_list
);
1090 xfree (sexp_template
);
1095 /* This functions breaks up the key contained in the S-Expression SEXP
1096 according to KEY_SPEC. The MPIs are bundled in a newly create
1097 list, which is to be stored in MPIS; a newly allocated string
1098 holding the comment will be stored in COMMENT; SECRET will be
1099 filled with a boolean flag specifying what kind of key it is.
1100 Returns usual error code. */
1102 sexp_key_extract (gcry_sexp_t sexp
,
1103 ssh_key_type_spec_t key_spec
, int *secret
,
1104 gcry_mpi_t
**mpis
, char **comment
)
1107 gcry_sexp_t value_list
;
1108 gcry_sexp_t value_pair
;
1109 gcry_sexp_t comment_list
;
1117 gcry_mpi_t
*mpis_new
;
1123 comment_list
= NULL
;
1127 data
= gcry_sexp_nth_data (sexp
, 0, &data_n
);
1130 err
= gpg_error (GPG_ERR_INV_SEXP
);
1134 if ((data_n
== 10 && !strncmp (data
, "public-key", 10))
1135 || (data_n
== 21 && !strncmp (data
, "protected-private-key", 21))
1136 || (data_n
== 20 && !strncmp (data
, "shadowed-private-key", 20)))
1139 elems
= key_spec
.elems_key_public
;
1141 else if (data_n
== 11 && !strncmp (data
, "private-key", 11))
1144 elems
= key_spec
.elems_key_secret
;
1148 err
= gpg_error (GPG_ERR_INV_SEXP
);
1152 elems_n
= strlen (elems
);
1153 mpis_new
= xtrycalloc (elems_n
+ 1, sizeof *mpis_new
);
1156 err
= gpg_error_from_syserror ();
1160 value_list
= gcry_sexp_find_token (sexp
, key_spec
.identifier
, 0);
1163 err
= gpg_error (GPG_ERR_INV_SEXP
);
1167 for (i
= 0; i
< elems_n
; i
++)
1169 value_pair
= gcry_sexp_find_token (value_list
, elems
+ i
, 1);
1172 err
= gpg_error (GPG_ERR_INV_SEXP
);
1176 /* Note that we need to use STD format; i.e. prepend a 0x00 to
1177 indicate a positive number if the high bit is set. */
1178 mpi
= gcry_sexp_nth_mpi (value_pair
, 1, GCRYMPI_FMT_STD
);
1181 err
= gpg_error (GPG_ERR_INV_SEXP
);
1185 gcry_sexp_release (value_pair
);
1191 /* We do not require a comment sublist to be present here. */
1195 comment_list
= gcry_sexp_find_token (sexp
, "comment", 0);
1197 data
= gcry_sexp_nth_data (comment_list
, 1, &data_n
);
1204 comment_new
= make_cstring (data
, data_n
);
1207 err
= gpg_error_from_syserror ();
1212 *secret
= is_secret
;
1214 *comment
= comment_new
;
1218 gcry_sexp_release (value_list
);
1219 gcry_sexp_release (value_pair
);
1220 gcry_sexp_release (comment_list
);
1224 xfree (comment_new
);
1225 mpint_list_free (mpis_new
);
1231 /* Extract the car from SEXP, and create a newly created C-string
1232 which is to be stored in IDENTIFIER. */
1234 sexp_extract_identifier (gcry_sexp_t sexp
, char **identifier
)
1236 char *identifier_new
;
1237 gcry_sexp_t sublist
;
1242 identifier_new
= NULL
;
1245 sublist
= gcry_sexp_nth (sexp
, 1);
1248 err
= gpg_error (GPG_ERR_INV_SEXP
);
1252 data
= gcry_sexp_nth_data (sublist
, 0, &data_n
);
1255 err
= gpg_error (GPG_ERR_INV_SEXP
);
1259 identifier_new
= make_cstring (data
, data_n
);
1260 if (! identifier_new
)
1262 err
= gpg_err_code_from_errno (errno
);
1266 *identifier
= identifier_new
;
1270 gcry_sexp_release (sublist
);
1283 /* Search for a key specification entry. If SSH_NAME is not NULL,
1284 search for an entry whose "ssh_name" is equal to SSH_NAME;
1285 otherwise, search for an entry whose "name" is equal to NAME.
1286 Store found entry in SPEC on success, return error otherwise. */
1288 ssh_key_type_lookup (const char *ssh_name
, const char *name
,
1289 ssh_key_type_spec_t
*spec
)
1294 for (i
= 0; i
< DIM (ssh_key_types
); i
++)
1295 if ((ssh_name
&& (! strcmp (ssh_name
, ssh_key_types
[i
].ssh_identifier
)))
1296 || (name
&& (! strcmp (name
, ssh_key_types
[i
].identifier
))))
1299 if (i
== DIM (ssh_key_types
))
1300 err
= gpg_error (GPG_ERR_NOT_FOUND
);
1303 *spec
= ssh_key_types
[i
];
1310 /* Receive a key from STREAM, according to the key specification given
1311 as KEY_SPEC. Depending on SECRET, receive a secret or a public
1312 key. If READ_COMMENT is true, receive a comment string as well.
1313 Constructs a new S-Expression from received data and stores it in
1314 KEY_NEW. Returns zero on success or an error code. */
1316 ssh_receive_key (estream_t stream
, gcry_sexp_t
*key_new
, int secret
,
1317 int read_comment
, ssh_key_type_spec_t
*key_spec
)
1323 ssh_key_type_spec_t spec
;
1324 gcry_mpi_t
*mpi_list
;
1332 err
= stream_read_cstring (stream
, &key_type
);
1336 err
= ssh_key_type_lookup (key_type
, NULL
, &spec
);
1340 err
= ssh_receive_mpint_list (stream
, secret
, spec
, &mpi_list
);
1346 err
= stream_read_cstring (stream
, &comment
);
1352 elems
= spec
.elems_key_secret
;
1354 elems
= spec
.elems_key_public
;
1356 if (spec
.key_modifier
)
1358 err
= (*spec
.key_modifier
) (elems
, mpi_list
);
1363 err
= sexp_key_construct (&key
, spec
, secret
, mpi_list
, comment
);
1373 mpint_list_free (mpi_list
);
1381 /* Converts a key of type TYPE, whose key material is given in MPIS,
1382 into a newly created binary blob, which is to be stored in
1383 BLOB/BLOB_SIZE. Returns zero on success or an error code. */
1385 ssh_convert_key_to_blob (unsigned char **blob
, size_t *blob_size
,
1386 const char *type
, gcry_mpi_t
*mpis
)
1388 unsigned char *blob_new
;
1389 long int blob_size_new
;
1401 stream
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
1404 err
= gpg_error_from_syserror ();
1408 err
= stream_write_cstring (stream
, type
);
1412 for (i
= 0; mpis
[i
] && (! err
); i
++)
1413 err
= stream_write_mpi (stream
, mpis
[i
]);
1417 blob_size_new
= es_ftell (stream
);
1418 if (blob_size_new
== -1)
1420 err
= gpg_error_from_syserror ();
1424 err
= es_fseek (stream
, 0, SEEK_SET
);
1428 blob_new
= xtrymalloc (blob_size_new
);
1431 err
= gpg_error_from_syserror ();
1435 err
= stream_read_data (stream
, blob_new
, blob_size_new
);
1440 *blob_size
= blob_size_new
;
1453 /* Write the public key KEY_PUBLIC to STREAM in SSH key format. If
1454 OVERRIDE_COMMENT is not NULL, it will be used instead of the
1455 comment stored in the key. */
1457 ssh_send_key_public (estream_t stream
, gcry_sexp_t key_public
,
1458 const char *override_comment
)
1460 ssh_key_type_spec_t spec
;
1461 gcry_mpi_t
*mpi_list
;
1464 unsigned char *blob
;
1473 err
= sexp_extract_identifier (key_public
, &key_type
);
1477 err
= ssh_key_type_lookup (NULL
, key_type
, &spec
);
1481 err
= sexp_key_extract (key_public
, spec
, NULL
, &mpi_list
, &comment
);
1485 err
= ssh_convert_key_to_blob (&blob
, &blob_n
,
1486 spec
.ssh_identifier
, mpi_list
);
1490 err
= stream_write_string (stream
, blob
, blob_n
);
1494 err
= stream_write_cstring (stream
,
1495 override_comment
? override_comment
: comment
);
1499 mpint_list_free (mpi_list
);
1507 /* Read a public key out of BLOB/BLOB_SIZE according to the key
1508 specification given as KEY_SPEC, storing the new key in KEY_PUBLIC.
1509 Returns zero on success or an error code. */
1511 ssh_read_key_public_from_blob (unsigned char *blob
, size_t blob_size
,
1512 gcry_sexp_t
*key_public
,
1513 ssh_key_type_spec_t
*key_spec
)
1515 estream_t blob_stream
;
1520 blob_stream
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
1523 err
= gpg_error_from_syserror ();
1527 err
= stream_write_data (blob_stream
, blob
, blob_size
);
1531 err
= es_fseek (blob_stream
, 0, SEEK_SET
);
1535 err
= ssh_receive_key (blob_stream
, key_public
, 0, 0, key_spec
);
1540 es_fclose (blob_stream
);
1547 /* This function calculates the key grip for the key contained in the
1548 S-Expression KEY and writes it to BUFFER, which must be large
1549 enough to hold it. Returns usual error code. */
1551 ssh_key_grip (gcry_sexp_t key
, unsigned char *buffer
)
1553 if (!gcry_pk_get_keygrip (key
, buffer
))
1554 return gpg_error (GPG_ERR_INTERNAL
);
1559 /* Converts the secret key KEY_SECRET into a public key, storing it in
1560 KEY_PUBLIC. SPEC is the according key specification. Returns zero
1561 on success or an error code. */
1563 key_secret_to_public (gcry_sexp_t
*key_public
,
1564 ssh_key_type_spec_t spec
, gcry_sexp_t key_secret
)
1574 err
= sexp_key_extract (key_secret
, spec
, &is_secret
, &mpis
, &comment
);
1578 err
= sexp_key_construct (key_public
, spec
, 0, mpis
, comment
);
1582 mpint_list_free (mpis
);
1589 /* Check whether a smartcard is available and whether it has a usable
1590 key. Store a copy of that key at R_PK and return 0. If no key is
1591 available store NULL at R_PK and return an error code. If CARDSN
1592 is not NULL, a string with the serial number of the card will be
1593 a malloced and stored there. */
1595 card_key_available (ctrl_t ctrl
, gcry_sexp_t
*r_pk
, char **cardsn
)
1599 char *serialno
= NULL
;
1600 unsigned char *pkbuf
;
1603 unsigned char grip
[20];
1609 /* First see whether a card is available and whether the application
1611 err
= agent_card_getattr (ctrl
, "$AUTHKEYID", &authkeyid
);
1612 if ( gpg_err_code (err
) == GPG_ERR_CARD_REMOVED
)
1614 /* Ask for the serial number to reset the card. */
1615 err
= agent_card_serialno (ctrl
, &serialno
);
1619 log_info (_("error getting serial number of card: %s\n"),
1620 gpg_strerror (err
));
1623 log_info (_("detected card with S/N: %s\n"), serialno
);
1624 err
= agent_card_getattr (ctrl
, "$AUTHKEYID", &authkeyid
);
1628 log_error (_("error getting default authentication keyID of card: %s\n"),
1629 gpg_strerror (err
));
1634 /* Get the S/N if we don't have it yet. Use the fast getattr method. */
1635 if (!serialno
&& (err
= agent_card_getattr (ctrl
, "SERIALNO", &serialno
)) )
1637 log_error (_("error getting serial number of card: %s\n"),
1638 gpg_strerror (err
));
1643 /* Read the public key. */
1644 err
= agent_card_readkey (ctrl
, authkeyid
, &pkbuf
);
1648 log_info (_("no suitable card key found: %s\n"), gpg_strerror (err
));
1654 pkbuflen
= gcry_sexp_canon_len (pkbuf
, 0, NULL
, NULL
);
1655 err
= gcry_sexp_sscan (&s_pk
, NULL
, (char*)pkbuf
, pkbuflen
);
1658 log_error ("failed to build S-Exp from received card key: %s\n",
1659 gpg_strerror (err
));
1666 err
= ssh_key_grip (s_pk
, grip
);
1669 log_debug ("error computing keygrip from received card key: %s\n",
1670 gcry_strerror (err
));
1672 gcry_sexp_release (s_pk
);
1678 if ( agent_key_available (grip
) )
1680 /* (Shadow)-key is not available in our key storage. */
1681 unsigned char *shadow_info
;
1684 shadow_info
= make_shadow_info (serialno
, authkeyid
);
1687 err
= gpg_error_from_syserror ();
1689 gcry_sexp_release (s_pk
);
1694 err
= agent_shadow_key (pkbuf
, shadow_info
, &tmp
);
1695 xfree (shadow_info
);
1698 log_error (_("shadowing the key failed: %s\n"), gpg_strerror (err
));
1700 gcry_sexp_release (s_pk
);
1707 pkbuflen
= gcry_sexp_canon_len (pkbuf
, 0, NULL
, NULL
);
1710 err
= agent_write_private_key (grip
, pkbuf
, pkbuflen
, 0);
1713 log_error (_("error writing key: %s\n"), gpg_strerror (err
));
1715 gcry_sexp_release (s_pk
);
1726 /* If the card handler is able to return a short serialnumber,
1727 use that one, else use the complete serialno. */
1728 if (!agent_card_getattr (ctrl
, "$DISPSERIALNO", &dispsn
))
1730 *cardsn
= xtryasprintf ("cardno:%s", dispsn
);
1734 *cardsn
= xtryasprintf ("cardno:%s", serialno
);
1737 err
= gpg_error_from_syserror ();
1739 gcry_sexp_release (s_pk
);
1758 Request handler. Each handler is provided with a CTRL context, a
1759 REQUEST object and a RESPONSE object. The actual request is to be
1760 read from REQUEST, the response needs to be written to RESPONSE.
1765 /* Handler for the "request_identities" command. */
1767 ssh_handler_request_identities (ctrl_t ctrl
,
1768 estream_t request
, estream_t response
)
1771 ssh_key_type_spec_t spec
;
1772 struct dirent
*dir_entry
;
1773 char *key_directory
;
1774 size_t key_directory_n
;
1776 unsigned char *buffer
;
1779 estream_t key_blobs
;
1780 gcry_sexp_t key_secret
;
1781 gcry_sexp_t key_public
;
1785 FILE *ctrl_fp
= NULL
;
1787 gpg_error_t ret_err
;
1789 /* Prepare buffer stream. */
1791 key_directory
= NULL
;
1801 key_blobs
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
1804 err
= gpg_error_from_syserror ();
1808 /* Open key directory. */
1809 key_directory
= make_filename (opt
.homedir
, GNUPG_PRIVATE_KEYS_DIR
, NULL
);
1810 if (! key_directory
)
1812 err
= gpg_err_code_from_errno (errno
);
1815 key_directory_n
= strlen (key_directory
);
1817 key_path
= xtrymalloc (key_directory_n
+ 46);
1820 err
= gpg_err_code_from_errno (errno
);
1824 sprintf (key_path
, "%s/", key_directory
);
1825 sprintf (key_path
+ key_directory_n
+ 41, ".key");
1827 dir
= opendir (key_directory
);
1830 err
= gpg_err_code_from_errno (errno
);
1836 /* First check whether a key is currently available in the card
1837 reader - this should be allowed even without being listed in
1840 if (!card_key_available (ctrl
, &key_public
, &cardsn
))
1842 err
= ssh_send_key_public (key_blobs
, key_public
, cardsn
);
1843 gcry_sexp_release (key_public
);
1853 /* Then look at all the registered an allowed keys. */
1856 /* Fixme: We should better iterate over the control file and check
1857 whether the key file is there. This is better in resepct to
1858 performance if tehre are a lot of key sin our key storage. */
1859 /* FIXME: make sure that buffer gets deallocated properly. */
1860 err
= open_control_file (&ctrl_fp
, 0);
1864 while ( (dir_entry
= readdir (dir
)) )
1866 if ((strlen (dir_entry
->d_name
) == 44)
1867 && (! strncmp (dir_entry
->d_name
+ 40, ".key", 4)))
1872 /* We do only want to return keys listed in our control
1874 strncpy (hexgrip
, dir_entry
->d_name
, 40);
1876 if ( strlen (hexgrip
) != 40 )
1878 if (search_control_file (ctrl_fp
, hexgrip
, &disabled
)
1882 strncpy (key_path
+ key_directory_n
+ 1, dir_entry
->d_name
, 40);
1884 /* Read file content. */
1885 err
= file_to_buffer (key_path
, &buffer
, &buffer_n
);
1889 err
= gcry_sexp_sscan (&key_secret
, NULL
, (char*)buffer
, buffer_n
);
1896 err
= sexp_extract_identifier (key_secret
, &key_type
);
1900 err
= ssh_key_type_lookup (NULL
, key_type
, &spec
);
1907 err
= key_secret_to_public (&key_public
, spec
, key_secret
);
1911 gcry_sexp_release (key_secret
);
1914 err
= ssh_send_key_public (key_blobs
, key_public
, NULL
);
1918 gcry_sexp_release (key_public
);
1925 ret
= es_fseek (key_blobs
, 0, SEEK_SET
);
1928 err
= gpg_error_from_syserror ();
1934 /* Send response. */
1936 gcry_sexp_release (key_secret
);
1937 gcry_sexp_release (key_public
);
1941 ret_err
= stream_write_byte (response
, SSH_RESPONSE_IDENTITIES_ANSWER
);
1944 ret_err
= stream_write_uint32 (response
, key_counter
);
1947 ret_err
= stream_copy (response
, key_blobs
);
1953 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
1960 es_fclose (key_blobs
);
1967 free (key_directory
);
1975 /* This function hashes the data contained in DATA of size DATA_N
1976 according to the message digest algorithm specified by MD_ALGORITHM
1977 and writes the message digest to HASH, which needs to large enough
1980 data_hash (unsigned char *data
, size_t data_n
,
1981 int md_algorithm
, unsigned char *hash
)
1983 gcry_md_hash_buffer (md_algorithm
, hash
, data
, data_n
);
1988 /* This function signs the data contained in CTRL, stores the created
1989 signature in newly allocated memory in SIG and it's size in SIG_N;
1990 SIG_ENCODER is the signature encoder to use. */
1992 data_sign (ctrl_t ctrl
, ssh_signature_encoder_t sig_encoder
,
1993 unsigned char **sig
, size_t *sig_n
)
1996 gcry_sexp_t signature_sexp
= NULL
;
1997 estream_t stream
= NULL
;
1998 gcry_sexp_t valuelist
= NULL
;
1999 gcry_sexp_t sublist
= NULL
;
2000 gcry_mpi_t sig_value
= NULL
;
2001 unsigned char *sig_blob
= NULL
;
2002 size_t sig_blob_n
= 0;
2003 char *identifier
= NULL
;
2004 const char *identifier_raw
;
2005 size_t identifier_n
;
2006 ssh_key_type_spec_t spec
;
2011 gcry_mpi_t
*mpis
= NULL
;
2016 ctrl
->use_auth_call
= 1;
2017 err
= agent_pksign_do (ctrl
,
2018 _("Please enter the passphrase "
2019 "for the ssh key%0A %c"), &signature_sexp
,
2021 ctrl
->use_auth_call
= 0;
2025 valuelist
= gcry_sexp_nth (signature_sexp
, 1);
2028 err
= gpg_error (GPG_ERR_INV_SEXP
);
2032 stream
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
2035 err
= gpg_error_from_syserror ();
2039 identifier_raw
= gcry_sexp_nth_data (valuelist
, 0, &identifier_n
);
2040 if (! identifier_raw
)
2042 err
= gpg_error (GPG_ERR_INV_SEXP
);
2046 identifier
= make_cstring (identifier_raw
, identifier_n
);
2049 err
= gpg_error_from_syserror ();
2053 err
= ssh_key_type_lookup (NULL
, identifier
, &spec
);
2057 err
= stream_write_cstring (stream
, spec
.ssh_identifier
);
2061 elems
= spec
.elems_signature
;
2062 elems_n
= strlen (elems
);
2064 mpis
= xtrycalloc (elems_n
+ 1, sizeof *mpis
);
2067 err
= gpg_error_from_syserror ();
2071 for (i
= 0; i
< elems_n
; i
++)
2073 sublist
= gcry_sexp_find_token (valuelist
, spec
.elems_signature
+ i
, 1);
2076 err
= gpg_error (GPG_ERR_INV_SEXP
);
2080 sig_value
= gcry_sexp_nth_mpi (sublist
, 1, GCRYMPI_FMT_USG
);
2083 err
= gpg_error (GPG_ERR_INTERNAL
); /* FIXME? */
2086 gcry_sexp_release (sublist
);
2089 mpis
[i
] = sig_value
;
2094 err
= (*sig_encoder
) (stream
, mpis
);
2098 sig_blob_n
= es_ftell (stream
);
2099 if (sig_blob_n
== -1)
2101 err
= gpg_error_from_syserror ();
2105 sig_blob
= xtrymalloc (sig_blob_n
);
2108 err
= gpg_error_from_syserror ();
2112 ret
= es_fseek (stream
, 0, SEEK_SET
);
2115 err
= gpg_error_from_syserror ();
2119 err
= stream_read_data (stream
, sig_blob
, sig_blob_n
);
2124 *sig_n
= sig_blob_n
;
2133 gcry_sexp_release (valuelist
);
2134 gcry_sexp_release (signature_sexp
);
2135 gcry_sexp_release (sublist
);
2136 mpint_list_free (mpis
);
2142 /* Handler for the "sign_request" command. */
2144 ssh_handler_sign_request (ctrl_t ctrl
, estream_t request
, estream_t response
)
2147 ssh_key_type_spec_t spec
;
2148 unsigned char hash
[MAX_DIGEST_LEN
];
2149 unsigned int hash_n
;
2150 unsigned char key_grip
[20];
2151 unsigned char *key_blob
;
2153 unsigned char *data
;
2159 gpg_error_t ret_err
;
2168 err
= stream_read_string (request
, 0, &key_blob
, &key_blob_size
);
2172 err
= ssh_read_key_public_from_blob (key_blob
, key_blob_size
, &key
, &spec
);
2176 /* Receive data to sign. */
2177 err
= stream_read_string (request
, 0, &data
, &data_size
);
2182 err
= stream_read_uint32 (request
, &flags
);
2187 hash_n
= gcry_md_get_algo_dlen (GCRY_MD_SHA1
);
2190 err
= gpg_error (GPG_ERR_INTERNAL
);
2193 err
= data_hash (data
, data_size
, GCRY_MD_SHA1
, hash
);
2197 /* Calculate key grip. */
2198 err
= ssh_key_grip (key
, key_grip
);
2204 ctrl
->digest
.algo
= GCRY_MD_SHA1
;
2205 memcpy (ctrl
->digest
.value
, hash
, hash_n
);
2206 ctrl
->digest
.valuelen
= hash_n
;
2207 ctrl
->digest
.raw_value
= ! (spec
.flags
& SPEC_FLAG_USE_PKCS1V2
);
2208 ctrl
->have_keygrip
= 1;
2209 memcpy (ctrl
->keygrip
, key_grip
, 20);
2211 err
= data_sign (ctrl
, spec
.signature_encoder
, &sig
, &sig_n
);
2219 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SIGN_RESPONSE
);
2222 ret_err
= stream_write_string (response
, sig
, sig_n
);
2228 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2235 gcry_sexp_release (key
);
2243 /* This function extracts the comment contained in the key
2244 S-Expression KEY and stores a copy in COMMENT. Returns usual error
2247 ssh_key_extract_comment (gcry_sexp_t key
, char **comment
)
2249 gcry_sexp_t comment_list
;
2255 comment_list
= gcry_sexp_find_token (key
, "comment", 0);
2258 err
= gpg_error (GPG_ERR_INV_SEXP
);
2262 data
= gcry_sexp_nth_data (comment_list
, 1, &data_n
);
2265 err
= gpg_error (GPG_ERR_INV_SEXP
);
2269 comment_new
= make_cstring (data
, data_n
);
2272 err
= gpg_error_from_syserror ();
2276 *comment
= comment_new
;
2281 gcry_sexp_release (comment_list
);
2286 /* This function converts the key contained in the S-Expression KEY
2287 into a buffer, which is protected by the passphrase PASSPHRASE.
2288 Returns usual error code. */
2290 ssh_key_to_protected_buffer (gcry_sexp_t key
, const char *passphrase
,
2291 unsigned char **buffer
, size_t *buffer_n
)
2293 unsigned char *buffer_new
;
2294 unsigned int buffer_new_n
;
2298 buffer_new_n
= gcry_sexp_sprint (key
, GCRYSEXP_FMT_CANON
, NULL
, 0);
2299 buffer_new
= xtrymalloc_secure (buffer_new_n
);
2302 err
= gpg_error_from_syserror ();
2306 gcry_sexp_sprint (key
, GCRYSEXP_FMT_CANON
, buffer_new
, buffer_new_n
);
2307 /* FIXME: guarantee? */
2309 err
= agent_protect (buffer_new
, passphrase
, buffer
, buffer_n
);
2320 /* Store the ssh KEY into our local key storage and protect it after
2321 asking for a passphrase. Cache that passphrase. TTL is the
2322 maximum caching time for that key. If the key already exists in
2323 our key storage, don't do anything. When entering a new key also
2324 add an entry to the sshcontrol file. */
2326 ssh_identity_register (ctrl_t ctrl
, gcry_sexp_t key
, int ttl
)
2329 unsigned char key_grip_raw
[20];
2331 unsigned char *buffer
= NULL
;
2332 unsigned int buffer_n
;
2333 char *description
= NULL
;
2334 char *comment
= NULL
;
2336 struct pin_entry_info_s
*pi
= NULL
;
2338 err
= ssh_key_grip (key
, key_grip_raw
);
2342 /* Check whether the key is already in our key storage. Don't do
2344 if ( !agent_key_available (key_grip_raw
) )
2345 goto out
; /* Yes, key is available. */
2348 err
= ssh_key_extract_comment (key
, &comment
);
2352 if ( asprintf (&description
,
2353 _("Please enter a passphrase to protect"
2354 " the received secret key%%0A"
2356 "within gpg-agent's key storage"),
2357 comment
? comment
: "?") < 0)
2359 err
= gpg_error_from_syserror ();
2364 pi
= gcry_calloc_secure (1, sizeof (*pi
) + 100 + 1);
2367 err
= gpg_error_from_syserror ();
2370 pi
->max_length
= 100;
2372 err
= agent_askpin (ctrl
, description
, NULL
, NULL
, pi
);
2376 err
= ssh_key_to_protected_buffer (key
, pi
->pin
, &buffer
, &buffer_n
);
2380 /* Store this key to our key storage. */
2381 err
= agent_write_private_key (key_grip_raw
, buffer
, buffer_n
, 0);
2385 /* Cache this passphrase. */
2386 for (i
= 0; i
< 20; i
++)
2387 sprintf (key_grip
+ 2 * i
, "%02X", key_grip_raw
[i
]);
2389 err
= agent_put_cache (key_grip
, CACHE_MODE_SSH
, pi
->pin
, ttl
);
2393 /* And add an entry to the sshcontrol file. */
2394 err
= add_control_entry (ctrl
, key_grip
, ttl
);
2398 if (pi
&& pi
->max_length
)
2399 wipememory (pi
->pin
, pi
->max_length
);
2403 free (description
); /* (asprintf allocated, thus regular free.) */
2409 /* This function removes the key contained in the S-Expression KEY
2410 from the local key storage, in case it exists there. Returns usual
2411 error code. FIXME: this function is a stub. */
2413 ssh_identity_drop (gcry_sexp_t key
)
2415 unsigned char key_grip
[21] = { 0 };
2418 err
= ssh_key_grip (key
, key_grip
);
2422 key_grip
[sizeof (key_grip
) - 1] = 0;
2424 /* FIXME: What to do here - forgetting the passphrase or deleting
2425 the key from key cache? */
2432 /* Handler for the "add_identity" command. */
2434 ssh_handler_add_identity (ctrl_t ctrl
, estream_t request
, estream_t response
)
2436 gpg_error_t ret_err
;
2448 err
= ssh_receive_key (request
, &key
, 1, 1, NULL
);
2454 err
= stream_read_byte (request
, &b
);
2455 if (gpg_err_code (err
) == GPG_ERR_EOF
)
2463 case SSH_OPT_CONSTRAIN_LIFETIME
:
2467 err
= stream_read_uint32 (request
, &n
);
2473 case SSH_OPT_CONSTRAIN_CONFIRM
:
2480 /* FIXME: log/bad? */
2487 /* FIXME: are constraints used correctly? */
2489 err
= ssh_identity_register (ctrl
, key
, ttl
);
2493 gcry_sexp_release (key
);
2496 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2498 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2503 /* Handler for the "remove_identity" command. */
2505 ssh_handler_remove_identity (ctrl_t ctrl
,
2506 estream_t request
, estream_t response
)
2508 unsigned char *key_blob
;
2511 gpg_error_t ret_err
;
2519 err
= stream_read_string (request
, 0, &key_blob
, &key_blob_size
);
2523 err
= ssh_read_key_public_from_blob (key_blob
, key_blob_size
, &key
, NULL
);
2527 err
= ssh_identity_drop (key
);
2532 gcry_sexp_release (key
);
2535 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2537 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2542 /* FIXME: stub function. Actually useful? */
2544 ssh_identities_remove_all (void)
2550 /* FIXME: shall we remove _all_ cache entries or only those
2551 registered through the ssh emulation? */
2556 /* Handler for the "remove_all_identities" command. */
2558 ssh_handler_remove_all_identities (ctrl_t ctrl
,
2559 estream_t request
, estream_t response
)
2561 gpg_error_t ret_err
;
2564 err
= ssh_identities_remove_all ();
2567 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2569 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2574 /* Lock agent? FIXME: stub function. */
2581 log_error ("ssh-agent's lock command is not implemented\n");
2587 /* Unock agent? FIXME: stub function. */
2593 log_error ("ssh-agent's unlock command is not implemented\n");
2599 /* Handler for the "lock" command. */
2601 ssh_handler_lock (ctrl_t ctrl
, estream_t request
, estream_t response
)
2603 gpg_error_t ret_err
;
2609 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2611 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2616 /* Handler for the "unlock" command. */
2618 ssh_handler_unlock (ctrl_t ctrl
, estream_t request
, estream_t response
)
2620 gpg_error_t ret_err
;
2623 err
= ssh_unlock ();
2626 ret_err
= stream_write_byte (response
, SSH_RESPONSE_SUCCESS
);
2628 ret_err
= stream_write_byte (response
, SSH_RESPONSE_FAILURE
);
2635 /* Return the request specification for the request identified by TYPE
2636 or NULL in case the requested request specification could not be
2638 static ssh_request_spec_t
*
2639 request_spec_lookup (int type
)
2641 ssh_request_spec_t
*spec
;
2644 for (i
= 0; i
< DIM (request_specs
); i
++)
2645 if (request_specs
[i
].type
== type
)
2647 if (i
== DIM (request_specs
))
2649 log_info ("ssh request %u is not supported\n", type
);
2653 spec
= request_specs
+ i
;
2658 /* Process a single request. The request is read from and the
2659 response is written to STREAM_SOCK. Uses CTRL as context. Returns
2660 zero in case of success, non zero in case of failure. */
2662 ssh_request_process (ctrl_t ctrl
, estream_t stream_sock
)
2664 ssh_request_spec_t
*spec
;
2667 unsigned char request_type
;
2671 unsigned char *request_data
;
2672 u32 request_data_size
;
2675 request_data
= NULL
;
2680 /* Create memory streams for request/response data. The entire
2681 request will be stored in secure memory, since it might contain
2682 secret key material. The response does not have to be stored in
2683 secure memory, since we never give out secret keys.
2685 Note: we only have little secure memory, but there is NO
2686 possibility of DoS here; only trusted clients are allowed to
2687 connect to the agent. What could happen is that the agent
2688 returns out-of-secure-memory errors on requests in case the
2689 agent's owner floods his own agent with many large messages.
2692 /* Retrieve request. */
2693 err
= stream_read_string (stream_sock
, 1, &request_data
, &request_data_size
);
2697 if (opt
.verbose
> 1)
2698 log_info ("received ssh request of length %u\n",
2699 (unsigned int)request_data_size
);
2701 if (! request_data_size
)
2705 /* Broken request; FIXME. */
2708 request_type
= request_data
[0];
2709 spec
= request_spec_lookup (request_type
);
2714 /* Unknown request; FIXME. */
2717 if (spec
->secret_input
)
2718 request
= es_mopen (NULL
, 0, 0, 1, realloc_secure
, gcry_free
, "r+");
2720 request
= es_mopen (NULL
, 0, 0, 1, gcry_realloc
, gcry_free
, "r+");
2723 err
= gpg_error_from_syserror ();
2726 ret
= es_setvbuf (request
, NULL
, _IONBF
, 0);
2729 err
= gpg_error_from_syserror ();
2732 err
= stream_write_data (request
, request_data
+ 1, request_data_size
- 1);
2735 es_rewind (request
);
2737 response
= es_mopen (NULL
, 0, 0, 1, NULL
, NULL
, "r+");
2740 err
= gpg_error_from_syserror ();
2745 log_info ("ssh request handler for %s (%u) started\n",
2746 spec
->identifier
, spec
->type
);
2748 err
= (*spec
->handler
) (ctrl
, request
, response
);
2753 log_info ("ssh request handler for %s (%u) failed: %s\n",
2754 spec
->identifier
, spec
->type
, gpg_strerror (err
));
2756 log_info ("ssh request handler for %s (%u) ready\n",
2757 spec
->identifier
, spec
->type
);
2766 response_size
= es_ftell (response
);
2767 if (opt
.verbose
> 1)
2768 log_info ("sending ssh response of length %u\n",
2769 (unsigned int)response_size
);
2771 err
= es_fseek (response
, 0, SEEK_SET
);
2778 err
= stream_write_uint32 (stream_sock
, response_size
);
2785 err
= stream_copy (stream_sock
, response
);
2789 err
= es_fflush (stream_sock
);
2795 if (err
&& es_feof (stream_sock
))
2796 log_error ("error occured while processing request: %s\n",
2797 gpg_strerror (err
));
2801 if (opt
.verbose
> 1)
2802 log_info ("sending ssh error response\n");
2803 err
= stream_write_uint32 (stream_sock
, 1);
2806 err
= stream_write_byte (stream_sock
, SSH_RESPONSE_FAILURE
);
2814 es_fclose (request
);
2816 es_fclose (response
);
2817 xfree (request_data
); /* FIXME? */
2822 /* Start serving client on SOCK_CLIENT. */
2824 start_command_handler_ssh (int sock_client
)
2826 struct server_control_s ctrl
;
2827 estream_t stream_sock
;
2831 /* Setup control structure. */
2833 memset (&ctrl
, 0, sizeof (ctrl
));
2834 agent_init_default_ctrl (&ctrl
);
2835 ctrl
.connection_fd
= sock_client
;
2837 /* Because the ssh protocol does not send us information about the
2838 the current TTY setting, we resort here to use those from startup
2839 or those explictly set. */
2840 if (!ctrl
.display
&& opt
.startup_display
)
2841 ctrl
.display
= strdup (opt
.startup_display
);
2842 if (!ctrl
.ttyname
&& opt
.startup_ttyname
)
2843 ctrl
.ttyname
= strdup (opt
.startup_ttyname
);
2844 if (!ctrl
.ttytype
&& opt
.startup_ttytype
)
2845 ctrl
.ttytype
= strdup (opt
.startup_ttytype
);
2846 if (!ctrl
.lc_ctype
&& opt
.startup_lc_ctype
)
2847 ctrl
.lc_ctype
= strdup (opt
.startup_lc_ctype
);
2848 if (!ctrl
.lc_messages
&& opt
.startup_lc_messages
)
2849 ctrl
.lc_messages
= strdup (opt
.startup_lc_messages
);
2852 /* Create stream from socket. */
2853 stream_sock
= es_fdopen (sock_client
, "r+");
2856 err
= gpg_error_from_syserror ();
2857 log_error (_("failed to create stream from socket: %s\n"),
2858 gpg_strerror (err
));
2861 /* We have to disable the estream buffering, because the estream
2862 core doesn't know about secure memory. */
2863 ret
= es_setvbuf (stream_sock
, NULL
, _IONBF
, 0);
2866 err
= gpg_error_from_syserror ();
2867 log_error ("failed to disable buffering "
2868 "on socket stream: %s\n", gpg_strerror (err
));
2872 /* Main processing loop. */
2873 while ( !ssh_request_process (&ctrl
, stream_sock
) )
2876 /* Reset the SCD in case it has been used. */
2877 agent_reset_scd (&ctrl
);
2882 es_fclose (stream_sock
);
2884 free (ctrl
.display
);
2885 free (ctrl
.ttyname
);
2886 free (ctrl
.ttytype
);
2887 free (ctrl
.lc_ctype
);
2888 free (ctrl
.lc_messages
);