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