* call-scd.c (unescape_status_string): New. Actual a copy of
[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 
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 /* Write the public key KEY_PUBLIC to STREAM in SSH key format. */
1408 static gpg_error_t
1409 ssh_send_key_public (estream_t stream, gcry_sexp_t key_public)
1410 {
1411   ssh_key_type_spec_t spec;
1412   gcry_mpi_t *mpi_list;
1413   const char *key_type;
1414   const char *comment;
1415   unsigned char *blob;
1416   size_t blob_n;
1417   gpg_error_t err;
1418
1419   key_type = NULL;
1420   mpi_list = NULL;
1421   comment = NULL;
1422   blob = NULL;
1423
1424   err = sexp_extract_identifier (key_public, &key_type);
1425   if (err)
1426     goto out;
1427
1428   err = ssh_key_type_lookup (NULL, key_type, &spec);
1429   if (err)
1430     goto out;
1431
1432   err = sexp_key_extract (key_public, spec, NULL, &mpi_list, &comment);
1433   if (err)
1434     goto out;
1435
1436   err = ssh_convert_key_to_blob (&blob, &blob_n,
1437                                  spec.ssh_identifier, mpi_list);
1438   if (err)
1439     goto out;
1440   
1441   err = stream_write_string (stream, blob, blob_n);
1442   if (err)
1443     goto out;
1444
1445   err = stream_write_cstring (stream, comment);
1446   
1447  out:
1448
1449   mpint_list_free (mpi_list);
1450   xfree ((void *) key_type);
1451   xfree ((void *) comment);
1452   xfree (blob);
1453
1454   return err;
1455 }
1456
1457 static gpg_error_t
1458 ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size,
1459                                gcry_sexp_t *key_public,
1460                                ssh_key_type_spec_t *key_spec)
1461 {
1462   estream_t blob_stream;
1463   gpg_error_t err;
1464
1465   err = 0;
1466   
1467   blob_stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1468   if (! blob_stream)
1469     {
1470       err = gpg_error_from_errno (errno);
1471       goto out;
1472     }
1473
1474   err = stream_write_data (blob_stream, blob, blob_size);
1475   if (err)
1476     goto out;
1477
1478   err = es_fseek (blob_stream, 0, SEEK_SET);
1479   if (err)
1480     goto out;
1481
1482   err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec);
1483
1484  out:
1485
1486   if (blob_stream)
1487     es_fclose (blob_stream);
1488
1489   return err;
1490 }
1491
1492 \f
1493
1494 static gpg_error_t
1495 key_secret_to_public (gcry_sexp_t *key_public,
1496                       ssh_key_type_spec_t spec, gcry_sexp_t key_secret)
1497 {
1498   const char *comment;
1499   gcry_mpi_t *mpis;
1500   gpg_error_t err;
1501   int is_secret;
1502
1503   comment = NULL;
1504   mpis = NULL;
1505
1506   err = sexp_key_extract (key_secret, spec, &is_secret, &mpis, &comment);
1507   if (err)
1508     goto out;
1509
1510   err = sexp_key_construct (key_public, spec, 0, mpis, comment);
1511
1512  out:
1513
1514   mpint_list_free (mpis);
1515   xfree ((char *) comment);
1516
1517   return err;
1518 }
1519
1520
1521 /* Chec whether a smartcard is available and whether it has a usable
1522    key.  Store a copy of that key at R_PK and return 0.  If no key is
1523    available store NULL at R_PK and return an error code.  */
1524 static gpg_error_t
1525 card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk)
1526 {
1527   gpg_error_t err;
1528   char *appname;
1529   unsigned char *sbuf;
1530   size_t sbuflen;
1531   gcry_sexp_t pk;
1532
1533   *r_pk = NULL;
1534
1535   /* First see whether a card is available and whether the application
1536      is supported.  */
1537   err = agent_card_getattr (ctrl, "APPTYPE", &appname);
1538   if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED )
1539     {
1540       /* Ask for the serial number to reset the card.  */
1541       err = agent_card_serialno (ctrl, &appname);
1542       if (err)
1543         {
1544           if (opt.verbose)
1545             log_info (_("can't get serial number of card: %s\n"),
1546                       gpg_strerror (err));
1547           return err;
1548         }
1549       log_info (_("detected card with S/N: %s\n"), appname);
1550       xfree (appname);
1551       err = agent_card_getattr (ctrl, "APPTYPE", &appname);
1552     }
1553   if (err)
1554     {
1555       log_error (_("error getting application type of card: %s\n"),
1556                  gpg_strerror (err));
1557       return err;
1558     }
1559   if (strcmp (appname, "OPENPGP"))
1560     {
1561       log_info (_("card application `%s' is not supported\n"), appname);
1562       xfree (appname);
1563       return gpg_error (GPG_ERR_NOT_SUPPORTED);
1564     }
1565   xfree (appname);
1566   appname = NULL;
1567
1568   /* Read the public key.  */
1569   err = agent_card_readkey (ctrl, "OPENPGP.3", &sbuf);
1570   if (err)
1571     {
1572       if (opt.verbose)
1573         log_info (_("no suitable card key found: %s\n"), gpg_strerror (err));
1574       return err;
1575     }
1576
1577   sbuflen = gcry_sexp_canon_len (sbuf, 0, NULL, NULL);
1578   err = gcry_sexp_sscan (&pk, NULL, sbuf, sbuflen);
1579   xfree (sbuf);
1580   if (err)
1581     {
1582       log_error ("failed to build S-Exp from received card key: %s\n",
1583                  gpg_strerror (err));
1584       return err;
1585     }
1586   
1587   *r_pk = pk;
1588   return 0;
1589 }
1590
1591
1592
1593 /*
1594   Request handler.  
1595  */
1596
1597 static gpg_error_t
1598 ssh_handler_request_identities (ctrl_t ctrl,
1599                                 estream_t request, estream_t response)
1600 {
1601   const char *key_type;
1602   ssh_key_type_spec_t spec;
1603   struct dirent *dir_entry;
1604   char *key_directory;
1605   size_t key_directory_n;
1606   char *key_path;
1607   unsigned char *buffer;
1608   size_t buffer_n;
1609   u32 key_counter;
1610   estream_t key_blobs;
1611   gcry_sexp_t key_secret;
1612   gcry_sexp_t key_public;
1613   DIR *dir;
1614   gpg_error_t err;
1615   gpg_error_t ret_err;
1616   int ret;
1617   FILE *ctrl_fp = NULL;
1618
1619   /* Prepare buffer stream.  */
1620
1621   key_directory = NULL;
1622   key_secret = NULL;
1623   key_public = NULL;
1624   key_type = NULL;
1625   key_path = NULL;
1626   key_counter = 0;
1627   buffer = NULL;
1628   dir = NULL;
1629   err = 0;
1630
1631   key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1632   if (! key_blobs)
1633     {
1634       err = gpg_error_from_errno (errno);
1635       goto out;
1636     }
1637
1638   /* Open key directory.  */
1639   key_directory = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
1640   if (! key_directory)
1641     {
1642       err = gpg_err_code_from_errno (errno);
1643       goto out;
1644     }
1645   key_directory_n = strlen (key_directory);
1646   
1647   key_path = xtrymalloc (key_directory_n + 46);
1648   if (! key_path)
1649     {
1650       err = gpg_err_code_from_errno (errno);
1651       goto out;
1652     }
1653
1654   sprintf (key_path, "%s/", key_directory);
1655   sprintf (key_path + key_directory_n + 41, ".key");
1656
1657   dir = opendir (key_directory);
1658   if (! dir)
1659     {
1660       err = gpg_err_code_from_errno (errno);
1661       goto out;
1662     }
1663
1664
1665
1666   /* First check whether a key is currently available in the card
1667      reader - this should be allowed even without being listed in
1668      sshcontrol.txt. */
1669
1670   if (!card_key_available (ctrl, &key_public))
1671     {
1672       err = ssh_send_key_public (key_blobs, key_public);
1673       gcry_sexp_release (key_public);
1674       key_public = NULL;
1675       if (err)
1676         goto out;
1677       
1678       key_counter++;
1679     }
1680
1681
1682   /* Then look at all the registered an allowed keys. */
1683
1684
1685   /* Fixme: We should better iterate over the control file and check
1686      whether the key file is there.  This is better in resepct to
1687      performance if tehre are a lot of key sin our key storage. */
1688   /* FIXME: make sure that buffer gets deallocated properly.  */
1689   err = open_control_file (&ctrl_fp, 0);
1690   if (err)
1691     goto out;
1692
1693   while ( (dir_entry = readdir (dir)) )
1694     {
1695       if ((strlen (dir_entry->d_name) == 44)
1696           && (! strncmp (dir_entry->d_name + 40, ".key", 4)))
1697         {
1698           char hexgrip[41];
1699           int disabled;
1700
1701           /* We do only want to return keys listed in our control
1702              file. */
1703           strncpy (hexgrip, dir_entry->d_name, 40);
1704           hexgrip[40] = 0;
1705           if ( strlen (hexgrip) != 40 )
1706             continue;
1707           if (search_control_file (ctrl_fp, hexgrip, &disabled)
1708               || disabled)
1709             continue;
1710
1711           strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40);
1712
1713           /* Read file content.  */
1714           err = file_to_buffer (key_path, &buffer, &buffer_n);
1715           if (err)
1716             goto out;
1717               
1718           err = gcry_sexp_sscan (&key_secret, NULL, buffer, buffer_n);
1719           if (err)
1720             goto out;
1721
1722           xfree (buffer);
1723           buffer = NULL;
1724
1725           err = sexp_extract_identifier (key_secret, &key_type);
1726           if (err)
1727             goto out;
1728
1729           err = ssh_key_type_lookup (NULL, key_type, &spec);
1730           if (err)
1731             goto out;
1732
1733           xfree ((void *) key_type);
1734           key_type = NULL;
1735
1736           err = key_secret_to_public (&key_public, spec, key_secret);
1737           if (err)
1738             goto out;
1739
1740           gcry_sexp_release (key_secret);
1741           key_secret = NULL;
1742               
1743           err = ssh_send_key_public (key_blobs, key_public);
1744           if (err)
1745             goto out;
1746
1747           gcry_sexp_release (key_public);
1748           key_public = NULL;
1749
1750           key_counter++;
1751         }
1752     }
1753   
1754   ret = es_fseek (key_blobs, 0, SEEK_SET);
1755   if (ret)
1756     {
1757       err = gpg_error_from_errno (errno);
1758       goto out;
1759     }
1760
1761  out:
1762
1763   /* Send response.  */
1764
1765   gcry_sexp_release (key_secret);
1766   gcry_sexp_release (key_public);
1767
1768   if (! err)
1769     {
1770       ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER);
1771       if (ret_err)
1772         goto leave;
1773       ret_err = stream_write_uint32 (response, key_counter);
1774       if (ret_err)
1775         goto leave;
1776       ret_err = stream_copy (response, key_blobs);
1777       if (ret_err)
1778         goto leave;
1779     }
1780   else
1781     {
1782       ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
1783       goto leave;
1784     };
1785
1786  leave:
1787
1788   if (key_blobs)
1789     es_fclose (key_blobs);
1790   if (dir)
1791     closedir (dir);
1792
1793   if (ctrl_fp)
1794     fclose (ctrl_fp);
1795
1796   free (key_directory);
1797   xfree (key_path);
1798   xfree (buffer);
1799   /* FIXME: Ist is for sure is a Bad Thing to use the const qualifier
1800      and later cast it away.  You can't do that!!! */
1801   xfree ((void *) key_type);            /* FIXME? */
1802
1803   return ret_err;
1804 }
1805
1806 static gpg_error_t
1807 data_hash (unsigned char *data, size_t data_n,
1808            int md_algorithm, unsigned char *hash)
1809 {
1810   gcry_md_hash_buffer (md_algorithm, hash, data, data_n);
1811
1812   return 0;
1813 }
1814
1815
1816 static gpg_error_t
1817 data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder,
1818            unsigned char **sig, size_t *sig_n)
1819 {
1820   gpg_error_t err;
1821   gcry_sexp_t signature_sexp;
1822   estream_t stream;
1823   gcry_sexp_t valuelist;
1824   gcry_sexp_t sublist;
1825   gcry_mpi_t sig_value;
1826   unsigned char *sig_blob;
1827   size_t sig_blob_n;
1828   const char *identifier;
1829   const char *identifier_raw;
1830   size_t identifier_n;
1831   ssh_key_type_spec_t spec;
1832   int ret;
1833   unsigned int i;
1834   const char *elems;
1835   size_t elems_n;
1836   gcry_mpi_t *mpis;
1837
1838   signature_sexp = NULL;
1839   identifier = NULL;
1840   valuelist = NULL;
1841   sublist = NULL;
1842   sig_blob = NULL;
1843   sig_blob_n = 0;
1844   stream = NULL;
1845   sig_value = NULL;
1846   mpis = NULL;
1847
1848   err = agent_pksign_do (ctrl,
1849                          _("Please provide the passphrase "
1850                            "for the ssh key `%c':"), &signature_sexp, 0);
1851   if (err)
1852     goto out;
1853
1854   valuelist = gcry_sexp_nth (signature_sexp, 1);
1855   if (! valuelist)
1856     {
1857       err = gpg_error (GPG_ERR_INV_SEXP);
1858       goto out;
1859     }
1860
1861   stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1862   if (! stream)
1863     {
1864       err = gpg_error_from_errno (errno);
1865       goto out;
1866     }
1867
1868   identifier_raw = gcry_sexp_nth_data (valuelist, 0, &identifier_n);
1869   if (! identifier_raw)
1870     {
1871       err = gpg_error (GPG_ERR_INV_SEXP);
1872       goto out;
1873     }
1874
1875   identifier = make_cstring (identifier_raw, identifier_n);
1876   if (! identifier)
1877     {
1878       err = gpg_error_from_errno (errno);
1879       goto out;
1880     }
1881
1882   err = ssh_key_type_lookup (NULL, identifier, &spec);
1883   if (err)
1884     goto out;
1885
1886   err = stream_write_cstring (stream, spec.ssh_identifier);
1887   if (err)
1888     goto out;
1889
1890   elems = spec.elems_signature;
1891   elems_n = strlen (elems);
1892
1893   mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1));
1894   if (! mpis)
1895     {
1896       err = gpg_error_from_errno (errno);
1897       goto out;
1898     }
1899   memset (mpis, 0, sizeof (*mpis) * (elems_n + 1));
1900
1901   for (i = 0; i < elems_n; i++)
1902     {
1903       sublist = gcry_sexp_find_token (valuelist, spec.elems_signature + i, 1);
1904       if (! sublist)
1905         {
1906           err = gpg_error (GPG_ERR_INV_SEXP);
1907           break;
1908         }
1909
1910       sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
1911       if (! sig_value)
1912         {
1913           err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
1914           break;
1915         }
1916       gcry_sexp_release (sublist);
1917       sublist = NULL;
1918
1919       mpis[i] = sig_value;
1920     }
1921   if (err)
1922     goto out;
1923
1924   err = (*sig_encoder) (stream, mpis);
1925   if (err)
1926     goto out;
1927
1928   sig_blob_n = es_ftell (stream);
1929   if (sig_blob_n == -1)
1930     {
1931       err = gpg_error_from_errno (errno);
1932       goto out;
1933     }
1934
1935   sig_blob = xtrymalloc (sig_blob_n);
1936   if (! sig_blob)
1937     {
1938       err = gpg_error_from_errno (errno);
1939       goto out;
1940     }
1941
1942   ret = es_fseek (stream, 0, SEEK_SET);
1943   if (ret)
1944     {
1945       err = gpg_error_from_errno (errno);
1946       goto out;
1947     }    
1948
1949   err = stream_read_data (stream, sig_blob, sig_blob_n);
1950   if (err)
1951     goto out;
1952   
1953   *sig = (char *) sig_blob;
1954   *sig_n = sig_blob_n;
1955   
1956  out:
1957
1958   if (err)
1959     xfree (sig_blob);
1960
1961   if (stream)
1962     es_fclose (stream);
1963   gcry_sexp_release (valuelist);
1964   gcry_sexp_release (signature_sexp);
1965   gcry_sexp_release (sublist);
1966   mpint_list_free (mpis);
1967   xfree ((void *) identifier);
1968
1969   return err;
1970 }
1971
1972 static gpg_error_t
1973 ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
1974 {
1975   gcry_sexp_t key;
1976   ssh_key_type_spec_t spec;
1977   unsigned char hash[MAX_DIGEST_LEN];
1978   unsigned int hash_n;
1979   unsigned char key_grip[20];
1980   unsigned char *key_blob;
1981   u32 key_blob_size;
1982   unsigned char *data;
1983   unsigned char *sig;
1984   size_t sig_n;
1985   u32 data_size;
1986   u32 flags;
1987   const void *p;
1988   gpg_error_t err;
1989   gpg_error_t ret_err;
1990
1991   key_blob = NULL;
1992   data = NULL;
1993   sig = NULL;
1994   key = NULL;
1995
1996   /* Receive key.  */
1997   
1998   err = stream_read_string (request, 0, &key_blob, &key_blob_size);
1999   if (err)
2000     goto out;
2001
2002   err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec);
2003   if (err)
2004     goto out;
2005
2006   /* Receive data to sign.  */
2007   err = stream_read_string (request, 0, &data, &data_size);
2008   if (err)
2009     goto out;
2010
2011   /* FIXME?  */
2012   err = stream_read_uint32 (request, &flags);
2013   if (err)
2014     goto out;
2015
2016   /* Hash data.  */
2017   hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
2018   if (! hash_n)
2019     {
2020       err = gpg_error (GPG_ERR_INTERNAL);
2021       goto out;
2022     }
2023   err = data_hash (data, data_size, GCRY_MD_SHA1, hash);
2024   if (err)
2025     goto out;
2026
2027   /* Calculate key grip.  */
2028   p = gcry_pk_get_keygrip (key, key_grip);
2029   if (! p)
2030     {
2031       err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
2032       goto out;
2033     }
2034
2035   /* Sign data.  */
2036
2037   ctrl->digest.algo = GCRY_MD_SHA1;
2038   memcpy (ctrl->digest.value, hash, hash_n);
2039   ctrl->digest.valuelen = hash_n;
2040   ctrl->digest.raw_value = ! (spec.flags & SPEC_FLAG_USE_PKCS1V2);
2041   ctrl->have_keygrip = 1;
2042   memcpy (ctrl->keygrip, key_grip, 20);
2043
2044   err = data_sign (ctrl, spec.signature_encoder, &sig, &sig_n);
2045   
2046  out:
2047
2048   /* Done.  */
2049
2050   if (! err)
2051     {
2052       ret_err = stream_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE);
2053       if (ret_err)
2054         goto leave;
2055       ret_err = stream_write_string (response, sig, sig_n);
2056       if (ret_err)
2057         goto leave;
2058     }
2059   else
2060     {
2061       ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2062       if (ret_err)
2063         goto leave;
2064     }
2065   
2066  leave:
2067
2068   gcry_sexp_release (key);
2069   xfree (key_blob);
2070   xfree (data);
2071   xfree (sig);
2072
2073   return ret_err;
2074 }
2075
2076
2077 static gpg_error_t
2078 ssh_key_extract_comment (gcry_sexp_t key, char **comment)
2079 {
2080   gcry_sexp_t comment_list;
2081   char *comment_new;
2082   const char *data;
2083   size_t data_n;
2084   gpg_error_t err;
2085
2086   comment_list = gcry_sexp_find_token (key, "comment", 0);
2087   if (! comment_list)
2088     {
2089       err = gpg_error (GPG_ERR_INV_SEXP);
2090       goto out;
2091     }
2092   
2093   data = gcry_sexp_nth_data (comment_list, 1, &data_n);
2094   if (! data)
2095     {
2096       err = gpg_error (GPG_ERR_INV_SEXP);
2097       goto out;
2098     }
2099
2100   comment_new = xtrymalloc (data_n + 1);
2101   if (! comment_new)
2102     {
2103       err = gpg_error_from_errno (errno);
2104       goto out;
2105     }
2106
2107   strncpy (comment_new, data, data_n);
2108   comment_new[data_n] = 0;
2109   *comment = comment_new;
2110   err = 0;
2111
2112  out:
2113
2114   gcry_sexp_release (comment_list);
2115
2116   return err;
2117 }
2118
2119 static gpg_error_t
2120 ssh_key_grip (gcry_sexp_t key, char *buffer)
2121 {
2122   gpg_error_t err;
2123   char *p;
2124
2125   /* FIXME: unsigned vs. signed.  */
2126   
2127   p = gcry_pk_get_keygrip (key, buffer);
2128   if (! p)
2129     err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
2130   else
2131     err = 0;
2132
2133   return err;
2134 }
2135
2136 static gpg_error_t
2137 ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase,
2138                    unsigned char **buffer, size_t *buffer_n)
2139 {
2140   unsigned char *buffer_new;
2141   unsigned int buffer_new_n;
2142   gpg_error_t err;
2143
2144   err = 0;
2145   buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0);
2146   buffer_new = xtrymalloc (buffer_new_n);
2147   /* FIXME: secmem? */
2148   if (! buffer_new)
2149     {
2150       err = gpg_error_from_errno (errno);
2151       goto out;
2152     }
2153   
2154   gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n);
2155   /* FIXME: guarantee?  */
2156
2157   err = agent_protect (buffer_new, passphrase, buffer, buffer_n);
2158
2159  out:
2160
2161   xfree (buffer_new);
2162
2163   return err;
2164 }
2165
2166
2167
2168 /* Store the ssh KEY into our local key storage and protect him after
2169    asking for a passphrase.  Cache that passphrase.  TTL is the
2170    maximum caching time for that key.  If the key already exists in
2171    our key storage, don't do anything.  When entering a new key also
2172    add an entry to the sshcontrol file.  */
2173 static gpg_error_t
2174 ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
2175 {
2176   gpg_error_t err;
2177   unsigned char key_grip_raw[21];
2178   char key_grip[41];
2179   unsigned char *buffer = NULL;
2180   unsigned int buffer_n;
2181   char *description = NULL;
2182   char *comment = NULL;
2183   unsigned int i;
2184   struct pin_entry_info_s *pi = NULL;
2185
2186   err = ssh_key_grip (key, key_grip_raw);
2187   if (err)
2188     goto out;
2189
2190   key_grip_raw[sizeof (key_grip_raw) - 1] = 0; /* FIXME:  Why?? */
2191
2192   /* Check whether the key is alread in our key storage.  Don't do
2193      anything then.  */
2194   if ( !agent_key_available (key_grip_raw) )
2195     goto out; /* Yes, key is available.  */
2196
2197   
2198   err = ssh_key_extract_comment (key, &comment);
2199   if (err)
2200     goto out;
2201
2202   if ( asprintf (&description,
2203                  _("Please enter a passphrase to protect%%0A"
2204                    "the received secret key%%0A"
2205                    "   %s%%0A"
2206                    "within gpg-agent's key storage"),
2207                  comment ? comment : "?") < 0)
2208     {
2209       err = gpg_error_from_errno (errno);
2210       goto out;
2211     }
2212
2213
2214   pi = gcry_calloc_secure (1, sizeof (*pi) + 100 + 1);
2215   if (!pi)
2216     {
2217       err = gpg_error_from_errno (errno);
2218       goto out;
2219     }
2220   pi->max_length = 100;
2221   pi->max_tries = 1;
2222   err = agent_askpin (ctrl, description, NULL, pi);
2223   if (err)
2224     goto out;
2225
2226   err = ssh_key_to_buffer (key, pi->pin, &buffer, &buffer_n);
2227   if (err)
2228     goto out;
2229
2230   /* Store this key to our key storage.  */
2231   err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0);
2232   if (err)
2233     goto out;
2234
2235   /* Cache this passphrase. */
2236   for (i = 0; i < 20; i++)
2237     sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]);
2238
2239   err = agent_put_cache (key_grip, pi->pin, ttl);
2240   if (err)
2241     goto out;
2242
2243   /* And add an entry to the sshcontrol file.  */
2244   err = add_control_entry (ctrl, key_grip, ttl);
2245
2246
2247  out:
2248   if (pi && pi->max_length)
2249     wipememory (pi->pin, pi->max_length);
2250   xfree (pi);
2251   xfree (buffer);
2252   xfree (comment);
2253   free (description); /* (asprintf allocated, thus regular free.)  */
2254
2255   return err;
2256 }
2257
2258
2259
2260 static gpg_error_t
2261 ssh_identity_drop (gcry_sexp_t key)
2262 {
2263   unsigned char key_grip[21] = { 0 };
2264   gpg_error_t err;
2265
2266   err = ssh_key_grip (key, key_grip);
2267   if (err)
2268     goto out;
2269
2270   key_grip[sizeof (key_grip) - 1] = 0;
2271
2272   /* FIXME: What to do here - forgetting the passphrase or deleting
2273      the key from key cache?  */
2274
2275  out:
2276
2277   return err;
2278 }
2279
2280 static gpg_error_t
2281 ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
2282 {
2283   gpg_error_t ret_err;
2284   gpg_error_t err;
2285   gcry_sexp_t key;
2286   unsigned char b;
2287   int confirm;
2288   int ttl;
2289   
2290   confirm = 0;
2291   key = NULL;
2292   ttl = 0;
2293
2294   /* FIXME?  */
2295   err = ssh_receive_key (request, &key, 1, 1, NULL);
2296   if (err)
2297     goto out;
2298
2299   while (1)
2300     {
2301       err = stream_read_byte (request, &b);
2302       if (gpg_err_code (err) == GPG_ERR_EOF)
2303         {
2304           err = 0;
2305           break;
2306         }
2307
2308       switch (b)
2309         {
2310         case SSH_OPT_CONSTRAIN_LIFETIME:
2311           {
2312             u32 n = 0;
2313
2314             err = stream_read_uint32 (request, &n);
2315             if (! err)
2316               ttl = n;
2317             break;
2318           }
2319
2320         case SSH_OPT_CONSTRAIN_CONFIRM:
2321           {
2322             confirm = 1;
2323             break;
2324           }
2325
2326         default:
2327           /* FIXME: log/bad?  */
2328           break;
2329         }
2330     }
2331   if (err)
2332     goto out;
2333
2334   /* FIXME: are constraints used correctly?  */
2335
2336   err = ssh_identity_register (ctrl, key, ttl);
2337
2338  out:
2339
2340   gcry_sexp_release (key);
2341
2342   ret_err = stream_write_byte (response,
2343                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2344
2345   return ret_err;
2346 }
2347
2348 static gpg_error_t
2349 ssh_handler_remove_identity (ctrl_t ctrl, estream_t request,
2350                              estream_t response)
2351 {
2352   unsigned char *key_blob;
2353   u32 key_blob_size;
2354   gcry_sexp_t key;
2355   gpg_error_t ret_err;
2356   gpg_error_t err;
2357
2358   /* Receive key.  */
2359
2360   key_blob = NULL;
2361   key = NULL;
2362   
2363   err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2364   if (err)
2365     goto out;
2366
2367   err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL);
2368   if (err)
2369     goto out;
2370   
2371   err = ssh_identity_drop (key);
2372
2373  out:
2374
2375   xfree (key_blob);
2376   gcry_sexp_release (key);
2377
2378   ret_err = stream_write_byte (response,
2379                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2380
2381   return ret_err;
2382 }
2383
2384 static gpg_error_t
2385 ssh_identities_remove_all (void)
2386 {
2387   gpg_error_t err;
2388
2389   err = 0;
2390
2391   /* FIXME: shall we remove _all_ cache entries or only those
2392      registered through the ssh emulation?  */
2393   
2394   return err;
2395 }
2396
2397 static gpg_error_t
2398 ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request,
2399                                    estream_t response)
2400 {
2401   gpg_error_t ret_err;
2402   gpg_error_t err;
2403   
2404   err = ssh_identities_remove_all ();
2405   ret_err = stream_write_byte (response,
2406                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2407
2408   return ret_err;
2409 }
2410
2411 static gpg_error_t
2412 ssh_lock (void)
2413 {
2414   gpg_error_t err;
2415
2416   /* FIXME */
2417   log_error ("ssh-agent's lock command is not implemented\n");
2418   err = 0;
2419
2420   return err;
2421 }
2422
2423 static gpg_error_t
2424 ssh_unlock (void)
2425 {
2426   gpg_error_t err;
2427
2428   log_error ("ssh-agent's unlock command is not implemented\n");
2429   err = 0;
2430
2431   return err;
2432 }
2433
2434 static gpg_error_t
2435 ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response)
2436 {
2437   gpg_error_t ret_err;
2438   gpg_error_t err;
2439   
2440   err = ssh_lock ();
2441   ret_err = stream_write_byte (response,
2442                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2443
2444   return ret_err;
2445 }
2446
2447 static gpg_error_t
2448 ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
2449 {
2450   gpg_error_t ret_err;
2451   gpg_error_t err;
2452   
2453   err = ssh_unlock ();
2454   ret_err = stream_write_byte (response,
2455                            err ? SSH_RESPONSE_FAILURE : SSH_RESPONSE_SUCCESS);
2456
2457   return ret_err;
2458 }
2459
2460 \f
2461
2462 static int
2463 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
2464 {
2465   estream_t response;
2466   estream_t request;
2467   unsigned char request_type;
2468   gpg_error_t err;
2469   unsigned int i;
2470   int send_err;
2471   int ret;
2472   unsigned char *request_data;
2473   u32 request_data_size;
2474   u32 response_size;
2475
2476   request_data = NULL;
2477   response = NULL;
2478   request = NULL;
2479   send_err = 0;
2480
2481   /* Create memory streams for request/response data.  The entire
2482      request will be stored in secure memory, since it might contain
2483      secret key material.  The response does not have to be stored in
2484      secure memory, since we never give out secret keys. 
2485
2486      FIXME: This is a pretty good DoS.  We only have a limited amount
2487      of secure memory, we can't trhow hin everything we get from a
2488      client -wk */
2489       
2490   /* Retrieve request.  */
2491   err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
2492   if (err)
2493     goto out;
2494
2495   if (opt.verbose > 1)
2496     log_info ("received ssh request of length %u\n",
2497               (unsigned int)request_data_size);
2498
2499   request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
2500   if (! request)
2501     {
2502       err = gpg_error_from_errno (errno);
2503       goto out;
2504     }
2505   ret = es_setvbuf (request, NULL, _IONBF, 0);
2506   if (ret)
2507     {
2508       err = gpg_error_from_errno (errno);
2509       goto out;
2510     }
2511   err = stream_write_data (request, request_data, request_data_size);
2512   if (err)
2513     goto out;
2514   es_rewind (request);
2515
2516   response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
2517   if (! response)
2518     {
2519       err = gpg_error_from_errno (errno);
2520       goto out;
2521     }
2522
2523   err = stream_read_byte (request, &request_type);
2524   if (err)
2525     {
2526       send_err = 1;
2527       goto out;
2528     }
2529
2530   for (i = 0; i < DIM (request_specs); i++)
2531     if (request_specs[i].type == request_type)
2532       break;
2533   if (i == DIM (request_specs))
2534     {
2535       log_info ("ssh request %u is not supported\n", request_type);
2536       send_err = 1;
2537       goto out;
2538     }
2539
2540   if (opt.verbose)
2541     log_info ("ssh request handler for %s (%u) started\n",
2542                request_specs[i].identifier, request_specs[i].type);
2543
2544   err = (*request_specs[i].handler) (ctrl, request, response);
2545
2546   if (opt.verbose)
2547     {
2548       if (err)
2549         log_info ("ssh request handler for %s (%u) failed: %s\n",
2550                   request_specs[i].identifier, request_specs[i].type,
2551                   gpg_strerror (err));
2552       else
2553         log_info ("ssh request handler for %s (%u) ready\n",
2554                   request_specs[i].identifier, request_specs[i].type);
2555     }
2556
2557   if (err)
2558     {
2559       send_err = 1;
2560       goto out;
2561     }
2562
2563   response_size = es_ftell (response);
2564   if (opt.verbose > 1)
2565     log_info ("sending ssh response of length %u\n",
2566               (unsigned int)response_size);
2567
2568   err = es_fseek (response, 0, SEEK_SET);
2569   if (err)
2570     {
2571       send_err = 1;
2572       goto out;
2573     }
2574
2575   err = stream_write_uint32 (stream_sock, response_size);
2576   if (err)
2577     {
2578       send_err = 1;
2579       goto out;
2580     }
2581
2582   err = stream_copy (stream_sock, response);
2583   if (err)
2584     goto out;
2585
2586   err = es_fflush (stream_sock);
2587   if (err)
2588     goto out;
2589
2590  out:
2591
2592   if (err && es_feof (stream_sock))
2593     log_error ("error occured while processing request: %s\n",
2594                gpg_strerror (err));
2595
2596   if (send_err)
2597     {
2598       if (opt.verbose > 1)
2599         log_info ("sending ssh error response\n");
2600       err = stream_write_uint32 (stream_sock, 1);
2601       if (err)
2602         goto leave;
2603       err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE);
2604       if (err)
2605         goto leave;
2606     }
2607
2608  leave:
2609
2610   if (request)
2611     es_fclose (request);
2612   if (response)
2613     es_fclose (response);
2614   xfree (request_data);         /* FIXME?  */
2615
2616   return !!err;
2617 }
2618
2619 void
2620 start_command_handler_ssh (int sock_client)
2621 {
2622   struct server_control_s ctrl;
2623   estream_t stream_sock;
2624   gpg_error_t err;
2625   int bad;
2626   int ret;
2627
2628   /* Setup control structure.  */
2629
2630   memset (&ctrl, 0, sizeof (ctrl));
2631   agent_init_default_ctrl (&ctrl);
2632   ctrl.connection_fd = sock_client;
2633
2634   /* Because the ssh protocol does not send us information about the
2635      the current TTY setting, we resort here to use those from startup
2636      or those explictly set.  */
2637   if (!ctrl.display && opt.startup_display)
2638     ctrl.display = strdup (opt.startup_display);
2639   if (!ctrl.ttyname && opt.startup_ttyname)
2640     ctrl.ttyname = strdup (opt.startup_ttyname);
2641   if (!ctrl.ttytype && opt.startup_ttytype)
2642     ctrl.ttytype = strdup (opt.startup_ttytype);
2643   if (!ctrl.lc_ctype && opt.startup_lc_ctype)
2644     ctrl.lc_ctype = strdup (opt.startup_lc_ctype);
2645   if (!ctrl.lc_messages && opt.startup_lc_messages)
2646     ctrl.lc_messages = strdup (opt.startup_lc_messages);
2647
2648
2649   /* Create stream from socket.  */
2650   stream_sock = es_fdopen (sock_client, "r+");
2651   if (!stream_sock)
2652     {
2653       err = gpg_error_from_errno (errno);
2654       log_error (_("failed to create stream from socket: %s\n"),
2655                  gpg_strerror (err));
2656       goto out;
2657     }
2658   /* We have to disable the estream buffering, because the estream
2659      core doesn't know about secure memory.  */
2660   ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
2661   if (ret)
2662     {
2663       err = gpg_error_from_errno (errno);
2664       log_error (_("failed to disable buffering "
2665                    "on socket stream: %s\n"), gpg_strerror (err));
2666       goto out;
2667     }
2668
2669   while (1)
2670     {
2671       bad = ssh_request_process (&ctrl, stream_sock);
2672       if (bad)
2673         break;
2674     };
2675
2676  out:
2677
2678   if (stream_sock)
2679     es_fclose (stream_sock);
2680
2681   free (ctrl.display);
2682   free (ctrl.ttyname);
2683   free (ctrl.ttytype);
2684   free (ctrl.lc_ctype);
2685   free (ctrl.lc_messages);
2686 }