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