1 /* $OpenBSD: ssh-agent.c,v 1.292 2022/09/17 10:11:29 djm Exp $ */
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6 * The authentication agent program.
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
14 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <sys/types.h>
40 #include <sys/resource.h>
42 #include <sys/socket.h>
44 #ifdef HAVE_SYS_TIME_H
45 # include <sys/time.h>
50 #include "openbsd-compat/sys-queue.h"
53 #include <openssl/evp.h>
54 #include "openbsd-compat/openssl-compat.h"
91 #include "pathnames.h"
92 #include "ssh-pkcs11.h"
94 #include "myproposal.h"
96 #ifndef DEFAULT_ALLOWED_PROVIDERS
97 # define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/local/lib*/*"
100 /* Maximum accepted message length */
101 #define AGENT_MAX_LEN (256*1024)
102 /* Maximum bytes to read from client socket */
103 #define AGENT_RBUF_LEN (4096)
104 /* Maximum number of recorded session IDs/hostkeys per connection */
105 #define AGENT_MAX_SESSION_IDS 16
106 /* Maximum size of session ID */
107 #define AGENT_MAX_SID_LEN 128
108 /* Maximum number of destination constraints to accept on a key */
109 #define AGENT_MAX_DEST_CONSTRAINTS 1024
111 /* XXX store hostkey_sid in a refcounted tree */
125 typedef struct socket_entry
{
128 struct sshbuf
*input
;
129 struct sshbuf
*output
;
130 struct sshbuf
*request
;
132 struct hostkey_sid
*session_ids
;
135 u_int sockets_alloc
= 0;
136 SocketEntry
*sockets
= NULL
;
138 typedef struct identity
{
139 TAILQ_ENTRY(identity
) next
;
146 struct dest_constraint
*dest_constraints
;
147 size_t ndest_constraints
;
152 TAILQ_HEAD(idqueue
, identity
) idlist
;
155 /* private key table */
156 struct idtable
*idtab
;
160 /* pid of shell == parent of agent */
161 pid_t parent_pid
= -1;
162 time_t parent_alive_interval
= 0;
164 /* pid of process for which cleanup_socket is applicable */
165 pid_t cleanup_pid
= 0;
167 /* pathname and directory for AUTH_SOCKET */
168 char socket_name
[PATH_MAX
];
169 char socket_dir
[PATH_MAX
];
171 /* Pattern-list of allowed PKCS#11/Security key paths */
172 static char *allowed_providers
;
176 #define LOCK_SALT_SIZE 16
177 #define LOCK_ROUNDS 1
179 u_char lock_pwhash
[LOCK_SIZE
];
180 u_char lock_salt
[LOCK_SALT_SIZE
];
182 extern char *__progname
;
184 /* Default lifetime in seconds (0 == forever) */
185 static int lifetime
= 0;
187 static int fingerprint_hash
= SSH_FP_HASH_DEFAULT
;
189 /* Refuse signing of non-SSH messages for web-origin FIDO keys */
190 static int restrict_websafe
= 1;
193 close_socket(SocketEntry
*e
)
198 sshbuf_free(e
->input
);
199 sshbuf_free(e
->output
);
200 sshbuf_free(e
->request
);
201 for (i
= 0; i
< e
->nsession_ids
; i
++) {
202 sshkey_free(e
->session_ids
[i
].key
);
203 sshbuf_free(e
->session_ids
[i
].sid
);
205 free(e
->session_ids
);
206 memset(e
, '\0', sizeof(*e
));
208 e
->type
= AUTH_UNUSED
;
214 idtab
= xcalloc(1, sizeof(*idtab
));
215 TAILQ_INIT(&idtab
->idlist
);
220 free_dest_constraint_hop(struct dest_constraint_hop
*dch
)
228 for (i
= 0; i
< dch
->nkeys
; i
++)
229 sshkey_free(dch
->keys
[i
]);
231 free(dch
->key_is_ca
);
235 free_dest_constraints(struct dest_constraint
*dcs
, size_t ndcs
)
239 for (i
= 0; i
< ndcs
; i
++) {
240 free_dest_constraint_hop(&dcs
[i
].from
);
241 free_dest_constraint_hop(&dcs
[i
].to
);
247 free_identity(Identity
*id
)
249 sshkey_free(id
->key
);
252 free(id
->sk_provider
);
253 free_dest_constraints(id
->dest_constraints
, id
->ndest_constraints
);
258 * Match 'key' against the key/CA list in a destination constraint hop
259 * Returns 0 on success or -1 otherwise.
262 match_key_hop(const char *tag
, const struct sshkey
*key
,
263 const struct dest_constraint_hop
*dch
)
265 const char *reason
= NULL
;
266 const char *hostname
= dch
->hostname
? dch
->hostname
: "(ORIGIN)";
273 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
274 SSH_FP_DEFAULT
)) == NULL
)
275 fatal_f("fingerprint failed");
276 debug3_f("%s: entering hostname %s, requested key %s %s, %u keys avail",
277 tag
, hostname
, sshkey_type(key
), fp
, dch
->nkeys
);
279 for (i
= 0; i
< dch
->nkeys
; i
++) {
280 if (dch
->keys
[i
] == NULL
)
283 if ((fp
= sshkey_fingerprint(dch
->keys
[i
], SSH_FP_HASH_DEFAULT
,
284 SSH_FP_DEFAULT
)) == NULL
)
285 fatal_f("fingerprint failed");
286 debug3_f("%s: key %u: %s%s %s", tag
, i
,
287 dch
->key_is_ca
[i
] ? "CA " : "",
288 sshkey_type(dch
->keys
[i
]), fp
);
290 if (!sshkey_is_cert(key
)) {
292 if (dch
->key_is_ca
[i
] ||
293 !sshkey_equal(key
, dch
->keys
[i
]))
298 if (!dch
->key_is_ca
[i
])
300 if (key
->cert
== NULL
|| key
->cert
->signature_key
== NULL
)
301 return -1; /* shouldn't happen */
302 if (!sshkey_equal(key
->cert
->signature_key
, dch
->keys
[i
]))
304 if (sshkey_cert_check_host(key
, hostname
, 1,
305 SSH_ALLOWED_CA_SIGALGS
, &reason
) != 0) {
306 debug_f("cert %s / hostname %s rejected: %s",
307 key
->cert
->key_id
, hostname
, reason
);
315 /* Check destination constraints on an identity against the hostkey/user */
317 permitted_by_dest_constraints(const struct sshkey
*fromkey
,
318 const struct sshkey
*tokey
, Identity
*id
, const char *user
,
319 const char **hostnamep
)
322 struct dest_constraint
*d
;
324 if (hostnamep
!= NULL
)
326 for (i
= 0; i
< id
->ndest_constraints
; i
++) {
327 d
= id
->dest_constraints
+ i
;
328 /* XXX remove logspam */
329 debug2_f("constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)",
330 i
, d
->from
.user
? d
->from
.user
: "",
331 d
->from
.user
? "@" : "",
332 d
->from
.hostname
? d
->from
.hostname
: "(ORIGIN)",
334 d
->to
.user
? d
->to
.user
: "", d
->to
.user
? "@" : "",
335 d
->to
.hostname
? d
->to
.hostname
: "(ANY)", d
->to
.nkeys
);
337 /* Match 'from' key */
338 if (fromkey
== NULL
) {
339 /* We are matching the first hop */
340 if (d
->from
.hostname
!= NULL
|| d
->from
.nkeys
!= 0)
342 } else if (match_key_hop("from", fromkey
, &d
->from
) != 0)
346 if (tokey
!= NULL
&& match_key_hop("to", tokey
, &d
->to
) != 0)
349 /* Match user if specified */
350 if (d
->to
.user
!= NULL
&& user
!= NULL
&&
351 !match_pattern(user
, d
->to
.user
))
354 /* successfully matched this constraint */
355 if (hostnamep
!= NULL
)
356 *hostnamep
= d
->to
.hostname
;
357 debug2_f("allowed for hostname %s",
358 d
->to
.hostname
== NULL
? "*" : d
->to
.hostname
);
362 debug2_f("%s identity \"%s\" not permitted for this destination",
363 sshkey_type(id
->key
), id
->comment
);
368 * Check whether hostkeys on a SocketEntry and the optionally specified user
369 * are permitted by the destination constraints on the Identity.
370 * Returns 0 on success or -1 otherwise.
373 identity_permitted(Identity
*id
, SocketEntry
*e
, char *user
,
374 const char **forward_hostnamep
, const char **last_hostnamep
)
378 struct hostkey_sid
*hks
;
379 const struct sshkey
*fromkey
= NULL
;
380 const char *test_user
;
383 /* XXX remove logspam */
384 debug3_f("entering: key %s comment \"%s\", %zu socket bindings, "
385 "%zu constraints", sshkey_type(id
->key
), id
->comment
,
386 e
->nsession_ids
, id
->ndest_constraints
);
387 if (id
->ndest_constraints
== 0)
388 return 0; /* unconstrained */
389 if (e
->nsession_ids
== 0)
390 return 0; /* local use */
392 * Walk through the hops recorded by session_id and try to find a
393 * constraint that satisfies each.
395 for (i
= 0; i
< e
->nsession_ids
; i
++) {
396 hks
= e
->session_ids
+ i
;
397 if (hks
->key
== NULL
)
398 fatal_f("internal error: no bound key");
399 /* XXX remove logspam */
401 if (fromkey
!= NULL
&&
402 (fp1
= sshkey_fingerprint(fromkey
, SSH_FP_HASH_DEFAULT
,
403 SSH_FP_DEFAULT
)) == NULL
)
404 fatal_f("fingerprint failed");
405 if ((fp2
= sshkey_fingerprint(hks
->key
, SSH_FP_HASH_DEFAULT
,
406 SSH_FP_DEFAULT
)) == NULL
)
407 fatal_f("fingerprint failed");
408 debug3_f("socketentry fd=%d, entry %zu %s, "
409 "from hostkey %s %s to user %s hostkey %s %s",
410 e
->fd
, i
, hks
->forwarded
? "FORWARD" : "AUTH",
411 fromkey
? sshkey_type(fromkey
) : "(ORIGIN)",
412 fromkey
? fp1
: "", user
? user
: "(ANY)",
413 sshkey_type(hks
->key
), fp2
);
417 * Record the hostnames for the initial forwarding and
418 * the final destination.
421 if (i
== e
->nsession_ids
- 1)
424 hp
= forward_hostnamep
;
425 /* Special handling for final recorded binding */
427 if (i
== e
->nsession_ids
- 1) {
428 /* Can only check user at final hop */
431 * user is only presented for signature requests.
432 * If this is the case, make sure last binding is not
435 if (hks
->forwarded
&& user
!= NULL
) {
436 error_f("tried to sign on forwarding hop");
439 } else if (!hks
->forwarded
) {
440 error_f("tried to forward though signing bind");
443 if (permitted_by_dest_constraints(fromkey
, hks
->key
, id
,
449 * Another special case: if the last bound session ID was for a
450 * forwarding, and this function is not being called to check a sign
451 * request (i.e. no 'user' supplied), then only permit the key if
452 * there is a permission that would allow it to be used at another
453 * destination. This hides keys that are allowed to be used to
454 * authenticate *to* a host but not permitted for *use* beyond it.
456 hks
= &e
->session_ids
[e
->nsession_ids
- 1];
457 if (hks
->forwarded
&& user
== NULL
&&
458 permitted_by_dest_constraints(hks
->key
, NULL
, id
,
460 debug3_f("key permitted at host but not after");
468 /* return matching private key for given public key */
470 lookup_identity(struct sshkey
*key
)
474 TAILQ_FOREACH(id
, &idtab
->idlist
, next
) {
475 if (sshkey_equal(key
, id
->key
))
481 /* Check confirmation of keysign request */
483 confirm_key(Identity
*id
, const char *extra
)
488 p
= sshkey_fingerprint(id
->key
, fingerprint_hash
, SSH_FP_DEFAULT
);
490 ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s",
492 extra
== NULL
? "" : "\n", extra
== NULL
? "" : extra
))
500 send_status(SocketEntry
*e
, int success
)
504 if ((r
= sshbuf_put_u32(e
->output
, 1)) != 0 ||
505 (r
= sshbuf_put_u8(e
->output
, success
?
506 SSH_AGENT_SUCCESS
: SSH_AGENT_FAILURE
)) != 0)
507 fatal_fr(r
, "compose");
510 /* send list of supported public keys to 'client' */
512 process_request_identities(SocketEntry
*e
)
515 struct sshbuf
*msg
, *keys
;
519 debug2_f("entering");
521 if ((msg
= sshbuf_new()) == NULL
|| (keys
= sshbuf_new()) == NULL
)
522 fatal_f("sshbuf_new failed");
523 TAILQ_FOREACH(id
, &idtab
->idlist
, next
) {
524 /* identity not visible, don't include in response */
525 if (identity_permitted(id
, e
, NULL
, NULL
, NULL
) != 0)
527 if ((r
= sshkey_puts_opts(id
->key
, keys
,
528 SSHKEY_SERIALIZE_INFO
)) != 0 ||
529 (r
= sshbuf_put_cstring(keys
, id
->comment
)) != 0) {
530 error_fr(r
, "compose key/comment");
535 debug2_f("replying with %u allowed of %u available keys",
536 nentries
, idtab
->nentries
);
537 if ((r
= sshbuf_put_u8(msg
, SSH2_AGENT_IDENTITIES_ANSWER
)) != 0 ||
538 (r
= sshbuf_put_u32(msg
, nentries
)) != 0 ||
539 (r
= sshbuf_putb(msg
, keys
)) != 0)
540 fatal_fr(r
, "compose");
541 if ((r
= sshbuf_put_stringb(e
->output
, msg
)) != 0)
542 fatal_fr(r
, "enqueue");
549 agent_decode_alg(struct sshkey
*key
, u_int flags
)
551 if (key
->type
== KEY_RSA
) {
552 if (flags
& SSH_AGENT_RSA_SHA2_256
)
553 return "rsa-sha2-256";
554 else if (flags
& SSH_AGENT_RSA_SHA2_512
)
555 return "rsa-sha2-512";
556 } else if (key
->type
== KEY_RSA_CERT
) {
557 if (flags
& SSH_AGENT_RSA_SHA2_256
)
558 return "rsa-sha2-256-cert-v01@openssh.com";
559 else if (flags
& SSH_AGENT_RSA_SHA2_512
)
560 return "rsa-sha2-512-cert-v01@openssh.com";
566 * Attempt to parse the contents of a buffer as a SSH publickey userauth
567 * request, checking its contents for consistency and matching the embedded
568 * key against the one that is being used for signing.
569 * Note: does not modify msg buffer.
570 * Optionally extract the username, session ID and/or hostkey from the request.
573 parse_userauth_request(struct sshbuf
*msg
, const struct sshkey
*expected_key
,
574 char **userp
, struct sshbuf
**sess_idp
, struct sshkey
**hostkeyp
)
576 struct sshbuf
*b
= NULL
, *sess_id
= NULL
;
577 char *user
= NULL
, *service
= NULL
, *method
= NULL
, *pkalg
= NULL
;
579 u_char t
, sig_follows
;
580 struct sshkey
*mkey
= NULL
, *hostkey
= NULL
;
584 if (sess_idp
!= NULL
)
586 if (hostkeyp
!= NULL
)
588 if ((b
= sshbuf_fromb(msg
)) == NULL
)
589 fatal_f("sshbuf_fromb");
591 /* SSH userauth request */
592 if ((r
= sshbuf_froms(b
, &sess_id
)) != 0)
594 if (sshbuf_len(sess_id
) == 0) {
595 r
= SSH_ERR_INVALID_FORMAT
;
598 if ((r
= sshbuf_get_u8(b
, &t
)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */
599 (r
= sshbuf_get_cstring(b
, &user
, NULL
)) != 0 || /* server user */
600 (r
= sshbuf_get_cstring(b
, &service
, NULL
)) != 0 || /* service */
601 (r
= sshbuf_get_cstring(b
, &method
, NULL
)) != 0 || /* method */
602 (r
= sshbuf_get_u8(b
, &sig_follows
)) != 0 || /* sig-follows */
603 (r
= sshbuf_get_cstring(b
, &pkalg
, NULL
)) != 0 || /* alg */
604 (r
= sshkey_froms(b
, &mkey
)) != 0) /* key */
606 if (t
!= SSH2_MSG_USERAUTH_REQUEST
||
608 strcmp(service
, "ssh-connection") != 0 ||
609 !sshkey_equal(expected_key
, mkey
) ||
610 sshkey_type_from_name(pkalg
) != expected_key
->type
) {
611 r
= SSH_ERR_INVALID_FORMAT
;
614 if (strcmp(method
, "publickey-hostbound-v00@openssh.com") == 0) {
615 if ((r
= sshkey_froms(b
, &hostkey
)) != 0)
617 } else if (strcmp(method
, "publickey") != 0) {
618 r
= SSH_ERR_INVALID_FORMAT
;
621 if (sshbuf_len(b
) != 0) {
622 r
= SSH_ERR_INVALID_FORMAT
;
627 debug3_f("well formed userauth");
632 if (sess_idp
!= NULL
) {
636 if (hostkeyp
!= NULL
) {
642 sshbuf_free(sess_id
);
648 sshkey_free(hostkey
);
653 * Attempt to parse the contents of a buffer as a SSHSIG signature request.
654 * Note: does not modify buffer.
657 parse_sshsig_request(struct sshbuf
*msg
)
662 if ((b
= sshbuf_fromb(msg
)) == NULL
)
663 fatal_f("sshbuf_fromb");
665 if ((r
= sshbuf_cmp(b
, 0, "SSHSIG", 6)) != 0 ||
666 (r
= sshbuf_consume(b
, 6)) != 0 ||
667 (r
= sshbuf_get_cstring(b
, NULL
, NULL
)) != 0 || /* namespace */
668 (r
= sshbuf_get_string_direct(b
, NULL
, NULL
)) != 0 || /* reserved */
669 (r
= sshbuf_get_cstring(b
, NULL
, NULL
)) != 0 || /* hashalg */
670 (r
= sshbuf_get_string_direct(b
, NULL
, NULL
)) != 0) /* H(msg) */
672 if (sshbuf_len(b
) != 0) {
673 r
= SSH_ERR_INVALID_FORMAT
;
684 * This function inspects a message to be signed by a FIDO key that has a
685 * web-like application string (i.e. one that does not begin with "ssh:".
686 * It checks that the message is one of those expected for SSH operations
687 * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
691 check_websafe_message_contents(struct sshkey
*key
, struct sshbuf
*data
)
693 if (parse_userauth_request(data
, key
, NULL
, NULL
, NULL
) == 0) {
694 debug_f("signed data matches public key userauth request");
697 if (parse_sshsig_request(data
) == 0) {
698 debug_f("signed data matches SSHSIG signature request");
702 /* XXX check CA signature operation */
704 error("web-origin key attempting to sign non-SSH message");
709 buf_equal(const struct sshbuf
*a
, const struct sshbuf
*b
)
711 if (sshbuf_ptr(a
) == NULL
|| sshbuf_ptr(b
) == NULL
)
712 return SSH_ERR_INVALID_ARGUMENT
;
713 if (sshbuf_len(a
) != sshbuf_len(b
))
714 return SSH_ERR_INVALID_FORMAT
;
715 if (timingsafe_bcmp(sshbuf_ptr(a
), sshbuf_ptr(b
), sshbuf_len(a
)) != 0)
716 return SSH_ERR_INVALID_FORMAT
;
722 process_sign_request2(SocketEntry
*e
)
724 u_char
*signature
= NULL
;
726 u_int compat
= 0, flags
;
727 int r
, ok
= -1, retried
= 0;
728 char *fp
= NULL
, *pin
= NULL
, *prompt
= NULL
;
729 char *user
= NULL
, *sig_dest
= NULL
;
730 const char *fwd_host
= NULL
, *dest_host
= NULL
;
731 struct sshbuf
*msg
= NULL
, *data
= NULL
, *sid
= NULL
;
732 struct sshkey
*key
= NULL
, *hostkey
= NULL
;
734 struct notifier_ctx
*notifier
= NULL
;
738 if ((msg
= sshbuf_new()) == NULL
|| (data
= sshbuf_new()) == NULL
)
739 fatal_f("sshbuf_new failed");
740 if ((r
= sshkey_froms(e
->request
, &key
)) != 0 ||
741 (r
= sshbuf_get_stringb(e
->request
, data
)) != 0 ||
742 (r
= sshbuf_get_u32(e
->request
, &flags
)) != 0) {
743 error_fr(r
, "parse");
747 if ((id
= lookup_identity(key
)) == NULL
) {
748 verbose_f("%s key not found", sshkey_type(key
));
751 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
752 SSH_FP_DEFAULT
)) == NULL
)
753 fatal_f("fingerprint failed");
755 if (id
->ndest_constraints
!= 0) {
756 if (e
->nsession_ids
== 0) {
757 logit_f("refusing use of destination-constrained key "
758 "to sign on unbound connection");
761 if (parse_userauth_request(data
, key
, &user
, &sid
,
763 logit_f("refusing use of destination-constrained key "
764 "to sign an unidentified signature");
768 debug_f("user=%s", user
);
769 if (identity_permitted(id
, e
, user
, &fwd_host
, &dest_host
) != 0)
771 /* XXX display fwd_host/dest_host in askpass UI */
773 * Ensure that the session ID is the most recent one
774 * registered on the socket - it should have been bound by
775 * ssh immediately before userauth.
778 e
->session_ids
[e
->nsession_ids
- 1].sid
) != 0) {
779 error_f("unexpected session ID (%zu listed) on "
780 "signature request for target user %s with "
781 "key %s %s", e
->nsession_ids
, user
,
782 sshkey_type(id
->key
), fp
);
786 * Ensure that the hostkey embedded in the signature matches
787 * the one most recently bound to the socket. An exception is
788 * made for the initial forwarding hop.
790 if (e
->nsession_ids
> 1 && hostkey
== NULL
) {
791 error_f("refusing use of destination-constrained key: "
792 "no hostkey recorded in signature for forwarded "
796 if (hostkey
!= NULL
&& !sshkey_equal(hostkey
,
797 e
->session_ids
[e
->nsession_ids
- 1].key
)) {
798 error_f("refusing use of destination-constrained key: "
799 "mismatch between hostkey in request and most "
800 "recently bound session");
803 xasprintf(&sig_dest
, "public key authentication request for "
804 "user \"%s\" to listed host", user
);
806 if (id
->confirm
&& confirm_key(id
, sig_dest
) != 0) {
807 verbose_f("user refused key");
810 if (sshkey_is_sk(id
->key
)) {
811 if (restrict_websafe
&&
812 strncmp(id
->key
->sk_application
, "ssh:", 4) != 0 &&
813 !check_websafe_message_contents(key
, data
)) {
814 /* error already logged */
817 if (id
->key
->sk_flags
& SSH_SK_USER_PRESENCE_REQD
) {
818 notifier
= notify_start(0,
819 "Confirm user presence for key %s %s%s%s",
820 sshkey_type(id
->key
), fp
,
821 sig_dest
== NULL
? "" : "\n",
822 sig_dest
== NULL
? "" : sig_dest
);
826 if ((r
= sshkey_sign(id
->key
, &signature
, &slen
,
827 sshbuf_ptr(data
), sshbuf_len(data
), agent_decode_alg(key
, flags
),
828 id
->sk_provider
, pin
, compat
)) != 0) {
829 debug_fr(r
, "sshkey_sign");
830 if (pin
== NULL
&& !retried
&& sshkey_is_sk(id
->key
) &&
831 r
== SSH_ERR_KEY_WRONG_PASSPHRASE
) {
832 notify_complete(notifier
, NULL
);
834 /* XXX include sig_dest */
835 xasprintf(&prompt
, "Enter PIN%sfor %s key %s: ",
836 (id
->key
->sk_flags
& SSH_SK_USER_PRESENCE_REQD
) ?
837 " and confirm user presence " : " ",
838 sshkey_type(id
->key
), fp
);
839 pin
= read_passphrase(prompt
, RP_USE_ASKPASS
);
843 error_fr(r
, "sshkey_sign");
849 debug_f("good signature");
850 notify_complete(notifier
, "User presence confirmed");
853 if ((r
= sshbuf_put_u8(msg
, SSH2_AGENT_SIGN_RESPONSE
)) != 0 ||
854 (r
= sshbuf_put_string(msg
, signature
, slen
)) != 0)
855 fatal_fr(r
, "compose");
856 } else if ((r
= sshbuf_put_u8(msg
, SSH_AGENT_FAILURE
)) != 0)
857 fatal_fr(r
, "compose failure");
859 if ((r
= sshbuf_put_stringb(e
->output
, msg
)) != 0)
860 fatal_fr(r
, "enqueue");
866 sshkey_free(hostkey
);
873 freezero(pin
, strlen(pin
));
878 process_remove_identity(SocketEntry
*e
)
881 struct sshkey
*key
= NULL
;
884 debug2_f("entering");
885 if ((r
= sshkey_froms(e
->request
, &key
)) != 0) {
886 error_fr(r
, "parse key");
889 if ((id
= lookup_identity(key
)) == NULL
) {
890 debug_f("key not found");
893 /* identity not visible, cannot be removed */
894 if (identity_permitted(id
, e
, NULL
, NULL
, NULL
) != 0)
895 goto done
; /* error already logged */
896 /* We have this key, free it. */
897 if (idtab
->nentries
< 1)
898 fatal_f("internal error: nentries %d", idtab
->nentries
);
899 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
905 send_status(e
, success
);
909 process_remove_all_identities(SocketEntry
*e
)
913 debug2_f("entering");
914 /* Loop over all identities and clear the keys. */
915 for (id
= TAILQ_FIRST(&idtab
->idlist
); id
;
916 id
= TAILQ_FIRST(&idtab
->idlist
)) {
917 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
921 /* Mark that there are no identities. */
928 /* removes expired keys and returns number of seconds until the next expiry */
932 time_t deadline
= 0, now
= monotime();
935 for (id
= TAILQ_FIRST(&idtab
->idlist
); id
; id
= nxt
) {
936 nxt
= TAILQ_NEXT(id
, next
);
939 if (now
>= id
->death
) {
940 debug("expiring key '%s'", id
->comment
);
941 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
945 deadline
= (deadline
== 0) ? id
->death
:
946 MINIMUM(deadline
, id
->death
);
948 if (deadline
== 0 || deadline
<= now
)
951 return (deadline
- now
);
955 parse_dest_constraint_hop(struct sshbuf
*b
, struct dest_constraint_hop
*dch
)
960 struct sshkey
*k
= NULL
;
963 memset(dch
, '\0', sizeof(*dch
));
964 if ((r
= sshbuf_get_cstring(b
, &dch
->user
, NULL
)) != 0 ||
965 (r
= sshbuf_get_cstring(b
, &dch
->hostname
, NULL
)) != 0 ||
966 (r
= sshbuf_get_string_direct(b
, NULL
, &elen
)) != 0) {
967 error_fr(r
, "parse");
971 error_f("unsupported extensions (len %zu)", elen
);
972 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
975 if (*dch
->hostname
== '\0') {
977 dch
->hostname
= NULL
;
979 if (*dch
->user
== '\0') {
983 while (sshbuf_len(b
) != 0) {
984 dch
->keys
= xrecallocarray(dch
->keys
, dch
->nkeys
,
985 dch
->nkeys
+ 1, sizeof(*dch
->keys
));
986 dch
->key_is_ca
= xrecallocarray(dch
->key_is_ca
, dch
->nkeys
,
987 dch
->nkeys
+ 1, sizeof(*dch
->key_is_ca
));
988 if ((r
= sshkey_froms(b
, &k
)) != 0 ||
989 (r
= sshbuf_get_u8(b
, &key_is_ca
)) != 0)
991 if ((fp
= sshkey_fingerprint(k
, SSH_FP_HASH_DEFAULT
,
992 SSH_FP_DEFAULT
)) == NULL
)
993 fatal_f("fingerprint failed");
994 debug3_f("%s%s%s: adding %skey %s %s",
995 dch
->user
== NULL
? "" : dch
->user
,
996 dch
->user
== NULL
? "" : "@",
997 dch
->hostname
, key_is_ca
? "CA " : "", sshkey_type(k
), fp
);
999 dch
->keys
[dch
->nkeys
] = k
;
1000 dch
->key_is_ca
[dch
->nkeys
] = key_is_ca
!= 0;
1002 k
= NULL
; /* transferred */
1012 parse_dest_constraint(struct sshbuf
*m
, struct dest_constraint
*dc
)
1014 struct sshbuf
*b
= NULL
, *frombuf
= NULL
, *tobuf
= NULL
;
1018 debug3_f("entering");
1020 memset(dc
, '\0', sizeof(*dc
));
1021 if ((r
= sshbuf_froms(m
, &b
)) != 0 ||
1022 (r
= sshbuf_froms(b
, &frombuf
)) != 0 ||
1023 (r
= sshbuf_froms(b
, &tobuf
)) != 0 ||
1024 (r
= sshbuf_get_string_direct(b
, NULL
, &elen
)) != 0) {
1025 error_fr(r
, "parse");
1028 if ((r
= parse_dest_constraint_hop(frombuf
, &dc
->from
) != 0) ||
1029 (r
= parse_dest_constraint_hop(tobuf
, &dc
->to
) != 0))
1030 goto out
; /* already logged */
1032 error_f("unsupported extensions (len %zu)", elen
);
1033 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1036 debug2_f("parsed %s (%u keys) > %s%s%s (%u keys)",
1037 dc
->from
.hostname
? dc
->from
.hostname
: "(ORIGIN)", dc
->from
.nkeys
,
1038 dc
->to
.user
? dc
->to
.user
: "", dc
->to
.user
? "@" : "",
1039 dc
->to
.hostname
? dc
->to
.hostname
: "(ANY)", dc
->to
.nkeys
);
1040 /* check consistency */
1041 if ((dc
->from
.hostname
== NULL
) != (dc
->from
.nkeys
== 0) ||
1042 dc
->from
.user
!= NULL
) {
1043 error_f("inconsistent \"from\" specification");
1044 r
= SSH_ERR_INVALID_FORMAT
;
1047 if (dc
->to
.hostname
== NULL
|| dc
->to
.nkeys
== 0) {
1048 error_f("incomplete \"to\" specification");
1049 r
= SSH_ERR_INVALID_FORMAT
;
1056 sshbuf_free(frombuf
);
1062 parse_key_constraint_extension(struct sshbuf
*m
, char **sk_providerp
,
1063 struct dest_constraint
**dcsp
, size_t *ndcsp
)
1065 char *ext_name
= NULL
;
1067 struct sshbuf
*b
= NULL
;
1069 if ((r
= sshbuf_get_cstring(m
, &ext_name
, NULL
)) != 0) {
1070 error_fr(r
, "parse constraint extension");
1073 debug_f("constraint ext %s", ext_name
);
1074 if (strcmp(ext_name
, "sk-provider@openssh.com") == 0) {
1075 if (sk_providerp
== NULL
) {
1076 error_f("%s not valid here", ext_name
);
1077 r
= SSH_ERR_INVALID_FORMAT
;
1080 if (*sk_providerp
!= NULL
) {
1081 error_f("%s already set", ext_name
);
1082 r
= SSH_ERR_INVALID_FORMAT
;
1085 if ((r
= sshbuf_get_cstring(m
, sk_providerp
, NULL
)) != 0) {
1086 error_fr(r
, "parse %s", ext_name
);
1089 } else if (strcmp(ext_name
,
1090 "restrict-destination-v00@openssh.com") == 0) {
1091 if (*dcsp
!= NULL
) {
1092 error_f("%s already set", ext_name
);
1095 if ((r
= sshbuf_froms(m
, &b
)) != 0) {
1096 error_fr(r
, "parse %s outer", ext_name
);
1099 while (sshbuf_len(b
) != 0) {
1100 if (*ndcsp
>= AGENT_MAX_DEST_CONSTRAINTS
) {
1101 error_f("too many %s constraints", ext_name
);
1104 *dcsp
= xrecallocarray(*dcsp
, *ndcsp
, *ndcsp
+ 1,
1106 if ((r
= parse_dest_constraint(b
,
1107 *dcsp
+ (*ndcsp
)++)) != 0)
1108 goto out
; /* error already logged */
1111 error_f("unsupported constraint \"%s\"", ext_name
);
1112 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1124 parse_key_constraints(struct sshbuf
*m
, struct sshkey
*k
, time_t *deathp
,
1125 u_int
*secondsp
, int *confirmp
, char **sk_providerp
,
1126 struct dest_constraint
**dcsp
, size_t *ndcsp
)
1130 u_int seconds
, maxsign
= 0;
1132 while (sshbuf_len(m
)) {
1133 if ((r
= sshbuf_get_u8(m
, &ctype
)) != 0) {
1134 error_fr(r
, "parse constraint type");
1138 case SSH_AGENT_CONSTRAIN_LIFETIME
:
1140 error_f("lifetime already set");
1141 r
= SSH_ERR_INVALID_FORMAT
;
1144 if ((r
= sshbuf_get_u32(m
, &seconds
)) != 0) {
1145 error_fr(r
, "parse lifetime constraint");
1148 *deathp
= monotime() + seconds
;
1149 *secondsp
= seconds
;
1151 case SSH_AGENT_CONSTRAIN_CONFIRM
:
1152 if (*confirmp
!= 0) {
1153 error_f("confirm already set");
1154 r
= SSH_ERR_INVALID_FORMAT
;
1159 case SSH_AGENT_CONSTRAIN_MAXSIGN
:
1161 error_f("maxsign not valid here");
1162 r
= SSH_ERR_INVALID_FORMAT
;
1166 error_f("maxsign already set");
1167 r
= SSH_ERR_INVALID_FORMAT
;
1170 if ((r
= sshbuf_get_u32(m
, &maxsign
)) != 0) {
1171 error_fr(r
, "parse maxsign constraint");
1174 if ((r
= sshkey_enable_maxsign(k
, maxsign
)) != 0) {
1175 error_fr(r
, "enable maxsign");
1179 case SSH_AGENT_CONSTRAIN_EXTENSION
:
1180 if ((r
= parse_key_constraint_extension(m
,
1181 sk_providerp
, dcsp
, ndcsp
)) != 0)
1182 goto out
; /* error already logged */
1185 error_f("Unknown constraint %d", ctype
);
1186 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1197 process_add_identity(SocketEntry
*e
)
1200 int success
= 0, confirm
= 0;
1201 char *fp
, *comment
= NULL
, *sk_provider
= NULL
;
1202 char canonical_provider
[PATH_MAX
];
1205 struct dest_constraint
*dest_constraints
= NULL
;
1206 size_t ndest_constraints
= 0;
1207 struct sshkey
*k
= NULL
;
1208 int r
= SSH_ERR_INTERNAL_ERROR
;
1210 debug2_f("entering");
1211 if ((r
= sshkey_private_deserialize(e
->request
, &k
)) != 0 ||
1213 (r
= sshbuf_get_cstring(e
->request
, &comment
, NULL
)) != 0) {
1214 error_fr(r
, "parse");
1217 if (parse_key_constraints(e
->request
, k
, &death
, &seconds
, &confirm
,
1218 &sk_provider
, &dest_constraints
, &ndest_constraints
) != 0) {
1219 error_f("failed to parse constraints");
1220 sshbuf_reset(e
->request
);
1224 if (sk_provider
!= NULL
) {
1225 if (!sshkey_is_sk(k
)) {
1226 error("Cannot add provider: %s is not an "
1227 "authenticator-hosted key", sshkey_type(k
));
1230 if (strcasecmp(sk_provider
, "internal") == 0) {
1231 debug_f("internal provider");
1233 if (realpath(sk_provider
, canonical_provider
) == NULL
) {
1234 verbose("failed provider \"%.100s\": "
1235 "realpath: %s", sk_provider
,
1240 sk_provider
= xstrdup(canonical_provider
);
1241 if (match_pattern_list(sk_provider
,
1242 allowed_providers
, 0) != 1) {
1243 error("Refusing add key: "
1244 "provider %s not allowed", sk_provider
);
1249 if ((r
= sshkey_shield_private(k
)) != 0) {
1250 error_fr(r
, "shield private");
1253 if (lifetime
&& !death
)
1254 death
= monotime() + lifetime
;
1255 if ((id
= lookup_identity(k
)) == NULL
) {
1256 id
= xcalloc(1, sizeof(Identity
));
1257 TAILQ_INSERT_TAIL(&idtab
->idlist
, id
, next
);
1258 /* Increment the number of identities. */
1261 /* identity not visible, do not update */
1262 if (identity_permitted(id
, e
, NULL
, NULL
, NULL
) != 0)
1263 goto out
; /* error already logged */
1264 /* key state might have been updated */
1265 sshkey_free(id
->key
);
1267 free(id
->sk_provider
);
1268 free_dest_constraints(id
->dest_constraints
,
1269 id
->ndest_constraints
);
1273 id
->comment
= comment
;
1275 id
->confirm
= confirm
;
1276 id
->sk_provider
= sk_provider
;
1277 id
->dest_constraints
= dest_constraints
;
1278 id
->ndest_constraints
= ndest_constraints
;
1280 if ((fp
= sshkey_fingerprint(k
, SSH_FP_HASH_DEFAULT
,
1281 SSH_FP_DEFAULT
)) == NULL
)
1282 fatal_f("sshkey_fingerprint failed");
1283 debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) "
1284 "(provider: %s) (destination constraints: %zu)",
1285 sshkey_ssh_name(k
), fp
, comment
, seconds
, confirm
,
1286 sk_provider
== NULL
? "none" : sk_provider
, ndest_constraints
);
1292 dest_constraints
= NULL
;
1293 ndest_constraints
= 0;
1299 free_dest_constraints(dest_constraints
, ndest_constraints
);
1300 send_status(e
, success
);
1303 /* XXX todo: encrypt sensitive data with passphrase */
1305 process_lock_agent(SocketEntry
*e
, int lock
)
1307 int r
, success
= 0, delay
;
1309 u_char passwdhash
[LOCK_SIZE
];
1310 static u_int fail_count
= 0;
1313 debug2_f("entering");
1315 * This is deliberately fatal: the user has requested that we lock,
1316 * but we can't parse their request properly. The only safe thing to
1319 if ((r
= sshbuf_get_cstring(e
->request
, &passwd
, &pwlen
)) != 0)
1320 fatal_fr(r
, "parse");
1322 debug("empty password not supported");
1323 } else if (locked
&& !lock
) {
1324 if (bcrypt_pbkdf(passwd
, pwlen
, lock_salt
, sizeof(lock_salt
),
1325 passwdhash
, sizeof(passwdhash
), LOCK_ROUNDS
) < 0)
1326 fatal("bcrypt_pbkdf");
1327 if (timingsafe_bcmp(passwdhash
, lock_pwhash
, LOCK_SIZE
) == 0) {
1328 debug("agent unlocked");
1331 explicit_bzero(lock_pwhash
, sizeof(lock_pwhash
));
1334 /* delay in 0.1s increments up to 10s */
1335 if (fail_count
< 100)
1337 delay
= 100000 * fail_count
;
1338 debug("unlock failed, delaying %0.1lf seconds",
1339 (double)delay
/1000000);
1342 explicit_bzero(passwdhash
, sizeof(passwdhash
));
1343 } else if (!locked
&& lock
) {
1344 debug("agent locked");
1346 arc4random_buf(lock_salt
, sizeof(lock_salt
));
1347 if (bcrypt_pbkdf(passwd
, pwlen
, lock_salt
, sizeof(lock_salt
),
1348 lock_pwhash
, sizeof(lock_pwhash
), LOCK_ROUNDS
) < 0)
1349 fatal("bcrypt_pbkdf");
1352 freezero(passwd
, pwlen
);
1353 send_status(e
, success
);
1357 no_identities(SocketEntry
*e
)
1362 if ((msg
= sshbuf_new()) == NULL
)
1363 fatal_f("sshbuf_new failed");
1364 if ((r
= sshbuf_put_u8(msg
, SSH2_AGENT_IDENTITIES_ANSWER
)) != 0 ||
1365 (r
= sshbuf_put_u32(msg
, 0)) != 0 ||
1366 (r
= sshbuf_put_stringb(e
->output
, msg
)) != 0)
1367 fatal_fr(r
, "compose");
1371 #ifdef ENABLE_PKCS11
1373 process_add_smartcard_key(SocketEntry
*e
)
1375 char *provider
= NULL
, *pin
= NULL
, canonical_provider
[PATH_MAX
];
1376 char **comments
= NULL
;
1377 int r
, i
, count
= 0, success
= 0, confirm
= 0;
1380 struct sshkey
**keys
= NULL
, *k
;
1382 struct dest_constraint
*dest_constraints
= NULL
;
1383 size_t ndest_constraints
= 0;
1385 debug2_f("entering");
1386 if ((r
= sshbuf_get_cstring(e
->request
, &provider
, NULL
)) != 0 ||
1387 (r
= sshbuf_get_cstring(e
->request
, &pin
, NULL
)) != 0) {
1388 error_fr(r
, "parse");
1391 if (parse_key_constraints(e
->request
, NULL
, &death
, &seconds
, &confirm
,
1392 NULL
, &dest_constraints
, &ndest_constraints
) != 0) {
1393 error_f("failed to parse constraints");
1396 if (realpath(provider
, canonical_provider
) == NULL
) {
1397 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1398 provider
, strerror(errno
));
1401 if (match_pattern_list(canonical_provider
, allowed_providers
, 0) != 1) {
1402 verbose("refusing PKCS#11 add of \"%.100s\": "
1403 "provider not allowed", canonical_provider
);
1406 debug_f("add %.100s", canonical_provider
);
1407 if (lifetime
&& !death
)
1408 death
= monotime() + lifetime
;
1410 count
= pkcs11_add_provider(canonical_provider
, pin
, &keys
, &comments
);
1411 for (i
= 0; i
< count
; i
++) {
1413 if (lookup_identity(k
) == NULL
) {
1414 id
= xcalloc(1, sizeof(Identity
));
1416 keys
[i
] = NULL
; /* transferred */
1417 id
->provider
= xstrdup(canonical_provider
);
1418 if (*comments
[i
] != '\0') {
1419 id
->comment
= comments
[i
];
1420 comments
[i
] = NULL
; /* transferred */
1422 id
->comment
= xstrdup(canonical_provider
);
1425 id
->confirm
= confirm
;
1426 id
->dest_constraints
= dest_constraints
;
1427 id
->ndest_constraints
= ndest_constraints
;
1428 dest_constraints
= NULL
; /* transferred */
1429 ndest_constraints
= 0;
1430 TAILQ_INSERT_TAIL(&idtab
->idlist
, id
, next
);
1434 /* XXX update constraints for existing keys */
1435 sshkey_free(keys
[i
]);
1443 free_dest_constraints(dest_constraints
, ndest_constraints
);
1444 send_status(e
, success
);
1448 process_remove_smartcard_key(SocketEntry
*e
)
1450 char *provider
= NULL
, *pin
= NULL
, canonical_provider
[PATH_MAX
];
1454 debug2_f("entering");
1455 if ((r
= sshbuf_get_cstring(e
->request
, &provider
, NULL
)) != 0 ||
1456 (r
= sshbuf_get_cstring(e
->request
, &pin
, NULL
)) != 0) {
1457 error_fr(r
, "parse");
1462 if (realpath(provider
, canonical_provider
) == NULL
) {
1463 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1464 provider
, strerror(errno
));
1468 debug_f("remove %.100s", canonical_provider
);
1469 for (id
= TAILQ_FIRST(&idtab
->idlist
); id
; id
= nxt
) {
1470 nxt
= TAILQ_NEXT(id
, next
);
1471 /* Skip file--based keys */
1472 if (id
->provider
== NULL
)
1474 if (!strcmp(canonical_provider
, id
->provider
)) {
1475 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
1480 if (pkcs11_del_provider(canonical_provider
) == 0)
1483 error_f("pkcs11_del_provider failed");
1486 send_status(e
, success
);
1488 #endif /* ENABLE_PKCS11 */
1491 process_ext_session_bind(SocketEntry
*e
)
1493 int r
, sid_match
, key_match
;
1494 struct sshkey
*key
= NULL
;
1495 struct sshbuf
*sid
= NULL
, *sig
= NULL
;
1500 debug2_f("entering");
1501 if ((r
= sshkey_froms(e
->request
, &key
)) != 0 ||
1502 (r
= sshbuf_froms(e
->request
, &sid
)) != 0 ||
1503 (r
= sshbuf_froms(e
->request
, &sig
)) != 0 ||
1504 (r
= sshbuf_get_u8(e
->request
, &fwd
)) != 0) {
1505 error_fr(r
, "parse");
1508 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
1509 SSH_FP_DEFAULT
)) == NULL
)
1510 fatal_f("fingerprint failed");
1511 /* check signature with hostkey on session ID */
1512 if ((r
= sshkey_verify(key
, sshbuf_ptr(sig
), sshbuf_len(sig
),
1513 sshbuf_ptr(sid
), sshbuf_len(sid
), NULL
, 0, NULL
)) != 0) {
1514 error_fr(r
, "sshkey_verify for %s %s", sshkey_type(key
), fp
);
1517 /* check whether sid/key already recorded */
1518 for (i
= 0; i
< e
->nsession_ids
; i
++) {
1519 if (!e
->session_ids
[i
].forwarded
) {
1520 error_f("attempt to bind session ID to socket "
1521 "previously bound for authentication attempt");
1525 sid_match
= buf_equal(sid
, e
->session_ids
[i
].sid
) == 0;
1526 key_match
= sshkey_equal(key
, e
->session_ids
[i
].key
);
1527 if (sid_match
&& key_match
) {
1528 debug_f("session ID already recorded for %s %s",
1529 sshkey_type(key
), fp
);
1532 } else if (sid_match
) {
1533 error_f("session ID recorded against different key "
1534 "for %s %s", sshkey_type(key
), fp
);
1539 * new sid with previously-seen key can happen, e.g. multiple
1540 * connections to the same host.
1543 /* record new key/sid */
1544 if (e
->nsession_ids
>= AGENT_MAX_SESSION_IDS
) {
1545 error_f("too many session IDs recorded");
1548 e
->session_ids
= xrecallocarray(e
->session_ids
, e
->nsession_ids
,
1549 e
->nsession_ids
+ 1, sizeof(*e
->session_ids
));
1550 i
= e
->nsession_ids
++;
1551 debug_f("recorded %s %s (slot %zu of %d)", sshkey_type(key
), fp
, i
,
1552 AGENT_MAX_SESSION_IDS
);
1553 e
->session_ids
[i
].key
= key
;
1554 e
->session_ids
[i
].forwarded
= fwd
!= 0;
1555 key
= NULL
; /* transferred */
1556 /* can't transfer sid; it's refcounted and scoped to request's life */
1557 if ((e
->session_ids
[i
].sid
= sshbuf_new()) == NULL
)
1558 fatal_f("sshbuf_new");
1559 if ((r
= sshbuf_putb(e
->session_ids
[i
].sid
, sid
)) != 0)
1560 fatal_fr(r
, "sshbuf_putb session ID");
1568 return r
== 0 ? 1 : 0;
1572 process_extension(SocketEntry
*e
)
1577 debug2_f("entering");
1578 if ((r
= sshbuf_get_cstring(e
->request
, &name
, NULL
)) != 0) {
1579 error_fr(r
, "parse");
1582 if (strcmp(name
, "session-bind@openssh.com") == 0)
1583 success
= process_ext_session_bind(e
);
1585 debug_f("unsupported extension \"%s\"", name
);
1588 send_status(e
, success
);
1591 * dispatch incoming message.
1592 * returns 1 on success, 0 for incomplete messages or -1 on error.
1595 process_message(u_int socknum
)
1603 if (socknum
>= sockets_alloc
)
1604 fatal_f("sock %u >= allocated %u", socknum
, sockets_alloc
);
1605 e
= &sockets
[socknum
];
1607 if (sshbuf_len(e
->input
) < 5)
1608 return 0; /* Incomplete message header. */
1609 cp
= sshbuf_ptr(e
->input
);
1610 msg_len
= PEEK_U32(cp
);
1611 if (msg_len
> AGENT_MAX_LEN
) {
1612 debug_f("socket %u (fd=%d) message too long %u > %u",
1613 socknum
, e
->fd
, msg_len
, AGENT_MAX_LEN
);
1616 if (sshbuf_len(e
->input
) < msg_len
+ 4)
1617 return 0; /* Incomplete message body. */
1619 /* move the current input to e->request */
1620 sshbuf_reset(e
->request
);
1621 if ((r
= sshbuf_get_stringb(e
->input
, e
->request
)) != 0 ||
1622 (r
= sshbuf_get_u8(e
->request
, &type
)) != 0) {
1623 if (r
== SSH_ERR_MESSAGE_INCOMPLETE
||
1624 r
== SSH_ERR_STRING_TOO_LARGE
) {
1625 error_fr(r
, "parse");
1628 fatal_fr(r
, "parse");
1631 debug_f("socket %u (fd=%d) type %d", socknum
, e
->fd
, type
);
1633 /* check whether agent is locked */
1634 if (locked
&& type
!= SSH_AGENTC_UNLOCK
) {
1635 sshbuf_reset(e
->request
);
1637 case SSH2_AGENTC_REQUEST_IDENTITIES
:
1638 /* send empty lists */
1642 /* send a fail message for all other request types */
1649 case SSH_AGENTC_LOCK
:
1650 case SSH_AGENTC_UNLOCK
:
1651 process_lock_agent(e
, type
== SSH_AGENTC_LOCK
);
1653 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES
:
1654 process_remove_all_identities(e
); /* safe for !WITH_SSH1 */
1657 case SSH2_AGENTC_SIGN_REQUEST
:
1658 process_sign_request2(e
);
1660 case SSH2_AGENTC_REQUEST_IDENTITIES
:
1661 process_request_identities(e
);
1663 case SSH2_AGENTC_ADD_IDENTITY
:
1664 case SSH2_AGENTC_ADD_ID_CONSTRAINED
:
1665 process_add_identity(e
);
1667 case SSH2_AGENTC_REMOVE_IDENTITY
:
1668 process_remove_identity(e
);
1670 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES
:
1671 process_remove_all_identities(e
);
1673 #ifdef ENABLE_PKCS11
1674 case SSH_AGENTC_ADD_SMARTCARD_KEY
:
1675 case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
:
1676 process_add_smartcard_key(e
);
1678 case SSH_AGENTC_REMOVE_SMARTCARD_KEY
:
1679 process_remove_smartcard_key(e
);
1681 #endif /* ENABLE_PKCS11 */
1682 case SSH_AGENTC_EXTENSION
:
1683 process_extension(e
);
1686 /* Unknown message. Respond with failure. */
1687 error("Unknown message %d", type
);
1688 sshbuf_reset(e
->request
);
1696 new_socket(sock_type type
, int fd
)
1698 u_int i
, old_alloc
, new_alloc
;
1700 debug_f("type = %s", type
== AUTH_CONNECTION
? "CONNECTION" :
1701 (type
== AUTH_SOCKET
? "SOCKET" : "UNKNOWN"));
1707 for (i
= 0; i
< sockets_alloc
; i
++)
1708 if (sockets
[i
].type
== AUTH_UNUSED
) {
1710 if ((sockets
[i
].input
= sshbuf_new()) == NULL
||
1711 (sockets
[i
].output
= sshbuf_new()) == NULL
||
1712 (sockets
[i
].request
= sshbuf_new()) == NULL
)
1713 fatal_f("sshbuf_new failed");
1714 sockets
[i
].type
= type
;
1717 old_alloc
= sockets_alloc
;
1718 new_alloc
= sockets_alloc
+ 10;
1719 sockets
= xrecallocarray(sockets
, old_alloc
, new_alloc
,
1720 sizeof(sockets
[0]));
1721 for (i
= old_alloc
; i
< new_alloc
; i
++)
1722 sockets
[i
].type
= AUTH_UNUSED
;
1723 sockets_alloc
= new_alloc
;
1724 sockets
[old_alloc
].fd
= fd
;
1725 if ((sockets
[old_alloc
].input
= sshbuf_new()) == NULL
||
1726 (sockets
[old_alloc
].output
= sshbuf_new()) == NULL
||
1727 (sockets
[old_alloc
].request
= sshbuf_new()) == NULL
)
1728 fatal_f("sshbuf_new failed");
1729 sockets
[old_alloc
].type
= type
;
1733 handle_socket_read(u_int socknum
)
1735 struct sockaddr_un sunaddr
;
1741 slen
= sizeof(sunaddr
);
1742 fd
= accept(sockets
[socknum
].fd
, (struct sockaddr
*)&sunaddr
, &slen
);
1744 error("accept from AUTH_SOCKET: %s", strerror(errno
));
1747 if (getpeereid(fd
, &euid
, &egid
) == -1) {
1748 error("getpeereid %d failed: %s", fd
, strerror(errno
));
1752 if ((euid
!= 0) && (getuid() != euid
)) {
1753 error("uid mismatch: peer euid %u != uid %u",
1754 (u_int
) euid
, (u_int
) getuid());
1758 new_socket(AUTH_CONNECTION
, fd
);
1763 handle_conn_read(u_int socknum
)
1765 char buf
[AGENT_RBUF_LEN
];
1769 if ((len
= read(sockets
[socknum
].fd
, buf
, sizeof(buf
))) <= 0) {
1771 if (errno
== EAGAIN
|| errno
== EINTR
)
1773 error_f("read error on socket %u (fd %d): %s",
1774 socknum
, sockets
[socknum
].fd
, strerror(errno
));
1778 if ((r
= sshbuf_put(sockets
[socknum
].input
, buf
, len
)) != 0)
1779 fatal_fr(r
, "compose");
1780 explicit_bzero(buf
, sizeof(buf
));
1782 if ((r
= process_message(socknum
)) == -1)
1791 handle_conn_write(u_int socknum
)
1796 if (sshbuf_len(sockets
[socknum
].output
) == 0)
1797 return 0; /* shouldn't happen */
1798 if ((len
= write(sockets
[socknum
].fd
,
1799 sshbuf_ptr(sockets
[socknum
].output
),
1800 sshbuf_len(sockets
[socknum
].output
))) <= 0) {
1802 if (errno
== EAGAIN
|| errno
== EINTR
)
1804 error_f("read error on socket %u (fd %d): %s",
1805 socknum
, sockets
[socknum
].fd
, strerror(errno
));
1809 if ((r
= sshbuf_consume(sockets
[socknum
].output
, len
)) != 0)
1810 fatal_fr(r
, "consume");
1815 after_poll(struct pollfd
*pfd
, size_t npfd
, u_int maxfds
)
1818 u_int socknum
, activefds
= npfd
;
1820 for (i
= 0; i
< npfd
; i
++) {
1821 if (pfd
[i
].revents
== 0)
1823 /* Find sockets entry */
1824 for (socknum
= 0; socknum
< sockets_alloc
; socknum
++) {
1825 if (sockets
[socknum
].type
!= AUTH_SOCKET
&&
1826 sockets
[socknum
].type
!= AUTH_CONNECTION
)
1828 if (pfd
[i
].fd
== sockets
[socknum
].fd
)
1831 if (socknum
>= sockets_alloc
) {
1832 error_f("no socket for fd %d", pfd
[i
].fd
);
1835 /* Process events */
1836 switch (sockets
[socknum
].type
) {
1838 if ((pfd
[i
].revents
& (POLLIN
|POLLERR
)) == 0)
1840 if (npfd
> maxfds
) {
1841 debug3("out of fds (active %u >= limit %u); "
1842 "skipping accept", activefds
, maxfds
);
1845 if (handle_socket_read(socknum
) == 0)
1848 case AUTH_CONNECTION
:
1849 if ((pfd
[i
].revents
& (POLLIN
|POLLHUP
|POLLERR
)) != 0 &&
1850 handle_conn_read(socknum
) != 0)
1852 if ((pfd
[i
].revents
& (POLLOUT
|POLLHUP
)) != 0 &&
1853 handle_conn_write(socknum
) != 0) {
1856 fatal("activefds == 0 at close_sock");
1857 close_socket(&sockets
[socknum
]);
1869 prepare_poll(struct pollfd
**pfdp
, size_t *npfdp
, int *timeoutp
, u_int maxfds
)
1871 struct pollfd
*pfd
= *pfdp
;
1872 size_t i
, j
, npfd
= 0;
1876 /* Count active sockets */
1877 for (i
= 0; i
< sockets_alloc
; i
++) {
1878 switch (sockets
[i
].type
) {
1880 case AUTH_CONNECTION
:
1886 fatal("Unknown socket type %d", sockets
[i
].type
);
1890 if (npfd
!= *npfdp
&&
1891 (pfd
= recallocarray(pfd
, *npfdp
, npfd
, sizeof(*pfd
))) == NULL
)
1892 fatal_f("recallocarray failed");
1896 for (i
= j
= 0; i
< sockets_alloc
; i
++) {
1897 switch (sockets
[i
].type
) {
1899 if (npfd
> maxfds
) {
1900 debug3("out of fds (active %zu >= limit %u); "
1901 "skipping arming listener", npfd
, maxfds
);
1904 pfd
[j
].fd
= sockets
[i
].fd
;
1906 pfd
[j
].events
= POLLIN
;
1909 case AUTH_CONNECTION
:
1910 pfd
[j
].fd
= sockets
[i
].fd
;
1913 * Only prepare to read if we can handle a full-size
1914 * input read buffer and enqueue a max size reply..
1916 if ((r
= sshbuf_check_reserve(sockets
[i
].input
,
1917 AGENT_RBUF_LEN
)) == 0 &&
1918 (r
= sshbuf_check_reserve(sockets
[i
].output
,
1919 AGENT_MAX_LEN
)) == 0)
1920 pfd
[j
].events
= POLLIN
;
1921 else if (r
!= SSH_ERR_NO_BUFFER_SPACE
)
1922 fatal_fr(r
, "reserve");
1923 if (sshbuf_len(sockets
[i
].output
) > 0)
1924 pfd
[j
].events
|= POLLOUT
;
1931 deadline
= reaper();
1932 if (parent_alive_interval
!= 0)
1933 deadline
= (deadline
== 0) ? parent_alive_interval
:
1934 MINIMUM(deadline
, parent_alive_interval
);
1935 if (deadline
== 0) {
1936 *timeoutp
= -1; /* INFTIM */
1938 if (deadline
> INT_MAX
/ 1000)
1939 *timeoutp
= INT_MAX
/ 1000;
1941 *timeoutp
= deadline
* 1000;
1947 cleanup_socket(void)
1949 if (cleanup_pid
!= 0 && getpid() != cleanup_pid
)
1953 unlink(socket_name
);
1967 cleanup_handler(int sig
)
1970 #ifdef ENABLE_PKCS11
1977 check_parent_exists(void)
1980 * If our parent has exited then getppid() will return (pid_t)1,
1981 * so testing for that should be safe.
1983 if (parent_pid
!= -1 && getppid() != parent_pid
) {
1984 /* printf("Parent has died - Authentication agent exiting.\n"); */
1994 "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
1995 " [-P allowed_providers] [-t life]\n"
1996 " ssh-agent [-a bind_address] [-E fingerprint_hash] [-P allowed_providers]\n"
1997 " [-t life] command [arg ...]\n"
1998 " ssh-agent [-c | -s] -k\n");
2003 main(int ac
, char **av
)
2005 int c_flag
= 0, d_flag
= 0, D_flag
= 0, k_flag
= 0, s_flag
= 0;
2006 int sock
, ch
, result
, saved_errno
;
2007 char *shell
, *format
, *pidstr
, *agentsocket
= NULL
;
2008 #ifdef HAVE_SETRLIMIT
2012 extern char *optarg
;
2014 char pidstrbuf
[1 + 3 * sizeof pid
];
2017 int timeout
= -1; /* INFTIM */
2018 struct pollfd
*pfd
= NULL
;
2022 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2029 platform_disable_tracing(0); /* strict=no */
2031 #ifdef RLIMIT_NOFILE
2032 if (getrlimit(RLIMIT_NOFILE
, &rlim
) == -1)
2033 fatal("%s: getrlimit: %s", __progname
, strerror(errno
));
2036 __progname
= ssh_get_progname(av
[0]);
2039 while ((ch
= getopt(ac
, av
, "cDdksE:a:O:P:t:")) != -1) {
2042 fingerprint_hash
= ssh_digest_alg_by_name(optarg
);
2043 if (fingerprint_hash
== -1)
2044 fatal("Invalid hash algorithm \"%s\"", optarg
);
2055 if (strcmp(optarg
, "no-restrict-websafe") == 0)
2056 restrict_websafe
= 0;
2058 fatal("Unknown -O option");
2061 if (allowed_providers
!= NULL
)
2062 fatal("-P option already specified");
2063 allowed_providers
= xstrdup(optarg
);
2071 if (d_flag
|| D_flag
)
2076 if (d_flag
|| D_flag
)
2081 agentsocket
= optarg
;
2084 if ((lifetime
= convtime(optarg
)) == -1) {
2085 fprintf(stderr
, "Invalid lifetime\n");
2096 if (ac
> 0 && (c_flag
|| k_flag
|| s_flag
|| d_flag
|| D_flag
))
2099 if (allowed_providers
== NULL
)
2100 allowed_providers
= xstrdup(DEFAULT_ALLOWED_PROVIDERS
);
2102 if (ac
== 0 && !c_flag
&& !s_flag
) {
2103 shell
= getenv("SHELL");
2104 if (shell
!= NULL
&& (len
= strlen(shell
)) > 2 &&
2105 strncmp(shell
+ len
- 3, "csh", 3) == 0)
2109 const char *errstr
= NULL
;
2111 pidstr
= getenv(SSH_AGENTPID_ENV_NAME
);
2112 if (pidstr
== NULL
) {
2113 fprintf(stderr
, "%s not set, cannot kill agent\n",
2114 SSH_AGENTPID_ENV_NAME
);
2117 pid
= (int)strtonum(pidstr
, 2, INT_MAX
, &errstr
);
2120 "%s=\"%s\", which is not a good PID: %s\n",
2121 SSH_AGENTPID_ENV_NAME
, pidstr
, errstr
);
2124 if (kill(pid
, SIGTERM
) == -1) {
2128 format
= c_flag
? "unsetenv %s;\n" : "unset %s;\n";
2129 printf(format
, SSH_AUTHSOCKET_ENV_NAME
);
2130 printf(format
, SSH_AGENTPID_ENV_NAME
);
2131 printf("echo Agent pid %ld killed;\n", (long)pid
);
2136 * Minimum file descriptors:
2137 * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) +
2138 * a few spare for libc / stack protectors / sanitisers, etc.
2140 #define SSH_AGENT_MIN_FDS (3+1+1+1+4)
2141 if (rlim
.rlim_cur
< SSH_AGENT_MIN_FDS
)
2142 fatal("%s: file descriptor rlimit %lld too low (minimum %u)",
2143 __progname
, (long long)rlim
.rlim_cur
, SSH_AGENT_MIN_FDS
);
2144 maxfds
= rlim
.rlim_cur
- SSH_AGENT_MIN_FDS
;
2146 parent_pid
= getpid();
2148 if (agentsocket
== NULL
) {
2149 /* Create private directory for agent socket */
2150 mktemp_proto(socket_dir
, sizeof(socket_dir
));
2151 if (mkdtemp(socket_dir
) == NULL
) {
2152 perror("mkdtemp: private socket dir");
2155 snprintf(socket_name
, sizeof socket_name
, "%s/agent.%ld", socket_dir
,
2158 /* Try to use specified agent socket */
2159 socket_dir
[0] = '\0';
2160 strlcpy(socket_name
, agentsocket
, sizeof socket_name
);
2164 * Create socket early so it will exist before command gets run from
2167 prev_mask
= umask(0177);
2168 sock
= unix_listener(socket_name
, SSH_LISTEN_BACKLOG
, 0);
2170 /* XXX - unix_listener() calls error() not perror() */
2171 *socket_name
= '\0'; /* Don't unlink any existing file */
2177 * Fork, and have the parent execute the command, if any, or present
2178 * the socket data. The child continues as the authentication agent.
2180 if (D_flag
|| d_flag
) {
2181 log_init(__progname
,
2182 d_flag
? SYSLOG_LEVEL_DEBUG3
: SYSLOG_LEVEL_INFO
,
2183 SYSLOG_FACILITY_AUTH
, 1);
2184 format
= c_flag
? "setenv %s %s;\n" : "%s=%s; export %s;\n";
2185 printf(format
, SSH_AUTHSOCKET_ENV_NAME
, socket_name
,
2186 SSH_AUTHSOCKET_ENV_NAME
);
2187 printf("echo Agent pid %ld;\n", (long)parent_pid
);
2196 if (pid
!= 0) { /* Parent - execute the given command. */
2198 snprintf(pidstrbuf
, sizeof pidstrbuf
, "%ld", (long)pid
);
2200 format
= c_flag
? "setenv %s %s;\n" : "%s=%s; export %s;\n";
2201 printf(format
, SSH_AUTHSOCKET_ENV_NAME
, socket_name
,
2202 SSH_AUTHSOCKET_ENV_NAME
);
2203 printf(format
, SSH_AGENTPID_ENV_NAME
, pidstrbuf
,
2204 SSH_AGENTPID_ENV_NAME
);
2205 printf("echo Agent pid %ld;\n", (long)pid
);
2208 if (setenv(SSH_AUTHSOCKET_ENV_NAME
, socket_name
, 1) == -1 ||
2209 setenv(SSH_AGENTPID_ENV_NAME
, pidstrbuf
, 1) == -1) {
2218 log_init(__progname
, SYSLOG_LEVEL_INFO
, SYSLOG_FACILITY_AUTH
, 0);
2220 if (setsid() == -1) {
2221 error("setsid: %s", strerror(errno
));
2226 if (stdfd_devnull(1, 1, 1) == -1)
2227 error_f("stdfd_devnull failed");
2229 #ifdef HAVE_SETRLIMIT
2230 /* deny core dumps, since memory contains unencrypted private keys */
2231 rlim
.rlim_cur
= rlim
.rlim_max
= 0;
2232 if (setrlimit(RLIMIT_CORE
, &rlim
) == -1) {
2233 error("setrlimit RLIMIT_CORE: %s", strerror(errno
));
2240 cleanup_pid
= getpid();
2242 #ifdef ENABLE_PKCS11
2245 new_socket(AUTH_SOCKET
, sock
);
2247 parent_alive_interval
= 10;
2249 ssh_signal(SIGPIPE
, SIG_IGN
);
2250 ssh_signal(SIGINT
, (d_flag
| D_flag
) ? cleanup_handler
: SIG_IGN
);
2251 ssh_signal(SIGHUP
, cleanup_handler
);
2252 ssh_signal(SIGTERM
, cleanup_handler
);
2254 if (pledge("stdio rpath cpath unix id proc exec", NULL
) == -1)
2255 fatal("%s: pledge: %s", __progname
, strerror(errno
));
2256 platform_pledge_agent();
2259 prepare_poll(&pfd
, &npfd
, &timeout
, maxfds
);
2260 result
= poll(pfd
, npfd
, timeout
);
2261 saved_errno
= errno
;
2262 if (parent_alive_interval
!= 0)
2263 check_parent_exists();
2264 (void) reaper(); /* remove expired keys */
2266 if (saved_errno
== EINTR
)
2268 fatal("poll: %s", strerror(saved_errno
));
2269 } else if (result
> 0)
2270 after_poll(pfd
, npfd
, maxfds
);