1 /* $OpenBSD: ssh-agent.c,v 1.309 2024/11/06 22:51:26 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"
89 #include "pathnames.h"
90 #include "ssh-pkcs11.h"
92 #include "myproposal.h"
94 #ifndef DEFAULT_ALLOWED_PROVIDERS
95 # define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/local/lib*/*"
97 #ifndef DEFAULT_WEBSAFE_ALLOWLIST
98 # define DEFAULT_WEBSAFE_ALLOWLIST "ssh:*"
101 /* Maximum accepted message length */
102 #define AGENT_MAX_LEN (256*1024)
103 /* Maximum bytes to read from client socket */
104 #define AGENT_RBUF_LEN (4096)
105 /* Maximum number of recorded session IDs/hostkeys per connection */
106 #define AGENT_MAX_SESSION_IDS 16
107 /* Maximum size of session ID */
108 #define AGENT_MAX_SID_LEN 128
109 /* Maximum number of destination constraints to accept on a key */
110 #define AGENT_MAX_DEST_CONSTRAINTS 1024
111 /* Maximum number of associated certificate constraints to accept on a key */
112 #define AGENT_MAX_EXT_CERTS 1024
114 /* XXX store hostkey_sid in a refcounted tree */
128 typedef struct socket_entry
{
131 struct sshbuf
*input
;
132 struct sshbuf
*output
;
133 struct sshbuf
*request
;
135 struct hostkey_sid
*session_ids
;
136 int session_bind_attempted
;
139 u_int sockets_alloc
= 0;
140 SocketEntry
*sockets
= NULL
;
142 typedef struct identity
{
143 TAILQ_ENTRY(identity
) next
;
150 struct dest_constraint
*dest_constraints
;
151 size_t ndest_constraints
;
156 TAILQ_HEAD(idqueue
, identity
) idlist
;
159 /* private key table */
160 struct idtable
*idtab
;
164 /* pid of shell == parent of agent */
165 pid_t parent_pid
= -1;
166 time_t parent_alive_interval
= 0;
168 static sig_atomic_t signalled_exit
;
169 static sig_atomic_t signalled_keydrop
;
171 /* pid of process for which cleanup_socket is applicable */
172 pid_t cleanup_pid
= 0;
174 /* pathname and directory for AUTH_SOCKET */
175 char socket_name
[PATH_MAX
];
176 char socket_dir
[PATH_MAX
];
178 /* Pattern-list of allowed PKCS#11/Security key paths */
179 static char *allowed_providers
;
182 * Allows PKCS11 providers or SK keys that use non-internal providers to
183 * be added over a remote connection (identified by session-bind@openssh.com).
185 static int remote_add_provider
;
189 #define LOCK_SALT_SIZE 16
190 #define LOCK_ROUNDS 1
192 u_char lock_pwhash
[LOCK_SIZE
];
193 u_char lock_salt
[LOCK_SALT_SIZE
];
195 extern char *__progname
;
197 /* Default lifetime in seconds (0 == forever) */
198 static int lifetime
= 0;
200 static int fingerprint_hash
= SSH_FP_HASH_DEFAULT
;
202 /* Refuse signing of non-SSH messages for web-origin FIDO keys */
203 static int restrict_websafe
= 1;
204 static char *websafe_allowlist
;
207 close_socket(SocketEntry
*e
)
212 sshbuf_free(e
->input
);
213 sshbuf_free(e
->output
);
214 sshbuf_free(e
->request
);
215 for (i
= 0; i
< e
->nsession_ids
; i
++) {
216 sshkey_free(e
->session_ids
[i
].key
);
217 sshbuf_free(e
->session_ids
[i
].sid
);
219 free(e
->session_ids
);
220 memset(e
, '\0', sizeof(*e
));
222 e
->type
= AUTH_UNUSED
;
228 idtab
= xcalloc(1, sizeof(*idtab
));
229 TAILQ_INIT(&idtab
->idlist
);
234 free_dest_constraint_hop(struct dest_constraint_hop
*dch
)
242 for (i
= 0; i
< dch
->nkeys
; i
++)
243 sshkey_free(dch
->keys
[i
]);
245 free(dch
->key_is_ca
);
249 free_dest_constraints(struct dest_constraint
*dcs
, size_t ndcs
)
253 for (i
= 0; i
< ndcs
; i
++) {
254 free_dest_constraint_hop(&dcs
[i
].from
);
255 free_dest_constraint_hop(&dcs
[i
].to
);
262 dup_dest_constraint_hop(const struct dest_constraint_hop
*dch
,
263 struct dest_constraint_hop
*out
)
268 out
->user
= dch
->user
== NULL
? NULL
: xstrdup(dch
->user
);
269 out
->hostname
= dch
->hostname
== NULL
? NULL
: xstrdup(dch
->hostname
);
270 out
->is_ca
= dch
->is_ca
;
271 out
->nkeys
= dch
->nkeys
;
272 out
->keys
= out
->nkeys
== 0 ? NULL
:
273 xcalloc(out
->nkeys
, sizeof(*out
->keys
));
274 out
->key_is_ca
= out
->nkeys
== 0 ? NULL
:
275 xcalloc(out
->nkeys
, sizeof(*out
->key_is_ca
));
276 for (i
= 0; i
< dch
->nkeys
; i
++) {
277 if (dch
->keys
[i
] != NULL
&&
278 (r
= sshkey_from_private(dch
->keys
[i
],
279 &(out
->keys
[i
]))) != 0)
280 fatal_fr(r
, "copy key");
281 out
->key_is_ca
[i
] = dch
->key_is_ca
[i
];
285 static struct dest_constraint
*
286 dup_dest_constraints(const struct dest_constraint
*dcs
, size_t ndcs
)
289 struct dest_constraint
*ret
;
293 ret
= xcalloc(ndcs
, sizeof(*ret
));
294 for (i
= 0; i
< ndcs
; i
++) {
295 dup_dest_constraint_hop(&dcs
[i
].from
, &ret
[i
].from
);
296 dup_dest_constraint_hop(&dcs
[i
].to
, &ret
[i
].to
);
300 #endif /* ENABLE_PKCS11 */
302 #ifdef DEBUG_CONSTRAINTS
304 dump_dest_constraint_hop(const struct dest_constraint_hop
*dch
)
309 debug_f("user %s hostname %s is_ca %d nkeys %u",
310 dch
->user
== NULL
? "(null)" : dch
->user
,
311 dch
->hostname
== NULL
? "(null)" : dch
->hostname
,
312 dch
->is_ca
, dch
->nkeys
);
313 for (i
= 0; i
< dch
->nkeys
; i
++) {
315 if (dch
->keys
[i
] != NULL
&&
316 (fp
= sshkey_fingerprint(dch
->keys
[i
],
317 SSH_FP_HASH_DEFAULT
, SSH_FP_DEFAULT
)) == NULL
)
318 fatal_f("fingerprint failed");
319 debug_f("key %u/%u: %s%s%s key_is_ca %d", i
, dch
->nkeys
,
320 dch
->keys
[i
] == NULL
? "" : sshkey_ssh_name(dch
->keys
[i
]),
321 dch
->keys
[i
] == NULL
? "" : " ",
322 dch
->keys
[i
] == NULL
? "none" : fp
,
327 #endif /* DEBUG_CONSTRAINTS */
330 dump_dest_constraints(const char *context
,
331 const struct dest_constraint
*dcs
, size_t ndcs
)
333 #ifdef DEBUG_CONSTRAINTS
336 debug_f("%s: %zu constraints", context
, ndcs
);
337 for (i
= 0; i
< ndcs
; i
++) {
338 debug_f("constraint %zu / %zu: from: ", i
, ndcs
);
339 dump_dest_constraint_hop(&dcs
[i
].from
);
340 debug_f("constraint %zu / %zu: to: ", i
, ndcs
);
341 dump_dest_constraint_hop(&dcs
[i
].to
);
343 debug_f("done for %s", context
);
344 #endif /* DEBUG_CONSTRAINTS */
348 free_identity(Identity
*id
)
350 sshkey_free(id
->key
);
353 free(id
->sk_provider
);
354 free_dest_constraints(id
->dest_constraints
, id
->ndest_constraints
);
359 * Match 'key' against the key/CA list in a destination constraint hop
360 * Returns 0 on success or -1 otherwise.
363 match_key_hop(const char *tag
, const struct sshkey
*key
,
364 const struct dest_constraint_hop
*dch
)
366 const char *reason
= NULL
;
367 const char *hostname
= dch
->hostname
? dch
->hostname
: "(ORIGIN)";
374 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
375 SSH_FP_DEFAULT
)) == NULL
)
376 fatal_f("fingerprint failed");
377 debug3_f("%s: entering hostname %s, requested key %s %s, %u keys avail",
378 tag
, hostname
, sshkey_type(key
), fp
, dch
->nkeys
);
380 for (i
= 0; i
< dch
->nkeys
; i
++) {
381 if (dch
->keys
[i
] == NULL
)
384 if ((fp
= sshkey_fingerprint(dch
->keys
[i
], SSH_FP_HASH_DEFAULT
,
385 SSH_FP_DEFAULT
)) == NULL
)
386 fatal_f("fingerprint failed");
387 debug3_f("%s: key %u: %s%s %s", tag
, i
,
388 dch
->key_is_ca
[i
] ? "CA " : "",
389 sshkey_type(dch
->keys
[i
]), fp
);
391 if (!sshkey_is_cert(key
)) {
393 if (dch
->key_is_ca
[i
] ||
394 !sshkey_equal(key
, dch
->keys
[i
]))
399 if (!dch
->key_is_ca
[i
])
401 if (key
->cert
== NULL
|| key
->cert
->signature_key
== NULL
)
402 return -1; /* shouldn't happen */
403 if (!sshkey_equal(key
->cert
->signature_key
, dch
->keys
[i
]))
405 if (sshkey_cert_check_host(key
, hostname
, 1,
406 SSH_ALLOWED_CA_SIGALGS
, &reason
) != 0) {
407 debug_f("cert %s / hostname %s rejected: %s",
408 key
->cert
->key_id
, hostname
, reason
);
416 /* Check destination constraints on an identity against the hostkey/user */
418 permitted_by_dest_constraints(const struct sshkey
*fromkey
,
419 const struct sshkey
*tokey
, Identity
*id
, const char *user
,
420 const char **hostnamep
)
423 struct dest_constraint
*d
;
425 if (hostnamep
!= NULL
)
427 for (i
= 0; i
< id
->ndest_constraints
; i
++) {
428 d
= id
->dest_constraints
+ i
;
429 /* XXX remove logspam */
430 debug2_f("constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)",
431 i
, d
->from
.user
? d
->from
.user
: "",
432 d
->from
.user
? "@" : "",
433 d
->from
.hostname
? d
->from
.hostname
: "(ORIGIN)",
435 d
->to
.user
? d
->to
.user
: "", d
->to
.user
? "@" : "",
436 d
->to
.hostname
? d
->to
.hostname
: "(ANY)", d
->to
.nkeys
);
438 /* Match 'from' key */
439 if (fromkey
== NULL
) {
440 /* We are matching the first hop */
441 if (d
->from
.hostname
!= NULL
|| d
->from
.nkeys
!= 0)
443 } else if (match_key_hop("from", fromkey
, &d
->from
) != 0)
447 if (tokey
!= NULL
&& match_key_hop("to", tokey
, &d
->to
) != 0)
450 /* Match user if specified */
451 if (d
->to
.user
!= NULL
&& user
!= NULL
&&
452 !match_pattern(user
, d
->to
.user
))
455 /* successfully matched this constraint */
456 if (hostnamep
!= NULL
)
457 *hostnamep
= d
->to
.hostname
;
458 debug2_f("allowed for hostname %s",
459 d
->to
.hostname
== NULL
? "*" : d
->to
.hostname
);
463 debug2_f("%s identity \"%s\" not permitted for this destination",
464 sshkey_type(id
->key
), id
->comment
);
469 * Check whether hostkeys on a SocketEntry and the optionally specified user
470 * are permitted by the destination constraints on the Identity.
471 * Returns 0 on success or -1 otherwise.
474 identity_permitted(Identity
*id
, SocketEntry
*e
, char *user
,
475 const char **forward_hostnamep
, const char **last_hostnamep
)
479 struct hostkey_sid
*hks
;
480 const struct sshkey
*fromkey
= NULL
;
481 const char *test_user
;
484 /* XXX remove logspam */
485 debug3_f("entering: key %s comment \"%s\", %zu socket bindings, "
486 "%zu constraints", sshkey_type(id
->key
), id
->comment
,
487 e
->nsession_ids
, id
->ndest_constraints
);
488 if (id
->ndest_constraints
== 0)
489 return 0; /* unconstrained */
490 if (e
->session_bind_attempted
&& e
->nsession_ids
== 0) {
491 error_f("previous session bind failed on socket");
494 if (e
->nsession_ids
== 0)
495 return 0; /* local use */
497 * Walk through the hops recorded by session_id and try to find a
498 * constraint that satisfies each.
500 for (i
= 0; i
< e
->nsession_ids
; i
++) {
501 hks
= e
->session_ids
+ i
;
502 if (hks
->key
== NULL
)
503 fatal_f("internal error: no bound key");
504 /* XXX remove logspam */
506 if (fromkey
!= NULL
&&
507 (fp1
= sshkey_fingerprint(fromkey
, SSH_FP_HASH_DEFAULT
,
508 SSH_FP_DEFAULT
)) == NULL
)
509 fatal_f("fingerprint failed");
510 if ((fp2
= sshkey_fingerprint(hks
->key
, SSH_FP_HASH_DEFAULT
,
511 SSH_FP_DEFAULT
)) == NULL
)
512 fatal_f("fingerprint failed");
513 debug3_f("socketentry fd=%d, entry %zu %s, "
514 "from hostkey %s %s to user %s hostkey %s %s",
515 e
->fd
, i
, hks
->forwarded
? "FORWARD" : "AUTH",
516 fromkey
? sshkey_type(fromkey
) : "(ORIGIN)",
517 fromkey
? fp1
: "", user
? user
: "(ANY)",
518 sshkey_type(hks
->key
), fp2
);
522 * Record the hostnames for the initial forwarding and
523 * the final destination.
526 if (i
== e
->nsession_ids
- 1)
529 hp
= forward_hostnamep
;
530 /* Special handling for final recorded binding */
532 if (i
== e
->nsession_ids
- 1) {
533 /* Can only check user at final hop */
536 * user is only presented for signature requests.
537 * If this is the case, make sure last binding is not
540 if (hks
->forwarded
&& user
!= NULL
) {
541 error_f("tried to sign on forwarding hop");
544 } else if (!hks
->forwarded
) {
545 error_f("tried to forward though signing bind");
548 if (permitted_by_dest_constraints(fromkey
, hks
->key
, id
,
554 * Another special case: if the last bound session ID was for a
555 * forwarding, and this function is not being called to check a sign
556 * request (i.e. no 'user' supplied), then only permit the key if
557 * there is a permission that would allow it to be used at another
558 * destination. This hides keys that are allowed to be used to
559 * authenticate *to* a host but not permitted for *use* beyond it.
561 hks
= &e
->session_ids
[e
->nsession_ids
- 1];
562 if (hks
->forwarded
&& user
== NULL
&&
563 permitted_by_dest_constraints(hks
->key
, NULL
, id
,
565 debug3_f("key permitted at host but not after");
574 socket_is_remote(SocketEntry
*e
)
576 return e
->session_bind_attempted
|| (e
->nsession_ids
!= 0);
579 /* return matching private key for given public key */
581 lookup_identity(struct sshkey
*key
)
585 TAILQ_FOREACH(id
, &idtab
->idlist
, next
) {
586 if (sshkey_equal(key
, id
->key
))
592 /* Check confirmation of keysign request */
594 confirm_key(Identity
*id
, const char *extra
)
599 p
= sshkey_fingerprint(id
->key
, fingerprint_hash
, SSH_FP_DEFAULT
);
601 ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s",
603 extra
== NULL
? "" : "\n", extra
== NULL
? "" : extra
))
611 send_status(SocketEntry
*e
, int success
)
615 if ((r
= sshbuf_put_u32(e
->output
, 1)) != 0 ||
616 (r
= sshbuf_put_u8(e
->output
, success
?
617 SSH_AGENT_SUCCESS
: SSH_AGENT_FAILURE
)) != 0)
618 fatal_fr(r
, "compose");
621 /* send list of supported public keys to 'client' */
623 process_request_identities(SocketEntry
*e
)
626 struct sshbuf
*msg
, *keys
;
628 u_int i
= 0, nentries
= 0;
631 debug2_f("entering");
633 if ((msg
= sshbuf_new()) == NULL
|| (keys
= sshbuf_new()) == NULL
)
634 fatal_f("sshbuf_new failed");
635 TAILQ_FOREACH(id
, &idtab
->idlist
, next
) {
636 if ((fp
= sshkey_fingerprint(id
->key
, SSH_FP_HASH_DEFAULT
,
637 SSH_FP_DEFAULT
)) == NULL
)
638 fatal_f("fingerprint failed");
639 debug_f("key %u / %u: %s %s", i
++, idtab
->nentries
,
640 sshkey_ssh_name(id
->key
), fp
);
641 dump_dest_constraints(__func__
,
642 id
->dest_constraints
, id
->ndest_constraints
);
644 /* identity not visible, don't include in response */
645 if (identity_permitted(id
, e
, NULL
, NULL
, NULL
) != 0)
647 if ((r
= sshkey_puts_opts(id
->key
, keys
,
648 SSHKEY_SERIALIZE_INFO
)) != 0 ||
649 (r
= sshbuf_put_cstring(keys
, id
->comment
)) != 0) {
650 error_fr(r
, "compose key/comment");
655 debug2_f("replying with %u allowed of %u available keys",
656 nentries
, idtab
->nentries
);
657 if ((r
= sshbuf_put_u8(msg
, SSH2_AGENT_IDENTITIES_ANSWER
)) != 0 ||
658 (r
= sshbuf_put_u32(msg
, nentries
)) != 0 ||
659 (r
= sshbuf_putb(msg
, keys
)) != 0)
660 fatal_fr(r
, "compose");
661 if ((r
= sshbuf_put_stringb(e
->output
, msg
)) != 0)
662 fatal_fr(r
, "enqueue");
669 agent_decode_alg(struct sshkey
*key
, u_int flags
)
671 if (key
->type
== KEY_RSA
) {
672 if (flags
& SSH_AGENT_RSA_SHA2_256
)
673 return "rsa-sha2-256";
674 else if (flags
& SSH_AGENT_RSA_SHA2_512
)
675 return "rsa-sha2-512";
676 } else if (key
->type
== KEY_RSA_CERT
) {
677 if (flags
& SSH_AGENT_RSA_SHA2_256
)
678 return "rsa-sha2-256-cert-v01@openssh.com";
679 else if (flags
& SSH_AGENT_RSA_SHA2_512
)
680 return "rsa-sha2-512-cert-v01@openssh.com";
686 * Attempt to parse the contents of a buffer as a SSH publickey userauth
687 * request, checking its contents for consistency and matching the embedded
688 * key against the one that is being used for signing.
689 * Note: does not modify msg buffer.
690 * Optionally extract the username, session ID and/or hostkey from the request.
693 parse_userauth_request(struct sshbuf
*msg
, const struct sshkey
*expected_key
,
694 char **userp
, struct sshbuf
**sess_idp
, struct sshkey
**hostkeyp
)
696 struct sshbuf
*b
= NULL
, *sess_id
= NULL
;
697 char *user
= NULL
, *service
= NULL
, *method
= NULL
, *pkalg
= NULL
;
699 u_char t
, sig_follows
;
700 struct sshkey
*mkey
= NULL
, *hostkey
= NULL
;
704 if (sess_idp
!= NULL
)
706 if (hostkeyp
!= NULL
)
708 if ((b
= sshbuf_fromb(msg
)) == NULL
)
709 fatal_f("sshbuf_fromb");
711 /* SSH userauth request */
712 if ((r
= sshbuf_froms(b
, &sess_id
)) != 0)
714 if (sshbuf_len(sess_id
) == 0) {
715 r
= SSH_ERR_INVALID_FORMAT
;
718 if ((r
= sshbuf_get_u8(b
, &t
)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */
719 (r
= sshbuf_get_cstring(b
, &user
, NULL
)) != 0 || /* server user */
720 (r
= sshbuf_get_cstring(b
, &service
, NULL
)) != 0 || /* service */
721 (r
= sshbuf_get_cstring(b
, &method
, NULL
)) != 0 || /* method */
722 (r
= sshbuf_get_u8(b
, &sig_follows
)) != 0 || /* sig-follows */
723 (r
= sshbuf_get_cstring(b
, &pkalg
, NULL
)) != 0 || /* alg */
724 (r
= sshkey_froms(b
, &mkey
)) != 0) /* key */
726 if (t
!= SSH2_MSG_USERAUTH_REQUEST
||
728 strcmp(service
, "ssh-connection") != 0 ||
729 !sshkey_equal(expected_key
, mkey
) ||
730 sshkey_type_from_name(pkalg
) != expected_key
->type
) {
731 r
= SSH_ERR_INVALID_FORMAT
;
734 if (strcmp(method
, "publickey-hostbound-v00@openssh.com") == 0) {
735 if ((r
= sshkey_froms(b
, &hostkey
)) != 0)
737 } else if (strcmp(method
, "publickey") != 0) {
738 r
= SSH_ERR_INVALID_FORMAT
;
741 if (sshbuf_len(b
) != 0) {
742 r
= SSH_ERR_INVALID_FORMAT
;
747 debug3_f("well formed userauth");
752 if (sess_idp
!= NULL
) {
756 if (hostkeyp
!= NULL
) {
762 sshbuf_free(sess_id
);
768 sshkey_free(hostkey
);
773 * Attempt to parse the contents of a buffer as a SSHSIG signature request.
774 * Note: does not modify buffer.
777 parse_sshsig_request(struct sshbuf
*msg
)
782 if ((b
= sshbuf_fromb(msg
)) == NULL
)
783 fatal_f("sshbuf_fromb");
785 if ((r
= sshbuf_cmp(b
, 0, "SSHSIG", 6)) != 0 ||
786 (r
= sshbuf_consume(b
, 6)) != 0 ||
787 (r
= sshbuf_get_cstring(b
, NULL
, NULL
)) != 0 || /* namespace */
788 (r
= sshbuf_get_string_direct(b
, NULL
, NULL
)) != 0 || /* reserved */
789 (r
= sshbuf_get_cstring(b
, NULL
, NULL
)) != 0 || /* hashalg */
790 (r
= sshbuf_get_string_direct(b
, NULL
, NULL
)) != 0) /* H(msg) */
792 if (sshbuf_len(b
) != 0) {
793 r
= SSH_ERR_INVALID_FORMAT
;
804 * This function inspects a message to be signed by a FIDO key that has a
805 * web-like application string (i.e. one that does not begin with "ssh:".
806 * It checks that the message is one of those expected for SSH operations
807 * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
811 check_websafe_message_contents(struct sshkey
*key
, struct sshbuf
*data
)
813 if (parse_userauth_request(data
, key
, NULL
, NULL
, NULL
) == 0) {
814 debug_f("signed data matches public key userauth request");
817 if (parse_sshsig_request(data
) == 0) {
818 debug_f("signed data matches SSHSIG signature request");
822 /* XXX check CA signature operation */
824 error("web-origin key attempting to sign non-SSH message");
829 buf_equal(const struct sshbuf
*a
, const struct sshbuf
*b
)
831 if (sshbuf_ptr(a
) == NULL
|| sshbuf_ptr(b
) == NULL
)
832 return SSH_ERR_INVALID_ARGUMENT
;
833 if (sshbuf_len(a
) != sshbuf_len(b
))
834 return SSH_ERR_INVALID_FORMAT
;
835 if (timingsafe_bcmp(sshbuf_ptr(a
), sshbuf_ptr(b
), sshbuf_len(a
)) != 0)
836 return SSH_ERR_INVALID_FORMAT
;
842 process_sign_request2(SocketEntry
*e
)
844 u_char
*signature
= NULL
;
846 u_int compat
= 0, flags
;
847 int r
, ok
= -1, retried
= 0;
848 char *fp
= NULL
, *pin
= NULL
, *prompt
= NULL
;
849 char *user
= NULL
, *sig_dest
= NULL
;
850 const char *fwd_host
= NULL
, *dest_host
= NULL
;
851 struct sshbuf
*msg
= NULL
, *data
= NULL
, *sid
= NULL
;
852 struct sshkey
*key
= NULL
, *hostkey
= NULL
;
854 struct notifier_ctx
*notifier
= NULL
;
858 if ((msg
= sshbuf_new()) == NULL
|| (data
= sshbuf_new()) == NULL
)
859 fatal_f("sshbuf_new failed");
860 if ((r
= sshkey_froms(e
->request
, &key
)) != 0 ||
861 (r
= sshbuf_get_stringb(e
->request
, data
)) != 0 ||
862 (r
= sshbuf_get_u32(e
->request
, &flags
)) != 0) {
863 error_fr(r
, "parse");
867 if ((id
= lookup_identity(key
)) == NULL
) {
868 verbose_f("%s key not found", sshkey_type(key
));
871 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
872 SSH_FP_DEFAULT
)) == NULL
)
873 fatal_f("fingerprint failed");
875 if (id
->ndest_constraints
!= 0) {
876 if (e
->nsession_ids
== 0) {
877 logit_f("refusing use of destination-constrained key "
878 "to sign on unbound connection");
881 if (parse_userauth_request(data
, key
, &user
, &sid
,
883 logit_f("refusing use of destination-constrained key "
884 "to sign an unidentified signature");
888 debug_f("user=%s", user
);
889 if (identity_permitted(id
, e
, user
, &fwd_host
, &dest_host
) != 0)
891 /* XXX display fwd_host/dest_host in askpass UI */
893 * Ensure that the session ID is the most recent one
894 * registered on the socket - it should have been bound by
895 * ssh immediately before userauth.
898 e
->session_ids
[e
->nsession_ids
- 1].sid
) != 0) {
899 error_f("unexpected session ID (%zu listed) on "
900 "signature request for target user %s with "
901 "key %s %s", e
->nsession_ids
, user
,
902 sshkey_type(id
->key
), fp
);
906 * Ensure that the hostkey embedded in the signature matches
907 * the one most recently bound to the socket. An exception is
908 * made for the initial forwarding hop.
910 if (e
->nsession_ids
> 1 && hostkey
== NULL
) {
911 error_f("refusing use of destination-constrained key: "
912 "no hostkey recorded in signature for forwarded "
916 if (hostkey
!= NULL
&& !sshkey_equal(hostkey
,
917 e
->session_ids
[e
->nsession_ids
- 1].key
)) {
918 error_f("refusing use of destination-constrained key: "
919 "mismatch between hostkey in request and most "
920 "recently bound session");
923 xasprintf(&sig_dest
, "public key authentication request for "
924 "user \"%s\" to listed host", user
);
926 if (id
->confirm
&& confirm_key(id
, sig_dest
) != 0) {
927 verbose_f("user refused key");
930 if (sshkey_is_sk(id
->key
)) {
931 if (restrict_websafe
&&
932 match_pattern_list(id
->key
->sk_application
,
933 websafe_allowlist
, 0) != 1 &&
934 !check_websafe_message_contents(key
, data
)) {
935 /* error already logged */
938 if (id
->key
->sk_flags
& SSH_SK_USER_PRESENCE_REQD
) {
939 notifier
= notify_start(0,
940 "Confirm user presence for key %s %s%s%s",
941 sshkey_type(id
->key
), fp
,
942 sig_dest
== NULL
? "" : "\n",
943 sig_dest
== NULL
? "" : sig_dest
);
947 if ((r
= sshkey_sign(id
->key
, &signature
, &slen
,
948 sshbuf_ptr(data
), sshbuf_len(data
), agent_decode_alg(key
, flags
),
949 id
->sk_provider
, pin
, compat
)) != 0) {
950 debug_fr(r
, "sshkey_sign");
951 if (pin
== NULL
&& !retried
&& sshkey_is_sk(id
->key
) &&
952 r
== SSH_ERR_KEY_WRONG_PASSPHRASE
) {
953 notify_complete(notifier
, NULL
);
955 /* XXX include sig_dest */
956 xasprintf(&prompt
, "Enter PIN%sfor %s key %s: ",
957 (id
->key
->sk_flags
& SSH_SK_USER_PRESENCE_REQD
) ?
958 " and confirm user presence " : " ",
959 sshkey_type(id
->key
), fp
);
960 pin
= read_passphrase(prompt
, RP_USE_ASKPASS
);
964 error_fr(r
, "sshkey_sign");
969 debug_f("good signature");
971 notify_complete(notifier
, "User presence confirmed");
974 if ((r
= sshbuf_put_u8(msg
, SSH2_AGENT_SIGN_RESPONSE
)) != 0 ||
975 (r
= sshbuf_put_string(msg
, signature
, slen
)) != 0)
976 fatal_fr(r
, "compose");
977 } else if ((r
= sshbuf_put_u8(msg
, SSH_AGENT_FAILURE
)) != 0)
978 fatal_fr(r
, "compose failure");
980 if ((r
= sshbuf_put_stringb(e
->output
, msg
)) != 0)
981 fatal_fr(r
, "enqueue");
987 sshkey_free(hostkey
);
994 freezero(pin
, strlen(pin
));
999 process_remove_identity(SocketEntry
*e
)
1002 struct sshkey
*key
= NULL
;
1005 debug2_f("entering");
1006 if ((r
= sshkey_froms(e
->request
, &key
)) != 0) {
1007 error_fr(r
, "parse key");
1010 if ((id
= lookup_identity(key
)) == NULL
) {
1011 debug_f("key not found");
1014 /* identity not visible, cannot be removed */
1015 if (identity_permitted(id
, e
, NULL
, NULL
, NULL
) != 0)
1016 goto done
; /* error already logged */
1017 /* We have this key, free it. */
1018 if (idtab
->nentries
< 1)
1019 fatal_f("internal error: nentries %d", idtab
->nentries
);
1020 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
1026 send_status(e
, success
);
1030 remove_all_identities(void)
1034 debug2_f("entering");
1035 /* Loop over all identities and clear the keys. */
1036 for (id
= TAILQ_FIRST(&idtab
->idlist
); id
;
1037 id
= TAILQ_FIRST(&idtab
->idlist
)) {
1038 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
1042 /* Mark that there are no identities. */
1043 idtab
->nentries
= 0;
1047 process_remove_all_identities(SocketEntry
*e
)
1049 remove_all_identities();
1055 /* removes expired keys and returns number of seconds until the next expiry */
1059 time_t deadline
= 0, now
= monotime();
1062 for (id
= TAILQ_FIRST(&idtab
->idlist
); id
; id
= nxt
) {
1063 nxt
= TAILQ_NEXT(id
, next
);
1066 if (now
>= id
->death
) {
1067 debug("expiring key '%s'", id
->comment
);
1068 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
1072 deadline
= (deadline
== 0) ? id
->death
:
1073 MINIMUM(deadline
, id
->death
);
1075 if (deadline
== 0 || deadline
<= now
)
1078 return (deadline
- now
);
1082 parse_dest_constraint_hop(struct sshbuf
*b
, struct dest_constraint_hop
*dch
)
1087 struct sshkey
*k
= NULL
;
1090 memset(dch
, '\0', sizeof(*dch
));
1091 if ((r
= sshbuf_get_cstring(b
, &dch
->user
, NULL
)) != 0 ||
1092 (r
= sshbuf_get_cstring(b
, &dch
->hostname
, NULL
)) != 0 ||
1093 (r
= sshbuf_get_string_direct(b
, NULL
, &elen
)) != 0) {
1094 error_fr(r
, "parse");
1098 error_f("unsupported extensions (len %zu)", elen
);
1099 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1102 if (*dch
->hostname
== '\0') {
1103 free(dch
->hostname
);
1104 dch
->hostname
= NULL
;
1106 if (*dch
->user
== '\0') {
1110 while (sshbuf_len(b
) != 0) {
1111 dch
->keys
= xrecallocarray(dch
->keys
, dch
->nkeys
,
1112 dch
->nkeys
+ 1, sizeof(*dch
->keys
));
1113 dch
->key_is_ca
= xrecallocarray(dch
->key_is_ca
, dch
->nkeys
,
1114 dch
->nkeys
+ 1, sizeof(*dch
->key_is_ca
));
1115 if ((r
= sshkey_froms(b
, &k
)) != 0 ||
1116 (r
= sshbuf_get_u8(b
, &key_is_ca
)) != 0)
1118 if ((fp
= sshkey_fingerprint(k
, SSH_FP_HASH_DEFAULT
,
1119 SSH_FP_DEFAULT
)) == NULL
)
1120 fatal_f("fingerprint failed");
1121 debug3_f("%s%s%s: adding %skey %s %s",
1122 dch
->user
== NULL
? "" : dch
->user
,
1123 dch
->user
== NULL
? "" : "@",
1124 dch
->hostname
, key_is_ca
? "CA " : "", sshkey_type(k
), fp
);
1126 dch
->keys
[dch
->nkeys
] = k
;
1127 dch
->key_is_ca
[dch
->nkeys
] = key_is_ca
!= 0;
1129 k
= NULL
; /* transferred */
1139 parse_dest_constraint(struct sshbuf
*m
, struct dest_constraint
*dc
)
1141 struct sshbuf
*b
= NULL
, *frombuf
= NULL
, *tobuf
= NULL
;
1145 debug3_f("entering");
1147 memset(dc
, '\0', sizeof(*dc
));
1148 if ((r
= sshbuf_froms(m
, &b
)) != 0 ||
1149 (r
= sshbuf_froms(b
, &frombuf
)) != 0 ||
1150 (r
= sshbuf_froms(b
, &tobuf
)) != 0 ||
1151 (r
= sshbuf_get_string_direct(b
, NULL
, &elen
)) != 0) {
1152 error_fr(r
, "parse");
1155 if ((r
= parse_dest_constraint_hop(frombuf
, &dc
->from
)) != 0 ||
1156 (r
= parse_dest_constraint_hop(tobuf
, &dc
->to
)) != 0)
1157 goto out
; /* already logged */
1159 error_f("unsupported extensions (len %zu)", elen
);
1160 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1163 debug2_f("parsed %s (%u keys) > %s%s%s (%u keys)",
1164 dc
->from
.hostname
? dc
->from
.hostname
: "(ORIGIN)", dc
->from
.nkeys
,
1165 dc
->to
.user
? dc
->to
.user
: "", dc
->to
.user
? "@" : "",
1166 dc
->to
.hostname
? dc
->to
.hostname
: "(ANY)", dc
->to
.nkeys
);
1167 /* check consistency */
1168 if ((dc
->from
.hostname
== NULL
) != (dc
->from
.nkeys
== 0) ||
1169 dc
->from
.user
!= NULL
) {
1170 error_f("inconsistent \"from\" specification");
1171 r
= SSH_ERR_INVALID_FORMAT
;
1174 if (dc
->to
.hostname
== NULL
|| dc
->to
.nkeys
== 0) {
1175 error_f("incomplete \"to\" specification");
1176 r
= SSH_ERR_INVALID_FORMAT
;
1183 sshbuf_free(frombuf
);
1189 parse_key_constraint_extension(struct sshbuf
*m
, char **sk_providerp
,
1190 struct dest_constraint
**dcsp
, size_t *ndcsp
, int *cert_onlyp
,
1191 struct sshkey
***certs
, size_t *ncerts
)
1193 char *ext_name
= NULL
;
1195 struct sshbuf
*b
= NULL
;
1199 if ((r
= sshbuf_get_cstring(m
, &ext_name
, NULL
)) != 0) {
1200 error_fr(r
, "parse constraint extension");
1203 debug_f("constraint ext %s", ext_name
);
1204 if (strcmp(ext_name
, "sk-provider@openssh.com") == 0) {
1205 if (sk_providerp
== NULL
) {
1206 error_f("%s not valid here", ext_name
);
1207 r
= SSH_ERR_INVALID_FORMAT
;
1210 if (*sk_providerp
!= NULL
) {
1211 error_f("%s already set", ext_name
);
1212 r
= SSH_ERR_INVALID_FORMAT
;
1215 if ((r
= sshbuf_get_cstring(m
, sk_providerp
, NULL
)) != 0) {
1216 error_fr(r
, "parse %s", ext_name
);
1219 } else if (strcmp(ext_name
,
1220 "restrict-destination-v00@openssh.com") == 0) {
1221 if (*dcsp
!= NULL
) {
1222 error_f("%s already set", ext_name
);
1225 if ((r
= sshbuf_froms(m
, &b
)) != 0) {
1226 error_fr(r
, "parse %s outer", ext_name
);
1229 while (sshbuf_len(b
) != 0) {
1230 if (*ndcsp
>= AGENT_MAX_DEST_CONSTRAINTS
) {
1231 error_f("too many %s constraints", ext_name
);
1234 *dcsp
= xrecallocarray(*dcsp
, *ndcsp
, *ndcsp
+ 1,
1236 if ((r
= parse_dest_constraint(b
,
1237 *dcsp
+ (*ndcsp
)++)) != 0)
1238 goto out
; /* error already logged */
1240 } else if (strcmp(ext_name
,
1241 "associated-certs-v00@openssh.com") == 0) {
1242 if (certs
== NULL
|| ncerts
== NULL
|| cert_onlyp
== NULL
) {
1243 error_f("%s not valid here", ext_name
);
1244 r
= SSH_ERR_INVALID_FORMAT
;
1247 if (*certs
!= NULL
) {
1248 error_f("%s already set", ext_name
);
1251 if ((r
= sshbuf_get_u8(m
, &v
)) != 0 ||
1252 (r
= sshbuf_froms(m
, &b
)) != 0) {
1253 error_fr(r
, "parse %s", ext_name
);
1256 *cert_onlyp
= v
!= 0;
1257 while (sshbuf_len(b
) != 0) {
1258 if (*ncerts
>= AGENT_MAX_EXT_CERTS
) {
1259 error_f("too many %s constraints", ext_name
);
1262 *certs
= xrecallocarray(*certs
, *ncerts
, *ncerts
+ 1,
1264 if ((r
= sshkey_froms(b
, &k
)) != 0) {
1265 error_fr(r
, "parse key");
1268 (*certs
)[(*ncerts
)++] = k
;
1271 error_f("unsupported constraint \"%s\"", ext_name
);
1272 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1284 parse_key_constraints(struct sshbuf
*m
, struct sshkey
*k
, time_t *deathp
,
1285 u_int
*secondsp
, int *confirmp
, char **sk_providerp
,
1286 struct dest_constraint
**dcsp
, size_t *ndcsp
,
1287 int *cert_onlyp
, size_t *ncerts
, struct sshkey
***certs
)
1291 u_int seconds
, maxsign
= 0;
1293 while (sshbuf_len(m
)) {
1294 if ((r
= sshbuf_get_u8(m
, &ctype
)) != 0) {
1295 error_fr(r
, "parse constraint type");
1299 case SSH_AGENT_CONSTRAIN_LIFETIME
:
1301 error_f("lifetime already set");
1302 r
= SSH_ERR_INVALID_FORMAT
;
1305 if ((r
= sshbuf_get_u32(m
, &seconds
)) != 0) {
1306 error_fr(r
, "parse lifetime constraint");
1309 *deathp
= monotime() + seconds
;
1310 *secondsp
= seconds
;
1312 case SSH_AGENT_CONSTRAIN_CONFIRM
:
1313 if (*confirmp
!= 0) {
1314 error_f("confirm already set");
1315 r
= SSH_ERR_INVALID_FORMAT
;
1320 case SSH_AGENT_CONSTRAIN_MAXSIGN
:
1322 error_f("maxsign not valid here");
1323 r
= SSH_ERR_INVALID_FORMAT
;
1327 error_f("maxsign already set");
1328 r
= SSH_ERR_INVALID_FORMAT
;
1331 if ((r
= sshbuf_get_u32(m
, &maxsign
)) != 0) {
1332 error_fr(r
, "parse maxsign constraint");
1335 if ((r
= sshkey_enable_maxsign(k
, maxsign
)) != 0) {
1336 error_fr(r
, "enable maxsign");
1340 case SSH_AGENT_CONSTRAIN_EXTENSION
:
1341 if ((r
= parse_key_constraint_extension(m
,
1342 sk_providerp
, dcsp
, ndcsp
,
1343 cert_onlyp
, certs
, ncerts
)) != 0)
1344 goto out
; /* error already logged */
1347 error_f("Unknown constraint %d", ctype
);
1348 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1359 process_add_identity(SocketEntry
*e
)
1362 int success
= 0, confirm
= 0;
1363 char *fp
, *comment
= NULL
, *sk_provider
= NULL
;
1364 char canonical_provider
[PATH_MAX
];
1367 struct dest_constraint
*dest_constraints
= NULL
;
1368 size_t ndest_constraints
= 0;
1369 struct sshkey
*k
= NULL
;
1370 int r
= SSH_ERR_INTERNAL_ERROR
;
1372 debug2_f("entering");
1373 if ((r
= sshkey_private_deserialize(e
->request
, &k
)) != 0 ||
1375 (r
= sshbuf_get_cstring(e
->request
, &comment
, NULL
)) != 0) {
1376 error_fr(r
, "parse");
1379 if (parse_key_constraints(e
->request
, k
, &death
, &seconds
, &confirm
,
1380 &sk_provider
, &dest_constraints
, &ndest_constraints
,
1381 NULL
, NULL
, NULL
) != 0) {
1382 error_f("failed to parse constraints");
1383 sshbuf_reset(e
->request
);
1386 dump_dest_constraints(__func__
, dest_constraints
, ndest_constraints
);
1388 if (sk_provider
!= NULL
) {
1389 if (!sshkey_is_sk(k
)) {
1390 error("Cannot add provider: %s is not an "
1391 "authenticator-hosted key", sshkey_type(k
));
1394 if (strcasecmp(sk_provider
, "internal") == 0) {
1395 debug_f("internal provider");
1397 if (socket_is_remote(e
) && !remote_add_provider
) {
1398 verbose("failed add of SK provider \"%.100s\": "
1399 "remote addition of providers is disabled",
1403 if (realpath(sk_provider
, canonical_provider
) == NULL
) {
1404 verbose("failed provider \"%.100s\": "
1405 "realpath: %s", sk_provider
,
1410 sk_provider
= xstrdup(canonical_provider
);
1411 if (match_pattern_list(sk_provider
,
1412 allowed_providers
, 0) != 1) {
1413 error("Refusing add key: "
1414 "provider %s not allowed", sk_provider
);
1419 if ((r
= sshkey_shield_private(k
)) != 0) {
1420 error_fr(r
, "shield private");
1423 if (lifetime
&& !death
)
1424 death
= monotime() + lifetime
;
1425 if ((id
= lookup_identity(k
)) == NULL
) {
1426 id
= xcalloc(1, sizeof(Identity
));
1427 TAILQ_INSERT_TAIL(&idtab
->idlist
, id
, next
);
1428 /* Increment the number of identities. */
1431 /* identity not visible, do not update */
1432 if (identity_permitted(id
, e
, NULL
, NULL
, NULL
) != 0)
1433 goto out
; /* error already logged */
1434 /* key state might have been updated */
1435 sshkey_free(id
->key
);
1437 free(id
->sk_provider
);
1438 free_dest_constraints(id
->dest_constraints
,
1439 id
->ndest_constraints
);
1443 id
->comment
= comment
;
1445 id
->confirm
= confirm
;
1446 id
->sk_provider
= sk_provider
;
1447 id
->dest_constraints
= dest_constraints
;
1448 id
->ndest_constraints
= ndest_constraints
;
1450 if ((fp
= sshkey_fingerprint(k
, SSH_FP_HASH_DEFAULT
,
1451 SSH_FP_DEFAULT
)) == NULL
)
1452 fatal_f("sshkey_fingerprint failed");
1453 debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) "
1454 "(provider: %s) (destination constraints: %zu)",
1455 sshkey_ssh_name(k
), fp
, comment
, seconds
, confirm
,
1456 sk_provider
== NULL
? "none" : sk_provider
, ndest_constraints
);
1462 dest_constraints
= NULL
;
1463 ndest_constraints
= 0;
1469 free_dest_constraints(dest_constraints
, ndest_constraints
);
1470 send_status(e
, success
);
1473 /* XXX todo: encrypt sensitive data with passphrase */
1475 process_lock_agent(SocketEntry
*e
, int lock
)
1477 int r
, success
= 0, delay
;
1479 u_char passwdhash
[LOCK_SIZE
];
1480 static u_int fail_count
= 0;
1483 debug2_f("entering");
1485 * This is deliberately fatal: the user has requested that we lock,
1486 * but we can't parse their request properly. The only safe thing to
1489 if ((r
= sshbuf_get_cstring(e
->request
, &passwd
, &pwlen
)) != 0)
1490 fatal_fr(r
, "parse");
1492 debug("empty password not supported");
1493 } else if (locked
&& !lock
) {
1494 if (bcrypt_pbkdf(passwd
, pwlen
, lock_salt
, sizeof(lock_salt
),
1495 passwdhash
, sizeof(passwdhash
), LOCK_ROUNDS
) < 0)
1496 fatal("bcrypt_pbkdf");
1497 if (timingsafe_bcmp(passwdhash
, lock_pwhash
, LOCK_SIZE
) == 0) {
1498 debug("agent unlocked");
1501 explicit_bzero(lock_pwhash
, sizeof(lock_pwhash
));
1504 /* delay in 0.1s increments up to 10s */
1505 if (fail_count
< 100)
1507 delay
= 100000 * fail_count
;
1508 debug("unlock failed, delaying %0.1lf seconds",
1509 (double)delay
/1000000);
1512 explicit_bzero(passwdhash
, sizeof(passwdhash
));
1513 } else if (!locked
&& lock
) {
1514 debug("agent locked");
1516 arc4random_buf(lock_salt
, sizeof(lock_salt
));
1517 if (bcrypt_pbkdf(passwd
, pwlen
, lock_salt
, sizeof(lock_salt
),
1518 lock_pwhash
, sizeof(lock_pwhash
), LOCK_ROUNDS
) < 0)
1519 fatal("bcrypt_pbkdf");
1522 freezero(passwd
, pwlen
);
1523 send_status(e
, success
);
1527 no_identities(SocketEntry
*e
)
1532 if ((msg
= sshbuf_new()) == NULL
)
1533 fatal_f("sshbuf_new failed");
1534 if ((r
= sshbuf_put_u8(msg
, SSH2_AGENT_IDENTITIES_ANSWER
)) != 0 ||
1535 (r
= sshbuf_put_u32(msg
, 0)) != 0 ||
1536 (r
= sshbuf_put_stringb(e
->output
, msg
)) != 0)
1537 fatal_fr(r
, "compose");
1541 #ifdef ENABLE_PKCS11
1542 /* Add an identity to idlist; takes ownership of 'key' and 'comment' */
1544 add_p11_identity(struct sshkey
*key
, char *comment
, const char *provider
,
1545 time_t death
, u_int confirm
, struct dest_constraint
*dest_constraints
,
1546 size_t ndest_constraints
)
1550 if (lookup_identity(key
) != NULL
) {
1555 id
= xcalloc(1, sizeof(Identity
));
1557 id
->comment
= comment
;
1558 id
->provider
= xstrdup(provider
);
1560 id
->confirm
= confirm
;
1561 id
->dest_constraints
= dup_dest_constraints(dest_constraints
,
1563 id
->ndest_constraints
= ndest_constraints
;
1564 TAILQ_INSERT_TAIL(&idtab
->idlist
, id
, next
);
1569 process_add_smartcard_key(SocketEntry
*e
)
1571 char *provider
= NULL
, *pin
= NULL
, canonical_provider
[PATH_MAX
];
1572 char **comments
= NULL
;
1573 int r
, i
, count
= 0, success
= 0, confirm
= 0;
1576 struct sshkey
**keys
= NULL
, *k
;
1577 struct dest_constraint
*dest_constraints
= NULL
;
1578 size_t j
, ndest_constraints
= 0, ncerts
= 0;
1579 struct sshkey
**certs
= NULL
;
1582 debug2_f("entering");
1583 if ((r
= sshbuf_get_cstring(e
->request
, &provider
, NULL
)) != 0 ||
1584 (r
= sshbuf_get_cstring(e
->request
, &pin
, NULL
)) != 0) {
1585 error_fr(r
, "parse");
1588 if (parse_key_constraints(e
->request
, NULL
, &death
, &seconds
, &confirm
,
1589 NULL
, &dest_constraints
, &ndest_constraints
, &cert_only
,
1590 &ncerts
, &certs
) != 0) {
1591 error_f("failed to parse constraints");
1594 dump_dest_constraints(__func__
, dest_constraints
, ndest_constraints
);
1595 if (socket_is_remote(e
) && !remote_add_provider
) {
1596 verbose("failed PKCS#11 add of \"%.100s\": remote addition of "
1597 "providers is disabled", provider
);
1600 if (realpath(provider
, canonical_provider
) == NULL
) {
1601 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1602 provider
, strerror(errno
));
1605 if (match_pattern_list(canonical_provider
, allowed_providers
, 0) != 1) {
1606 verbose("refusing PKCS#11 add of \"%.100s\": "
1607 "provider not allowed", canonical_provider
);
1610 debug_f("add %.100s", canonical_provider
);
1611 if (lifetime
&& !death
)
1612 death
= monotime() + lifetime
;
1614 count
= pkcs11_add_provider(canonical_provider
, pin
, &keys
, &comments
);
1615 for (i
= 0; i
< count
; i
++) {
1616 if (comments
[i
] == NULL
|| comments
[i
][0] == '\0') {
1618 comments
[i
] = xstrdup(canonical_provider
);
1620 for (j
= 0; j
< ncerts
; j
++) {
1621 if (!sshkey_is_cert(certs
[j
]))
1623 if (!sshkey_equal_public(keys
[i
], certs
[j
]))
1625 if (pkcs11_make_cert(keys
[i
], certs
[j
], &k
) != 0)
1627 add_p11_identity(k
, xstrdup(comments
[i
]),
1628 canonical_provider
, death
, confirm
,
1629 dest_constraints
, ndest_constraints
);
1632 if (!cert_only
&& lookup_identity(keys
[i
]) == NULL
) {
1633 add_p11_identity(keys
[i
], comments
[i
],
1634 canonical_provider
, death
, confirm
,
1635 dest_constraints
, ndest_constraints
);
1636 keys
[i
] = NULL
; /* transferred */
1637 comments
[i
] = NULL
; /* transferred */
1640 /* XXX update constraints for existing keys */
1641 sshkey_free(keys
[i
]);
1649 free_dest_constraints(dest_constraints
, ndest_constraints
);
1650 for (j
= 0; j
< ncerts
; j
++)
1651 sshkey_free(certs
[j
]);
1653 send_status(e
, success
);
1657 process_remove_smartcard_key(SocketEntry
*e
)
1659 char *provider
= NULL
, *pin
= NULL
, canonical_provider
[PATH_MAX
];
1663 debug2_f("entering");
1664 if ((r
= sshbuf_get_cstring(e
->request
, &provider
, NULL
)) != 0 ||
1665 (r
= sshbuf_get_cstring(e
->request
, &pin
, NULL
)) != 0) {
1666 error_fr(r
, "parse");
1671 if (realpath(provider
, canonical_provider
) == NULL
) {
1672 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1673 provider
, strerror(errno
));
1677 debug_f("remove %.100s", canonical_provider
);
1678 for (id
= TAILQ_FIRST(&idtab
->idlist
); id
; id
= nxt
) {
1679 nxt
= TAILQ_NEXT(id
, next
);
1680 /* Skip file--based keys */
1681 if (id
->provider
== NULL
)
1683 if (!strcmp(canonical_provider
, id
->provider
)) {
1684 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
1689 if (pkcs11_del_provider(canonical_provider
) == 0)
1692 error_f("pkcs11_del_provider failed");
1695 send_status(e
, success
);
1697 #endif /* ENABLE_PKCS11 */
1700 process_ext_session_bind(SocketEntry
*e
)
1702 int r
, sid_match
, key_match
;
1703 struct sshkey
*key
= NULL
;
1704 struct sshbuf
*sid
= NULL
, *sig
= NULL
;
1709 debug2_f("entering");
1710 e
->session_bind_attempted
= 1;
1711 if ((r
= sshkey_froms(e
->request
, &key
)) != 0 ||
1712 (r
= sshbuf_froms(e
->request
, &sid
)) != 0 ||
1713 (r
= sshbuf_froms(e
->request
, &sig
)) != 0 ||
1714 (r
= sshbuf_get_u8(e
->request
, &fwd
)) != 0) {
1715 error_fr(r
, "parse");
1718 if (sshbuf_len(sid
) > AGENT_MAX_SID_LEN
) {
1719 error_f("session ID too long");
1722 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
1723 SSH_FP_DEFAULT
)) == NULL
)
1724 fatal_f("fingerprint failed");
1725 /* check signature with hostkey on session ID */
1726 if ((r
= sshkey_verify(key
, sshbuf_ptr(sig
), sshbuf_len(sig
),
1727 sshbuf_ptr(sid
), sshbuf_len(sid
), NULL
, 0, NULL
)) != 0) {
1728 error_fr(r
, "sshkey_verify for %s %s", sshkey_type(key
), fp
);
1731 /* check whether sid/key already recorded */
1732 for (i
= 0; i
< e
->nsession_ids
; i
++) {
1733 if (!e
->session_ids
[i
].forwarded
) {
1734 error_f("attempt to bind session ID to socket "
1735 "previously bound for authentication attempt");
1739 sid_match
= buf_equal(sid
, e
->session_ids
[i
].sid
) == 0;
1740 key_match
= sshkey_equal(key
, e
->session_ids
[i
].key
);
1741 if (sid_match
&& key_match
) {
1742 debug_f("session ID already recorded for %s %s",
1743 sshkey_type(key
), fp
);
1746 } else if (sid_match
) {
1747 error_f("session ID recorded against different key "
1748 "for %s %s", sshkey_type(key
), fp
);
1753 * new sid with previously-seen key can happen, e.g. multiple
1754 * connections to the same host.
1757 /* record new key/sid */
1758 if (e
->nsession_ids
>= AGENT_MAX_SESSION_IDS
) {
1759 error_f("too many session IDs recorded");
1762 e
->session_ids
= xrecallocarray(e
->session_ids
, e
->nsession_ids
,
1763 e
->nsession_ids
+ 1, sizeof(*e
->session_ids
));
1764 i
= e
->nsession_ids
++;
1765 debug_f("recorded %s %s (slot %zu of %d)", sshkey_type(key
), fp
, i
,
1766 AGENT_MAX_SESSION_IDS
);
1767 e
->session_ids
[i
].key
= key
;
1768 e
->session_ids
[i
].forwarded
= fwd
!= 0;
1769 key
= NULL
; /* transferred */
1770 /* can't transfer sid; it's refcounted and scoped to request's life */
1771 if ((e
->session_ids
[i
].sid
= sshbuf_new()) == NULL
)
1772 fatal_f("sshbuf_new");
1773 if ((r
= sshbuf_putb(e
->session_ids
[i
].sid
, sid
)) != 0)
1774 fatal_fr(r
, "sshbuf_putb session ID");
1782 return r
== 0 ? 1 : 0;
1786 process_extension(SocketEntry
*e
)
1791 debug2_f("entering");
1792 if ((r
= sshbuf_get_cstring(e
->request
, &name
, NULL
)) != 0) {
1793 error_fr(r
, "parse");
1796 if (strcmp(name
, "session-bind@openssh.com") == 0)
1797 success
= process_ext_session_bind(e
);
1799 debug_f("unsupported extension \"%s\"", name
);
1802 send_status(e
, success
);
1805 * dispatch incoming message.
1806 * returns 1 on success, 0 for incomplete messages or -1 on error.
1809 process_message(u_int socknum
)
1817 if (socknum
>= sockets_alloc
)
1818 fatal_f("sock %u >= allocated %u", socknum
, sockets_alloc
);
1819 e
= &sockets
[socknum
];
1821 if (sshbuf_len(e
->input
) < 5)
1822 return 0; /* Incomplete message header. */
1823 cp
= sshbuf_ptr(e
->input
);
1824 msg_len
= PEEK_U32(cp
);
1825 if (msg_len
> AGENT_MAX_LEN
) {
1826 debug_f("socket %u (fd=%d) message too long %u > %u",
1827 socknum
, e
->fd
, msg_len
, AGENT_MAX_LEN
);
1830 if (sshbuf_len(e
->input
) < msg_len
+ 4)
1831 return 0; /* Incomplete message body. */
1833 /* move the current input to e->request */
1834 sshbuf_reset(e
->request
);
1835 if ((r
= sshbuf_get_stringb(e
->input
, e
->request
)) != 0 ||
1836 (r
= sshbuf_get_u8(e
->request
, &type
)) != 0) {
1837 if (r
== SSH_ERR_MESSAGE_INCOMPLETE
||
1838 r
== SSH_ERR_STRING_TOO_LARGE
) {
1839 error_fr(r
, "parse");
1842 fatal_fr(r
, "parse");
1845 debug_f("socket %u (fd=%d) type %d", socknum
, e
->fd
, type
);
1847 /* check whether agent is locked */
1848 if (locked
&& type
!= SSH_AGENTC_UNLOCK
) {
1849 sshbuf_reset(e
->request
);
1851 case SSH2_AGENTC_REQUEST_IDENTITIES
:
1852 /* send empty lists */
1856 /* send a fail message for all other request types */
1863 case SSH_AGENTC_LOCK
:
1864 case SSH_AGENTC_UNLOCK
:
1865 process_lock_agent(e
, type
== SSH_AGENTC_LOCK
);
1867 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES
:
1868 process_remove_all_identities(e
); /* safe for !WITH_SSH1 */
1871 case SSH2_AGENTC_SIGN_REQUEST
:
1872 process_sign_request2(e
);
1874 case SSH2_AGENTC_REQUEST_IDENTITIES
:
1875 process_request_identities(e
);
1877 case SSH2_AGENTC_ADD_IDENTITY
:
1878 case SSH2_AGENTC_ADD_ID_CONSTRAINED
:
1879 process_add_identity(e
);
1881 case SSH2_AGENTC_REMOVE_IDENTITY
:
1882 process_remove_identity(e
);
1884 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES
:
1885 process_remove_all_identities(e
);
1887 #ifdef ENABLE_PKCS11
1888 case SSH_AGENTC_ADD_SMARTCARD_KEY
:
1889 case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
:
1890 process_add_smartcard_key(e
);
1892 case SSH_AGENTC_REMOVE_SMARTCARD_KEY
:
1893 process_remove_smartcard_key(e
);
1895 #endif /* ENABLE_PKCS11 */
1896 case SSH_AGENTC_EXTENSION
:
1897 process_extension(e
);
1900 /* Unknown message. Respond with failure. */
1901 error("Unknown message %d", type
);
1902 sshbuf_reset(e
->request
);
1910 new_socket(sock_type type
, int fd
)
1912 u_int i
, old_alloc
, new_alloc
;
1914 debug_f("type = %s", type
== AUTH_CONNECTION
? "CONNECTION" :
1915 (type
== AUTH_SOCKET
? "SOCKET" : "UNKNOWN"));
1921 for (i
= 0; i
< sockets_alloc
; i
++)
1922 if (sockets
[i
].type
== AUTH_UNUSED
) {
1924 if ((sockets
[i
].input
= sshbuf_new()) == NULL
||
1925 (sockets
[i
].output
= sshbuf_new()) == NULL
||
1926 (sockets
[i
].request
= sshbuf_new()) == NULL
)
1927 fatal_f("sshbuf_new failed");
1928 sockets
[i
].type
= type
;
1931 old_alloc
= sockets_alloc
;
1932 new_alloc
= sockets_alloc
+ 10;
1933 sockets
= xrecallocarray(sockets
, old_alloc
, new_alloc
,
1934 sizeof(sockets
[0]));
1935 for (i
= old_alloc
; i
< new_alloc
; i
++)
1936 sockets
[i
].type
= AUTH_UNUSED
;
1937 sockets_alloc
= new_alloc
;
1938 sockets
[old_alloc
].fd
= fd
;
1939 if ((sockets
[old_alloc
].input
= sshbuf_new()) == NULL
||
1940 (sockets
[old_alloc
].output
= sshbuf_new()) == NULL
||
1941 (sockets
[old_alloc
].request
= sshbuf_new()) == NULL
)
1942 fatal_f("sshbuf_new failed");
1943 sockets
[old_alloc
].type
= type
;
1947 handle_socket_read(u_int socknum
)
1949 struct sockaddr_un sunaddr
;
1955 slen
= sizeof(sunaddr
);
1956 fd
= accept(sockets
[socknum
].fd
, (struct sockaddr
*)&sunaddr
, &slen
);
1958 error("accept from AUTH_SOCKET: %s", strerror(errno
));
1961 if (getpeereid(fd
, &euid
, &egid
) == -1) {
1962 error("getpeereid %d failed: %s", fd
, strerror(errno
));
1966 if ((euid
!= 0) && (getuid() != euid
)) {
1967 error("uid mismatch: peer euid %u != uid %u",
1968 (u_int
) euid
, (u_int
) getuid());
1972 new_socket(AUTH_CONNECTION
, fd
);
1977 handle_conn_read(u_int socknum
)
1979 char buf
[AGENT_RBUF_LEN
];
1983 if ((len
= read(sockets
[socknum
].fd
, buf
, sizeof(buf
))) <= 0) {
1985 if (errno
== EAGAIN
|| errno
== EINTR
)
1987 error_f("read error on socket %u (fd %d): %s",
1988 socknum
, sockets
[socknum
].fd
, strerror(errno
));
1992 if ((r
= sshbuf_put(sockets
[socknum
].input
, buf
, len
)) != 0)
1993 fatal_fr(r
, "compose");
1994 explicit_bzero(buf
, sizeof(buf
));
1996 if ((r
= process_message(socknum
)) == -1)
2005 handle_conn_write(u_int socknum
)
2010 if (sshbuf_len(sockets
[socknum
].output
) == 0)
2011 return 0; /* shouldn't happen */
2012 if ((len
= write(sockets
[socknum
].fd
,
2013 sshbuf_ptr(sockets
[socknum
].output
),
2014 sshbuf_len(sockets
[socknum
].output
))) <= 0) {
2016 if (errno
== EAGAIN
|| errno
== EINTR
)
2018 error_f("read error on socket %u (fd %d): %s",
2019 socknum
, sockets
[socknum
].fd
, strerror(errno
));
2023 if ((r
= sshbuf_consume(sockets
[socknum
].output
, len
)) != 0)
2024 fatal_fr(r
, "consume");
2029 after_poll(struct pollfd
*pfd
, size_t npfd
, u_int maxfds
)
2032 u_int socknum
, activefds
= npfd
;
2034 for (i
= 0; i
< npfd
; i
++) {
2035 if (pfd
[i
].revents
== 0)
2037 /* Find sockets entry */
2038 for (socknum
= 0; socknum
< sockets_alloc
; socknum
++) {
2039 if (sockets
[socknum
].type
!= AUTH_SOCKET
&&
2040 sockets
[socknum
].type
!= AUTH_CONNECTION
)
2042 if (pfd
[i
].fd
== sockets
[socknum
].fd
)
2045 if (socknum
>= sockets_alloc
) {
2046 error_f("no socket for fd %d", pfd
[i
].fd
);
2049 /* Process events */
2050 switch (sockets
[socknum
].type
) {
2052 if ((pfd
[i
].revents
& (POLLIN
|POLLERR
)) == 0)
2054 if (npfd
> maxfds
) {
2055 debug3("out of fds (active %u >= limit %u); "
2056 "skipping accept", activefds
, maxfds
);
2059 if (handle_socket_read(socknum
) == 0)
2062 case AUTH_CONNECTION
:
2063 if ((pfd
[i
].revents
& (POLLIN
|POLLHUP
|POLLERR
)) != 0 &&
2064 handle_conn_read(socknum
) != 0)
2066 if ((pfd
[i
].revents
& (POLLOUT
|POLLHUP
)) != 0 &&
2067 handle_conn_write(socknum
) != 0) {
2070 fatal("activefds == 0 at close_sock");
2071 close_socket(&sockets
[socknum
]);
2083 prepare_poll(struct pollfd
**pfdp
, size_t *npfdp
, struct timespec
*timeoutp
, u_int maxfds
)
2085 struct pollfd
*pfd
= *pfdp
;
2086 size_t i
, j
, npfd
= 0;
2090 /* Count active sockets */
2091 for (i
= 0; i
< sockets_alloc
; i
++) {
2092 switch (sockets
[i
].type
) {
2094 case AUTH_CONNECTION
:
2100 fatal("Unknown socket type %d", sockets
[i
].type
);
2104 if (npfd
!= *npfdp
&&
2105 (pfd
= recallocarray(pfd
, *npfdp
, npfd
, sizeof(*pfd
))) == NULL
)
2106 fatal_f("recallocarray failed");
2110 for (i
= j
= 0; i
< sockets_alloc
; i
++) {
2111 switch (sockets
[i
].type
) {
2113 if (npfd
> maxfds
) {
2114 debug3("out of fds (active %zu >= limit %u); "
2115 "skipping arming listener", npfd
, maxfds
);
2118 pfd
[j
].fd
= sockets
[i
].fd
;
2120 pfd
[j
].events
= POLLIN
;
2123 case AUTH_CONNECTION
:
2124 pfd
[j
].fd
= sockets
[i
].fd
;
2127 * Only prepare to read if we can handle a full-size
2128 * input read buffer and enqueue a max size reply..
2130 if ((r
= sshbuf_check_reserve(sockets
[i
].input
,
2131 AGENT_RBUF_LEN
)) == 0 &&
2132 (r
= sshbuf_check_reserve(sockets
[i
].output
,
2133 AGENT_MAX_LEN
)) == 0)
2134 pfd
[j
].events
= POLLIN
;
2135 else if (r
!= SSH_ERR_NO_BUFFER_SPACE
)
2136 fatal_fr(r
, "reserve");
2137 if (sshbuf_len(sockets
[i
].output
) > 0)
2138 pfd
[j
].events
|= POLLOUT
;
2145 deadline
= reaper();
2146 if (parent_alive_interval
!= 0)
2147 deadline
= (deadline
== 0) ? parent_alive_interval
:
2148 MINIMUM(deadline
, parent_alive_interval
);
2150 ptimeout_deadline_sec(timeoutp
, deadline
);
2155 cleanup_socket(void)
2157 if (cleanup_pid
!= 0 && getpid() != cleanup_pid
)
2161 unlink(socket_name
);
2170 #ifdef ENABLE_PKCS11
2177 cleanup_handler(int sig
)
2179 signalled_exit
= sig
;
2183 keydrop_handler(int sig
)
2185 signalled_keydrop
= sig
;
2189 check_parent_exists(void)
2192 * If our parent has exited then getppid() will return (pid_t)1,
2193 * so testing for that should be safe.
2195 if (parent_pid
!= -1 && getppid() != parent_pid
) {
2196 /* printf("Parent has died - Authentication agent exiting.\n"); */
2206 "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
2207 " [-O option] [-P allowed_providers] [-t life]\n"
2208 " ssh-agent [-a bind_address] [-E fingerprint_hash] [-O option]\n"
2209 " [-P allowed_providers] [-t life] command [arg ...]\n"
2210 " ssh-agent [-c | -s] -k\n");
2215 main(int ac
, char **av
)
2217 int c_flag
= 0, d_flag
= 0, D_flag
= 0, k_flag
= 0, s_flag
= 0;
2218 int sock
, ch
, result
, saved_errno
;
2219 char *shell
, *format
, *pidstr
, *agentsocket
= NULL
;
2221 #ifdef HAVE_SETRLIMIT
2225 extern char *optarg
;
2227 char pidstrbuf
[1 + 3 * sizeof pid
];
2230 struct timespec timeout
;
2231 struct pollfd
*pfd
= NULL
;
2234 sigset_t nsigset
, osigset
;
2236 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2240 (void)setegid(getgid());
2241 (void)setgid(getgid());
2243 platform_disable_tracing(0); /* strict=no */
2245 #ifdef RLIMIT_NOFILE
2246 if (getrlimit(RLIMIT_NOFILE
, &rlim
) == -1)
2247 fatal("%s: getrlimit: %s", __progname
, strerror(errno
));
2250 __progname
= ssh_get_progname(av
[0]);
2253 while ((ch
= getopt(ac
, av
, "cDdksE:a:O:P:t:")) != -1) {
2256 fingerprint_hash
= ssh_digest_alg_by_name(optarg
);
2257 if (fingerprint_hash
== -1)
2258 fatal("Invalid hash algorithm \"%s\"", optarg
);
2269 if (strcmp(optarg
, "no-restrict-websafe") == 0)
2270 restrict_websafe
= 0;
2271 else if (strcmp(optarg
, "allow-remote-pkcs11") == 0)
2272 remote_add_provider
= 1;
2273 else if ((ccp
= strprefix(optarg
,
2274 "websafe-allow=", 0)) != NULL
) {
2275 if (websafe_allowlist
!= NULL
)
2276 fatal("websafe-allow already set");
2277 websafe_allowlist
= xstrdup(ccp
);
2279 fatal("Unknown -O option");
2282 if (allowed_providers
!= NULL
)
2283 fatal("-P option already specified");
2284 allowed_providers
= xstrdup(optarg
);
2292 if (d_flag
|| D_flag
)
2297 if (d_flag
|| D_flag
)
2302 agentsocket
= optarg
;
2305 if ((lifetime
= convtime(optarg
)) == -1) {
2306 fprintf(stderr
, "Invalid lifetime\n");
2317 if (ac
> 0 && (c_flag
|| k_flag
|| s_flag
|| d_flag
|| D_flag
))
2320 if (allowed_providers
== NULL
)
2321 allowed_providers
= xstrdup(DEFAULT_ALLOWED_PROVIDERS
);
2322 if (websafe_allowlist
== NULL
)
2323 websafe_allowlist
= xstrdup(DEFAULT_WEBSAFE_ALLOWLIST
);
2325 if (ac
== 0 && !c_flag
&& !s_flag
) {
2326 shell
= getenv("SHELL");
2327 if (shell
!= NULL
&& (len
= strlen(shell
)) > 2 &&
2328 strncmp(shell
+ len
- 3, "csh", 3) == 0)
2332 const char *errstr
= NULL
;
2334 pidstr
= getenv(SSH_AGENTPID_ENV_NAME
);
2335 if (pidstr
== NULL
) {
2336 fprintf(stderr
, "%s not set, cannot kill agent\n",
2337 SSH_AGENTPID_ENV_NAME
);
2340 pid
= (int)strtonum(pidstr
, 2, INT_MAX
, &errstr
);
2343 "%s=\"%s\", which is not a good PID: %s\n",
2344 SSH_AGENTPID_ENV_NAME
, pidstr
, errstr
);
2347 if (kill(pid
, SIGTERM
) == -1) {
2351 format
= c_flag
? "unsetenv %s;\n" : "unset %s;\n";
2352 printf(format
, SSH_AUTHSOCKET_ENV_NAME
);
2353 printf(format
, SSH_AGENTPID_ENV_NAME
);
2354 printf("echo Agent pid %ld killed;\n", (long)pid
);
2359 * Minimum file descriptors:
2360 * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) +
2361 * a few spare for libc / stack protectors / sanitisers, etc.
2363 #define SSH_AGENT_MIN_FDS (3+1+1+1+4)
2364 if (rlim
.rlim_cur
< SSH_AGENT_MIN_FDS
)
2365 fatal("%s: file descriptor rlimit %lld too low (minimum %u)",
2366 __progname
, (long long)rlim
.rlim_cur
, SSH_AGENT_MIN_FDS
);
2367 maxfds
= rlim
.rlim_cur
- SSH_AGENT_MIN_FDS
;
2369 parent_pid
= getpid();
2371 if (agentsocket
== NULL
) {
2372 /* Create private directory for agent socket */
2373 mktemp_proto(socket_dir
, sizeof(socket_dir
));
2374 if (mkdtemp(socket_dir
) == NULL
) {
2375 perror("mkdtemp: private socket dir");
2378 snprintf(socket_name
, sizeof socket_name
, "%s/agent.%ld", socket_dir
,
2381 /* Try to use specified agent socket */
2382 socket_dir
[0] = '\0';
2383 strlcpy(socket_name
, agentsocket
, sizeof socket_name
);
2387 * Create socket early so it will exist before command gets run from
2390 prev_mask
= umask(0177);
2391 sock
= unix_listener(socket_name
, SSH_LISTEN_BACKLOG
, 0);
2393 /* XXX - unix_listener() calls error() not perror() */
2394 *socket_name
= '\0'; /* Don't unlink any existing file */
2400 * Fork, and have the parent execute the command, if any, or present
2401 * the socket data. The child continues as the authentication agent.
2403 if (D_flag
|| d_flag
) {
2404 log_init(__progname
,
2405 d_flag
? SYSLOG_LEVEL_DEBUG3
: SYSLOG_LEVEL_INFO
,
2406 SYSLOG_FACILITY_AUTH
, 1);
2407 format
= c_flag
? "setenv %s %s;\n" : "%s=%s; export %s;\n";
2408 printf(format
, SSH_AUTHSOCKET_ENV_NAME
, socket_name
,
2409 SSH_AUTHSOCKET_ENV_NAME
);
2410 printf("echo Agent pid %ld;\n", (long)parent_pid
);
2419 if (pid
!= 0) { /* Parent - execute the given command. */
2421 snprintf(pidstrbuf
, sizeof pidstrbuf
, "%ld", (long)pid
);
2423 format
= c_flag
? "setenv %s %s;\n" : "%s=%s; export %s;\n";
2424 printf(format
, SSH_AUTHSOCKET_ENV_NAME
, socket_name
,
2425 SSH_AUTHSOCKET_ENV_NAME
);
2426 printf(format
, SSH_AGENTPID_ENV_NAME
, pidstrbuf
,
2427 SSH_AGENTPID_ENV_NAME
);
2428 printf("echo Agent pid %ld;\n", (long)pid
);
2431 if (setenv(SSH_AUTHSOCKET_ENV_NAME
, socket_name
, 1) == -1 ||
2432 setenv(SSH_AGENTPID_ENV_NAME
, pidstrbuf
, 1) == -1) {
2441 log_init(__progname
, SYSLOG_LEVEL_INFO
, SYSLOG_FACILITY_AUTH
, 0);
2443 if (setsid() == -1) {
2444 error("setsid: %s", strerror(errno
));
2449 if (stdfd_devnull(1, 1, 1) == -1)
2450 error_f("stdfd_devnull failed");
2452 #ifdef HAVE_SETRLIMIT
2453 /* deny core dumps, since memory contains unencrypted private keys */
2454 rlim
.rlim_cur
= rlim
.rlim_max
= 0;
2455 if (setrlimit(RLIMIT_CORE
, &rlim
) == -1) {
2456 error("setrlimit RLIMIT_CORE: %s", strerror(errno
));
2463 cleanup_pid
= getpid();
2465 #ifdef ENABLE_PKCS11
2468 new_socket(AUTH_SOCKET
, sock
);
2470 parent_alive_interval
= 10;
2472 ssh_signal(SIGPIPE
, SIG_IGN
);
2473 ssh_signal(SIGINT
, (d_flag
| D_flag
) ? cleanup_handler
: SIG_IGN
);
2474 ssh_signal(SIGHUP
, cleanup_handler
);
2475 ssh_signal(SIGTERM
, cleanup_handler
);
2476 ssh_signal(SIGUSR1
, keydrop_handler
);
2478 sigemptyset(&nsigset
);
2479 sigaddset(&nsigset
, SIGINT
);
2480 sigaddset(&nsigset
, SIGHUP
);
2481 sigaddset(&nsigset
, SIGTERM
);
2482 sigaddset(&nsigset
, SIGUSR1
);
2484 if (pledge("stdio rpath cpath unix id proc exec", NULL
) == -1)
2485 fatal("%s: pledge: %s", __progname
, strerror(errno
));
2486 platform_pledge_agent();
2489 sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
2490 if (signalled_exit
!= 0) {
2491 logit("exiting on signal %d", (int)signalled_exit
);
2494 if (signalled_keydrop
) {
2495 logit("signal %d received; removing all keys",
2497 remove_all_identities();
2498 signalled_keydrop
= 0;
2500 ptimeout_init(&timeout
);
2501 prepare_poll(&pfd
, &npfd
, &timeout
, maxfds
);
2502 result
= ppoll(pfd
, npfd
, ptimeout_get_tsp(&timeout
), &osigset
);
2503 sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
2504 saved_errno
= errno
;
2505 if (parent_alive_interval
!= 0)
2506 check_parent_exists();
2507 (void) reaper(); /* remove expired keys */
2509 if (saved_errno
== EINTR
)
2511 fatal("poll: %s", strerror(saved_errno
));
2512 } else if (result
> 0)
2513 after_poll(pfd
, npfd
, maxfds
);