Rename encode.c to encrypt.c.
[gnupg.git] / agent / command-ssh.c
blob12fe60a153db51c7196a325f840df73cd50fc662
1 /* command-ssh.c - gpg-agent's ssh-agent emulation layer
2 * Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 /* Only v2 of the ssh-agent protocol is implemented. */
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. If R_TTL is not NULL
714 a specified TTL for that key is stored there. */
715 static gpg_error_t
716 search_control_file (FILE *fp, const char *hexgrip,
717 int *r_disabled, int *r_ttl)
719 int c, i;
720 char *p, *pend, line[256];
721 long ttl;
723 assert (strlen (hexgrip) == 40 );
725 rewind (fp);
726 *r_disabled = 0;
727 next_line:
730 if (!fgets (line, DIM(line)-1, fp) )
732 if (feof (fp))
733 return gpg_error (GPG_ERR_EOF);
734 return gpg_error (gpg_err_code_from_errno (errno));
737 if (!*line || line[strlen(line)-1] != '\n')
739 /* Eat until end of line */
740 while ( (c=getc (fp)) != EOF && c != '\n')
742 return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
743 : GPG_ERR_INCOMPLETE_LINE);
746 /* Allow for empty lines and spaces */
747 for (p=line; spacep (p); p++)
750 while (!*p || *p == '\n' || *p == '#');
752 *r_disabled = 0;
753 if (*p == '!')
755 *r_disabled = 1;
756 for (p++; spacep (p); p++)
760 for (i=0; hexdigitp (p) && i < 40; p++, i++)
761 if (hexgrip[i] != (*p >= 'a'? (*p & 0xdf): *p))
762 goto next_line;
763 if (i != 40 || !(spacep (p) || *p == '\n'))
765 log_error ("invalid formatted line in ssh control file\n");
766 return gpg_error (GPG_ERR_BAD_DATA);
769 ttl = strtol (p, &pend, 10);
770 p = pend;
771 if (!(spacep (p) || *p == '\n') || ttl < -1)
773 log_error ("invalid TTL value in ssh control file; assuming 0\n");
774 ttl = 0;
776 if (r_ttl)
777 *r_ttl = ttl;
779 /* Here is the place to parse flags if we need them. */
781 return 0; /* Okay: found it. */
786 /* Add an entry to the control file to mark the key with the keygrip
787 HEXGRIP as usable for SSH; i.e. it will be returned when ssh asks
788 for it. This function is in general used to add a key received
789 through the ssh-add function. We can assume that the user wants to
790 allow ssh using this key. */
791 static gpg_error_t
792 add_control_entry (ctrl_t ctrl, const char *hexgrip, int ttl)
794 gpg_error_t err;
795 FILE *fp;
796 int disabled;
798 (void)ctrl;
800 err = open_control_file (&fp, 1);
801 if (err)
802 return err;
804 err = search_control_file (fp, hexgrip, &disabled, NULL);
805 if (err && gpg_err_code(err) == GPG_ERR_EOF)
807 struct tm *tp;
808 time_t atime = time (NULL);
810 /* Not yet in the file - add it. Because the file has been
811 opened in append mode, we simply need to write to it. */
812 tp = localtime (&atime);
813 fprintf (fp, "# Key added on %04d-%02d-%02d %02d:%02d:%02d\n%s %d\n",
814 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
815 tp->tm_hour, tp->tm_min, tp->tm_sec,
816 hexgrip, ttl);
819 fclose (fp);
820 return 0;
824 /* Scan the sshcontrol file and return the TTL. */
825 static int
826 ttl_from_sshcontrol (const char *hexgrip)
828 FILE *fp;
829 int disabled, ttl;
831 if (!hexgrip || strlen (hexgrip) != 40)
832 return 0; /* Wrong input: Use global default. */
834 if (open_control_file (&fp, 0))
835 return 0; /* Error: Use the global default TTL. */
837 if (search_control_file (fp, hexgrip, &disabled, &ttl)
838 || disabled)
839 ttl = 0; /* Use the global default if not found or disabled. */
841 fclose (fp);
843 return ttl;
852 MPI lists.
856 /* Free the list of MPIs MPI_LIST. */
857 static void
858 mpint_list_free (gcry_mpi_t *mpi_list)
860 if (mpi_list)
862 unsigned int i;
864 for (i = 0; mpi_list[i]; i++)
865 gcry_mpi_release (mpi_list[i]);
866 xfree (mpi_list);
870 /* Receive key material MPIs from STREAM according to KEY_SPEC;
871 depending on SECRET expect a public key or secret key. The newly
872 allocated list of MPIs is stored in MPI_LIST. Returns usual error
873 code. */
874 static gpg_error_t
875 ssh_receive_mpint_list (estream_t stream, int secret,
876 ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list)
878 unsigned int elems_public_n;
879 const char *elems_public;
880 unsigned int elems_n;
881 const char *elems;
882 int elem_is_secret;
883 gcry_mpi_t *mpis;
884 gpg_error_t err;
885 unsigned int i;
887 mpis = NULL;
888 err = 0;
890 if (secret)
891 elems = key_spec.elems_key_secret;
892 else
893 elems = key_spec.elems_key_public;
894 elems_n = strlen (elems);
896 elems_public = key_spec.elems_key_public;
897 elems_public_n = strlen (elems_public);
899 mpis = xtrycalloc (elems_n + 1, sizeof *mpis );
900 if (!mpis)
902 err = gpg_error_from_syserror ();
903 goto out;
906 elem_is_secret = 0;
907 for (i = 0; i < elems_n; i++)
909 if (secret)
910 elem_is_secret = ! strchr (elems_public, elems[i]);
911 err = stream_read_mpi (stream, elem_is_secret, &mpis[i]);
912 if (err)
913 break;
915 if (err)
916 goto out;
918 *mpi_list = mpis;
920 out:
922 if (err)
923 mpint_list_free (mpis);
925 return err;
930 /* Key modifier function for RSA. */
931 static gpg_error_t
932 ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis)
934 gcry_mpi_t p;
935 gcry_mpi_t q;
936 gcry_mpi_t u;
938 if (strcmp (elems, "nedupq"))
939 /* Modifying only necessary for secret keys. */
940 goto out;
942 u = mpis[3];
943 p = mpis[4];
944 q = mpis[5];
946 if (gcry_mpi_cmp (p, q) > 0)
948 /* P shall be smaller then Q! Swap primes. iqmp becomes u. */
949 gcry_mpi_t tmp;
951 tmp = mpis[4];
952 mpis[4] = mpis[5];
953 mpis[5] = tmp;
955 else
956 /* U needs to be recomputed. */
957 gcry_mpi_invm (u, p, q);
959 out:
961 return 0;
964 /* Signature encoder function for RSA. */
965 static gpg_error_t
966 ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis)
968 unsigned char *data;
969 size_t data_n;
970 gpg_error_t err;
971 gcry_mpi_t s;
973 s = mpis[0];
975 err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s);
976 if (err)
977 goto out;
979 err = stream_write_string (signature_blob, data, data_n);
980 xfree (data);
982 out:
984 return err;
988 /* Signature encoder function for DSA. */
989 static gpg_error_t
990 ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis)
992 unsigned char buffer[SSH_DSA_SIGNATURE_PADDING * SSH_DSA_SIGNATURE_ELEMS];
993 unsigned char *data;
994 size_t data_n;
995 gpg_error_t err;
996 int i;
998 data = NULL;
1000 for (i = 0; i < 2; i++)
1002 err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]);
1003 if (err)
1004 break;
1006 if (data_n > SSH_DSA_SIGNATURE_PADDING)
1008 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
1009 break;
1012 memset (buffer + (i * SSH_DSA_SIGNATURE_PADDING), 0,
1013 SSH_DSA_SIGNATURE_PADDING - data_n);
1014 memcpy (buffer + (i * SSH_DSA_SIGNATURE_PADDING)
1015 + (SSH_DSA_SIGNATURE_PADDING - data_n), data, data_n);
1017 xfree (data);
1018 data = NULL;
1020 if (err)
1021 goto out;
1023 err = stream_write_string (signature_blob, buffer, sizeof (buffer));
1025 out:
1027 xfree (data);
1029 return err;
1033 S-Expressions.
1037 /* This function constructs a new S-Expression for the key identified
1038 by the KEY_SPEC, SECRET, MPIS and COMMENT, which is to be stored in
1039 *SEXP. Returns usual error code. */
1040 static gpg_error_t
1041 sexp_key_construct (gcry_sexp_t *sexp,
1042 ssh_key_type_spec_t key_spec, int secret,
1043 gcry_mpi_t *mpis, const char *comment)
1045 const char *key_identifier[] = { "public-key", "private-key" };
1046 gcry_sexp_t sexp_new;
1047 char *sexp_template;
1048 size_t sexp_template_n;
1049 gpg_error_t err;
1050 const char *elems;
1051 size_t elems_n;
1052 unsigned int i;
1053 unsigned int j;
1054 void **arg_list;
1056 err = 0;
1057 sexp_new = NULL;
1058 arg_list = NULL;
1059 if (secret)
1060 elems = key_spec.elems_sexp_order;
1061 else
1062 elems = key_spec.elems_key_public;
1063 elems_n = strlen (elems);
1066 Calculate size for sexp_template_n:
1068 "(%s(%s<mpis>)(comment%s))" -> 20 + sizeof (<mpis>).
1070 mpi: (X%m) -> 5.
1073 sexp_template_n = 20 + (elems_n * 5);
1074 sexp_template = xtrymalloc (sexp_template_n);
1075 if (! sexp_template)
1077 err = gpg_error_from_syserror ();
1078 goto out;
1081 /* Key identifier, algorithm identifier, mpis, comment. */
1082 arg_list = xtrymalloc (sizeof (*arg_list) * (2 + elems_n + 1));
1083 if (! arg_list)
1085 err = gpg_error_from_syserror ();
1086 goto out;
1089 i = 0;
1090 arg_list[i++] = &key_identifier[secret];
1091 arg_list[i++] = &key_spec.identifier;
1093 *sexp_template = 0;
1094 sexp_template_n = 0;
1095 sexp_template_n = sprintf (sexp_template + sexp_template_n, "(%%s(%%s");
1096 for (i = 0; i < elems_n; i++)
1098 sexp_template_n += sprintf (sexp_template + sexp_template_n, "(%c%%m)",
1099 elems[i]);
1100 if (secret)
1102 for (j = 0; j < elems_n; j++)
1103 if (key_spec.elems_key_secret[j] == elems[i])
1104 break;
1106 else
1107 j = i;
1108 arg_list[i + 2] = &mpis[j];
1110 sexp_template_n += sprintf (sexp_template + sexp_template_n,
1111 ")(comment%%s))");
1113 arg_list[i + 2] = &comment;
1115 err = gcry_sexp_build_array (&sexp_new, NULL, sexp_template, arg_list);
1116 if (err)
1117 goto out;
1119 *sexp = sexp_new;
1121 out:
1123 xfree (arg_list);
1124 xfree (sexp_template);
1126 return err;
1129 /* This functions breaks up the key contained in the S-Expression SEXP
1130 according to KEY_SPEC. The MPIs are bundled in a newly create
1131 list, which is to be stored in MPIS; a newly allocated string
1132 holding the comment will be stored in COMMENT; SECRET will be
1133 filled with a boolean flag specifying what kind of key it is.
1134 Returns usual error code. */
1135 static gpg_error_t
1136 sexp_key_extract (gcry_sexp_t sexp,
1137 ssh_key_type_spec_t key_spec, int *secret,
1138 gcry_mpi_t **mpis, char **comment)
1140 gpg_error_t err;
1141 gcry_sexp_t value_list;
1142 gcry_sexp_t value_pair;
1143 gcry_sexp_t comment_list;
1144 unsigned int i;
1145 char *comment_new;
1146 const char *data;
1147 size_t data_n;
1148 int is_secret;
1149 size_t elems_n;
1150 const char *elems;
1151 gcry_mpi_t *mpis_new;
1152 gcry_mpi_t mpi;
1154 err = 0;
1155 value_list = NULL;
1156 value_pair = NULL;
1157 comment_list = NULL;
1158 comment_new = NULL;
1159 mpis_new = NULL;
1161 data = gcry_sexp_nth_data (sexp, 0, &data_n);
1162 if (! data)
1164 err = gpg_error (GPG_ERR_INV_SEXP);
1165 goto out;
1168 if ((data_n == 10 && !strncmp (data, "public-key", 10))
1169 || (data_n == 21 && !strncmp (data, "protected-private-key", 21))
1170 || (data_n == 20 && !strncmp (data, "shadowed-private-key", 20)))
1172 is_secret = 0;
1173 elems = key_spec.elems_key_public;
1175 else if (data_n == 11 && !strncmp (data, "private-key", 11))
1177 is_secret = 1;
1178 elems = key_spec.elems_key_secret;
1180 else
1182 err = gpg_error (GPG_ERR_INV_SEXP);
1183 goto out;
1186 elems_n = strlen (elems);
1187 mpis_new = xtrycalloc (elems_n + 1, sizeof *mpis_new );
1188 if (!mpis_new)
1190 err = gpg_error_from_syserror ();
1191 goto out;
1194 value_list = gcry_sexp_find_token (sexp, key_spec.identifier, 0);
1195 if (! value_list)
1197 err = gpg_error (GPG_ERR_INV_SEXP);
1198 goto out;
1201 for (i = 0; i < elems_n; i++)
1203 value_pair = gcry_sexp_find_token (value_list, elems + i, 1);
1204 if (! value_pair)
1206 err = gpg_error (GPG_ERR_INV_SEXP);
1207 break;
1210 /* Note that we need to use STD format; i.e. prepend a 0x00 to
1211 indicate a positive number if the high bit is set. */
1212 mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_STD);
1213 if (! mpi)
1215 err = gpg_error (GPG_ERR_INV_SEXP);
1216 break;
1218 mpis_new[i] = mpi;
1219 gcry_sexp_release (value_pair);
1220 value_pair = NULL;
1222 if (err)
1223 goto out;
1225 /* We do not require a comment sublist to be present here. */
1226 data = NULL;
1227 data_n = 0;
1229 comment_list = gcry_sexp_find_token (sexp, "comment", 0);
1230 if (comment_list)
1231 data = gcry_sexp_nth_data (comment_list, 1, &data_n);
1232 if (! data)
1234 data = "(none)";
1235 data_n = 6;
1238 comment_new = make_cstring (data, data_n);
1239 if (! comment_new)
1241 err = gpg_error_from_syserror ();
1242 goto out;
1245 if (secret)
1246 *secret = is_secret;
1247 *mpis = mpis_new;
1248 *comment = comment_new;
1250 out:
1252 gcry_sexp_release (value_list);
1253 gcry_sexp_release (value_pair);
1254 gcry_sexp_release (comment_list);
1256 if (err)
1258 xfree (comment_new);
1259 mpint_list_free (mpis_new);
1262 return err;
1265 /* Extract the car from SEXP, and create a newly created C-string
1266 which is to be stored in IDENTIFIER. */
1267 static gpg_error_t
1268 sexp_extract_identifier (gcry_sexp_t sexp, char **identifier)
1270 char *identifier_new;
1271 gcry_sexp_t sublist;
1272 const char *data;
1273 size_t data_n;
1274 gpg_error_t err;
1276 identifier_new = NULL;
1277 err = 0;
1279 sublist = gcry_sexp_nth (sexp, 1);
1280 if (! sublist)
1282 err = gpg_error (GPG_ERR_INV_SEXP);
1283 goto out;
1286 data = gcry_sexp_nth_data (sublist, 0, &data_n);
1287 if (! data)
1289 err = gpg_error (GPG_ERR_INV_SEXP);
1290 goto out;
1293 identifier_new = make_cstring (data, data_n);
1294 if (! identifier_new)
1296 err = gpg_err_code_from_errno (errno);
1297 goto out;
1300 *identifier = identifier_new;
1302 out:
1304 gcry_sexp_release (sublist);
1306 return err;
1313 Key I/O.
1317 /* Search for a key specification entry. If SSH_NAME is not NULL,
1318 search for an entry whose "ssh_name" is equal to SSH_NAME;
1319 otherwise, search for an entry whose "name" is equal to NAME.
1320 Store found entry in SPEC on success, return error otherwise. */
1321 static gpg_error_t
1322 ssh_key_type_lookup (const char *ssh_name, const char *name,
1323 ssh_key_type_spec_t *spec)
1325 gpg_error_t err;
1326 unsigned int i;
1328 for (i = 0; i < DIM (ssh_key_types); i++)
1329 if ((ssh_name && (! strcmp (ssh_name, ssh_key_types[i].ssh_identifier)))
1330 || (name && (! strcmp (name, ssh_key_types[i].identifier))))
1331 break;
1333 if (i == DIM (ssh_key_types))
1334 err = gpg_error (GPG_ERR_NOT_FOUND);
1335 else
1337 *spec = ssh_key_types[i];
1338 err = 0;
1341 return err;
1344 /* Receive a key from STREAM, according to the key specification given
1345 as KEY_SPEC. Depending on SECRET, receive a secret or a public
1346 key. If READ_COMMENT is true, receive a comment string as well.
1347 Constructs a new S-Expression from received data and stores it in
1348 KEY_NEW. Returns zero on success or an error code. */
1349 static gpg_error_t
1350 ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret,
1351 int read_comment, ssh_key_type_spec_t *key_spec)
1353 gpg_error_t err;
1354 char *key_type;
1355 char *comment;
1356 gcry_sexp_t key;
1357 ssh_key_type_spec_t spec;
1358 gcry_mpi_t *mpi_list;
1359 const char *elems;
1361 mpi_list = NULL;
1362 key_type = NULL;
1363 comment = "";
1364 key = NULL;
1366 err = stream_read_cstring (stream, &key_type);
1367 if (err)
1368 goto out;
1370 err = ssh_key_type_lookup (key_type, NULL, &spec);
1371 if (err)
1372 goto out;
1374 err = ssh_receive_mpint_list (stream, secret, spec, &mpi_list);
1375 if (err)
1376 goto out;
1378 if (read_comment)
1380 err = stream_read_cstring (stream, &comment);
1381 if (err)
1382 goto out;
1385 if (secret)
1386 elems = spec.elems_key_secret;
1387 else
1388 elems = spec.elems_key_public;
1390 if (spec.key_modifier)
1392 err = (*spec.key_modifier) (elems, mpi_list);
1393 if (err)
1394 goto out;
1397 err = sexp_key_construct (&key, spec, secret, mpi_list, comment);
1398 if (err)
1399 goto out;
1401 if (key_spec)
1402 *key_spec = spec;
1403 *key_new = key;
1405 out:
1407 mpint_list_free (mpi_list);
1408 xfree (key_type);
1409 if (read_comment)
1410 xfree (comment);
1412 return err;
1415 /* Converts a key of type TYPE, whose key material is given in MPIS,
1416 into a newly created binary blob, which is to be stored in
1417 BLOB/BLOB_SIZE. Returns zero on success or an error code. */
1418 static gpg_error_t
1419 ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size,
1420 const char *type, gcry_mpi_t *mpis)
1422 unsigned char *blob_new;
1423 long int blob_size_new;
1424 estream_t stream;
1425 gpg_error_t err;
1426 unsigned int i;
1428 *blob = NULL;
1429 *blob_size = 0;
1431 blob_new = NULL;
1432 stream = NULL;
1433 err = 0;
1435 stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1436 if (! stream)
1438 err = gpg_error_from_syserror ();
1439 goto out;
1442 err = stream_write_cstring (stream, type);
1443 if (err)
1444 goto out;
1446 for (i = 0; mpis[i] && (! err); i++)
1447 err = stream_write_mpi (stream, mpis[i]);
1448 if (err)
1449 goto out;
1451 blob_size_new = es_ftell (stream);
1452 if (blob_size_new == -1)
1454 err = gpg_error_from_syserror ();
1455 goto out;
1458 err = es_fseek (stream, 0, SEEK_SET);
1459 if (err)
1460 goto out;
1462 blob_new = xtrymalloc (blob_size_new);
1463 if (! blob_new)
1465 err = gpg_error_from_syserror ();
1466 goto out;
1469 err = stream_read_data (stream, blob_new, blob_size_new);
1470 if (err)
1471 goto out;
1473 *blob = blob_new;
1474 *blob_size = blob_size_new;
1476 out:
1478 if (stream)
1479 es_fclose (stream);
1480 if (err)
1481 xfree (blob_new);
1483 return err;
1487 /* Write the public key KEY_PUBLIC to STREAM in SSH key format. If
1488 OVERRIDE_COMMENT is not NULL, it will be used instead of the
1489 comment stored in the key. */
1490 static gpg_error_t
1491 ssh_send_key_public (estream_t stream, gcry_sexp_t key_public,
1492 const char *override_comment)
1494 ssh_key_type_spec_t spec;
1495 gcry_mpi_t *mpi_list;
1496 char *key_type;
1497 char *comment;
1498 unsigned char *blob;
1499 size_t blob_n;
1500 gpg_error_t err;
1502 key_type = NULL;
1503 mpi_list = NULL;
1504 comment = NULL;
1505 blob = NULL;
1507 err = sexp_extract_identifier (key_public, &key_type);
1508 if (err)
1509 goto out;
1511 err = ssh_key_type_lookup (NULL, key_type, &spec);
1512 if (err)
1513 goto out;
1515 err = sexp_key_extract (key_public, spec, NULL, &mpi_list, &comment);
1516 if (err)
1517 goto out;
1519 err = ssh_convert_key_to_blob (&blob, &blob_n,
1520 spec.ssh_identifier, mpi_list);
1521 if (err)
1522 goto out;
1524 err = stream_write_string (stream, blob, blob_n);
1525 if (err)
1526 goto out;
1528 err = stream_write_cstring (stream,
1529 override_comment? override_comment : comment);
1531 out:
1533 mpint_list_free (mpi_list);
1534 xfree (key_type);
1535 xfree (comment);
1536 xfree (blob);
1538 return err;
1541 /* Read a public key out of BLOB/BLOB_SIZE according to the key
1542 specification given as KEY_SPEC, storing the new key in KEY_PUBLIC.
1543 Returns zero on success or an error code. */
1544 static gpg_error_t
1545 ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size,
1546 gcry_sexp_t *key_public,
1547 ssh_key_type_spec_t *key_spec)
1549 estream_t blob_stream;
1550 gpg_error_t err;
1552 err = 0;
1554 blob_stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1555 if (! blob_stream)
1557 err = gpg_error_from_syserror ();
1558 goto out;
1561 err = stream_write_data (blob_stream, blob, blob_size);
1562 if (err)
1563 goto out;
1565 err = es_fseek (blob_stream, 0, SEEK_SET);
1566 if (err)
1567 goto out;
1569 err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec);
1571 out:
1573 if (blob_stream)
1574 es_fclose (blob_stream);
1576 return err;
1581 /* This function calculates the key grip for the key contained in the
1582 S-Expression KEY and writes it to BUFFER, which must be large
1583 enough to hold it. Returns usual error code. */
1584 static gpg_error_t
1585 ssh_key_grip (gcry_sexp_t key, unsigned char *buffer)
1587 if (!gcry_pk_get_keygrip (key, buffer))
1588 return gpg_error (GPG_ERR_INTERNAL);
1590 return 0;
1593 /* Converts the secret key KEY_SECRET into a public key, storing it in
1594 KEY_PUBLIC. SPEC is the according key specification. Returns zero
1595 on success or an error code. */
1596 static gpg_error_t
1597 key_secret_to_public (gcry_sexp_t *key_public,
1598 ssh_key_type_spec_t spec, gcry_sexp_t key_secret)
1600 char *comment;
1601 gcry_mpi_t *mpis;
1602 gpg_error_t err;
1603 int is_secret;
1605 comment = NULL;
1606 mpis = NULL;
1608 err = sexp_key_extract (key_secret, spec, &is_secret, &mpis, &comment);
1609 if (err)
1610 goto out;
1612 err = sexp_key_construct (key_public, spec, 0, mpis, comment);
1614 out:
1616 mpint_list_free (mpis);
1617 xfree (comment);
1619 return err;
1623 /* Check whether a smartcard is available and whether it has a usable
1624 key. Store a copy of that key at R_PK and return 0. If no key is
1625 available store NULL at R_PK and return an error code. If CARDSN
1626 is not NULL, a string with the serial number of the card will be
1627 a malloced and stored there. */
1628 static gpg_error_t
1629 card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
1631 gpg_error_t err;
1632 char *authkeyid;
1633 char *serialno = NULL;
1634 unsigned char *pkbuf;
1635 size_t pkbuflen;
1636 gcry_sexp_t s_pk;
1637 unsigned char grip[20];
1639 *r_pk = NULL;
1640 if (cardsn)
1641 *cardsn = NULL;
1643 /* First see whether a card is available and whether the application
1644 is supported. */
1645 err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid);
1646 if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED )
1648 /* Ask for the serial number to reset the card. */
1649 err = agent_card_serialno (ctrl, &serialno);
1650 if (err)
1652 if (opt.verbose)
1653 log_info (_("error getting serial number of card: %s\n"),
1654 gpg_strerror (err));
1655 return err;
1657 log_info (_("detected card with S/N: %s\n"), serialno);
1658 err = agent_card_getattr (ctrl, "$AUTHKEYID", &authkeyid);
1660 if (err)
1662 log_error (_("error getting default authentication keyID of card: %s\n"),
1663 gpg_strerror (err));
1664 xfree (serialno);
1665 return err;
1668 /* Get the S/N if we don't have it yet. Use the fast getattr method. */
1669 if (!serialno && (err = agent_card_getattr (ctrl, "SERIALNO", &serialno)) )
1671 log_error (_("error getting serial number of card: %s\n"),
1672 gpg_strerror (err));
1673 xfree (authkeyid);
1674 return err;
1677 /* Read the public key. */
1678 err = agent_card_readkey (ctrl, authkeyid, &pkbuf);
1679 if (err)
1681 if (opt.verbose)
1682 log_info (_("no suitable card key found: %s\n"), gpg_strerror (err));
1683 xfree (serialno);
1684 xfree (authkeyid);
1685 return err;
1688 pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
1689 err = gcry_sexp_sscan (&s_pk, NULL, (char*)pkbuf, pkbuflen);
1690 if (err)
1692 log_error ("failed to build S-Exp from received card key: %s\n",
1693 gpg_strerror (err));
1694 xfree (pkbuf);
1695 xfree (serialno);
1696 xfree (authkeyid);
1697 return err;
1700 err = ssh_key_grip (s_pk, grip);
1701 if (err)
1703 log_debug ("error computing keygrip from received card key: %s\n",
1704 gcry_strerror (err));
1705 xfree (pkbuf);
1706 gcry_sexp_release (s_pk);
1707 xfree (serialno);
1708 xfree (authkeyid);
1709 return err;
1712 if ( agent_key_available (grip) )
1714 /* (Shadow)-key is not available in our key storage. */
1715 unsigned char *shadow_info;
1716 unsigned char *tmp;
1718 shadow_info = make_shadow_info (serialno, authkeyid);
1719 if (!shadow_info)
1721 err = gpg_error_from_syserror ();
1722 xfree (pkbuf);
1723 gcry_sexp_release (s_pk);
1724 xfree (serialno);
1725 xfree (authkeyid);
1726 return err;
1728 err = agent_shadow_key (pkbuf, shadow_info, &tmp);
1729 xfree (shadow_info);
1730 if (err)
1732 log_error (_("shadowing the key failed: %s\n"), gpg_strerror (err));
1733 xfree (pkbuf);
1734 gcry_sexp_release (s_pk);
1735 xfree (serialno);
1736 xfree (authkeyid);
1737 return err;
1739 xfree (pkbuf);
1740 pkbuf = tmp;
1741 pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
1742 assert (pkbuflen);
1744 err = agent_write_private_key (grip, pkbuf, pkbuflen, 0);
1745 if (err)
1747 log_error (_("error writing key: %s\n"), gpg_strerror (err));
1748 xfree (pkbuf);
1749 gcry_sexp_release (s_pk);
1750 xfree (serialno);
1751 xfree (authkeyid);
1752 return err;
1756 if (cardsn)
1758 char *dispsn;
1760 /* If the card handler is able to return a short serialnumber,
1761 use that one, else use the complete serialno. */
1762 if (!agent_card_getattr (ctrl, "$DISPSERIALNO", &dispsn))
1764 *cardsn = xtryasprintf ("cardno:%s", dispsn);
1765 xfree (dispsn);
1767 else
1768 *cardsn = xtryasprintf ("cardno:%s", serialno);
1769 if (!*cardsn)
1771 err = gpg_error_from_syserror ();
1772 xfree (pkbuf);
1773 gcry_sexp_release (s_pk);
1774 xfree (serialno);
1775 xfree (authkeyid);
1776 return err;
1780 xfree (pkbuf);
1781 xfree (serialno);
1782 xfree (authkeyid);
1783 *r_pk = s_pk;
1784 return 0;
1792 Request handler. Each handler is provided with a CTRL context, a
1793 REQUEST object and a RESPONSE object. The actual request is to be
1794 read from REQUEST, the response needs to be written to RESPONSE.
1799 /* Handler for the "request_identities" command. */
1800 static gpg_error_t
1801 ssh_handler_request_identities (ctrl_t ctrl,
1802 estream_t request, estream_t response)
1804 char *key_type;
1805 ssh_key_type_spec_t spec;
1806 struct dirent *dir_entry;
1807 char *key_directory;
1808 size_t key_directory_n;
1809 char *key_path;
1810 unsigned char *buffer;
1811 size_t buffer_n;
1812 u32 key_counter;
1813 estream_t key_blobs;
1814 gcry_sexp_t key_secret;
1815 gcry_sexp_t key_public;
1816 DIR *dir;
1817 gpg_error_t err;
1818 int ret;
1819 FILE *ctrl_fp = NULL;
1820 char *cardsn;
1821 gpg_error_t ret_err;
1823 (void)request;
1825 /* Prepare buffer stream. */
1827 key_directory = NULL;
1828 key_secret = NULL;
1829 key_public = NULL;
1830 key_type = NULL;
1831 key_path = NULL;
1832 key_counter = 0;
1833 buffer = NULL;
1834 dir = NULL;
1835 err = 0;
1837 key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1838 if (! key_blobs)
1840 err = gpg_error_from_syserror ();
1841 goto out;
1844 /* Open key directory. */
1845 key_directory = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
1846 if (! key_directory)
1848 err = gpg_err_code_from_errno (errno);
1849 goto out;
1851 key_directory_n = strlen (key_directory);
1853 key_path = xtrymalloc (key_directory_n + 46);
1854 if (! key_path)
1856 err = gpg_err_code_from_errno (errno);
1857 goto out;
1860 sprintf (key_path, "%s/", key_directory);
1861 sprintf (key_path + key_directory_n + 41, ".key");
1863 dir = opendir (key_directory);
1864 if (! dir)
1866 err = gpg_err_code_from_errno (errno);
1867 goto out;
1872 /* First check whether a key is currently available in the card
1873 reader - this should be allowed even without being listed in
1874 sshcontrol. */
1876 if (!card_key_available (ctrl, &key_public, &cardsn))
1878 err = ssh_send_key_public (key_blobs, key_public, cardsn);
1879 gcry_sexp_release (key_public);
1880 key_public = NULL;
1881 xfree (cardsn);
1882 if (err)
1883 goto out;
1885 key_counter++;
1889 /* Then look at all the registered an allowed keys. */
1892 /* Fixme: We should better iterate over the control file and check
1893 whether the key file is there. This is better in resepct to
1894 performance if tehre are a lot of key sin our key storage. */
1895 /* FIXME: make sure that buffer gets deallocated properly. */
1896 err = open_control_file (&ctrl_fp, 0);
1897 if (err)
1898 goto out;
1900 while ( (dir_entry = readdir (dir)) )
1902 if ((strlen (dir_entry->d_name) == 44)
1903 && (! strncmp (dir_entry->d_name + 40, ".key", 4)))
1905 char hexgrip[41];
1906 int disabled;
1908 /* We do only want to return keys listed in our control
1909 file. */
1910 strncpy (hexgrip, dir_entry->d_name, 40);
1911 hexgrip[40] = 0;
1912 if ( strlen (hexgrip) != 40 )
1913 continue;
1914 if (search_control_file (ctrl_fp, hexgrip, &disabled, NULL)
1915 || disabled)
1916 continue;
1918 strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40);
1920 /* Read file content. */
1921 err = file_to_buffer (key_path, &buffer, &buffer_n);
1922 if (err)
1923 goto out;
1925 err = gcry_sexp_sscan (&key_secret, NULL, (char*)buffer, buffer_n);
1926 if (err)
1927 goto out;
1929 xfree (buffer);
1930 buffer = NULL;
1932 err = sexp_extract_identifier (key_secret, &key_type);
1933 if (err)
1934 goto out;
1936 err = ssh_key_type_lookup (NULL, key_type, &spec);
1937 if (err)
1938 goto out;
1940 xfree (key_type);
1941 key_type = NULL;
1943 err = key_secret_to_public (&key_public, spec, key_secret);
1944 if (err)
1945 goto out;
1947 gcry_sexp_release (key_secret);
1948 key_secret = NULL;
1950 err = ssh_send_key_public (key_blobs, key_public, NULL);
1951 if (err)
1952 goto out;
1954 gcry_sexp_release (key_public);
1955 key_public = NULL;
1957 key_counter++;
1961 ret = es_fseek (key_blobs, 0, SEEK_SET);
1962 if (ret)
1964 err = gpg_error_from_syserror ();
1965 goto out;
1968 out:
1970 /* Send response. */
1972 gcry_sexp_release (key_secret);
1973 gcry_sexp_release (key_public);
1975 if (! err)
1977 ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER);
1978 if (ret_err)
1979 goto leave;
1980 ret_err = stream_write_uint32 (response, key_counter);
1981 if (ret_err)
1982 goto leave;
1983 ret_err = stream_copy (response, key_blobs);
1984 if (ret_err)
1985 goto leave;
1987 else
1989 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
1990 goto leave;
1993 leave:
1995 if (key_blobs)
1996 es_fclose (key_blobs);
1997 if (dir)
1998 closedir (dir);
2000 if (ctrl_fp)
2001 fclose (ctrl_fp);
2003 xfree (key_directory);
2004 xfree (key_path);
2005 xfree (buffer);
2006 xfree (key_type);
2008 return ret_err;
2012 /* This function hashes the data contained in DATA of size DATA_N
2013 according to the message digest algorithm specified by MD_ALGORITHM
2014 and writes the message digest to HASH, which needs to large enough
2015 for the digest. */
2016 static gpg_error_t
2017 data_hash (unsigned char *data, size_t data_n,
2018 int md_algorithm, unsigned char *hash)
2020 gcry_md_hash_buffer (md_algorithm, hash, data, data_n);
2022 return 0;
2025 /* This function signs the data contained in CTRL, stores the created
2026 signature in newly allocated memory in SIG and it's size in SIG_N;
2027 SIG_ENCODER is the signature encoder to use. */
2028 static gpg_error_t
2029 data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder,
2030 unsigned char **sig, size_t *sig_n)
2032 gpg_error_t err;
2033 gcry_sexp_t signature_sexp = NULL;
2034 estream_t stream = NULL;
2035 gcry_sexp_t valuelist = NULL;
2036 gcry_sexp_t sublist = NULL;
2037 gcry_mpi_t sig_value = NULL;
2038 unsigned char *sig_blob = NULL;
2039 size_t sig_blob_n = 0;
2040 char *identifier = NULL;
2041 const char *identifier_raw;
2042 size_t identifier_n;
2043 ssh_key_type_spec_t spec;
2044 int ret;
2045 unsigned int i;
2046 const char *elems;
2047 size_t elems_n;
2048 gcry_mpi_t *mpis = NULL;
2050 *sig = NULL;
2051 *sig_n = 0;
2053 ctrl->use_auth_call = 1;
2054 err = agent_pksign_do (ctrl,
2055 _("Please enter the passphrase "
2056 "for the ssh key%0A %c"), &signature_sexp,
2057 CACHE_MODE_SSH, ttl_from_sshcontrol);
2058 ctrl->use_auth_call = 0;
2059 if (err)
2060 goto out;
2062 valuelist = gcry_sexp_nth (signature_sexp, 1);
2063 if (! valuelist)
2065 err = gpg_error (GPG_ERR_INV_SEXP);
2066 goto out;
2069 stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
2070 if (! stream)
2072 err = gpg_error_from_syserror ();
2073 goto out;
2076 identifier_raw = gcry_sexp_nth_data (valuelist, 0, &identifier_n);
2077 if (! identifier_raw)
2079 err = gpg_error (GPG_ERR_INV_SEXP);
2080 goto out;
2083 identifier = make_cstring (identifier_raw, identifier_n);
2084 if (! identifier)
2086 err = gpg_error_from_syserror ();
2087 goto out;
2090 err = ssh_key_type_lookup (NULL, identifier, &spec);
2091 if (err)
2092 goto out;
2094 err = stream_write_cstring (stream, spec.ssh_identifier);
2095 if (err)
2096 goto out;
2098 elems = spec.elems_signature;
2099 elems_n = strlen (elems);
2101 mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
2102 if (!mpis)
2104 err = gpg_error_from_syserror ();
2105 goto out;
2108 for (i = 0; i < elems_n; i++)
2110 sublist = gcry_sexp_find_token (valuelist, spec.elems_signature + i, 1);
2111 if (! sublist)
2113 err = gpg_error (GPG_ERR_INV_SEXP);
2114 break;
2117 sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
2118 if (! sig_value)
2120 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
2121 break;
2123 gcry_sexp_release (sublist);
2124 sublist = NULL;
2126 mpis[i] = sig_value;
2128 if (err)
2129 goto out;
2131 err = (*sig_encoder) (stream, mpis);
2132 if (err)
2133 goto out;
2135 sig_blob_n = es_ftell (stream);
2136 if (sig_blob_n == -1)
2138 err = gpg_error_from_syserror ();
2139 goto out;
2142 sig_blob = xtrymalloc (sig_blob_n);
2143 if (! sig_blob)
2145 err = gpg_error_from_syserror ();
2146 goto out;
2149 ret = es_fseek (stream, 0, SEEK_SET);
2150 if (ret)
2152 err = gpg_error_from_syserror ();
2153 goto out;
2156 err = stream_read_data (stream, sig_blob, sig_blob_n);
2157 if (err)
2158 goto out;
2160 *sig = sig_blob;
2161 *sig_n = sig_blob_n;
2163 out:
2165 if (err)
2166 xfree (sig_blob);
2168 if (stream)
2169 es_fclose (stream);
2170 gcry_sexp_release (valuelist);
2171 gcry_sexp_release (signature_sexp);
2172 gcry_sexp_release (sublist);
2173 mpint_list_free (mpis);
2174 xfree (identifier);
2176 return err;
2179 /* Handler for the "sign_request" command. */
2180 static gpg_error_t
2181 ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
2183 gcry_sexp_t key;
2184 ssh_key_type_spec_t spec;
2185 unsigned char hash[MAX_DIGEST_LEN];
2186 unsigned int hash_n;
2187 unsigned char key_grip[20];
2188 unsigned char *key_blob;
2189 u32 key_blob_size;
2190 unsigned char *data;
2191 unsigned char *sig;
2192 size_t sig_n;
2193 u32 data_size;
2194 u32 flags;
2195 gpg_error_t err;
2196 gpg_error_t ret_err;
2198 key_blob = NULL;
2199 data = NULL;
2200 sig = NULL;
2201 key = NULL;
2203 /* Receive key. */
2205 err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2206 if (err)
2207 goto out;
2209 err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec);
2210 if (err)
2211 goto out;
2213 /* Receive data to sign. */
2214 err = stream_read_string (request, 0, &data, &data_size);
2215 if (err)
2216 goto out;
2218 /* FIXME? */
2219 err = stream_read_uint32 (request, &flags);
2220 if (err)
2221 goto out;
2223 /* Hash data. */
2224 hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
2225 if (! hash_n)
2227 err = gpg_error (GPG_ERR_INTERNAL);
2228 goto out;
2230 err = data_hash (data, data_size, GCRY_MD_SHA1, hash);
2231 if (err)
2232 goto out;
2234 /* Calculate key grip. */
2235 err = ssh_key_grip (key, key_grip);
2236 if (err)
2237 goto out;
2239 /* Sign data. */
2241 ctrl->digest.algo = GCRY_MD_SHA1;
2242 memcpy (ctrl->digest.value, hash, hash_n);
2243 ctrl->digest.valuelen = hash_n;
2244 ctrl->digest.raw_value = ! (spec.flags & SPEC_FLAG_USE_PKCS1V2);
2245 ctrl->have_keygrip = 1;
2246 memcpy (ctrl->keygrip, key_grip, 20);
2248 err = data_sign (ctrl, spec.signature_encoder, &sig, &sig_n);
2250 out:
2252 /* Done. */
2254 if (! err)
2256 ret_err = stream_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE);
2257 if (ret_err)
2258 goto leave;
2259 ret_err = stream_write_string (response, sig, sig_n);
2260 if (ret_err)
2261 goto leave;
2263 else
2265 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2266 if (ret_err)
2267 goto leave;
2270 leave:
2272 gcry_sexp_release (key);
2273 xfree (key_blob);
2274 xfree (data);
2275 xfree (sig);
2277 return ret_err;
2280 /* This function extracts the comment contained in the key
2281 S-Expression KEY and stores a copy in COMMENT. Returns usual error
2282 code. */
2283 static gpg_error_t
2284 ssh_key_extract_comment (gcry_sexp_t key, char **comment)
2286 gcry_sexp_t comment_list;
2287 char *comment_new;
2288 const char *data;
2289 size_t data_n;
2290 gpg_error_t err;
2292 comment_list = gcry_sexp_find_token (key, "comment", 0);
2293 if (! comment_list)
2295 err = gpg_error (GPG_ERR_INV_SEXP);
2296 goto out;
2299 data = gcry_sexp_nth_data (comment_list, 1, &data_n);
2300 if (! data)
2302 err = gpg_error (GPG_ERR_INV_SEXP);
2303 goto out;
2306 comment_new = make_cstring (data, data_n);
2307 if (! comment_new)
2309 err = gpg_error_from_syserror ();
2310 goto out;
2313 *comment = comment_new;
2314 err = 0;
2316 out:
2318 gcry_sexp_release (comment_list);
2320 return err;
2323 /* This function converts the key contained in the S-Expression KEY
2324 into a buffer, which is protected by the passphrase PASSPHRASE.
2325 Returns usual error code. */
2326 static gpg_error_t
2327 ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase,
2328 unsigned char **buffer, size_t *buffer_n)
2330 unsigned char *buffer_new;
2331 unsigned int buffer_new_n;
2332 gpg_error_t err;
2334 err = 0;
2335 buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0);
2336 buffer_new = xtrymalloc_secure (buffer_new_n);
2337 if (! buffer_new)
2339 err = gpg_error_from_syserror ();
2340 goto out;
2343 gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n);
2344 /* FIXME: guarantee? */
2346 err = agent_protect (buffer_new, passphrase, buffer, buffer_n);
2348 out:
2350 xfree (buffer_new);
2352 return err;
2357 /* Callback function to compare the first entered PIN with the one
2358 currently being entered. */
2359 static int
2360 reenter_compare_cb (struct pin_entry_info_s *pi)
2362 const char *pin1 = pi->check_cb_arg;
2364 if (!strcmp (pin1, pi->pin))
2365 return 0; /* okay */
2366 return -1;
2369 /* Store the ssh KEY into our local key storage and protect it after
2370 asking for a passphrase. Cache that passphrase. TTL is the
2371 maximum caching time for that key. If the key already exists in
2372 our key storage, don't do anything. When entering a new key also
2373 add an entry to the sshcontrol file. */
2374 static gpg_error_t
2375 ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
2377 gpg_error_t err;
2378 unsigned char key_grip_raw[20];
2379 char key_grip[41];
2380 unsigned char *buffer = NULL;
2381 size_t buffer_n;
2382 char *description = NULL;
2383 const char *description2 = _("Please re-enter this passphrase");
2384 char *comment = NULL;
2385 const char *initial_errtext = NULL;
2386 unsigned int i;
2387 struct pin_entry_info_s *pi = NULL, *pi2;
2389 err = ssh_key_grip (key, key_grip_raw);
2390 if (err)
2391 goto out;
2393 /* Check whether the key is already in our key storage. Don't do
2394 anything then. */
2395 if ( !agent_key_available (key_grip_raw) )
2396 goto out; /* Yes, key is available. */
2399 err = ssh_key_extract_comment (key, &comment);
2400 if (err)
2401 goto out;
2403 if ( asprintf (&description,
2404 _("Please enter a passphrase to protect"
2405 " the received secret key%%0A"
2406 " %s%%0A"
2407 "within gpg-agent's key storage"),
2408 comment ? comment : "?") < 0)
2410 err = gpg_error_from_syserror ();
2411 goto out;
2415 pi = gcry_calloc_secure (2, sizeof (*pi) + 100 + 1);
2416 if (!pi)
2418 err = gpg_error_from_syserror ();
2419 goto out;
2421 pi2 = pi + (sizeof *pi + 100 + 1);
2422 pi->max_length = 100;
2423 pi->max_tries = 1;
2424 pi2->max_length = 100;
2425 pi2->max_tries = 1;
2426 pi2->check_cb = reenter_compare_cb;
2427 pi2->check_cb_arg = pi->pin;
2429 next_try:
2430 err = agent_askpin (ctrl, description, NULL, initial_errtext, pi);
2431 initial_errtext = NULL;
2432 if (err)
2433 goto out;
2435 /* Unless the passphrase is empty, ask to confirm it. */
2436 if (pi->pin && *pi->pin)
2438 err = agent_askpin (ctrl, description2, NULL, NULL, pi2);
2439 if (err == -1)
2440 { /* The re-entered one did not match and the user did not
2441 hit cancel. */
2442 initial_errtext = _("does not match - try again");
2443 goto next_try;
2447 err = ssh_key_to_protected_buffer (key, pi->pin, &buffer, &buffer_n);
2448 if (err)
2449 goto out;
2451 /* Store this key to our key storage. */
2452 err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0);
2453 if (err)
2454 goto out;
2456 /* Cache this passphrase. */
2457 for (i = 0; i < 20; i++)
2458 sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]);
2460 err = agent_put_cache (key_grip, CACHE_MODE_SSH, pi->pin, ttl);
2461 if (err)
2462 goto out;
2464 /* And add an entry to the sshcontrol file. */
2465 err = add_control_entry (ctrl, key_grip, ttl);
2468 out:
2469 if (pi && pi->max_length)
2470 wipememory (pi->pin, pi->max_length);
2471 xfree (pi);
2472 xfree (buffer);
2473 xfree (comment);
2474 xfree (description);
2476 return err;
2480 /* This function removes the key contained in the S-Expression KEY
2481 from the local key storage, in case it exists there. Returns usual
2482 error code. FIXME: this function is a stub. */
2483 static gpg_error_t
2484 ssh_identity_drop (gcry_sexp_t key)
2486 unsigned char key_grip[21] = { 0 };
2487 gpg_error_t err;
2489 err = ssh_key_grip (key, key_grip);
2490 if (err)
2491 goto out;
2493 key_grip[sizeof (key_grip) - 1] = 0;
2495 /* FIXME: What to do here - forgetting the passphrase or deleting
2496 the key from key cache? */
2498 out:
2500 return err;
2503 /* Handler for the "add_identity" command. */
2504 static gpg_error_t
2505 ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
2507 gpg_error_t ret_err;
2508 gpg_error_t err;
2509 gcry_sexp_t key;
2510 unsigned char b;
2511 int confirm;
2512 int ttl;
2514 confirm = 0;
2515 key = NULL;
2516 ttl = 0;
2518 /* FIXME? */
2519 err = ssh_receive_key (request, &key, 1, 1, NULL);
2520 if (err)
2521 goto out;
2523 while (1)
2525 err = stream_read_byte (request, &b);
2526 if (gpg_err_code (err) == GPG_ERR_EOF)
2528 err = 0;
2529 break;
2532 switch (b)
2534 case SSH_OPT_CONSTRAIN_LIFETIME:
2536 u32 n = 0;
2538 err = stream_read_uint32 (request, &n);
2539 if (! err)
2540 ttl = n;
2541 break;
2544 case SSH_OPT_CONSTRAIN_CONFIRM:
2546 confirm = 1;
2547 break;
2550 default:
2551 /* FIXME: log/bad? */
2552 break;
2555 if (err)
2556 goto out;
2558 /* FIXME: are constraints used correctly? */
2560 err = ssh_identity_register (ctrl, key, ttl);
2562 out:
2564 gcry_sexp_release (key);
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 /* Handler for the "remove_identity" command. */
2575 static gpg_error_t
2576 ssh_handler_remove_identity (ctrl_t ctrl,
2577 estream_t request, estream_t response)
2579 unsigned char *key_blob;
2580 u32 key_blob_size;
2581 gcry_sexp_t key;
2582 gpg_error_t ret_err;
2583 gpg_error_t err;
2585 (void)ctrl;
2587 /* Receive key. */
2589 key_blob = NULL;
2590 key = NULL;
2592 err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2593 if (err)
2594 goto out;
2596 err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL);
2597 if (err)
2598 goto out;
2600 err = ssh_identity_drop (key);
2602 out:
2604 xfree (key_blob);
2605 gcry_sexp_release (key);
2607 if (! err)
2608 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2609 else
2610 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2612 return ret_err;
2615 /* FIXME: stub function. Actually useful? */
2616 static gpg_error_t
2617 ssh_identities_remove_all (void)
2619 gpg_error_t err;
2621 err = 0;
2623 /* FIXME: shall we remove _all_ cache entries or only those
2624 registered through the ssh emulation? */
2626 return err;
2629 /* Handler for the "remove_all_identities" command. */
2630 static gpg_error_t
2631 ssh_handler_remove_all_identities (ctrl_t ctrl,
2632 estream_t request, estream_t response)
2634 gpg_error_t ret_err;
2635 gpg_error_t err;
2637 (void)ctrl;
2638 (void)request;
2640 err = ssh_identities_remove_all ();
2642 if (! err)
2643 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2644 else
2645 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2647 return ret_err;
2650 /* Lock agent? FIXME: stub function. */
2651 static gpg_error_t
2652 ssh_lock (void)
2654 gpg_error_t err;
2656 /* FIXME */
2657 log_error ("ssh-agent's lock command is not implemented\n");
2658 err = 0;
2660 return err;
2663 /* Unock agent? FIXME: stub function. */
2664 static gpg_error_t
2665 ssh_unlock (void)
2667 gpg_error_t err;
2669 log_error ("ssh-agent's unlock command is not implemented\n");
2670 err = 0;
2672 return err;
2675 /* Handler for the "lock" command. */
2676 static gpg_error_t
2677 ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response)
2679 gpg_error_t ret_err;
2680 gpg_error_t err;
2682 (void)ctrl;
2683 (void)request;
2685 err = ssh_lock ();
2687 if (! err)
2688 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2689 else
2690 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2692 return ret_err;
2695 /* Handler for the "unlock" command. */
2696 static gpg_error_t
2697 ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
2699 gpg_error_t ret_err;
2700 gpg_error_t err;
2702 (void)ctrl;
2703 (void)request;
2705 err = ssh_unlock ();
2707 if (! err)
2708 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2709 else
2710 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2712 return ret_err;
2717 /* Return the request specification for the request identified by TYPE
2718 or NULL in case the requested request specification could not be
2719 found. */
2720 static ssh_request_spec_t *
2721 request_spec_lookup (int type)
2723 ssh_request_spec_t *spec;
2724 unsigned int i;
2726 for (i = 0; i < DIM (request_specs); i++)
2727 if (request_specs[i].type == type)
2728 break;
2729 if (i == DIM (request_specs))
2731 if (opt.verbose)
2732 log_info ("ssh request %u is not supported\n", type);
2733 spec = NULL;
2735 else
2736 spec = request_specs + i;
2738 return spec;
2741 /* Process a single request. The request is read from and the
2742 response is written to STREAM_SOCK. Uses CTRL as context. Returns
2743 zero in case of success, non zero in case of failure. */
2744 static int
2745 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
2747 ssh_request_spec_t *spec;
2748 estream_t response;
2749 estream_t request;
2750 unsigned char request_type;
2751 gpg_error_t err;
2752 int send_err;
2753 int ret;
2754 unsigned char *request_data;
2755 u32 request_data_size;
2756 u32 response_size;
2758 request_data = NULL;
2759 response = NULL;
2760 request = NULL;
2761 send_err = 0;
2763 /* Create memory streams for request/response data. The entire
2764 request will be stored in secure memory, since it might contain
2765 secret key material. The response does not have to be stored in
2766 secure memory, since we never give out secret keys.
2768 Note: we only have little secure memory, but there is NO
2769 possibility of DoS here; only trusted clients are allowed to
2770 connect to the agent. What could happen is that the agent
2771 returns out-of-secure-memory errors on requests in case the
2772 agent's owner floods his own agent with many large messages.
2773 -moritz */
2775 /* Retrieve request. */
2776 err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
2777 if (err)
2778 goto out;
2780 if (opt.verbose > 1)
2781 log_info ("received ssh request of length %u\n",
2782 (unsigned int)request_data_size);
2784 if (! request_data_size)
2786 send_err = 1;
2787 goto out;
2788 /* Broken request; FIXME. */
2791 request_type = request_data[0];
2792 spec = request_spec_lookup (request_type);
2793 if (! spec)
2795 send_err = 1;
2796 goto out;
2797 /* Unknown request; FIXME. */
2800 if (spec->secret_input)
2801 request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
2802 else
2803 request = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+");
2804 if (! request)
2806 err = gpg_error_from_syserror ();
2807 goto out;
2809 ret = es_setvbuf (request, NULL, _IONBF, 0);
2810 if (ret)
2812 err = gpg_error_from_syserror ();
2813 goto out;
2815 err = stream_write_data (request, request_data + 1, request_data_size - 1);
2816 if (err)
2817 goto out;
2818 es_rewind (request);
2820 response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
2821 if (! response)
2823 err = gpg_error_from_syserror ();
2824 goto out;
2827 if (opt.verbose)
2828 log_info ("ssh request handler for %s (%u) started\n",
2829 spec->identifier, spec->type);
2831 err = (*spec->handler) (ctrl, request, response);
2833 if (opt.verbose)
2835 if (err)
2836 log_info ("ssh request handler for %s (%u) failed: %s\n",
2837 spec->identifier, spec->type, gpg_strerror (err));
2838 else
2839 log_info ("ssh request handler for %s (%u) ready\n",
2840 spec->identifier, spec->type);
2843 if (err)
2845 send_err = 1;
2846 goto out;
2849 response_size = es_ftell (response);
2850 if (opt.verbose > 1)
2851 log_info ("sending ssh response of length %u\n",
2852 (unsigned int)response_size);
2854 err = es_fseek (response, 0, SEEK_SET);
2855 if (err)
2857 send_err = 1;
2858 goto out;
2861 err = stream_write_uint32 (stream_sock, response_size);
2862 if (err)
2864 send_err = 1;
2865 goto out;
2868 err = stream_copy (stream_sock, response);
2869 if (err)
2870 goto out;
2872 err = es_fflush (stream_sock);
2873 if (err)
2874 goto out;
2876 out:
2878 if (err && es_feof (stream_sock))
2879 log_error ("error occured while processing request: %s\n",
2880 gpg_strerror (err));
2882 if (send_err)
2884 if (opt.verbose > 1)
2885 log_info ("sending ssh error response\n");
2886 err = stream_write_uint32 (stream_sock, 1);
2887 if (err)
2888 goto leave;
2889 err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE);
2890 if (err)
2891 goto leave;
2894 leave:
2896 if (request)
2897 es_fclose (request);
2898 if (response)
2899 es_fclose (response);
2900 xfree (request_data); /* FIXME? */
2902 return !!err;
2905 /* Start serving client on SOCK_CLIENT. */
2906 void
2907 start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
2909 estream_t stream_sock = NULL;
2910 gpg_error_t err = 0;
2911 int ret;
2913 /* Because the ssh protocol does not send us information about the
2914 the current TTY setting, we resort here to use those from startup
2915 or those explictly set. */
2917 static const char *names[] =
2918 {"GPG_TTY", "DISPLAY", "TERM", "XAUTHORITY", "PINENTRY_USER_DATA", NULL};
2919 int idx;
2920 const char *value;
2922 for (idx=0; !err && names[idx]; idx++)
2923 if (!session_env_getenv (ctrl->session_env, names[idx])
2924 && (value = session_env_getenv (opt.startup_env, names[idx])))
2925 err = session_env_setenv (ctrl->session_env, names[idx], value);
2927 if (!err && !ctrl->lc_ctype && opt.startup_lc_ctype)
2928 if (!(ctrl->lc_ctype = xtrystrdup (opt.startup_lc_ctype)))
2929 err = gpg_error_from_syserror ();
2931 if (!err && !ctrl->lc_messages && opt.startup_lc_messages)
2932 if (!(ctrl->lc_messages = xtrystrdup (opt.startup_lc_messages)))
2933 err = gpg_error_from_syserror ();
2935 if (err)
2937 log_error ("error setting default session environment: %s\n",
2938 gpg_strerror (err));
2939 goto out;
2944 /* Create stream from socket. */
2945 stream_sock = es_fdopen (FD2INT(sock_client), "r+");
2946 if (!stream_sock)
2948 err = gpg_error_from_syserror ();
2949 log_error (_("failed to create stream from socket: %s\n"),
2950 gpg_strerror (err));
2951 goto out;
2953 /* We have to disable the estream buffering, because the estream
2954 core doesn't know about secure memory. */
2955 ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
2956 if (ret)
2958 err = gpg_error_from_syserror ();
2959 log_error ("failed to disable buffering "
2960 "on socket stream: %s\n", gpg_strerror (err));
2961 goto out;
2964 /* Main processing loop. */
2965 while ( !ssh_request_process (ctrl, stream_sock) )
2967 /* Check wether we have reached EOF before trying to read
2968 another request. */
2969 int c;
2971 c = es_fgetc (stream_sock);
2972 if (c == EOF)
2973 break;
2974 es_ungetc (c, stream_sock);
2977 /* Reset the SCD in case it has been used. */
2978 agent_reset_scd (ctrl);
2981 out:
2982 if (stream_sock)
2983 es_fclose (stream_sock);