d9e78c1481d7da2fc679502d125d41f4c1acdfd5
[gnupg.git] / agent / command-ssh.c
1 /* command-ssh.c - gpg-agent's ssh-agent emulation layer
2  * Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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.
10  *
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.
15  *
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., 59 Temple Place - Suite 330, Boston, MA
19  * 02111-1307, USA
20  */
21
22 /* Only v2 of the ssh-agent protocol is implemented.  */
23
24 #include <config.h>
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <dirent.h>
32 #include <stdio.h>
33
34 #include "agent.h"
35
36 #include "estream.h"
37 #include "i18n.h"
38
39 \f
40
41 /* Request types. */
42 #define SSH_REQUEST_REQUEST_IDENTITIES    11
43 #define SSH_REQUEST_SIGN_REQUEST          13
44 #define SSH_REQUEST_ADD_IDENTITY          17
45 #define SSH_REQUEST_REMOVE_IDENTITY       18
46 #define SSH_REQUEST_REMOVE_ALL_IDENTITIES 19
47 #define SSH_REQUEST_LOCK                  22
48 #define SSH_REQUEST_UNLOCK                23
49 #define SSH_REQUEST_ADD_ID_CONSTRAINED    25
50
51 /* Options. */
52 #define SSH_OPT_CONSTRAIN_LIFETIME         1
53 #define SSH_OPT_CONSTRAIN_CONFIRM          2
54
55 /* Response types. */
56 #define SSH_RESPONSE_SUCCESS               6
57 #define SSH_RESPONSE_FAILURE               5
58 #define SSH_RESPONSE_IDENTITIES_ANSWER    12
59 #define SSH_RESPONSE_SIGN_RESPONSE        14
60
61 /* Other constants.  */
62 #define SSH_DSA_SIGNATURE_PADDING 20
63 #define SSH_DSA_SIGNATURE_ELEMS    2
64 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0)
65
66 \f
67
68 /* Macros.  */
69
70 /* Return a new uint32 with b0 being the most significant byte and b3
71    being the least significant byte.  */
72 #define uint32_construct(b0, b1, b2, b3) \
73   ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3)
74
75 \f
76
77
78 /* Basic types.  */
79
80 typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl,
81                                               estream_t request,
82                                               estream_t response);
83
84 typedef struct ssh_request_spec
85 {
86   unsigned char type;
87   ssh_request_handler_t handler;
88   const char *identifier;
89 } ssh_request_spec_t;
90
91 typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems,
92                                            gcry_mpi_t *mpis);
93 typedef gpg_error_t (*ssh_signature_encoder_t) (estream_t signature_blob,
94                                                 gcry_mpi_t *mpis);
95
96 typedef struct ssh_key_type_spec
97 {
98   const char *ssh_identifier;
99   const char *identifier;
100   const char *elems_key_secret;
101   const char *elems_key_public;
102   const char *elems_secret;
103   const char *elems_signature;
104   const char *elems_sexp_order;
105   ssh_key_modifier_t key_modifier;
106   ssh_signature_encoder_t signature_encoder;
107   unsigned int flags;
108 } ssh_key_type_spec_t;
109
110
111 /* Prototypes.  */
112 static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl,
113                                                    estream_t request,
114                                                    estream_t response);
115 static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl,
116                                              estream_t request,
117                                              estream_t response);
118 static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl,
119                                              estream_t request,
120                                              estream_t response);
121 static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl,
122                                                 estream_t request,
123                                                 estream_t response);
124 static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl,
125                                                       estream_t request,
126                                                       estream_t response);
127 static gpg_error_t ssh_handler_lock (ctrl_t ctrl,
128                                      estream_t request,
129                                      estream_t response);
130 static gpg_error_t ssh_handler_unlock (ctrl_t ctrl,
131                                      estream_t request,
132                                      estream_t response);
133
134 static gpg_error_t ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis);
135 static gpg_error_t ssh_signature_encoder_rsa (estream_t signature_blob,
136                                               gcry_mpi_t *mpis);
137 static gpg_error_t ssh_signature_encoder_dsa (estream_t signature_blob,
138                                               gcry_mpi_t *mpis);
139
140
141
142 /* Global variables.  */
143    
144
145 /* Associating request types with the corresponding request
146    handlers.  */
147
148 #define REQUEST_SPEC_DEFINE(id, name) \
149   { SSH_REQUEST_##id, ssh_handler_##name, #name }
150
151 static ssh_request_spec_t request_specs[] =
152   {
153     REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES,    request_identities),
154     REQUEST_SPEC_DEFINE (SIGN_REQUEST,          sign_request),
155     REQUEST_SPEC_DEFINE (ADD_IDENTITY,          add_identity),
156     REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED,    add_identity),
157     REQUEST_SPEC_DEFINE (REMOVE_IDENTITY,       remove_identity),
158     REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities),
159     REQUEST_SPEC_DEFINE (LOCK,                  lock),
160     REQUEST_SPEC_DEFINE (UNLOCK,                unlock)
161   };
162 #undef REQUEST_SPEC_DEFINE
163
164
165 /* Table holding key type specifications.  */
166 static ssh_key_type_spec_t ssh_key_types[] =
167   {
168     {
169       "ssh-rsa", "rsa", "nedupq", "en",   "dupq", "s",  "nedpqu",
170       ssh_key_modifier_rsa, ssh_signature_encoder_rsa,
171       SPEC_FLAG_USE_PKCS1V2
172     },
173     {
174       "ssh-dss", "dsa", "pqgyx",  "pqgy", "x",    "rs", "pqgyx",
175       NULL,                 ssh_signature_encoder_dsa,
176       0
177     },
178   };
179
180 \f
181
182
183
184
185 \f
186
187 /*
188    General utility functions. 
189  */
190
191 /* A secure realloc, i.e. it makes sure to allocate secure memory if A
192    is NULL.  This is required becuase the standard gcry_realloc does
193    not know whether to allocate secure or normal if NULL is passed as
194    existing buffer.  */
195 static void *
196 realloc_secure (void *a, size_t n)
197 {
198   void *p;
199   
200   if (a)
201     p = gcry_realloc (a, n);
202   else
203     p = gcry_malloc_secure (n);
204
205   return p;
206 }
207
208
209
210 static char *
211 make_cstring (const char *data, size_t data_n)
212 {
213   char *s;
214
215   s = xtrymalloc (data_n + 1);
216   if (s)
217     {
218       strncpy (s, data, data_n);
219       s[data_n] = 0;
220     }
221
222   return s;
223 }
224
225
226
227
228 /* 
229    Primitive I/O functions.  
230  */
231
232
233 /* Read a byte from STREAM, store it in B.  */
234 static gpg_error_t
235 stream_read_byte (estream_t stream, unsigned char *b)
236 {
237   gpg_error_t err;
238   int ret;
239
240   ret = es_fgetc (stream);
241   if (ret == EOF)
242     {
243       if (es_ferror (stream))
244         err = gpg_error_from_errno (errno);
245       else
246         err = gpg_error (GPG_ERR_EOF);
247     }
248   else
249     {
250       *b = ret & 0xFF;
251       err = 0;
252     }
253
254   return err;
255 }
256
257 /* Write the byte contained in B to STREAM.  */
258 static gpg_error_t
259 stream_write_byte (estream_t stream, unsigned char b)
260 {
261   gpg_error_t err;
262   int ret;
263
264   ret = es_fputc (b, stream);
265   if (ret == EOF)
266     err = gpg_error_from_errno (errno);
267   else
268     err = 0;
269
270   return err;
271 }
272
273 /* Read a uint32 from STREAM, store it in UINT32.  */
274 static gpg_error_t
275 stream_read_uint32 (estream_t stream, u32 *uint32)
276 {
277   unsigned char buffer[4];
278   size_t bytes_read;
279   gpg_error_t err;
280   int ret;
281
282   ret = es_read (stream, buffer, sizeof (buffer), &bytes_read);
283   if (ret)
284     err = gpg_error_from_errno (errno);
285   else
286     {
287       if (bytes_read != sizeof (buffer))
288         err = gpg_error (GPG_ERR_EOF);
289       else
290         {
291           u32 n;
292
293           n = uint32_construct (buffer[0], buffer[1], buffer[2], buffer[3]);
294           *uint32 = n;
295           err = 0;
296         }
297     }
298
299   return err;
300 }
301
302 /* Write the uint32 contained in UINT32 to STREAM.  */
303 static gpg_error_t
304 stream_write_uint32 (estream_t stream, u32 uint32)
305 {
306   unsigned char buffer[4];
307   gpg_error_t err;
308   int ret;
309
310   buffer[0] = uint32 >> 24;
311   buffer[1] = uint32 >> 16;
312   buffer[2] = uint32 >>  8;
313   buffer[3] = uint32 >>  0;
314
315   ret = es_write (stream, buffer, sizeof (buffer), NULL);
316   if (ret)
317     err = gpg_error_from_errno (errno);
318   else
319     err = 0;
320
321   return err;
322 }
323
324 /* Read SIZE bytes from STREAM into BUFFER.  */
325 static gpg_error_t
326 stream_read_data (estream_t stream, unsigned char *buffer, size_t size)
327 {
328   gpg_error_t err;
329   size_t bytes_read;
330   int ret;
331
332   ret = es_read (stream, buffer, size, &bytes_read);
333   if (ret)
334     err = gpg_error_from_errno (errno);
335   else
336     {
337       if (bytes_read != size)
338         err = gpg_error (GPG_ERR_EOF);
339       else
340         err = 0;
341     }
342
343   return err;
344 }
345
346 /* Write SIZE bytes from BUFFER to STREAM.  */
347 static gpg_error_t
348 stream_write_data (estream_t stream, const unsigned char *buffer, size_t size)
349 {
350   gpg_error_t err;
351   int ret;
352
353   ret = es_write (stream, buffer, size, NULL);
354   if (ret)
355     err = gpg_error_from_errno (errno);
356   else
357     err = 0;
358
359   return err;
360 }
361
362 /* Read a binary string from STREAM into STRING, store size of string
363    in STRING_SIZE; depending on SECURE use secure memory for
364    string.  */
365 static gpg_error_t
366 stream_read_string (estream_t stream, unsigned int secure,
367                     unsigned char **string, u32 *string_size)
368 {
369   gpg_error_t err;
370   unsigned char *buffer;
371   u32 length;
372
373   buffer = NULL;
374
375   /* Read string length.  */
376   err = stream_read_uint32 (stream, &length);
377   if (err)
378     goto out;
379
380   /* Allocate space.  */
381   if (secure)
382     buffer = xtrymalloc_secure (length + 1);
383   else
384     buffer = xtrymalloc (length + 1);
385   if (! buffer)
386     {
387       /* FIXME: xtrymalloc_secure does not set errno, does it?  */
388       err = gpg_error_from_errno (errno);
389       abort ();
390       goto out;
391     }
392
393   /* Read data.  */
394   err = stream_read_data (stream, buffer, length);
395   if (err)
396     goto out;
397
398   /* Finalize string object.  */
399   buffer[length] = 0;
400   *string = buffer;
401   if (string_size)
402     *string_size = length;
403
404  out:
405
406   if (err)
407     xfree (buffer);
408
409   return err;
410 }
411
412 /* Read a C-string from STREAM, store copy in STRING.  */
413 static gpg_error_t
414 stream_read_cstring (estream_t stream, char **string)
415 {
416   unsigned char *buffer;
417   gpg_error_t err;
418
419   err = stream_read_string (stream, 0, &buffer, NULL);
420   if (err)
421     goto out;
422   
423   *string = (char *) buffer;
424
425  out:
426
427   return err;
428 }
429
430
431 /* Write a binary string from STRING of size STRING_N to STREAM.  */
432 static gpg_error_t
433 stream_write_string (estream_t stream,
434                      const unsigned char *string, u32 string_n)
435 {
436   gpg_error_t err;
437
438   err = stream_write_uint32 (stream, string_n);
439   if (err)
440     goto out;
441
442   err = stream_write_data (stream, string, string_n);
443
444  out:
445
446   return err;
447 }
448
449 /* Write a C-string from STRING to STREAM.  */
450 static gpg_error_t
451 stream_write_cstring (estream_t stream, const char *string)
452 {
453   gpg_error_t err;
454
455   err = stream_write_string (stream,
456                              (const unsigned char *) string, strlen (string));
457
458   return err;
459 }                         
460
461 /* Read an MPI from STREAM, store it in MPINT.  Depending on SECURE
462    use secure memory.  */
463 static gpg_error_t
464 stream_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint)
465 {
466   unsigned char *mpi_data;
467   u32 mpi_data_size;
468   gpg_error_t err;
469   gcry_mpi_t mpi;
470
471   mpi_data = NULL;
472
473   err = stream_read_string (stream, secure, &mpi_data, &mpi_data_size);
474   if (err)
475     goto out;
476
477   err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_STD, mpi_data, mpi_data_size, NULL);
478   if (err)
479     goto out;
480
481   *mpint = mpi;
482
483  out:
484
485   xfree (mpi_data);
486
487   return err;
488 }
489
490 /* Write the MPI contained in MPINT to STREAM.  */
491 static gpg_error_t
492 stream_write_mpi (estream_t stream, gcry_mpi_t mpint)
493 {
494   unsigned char *mpi_buffer;
495   size_t mpi_buffer_n;
496   gpg_error_t err;
497
498   mpi_buffer = NULL;
499
500   err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &mpi_buffer, &mpi_buffer_n, mpint);
501   if (err)
502     goto out;
503
504   err = stream_write_string (stream, mpi_buffer, mpi_buffer_n);
505
506  out:
507
508   xfree (mpi_buffer);
509
510   return err;
511 }
512
513 /* Copy data from SRC to DST until EOF is reached.  */
514 static gpg_error_t
515 stream_copy (estream_t dst, estream_t src)
516 {
517   char buffer[BUFSIZ];
518   size_t bytes_read;
519   gpg_error_t err;
520   int ret;
521
522   err = 0;
523   while (1)
524     {
525       ret = es_read (src, buffer, sizeof (buffer), &bytes_read);
526       if (ret || (! bytes_read))
527         {
528           if (ret)
529             err = gpg_error_from_errno (errno);
530           break;
531         }
532       ret = es_write (dst, buffer, bytes_read, NULL);
533       if (ret)
534         {
535           err = gpg_error_from_errno (errno);
536           break;
537         }
538     }
539
540   return err;
541 }
542
543
544 /* Read the content of the file specified by FILENAME into a newly
545    create buffer, which is to be stored in BUFFER; store length of
546    buffer in BUFFER_N.  */
547 static gpg_error_t
548 file_to_buffer (const char *filename, unsigned char **buffer, size_t *buffer_n)
549 {
550   unsigned char *buffer_new;
551   struct stat statbuf;
552   estream_t stream;
553   gpg_error_t err;
554   int ret;
555
556   buffer_new = NULL;
557   err = 0;
558   
559   stream = es_fopen (filename, "r");
560   if (! stream)
561     {
562       err = gpg_error_from_errno (errno);
563       goto out;
564     }
565
566   ret = fstat (es_fileno (stream), &statbuf);
567   if (ret)
568     {
569       err = gpg_error_from_errno (errno);
570       goto out;
571     }
572
573   buffer_new = xtrymalloc (statbuf.st_size);
574   if (! buffer_new)
575     {
576       err = gpg_error_from_errno (errno);
577       goto out;
578     }
579
580   err = stream_read_data (stream, buffer_new, statbuf.st_size);
581   if (err)
582     goto out;
583
584   *buffer = buffer_new;
585   *buffer_n = statbuf.st_size;
586
587  out:
588
589   if (stream)
590     es_fclose (stream);
591
592   if (err)
593     xfree (buffer_new);
594
595   return err;
596 }
597
598
599 \f
600
601 /*
602
603   MPI lists. 
604
605  */
606
607 static void
608 mpint_list_free (gcry_mpi_t *mpi_list)
609 {
610   if (mpi_list)
611     {
612       unsigned int i;
613
614       for (i = 0; mpi_list[i]; i++)
615         gcry_mpi_release (mpi_list[i]);
616       xfree (mpi_list);
617     }
618 }
619
620
621 static gpg_error_t
622 ssh_receive_mpint_list (estream_t stream, int secret,
623                         ssh_key_type_spec_t key_spec, gcry_mpi_t **mpi_list)
624 {
625   const char *elems_secret;
626   const char *elems;
627   unsigned int elems_n;
628   gcry_mpi_t *mpis;
629   unsigned int i;
630   gpg_error_t err;
631   int elem_is_secret;
632
633   mpis = NULL;
634   err = 0;
635   
636   if (secret)
637     {
638       elems = key_spec.elems_key_secret;
639       elems_secret = key_spec.elems_secret;
640     }
641   else
642     {
643       elems = key_spec.elems_key_public;
644       elems_secret = "";
645     }
646   elems_n = strlen (elems);
647
648   mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1));
649   if (! mpis)
650     {
651       err = gpg_error_from_errno (errno);
652       goto out;
653     }
654   
655   memset (mpis, 0, sizeof (*mpis) * (elems_n + 1));
656   
657   for (i = 0; i < elems_n; i++)
658     {
659       elem_is_secret = strchr (elems_secret, elems[i]) ? 1 : 0;
660       err = stream_read_mpi (stream, elem_is_secret, &mpis[i]);
661       if (err)
662         break;
663     }
664   if (err)
665     goto out;
666
667   *mpi_list = mpis;
668
669  out:
670
671   if (err)
672     mpint_list_free (mpis);
673
674   return err;
675 }
676
677 \f
678
679 static gpg_error_t
680 ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis)
681 {
682   gcry_mpi_t p;
683   gcry_mpi_t q;
684   gcry_mpi_t u;
685
686   if (strcmp (elems, "nedupq"))
687     /* Modifying only necessary for secret keys.  */
688     goto out;
689
690   u = mpis[3];
691   p = mpis[4];
692   q = mpis[5];
693
694   if (gcry_mpi_cmp (p, q) > 0)
695     {
696       /* P shall be smaller then Q!  Swap primes.  iqmp becomes u.  */
697       gcry_mpi_t tmp;
698
699       tmp = mpis[4];
700       mpis[4] = mpis[5];
701       mpis[5] = tmp;
702     }
703   else
704     /* U needs to be recomputed.  */
705     gcry_mpi_invm (u, p, q);
706
707  out:
708
709   return 0;
710 }
711
712 static gpg_error_t
713 ssh_signature_encoder_rsa (estream_t signature_blob, gcry_mpi_t *mpis)
714 {
715   unsigned char *data;
716   size_t data_n;
717   gpg_error_t err;
718   gcry_mpi_t s;
719
720   s = mpis[0];
721
722   err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s);
723   if (err)
724     goto out;
725
726   err = stream_write_string (signature_blob, data, data_n);
727   xfree (data);
728
729  out:
730
731   return err;
732 }
733
734
735
736 static gpg_error_t
737 ssh_signature_encoder_dsa (estream_t signature_blob, gcry_mpi_t *mpis)
738 {
739   unsigned char buffer[SSH_DSA_SIGNATURE_PADDING * SSH_DSA_SIGNATURE_ELEMS];
740   unsigned char *data;
741   size_t data_n;
742   gpg_error_t err;
743   int i;
744
745   data = NULL;
746
747   for (i = 0; i < 2; i++)
748     {
749       err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]);
750       if (err)
751         break;
752
753       if (data_n > SSH_DSA_SIGNATURE_PADDING)
754         {
755           err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
756           break;
757         }
758       
759       memset (buffer + (i * SSH_DSA_SIGNATURE_PADDING), 0,
760               SSH_DSA_SIGNATURE_PADDING - data_n);
761       memcpy (buffer + (i * SSH_DSA_SIGNATURE_PADDING)
762               + (SSH_DSA_SIGNATURE_PADDING - data_n), data, data_n);
763
764       xfree (data);
765       data = NULL;
766     }
767   if (err)
768     goto out;
769
770   err = stream_write_string (signature_blob, buffer, sizeof (buffer));
771
772  out:
773
774   xfree (data);
775
776   return err;
777 }
778
779 /* 
780    S-Expressions. 
781  */
782
783 static gpg_error_t
784 ssh_sexp_construct (gcry_sexp_t *sexp,
785                     ssh_key_type_spec_t key_spec, int secret,
786                     gcry_mpi_t *mpis, const char *comment)
787 {
788   gcry_sexp_t sexp_new;
789   char *sexp_template;
790   size_t sexp_template_n;
791   gpg_error_t err;
792   const char *elems;
793   size_t elems_n;
794   unsigned int i;
795   unsigned int j;
796   void **arg_list;
797
798   err = 0;
799   sexp_new = NULL;
800   arg_list = NULL;
801   if (secret)
802     elems = key_spec.elems_sexp_order;
803   else
804     elems = key_spec.elems_key_public;
805   elems_n = strlen (elems);
806
807   /* FIXME: Why 33? -wk */
808   sexp_template_n = (33 + strlen (key_spec.identifier)
809                      + (elems_n * 6) - (!secret));
810   sexp_template = xtrymalloc (sexp_template_n);
811   if (! sexp_template)
812     {
813       err = gpg_error_from_errno (errno);
814       goto out;
815     }
816
817   arg_list = xtrymalloc (sizeof (*arg_list) * (elems_n + 1));
818   if (! arg_list)
819     {
820       err = gpg_error_from_errno (errno);
821       goto out;
822     }
823
824   sprintf (sexp_template, "(%s-key (%s ",
825            secret ? "private" : "public", key_spec.identifier);
826   for (i = 0; i < elems_n; i++)
827     {
828       sprintf (strchr (sexp_template, 0), "(%c %%m)", elems[i]);
829       if (secret)
830         {
831           for (j = 0; j < elems_n; j++)
832             if (key_spec.elems_key_secret[j] == elems[i])
833               break;
834         }
835       else
836         j = i;
837       arg_list[i] = &mpis[j];
838     }
839   arg_list[i] = &comment;
840   sprintf (strchr (sexp_template, 0), ") (comment %%s))");
841
842   err = gcry_sexp_build_array (&sexp_new, NULL, sexp_template, arg_list);
843   if (err)
844     goto out;
845
846   *sexp = sexp_new;
847
848  out:
849
850   xfree (arg_list);
851   xfree (sexp_template);
852
853   return err;
854 }
855
856 static gpg_error_t
857 ssh_sexp_extract (gcry_sexp_t sexp,
858                   ssh_key_type_spec_t key_spec, int *secret,
859                   gcry_mpi_t **mpis, const char **comment)
860 {
861   gpg_error_t err;
862   gcry_sexp_t value_list;
863   gcry_sexp_t value_pair;
864   gcry_sexp_t comment_list;
865   unsigned int i;
866   char *comment_new;
867   const char *data;
868   size_t data_n;
869   int is_secret;
870   size_t elems_n;
871   const char *elems;
872   gcry_mpi_t *mpis_new;
873   gcry_mpi_t mpi;
874
875   err = 0;
876   value_list = NULL;
877   value_pair = NULL;
878   comment_list = NULL;
879   comment_new = NULL;
880   mpis_new = NULL;
881
882   data = gcry_sexp_nth_data (sexp, 0, &data_n);
883   if (! data)
884     {
885       err = gpg_error (GPG_ERR_INV_SEXP);
886       goto out;
887     }
888
889   if (data_n == 10 && !strncmp (data, "public-key", 10))
890     {
891       is_secret = 0;
892       elems = key_spec.elems_key_public;
893     }
894   else if ((data_n == 11 && !strncmp (data, "private-key", 11))
895            || (data_n == 21 && !strncmp (data, "protected-private-key", 21)))
896     {
897       is_secret = 1;
898       elems = key_spec.elems_key_secret;
899     }
900   else
901     {
902       err = gpg_error (GPG_ERR_INV_SEXP);
903       goto out;
904     }
905
906   elems_n = strlen (elems);
907   mpis_new = xtrymalloc (sizeof (*mpis_new) * (elems_n + 1));
908   if (! mpis_new)
909     {
910       err = gpg_error_from_errno (errno); /* FIXME, xtrymalloc+errno.  */
911       goto out;
912     }
913   memset (mpis_new, 0, sizeof (*mpis_new) * (elems_n + 1));
914
915   value_list = gcry_sexp_find_token (sexp, key_spec.identifier, 0);
916   if (! value_list)
917     {
918       err = gpg_error (GPG_ERR_INV_SEXP);
919       goto out;
920     }
921
922   for (i = 0; i < elems_n; i++)
923     {
924       value_pair = gcry_sexp_find_token (value_list, elems + i, 1);
925       if (! value_pair)
926         {
927           err = gpg_error (GPG_ERR_INV_SEXP);
928           break;
929         }
930
931       mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_USG);
932       if (! mpi)
933         {
934           err = gpg_error (GPG_ERR_INV_SEXP);
935           break;
936         }
937       mpis_new[i] = mpi;
938       gcry_sexp_release (value_pair);
939       value_pair = NULL;
940     }
941   if (err)
942     goto out;
943
944   /* We do not require a comment sublist to be present here.  */
945   data = NULL;
946   data_n = 0;
947
948   comment_list = gcry_sexp_find_token (sexp, "comment", 0);
949   if (comment_list)
950     data = gcry_sexp_nth_data (comment_list, 1, &data_n);
951   if (! data)
952     {
953       data = "(none)";
954       data_n = 6;
955     }
956
957   comment_new = xtrymalloc (data_n + 1);
958   if (! comment_new)
959     {
960       err = gpg_error_from_errno (errno);
961       goto out;
962     }
963   strncpy (comment_new, data, data_n);
964   comment_new[data_n] = 0;
965
966   if (secret)
967     *secret = is_secret;
968   *mpis = mpis_new;
969   *comment = comment_new;
970
971  out:
972
973   gcry_sexp_release (value_list);
974   gcry_sexp_release (value_pair);
975   gcry_sexp_release (comment_list);
976   
977   if (err)
978     {
979       xfree (comment_new);
980       mpint_list_free (mpis_new);
981     }
982
983   return err;
984 }
985
986 static gpg_error_t
987 ssh_sexp_extract_key_type (gcry_sexp_t sexp, const char **key_type)
988 {
989   gcry_sexp_t sublist;
990   char *key_type_new;
991   const char *data;
992   size_t data_n;
993   gpg_error_t err;
994
995   err = 0;
996   key_type_new = NULL;
997   
998   sublist = gcry_sexp_nth (sexp, 1);
999   if (! sublist)
1000     {
1001       err = gpg_error (GPG_ERR_INV_SEXP);
1002       goto out;
1003     }
1004
1005   data = gcry_sexp_nth_data (sublist, 0, &data_n);
1006   if (! data)
1007     {
1008       err = gpg_error (GPG_ERR_INV_SEXP);
1009       goto out;
1010     }
1011
1012   key_type_new = xtrymalloc (data_n + 1);
1013   if (! key_type_new)
1014     {
1015       err = gpg_error_from_errno (errno);
1016       goto out;
1017     }
1018
1019   strncpy (key_type_new, data, data_n);
1020   key_type_new[data_n] = 0;
1021   *key_type = key_type_new;
1022
1023  out:
1024
1025   gcry_sexp_release (sublist);
1026
1027   return err;
1028 }
1029
1030 \f
1031
1032 /* Key I/O.  */
1033
1034 static gpg_error_t
1035 ssh_key_type_lookup (const char *ssh_name, const char *name,
1036                      ssh_key_type_spec_t *spec)
1037 {
1038   gpg_error_t err;
1039   unsigned int i;
1040
1041   for (i = 0; i < DIM (ssh_key_types); i++)
1042     if ((ssh_name && (! strcmp (ssh_name, ssh_key_types[i].ssh_identifier)))
1043         || (name && (! strcmp (name, ssh_key_types[i].identifier))))
1044       break;
1045   
1046   if (i == DIM (ssh_key_types))
1047     err = gpg_error (GPG_ERR_NOT_FOUND);
1048   else
1049     {
1050       *spec = ssh_key_types[i];
1051       err = 0;
1052     }
1053
1054   return err;
1055 }
1056
1057 static gpg_error_t
1058 ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret,
1059                  int read_comment, ssh_key_type_spec_t *key_spec)
1060 {
1061   gpg_error_t err;
1062   char *key_type;
1063   char *comment;
1064   gcry_sexp_t key;
1065   ssh_key_type_spec_t spec;
1066   gcry_mpi_t *mpi_list;
1067   const char *elems;
1068
1069   mpi_list = NULL;
1070   key_type = NULL;
1071   comment = "";
1072   key = NULL;
1073         
1074   err = stream_read_cstring (stream, &key_type);
1075   if (err)
1076     goto out;
1077
1078   err = ssh_key_type_lookup (key_type, NULL, &spec);
1079   if (err)
1080     goto out;
1081
1082   err = ssh_receive_mpint_list (stream, secret, spec, &mpi_list);
1083   if (err)
1084     goto out;
1085
1086   if (read_comment)
1087     {
1088       err = stream_read_cstring (stream, &comment);
1089       if (err)
1090         goto out;
1091     }
1092
1093   if (secret)
1094     elems = spec.elems_key_secret;
1095   else
1096     elems = spec.elems_key_public;
1097
1098   if (spec.key_modifier)
1099     {
1100       err = (*spec.key_modifier) (elems, mpi_list);
1101       if (err)
1102         goto out;
1103     }
1104
1105   err = ssh_sexp_construct (&key, spec, secret, mpi_list, comment);
1106   if (err)
1107     goto out;
1108
1109   if (key_spec)
1110     *key_spec = spec;
1111   *key_new = key;
1112   
1113  out:
1114
1115   mpint_list_free (mpi_list);
1116   xfree (key_type);
1117   if (read_comment)
1118     xfree (comment);
1119
1120   return err;
1121 }
1122
1123 static gpg_error_t
1124 ssh_convert_key_to_blob (unsigned char **blob, size_t *blob_size,
1125                          const char *type, gcry_mpi_t *mpis)
1126 {
1127   unsigned char *blob_new;
1128   long int blob_size_new;
1129   estream_t stream;
1130   gpg_error_t err;
1131   unsigned int i;
1132
1133   blob_new = NULL;
1134   stream = NULL;
1135   err = 0;
1136
1137   stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1138   if (! stream)
1139     {
1140       err = gpg_error_from_errno (errno);
1141       goto out;
1142     }
1143
1144   err = stream_write_cstring (stream, type);
1145   if (err)
1146     goto out;
1147
1148   for (i = 0; mpis[i] && (! err); i++)
1149     err = stream_write_mpi (stream, mpis[i]);
1150   if (err)
1151     goto out;
1152
1153   blob_size_new = es_ftell (stream);
1154   if (blob_size_new == -1)
1155     {
1156       err = gpg_error_from_errno (errno);
1157       goto out;
1158     }
1159   
1160   err = es_fseek (stream, 0, SEEK_SET);
1161   if (err)
1162     goto out;
1163
1164   blob_new = xtrymalloc (blob_size_new);
1165   if (! blob_new)
1166     {
1167       err = gpg_error_from_errno (errno);
1168       goto out;
1169     }
1170
1171   err = stream_read_data (stream, blob_new, blob_size_new);
1172   if (err)
1173     goto out;
1174
1175   *blob = blob_new;
1176   *blob_size = blob_size_new;
1177
1178  out:
1179
1180   if (stream)
1181     es_fclose (stream);
1182   if (err)
1183     xfree (blob_new);
1184
1185   return err;
1186 }
1187                               
1188
1189 static gpg_error_t
1190 ssh_send_key_public (estream_t stream, gcry_sexp_t key_public)
1191 {
1192   ssh_key_type_spec_t spec;
1193   gcry_mpi_t *mpi_list;
1194   const char *key_type;
1195   const char *comment;
1196   unsigned char *blob;
1197   size_t blob_n;
1198   gpg_error_t err;
1199
1200   key_type = NULL;
1201   mpi_list = NULL;
1202   comment = NULL;
1203   blob = NULL;
1204
1205   err = ssh_sexp_extract_key_type (key_public, &key_type);
1206   if (err)
1207     goto out;
1208
1209   err = ssh_key_type_lookup (NULL, key_type, &spec);
1210   if (err)
1211     goto out;
1212
1213   err = ssh_sexp_extract (key_public, spec, NULL, &mpi_list, &comment);
1214   if (err)
1215     goto out;
1216
1217   err = ssh_convert_key_to_blob (&blob, &blob_n,
1218                                  spec.ssh_identifier, mpi_list);
1219   if (err)
1220     goto out;
1221   
1222   err = stream_write_string (stream, blob, blob_n);
1223   if (err)
1224     goto out;
1225
1226   err = stream_write_cstring (stream, comment);
1227   
1228  out:
1229
1230   mpint_list_free (mpi_list);
1231   xfree ((void *) key_type);
1232   xfree ((void *) comment);
1233   xfree (blob);
1234
1235   return err;
1236 }
1237
1238 static gpg_error_t
1239 ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size,
1240                                gcry_sexp_t *key_public,
1241                                ssh_key_type_spec_t *key_spec)
1242 {
1243   estream_t blob_stream;
1244   gpg_error_t err;
1245
1246   err = 0;
1247   
1248   blob_stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1249   if (! blob_stream)
1250     {
1251       err = gpg_error_from_errno (errno);
1252       goto out;
1253     }
1254
1255   err = stream_write_data (blob_stream, blob, blob_size);
1256   if (err)
1257     goto out;
1258
1259   err = es_fseek (blob_stream, 0, SEEK_SET);
1260   if (err)
1261     goto out;
1262
1263   err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec);
1264
1265  out:
1266
1267   if (blob_stream)
1268     es_fclose (blob_stream);
1269
1270   return err;
1271 }
1272
1273 \f
1274
1275 static gpg_error_t
1276 key_secret_to_public (gcry_sexp_t *key_public,
1277                       ssh_key_type_spec_t spec, gcry_sexp_t key_secret)
1278 {
1279   gpg_error_t err;
1280   gcry_sexp_t value_pair;
1281   unsigned int i;
1282   gcry_mpi_t *mpis;
1283   gcry_mpi_t mpi;
1284   void **arglist;
1285   size_t elems_n;
1286   char *template;
1287   size_t template_n;
1288   const char *elems;
1289   char *comment;
1290   const char *data;
1291   size_t data_n;
1292
1293   err = 0;
1294   mpis = NULL;
1295   arglist = NULL;
1296   comment = NULL;
1297   template = NULL;
1298   value_pair = NULL;
1299
1300   elems = spec.elems_key_public;
1301   elems_n = strlen (elems);
1302
1303   data = NULL;
1304   value_pair  = gcry_sexp_find_token (key_secret, "comment", 0);
1305   if (value_pair)
1306     data = gcry_sexp_nth_data (value_pair, 1, &data_n);
1307   if (! data)
1308     {
1309       data = "";
1310       data_n = 0;
1311     }
1312
1313   comment = xtrymalloc (data_n + 1);
1314   if (! comment)
1315     {
1316       err = gpg_error_from_errno (errno);
1317       goto out;
1318     }
1319   strncpy (comment, data, data_n);
1320   comment[data_n] = 0;
1321
1322   gcry_sexp_release (value_pair);
1323   value_pair = NULL;
1324   
1325   template_n = 29 + strlen (spec.identifier) + (elems_n * 7) + 1;
1326   template = xtrymalloc (template_n);
1327   if (! template)
1328     {
1329       err = gpg_error_from_errno (errno);
1330       goto out;
1331     }
1332
1333   mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1));
1334   if (! mpis)
1335     {
1336       err = gpg_error_from_errno (errno);       /* FIXME: errno.  */
1337       goto out;
1338     }
1339   memset (mpis, 0, sizeof (*mpis) * (elems_n + 1));
1340
1341   arglist = xtrymalloc (sizeof (*arglist) * (elems_n + 1));
1342   if (! arglist)
1343     {
1344       err = gpg_error_from_errno (errno);
1345       goto out;
1346     }
1347
1348   for (i = 0; i < elems_n; i++)
1349     {
1350       value_pair = gcry_sexp_find_token (key_secret, elems + i, 1);
1351       if (! value_pair)
1352         {
1353           err = gpg_error (GPG_ERR_INV_SEXP);
1354           break;
1355         }
1356       mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_USG);
1357       if (! mpi)
1358         {
1359           err = gpg_error (GPG_ERR_INV_SEXP);
1360           break;
1361         }
1362       gcry_sexp_release (value_pair);
1363       value_pair = NULL;
1364
1365       mpis[i] = mpi;
1366       arglist[i] = &mpis[i];
1367       mpi = NULL;
1368     }
1369   if (err)
1370     goto out;
1371
1372   /* FIXME: write better.  */
1373   sprintf (template, "(public-key (%s", spec.identifier);
1374   for (i = 0; i < elems_n; i++)
1375     sprintf (strchr (template, 0)," (%c %%m)", elems[i]);
1376   sprintf (strchr (template, 0), ") (comment %%s))");
1377   arglist[i] = &comment;
1378
1379   err = gcry_sexp_build_array (key_public, NULL, template, arglist);
1380   
1381  out:
1382
1383   gcry_sexp_release (value_pair);
1384   xfree (template);
1385   mpint_list_free (mpis);
1386   xfree (arglist);
1387   xfree (comment);
1388
1389   return err;
1390 }
1391
1392 \f
1393
1394 /*
1395   Request handler.  
1396  */
1397
1398 static gpg_error_t
1399 ssh_handler_request_identities (ctrl_t ctrl,
1400                                 estream_t request, estream_t response)
1401 {
1402   const char *key_type;
1403   ssh_key_type_spec_t spec;
1404   struct dirent *dir_entry;
1405   char *key_directory;
1406   size_t key_directory_n;
1407   char *key_path;
1408   unsigned char *buffer;
1409   size_t buffer_n;
1410   u32 key_counter;
1411   estream_t key_blobs;
1412   gcry_sexp_t key_secret;
1413   gcry_sexp_t key_public;
1414   DIR *dir;
1415   gpg_error_t err;
1416   gpg_error_t ret_err;
1417   int ret;
1418
1419   /* Prepare buffer stream.  */
1420
1421   key_directory = NULL;
1422   key_secret = NULL;
1423   key_public = NULL;
1424   key_type = NULL;
1425   key_path = NULL;
1426   key_counter = 0;
1427   buffer = NULL;
1428   dir = NULL;
1429   err = 0;
1430
1431   key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1432   if (! key_blobs)
1433     {
1434       err = gpg_error_from_errno (errno);
1435       goto out;
1436     }
1437
1438   /* Open key directory.  */
1439   key_directory = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
1440   if (! key_directory)
1441     {
1442       err = gpg_err_code_from_errno (errno);
1443       goto out;
1444     }
1445   key_directory_n = strlen (key_directory);
1446   
1447   key_path = xtrymalloc (key_directory_n + 46);
1448   if (! key_path)
1449     {
1450       err = gpg_err_code_from_errno (errno);
1451       goto out;
1452     }
1453
1454   sprintf (key_path, "%s/", key_directory);
1455   sprintf (key_path + key_directory_n + 41, ".key");
1456
1457   dir = opendir (key_directory);
1458   if (! dir)
1459     {
1460       err = gpg_err_code_from_errno (errno);
1461       goto out;
1462     }
1463
1464   /* Iterate over key files.  */
1465
1466   /* FIXME: make sure that buffer gets deallocated properly.  */
1467
1468   while (1)
1469     {
1470       dir_entry = readdir (dir);
1471       if (dir_entry)
1472         {
1473           if ((strlen (dir_entry->d_name) == 44)
1474               && (! strncmp (dir_entry->d_name + 40, ".key", 4)))
1475             {
1476               strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40);
1477
1478               /* Read file content.  */
1479               err = file_to_buffer (key_path, &buffer, &buffer_n);
1480               if (err)
1481                 break;
1482               
1483               err = gcry_sexp_sscan (&key_secret, NULL, buffer, buffer_n);
1484               if (err)
1485                 break;
1486
1487               xfree (buffer);
1488               buffer = NULL;
1489
1490               err = ssh_sexp_extract_key_type (key_secret, &key_type);
1491               if (err)
1492                 break;
1493
1494               err = ssh_key_type_lookup (NULL, key_type, &spec);
1495               if (err)
1496                 break;
1497
1498               xfree ((void *) key_type);
1499               key_type = NULL;
1500
1501               err = key_secret_to_public (&key_public, spec, key_secret);
1502               if (err)
1503                 break;
1504
1505               gcry_sexp_release (key_secret);
1506               key_secret = NULL;
1507               
1508               err = ssh_send_key_public (key_blobs, key_public);
1509               if (err)
1510                 break;
1511
1512               gcry_sexp_release (key_public);
1513               key_public = NULL;
1514
1515               key_counter++;
1516             }
1517         }
1518       else
1519         break;
1520     }
1521   if (err)
1522     goto out;
1523   
1524   ret = es_fseek (key_blobs, 0, SEEK_SET);
1525   if (ret)
1526     {
1527       err = gpg_error_from_errno (errno);
1528       goto out;
1529     }
1530
1531  out:
1532
1533   /* Send response.  */
1534
1535   gcry_sexp_release (key_secret);
1536   gcry_sexp_release (key_public);
1537
1538   if (! err)
1539     {
1540       ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER);
1541       if (ret_err)
1542         goto leave;
1543       ret_err = stream_write_uint32 (response, key_counter);
1544       if (ret_err)
1545         goto leave;
1546       ret_err = stream_copy (response, key_blobs);
1547       if (ret_err)
1548         goto leave;
1549     }
1550   else
1551     {
1552       ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
1553       goto leave;
1554     };
1555
1556  leave:
1557
1558   if (key_blobs)
1559     es_fclose (key_blobs);
1560   if (dir)
1561     closedir (dir);
1562
1563   free (key_directory);
1564   xfree (key_path);
1565   xfree (buffer);
1566   xfree ((void *) key_type);            /* FIXME? */
1567
1568   return ret_err;
1569 }
1570
1571 static gpg_error_t
1572 data_hash (unsigned char *data, size_t data_n,
1573            int md_algorithm, unsigned char *hash)
1574 {
1575   gcry_md_hash_buffer (md_algorithm, hash, data, data_n);
1576
1577   return 0;
1578 }
1579
1580
1581 static gpg_error_t
1582 data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder,
1583            unsigned char **sig, size_t *sig_n)
1584 {
1585   gpg_error_t err;
1586   gcry_sexp_t signature_sexp;
1587   estream_t stream;
1588   gcry_sexp_t valuelist;
1589   gcry_sexp_t sublist;
1590   gcry_mpi_t sig_value;
1591   unsigned char *sig_blob;
1592   size_t sig_blob_n;
1593   const char *identifier;
1594   const char *identifier_raw;
1595   size_t identifier_n;
1596   ssh_key_type_spec_t spec;
1597   int ret;
1598   unsigned int i;
1599   const char *elems;
1600   size_t elems_n;
1601   gcry_mpi_t *mpis;
1602
1603   signature_sexp = NULL;
1604   identifier = NULL;
1605   valuelist = NULL;
1606   sublist = NULL;
1607   sig_blob = NULL;
1608   sig_blob_n = 0;
1609   stream = NULL;
1610   sig_value = NULL;
1611   mpis = NULL;
1612
1613   err = agent_pksign_do (ctrl,
1614                          _("Please provide the passphrase "
1615                            "for the ssh key `%c':"), &signature_sexp, 0);
1616   if (err)
1617     goto out;
1618
1619   valuelist = gcry_sexp_nth (signature_sexp, 1);
1620   if (! valuelist)
1621     {
1622       err = gpg_error (GPG_ERR_INV_SEXP);
1623       goto out;
1624     }
1625
1626   stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1627   if (! stream)
1628     {
1629       err = gpg_error_from_errno (errno);
1630       goto out;
1631     }
1632
1633   identifier_raw = gcry_sexp_nth_data (valuelist, 0, &identifier_n);
1634   if (! identifier_raw)
1635     {
1636       err = gpg_error (GPG_ERR_INV_SEXP);
1637       goto out;
1638     }
1639
1640   identifier = make_cstring (identifier_raw, identifier_n);
1641   if (! identifier)
1642     {
1643       err = gpg_error_from_errno (errno);
1644       goto out;
1645     }
1646
1647   err = ssh_key_type_lookup (NULL, identifier, &spec);
1648   if (err)
1649     goto out;
1650
1651   err = stream_write_cstring (stream, spec.ssh_identifier);
1652   if (err)
1653     goto out;
1654
1655   elems = spec.elems_signature;
1656   elems_n = strlen (elems);
1657
1658   mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1));
1659   if (! mpis)
1660     {
1661       err = gpg_error_from_errno (errno);
1662       goto out;
1663     }
1664   memset (mpis, 0, sizeof (*mpis) * (elems_n + 1));
1665
1666   for (i = 0; i < elems_n; i++)
1667     {
1668       sublist = gcry_sexp_find_token (valuelist, spec.elems_signature + i, 1);
1669       if (! sublist)
1670         {
1671           err = gpg_error (GPG_ERR_INV_SEXP);
1672           break;
1673         }
1674
1675       sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
1676       if (! sig_value)
1677         {
1678           err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
1679           break;
1680         }
1681       gcry_sexp_release (sublist);
1682       sublist = NULL;
1683
1684       mpis[i] = sig_value;
1685     }
1686   if (err)
1687     goto out;
1688
1689   err = (*sig_encoder) (stream, mpis);
1690   if (err)
1691     goto out;
1692
1693   sig_blob_n = es_ftell (stream);
1694   if (sig_blob_n == -1)
1695     {
1696       err = gpg_error_from_errno (errno);
1697       goto out;
1698     }
1699
1700   sig_blob = xtrymalloc (sig_blob_n);
1701   if (! sig_blob)
1702     {
1703       err = gpg_error_from_errno (errno);
1704       goto out;
1705     }
1706
1707   ret = es_fseek (stream, 0, SEEK_SET);
1708   if (ret)
1709     {
1710       err = gpg_error_from_errno (errno);
1711       goto out;
1712     }    
1713
1714   err = stream_read_data (stream, sig_blob, sig_blob_n);
1715   if (err)
1716     goto out;
1717   
1718   *sig = (char *) sig_blob;
1719   *sig_n = sig_blob_n;
1720   
1721  out:
1722
1723   if (err)
1724     xfree (sig_blob);
1725
1726   if (stream)
1727     es_fclose (stream);
1728   gcry_sexp_release (valuelist);
1729   gcry_sexp_release (signature_sexp);
1730   gcry_sexp_release (sublist);
1731   mpint_list_free (mpis);
1732   xfree ((void *) identifier);
1733
1734   return err;
1735 }
1736
1737 static gpg_error_t
1738 ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
1739 {
1740   gcry_sexp_t key;
1741   ssh_key_type_spec_t spec;
1742   unsigned char hash[MAX_DIGEST_LEN];
1743   unsigned int hash_n;
1744   unsigned char key_grip[20];
1745   unsigned char *key_blob;
1746   u32 key_blob_size;
1747   unsigned char *data;
1748   unsigned char *sig;
1749   size_t sig_n;
1750   u32 data_size;
1751   u32 flags;
1752   const void *p;
1753   gpg_error_t err;
1754   gpg_error_t ret_err;
1755
1756   key_blob = NULL;
1757   data = NULL;
1758   sig = NULL;
1759   key = NULL;
1760
1761   /* Receive key.  */
1762   
1763   err = stream_read_string (request, 0, &key_blob, &key_blob_size);
1764   if (err)
1765     goto out;
1766
1767   err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec);
1768   if (err)
1769     goto out;
1770
1771   /* Receive data to sign.  */
1772   err = stream_read_string (request, 0, &data, &data_size);
1773   if (err)
1774     goto out;
1775
1776   /* FIXME?  */
1777   err = stream_read_uint32 (request, &flags);
1778   if (err)
1779     goto out;
1780
1781   /* Hash data.  */
1782   hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
1783   if (! hash_n)
1784     {
1785       err = gpg_error (GPG_ERR_INTERNAL);
1786       goto out;
1787     }
1788   err = data_hash (data, data_size, GCRY_MD_SHA1, hash);
1789   if (err)
1790     goto out;
1791
1792   /* Calculate key grip.  */
1793   p = gcry_pk_get_keygrip (key, key_grip);
1794   if (! p)
1795     {
1796       err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
1797       goto out;
1798     }
1799
1800   /* Sign data.  */
1801
1802   ctrl->digest.algo = GCRY_MD_SHA1;
1803   memcpy (ctrl->digest.value, hash, hash_n);
1804   ctrl->digest.valuelen = hash_n;
1805   ctrl->digest.raw_value = ! (spec.flags & SPEC_FLAG_USE_PKCS1V2);
1806   ctrl->have_keygrip = 1;
1807   memcpy (ctrl->keygrip, key_grip, 20);
1808
1809   err = data_sign (ctrl, spec.signature_encoder, &sig, &sig_n);
1810   
1811  out:
1812
1813   /* Done.  */
1814
1815   if (! err)
1816     {
1817       ret_err = stream_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE);
1818       if (ret_err)
1819         goto leave;
1820       ret_err = stream_write_string (response, sig, sig_n);
1821       if (ret_err)
1822         goto leave;
1823     }
1824   else
1825     {
1826       ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
1827       if (ret_err)
1828         goto leave;
1829     }
1830   
1831  leave:
1832
1833   gcry_sexp_release (key);
1834   xfree (key_blob);
1835   xfree (data);
1836   xfree (sig);
1837
1838   return ret_err;
1839 }
1840
1841 static gpg_error_t
1842 get_passphrase (ctrl_t ctrl,
1843                 const char *description, size_t passphrase_n, char *passphrase)
1844 {
1845   struct pin_entry_info_s *pi;
1846   gpg_error_t err;
1847
1848   err = 0;
1849   pi = gcry_calloc_secure (1, sizeof (*pi) + passphrase_n + 1);
1850   if (! pi)
1851     {
1852       err = gpg_error (GPG_ERR_ENOMEM);
1853       goto out;
1854     }
1855
1856   pi->min_digits = 0;           /* We want a real passphrase.  */
1857   pi->max_digits = 8;
1858   pi->max_tries = 1;
1859   pi->failed_tries = 0;
1860   pi->check_cb = NULL;
1861   pi->check_cb_arg = NULL;
1862   pi->cb_errtext = NULL;
1863   pi->max_length = 100;
1864
1865   err = agent_askpin (ctrl, description, NULL, pi);
1866   if (err)
1867     goto out;
1868
1869   memcpy (passphrase, pi->pin, passphrase_n);
1870   passphrase[passphrase_n] = 0;
1871
1872  out:
1873
1874   xfree (pi);
1875   
1876   return err;
1877 }
1878
1879 static gpg_error_t
1880 ssh_key_extract_comment (gcry_sexp_t key, char **comment)
1881 {
1882   gcry_sexp_t comment_list;
1883   char *comment_new;
1884   const char *data;
1885   size_t data_n;
1886   gpg_error_t err;
1887
1888   comment_list = gcry_sexp_find_token (key, "comment", 0);
1889   if (! comment_list)
1890     {
1891       err = gpg_error (GPG_ERR_INV_SEXP);
1892       goto out;
1893     }
1894   
1895   data = gcry_sexp_nth_data (comment_list, 1, &data_n);
1896   if (! data)
1897     {
1898       err = gpg_error (GPG_ERR_INV_SEXP);
1899       goto out;
1900     }
1901
1902   comment_new = xtrymalloc (data_n + 1);
1903   if (! comment_new)
1904     {
1905       err = gpg_error_from_errno (errno);
1906       goto out;
1907     }
1908
1909   strncpy (comment_new, data, data_n);
1910   comment_new[data_n] = 0;
1911   *comment = comment_new;
1912   err = 0;
1913
1914  out:
1915
1916   gcry_sexp_release (comment_list);
1917
1918   return err;
1919 }
1920
1921 static gpg_error_t
1922 ssh_key_grip (gcry_sexp_t key, char *buffer)
1923 {
1924   gpg_error_t err;
1925   char *p;
1926
1927   /* FIXME: unsigned vs. signed.  */
1928   
1929   p = gcry_pk_get_keygrip (key, buffer);
1930   if (! p)
1931     err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
1932   else
1933     err = 0;
1934
1935   return err;
1936 }
1937
1938 static gpg_error_t
1939 ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase,
1940                    unsigned char **buffer, size_t *buffer_n)
1941 {
1942   unsigned char *buffer_new;
1943   unsigned int buffer_new_n;
1944   gpg_error_t err;
1945
1946   err = 0;
1947   buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0);
1948   buffer_new = xtrymalloc (buffer_new_n);
1949   /* FIXME: secmem? */
1950   if (! buffer_new)
1951     {
1952       err = gpg_error_from_errno (errno);
1953       goto out;
1954     }
1955   
1956   gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n);
1957   /* FIXME: guarantee?  */
1958
1959   err = agent_protect (buffer_new, passphrase, buffer, buffer_n);
1960
1961  out:
1962
1963   xfree (buffer_new);
1964
1965   return err;
1966 }
1967
1968 static gpg_error_t
1969 ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
1970 {
1971   unsigned char key_grip_raw[21];
1972   unsigned char *buffer;
1973   unsigned int buffer_n;
1974   char passphrase[100];
1975   char *description;
1976   char key_grip[41];
1977   char *comment;
1978   gpg_error_t err;
1979   unsigned int i;
1980   int ret;
1981
1982   description = NULL;
1983   comment = NULL;
1984   buffer = NULL;
1985
1986   err = ssh_key_grip (key, key_grip_raw);
1987   if (err)
1988     goto out;
1989
1990   key_grip_raw[sizeof (key_grip_raw) - 1] = 0;
1991   ret = agent_key_available (key_grip_raw);
1992   if (! ret)
1993     goto out;
1994
1995   err = ssh_key_extract_comment (key, &comment);
1996   if (err)
1997     goto out;
1998
1999   ret = asprintf (&description,
2000                   "Please provide the passphrase, which should be used "
2001                   "for protecting the received secret key `%s':",
2002                   comment ? comment : "");
2003   if (ret < 0)
2004     {
2005       err = gpg_err_code_from_errno (errno);
2006       goto out;
2007     }
2008
2009   err = get_passphrase (ctrl, description, sizeof (passphrase), passphrase);
2010   if (err)
2011     goto out;
2012
2013   err = ssh_key_to_buffer (key, passphrase, &buffer, &buffer_n);
2014   if (err)
2015     goto out;
2016
2017   err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0);
2018   if (err)
2019     goto out;
2020
2021   for (i = 0; i < 20; i++)
2022     sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]);
2023
2024   err = agent_put_cache (key_grip, passphrase, ttl);
2025   if (err)
2026     goto out;
2027
2028  out:
2029
2030   xfree (buffer);
2031   xfree (comment);
2032   free (description);
2033   /* FIXME: verify xfree vs free.  */
2034
2035   return err;
2036 }
2037
2038 static gpg_error_t
2039 ssh_identity_drop (gcry_sexp_t key)
2040 {
2041   unsigned char key_grip[21] = { 0 };
2042   gpg_error_t err;
2043
2044   err = ssh_key_grip (key, key_grip);
2045   if (err)
2046     goto out;
2047
2048   key_grip[sizeof (key_grip) - 1] = 0;
2049
2050   /* FIXME: What to do here - forgetting the passphrase or deleting
2051      the key from key cache?  */
2052
2053  out:
2054
2055   return err;
2056 }
2057
2058 static gpg_error_t
2059 ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
2060 {
2061   gpg_error_t ret_err;
2062   gpg_error_t err;
2063   gcry_sexp_t key;
2064   unsigned char b;
2065   int confirm;
2066   int ttl;
2067   
2068   confirm = 0;
2069   key = NULL;
2070   ttl = 0;
2071
2072   /* FIXME?  */
2073   err = ssh_receive_key (request, &key, 1, 1, NULL);
2074   if (err)
2075     goto out;
2076
2077   while (1)
2078     {
2079       err = stream_read_byte (request, &b);
2080       if (gpg_err_code (err) == GPG_ERR_EOF)
2081         {
2082           err = 0;
2083           break;
2084         }
2085
2086       switch (b)
2087         {
2088         case SSH_OPT_CONSTRAIN_LIFETIME:
2089           {
2090             u32 n = 0;
2091
2092             err = stream_read_uint32 (request, &n);
2093             if (! err)
2094               ttl = n;
2095             break;
2096           }
2097
2098         case SSH_OPT_CONSTRAIN_CONFIRM:
2099           {
2100             confirm = 1;
2101             break;
2102           }
2103
2104         default:
2105           /* FIXME: log/bad?  */
2106           break;
2107         }
2108     }
2109   if (err)
2110     goto out;
2111
2112   /* FIXME: are constraints used correctly?  */
2113
2114   err = ssh_identity_register (ctrl, key, ttl);
2115
2116  out:
2117
2118   gcry_sexp_release (key);
2119
2120   ret_err = stream_write_byte (response,
2121                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2122
2123   return ret_err;
2124 }
2125
2126 static gpg_error_t
2127 ssh_handler_remove_identity (ctrl_t ctrl, estream_t request,
2128                              estream_t response)
2129 {
2130   unsigned char *key_blob;
2131   u32 key_blob_size;
2132   gcry_sexp_t key;
2133   gpg_error_t ret_err;
2134   gpg_error_t err;
2135
2136   /* Receive key.  */
2137
2138   key_blob = NULL;
2139   key = NULL;
2140   
2141   err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2142   if (err)
2143     goto out;
2144
2145   err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL);
2146   if (err)
2147     goto out;
2148   
2149   err = ssh_identity_drop (key);
2150
2151  out:
2152
2153   xfree (key_blob);
2154   gcry_sexp_release (key);
2155
2156   ret_err = stream_write_byte (response,
2157                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2158
2159   return ret_err;
2160 }
2161
2162 static gpg_error_t
2163 ssh_identities_remove_all (void)
2164 {
2165   gpg_error_t err;
2166
2167   err = 0;
2168
2169   /* FIXME: shall we remove _all_ cache entries or only those
2170      registered through the ssh emulation?  */
2171   
2172   return err;
2173 }
2174
2175 static gpg_error_t
2176 ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request,
2177                                    estream_t response)
2178 {
2179   gpg_error_t ret_err;
2180   gpg_error_t err;
2181   
2182   err = ssh_identities_remove_all ();
2183   ret_err = stream_write_byte (response,
2184                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2185
2186   return ret_err;
2187 }
2188
2189 static gpg_error_t
2190 ssh_lock (void)
2191 {
2192   gpg_error_t err;
2193
2194   /* FIXME */
2195   log_error (_("lock command is not implemented\n"));
2196   err = 0;
2197
2198   return err;
2199 }
2200
2201 static gpg_error_t
2202 ssh_unlock (void)
2203 {
2204   gpg_error_t err;
2205
2206   log_error (_("unlock command is not implemented\n"));
2207   err = 0;
2208
2209   return err;
2210 }
2211
2212 static gpg_error_t
2213 ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response)
2214 {
2215   gpg_error_t ret_err;
2216   gpg_error_t err;
2217   
2218   err = ssh_lock ();
2219   ret_err = stream_write_byte (response,
2220                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2221
2222   return ret_err;
2223 }
2224
2225 static gpg_error_t
2226 ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
2227 {
2228   gpg_error_t ret_err;
2229   gpg_error_t err;
2230   
2231   err = ssh_unlock ();
2232   ret_err = stream_write_byte (response,
2233                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2234
2235   return ret_err;
2236 }
2237
2238 \f
2239
2240 static int
2241 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
2242 {
2243   estream_t response;
2244   estream_t request;
2245   unsigned char request_type;
2246   gpg_error_t err;
2247   unsigned int i;
2248   int send_err;
2249   int ret;
2250   unsigned char *request_data;
2251   u32 request_data_size;
2252   u32 response_size;
2253
2254   request_data = NULL;
2255   response = NULL;
2256   request = NULL;
2257   send_err = 0;
2258
2259   /* Create memory streams for request/response data.  The entire
2260      request will be stored in secure memory, since it might contain
2261      secret key material.  The response does not have to be stored in
2262      secure memory, since we never give out secret keys. 
2263
2264      FIXME: This is a pretty good DoS.  We only have a limited amount
2265      of secure memory, we can't trhow hin everything we get from a
2266      client -wk */
2267       
2268   /* Retrieve request.  */
2269   err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
2270   if (err)
2271     goto out;
2272
2273   if (opt.verbose) /* FIXME: using log_debug is not good with
2274                       verbose. log_debug should only be used in
2275                       debugging mode or in sitattions which are
2276                       unexpected. */
2277     log_debug ("received request of length: %u\n",
2278                request_data_size);
2279
2280   request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
2281   if (! request)
2282     {
2283       err = gpg_error_from_errno (errno);
2284       goto out;
2285     }
2286   ret = es_setvbuf (request, NULL, _IONBF, 0);
2287   if (ret)
2288     {
2289       err = gpg_error_from_errno (errno);
2290       goto out;
2291     }
2292   err = stream_write_data (request, request_data, request_data_size);
2293   if (err)
2294     goto out;
2295   es_rewind (request);
2296
2297   response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
2298   if (! response)
2299     {
2300       err = gpg_error_from_errno (errno);
2301       goto out;
2302     }
2303
2304   err = stream_read_byte (request, &request_type);
2305   if (err)
2306     {
2307       send_err = 1;
2308       goto out;
2309     }
2310
2311   for (i = 0; i < DIM (request_specs); i++)
2312     if (request_specs[i].type == request_type)
2313       break;
2314   if (i == DIM (request_specs))
2315     {
2316       log_debug ("request %u is not supported\n",
2317                  request_type);
2318       send_err = 1;
2319       goto out;
2320     }
2321
2322   if (opt.verbose)
2323     log_debug ("executing request handler: %s (%u)\n",
2324                request_specs[i].identifier, request_specs[i].type);
2325
2326   err = (*request_specs[i].handler) (ctrl, request, response);
2327   if (err)
2328     {
2329       send_err = 1;
2330       goto out;
2331     }
2332
2333   response_size = es_ftell (response);
2334   err = es_fseek (response, 0, SEEK_SET);
2335   if (err)
2336     {
2337       send_err = 1;
2338       goto out;
2339     }
2340
2341   err = stream_write_uint32 (stream_sock, response_size);
2342   if (err)
2343     {
2344       send_err = 1;
2345       goto out;
2346     }
2347
2348   err = stream_copy (stream_sock, response);
2349   if (err)
2350     goto out;
2351
2352   err = es_fflush (stream_sock);
2353   if (err)
2354     goto out;
2355
2356  out:
2357
2358   if (err && es_feof (stream_sock))
2359     log_error ("error occured while processing request: %s\n",
2360                gpg_strerror (err));
2361
2362   if (send_err)
2363     {
2364       err = stream_write_uint32 (stream_sock, 1);
2365       if (err)
2366         goto leave;
2367       err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE);
2368       if (err)
2369         goto leave;
2370     }
2371
2372  leave:
2373
2374   if (request)
2375     es_fclose (request);
2376   if (response)
2377     es_fclose (response);
2378   xfree (request_data);         /* FIXME?  */
2379
2380   return !! err;
2381 }
2382
2383 void
2384 start_command_handler_ssh (int sock_client)
2385 {
2386   struct server_control_s ctrl;
2387   estream_t stream_sock;
2388   gpg_error_t err;
2389   int bad;
2390   int ret;
2391
2392   /* Setup control structure.  */
2393
2394   memset (&ctrl, 0, sizeof (ctrl));
2395   agent_init_default_ctrl (&ctrl);
2396   ctrl.connection_fd = sock_client;
2397
2398   /* Create stream from socket.  */
2399   stream_sock = es_fdopen (sock_client, "r+");
2400   if (!stream_sock)
2401     {
2402       err = gpg_error_from_errno (errno);
2403       log_error (_("failed to create stream from socket: %s\n"),
2404                  gpg_strerror (err));
2405       goto out;
2406     }
2407   /* We have to disable the estream buffering, because the estream
2408      core doesn't know about secure memory.  */
2409   ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
2410   if (ret)
2411     {
2412       err = gpg_error_from_errno (errno);
2413       log_error (_("failed to disable buffering "
2414                    "on socket stream: %s\n"), gpg_strerror (err));
2415       goto out;
2416     }
2417
2418   while (1)
2419     {
2420       bad = ssh_request_process (&ctrl, stream_sock);
2421       if (bad)
2422         break;
2423     };
2424
2425  out:
2426
2427   if (stream_sock)
2428     es_fclose (stream_sock);
2429
2430   free (ctrl.display);
2431   free (ctrl.ttyname);
2432   free (ctrl.ttytype);
2433   free (ctrl.lc_ctype);
2434   free (ctrl.lc_messages);
2435 }