2005-04-20 Moritz Schulte <moritz@g10code.com>
[gnupg.git] / agent / command-ssh.c
1 /* command-ssh.c - gpg-agent's ssh-agent emulation layer
2  * Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19  * 02111-1307, USA
20  */
21
22 /* Only v2 of the ssh-agent protocol is implemented.  */
23
24 #include <config.h>
25
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   key_directory = NULL;
1745   key_secret = NULL;
1746   key_public = NULL;
1747   key_type = NULL;
1748   key_path = NULL;
1749   key_counter = 0;
1750   buffer = NULL;
1751   dir = NULL;
1752   err = 0;
1753
1754   key_blobs = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1755   if (! key_blobs)
1756     {
1757       err = gpg_error_from_errno (errno);
1758       goto out;
1759     }
1760
1761   /* Open key directory.  */
1762   key_directory = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
1763   if (! key_directory)
1764     {
1765       err = gpg_err_code_from_errno (errno);
1766       goto out;
1767     }
1768   key_directory_n = strlen (key_directory);
1769   
1770   key_path = xtrymalloc (key_directory_n + 46);
1771   if (! key_path)
1772     {
1773       err = gpg_err_code_from_errno (errno);
1774       goto out;
1775     }
1776
1777   sprintf (key_path, "%s/", key_directory);
1778   sprintf (key_path + key_directory_n + 41, ".key");
1779
1780   dir = opendir (key_directory);
1781   if (! dir)
1782     {
1783       err = gpg_err_code_from_errno (errno);
1784       goto out;
1785     }
1786
1787
1788
1789   /* First check whether a key is currently available in the card
1790      reader - this should be allowed even without being listed in
1791      sshcontrol. */
1792
1793   if (!card_key_available (ctrl, &key_public, &cardsn))
1794     {
1795       err = ssh_send_key_public (key_blobs, key_public, cardsn);
1796       gcry_sexp_release (key_public);
1797       key_public = NULL;
1798       xfree (cardsn);
1799       if (err)
1800         goto out;
1801       
1802       key_counter++;
1803     }
1804
1805
1806   /* Then look at all the registered an allowed keys. */
1807
1808
1809   /* Fixme: We should better iterate over the control file and check
1810      whether the key file is there.  This is better in resepct to
1811      performance if tehre are a lot of key sin our key storage. */
1812   /* FIXME: make sure that buffer gets deallocated properly.  */
1813   err = open_control_file (&ctrl_fp, 0);
1814   if (err)
1815     goto out;
1816
1817   while ( (dir_entry = readdir (dir)) )
1818     {
1819       if ((strlen (dir_entry->d_name) == 44)
1820           && (! strncmp (dir_entry->d_name + 40, ".key", 4)))
1821         {
1822           char hexgrip[41];
1823           int disabled;
1824
1825           /* We do only want to return keys listed in our control
1826              file. */
1827           strncpy (hexgrip, dir_entry->d_name, 40);
1828           hexgrip[40] = 0;
1829           if ( strlen (hexgrip) != 40 )
1830             continue;
1831           if (search_control_file (ctrl_fp, hexgrip, &disabled)
1832               || disabled)
1833             continue;
1834
1835           strncpy (key_path + key_directory_n + 1, dir_entry->d_name, 40);
1836
1837           /* Read file content.  */
1838           err = file_to_buffer (key_path, &buffer, &buffer_n);
1839           if (err)
1840             goto out;
1841               
1842           err = gcry_sexp_sscan (&key_secret, NULL, buffer, buffer_n);
1843           if (err)
1844             goto out;
1845
1846           xfree (buffer);
1847           buffer = NULL;
1848
1849           err = sexp_extract_identifier (key_secret, &key_type);
1850           if (err)
1851             goto out;
1852
1853           err = ssh_key_type_lookup (NULL, key_type, &spec);
1854           if (err)
1855             goto out;
1856
1857           xfree (key_type);
1858           key_type = NULL;
1859
1860           err = key_secret_to_public (&key_public, spec, key_secret);
1861           if (err)
1862             goto out;
1863
1864           gcry_sexp_release (key_secret);
1865           key_secret = NULL;
1866               
1867           err = ssh_send_key_public (key_blobs, key_public, NULL);
1868           if (err)
1869             goto out;
1870
1871           gcry_sexp_release (key_public);
1872           key_public = NULL;
1873
1874           key_counter++;
1875         }
1876     }
1877   
1878   ret = es_fseek (key_blobs, 0, SEEK_SET);
1879   if (ret)
1880     {
1881       err = gpg_error_from_errno (errno);
1882       goto out;
1883     }
1884
1885  out:
1886
1887   /* Send response.  */
1888
1889   gcry_sexp_release (key_secret);
1890   gcry_sexp_release (key_public);
1891
1892   if (! err)
1893     {
1894       ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER);
1895       if (ret_err)
1896         goto leave;
1897       ret_err = stream_write_uint32 (response, key_counter);
1898       if (ret_err)
1899         goto leave;
1900       ret_err = stream_copy (response, key_blobs);
1901       if (ret_err)
1902         goto leave;
1903     }
1904   else
1905     {
1906       ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
1907       goto leave;
1908     };
1909
1910  leave:
1911
1912   if (key_blobs)
1913     es_fclose (key_blobs);
1914   if (dir)
1915     closedir (dir);
1916
1917   if (ctrl_fp)
1918     fclose (ctrl_fp);
1919
1920   free (key_directory);
1921   xfree (key_path);
1922   xfree (buffer);
1923   xfree (key_type);
1924
1925   return ret_err;
1926 }
1927
1928 /*  */
1929 static gpg_error_t
1930 data_hash (unsigned char *data, size_t data_n,
1931            int md_algorithm, unsigned char *hash)
1932 {
1933   gcry_md_hash_buffer (md_algorithm, hash, data, data_n);
1934
1935   return 0;
1936 }
1937
1938
1939 static gpg_error_t
1940 data_sign (ctrl_t ctrl, ssh_signature_encoder_t sig_encoder,
1941            unsigned char **sig, size_t *sig_n)
1942 {
1943   gpg_error_t err;
1944   gcry_sexp_t signature_sexp;
1945   estream_t stream;
1946   gcry_sexp_t valuelist;
1947   gcry_sexp_t sublist;
1948   gcry_mpi_t sig_value;
1949   unsigned char *sig_blob;
1950   size_t sig_blob_n;
1951   char *identifier;
1952   const char *identifier_raw;
1953   size_t identifier_n;
1954   ssh_key_type_spec_t spec;
1955   int ret;
1956   unsigned int i;
1957   const char *elems;
1958   size_t elems_n;
1959   gcry_mpi_t *mpis;
1960
1961   signature_sexp = NULL;
1962   identifier = NULL;
1963   valuelist = NULL;
1964   sublist = NULL;
1965   sig_blob = NULL;
1966   sig_blob_n = 0;
1967   stream = NULL;
1968   sig_value = NULL;
1969   mpis = NULL;
1970
1971   ctrl->use_auth_call = 1;
1972   err = agent_pksign_do (ctrl,
1973                          _("Please enter the passphrase "
1974                            "for the ssh key%0A  %c"), &signature_sexp, 0);
1975   ctrl->use_auth_call = 0;
1976   if (err)
1977     goto out;
1978
1979   valuelist = gcry_sexp_nth (signature_sexp, 1);
1980   if (! valuelist)
1981     {
1982       err = gpg_error (GPG_ERR_INV_SEXP);
1983       goto out;
1984     }
1985
1986   stream = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
1987   if (! stream)
1988     {
1989       err = gpg_error_from_errno (errno);
1990       goto out;
1991     }
1992
1993   identifier_raw = gcry_sexp_nth_data (valuelist, 0, &identifier_n);
1994   if (! identifier_raw)
1995     {
1996       err = gpg_error (GPG_ERR_INV_SEXP);
1997       goto out;
1998     }
1999
2000   identifier = make_cstring (identifier_raw, identifier_n);
2001   if (! identifier)
2002     {
2003       err = gpg_error_from_errno (errno);
2004       goto out;
2005     }
2006
2007   err = ssh_key_type_lookup (NULL, identifier, &spec);
2008   if (err)
2009     goto out;
2010
2011   err = stream_write_cstring (stream, spec.ssh_identifier);
2012   if (err)
2013     goto out;
2014
2015   elems = spec.elems_signature;
2016   elems_n = strlen (elems);
2017
2018   mpis = xtrymalloc (sizeof (*mpis) * (elems_n + 1));
2019   if (! mpis)
2020     {
2021       err = gpg_error_from_errno (errno);
2022       goto out;
2023     }
2024   memset (mpis, 0, sizeof (*mpis) * (elems_n + 1));
2025
2026   for (i = 0; i < elems_n; i++)
2027     {
2028       sublist = gcry_sexp_find_token (valuelist, spec.elems_signature + i, 1);
2029       if (! sublist)
2030         {
2031           err = gpg_error (GPG_ERR_INV_SEXP);
2032           break;
2033         }
2034
2035       sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
2036       if (! sig_value)
2037         {
2038           err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
2039           break;
2040         }
2041       gcry_sexp_release (sublist);
2042       sublist = NULL;
2043
2044       mpis[i] = sig_value;
2045     }
2046   if (err)
2047     goto out;
2048
2049   err = (*sig_encoder) (stream, mpis);
2050   if (err)
2051     goto out;
2052
2053   sig_blob_n = es_ftell (stream);
2054   if (sig_blob_n == -1)
2055     {
2056       err = gpg_error_from_errno (errno);
2057       goto out;
2058     }
2059
2060   sig_blob = xtrymalloc (sig_blob_n);
2061   if (! sig_blob)
2062     {
2063       err = gpg_error_from_errno (errno);
2064       goto out;
2065     }
2066
2067   ret = es_fseek (stream, 0, SEEK_SET);
2068   if (ret)
2069     {
2070       err = gpg_error_from_errno (errno);
2071       goto out;
2072     }    
2073
2074   err = stream_read_data (stream, sig_blob, sig_blob_n);
2075   if (err)
2076     goto out;
2077   
2078   *sig = (char *) sig_blob;
2079   *sig_n = sig_blob_n;
2080   
2081  out:
2082
2083   if (err)
2084     xfree (sig_blob);
2085
2086   if (stream)
2087     es_fclose (stream);
2088   gcry_sexp_release (valuelist);
2089   gcry_sexp_release (signature_sexp);
2090   gcry_sexp_release (sublist);
2091   mpint_list_free (mpis);
2092   xfree (identifier);
2093
2094   return err;
2095 }
2096
2097 static gpg_error_t
2098 ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
2099 {
2100   gcry_sexp_t key;
2101   ssh_key_type_spec_t spec;
2102   unsigned char hash[MAX_DIGEST_LEN];
2103   unsigned int hash_n;
2104   unsigned char key_grip[20];
2105   unsigned char *key_blob;
2106   u32 key_blob_size;
2107   unsigned char *data;
2108   unsigned char *sig;
2109   size_t sig_n;
2110   u32 data_size;
2111   u32 flags;
2112   void *p;
2113   gpg_error_t err;
2114   gpg_error_t ret_err;
2115
2116   key_blob = NULL;
2117   data = NULL;
2118   sig = NULL;
2119   key = NULL;
2120
2121   /* Receive key.  */
2122   
2123   err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2124   if (err)
2125     goto out;
2126
2127   err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec);
2128   if (err)
2129     goto out;
2130
2131   /* Receive data to sign.  */
2132   err = stream_read_string (request, 0, &data, &data_size);
2133   if (err)
2134     goto out;
2135
2136   /* FIXME?  */
2137   err = stream_read_uint32 (request, &flags);
2138   if (err)
2139     goto out;
2140
2141   /* Hash data.  */
2142   hash_n = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
2143   if (! hash_n)
2144     {
2145       err = gpg_error (GPG_ERR_INTERNAL);
2146       goto out;
2147     }
2148   err = data_hash (data, data_size, GCRY_MD_SHA1, hash);
2149   if (err)
2150     goto out;
2151
2152   /* Calculate key grip.  */
2153   p = gcry_pk_get_keygrip (key, key_grip);
2154   if (! p)
2155     {
2156       err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
2157       goto out;
2158     }
2159
2160   /* Sign data.  */
2161
2162   ctrl->digest.algo = GCRY_MD_SHA1;
2163   memcpy (ctrl->digest.value, hash, hash_n);
2164   ctrl->digest.valuelen = hash_n;
2165   ctrl->digest.raw_value = ! (spec.flags & SPEC_FLAG_USE_PKCS1V2);
2166   ctrl->have_keygrip = 1;
2167   memcpy (ctrl->keygrip, key_grip, 20);
2168
2169   err = data_sign (ctrl, spec.signature_encoder, &sig, &sig_n);
2170   
2171  out:
2172
2173   /* Done.  */
2174
2175   if (! err)
2176     {
2177       ret_err = stream_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE);
2178       if (ret_err)
2179         goto leave;
2180       ret_err = stream_write_string (response, sig, sig_n);
2181       if (ret_err)
2182         goto leave;
2183     }
2184   else
2185     {
2186       ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2187       if (ret_err)
2188         goto leave;
2189     }
2190   
2191  leave:
2192
2193   gcry_sexp_release (key);
2194   xfree (key_blob);
2195   xfree (data);
2196   xfree (sig);
2197
2198   return ret_err;
2199 }
2200
2201
2202 static gpg_error_t
2203 ssh_key_extract_comment (gcry_sexp_t key, char **comment)
2204 {
2205   gcry_sexp_t comment_list;
2206   char *comment_new;
2207   const char *data;
2208   size_t data_n;
2209   gpg_error_t err;
2210
2211   comment_list = gcry_sexp_find_token (key, "comment", 0);
2212   if (! comment_list)
2213     {
2214       err = gpg_error (GPG_ERR_INV_SEXP);
2215       goto out;
2216     }
2217   
2218   data = gcry_sexp_nth_data (comment_list, 1, &data_n);
2219   if (! data)
2220     {
2221       err = gpg_error (GPG_ERR_INV_SEXP);
2222       goto out;
2223     }
2224
2225   comment_new = make_cstring (data, data_n);
2226   if (! comment_new)
2227     {
2228       err = gpg_error_from_errno (errno);
2229       goto out;
2230     }
2231
2232   *comment = comment_new;
2233   err = 0;
2234
2235  out:
2236
2237   gcry_sexp_release (comment_list);
2238
2239   return err;
2240 }
2241
2242 static gpg_error_t
2243 ssh_key_grip (gcry_sexp_t key, char *buffer)
2244 {
2245   gpg_error_t err;
2246   char *p;
2247
2248   /* FIXME: unsigned vs. signed.  */
2249   
2250   p = gcry_pk_get_keygrip (key, buffer);
2251   if (! p)
2252     err = gpg_error (GPG_ERR_INTERNAL); /* FIXME?  */
2253   else
2254     err = 0;
2255
2256   return err;
2257 }
2258
2259 static gpg_error_t
2260 ssh_key_to_buffer (gcry_sexp_t key, const char *passphrase,
2261                    unsigned char **buffer, size_t *buffer_n)
2262 {
2263   unsigned char *buffer_new;
2264   unsigned int buffer_new_n;
2265   gpg_error_t err;
2266
2267   err = 0;
2268   buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0);
2269   buffer_new = xtrymalloc_secure (buffer_new_n);
2270   if (! buffer_new)
2271     {
2272       err = gpg_error_from_errno (errno);
2273       goto out;
2274     }
2275   
2276   gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, buffer_new, buffer_new_n);
2277   /* FIXME: guarantee?  */
2278
2279   err = agent_protect (buffer_new, passphrase, buffer, buffer_n);
2280
2281  out:
2282
2283   xfree (buffer_new);
2284
2285   return err;
2286 }
2287
2288
2289
2290 /* Store the ssh KEY into our local key storage and protect him after
2291    asking for a passphrase.  Cache that passphrase.  TTL is the
2292    maximum caching time for that key.  If the key already exists in
2293    our key storage, don't do anything.  When entering a new key also
2294    add an entry to the sshcontrol file.  */
2295 static gpg_error_t
2296 ssh_identity_register (ctrl_t ctrl, gcry_sexp_t key, int ttl)
2297 {
2298   gpg_error_t err;
2299   unsigned char key_grip_raw[21];
2300   char key_grip[41];
2301   unsigned char *buffer = NULL;
2302   unsigned int buffer_n;
2303   char *description = NULL;
2304   char *comment = NULL;
2305   unsigned int i;
2306   struct pin_entry_info_s *pi = NULL;
2307
2308   err = ssh_key_grip (key, key_grip_raw);
2309   if (err)
2310     goto out;
2311
2312   key_grip_raw[sizeof (key_grip_raw) - 1] = 0; /* FIXME:  Why?? */
2313
2314   /* Check whether the key is already in our key storage.  Don't do
2315      anything then.  */
2316   if ( !agent_key_available (key_grip_raw) )
2317     goto out; /* Yes, key is available.  */
2318
2319   
2320   err = ssh_key_extract_comment (key, &comment);
2321   if (err)
2322     goto out;
2323
2324   if ( asprintf (&description,
2325                  _("Please enter a passphrase to protect"
2326                    " the received secret key%%0A"
2327                    "   %s%%0A"
2328                    "within gpg-agent's key storage"),
2329                  comment ? comment : "?") < 0)
2330     {
2331       err = gpg_error_from_errno (errno);
2332       goto out;
2333     }
2334
2335
2336   pi = gcry_calloc_secure (1, sizeof (*pi) + 100 + 1);
2337   if (!pi)
2338     {
2339       err = gpg_error_from_errno (errno);
2340       goto out;
2341     }
2342   pi->max_length = 100;
2343   pi->max_tries = 1;
2344   err = agent_askpin (ctrl, description, NULL, pi);
2345   if (err)
2346     goto out;
2347
2348   err = ssh_key_to_buffer (key, pi->pin, &buffer, &buffer_n);
2349   if (err)
2350     goto out;
2351
2352   /* Store this key to our key storage.  */
2353   err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0);
2354   if (err)
2355     goto out;
2356
2357   /* Cache this passphrase. */
2358   for (i = 0; i < 20; i++)
2359     sprintf (key_grip + 2 * i, "%02X", key_grip_raw[i]);
2360
2361   err = agent_put_cache (key_grip, pi->pin, ttl);
2362   if (err)
2363     goto out;
2364
2365   /* And add an entry to the sshcontrol file.  */
2366   err = add_control_entry (ctrl, key_grip, ttl);
2367
2368
2369  out:
2370   if (pi && pi->max_length)
2371     wipememory (pi->pin, pi->max_length);
2372   xfree (pi);
2373   xfree (buffer);
2374   xfree (comment);
2375   free (description); /* (asprintf allocated, thus regular free.)  */
2376
2377   return err;
2378 }
2379
2380
2381
2382 static gpg_error_t
2383 ssh_identity_drop (gcry_sexp_t key)
2384 {
2385   unsigned char key_grip[21] = { 0 };
2386   gpg_error_t err;
2387
2388   err = ssh_key_grip (key, key_grip);
2389   if (err)
2390     goto out;
2391
2392   key_grip[sizeof (key_grip) - 1] = 0;
2393
2394   /* FIXME: What to do here - forgetting the passphrase or deleting
2395      the key from key cache?  */
2396
2397  out:
2398
2399   return err;
2400 }
2401
2402 static gpg_error_t
2403 ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
2404 {
2405   gpg_error_t ret_err;
2406   gpg_error_t err;
2407   gcry_sexp_t key;
2408   unsigned char b;
2409   int confirm;
2410   int ttl;
2411   
2412   confirm = 0;
2413   key = NULL;
2414   ttl = 0;
2415
2416   /* FIXME?  */
2417   err = ssh_receive_key (request, &key, 1, 1, NULL);
2418   if (err)
2419     goto out;
2420
2421   while (1)
2422     {
2423       err = stream_read_byte (request, &b);
2424       if (gpg_err_code (err) == GPG_ERR_EOF)
2425         {
2426           err = 0;
2427           break;
2428         }
2429
2430       switch (b)
2431         {
2432         case SSH_OPT_CONSTRAIN_LIFETIME:
2433           {
2434             u32 n = 0;
2435
2436             err = stream_read_uint32 (request, &n);
2437             if (! err)
2438               ttl = n;
2439             break;
2440           }
2441
2442         case SSH_OPT_CONSTRAIN_CONFIRM:
2443           {
2444             confirm = 1;
2445             break;
2446           }
2447
2448         default:
2449           /* FIXME: log/bad?  */
2450           break;
2451         }
2452     }
2453   if (err)
2454     goto out;
2455
2456   /* FIXME: are constraints used correctly?  */
2457
2458   err = ssh_identity_register (ctrl, key, ttl);
2459
2460  out:
2461
2462   gcry_sexp_release (key);
2463
2464   if (! err)
2465     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2466   else
2467     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2468
2469   return ret_err;
2470 }
2471
2472 static gpg_error_t
2473 ssh_handler_remove_identity (ctrl_t ctrl, estream_t request,
2474                              estream_t response)
2475 {
2476   unsigned char *key_blob;
2477   u32 key_blob_size;
2478   gcry_sexp_t key;
2479   gpg_error_t ret_err;
2480   gpg_error_t err;
2481
2482   /* Receive key.  */
2483
2484   key_blob = NULL;
2485   key = NULL;
2486   
2487   err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2488   if (err)
2489     goto out;
2490
2491   err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL);
2492   if (err)
2493     goto out;
2494   
2495   err = ssh_identity_drop (key);
2496
2497  out:
2498
2499   xfree (key_blob);
2500   gcry_sexp_release (key);
2501
2502   if (! err)
2503     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2504   else
2505     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2506
2507   return ret_err;
2508 }
2509
2510 static gpg_error_t
2511 ssh_identities_remove_all (void)
2512 {
2513   gpg_error_t err;
2514
2515   err = 0;
2516
2517   /* FIXME: shall we remove _all_ cache entries or only those
2518      registered through the ssh emulation?  */
2519   
2520   return err;
2521 }
2522
2523 static gpg_error_t
2524 ssh_handler_remove_all_identities (ctrl_t ctrl, estream_t request,
2525                                    estream_t response)
2526 {
2527   gpg_error_t ret_err;
2528   gpg_error_t err;
2529   
2530   err = ssh_identities_remove_all ();
2531
2532   if (! err)
2533     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2534   else
2535     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2536
2537   return ret_err;
2538 }
2539
2540 static gpg_error_t
2541 ssh_lock (void)
2542 {
2543   gpg_error_t err;
2544
2545   /* FIXME */
2546   log_error ("ssh-agent's lock command is not implemented\n");
2547   err = 0;
2548
2549   return err;
2550 }
2551
2552 static gpg_error_t
2553 ssh_unlock (void)
2554 {
2555   gpg_error_t err;
2556
2557   log_error ("ssh-agent's unlock command is not implemented\n");
2558   err = 0;
2559
2560   return err;
2561 }
2562
2563 static gpg_error_t
2564 ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response)
2565 {
2566   gpg_error_t ret_err;
2567   gpg_error_t err;
2568   
2569   err = ssh_lock ();
2570
2571   if (! err)
2572     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2573   else
2574     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2575
2576   return ret_err;
2577 }
2578
2579 static gpg_error_t
2580 ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
2581 {
2582   gpg_error_t ret_err;
2583   gpg_error_t err;
2584   
2585   err = ssh_unlock ();
2586
2587   if (! err)
2588     ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
2589   else
2590     ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2591
2592   return ret_err;
2593 }
2594
2595 \f
2596
2597 static ssh_request_spec_t *
2598 request_spec_lookup (int type)
2599 {
2600   ssh_request_spec_t *spec;
2601   unsigned int i;
2602
2603   for (i = 0; i < DIM (request_specs); i++)
2604     if (request_specs[i].type == type)
2605       break;
2606   if (i == DIM (request_specs))
2607     {
2608       log_info ("ssh request %u is not supported\n", type);
2609       spec = NULL;
2610     }
2611   else
2612     spec = request_specs + i;
2613
2614   return spec;
2615 }
2616
2617 static int
2618 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
2619 {
2620   ssh_request_spec_t *spec;
2621   estream_t response;
2622   estream_t request;
2623   unsigned char request_type;
2624   gpg_error_t err;
2625   int send_err;
2626   int ret;
2627   unsigned char *request_data;
2628   u32 request_data_size;
2629   u32 response_size;
2630
2631   request_data = NULL;
2632   response = NULL;
2633   request = NULL;
2634   send_err = 0;
2635
2636   /* Create memory streams for request/response data.  The entire
2637      request will be stored in secure memory, since it might contain
2638      secret key material.  The response does not have to be stored in
2639      secure memory, since we never give out secret keys. 
2640
2641      FIXME: This is a pretty good DoS.  We only have a limited amount
2642      of secure memory, we can't trhow hin everything we get from a
2643      client -wk */
2644       
2645   /* Retrieve request.  */
2646   err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
2647   if (err)
2648     goto out;
2649
2650   if (opt.verbose > 1)
2651     log_info ("received ssh request of length %u\n",
2652               (unsigned int)request_data_size);
2653
2654   if (! request_data_size)
2655     {
2656       send_err = 1;
2657       goto out;
2658       /* Broken request; FIXME.  */
2659     }
2660
2661   request_type = request_data[0];
2662   spec = request_spec_lookup (request_type);
2663   if (! spec)
2664     {
2665       send_err = 1;
2666       goto out;
2667       /* Unknown request; FIXME.  */
2668     }
2669
2670   if (spec->secret_input)
2671     request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
2672   else
2673     request = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+");
2674   if (! request)
2675     {
2676       err = gpg_error_from_errno (errno);
2677       goto out;
2678     }
2679   ret = es_setvbuf (request, NULL, _IONBF, 0);
2680   if (ret)
2681     {
2682       err = gpg_error_from_errno (errno);
2683       goto out;
2684     }
2685   err = stream_write_data (request, request_data + 1, request_data_size - 1);
2686   if (err)
2687     goto out;
2688   es_rewind (request);
2689
2690   response = es_mopen (NULL, 0, 0, 1, NULL, NULL, "r+");
2691   if (! response)
2692     {
2693       err = gpg_error_from_errno (errno);
2694       goto out;
2695     }
2696
2697   if (opt.verbose)
2698     log_info ("ssh request handler for %s (%u) started\n",
2699                spec->identifier, spec->type);
2700
2701   err = (*spec->handler) (ctrl, request, response);
2702
2703   if (opt.verbose)
2704     {
2705       if (err)
2706         log_info ("ssh request handler for %s (%u) failed: %s\n",
2707                   spec->identifier, spec->type, gpg_strerror (err));
2708       else
2709         log_info ("ssh request handler for %s (%u) ready\n",
2710                   spec->identifier, spec->type);
2711     }
2712
2713   if (err)
2714     {
2715       send_err = 1;
2716       goto out;
2717     }
2718
2719   response_size = es_ftell (response);
2720   if (opt.verbose > 1)
2721     log_info ("sending ssh response of length %u\n",
2722               (unsigned int)response_size);
2723
2724   err = es_fseek (response, 0, SEEK_SET);
2725   if (err)
2726     {
2727       send_err = 1;
2728       goto out;
2729     }
2730
2731   err = stream_write_uint32 (stream_sock, response_size);
2732   if (err)
2733     {
2734       send_err = 1;
2735       goto out;
2736     }
2737
2738   err = stream_copy (stream_sock, response);
2739   if (err)
2740     goto out;
2741
2742   err = es_fflush (stream_sock);
2743   if (err)
2744     goto out;
2745
2746  out:
2747
2748   if (err && es_feof (stream_sock))
2749     log_error ("error occured while processing request: %s\n",
2750                gpg_strerror (err));
2751
2752   if (send_err)
2753     {
2754       if (opt.verbose > 1)
2755         log_info ("sending ssh error response\n");
2756       err = stream_write_uint32 (stream_sock, 1);
2757       if (err)
2758         goto leave;
2759       err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE);
2760       if (err)
2761         goto leave;
2762     }
2763
2764  leave:
2765
2766   if (request)
2767     es_fclose (request);
2768   if (response)
2769     es_fclose (response);
2770   xfree (request_data);         /* FIXME?  */
2771
2772   return !!err;
2773 }
2774
2775 void
2776 start_command_handler_ssh (int sock_client)
2777 {
2778   struct server_control_s ctrl;
2779   estream_t stream_sock;
2780   gpg_error_t err;
2781   int bad;
2782   int ret;
2783
2784   /* Setup control structure.  */
2785
2786   memset (&ctrl, 0, sizeof (ctrl));
2787   agent_init_default_ctrl (&ctrl);
2788   ctrl.connection_fd = sock_client;
2789
2790   /* Because the ssh protocol does not send us information about the
2791      the current TTY setting, we resort here to use those from startup
2792      or those explictly set.  */
2793   if (!ctrl.display && opt.startup_display)
2794     ctrl.display = strdup (opt.startup_display);
2795   if (!ctrl.ttyname && opt.startup_ttyname)
2796     ctrl.ttyname = strdup (opt.startup_ttyname);
2797   if (!ctrl.ttytype && opt.startup_ttytype)
2798     ctrl.ttytype = strdup (opt.startup_ttytype);
2799   if (!ctrl.lc_ctype && opt.startup_lc_ctype)
2800     ctrl.lc_ctype = strdup (opt.startup_lc_ctype);
2801   if (!ctrl.lc_messages && opt.startup_lc_messages)
2802     ctrl.lc_messages = strdup (opt.startup_lc_messages);
2803
2804
2805   /* Create stream from socket.  */
2806   stream_sock = es_fdopen (sock_client, "r+");
2807   if (!stream_sock)
2808     {
2809       err = gpg_error_from_errno (errno);
2810       log_error (_("failed to create stream from socket: %s\n"),
2811                  gpg_strerror (err));
2812       goto out;
2813     }
2814   /* We have to disable the estream buffering, because the estream
2815      core doesn't know about secure memory.  */
2816   ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
2817   if (ret)
2818     {
2819       err = gpg_error_from_errno (errno);
2820       log_error (_("failed to disable buffering "
2821                    "on socket stream: %s\n"), gpg_strerror (err));
2822       goto out;
2823     }
2824
2825   while (1)
2826     {
2827       bad = ssh_request_process (&ctrl, stream_sock);
2828       if (bad)
2829         break;
2830     };
2831
2832  out:
2833
2834   if (stream_sock)
2835     es_fclose (stream_sock);
2836
2837   free (ctrl.display);
2838   free (ctrl.ttyname);
2839   free (ctrl.ttytype);
2840   free (ctrl.lc_ctype);
2841   free (ctrl.lc_messages);
2842 }