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