1 /* command-ssh.c - gpg-agent's implementation of the ssh-agent protocol.
2 * Copyright (C) 2004-2006, 2009, 2012 Free Software Foundation, Inc.
3 * Copyright (C) 2004-2006, 2009, 2012-2014 Werner Koch
4 *
5 * This file is part of GnuPG.
6 *
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19 */
20
21 /* Only v2 of the ssh-agent protocol is implemented. Relevant RFCs
22 are:
23
24 RFC-4250 - Protocol Assigned Numbers
25 RFC-4251 - Protocol Architecture
26 RFC-4252 - Authentication Protocol
27 RFC-4253 - Transport Layer Protocol
28 RFC-5656 - ECC support
29
30 The protocol for the agent is defined in:
31
32 https://tools.ietf.org/html/draft-miller-ssh-agent
33
34 */
35
36 #include <config.h>
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #ifndef HAVE_W32_SYSTEM
45 #include <sys/socket.h>
46 #include <sys/un.h>
47 #endif /*!HAVE_W32_SYSTEM*/
48 #ifdef HAVE_SYS_UCRED_H
49 #include <sys/ucred.h>
50 #endif
51 #ifdef HAVE_UCRED_H
52 #include <ucred.h>
53 #endif
54
55 #include "agent.h"
56
57 #include "../common/i18n.h"
58 #include "../common/util.h"
59 #include "../common/ssh-utils.h"
60
61
62
63
64 /* Request types. */
65 #define SSH_REQUEST_REQUEST_IDENTITIES 11
66 #define SSH_REQUEST_SIGN_REQUEST 13
67 #define SSH_REQUEST_ADD_IDENTITY 17
68 #define SSH_REQUEST_REMOVE_IDENTITY 18
69 #define SSH_REQUEST_REMOVE_ALL_IDENTITIES 19
70 #define SSH_REQUEST_LOCK 22
71 #define SSH_REQUEST_UNLOCK 23
72 #define SSH_REQUEST_ADD_ID_CONSTRAINED 25
73 #define SSH_REQUEST_EXTENSION 27
74
75 /* Options. */
76 #define SSH_OPT_CONSTRAIN_LIFETIME 1
77 #define SSH_OPT_CONSTRAIN_CONFIRM 2
78
79 /* Response types. */
80 #define SSH_RESPONSE_SUCCESS 6
81 #define SSH_RESPONSE_FAILURE 5
82 #define SSH_RESPONSE_IDENTITIES_ANSWER 12
83 #define SSH_RESPONSE_SIGN_RESPONSE 14
84 #define SSH_RESPONSE_EXTENSION_FAILURE 28
85
86 /* Other constants. */
87 #define SSH_DSA_SIGNATURE_PADDING 20
88 #define SSH_DSA_SIGNATURE_ELEMS 2
89 #define SSH_AGENT_RSA_SHA2_256 0x02
90 #define SSH_AGENT_RSA_SHA2_512 0x04
91 #define SPEC_FLAG_USE_PKCS1V2 (1 << 0)
92 #define SPEC_FLAG_IS_ECDSA (1 << 1)
93 #define SPEC_FLAG_IS_EdDSA (1 << 2) /*(lowercase 'd' on purpose.)*/
94 #define SPEC_FLAG_WITH_CERT (1 << 7)
95
96 /* The name of the control file. */
97 #define SSH_CONTROL_FILE_NAME "sshcontrol"
98
99 /* The blurb we put into the header of a newly created control file. */
100 static const char sshcontrolblurb[] =
101 "# List of allowed ssh keys. Only keys present in this file are used\n"
102 "# in the SSH protocol. The ssh-add tool may add new entries to this\n"
103 "# file to enable them; you may also add them manually. Comment\n"
104 "# lines, like this one, as well as empty lines are ignored. Lines do\n"
105 "# have a certain length limit but this is not serious limitation as\n"
106 "# the format of the entries is fixed and checked by gpg-agent. A\n"
107 "# non-comment line starts with optional white spaces, followed by the\n"
108 "# keygrip of the key given as 40 hex digits, optionally followed by a\n"
109 "# caching TTL in seconds, and another optional field for arbitrary\n"
110 "# flags. Prepend the keygrip with an '!' mark to disable it.\n"
111 "\n";
112
113
114 /* Macros. */
115
116 /* Return a new uint32 with b0 being the most significant byte and b3
117 being the least significant byte. */
118 #define uint32_construct(b0, b1, b2, b3) \
119 ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3)
120
121
122
123
124 /*
125 * Basic types.
126 */
127
128 /* Type for a request handler. */
129 typedef gpg_error_t (*ssh_request_handler_t) (ctrl_t ctrl,
130 estream_t request,
131 estream_t response);
132
133
134 struct ssh_key_type_spec;
135 typedef struct ssh_key_type_spec ssh_key_type_spec_t;
136
137 /* Type, which is used for associating request handlers with the
138 appropriate request IDs. */
139 typedef struct ssh_request_spec
140 {
141 unsigned char type;
142 ssh_request_handler_t handler;
143 const char *identifier;
144 unsigned int secret_input;
145 } ssh_request_spec_t;
146
147 /* Type for "key modifier functions", which are necessary since
148 OpenSSH and GnuPG treat key material slightly different. A key
149 modifier is called right after a new key identity has been received
150 in order to "sanitize" the material. */
151 typedef gpg_error_t (*ssh_key_modifier_t) (const char *elems,
152 gcry_mpi_t *mpis);
153
154 /* The encoding of a generated signature is dependent on the
155 algorithm; therefore algorithm specific signature encoding
156 functions are necessary. */
157 typedef gpg_error_t (*ssh_signature_encoder_t) (ssh_key_type_spec_t *spec,
158 estream_t signature_blob,
159 gcry_sexp_t sig);
160
161 /* Type, which is used for bundling all the algorithm specific
162 information together in a single object. */
163 struct ssh_key_type_spec
164 {
165 /* Algorithm identifier as used by OpenSSH. */
166 const char *ssh_identifier;
167
168 /* Human readable name of the algorithm. */
169 const char *name;
170
171 /* Algorithm identifier as used by GnuPG. */
172 int algo;
173
174 /* List of MPI names for secret keys; order matches the one of the
175 agent protocol. */
176 const char *elems_key_secret;
177
178 /* List of MPI names for public keys; order matches the one of the
179 agent protocol. */
180 const char *elems_key_public;
181
182 /* List of MPI names for signature data. */
183 const char *elems_signature;
184
185 /* List of MPI names for secret keys; order matches the one, which
186 is required by gpg-agent's key access layer. */
187 const char *elems_sexp_order;
188
189 /* Key modifier function. Key modifier functions are necessary in
190 order to fix any inconsistencies between the representation of
191 keys on the SSH and on the GnuPG side. */
192 ssh_key_modifier_t key_modifier;
193
194 /* Signature encoder function. Signature encoder functions are
195 necessary since the encoding of signatures depends on the used
196 algorithm. */
197 ssh_signature_encoder_t signature_encoder;
198
199 /* The name of the ECC curve or NULL for non-ECC algos. This is the
200 * canonical name for the curve as specified by RFC-5656. */
201 const char *curve_name;
202
203 /* An alias for curve_name or NULL. Actually this is Libcgrypt's
204 * primary name of the curve. */
205 const char *alt_curve_name;
206
207 /* The hash algorithm to be used with this key. 0 for using the
208 default. */
209 int hash_algo;
210
211 /* Misc flags. */
212 unsigned int flags;
213 };
214
215
216 /* Definition of an object to access the sshcontrol file. */
217 struct ssh_control_file_s
218 {
219 char *fname; /* Name of the file. */
220 estream_t fp; /* This is never NULL. */
221 int lnr; /* The current line number. */
222 struct {
223 int valid; /* True if the data of this structure is valid. */
224 int disabled; /* The item is disabled. */
225 int ttl; /* The TTL of the item. */
226 int confirm; /* The confirm flag is set. */
227 char hexgrip[40+1]; /* The hexgrip of the item (uppercase). */
228 } item;
229 };
230
231
232 /* Prototypes. */
233 static gpg_error_t ssh_handler_request_identities (ctrl_t ctrl,
234 estream_t request,
235 estream_t response);
236 static gpg_error_t ssh_handler_sign_request (ctrl_t ctrl,
237 estream_t request,
238 estream_t response);
239 static gpg_error_t ssh_handler_add_identity (ctrl_t ctrl,
240 estream_t request,
241 estream_t response);
242 static gpg_error_t ssh_handler_remove_identity (ctrl_t ctrl,
243 estream_t request,
244 estream_t response);
245 static gpg_error_t ssh_handler_remove_all_identities (ctrl_t ctrl,
246 estream_t request,
247 estream_t response);
248 static gpg_error_t ssh_handler_lock (ctrl_t ctrl,
249 estream_t request,
250 estream_t response);
251 static gpg_error_t ssh_handler_unlock (ctrl_t ctrl,
252 estream_t request,
253 estream_t response);
254 static gpg_error_t ssh_handler_extension (ctrl_t ctrl,
255 estream_t request,
256 estream_t response);
257
258 static gpg_error_t ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis);
259 static gpg_error_t ssh_signature_encoder_rsa (ssh_key_type_spec_t *spec,
260 estream_t signature_blob,
261 gcry_sexp_t signature);
262 static gpg_error_t ssh_signature_encoder_dsa (ssh_key_type_spec_t *spec,
263 estream_t signature_blob,
264 gcry_sexp_t signature);
265 static gpg_error_t ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec,
266 estream_t signature_blob,
267 gcry_sexp_t signature);
268 static gpg_error_t ssh_signature_encoder_eddsa (ssh_key_type_spec_t *spec,
269 estream_t signature_blob,
270 gcry_sexp_t signature);
271 static gpg_error_t ssh_key_extract_comment (gcry_sexp_t key, char **comment);
272
273
274 struct peer_info_s
275 {
276 unsigned long pid;
277 int uid;
278 };
279
280 /* Global variables. */
281
282
283 /* Associating request types with the corresponding request
284 handlers. */
285
286 static const ssh_request_spec_t request_specs[] =
287 {
288 #define REQUEST_SPEC_DEFINE(id, name, secret_input) \
289 { SSH_REQUEST_##id, ssh_handler_##name, #name, secret_input }
290
291 REQUEST_SPEC_DEFINE (REQUEST_IDENTITIES, request_identities, 1),
292 REQUEST_SPEC_DEFINE (SIGN_REQUEST, sign_request, 0),
293 REQUEST_SPEC_DEFINE (ADD_IDENTITY, add_identity, 1),
294 REQUEST_SPEC_DEFINE (ADD_ID_CONSTRAINED, add_identity, 1),
295 REQUEST_SPEC_DEFINE (REMOVE_IDENTITY, remove_identity, 0),
296 REQUEST_SPEC_DEFINE (REMOVE_ALL_IDENTITIES, remove_all_identities, 0),
297 REQUEST_SPEC_DEFINE (LOCK, lock, 0),
298 REQUEST_SPEC_DEFINE (UNLOCK, unlock, 0),
299 REQUEST_SPEC_DEFINE (EXTENSION, extension, 0)
300 #undef REQUEST_SPEC_DEFINE
301 };
302
303
304 /* Table holding key type specifications. */
305 static const ssh_key_type_spec_t ssh_key_types[] =
306 {
307 {
308 "ssh-ed25519", "Ed25519", GCRY_PK_EDDSA, "qd", "q", "rs", "qd",
309 NULL, ssh_signature_encoder_eddsa,
310 "Ed25519", NULL, 0, SPEC_FLAG_IS_EdDSA
311 },
312 {
313 "ssh-rsa", "RSA", GCRY_PK_RSA, "nedupq", "en", "s", "nedpqu",
314 ssh_key_modifier_rsa, ssh_signature_encoder_rsa,
315 NULL, NULL, 0, SPEC_FLAG_USE_PKCS1V2
316 },
317 {
318 "ssh-dss", "DSA", GCRY_PK_DSA, "pqgyx", "pqgy", "rs", "pqgyx",
319 NULL, ssh_signature_encoder_dsa,
320 NULL, NULL, 0, 0
321 },
322 {
323 "ecdsa-sha2-nistp256", "ECDSA", GCRY_PK_ECC, "qd", "q", "rs", "qd",
324 NULL, ssh_signature_encoder_ecdsa,
325 "nistp256", "NIST P-256", GCRY_MD_SHA256, SPEC_FLAG_IS_ECDSA
326 },
327 {
328 "ecdsa-sha2-nistp384", "ECDSA", GCRY_PK_ECC, "qd", "q", "rs", "qd",
329 NULL, ssh_signature_encoder_ecdsa,
330 "nistp384", "NIST P-384", GCRY_MD_SHA384, SPEC_FLAG_IS_ECDSA
331 },
332 {
333 "ecdsa-sha2-nistp521", "ECDSA", GCRY_PK_ECC, "qd", "q", "rs", "qd",
334 NULL, ssh_signature_encoder_ecdsa,
335 "nistp521", "NIST P-521", GCRY_MD_SHA512, SPEC_FLAG_IS_ECDSA
336 },
337 {
338 "ssh-ed25519-cert-v01@openssh.com", "Ed25519",
339 GCRY_PK_EDDSA, "qd", "q", "rs", "qd",
340 NULL, ssh_signature_encoder_eddsa,
341 "Ed25519", NULL, 0, SPEC_FLAG_IS_EdDSA | SPEC_FLAG_WITH_CERT
342 },
343 {
344 "ssh-rsa-cert-v01@openssh.com", "RSA",
345 GCRY_PK_RSA, "nedupq", "en", "s", "nedpqu",
346 ssh_key_modifier_rsa, ssh_signature_encoder_rsa,
347 NULL, NULL, 0, SPEC_FLAG_USE_PKCS1V2 | SPEC_FLAG_WITH_CERT
348 },
349 {
350 "ssh-dss-cert-v01@openssh.com", "DSA",
351 GCRY_PK_DSA, "pqgyx", "pqgy", "rs", "pqgyx",
352 NULL, ssh_signature_encoder_dsa,
353 NULL, NULL, 0, SPEC_FLAG_WITH_CERT | SPEC_FLAG_WITH_CERT
354 },
355 {
356 "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA",
357 GCRY_PK_ECC, "qd", "q", "rs", "qd",
358 NULL, ssh_signature_encoder_ecdsa,
359 "nistp256", "NIST P-256", GCRY_MD_SHA256,
360 SPEC_FLAG_IS_ECDSA | SPEC_FLAG_WITH_CERT
361 },
362 {
363 "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA",
364 GCRY_PK_ECC, "qd", "q", "rs", "qd",
365 NULL, ssh_signature_encoder_ecdsa,
366 "nistp384", "NIST P-384", GCRY_MD_SHA384,
367 SPEC_FLAG_IS_ECDSA | SPEC_FLAG_WITH_CERT
368 },
369 {
370 "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA",
371 GCRY_PK_ECC, "qd", "q", "rs", "qd",
372 NULL, ssh_signature_encoder_ecdsa,
373 "nistp521", "NIST P-521", GCRY_MD_SHA512,
374 SPEC_FLAG_IS_ECDSA | SPEC_FLAG_WITH_CERT
375 }
376 };
377
378
379
380
381
382 /*
383 General utility functions.
384 */
385
386 /* A secure realloc, i.e. it makes sure to allocate secure memory if A
387 is NULL. This is required because the standard gcry_realloc does
388 not know whether to allocate secure or normal if NULL is passed as
389 existing buffer. */
390 static void *
realloc_secure(void * a,size_t n)391 realloc_secure (void *a, size_t n)
392 {
393 void *p;
394
395 if (a)
396 p = gcry_realloc (a, n);
397 else
398 p = gcry_malloc_secure (n);
399
400 return p;
401 }
402
403
404 /* Lookup the ssh-identifier for the ECC curve CURVE_NAME. Returns
405 * NULL if not found. If found the ssh indetifier is returned and a
406 * pointer to the canonical curve name as specified for ssh is stored
407 * at R_CANON_NAME. */
408 static const char *
ssh_identifier_from_curve_name(const char * curve_name,const char ** r_canon_name)409 ssh_identifier_from_curve_name (const char *curve_name,
410 const char **r_canon_name)
411 {
412 int i;
413
414 for (i = 0; i < DIM (ssh_key_types); i++)
415 if (ssh_key_types[i].curve_name
416 && (!strcmp (ssh_key_types[i].curve_name, curve_name)
417 || (ssh_key_types[i].alt_curve_name
418 && !strcmp (ssh_key_types[i].alt_curve_name, curve_name))))
419 {
420 *r_canon_name = ssh_key_types[i].curve_name;
421 return ssh_key_types[i].ssh_identifier;
422 }
423
424 return NULL;
425 }
426
427
428 /*
429 Primitive I/O functions.
430 */
431
432
433 /* Read a byte from STREAM, store it in B. */
434 static gpg_error_t
stream_read_byte(estream_t stream,unsigned char * b)435 stream_read_byte (estream_t stream, unsigned char *b)
436 {
437 gpg_error_t err;
438 int ret;
439
440 ret = es_fgetc (stream);
441 if (ret == EOF)
442 {
443 if (es_ferror (stream))
444 err = gpg_error_from_syserror ();
445 else
446 err = gpg_error (GPG_ERR_EOF);
447 *b = 0;
448 }
449 else
450 {
451 *b = ret & 0xFF;
452 err = 0;
453 }
454
455 return err;
456 }
457
458 /* Write the byte contained in B to STREAM. */
459 static gpg_error_t
stream_write_byte(estream_t stream,unsigned char b)460 stream_write_byte (estream_t stream, unsigned char b)
461 {
462 gpg_error_t err;
463 int ret;
464
465 ret = es_fputc (b, stream);
466 if (ret == EOF)
467 err = gpg_error_from_syserror ();
468 else
469 err = 0;
470
471 return err;
472 }
473
474
475 /* Read a uint32 from STREAM, store it in UINT32. */
476 static gpg_error_t
stream_read_uint32(estream_t stream,u32 * uint32)477 stream_read_uint32 (estream_t stream, u32 *uint32)
478 {
479 unsigned char buffer[4];
480 size_t bytes_read;
481 gpg_error_t err;
482 int ret;
483
484 ret = es_read (stream, buffer, sizeof (buffer), &bytes_read);
485 if (ret)
486 err = gpg_error_from_syserror ();
487 else
488 {
489 if (bytes_read != sizeof (buffer))
490 err = gpg_error (GPG_ERR_EOF);
491 else
492 {
493 u32 n;
494
495 n = uint32_construct (buffer[0], buffer[1], buffer[2], buffer[3]);
496 *uint32 = n;
497 err = 0;
498 }
499 }
500
501 return err;
502 }
503
504 /* Write the uint32 contained in UINT32 to STREAM. */
505 static gpg_error_t
stream_write_uint32(estream_t stream,u32 uint32)506 stream_write_uint32 (estream_t stream, u32 uint32)
507 {
508 unsigned char buffer[4];
509 gpg_error_t err;
510 int ret;
511
512 buffer[0] = uint32 >> 24;
513 buffer[1] = uint32 >> 16;
514 buffer[2] = uint32 >> 8;
515 buffer[3] = uint32 >> 0;
516
517 ret = es_write (stream, buffer, sizeof (buffer), NULL);
518 if (ret)
519 err = gpg_error_from_syserror ();
520 else
521 err = 0;
522
523 return err;
524 }
525
526 /* Read SIZE bytes from STREAM into BUFFER. */
527 static gpg_error_t
stream_read_data(estream_t stream,unsigned char * buffer,size_t size)528 stream_read_data (estream_t stream, unsigned char *buffer, size_t size)
529 {
530 gpg_error_t err;
531 size_t bytes_read;
532 int ret;
533
534 ret = es_read (stream, buffer, size, &bytes_read);
535 if (ret)
536 err = gpg_error_from_syserror ();
537 else
538 {
539 if (bytes_read != size)
540 err = gpg_error (GPG_ERR_EOF);
541 else
542 err = 0;
543 }
544
545 return err;
546 }
547
548 /* Skip over SIZE bytes from STREAM. */
549 static gpg_error_t
stream_read_skip(estream_t stream,size_t size)550 stream_read_skip (estream_t stream, size_t size)
551 {
552 char buffer[128];
553 size_t bytes_to_read, bytes_read;
554 int ret;
555
556 do
557 {
558 bytes_to_read = size;
559 if (bytes_to_read > sizeof buffer)
560 bytes_to_read = sizeof buffer;
561
562 ret = es_read (stream, buffer, bytes_to_read, &bytes_read);
563 if (ret)
564 return gpg_error_from_syserror ();
565 else if (bytes_read != bytes_to_read)
566 return gpg_error (GPG_ERR_EOF);
567 else
568 size -= bytes_to_read;
569 }
570 while (size);
571
572 return 0;
573 }
574
575
576 /* Write SIZE bytes from BUFFER to STREAM. */
577 static gpg_error_t
stream_write_data(estream_t stream,const unsigned char * buffer,size_t size)578 stream_write_data (estream_t stream, const unsigned char *buffer, size_t size)
579 {
580 gpg_error_t err;
581 int ret;
582
583 ret = es_write (stream, buffer, size, NULL);
584 if (ret)
585 err = gpg_error_from_syserror ();
586 else
587 err = 0;
588
589 return err;
590 }
591
592 /* Read a binary string from STREAM into STRING, store size of string
593 in STRING_SIZE. Append a hidden nul so that the result may
594 directly be used as a C string. Depending on SECURE use secure
595 memory for STRING. If STRING is NULL do only a dummy read. */
596 static gpg_error_t
stream_read_string(estream_t stream,unsigned int secure,unsigned char ** string,u32 * string_size)597 stream_read_string (estream_t stream, unsigned int secure,
598 unsigned char **string, u32 *string_size)
599 {
600 gpg_error_t err;
601 unsigned char *buffer = NULL;
602 u32 length = 0;
603
604 if (string_size)
605 *string_size = 0;
606
607 /* Read string length. */
608 err = stream_read_uint32 (stream, &length);
609 if (err)
610 goto out;
611
612 if (string)
613 {
614 /* Allocate space. */
615 if (secure)
616 buffer = xtrymalloc_secure (length + 1);
617 else
618 buffer = xtrymalloc (length + 1);
619 if (! buffer)
620 {
621 err = gpg_error_from_syserror ();
622 goto out;
623 }
624
625 /* Read data. */
626 err = stream_read_data (stream, buffer, length);
627 if (err)
628 goto out;
629
630 /* Finalize string object. */
631 buffer[length] = 0;
632 *string = buffer;
633 }
634 else /* Dummy read requested. */
635 {
636 err = stream_read_skip (stream, length);
637 if (err)
638 goto out;
639 }
640
641 if (string_size)
642 *string_size = length;
643
644 out:
645
646 if (err)
647 xfree (buffer);
648
649 return err;
650 }
651
652
653 /* Read a binary string from STREAM and store it as an opaque MPI at
654 R_MPI, adding 0x40 (this is the prefix for EdDSA key in OpenPGP).
655 Depending on SECURE use secure memory. If the string is too large
656 for key material return an error. */
657 static gpg_error_t
stream_read_blob(estream_t stream,unsigned int secure,gcry_mpi_t * r_mpi)658 stream_read_blob (estream_t stream, unsigned int secure, gcry_mpi_t *r_mpi)
659 {
660 gpg_error_t err;
661 unsigned char *buffer = NULL;
662 u32 length = 0;
663
664 *r_mpi = NULL;
665
666 /* Read string length. */
667 err = stream_read_uint32 (stream, &length);
668 if (err)
669 goto leave;
670
671 /* To avoid excessive use of secure memory we check that an MPI is
672 not too large. */
673 if (length > (4096/8) + 8)
674 {
675 log_error (_("ssh keys greater than %d bits are not supported\n"), 4096);
676 err = GPG_ERR_TOO_LARGE;
677 goto leave;
678 }
679
680 /* Allocate space. */
681 if (secure)
682 buffer = xtrymalloc_secure (length+1);
683 else
684 buffer = xtrymalloc (length+1);
685 if (!buffer)
686 {
687 err = gpg_error_from_syserror ();
688 goto leave;
689 }
690
691 /* Read data. */
692 err = stream_read_data (stream, buffer + 1, length);
693 if (err)
694 goto leave;
695
696 buffer[0] = 0x40;
697 *r_mpi = gcry_mpi_set_opaque (NULL, buffer, 8*(length+1));
698 buffer = NULL;
699
700 leave:
701 xfree (buffer);
702 return err;
703 }
704
705
706 /* Read a C-string from STREAM, store copy in STRING. */
707 static gpg_error_t
stream_read_cstring(estream_t stream,char ** string)708 stream_read_cstring (estream_t stream, char **string)
709 {
710 return stream_read_string (stream, 0, (unsigned char **)string, NULL);
711 }
712
713
714 /* Write a binary string from STRING of size STRING_N to STREAM. */
715 static gpg_error_t
stream_write_string(estream_t stream,const unsigned char * string,u32 string_n)716 stream_write_string (estream_t stream,
717 const unsigned char *string, u32 string_n)
718 {
719 gpg_error_t err;
720
721 err = stream_write_uint32 (stream, string_n);
722 if (err)
723 goto out;
724
725 err = stream_write_data (stream, string, string_n);
726
727 out:
728
729 return err;
730 }
731
732 /* Write a C-string from STRING to STREAM. */
733 static gpg_error_t
stream_write_cstring(estream_t stream,const char * string)734 stream_write_cstring (estream_t stream, const char *string)
735 {
736 gpg_error_t err;
737
738 err = stream_write_string (stream,
739 (const unsigned char *) string, strlen (string));
740
741 return err;
742 }
743
744 /* Read an MPI from STREAM, store it in MPINT. Depending on SECURE
745 use secure memory. */
746 static gpg_error_t
stream_read_mpi(estream_t stream,unsigned int secure,gcry_mpi_t * mpint)747 stream_read_mpi (estream_t stream, unsigned int secure, gcry_mpi_t *mpint)
748 {
749 unsigned char *mpi_data;
750 u32 mpi_data_size;
751 gpg_error_t err;
752 gcry_mpi_t mpi;
753
754 mpi_data = NULL;
755
756 err = stream_read_string (stream, secure, &mpi_data, &mpi_data_size);
757 if (err)
758 goto out;
759
760 /* To avoid excessive use of secure memory we check that an MPI is
761 not too large. */
762 if (mpi_data_size > 520)
763 {
764 log_error (_("ssh keys greater than %d bits are not supported\n"), 4096);
765 err = GPG_ERR_TOO_LARGE;
766 goto out;
767 }
768
769 err = gcry_mpi_scan (&mpi, GCRYMPI_FMT_STD, mpi_data, mpi_data_size, NULL);
770 if (err)
771 goto out;
772
773 *mpint = mpi;
774
775 out:
776
777 xfree (mpi_data);
778
779 return err;
780 }
781
782 /* Write the MPI contained in MPINT to STREAM. */
783 static gpg_error_t
stream_write_mpi(estream_t stream,gcry_mpi_t mpint)784 stream_write_mpi (estream_t stream, gcry_mpi_t mpint)
785 {
786 unsigned char *mpi_buffer;
787 size_t mpi_buffer_n;
788 gpg_error_t err;
789
790 mpi_buffer = NULL;
791
792 err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &mpi_buffer, &mpi_buffer_n, mpint);
793 if (err)
794 goto out;
795
796 err = stream_write_string (stream, mpi_buffer, mpi_buffer_n);
797
798 out:
799
800 xfree (mpi_buffer);
801
802 return err;
803 }
804
805
806 /* Copy data from SRC to DST until EOF is reached. */
807 static gpg_error_t
stream_copy(estream_t dst,estream_t src)808 stream_copy (estream_t dst, estream_t src)
809 {
810 char buffer[BUFSIZ];
811 size_t bytes_read;
812 gpg_error_t err;
813 int ret;
814
815 err = 0;
816 while (1)
817 {
818 ret = es_read (src, buffer, sizeof (buffer), &bytes_read);
819 if (ret || (! bytes_read))
820 {
821 if (ret)
822 err = gpg_error_from_syserror ();
823 break;
824 }
825 ret = es_write (dst, buffer, bytes_read, NULL);
826 if (ret)
827 {
828 err = gpg_error_from_syserror ();
829 break;
830 }
831 }
832
833 return err;
834 }
835
836 /* Open the ssh control file and create it if not available. With
837 APPEND passed as true the file will be opened in append mode,
838 otherwise in read only mode. On success 0 is returned and a new
839 control file object stored at R_CF. On error an error code is
840 returned and NULL is stored at R_CF. */
841 static gpg_error_t
open_control_file(ssh_control_file_t * r_cf,int append)842 open_control_file (ssh_control_file_t *r_cf, int append)
843 {
844 gpg_error_t err;
845 ssh_control_file_t cf;
846
847 cf = xtrycalloc (1, sizeof *cf);
848 if (!cf)
849 {
850 err = gpg_error_from_syserror ();
851 goto leave;
852 }
853
854 /* Note: As soon as we start to use non blocking functions here
855 (i.e. where Pth might switch threads) we need to employ a
856 mutex. */
857 cf->fname = make_filename_try (gnupg_homedir (), SSH_CONTROL_FILE_NAME, NULL);
858 if (!cf->fname)
859 {
860 err = gpg_error_from_syserror ();
861 goto leave;
862 }
863 /* FIXME: With "a+" we are not able to check whether this will
864 be created and thus the blurb needs to be written first. */
865 cf->fp = es_fopen (cf->fname, append? "a+":"r");
866 if (!cf->fp && errno == ENOENT)
867 {
868 estream_t stream = es_fopen (cf->fname, "wx,mode=-rw-r");
869 if (!stream)
870 {
871 err = gpg_error_from_syserror ();
872 log_error (_("can't create '%s': %s\n"),
873 cf->fname, gpg_strerror (err));
874 goto leave;
875 }
876 es_fputs (sshcontrolblurb, stream);
877 es_fclose (stream);
878 cf->fp = es_fopen (cf->fname, append? "a+":"r");
879 }
880
881 if (!cf->fp)
882 {
883 err = gpg_error_from_syserror ();
884 log_error (_("can't open '%s': %s\n"),
885 cf->fname, gpg_strerror (err));
886 goto leave;
887 }
888
889 err = 0;
890
891 leave:
892 if (err && cf)
893 {
894 if (cf->fp)
895 es_fclose (cf->fp);
896 xfree (cf->fname);
897 xfree (cf);
898 }
899 else
900 *r_cf = cf;
901
902 return err;
903 }
904
905
906 static void
rewind_control_file(ssh_control_file_t cf)907 rewind_control_file (ssh_control_file_t cf)
908 {
909 es_fseek (cf->fp, 0, SEEK_SET);
910 cf->lnr = 0;
911 es_clearerr (cf->fp);
912 }
913
914
915 static void
close_control_file(ssh_control_file_t cf)916 close_control_file (ssh_control_file_t cf)
917 {
918 if (!cf)
919 return;
920 es_fclose (cf->fp);
921 xfree (cf->fname);
922 xfree (cf);
923 }
924
925
926
927 /* Read the next line from the control file and store the data in CF.
928 Returns 0 on success, GPG_ERR_EOF on EOF, or other error codes. */
929 static gpg_error_t
read_control_file_item(ssh_control_file_t cf)930 read_control_file_item (ssh_control_file_t cf)
931 {
932 int c, i, n;
933 char *p, *pend, line[256];
934 long ttl = 0;
935
936 cf->item.valid = 0;
937 es_clearerr (cf->fp);
938
939 do
940 {
941 if (!es_fgets (line, DIM(line)-1, cf->fp) )
942 {
943 if (es_feof (cf->fp))
944 return gpg_error (GPG_ERR_EOF);
945 return gpg_error_from_syserror ();
946 }
947 cf->lnr++;
948
949 if (!*line || line[strlen(line)-1] != '\n')
950 {
951 /* Eat until end of line */
952 while ((c = es_getc (cf->fp)) != EOF && c != '\n')
953 ;
954 return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
955 : GPG_ERR_INCOMPLETE_LINE);
956 }
957
958 /* Allow for empty lines and spaces */
959 for (p=line; spacep (p); p++)
960 ;
961 }
962 while (!*p || *p == '\n' || *p == '#');
963
964 cf->item.disabled = 0;
965 if (*p == '!')
966 {
967 cf->item.disabled = 1;
968 for (p++; spacep (p); p++)
969 ;
970 }
971
972 for (i=0; hexdigitp (p) && i < 40; p++, i++)
973 cf->item.hexgrip[i] = (*p >= 'a'? (*p & 0xdf): *p);
974 cf->item.hexgrip[i] = 0;
975 if (i != 40 || !(spacep (p) || *p == '\n'))
976 {
977 log_error ("%s:%d: invalid formatted line\n", cf->fname, cf->lnr);
978 return gpg_error (GPG_ERR_BAD_DATA);
979 }
980
981 ttl = strtol (p, &pend, 10);
982 p = pend;
983 if (!(spacep (p) || *p == '\n') || (int)ttl < -1)
984 {
985 log_error ("%s:%d: invalid TTL value; assuming 0\n", cf->fname, cf->lnr);
986 cf->item.ttl = 0;
987 }
988 cf->item.ttl = ttl;
989
990 /* Now check for key-value pairs of the form NAME[=VALUE]. */
991 cf->item.confirm = 0;
992 while (*p)
993 {
994 for (; spacep (p) && *p != '\n'; p++)
995 ;
996 if (!*p || *p == '\n')
997 break;
998 n = strcspn (p, "= \t\n");
999 if (p[n] == '=')
1000 {
1001 log_error ("%s:%d: assigning a value to a flag is not yet supported; "
1002 "flag ignored\n", cf->fname, cf->lnr);
1003 p++;
1004 }
1005 else if (n == 7 && !memcmp (p, "confirm", 7))
1006 {
1007 cf->item.confirm = 1;
1008 }
1009 else
1010 log_error ("%s:%d: invalid flag '%.*s'; ignored\n",
1011 cf->fname, cf->lnr, n, p);
1012 p += n;
1013 }
1014
1015 /* log_debug ("%s:%d: grip=%s ttl=%d%s%s\n", */
1016 /* cf->fname, cf->lnr, */
1017 /* cf->item.hexgrip, cf->item.ttl, */
1018 /* cf->item.disabled? " disabled":"", */
1019 /* cf->item.confirm? " confirm":""); */
1020
1021 cf->item.valid = 1;
1022 return 0; /* Okay: valid entry found. */
1023 }
1024
1025
1026
1027 /* Search the control file CF from the beginning until a matching
1028 HEXGRIP is found; return success in this case and store true at
1029 DISABLED if the found key has been disabled. If R_TTL is not NULL
1030 a specified TTL for that key is stored there. If R_CONFIRM is not
1031 NULL it is set to 1 if the key has the confirm flag set. */
1032 static gpg_error_t
search_control_file(ssh_control_file_t cf,const char * hexgrip,int * r_disabled,int * r_ttl,int * r_confirm)1033 search_control_file (ssh_control_file_t cf, const char *hexgrip,
1034 int *r_disabled, int *r_ttl, int *r_confirm)
1035 {
1036 gpg_error_t err;
1037
1038 log_assert (strlen (hexgrip) == 40 );
1039
1040 if (r_disabled)
1041 *r_disabled = 0;
1042 if (r_ttl)
1043 *r_ttl = 0;
1044 if (r_confirm)
1045 *r_confirm = 0;
1046
1047 rewind_control_file (cf);
1048 while (!(err=read_control_file_item (cf)))
1049 {
1050 if (!cf->item.valid)
1051 continue; /* Should not happen. */
1052 if (!strcmp (hexgrip, cf->item.hexgrip))
1053 break;
1054 }
1055 if (!err)
1056 {
1057 if (r_disabled)
1058 *r_disabled = cf->item.disabled;
1059 if (r_ttl)
1060 *r_ttl = cf->item.ttl;
1061 if (r_confirm)
1062 *r_confirm = cf->item.confirm;
1063 }
1064 return err;
1065 }
1066
1067
1068
1069 /* Add an entry to the control file to mark the key with the keygrip
1070 HEXGRIP as usable for SSH; i.e. it will be returned when ssh asks
1071 for it. FMTFPR is the fingerprint string. This function is in
1072 general used to add a key received through the ssh-add function.
1073 We can assume that the user wants to allow ssh using this key. */
1074 static gpg_error_t
add_control_entry(ctrl_t ctrl,ssh_key_type_spec_t * spec,const char * hexgrip,gcry_sexp_t key,int ttl,int confirm)1075 add_control_entry (ctrl_t ctrl, ssh_key_type_spec_t *spec,
1076 const char *hexgrip, gcry_sexp_t key,
1077 int ttl, int confirm)
1078 {
1079 gpg_error_t err;
1080 ssh_control_file_t cf;
1081 int disabled;
1082 char *fpr_md5 = NULL;
1083 char *fpr_sha256 = NULL;
1084
1085 (void)ctrl;
1086
1087 err = open_control_file (&cf, 1);
1088 if (err)
1089 return err;
1090
1091 err = search_control_file (cf, hexgrip, &disabled, NULL, NULL);
1092 if (err && gpg_err_code(err) == GPG_ERR_EOF)
1093 {
1094 struct tm *tp;
1095 time_t atime = time (NULL);
1096
1097 err = ssh_get_fingerprint_string (key, GCRY_MD_MD5, &fpr_md5);
1098 if (err)
1099 goto out;
1100
1101 err = ssh_get_fingerprint_string (key, GCRY_MD_SHA256, &fpr_sha256);
1102 if (err)
1103 goto out;
1104
1105 /* Not yet in the file - add it. Because the file has been
1106 opened in append mode, we simply need to write to it. */
1107 tp = localtime (&atime);
1108 es_fprintf (cf->fp,
1109 ("# %s key added on: %04d-%02d-%02d %02d:%02d:%02d\n"
1110 "# Fingerprints: %s\n"
1111 "# %s\n"
1112 "%s %d%s\n"),
1113 spec->name,
1114 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
1115 tp->tm_hour, tp->tm_min, tp->tm_sec,
1116 fpr_md5, fpr_sha256, hexgrip, ttl, confirm? " confirm":"");
1117
1118 }
1119 out:
1120 xfree (fpr_md5);
1121 xfree (fpr_sha256);
1122 close_control_file (cf);
1123 return 0;
1124 }
1125
1126
1127 /* Scan the sshcontrol file and return the TTL. */
1128 static int
ttl_from_sshcontrol(const char * hexgrip)1129 ttl_from_sshcontrol (const char *hexgrip)
1130 {
1131 ssh_control_file_t cf;
1132 int disabled, ttl;
1133
1134 if (!hexgrip || strlen (hexgrip) != 40)
1135 return 0; /* Wrong input: Use global default. */
1136
1137 if (open_control_file (&cf, 0))
1138 return 0; /* Error: Use the global default TTL. */
1139
1140 if (search_control_file (cf, hexgrip, &disabled, &ttl, NULL)
1141 || disabled)
1142 ttl = 0; /* Use the global default if not found or disabled. */
1143
1144 close_control_file (cf);
1145
1146 return ttl;
1147 }
1148
1149
1150 /* Scan the sshcontrol file and return the confirm flag. */
1151 static int
confirm_flag_from_sshcontrol(const char * hexgrip)1152 confirm_flag_from_sshcontrol (const char *hexgrip)
1153 {
1154 ssh_control_file_t cf;
1155 int disabled, confirm;
1156
1157 if (!hexgrip || strlen (hexgrip) != 40)
1158 return 1; /* Wrong input: Better ask for confirmation. */
1159
1160 if (open_control_file (&cf, 0))
1161 return 1; /* Error: Better ask for confirmation. */
1162
1163 if (search_control_file (cf, hexgrip, &disabled, NULL, &confirm)
1164 || disabled)
1165 confirm = 0; /* If not found or disabled, there is no reason to
1166 ask for confirmation. */
1167
1168 close_control_file (cf);
1169
1170 return confirm;
1171 }
1172
1173
1174
1175
1176 /* Open the ssh control file for reading. This is a public version of
1177 open_control_file. The caller must use ssh_close_control_file to
1178 release the returned handle. */
1179 ssh_control_file_t
ssh_open_control_file(void)1180 ssh_open_control_file (void)
1181 {
1182 ssh_control_file_t cf;
1183
1184 /* Then look at all the registered and non-disabled keys. */
1185 if (open_control_file (&cf, 0))
1186 return NULL;
1187 return cf;
1188 }
1189
1190 /* Close an ssh control file handle. This is the public version of
1191 close_control_file. CF may be NULL. */
1192 void
ssh_close_control_file(ssh_control_file_t cf)1193 ssh_close_control_file (ssh_control_file_t cf)
1194 {
1195 close_control_file (cf);
1196 }
1197
1198 /* Read the next item from the ssh control file. The function returns
1199 0 if a item was read, GPG_ERR_EOF on eof or another error value.
1200 R_HEXGRIP shall either be null or a BUFFER of at least 41 byte.
1201 R_DISABLED, R_TTLm and R_CONFIRM return flags from the control
1202 file; they are only set on success. */
1203 gpg_error_t
ssh_read_control_file(ssh_control_file_t cf,char * r_hexgrip,int * r_disabled,int * r_ttl,int * r_confirm)1204 ssh_read_control_file (ssh_control_file_t cf,
1205 char *r_hexgrip,
1206 int *r_disabled, int *r_ttl, int *r_confirm)
1207 {
1208 gpg_error_t err;
1209
1210 do
1211 err = read_control_file_item (cf);
1212 while (!err && !cf->item.valid);
1213 if (!err)
1214 {
1215 if (r_hexgrip)
1216 strcpy (r_hexgrip, cf->item.hexgrip);
1217 if (r_disabled)
1218 *r_disabled = cf->item.disabled;
1219 if (r_ttl)
1220 *r_ttl = cf->item.ttl;
1221 if (r_confirm)
1222 *r_confirm = cf->item.confirm;
1223 }
1224 return err;
1225 }
1226
1227
1228 /* Search for a key with HEXGRIP in sshcontrol and return all
1229 info. */
1230 gpg_error_t
ssh_search_control_file(ssh_control_file_t cf,const char * hexgrip,int * r_disabled,int * r_ttl,int * r_confirm)1231 ssh_search_control_file (ssh_control_file_t cf,
1232 const char *hexgrip,
1233 int *r_disabled, int *r_ttl, int *r_confirm)
1234 {
1235 gpg_error_t err;
1236 int i;
1237 const char *s;
1238 char uphexgrip[41];
1239
1240 /* We need to make sure that HEXGRIP is all uppercase. The easiest
1241 way to do this and also check its length is by copying to a
1242 second buffer. */
1243 for (i=0, s=hexgrip; i < 40 && *s; s++, i++)
1244 uphexgrip[i] = *s >= 'a'? (*s & 0xdf): *s;
1245 uphexgrip[i] = 0;
1246 if (i != 40)
1247 err = gpg_error (GPG_ERR_INV_LENGTH);
1248 else
1249 err = search_control_file (cf, uphexgrip, r_disabled, r_ttl, r_confirm);
1250 if (gpg_err_code (err) == GPG_ERR_EOF)
1251 err = gpg_error (GPG_ERR_NOT_FOUND);
1252 return err;
1253 }
1254
1255
1256
1257
1258 /*
1259
1260 MPI lists.
1261
1262 */
1263
1264 /* Free the list of MPIs MPI_LIST. */
1265 static void
mpint_list_free(gcry_mpi_t * mpi_list)1266 mpint_list_free (gcry_mpi_t *mpi_list)
1267 {
1268 if (mpi_list)
1269 {
1270 unsigned int i;
1271
1272 for (i = 0; mpi_list[i]; i++)
1273 gcry_mpi_release (mpi_list[i]);
1274 xfree (mpi_list);
1275 }
1276 }
1277
1278 /* Receive key material MPIs from STREAM according to KEY_SPEC;
1279 depending on SECRET expect a public key or secret key. CERT is the
1280 certificate blob used if KEY_SPEC indicates the certificate format;
1281 it needs to be positioned to the end of the nonce. The newly
1282 allocated list of MPIs is stored in MPI_LIST. Returns usual error
1283 code. */
1284 static gpg_error_t
ssh_receive_mpint_list(estream_t stream,int secret,ssh_key_type_spec_t * spec,estream_t cert,gcry_mpi_t ** mpi_list)1285 ssh_receive_mpint_list (estream_t stream, int secret,
1286 ssh_key_type_spec_t *spec, estream_t cert,
1287 gcry_mpi_t **mpi_list)
1288 {
1289 const char *elems_public;
1290 unsigned int elems_n;
1291 const char *elems;
1292 int elem_is_secret;
1293 gcry_mpi_t *mpis = NULL;
1294 gpg_error_t err = 0;
1295 unsigned int i;
1296
1297 if (secret)
1298 elems = spec->elems_key_secret;
1299 else
1300 elems = spec->elems_key_public;
1301 elems_n = strlen (elems);
1302 elems_public = spec->elems_key_public;
1303
1304 /* Check that either both, CERT and the WITH_CERT flag, are given or
1305 none of them. */
1306 if (!(!!(spec->flags & SPEC_FLAG_WITH_CERT) ^ !cert))
1307 {
1308 err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1309 goto out;
1310 }
1311
1312 mpis = xtrycalloc (elems_n + 1, sizeof *mpis );
1313 if (!mpis)
1314 {
1315 err = gpg_error_from_syserror ();
1316 goto out;
1317 }
1318
1319 elem_is_secret = 0;
1320 for (i = 0; i < elems_n; i++)
1321 {
1322 if (secret)
1323 elem_is_secret = !strchr (elems_public, elems[i]);
1324
1325 if (cert && !elem_is_secret)
1326 err = stream_read_mpi (cert, elem_is_secret, &mpis[i]);
1327 else
1328 err = stream_read_mpi (stream, elem_is_secret, &mpis[i]);
1329 if (err)
1330 goto out;
1331 }
1332
1333 *mpi_list = mpis;
1334 mpis = NULL;
1335
1336 out:
1337 if (err)
1338 mpint_list_free (mpis);
1339
1340 return err;
1341 }
1342
1343
1344
1345 /* Key modifier function for RSA. */
1346 static gpg_error_t
ssh_key_modifier_rsa(const char * elems,gcry_mpi_t * mpis)1347 ssh_key_modifier_rsa (const char *elems, gcry_mpi_t *mpis)
1348 {
1349 gcry_mpi_t p;
1350 gcry_mpi_t q;
1351 gcry_mpi_t u;
1352
1353 if (strcmp (elems, "nedupq"))
1354 /* Modifying only necessary for secret keys. */
1355 goto out;
1356
1357 u = mpis[3];
1358 p = mpis[4];
1359 q = mpis[5];
1360
1361 if (gcry_mpi_cmp (p, q) > 0)
1362 {
1363 /* P shall be smaller then Q! Swap primes. iqmp becomes u. */
1364 gcry_mpi_t tmp;
1365
1366 tmp = mpis[4];
1367 mpis[4] = mpis[5];
1368 mpis[5] = tmp;
1369 }
1370 else
1371 /* U needs to be recomputed. */
1372 gcry_mpi_invm (u, p, q);
1373
1374 out:
1375
1376 return 0;
1377 }
1378
1379 /* Signature encoder function for RSA. */
1380 static gpg_error_t
ssh_signature_encoder_rsa(ssh_key_type_spec_t * spec,estream_t signature_blob,gcry_sexp_t s_signature)1381 ssh_signature_encoder_rsa (ssh_key_type_spec_t *spec,
1382 estream_t signature_blob,
1383 gcry_sexp_t s_signature)
1384 {
1385 gpg_error_t err = 0;
1386 gcry_sexp_t valuelist = NULL;
1387 gcry_sexp_t sublist = NULL;
1388 gcry_mpi_t sig_value = NULL;
1389 gcry_mpi_t *mpis = NULL;
1390 const char *elems;
1391 size_t elems_n;
1392 int i;
1393
1394 unsigned char *data;
1395 size_t data_n;
1396 gcry_mpi_t s;
1397
1398 valuelist = gcry_sexp_nth (s_signature, 1);
1399 if (!valuelist)
1400 {
1401 err = gpg_error (GPG_ERR_INV_SEXP);
1402 goto out;
1403 }
1404
1405 elems = spec->elems_signature;
1406 elems_n = strlen (elems);
1407
1408 mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
1409 if (!mpis)
1410 {
1411 err = gpg_error_from_syserror ();
1412 goto out;
1413 }
1414
1415 for (i = 0; i < elems_n; i++)
1416 {
1417 sublist = gcry_sexp_find_token (valuelist, spec->elems_signature + i, 1);
1418 if (!sublist)
1419 {
1420 err = gpg_error (GPG_ERR_INV_SEXP);
1421 break;
1422 }
1423
1424 sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
1425 if (!sig_value)
1426 {
1427 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
1428 break;
1429 }
1430 gcry_sexp_release (sublist);
1431 sublist = NULL;
1432
1433 mpis[i] = sig_value;
1434 }
1435 if (err)
1436 goto out;
1437
1438 /* RSA specific */
1439 s = mpis[0];
1440
1441 err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, s);
1442 if (err)
1443 goto out;
1444
1445 err = stream_write_string (signature_blob, data, data_n);
1446 xfree (data);
1447
1448 out:
1449 gcry_sexp_release (valuelist);
1450 gcry_sexp_release (sublist);
1451 mpint_list_free (mpis);
1452 return err;
1453 }
1454
1455
1456 /* Signature encoder function for DSA. */
1457 static gpg_error_t
ssh_signature_encoder_dsa(ssh_key_type_spec_t * spec,estream_t signature_blob,gcry_sexp_t s_signature)1458 ssh_signature_encoder_dsa (ssh_key_type_spec_t *spec,
1459 estream_t signature_blob,
1460 gcry_sexp_t s_signature)
1461 {
1462 gpg_error_t err = 0;
1463 gcry_sexp_t valuelist = NULL;
1464 gcry_sexp_t sublist = NULL;
1465 gcry_mpi_t sig_value = NULL;
1466 gcry_mpi_t *mpis = NULL;
1467 const char *elems;
1468 size_t elems_n;
1469 int i;
1470
1471 unsigned char buffer[SSH_DSA_SIGNATURE_PADDING * SSH_DSA_SIGNATURE_ELEMS];
1472 unsigned char *data = NULL;
1473 size_t data_n;
1474
1475 valuelist = gcry_sexp_nth (s_signature, 1);
1476 if (!valuelist)
1477 {
1478 err = gpg_error (GPG_ERR_INV_SEXP);
1479 goto out;
1480 }
1481
1482 elems = spec->elems_signature;
1483 elems_n = strlen (elems);
1484
1485 mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
1486 if (!mpis)
1487 {
1488 err = gpg_error_from_syserror ();
1489 goto out;
1490 }
1491
1492 for (i = 0; i < elems_n; i++)
1493 {
1494 sublist = gcry_sexp_find_token (valuelist, spec->elems_signature + i, 1);
1495 if (!sublist)
1496 {
1497 err = gpg_error (GPG_ERR_INV_SEXP);
1498 break;
1499 }
1500
1501 sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
1502 if (!sig_value)
1503 {
1504 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
1505 break;
1506 }
1507 gcry_sexp_release (sublist);
1508 sublist = NULL;
1509
1510 mpis[i] = sig_value;
1511 }
1512 if (err)
1513 goto out;
1514
1515 /* DSA specific code. */
1516
1517 /* FIXME: Why this complicated code? Why collecting both mpis in a
1518 buffer instead of writing them out one after the other? */
1519 for (i = 0; i < 2; i++)
1520 {
1521 err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &data, &data_n, mpis[i]);
1522 if (err)
1523 break;
1524
1525 if (data_n > SSH_DSA_SIGNATURE_PADDING)
1526 {
1527 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
1528 break;
1529 }
1530
1531 memset (buffer + (i * SSH_DSA_SIGNATURE_PADDING), 0,
1532 SSH_DSA_SIGNATURE_PADDING - data_n);
1533 memcpy (buffer + (i * SSH_DSA_SIGNATURE_PADDING)
1534 + (SSH_DSA_SIGNATURE_PADDING - data_n), data, data_n);
1535
1536 xfree (data);
1537 data = NULL;
1538 }
1539 if (err)
1540 goto out;
1541
1542 err = stream_write_string (signature_blob, buffer, sizeof (buffer));
1543
1544 out:
1545 xfree (data);
1546 gcry_sexp_release (valuelist);
1547 gcry_sexp_release (sublist);
1548 mpint_list_free (mpis);
1549 return err;
1550 }
1551
1552
1553 /* Signature encoder function for ECDSA. */
1554 static gpg_error_t
ssh_signature_encoder_ecdsa(ssh_key_type_spec_t * spec,estream_t stream,gcry_sexp_t s_signature)1555 ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec,
1556 estream_t stream, gcry_sexp_t s_signature)
1557 {
1558 gpg_error_t err = 0;
1559 gcry_sexp_t valuelist = NULL;
1560 gcry_sexp_t sublist = NULL;
1561 gcry_mpi_t sig_value = NULL;
1562 gcry_mpi_t *mpis = NULL;
1563 const char *elems;
1564 size_t elems_n;
1565 int i;
1566
1567 unsigned char *data[2] = {NULL, NULL};
1568 size_t data_n[2];
1569 size_t innerlen;
1570
1571 valuelist = gcry_sexp_nth (s_signature, 1);
1572 if (!valuelist)
1573 {
1574 err = gpg_error (GPG_ERR_INV_SEXP);
1575 goto out;
1576 }
1577
1578 elems = spec->elems_signature;
1579 elems_n = strlen (elems);
1580
1581 mpis = xtrycalloc (elems_n + 1, sizeof *mpis);
1582 if (!mpis)
1583 {
1584 err = gpg_error_from_syserror ();
1585 goto out;
1586 }
1587
1588 for (i = 0; i < elems_n; i++)
1589 {
1590 sublist = gcry_sexp_find_token (valuelist, spec->elems_signature + i, 1);
1591 if (!sublist)
1592 {
1593 err = gpg_error (GPG_ERR_INV_SEXP);
1594 break;
1595 }
1596
1597 sig_value = gcry_sexp_nth_mpi (sublist, 1, GCRYMPI_FMT_USG);
1598 if (!sig_value)
1599 {
1600 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
1601 break;
1602 }
1603 gcry_sexp_release (sublist);
1604 sublist = NULL;
1605
1606 mpis[i] = sig_value;
1607 }
1608 if (err)
1609 goto out;
1610
1611 /* ECDSA specific */
1612
1613 innerlen = 0;
1614 for (i = 0; i < DIM(data); i++)
1615 {
1616 err = gcry_mpi_aprint (GCRYMPI_FMT_STD, &data[i], &data_n[i], mpis[i]);
1617 if (err)
1618 goto out;
1619 innerlen += 4 + data_n[i];
1620 }
1621
1622 err = stream_write_uint32 (stream, innerlen);
1623 if (err)
1624 goto out;
1625
1626 for (i = 0; i < DIM(data); i++)
1627 {
1628 err = stream_write_string (stream, data[i], data_n[i]);
1629 if (err)
1630 goto out;
1631 }
1632
1633 out:
1634 for (i = 0; i < DIM(data); i++)
1635 xfree (data[i]);
1636 gcry_sexp_release (valuelist);
1637 gcry_sexp_release (sublist);
1638 mpint_list_free (mpis);
1639 return err;
1640 }
1641
1642
1643 /* Signature encoder function for EdDSA. */
1644 static gpg_error_t
ssh_signature_encoder_eddsa(ssh_key_type_spec_t * spec,estream_t stream,gcry_sexp_t s_signature)1645 ssh_signature_encoder_eddsa (ssh_key_type_spec_t *spec,
1646 estream_t stream, gcry_sexp_t s_signature)
1647 {
1648 gpg_error_t err = 0;
1649 gcry_sexp_t valuelist = NULL;
1650 gcry_sexp_t sublist = NULL;
1651 const char *elems;
1652 size_t elems_n;
1653 int i;
1654
1655 unsigned char *data[2] = {NULL, NULL};
1656 size_t data_n[2];
1657 size_t totallen = 0;
1658
1659 valuelist = gcry_sexp_nth (s_signature, 1);
1660 if (!valuelist)
1661 {
1662 err = gpg_error (GPG_ERR_INV_SEXP);
1663 goto out;
1664 }
1665
1666 elems = spec->elems_signature;
1667 elems_n = strlen (elems);
1668
1669 if (elems_n != DIM(data))
1670 {
1671 err = gpg_error (GPG_ERR_INV_SEXP);
1672 goto out;
1673 }
1674
1675 for (i = 0; i < DIM(data); i++)
1676 {
1677 sublist = gcry_sexp_find_token (valuelist, spec->elems_signature + i, 1);
1678 if (!sublist)
1679 {
1680 err = gpg_error (GPG_ERR_INV_SEXP);
1681 break;
1682 }
1683
1684 data[i] = gcry_sexp_nth_buffer (sublist, 1, &data_n[i]);
1685 if (!data[i])
1686 {
1687 err = gpg_error (GPG_ERR_INTERNAL); /* FIXME? */
1688 break;
1689 }
1690 totallen += data_n[i];
1691 gcry_sexp_release (sublist);
1692 sublist = NULL;
1693 }
1694 if (err)
1695 goto out;
1696
1697 err = stream_write_uint32 (stream, totallen);
1698 if (err)
1699 goto out;
1700
1701 for (i = 0; i < DIM(data); i++)
1702 {
1703 err = stream_write_data (stream, data[i], data_n[i]);
1704 if (err)
1705 goto out;
1706 }
1707
1708 out:
1709 for (i = 0; i < DIM(data); i++)
1710 xfree (data[i]);
1711 gcry_sexp_release (valuelist);
1712 gcry_sexp_release (sublist);
1713 return err;
1714 }
1715
1716
1717 /*
1718 S-Expressions.
1719 */
1720
1721
1722 /* This function constructs a new S-Expression for the key identified
1723 by the KEY_SPEC, SECRET, CURVE_NAME, MPIS, and COMMENT, which is to
1724 be stored at R_SEXP. Returns an error code. */
1725 static gpg_error_t
sexp_key_construct(gcry_sexp_t * r_sexp,ssh_key_type_spec_t key_spec,int secret,const char * curve_name,gcry_mpi_t * mpis,const char * comment)1726 sexp_key_construct (gcry_sexp_t *r_sexp,
1727 ssh_key_type_spec_t key_spec, int secret,
1728 const char *curve_name, gcry_mpi_t *mpis,
1729 const char *comment)
1730 {
1731 gpg_error_t err;
1732 gcry_sexp_t sexp_new = NULL;
1733 void *formatbuf = NULL;
1734 void **arg_list = NULL;
1735 estream_t format = NULL;
1736 char *algo_name = NULL;
1737
1738 if ((key_spec.flags & SPEC_FLAG_IS_EdDSA))
1739 {
1740 /* It is much easier and more readable to use a separate code
1741 path for EdDSA. */
1742 if (!curve_name)
1743 err = gpg_error (GPG_ERR_INV_CURVE);
1744 else if (!mpis[0] || !gcry_mpi_get_flag (mpis[0], GCRYMPI_FLAG_OPAQUE))
1745 err = gpg_error (GPG_ERR_BAD_PUBKEY);
1746 else if (secret
1747 && (!mpis[1]
1748 || !gcry_mpi_get_flag (mpis[1], GCRYMPI_FLAG_OPAQUE)))
1749 err = gpg_error (GPG_ERR_BAD_SECKEY);
1750 else if (secret)
1751 err = gcry_sexp_build (&sexp_new, NULL,
1752 "(private-key(ecc(curve %s)"
1753 "(flags eddsa)(q %m)(d %m))"
1754 "(comment%s))",
1755 curve_name,
1756 mpis[0], mpis[1],
1757 comment? comment:"");
1758 else
1759 err = gcry_sexp_build (&sexp_new, NULL,
1760 "(public-key(ecc(curve %s)"
1761 "(flags eddsa)(q %m))"
1762 "(comment%s))",
1763 curve_name,
1764 mpis[0],
1765 comment? comment:"");
1766 }
1767 else
1768 {
1769 const char *key_identifier[] = { "public-key", "private-key" };
1770 int arg_idx;
1771 const char *elems;
1772 size_t elems_n;
1773 unsigned int i, j;
1774
1775 if (secret)
1776 elems = key_spec.elems_sexp_order;
1777 else
1778 elems = key_spec.elems_key_public;
1779 elems_n = strlen (elems);
1780
1781 format = es_fopenmem (0, "a+b");
1782 if (!format)
1783 {
1784 err = gpg_error_from_syserror ();
1785 goto out;
1786 }
1787
1788 /* Key identifier, algorithm identifier, mpis, comment, and a NULL
1789 as a safeguard. */
1790 arg_list = xtrymalloc (sizeof (*arg_list) * (2 + 1 + elems_n + 1 + 1));
1791 if (!arg_list)
1792 {
1793 err = gpg_error_from_syserror ();
1794 goto out;
1795 }
1796 arg_idx = 0;
1797
1798 es_fputs ("(%s(%s", format);
1799 arg_list[arg_idx++] = &key_identifier[secret];
1800 algo_name = xtrystrdup (gcry_pk_algo_name (key_spec.algo));
1801 if (!algo_name)
1802 {
1803 err = gpg_error_from_syserror ();
1804 goto out;
1805 }
1806 strlwr (algo_name);
1807 arg_list[arg_idx++] = &algo_name;
1808 if (curve_name)
1809 {
1810 es_fputs ("(curve%s)", format);
1811 arg_list[arg_idx++] = &curve_name;
1812 }
1813
1814 for (i = 0; i < elems_n; i++)
1815 {
1816 es_fprintf (format, "(%c%%m)", elems[i]);
1817 if (secret)
1818 {
1819 for (j = 0; j < elems_n; j++)
1820 if (key_spec.elems_key_secret[j] == elems[i])
1821 break;
1822 }
1823 else
1824 j = i;
1825 arg_list[arg_idx++] = &mpis[j];
1826 }
1827 es_fputs (")(comment%s))", format);
1828 arg_list[arg_idx++] = &comment;
1829 arg_list[arg_idx] = NULL;
1830
1831 es_putc (0, format);
1832 if (es_ferror (format))
1833 {
1834 err = gpg_error_from_syserror ();
1835 goto out;
1836 }
1837 if (es_fclose_snatch (format, &formatbuf, NULL))
1838 {
1839 err = gpg_error_from_syserror ();
1840 goto out;
1841 }
1842 format = NULL;
1843
1844 err = gcry_sexp_build_array (&sexp_new, NULL, formatbuf, arg_list);
1845 }
1846
1847 if (!err)
1848 *r_sexp = sexp_new;
1849
1850 out:
1851 es_fclose (format);
1852 xfree (arg_list);
1853 xfree (formatbuf);
1854 xfree (algo_name);
1855
1856 return err;
1857 }
1858
1859
1860 /* This function extracts the key from the s-expression SEXP according
1861 to KEY_SPEC and stores it in ssh format at (R_BLOB, R_BLOBLEN). If
1862 WITH_SECRET is true, the secret key parts are also extracted if
1863 possible. Returns 0 on success or an error code. Note that data
1864 stored at R_BLOB must be freed using es_free! */
1865 static gpg_error_t
ssh_key_to_blob(gcry_sexp_t sexp,int with_secret,ssh_key_type_spec_t key_spec,void ** r_blob,size_t * r_blob_size)1866 ssh_key_to_blob (gcry_sexp_t sexp, int with_secret,
1867 ssh_key_type_spec_t key_spec,
1868 void **r_blob, size_t *r_blob_size)
1869 {
1870 gpg_error_t err = 0;
1871 gcry_sexp_t value_list = NULL;
1872 gcry_sexp_t value_pair = NULL;
1873 estream_t stream = NULL;
1874 void *blob = NULL;
1875 size_t blob_size;
1876 const char *elems, *p_elems;
1877 const char *data;
1878 size_t datalen;
1879
1880 *r_blob = NULL;
1881 *r_blob_size = 0;
1882
1883 stream = es_fopenmem (0, "r+b");
1884 if (!stream)
1885 {
1886 err = gpg_error_from_syserror ();
1887 goto out;
1888 }
1889
1890 /* Get the type of the key expression. */
1891 data = gcry_sexp_nth_data (sexp, 0, &datalen);
1892 if (!data)
1893 {
1894 err = gpg_error (GPG_ERR_INV_SEXP);
1895 goto out;
1896 }
1897
1898 if ((datalen == 10 && !strncmp (data, "public-key", 10))
1899 || (datalen == 21 && !strncmp (data, "protected-private-key", 21))
1900 || (datalen == 20 && !strncmp (data, "shadowed-private-key", 20)))
1901 elems = key_spec.elems_key_public;
1902 else if (datalen == 11 && !strncmp (data, "private-key", 11))
1903 elems = with_secret? key_spec.elems_key_secret : key_spec.elems_key_public;
1904 else
1905 {
1906 err = gpg_error (GPG_ERR_INV_SEXP);
1907 goto out;
1908 }
1909
1910 /* Get key value list. */
1911 value_list = gcry_sexp_cadr (sexp);
1912 if (!value_list)
1913 {
1914 err = gpg_error (GPG_ERR_INV_SEXP);
1915 goto out;
1916 }
1917
1918 /* Write the ssh algorithm identifier. */
1919 if ((key_spec.flags & SPEC_FLAG_IS_ECDSA))
1920 {
1921 /* Map the curve name to the ssh name. */
1922 const char *name, *sshname, *canon_name;
1923
1924 name = gcry_pk_get_curve (sexp, 0, NULL);
1925 if (!name)
1926 {
1927 err = gpg_error (GPG_ERR_INV_CURVE);
1928 goto out;
1929 }
1930
1931 sshname = ssh_identifier_from_curve_name (name, &canon_name);
1932 if (!sshname)
1933 {
1934 err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
1935 goto out;
1936 }
1937 err = stream_write_cstring (stream, sshname);
1938 if (err)
1939 goto out;
1940 err = stream_write_cstring (stream, canon_name);
1941 if (err)
1942 goto out;
1943 }
1944 else
1945 {
1946 /* Note: This is also used for EdDSA. */
1947 err = stream_write_cstring (stream, key_spec.ssh_identifier);
1948 if (err)
1949 goto out;
1950 }
1951
1952 /* Write the parameters. */
1953 for (p_elems = elems; *p_elems; p_elems++)
1954 {
1955 gcry_sexp_release (value_pair);
1956 value_pair = gcry_sexp_find_token (value_list, p_elems, 1);
1957 if (!value_pair)
1958 {
1959 err = gpg_error (GPG_ERR_INV_SEXP);
1960 goto out;
1961 }
1962 if ((key_spec.flags & SPEC_FLAG_IS_EdDSA))
1963 {
1964 data = gcry_sexp_nth_data (value_pair, 1, &datalen);
1965 if (!data)
1966 {
1967 err = gpg_error (GPG_ERR_INV_SEXP);
1968 goto out;
1969 }
1970 if (*p_elems == 'q' && (datalen & 1) && *data == 0x40)
1971 { /* Remove the prefix 0x40. */
1972 data++;
1973 datalen--;
1974 }
1975 err = stream_write_string (stream, data, datalen);
1976 if (err)
1977 goto out;
1978 }
1979 else
1980 {
1981 gcry_mpi_t mpi;
1982
1983 /* Note that we need to use STD format; i.e. prepend a 0x00
1984 to indicate a positive number if the high bit is set. */
1985 mpi = gcry_sexp_nth_mpi (value_pair, 1, GCRYMPI_FMT_STD);
1986 if (!mpi)
1987 {
1988 err = gpg_error (GPG_ERR_INV_SEXP);
1989 goto out;
1990 }
1991 err = stream_write_mpi (stream, mpi);
1992 gcry_mpi_release (mpi);
1993 if (err)
1994 goto out;
1995 }
1996 }
1997
1998 if (es_fclose_snatch (stream, &blob, &blob_size))
1999 {
2000 err = gpg_error_from_syserror ();
2001 goto out;
2002 }
2003 stream = NULL;
2004
2005 *r_blob = blob;
2006 blob = NULL;
2007 *r_blob_size = blob_size;
2008
2009 out:
2010 gcry_sexp_release (value_list);
2011 gcry_sexp_release (value_pair);
2012 es_fclose (stream);
2013 es_free (blob);
2014
2015 return err;
2016 }
2017
2018
2019 /*
2020
2021 Key I/O.
2022
2023 */
2024
2025 /* Search for a key specification entry. If SSH_NAME is not NULL,
2026 search for an entry whose "ssh_name" is equal to SSH_NAME;
2027 otherwise, search for an entry whose algorithm is equal to ALGO.
2028 Store found entry in SPEC on success, return error otherwise. */
2029 static gpg_error_t
ssh_key_type_lookup(const char * ssh_name,int algo,ssh_key_type_spec_t * spec)2030 ssh_key_type_lookup (const char *ssh_name, int algo,
2031 ssh_key_type_spec_t *spec)
2032 {
2033 gpg_error_t err;
2034 unsigned int i;
2035
2036 for (i = 0; i < DIM (ssh_key_types); i++)
2037 if ((ssh_name && (! strcmp (ssh_name, ssh_key_types[i].ssh_identifier)))
2038 || algo == ssh_key_types[i].algo)
2039 break;
2040
2041 if (i == DIM (ssh_key_types))
2042 err = gpg_error (GPG_ERR_NOT_FOUND);
2043 else
2044 {
2045 *spec = ssh_key_types[i];
2046 err = 0;
2047 }
2048
2049 return err;
2050 }
2051
2052
2053 /* Receive a key from STREAM, according to the key specification given
2054 as KEY_SPEC. Depending on SECRET, receive a secret or a public
2055 key. If READ_COMMENT is true, receive a comment string as well.
2056 Constructs a new S-Expression from received data and stores it in
2057 KEY_NEW. Returns zero on success or an error code. */
2058 static gpg_error_t
ssh_receive_key(estream_t stream,gcry_sexp_t * key_new,int secret,int read_comment,ssh_key_type_spec_t * key_spec)2059 ssh_receive_key (estream_t stream, gcry_sexp_t *key_new, int secret,
2060 int read_comment, ssh_key_type_spec_t *key_spec)
2061 {
2062 gpg_error_t err;
2063 char *key_type = NULL;
2064 char *comment = NULL;
2065 estream_t cert = NULL;
2066 gcry_sexp_t key = NULL;
2067 ssh_key_type_spec_t spec;
2068 gcry_mpi_t *mpi_list = NULL;
2069 const char *elems;
2070 const char *curve_name = NULL;
2071
2072
2073 err = stream_read_cstring (stream, &key_type);
2074 if (err)
2075 goto out;
2076
2077 err = ssh_key_type_lookup (key_type, 0, &spec);
2078 if (err)
2079 goto out;
2080
2081 if ((spec.flags & SPEC_FLAG_WITH_CERT))
2082 {
2083 /* This is an OpenSSH certificate+private key. The certificate
2084 is an SSH string and which we store in an estream object. */
2085 unsigned char *buffer;
2086 u32 buflen;
2087 char *cert_key_type;
2088
2089 err = stream_read_string (stream, 0, &buffer, &buflen);
2090 if (err)
2091 goto out;
2092 cert = es_fopenmem_init (0, "rb", buffer, buflen);
2093 xfree (buffer);
2094 if (!cert)
2095 {
2096 err = gpg_error_from_syserror ();
2097 goto out;
2098 }
2099
2100 /* Check that the key type matches. */
2101 err = stream_read_cstring (cert, &cert_key_type);
2102 if (err)
2103 goto out;
2104 if (strcmp (cert_key_type, key_type) )
2105 {
2106 xfree (cert_key_type);
2107 log_error ("key types in received ssh certificate do not match\n");
2108 err = gpg_error (GPG_ERR_INV_CERT_OBJ);
2109 goto out;
2110 }
2111 xfree (cert_key_type);
2112
2113 /* Skip the nonce. */
2114 err = stream_read_string (cert, 0, NULL, NULL);
2115 if (err)
2116 goto out;
2117 }
2118
2119 if ((spec.flags & SPEC_FLAG_IS_EdDSA))
2120 {
2121 /* The format of an EdDSA key is:
2122 * string key_type ("ssh-ed25519")
2123 * string public_key
2124 * string private_key
2125 *
2126 * Note that the private key is the concatenation of the private
2127 * key with the public key. Thus there's are 64 bytes; however
2128 * we only want the real 32 byte private key - Libgcrypt expects
2129 * this.
2130 */
2131
2132 /* For now, it's only Ed25519. In future, Ed448 will come. */
2133 curve_name = "Ed25519";
2134
2135 mpi_list = xtrycalloc (3, sizeof *mpi_list);
2136 if (!mpi_list)
2137 {
2138 err = gpg_error_from_syserror ();
2139 goto out;
2140 }
2141
2142 err = stream_read_blob (cert? cert : stream, 0, &mpi_list[0]);
2143 if (err)
2144 goto out;
2145 if (secret)
2146 {
2147 u32 len = 0;
2148 unsigned char *buffer;
2149
2150 /* Read string length. */
2151 err = stream_read_uint32 (stream, &len);
2152 if (err)
2153 goto out;
2154 if (len != 32 && len != 64)
2155 {
2156 err = gpg_error (GPG_ERR_BAD_SECKEY);
2157 goto out;
2158 }
2159 buffer = xtrymalloc_secure (32);
2160 if (!buffer)
2161 {
2162 err = gpg_error_from_syserror ();
2163 goto out;
2164 }
2165 err = stream_read_data (stream, buffer, 32);
2166 if (err)
2167 {
2168 xfree (buffer);
2169 goto out;
2170 }
2171 mpi_list[1] = gcry_mpi_set_opaque (NULL, buffer, 8*32);
2172 buffer = NULL;
2173 if (len == 64)
2174 {
2175 err = stream_read_skip (stream, 32);
2176 if (err)
2177 goto out;
2178 }
2179 }
2180 }
2181 else if ((spec.flags & SPEC_FLAG_IS_ECDSA))
2182 {
2183 /* The format of an ECDSA key is:
2184 * string key_type ("ecdsa-sha2-nistp256" |
2185 * "ecdsa-sha2-nistp384" |
2186 * "ecdsa-sha2-nistp521" )
2187 * string ecdsa_curve_name
2188 * string ecdsa_public_key
2189 * mpint ecdsa_private
2190 *
2191 * Note that we use the mpint reader instead of the string
2192 * reader for ecsa_public_key. For the certificate variante
2193 * ecdsa_curve_name+ecdsa_public_key are replaced by the
2194 * certificate.
2195 */
2196 unsigned char *buffer;
2197
2198 err = stream_read_string (cert? cert : stream, 0, &buffer, NULL);
2199 if (err)
2200 goto out;
2201 /* Get the canonical name. Should be the same as the read
2202 * string but we use this mapping to validate that name. */
2203 if (!ssh_identifier_from_curve_name (buffer, &curve_name))
2204 {
2205 err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
2206 xfree (buffer);
2207 goto out;
2208 }
2209 xfree (buffer);
2210
2211 err = ssh_receive_mpint_list (stream, secret, &spec, cert, &mpi_list);
2212 if (err)
2213 goto out;
2214 }
2215 else
2216 {
2217 err = ssh_receive_mpint_list (stream, secret, &spec, cert, &mpi_list);
2218 if (err)
2219 goto out;
2220 }
2221
2222 if (read_comment)
2223 {
2224 err = stream_read_cstring (stream, &comment);
2225 if (err)
2226 goto out;
2227 }
2228
2229 if (secret)
2230 elems = spec.elems_key_secret;
2231 else
2232 elems = spec.elems_key_public;
2233
2234 if (spec.key_modifier)
2235 {
2236 err = (*spec.key_modifier) (elems, mpi_list);
2237 if (err)
2238 goto out;
2239 }
2240
2241 err = sexp_key_construct (&key, spec, secret, curve_name, mpi_list,
2242 comment? comment:"");
2243 if (!err)
2244 {
2245 if (key_spec)
2246 *key_spec = spec;
2247 *key_new = key;
2248 }
2249
2250 out:
2251 es_fclose (cert);
2252 mpint_list_free (mpi_list);
2253 xfree (key_type);
2254 xfree (comment);
2255
2256 return err;
2257 }
2258
2259
2260 /* Write the public key from KEY to STREAM in SSH key format. If
2261 OVERRIDE_COMMENT is not NULL, it will be used instead of the
2262 comment stored in the key. */
2263 static gpg_error_t
ssh_send_key_public(estream_t stream,gcry_sexp_t key,const char * override_comment)2264 ssh_send_key_public (estream_t stream, gcry_sexp_t key,
2265 const char *override_comment)
2266 {
2267 ssh_key_type_spec_t spec;
2268 int algo;
2269 char *comment = NULL;
2270 void *blob = NULL;
2271 size_t bloblen;
2272 gpg_error_t err = 0;
2273
2274 algo = get_pk_algo_from_key (key);
2275 if (algo == 0)
2276 goto out;
2277
2278 err = ssh_key_type_lookup (NULL, algo, &spec);
2279 if (err)
2280 goto out;
2281
2282 err = ssh_key_to_blob (key, 0, spec, &blob, &bloblen);
2283 if (err)
2284 goto out;
2285
2286 err = stream_write_string (stream, blob, bloblen);
2287 if (err)
2288 goto out;
2289
2290 if (override_comment)
2291 err = stream_write_cstring (stream, override_comment);
2292 else
2293 {
2294 err = ssh_key_extract_comment (key, &comment);
2295 if (err)
2296 err = stream_write_cstring (stream, "(none)");
2297 else
2298 err = stream_write_cstring (stream, comment);
2299 }
2300 if (err)
2301 goto out;
2302
2303 out:
2304 xfree (comment);
2305 es_free (blob);
2306
2307 return err;
2308 }
2309
2310
2311 /* Read a public key out of BLOB/BLOB_SIZE according to the key
2312 specification given as KEY_SPEC, storing the new key in KEY_PUBLIC.
2313 Returns zero on success or an error code. */
2314 static gpg_error_t
ssh_read_key_public_from_blob(unsigned char * blob,size_t blob_size,gcry_sexp_t * key_public,ssh_key_type_spec_t * key_spec)2315 ssh_read_key_public_from_blob (unsigned char *blob, size_t blob_size,
2316 gcry_sexp_t *key_public,
2317 ssh_key_type_spec_t *key_spec)
2318 {
2319 gpg_error_t err;
2320 estream_t blob_stream;
2321
2322 blob_stream = es_fopenmem (0, "r+b");
2323 if (!blob_stream)
2324 {
2325 err = gpg_error_from_syserror ();
2326 goto out;
2327 }
2328
2329 err = stream_write_data (blob_stream, blob, blob_size);
2330 if (err)
2331 goto out;
2332
2333 err = es_fseek (blob_stream, 0, SEEK_SET);
2334 if (err)
2335 goto out;
2336
2337 err = ssh_receive_key (blob_stream, key_public, 0, 0, key_spec);
2338
2339 out:
2340 es_fclose (blob_stream);
2341 return err;
2342 }
2343
2344
2345
2346 /* This function calculates the key grip for the key contained in the
2347 S-Expression KEY and writes it to BUFFER, which must be large
2348 enough to hold it. Returns usual error code. */
2349 static gpg_error_t
ssh_key_grip(gcry_sexp_t key,unsigned char * buffer)2350 ssh_key_grip (gcry_sexp_t key, unsigned char *buffer)
2351 {
2352 if (!gcry_pk_get_keygrip (key, buffer))
2353 {
2354 gpg_error_t err = gcry_pk_testkey (key);
2355 return err? err : gpg_error (GPG_ERR_INTERNAL);
2356 }
2357
2358 return 0;
2359 }
2360
2361
2362 /* Check whether a key of KEYGRIP on smartcard is available and
2363 whether it has a usable key. Store a copy of that key at R_PK and
2364 return 0. If no key is available store NULL at R_PK and return an
2365 error code. If CARDSN is not NULL, a string with the serial number
2366 of the card will be a malloced and stored there. */
2367 static gpg_error_t
card_key_available(ctrl_t ctrl,const struct card_key_info_s * keyinfo,gcry_sexp_t * r_pk,char ** cardsn)2368 card_key_available (ctrl_t ctrl, const struct card_key_info_s *keyinfo,
2369 gcry_sexp_t *r_pk, char **cardsn)
2370 {
2371 gpg_error_t err;
2372 unsigned char *pkbuf;
2373 size_t pkbuflen;
2374 gcry_sexp_t s_pk;
2375 unsigned char grip[20];
2376
2377 *r_pk = NULL;
2378 if (cardsn)
2379 *cardsn = NULL;
2380
2381 /* Read the public key. */
2382 err = agent_card_readkey (ctrl, keyinfo->keygrip, &pkbuf, NULL);
2383 if (err)
2384 {
2385 if (opt.verbose)
2386 log_info (_("no suitable card key found: %s\n"), gpg_strerror (err));
2387 return err;
2388 }
2389
2390 pkbuflen = gcry_sexp_canon_len (pkbuf, 0, NULL, NULL);
2391 err = gcry_sexp_sscan (&s_pk, NULL, (char*)pkbuf, pkbuflen);
2392 if (err)
2393 {
2394 log_error ("failed to build S-Exp from received card key: %s\n",
2395 gpg_strerror (err));
2396 xfree (pkbuf);
2397 return err;
2398 }
2399
2400 hex2bin (keyinfo->keygrip, grip, sizeof (grip));
2401 if ( agent_key_available (grip) )
2402 {
2403 /* (Shadow)-key is not available in our key storage. */
2404 err = agent_write_shadow_key (grip, keyinfo->serialno,
2405 keyinfo->idstr, pkbuf, 0);
2406 if (err)
2407 {
2408 xfree (pkbuf);
2409 gcry_sexp_release (s_pk);
2410 return err;
2411 }
2412 }
2413
2414 if (cardsn)
2415 {
2416 char *dispsn;
2417
2418 /* If the card handler is able to return a short serialnumber,
2419 use that one, else use the complete serialno. */
2420 if (!agent_card_getattr (ctrl, "$DISPSERIALNO", &dispsn,
2421 keyinfo->keygrip))
2422 {
2423 *cardsn = xtryasprintf ("cardno:%s", dispsn);
2424 xfree (dispsn);
2425 }
2426 else
2427 *cardsn = xtryasprintf ("cardno:%s", keyinfo->serialno);
2428 if (!*cardsn)
2429 {
2430 err = gpg_error_from_syserror ();
2431 xfree (pkbuf);
2432 gcry_sexp_release (s_pk);
2433 return err;
2434 }
2435 }
2436
2437 xfree (pkbuf);
2438 *r_pk = s_pk;
2439 return 0;
2440 }
2441
2442
2443
2444
2445 /*
2446
2447 Request handler. Each handler is provided with a CTRL context, a
2448 REQUEST object and a RESPONSE object. The actual request is to be
2449 read from REQUEST, the response needs to be written to RESPONSE.
2450
2451 */
2452
2453
2454 /* Handler for the "request_identities" command. */
2455 static gpg_error_t
ssh_handler_request_identities(ctrl_t ctrl,estream_t request,estream_t response)2456 ssh_handler_request_identities (ctrl_t ctrl,
2457 estream_t request, estream_t response)
2458 {
2459 u32 key_counter;
2460 estream_t key_blobs;
2461 gcry_sexp_t key_public;
2462 gpg_error_t err;
2463 int ret;
2464 ssh_control_file_t cf = NULL;
2465 gpg_error_t ret_err;
2466
2467 (void)request;
2468
2469 /* Prepare buffer stream. */
2470
2471 key_public = NULL;
2472 key_counter = 0;
2473
2474 key_blobs = es_fopenmem (0, "r+b");
2475 if (! key_blobs)
2476 {
2477 err = gpg_error_from_syserror ();
2478 goto out;
2479 }
2480
2481 /* First check whether a key is currently available in the card
2482 reader - this should be allowed even without being listed in
2483 sshcontrol. */
2484
2485 if (!opt.disable_daemon[DAEMON_SCD])
2486 {
2487 char *serialno;
2488 struct card_key_info_s *keyinfo_list;
2489 struct card_key_info_s *keyinfo;
2490
2491 /* Scan device(s), and get list of KEYGRIP. */
2492 err = agent_card_serialno (ctrl, &serialno, NULL);
2493 if (!err)
2494 {
2495 xfree (serialno);
2496 err = agent_card_keyinfo (ctrl, NULL, GCRY_PK_USAGE_AUTH,
2497 &keyinfo_list);
2498 }
2499
2500 if (err)
2501 {
2502 if (opt.verbose)
2503 log_info (_("error getting list of cards: %s\n"),
2504 gpg_strerror (err));
2505 goto scd_out;
2506 }
2507
2508 for (keyinfo = keyinfo_list; keyinfo; keyinfo = keyinfo->next)
2509 {
2510 char *cardsn;
2511
2512 if (card_key_available (ctrl, keyinfo, &key_public, &cardsn))
2513 continue;
2514
2515 err = ssh_send_key_public (key_blobs, key_public, cardsn);
2516 gcry_sexp_release (key_public);
2517 key_public = NULL;
2518 xfree (cardsn);
2519 if (err)
2520 {
2521 if (opt.verbose)
2522 gcry_log_debugsxp ("pubkey", key_public);
2523 if (gpg_err_code (err) == GPG_ERR_UNKNOWN_CURVE
2524 || gpg_err_code (err) == GPG_ERR_INV_CURVE)
2525 {
2526 /* For example a Brainpool curve or a curve we don't
2527 * support at all but a smartcard lists that curve.
2528 * We ignore them. */
2529 }
2530 else
2531 {
2532 agent_card_free_keyinfo (keyinfo_list);
2533 goto out;
2534 }
2535 }
2536 else
2537 key_counter++;
2538 }
2539
2540 agent_card_free_keyinfo (keyinfo_list);
2541 }
2542
2543 scd_out:
2544 /* Then look at all the registered and non-disabled keys. */
2545 err = open_control_file (&cf, 0);
2546 if (err)
2547 goto out;
2548
2549 while (!read_control_file_item (cf))
2550 {
2551 unsigned char grip[20];
2552
2553 if (!cf->item.valid)
2554 continue; /* Should not happen. */
2555 if (cf->item.disabled)
2556 continue;
2557 log_assert (strlen (cf->item.hexgrip) == 40);
2558 hex2bin (cf->item.hexgrip, grip, sizeof (grip));
2559
2560 err = agent_public_key_from_file (ctrl, grip, &key_public);
2561 if (err)
2562 {
2563 log_error ("%s:%d: key '%s' skipped: %s\n",
2564 cf->fname, cf->lnr, cf->item.hexgrip,
2565 gpg_strerror (err));
2566 continue;
2567 }
2568
2569 err = ssh_send_key_public (key_blobs, key_public, NULL);
2570 if (err)
2571 goto out;
2572 gcry_sexp_release (key_public);
2573 key_public = NULL;
2574
2575 key_counter++;
2576 }
2577 err = 0;
2578
2579 ret = es_fseek (key_blobs, 0, SEEK_SET);
2580 if (ret)
2581 {
2582 err = gpg_error_from_syserror ();
2583 goto out;
2584 }
2585
2586 out:
2587 /* Send response. */
2588
2589 gcry_sexp_release (key_public);
2590
2591 if (!err)
2592 {
2593 ret_err = stream_write_byte (response, SSH_RESPONSE_IDENTITIES_ANSWER);
2594 if (!ret_err)
2595 ret_err = stream_write_uint32 (response, key_counter);
2596 if (!ret_err)
2597 ret_err = stream_copy (response, key_blobs);
2598 }
2599 else
2600 {
2601 log_error ("ssh request identities failed: %s <%s>\n",
2602 gpg_strerror (err), gpg_strsource (err));
2603 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2604 }
2605
2606 es_fclose (key_blobs);
2607 close_control_file (cf);
2608
2609 return ret_err;
2610 }
2611
2612
2613 /* This function hashes the data contained in DATA of size DATA_N
2614 according to the message digest algorithm specified by MD_ALGORITHM
2615 and writes the message digest to HASH, which needs to large enough
2616 for the digest. */
2617 static gpg_error_t
data_hash(unsigned char * data,size_t data_n,int md_algorithm,unsigned char * hash)2618 data_hash (unsigned char *data, size_t data_n,
2619 int md_algorithm, unsigned char *hash)
2620 {
2621 gcry_md_hash_buffer (md_algorithm, hash, data, data_n);
2622
2623 return 0;
2624 }
2625
2626
2627 /* This function signs the data described by CTRL. If HASH is not
2628 NULL, (HASH,HASHLEN) overrides the hash stored in CTRL. This is to
2629 allow the use of signature algorithms that implement the hashing
2630 internally (e.g. Ed25519). On success the created signature is
2631 stored in ssh format at R_SIG and it's size at R_SIGLEN; the caller
2632 must use es_free to release this memory. */
2633 static gpg_error_t
data_sign(ctrl_t ctrl,ssh_key_type_spec_t * spec,const void * hash,size_t hashlen,unsigned char ** r_sig,size_t * r_siglen)2634 data_sign (ctrl_t ctrl, ssh_key_type_spec_t *spec,
2635 const void *hash, size_t hashlen,
2636 unsigned char **r_sig, size_t *r_siglen)
2637 {
2638 gpg_error_t err;
2639 gcry_sexp_t signature_sexp = NULL;
2640 estream_t stream = NULL;
2641 void *blob = NULL;
2642 size_t bloblen;
2643 char hexgrip[40+1];
2644
2645 *r_sig = NULL;
2646 *r_siglen = 0;
2647
2648 /* Quick check to see whether we have a valid keygrip and convert it
2649 to hex. */
2650 if (!ctrl->have_keygrip)
2651 {
2652 err = gpg_error (GPG_ERR_NO_SECKEY);
2653 goto out;
2654 }
2655 bin2hex (ctrl->keygrip, 20, hexgrip);
2656
2657 /* Ask for confirmation if needed. */
2658 if (confirm_flag_from_sshcontrol (hexgrip))
2659 {
2660 gcry_sexp_t key;
2661 char *fpr, *prompt;
2662 char *comment = NULL;
2663
2664 err = agent_raw_key_from_file (ctrl, ctrl->keygrip, &key);
2665 if (err)
2666 goto out;
2667 err = ssh_get_fingerprint_string (key, opt.ssh_fingerprint_digest, &fpr);
2668 if (!err)
2669 {
2670 gcry_sexp_t tmpsxp = gcry_sexp_find_token (key, "comment", 0);
2671 if (tmpsxp)
2672 comment = gcry_sexp_nth_string (tmpsxp, 1);
2673 gcry_sexp_release (tmpsxp);
2674 }
2675 gcry_sexp_release (key);
2676 if (err)
2677 goto out;
2678 prompt = xtryasprintf (L_("An ssh process requested the use of key%%0A"
2679 " %s%%0A"
2680 " (%s)%%0A"
2681 "Do you want to allow this?"),
2682 fpr, comment? comment:"");
2683 xfree (fpr);
2684 gcry_free (comment);
2685 err = agent_get_confirmation (ctrl, prompt, L_("Allow"), L_("Deny"), 0);
2686 xfree (prompt);
2687 if (err)
2688 goto out;
2689 }
2690
2691 /* Create signature. */
2692 ctrl->use_auth_call = 1;
2693 err = agent_pksign_do (ctrl, NULL,
2694 L_("Please enter the passphrase "
2695 "for the ssh key%%0A %F%%0A (%c)"),
2696 &signature_sexp,
2697 CACHE_MODE_SSH, ttl_from_sshcontrol,
2698 hash, hashlen);
2699 ctrl->use_auth_call = 0;
2700 if (err)
2701 goto out;
2702
2703 stream = es_fopenmem (0, "r+b");
2704 if (!stream)
2705 {
2706 err = gpg_error_from_syserror ();
2707 goto out;
2708 }
2709
2710 err = stream_write_cstring (stream, spec->ssh_identifier);
2711 if (err)
2712 goto out;
2713
2714 err = spec->signature_encoder (spec, stream, signature_sexp);
2715 if (err)
2716 goto out;
2717
2718 err = es_fclose_snatch (stream, &blob, &bloblen);
2719 if (err)
2720 goto out;
2721 stream = NULL;
2722
2723 *r_sig = blob; blob = NULL;
2724 *r_siglen = bloblen;
2725
2726 out:
2727 xfree (blob);
2728 es_fclose (stream);
2729 gcry_sexp_release (signature_sexp);
2730
2731 return err;
2732 }
2733
2734
2735 /* Handler for the "sign_request" command. */
2736 static gpg_error_t
ssh_handler_sign_request(ctrl_t ctrl,estream_t request,estream_t response)2737 ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
2738 {
2739 gcry_sexp_t key = NULL;
2740 ssh_key_type_spec_t spec;
2741 unsigned char hash[MAX_DIGEST_LEN];
2742 unsigned int hash_n;
2743 unsigned char key_grip[20];
2744 unsigned char *key_blob = NULL;
2745 u32 key_blob_size;
2746 unsigned char *data = NULL;
2747 unsigned char *sig = NULL;
2748 size_t sig_n;
2749 u32 data_size;
2750 gpg_error_t err;
2751 gpg_error_t ret_err;
2752 int hash_algo;
2753
2754 /* Receive key. */
2755
2756 err = stream_read_string (request, 0, &key_blob, &key_blob_size);
2757 if (err)
2758 goto out;
2759
2760 err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, &spec);
2761 if (err)
2762 goto out;
2763
2764 /* Receive data to sign. */
2765 err = stream_read_string (request, 0, &data, &data_size);
2766 if (err)
2767 goto out;
2768
2769 /* Flag processing. */
2770 {
2771 u32 flags;
2772
2773 err = stream_read_uint32 (request, &flags);
2774 if (err)
2775 goto out;
2776
2777 if (spec.algo == GCRY_PK_RSA)
2778 {
2779 if ((flags & SSH_AGENT_RSA_SHA2_512))
2780 {
2781 flags &= ~SSH_AGENT_RSA_SHA2_512;
2782 spec.ssh_identifier = "rsa-sha2-512";
2783 spec.hash_algo = GCRY_MD_SHA512;
2784 }
2785 if ((flags & SSH_AGENT_RSA_SHA2_256))
2786 {
2787 /* Note: We prefer SHA256 over SHA512. */
2788 flags &= ~SSH_AGENT_RSA_SHA2_256;
2789 spec.ssh_identifier = "rsa-sha2-256";
2790 spec.hash_algo = GCRY_MD_SHA256;
2791 }
2792 }
2793
2794 /* Some flag is present that we do not know about. Note that
2795 * processed or known flags have been cleared at this point. */
2796 if (flags)
2797 {
2798 err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
2799 goto out;
2800 }
2801 }
2802
2803 hash_algo = spec.hash_algo;
2804 if (!hash_algo)
2805 hash_algo = GCRY_MD_SHA1; /* Use the default. */
2806 ctrl->digest.algo = hash_algo;
2807 xfree (ctrl->digest.data);
2808 ctrl->digest.data = NULL;
2809 ctrl->digest.is_pss = 0;
2810 if ((spec.flags & SPEC_FLAG_USE_PKCS1V2))
2811 ctrl->digest.raw_value = 0;
2812 else
2813 ctrl->digest.raw_value = 1;
2814
2815 /* Calculate key grip. */
2816 err = ssh_key_grip (key, key_grip);
2817 if (err)
2818 goto out;
2819 ctrl->have_keygrip = 1;
2820 memcpy (ctrl->keygrip, key_grip, 20);
2821
2822 /* Hash data unless we use EdDSA. */
2823 if ((spec.flags & SPEC_FLAG_IS_EdDSA))
2824 {
2825 ctrl->digest.valuelen = 0;
2826 }
2827 else
2828 {
2829 hash_n = gcry_md_get_algo_dlen (hash_algo);
2830 if (!hash_n)
2831 {
2832 err = gpg_error (GPG_ERR_INTERNAL);
2833 goto out;
2834 }
2835 err = data_hash (data, data_size, hash_algo, hash);
2836 if (err)
2837 goto out;
2838 memcpy (ctrl->digest.value, hash, hash_n);
2839 ctrl->digest.valuelen = hash_n;
2840 }
2841
2842 /* Sign data. */
2843 if ((spec.flags & SPEC_FLAG_IS_EdDSA))
2844 err = data_sign (ctrl, &spec, data, data_size, &sig, &sig_n);
2845 else
2846 err = data_sign (ctrl, &spec, NULL, 0, &sig, &sig_n);
2847
2848 out:
2849 /* Done. */
2850 if (!err)
2851 {
2852 ret_err = stream_write_byte (response, SSH_RESPONSE_SIGN_RESPONSE);
2853 if (ret_err)
2854 goto leave;
2855 ret_err = stream_write_string (response, sig, sig_n);
2856 if (ret_err)
2857 goto leave;
2858 }
2859 else
2860 {
2861 log_error ("ssh sign request failed: %s <%s>\n",
2862 gpg_strerror (err), gpg_strsource (err));
2863 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
2864 if (ret_err)
2865 goto leave;
2866 }
2867
2868 leave:
2869
2870 gcry_sexp_release (key);
2871 xfree (key_blob);
2872 xfree (data);
2873 es_free (sig);
2874
2875 return ret_err;
2876 }
2877
2878
2879 /* This function extracts the comment contained in the key
2880 s-expression KEY and stores a copy in COMMENT. Returns usual error
2881 code. */
2882 static gpg_error_t
ssh_key_extract_comment(gcry_sexp_t key,char ** r_comment)2883 ssh_key_extract_comment (gcry_sexp_t key, char **r_comment)
2884 {
2885 gcry_sexp_t comment_list;
2886
2887 *r_comment = NULL;
2888
2889 comment_list = gcry_sexp_find_token (key, "comment", 0);
2890 if (!comment_list)
2891 return gpg_error (GPG_ERR_INV_SEXP);
2892
2893 *r_comment = gcry_sexp_nth_string (comment_list, 1);
2894 gcry_sexp_release (comment_list);
2895 if (!*r_comment)
2896 return gpg_error (GPG_ERR_INV_SEXP);
2897
2898 return 0;
2899 }
2900
2901
2902 /* This function converts the key contained in the S-Expression KEY
2903 into a buffer, which is protected by the passphrase PASSPHRASE.
2904 If PASSPHRASE is the empty passphrase, the key is not protected.
2905 Returns usual error code. */
2906 static gpg_error_t
ssh_key_to_protected_buffer(gcry_sexp_t key,const char * passphrase,unsigned char ** buffer,size_t * buffer_n)2907 ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase,
2908 unsigned char **buffer, size_t *buffer_n)
2909 {
2910 unsigned char *buffer_new;
2911 unsigned int buffer_new_n;
2912 gpg_error_t err;
2913
2914 buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON, NULL, 0);
2915 buffer_new = xtrymalloc_secure (buffer_new_n);
2916 if (! buffer_new)
2917 {
2918 err = gpg_error_from_syserror ();
2919 goto out;
2920 }
2921
2922 buffer_new_n = gcry_sexp_sprint (key, GCRYSEXP_FMT_CANON,
2923 buffer_new, buffer_new_n);
2924
2925 if (*passphrase)
2926 err = agent_protect (buffer_new, passphrase, buffer, buffer_n, 0, -1);
2927 else
2928 {
2929 /* The key derivation function does not support zero length
2930 * strings. Store key unprotected if the user wishes so. */
2931 *buffer = buffer_new;
2932 *buffer_n = buffer_new_n;
2933 buffer_new = NULL;
2934 err = 0;
2935 }
2936
2937 out:
2938
2939 xfree (buffer_new);
2940
2941 return err;
2942 }
2943
2944
2945
2946 /* Callback function to compare the first entered PIN with the one
2947 currently being entered. */
2948 static gpg_error_t
reenter_compare_cb(struct pin_entry_info_s * pi)2949 reenter_compare_cb (struct pin_entry_info_s *pi)
2950 {
2951 const char *pin1 = pi->check_cb_arg;
2952
2953 if (!strcmp (pin1, pi->pin))
2954 return 0; /* okay */
2955 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
2956 }
2957
2958
2959 /* Store the ssh KEY into our local key storage and protect it after
2960 asking for a passphrase. Cache that passphrase. TTL is the
2961 maximum caching time for that key. If the key already exists in
2962 our key storage, don't do anything. When entering a key also add
2963 an entry to the sshcontrol file. */
2964 static gpg_error_t
ssh_identity_register(ctrl_t ctrl,ssh_key_type_spec_t * spec,gcry_sexp_t key,int ttl,int confirm)2965 ssh_identity_register (ctrl_t ctrl, ssh_key_type_spec_t *spec,
2966 gcry_sexp_t key, int ttl, int confirm)
2967 {
2968 gpg_error_t err;
2969 unsigned char key_grip_raw[20];
2970 char key_grip[41];
2971 unsigned char *buffer = NULL;
2972 size_t buffer_n;
2973 char *description = NULL;
2974 const char *description2 = L_("Please re-enter this passphrase");
2975 char *comment = NULL;
2976 char *key_fpr = NULL;
2977 const char *initial_errtext = NULL;
2978 struct pin_entry_info_s *pi = NULL;
2979 struct pin_entry_info_s *pi2 = NULL;
2980
2981 err = ssh_key_grip (key, key_grip_raw);
2982 if (err)
2983 goto out;
2984
2985 bin2hex (key_grip_raw, 20, key_grip);
2986
2987 err = ssh_get_fingerprint_string (key, opt.ssh_fingerprint_digest, &key_fpr);
2988 if (err)
2989 goto out;
2990
2991 /* Check whether the key is already in our key storage. Don't do
2992 anything then besides (re-)adding it to sshcontrol. */
2993 if ( !agent_key_available (key_grip_raw) )
2994 goto key_exists; /* Yes, key is available. */
2995
2996 err = ssh_key_extract_comment (key, &comment);
2997 if (err)
2998 goto out;
2999
3000 if ( asprintf (&description,
3001 L_("Please enter a passphrase to protect"
3002 " the received secret key%%0A"
3003 " %s%%0A"
3004 " %s%%0A"
3005 "within gpg-agent's key storage"),
3006 key_fpr, comment ? comment : "") < 0)
3007 {
3008 err = gpg_error_from_syserror ();
3009 goto out;
3010 }
3011
3012 pi = gcry_calloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
3013 if (!pi)
3014 {
3015 err = gpg_error_from_syserror ();
3016 goto out;
3017 }
3018 pi2 = gcry_calloc_secure (1, sizeof (*pi2) + MAX_PASSPHRASE_LEN + 1);
3019 if (!pi2)
3020 {
3021 err = gpg_error_from_syserror ();
3022 goto out;
3023 }
3024 pi->max_length = MAX_PASSPHRASE_LEN + 1;
3025 pi->max_tries = 1;
3026 pi->with_repeat = 1;
3027 pi2->max_length = MAX_PASSPHRASE_LEN + 1;
3028 pi2->max_tries = 1;
3029 pi2->check_cb = reenter_compare_cb;
3030 pi2->check_cb_arg = pi->pin;
3031
3032 next_try:
3033 err = agent_askpin (ctrl, description, NULL, initial_errtext, pi, NULL, 0);
3034 initial_errtext = NULL;
3035 if (err)
3036 goto out;
3037
3038 /* Unless the passphrase is empty or the pinentry told us that
3039 it already did the repetition check, ask to confirm it. */
3040 if (*pi->pin && !pi->repeat_okay)
3041 {
3042 err = agent_askpin (ctrl, description2, NULL, NULL, pi2, NULL, 0);
3043 if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
3044 { /* The re-entered one did not match and the user did not
3045 hit cancel. */
3046 initial_errtext = L_("does not match - try again");
3047 goto next_try;
3048 }
3049 }
3050
3051 err = ssh_key_to_protected_buffer (key, pi->pin, &buffer, &buffer_n);
3052 if (err)
3053 goto out;
3054
3055 /* Store this key to our key storage. We do not store a creation
3056 * timestamp because we simply do not know. */
3057 err = agent_write_private_key (key_grip_raw, buffer, buffer_n, 0,
3058 NULL, NULL, 0);
3059 if (err)
3060 goto out;
3061
3062 /* Cache this passphrase. */
3063 err = agent_put_cache (ctrl, key_grip, CACHE_MODE_SSH, pi->pin, ttl);
3064 if (err)
3065 goto out;
3066
3067 key_exists:
3068 /* And add an entry to the sshcontrol file. */
3069 err = add_control_entry (ctrl, spec, key_grip, key, ttl, confirm);
3070
3071
3072 out:
3073 if (pi2 && pi2->max_length)
3074 wipememory (pi2->pin, pi2->max_length);
3075 xfree (pi2);
3076 if (pi && pi->max_length)
3077 wipememory (pi->pin, pi->max_length);
3078 xfree (pi);
3079 xfree (buffer);
3080 xfree (comment);
3081 xfree (key_fpr);
3082 xfree (description);
3083
3084 return err;
3085 }
3086
3087
3088 /* This function removes the key contained in the S-Expression KEY
3089 from the local key storage, in case it exists there. Returns usual
3090 error code. FIXME: this function is a stub. */
3091 static gpg_error_t
ssh_identity_drop(gcry_sexp_t key)3092 ssh_identity_drop (gcry_sexp_t key)
3093 {
3094 unsigned char key_grip[21] = { 0 };
3095 gpg_error_t err;
3096
3097 err = ssh_key_grip (key, key_grip);
3098 if (err)
3099 goto out;
3100
3101 key_grip[sizeof (key_grip) - 1] = 0;
3102
3103 /* FIXME: What to do here - forgetting the passphrase or deleting
3104 the key from key cache? */
3105
3106 out:
3107
3108 return err;
3109 }
3110
3111 /* Handler for the "add_identity" command. */
3112 static gpg_error_t
ssh_handler_add_identity(ctrl_t ctrl,estream_t request,estream_t response)3113 ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
3114 {
3115 gpg_error_t ret_err;
3116 ssh_key_type_spec_t spec;
3117 gpg_error_t err;
3118 gcry_sexp_t key;
3119 unsigned char b;
3120 int confirm;
3121 int ttl;
3122
3123 confirm = 0;
3124 key = NULL;
3125 ttl = 0;
3126
3127 /* FIXME? */
3128 err = ssh_receive_key (request, &key, 1, 1, &spec);
3129 if (err)
3130 goto out;
3131
3132 while (1)
3133 {
3134 err = stream_read_byte (request, &b);
3135 if (err)
3136 {
3137 if (gpg_err_code (err) == GPG_ERR_EOF)
3138 err = 0;
3139 break;
3140 }
3141
3142 switch (b)
3143 {
3144 case SSH_OPT_CONSTRAIN_LIFETIME:
3145 {
3146 u32 n = 0;
3147
3148 err = stream_read_uint32 (request, &n);
3149 if (! err)
3150 ttl = n;
3151 break;
3152 }
3153
3154 case SSH_OPT_CONSTRAIN_CONFIRM:
3155 {
3156 confirm = 1;
3157 break;
3158 }
3159
3160 default:
3161 /* FIXME: log/bad? */
3162 break;
3163 }
3164 }
3165 if (err)
3166 goto out;
3167
3168 err = ssh_identity_register (ctrl, &spec, key, ttl, confirm);
3169
3170 out:
3171
3172 gcry_sexp_release (key);
3173
3174 if (! err)
3175 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
3176 else
3177 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
3178
3179 return ret_err;
3180 }
3181
3182 /* Handler for the "remove_identity" command. */
3183 static gpg_error_t
ssh_handler_remove_identity(ctrl_t ctrl,estream_t request,estream_t response)3184 ssh_handler_remove_identity (ctrl_t ctrl,
3185 estream_t request, estream_t response)
3186 {
3187 unsigned char *key_blob;
3188 u32 key_blob_size;
3189 gcry_sexp_t key;
3190 gpg_error_t ret_err;
3191 gpg_error_t err;
3192
3193 (void)ctrl;
3194
3195 /* Receive key. */
3196
3197 key_blob = NULL;
3198 key = NULL;
3199
3200 err = stream_read_string (request, 0, &key_blob, &key_blob_size);
3201 if (err)
3202 goto out;
3203
3204 err = ssh_read_key_public_from_blob (key_blob, key_blob_size, &key, NULL);
3205 if (err)
3206 goto out;
3207
3208 err = ssh_identity_drop (key);
3209
3210 out:
3211
3212 xfree (key_blob);
3213 gcry_sexp_release (key);
3214
3215 if (! err)
3216 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
3217 else
3218 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
3219
3220 return ret_err;
3221 }
3222
3223 /* FIXME: stub function. Actually useful? */
3224 static gpg_error_t
ssh_identities_remove_all(void)3225 ssh_identities_remove_all (void)
3226 {
3227 gpg_error_t err;
3228
3229 err = 0;
3230
3231 /* FIXME: shall we remove _all_ cache entries or only those
3232 registered through the ssh-agent protocol? */
3233
3234 return err;
3235 }
3236
3237 /* Handler for the "remove_all_identities" command. */
3238 static gpg_error_t
ssh_handler_remove_all_identities(ctrl_t ctrl,estream_t request,estream_t response)3239 ssh_handler_remove_all_identities (ctrl_t ctrl,
3240 estream_t request, estream_t response)
3241 {
3242 gpg_error_t ret_err;
3243 gpg_error_t err;
3244
3245 (void)ctrl;
3246 (void)request;
3247
3248 err = ssh_identities_remove_all ();
3249
3250 if (! err)
3251 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
3252 else
3253 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
3254
3255 return ret_err;
3256 }
3257
3258 /* Lock agent? FIXME: stub function. */
3259 static gpg_error_t
ssh_lock(void)3260 ssh_lock (void)
3261 {
3262 gpg_error_t err;
3263
3264 /* FIXME */
3265 log_error ("ssh-agent's lock command is not implemented\n");
3266 err = 0;
3267
3268 return err;
3269 }
3270
3271 /* Unock agent? FIXME: stub function. */
3272 static gpg_error_t
ssh_unlock(void)3273 ssh_unlock (void)
3274 {
3275 gpg_error_t err;
3276
3277 log_error ("ssh-agent's unlock command is not implemented\n");
3278 err = 0;
3279
3280 return err;
3281 }
3282
3283 /* Handler for the "lock" command. */
3284 static gpg_error_t
ssh_handler_lock(ctrl_t ctrl,estream_t request,estream_t response)3285 ssh_handler_lock (ctrl_t ctrl, estream_t request, estream_t response)
3286 {
3287 gpg_error_t ret_err;
3288 gpg_error_t err;
3289
3290 (void)ctrl;
3291 (void)request;
3292
3293 err = ssh_lock ();
3294
3295 if (! err)
3296 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
3297 else
3298 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
3299
3300 return ret_err;
3301 }
3302
3303 /* Handler for the "unlock" command. */
3304 static gpg_error_t
ssh_handler_unlock(ctrl_t ctrl,estream_t request,estream_t response)3305 ssh_handler_unlock (ctrl_t ctrl, estream_t request, estream_t response)
3306 {
3307 gpg_error_t ret_err;
3308 gpg_error_t err;
3309
3310 (void)ctrl;
3311 (void)request;
3312
3313 err = ssh_unlock ();
3314
3315 if (! err)
3316 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
3317 else
3318 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
3319
3320 return ret_err;
3321 }
3322
3323 /* Handler for the "extension" command. */
3324 static gpg_error_t
ssh_handler_extension(ctrl_t ctrl,estream_t request,estream_t response)3325 ssh_handler_extension (ctrl_t ctrl, estream_t request, estream_t response)
3326 {
3327 gpg_error_t ret_err;
3328 gpg_error_t err;
3329 char *exttype = NULL;
3330 char *name = NULL;
3331 char *value = NULL;
3332
3333 err = stream_read_cstring (request, &exttype);
3334 if (err)
3335 goto leave;
3336
3337 if (opt.verbose)
3338 log_info ("ssh-agent extension '%s' received\n", exttype);
3339 if (!strcmp (exttype, "ssh-env@gnupg.org"))
3340 {
3341 for (;;)
3342 {
3343 xfree (name); name = NULL;
3344 err = stream_read_cstring (request, &name);
3345 if (gpg_err_code (err) == GPG_ERR_EOF)
3346 break; /* ready. */
3347 if (err)
3348 {
3349 if (opt.verbose)
3350 log_error ("error reading ssh-agent env name\n");
3351 goto leave;
3352 }
3353 xfree (value); value = NULL;
3354 err = stream_read_cstring (request, &value);
3355 if (err)
3356 {
3357 if (opt.verbose)
3358 log_error ("error reading ssh-agent env value\n");
3359 goto leave;
3360 }
3361 if (opt.debug)
3362 log_debug ("ssh-agent env '%s'='%s'\n", name, value);
3363 err = session_env_setenv (ctrl->session_env, name,
3364 *value? value : NULL);
3365 if (err)
3366 {
3367 log_error ("error setting ssh-agent env value: %s\n",
3368 gpg_strerror (err));
3369 goto leave;
3370 }
3371 }
3372 err = 0;
3373 }
3374 else if (!strcmp (exttype, "ssh-envnames@gnupg.org"))
3375 {
3376 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
3377 if (!ret_err)
3378 ret_err = stream_write_cstring
3379 (response, session_env_list_stdenvnames (NULL, NULL));
3380 goto finalleave;
3381 }
3382 else
3383 {
3384 if (opt.verbose)
3385 log_info ("ssh-agent extension '%s' not supported\n", exttype);
3386 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
3387 }
3388
3389 leave:
3390 if (!err)
3391 ret_err = stream_write_byte (response, SSH_RESPONSE_SUCCESS);
3392 else
3393 ret_err = stream_write_byte (response, SSH_RESPONSE_FAILURE);
3394 finalleave:
3395 xfree (exttype);
3396 xfree (name);
3397 xfree (value);
3398 return ret_err;
3399 }
3400
3401
3402
3403 /* Return the request specification for the request identified by TYPE
3404 or NULL in case the requested request specification could not be
3405 found. */
3406 static const ssh_request_spec_t *
request_spec_lookup(int type)3407 request_spec_lookup (int type)
3408 {
3409 const ssh_request_spec_t *spec;
3410 unsigned int i;
3411
3412 for (i = 0; i < DIM (request_specs); i++)
3413 if (request_specs[i].type == type)
3414 break;
3415 if (i == DIM (request_specs))
3416 {
3417 if (opt.verbose)
3418 log_info ("ssh request %u is not supported\n", type);
3419 spec = NULL;
3420 }
3421 else
3422 spec = request_specs + i;
3423
3424 return spec;
3425 }
3426
3427 /* Process a single request. The request is read from and the
3428 response is written to STREAM_SOCK. Uses CTRL as context. Returns
3429 zero in case of success, non zero in case of failure. */
3430 static int
ssh_request_process(ctrl_t ctrl,estream_t stream_sock)3431 ssh_request_process (ctrl_t ctrl, estream_t stream_sock)
3432 {
3433 const ssh_request_spec_t *spec;
3434 estream_t response = NULL;
3435 estream_t request = NULL;
3436 unsigned char request_type;
3437 gpg_error_t err;
3438 int send_err = 0;
3439 int ret;
3440 unsigned char *request_data = NULL;
3441 u32 request_data_size;
3442 u32 response_size;
3443
3444 /* Create memory streams for request/response data. The entire
3445 request will be stored in secure memory, since it might contain
3446 secret key material. The response does not have to be stored in
3447 secure memory, since we never give out secret keys.
3448
3449 Note: we only have little secure memory, but there is NO
3450 possibility of DoS here; only trusted clients are allowed to
3451 connect to the agent. What could happen is that the agent
3452 returns out-of-secure-memory errors on requests in case the
3453 agent's owner floods his own agent with many large messages.
3454 -moritz */
3455
3456 /* Retrieve request. */
3457 err = stream_read_string (stream_sock, 1, &request_data, &request_data_size);
3458 if (err)
3459 goto out;
3460
3461 if (opt.verbose > 1)
3462 log_info ("received ssh request of length %u\n",
3463 (unsigned int)request_data_size);
3464
3465 if (! request_data_size)
3466 {
3467 send_err = 1;
3468 goto out;
3469 /* Broken request; FIXME. */
3470 }
3471
3472 request_type = request_data[0];
3473 spec = request_spec_lookup (request_type);
3474 if (! spec)
3475 {
3476 send_err = 1;
3477 goto out;
3478 /* Unknown request; FIXME. */
3479 }
3480
3481 if (spec->secret_input)
3482 request = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+b");
3483 else
3484 request = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+b");
3485 if (! request)
3486 {
3487 err = gpg_error_from_syserror ();
3488 goto out;
3489 }
3490 ret = es_setvbuf (request, NULL, _IONBF, 0);
3491 if (ret)
3492 {
3493 err = gpg_error_from_syserror ();
3494 goto out;
3495 }
3496 err = stream_write_data (request, request_data + 1, request_data_size - 1);
3497 if (err)
3498 goto out;
3499 es_rewind (request);
3500
3501 response = es_fopenmem (0, "r+b");
3502 if (! response)
3503 {
3504 err = gpg_error_from_syserror ();
3505 goto out;
3506 }
3507
3508 if (opt.verbose)
3509 log_info ("ssh request handler for %s (%u) started\n",
3510 spec->identifier, spec->type);
3511
3512 err = (*spec->handler) (ctrl, request, response);
3513
3514 if (opt.verbose)
3515 {
3516 if (err)
3517 log_info ("ssh request handler for %s (%u) failed: %s\n",
3518 spec->identifier, spec->type, gpg_strerror (err));
3519 else
3520 log_info ("ssh request handler for %s (%u) ready\n",
3521 spec->identifier, spec->type);
3522 }
3523
3524 if (err)
3525 {
3526 send_err = 1;
3527 goto out;
3528 }
3529
3530 response_size = es_ftell (response);
3531 if (opt.verbose > 1)
3532 log_info ("sending ssh response of length %u\n",
3533 (unsigned int)response_size);
3534
3535 err = es_fseek (response, 0, SEEK_SET);
3536 if (err)
3537 {
3538 send_err = 1;
3539 goto out;
3540 }
3541
3542 err = stream_write_uint32 (stream_sock, response_size);
3543 if (err)
3544 {
3545 send_err = 1;
3546 goto out;
3547 }
3548
3549 err = stream_copy (stream_sock, response);
3550 if (err)
3551 goto out;
3552
3553 err = es_fflush (stream_sock);
3554 if (err)
3555 goto out;
3556
3557 out:
3558
3559 if (err && es_feof (stream_sock))
3560 log_error ("error occurred while processing request: %s\n",
3561 gpg_strerror (err));
3562
3563 if (send_err)
3564 {
3565 if (opt.verbose > 1)
3566 log_info ("sending ssh error response\n");
3567 err = stream_write_uint32 (stream_sock, 1);
3568 if (err)
3569 goto leave;
3570 err = stream_write_byte (stream_sock, SSH_RESPONSE_FAILURE);
3571 if (err)
3572 goto leave;
3573 }
3574
3575 leave:
3576
3577 es_fclose (request);
3578 es_fclose (response);
3579 xfree (request_data);
3580
3581 return !!err;
3582 }
3583
3584
3585 /* Return the peer's pid. */
3586 static void
get_client_info(int fd,struct peer_info_s * out)3587 get_client_info (int fd, struct peer_info_s *out)
3588 {
3589 pid_t client_pid = (pid_t)(-1);
3590 int client_uid = -1;
3591
3592 #ifdef SO_PEERCRED
3593 {
3594 #ifdef HAVE_STRUCT_SOCKPEERCRED_PID
3595 struct sockpeercred cr;
3596 #else
3597 struct ucred cr;
3598 #endif
3599 socklen_t cl = sizeof cr;
3600
3601 if (!getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
3602 {
3603 #if defined (HAVE_STRUCT_SOCKPEERCRED_PID) || defined (HAVE_STRUCT_UCRED_PID)
3604 client_pid = cr.pid;
3605 client_uid = (int)cr.uid;
3606 #elif defined (HAVE_STRUCT_UCRED_CR_PID)
3607 client_pid = cr.cr_pid;
3608 client_uid = (int)cr.cr_uid;
3609 #else
3610 #error "Unknown SO_PEERCRED struct"
3611 #endif
3612 }
3613 }
3614 #elif defined (LOCAL_PEERPID)
3615 {
3616 socklen_t len = sizeof (pid_t);
3617
3618 getsockopt (fd, SOL_LOCAL, LOCAL_PEERPID, &client_pid, &len);
3619 #if defined (LOCAL_PEERCRED)
3620 {
3621 struct xucred cr;
3622 len = sizeof (struct xucred);
3623
3624 if (!getsockopt (fd, SOL_LOCAL, LOCAL_PEERCRED, &cr, &len))
3625 client_uid = (int)cr.cr_uid;
3626 }
3627 #endif
3628 }
3629 #elif defined (LOCAL_PEEREID)
3630 {
3631 struct unpcbid unp;
3632 socklen_t unpl = sizeof unp;
3633
3634 if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1)
3635 {
3636 client_pid = unp.unp_pid;
3637 client_uid = (int)unp.unp_euid;
3638 }
3639 }
3640 #elif defined (HAVE_GETPEERUCRED)
3641 {
3642 ucred_t *ucred = NULL;
3643
3644 if (getpeerucred (fd, &ucred) != -1)
3645 {
3646 client_pid = ucred_getpid (ucred);
3647 client_uid = (int)ucred_geteuid (ucred);
3648 ucred_free (ucred);
3649 }
3650 }
3651 #else
3652 (void)fd;
3653 #endif
3654
3655 out->pid = (client_pid == (pid_t)(-1)? 0 : (unsigned long)client_pid);
3656 out->uid = client_uid;
3657 }
3658
3659
3660 /* Start serving client on SOCK_CLIENT. */
3661 void
start_command_handler_ssh(ctrl_t ctrl,gnupg_fd_t sock_client)3662 start_command_handler_ssh (ctrl_t ctrl, gnupg_fd_t sock_client)
3663 {
3664 estream_t stream_sock = NULL;
3665 gpg_error_t err;
3666 int ret;
3667 struct peer_info_s peer_info;
3668
3669 err = agent_copy_startup_env (ctrl);
3670 if (err)
3671 goto out;
3672
3673 get_client_info (FD2INT(sock_client), &peer_info);
3674 ctrl->client_pid = peer_info.pid;
3675 ctrl->client_uid = peer_info.uid;
3676
3677 /* Create stream from socket. */
3678 stream_sock = es_fdopen (FD2INT(sock_client), "r+");
3679 if (!stream_sock)
3680 {
3681 err = gpg_error_from_syserror ();
3682 log_error (_("failed to create stream from socket: %s\n"),
3683 gpg_strerror (err));
3684 goto out;
3685 }
3686 /* We have to disable the estream buffering, because the estream
3687 core doesn't know about secure memory. */
3688 ret = es_setvbuf (stream_sock, NULL, _IONBF, 0);
3689 if (ret)
3690 {
3691 err = gpg_error_from_syserror ();
3692 log_error ("failed to disable buffering "
3693 "on socket stream: %s\n", gpg_strerror (err));
3694 goto out;
3695 }
3696
3697 /* Main processing loop. */
3698 while ( !ssh_request_process (ctrl, stream_sock) )
3699 {
3700 /* Check whether we have reached EOF before trying to read
3701 another request. */
3702 int c;
3703
3704 c = es_fgetc (stream_sock);
3705 if (c == EOF)
3706 break;
3707 es_ungetc (c, stream_sock);
3708 }
3709
3710 /* Reset the daemon in case it has been used. */
3711 agent_reset_daemon (ctrl);
3712
3713
3714 out:
3715 if (stream_sock)
3716 es_fclose (stream_sock);
3717 }
3718
3719
3720 #ifdef HAVE_W32_SYSTEM
3721 /* Serve one ssh-agent request. This is used for the Putty support.
3722 REQUEST is the mmapped memory which may be accessed up to a
3723 length of MAXREQLEN. Returns 0 on success which also indicates
3724 that a valid SSH response message is now in REQUEST. */
3725 int
serve_mmapped_ssh_request(ctrl_t ctrl,unsigned char * request,size_t maxreqlen)3726 serve_mmapped_ssh_request (ctrl_t ctrl,
3727 unsigned char *request, size_t maxreqlen)
3728 {
3729 gpg_error_t err;
3730 int send_err = 0;
3731 int valid_response = 0;
3732 const ssh_request_spec_t *spec;
3733 u32 msglen;
3734 estream_t request_stream, response_stream;
3735
3736 if (agent_copy_startup_env (ctrl))
3737 goto leave; /* Error setting up the environment. */
3738
3739 if (maxreqlen < 5)
3740 goto leave; /* Caller error. */
3741
3742 msglen = uint32_construct (request[0], request[1], request[2], request[3]);
3743 if (msglen < 1 || msglen > maxreqlen - 4)
3744 {
3745 log_error ("ssh message len (%u) out of range", (unsigned int)msglen);
3746 goto leave;
3747 }
3748
3749 spec = request_spec_lookup (request[4]);
3750 if (!spec)
3751 {
3752 send_err = 1; /* Unknown request type. */
3753 goto leave;
3754 }
3755
3756 /* Create a stream object with the data part of the request. */
3757 if (spec->secret_input)
3758 request_stream = es_mopen (NULL, 0, 0, 1, realloc_secure, gcry_free, "r+");
3759 else
3760 request_stream = es_mopen (NULL, 0, 0, 1, gcry_realloc, gcry_free, "r+");
3761 if (!request_stream)
3762 {
3763 err = gpg_error_from_syserror ();
3764 goto leave;
3765 }
3766 /* We have to disable the estream buffering, because the estream
3767 core doesn't know about secure memory. */
3768 if (es_setvbuf (request_stream, NULL, _IONBF, 0))
3769 {
3770 err = gpg_error_from_syserror ();
3771 goto leave;
3772 }
3773 /* Copy the request to the stream but omit the request type. */
3774 err = stream_write_data (request_stream, request + 5, msglen - 1);
3775 if (err)
3776 goto leave;
3777 es_rewind (request_stream);
3778
3779 response_stream = es_fopenmem (0, "r+b");
3780 if (!response_stream)
3781 {
3782 err = gpg_error_from_syserror ();
3783 goto leave;
3784 }
3785
3786 if (opt.verbose)
3787 log_info ("ssh request handler for %s (%u) started\n",
3788 spec->identifier, spec->type);
3789
3790 err = (*spec->handler) (ctrl, request_stream, response_stream);
3791
3792 if (opt.verbose)
3793 {
3794 if (err)
3795 log_info ("ssh request handler for %s (%u) failed: %s\n",
3796 spec->identifier, spec->type, gpg_strerror (err));
3797 else
3798 log_info ("ssh request handler for %s (%u) ready\n",
3799 spec->identifier, spec->type);
3800 }
3801
3802 es_fclose (request_stream);
3803 request_stream = NULL;
3804
3805 if (err)
3806 {
3807 send_err = 1;
3808 goto leave;
3809 }
3810
3811 /* Put the response back into the mmapped buffer. */
3812 {
3813 void *response_data;
3814 size_t response_size;
3815
3816 /* NB: In contrast to the request-stream, the response stream
3817 includes the message type byte. */
3818 if (es_fclose_snatch (response_stream, &response_data, &response_size))
3819 {
3820 log_error ("snatching ssh response failed: %s",
3821 gpg_strerror (gpg_error_from_syserror ()));
3822 send_err = 1; /* Ooops. */
3823 goto leave;
3824 }
3825
3826 if (opt.verbose > 1)
3827 log_info ("sending ssh response of length %u\n",
3828 (unsigned int)response_size);
3829 if (response_size > maxreqlen - 4)
3830 {
3831 log_error ("invalid length of the ssh response: %s",
3832 gpg_strerror (GPG_ERR_INTERNAL));
3833 es_free (response_data);
3834 send_err = 1;
3835 goto leave;
3836 }
3837
3838 request[0] = response_size >> 24;
3839 request[1] = response_size >> 16;
3840 request[2] = response_size >> 8;
3841 request[3] = response_size >> 0;
3842 memcpy (request+4, response_data, response_size);
3843 es_free (response_data);
3844 valid_response = 1;
3845 }
3846
3847 leave:
3848 if (send_err)
3849 {
3850 request[0] = 0;
3851 request[1] = 0;
3852 request[2] = 0;
3853 request[3] = 1;
3854 request[4] = SSH_RESPONSE_FAILURE;
3855 valid_response = 1;
3856 }
3857
3858 /* Reset the daemon in case it has been used. */
3859 agent_reset_daemon (ctrl);
3860
3861 return valid_response? 0 : -1;
3862 }
3863 #endif /*HAVE_W32_SYSTEM*/
3864