Move password repetition from gpg to gpg-agent.
[gnupg.git] / agent / command-ssh.c
blobc262cade7b19a04f7830beff030e3e46900b53c4
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 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. */
22 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <dirent.h>
31 #include <assert.h>
33 #include "agent.h"
35 #include "estream.h"
36 #include "i18n.h"
40 /* Request types. */
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
50 /* Options. */
51 #define SSH_OPT_CONSTRAIN_LIFETIME 1
52 #define SSH_OPT_CONSTRAIN_CONFIRM 2
54 /* Response types. */
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"
78 "\n";
82 /* Macros. */
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)
93 * Basic types.
96 /* Type for a request handler. */
97 typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl,
98 estream_t request,
99 estream_t response);
101 /* Type, which is used for associating request handlers with the
102 appropriate request IDs. */
103 typedef struct ssh_request_spec
105 unsigned char type;
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,
116 gcry_mpi_t *mpis);
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,
122 gcry_mpi_t *mpis);
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
135 agent protocol. */
136 const char *elems_key_secret;
138 /* List of MPI names for public keys; order matches the one of the
139 agent protocol. */
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
156 algorithm. */
157 ssh_signature_encoder_t signature_encoder;
159 /* Misc flags. */
160 unsigned int flags;
161 } ssh_key_type_spec_t;
164 /* Prototypes. */
165 static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl,
166 estream_t request,
167 estream_t response);
168 static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl,
169 estream_t request,
170 estream_t response);
171 static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl,
172 estream_t request,
173 estream_t response);
174 static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl,
175 estream_t request,
176 estream_t response);
177 static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl,
178 estream_t request,
179 estream_t response);
180 static gpg_error_t ssh_handler_lock (ctrl_t ctrl,
181 estream_t request,
182 estream_t response);
183 static gpg_error_t ssh_handler_unlock (ctrl_t ctrl,
184 estream_t request,
185 estream_t response);
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,
189 gcry_mpi_t *mpis);
190 static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob,
191 gcry_mpi_t *mpis);
195 /* Global variables. */
198 /* Associating request types with the corresponding request
199 handlers. */
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
244 existing buffer. */
245 static void *
246 realloc_secure (void *a, size_t n)
248 void *p;
250 if (a)
251 p = gcry_realloc (a, n);
252 else
253 p = gcry_malloc_secure (n);
255 return p;
259 /* Create and return a new C-string from DATA/DATA_N (i.e.: add
260 NUL-termination); return NULL on OOM. */
261 static char *
262 make_cstring (const char *data, size_t data_n)
264 char *s;
266 s = xtrymalloc (data_n + 1);
267 if (s)
269 memcpy (s, data, data_n);
270 s[data_n] = 0;
273 return s;
280 Primitive I/O functions.
284 /* Read a byte from STREAM, store it in B. */
285 static gpg_error_t
286 stream_read_byte (estream_t stream, unsigned char *b)
288 gpg_error_t err;
289 int ret;
291 ret = es_fgetc (stream);
292 if (ret == EOF)
294 if (es_ferror (stream))
295 err = gpg_error_from_syserror ();
296 else
297 err = gpg_error (GPG_ERR_EOF);
298 *b = 0;
300 else
302 *b = ret & 0xFF;
303 err = 0;
306 return err;
309 /* Write the byte contained in B to STREAM. */
310 static gpg_error_t
311 stream_write_byte (estream_t stream, unsigned char b)
313 gpg_error_t err;
314 int ret;
316 ret = es_fputc (b, stream);
317 if (ret == EOF)
318 err = gpg_error_from_syserror ();
319 else
320 err = 0;
322 return err;
325 /* Read a uint32 from STREAM, store it in UINT32. */
326 static gpg_error_t
327 stream_read_uint32 (estream_t stream, u32 *uint32)
329 unsigned char buffer[4];
330 size_t bytes_read;
331 gpg_error_t err;
332 int ret;
334 ret = es_read (stream, buffer, sizeof (buffer), &bytes_read);
335 if (ret)
336 err = gpg_error_from_syserror ();
337 else
339 if (bytes_read != sizeof (buffer))
340 err = gpg_error (GPG_ERR_EOF);
341 else
343 u32 n;
345 n = uint32_construct (buffer[0], buffer[1], buffer[2], buffer[3]);
346 *uint32 = n;
347 err = 0;
351 return err;
354 /* Write the uint32 contained in UINT32 to STREAM. */
355 static gpg_error_t
356 stream_write_uint32 (estream_t stream, u32 uint32)
358 unsigned char buffer[4];
359 gpg_error_t err;
360 int ret;
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);
368 if (ret)
369 err = gpg_error_from_syserror ();
370 else
371 err = 0;
373 return err;
376 /* Read SIZE bytes from STREAM into BUFFER. */
377 static gpg_error_t
378 stream_read_data (estream_t stream, unsigned char *buffer, size_t size)
380 gpg_error_t err;
381 size_t bytes_read;
382 int ret;
384 ret = es_read (stream, buffer, size, &bytes_read);
385 if (ret)
386 err = gpg_error_from_syserror ();
387 else
389 if (bytes_read != size)
390 err = gpg_error (GPG_ERR_EOF);
391 else
392 err = 0;
395 return err;
398 /* Write SIZE bytes from BUFFER to STREAM. */
399 static gpg_error_t
400 stream_write_data (estream_t stream, const unsigned char *buffer, size_t size)
402 gpg_error_t err;
403 int ret;
405 ret = es_write (stream, buffer, size, NULL);
406 if (ret)
407 err = gpg_error_from_syserror ();
408 else
409 err = 0;
411 return err;
414 /* Read a binary string from STREAM into STRING, store size of string
415 in STRING_SIZE; depending on SECURE use secure memory for
416 string. */
417 static gpg_error_t
418 stream_read_string (estream_t stream, unsigned int secure,
419 unsigned char **string, u32 *string_size)
421 gpg_error_t err;
422 unsigned char *buffer = NULL;
423 u32 length = 0;
425 /* Read string length. */
426 err = stream_read_uint32 (stream, &length);
427 if (err)
428 goto out;
430 /* Allocate space. */
431 if (secure)
432 buffer = xtrymalloc_secure (length + 1);
433 else
434 buffer = xtrymalloc (length + 1);
435 if (! buffer)
437 err = gpg_error_from_syserror ();
438 goto out;
441 /* Read data. */
442 err = stream_read_data (stream, buffer, length);
443 if (err)
444 goto out;
446 /* Finalize string object. */
447 buffer[length] = 0;
448 *string = buffer;
449 if (string_size)
450 *string_size = length;
452 out:
454 if (err)
455 xfree (buffer);
457 return err;
460 /* Read a C-string from STREAM, store copy in STRING. */
461 static gpg_error_t
462 stream_read_cstring (estream_t stream, char **string)
464 unsigned char *buffer;
465 gpg_error_t err;
467 err = stream_read_string (stream, 0, &buffer, NULL);
468 if (err)
469 goto out;
471 *string = (char *) buffer;
473 out:
475 return err;
479 /* Write a binary string from STRING of size STRING_N to STREAM. */
480 static gpg_error_t
481 stream_write_string (estream_t stream,
482 const unsigned char *string, u32 string_n)
484 gpg_error_t err;
486 err = stream_write_uint32 (stream, string_n);
487 if (err)
488 goto out;
490 err = stream_write_data (stream, string, string_n);
492 out:
494 return err;
497 /* Write a C-string from STRING to STREAM. */
498 static gpg_error_t
499 stream_write_cstring (estream_t stream, const char *string)
501 gpg_error_t err;
503 err = stream_write_string (stream,
504 (const unsigned char *) string, strlen (string));
506 return err;
509 /* Read an MPI from STREAM, store it in MPINT. Depending on SECURE
510 use secure memory. */
511 static gpg_error_t
512 stream_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint)
514 unsigned char *mpi_data;
515 u32 mpi_data_size;
516 gpg_error_t err;
517 gcry_mpi_t mpi;
519 mpi_data = NULL;
521 err = stream_read_string (stream, secure, &mpi_data, &mpi_data_size);
522 if (err)
523 goto out;
525 /* To avoid excessive use of secure memory we check that an MPI is
526 not too large. */
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;
531 goto out;
534 err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_STD, mpi_data, mpi_data_size, NULL);
535 if (err)
536 goto out;
538 *mpint = mpi;
540 out:
542 xfree (mpi_data);
544 return err;
547 /* Write the MPI contained in MPINT to STREAM. */
548 static gpg_error_t
549 stream_write_mpi (estream_t stream, gcry_mpi_t mpint)
551 unsigned char *mpi_buffer;
552 size_t mpi_buffer_n;
553 gpg_error_t err;
555 mpi_buffer = NULL;
557 err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &mpi_buffer, &mpi_buffer_n, mpint);
558 if (err)
559 goto out;
561 err = stream_write_string (stream, mpi_buffer, mpi_buffer_n);
563 out:
565 xfree (mpi_buffer);
567 return err;
570 /* Copy data from SRC to DST until EOF is reached. */
571 static gpg_error_t
572 stream_copy (estream_t dst, estream_t src)
574 char buffer[BUFSIZ];
575 size_t bytes_read;
576 gpg_error_t err;
577 int ret;
579 err = 0;
580 while (1)
582 ret = es_read (src, buffer, sizeof (buffer), &bytes_read);
583 if (ret || (! bytes_read))
585 if (ret)
586 err = gpg_error_from_syserror ();
587 break;
589 ret = es_write (dst, buffer, bytes_read, NULL);
590 if (ret)
592 err = gpg_error_from_syserror ();
593 break;
597 return err;
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. */
604 static gpg_error_t
605 file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n)
607 unsigned char *buffer_new;
608 struct stat statbuf;
609 estream_t stream;
610 gpg_error_t err;
611 int ret;
613 *buffer = NULL;
614 *buffer_n = 0;
616 buffer_new = NULL;
617 err = 0;
619 stream = es_fopen (filename, "r");
620 if (! stream)
622 err = gpg_error_from_syserror ();
623 goto out;
626 ret = fstat (es_fileno (stream), &statbuf);
627 if (ret)
629 err = gpg_error_from_syserror ();
630 goto out;
633 buffer_new = xtrymalloc (statbuf.st_size);
634 if (! buffer_new)
636 err = gpg_error_from_syserror ();
637 goto out;
640 err = stream_read_data (stream, buffer_new, statbuf.st_size);
641 if (err)
642 goto out;
644 *buffer = buffer_new;
645 *buffer_n = statbuf.st_size;
647 out:
649 if (stream)
650 es_fclose (stream);
652 if (err)
653 xfree (buffer_new);
655 return err;
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. */
665 static gpg_error_t
666 open_control_file (FILE **r_fp, int append)
668 gpg_error_t err;
669 char *fname;
670 FILE *fp;
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
674 mutex. */
675 *r_fp = NULL;
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_
683 functions here. */
684 fp = fopen (fname, "wx");
685 if (!fp)
687 err = gpg_error (gpg_err_code_from_errno (errno));
688 log_error (_("can't create `%s': %s\n"), fname, gpg_strerror (err));
689 xfree (fname);
690 return err;
692 fputs (sshcontrolblurb, fp);
693 fclose (fp);
694 fp = fopen (fname, append? "a+":"r");
697 if (!fp)
699 err = gpg_error (gpg_err_code_from_errno (errno));
700 log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err));
701 xfree (fname);
702 return err;
705 *r_fp = fp;
707 return 0;
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. */
714 static gpg_error_t
715 search_control_file (FILE *fp, const char *hexgrip, int *disabled)
717 int c, i;
718 char *p, line[256];
720 assert (strlen (hexgrip) == 40 );
722 rewind (fp);
723 *disabled = 0;
724 next_line:
727 if (!fgets (line, DIM(line)-1, fp) )
729 if (feof (fp))
730 return gpg_error (GPG_ERR_EOF);
731 return gpg_error (gpg_err_code_from_errno (errno));
734 if (!*line || line[strlen(line)-1] != '\n')
736 /* Eat until end of line */
737 while ( (c=getc (fp)) != EOF && c != '\n')
739 return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
740 : GPG_ERR_INCOMPLETE_LINE);
743 /* Allow for empty lines and spaces */
744 for (p=line; spacep (p); p++)
747 while (!*p || *p == '\n' || *p == '#');
749 *disabled = 0;
750 if (*p == '!')
752 *disabled = 1;
753 for (p++; spacep (p); p++)
757 for (i=0; hexdigitp (p) && i < 40; p++, i++)
758 if (hexgrip[i] != (*p >= 'a'? (*p & 0xdf): *p))
759 goto next_line;
760 if (i != 40 || !(spacep (p) || *p == '\n'))
762 log_error ("invalid formatted line in ssh control file\n");
763 return gpg_error (GPG_ERR_BAD_DATA);
766 /* Fixme: Get TTL and flags. */
768 return 0; /* Okay: found it. */
773 /* Add an entry to the control file to mark the key with the keygrip
774 HEXGRIP as usable for SSH; i.e. it will be returned when ssh asks
775 for it. This function is in general used to add a key received
776 through the ssh-add function. We can assume that the user wants to
777 allow ssh using this key. */
778 static gpg_error_t
779 add_control_entry (ctrl_t ctrl, const char *hexgrip, int ttl)
781 gpg_error_t err;
782 FILE *fp;
783 int disabled;
785 (void)ctrl;
787 err = open_control_file (&fp, 1);
788 if (err)
789 return err;
791 err = search_control_file (fp, hexgrip, &disabled);
792 if (err && gpg_err_code(err) == GPG_ERR_EOF)
794 struct tm *tp;
795 time_t atime = time (NULL);
797 /* Not yet in the file - add it. Because the file has been
798 opened in append mode, we simply need to write to it. */
799 tp = localtime (&atime);
800 fprintf (fp, "# Key added on %04d-%02d-%02d %02d:%02d:%02d\n%s %d\n",
801 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
802 tp->tm_hour, tp->tm_min, tp->tm_sec,
803 hexgrip, ttl);
806 fclose (fp);
807 return 0;
816 MPI lists.
820 /* Free the list of MPIs MPI_LIST. */
821 static void
822 mpint_list_free (gcry_mpi_t *mpi_list)
824 if (mpi_list)
826 unsigned int i;
828 for (i = 0; mpi_list[i]; i++)
829 gcry_mpi_release (mpi_list[i]);
830 xfree (mpi_list);
834 /* Receive key material MPIs from STREAM according to KEY_SPEC;
835 depending on SECRET expect a public key or secret key. The newly
836 allocated list of MPIs is stored in MPI_LIST. Returns usual error
837 code. */
838 static gpg_error_t
839 ssh_receive_mpint_list (estream_t stream, int secret,
840 ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list)
842 unsigned int elems_public_n;
843 const char *elems_public;
844 unsigned int elems_n;
845 const char *elems;
846 int elem_is_secret;
847 gcry_mpi_t *mpis;
848 gpg_error_t err;
849 unsigned int i;
851 mpis = NULL;
852 err = 0;
854 if (secret)
855 elems = key_spec.elems_key_secret;
856 else
857 elems = key_spec.elems_key_public;
858 elems_n = strlen (elems);
860 elems_public = key_spec.elems_key_public;
861 elems_public_n = strlen (elems_public);
863 mpis = xtrycalloc (elems_n + 1, sizeof *mpis );
864 if (!mpis)
866 err = gpg_error_from_syserror ();
867 goto out;
870 elem_is_secret = 0;
871 for (i = 0; i < elems_n; i++)
873 if (secret)
874 elem_is_secret = ! strchr (elems_public, elems[i]);
875 err = stream_read_mpi (stream, elem_is_secret, &mpis[i]);
876 if (err)
877 break;
879 if (err)
880 goto out;
882 *mpi_list = mpis;
884 out:
886 if (err)
887 mpint_list_free (mpis);
889 return err;
894 /* Key modifier function for RSA. */
895 static gpg_error_t
896 ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis)
898 gcry_mpi_t p;
899 gcry_mpi_t q;
900 gcry_mpi_t u;
902 if (strcmp (elems, "nedupq"))
903 /* Modifying only necessary for secret keys. */
904 goto out;
906 u = mpis[3];
907 p = mpis[4];
908 q = mpis[5];
910 if (gcry_mpi_cmp (p, q) > 0)
912 /* P shall be smaller then Q! Swap primes. iqmp becomes u. */
913 gcry_mpi_t tmp;
915 tmp = mpis[4];
916 mpis[4] = mpis[5];
917 mpis[5] = tmp;
919 else
920 /* U needs to be recomputed. */
921 gcry_mpi_invm (u, p, q);
923 out:
925 return 0;
928 /* Signature encoder function for RSA. */
929 static gpg_error_t
930 ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis)
932 unsigned char *data;
933 size_t data_n;
934 gpg_error_t err;
935 gcry_mpi_t s;
937 s = mpis[0];
939 err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s);
940 if (err)
941 goto out;
943 err = stream_write_string (signature_blob, data, data_n);
944 xfree (data);
946 out:
948 return err;
952 /* Signature encoder function for DSA. */
953 static gpg_error_t
954 ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis)
956 unsigned char buffer[SSH_DSA_SIGNATURE_PADDING * SSH_DSA_SIGNATURE_ELEMS];
957 unsigned char *data;
958 size_t data_n;
959 gpg_error_t err;
960 int i;
962 data = NULL;
964 for (i = 0; i < 2; i++)
966 err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]);
967 if (err)
968 break;
970 if (data_n > SSH_DSA_SIGNATURE_PADDING)
972 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
973 break;
976 memset (buffer + (i * SSH_DSA_SIGNATURE_PADDING), 0,
977 SSH_DSA_SIGNATURE_PADDING - data_n);
978 memcpy (buffer + (i * SSH_DSA_SIGNATURE_PADDING)
979 + (SSH_DSA_SIGNATURE_PADDING - data_n), data, data_n);
981 xfree (data);
982 data = NULL;
984 if (err)
985 goto out;
987 err = stream_write_string (signature_blob, buffer, sizeof (buffer));
989 out:
991 xfree (data);
993 return err;
997 S-Expressions.
1001 /* This function constructs a new S-Expression for the key identified
1002 by the KEY_SPEC, SECRET, MPIS and COMMENT, which is to be stored in
1003 *SEXP. Returns usual error code. */
1004 static gpg_error_t
1005 sexp_key_construct (gcry_sexp_t *sexp,
1006 ssh_key_type_spec_t key_spec, int secret,
1007 gcry_mpi_t *mpis, const char *comment)
1009 const char *key_identifier[] = { "public-key", "private-key" };
1010 gcry_sexp_t sexp_new;
1011 char *sexp_template;
1012 size_t sexp_template_n;
1013 gpg_error_t err;
1014 const char *elems;
1015 size_t elems_n;
1016 unsigned int i;
1017 unsigned int j;
1018 void **arg_list;
1020 err = 0;
1021 sexp_new = NULL;
1022 arg_list = NULL;
1023 if (secret)
1024 elems = key_spec.elems_sexp_order;
1025 else
1026 elems = key_spec.elems_key_public;
1027 elems_n = strlen (elems);
1030 Calculate size for sexp_template_n:
1032 "(%s(%s<mpis>)(comment%s))" -> 20 + sizeof (<mpis>).
1034 mpi: (X%m) -> 5.
1037 sexp_template_n = 20 + (elems_n * 5);
1038 sexp_template = xtrymalloc (sexp_template_n);
1039 if (! sexp_template)
1041 err = gpg_error_from_syserror ();
1042 goto out;
1045 /* Key identifier, algorithm identifier, mpis, comment. */
1046 arg_list = xtrymalloc (sizeof (*arg_list) * (2 + elems_n + 1));
1047 if (! arg_list)
1049 err = gpg_error_from_syserror ();
1050 goto out;
1053 i = 0;
1054 arg_list[i++] = &key_identifier[secret];
1055 arg_list[i++] = &key_spec.identifier;
1057 *sexp_template = 0;
1058 sexp_template_n = 0;
1059 sexp_template_n = sprintf (sexp_template + sexp_template_n, "(%%s(%%s");
1060 for (i = 0; i < elems_n; i++)
1062 sexp_template_n += sprintf (sexp_template + sexp_template_n, "(%c%%m)",
1063 elems[i]);
1064 if (secret)
1066 for (j = 0; j < elems_n; j++)
1067 if (key_spec.elems_key_secret[j] == elems[i])
1068 break;
1070 else
1071 j = i;
1072 arg_list[i + 2] = &mpis[j];
1074 sexp_template_n += sprintf (sexp_template + sexp_template_n,
1075 ")(comment%%s))");
1077 arg_list[i + 2] = &comment;
1079 err = gcry_sexp_build_array (&sexp_new, NULL, sexp_template, arg_list);
1080 if (err)
1081 goto out;
1083 *sexp = sexp_new;
1085 out:
1087 xfree (arg_list);
1088 xfree (sexp_template);
1090 return err;
1093 /* This functions breaks up the key contained in the S-Expression SEXP
1094 according to KEY_SPEC. The MPIs are bundled in a newly create
1095 list, which is to be stored in MPIS; a newly allocated string
1096 holding the comment will be stored in COMMENT; SECRET will be
1097 filled with a boolean flag specifying what kind of key it is.
1098 Returns usual error code. */
1099 static gpg_error_t
1100 sexp_key_extract (gcry_sexp_t sexp,
1101 ssh_key_type_spec_t key_spec, int *secret,
1102 gcry_mpi_t **mpis, char **comment)
1104 gpg_error_t err;
1105 gcry_sexp_t value_list;
1106 gcry_sexp_t value_pair;
1107 gcry_sexp_t comment_list;
1108 unsigned int i;
1109 char *comment_new;
1110 const char *data;
1111 size_t data_n;
1112 int is_secret;
1113 size_t elems_n;
1114 const char *elems;
1115 gcry_mpi_t *mpis_new;
1116 gcry_mpi_t mpi;
1118 err = 0;
1119 value_list = NULL;
1120 value_pair = NULL;
1121 comment_list = NULL;
1122 comment_new = NULL;
1123 mpis_new = NULL;
1125 data = gcry_sexp_nth_data (sexp, 0, &data_n);
1126 if (! data)
1128 err = gpg_error (GPG_ERR_INV_SEXP);
1129 goto out;
1132 if ((data_n == 10 && !strncmp (data, "public-key", 10))
1133 || (data_n == 21 && !strncmp (data, "protected-private-key", 21))
1134 || (data_n == 20 && !strncmp (data, "shadowed-private-key", 20)))
1136 is_secret = 0;
1137 elems = key_spec.elems_key_public;
1139 else if (data_n == 11 && !strncmp (data, "private-key", 11))
1141 is_secret = 1;
1142 elems = key_spec.elems_key_secret;
1144 else
1146 err = gpg_error (GPG_ERR_INV_SEXP);
1147 goto out;
1150 elems_n = strlen (elems);
1151 mpis_new = xtrycalloc (elems_n + 1, sizeof *mpis_new );
1152 if (!mpis_new)
1154 err = gpg_error_from_syserror ();
1155 goto out;
1158 value_list = gcry_sexp_find_token (sexp, key_spec.identifier, 0);
1159 if (! value_list)
1161 err = gpg_error (GPG_ERR_INV_SEXP);
1162 goto out;
1165 for (i = 0; i < elems_n; i++)
1167 value_pair = gcry_sexp_find_token (value_list, elems + i, 1);
1168 if (! value_pair)
1170 err = gpg_error (GPG_ERR_INV_SEXP);
1171 break;
1174 /* Note that we need to use STD format; i.e. prepend a 0x00 to
1175 indicate a positive number if the high bit is set. */
1176 mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_STD);
1177 if (! mpi)
1179 err = gpg_error (GPG_ERR_INV_SEXP);
1180 break;
1182 mpis_new[i] = mpi;
1183 gcry_sexp_release (value_pair);
1184 value_pair = NULL;
1186 if (err)
1187 goto out;
1189 /* We do not require a comment sublist to be present here. */
1190 data = NULL;
1191 data_n = 0;
1193 comment_list = gcry_sexp_find_token (sexp, "comment", 0);
1194 if (comment_list)
1195 data = gcry_sexp_nth_data (comment_list, 1, &data_n);
1196 if (! data)
1198 data = "(none)";
1199 data_n = 6;
1202 comment_new = make_cstring (data, data_n);
1203 if (! comment_new)
1205 err = gpg_error_from_syserror ();
1206 goto out;
1209 if (secret)
1210 *secret = is_secret;
1211 *mpis = mpis_new;
1212 *comment = comment_new;
1214 out:
1216 gcry_sexp_release (value_list);
1217 gcry_sexp_release (value_pair);
1218 gcry_sexp_release (comment_list);
1220 if (err)
1222 xfree (comment_new);
1223 mpint_list_free (mpis_new);
1226 return err;
1229 /* Extract the car from SEXP, and create a newly created C-string
1230 which is to be stored in IDENTIFIER. */
1231 static gpg_error_t
1232 sexp_extract_identifier (gcry_sexp_t sexp, char **identifier)
1234 char *identifier_new;
1235 gcry_sexp_t sublist;
1236 const char *data;
1237 size_t data_n;
1238 gpg_error_t err;
1240 identifier_new = NULL;
1241 err = 0;
1243 sublist = gcry_sexp_nth (sexp, 1);
1244 if (! sublist)
1246 err = gpg_error (GPG_ERR_INV_SEXP);
1247 goto out;
1250 data = gcry_sexp_nth_data (sublist, 0, &data_n);
1251 if (! data)
1253 err = gpg_error (GPG_ERR_INV_SEXP);
1254 goto out;
1257 identifier_new = make_cstring (data, data_n);
1258 if (! identifier_new)
1260 err = gpg_err_code_from_errno (errno);
1261 goto out;
1264 *identifier = identifier_new;
1266 out:
1268 gcry_sexp_release (sublist);
1270 return err;
1277 Key I/O.
1281 /* Search for a key specification entry. If SSH_NAME is not NULL,
1282 search for an entry whose "ssh_name" is equal to SSH_NAME;
1283 otherwise, search for an entry whose "name" is equal to NAME.
1284 Store found entry in SPEC on success, return error otherwise. */
1285 static gpg_error_t
1286 ssh_key_type_lookup (const char *ssh_name, const char *name,
1287 ssh_key_type_spec_t *spec)
1289 gpg_error_t err;
1290 unsigned int i;
1292 for (i = 0; i < DIM (ssh_key_types); i++)
1293 if ((ssh_name && (! strcmp (ssh_name, ssh_key_types[i].ssh_identifier)))
1294 || (name && (! strcmp (name, ssh_key_types[i].identifier))))
1295 break;
1297 if (i == DIM (ssh_key_types))
1298 err = gpg_error (GPG_ERR_NOT_FOUND);
1299 else
1301 *spec = ssh_key_types[i];
1302 err = 0;
1305 return err;
1308 /* Receive a key from STREAM, according to the key specification given
1309 as KEY_SPEC. Depending on SECRET, receive a secret or a public
1310 key. If READ_COMMENT is true, receive a comment string as well.
1311 Constructs a new S-Expression from received data and stores it in
1312 KEY_NEW. Returns zero on success or an error code. */
1313 static gpg_error_t
1314 ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret,
1315 int read_comment, ssh_key_type_spec_t *key_spec)
1317 gpg_error_t err;
1318 char *key_type;
1319 char *comment;
1320 gcry_sexp_t key;
1321 ssh_key_type_spec_t spec;
1322 gcry_mpi_t *mpi_list;
1323 const char *elems;
1325 mpi_list = NULL;
1326 key_type = NULL;
1327 comment = "";
1328 key = NULL;
1330 err = stream_read_cstring (stream, &key_type);
1331 if (err)
1332 goto out;
1334 err = ssh_key_type_lookup (key_type, NULL, &spec);
1335 if (err)
1336 goto out;
1338 err = ssh_receive_mpint_list (stream, secret, spec, &mpi_list);
1339 if (err)
1340 goto out;
1342 if (read_comment)
1344 err = stream_read_cstring (stream, &comment);
1345 if (err)
1346 goto out;
1349 if (secret)
1350 elems = spec.elems_key_secret;
1351 else
1352 elems = spec.elems_key_public;
1354 if (spec.key_modifier)
1356 err = (*spec.key_modifier) (elems, mpi_list);
1357 if (err)
1358 goto out;
1361 err = sexp_key_construct (&key, spec, secret, mpi_list, comment);
1362 if (err)
1363 goto out;
1365 if (key_spec)
1366 *key_spec = spec;
1367 *key_new = key;
1369 out:
1371 mpint_list_free (mpi_list);
1372 xfree (key_type);
1373 if (read_comment)
1374 xfree (comment);
1376 return err;
1379 /* Converts a key of type TYPE, whose key material is given in MPIS,
1380 into a newly created binary blob, which is to be stored in
1381 BLOB/BLOB_SIZE. Returns zero on success or an error code. */
1382 static gpg_error_t
1383 ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size,
1384 const char *type, gcry_mpi_t *mpis)
1386 unsigned char *blob_new;
1387 long int blob_size_new;
1388 estream_t stream;
1389 gpg_error_t err;
1390 unsigned int i;
1392 *blob = NULL;
1393 *blob_size = 0;
1395 blob_new = NULL;
1396 stream = NULL;
1397 err = 0;
1399 stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1400 if (! stream)
1402 err = gpg_error_from_syserror ();
1403 goto out;
1406 err = stream_write_cstring (stream, type);
1407 if (err)
1408 goto out;
1410 for (i = 0; mpis[i] && (! err); i++)
1411 err = stream_write_mpi (stream, mpis[i]);
1412 if (err)
1413 goto out;
1415 blob_size_new = es_ftell (stream);
1416 if (blob_size_new == -1)
1418 err = gpg_error_from_syserror ();
1419 goto out;
1422 err = es_fseek (stream, 0, SEEK_SET);
1423 if (err)
1424 goto out;
1426 blob_new = xtrymalloc (blob_size_new);
1427 if (! blob_new)
1429 err = gpg_error_from_syserror ();
1430 goto out;
1433 err = stream_read_data (stream, blob_new, blob_size_new);
1434 if (err)
1435 goto out;
1437 *blob = blob_new;
1438 *blob_size = blob_size_new;
1440 out:
1442 if (stream)
1443 es_fclose (stream);
1444 if (err)
1445 xfree (blob_new);
1447 return err;
1451 /* Write the public key KEY_PUBLIC to STREAM in SSH key format. If
1452 OVERRIDE_COMMENT is not NULL, it will be used instead of the
1453 comment stored in the key. */
1454 static gpg_error_t
1455 ssh_send_key_public (estream_t stream, gcry_sexp_t key_public,
1456 const char *override_comment)
1458 ssh_key_type_spec_t spec;
1459 gcry_mpi_t *mpi_list;
1460 char *key_type;
1461 char *comment;
1462 unsigned char *blob;
1463 size_t blob_n;
1464 gpg_error_t err;
1466 key_type = NULL;
1467 mpi_list = NULL;
1468 comment = NULL;
1469 blob = NULL;
1471 err = sexp_extract_identifier (key_public, &key_type);
1472 if (err)
1473 goto out;
1475 err = ssh_key_type_lookup (NULL, key_type, &spec);
1476 if (err)
1477 goto out;
1479 err = sexp_key_extract (key_public, spec, NULL, &mpi_list, &comment);
1480 if (err)
1481 goto out;
1483 err = ssh_convert_key_to_blob (&blob, &blob_n,
1484 spec.ssh_identifier, mpi_list);
1485 if (err)
1486 goto out;
1488 err = stream_write_string (stream, blob, blob_n);
1489 if (err)
1490 goto out;
1492 err = stream_write_cstring (stream,
1493 override_comment? override_comment : comment);
1495 out:
1497 mpint_list_free (mpi_list);
1498 xfree (key_type);
1499 xfree (comment);
1500 xfree (blob);
1502 return err;
1505 /* Read a public key out of BLOB/BLOB_SIZE according to the key
1506 specification given as KEY_SPEC, storing the new key in KEY_PUBLIC.
1507 Returns zero on success or an error code. */
1508 static gpg_error_t
1509 ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size,
1510 gcry_sexp_t *key_public,
1511 ssh_key_type_spec_t *key_spec)
1513 estream_t blob_stream;
1514 gpg_error_t err;
1516 err = 0;
1518 blob_stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1519 if (! blob_stream)
1521 err = gpg_error_from_syserror ();
1522 goto out;
1525 err = stream_write_data (blob_stream, blob, blob_size);
1526 if (err)
1527 goto out;
1529 err = es_fseek (blob_stream, 0, SEEK_SET);
1530 if (err)
1531 goto out;
1533 err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec);
1535 out:
1537 if (blob_stream)
1538 es_fclose (blob_stream);
1540 return err;
1545 /* This function calculates the key grip for the key contained in the
1546 S-Expression KEY and writes it to BUFFER, which must be large
1547 enough to hold it. Returns usual error code. */
1548 static gpg_error_t
1549 ssh_key_grip (gcry_sexp_t key, unsigned char *buffer)
1551 if (!gcry_pk_get_keygrip (key, buffer))
1552 return gpg_error (GPG_ERR_INTERNAL);
1554 return 0;
1557 /* Converts the secret key KEY_SECRET into a public key, storing it in
1558 KEY_PUBLIC. SPEC is the according key specification. Returns zero
1559 on success or an error code. */
1560 static gpg_error_t
1561 key_secret_to_public (gcry_sexp_t *key_public,
1562 ssh_key_type_spec_t spec, gcry_sexp_t key_secret)
1564 char *comment;
1565 gcry_mpi_t *mpis;
1566 gpg_error_t err;
1567 int is_secret;
1569 comment = NULL;
1570 mpis = NULL;
1572 err = sexp_key_extract (key_secret, spec, &is_secret, &mpis, &comment);
1573 if (err)
1574 goto out;
1576 err = sexp_key_construct (key_public, spec, 0, mpis, comment);
1578 out:
1580 mpint_list_free (mpis);
1581 xfree (comment);
1583 return err;
1587 /* Check whether a smartcard is available and whether it has a usable
1588 key. Store a copy of that key at R_PK and return 0. If no key is
1589 available store NULL at R_PK and return an error code. If CARDSN
1590 is not NULL, a string with the serial number of the card will be
1591 a malloced and stored there. */
1592 static gpg_error_t
1593 card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
1595 gpg_error_t err;
1596 char *authkeyid;
1597 char *serialno = NULL;
1598 unsigned char *pkbuf;
1599 size_t pkbuflen;
1600 gcry_sexp_t s_pk;
1601 unsigned char grip[20];
1603 *r_pk = NULL;
1604 if (cardsn)
1605 *cardsn = NULL;
1607 /* First see whether a card is available and whether the application
1608 is supported. */
1609 err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid);
1610 if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED )
1612 /* Ask for the serial number to reset the card. */
1613 err = agent_card_serialno (ctrl, &serialno);
1614 if (err)
1616 if (opt.verbose)
1617 log_info (_("error getting serial number of card: %s\n"),
1618 gpg_strerror (err));
1619 return err;
1621 log_info (_("detected card with S/N: %s\n"), serialno);
1622 err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid);
1624 if (err)
1626 log_error (_("error getting default authentication keyID of card: %s\n"),
1627 gpg_strerror (err));
1628 xfree (serialno);
1629 return err;
1632 /* Get the S/N if we don't have it yet. Use the fast getattr method. */
1633 if (!serialno && (err = agent_card_getattr (ctrl, "SERIALNO", &serialno)) )
1635 log_error (_("error getting serial number of card: %s\n"),
1636 gpg_strerror (err));
1637 xfree (authkeyid);
1638 return err;
1641 /* Read the public key. */
1642 err = agent_card_readkey (ctrl, authkeyid, &pkbuf);
1643 if (err)
1645 if (opt.verbose)
1646 log_info (_("no suitable card key found: %s\n"), gpg_strerror (err));
1647 xfree (serialno);
1648 xfree (authkeyid);
1649 return err;
1652 pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
1653 err = gcry_sexp_sscan (&s_pk, NULL, (char*)pkbuf, pkbuflen);
1654 if (err)
1656 log_error ("failed to build S-Exp from received card key: %s\n",
1657 gpg_strerror (err));
1658 xfree (pkbuf);
1659 xfree (serialno);
1660 xfree (authkeyid);
1661 return err;
1664 err = ssh_key_grip (s_pk, grip);
1665 if (err)
1667 log_debug ("error computing keygrip from received card key: %s\n",
1668 gcry_strerror (err));
1669 xfree (pkbuf);
1670 gcry_sexp_release (s_pk);
1671 xfree (serialno);
1672 xfree (authkeyid);
1673 return err;
1676 if ( agent_key_available (grip) )
1678 /* (Shadow)-key is not available in our key storage. */
1679 unsigned char *shadow_info;
1680 unsigned char *tmp;
1682 shadow_info = make_shadow_info (serialno, authkeyid);
1683 if (!shadow_info)
1685 err = gpg_error_from_syserror ();
1686 xfree (pkbuf);
1687 gcry_sexp_release (s_pk);
1688 xfree (serialno);
1689 xfree (authkeyid);
1690 return err;
1692 err = agent_shadow_key (pkbuf, shadow_info, &tmp);
1693 xfree (shadow_info);
1694 if (err)
1696 log_error (_("shadowing the key failed: %s\n"), gpg_strerror (err));
1697 xfree (pkbuf);
1698 gcry_sexp_release (s_pk);
1699 xfree (serialno);
1700 xfree (authkeyid);
1701 return err;
1703 xfree (pkbuf);
1704 pkbuf = tmp;
1705 pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
1706 assert (pkbuflen);
1708 err = agent_write_private_key (grip, pkbuf, pkbuflen, 0);
1709 if (err)
1711 log_error (_("error writing key: %s\n"), gpg_strerror (err));
1712 xfree (pkbuf);
1713 gcry_sexp_release (s_pk);
1714 xfree (serialno);
1715 xfree (authkeyid);
1716 return err;
1720 if (cardsn)
1722 char *dispsn;
1724 /* If the card handler is able to return a short serialnumber,
1725 use that one, else use the complete serialno. */
1726 if (!agent_card_getattr (ctrl, "$DISPSERIALNO", &dispsn))
1728 *cardsn = xtryasprintf ("cardno:%s", dispsn);
1729 xfree (dispsn);
1731 else
1732 *cardsn = xtryasprintf ("cardno:%s", serialno);
1733 if (!*cardsn)
1735 err = gpg_error_from_syserror ();
1736 xfree (pkbuf);
1737 gcry_sexp_release (s_pk);
1738 xfree (serialno);
1739 xfree (authkeyid);
1740 return err;
1744 xfree (pkbuf);
1745 xfree (serialno);
1746 xfree (authkeyid);
1747 *r_pk = s_pk;
1748 return 0;
1756 Request handler. Each handler is provided with a CTRL context, a
1757 REQUEST object and a RESPONSE object. The actual request is to be
1758 read from REQUEST, the response needs to be written to RESPONSE.
1763 /* Handler for the "request_identities" command. */
1764 static gpg_error_t
1765 ssh_handler_request_identities (ctrl_t ctrl,
1766 estream_t request, estream_t response)
1768 char *key_type;
1769 ssh_key_type_spec_t spec;
1770 struct dirent *dir_entry;
1771 char *key_directory;
1772 size_t key_directory_n;
1773 char *key_path;
1774 unsigned char *buffer;
1775 size_t buffer_n;
1776 u32 key_counter;
1777 estream_t key_blobs;
1778 gcry_sexp_t key_secret;
1779 gcry_sexp_t key_public;
1780 DIR *dir;
1781 gpg_error_t err;
1782 int ret;
1783 FILE *ctrl_fp = NULL;
1784 char *cardsn;
1785 gpg_error_t ret_err;
1787 (void)request;
1789 /* Prepare buffer stream. */
1791 key_directory = NULL;
1792 key_secret = NULL;
1793 key_public = NULL;
1794 key_type = NULL;
1795 key_path = NULL;
1796 key_counter = 0;
1797 buffer = NULL;
1798 dir = NULL;
1799 err = 0;
1801 key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1802 if (! key_blobs)
1804 err = gpg_error_from_syserror ();
1805 goto out;
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);
1813 goto out;
1815 key_directory_n = strlen (key_directory);
1817 key_path = xtrymalloc (key_directory_n + 46);
1818 if (! key_path)
1820 err = gpg_err_code_from_errno (errno);
1821 goto out;
1824 sprintf (key_path, "%s/", key_directory);
1825 sprintf (key_path + key_directory_n + 41, ".key");
1827 dir = opendir (key_directory);
1828 if (! dir)
1830 err = gpg_err_code_from_errno (errno);
1831 goto out;
1836 /* First check whether a key is currently available in the card
1837 reader - this should be allowed even without being listed in
1838 sshcontrol. */
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);
1844 key_public = NULL;
1845 xfree (cardsn);
1846 if (err)
1847 goto out;
1849 key_counter++;
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);
1861 if (err)
1862 goto out;
1864 while ( (dir_entry = readdir (dir)) )
1866 if ((strlen (dir_entry->d_name) == 44)
1867 && (! strncmp (dir_entry->d_name + 40, ".key", 4)))
1869 char hexgrip[41];
1870 int disabled;
1872 /* We do only want to return keys listed in our control
1873 file. */
1874 strncpy (hexgrip, dir_entry->d_name, 40);
1875 hexgrip[40] = 0;
1876 if ( strlen (hexgrip) != 40 )
1877 continue;
1878 if (search_control_file (ctrl_fp, hexgrip, &disabled)
1879 || disabled)
1880 continue;
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);
1886 if (err)
1887 goto out;
1889 err = gcry_sexp_sscan (&key_secret, NULL, (char*)buffer, buffer_n);
1890 if (err)
1891 goto out;
1893 xfree (buffer);
1894 buffer = NULL;
1896 err = sexp_extract_identifier (key_secret, &key_type);
1897 if (err)
1898 goto out;
1900 err = ssh_key_type_lookup (NULL, key_type, &spec);
1901 if (err)
1902 goto out;
1904 xfree (key_type);
1905 key_type = NULL;
1907 err = key_secret_to_public (&key_public, spec, key_secret);
1908 if (err)
1909 goto out;
1911 gcry_sexp_release (key_secret);
1912 key_secret = NULL;
1914 err = ssh_send_key_public (key_blobs, key_public, NULL);
1915 if (err)
1916 goto out;
1918 gcry_sexp_release (key_public);
1919 key_public = NULL;
1921 key_counter++;
1925 ret = es_fseek (key_blobs, 0, SEEK_SET);
1926 if (ret)
1928 err = gpg_error_from_syserror ();
1929 goto out;
1932 out:
1934 /* Send response. */
1936 gcry_sexp_release (key_secret);
1937 gcry_sexp_release (key_public);
1939 if (! err)
1941 ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER);
1942 if (ret_err)
1943 goto leave;
1944 ret_err = stream_write_uint32 (response, key_counter);
1945 if (ret_err)
1946 goto leave;
1947 ret_err = stream_copy (response, key_blobs);
1948 if (ret_err)
1949 goto leave;
1951 else
1953 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
1954 goto leave;
1957 leave:
1959 if (key_blobs)
1960 es_fclose (key_blobs);
1961 if (dir)
1962 closedir (dir);
1964 if (ctrl_fp)
1965 fclose (ctrl_fp);
1967 xfree (key_directory);
1968 xfree (key_path);
1969 xfree (buffer);
1970 xfree (key_type);
1972 return ret_err;
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
1978 for the digest. */
1979 static gpg_error_t
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);
1985 return 0;
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. */
1991 static gpg_error_t
1992 data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder,
1993 unsigned char **sig, size_t *sig_n)
1995 gpg_error_t err;
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;
2007 int ret;
2008 unsigned int i;
2009 const char *elems;
2010 size_t elems_n;
2011 gcry_mpi_t *mpis = NULL;
2013 *sig = NULL;
2014 *sig_n = 0;
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,
2020 CACHE_MODE_SSH);
2021 ctrl->use_auth_call = 0;
2022 if (err)
2023 goto out;
2025 valuelist = gcry_sexp_nth (signature_sexp, 1);
2026 if (! valuelist)
2028 err = gpg_error (GPG_ERR_INV_SEXP);
2029 goto out;
2032 stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
2033 if (! stream)
2035 err = gpg_error_from_syserror ();
2036 goto out;
2039 identifier_raw = gcry_sexp_nth_data (valuelist, 0, &identifier_n);
2040 if (! identifier_raw)
2042 err = gpg_error (GPG_ERR_INV_SEXP);
2043 goto out;
2046 identifier = make_cstring (identifier_raw, identifier_n);
2047 if (! identifier)
2049 err = gpg_error_from_syserror ();
2050 goto out;
2053 err = ssh_key_type_lookup (NULL, identifier, &spec);
2054 if (err)
2055 goto out;
2057 err = stream_write_cstring (stream, spec.ssh_identifier);
2058 if (err)
2059 goto out;
2061 elems = spec.elems_signature;
2062 elems_n = strlen (elems);
2064 mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
2065 if (!mpis)
2067 err = gpg_error_from_syserror ();
2068 goto out;
2071 for (i = 0; i < elems_n; i++)
2073 sublist = gcry_sexp_find_token (valuelist, spec.elems_signature + i, 1);
2074 if (! sublist)
2076 err = gpg_error (GPG_ERR_INV_SEXP);
2077 break;
2080 sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
2081 if (! sig_value)
2083 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
2084 break;
2086 gcry_sexp_release (sublist);
2087 sublist = NULL;
2089 mpis[i] = sig_value;
2091 if (err)
2092 goto out;
2094 err = (*sig_encoder) (stream, mpis);
2095 if (err)
2096 goto out;
2098 sig_blob_n = es_ftell (stream);
2099 if (sig_blob_n == -1)
2101 err = gpg_error_from_syserror ();
2102 goto out;
2105 sig_blob = xtrymalloc (sig_blob_n);
2106 if (! sig_blob)
2108 err = gpg_error_from_syserror ();
2109 goto out;
2112 ret = es_fseek (stream, 0, SEEK_SET);
2113 if (ret)
2115 err = gpg_error_from_syserror ();
2116 goto out;
2119 err = stream_read_data (stream, sig_blob, sig_blob_n);
2120 if (err)
2121 goto out;
2123 *sig = sig_blob;
2124 *sig_n = sig_blob_n;
2126 out:
2128 if (err)
2129 xfree (sig_blob);
2131 if (stream)
2132 es_fclose (stream);
2133 gcry_sexp_release (valuelist);
2134 gcry_sexp_release (signature_sexp);
2135 gcry_sexp_release (sublist);
2136 mpint_list_free (mpis);
2137 xfree (identifier);
2139 return err;
2142 /* Handler for the "sign_request" command. */
2143 static gpg_error_t
2144 ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
2146 gcry_sexp_t key;
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;
2152 u32 key_blob_size;
2153 unsigned char *data;
2154 unsigned char *sig;
2155 size_t sig_n;
2156 u32 data_size;
2157 u32 flags;
2158 gpg_error_t err;
2159 gpg_error_t ret_err;
2161 key_blob = NULL;
2162 data = NULL;
2163 sig = NULL;
2164 key = NULL;
2166 /* Receive key. */
2168 err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2169 if (err)
2170 goto out;
2172 err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec);
2173 if (err)
2174 goto out;
2176 /* Receive data to sign. */
2177 err = stream_read_string (request, 0, &data, &data_size);
2178 if (err)
2179 goto out;
2181 /* FIXME? */
2182 err = stream_read_uint32 (request, &flags);
2183 if (err)
2184 goto out;
2186 /* Hash data. */
2187 hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
2188 if (! hash_n)
2190 err = gpg_error (GPG_ERR_INTERNAL);
2191 goto out;
2193 err = data_hash (data, data_size, GCRY_MD_SHA1, hash);
2194 if (err)
2195 goto out;
2197 /* Calculate key grip. */
2198 err = ssh_key_grip (key, key_grip);
2199 if (err)
2200 goto out;
2202 /* Sign data. */
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);
2213 out:
2215 /* Done. */
2217 if (! err)
2219 ret_err = stream_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE);
2220 if (ret_err)
2221 goto leave;
2222 ret_err = stream_write_string (response, sig, sig_n);
2223 if (ret_err)
2224 goto leave;
2226 else
2228 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2229 if (ret_err)
2230 goto leave;
2233 leave:
2235 gcry_sexp_release (key);
2236 xfree (key_blob);
2237 xfree (data);
2238 xfree (sig);
2240 return ret_err;
2243 /* This function extracts the comment contained in the key
2244 S-Expression KEY and stores a copy in COMMENT. Returns usual error
2245 code. */
2246 static gpg_error_t
2247 ssh_key_extract_comment (gcry_sexp_t key, char **comment)
2249 gcry_sexp_t comment_list;
2250 char *comment_new;
2251 const char *data;
2252 size_t data_n;
2253 gpg_error_t err;
2255 comment_list = gcry_sexp_find_token (key, "comment", 0);
2256 if (! comment_list)
2258 err = gpg_error (GPG_ERR_INV_SEXP);
2259 goto out;
2262 data = gcry_sexp_nth_data (comment_list, 1, &data_n);
2263 if (! data)
2265 err = gpg_error (GPG_ERR_INV_SEXP);
2266 goto out;
2269 comment_new = make_cstring (data, data_n);
2270 if (! comment_new)
2272 err = gpg_error_from_syserror ();
2273 goto out;
2276 *comment = comment_new;
2277 err = 0;
2279 out:
2281 gcry_sexp_release (comment_list);
2283 return err;
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. */
2289 static gpg_error_t
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;
2295 gpg_error_t err;
2297 err = 0;
2298 buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0);
2299 buffer_new = xtrymalloc_secure (buffer_new_n);
2300 if (! buffer_new)
2302 err = gpg_error_from_syserror ();
2303 goto out;
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);
2311 out:
2313 xfree (buffer_new);
2315 return err;
2320 /* Callback function to compare the first entered PIN with the one
2321 currently being entered. */
2322 static int
2323 reenter_compare_cb (struct pin_entry_info_s *pi)
2325 const char *pin1 = pi->check_cb_arg;
2327 if (!strcmp (pin1, pi->pin))
2328 return 0; /* okay */
2329 return -1;
2332 /* Store the ssh KEY into our local key storage and protect it after
2333 asking for a passphrase. Cache that passphrase. TTL is the
2334 maximum caching time for that key. If the key already exists in
2335 our key storage, don't do anything. When entering a new key also
2336 add an entry to the sshcontrol file. */
2337 static gpg_error_t
2338 ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
2340 gpg_error_t err;
2341 unsigned char key_grip_raw[20];
2342 char key_grip[41];
2343 unsigned char *buffer = NULL;
2344 size_t buffer_n;
2345 char *description = NULL;
2346 const char *description2 = _("Please re-enter this passphrase");
2347 char *comment = NULL;
2348 const char *initial_errtext = NULL;
2349 unsigned int i;
2350 struct pin_entry_info_s *pi = NULL, *pi2;
2352 err = ssh_key_grip (key, key_grip_raw);
2353 if (err)
2354 goto out;
2356 /* Check whether the key is already in our key storage. Don't do
2357 anything then. */
2358 if ( !agent_key_available (key_grip_raw) )
2359 goto out; /* Yes, key is available. */
2362 err = ssh_key_extract_comment (key, &comment);
2363 if (err)
2364 goto out;
2366 if ( asprintf (&description,
2367 _("Please enter a passphrase to protect"
2368 " the received secret key%%0A"
2369 " %s%%0A"
2370 "within gpg-agent's key storage"),
2371 comment ? comment : "?") < 0)
2373 err = gpg_error_from_syserror ();
2374 goto out;
2378 pi = gcry_calloc_secure (2, sizeof (*pi) + 100 + 1);
2379 if (!pi)
2381 err = gpg_error_from_syserror ();
2382 goto out;
2384 pi2 = pi + (sizeof *pi + 100 + 1);
2385 pi->max_length = 100;
2386 pi->max_tries = 1;
2387 pi2->max_length = 100;
2388 pi2->max_tries = 1;
2389 pi2->check_cb = reenter_compare_cb;
2390 pi2->check_cb_arg = pi->pin;
2392 next_try:
2393 err = agent_askpin (ctrl, description, NULL, initial_errtext, pi);
2394 initial_errtext = NULL;
2395 if (err)
2396 goto out;
2398 /* Unless the passphrase is empty, ask to confirm it. */
2399 if (pi->pin && *pi->pin)
2401 err = agent_askpin (ctrl, description2, NULL, NULL, pi2);
2402 if (err == -1)
2403 { /* The re-entered one did not match and the user did not
2404 hit cancel. */
2405 initial_errtext = _("does not match - try again");
2406 goto next_try;
2410 err = ssh_key_to_protected_buffer (key, pi->pin, &buffer, &buffer_n);
2411 if (err)
2412 goto out;
2414 /* Store this key to our key storage. */
2415 err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0);
2416 if (err)
2417 goto out;
2419 /* Cache this passphrase. */
2420 for (i = 0; i < 20; i++)
2421 sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]);
2423 err = agent_put_cache (key_grip, CACHE_MODE_SSH, pi->pin, ttl);
2424 if (err)
2425 goto out;
2427 /* And add an entry to the sshcontrol file. */
2428 err = add_control_entry (ctrl, key_grip, ttl);
2431 out:
2432 if (pi && pi->max_length)
2433 wipememory (pi->pin, pi->max_length);
2434 xfree (pi);
2435 xfree (buffer);
2436 xfree (comment);
2437 xfree (description);
2439 return err;
2443 /* This function removes the key contained in the S-Expression KEY
2444 from the local key storage, in case it exists there. Returns usual
2445 error code. FIXME: this function is a stub. */
2446 static gpg_error_t
2447 ssh_identity_drop (gcry_sexp_t key)
2449 unsigned char key_grip[21] = { 0 };
2450 gpg_error_t err;
2452 err = ssh_key_grip (key, key_grip);
2453 if (err)
2454 goto out;
2456 key_grip[sizeof (key_grip) - 1] = 0;
2458 /* FIXME: What to do here - forgetting the passphrase or deleting
2459 the key from key cache? */
2461 out:
2463 return err;
2466 /* Handler for the "add_identity" command. */
2467 static gpg_error_t
2468 ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
2470 gpg_error_t ret_err;
2471 gpg_error_t err;
2472 gcry_sexp_t key;
2473 unsigned char b;
2474 int confirm;
2475 int ttl;
2477 confirm = 0;
2478 key = NULL;
2479 ttl = 0;
2481 /* FIXME? */
2482 err = ssh_receive_key (request, &key, 1, 1, NULL);
2483 if (err)
2484 goto out;
2486 while (1)
2488 err = stream_read_byte (request, &b);
2489 if (gpg_err_code (err) == GPG_ERR_EOF)
2491 err = 0;
2492 break;
2495 switch (b)
2497 case SSH_OPT_CONSTRAIN_LIFETIME:
2499 u32 n = 0;
2501 err = stream_read_uint32 (request, &n);
2502 if (! err)
2503 ttl = n;
2504 break;
2507 case SSH_OPT_CONSTRAIN_CONFIRM:
2509 confirm = 1;
2510 break;
2513 default:
2514 /* FIXME: log/bad? */
2515 break;
2518 if (err)
2519 goto out;
2521 /* FIXME: are constraints used correctly? */
2523 err = ssh_identity_register (ctrl, key, ttl);
2525 out:
2527 gcry_sexp_release (key);
2529 if (! err)
2530 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2531 else
2532 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2534 return ret_err;
2537 /* Handler for the "remove_identity" command. */
2538 static gpg_error_t
2539 ssh_handler_remove_identity (ctrl_t ctrl,
2540 estream_t request, estream_t response)
2542 unsigned char *key_blob;
2543 u32 key_blob_size;
2544 gcry_sexp_t key;
2545 gpg_error_t ret_err;
2546 gpg_error_t err;
2548 (void)ctrl;
2550 /* Receive key. */
2552 key_blob = NULL;
2553 key = NULL;
2555 err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2556 if (err)
2557 goto out;
2559 err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL);
2560 if (err)
2561 goto out;
2563 err = ssh_identity_drop (key);
2565 out:
2567 xfree (key_blob);
2568 gcry_sexp_release (key);
2570 if (! err)
2571 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2572 else
2573 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2575 return ret_err;
2578 /* FIXME: stub function. Actually useful? */
2579 static gpg_error_t
2580 ssh_identities_remove_all (void)
2582 gpg_error_t err;
2584 err = 0;
2586 /* FIXME: shall we remove _all_ cache entries or only those
2587 registered through the ssh emulation? */
2589 return err;
2592 /* Handler for the "remove_all_identities" command. */
2593 static gpg_error_t
2594 ssh_handler_remove_all_identities (ctrl_t ctrl,
2595 estream_t request, estream_t response)
2597 gpg_error_t ret_err;
2598 gpg_error_t err;
2600 (void)ctrl;
2601 (void)request;
2603 err = ssh_identities_remove_all ();
2605 if (! err)
2606 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2607 else
2608 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2610 return ret_err;
2613 /* Lock agent? FIXME: stub function. */
2614 static gpg_error_t
2615 ssh_lock (void)
2617 gpg_error_t err;
2619 /* FIXME */
2620 log_error ("ssh-agent's lock command is not implemented\n");
2621 err = 0;
2623 return err;
2626 /* Unock agent? FIXME: stub function. */
2627 static gpg_error_t
2628 ssh_unlock (void)
2630 gpg_error_t err;
2632 log_error ("ssh-agent's unlock command is not implemented\n");
2633 err = 0;
2635 return err;
2638 /* Handler for the "lock" command. */
2639 static gpg_error_t
2640 ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response)
2642 gpg_error_t ret_err;
2643 gpg_error_t err;
2645 (void)ctrl;
2646 (void)request;
2648 err = ssh_lock ();
2650 if (! err)
2651 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2652 else
2653 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2655 return ret_err;
2658 /* Handler for the "unlock" command. */
2659 static gpg_error_t
2660 ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
2662 gpg_error_t ret_err;
2663 gpg_error_t err;
2665 (void)ctrl;
2666 (void)request;
2668 err = ssh_unlock ();
2670 if (! err)
2671 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2672 else
2673 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2675 return ret_err;
2680 /* Return the request specification for the request identified by TYPE
2681 or NULL in case the requested request specification could not be
2682 found. */
2683 static ssh_request_spec_t *
2684 request_spec_lookup (int type)
2686 ssh_request_spec_t *spec;
2687 unsigned int i;
2689 for (i = 0; i < DIM (request_specs); i++)
2690 if (request_specs[i].type == type)
2691 break;
2692 if (i == DIM (request_specs))
2694 if (opt.verbose)
2695 log_info ("ssh request %u is not supported\n", type);
2696 spec = NULL;
2698 else
2699 spec = request_specs + i;
2701 return spec;
2704 /* Process a single request. The request is read from and the
2705 response is written to STREAM_SOCK. Uses CTRL as context. Returns
2706 zero in case of success, non zero in case of failure. */
2707 static int
2708 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
2710 ssh_request_spec_t *spec;
2711 estream_t response;
2712 estream_t request;
2713 unsigned char request_type;
2714 gpg_error_t err;
2715 int send_err;
2716 int ret;
2717 unsigned char *request_data;
2718 u32 request_data_size;
2719 u32 response_size;
2721 request_data = NULL;
2722 response = NULL;
2723 request = NULL;
2724 send_err = 0;
2726 /* Create memory streams for request/response data. The entire
2727 request will be stored in secure memory, since it might contain
2728 secret key material. The response does not have to be stored in
2729 secure memory, since we never give out secret keys.
2731 Note: we only have little secure memory, but there is NO
2732 possibility of DoS here; only trusted clients are allowed to
2733 connect to the agent. What could happen is that the agent
2734 returns out-of-secure-memory errors on requests in case the
2735 agent's owner floods his own agent with many large messages.
2736 -moritz */
2738 /* Retrieve request. */
2739 err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
2740 if (err)
2741 goto out;
2743 if (opt.verbose > 1)
2744 log_info ("received ssh request of length %u\n",
2745 (unsigned int)request_data_size);
2747 if (! request_data_size)
2749 send_err = 1;
2750 goto out;
2751 /* Broken request; FIXME. */
2754 request_type = request_data[0];
2755 spec = request_spec_lookup (request_type);
2756 if (! spec)
2758 send_err = 1;
2759 goto out;
2760 /* Unknown request; FIXME. */
2763 if (spec->secret_input)
2764 request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
2765 else
2766 request = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+");
2767 if (! request)
2769 err = gpg_error_from_syserror ();
2770 goto out;
2772 ret = es_setvbuf (request, NULL, _IONBF, 0);
2773 if (ret)
2775 err = gpg_error_from_syserror ();
2776 goto out;
2778 err = stream_write_data (request, request_data + 1, request_data_size - 1);
2779 if (err)
2780 goto out;
2781 es_rewind (request);
2783 response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
2784 if (! response)
2786 err = gpg_error_from_syserror ();
2787 goto out;
2790 if (opt.verbose)
2791 log_info ("ssh request handler for %s (%u) started\n",
2792 spec->identifier, spec->type);
2794 err = (*spec->handler) (ctrl, request, response);
2796 if (opt.verbose)
2798 if (err)
2799 log_info ("ssh request handler for %s (%u) failed: %s\n",
2800 spec->identifier, spec->type, gpg_strerror (err));
2801 else
2802 log_info ("ssh request handler for %s (%u) ready\n",
2803 spec->identifier, spec->type);
2806 if (err)
2808 send_err = 1;
2809 goto out;
2812 response_size = es_ftell (response);
2813 if (opt.verbose > 1)
2814 log_info ("sending ssh response of length %u\n",
2815 (unsigned int)response_size);
2817 err = es_fseek (response, 0, SEEK_SET);
2818 if (err)
2820 send_err = 1;
2821 goto out;
2824 err = stream_write_uint32 (stream_sock, response_size);
2825 if (err)
2827 send_err = 1;
2828 goto out;
2831 err = stream_copy (stream_sock, response);
2832 if (err)
2833 goto out;
2835 err = es_fflush (stream_sock);
2836 if (err)
2837 goto out;
2839 out:
2841 if (err && es_feof (stream_sock))
2842 log_error ("error occured while processing request: %s\n",
2843 gpg_strerror (err));
2845 if (send_err)
2847 if (opt.verbose > 1)
2848 log_info ("sending ssh error response\n");
2849 err = stream_write_uint32 (stream_sock, 1);
2850 if (err)
2851 goto leave;
2852 err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE);
2853 if (err)
2854 goto leave;
2857 leave:
2859 if (request)
2860 es_fclose (request);
2861 if (response)
2862 es_fclose (response);
2863 xfree (request_data); /* FIXME? */
2865 return !!err;
2868 /* Start serving client on SOCK_CLIENT. */
2869 void
2870 start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
2872 estream_t stream_sock;
2873 gpg_error_t err;
2874 int ret;
2876 /* Because the ssh protocol does not send us information about the
2877 the current TTY setting, we resort here to use those from startup
2878 or those explictly set. */
2879 if (!ctrl->display && opt.startup_display)
2880 ctrl->display = strdup (opt.startup_display);
2881 if (!ctrl->ttyname && opt.startup_ttyname)
2882 ctrl->ttyname = strdup (opt.startup_ttyname);
2883 if (!ctrl->ttytype && opt.startup_ttytype)
2884 ctrl->ttytype = strdup (opt.startup_ttytype);
2885 if (!ctrl->lc_ctype && opt.startup_lc_ctype)
2886 ctrl->lc_ctype = strdup (opt.startup_lc_ctype);
2887 if (!ctrl->lc_messages && opt.startup_lc_messages)
2888 ctrl->lc_messages = strdup (opt.startup_lc_messages);
2889 if (!ctrl->xauthority && opt.startup_xauthority)
2890 ctrl->xauthority = strdup (opt.startup_xauthority);
2891 if (!ctrl->pinentry_user_data && opt.startup_pinentry_user_data)
2892 ctrl->pinentry_user_data = strdup (opt.startup_pinentry_user_data);
2895 /* Create stream from socket. */
2896 stream_sock = es_fdopen (FD2INT(sock_client), "r+");
2897 if (!stream_sock)
2899 err = gpg_error_from_syserror ();
2900 log_error (_("failed to create stream from socket: %s\n"),
2901 gpg_strerror (err));
2902 goto out;
2904 /* We have to disable the estream buffering, because the estream
2905 core doesn't know about secure memory. */
2906 ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
2907 if (ret)
2909 err = gpg_error_from_syserror ();
2910 log_error ("failed to disable buffering "
2911 "on socket stream: %s\n", gpg_strerror (err));
2912 goto out;
2915 /* Main processing loop. */
2916 while ( !ssh_request_process (ctrl, stream_sock) )
2918 /* Check wether we have reached EOF before trying to read
2919 another request. */
2920 int c;
2922 c = es_fgetc (stream_sock);
2923 if (c == EOF)
2924 break;
2925 es_ungetc (c, stream_sock);
2928 /* Reset the SCD in case it has been used. */
2929 agent_reset_scd (ctrl);
2932 out:
2933 if (stream_sock)
2934 es_fclose (stream_sock);