1 /* $OpenBSD: ssh-agent.c,v 1.306 2024/03/09 05:12:13 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*/*"
98 /* Maximum accepted message length */
99 #define AGENT_MAX_LEN (256*1024)
100 /* Maximum bytes to read from client socket */
101 #define AGENT_RBUF_LEN (4096)
102 /* Maximum number of recorded session IDs/hostkeys per connection */
103 #define AGENT_MAX_SESSION_IDS 16
104 /* Maximum size of session ID */
105 #define AGENT_MAX_SID_LEN 128
106 /* Maximum number of destination constraints to accept on a key */
107 #define AGENT_MAX_DEST_CONSTRAINTS 1024
108 /* Maximum number of associated certificate constraints to accept on a key */
109 #define AGENT_MAX_EXT_CERTS 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
;
133 int session_bind_attempted
;
136 u_int sockets_alloc
= 0;
137 SocketEntry
*sockets
= NULL
;
139 typedef struct identity
{
140 TAILQ_ENTRY(identity
) next
;
147 struct dest_constraint
*dest_constraints
;
148 size_t ndest_constraints
;
153 TAILQ_HEAD(idqueue
, identity
) idlist
;
156 /* private key table */
157 struct idtable
*idtab
;
161 /* pid of shell == parent of agent */
162 pid_t parent_pid
= -1;
163 time_t parent_alive_interval
= 0;
165 sig_atomic_t signalled
= 0;
167 /* pid of process for which cleanup_socket is applicable */
168 pid_t cleanup_pid
= 0;
170 /* pathname and directory for AUTH_SOCKET */
171 char socket_name
[PATH_MAX
];
172 char socket_dir
[PATH_MAX
];
174 /* Pattern-list of allowed PKCS#11/Security key paths */
175 static char *allowed_providers
;
178 * Allows PKCS11 providers or SK keys that use non-internal providers to
179 * be added over a remote connection (identified by session-bind@openssh.com).
181 static int remote_add_provider
;
185 #define LOCK_SALT_SIZE 16
186 #define LOCK_ROUNDS 1
188 u_char lock_pwhash
[LOCK_SIZE
];
189 u_char lock_salt
[LOCK_SALT_SIZE
];
191 extern char *__progname
;
193 /* Default lifetime in seconds (0 == forever) */
194 static int lifetime
= 0;
196 static int fingerprint_hash
= SSH_FP_HASH_DEFAULT
;
198 /* Refuse signing of non-SSH messages for web-origin FIDO keys */
199 static int restrict_websafe
= 1;
202 * Client connection count; incremented in new_socket() and decremented in
203 * close_socket(). When it reaches 0, ssh-agent will exit. Since it is
204 * normally initialized to 1, it will never reach 0. However, if the -x
205 * option is specified, it is initialized to 0 in main(); in that case,
206 * ssh-agent will exit as soon as it has had at least one client but no
209 static int xcount
= 1;
212 close_socket(SocketEntry
*e
)
217 if (e
->type
== AUTH_CONNECTION
) {
218 debug("xcount %d -> %d", xcount
, xcount
- 1);
223 sshbuf_free(e
->input
);
224 sshbuf_free(e
->output
);
225 sshbuf_free(e
->request
);
226 for (i
= 0; i
< e
->nsession_ids
; i
++) {
227 sshkey_free(e
->session_ids
[i
].key
);
228 sshbuf_free(e
->session_ids
[i
].sid
);
230 free(e
->session_ids
);
231 memset(e
, '\0', sizeof(*e
));
233 e
->type
= AUTH_UNUSED
;
241 idtab
= xcalloc(1, sizeof(*idtab
));
242 TAILQ_INIT(&idtab
->idlist
);
247 free_dest_constraint_hop(struct dest_constraint_hop
*dch
)
255 for (i
= 0; i
< dch
->nkeys
; i
++)
256 sshkey_free(dch
->keys
[i
]);
258 free(dch
->key_is_ca
);
262 free_dest_constraints(struct dest_constraint
*dcs
, size_t ndcs
)
266 for (i
= 0; i
< ndcs
; i
++) {
267 free_dest_constraint_hop(&dcs
[i
].from
);
268 free_dest_constraint_hop(&dcs
[i
].to
);
275 dup_dest_constraint_hop(const struct dest_constraint_hop
*dch
,
276 struct dest_constraint_hop
*out
)
281 out
->user
= dch
->user
== NULL
? NULL
: xstrdup(dch
->user
);
282 out
->hostname
= dch
->hostname
== NULL
? NULL
: xstrdup(dch
->hostname
);
283 out
->is_ca
= dch
->is_ca
;
284 out
->nkeys
= dch
->nkeys
;
285 out
->keys
= out
->nkeys
== 0 ? NULL
:
286 xcalloc(out
->nkeys
, sizeof(*out
->keys
));
287 out
->key_is_ca
= out
->nkeys
== 0 ? NULL
:
288 xcalloc(out
->nkeys
, sizeof(*out
->key_is_ca
));
289 for (i
= 0; i
< dch
->nkeys
; i
++) {
290 if (dch
->keys
[i
] != NULL
&&
291 (r
= sshkey_from_private(dch
->keys
[i
],
292 &(out
->keys
[i
]))) != 0)
293 fatal_fr(r
, "copy key");
294 out
->key_is_ca
[i
] = dch
->key_is_ca
[i
];
298 static struct dest_constraint
*
299 dup_dest_constraints(const struct dest_constraint
*dcs
, size_t ndcs
)
302 struct dest_constraint
*ret
;
306 ret
= xcalloc(ndcs
, sizeof(*ret
));
307 for (i
= 0; i
< ndcs
; i
++) {
308 dup_dest_constraint_hop(&dcs
[i
].from
, &ret
[i
].from
);
309 dup_dest_constraint_hop(&dcs
[i
].to
, &ret
[i
].to
);
313 #endif /* ENABLE_PKCS11 */
315 #ifdef DEBUG_CONSTRAINTS
317 dump_dest_constraint_hop(const struct dest_constraint_hop
*dch
)
322 debug_f("user %s hostname %s is_ca %d nkeys %u",
323 dch
->user
== NULL
? "(null)" : dch
->user
,
324 dch
->hostname
== NULL
? "(null)" : dch
->hostname
,
325 dch
->is_ca
, dch
->nkeys
);
326 for (i
= 0; i
< dch
->nkeys
; i
++) {
328 if (dch
->keys
[i
] != NULL
&&
329 (fp
= sshkey_fingerprint(dch
->keys
[i
],
330 SSH_FP_HASH_DEFAULT
, SSH_FP_DEFAULT
)) == NULL
)
331 fatal_f("fingerprint failed");
332 debug_f("key %u/%u: %s%s%s key_is_ca %d", i
, dch
->nkeys
,
333 dch
->keys
[i
] == NULL
? "" : sshkey_ssh_name(dch
->keys
[i
]),
334 dch
->keys
[i
] == NULL
? "" : " ",
335 dch
->keys
[i
] == NULL
? "none" : fp
,
340 #endif /* DEBUG_CONSTRAINTS */
343 dump_dest_constraints(const char *context
,
344 const struct dest_constraint
*dcs
, size_t ndcs
)
346 #ifdef DEBUG_CONSTRAINTS
349 debug_f("%s: %zu constraints", context
, ndcs
);
350 for (i
= 0; i
< ndcs
; i
++) {
351 debug_f("constraint %zu / %zu: from: ", i
, ndcs
);
352 dump_dest_constraint_hop(&dcs
[i
].from
);
353 debug_f("constraint %zu / %zu: to: ", i
, ndcs
);
354 dump_dest_constraint_hop(&dcs
[i
].to
);
356 debug_f("done for %s", context
);
357 #endif /* DEBUG_CONSTRAINTS */
361 free_identity(Identity
*id
)
363 sshkey_free(id
->key
);
366 free(id
->sk_provider
);
367 free_dest_constraints(id
->dest_constraints
, id
->ndest_constraints
);
372 * Match 'key' against the key/CA list in a destination constraint hop
373 * Returns 0 on success or -1 otherwise.
376 match_key_hop(const char *tag
, const struct sshkey
*key
,
377 const struct dest_constraint_hop
*dch
)
379 const char *reason
= NULL
;
380 const char *hostname
= dch
->hostname
? dch
->hostname
: "(ORIGIN)";
387 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
388 SSH_FP_DEFAULT
)) == NULL
)
389 fatal_f("fingerprint failed");
390 debug3_f("%s: entering hostname %s, requested key %s %s, %u keys avail",
391 tag
, hostname
, sshkey_type(key
), fp
, dch
->nkeys
);
393 for (i
= 0; i
< dch
->nkeys
; i
++) {
394 if (dch
->keys
[i
] == NULL
)
397 if ((fp
= sshkey_fingerprint(dch
->keys
[i
], SSH_FP_HASH_DEFAULT
,
398 SSH_FP_DEFAULT
)) == NULL
)
399 fatal_f("fingerprint failed");
400 debug3_f("%s: key %u: %s%s %s", tag
, i
,
401 dch
->key_is_ca
[i
] ? "CA " : "",
402 sshkey_type(dch
->keys
[i
]), fp
);
404 if (!sshkey_is_cert(key
)) {
406 if (dch
->key_is_ca
[i
] ||
407 !sshkey_equal(key
, dch
->keys
[i
]))
412 if (!dch
->key_is_ca
[i
])
414 if (key
->cert
== NULL
|| key
->cert
->signature_key
== NULL
)
415 return -1; /* shouldn't happen */
416 if (!sshkey_equal(key
->cert
->signature_key
, dch
->keys
[i
]))
418 if (sshkey_cert_check_host(key
, hostname
, 1,
419 SSH_ALLOWED_CA_SIGALGS
, &reason
) != 0) {
420 debug_f("cert %s / hostname %s rejected: %s",
421 key
->cert
->key_id
, hostname
, reason
);
429 /* Check destination constraints on an identity against the hostkey/user */
431 permitted_by_dest_constraints(const struct sshkey
*fromkey
,
432 const struct sshkey
*tokey
, Identity
*id
, const char *user
,
433 const char **hostnamep
)
436 struct dest_constraint
*d
;
438 if (hostnamep
!= NULL
)
440 for (i
= 0; i
< id
->ndest_constraints
; i
++) {
441 d
= id
->dest_constraints
+ i
;
442 /* XXX remove logspam */
443 debug2_f("constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)",
444 i
, d
->from
.user
? d
->from
.user
: "",
445 d
->from
.user
? "@" : "",
446 d
->from
.hostname
? d
->from
.hostname
: "(ORIGIN)",
448 d
->to
.user
? d
->to
.user
: "", d
->to
.user
? "@" : "",
449 d
->to
.hostname
? d
->to
.hostname
: "(ANY)", d
->to
.nkeys
);
451 /* Match 'from' key */
452 if (fromkey
== NULL
) {
453 /* We are matching the first hop */
454 if (d
->from
.hostname
!= NULL
|| d
->from
.nkeys
!= 0)
456 } else if (match_key_hop("from", fromkey
, &d
->from
) != 0)
460 if (tokey
!= NULL
&& match_key_hop("to", tokey
, &d
->to
) != 0)
463 /* Match user if specified */
464 if (d
->to
.user
!= NULL
&& user
!= NULL
&&
465 !match_pattern(user
, d
->to
.user
))
468 /* successfully matched this constraint */
469 if (hostnamep
!= NULL
)
470 *hostnamep
= d
->to
.hostname
;
471 debug2_f("allowed for hostname %s",
472 d
->to
.hostname
== NULL
? "*" : d
->to
.hostname
);
476 debug2_f("%s identity \"%s\" not permitted for this destination",
477 sshkey_type(id
->key
), id
->comment
);
482 * Check whether hostkeys on a SocketEntry and the optionally specified user
483 * are permitted by the destination constraints on the Identity.
484 * Returns 0 on success or -1 otherwise.
487 identity_permitted(Identity
*id
, SocketEntry
*e
, char *user
,
488 const char **forward_hostnamep
, const char **last_hostnamep
)
492 struct hostkey_sid
*hks
;
493 const struct sshkey
*fromkey
= NULL
;
494 const char *test_user
;
497 /* XXX remove logspam */
498 debug3_f("entering: key %s comment \"%s\", %zu socket bindings, "
499 "%zu constraints", sshkey_type(id
->key
), id
->comment
,
500 e
->nsession_ids
, id
->ndest_constraints
);
501 if (id
->ndest_constraints
== 0)
502 return 0; /* unconstrained */
503 if (e
->session_bind_attempted
&& e
->nsession_ids
== 0) {
504 error_f("previous session bind failed on socket");
507 if (e
->nsession_ids
== 0)
508 return 0; /* local use */
510 * Walk through the hops recorded by session_id and try to find a
511 * constraint that satisfies each.
513 for (i
= 0; i
< e
->nsession_ids
; i
++) {
514 hks
= e
->session_ids
+ i
;
515 if (hks
->key
== NULL
)
516 fatal_f("internal error: no bound key");
517 /* XXX remove logspam */
519 if (fromkey
!= NULL
&&
520 (fp1
= sshkey_fingerprint(fromkey
, SSH_FP_HASH_DEFAULT
,
521 SSH_FP_DEFAULT
)) == NULL
)
522 fatal_f("fingerprint failed");
523 if ((fp2
= sshkey_fingerprint(hks
->key
, SSH_FP_HASH_DEFAULT
,
524 SSH_FP_DEFAULT
)) == NULL
)
525 fatal_f("fingerprint failed");
526 debug3_f("socketentry fd=%d, entry %zu %s, "
527 "from hostkey %s %s to user %s hostkey %s %s",
528 e
->fd
, i
, hks
->forwarded
? "FORWARD" : "AUTH",
529 fromkey
? sshkey_type(fromkey
) : "(ORIGIN)",
530 fromkey
? fp1
: "", user
? user
: "(ANY)",
531 sshkey_type(hks
->key
), fp2
);
535 * Record the hostnames for the initial forwarding and
536 * the final destination.
539 if (i
== e
->nsession_ids
- 1)
542 hp
= forward_hostnamep
;
543 /* Special handling for final recorded binding */
545 if (i
== e
->nsession_ids
- 1) {
546 /* Can only check user at final hop */
549 * user is only presented for signature requests.
550 * If this is the case, make sure last binding is not
553 if (hks
->forwarded
&& user
!= NULL
) {
554 error_f("tried to sign on forwarding hop");
557 } else if (!hks
->forwarded
) {
558 error_f("tried to forward though signing bind");
561 if (permitted_by_dest_constraints(fromkey
, hks
->key
, id
,
567 * Another special case: if the last bound session ID was for a
568 * forwarding, and this function is not being called to check a sign
569 * request (i.e. no 'user' supplied), then only permit the key if
570 * there is a permission that would allow it to be used at another
571 * destination. This hides keys that are allowed to be used to
572 * authenticate *to* a host but not permitted for *use* beyond it.
574 hks
= &e
->session_ids
[e
->nsession_ids
- 1];
575 if (hks
->forwarded
&& user
== NULL
&&
576 permitted_by_dest_constraints(hks
->key
, NULL
, id
,
578 debug3_f("key permitted at host but not after");
587 socket_is_remote(SocketEntry
*e
)
589 return e
->session_bind_attempted
|| (e
->nsession_ids
!= 0);
592 /* return matching private key for given public key */
594 lookup_identity(struct sshkey
*key
)
598 TAILQ_FOREACH(id
, &idtab
->idlist
, next
) {
599 if (sshkey_equal(key
, id
->key
))
605 /* Check confirmation of keysign request */
607 confirm_key(Identity
*id
, const char *extra
)
612 p
= sshkey_fingerprint(id
->key
, fingerprint_hash
, SSH_FP_DEFAULT
);
614 ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s",
616 extra
== NULL
? "" : "\n", extra
== NULL
? "" : extra
))
624 send_status(SocketEntry
*e
, int success
)
628 if ((r
= sshbuf_put_u32(e
->output
, 1)) != 0 ||
629 (r
= sshbuf_put_u8(e
->output
, success
?
630 SSH_AGENT_SUCCESS
: SSH_AGENT_FAILURE
)) != 0)
631 fatal_fr(r
, "compose");
634 /* send list of supported public keys to 'client' */
636 process_request_identities(SocketEntry
*e
)
639 struct sshbuf
*msg
, *keys
;
641 u_int i
= 0, nentries
= 0;
644 debug2_f("entering");
646 if ((msg
= sshbuf_new()) == NULL
|| (keys
= sshbuf_new()) == NULL
)
647 fatal_f("sshbuf_new failed");
648 TAILQ_FOREACH(id
, &idtab
->idlist
, next
) {
649 if ((fp
= sshkey_fingerprint(id
->key
, SSH_FP_HASH_DEFAULT
,
650 SSH_FP_DEFAULT
)) == NULL
)
651 fatal_f("fingerprint failed");
652 debug_f("key %u / %u: %s %s", i
++, idtab
->nentries
,
653 sshkey_ssh_name(id
->key
), fp
);
654 dump_dest_constraints(__func__
,
655 id
->dest_constraints
, id
->ndest_constraints
);
657 /* identity not visible, don't include in response */
658 if (identity_permitted(id
, e
, NULL
, NULL
, NULL
) != 0)
660 if ((r
= sshkey_puts_opts(id
->key
, keys
,
661 SSHKEY_SERIALIZE_INFO
)) != 0 ||
662 (r
= sshbuf_put_cstring(keys
, id
->comment
)) != 0) {
663 error_fr(r
, "compose key/comment");
668 debug2_f("replying with %u allowed of %u available keys",
669 nentries
, idtab
->nentries
);
670 if ((r
= sshbuf_put_u8(msg
, SSH2_AGENT_IDENTITIES_ANSWER
)) != 0 ||
671 (r
= sshbuf_put_u32(msg
, nentries
)) != 0 ||
672 (r
= sshbuf_putb(msg
, keys
)) != 0)
673 fatal_fr(r
, "compose");
674 if ((r
= sshbuf_put_stringb(e
->output
, msg
)) != 0)
675 fatal_fr(r
, "enqueue");
682 agent_decode_alg(struct sshkey
*key
, u_int flags
)
684 if (key
->type
== KEY_RSA
) {
685 if (flags
& SSH_AGENT_RSA_SHA2_256
)
686 return "rsa-sha2-256";
687 else if (flags
& SSH_AGENT_RSA_SHA2_512
)
688 return "rsa-sha2-512";
689 } else if (key
->type
== KEY_RSA_CERT
) {
690 if (flags
& SSH_AGENT_RSA_SHA2_256
)
691 return "rsa-sha2-256-cert-v01@openssh.com";
692 else if (flags
& SSH_AGENT_RSA_SHA2_512
)
693 return "rsa-sha2-512-cert-v01@openssh.com";
699 * Attempt to parse the contents of a buffer as a SSH publickey userauth
700 * request, checking its contents for consistency and matching the embedded
701 * key against the one that is being used for signing.
702 * Note: does not modify msg buffer.
703 * Optionally extract the username, session ID and/or hostkey from the request.
706 parse_userauth_request(struct sshbuf
*msg
, const struct sshkey
*expected_key
,
707 char **userp
, struct sshbuf
**sess_idp
, struct sshkey
**hostkeyp
)
709 struct sshbuf
*b
= NULL
, *sess_id
= NULL
;
710 char *user
= NULL
, *service
= NULL
, *method
= NULL
, *pkalg
= NULL
;
712 u_char t
, sig_follows
;
713 struct sshkey
*mkey
= NULL
, *hostkey
= NULL
;
717 if (sess_idp
!= NULL
)
719 if (hostkeyp
!= NULL
)
721 if ((b
= sshbuf_fromb(msg
)) == NULL
)
722 fatal_f("sshbuf_fromb");
724 /* SSH userauth request */
725 if ((r
= sshbuf_froms(b
, &sess_id
)) != 0)
727 if (sshbuf_len(sess_id
) == 0) {
728 r
= SSH_ERR_INVALID_FORMAT
;
731 if ((r
= sshbuf_get_u8(b
, &t
)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */
732 (r
= sshbuf_get_cstring(b
, &user
, NULL
)) != 0 || /* server user */
733 (r
= sshbuf_get_cstring(b
, &service
, NULL
)) != 0 || /* service */
734 (r
= sshbuf_get_cstring(b
, &method
, NULL
)) != 0 || /* method */
735 (r
= sshbuf_get_u8(b
, &sig_follows
)) != 0 || /* sig-follows */
736 (r
= sshbuf_get_cstring(b
, &pkalg
, NULL
)) != 0 || /* alg */
737 (r
= sshkey_froms(b
, &mkey
)) != 0) /* key */
739 if (t
!= SSH2_MSG_USERAUTH_REQUEST
||
741 strcmp(service
, "ssh-connection") != 0 ||
742 !sshkey_equal(expected_key
, mkey
) ||
743 sshkey_type_from_name(pkalg
) != expected_key
->type
) {
744 r
= SSH_ERR_INVALID_FORMAT
;
747 if (strcmp(method
, "publickey-hostbound-v00@openssh.com") == 0) {
748 if ((r
= sshkey_froms(b
, &hostkey
)) != 0)
750 } else if (strcmp(method
, "publickey") != 0) {
751 r
= SSH_ERR_INVALID_FORMAT
;
754 if (sshbuf_len(b
) != 0) {
755 r
= SSH_ERR_INVALID_FORMAT
;
760 debug3_f("well formed userauth");
765 if (sess_idp
!= NULL
) {
769 if (hostkeyp
!= NULL
) {
775 sshbuf_free(sess_id
);
781 sshkey_free(hostkey
);
786 * Attempt to parse the contents of a buffer as a SSHSIG signature request.
787 * Note: does not modify buffer.
790 parse_sshsig_request(struct sshbuf
*msg
)
795 if ((b
= sshbuf_fromb(msg
)) == NULL
)
796 fatal_f("sshbuf_fromb");
798 if ((r
= sshbuf_cmp(b
, 0, "SSHSIG", 6)) != 0 ||
799 (r
= sshbuf_consume(b
, 6)) != 0 ||
800 (r
= sshbuf_get_cstring(b
, NULL
, NULL
)) != 0 || /* namespace */
801 (r
= sshbuf_get_string_direct(b
, NULL
, NULL
)) != 0 || /* reserved */
802 (r
= sshbuf_get_cstring(b
, NULL
, NULL
)) != 0 || /* hashalg */
803 (r
= sshbuf_get_string_direct(b
, NULL
, NULL
)) != 0) /* H(msg) */
805 if (sshbuf_len(b
) != 0) {
806 r
= SSH_ERR_INVALID_FORMAT
;
817 * This function inspects a message to be signed by a FIDO key that has a
818 * web-like application string (i.e. one that does not begin with "ssh:".
819 * It checks that the message is one of those expected for SSH operations
820 * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
824 check_websafe_message_contents(struct sshkey
*key
, struct sshbuf
*data
)
826 if (parse_userauth_request(data
, key
, NULL
, NULL
, NULL
) == 0) {
827 debug_f("signed data matches public key userauth request");
830 if (parse_sshsig_request(data
) == 0) {
831 debug_f("signed data matches SSHSIG signature request");
835 /* XXX check CA signature operation */
837 error("web-origin key attempting to sign non-SSH message");
842 buf_equal(const struct sshbuf
*a
, const struct sshbuf
*b
)
844 if (sshbuf_ptr(a
) == NULL
|| sshbuf_ptr(b
) == NULL
)
845 return SSH_ERR_INVALID_ARGUMENT
;
846 if (sshbuf_len(a
) != sshbuf_len(b
))
847 return SSH_ERR_INVALID_FORMAT
;
848 if (timingsafe_bcmp(sshbuf_ptr(a
), sshbuf_ptr(b
), sshbuf_len(a
)) != 0)
849 return SSH_ERR_INVALID_FORMAT
;
855 process_sign_request2(SocketEntry
*e
)
857 u_char
*signature
= NULL
;
859 u_int compat
= 0, flags
;
860 int r
, ok
= -1, retried
= 0;
861 char *fp
= NULL
, *pin
= NULL
, *prompt
= NULL
;
862 char *user
= NULL
, *sig_dest
= NULL
;
863 const char *fwd_host
= NULL
, *dest_host
= NULL
;
864 struct sshbuf
*msg
= NULL
, *data
= NULL
, *sid
= NULL
;
865 struct sshkey
*key
= NULL
, *hostkey
= NULL
;
867 struct notifier_ctx
*notifier
= NULL
;
871 if ((msg
= sshbuf_new()) == NULL
|| (data
= sshbuf_new()) == NULL
)
872 fatal_f("sshbuf_new failed");
873 if ((r
= sshkey_froms(e
->request
, &key
)) != 0 ||
874 (r
= sshbuf_get_stringb(e
->request
, data
)) != 0 ||
875 (r
= sshbuf_get_u32(e
->request
, &flags
)) != 0) {
876 error_fr(r
, "parse");
880 if ((id
= lookup_identity(key
)) == NULL
) {
881 verbose_f("%s key not found", sshkey_type(key
));
884 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
885 SSH_FP_DEFAULT
)) == NULL
)
886 fatal_f("fingerprint failed");
888 if (id
->ndest_constraints
!= 0) {
889 if (e
->nsession_ids
== 0) {
890 logit_f("refusing use of destination-constrained key "
891 "to sign on unbound connection");
894 if (parse_userauth_request(data
, key
, &user
, &sid
,
896 logit_f("refusing use of destination-constrained key "
897 "to sign an unidentified signature");
901 debug_f("user=%s", user
);
902 if (identity_permitted(id
, e
, user
, &fwd_host
, &dest_host
) != 0)
904 /* XXX display fwd_host/dest_host in askpass UI */
906 * Ensure that the session ID is the most recent one
907 * registered on the socket - it should have been bound by
908 * ssh immediately before userauth.
911 e
->session_ids
[e
->nsession_ids
- 1].sid
) != 0) {
912 error_f("unexpected session ID (%zu listed) on "
913 "signature request for target user %s with "
914 "key %s %s", e
->nsession_ids
, user
,
915 sshkey_type(id
->key
), fp
);
919 * Ensure that the hostkey embedded in the signature matches
920 * the one most recently bound to the socket. An exception is
921 * made for the initial forwarding hop.
923 if (e
->nsession_ids
> 1 && hostkey
== NULL
) {
924 error_f("refusing use of destination-constrained key: "
925 "no hostkey recorded in signature for forwarded "
929 if (hostkey
!= NULL
&& !sshkey_equal(hostkey
,
930 e
->session_ids
[e
->nsession_ids
- 1].key
)) {
931 error_f("refusing use of destination-constrained key: "
932 "mismatch between hostkey in request and most "
933 "recently bound session");
936 xasprintf(&sig_dest
, "public key authentication request for "
937 "user \"%s\" to listed host", user
);
939 if (id
->confirm
&& confirm_key(id
, sig_dest
) != 0) {
940 verbose_f("user refused key");
943 if (sshkey_is_sk(id
->key
)) {
944 if (restrict_websafe
&&
945 strncmp(id
->key
->sk_application
, "ssh:", 4) != 0 &&
946 !check_websafe_message_contents(key
, data
)) {
947 /* error already logged */
950 if (id
->key
->sk_flags
& SSH_SK_USER_PRESENCE_REQD
) {
951 notifier
= notify_start(0,
952 "Confirm user presence for key %s %s%s%s",
953 sshkey_type(id
->key
), fp
,
954 sig_dest
== NULL
? "" : "\n",
955 sig_dest
== NULL
? "" : sig_dest
);
959 if ((r
= sshkey_sign(id
->key
, &signature
, &slen
,
960 sshbuf_ptr(data
), sshbuf_len(data
), agent_decode_alg(key
, flags
),
961 id
->sk_provider
, pin
, compat
)) != 0) {
962 debug_fr(r
, "sshkey_sign");
963 if (pin
== NULL
&& !retried
&& sshkey_is_sk(id
->key
) &&
964 r
== SSH_ERR_KEY_WRONG_PASSPHRASE
) {
965 notify_complete(notifier
, NULL
);
967 /* XXX include sig_dest */
968 xasprintf(&prompt
, "Enter PIN%sfor %s key %s: ",
969 (id
->key
->sk_flags
& SSH_SK_USER_PRESENCE_REQD
) ?
970 " and confirm user presence " : " ",
971 sshkey_type(id
->key
), fp
);
972 pin
= read_passphrase(prompt
, RP_USE_ASKPASS
);
976 error_fr(r
, "sshkey_sign");
981 debug_f("good signature");
983 notify_complete(notifier
, "User presence confirmed");
986 if ((r
= sshbuf_put_u8(msg
, SSH2_AGENT_SIGN_RESPONSE
)) != 0 ||
987 (r
= sshbuf_put_string(msg
, signature
, slen
)) != 0)
988 fatal_fr(r
, "compose");
989 } else if ((r
= sshbuf_put_u8(msg
, SSH_AGENT_FAILURE
)) != 0)
990 fatal_fr(r
, "compose failure");
992 if ((r
= sshbuf_put_stringb(e
->output
, msg
)) != 0)
993 fatal_fr(r
, "enqueue");
999 sshkey_free(hostkey
);
1006 freezero(pin
, strlen(pin
));
1011 process_remove_identity(SocketEntry
*e
)
1014 struct sshkey
*key
= NULL
;
1017 debug2_f("entering");
1018 if ((r
= sshkey_froms(e
->request
, &key
)) != 0) {
1019 error_fr(r
, "parse key");
1022 if ((id
= lookup_identity(key
)) == NULL
) {
1023 debug_f("key not found");
1026 /* identity not visible, cannot be removed */
1027 if (identity_permitted(id
, e
, NULL
, NULL
, NULL
) != 0)
1028 goto done
; /* error already logged */
1029 /* We have this key, free it. */
1030 if (idtab
->nentries
< 1)
1031 fatal_f("internal error: nentries %d", idtab
->nentries
);
1032 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
1038 send_status(e
, success
);
1042 process_remove_all_identities(SocketEntry
*e
)
1046 debug2_f("entering");
1047 /* Loop over all identities and clear the keys. */
1048 for (id
= TAILQ_FIRST(&idtab
->idlist
); id
;
1049 id
= TAILQ_FIRST(&idtab
->idlist
)) {
1050 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
1054 /* Mark that there are no identities. */
1055 idtab
->nentries
= 0;
1061 /* removes expired keys and returns number of seconds until the next expiry */
1065 time_t deadline
= 0, now
= monotime();
1068 for (id
= TAILQ_FIRST(&idtab
->idlist
); id
; id
= nxt
) {
1069 nxt
= TAILQ_NEXT(id
, next
);
1072 if (now
>= id
->death
) {
1073 debug("expiring key '%s'", id
->comment
);
1074 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
1078 deadline
= (deadline
== 0) ? id
->death
:
1079 MINIMUM(deadline
, id
->death
);
1081 if (deadline
== 0 || deadline
<= now
)
1084 return (deadline
- now
);
1088 parse_dest_constraint_hop(struct sshbuf
*b
, struct dest_constraint_hop
*dch
)
1093 struct sshkey
*k
= NULL
;
1096 memset(dch
, '\0', sizeof(*dch
));
1097 if ((r
= sshbuf_get_cstring(b
, &dch
->user
, NULL
)) != 0 ||
1098 (r
= sshbuf_get_cstring(b
, &dch
->hostname
, NULL
)) != 0 ||
1099 (r
= sshbuf_get_string_direct(b
, NULL
, &elen
)) != 0) {
1100 error_fr(r
, "parse");
1104 error_f("unsupported extensions (len %zu)", elen
);
1105 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1108 if (*dch
->hostname
== '\0') {
1109 free(dch
->hostname
);
1110 dch
->hostname
= NULL
;
1112 if (*dch
->user
== '\0') {
1116 while (sshbuf_len(b
) != 0) {
1117 dch
->keys
= xrecallocarray(dch
->keys
, dch
->nkeys
,
1118 dch
->nkeys
+ 1, sizeof(*dch
->keys
));
1119 dch
->key_is_ca
= xrecallocarray(dch
->key_is_ca
, dch
->nkeys
,
1120 dch
->nkeys
+ 1, sizeof(*dch
->key_is_ca
));
1121 if ((r
= sshkey_froms(b
, &k
)) != 0 ||
1122 (r
= sshbuf_get_u8(b
, &key_is_ca
)) != 0)
1124 if ((fp
= sshkey_fingerprint(k
, SSH_FP_HASH_DEFAULT
,
1125 SSH_FP_DEFAULT
)) == NULL
)
1126 fatal_f("fingerprint failed");
1127 debug3_f("%s%s%s: adding %skey %s %s",
1128 dch
->user
== NULL
? "" : dch
->user
,
1129 dch
->user
== NULL
? "" : "@",
1130 dch
->hostname
, key_is_ca
? "CA " : "", sshkey_type(k
), fp
);
1132 dch
->keys
[dch
->nkeys
] = k
;
1133 dch
->key_is_ca
[dch
->nkeys
] = key_is_ca
!= 0;
1135 k
= NULL
; /* transferred */
1145 parse_dest_constraint(struct sshbuf
*m
, struct dest_constraint
*dc
)
1147 struct sshbuf
*b
= NULL
, *frombuf
= NULL
, *tobuf
= NULL
;
1151 debug3_f("entering");
1153 memset(dc
, '\0', sizeof(*dc
));
1154 if ((r
= sshbuf_froms(m
, &b
)) != 0 ||
1155 (r
= sshbuf_froms(b
, &frombuf
)) != 0 ||
1156 (r
= sshbuf_froms(b
, &tobuf
)) != 0 ||
1157 (r
= sshbuf_get_string_direct(b
, NULL
, &elen
)) != 0) {
1158 error_fr(r
, "parse");
1161 if ((r
= parse_dest_constraint_hop(frombuf
, &dc
->from
)) != 0 ||
1162 (r
= parse_dest_constraint_hop(tobuf
, &dc
->to
)) != 0)
1163 goto out
; /* already logged */
1165 error_f("unsupported extensions (len %zu)", elen
);
1166 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1169 debug2_f("parsed %s (%u keys) > %s%s%s (%u keys)",
1170 dc
->from
.hostname
? dc
->from
.hostname
: "(ORIGIN)", dc
->from
.nkeys
,
1171 dc
->to
.user
? dc
->to
.user
: "", dc
->to
.user
? "@" : "",
1172 dc
->to
.hostname
? dc
->to
.hostname
: "(ANY)", dc
->to
.nkeys
);
1173 /* check consistency */
1174 if ((dc
->from
.hostname
== NULL
) != (dc
->from
.nkeys
== 0) ||
1175 dc
->from
.user
!= NULL
) {
1176 error_f("inconsistent \"from\" specification");
1177 r
= SSH_ERR_INVALID_FORMAT
;
1180 if (dc
->to
.hostname
== NULL
|| dc
->to
.nkeys
== 0) {
1181 error_f("incomplete \"to\" specification");
1182 r
= SSH_ERR_INVALID_FORMAT
;
1189 sshbuf_free(frombuf
);
1195 parse_key_constraint_extension(struct sshbuf
*m
, char **sk_providerp
,
1196 struct dest_constraint
**dcsp
, size_t *ndcsp
, int *cert_onlyp
,
1197 struct sshkey
***certs
, size_t *ncerts
)
1199 char *ext_name
= NULL
;
1201 struct sshbuf
*b
= NULL
;
1205 if ((r
= sshbuf_get_cstring(m
, &ext_name
, NULL
)) != 0) {
1206 error_fr(r
, "parse constraint extension");
1209 debug_f("constraint ext %s", ext_name
);
1210 if (strcmp(ext_name
, "sk-provider@openssh.com") == 0) {
1211 if (sk_providerp
== NULL
) {
1212 error_f("%s not valid here", ext_name
);
1213 r
= SSH_ERR_INVALID_FORMAT
;
1216 if (*sk_providerp
!= NULL
) {
1217 error_f("%s already set", ext_name
);
1218 r
= SSH_ERR_INVALID_FORMAT
;
1221 if ((r
= sshbuf_get_cstring(m
, sk_providerp
, NULL
)) != 0) {
1222 error_fr(r
, "parse %s", ext_name
);
1225 } else if (strcmp(ext_name
,
1226 "restrict-destination-v00@openssh.com") == 0) {
1227 if (*dcsp
!= NULL
) {
1228 error_f("%s already set", ext_name
);
1231 if ((r
= sshbuf_froms(m
, &b
)) != 0) {
1232 error_fr(r
, "parse %s outer", ext_name
);
1235 while (sshbuf_len(b
) != 0) {
1236 if (*ndcsp
>= AGENT_MAX_DEST_CONSTRAINTS
) {
1237 error_f("too many %s constraints", ext_name
);
1240 *dcsp
= xrecallocarray(*dcsp
, *ndcsp
, *ndcsp
+ 1,
1242 if ((r
= parse_dest_constraint(b
,
1243 *dcsp
+ (*ndcsp
)++)) != 0)
1244 goto out
; /* error already logged */
1246 } else if (strcmp(ext_name
,
1247 "associated-certs-v00@openssh.com") == 0) {
1248 if (certs
== NULL
|| ncerts
== NULL
|| cert_onlyp
== NULL
) {
1249 error_f("%s not valid here", ext_name
);
1250 r
= SSH_ERR_INVALID_FORMAT
;
1253 if (*certs
!= NULL
) {
1254 error_f("%s already set", ext_name
);
1257 if ((r
= sshbuf_get_u8(m
, &v
)) != 0 ||
1258 (r
= sshbuf_froms(m
, &b
)) != 0) {
1259 error_fr(r
, "parse %s", ext_name
);
1262 *cert_onlyp
= v
!= 0;
1263 while (sshbuf_len(b
) != 0) {
1264 if (*ncerts
>= AGENT_MAX_EXT_CERTS
) {
1265 error_f("too many %s constraints", ext_name
);
1268 *certs
= xrecallocarray(*certs
, *ncerts
, *ncerts
+ 1,
1270 if ((r
= sshkey_froms(b
, &k
)) != 0) {
1271 error_fr(r
, "parse key");
1274 (*certs
)[(*ncerts
)++] = k
;
1277 error_f("unsupported constraint \"%s\"", ext_name
);
1278 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1290 parse_key_constraints(struct sshbuf
*m
, struct sshkey
*k
, time_t *deathp
,
1291 u_int
*secondsp
, int *confirmp
, char **sk_providerp
,
1292 struct dest_constraint
**dcsp
, size_t *ndcsp
,
1293 int *cert_onlyp
, size_t *ncerts
, struct sshkey
***certs
)
1297 u_int seconds
, maxsign
= 0;
1299 while (sshbuf_len(m
)) {
1300 if ((r
= sshbuf_get_u8(m
, &ctype
)) != 0) {
1301 error_fr(r
, "parse constraint type");
1305 case SSH_AGENT_CONSTRAIN_LIFETIME
:
1307 error_f("lifetime already set");
1308 r
= SSH_ERR_INVALID_FORMAT
;
1311 if ((r
= sshbuf_get_u32(m
, &seconds
)) != 0) {
1312 error_fr(r
, "parse lifetime constraint");
1315 *deathp
= monotime() + seconds
;
1316 *secondsp
= seconds
;
1318 case SSH_AGENT_CONSTRAIN_CONFIRM
:
1319 if (*confirmp
!= 0) {
1320 error_f("confirm already set");
1321 r
= SSH_ERR_INVALID_FORMAT
;
1326 case SSH_AGENT_CONSTRAIN_MAXSIGN
:
1328 error_f("maxsign not valid here");
1329 r
= SSH_ERR_INVALID_FORMAT
;
1333 error_f("maxsign already set");
1334 r
= SSH_ERR_INVALID_FORMAT
;
1337 if ((r
= sshbuf_get_u32(m
, &maxsign
)) != 0) {
1338 error_fr(r
, "parse maxsign constraint");
1341 if ((r
= sshkey_enable_maxsign(k
, maxsign
)) != 0) {
1342 error_fr(r
, "enable maxsign");
1346 case SSH_AGENT_CONSTRAIN_EXTENSION
:
1347 if ((r
= parse_key_constraint_extension(m
,
1348 sk_providerp
, dcsp
, ndcsp
,
1349 cert_onlyp
, certs
, ncerts
)) != 0)
1350 goto out
; /* error already logged */
1353 error_f("Unknown constraint %d", ctype
);
1354 r
= SSH_ERR_FEATURE_UNSUPPORTED
;
1365 process_add_identity(SocketEntry
*e
)
1368 int success
= 0, confirm
= 0;
1369 char *fp
, *comment
= NULL
, *sk_provider
= NULL
;
1370 char canonical_provider
[PATH_MAX
];
1373 struct dest_constraint
*dest_constraints
= NULL
;
1374 size_t ndest_constraints
= 0;
1375 struct sshkey
*k
= NULL
;
1376 int r
= SSH_ERR_INTERNAL_ERROR
;
1378 debug2_f("entering");
1379 if ((r
= sshkey_private_deserialize(e
->request
, &k
)) != 0 ||
1381 (r
= sshbuf_get_cstring(e
->request
, &comment
, NULL
)) != 0) {
1382 error_fr(r
, "parse");
1385 if (parse_key_constraints(e
->request
, k
, &death
, &seconds
, &confirm
,
1386 &sk_provider
, &dest_constraints
, &ndest_constraints
,
1387 NULL
, NULL
, NULL
) != 0) {
1388 error_f("failed to parse constraints");
1389 sshbuf_reset(e
->request
);
1392 dump_dest_constraints(__func__
, dest_constraints
, ndest_constraints
);
1394 if (sk_provider
!= NULL
) {
1395 if (!sshkey_is_sk(k
)) {
1396 error("Cannot add provider: %s is not an "
1397 "authenticator-hosted key", sshkey_type(k
));
1400 if (strcasecmp(sk_provider
, "internal") == 0) {
1401 debug_f("internal provider");
1403 if (socket_is_remote(e
) && !remote_add_provider
) {
1404 verbose("failed add of SK provider \"%.100s\": "
1405 "remote addition of providers is disabled",
1409 if (realpath(sk_provider
, canonical_provider
) == NULL
) {
1410 verbose("failed provider \"%.100s\": "
1411 "realpath: %s", sk_provider
,
1416 sk_provider
= xstrdup(canonical_provider
);
1417 if (match_pattern_list(sk_provider
,
1418 allowed_providers
, 0) != 1) {
1419 error("Refusing add key: "
1420 "provider %s not allowed", sk_provider
);
1425 if ((r
= sshkey_shield_private(k
)) != 0) {
1426 error_fr(r
, "shield private");
1429 if (lifetime
&& !death
)
1430 death
= monotime() + lifetime
;
1431 if ((id
= lookup_identity(k
)) == NULL
) {
1432 id
= xcalloc(1, sizeof(Identity
));
1433 TAILQ_INSERT_TAIL(&idtab
->idlist
, id
, next
);
1434 /* Increment the number of identities. */
1437 /* identity not visible, do not update */
1438 if (identity_permitted(id
, e
, NULL
, NULL
, NULL
) != 0)
1439 goto out
; /* error already logged */
1440 /* key state might have been updated */
1441 sshkey_free(id
->key
);
1443 free(id
->sk_provider
);
1444 free_dest_constraints(id
->dest_constraints
,
1445 id
->ndest_constraints
);
1449 id
->comment
= comment
;
1451 id
->confirm
= confirm
;
1452 id
->sk_provider
= sk_provider
;
1453 id
->dest_constraints
= dest_constraints
;
1454 id
->ndest_constraints
= ndest_constraints
;
1456 if ((fp
= sshkey_fingerprint(k
, SSH_FP_HASH_DEFAULT
,
1457 SSH_FP_DEFAULT
)) == NULL
)
1458 fatal_f("sshkey_fingerprint failed");
1459 debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) "
1460 "(provider: %s) (destination constraints: %zu)",
1461 sshkey_ssh_name(k
), fp
, comment
, seconds
, confirm
,
1462 sk_provider
== NULL
? "none" : sk_provider
, ndest_constraints
);
1468 dest_constraints
= NULL
;
1469 ndest_constraints
= 0;
1475 free_dest_constraints(dest_constraints
, ndest_constraints
);
1476 send_status(e
, success
);
1479 /* XXX todo: encrypt sensitive data with passphrase */
1481 process_lock_agent(SocketEntry
*e
, int lock
)
1483 int r
, success
= 0, delay
;
1485 u_char passwdhash
[LOCK_SIZE
];
1486 static u_int fail_count
= 0;
1489 debug2_f("entering");
1491 * This is deliberately fatal: the user has requested that we lock,
1492 * but we can't parse their request properly. The only safe thing to
1495 if ((r
= sshbuf_get_cstring(e
->request
, &passwd
, &pwlen
)) != 0)
1496 fatal_fr(r
, "parse");
1498 debug("empty password not supported");
1499 } else if (locked
&& !lock
) {
1500 if (bcrypt_pbkdf(passwd
, pwlen
, lock_salt
, sizeof(lock_salt
),
1501 passwdhash
, sizeof(passwdhash
), LOCK_ROUNDS
) < 0)
1502 fatal("bcrypt_pbkdf");
1503 if (timingsafe_bcmp(passwdhash
, lock_pwhash
, LOCK_SIZE
) == 0) {
1504 debug("agent unlocked");
1507 explicit_bzero(lock_pwhash
, sizeof(lock_pwhash
));
1510 /* delay in 0.1s increments up to 10s */
1511 if (fail_count
< 100)
1513 delay
= 100000 * fail_count
;
1514 debug("unlock failed, delaying %0.1lf seconds",
1515 (double)delay
/1000000);
1518 explicit_bzero(passwdhash
, sizeof(passwdhash
));
1519 } else if (!locked
&& lock
) {
1520 debug("agent locked");
1522 arc4random_buf(lock_salt
, sizeof(lock_salt
));
1523 if (bcrypt_pbkdf(passwd
, pwlen
, lock_salt
, sizeof(lock_salt
),
1524 lock_pwhash
, sizeof(lock_pwhash
), LOCK_ROUNDS
) < 0)
1525 fatal("bcrypt_pbkdf");
1528 freezero(passwd
, pwlen
);
1529 send_status(e
, success
);
1533 no_identities(SocketEntry
*e
)
1538 if ((msg
= sshbuf_new()) == NULL
)
1539 fatal_f("sshbuf_new failed");
1540 if ((r
= sshbuf_put_u8(msg
, SSH2_AGENT_IDENTITIES_ANSWER
)) != 0 ||
1541 (r
= sshbuf_put_u32(msg
, 0)) != 0 ||
1542 (r
= sshbuf_put_stringb(e
->output
, msg
)) != 0)
1543 fatal_fr(r
, "compose");
1547 #ifdef ENABLE_PKCS11
1548 /* Add an identity to idlist; takes ownership of 'key' and 'comment' */
1550 add_p11_identity(struct sshkey
*key
, char *comment
, const char *provider
,
1551 time_t death
, u_int confirm
, struct dest_constraint
*dest_constraints
,
1552 size_t ndest_constraints
)
1556 if (lookup_identity(key
) != NULL
) {
1561 id
= xcalloc(1, sizeof(Identity
));
1563 id
->comment
= comment
;
1564 id
->provider
= xstrdup(provider
);
1566 id
->confirm
= confirm
;
1567 id
->dest_constraints
= dup_dest_constraints(dest_constraints
,
1569 id
->ndest_constraints
= ndest_constraints
;
1570 TAILQ_INSERT_TAIL(&idtab
->idlist
, id
, next
);
1575 process_add_smartcard_key(SocketEntry
*e
)
1577 char *provider
= NULL
, *pin
= NULL
, canonical_provider
[PATH_MAX
];
1578 char **comments
= NULL
;
1579 int r
, i
, count
= 0, success
= 0, confirm
= 0;
1582 struct sshkey
**keys
= NULL
, *k
;
1583 struct dest_constraint
*dest_constraints
= NULL
;
1584 size_t j
, ndest_constraints
= 0, ncerts
= 0;
1585 struct sshkey
**certs
= NULL
;
1588 debug2_f("entering");
1589 if ((r
= sshbuf_get_cstring(e
->request
, &provider
, NULL
)) != 0 ||
1590 (r
= sshbuf_get_cstring(e
->request
, &pin
, NULL
)) != 0) {
1591 error_fr(r
, "parse");
1594 if (parse_key_constraints(e
->request
, NULL
, &death
, &seconds
, &confirm
,
1595 NULL
, &dest_constraints
, &ndest_constraints
, &cert_only
,
1596 &ncerts
, &certs
) != 0) {
1597 error_f("failed to parse constraints");
1600 dump_dest_constraints(__func__
, dest_constraints
, ndest_constraints
);
1601 if (socket_is_remote(e
) && !remote_add_provider
) {
1602 verbose("failed PKCS#11 add of \"%.100s\": remote addition of "
1603 "providers is disabled", provider
);
1606 if (realpath(provider
, canonical_provider
) == NULL
) {
1607 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1608 provider
, strerror(errno
));
1611 if (match_pattern_list(canonical_provider
, allowed_providers
, 0) != 1) {
1612 verbose("refusing PKCS#11 add of \"%.100s\": "
1613 "provider not allowed", canonical_provider
);
1616 debug_f("add %.100s", canonical_provider
);
1617 if (lifetime
&& !death
)
1618 death
= monotime() + lifetime
;
1620 count
= pkcs11_add_provider(canonical_provider
, pin
, &keys
, &comments
);
1621 for (i
= 0; i
< count
; i
++) {
1622 if (comments
[i
] == NULL
|| comments
[i
][0] == '\0') {
1624 comments
[i
] = xstrdup(canonical_provider
);
1626 for (j
= 0; j
< ncerts
; j
++) {
1627 if (!sshkey_is_cert(certs
[j
]))
1629 if (!sshkey_equal_public(keys
[i
], certs
[j
]))
1631 if (pkcs11_make_cert(keys
[i
], certs
[j
], &k
) != 0)
1633 add_p11_identity(k
, xstrdup(comments
[i
]),
1634 canonical_provider
, death
, confirm
,
1635 dest_constraints
, ndest_constraints
);
1638 if (!cert_only
&& lookup_identity(keys
[i
]) == NULL
) {
1639 add_p11_identity(keys
[i
], comments
[i
],
1640 canonical_provider
, death
, confirm
,
1641 dest_constraints
, ndest_constraints
);
1642 keys
[i
] = NULL
; /* transferred */
1643 comments
[i
] = NULL
; /* transferred */
1646 /* XXX update constraints for existing keys */
1647 sshkey_free(keys
[i
]);
1655 free_dest_constraints(dest_constraints
, ndest_constraints
);
1656 for (j
= 0; j
< ncerts
; j
++)
1657 sshkey_free(certs
[j
]);
1659 send_status(e
, success
);
1663 process_remove_smartcard_key(SocketEntry
*e
)
1665 char *provider
= NULL
, *pin
= NULL
, canonical_provider
[PATH_MAX
];
1669 debug2_f("entering");
1670 if ((r
= sshbuf_get_cstring(e
->request
, &provider
, NULL
)) != 0 ||
1671 (r
= sshbuf_get_cstring(e
->request
, &pin
, NULL
)) != 0) {
1672 error_fr(r
, "parse");
1677 if (realpath(provider
, canonical_provider
) == NULL
) {
1678 verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1679 provider
, strerror(errno
));
1683 debug_f("remove %.100s", canonical_provider
);
1684 for (id
= TAILQ_FIRST(&idtab
->idlist
); id
; id
= nxt
) {
1685 nxt
= TAILQ_NEXT(id
, next
);
1686 /* Skip file--based keys */
1687 if (id
->provider
== NULL
)
1689 if (!strcmp(canonical_provider
, id
->provider
)) {
1690 TAILQ_REMOVE(&idtab
->idlist
, id
, next
);
1695 if (pkcs11_del_provider(canonical_provider
) == 0)
1698 error_f("pkcs11_del_provider failed");
1701 send_status(e
, success
);
1703 #endif /* ENABLE_PKCS11 */
1706 process_ext_session_bind(SocketEntry
*e
)
1708 int r
, sid_match
, key_match
;
1709 struct sshkey
*key
= NULL
;
1710 struct sshbuf
*sid
= NULL
, *sig
= NULL
;
1715 debug2_f("entering");
1716 e
->session_bind_attempted
= 1;
1717 if ((r
= sshkey_froms(e
->request
, &key
)) != 0 ||
1718 (r
= sshbuf_froms(e
->request
, &sid
)) != 0 ||
1719 (r
= sshbuf_froms(e
->request
, &sig
)) != 0 ||
1720 (r
= sshbuf_get_u8(e
->request
, &fwd
)) != 0) {
1721 error_fr(r
, "parse");
1724 if ((fp
= sshkey_fingerprint(key
, SSH_FP_HASH_DEFAULT
,
1725 SSH_FP_DEFAULT
)) == NULL
)
1726 fatal_f("fingerprint failed");
1727 /* check signature with hostkey on session ID */
1728 if ((r
= sshkey_verify(key
, sshbuf_ptr(sig
), sshbuf_len(sig
),
1729 sshbuf_ptr(sid
), sshbuf_len(sid
), NULL
, 0, NULL
)) != 0) {
1730 error_fr(r
, "sshkey_verify for %s %s", sshkey_type(key
), fp
);
1733 /* check whether sid/key already recorded */
1734 for (i
= 0; i
< e
->nsession_ids
; i
++) {
1735 if (!e
->session_ids
[i
].forwarded
) {
1736 error_f("attempt to bind session ID to socket "
1737 "previously bound for authentication attempt");
1741 sid_match
= buf_equal(sid
, e
->session_ids
[i
].sid
) == 0;
1742 key_match
= sshkey_equal(key
, e
->session_ids
[i
].key
);
1743 if (sid_match
&& key_match
) {
1744 debug_f("session ID already recorded for %s %s",
1745 sshkey_type(key
), fp
);
1748 } else if (sid_match
) {
1749 error_f("session ID recorded against different key "
1750 "for %s %s", sshkey_type(key
), fp
);
1755 * new sid with previously-seen key can happen, e.g. multiple
1756 * connections to the same host.
1759 /* record new key/sid */
1760 if (e
->nsession_ids
>= AGENT_MAX_SESSION_IDS
) {
1761 error_f("too many session IDs recorded");
1764 e
->session_ids
= xrecallocarray(e
->session_ids
, e
->nsession_ids
,
1765 e
->nsession_ids
+ 1, sizeof(*e
->session_ids
));
1766 i
= e
->nsession_ids
++;
1767 debug_f("recorded %s %s (slot %zu of %d)", sshkey_type(key
), fp
, i
,
1768 AGENT_MAX_SESSION_IDS
);
1769 e
->session_ids
[i
].key
= key
;
1770 e
->session_ids
[i
].forwarded
= fwd
!= 0;
1771 key
= NULL
; /* transferred */
1772 /* can't transfer sid; it's refcounted and scoped to request's life */
1773 if ((e
->session_ids
[i
].sid
= sshbuf_new()) == NULL
)
1774 fatal_f("sshbuf_new");
1775 if ((r
= sshbuf_putb(e
->session_ids
[i
].sid
, sid
)) != 0)
1776 fatal_fr(r
, "sshbuf_putb session ID");
1784 return r
== 0 ? 1 : 0;
1788 process_extension(SocketEntry
*e
)
1793 debug2_f("entering");
1794 if ((r
= sshbuf_get_cstring(e
->request
, &name
, NULL
)) != 0) {
1795 error_fr(r
, "parse");
1798 if (strcmp(name
, "session-bind@openssh.com") == 0)
1799 success
= process_ext_session_bind(e
);
1801 debug_f("unsupported extension \"%s\"", name
);
1804 send_status(e
, success
);
1807 * dispatch incoming message.
1808 * returns 1 on success, 0 for incomplete messages or -1 on error.
1811 process_message(u_int socknum
)
1819 if (socknum
>= sockets_alloc
)
1820 fatal_f("sock %u >= allocated %u", socknum
, sockets_alloc
);
1821 e
= &sockets
[socknum
];
1823 if (sshbuf_len(e
->input
) < 5)
1824 return 0; /* Incomplete message header. */
1825 cp
= sshbuf_ptr(e
->input
);
1826 msg_len
= PEEK_U32(cp
);
1827 if (msg_len
> AGENT_MAX_LEN
) {
1828 debug_f("socket %u (fd=%d) message too long %u > %u",
1829 socknum
, e
->fd
, msg_len
, AGENT_MAX_LEN
);
1832 if (sshbuf_len(e
->input
) < msg_len
+ 4)
1833 return 0; /* Incomplete message body. */
1835 /* move the current input to e->request */
1836 sshbuf_reset(e
->request
);
1837 if ((r
= sshbuf_get_stringb(e
->input
, e
->request
)) != 0 ||
1838 (r
= sshbuf_get_u8(e
->request
, &type
)) != 0) {
1839 if (r
== SSH_ERR_MESSAGE_INCOMPLETE
||
1840 r
== SSH_ERR_STRING_TOO_LARGE
) {
1841 error_fr(r
, "parse");
1844 fatal_fr(r
, "parse");
1847 debug_f("socket %u (fd=%d) type %d", socknum
, e
->fd
, type
);
1849 /* check whether agent is locked */
1850 if (locked
&& type
!= SSH_AGENTC_UNLOCK
) {
1851 sshbuf_reset(e
->request
);
1853 case SSH2_AGENTC_REQUEST_IDENTITIES
:
1854 /* send empty lists */
1858 /* send a fail message for all other request types */
1865 case SSH_AGENTC_LOCK
:
1866 case SSH_AGENTC_UNLOCK
:
1867 process_lock_agent(e
, type
== SSH_AGENTC_LOCK
);
1869 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES
:
1870 process_remove_all_identities(e
); /* safe for !WITH_SSH1 */
1873 case SSH2_AGENTC_SIGN_REQUEST
:
1874 process_sign_request2(e
);
1876 case SSH2_AGENTC_REQUEST_IDENTITIES
:
1877 process_request_identities(e
);
1879 case SSH2_AGENTC_ADD_IDENTITY
:
1880 case SSH2_AGENTC_ADD_ID_CONSTRAINED
:
1881 process_add_identity(e
);
1883 case SSH2_AGENTC_REMOVE_IDENTITY
:
1884 process_remove_identity(e
);
1886 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES
:
1887 process_remove_all_identities(e
);
1889 #ifdef ENABLE_PKCS11
1890 case SSH_AGENTC_ADD_SMARTCARD_KEY
:
1891 case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
:
1892 process_add_smartcard_key(e
);
1894 case SSH_AGENTC_REMOVE_SMARTCARD_KEY
:
1895 process_remove_smartcard_key(e
);
1897 #endif /* ENABLE_PKCS11 */
1898 case SSH_AGENTC_EXTENSION
:
1899 process_extension(e
);
1902 /* Unknown message. Respond with failure. */
1903 error("Unknown message %d", type
);
1904 sshbuf_reset(e
->request
);
1912 new_socket(sock_type type
, int fd
)
1914 u_int i
, old_alloc
, new_alloc
;
1916 debug_f("type = %s", type
== AUTH_CONNECTION
? "CONNECTION" :
1917 (type
== AUTH_SOCKET
? "SOCKET" : "UNKNOWN"));
1918 if (type
== AUTH_CONNECTION
) {
1919 debug("xcount %d -> %d", xcount
, xcount
+ 1);
1927 for (i
= 0; i
< sockets_alloc
; i
++)
1928 if (sockets
[i
].type
== AUTH_UNUSED
) {
1930 if ((sockets
[i
].input
= sshbuf_new()) == NULL
||
1931 (sockets
[i
].output
= sshbuf_new()) == NULL
||
1932 (sockets
[i
].request
= sshbuf_new()) == NULL
)
1933 fatal_f("sshbuf_new failed");
1934 sockets
[i
].type
= type
;
1937 old_alloc
= sockets_alloc
;
1938 new_alloc
= sockets_alloc
+ 10;
1939 sockets
= xrecallocarray(sockets
, old_alloc
, new_alloc
,
1940 sizeof(sockets
[0]));
1941 for (i
= old_alloc
; i
< new_alloc
; i
++)
1942 sockets
[i
].type
= AUTH_UNUSED
;
1943 sockets_alloc
= new_alloc
;
1944 sockets
[old_alloc
].fd
= fd
;
1945 if ((sockets
[old_alloc
].input
= sshbuf_new()) == NULL
||
1946 (sockets
[old_alloc
].output
= sshbuf_new()) == NULL
||
1947 (sockets
[old_alloc
].request
= sshbuf_new()) == NULL
)
1948 fatal_f("sshbuf_new failed");
1949 sockets
[old_alloc
].type
= type
;
1953 handle_socket_read(u_int socknum
)
1955 struct sockaddr_un sunaddr
;
1961 slen
= sizeof(sunaddr
);
1962 fd
= accept(sockets
[socknum
].fd
, (struct sockaddr
*)&sunaddr
, &slen
);
1964 error("accept from AUTH_SOCKET: %s", strerror(errno
));
1967 if (getpeereid(fd
, &euid
, &egid
) == -1) {
1968 error("getpeereid %d failed: %s", fd
, strerror(errno
));
1972 if ((euid
!= 0) && (getuid() != euid
)) {
1973 error("uid mismatch: peer euid %u != uid %u",
1974 (u_int
) euid
, (u_int
) getuid());
1978 new_socket(AUTH_CONNECTION
, fd
);
1983 handle_conn_read(u_int socknum
)
1985 char buf
[AGENT_RBUF_LEN
];
1989 if ((len
= read(sockets
[socknum
].fd
, buf
, sizeof(buf
))) <= 0) {
1991 if (errno
== EAGAIN
|| errno
== EINTR
)
1993 error_f("read error on socket %u (fd %d): %s",
1994 socknum
, sockets
[socknum
].fd
, strerror(errno
));
1998 if ((r
= sshbuf_put(sockets
[socknum
].input
, buf
, len
)) != 0)
1999 fatal_fr(r
, "compose");
2000 explicit_bzero(buf
, sizeof(buf
));
2002 if ((r
= process_message(socknum
)) == -1)
2011 handle_conn_write(u_int socknum
)
2016 if (sshbuf_len(sockets
[socknum
].output
) == 0)
2017 return 0; /* shouldn't happen */
2018 if ((len
= write(sockets
[socknum
].fd
,
2019 sshbuf_ptr(sockets
[socknum
].output
),
2020 sshbuf_len(sockets
[socknum
].output
))) <= 0) {
2022 if (errno
== EAGAIN
|| errno
== EINTR
)
2024 error_f("read error on socket %u (fd %d): %s",
2025 socknum
, sockets
[socknum
].fd
, strerror(errno
));
2029 if ((r
= sshbuf_consume(sockets
[socknum
].output
, len
)) != 0)
2030 fatal_fr(r
, "consume");
2035 after_poll(struct pollfd
*pfd
, size_t npfd
, u_int maxfds
)
2038 u_int socknum
, activefds
= npfd
;
2040 for (i
= 0; i
< npfd
; i
++) {
2041 if (pfd
[i
].revents
== 0)
2043 /* Find sockets entry */
2044 for (socknum
= 0; socknum
< sockets_alloc
; socknum
++) {
2045 if (sockets
[socknum
].type
!= AUTH_SOCKET
&&
2046 sockets
[socknum
].type
!= AUTH_CONNECTION
)
2048 if (pfd
[i
].fd
== sockets
[socknum
].fd
)
2051 if (socknum
>= sockets_alloc
) {
2052 error_f("no socket for fd %d", pfd
[i
].fd
);
2055 /* Process events */
2056 switch (sockets
[socknum
].type
) {
2058 if ((pfd
[i
].revents
& (POLLIN
|POLLERR
)) == 0)
2060 if (npfd
> maxfds
) {
2061 debug3("out of fds (active %u >= limit %u); "
2062 "skipping accept", activefds
, maxfds
);
2065 if (handle_socket_read(socknum
) == 0)
2068 case AUTH_CONNECTION
:
2069 if ((pfd
[i
].revents
& (POLLIN
|POLLHUP
|POLLERR
)) != 0 &&
2070 handle_conn_read(socknum
) != 0)
2072 if ((pfd
[i
].revents
& (POLLOUT
|POLLHUP
)) != 0 &&
2073 handle_conn_write(socknum
) != 0) {
2076 fatal("activefds == 0 at close_sock");
2077 close_socket(&sockets
[socknum
]);
2089 prepare_poll(struct pollfd
**pfdp
, size_t *npfdp
, struct timespec
*timeoutp
, u_int maxfds
)
2091 struct pollfd
*pfd
= *pfdp
;
2092 size_t i
, j
, npfd
= 0;
2096 /* Count active sockets */
2097 for (i
= 0; i
< sockets_alloc
; i
++) {
2098 switch (sockets
[i
].type
) {
2100 case AUTH_CONNECTION
:
2106 fatal("Unknown socket type %d", sockets
[i
].type
);
2110 if (npfd
!= *npfdp
&&
2111 (pfd
= recallocarray(pfd
, *npfdp
, npfd
, sizeof(*pfd
))) == NULL
)
2112 fatal_f("recallocarray failed");
2116 for (i
= j
= 0; i
< sockets_alloc
; i
++) {
2117 switch (sockets
[i
].type
) {
2119 if (npfd
> maxfds
) {
2120 debug3("out of fds (active %zu >= limit %u); "
2121 "skipping arming listener", npfd
, maxfds
);
2124 pfd
[j
].fd
= sockets
[i
].fd
;
2126 pfd
[j
].events
= POLLIN
;
2129 case AUTH_CONNECTION
:
2130 pfd
[j
].fd
= sockets
[i
].fd
;
2133 * Only prepare to read if we can handle a full-size
2134 * input read buffer and enqueue a max size reply..
2136 if ((r
= sshbuf_check_reserve(sockets
[i
].input
,
2137 AGENT_RBUF_LEN
)) == 0 &&
2138 (r
= sshbuf_check_reserve(sockets
[i
].output
,
2139 AGENT_MAX_LEN
)) == 0)
2140 pfd
[j
].events
= POLLIN
;
2141 else if (r
!= SSH_ERR_NO_BUFFER_SPACE
)
2142 fatal_fr(r
, "reserve");
2143 if (sshbuf_len(sockets
[i
].output
) > 0)
2144 pfd
[j
].events
|= POLLOUT
;
2151 deadline
= reaper();
2152 if (parent_alive_interval
!= 0)
2153 deadline
= (deadline
== 0) ? parent_alive_interval
:
2154 MINIMUM(deadline
, parent_alive_interval
);
2156 ptimeout_deadline_sec(timeoutp
, deadline
);
2161 cleanup_socket(void)
2163 if (cleanup_pid
!= 0 && getpid() != cleanup_pid
)
2167 unlink(socket_name
);
2176 #ifdef ENABLE_PKCS11
2183 cleanup_handler(int 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] [-Ddx] [-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
;
2220 #ifdef HAVE_SETRLIMIT
2224 extern char *optarg
;
2226 char pidstrbuf
[1 + 3 * sizeof pid
];
2229 struct timespec timeout
;
2230 struct pollfd
*pfd
= NULL
;
2233 sigset_t nsigset
, osigset
;
2235 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2239 (void)setegid(getgid());
2240 (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:x")) != -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;
2274 fatal("Unknown -O option");
2277 if (allowed_providers
!= NULL
)
2278 fatal("-P option already specified");
2279 allowed_providers
= xstrdup(optarg
);
2287 if (d_flag
|| D_flag
)
2292 if (d_flag
|| D_flag
)
2297 agentsocket
= optarg
;
2300 if ((lifetime
= convtime(optarg
)) == -1) {
2301 fprintf(stderr
, "Invalid lifetime\n");
2315 if (ac
> 0 && (c_flag
|| k_flag
|| s_flag
|| d_flag
|| D_flag
))
2318 if (allowed_providers
== NULL
)
2319 allowed_providers
= xstrdup(DEFAULT_ALLOWED_PROVIDERS
);
2321 if (ac
== 0 && !c_flag
&& !s_flag
) {
2322 shell
= getenv("SHELL");
2323 if (shell
!= NULL
&& (len
= strlen(shell
)) > 2 &&
2324 strncmp(shell
+ len
- 3, "csh", 3) == 0)
2328 const char *errstr
= NULL
;
2330 pidstr
= getenv(SSH_AGENTPID_ENV_NAME
);
2331 if (pidstr
== NULL
) {
2332 fprintf(stderr
, "%s not set, cannot kill agent\n",
2333 SSH_AGENTPID_ENV_NAME
);
2336 pid
= (int)strtonum(pidstr
, 2, INT_MAX
, &errstr
);
2339 "%s=\"%s\", which is not a good PID: %s\n",
2340 SSH_AGENTPID_ENV_NAME
, pidstr
, errstr
);
2343 if (kill(pid
, SIGTERM
) == -1) {
2347 format
= c_flag
? "unsetenv %s;\n" : "unset %s;\n";
2348 printf(format
, SSH_AUTHSOCKET_ENV_NAME
);
2349 printf(format
, SSH_AGENTPID_ENV_NAME
);
2350 printf("echo Agent pid %ld killed;\n", (long)pid
);
2355 * Minimum file descriptors:
2356 * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) +
2357 * a few spare for libc / stack protectors / sanitisers, etc.
2359 #define SSH_AGENT_MIN_FDS (3+1+1+1+4)
2360 if (rlim
.rlim_cur
< SSH_AGENT_MIN_FDS
)
2361 fatal("%s: file descriptor rlimit %lld too low (minimum %u)",
2362 __progname
, (long long)rlim
.rlim_cur
, SSH_AGENT_MIN_FDS
);
2363 maxfds
= rlim
.rlim_cur
- SSH_AGENT_MIN_FDS
;
2365 parent_pid
= getpid();
2367 if (agentsocket
== NULL
) {
2368 /* Create private directory for agent socket */
2369 mktemp_proto(socket_dir
, sizeof(socket_dir
));
2370 if (mkdtemp(socket_dir
) == NULL
) {
2371 perror("mkdtemp: private socket dir");
2374 snprintf(socket_name
, sizeof socket_name
, "%s/agent.%ld", socket_dir
,
2377 /* Try to use specified agent socket */
2378 socket_dir
[0] = '\0';
2379 strlcpy(socket_name
, agentsocket
, sizeof socket_name
);
2383 * Create socket early so it will exist before command gets run from
2386 prev_mask
= umask(0177);
2387 sock
= unix_listener(socket_name
, SSH_LISTEN_BACKLOG
, 0);
2389 /* XXX - unix_listener() calls error() not perror() */
2390 *socket_name
= '\0'; /* Don't unlink any existing file */
2396 * Fork, and have the parent execute the command, if any, or present
2397 * the socket data. The child continues as the authentication agent.
2399 if (D_flag
|| d_flag
) {
2400 log_init(__progname
,
2401 d_flag
? SYSLOG_LEVEL_DEBUG3
: SYSLOG_LEVEL_INFO
,
2402 SYSLOG_FACILITY_AUTH
, 1);
2403 format
= c_flag
? "setenv %s %s;\n" : "%s=%s; export %s;\n";
2404 printf(format
, SSH_AUTHSOCKET_ENV_NAME
, socket_name
,
2405 SSH_AUTHSOCKET_ENV_NAME
);
2406 printf("echo Agent pid %ld;\n", (long)parent_pid
);
2415 if (pid
!= 0) { /* Parent - execute the given command. */
2417 snprintf(pidstrbuf
, sizeof pidstrbuf
, "%ld", (long)pid
);
2419 format
= c_flag
? "setenv %s %s;\n" : "%s=%s; export %s;\n";
2420 printf(format
, SSH_AUTHSOCKET_ENV_NAME
, socket_name
,
2421 SSH_AUTHSOCKET_ENV_NAME
);
2422 printf(format
, SSH_AGENTPID_ENV_NAME
, pidstrbuf
,
2423 SSH_AGENTPID_ENV_NAME
);
2424 printf("echo Agent pid %ld;\n", (long)pid
);
2427 if (setenv(SSH_AUTHSOCKET_ENV_NAME
, socket_name
, 1) == -1 ||
2428 setenv(SSH_AGENTPID_ENV_NAME
, pidstrbuf
, 1) == -1) {
2437 log_init(__progname
, SYSLOG_LEVEL_INFO
, SYSLOG_FACILITY_AUTH
, 0);
2439 if (setsid() == -1) {
2440 error("setsid: %s", strerror(errno
));
2445 if (stdfd_devnull(1, 1, 1) == -1)
2446 error_f("stdfd_devnull failed");
2448 #ifdef HAVE_SETRLIMIT
2449 /* deny core dumps, since memory contains unencrypted private keys */
2450 rlim
.rlim_cur
= rlim
.rlim_max
= 0;
2451 if (setrlimit(RLIMIT_CORE
, &rlim
) == -1) {
2452 error("setrlimit RLIMIT_CORE: %s", strerror(errno
));
2459 cleanup_pid
= getpid();
2461 #ifdef ENABLE_PKCS11
2464 new_socket(AUTH_SOCKET
, sock
);
2466 parent_alive_interval
= 10;
2468 ssh_signal(SIGPIPE
, SIG_IGN
);
2469 ssh_signal(SIGINT
, (d_flag
| D_flag
) ? cleanup_handler
: SIG_IGN
);
2470 ssh_signal(SIGHUP
, cleanup_handler
);
2471 ssh_signal(SIGTERM
, cleanup_handler
);
2473 sigemptyset(&nsigset
);
2474 sigaddset(&nsigset
, SIGINT
);
2475 sigaddset(&nsigset
, SIGHUP
);
2476 sigaddset(&nsigset
, SIGTERM
);
2478 if (pledge("stdio rpath cpath unix id proc exec", NULL
) == -1)
2479 fatal("%s: pledge: %s", __progname
, strerror(errno
));
2480 platform_pledge_agent();
2483 sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
2484 if (signalled
!= 0) {
2485 logit("exiting on signal %d", (int)signalled
);
2488 ptimeout_init(&timeout
);
2489 prepare_poll(&pfd
, &npfd
, &timeout
, maxfds
);
2490 result
= ppoll(pfd
, npfd
, ptimeout_get_tsp(&timeout
), &osigset
);
2491 sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
2492 saved_errno
= errno
;
2493 if (parent_alive_interval
!= 0)
2494 check_parent_exists();
2495 (void) reaper(); /* remove expired keys */
2497 if (saved_errno
== EINTR
)
2499 fatal("poll: %s", strerror(saved_errno
));
2500 } else if (result
> 0)
2501 after_poll(pfd
, npfd
, maxfds
);