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