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