2006-10-24 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / agent / command-ssh.c
blob1adf8ba949f4dcb3f9eafab3089785e94d5bef70
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,
19 * USA.
22 /* Only v2 of the ssh-agent protocol is implemented. */
24 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <dirent.h>
33 #include <assert.h>
35 #include "agent.h"
37 #include "estream.h"
38 #include "i18n.h"
42 /* Request types. */
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
52 /* Options. */
53 #define SSH_OPT_CONSTRAIN_LIFETIME 1
54 #define SSH_OPT_CONSTRAIN_CONFIRM 2
56 /* Response types. */
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"
80 "\n";
84 /* Macros. */
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)
95 * Basic types.
98 /* Type for a request handler. */
99 typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl,
100 estream_t request,
101 estream_t response);
103 /* Type, which is used for associating request handlers with the
104 appropriate request IDs. */
105 typedef struct ssh_request_spec
107 unsigned char type;
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,
118 gcry_mpi_t *mpis);
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,
124 gcry_mpi_t *mpis);
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
137 agent protocol. */
138 const char *elems_key_secret;
140 /* List of MPI names for public keys; order matches the one of the
141 agent protocol. */
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
158 algorithm. */
159 ssh_signature_encoder_t signature_encoder;
161 /* Misc flags. */
162 unsigned int flags;
163 } ssh_key_type_spec_t;
166 /* Prototypes. */
167 static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl,
168 estream_t request,
169 estream_t response);
170 static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl,
171 estream_t request,
172 estream_t response);
173 static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl,
174 estream_t request,
175 estream_t response);
176 static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl,
177 estream_t request,
178 estream_t response);
179 static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl,
180 estream_t request,
181 estream_t response);
182 static gpg_error_t ssh_handler_lock (ctrl_t ctrl,
183 estream_t request,
184 estream_t response);
185 static gpg_error_t ssh_handler_unlock (ctrl_t ctrl,
186 estream_t request,
187 estream_t response);
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,
191 gcry_mpi_t *mpis);
192 static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob,
193 gcry_mpi_t *mpis);
197 /* Global variables. */
200 /* Associating request types with the corresponding request
201 handlers. */
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
246 existing buffer. */
247 static void *
248 realloc_secure (void *a, size_t n)
250 void *p;
252 if (a)
253 p = gcry_realloc (a, n);
254 else
255 p = gcry_malloc_secure (n);
257 return p;
261 /* Create and return a new C-string from DATA/DATA_N (i.e.: add
262 NUL-termination); return NULL on OOM. */
263 static char *
264 make_cstring (const char *data, size_t data_n)
266 char *s;
268 s = xtrymalloc (data_n + 1);
269 if (s)
271 memcpy (s, data, data_n);
272 s[data_n] = 0;
275 return s;
282 Primitive I/O functions.
286 /* Read a byte from STREAM, store it in B. */
287 static gpg_error_t
288 stream_read_byte (estream_t stream, unsigned char *b)
290 gpg_error_t err;
291 int ret;
293 ret = es_fgetc (stream);
294 if (ret == EOF)
296 if (es_ferror (stream))
297 err = gpg_error_from_syserror ();
298 else
299 err = gpg_error (GPG_ERR_EOF);
300 *b = 0;
302 else
304 *b = ret & 0xFF;
305 err = 0;
308 return err;
311 /* Write the byte contained in B to STREAM. */
312 static gpg_error_t
313 stream_write_byte (estream_t stream, unsigned char b)
315 gpg_error_t err;
316 int ret;
318 ret = es_fputc (b, stream);
319 if (ret == EOF)
320 err = gpg_error_from_syserror ();
321 else
322 err = 0;
324 return err;
327 /* Read a uint32 from STREAM, store it in UINT32. */
328 static gpg_error_t
329 stream_read_uint32 (estream_t stream, u32 *uint32)
331 unsigned char buffer[4];
332 size_t bytes_read;
333 gpg_error_t err;
334 int ret;
336 ret = es_read (stream, buffer, sizeof (buffer), &bytes_read);
337 if (ret)
338 err = gpg_error_from_syserror ();
339 else
341 if (bytes_read != sizeof (buffer))
342 err = gpg_error (GPG_ERR_EOF);
343 else
345 u32 n;
347 n = uint32_construct (buffer[0], buffer[1], buffer[2], buffer[3]);
348 *uint32 = n;
349 err = 0;
353 return err;
356 /* Write the uint32 contained in UINT32 to STREAM. */
357 static gpg_error_t
358 stream_write_uint32 (estream_t stream, u32 uint32)
360 unsigned char buffer[4];
361 gpg_error_t err;
362 int ret;
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);
370 if (ret)
371 err = gpg_error_from_syserror ();
372 else
373 err = 0;
375 return err;
378 /* Read SIZE bytes from STREAM into BUFFER. */
379 static gpg_error_t
380 stream_read_data (estream_t stream, unsigned char *buffer, size_t size)
382 gpg_error_t err;
383 size_t bytes_read;
384 int ret;
386 ret = es_read (stream, buffer, size, &bytes_read);
387 if (ret)
388 err = gpg_error_from_syserror ();
389 else
391 if (bytes_read != size)
392 err = gpg_error (GPG_ERR_EOF);
393 else
394 err = 0;
397 return err;
400 /* Write SIZE bytes from BUFFER to STREAM. */
401 static gpg_error_t
402 stream_write_data (estream_t stream, const unsigned char *buffer, size_t size)
404 gpg_error_t err;
405 int ret;
407 ret = es_write (stream, buffer, size, NULL);
408 if (ret)
409 err = gpg_error_from_syserror ();
410 else
411 err = 0;
413 return err;
416 /* Read a binary string from STREAM into STRING, store size of string
417 in STRING_SIZE; depending on SECURE use secure memory for
418 string. */
419 static gpg_error_t
420 stream_read_string (estream_t stream, unsigned int secure,
421 unsigned char **string, u32 *string_size)
423 gpg_error_t err;
424 unsigned char *buffer;
425 u32 length;
427 buffer = NULL;
429 /* Read string length. */
430 err = stream_read_uint32 (stream, &length);
431 if (err)
432 goto out;
434 /* Allocate space. */
435 if (secure)
436 buffer = xtrymalloc_secure (length + 1);
437 else
438 buffer = xtrymalloc (length + 1);
439 if (! buffer)
441 err = gpg_error_from_syserror ();
442 goto out;
445 /* Read data. */
446 err = stream_read_data (stream, buffer, length);
447 if (err)
448 goto out;
450 /* Finalize string object. */
451 buffer[length] = 0;
452 *string = buffer;
453 if (string_size)
454 *string_size = length;
456 out:
458 if (err)
459 xfree (buffer);
461 return err;
464 /* Read a C-string from STREAM, store copy in STRING. */
465 static gpg_error_t
466 stream_read_cstring (estream_t stream, char **string)
468 unsigned char *buffer;
469 gpg_error_t err;
471 err = stream_read_string (stream, 0, &buffer, NULL);
472 if (err)
473 goto out;
475 *string = (char *) buffer;
477 out:
479 return err;
483 /* Write a binary string from STRING of size STRING_N to STREAM. */
484 static gpg_error_t
485 stream_write_string (estream_t stream,
486 const unsigned char *string, u32 string_n)
488 gpg_error_t err;
490 err = stream_write_uint32 (stream, string_n);
491 if (err)
492 goto out;
494 err = stream_write_data (stream, string, string_n);
496 out:
498 return err;
501 /* Write a C-string from STRING to STREAM. */
502 static gpg_error_t
503 stream_write_cstring (estream_t stream, const char *string)
505 gpg_error_t err;
507 err = stream_write_string (stream,
508 (const unsigned char *) string, strlen (string));
510 return err;
513 /* Read an MPI from STREAM, store it in MPINT. Depending on SECURE
514 use secure memory. */
515 static gpg_error_t
516 stream_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint)
518 unsigned char *mpi_data;
519 u32 mpi_data_size;
520 gpg_error_t err;
521 gcry_mpi_t mpi;
523 mpi_data = NULL;
525 err = stream_read_string (stream, secure, &mpi_data, &mpi_data_size);
526 if (err)
527 goto out;
529 /* To avoid excessive use of secure memory we check that an MPI is
530 not too large. */
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;
535 goto out;
538 err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_STD, mpi_data, mpi_data_size, NULL);
539 if (err)
540 goto out;
542 *mpint = mpi;
544 out:
546 xfree (mpi_data);
548 return err;
551 /* Write the MPI contained in MPINT to STREAM. */
552 static gpg_error_t
553 stream_write_mpi (estream_t stream, gcry_mpi_t mpint)
555 unsigned char *mpi_buffer;
556 size_t mpi_buffer_n;
557 gpg_error_t err;
559 mpi_buffer = NULL;
561 err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &mpi_buffer, &mpi_buffer_n, mpint);
562 if (err)
563 goto out;
565 err = stream_write_string (stream, mpi_buffer, mpi_buffer_n);
567 out:
569 xfree (mpi_buffer);
571 return err;
574 /* Copy data from SRC to DST until EOF is reached. */
575 static gpg_error_t
576 stream_copy (estream_t dst, estream_t src)
578 char buffer[BUFSIZ];
579 size_t bytes_read;
580 gpg_error_t err;
581 int ret;
583 err = 0;
584 while (1)
586 ret = es_read (src, buffer, sizeof (buffer), &bytes_read);
587 if (ret || (! bytes_read))
589 if (ret)
590 err = gpg_error_from_syserror ();
591 break;
593 ret = es_write (dst, buffer, bytes_read, NULL);
594 if (ret)
596 err = gpg_error_from_syserror ();
597 break;
601 return err;
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. */
608 static gpg_error_t
609 file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n)
611 unsigned char *buffer_new;
612 struct stat statbuf;
613 estream_t stream;
614 gpg_error_t err;
615 int ret;
617 *buffer = NULL;
618 *buffer_n = 0;
620 buffer_new = NULL;
621 err = 0;
623 stream = es_fopen (filename, "r");
624 if (! stream)
626 err = gpg_error_from_syserror ();
627 goto out;
630 ret = fstat (es_fileno (stream), &statbuf);
631 if (ret)
633 err = gpg_error_from_syserror ();
634 goto out;
637 buffer_new = xtrymalloc (statbuf.st_size);
638 if (! buffer_new)
640 err = gpg_error_from_syserror ();
641 goto out;
644 err = stream_read_data (stream, buffer_new, statbuf.st_size);
645 if (err)
646 goto out;
648 *buffer = buffer_new;
649 *buffer_n = statbuf.st_size;
651 out:
653 if (stream)
654 es_fclose (stream);
656 if (err)
657 xfree (buffer_new);
659 return err;
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. */
669 static gpg_error_t
670 open_control_file (FILE **r_fp, int append)
672 gpg_error_t err;
673 char *fname;
674 FILE *fp;
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
678 mutex. */
679 *r_fp = NULL;
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_
687 functions here. */
688 fp = fopen (fname, "wx");
689 if (!fp)
691 err = gpg_error (gpg_err_code_from_errno (errno));
692 log_error (_("can't create `%s': %s\n"), fname, gpg_strerror (err));
693 xfree (fname);
694 return err;
696 fputs (sshcontrolblurb, fp);
697 fclose (fp);
698 fp = fopen (fname, append? "a+":"r");
701 if (!fp)
703 err = gpg_error (gpg_err_code_from_errno (errno));
704 log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err));
705 xfree (fname);
706 return err;
709 *r_fp = fp;
711 return 0;
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. */
718 static gpg_error_t
719 search_control_file (FILE *fp, const char *hexgrip, int *disabled)
721 int c, i;
722 char *p, line[256];
724 assert (strlen (hexgrip) == 40 );
726 rewind (fp);
727 *disabled = 0;
728 next_line:
731 if (!fgets (line, DIM(line)-1, fp) )
733 if (feof (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 == '#');
753 *disabled = 0;
754 if (*p == '!')
756 *disabled = 1;
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))
763 goto next_line;
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. */
782 static gpg_error_t
783 add_control_entry (ctrl_t ctrl, const char *hexgrip, int ttl)
785 gpg_error_t err;
786 FILE *fp;
787 int disabled;
789 err = open_control_file (&fp, 1);
790 if (err)
791 return err;
793 err = search_control_file (fp, hexgrip, &disabled);
794 if (err && gpg_err_code(err) == GPG_ERR_EOF)
796 struct tm *tp;
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,
805 hexgrip, ttl);
808 fclose (fp);
809 return 0;
818 MPI lists.
822 /* Free the list of MPIs MPI_LIST. */
823 static void
824 mpint_list_free (gcry_mpi_t *mpi_list)
826 if (mpi_list)
828 unsigned int i;
830 for (i = 0; mpi_list[i]; i++)
831 gcry_mpi_release (mpi_list[i]);
832 xfree (mpi_list);
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
839 code. */
840 static gpg_error_t
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;
847 const char *elems;
848 int elem_is_secret;
849 gcry_mpi_t *mpis;
850 gpg_error_t err;
851 unsigned int i;
853 mpis = NULL;
854 err = 0;
856 if (secret)
857 elems = key_spec.elems_key_secret;
858 else
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 );
866 if (!mpis)
868 err = gpg_error_from_syserror ();
869 goto out;
872 elem_is_secret = 0;
873 for (i = 0; i < elems_n; i++)
875 if (secret)
876 elem_is_secret = ! strchr (elems_public, elems[i]);
877 err = stream_read_mpi (stream, elem_is_secret, &mpis[i]);
878 if (err)
879 break;
881 if (err)
882 goto out;
884 *mpi_list = mpis;
886 out:
888 if (err)
889 mpint_list_free (mpis);
891 return err;
896 /* Key modifier function for RSA. */
897 static gpg_error_t
898 ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis)
900 gcry_mpi_t p;
901 gcry_mpi_t q;
902 gcry_mpi_t u;
904 if (strcmp (elems, "nedupq"))
905 /* Modifying only necessary for secret keys. */
906 goto out;
908 u = mpis[3];
909 p = mpis[4];
910 q = mpis[5];
912 if (gcry_mpi_cmp (p, q) > 0)
914 /* P shall be smaller then Q! Swap primes. iqmp becomes u. */
915 gcry_mpi_t tmp;
917 tmp = mpis[4];
918 mpis[4] = mpis[5];
919 mpis[5] = tmp;
921 else
922 /* U needs to be recomputed. */
923 gcry_mpi_invm (u, p, q);
925 out:
927 return 0;
930 /* Signature encoder function for RSA. */
931 static gpg_error_t
932 ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis)
934 unsigned char *data;
935 size_t data_n;
936 gpg_error_t err;
937 gcry_mpi_t s;
939 s = mpis[0];
941 err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s);
942 if (err)
943 goto out;
945 err = stream_write_string (signature_blob, data, data_n);
946 xfree (data);
948 out:
950 return err;
954 /* Signature encoder function for DSA. */
955 static gpg_error_t
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];
959 unsigned char *data;
960 size_t data_n;
961 gpg_error_t err;
962 int i;
964 data = NULL;
966 for (i = 0; i < 2; i++)
968 err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]);
969 if (err)
970 break;
972 if (data_n > SSH_DSA_SIGNATURE_PADDING)
974 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
975 break;
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);
983 xfree (data);
984 data = NULL;
986 if (err)
987 goto out;
989 err = stream_write_string (signature_blob, buffer, sizeof (buffer));
991 out:
993 xfree (data);
995 return err;
999 S-Expressions.
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. */
1006 static gpg_error_t
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;
1015 gpg_error_t err;
1016 const char *elems;
1017 size_t elems_n;
1018 unsigned int i;
1019 unsigned int j;
1020 void **arg_list;
1022 err = 0;
1023 sexp_new = NULL;
1024 arg_list = NULL;
1025 if (secret)
1026 elems = key_spec.elems_sexp_order;
1027 else
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>).
1036 mpi: (X%m) -> 5.
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 ();
1044 goto out;
1047 /* Key identifier, algorithm identifier, mpis, comment. */
1048 arg_list = xtrymalloc (sizeof (*arg_list) * (2 + elems_n + 1));
1049 if (! arg_list)
1051 err = gpg_error_from_syserror ();
1052 goto out;
1055 i = 0;
1056 arg_list[i++] = &key_identifier[secret];
1057 arg_list[i++] = &key_spec.identifier;
1059 *sexp_template = 0;
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)",
1065 elems[i]);
1066 if (secret)
1068 for (j = 0; j < elems_n; j++)
1069 if (key_spec.elems_key_secret[j] == elems[i])
1070 break;
1072 else
1073 j = i;
1074 arg_list[i + 2] = &mpis[j];
1076 sexp_template_n += sprintf (sexp_template + sexp_template_n,
1077 ")(comment%%s))");
1079 arg_list[i + 2] = &comment;
1081 err = gcry_sexp_build_array (&sexp_new, NULL, sexp_template, arg_list);
1082 if (err)
1083 goto out;
1085 *sexp = sexp_new;
1087 out:
1089 xfree (arg_list);
1090 xfree (sexp_template);
1092 return err;
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. */
1101 static gpg_error_t
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)
1106 gpg_error_t err;
1107 gcry_sexp_t value_list;
1108 gcry_sexp_t value_pair;
1109 gcry_sexp_t comment_list;
1110 unsigned int i;
1111 char *comment_new;
1112 const char *data;
1113 size_t data_n;
1114 int is_secret;
1115 size_t elems_n;
1116 const char *elems;
1117 gcry_mpi_t *mpis_new;
1118 gcry_mpi_t mpi;
1120 err = 0;
1121 value_list = NULL;
1122 value_pair = NULL;
1123 comment_list = NULL;
1124 comment_new = NULL;
1125 mpis_new = NULL;
1127 data = gcry_sexp_nth_data (sexp, 0, &data_n);
1128 if (! data)
1130 err = gpg_error (GPG_ERR_INV_SEXP);
1131 goto out;
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)))
1138 is_secret = 0;
1139 elems = key_spec.elems_key_public;
1141 else if (data_n == 11 && !strncmp (data, "private-key", 11))
1143 is_secret = 1;
1144 elems = key_spec.elems_key_secret;
1146 else
1148 err = gpg_error (GPG_ERR_INV_SEXP);
1149 goto out;
1152 elems_n = strlen (elems);
1153 mpis_new = xtrycalloc (elems_n + 1, sizeof *mpis_new );
1154 if (!mpis_new)
1156 err = gpg_error_from_syserror ();
1157 goto out;
1160 value_list = gcry_sexp_find_token (sexp, key_spec.identifier, 0);
1161 if (! value_list)
1163 err = gpg_error (GPG_ERR_INV_SEXP);
1164 goto out;
1167 for (i = 0; i < elems_n; i++)
1169 value_pair = gcry_sexp_find_token (value_list, elems + i, 1);
1170 if (! value_pair)
1172 err = gpg_error (GPG_ERR_INV_SEXP);
1173 break;
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);
1179 if (! mpi)
1181 err = gpg_error (GPG_ERR_INV_SEXP);
1182 break;
1184 mpis_new[i] = mpi;
1185 gcry_sexp_release (value_pair);
1186 value_pair = NULL;
1188 if (err)
1189 goto out;
1191 /* We do not require a comment sublist to be present here. */
1192 data = NULL;
1193 data_n = 0;
1195 comment_list = gcry_sexp_find_token (sexp, "comment", 0);
1196 if (comment_list)
1197 data = gcry_sexp_nth_data (comment_list, 1, &data_n);
1198 if (! data)
1200 data = "(none)";
1201 data_n = 6;
1204 comment_new = make_cstring (data, data_n);
1205 if (! comment_new)
1207 err = gpg_error_from_syserror ();
1208 goto out;
1211 if (secret)
1212 *secret = is_secret;
1213 *mpis = mpis_new;
1214 *comment = comment_new;
1216 out:
1218 gcry_sexp_release (value_list);
1219 gcry_sexp_release (value_pair);
1220 gcry_sexp_release (comment_list);
1222 if (err)
1224 xfree (comment_new);
1225 mpint_list_free (mpis_new);
1228 return err;
1231 /* Extract the car from SEXP, and create a newly created C-string
1232 which is to be stored in IDENTIFIER. */
1233 static gpg_error_t
1234 sexp_extract_identifier (gcry_sexp_t sexp, char **identifier)
1236 char *identifier_new;
1237 gcry_sexp_t sublist;
1238 const char *data;
1239 size_t data_n;
1240 gpg_error_t err;
1242 identifier_new = NULL;
1243 err = 0;
1245 sublist = gcry_sexp_nth (sexp, 1);
1246 if (! sublist)
1248 err = gpg_error (GPG_ERR_INV_SEXP);
1249 goto out;
1252 data = gcry_sexp_nth_data (sublist, 0, &data_n);
1253 if (! data)
1255 err = gpg_error (GPG_ERR_INV_SEXP);
1256 goto out;
1259 identifier_new = make_cstring (data, data_n);
1260 if (! identifier_new)
1262 err = gpg_err_code_from_errno (errno);
1263 goto out;
1266 *identifier = identifier_new;
1268 out:
1270 gcry_sexp_release (sublist);
1272 return err;
1279 Key I/O.
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. */
1287 static gpg_error_t
1288 ssh_key_type_lookup (const char *ssh_name, const char *name,
1289 ssh_key_type_spec_t *spec)
1291 gpg_error_t err;
1292 unsigned int i;
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))))
1297 break;
1299 if (i == DIM (ssh_key_types))
1300 err = gpg_error (GPG_ERR_NOT_FOUND);
1301 else
1303 *spec = ssh_key_types[i];
1304 err = 0;
1307 return err;
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. */
1315 static gpg_error_t
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)
1319 gpg_error_t err;
1320 char *key_type;
1321 char *comment;
1322 gcry_sexp_t key;
1323 ssh_key_type_spec_t spec;
1324 gcry_mpi_t *mpi_list;
1325 const char *elems;
1327 mpi_list = NULL;
1328 key_type = NULL;
1329 comment = "";
1330 key = NULL;
1332 err = stream_read_cstring (stream, &key_type);
1333 if (err)
1334 goto out;
1336 err = ssh_key_type_lookup (key_type, NULL, &spec);
1337 if (err)
1338 goto out;
1340 err = ssh_receive_mpint_list (stream, secret, spec, &mpi_list);
1341 if (err)
1342 goto out;
1344 if (read_comment)
1346 err = stream_read_cstring (stream, &comment);
1347 if (err)
1348 goto out;
1351 if (secret)
1352 elems = spec.elems_key_secret;
1353 else
1354 elems = spec.elems_key_public;
1356 if (spec.key_modifier)
1358 err = (*spec.key_modifier) (elems, mpi_list);
1359 if (err)
1360 goto out;
1363 err = sexp_key_construct (&key, spec, secret, mpi_list, comment);
1364 if (err)
1365 goto out;
1367 if (key_spec)
1368 *key_spec = spec;
1369 *key_new = key;
1371 out:
1373 mpint_list_free (mpi_list);
1374 xfree (key_type);
1375 if (read_comment)
1376 xfree (comment);
1378 return err;
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. */
1384 static gpg_error_t
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;
1390 estream_t stream;
1391 gpg_error_t err;
1392 unsigned int i;
1394 *blob = NULL;
1395 *blob_size = 0;
1397 blob_new = NULL;
1398 stream = NULL;
1399 err = 0;
1401 stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1402 if (! stream)
1404 err = gpg_error_from_syserror ();
1405 goto out;
1408 err = stream_write_cstring (stream, type);
1409 if (err)
1410 goto out;
1412 for (i = 0; mpis[i] && (! err); i++)
1413 err = stream_write_mpi (stream, mpis[i]);
1414 if (err)
1415 goto out;
1417 blob_size_new = es_ftell (stream);
1418 if (blob_size_new == -1)
1420 err = gpg_error_from_syserror ();
1421 goto out;
1424 err = es_fseek (stream, 0, SEEK_SET);
1425 if (err)
1426 goto out;
1428 blob_new = xtrymalloc (blob_size_new);
1429 if (! blob_new)
1431 err = gpg_error_from_syserror ();
1432 goto out;
1435 err = stream_read_data (stream, blob_new, blob_size_new);
1436 if (err)
1437 goto out;
1439 *blob = blob_new;
1440 *blob_size = blob_size_new;
1442 out:
1444 if (stream)
1445 es_fclose (stream);
1446 if (err)
1447 xfree (blob_new);
1449 return err;
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. */
1456 static gpg_error_t
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;
1462 char *key_type;
1463 char *comment;
1464 unsigned char *blob;
1465 size_t blob_n;
1466 gpg_error_t err;
1468 key_type = NULL;
1469 mpi_list = NULL;
1470 comment = NULL;
1471 blob = NULL;
1473 err = sexp_extract_identifier (key_public, &key_type);
1474 if (err)
1475 goto out;
1477 err = ssh_key_type_lookup (NULL, key_type, &spec);
1478 if (err)
1479 goto out;
1481 err = sexp_key_extract (key_public, spec, NULL, &mpi_list, &comment);
1482 if (err)
1483 goto out;
1485 err = ssh_convert_key_to_blob (&blob, &blob_n,
1486 spec.ssh_identifier, mpi_list);
1487 if (err)
1488 goto out;
1490 err = stream_write_string (stream, blob, blob_n);
1491 if (err)
1492 goto out;
1494 err = stream_write_cstring (stream,
1495 override_comment? override_comment : comment);
1497 out:
1499 mpint_list_free (mpi_list);
1500 xfree (key_type);
1501 xfree (comment);
1502 xfree (blob);
1504 return err;
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. */
1510 static gpg_error_t
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;
1516 gpg_error_t err;
1518 err = 0;
1520 blob_stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1521 if (! blob_stream)
1523 err = gpg_error_from_syserror ();
1524 goto out;
1527 err = stream_write_data (blob_stream, blob, blob_size);
1528 if (err)
1529 goto out;
1531 err = es_fseek (blob_stream, 0, SEEK_SET);
1532 if (err)
1533 goto out;
1535 err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec);
1537 out:
1539 if (blob_stream)
1540 es_fclose (blob_stream);
1542 return err;
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. */
1550 static gpg_error_t
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);
1556 return 0;
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. */
1562 static gpg_error_t
1563 key_secret_to_public (gcry_sexp_t *key_public,
1564 ssh_key_type_spec_t spec, gcry_sexp_t key_secret)
1566 char *comment;
1567 gcry_mpi_t *mpis;
1568 gpg_error_t err;
1569 int is_secret;
1571 comment = NULL;
1572 mpis = NULL;
1574 err = sexp_key_extract (key_secret, spec, &is_secret, &mpis, &comment);
1575 if (err)
1576 goto out;
1578 err = sexp_key_construct (key_public, spec, 0, mpis, comment);
1580 out:
1582 mpint_list_free (mpis);
1583 xfree (comment);
1585 return err;
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. */
1594 static gpg_error_t
1595 card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
1597 gpg_error_t err;
1598 char *authkeyid;
1599 char *serialno = NULL;
1600 unsigned char *pkbuf;
1601 size_t pkbuflen;
1602 gcry_sexp_t s_pk;
1603 unsigned char grip[20];
1605 *r_pk = NULL;
1606 if (cardsn)
1607 *cardsn = NULL;
1609 /* First see whether a card is available and whether the application
1610 is supported. */
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);
1616 if (err)
1618 if (opt.verbose)
1619 log_info (_("error getting serial number of card: %s\n"),
1620 gpg_strerror (err));
1621 return err;
1623 log_info (_("detected card with S/N: %s\n"), serialno);
1624 err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid);
1626 if (err)
1628 log_error (_("error getting default authentication keyID of card: %s\n"),
1629 gpg_strerror (err));
1630 xfree (serialno);
1631 return 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));
1639 xfree (authkeyid);
1640 return err;
1643 /* Read the public key. */
1644 err = agent_card_readkey (ctrl, authkeyid, &pkbuf);
1645 if (err)
1647 if (opt.verbose)
1648 log_info (_("no suitable card key found: %s\n"), gpg_strerror (err));
1649 xfree (serialno);
1650 xfree (authkeyid);
1651 return err;
1654 pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
1655 err = gcry_sexp_sscan (&s_pk, NULL, (char*)pkbuf, pkbuflen);
1656 if (err)
1658 log_error ("failed to build S-Exp from received card key: %s\n",
1659 gpg_strerror (err));
1660 xfree (pkbuf);
1661 xfree (serialno);
1662 xfree (authkeyid);
1663 return err;
1666 err = ssh_key_grip (s_pk, grip);
1667 if (err)
1669 log_debug ("error computing keygrip from received card key: %s\n",
1670 gcry_strerror (err));
1671 xfree (pkbuf);
1672 gcry_sexp_release (s_pk);
1673 xfree (serialno);
1674 xfree (authkeyid);
1675 return err;
1678 if ( agent_key_available (grip) )
1680 /* (Shadow)-key is not available in our key storage. */
1681 unsigned char *shadow_info;
1682 unsigned char *tmp;
1684 shadow_info = make_shadow_info (serialno, authkeyid);
1685 if (!shadow_info)
1687 err = gpg_error_from_syserror ();
1688 xfree (pkbuf);
1689 gcry_sexp_release (s_pk);
1690 xfree (serialno);
1691 xfree (authkeyid);
1692 return err;
1694 err = agent_shadow_key (pkbuf, shadow_info, &tmp);
1695 xfree (shadow_info);
1696 if (err)
1698 log_error (_("shadowing the key failed: %s\n"), gpg_strerror (err));
1699 xfree (pkbuf);
1700 gcry_sexp_release (s_pk);
1701 xfree (serialno);
1702 xfree (authkeyid);
1703 return err;
1705 xfree (pkbuf);
1706 pkbuf = tmp;
1707 pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
1708 assert (pkbuflen);
1710 err = agent_write_private_key (grip, pkbuf, pkbuflen, 0);
1711 if (err)
1713 log_error (_("error writing key: %s\n"), gpg_strerror (err));
1714 xfree (pkbuf);
1715 gcry_sexp_release (s_pk);
1716 xfree (serialno);
1717 xfree (authkeyid);
1718 return err;
1722 if (cardsn)
1724 char *dispsn;
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);
1731 xfree (dispsn);
1733 else
1734 *cardsn = xtryasprintf ("cardno:%s", serialno);
1735 if (!*cardsn)
1737 err = gpg_error_from_syserror ();
1738 xfree (pkbuf);
1739 gcry_sexp_release (s_pk);
1740 xfree (serialno);
1741 xfree (authkeyid);
1742 return err;
1746 xfree (pkbuf);
1747 xfree (serialno);
1748 xfree (authkeyid);
1749 *r_pk = s_pk;
1750 return 0;
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. */
1766 static gpg_error_t
1767 ssh_handler_request_identities (ctrl_t ctrl,
1768 estream_t request, estream_t response)
1770 char *key_type;
1771 ssh_key_type_spec_t spec;
1772 struct dirent *dir_entry;
1773 char *key_directory;
1774 size_t key_directory_n;
1775 char *key_path;
1776 unsigned char *buffer;
1777 size_t buffer_n;
1778 u32 key_counter;
1779 estream_t key_blobs;
1780 gcry_sexp_t key_secret;
1781 gcry_sexp_t key_public;
1782 DIR *dir;
1783 gpg_error_t err;
1784 int ret;
1785 FILE *ctrl_fp = NULL;
1786 char *cardsn;
1787 gpg_error_t ret_err;
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 free (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 /* 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. */
2325 static gpg_error_t
2326 ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
2328 gpg_error_t err;
2329 unsigned char key_grip_raw[20];
2330 char key_grip[41];
2331 unsigned char *buffer = NULL;
2332 unsigned int buffer_n;
2333 char *description = NULL;
2334 char *comment = NULL;
2335 unsigned int i;
2336 struct pin_entry_info_s *pi = NULL;
2338 err = ssh_key_grip (key, key_grip_raw);
2339 if (err)
2340 goto out;
2342 /* Check whether the key is already in our key storage. Don't do
2343 anything then. */
2344 if ( !agent_key_available (key_grip_raw) )
2345 goto out; /* Yes, key is available. */
2348 err = ssh_key_extract_comment (key, &comment);
2349 if (err)
2350 goto out;
2352 if ( asprintf (&description,
2353 _("Please enter a passphrase to protect"
2354 " the received secret key%%0A"
2355 " %s%%0A"
2356 "within gpg-agent's key storage"),
2357 comment ? comment : "?") < 0)
2359 err = gpg_error_from_syserror ();
2360 goto out;
2364 pi = gcry_calloc_secure (1, sizeof (*pi) + 100 + 1);
2365 if (!pi)
2367 err = gpg_error_from_syserror ();
2368 goto out;
2370 pi->max_length = 100;
2371 pi->max_tries = 1;
2372 err = agent_askpin (ctrl, description, NULL, NULL, pi);
2373 if (err)
2374 goto out;
2376 err = ssh_key_to_protected_buffer (key, pi->pin, &buffer, &buffer_n);
2377 if (err)
2378 goto out;
2380 /* Store this key to our key storage. */
2381 err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0);
2382 if (err)
2383 goto out;
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);
2390 if (err)
2391 goto out;
2393 /* And add an entry to the sshcontrol file. */
2394 err = add_control_entry (ctrl, key_grip, ttl);
2397 out:
2398 if (pi && pi->max_length)
2399 wipememory (pi->pin, pi->max_length);
2400 xfree (pi);
2401 xfree (buffer);
2402 xfree (comment);
2403 free (description); /* (asprintf allocated, thus regular free.) */
2405 return err;
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. */
2412 static gpg_error_t
2413 ssh_identity_drop (gcry_sexp_t key)
2415 unsigned char key_grip[21] = { 0 };
2416 gpg_error_t err;
2418 err = ssh_key_grip (key, key_grip);
2419 if (err)
2420 goto out;
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? */
2427 out:
2429 return err;
2432 /* Handler for the "add_identity" command. */
2433 static gpg_error_t
2434 ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
2436 gpg_error_t ret_err;
2437 gpg_error_t err;
2438 gcry_sexp_t key;
2439 unsigned char b;
2440 int confirm;
2441 int ttl;
2443 confirm = 0;
2444 key = NULL;
2445 ttl = 0;
2447 /* FIXME? */
2448 err = ssh_receive_key (request, &key, 1, 1, NULL);
2449 if (err)
2450 goto out;
2452 while (1)
2454 err = stream_read_byte (request, &b);
2455 if (gpg_err_code (err) == GPG_ERR_EOF)
2457 err = 0;
2458 break;
2461 switch (b)
2463 case SSH_OPT_CONSTRAIN_LIFETIME:
2465 u32 n = 0;
2467 err = stream_read_uint32 (request, &n);
2468 if (! err)
2469 ttl = n;
2470 break;
2473 case SSH_OPT_CONSTRAIN_CONFIRM:
2475 confirm = 1;
2476 break;
2479 default:
2480 /* FIXME: log/bad? */
2481 break;
2484 if (err)
2485 goto out;
2487 /* FIXME: are constraints used correctly? */
2489 err = ssh_identity_register (ctrl, key, ttl);
2491 out:
2493 gcry_sexp_release (key);
2495 if (! err)
2496 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2497 else
2498 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2500 return ret_err;
2503 /* Handler for the "remove_identity" command. */
2504 static gpg_error_t
2505 ssh_handler_remove_identity (ctrl_t ctrl,
2506 estream_t request, estream_t response)
2508 unsigned char *key_blob;
2509 u32 key_blob_size;
2510 gcry_sexp_t key;
2511 gpg_error_t ret_err;
2512 gpg_error_t err;
2514 /* Receive key. */
2516 key_blob = NULL;
2517 key = NULL;
2519 err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2520 if (err)
2521 goto out;
2523 err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL);
2524 if (err)
2525 goto out;
2527 err = ssh_identity_drop (key);
2529 out:
2531 xfree (key_blob);
2532 gcry_sexp_release (key);
2534 if (! err)
2535 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2536 else
2537 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2539 return ret_err;
2542 /* FIXME: stub function. Actually useful? */
2543 static gpg_error_t
2544 ssh_identities_remove_all (void)
2546 gpg_error_t err;
2548 err = 0;
2550 /* FIXME: shall we remove _all_ cache entries or only those
2551 registered through the ssh emulation? */
2553 return err;
2556 /* Handler for the "remove_all_identities" command. */
2557 static gpg_error_t
2558 ssh_handler_remove_all_identities (ctrl_t ctrl,
2559 estream_t request, estream_t response)
2561 gpg_error_t ret_err;
2562 gpg_error_t err;
2564 err = ssh_identities_remove_all ();
2566 if (! err)
2567 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2568 else
2569 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2571 return ret_err;
2574 /* Lock agent? FIXME: stub function. */
2575 static gpg_error_t
2576 ssh_lock (void)
2578 gpg_error_t err;
2580 /* FIXME */
2581 log_error ("ssh-agent's lock command is not implemented\n");
2582 err = 0;
2584 return err;
2587 /* Unock agent? FIXME: stub function. */
2588 static gpg_error_t
2589 ssh_unlock (void)
2591 gpg_error_t err;
2593 log_error ("ssh-agent's unlock command is not implemented\n");
2594 err = 0;
2596 return err;
2599 /* Handler for the "lock" command. */
2600 static gpg_error_t
2601 ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response)
2603 gpg_error_t ret_err;
2604 gpg_error_t err;
2606 err = ssh_lock ();
2608 if (! err)
2609 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2610 else
2611 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2613 return ret_err;
2616 /* Handler for the "unlock" command. */
2617 static gpg_error_t
2618 ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
2620 gpg_error_t ret_err;
2621 gpg_error_t err;
2623 err = ssh_unlock ();
2625 if (! err)
2626 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2627 else
2628 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2630 return ret_err;
2635 /* Return the request specification for the request identified by TYPE
2636 or NULL in case the requested request specification could not be
2637 found. */
2638 static ssh_request_spec_t *
2639 request_spec_lookup (int type)
2641 ssh_request_spec_t *spec;
2642 unsigned int i;
2644 for (i = 0; i < DIM (request_specs); i++)
2645 if (request_specs[i].type == type)
2646 break;
2647 if (i == DIM (request_specs))
2649 log_info ("ssh request %u is not supported\n", type);
2650 spec = NULL;
2652 else
2653 spec = request_specs + i;
2655 return spec;
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. */
2661 static int
2662 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
2664 ssh_request_spec_t *spec;
2665 estream_t response;
2666 estream_t request;
2667 unsigned char request_type;
2668 gpg_error_t err;
2669 int send_err;
2670 int ret;
2671 unsigned char *request_data;
2672 u32 request_data_size;
2673 u32 response_size;
2675 request_data = NULL;
2676 response = NULL;
2677 request = NULL;
2678 send_err = 0;
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.
2690 -moritz */
2692 /* Retrieve request. */
2693 err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
2694 if (err)
2695 goto out;
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)
2703 send_err = 1;
2704 goto out;
2705 /* Broken request; FIXME. */
2708 request_type = request_data[0];
2709 spec = request_spec_lookup (request_type);
2710 if (! spec)
2712 send_err = 1;
2713 goto out;
2714 /* Unknown request; FIXME. */
2717 if (spec->secret_input)
2718 request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
2719 else
2720 request = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+");
2721 if (! request)
2723 err = gpg_error_from_syserror ();
2724 goto out;
2726 ret = es_setvbuf (request, NULL, _IONBF, 0);
2727 if (ret)
2729 err = gpg_error_from_syserror ();
2730 goto out;
2732 err = stream_write_data (request, request_data + 1, request_data_size - 1);
2733 if (err)
2734 goto out;
2735 es_rewind (request);
2737 response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
2738 if (! response)
2740 err = gpg_error_from_syserror ();
2741 goto out;
2744 if (opt.verbose)
2745 log_info ("ssh request handler for %s (%u) started\n",
2746 spec->identifier, spec->type);
2748 err = (*spec->handler) (ctrl, request, response);
2750 if (opt.verbose)
2752 if (err)
2753 log_info ("ssh request handler for %s (%u) failed: %s\n",
2754 spec->identifier, spec->type, gpg_strerror (err));
2755 else
2756 log_info ("ssh request handler for %s (%u) ready\n",
2757 spec->identifier, spec->type);
2760 if (err)
2762 send_err = 1;
2763 goto out;
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);
2772 if (err)
2774 send_err = 1;
2775 goto out;
2778 err = stream_write_uint32 (stream_sock, response_size);
2779 if (err)
2781 send_err = 1;
2782 goto out;
2785 err = stream_copy (stream_sock, response);
2786 if (err)
2787 goto out;
2789 err = es_fflush (stream_sock);
2790 if (err)
2791 goto out;
2793 out:
2795 if (err && es_feof (stream_sock))
2796 log_error ("error occured while processing request: %s\n",
2797 gpg_strerror (err));
2799 if (send_err)
2801 if (opt.verbose > 1)
2802 log_info ("sending ssh error response\n");
2803 err = stream_write_uint32 (stream_sock, 1);
2804 if (err)
2805 goto leave;
2806 err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE);
2807 if (err)
2808 goto leave;
2811 leave:
2813 if (request)
2814 es_fclose (request);
2815 if (response)
2816 es_fclose (response);
2817 xfree (request_data); /* FIXME? */
2819 return !!err;
2822 /* Start serving client on SOCK_CLIENT. */
2823 void
2824 start_command_handler_ssh (int sock_client)
2826 struct server_control_s ctrl;
2827 estream_t stream_sock;
2828 gpg_error_t err;
2829 int ret;
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+");
2854 if (!stream_sock)
2856 err = gpg_error_from_syserror ();
2857 log_error (_("failed to create stream from socket: %s\n"),
2858 gpg_strerror (err));
2859 goto out;
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);
2864 if (ret)
2866 err = gpg_error_from_syserror ();
2867 log_error ("failed to disable buffering "
2868 "on socket stream: %s\n", gpg_strerror (err));
2869 goto out;
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);
2880 out:
2881 if (stream_sock)
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);