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