1/* $OpenBSD: ssh-agent.c,v 1.306 2024/03/09 05:12:13 djm Exp $ */
2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 *                    All rights reserved
6 * The authentication agent program.
7 *
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".
13 *
14 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
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.
24 *
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.
35 */
36
37#include "includes.h"
38
39#include <sys/types.h>
40#include <sys/resource.h>
41#include <sys/stat.h>
42#include <sys/socket.h>
43#include <sys/wait.h>
44#ifdef HAVE_SYS_TIME_H
45# include <sys/time.h>
46#endif
47#ifdef HAVE_SYS_UN_H
48# include <sys/un.h>
49#endif
50#include "openbsd-compat/sys-queue.h"
51
52#ifdef WITH_OPENSSL
53#include <openssl/evp.h>
54#include "openbsd-compat/openssl-compat.h"
55#endif
56
57#include <errno.h>
58#include <fcntl.h>
59#include <limits.h>
60#ifdef HAVE_PATHS_H
61# include <paths.h>
62#endif
63#ifdef HAVE_POLL_H
64# include <poll.h>
65#endif
66#include <signal.h>
67#include <stdarg.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <time.h>
71#include <string.h>
72#include <unistd.h>
73#ifdef HAVE_UTIL_H
74# include <util.h>
75#endif
76
77#include "xmalloc.h"
78#include "ssh.h"
79#include "ssh2.h"
80#include "sshbuf.h"
81#include "sshkey.h"
82#include "authfd.h"
83#include "log.h"
84#include "misc.h"
85#include "digest.h"
86#include "ssherr.h"
87#include "match.h"
88#include "msg.h"
89#include "pathnames.h"
90#include "ssh-pkcs11.h"
91#include "sk-api.h"
92#include "myproposal.h"
93
94#ifndef DEFAULT_ALLOWED_PROVIDERS
95# define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/local/lib*/*"
96#endif
97
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
110
111/* XXX store hostkey_sid in a refcounted tree */
112
113typedef enum {
114	AUTH_UNUSED = 0,
115	AUTH_SOCKET = 1,
116	AUTH_CONNECTION = 2,
117} sock_type;
118
119struct hostkey_sid {
120	struct sshkey *key;
121	struct sshbuf *sid;
122	int forwarded;
123};
124
125typedef struct socket_entry {
126	int fd;
127	sock_type type;
128	struct sshbuf *input;
129	struct sshbuf *output;
130	struct sshbuf *request;
131	size_t nsession_ids;
132	struct hostkey_sid *session_ids;
133	int session_bind_attempted;
134} SocketEntry;
135
136u_int sockets_alloc = 0;
137SocketEntry *sockets = NULL;
138
139typedef struct identity {
140	TAILQ_ENTRY(identity) next;
141	struct sshkey *key;
142	char *comment;
143	char *provider;
144	time_t death;
145	u_int confirm;
146	char *sk_provider;
147	struct dest_constraint *dest_constraints;
148	size_t ndest_constraints;
149} Identity;
150
151struct idtable {
152	int nentries;
153	TAILQ_HEAD(idqueue, identity) idlist;
154};
155
156/* private key table */
157struct idtable *idtab;
158
159int max_fd = 0;
160
161/* pid of shell == parent of agent */
162pid_t parent_pid = -1;
163time_t parent_alive_interval = 0;
164
165sig_atomic_t signalled = 0;
166
167/* pid of process for which cleanup_socket is applicable */
168pid_t cleanup_pid = 0;
169
170/* pathname and directory for AUTH_SOCKET */
171char socket_name[PATH_MAX];
172char socket_dir[PATH_MAX];
173
174/* Pattern-list of allowed PKCS#11/Security key paths */
175static char *allowed_providers;
176
177/*
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).
180 */
181static int remote_add_provider;
182
183/* locking */
184#define LOCK_SIZE	32
185#define LOCK_SALT_SIZE	16
186#define LOCK_ROUNDS	1
187int locked = 0;
188u_char lock_pwhash[LOCK_SIZE];
189u_char lock_salt[LOCK_SALT_SIZE];
190
191extern char *__progname;
192
193/* Default lifetime in seconds (0 == forever) */
194static int lifetime = 0;
195
196static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
197
198/* Refuse signing of non-SSH messages for web-origin FIDO keys */
199static int restrict_websafe = 1;
200
201/*
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
207 * longer has any.
208 */
209static int xcount = 1;
210
211static void
212close_socket(SocketEntry *e)
213{
214	size_t i;
215	int last = 0;
216
217	if (e->type == AUTH_CONNECTION) {
218		debug("xcount %d -> %d", xcount, xcount - 1);
219		if (--xcount == 0)
220			last = 1;
221	}
222	close(e->fd);
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);
229	}
230	free(e->session_ids);
231	memset(e, '\0', sizeof(*e));
232	e->fd = -1;
233	e->type = AUTH_UNUSED;
234	if (last)
235		cleanup_exit(0);
236}
237
238static void
239idtab_init(void)
240{
241	idtab = xcalloc(1, sizeof(*idtab));
242	TAILQ_INIT(&idtab->idlist);
243	idtab->nentries = 0;
244}
245
246static void
247free_dest_constraint_hop(struct dest_constraint_hop *dch)
248{
249	u_int i;
250
251	if (dch == NULL)
252		return;
253	free(dch->user);
254	free(dch->hostname);
255	for (i = 0; i < dch->nkeys; i++)
256		sshkey_free(dch->keys[i]);
257	free(dch->keys);
258	free(dch->key_is_ca);
259}
260
261static void
262free_dest_constraints(struct dest_constraint *dcs, size_t ndcs)
263{
264	size_t i;
265
266	for (i = 0; i < ndcs; i++) {
267		free_dest_constraint_hop(&dcs[i].from);
268		free_dest_constraint_hop(&dcs[i].to);
269	}
270	free(dcs);
271}
272
273#ifdef ENABLE_PKCS11
274static void
275dup_dest_constraint_hop(const struct dest_constraint_hop *dch,
276    struct dest_constraint_hop *out)
277{
278	u_int i;
279	int r;
280
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];
295	}
296}
297
298static struct dest_constraint *
299dup_dest_constraints(const struct dest_constraint *dcs, size_t ndcs)
300{
301	size_t i;
302	struct dest_constraint *ret;
303
304	if (ndcs == 0)
305		return NULL;
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);
310	}
311	return ret;
312}
313#endif /* ENABLE_PKCS11 */
314
315#ifdef DEBUG_CONSTRAINTS
316static void
317dump_dest_constraint_hop(const struct dest_constraint_hop *dch)
318{
319	u_int i;
320	char *fp;
321
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++) {
327		fp = NULL;
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,
336		    dch->key_is_ca[i]);
337		free(fp);
338	}
339}
340#endif /* DEBUG_CONSTRAINTS */
341
342static void
343dump_dest_constraints(const char *context,
344    const struct dest_constraint *dcs, size_t ndcs)
345{
346#ifdef DEBUG_CONSTRAINTS
347	size_t i;
348
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);
355	}
356	debug_f("done for %s", context);
357#endif /* DEBUG_CONSTRAINTS */
358}
359
360static void
361free_identity(Identity *id)
362{
363	sshkey_free(id->key);
364	free(id->provider);
365	free(id->comment);
366	free(id->sk_provider);
367	free_dest_constraints(id->dest_constraints, id->ndest_constraints);
368	free(id);
369}
370
371/*
372 * Match 'key' against the key/CA list in a destination constraint hop
373 * Returns 0 on success or -1 otherwise.
374 */
375static int
376match_key_hop(const char *tag, const struct sshkey *key,
377    const struct dest_constraint_hop *dch)
378{
379	const char *reason = NULL;
380	const char *hostname = dch->hostname ? dch->hostname : "(ORIGIN)";
381	u_int i;
382	char *fp;
383
384	if (key == NULL)
385		return -1;
386	/* XXX logspam */
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);
392	free(fp);
393	for (i = 0; i < dch->nkeys; i++) {
394		if (dch->keys[i] == NULL)
395			return -1;
396		/* XXX logspam */
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);
403		free(fp);
404		if (!sshkey_is_cert(key)) {
405			/* plain key */
406			if (dch->key_is_ca[i] ||
407			    !sshkey_equal(key, dch->keys[i]))
408				continue;
409			return 0;
410		}
411		/* certificate */
412		if (!dch->key_is_ca[i])
413			continue;
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]))
417			continue;
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);
422			continue;
423		}
424		return 0;
425	}
426	return -1;
427}
428
429/* Check destination constraints on an identity against the hostkey/user */
430static int
431permitted_by_dest_constraints(const struct sshkey *fromkey,
432    const struct sshkey *tokey, Identity *id, const char *user,
433    const char **hostnamep)
434{
435	size_t i;
436	struct dest_constraint *d;
437
438	if (hostnamep != NULL)
439		*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)",
447		    d->from.nkeys,
448		    d->to.user ? d->to.user : "", d->to.user ? "@" : "",
449		    d->to.hostname ? d->to.hostname : "(ANY)", d->to.nkeys);
450
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)
455				continue;
456		} else if (match_key_hop("from", fromkey, &d->from) != 0)
457			continue;
458
459		/* Match 'to' key */
460		if (tokey != NULL && match_key_hop("to", tokey, &d->to) != 0)
461			continue;
462
463		/* Match user if specified */
464		if (d->to.user != NULL && user != NULL &&
465		    !match_pattern(user, d->to.user))
466			continue;
467
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);
473		return 0;
474	}
475	/* no match */
476	debug2_f("%s identity \"%s\" not permitted for this destination",
477	    sshkey_type(id->key), id->comment);
478	return -1;
479}
480
481/*
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.
485 */
486static int
487identity_permitted(Identity *id, SocketEntry *e, char *user,
488    const char **forward_hostnamep, const char **last_hostnamep)
489{
490	size_t i;
491	const char **hp;
492	struct hostkey_sid *hks;
493	const struct sshkey *fromkey = NULL;
494	const char *test_user;
495	char *fp1, *fp2;
496
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");
505		return -1;
506	}
507	if (e->nsession_ids == 0)
508		return 0; /* local use */
509	/*
510	 * Walk through the hops recorded by session_id and try to find a
511	 * constraint that satisfies each.
512	 */
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 */
518		fp1 = fp2 = NULL;
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);
532		free(fp1);
533		free(fp2);
534		/*
535		 * Record the hostnames for the initial forwarding and
536		 * the final destination.
537		 */
538		hp = NULL;
539		if (i == e->nsession_ids - 1)
540			hp = last_hostnamep;
541		else if (i == 0)
542			hp = forward_hostnamep;
543		/* Special handling for final recorded binding */
544		test_user = NULL;
545		if (i == e->nsession_ids - 1) {
546			/* Can only check user at final hop */
547			test_user = user;
548			/*
549			 * user is only presented for signature requests.
550			 * If this is the case, make sure last binding is not
551			 * for a forwarding.
552			 */
553			if (hks->forwarded && user != NULL) {
554				error_f("tried to sign on forwarding hop");
555				return -1;
556			}
557		} else if (!hks->forwarded) {
558			error_f("tried to forward though signing bind");
559			return -1;
560		}
561		if (permitted_by_dest_constraints(fromkey, hks->key, id,
562		    test_user, hp) != 0)
563			return -1;
564		fromkey = hks->key;
565	}
566	/*
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.
573	 */
574	hks = &e->session_ids[e->nsession_ids - 1];
575	if (hks->forwarded && user == NULL &&
576	    permitted_by_dest_constraints(hks->key, NULL, id,
577	    NULL, NULL) != 0) {
578		debug3_f("key permitted at host but not after");
579		return -1;
580	}
581
582	/* success */
583	return 0;
584}
585
586static int
587socket_is_remote(SocketEntry *e)
588{
589	return e->session_bind_attempted || (e->nsession_ids != 0);
590}
591
592/* return matching private key for given public key */
593static Identity *
594lookup_identity(struct sshkey *key)
595{
596	Identity *id;
597
598	TAILQ_FOREACH(id, &idtab->idlist, next) {
599		if (sshkey_equal(key, id->key))
600			return (id);
601	}
602	return (NULL);
603}
604
605/* Check confirmation of keysign request */
606static int
607confirm_key(Identity *id, const char *extra)
608{
609	char *p;
610	int ret = -1;
611
612	p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT);
613	if (p != NULL &&
614	    ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s",
615	    id->comment, p,
616	    extra == NULL ? "" : "\n", extra == NULL ? "" : extra))
617		ret = 0;
618	free(p);
619
620	return (ret);
621}
622
623static void
624send_status(SocketEntry *e, int success)
625{
626	int r;
627
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");
632}
633
634/* send list of supported public keys to 'client' */
635static void
636process_request_identities(SocketEntry *e)
637{
638	Identity *id;
639	struct sshbuf *msg, *keys;
640	int r;
641	u_int i = 0, nentries = 0;
642	char *fp;
643
644	debug2_f("entering");
645
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);
656		free(fp);
657		/* identity not visible, don't include in response */
658		if (identity_permitted(id, e, NULL, NULL, NULL) != 0)
659			continue;
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");
664			continue;
665		}
666		nentries++;
667	}
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");
676	sshbuf_free(msg);
677	sshbuf_free(keys);
678}
679
680
681static char *
682agent_decode_alg(struct sshkey *key, u_int flags)
683{
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";
694	}
695	return NULL;
696}
697
698/*
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.
704 */
705static int
706parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
707    char **userp, struct sshbuf **sess_idp, struct sshkey **hostkeyp)
708{
709	struct sshbuf *b = NULL, *sess_id = NULL;
710	char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL;
711	int r;
712	u_char t, sig_follows;
713	struct sshkey *mkey = NULL, *hostkey = NULL;
714
715	if (userp != NULL)
716		*userp = NULL;
717	if (sess_idp != NULL)
718		*sess_idp = NULL;
719	if (hostkeyp != NULL)
720		*hostkeyp = NULL;
721	if ((b = sshbuf_fromb(msg)) == NULL)
722		fatal_f("sshbuf_fromb");
723
724	/* SSH userauth request */
725	if ((r = sshbuf_froms(b, &sess_id)) != 0)
726		goto out;
727	if (sshbuf_len(sess_id) == 0) {
728		r = SSH_ERR_INVALID_FORMAT;
729		goto out;
730	}
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 */
738		goto out;
739	if (t != SSH2_MSG_USERAUTH_REQUEST ||
740	    sig_follows != 1 ||
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;
745		goto out;
746	}
747	if (strcmp(method, "publickey-hostbound-v00@openssh.com") == 0) {
748		if ((r = sshkey_froms(b, &hostkey)) != 0)
749			goto out;
750	} else if (strcmp(method, "publickey") != 0) {
751		r = SSH_ERR_INVALID_FORMAT;
752		goto out;
753	}
754	if (sshbuf_len(b) != 0) {
755		r = SSH_ERR_INVALID_FORMAT;
756		goto out;
757	}
758	/* success */
759	r = 0;
760	debug3_f("well formed userauth");
761	if (userp != NULL) {
762		*userp = user;
763		user = NULL;
764	}
765	if (sess_idp != NULL) {
766		*sess_idp = sess_id;
767		sess_id = NULL;
768	}
769	if (hostkeyp != NULL) {
770		*hostkeyp = hostkey;
771		hostkey = NULL;
772	}
773 out:
774	sshbuf_free(b);
775	sshbuf_free(sess_id);
776	free(user);
777	free(service);
778	free(method);
779	free(pkalg);
780	sshkey_free(mkey);
781	sshkey_free(hostkey);
782	return r;
783}
784
785/*
786 * Attempt to parse the contents of a buffer as a SSHSIG signature request.
787 * Note: does not modify buffer.
788 */
789static int
790parse_sshsig_request(struct sshbuf *msg)
791{
792	int r;
793	struct sshbuf *b;
794
795	if ((b = sshbuf_fromb(msg)) == NULL)
796		fatal_f("sshbuf_fromb");
797
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) */
804		goto out;
805	if (sshbuf_len(b) != 0) {
806		r = SSH_ERR_INVALID_FORMAT;
807		goto out;
808	}
809	/* success */
810	r = 0;
811 out:
812	sshbuf_free(b);
813	return r;
814}
815
816/*
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
821 * for the web.
822 */
823static int
824check_websafe_message_contents(struct sshkey *key, struct sshbuf *data)
825{
826	if (parse_userauth_request(data, key, NULL, NULL, NULL) == 0) {
827		debug_f("signed data matches public key userauth request");
828		return 1;
829	}
830	if (parse_sshsig_request(data) == 0) {
831		debug_f("signed data matches SSHSIG signature request");
832		return 1;
833	}
834
835	/* XXX check CA signature operation */
836
837	error("web-origin key attempting to sign non-SSH message");
838	return 0;
839}
840
841static int
842buf_equal(const struct sshbuf *a, const struct sshbuf *b)
843{
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;
850	return 0;
851}
852
853/* ssh2 only */
854static void
855process_sign_request2(SocketEntry *e)
856{
857	u_char *signature = NULL;
858	size_t slen = 0;
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;
866	struct identity *id;
867	struct notifier_ctx *notifier = NULL;
868
869	debug_f("entering");
870
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");
877		goto send;
878	}
879
880	if ((id = lookup_identity(key)) == NULL) {
881		verbose_f("%s key not found", sshkey_type(key));
882		goto send;
883	}
884	if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
885	    SSH_FP_DEFAULT)) == NULL)
886		fatal_f("fingerprint failed");
887
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");
892			goto send;
893		}
894		if (parse_userauth_request(data, key, &user, &sid,
895		    &hostkey) != 0) {
896			logit_f("refusing use of destination-constrained key "
897			   "to sign an unidentified signature");
898			goto send;
899		}
900		/* XXX logspam */
901		debug_f("user=%s", user);
902		if (identity_permitted(id, e, user, &fwd_host, &dest_host) != 0)
903			goto send;
904		/* XXX display fwd_host/dest_host in askpass UI */
905		/*
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.
909		 */
910		if (buf_equal(sid,
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);
916			goto send;
917		}
918		/*
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.
922		 */
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 "
926			    "connection");
927			goto send;
928		}
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");
934			goto send;
935		}
936		xasprintf(&sig_dest, "public key authentication request for "
937		    "user \"%s\" to listed host", user);
938	}
939	if (id->confirm && confirm_key(id, sig_dest) != 0) {
940		verbose_f("user refused key");
941		goto send;
942	}
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 */
948			goto send;
949		}
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);
956		}
957	}
958 retry_pin:
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);
966			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);
973			retried = 1;
974			goto retry_pin;
975		}
976		error_fr(r, "sshkey_sign");
977		goto send;
978	}
979	/* Success */
980	ok = 0;
981	debug_f("good signature");
982 send:
983	notify_complete(notifier, "User presence confirmed");
984
985	if (ok == 0) {
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");
991
992	if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
993		fatal_fr(r, "enqueue");
994
995	sshbuf_free(sid);
996	sshbuf_free(data);
997	sshbuf_free(msg);
998	sshkey_free(key);
999	sshkey_free(hostkey);
1000	free(fp);
1001	free(signature);
1002	free(sig_dest);
1003	free(user);
1004	free(prompt);
1005	if (pin != NULL)
1006		freezero(pin, strlen(pin));
1007}
1008
1009/* shared */
1010static void
1011process_remove_identity(SocketEntry *e)
1012{
1013	int r, success = 0;
1014	struct sshkey *key = NULL;
1015	Identity *id;
1016
1017	debug2_f("entering");
1018	if ((r = sshkey_froms(e->request, &key)) != 0) {
1019		error_fr(r, "parse key");
1020		goto done;
1021	}
1022	if ((id = lookup_identity(key)) == NULL) {
1023		debug_f("key not found");
1024		goto done;
1025	}
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);
1033	free_identity(id);
1034	idtab->nentries--;
1035	success = 1;
1036 done:
1037	sshkey_free(key);
1038	send_status(e, success);
1039}
1040
1041static void
1042process_remove_all_identities(SocketEntry *e)
1043{
1044	Identity *id;
1045
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);
1051		free_identity(id);
1052	}
1053
1054	/* Mark that there are no identities. */
1055	idtab->nentries = 0;
1056
1057	/* Send success. */
1058	send_status(e, 1);
1059}
1060
1061/* removes expired keys and returns number of seconds until the next expiry */
1062static time_t
1063reaper(void)
1064{
1065	time_t deadline = 0, now = monotime();
1066	Identity *id, *nxt;
1067
1068	for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
1069		nxt = TAILQ_NEXT(id, next);
1070		if (id->death == 0)
1071			continue;
1072		if (now >= id->death) {
1073			debug("expiring key '%s'", id->comment);
1074			TAILQ_REMOVE(&idtab->idlist, id, next);
1075			free_identity(id);
1076			idtab->nentries--;
1077		} else
1078			deadline = (deadline == 0) ? id->death :
1079			    MINIMUM(deadline, id->death);
1080	}
1081	if (deadline == 0 || deadline <= now)
1082		return 0;
1083	else
1084		return (deadline - now);
1085}
1086
1087static int
1088parse_dest_constraint_hop(struct sshbuf *b, struct dest_constraint_hop *dch)
1089{
1090	u_char key_is_ca;
1091	size_t elen = 0;
1092	int r;
1093	struct sshkey *k = NULL;
1094	char *fp;
1095
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");
1101		goto out;
1102	}
1103	if (elen != 0) {
1104		error_f("unsupported extensions (len %zu)", elen);
1105		r = SSH_ERR_FEATURE_UNSUPPORTED;
1106		goto out;
1107	}
1108	if (*dch->hostname == '\0') {
1109		free(dch->hostname);
1110		dch->hostname = NULL;
1111	}
1112	if (*dch->user == '\0') {
1113		free(dch->user);
1114		dch->user = NULL;
1115	}
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)
1123			goto out;
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);
1131		free(fp);
1132		dch->keys[dch->nkeys] = k;
1133		dch->key_is_ca[dch->nkeys] = key_is_ca != 0;
1134		dch->nkeys++;
1135		k = NULL; /* transferred */
1136	}
1137	/* success */
1138	r = 0;
1139 out:
1140	sshkey_free(k);
1141	return r;
1142}
1143
1144static int
1145parse_dest_constraint(struct sshbuf *m, struct dest_constraint *dc)
1146{
1147	struct sshbuf *b = NULL, *frombuf = NULL, *tobuf = NULL;
1148	int r;
1149	size_t elen = 0;
1150
1151	debug3_f("entering");
1152
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");
1159		goto out;
1160	}
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 */
1164	if (elen != 0) {
1165		error_f("unsupported extensions (len %zu)", elen);
1166		r = SSH_ERR_FEATURE_UNSUPPORTED;
1167		goto out;
1168	}
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;
1178		goto out;
1179	}
1180	if (dc->to.hostname == NULL || dc->to.nkeys == 0) {
1181		error_f("incomplete \"to\" specification");
1182		r = SSH_ERR_INVALID_FORMAT;
1183		goto out;
1184	}
1185	/* success */
1186	r = 0;
1187 out:
1188	sshbuf_free(b);
1189	sshbuf_free(frombuf);
1190	sshbuf_free(tobuf);
1191	return r;
1192}
1193
1194static int
1195parse_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)
1198{
1199	char *ext_name = NULL;
1200	int r;
1201	struct sshbuf *b = NULL;
1202	u_char v;
1203	struct sshkey *k;
1204
1205	if ((r = sshbuf_get_cstring(m, &ext_name, NULL)) != 0) {
1206		error_fr(r, "parse constraint extension");
1207		goto out;
1208	}
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;
1214			goto out;
1215		}
1216		if (*sk_providerp != NULL) {
1217			error_f("%s already set", ext_name);
1218			r = SSH_ERR_INVALID_FORMAT;
1219			goto out;
1220		}
1221		if ((r = sshbuf_get_cstring(m, sk_providerp, NULL)) != 0) {
1222			error_fr(r, "parse %s", ext_name);
1223			goto out;
1224		}
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);
1229			goto out;
1230		}
1231		if ((r = sshbuf_froms(m, &b)) != 0) {
1232			error_fr(r, "parse %s outer", ext_name);
1233			goto out;
1234		}
1235		while (sshbuf_len(b) != 0) {
1236			if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS) {
1237				error_f("too many %s constraints", ext_name);
1238				goto out;
1239			}
1240			*dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1,
1241			    sizeof(**dcsp));
1242			if ((r = parse_dest_constraint(b,
1243			    *dcsp + (*ndcsp)++)) != 0)
1244				goto out; /* error already logged */
1245		}
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;
1251			goto out;
1252		}
1253		if (*certs != NULL) {
1254			error_f("%s already set", ext_name);
1255			goto out;
1256		}
1257		if ((r = sshbuf_get_u8(m, &v)) != 0 ||
1258		    (r = sshbuf_froms(m, &b)) != 0) {
1259			error_fr(r, "parse %s", ext_name);
1260			goto out;
1261		}
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);
1266				goto out;
1267			}
1268			*certs = xrecallocarray(*certs, *ncerts, *ncerts + 1,
1269			    sizeof(**certs));
1270			if ((r = sshkey_froms(b, &k)) != 0) {
1271				error_fr(r, "parse key");
1272				goto out;
1273			}
1274			(*certs)[(*ncerts)++] = k;
1275		}
1276	} else {
1277		error_f("unsupported constraint \"%s\"", ext_name);
1278		r = SSH_ERR_FEATURE_UNSUPPORTED;
1279		goto out;
1280	}
1281	/* success */
1282	r = 0;
1283 out:
1284	free(ext_name);
1285	sshbuf_free(b);
1286	return r;
1287}
1288
1289static int
1290parse_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)
1294{
1295	u_char ctype;
1296	int r;
1297	u_int seconds, maxsign = 0;
1298
1299	while (sshbuf_len(m)) {
1300		if ((r = sshbuf_get_u8(m, &ctype)) != 0) {
1301			error_fr(r, "parse constraint type");
1302			goto out;
1303		}
1304		switch (ctype) {
1305		case SSH_AGENT_CONSTRAIN_LIFETIME:
1306			if (*deathp != 0) {
1307				error_f("lifetime already set");
1308				r = SSH_ERR_INVALID_FORMAT;
1309				goto out;
1310			}
1311			if ((r = sshbuf_get_u32(m, &seconds)) != 0) {
1312				error_fr(r, "parse lifetime constraint");
1313				goto out;
1314			}
1315			*deathp = monotime() + seconds;
1316			*secondsp = seconds;
1317			break;
1318		case SSH_AGENT_CONSTRAIN_CONFIRM:
1319			if (*confirmp != 0) {
1320				error_f("confirm already set");
1321				r = SSH_ERR_INVALID_FORMAT;
1322				goto out;
1323			}
1324			*confirmp = 1;
1325			break;
1326		case SSH_AGENT_CONSTRAIN_MAXSIGN:
1327			if (k == NULL) {
1328				error_f("maxsign not valid here");
1329				r = SSH_ERR_INVALID_FORMAT;
1330				goto out;
1331			}
1332			if (maxsign != 0) {
1333				error_f("maxsign already set");
1334				r = SSH_ERR_INVALID_FORMAT;
1335				goto out;
1336			}
1337			if ((r = sshbuf_get_u32(m, &maxsign)) != 0) {
1338				error_fr(r, "parse maxsign constraint");
1339				goto out;
1340			}
1341			if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) {
1342				error_fr(r, "enable maxsign");
1343				goto out;
1344			}
1345			break;
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 */
1351			break;
1352		default:
1353			error_f("Unknown constraint %d", ctype);
1354			r = SSH_ERR_FEATURE_UNSUPPORTED;
1355			goto out;
1356		}
1357	}
1358	/* success */
1359	r = 0;
1360 out:
1361	return r;
1362}
1363
1364static void
1365process_add_identity(SocketEntry *e)
1366{
1367	Identity *id;
1368	int success = 0, confirm = 0;
1369	char *fp, *comment = NULL, *sk_provider = NULL;
1370	char canonical_provider[PATH_MAX];
1371	time_t death = 0;
1372	u_int seconds = 0;
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;
1377
1378	debug2_f("entering");
1379	if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
1380	    k == NULL ||
1381	    (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
1382		error_fr(r, "parse");
1383		goto out;
1384	}
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);
1390		goto out;
1391	}
1392	dump_dest_constraints(__func__, dest_constraints, ndest_constraints);
1393
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));
1398			goto out;
1399		}
1400		if (strcasecmp(sk_provider, "internal") == 0) {
1401			debug_f("internal provider");
1402		} else {
1403			if (socket_is_remote(e) && !remote_add_provider) {
1404				verbose("failed add of SK provider \"%.100s\": "
1405				    "remote addition of providers is disabled",
1406				    sk_provider);
1407				goto out;
1408			}
1409			if (realpath(sk_provider, canonical_provider) == NULL) {
1410				verbose("failed provider \"%.100s\": "
1411				    "realpath: %s", sk_provider,
1412				    strerror(errno));
1413				goto out;
1414			}
1415			free(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);
1421				goto out;
1422			}
1423		}
1424	}
1425	if ((r = sshkey_shield_private(k)) != 0) {
1426		error_fr(r, "shield private");
1427		goto out;
1428	}
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. */
1435		idtab->nentries++;
1436	} else {
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);
1442		free(id->comment);
1443		free(id->sk_provider);
1444		free_dest_constraints(id->dest_constraints,
1445		    id->ndest_constraints);
1446	}
1447	/* success */
1448	id->key = k;
1449	id->comment = comment;
1450	id->death = death;
1451	id->confirm = confirm;
1452	id->sk_provider = sk_provider;
1453	id->dest_constraints = dest_constraints;
1454	id->ndest_constraints = ndest_constraints;
1455
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);
1463	free(fp);
1464	/* transferred */
1465	k = NULL;
1466	comment = NULL;
1467	sk_provider = NULL;
1468	dest_constraints = NULL;
1469	ndest_constraints = 0;
1470	success = 1;
1471 out:
1472	free(sk_provider);
1473	free(comment);
1474	sshkey_free(k);
1475	free_dest_constraints(dest_constraints, ndest_constraints);
1476	send_status(e, success);
1477}
1478
1479/* XXX todo: encrypt sensitive data with passphrase */
1480static void
1481process_lock_agent(SocketEntry *e, int lock)
1482{
1483	int r, success = 0, delay;
1484	char *passwd;
1485	u_char passwdhash[LOCK_SIZE];
1486	static u_int fail_count = 0;
1487	size_t pwlen;
1488
1489	debug2_f("entering");
1490	/*
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
1493	 * do is abort.
1494	 */
1495	if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0)
1496		fatal_fr(r, "parse");
1497	if (pwlen == 0) {
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");
1505			locked = 0;
1506			fail_count = 0;
1507			explicit_bzero(lock_pwhash, sizeof(lock_pwhash));
1508			success = 1;
1509		} else {
1510			/* delay in 0.1s increments up to 10s */
1511			if (fail_count < 100)
1512				fail_count++;
1513			delay = 100000 * fail_count;
1514			debug("unlock failed, delaying %0.1lf seconds",
1515			    (double)delay/1000000);
1516			usleep(delay);
1517		}
1518		explicit_bzero(passwdhash, sizeof(passwdhash));
1519	} else if (!locked && lock) {
1520		debug("agent locked");
1521		locked = 1;
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");
1526		success = 1;
1527	}
1528	freezero(passwd, pwlen);
1529	send_status(e, success);
1530}
1531
1532static void
1533no_identities(SocketEntry *e)
1534{
1535	struct sshbuf *msg;
1536	int r;
1537
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");
1544	sshbuf_free(msg);
1545}
1546
1547#ifdef ENABLE_PKCS11
1548/* Add an identity to idlist; takes ownership of 'key' and 'comment' */
1549static void
1550add_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)
1553{
1554	Identity *id;
1555
1556	if (lookup_identity(key) != NULL) {
1557		sshkey_free(key);
1558		free(comment);
1559		return;
1560	}
1561	id = xcalloc(1, sizeof(Identity));
1562	id->key = key;
1563	id->comment = comment;
1564	id->provider = xstrdup(provider);
1565	id->death = death;
1566	id->confirm = confirm;
1567	id->dest_constraints = dup_dest_constraints(dest_constraints,
1568	    ndest_constraints);
1569	id->ndest_constraints = ndest_constraints;
1570	TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
1571	idtab->nentries++;
1572}
1573
1574static void
1575process_add_smartcard_key(SocketEntry *e)
1576{
1577	char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
1578	char **comments = NULL;
1579	int r, i, count = 0, success = 0, confirm = 0;
1580	u_int seconds = 0;
1581	time_t death = 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;
1586	int cert_only = 0;
1587
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");
1592		goto send;
1593	}
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");
1598		goto send;
1599	}
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);
1604		goto send;
1605	}
1606	if (realpath(provider, canonical_provider) == NULL) {
1607		verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1608		    provider, strerror(errno));
1609		goto send;
1610	}
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);
1614		goto send;
1615	}
1616	debug_f("add %.100s", canonical_provider);
1617	if (lifetime && !death)
1618		death = monotime() + lifetime;
1619
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') {
1623			free(comments[i]);
1624			comments[i] = xstrdup(canonical_provider);
1625		}
1626		for (j = 0; j < ncerts; j++) {
1627			if (!sshkey_is_cert(certs[j]))
1628				continue;
1629			if (!sshkey_equal_public(keys[i], certs[j]))
1630				continue;
1631			if (pkcs11_make_cert(keys[i], certs[j], &k) != 0)
1632				continue;
1633			add_p11_identity(k, xstrdup(comments[i]),
1634			    canonical_provider, death, confirm,
1635			    dest_constraints, ndest_constraints);
1636			success = 1;
1637		}
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 */
1644			success = 1;
1645		}
1646		/* XXX update constraints for existing keys */
1647		sshkey_free(keys[i]);
1648		free(comments[i]);
1649	}
1650send:
1651	free(pin);
1652	free(provider);
1653	free(keys);
1654	free(comments);
1655	free_dest_constraints(dest_constraints, ndest_constraints);
1656	for (j = 0; j < ncerts; j++)
1657		sshkey_free(certs[j]);
1658	free(certs);
1659	send_status(e, success);
1660}
1661
1662static void
1663process_remove_smartcard_key(SocketEntry *e)
1664{
1665	char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
1666	int r, success = 0;
1667	Identity *id, *nxt;
1668
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");
1673		goto send;
1674	}
1675	free(pin);
1676
1677	if (realpath(provider, canonical_provider) == NULL) {
1678		verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1679		    provider, strerror(errno));
1680		goto send;
1681	}
1682
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)
1688			continue;
1689		if (!strcmp(canonical_provider, id->provider)) {
1690			TAILQ_REMOVE(&idtab->idlist, id, next);
1691			free_identity(id);
1692			idtab->nentries--;
1693		}
1694	}
1695	if (pkcs11_del_provider(canonical_provider) == 0)
1696		success = 1;
1697	else
1698		error_f("pkcs11_del_provider failed");
1699send:
1700	free(provider);
1701	send_status(e, success);
1702}
1703#endif /* ENABLE_PKCS11 */
1704
1705static int
1706process_ext_session_bind(SocketEntry *e)
1707{
1708	int r, sid_match, key_match;
1709	struct sshkey *key = NULL;
1710	struct sshbuf *sid = NULL, *sig = NULL;
1711	char *fp = NULL;
1712	size_t i;
1713	u_char fwd = 0;
1714
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");
1722		goto out;
1723	}
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);
1731		goto out;
1732	}
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");
1738			r = -1;
1739			goto out;
1740		}
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);
1746			r = 0;
1747			goto out;
1748		} else if (sid_match) {
1749			error_f("session ID recorded against different key "
1750			    "for %s %s", sshkey_type(key), fp);
1751			r = -1;
1752			goto out;
1753		}
1754		/*
1755		 * new sid with previously-seen key can happen, e.g. multiple
1756		 * connections to the same host.
1757		 */
1758	}
1759	/* record new key/sid */
1760	if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) {
1761		error_f("too many session IDs recorded");
1762		goto out;
1763	}
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");
1777	/* success */
1778	r = 0;
1779 out:
1780	free(fp);
1781	sshkey_free(key);
1782	sshbuf_free(sid);
1783	sshbuf_free(sig);
1784	return r == 0 ? 1 : 0;
1785}
1786
1787static void
1788process_extension(SocketEntry *e)
1789{
1790	int r, success = 0;
1791	char *name;
1792
1793	debug2_f("entering");
1794	if ((r = sshbuf_get_cstring(e->request, &name, NULL)) != 0) {
1795		error_fr(r, "parse");
1796		goto send;
1797	}
1798	if (strcmp(name, "session-bind@openssh.com") == 0)
1799		success = process_ext_session_bind(e);
1800	else
1801		debug_f("unsupported extension \"%s\"", name);
1802	free(name);
1803send:
1804	send_status(e, success);
1805}
1806/*
1807 * dispatch incoming message.
1808 * returns 1 on success, 0 for incomplete messages or -1 on error.
1809 */
1810static int
1811process_message(u_int socknum)
1812{
1813	u_int msg_len;
1814	u_char type;
1815	const u_char *cp;
1816	int r;
1817	SocketEntry *e;
1818
1819	if (socknum >= sockets_alloc)
1820		fatal_f("sock %u >= allocated %u", socknum, sockets_alloc);
1821	e = &sockets[socknum];
1822
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);
1830		return -1;
1831	}
1832	if (sshbuf_len(e->input) < msg_len + 4)
1833		return 0;		/* Incomplete message body. */
1834
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");
1842			return -1;
1843		}
1844		fatal_fr(r, "parse");
1845	}
1846
1847	debug_f("socket %u (fd=%d) type %d", socknum, e->fd, type);
1848
1849	/* check whether agent is locked */
1850	if (locked && type != SSH_AGENTC_UNLOCK) {
1851		sshbuf_reset(e->request);
1852		switch (type) {
1853		case SSH2_AGENTC_REQUEST_IDENTITIES:
1854			/* send empty lists */
1855			no_identities(e);
1856			break;
1857		default:
1858			/* send a fail message for all other request types */
1859			send_status(e, 0);
1860		}
1861		return 1;
1862	}
1863
1864	switch (type) {
1865	case SSH_AGENTC_LOCK:
1866	case SSH_AGENTC_UNLOCK:
1867		process_lock_agent(e, type == SSH_AGENTC_LOCK);
1868		break;
1869	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
1870		process_remove_all_identities(e); /* safe for !WITH_SSH1 */
1871		break;
1872	/* ssh2 */
1873	case SSH2_AGENTC_SIGN_REQUEST:
1874		process_sign_request2(e);
1875		break;
1876	case SSH2_AGENTC_REQUEST_IDENTITIES:
1877		process_request_identities(e);
1878		break;
1879	case SSH2_AGENTC_ADD_IDENTITY:
1880	case SSH2_AGENTC_ADD_ID_CONSTRAINED:
1881		process_add_identity(e);
1882		break;
1883	case SSH2_AGENTC_REMOVE_IDENTITY:
1884		process_remove_identity(e);
1885		break;
1886	case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
1887		process_remove_all_identities(e);
1888		break;
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);
1893		break;
1894	case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
1895		process_remove_smartcard_key(e);
1896		break;
1897#endif /* ENABLE_PKCS11 */
1898	case SSH_AGENTC_EXTENSION:
1899		process_extension(e);
1900		break;
1901	default:
1902		/* Unknown message.  Respond with failure. */
1903		error("Unknown message %d", type);
1904		sshbuf_reset(e->request);
1905		send_status(e, 0);
1906		break;
1907	}
1908	return 1;
1909}
1910
1911static void
1912new_socket(sock_type type, int fd)
1913{
1914	u_int i, old_alloc, new_alloc;
1915
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);
1920		++xcount;
1921	}
1922	set_nonblock(fd);
1923
1924	if (fd > max_fd)
1925		max_fd = fd;
1926
1927	for (i = 0; i < sockets_alloc; i++)
1928		if (sockets[i].type == AUTH_UNUSED) {
1929			sockets[i].fd = fd;
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;
1935			return;
1936		}
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;
1950}
1951
1952static int
1953handle_socket_read(u_int socknum)
1954{
1955	struct sockaddr_un sunaddr;
1956	socklen_t slen;
1957	uid_t euid;
1958	gid_t egid;
1959	int fd;
1960
1961	slen = sizeof(sunaddr);
1962	fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen);
1963	if (fd == -1) {
1964		error("accept from AUTH_SOCKET: %s", strerror(errno));
1965		return -1;
1966	}
1967	if (getpeereid(fd, &euid, &egid) == -1) {
1968		error("getpeereid %d failed: %s", fd, strerror(errno));
1969		close(fd);
1970		return -1;
1971	}
1972	if ((euid != 0) && (getuid() != euid)) {
1973		error("uid mismatch: peer euid %u != uid %u",
1974		    (u_int) euid, (u_int) getuid());
1975		close(fd);
1976		return -1;
1977	}
1978	new_socket(AUTH_CONNECTION, fd);
1979	return 0;
1980}
1981
1982static int
1983handle_conn_read(u_int socknum)
1984{
1985	char buf[AGENT_RBUF_LEN];
1986	ssize_t len;
1987	int r;
1988
1989	if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) {
1990		if (len == -1) {
1991			if (errno == EAGAIN || errno == EINTR)
1992				return 0;
1993			error_f("read error on socket %u (fd %d): %s",
1994			    socknum, sockets[socknum].fd, strerror(errno));
1995		}
1996		return -1;
1997	}
1998	if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0)
1999		fatal_fr(r, "compose");
2000	explicit_bzero(buf, sizeof(buf));
2001	for (;;) {
2002		if ((r = process_message(socknum)) == -1)
2003			return -1;
2004		else if (r == 0)
2005			break;
2006	}
2007	return 0;
2008}
2009
2010static int
2011handle_conn_write(u_int socknum)
2012{
2013	ssize_t len;
2014	int r;
2015
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) {
2021		if (len == -1) {
2022			if (errno == EAGAIN || errno == EINTR)
2023				return 0;
2024			error_f("read error on socket %u (fd %d): %s",
2025			    socknum, sockets[socknum].fd, strerror(errno));
2026		}
2027		return -1;
2028	}
2029	if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0)
2030		fatal_fr(r, "consume");
2031	return 0;
2032}
2033
2034static void
2035after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds)
2036{
2037	size_t i;
2038	u_int socknum, activefds = npfd;
2039
2040	for (i = 0; i < npfd; i++) {
2041		if (pfd[i].revents == 0)
2042			continue;
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)
2047				continue;
2048			if (pfd[i].fd == sockets[socknum].fd)
2049				break;
2050		}
2051		if (socknum >= sockets_alloc) {
2052			error_f("no socket for fd %d", pfd[i].fd);
2053			continue;
2054		}
2055		/* Process events */
2056		switch (sockets[socknum].type) {
2057		case AUTH_SOCKET:
2058			if ((pfd[i].revents & (POLLIN|POLLERR)) == 0)
2059				break;
2060			if (npfd > maxfds) {
2061				debug3("out of fds (active %u >= limit %u); "
2062				    "skipping accept", activefds, maxfds);
2063				break;
2064			}
2065			if (handle_socket_read(socknum) == 0)
2066				activefds++;
2067			break;
2068		case AUTH_CONNECTION:
2069			if ((pfd[i].revents & (POLLIN|POLLHUP|POLLERR)) != 0 &&
2070			    handle_conn_read(socknum) != 0)
2071				goto close_sock;
2072			if ((pfd[i].revents & (POLLOUT|POLLHUP)) != 0 &&
2073			    handle_conn_write(socknum) != 0) {
2074 close_sock:
2075				if (activefds == 0)
2076					fatal("activefds == 0 at close_sock");
2077				close_socket(&sockets[socknum]);
2078				activefds--;
2079				break;
2080			}
2081			break;
2082		default:
2083			break;
2084		}
2085	}
2086}
2087
2088static int
2089prepare_poll(struct pollfd **pfdp, size_t *npfdp, struct timespec *timeoutp, u_int maxfds)
2090{
2091	struct pollfd *pfd = *pfdp;
2092	size_t i, j, npfd = 0;
2093	time_t deadline;
2094	int r;
2095
2096	/* Count active sockets */
2097	for (i = 0; i < sockets_alloc; i++) {
2098		switch (sockets[i].type) {
2099		case AUTH_SOCKET:
2100		case AUTH_CONNECTION:
2101			npfd++;
2102			break;
2103		case AUTH_UNUSED:
2104			break;
2105		default:
2106			fatal("Unknown socket type %d", sockets[i].type);
2107			break;
2108		}
2109	}
2110	if (npfd != *npfdp &&
2111	    (pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL)
2112		fatal_f("recallocarray failed");
2113	*pfdp = pfd;
2114	*npfdp = npfd;
2115
2116	for (i = j = 0; i < sockets_alloc; i++) {
2117		switch (sockets[i].type) {
2118		case AUTH_SOCKET:
2119			if (npfd > maxfds) {
2120				debug3("out of fds (active %zu >= limit %u); "
2121				    "skipping arming listener", npfd, maxfds);
2122				break;
2123			}
2124			pfd[j].fd = sockets[i].fd;
2125			pfd[j].revents = 0;
2126			pfd[j].events = POLLIN;
2127			j++;
2128			break;
2129		case AUTH_CONNECTION:
2130			pfd[j].fd = sockets[i].fd;
2131			pfd[j].revents = 0;
2132			/*
2133			 * Only prepare to read if we can handle a full-size
2134			 * input read buffer and enqueue a max size reply..
2135			 */
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;
2145			j++;
2146			break;
2147		default:
2148			break;
2149		}
2150	}
2151	deadline = reaper();
2152	if (parent_alive_interval != 0)
2153		deadline = (deadline == 0) ? parent_alive_interval :
2154		    MINIMUM(deadline, parent_alive_interval);
2155	if (deadline != 0)
2156		ptimeout_deadline_sec(timeoutp, deadline);
2157	return (1);
2158}
2159
2160static void
2161cleanup_socket(void)
2162{
2163	if (cleanup_pid != 0 && getpid() != cleanup_pid)
2164		return;
2165	debug_f("cleanup");
2166	if (socket_name[0])
2167		unlink(socket_name);
2168	if (socket_dir[0])
2169		rmdir(socket_dir);
2170}
2171
2172void
2173cleanup_exit(int i)
2174{
2175	cleanup_socket();
2176#ifdef ENABLE_PKCS11
2177	pkcs11_terminate();
2178#endif
2179	_exit(i);
2180}
2181
2182static void
2183cleanup_handler(int sig)
2184{
2185	signalled = sig;
2186}
2187
2188static void
2189check_parent_exists(void)
2190{
2191	/*
2192	 * If our parent has exited then getppid() will return (pid_t)1,
2193	 * so testing for that should be safe.
2194	 */
2195	if (parent_pid != -1 && getppid() != parent_pid) {
2196		/* printf("Parent has died - Authentication agent exiting.\n"); */
2197		cleanup_socket();
2198		_exit(2);
2199	}
2200}
2201
2202static void
2203usage(void)
2204{
2205	fprintf(stderr,
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");
2211	exit(1);
2212}
2213
2214int
2215main(int ac, char **av)
2216{
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
2221	struct rlimit rlim;
2222#endif
2223	extern int optind;
2224	extern char *optarg;
2225	pid_t pid;
2226	char pidstrbuf[1 + 3 * sizeof pid];
2227	size_t len;
2228	mode_t prev_mask;
2229	struct timespec timeout;
2230	struct pollfd *pfd = NULL;
2231	size_t npfd = 0;
2232	u_int maxfds;
2233	sigset_t nsigset, osigset;
2234
2235	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2236	sanitise_stdfd();
2237
2238	/* drop */
2239	(void)setegid(getgid());
2240	(void)setgid(getgid());
2241	setuid(geteuid());
2242
2243	platform_disable_tracing(0);	/* strict=no */
2244
2245#ifdef RLIMIT_NOFILE
2246	if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
2247		fatal("%s: getrlimit: %s", __progname, strerror(errno));
2248#endif
2249
2250	__progname = ssh_get_progname(av[0]);
2251	seed_rng();
2252
2253	while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:x")) != -1) {
2254		switch (ch) {
2255		case 'E':
2256			fingerprint_hash = ssh_digest_alg_by_name(optarg);
2257			if (fingerprint_hash == -1)
2258				fatal("Invalid hash algorithm \"%s\"", optarg);
2259			break;
2260		case 'c':
2261			if (s_flag)
2262				usage();
2263			c_flag++;
2264			break;
2265		case 'k':
2266			k_flag++;
2267			break;
2268		case 'O':
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
2274				fatal("Unknown -O option");
2275			break;
2276		case 'P':
2277			if (allowed_providers != NULL)
2278				fatal("-P option already specified");
2279			allowed_providers = xstrdup(optarg);
2280			break;
2281		case 's':
2282			if (c_flag)
2283				usage();
2284			s_flag++;
2285			break;
2286		case 'd':
2287			if (d_flag || D_flag)
2288				usage();
2289			d_flag++;
2290			break;
2291		case 'D':
2292			if (d_flag || D_flag)
2293				usage();
2294			D_flag++;
2295			break;
2296		case 'a':
2297			agentsocket = optarg;
2298			break;
2299		case 't':
2300			if ((lifetime = convtime(optarg)) == -1) {
2301				fprintf(stderr, "Invalid lifetime\n");
2302				usage();
2303			}
2304			break;
2305		case 'x':
2306			xcount = 0;
2307			break;
2308		default:
2309			usage();
2310		}
2311	}
2312	ac -= optind;
2313	av += optind;
2314
2315	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag))
2316		usage();
2317
2318	if (allowed_providers == NULL)
2319		allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS);
2320
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)
2325			c_flag = 1;
2326	}
2327	if (k_flag) {
2328		const char *errstr = NULL;
2329
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);
2334			exit(1);
2335		}
2336		pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr);
2337		if (errstr) {
2338			fprintf(stderr,
2339			    "%s=\"%s\", which is not a good PID: %s\n",
2340			    SSH_AGENTPID_ENV_NAME, pidstr, errstr);
2341			exit(1);
2342		}
2343		if (kill(pid, SIGTERM) == -1) {
2344			perror("kill");
2345			exit(1);
2346		}
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);
2351		exit(0);
2352	}
2353
2354	/*
2355	 * Minimum file descriptors:
2356	 * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) +
2357	 * a few spare for libc / stack protectors / sanitisers, etc.
2358	 */
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;
2364
2365	parent_pid = getpid();
2366
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");
2372			exit(1);
2373		}
2374		snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
2375		    (long)parent_pid);
2376	} else {
2377		/* Try to use specified agent socket */
2378		socket_dir[0] = '\0';
2379		strlcpy(socket_name, agentsocket, sizeof socket_name);
2380	}
2381
2382	/*
2383	 * Create socket early so it will exist before command gets run from
2384	 * the parent.
2385	 */
2386	prev_mask = umask(0177);
2387	sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0);
2388	if (sock < 0) {
2389		/* XXX - unix_listener() calls error() not perror() */
2390		*socket_name = '\0'; /* Don't unlink any existing file */
2391		cleanup_exit(1);
2392	}
2393	umask(prev_mask);
2394
2395	/*
2396	 * Fork, and have the parent execute the command, if any, or present
2397	 * the socket data.  The child continues as the authentication agent.
2398	 */
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);
2407		fflush(stdout);
2408		goto skip;
2409	}
2410	pid = fork();
2411	if (pid == -1) {
2412		perror("fork");
2413		cleanup_exit(1);
2414	}
2415	if (pid != 0) {		/* Parent - execute the given command. */
2416		close(sock);
2417		snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
2418		if (ac == 0) {
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);
2425			exit(0);
2426		}
2427		if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
2428		    setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
2429			perror("setenv");
2430			exit(1);
2431		}
2432		execvp(av[0], av);
2433		perror(av[0]);
2434		exit(1);
2435	}
2436	/* child */
2437	log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
2438
2439	if (setsid() == -1) {
2440		error("setsid: %s", strerror(errno));
2441		cleanup_exit(1);
2442	}
2443
2444	(void)chdir("/");
2445	if (stdfd_devnull(1, 1, 1) == -1)
2446		error_f("stdfd_devnull failed");
2447
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));
2453		cleanup_exit(1);
2454	}
2455#endif
2456
2457skip:
2458
2459	cleanup_pid = getpid();
2460
2461#ifdef ENABLE_PKCS11
2462	pkcs11_init(0);
2463#endif
2464	new_socket(AUTH_SOCKET, sock);
2465	if (ac > 0)
2466		parent_alive_interval = 10;
2467	idtab_init();
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);
2472
2473	sigemptyset(&nsigset);
2474	sigaddset(&nsigset, SIGINT);
2475	sigaddset(&nsigset, SIGHUP);
2476	sigaddset(&nsigset, SIGTERM);
2477
2478	if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1)
2479		fatal("%s: pledge: %s", __progname, strerror(errno));
2480	platform_pledge_agent();
2481
2482	while (1) {
2483		sigprocmask(SIG_BLOCK, &nsigset, &osigset);
2484		if (signalled != 0) {
2485			logit("exiting on signal %d", (int)signalled);
2486			cleanup_exit(2);
2487		}
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 */
2496		if (result == -1) {
2497			if (saved_errno == EINTR)
2498				continue;
2499			fatal("poll: %s", strerror(saved_errno));
2500		} else if (result > 0)
2501			after_poll(pfd, npfd, maxfds);
2502	}
2503	/* NOTREACHED */
2504}
2505