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