1/*	$NetBSD: ssh-agent.c,v 1.37 2023/12/20 17:15:21 christos Exp $	*/
2/* $OpenBSD: ssh-agent.c,v 1.303 2023/12/18 14:48:08 djm Exp $ */
3
4/*
5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
6 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
7 *                    All rights reserved
8 * The authentication agent program.
9 *
10 * As far as I am concerned, the code I have written for this software
11 * can be used freely for any purpose.  Any derived versions of this
12 * software must be clearly marked as such, and if the derived work is
13 * incompatible with the protocol description in the RFC file, it must be
14 * called by a name other than "ssh" or "Secure Shell".
15 *
16 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include "includes.h"
40__RCSID("$NetBSD: ssh-agent.c,v 1.37 2023/12/20 17:15:21 christos Exp $");
41
42#include <sys/param.h>	/* MIN MAX */
43#include <sys/types.h>
44#include <sys/time.h>
45#include <sys/queue.h>
46#include <sys/resource.h>
47#include <sys/socket.h>
48#include <sys/stat.h>
49#include <sys/un.h>
50#include <sys/wait.h>
51
52#ifdef WITH_OPENSSL
53#include <openssl/evp.h>
54#endif
55
56#include <errno.h>
57#include <fcntl.h>
58#include <paths.h>
59#include <poll.h>
60#include <signal.h>
61#include <stdlib.h>
62#include <stdio.h>
63#include <string.h>
64#include <stdarg.h>
65#include <limits.h>
66#include <time.h>
67#include <unistd.h>
68#include <util.h>
69
70#include "xmalloc.h"
71#include "ssh.h"
72#include "ssh2.h"
73#include "sshbuf.h"
74#include "sshkey.h"
75#include "authfd.h"
76#include "log.h"
77#include "misc.h"
78#include "getpeereid.h"
79#include "digest.h"
80#include "ssherr.h"
81#include "match.h"
82#include "msg.h"
83#include "pathnames.h"
84#include "ssh-pkcs11.h"
85#include "sk-api.h"
86#include "myproposal.h"
87
88#ifndef DEFAULT_ALLOWED_PROVIDERS
89# define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/pkg/lib*/*"
90#endif
91
92/* Maximum accepted message length */
93#define AGENT_MAX_LEN		(256*1024)
94/* Maximum bytes to read from client socket */
95#define AGENT_RBUF_LEN		(4096)
96/* Maximum number of recorded session IDs/hostkeys per connection */
97#define AGENT_MAX_SESSION_IDS		16
98/* Maximum size of session ID */
99#define AGENT_MAX_SID_LEN		128
100/* Maximum number of destination constraints to accept on a key */
101#define AGENT_MAX_DEST_CONSTRAINTS	1024
102/* Maximum number of associated certificate constraints to accept on a key */
103#define AGENT_MAX_EXT_CERTS		1024
104
105/* XXX store hostkey_sid in a refcounted tree */
106
107typedef enum {
108	AUTH_UNUSED = 0,
109	AUTH_SOCKET = 1,
110	AUTH_CONNECTION = 2,
111} sock_type;
112
113struct hostkey_sid {
114	struct sshkey *key;
115	struct sshbuf *sid;
116	int forwarded;
117};
118
119typedef struct socket_entry {
120	int fd;
121	sock_type type;
122	struct sshbuf *input;
123	struct sshbuf *output;
124	struct sshbuf *request;
125	size_t nsession_ids;
126	struct hostkey_sid *session_ids;
127	int session_bind_attempted;
128} SocketEntry;
129
130u_int sockets_alloc = 0;
131SocketEntry *sockets = NULL;
132
133typedef struct identity {
134	TAILQ_ENTRY(identity) next;
135	struct sshkey *key;
136	char *comment;
137	char *provider;
138	time_t death;
139	u_int confirm;
140	char *sk_provider;
141	struct dest_constraint *dest_constraints;
142	size_t ndest_constraints;
143} Identity;
144
145struct idtable {
146	int nentries;
147	TAILQ_HEAD(idqueue, identity) idlist;
148};
149
150/* private key table */
151struct idtable *idtab;
152
153int max_fd = 0;
154
155/* pid of shell == parent of agent */
156pid_t parent_pid = -1;
157time_t parent_alive_interval = 0;
158
159/* pid of process for which cleanup_socket is applicable */
160pid_t cleanup_pid = 0;
161
162/* pathname and directory for AUTH_SOCKET */
163char socket_name[PATH_MAX];
164char socket_dir[PATH_MAX];
165
166/* Pattern-list of allowed PKCS#11/Security key paths */
167static char *allowed_providers;
168
169/*
170 * Allows PKCS11 providers or SK keys that use non-internal providers to
171 * be added over a remote connection (identified by session-bind@openssh.com).
172 */
173static int remote_add_provider;
174
175/* locking */
176#define LOCK_SIZE	32
177#define LOCK_SALT_SIZE	16
178#define LOCK_ROUNDS	1
179int locked = 0;
180u_char lock_pwhash[LOCK_SIZE];
181u_char lock_salt[LOCK_SALT_SIZE];
182
183extern char *__progname;
184
185/* Default lifetime in seconds (0 == forever) */
186static int lifetime = 0;
187
188static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
189
190/* Refuse signing of non-SSH messages for web-origin FIDO keys */
191static int restrict_websafe = 1;
192
193static void
194close_socket(SocketEntry *e)
195{
196	size_t i;
197
198	close(e->fd);
199	sshbuf_free(e->input);
200	sshbuf_free(e->output);
201	sshbuf_free(e->request);
202	for (i = 0; i < e->nsession_ids; i++) {
203		sshkey_free(e->session_ids[i].key);
204		sshbuf_free(e->session_ids[i].sid);
205	}
206	free(e->session_ids);
207	memset(e, '\0', sizeof(*e));
208	e->fd = -1;
209	e->type = AUTH_UNUSED;
210}
211
212static void
213idtab_init(void)
214{
215	idtab = xcalloc(1, sizeof(*idtab));
216	TAILQ_INIT(&idtab->idlist);
217	idtab->nentries = 0;
218}
219
220static void
221free_dest_constraint_hop(struct dest_constraint_hop *dch)
222{
223	u_int i;
224
225	if (dch == NULL)
226		return;
227	free(dch->user);
228	free(dch->hostname);
229	for (i = 0; i < dch->nkeys; i++)
230		sshkey_free(dch->keys[i]);
231	free(dch->keys);
232	free(dch->key_is_ca);
233}
234
235static void
236free_dest_constraints(struct dest_constraint *dcs, size_t ndcs)
237{
238	size_t i;
239
240	for (i = 0; i < ndcs; i++) {
241		free_dest_constraint_hop(&dcs[i].from);
242		free_dest_constraint_hop(&dcs[i].to);
243	}
244	free(dcs);
245}
246
247static void
248dup_dest_constraint_hop(const struct dest_constraint_hop *dch,
249    struct dest_constraint_hop *out)
250{
251	u_int i;
252	int r;
253
254	out->user = dch->user == NULL ? NULL : xstrdup(dch->user);
255	out->hostname = dch->hostname == NULL ? NULL : xstrdup(dch->hostname);
256	out->is_ca = dch->is_ca;
257	out->nkeys = dch->nkeys;
258	out->keys = out->nkeys == 0 ? NULL :
259	    xcalloc(out->nkeys, sizeof(*out->keys));
260	out->key_is_ca = out->nkeys == 0 ? NULL :
261	    xcalloc(out->nkeys, sizeof(*out->key_is_ca));
262	for (i = 0; i < dch->nkeys; i++) {
263		if (dch->keys[i] != NULL &&
264		    (r = sshkey_from_private(dch->keys[i],
265		    &(out->keys[i]))) != 0)
266			fatal_fr(r, "copy key");
267		out->key_is_ca[i] = dch->key_is_ca[i];
268	}
269}
270
271static struct dest_constraint *
272dup_dest_constraints(const struct dest_constraint *dcs, size_t ndcs)
273{
274	size_t i;
275	struct dest_constraint *ret;
276
277	if (ndcs == 0)
278		return NULL;
279	ret = xcalloc(ndcs, sizeof(*ret));
280	for (i = 0; i < ndcs; i++) {
281		dup_dest_constraint_hop(&dcs[i].from, &ret[i].from);
282		dup_dest_constraint_hop(&dcs[i].to, &ret[i].to);
283	}
284	return ret;
285}
286
287#ifdef DEBUG_CONSTRAINTS
288static void
289dump_dest_constraint_hop(const struct dest_constraint_hop *dch)
290{
291	u_int i;
292	char *fp;
293
294	debug_f("user %s hostname %s is_ca %d nkeys %u",
295	    dch->user == NULL ? "(null)" : dch->user,
296	    dch->hostname == NULL ? "(null)" : dch->hostname,
297	    dch->is_ca, dch->nkeys);
298	for (i = 0; i < dch->nkeys; i++) {
299		fp = NULL;
300		if (dch->keys[i] != NULL &&
301		    (fp = sshkey_fingerprint(dch->keys[i],
302		    SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL)
303			fatal_f("fingerprint failed");
304		debug_f("key %u/%u: %s%s%s key_is_ca %d", i, dch->nkeys,
305		    dch->keys[i] == NULL ? "" : sshkey_ssh_name(dch->keys[i]),
306		    dch->keys[i] == NULL ? "" : " ",
307		    dch->keys[i] == NULL ? "none" : fp,
308		    dch->key_is_ca[i]);
309		free(fp);
310	}
311}
312#endif /* DEBUG_CONSTRAINTS */
313
314static void
315dump_dest_constraints(const char *context,
316    const struct dest_constraint *dcs, size_t ndcs)
317{
318#ifdef DEBUG_CONSTRAINTS
319	size_t i;
320
321	debug_f("%s: %zu constraints", context, ndcs);
322	for (i = 0; i < ndcs; i++) {
323		debug_f("constraint %zu / %zu: from: ", i, ndcs);
324		dump_dest_constraint_hop(&dcs[i].from);
325		debug_f("constraint %zu / %zu: to: ", i, ndcs);
326		dump_dest_constraint_hop(&dcs[i].to);
327	}
328	debug_f("done for %s", context);
329#endif /* DEBUG_CONSTRAINTS */
330}
331
332static void
333free_identity(Identity *id)
334{
335	sshkey_free(id->key);
336	free(id->provider);
337	free(id->comment);
338	free(id->sk_provider);
339	free_dest_constraints(id->dest_constraints, id->ndest_constraints);
340	free(id);
341}
342
343/*
344 * Match 'key' against the key/CA list in a destination constraint hop
345 * Returns 0 on success or -1 otherwise.
346 */
347static int
348match_key_hop(const char *tag, const struct sshkey *key,
349    const struct dest_constraint_hop *dch)
350{
351	const char *reason = NULL;
352	const char *hostname = dch->hostname ? dch->hostname : "(ORIGIN)";
353	u_int i;
354	char *fp;
355
356	if (key == NULL)
357		return -1;
358	/* XXX logspam */
359	if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
360	    SSH_FP_DEFAULT)) == NULL)
361		fatal_f("fingerprint failed");
362	debug3_f("%s: entering hostname %s, requested key %s %s, %u keys avail",
363	    tag, hostname, sshkey_type(key), fp, dch->nkeys);
364	free(fp);
365	for (i = 0; i < dch->nkeys; i++) {
366		if (dch->keys[i] == NULL)
367			return -1;
368		/* XXX logspam */
369		if ((fp = sshkey_fingerprint(dch->keys[i], SSH_FP_HASH_DEFAULT,
370		    SSH_FP_DEFAULT)) == NULL)
371			fatal_f("fingerprint failed");
372		debug3_f("%s: key %u: %s%s %s", tag, i,
373		    dch->key_is_ca[i] ? "CA " : "",
374		    sshkey_type(dch->keys[i]), fp);
375		free(fp);
376		if (!sshkey_is_cert(key)) {
377			/* plain key */
378			if (dch->key_is_ca[i] ||
379			    !sshkey_equal(key, dch->keys[i]))
380				continue;
381			return 0;
382		}
383		/* certificate */
384		if (!dch->key_is_ca[i])
385			continue;
386		if (key->cert == NULL || key->cert->signature_key == NULL)
387			return -1; /* shouldn't happen */
388		if (!sshkey_equal(key->cert->signature_key, dch->keys[i]))
389			continue;
390		if (sshkey_cert_check_host(key, hostname, 1,
391		    SSH_ALLOWED_CA_SIGALGS, &reason) != 0) {
392			debug_f("cert %s / hostname %s rejected: %s",
393			    key->cert->key_id, hostname, reason);
394			continue;
395		}
396		return 0;
397	}
398	return -1;
399}
400
401/* Check destination constraints on an identity against the hostkey/user */
402static int
403permitted_by_dest_constraints(const struct sshkey *fromkey,
404    const struct sshkey *tokey, Identity *id, const char *user,
405    const char **hostnamep)
406{
407	size_t i;
408	struct dest_constraint *d;
409
410	if (hostnamep != NULL)
411		*hostnamep = NULL;
412	for (i = 0; i < id->ndest_constraints; i++) {
413		d = id->dest_constraints + i;
414		/* XXX remove logspam */
415		debug2_f("constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)",
416		    i, d->from.user ? d->from.user : "",
417		    d->from.user ? "@" : "",
418		    d->from.hostname ? d->from.hostname : "(ORIGIN)",
419		    d->from.nkeys,
420		    d->to.user ? d->to.user : "", d->to.user ? "@" : "",
421		    d->to.hostname ? d->to.hostname : "(ANY)", d->to.nkeys);
422
423		/* Match 'from' key */
424		if (fromkey == NULL) {
425			/* We are matching the first hop */
426			if (d->from.hostname != NULL || d->from.nkeys != 0)
427				continue;
428		} else if (match_key_hop("from", fromkey, &d->from) != 0)
429			continue;
430
431		/* Match 'to' key */
432		if (tokey != NULL && match_key_hop("to", tokey, &d->to) != 0)
433			continue;
434
435		/* Match user if specified */
436		if (d->to.user != NULL && user != NULL &&
437		    !match_pattern(user, d->to.user))
438			continue;
439
440		/* successfully matched this constraint */
441		if (hostnamep != NULL)
442			*hostnamep = d->to.hostname;
443		debug2_f("allowed for hostname %s",
444		    d->to.hostname == NULL ? "*" : d->to.hostname);
445		return 0;
446	}
447	/* no match */
448	debug2_f("%s identity \"%s\" not permitted for this destination",
449	    sshkey_type(id->key), id->comment);
450	return -1;
451}
452
453/*
454 * Check whether hostkeys on a SocketEntry and the optionally specified user
455 * are permitted by the destination constraints on the Identity.
456 * Returns 0 on success or -1 otherwise.
457 */
458static int
459identity_permitted(Identity *id, SocketEntry *e, char *user,
460    const char **forward_hostnamep, const char **last_hostnamep)
461{
462	size_t i;
463	const char **hp;
464	struct hostkey_sid *hks;
465	const struct sshkey *fromkey = NULL;
466	const char *test_user;
467	char *fp1, *fp2;
468
469	/* XXX remove logspam */
470	debug3_f("entering: key %s comment \"%s\", %zu socket bindings, "
471	    "%zu constraints", sshkey_type(id->key), id->comment,
472	    e->nsession_ids, id->ndest_constraints);
473	if (id->ndest_constraints == 0)
474		return 0; /* unconstrained */
475	if (e->session_bind_attempted && e->nsession_ids == 0) {
476		error_f("previous session bind failed on socket");
477		return -1;
478	}
479	if (e->nsession_ids == 0)
480		return 0; /* local use */
481	/*
482	 * Walk through the hops recorded by session_id and try to find a
483	 * constraint that satisfies each.
484	 */
485	for (i = 0; i < e->nsession_ids; i++) {
486		hks = e->session_ids + i;
487		if (hks->key == NULL)
488			fatal_f("internal error: no bound key");
489		/* XXX remove logspam */
490		fp1 = fp2 = NULL;
491		if (fromkey != NULL &&
492		    (fp1 = sshkey_fingerprint(fromkey, SSH_FP_HASH_DEFAULT,
493		    SSH_FP_DEFAULT)) == NULL)
494			fatal_f("fingerprint failed");
495		if ((fp2 = sshkey_fingerprint(hks->key, SSH_FP_HASH_DEFAULT,
496		    SSH_FP_DEFAULT)) == NULL)
497			fatal_f("fingerprint failed");
498		debug3_f("socketentry fd=%d, entry %zu %s, "
499		    "from hostkey %s %s to user %s hostkey %s %s",
500		    e->fd, i, hks->forwarded ? "FORWARD" : "AUTH",
501		    fromkey ? sshkey_type(fromkey) : "(ORIGIN)",
502		    fromkey ? fp1 : "", user ? user : "(ANY)",
503		    sshkey_type(hks->key), fp2);
504		free(fp1);
505		free(fp2);
506		/*
507		 * Record the hostnames for the initial forwarding and
508		 * the final destination.
509		 */
510		hp = NULL;
511		if (i == e->nsession_ids - 1)
512			hp = last_hostnamep;
513		else if (i == 0)
514			hp = forward_hostnamep;
515		/* Special handling for final recorded binding */
516		test_user = NULL;
517		if (i == e->nsession_ids - 1) {
518			/* Can only check user at final hop */
519			test_user = user;
520			/*
521			 * user is only presented for signature requests.
522			 * If this is the case, make sure last binding is not
523			 * for a forwarding.
524			 */
525			if (hks->forwarded && user != NULL) {
526				error_f("tried to sign on forwarding hop");
527				return -1;
528			}
529		} else if (!hks->forwarded) {
530			error_f("tried to forward though signing bind");
531			return -1;
532		}
533		if (permitted_by_dest_constraints(fromkey, hks->key, id,
534		    test_user, hp) != 0)
535			return -1;
536		fromkey = hks->key;
537	}
538	/*
539	 * Another special case: if the last bound session ID was for a
540	 * forwarding, and this function is not being called to check a sign
541	 * request (i.e. no 'user' supplied), then only permit the key if
542	 * there is a permission that would allow it to be used at another
543	 * destination. This hides keys that are allowed to be used to
544	 * authenticate *to* a host but not permitted for *use* beyond it.
545	 */
546	hks = &e->session_ids[e->nsession_ids - 1];
547	if (hks->forwarded && user == NULL &&
548	    permitted_by_dest_constraints(hks->key, NULL, id,
549	    NULL, NULL) != 0) {
550		debug3_f("key permitted at host but not after");
551		return -1;
552	}
553
554	/* success */
555	return 0;
556}
557
558static int
559socket_is_remote(SocketEntry *e)
560{
561	return e->session_bind_attempted || (e->nsession_ids != 0);
562}
563
564/* return matching private key for given public key */
565static Identity *
566lookup_identity(struct sshkey *key)
567{
568	Identity *id;
569
570	TAILQ_FOREACH(id, &idtab->idlist, next) {
571		if (sshkey_equal(key, id->key))
572			return (id);
573	}
574	return (NULL);
575}
576
577/* Check confirmation of keysign request */
578static int
579confirm_key(Identity *id, const char *extra)
580{
581	char *p;
582	int ret = -1;
583
584	p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT);
585	if (p != NULL &&
586	    ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s",
587	    id->comment, p,
588	    extra == NULL ? "" : "\n", extra == NULL ? "" : extra))
589		ret = 0;
590	free(p);
591
592	return (ret);
593}
594
595static void
596send_status(SocketEntry *e, int success)
597{
598	int r;
599
600	if ((r = sshbuf_put_u32(e->output, 1)) != 0 ||
601	    (r = sshbuf_put_u8(e->output, success ?
602	    SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
603		fatal_fr(r, "compose");
604}
605
606/* send list of supported public keys to 'client' */
607static void
608process_request_identities(SocketEntry *e)
609{
610	Identity *id;
611	struct sshbuf *msg, *keys;
612	int r;
613	u_int i = 0, nentries = 0;
614	char *fp;
615
616	debug2_f("entering");
617
618	if ((msg = sshbuf_new()) == NULL || (keys = sshbuf_new()) == NULL)
619		fatal_f("sshbuf_new failed");
620	TAILQ_FOREACH(id, &idtab->idlist, next) {
621		if ((fp = sshkey_fingerprint(id->key, SSH_FP_HASH_DEFAULT,
622		    SSH_FP_DEFAULT)) == NULL)
623			fatal_f("fingerprint failed");
624		debug_f("key %u / %u: %s %s", i++, idtab->nentries,
625		    sshkey_ssh_name(id->key), fp);
626		dump_dest_constraints(__func__,
627		    id->dest_constraints, id->ndest_constraints);
628		free(fp);
629		/* identity not visible, don't include in response */
630		if (identity_permitted(id, e, NULL, NULL, NULL) != 0)
631			continue;
632		if ((r = sshkey_puts_opts(id->key, keys,
633		    SSHKEY_SERIALIZE_INFO)) != 0 ||
634		    (r = sshbuf_put_cstring(keys, id->comment)) != 0) {
635			error_fr(r, "compose key/comment");
636			continue;
637		}
638		nentries++;
639	}
640	debug2_f("replying with %u allowed of %u available keys",
641	    nentries, idtab->nentries);
642	if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
643	    (r = sshbuf_put_u32(msg, nentries)) != 0 ||
644	    (r = sshbuf_putb(msg, keys)) != 0)
645		fatal_fr(r, "compose");
646	if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
647		fatal_fr(r, "enqueue");
648	sshbuf_free(msg);
649	sshbuf_free(keys);
650}
651
652
653static const char *
654agent_decode_alg(struct sshkey *key, u_int flags)
655{
656	if (key->type == KEY_RSA) {
657		if (flags & SSH_AGENT_RSA_SHA2_256)
658			return "rsa-sha2-256";
659		else if (flags & SSH_AGENT_RSA_SHA2_512)
660			return "rsa-sha2-512";
661	} else if (key->type == KEY_RSA_CERT) {
662		if (flags & SSH_AGENT_RSA_SHA2_256)
663			return "rsa-sha2-256-cert-v01@openssh.com";
664		else if (flags & SSH_AGENT_RSA_SHA2_512)
665			return "rsa-sha2-512-cert-v01@openssh.com";
666	}
667	return NULL;
668}
669
670/*
671 * Attempt to parse the contents of a buffer as a SSH publickey userauth
672 * request, checking its contents for consistency and matching the embedded
673 * key against the one that is being used for signing.
674 * Note: does not modify msg buffer.
675 * Optionally extract the username, session ID and/or hostkey from the request.
676 */
677static int
678parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
679    char **userp, struct sshbuf **sess_idp, struct sshkey **hostkeyp)
680{
681	struct sshbuf *b = NULL, *sess_id = NULL;
682	char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL;
683	int r;
684	u_char t, sig_follows;
685	struct sshkey *mkey = NULL, *hostkey = NULL;
686
687	if (userp != NULL)
688		*userp = NULL;
689	if (sess_idp != NULL)
690		*sess_idp = NULL;
691	if (hostkeyp != NULL)
692		*hostkeyp = NULL;
693	if ((b = sshbuf_fromb(msg)) == NULL)
694		fatal_f("sshbuf_fromb");
695
696	/* SSH userauth request */
697	if ((r = sshbuf_froms(b, &sess_id)) != 0)
698		goto out;
699	if (sshbuf_len(sess_id) == 0) {
700		r = SSH_ERR_INVALID_FORMAT;
701		goto out;
702	}
703	if ((r = sshbuf_get_u8(b, &t)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */
704	    (r = sshbuf_get_cstring(b, &user, NULL)) != 0 || /* server user */
705	    (r = sshbuf_get_cstring(b, &service, NULL)) != 0 || /* service */
706	    (r = sshbuf_get_cstring(b, &method, NULL)) != 0 || /* method */
707	    (r = sshbuf_get_u8(b, &sig_follows)) != 0 || /* sig-follows */
708	    (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || /* alg */
709	    (r = sshkey_froms(b, &mkey)) != 0) /* key */
710		goto out;
711	if (t != SSH2_MSG_USERAUTH_REQUEST ||
712	    sig_follows != 1 ||
713	    strcmp(service, "ssh-connection") != 0 ||
714	    !sshkey_equal(expected_key, mkey) ||
715	    sshkey_type_from_name(pkalg) != expected_key->type) {
716		r = SSH_ERR_INVALID_FORMAT;
717		goto out;
718	}
719	if (strcmp(method, "publickey-hostbound-v00@openssh.com") == 0) {
720		if ((r = sshkey_froms(b, &hostkey)) != 0)
721			goto out;
722	} else if (strcmp(method, "publickey") != 0) {
723		r = SSH_ERR_INVALID_FORMAT;
724		goto out;
725	}
726	if (sshbuf_len(b) != 0) {
727		r = SSH_ERR_INVALID_FORMAT;
728		goto out;
729	}
730	/* success */
731	r = 0;
732	debug3_f("well formed userauth");
733	if (userp != NULL) {
734		*userp = user;
735		user = NULL;
736	}
737	if (sess_idp != NULL) {
738		*sess_idp = sess_id;
739		sess_id = NULL;
740	}
741	if (hostkeyp != NULL) {
742		*hostkeyp = hostkey;
743		hostkey = NULL;
744	}
745 out:
746	sshbuf_free(b);
747	sshbuf_free(sess_id);
748	free(user);
749	free(service);
750	free(method);
751	free(pkalg);
752	sshkey_free(mkey);
753	sshkey_free(hostkey);
754	return r;
755}
756
757/*
758 * Attempt to parse the contents of a buffer as a SSHSIG signature request.
759 * Note: does not modify buffer.
760 */
761static int
762parse_sshsig_request(struct sshbuf *msg)
763{
764	int r;
765	struct sshbuf *b;
766
767	if ((b = sshbuf_fromb(msg)) == NULL)
768		fatal_f("sshbuf_fromb");
769
770	if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) != 0 ||
771	    (r = sshbuf_consume(b, 6)) != 0 ||
772	    (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* namespace */
773	    (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || /* reserved */
774	    (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* hashalg */
775	    (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) /* H(msg) */
776		goto out;
777	if (sshbuf_len(b) != 0) {
778		r = SSH_ERR_INVALID_FORMAT;
779		goto out;
780	}
781	/* success */
782	r = 0;
783 out:
784	sshbuf_free(b);
785	return r;
786}
787
788/*
789 * This function inspects a message to be signed by a FIDO key that has a
790 * web-like application string (i.e. one that does not begin with "ssh:".
791 * It checks that the message is one of those expected for SSH operations
792 * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
793 * for the web.
794 */
795static int
796check_websafe_message_contents(struct sshkey *key, struct sshbuf *data)
797{
798	if (parse_userauth_request(data, key, NULL, NULL, NULL) == 0) {
799		debug_f("signed data matches public key userauth request");
800		return 1;
801	}
802	if (parse_sshsig_request(data) == 0) {
803		debug_f("signed data matches SSHSIG signature request");
804		return 1;
805	}
806
807	/* XXX check CA signature operation */
808
809	error("web-origin key attempting to sign non-SSH message");
810	return 0;
811}
812
813static int
814buf_equal(const struct sshbuf *a, const struct sshbuf *b)
815{
816	if (sshbuf_ptr(a) == NULL || sshbuf_ptr(b) == NULL)
817		return SSH_ERR_INVALID_ARGUMENT;
818	if (sshbuf_len(a) != sshbuf_len(b))
819		return SSH_ERR_INVALID_FORMAT;
820	if (timingsafe_bcmp(sshbuf_ptr(a), sshbuf_ptr(b), sshbuf_len(a)) != 0)
821		return SSH_ERR_INVALID_FORMAT;
822	return 0;
823}
824
825/* ssh2 only */
826static void
827process_sign_request2(SocketEntry *e)
828{
829	u_char *signature = NULL;
830	size_t slen = 0;
831	u_int compat = 0, flags;
832	int r, ok = -1, retried = 0;
833	char *fp = NULL, *pin = NULL, *prompt = NULL;
834	char *user = NULL, *sig_dest = NULL;
835	const char *fwd_host = NULL, *dest_host = NULL;
836	struct sshbuf *msg = NULL, *data = NULL, *sid = NULL;
837	struct sshkey *key = NULL, *hostkey = NULL;
838	struct identity *id;
839	struct notifier_ctx *notifier = NULL;
840
841	debug_f("entering");
842
843	if ((msg = sshbuf_new()) == NULL || (data = sshbuf_new()) == NULL)
844		fatal_f("sshbuf_new failed");
845	if ((r = sshkey_froms(e->request, &key)) != 0 ||
846	    (r = sshbuf_get_stringb(e->request, data)) != 0 ||
847	    (r = sshbuf_get_u32(e->request, &flags)) != 0) {
848		error_fr(r, "parse");
849		goto send;
850	}
851
852	if ((id = lookup_identity(key)) == NULL) {
853		verbose_f("%s key not found", sshkey_type(key));
854		goto send;
855	}
856	if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
857	    SSH_FP_DEFAULT)) == NULL)
858		fatal_f("fingerprint failed");
859
860	if (id->ndest_constraints != 0) {
861		if (e->nsession_ids == 0) {
862			logit_f("refusing use of destination-constrained key "
863			    "to sign on unbound connection");
864			goto send;
865		}
866		if (parse_userauth_request(data, key, &user, &sid,
867		    &hostkey) != 0) {
868			logit_f("refusing use of destination-constrained key "
869			   "to sign an unidentified signature");
870			goto send;
871		}
872		/* XXX logspam */
873		debug_f("user=%s", user);
874		if (identity_permitted(id, e, user, &fwd_host, &dest_host) != 0)
875			goto send;
876		/* XXX display fwd_host/dest_host in askpass UI */
877		/*
878		 * Ensure that the session ID is the most recent one
879		 * registered on the socket - it should have been bound by
880		 * ssh immediately before userauth.
881		 */
882		if (buf_equal(sid,
883		    e->session_ids[e->nsession_ids - 1].sid) != 0) {
884			error_f("unexpected session ID (%zu listed) on "
885			    "signature request for target user %s with "
886			    "key %s %s", e->nsession_ids, user,
887			    sshkey_type(id->key), fp);
888			goto send;
889		}
890		/*
891		 * Ensure that the hostkey embedded in the signature matches
892		 * the one most recently bound to the socket. An exception is
893		 * made for the initial forwarding hop.
894		 */
895		if (e->nsession_ids > 1 && hostkey == NULL) {
896			error_f("refusing use of destination-constrained key: "
897			    "no hostkey recorded in signature for forwarded "
898			    "connection");
899			goto send;
900		}
901		if (hostkey != NULL && !sshkey_equal(hostkey,
902		    e->session_ids[e->nsession_ids - 1].key)) {
903			error_f("refusing use of destination-constrained key: "
904			    "mismatch between hostkey in request and most "
905			    "recently bound session");
906			goto send;
907		}
908		xasprintf(&sig_dest, "public key authentication request for "
909		    "user \"%s\" to listed host", user);
910	}
911	if (id->confirm && confirm_key(id, sig_dest) != 0) {
912		verbose_f("user refused key");
913		goto send;
914	}
915	if (sshkey_is_sk(id->key)) {
916		if (restrict_websafe &&
917		    strncmp(id->key->sk_application, "ssh:", 4) != 0 &&
918		    !check_websafe_message_contents(key, data)) {
919			/* error already logged */
920			goto send;
921		}
922		if (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD) {
923			notifier = notify_start(0,
924			    "Confirm user presence for key %s %s%s%s",
925			    sshkey_type(id->key), fp,
926			    sig_dest == NULL ? "" : "\n",
927			    sig_dest == NULL ? "" : sig_dest);
928		}
929	}
930 retry_pin:
931	if ((r = sshkey_sign(id->key, &signature, &slen,
932	    sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags),
933	    id->sk_provider, pin, compat)) != 0) {
934		debug_fr(r, "sshkey_sign");
935		if (pin == NULL && !retried && sshkey_is_sk(id->key) &&
936		    r == SSH_ERR_KEY_WRONG_PASSPHRASE) {
937			notify_complete(notifier, NULL);
938			notifier = NULL;
939			/* XXX include sig_dest */
940			xasprintf(&prompt, "Enter PIN%sfor %s key %s: ",
941			    (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD) ?
942			    " and confirm user presence " : " ",
943			    sshkey_type(id->key), fp);
944			pin = read_passphrase(prompt, RP_USE_ASKPASS);
945			retried = 1;
946			goto retry_pin;
947		}
948		error_fr(r, "sshkey_sign");
949		goto send;
950	}
951	/* Success */
952	ok = 0;
953	debug_f("good signature");
954 send:
955	notify_complete(notifier, "User presence confirmed");
956
957	if (ok == 0) {
958		if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
959		    (r = sshbuf_put_string(msg, signature, slen)) != 0)
960			fatal_fr(r, "compose");
961	} else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
962		fatal_fr(r, "compose failure");
963
964	if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
965		fatal_fr(r, "enqueue");
966
967	sshbuf_free(sid);
968	sshbuf_free(data);
969	sshbuf_free(msg);
970	sshkey_free(key);
971	sshkey_free(hostkey);
972	free(fp);
973	free(signature);
974	free(sig_dest);
975	free(user);
976	free(prompt);
977	if (pin != NULL)
978		freezero(pin, strlen(pin));
979}
980
981/* shared */
982static void
983process_remove_identity(SocketEntry *e)
984{
985	int r, success = 0;
986	struct sshkey *key = NULL;
987	Identity *id;
988
989	debug2_f("entering");
990	if ((r = sshkey_froms(e->request, &key)) != 0) {
991		error_fr(r, "parse key");
992		goto done;
993	}
994	if ((id = lookup_identity(key)) == NULL) {
995		debug_f("key not found");
996		goto done;
997	}
998	/* identity not visible, cannot be removed */
999	if (identity_permitted(id, e, NULL, NULL, NULL) != 0)
1000		goto done; /* error already logged */
1001	/* We have this key, free it. */
1002	if (idtab->nentries < 1)
1003		fatal_f("internal error: nentries %d", idtab->nentries);
1004	TAILQ_REMOVE(&idtab->idlist, id, next);
1005	free_identity(id);
1006	idtab->nentries--;
1007	success = 1;
1008 done:
1009	sshkey_free(key);
1010	send_status(e, success);
1011}
1012
1013static void
1014process_remove_all_identities(SocketEntry *e)
1015{
1016	Identity *id;
1017
1018	debug2_f("entering");
1019	/* Loop over all identities and clear the keys. */
1020	for (id = TAILQ_FIRST(&idtab->idlist); id;
1021	    id = TAILQ_FIRST(&idtab->idlist)) {
1022		TAILQ_REMOVE(&idtab->idlist, id, next);
1023		free_identity(id);
1024	}
1025
1026	/* Mark that there are no identities. */
1027	idtab->nentries = 0;
1028
1029	/* Send success. */
1030	send_status(e, 1);
1031}
1032
1033/* removes expired keys and returns number of seconds until the next expiry */
1034static time_t
1035reaper(void)
1036{
1037	time_t deadline = 0, now = monotime();
1038	Identity *id, *nxt;
1039
1040	for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
1041		nxt = TAILQ_NEXT(id, next);
1042		if (id->death == 0)
1043			continue;
1044		if (now >= id->death) {
1045			debug("expiring key '%s'", id->comment);
1046			TAILQ_REMOVE(&idtab->idlist, id, next);
1047			free_identity(id);
1048			idtab->nentries--;
1049		} else
1050			deadline = (deadline == 0) ? id->death :
1051			    MINIMUM(deadline, id->death);
1052	}
1053	if (deadline == 0 || deadline <= now)
1054		return 0;
1055	else
1056		return (deadline - now);
1057}
1058
1059static int
1060parse_dest_constraint_hop(struct sshbuf *b, struct dest_constraint_hop *dch)
1061{
1062	u_char key_is_ca;
1063	size_t elen = 0;
1064	int r;
1065	struct sshkey *k = NULL;
1066	char *fp;
1067
1068	memset(dch, '\0', sizeof(*dch));
1069	if ((r = sshbuf_get_cstring(b, &dch->user, NULL)) != 0 ||
1070	    (r = sshbuf_get_cstring(b, &dch->hostname, NULL)) != 0 ||
1071	    (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) {
1072		error_fr(r, "parse");
1073		goto out;
1074	}
1075	if (elen != 0) {
1076		error_f("unsupported extensions (len %zu)", elen);
1077		r = SSH_ERR_FEATURE_UNSUPPORTED;
1078		goto out;
1079	}
1080	if (*dch->hostname == '\0') {
1081		free(dch->hostname);
1082		dch->hostname = NULL;
1083	}
1084	if (*dch->user == '\0') {
1085		free(dch->user);
1086		dch->user = NULL;
1087	}
1088	while (sshbuf_len(b) != 0) {
1089		dch->keys = xrecallocarray(dch->keys, dch->nkeys,
1090		    dch->nkeys + 1, sizeof(*dch->keys));
1091		dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys,
1092		    dch->nkeys + 1, sizeof(*dch->key_is_ca));
1093		if ((r = sshkey_froms(b, &k)) != 0 ||
1094		    (r = sshbuf_get_u8(b, &key_is_ca)) != 0)
1095			goto out;
1096		if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT,
1097		    SSH_FP_DEFAULT)) == NULL)
1098			fatal_f("fingerprint failed");
1099		debug3_f("%s%s%s: adding %skey %s %s",
1100		    dch->user == NULL ? "" : dch->user,
1101		    dch->user == NULL ? "" : "@",
1102		    dch->hostname, key_is_ca ? "CA " : "", sshkey_type(k), fp);
1103		free(fp);
1104		dch->keys[dch->nkeys] = k;
1105		dch->key_is_ca[dch->nkeys] = key_is_ca != 0;
1106		dch->nkeys++;
1107		k = NULL; /* transferred */
1108	}
1109	/* success */
1110	r = 0;
1111 out:
1112	sshkey_free(k);
1113	return r;
1114}
1115
1116static int
1117parse_dest_constraint(struct sshbuf *m, struct dest_constraint *dc)
1118{
1119	struct sshbuf *b = NULL, *frombuf = NULL, *tobuf = NULL;
1120	int r;
1121	size_t elen = 0;
1122
1123	debug3_f("entering");
1124
1125	memset(dc, '\0', sizeof(*dc));
1126	if ((r = sshbuf_froms(m, &b)) != 0 ||
1127	    (r = sshbuf_froms(b, &frombuf)) != 0 ||
1128	    (r = sshbuf_froms(b, &tobuf)) != 0 ||
1129	    (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) {
1130		error_fr(r, "parse");
1131		goto out;
1132	}
1133	if ((r = parse_dest_constraint_hop(frombuf, &dc->from)) != 0 ||
1134	    (r = parse_dest_constraint_hop(tobuf, &dc->to)) != 0)
1135		goto out; /* already logged */
1136	if (elen != 0) {
1137		error_f("unsupported extensions (len %zu)", elen);
1138		r = SSH_ERR_FEATURE_UNSUPPORTED;
1139		goto out;
1140	}
1141	debug2_f("parsed %s (%u keys) > %s%s%s (%u keys)",
1142	    dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys,
1143	    dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "",
1144	    dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys);
1145	/* check consistency */
1146	if ((dc->from.hostname == NULL) != (dc->from.nkeys == 0) ||
1147	    dc->from.user != NULL) {
1148		error_f("inconsistent \"from\" specification");
1149		r = SSH_ERR_INVALID_FORMAT;
1150		goto out;
1151	}
1152	if (dc->to.hostname == NULL || dc->to.nkeys == 0) {
1153		error_f("incomplete \"to\" specification");
1154		r = SSH_ERR_INVALID_FORMAT;
1155		goto out;
1156	}
1157	/* success */
1158	r = 0;
1159 out:
1160	sshbuf_free(b);
1161	sshbuf_free(frombuf);
1162	sshbuf_free(tobuf);
1163	return r;
1164}
1165
1166static int
1167parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp,
1168    struct dest_constraint **dcsp, size_t *ndcsp, int *cert_onlyp,
1169    struct sshkey ***certs, size_t *ncerts)
1170{
1171	char *ext_name = NULL;
1172	int r;
1173	struct sshbuf *b = NULL;
1174	u_char v;
1175	struct sshkey *k;
1176
1177	if ((r = sshbuf_get_cstring(m, &ext_name, NULL)) != 0) {
1178		error_fr(r, "parse constraint extension");
1179		goto out;
1180	}
1181	debug_f("constraint ext %s", ext_name);
1182	if (strcmp(ext_name, "sk-provider@openssh.com") == 0) {
1183		if (sk_providerp == NULL) {
1184			error_f("%s not valid here", ext_name);
1185			r = SSH_ERR_INVALID_FORMAT;
1186			goto out;
1187		}
1188		if (*sk_providerp != NULL) {
1189			error_f("%s already set", ext_name);
1190			r = SSH_ERR_INVALID_FORMAT;
1191			goto out;
1192		}
1193		if ((r = sshbuf_get_cstring(m, sk_providerp, NULL)) != 0) {
1194			error_fr(r, "parse %s", ext_name);
1195			goto out;
1196		}
1197	} else if (strcmp(ext_name,
1198	    "restrict-destination-v00@openssh.com") == 0) {
1199		if (*dcsp != NULL) {
1200			error_f("%s already set", ext_name);
1201			goto out;
1202		}
1203		if ((r = sshbuf_froms(m, &b)) != 0) {
1204			error_fr(r, "parse %s outer", ext_name);
1205			goto out;
1206		}
1207		while (sshbuf_len(b) != 0) {
1208			if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS) {
1209				error_f("too many %s constraints", ext_name);
1210				goto out;
1211			}
1212			*dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1,
1213			    sizeof(**dcsp));
1214			if ((r = parse_dest_constraint(b,
1215			    *dcsp + (*ndcsp)++)) != 0)
1216				goto out; /* error already logged */
1217		}
1218	} else if (strcmp(ext_name,
1219	    "associated-certs-v00@openssh.com") == 0) {
1220		if (certs == NULL || ncerts == NULL || cert_onlyp == NULL) {
1221			error_f("%s not valid here", ext_name);
1222			r = SSH_ERR_INVALID_FORMAT;
1223			goto out;
1224		}
1225		if (*certs != NULL) {
1226			error_f("%s already set", ext_name);
1227			goto out;
1228		}
1229		if ((r = sshbuf_get_u8(m, &v)) != 0 ||
1230		    (r = sshbuf_froms(m, &b)) != 0) {
1231			error_fr(r, "parse %s", ext_name);
1232			goto out;
1233		}
1234		*cert_onlyp = v != 0;
1235		while (sshbuf_len(b) != 0) {
1236			if (*ncerts >= AGENT_MAX_EXT_CERTS) {
1237				error_f("too many %s constraints", ext_name);
1238				goto out;
1239			}
1240			*certs = xrecallocarray(*certs, *ncerts, *ncerts + 1,
1241			    sizeof(**certs));
1242			if ((r = sshkey_froms(b, &k)) != 0) {
1243				error_fr(r, "parse key");
1244				goto out;
1245			}
1246			(*certs)[(*ncerts)++] = k;
1247		}
1248	} else {
1249		error_f("unsupported constraint \"%s\"", ext_name);
1250		r = SSH_ERR_FEATURE_UNSUPPORTED;
1251		goto out;
1252	}
1253	/* success */
1254	r = 0;
1255 out:
1256	free(ext_name);
1257	sshbuf_free(b);
1258	return r;
1259}
1260
1261static int
1262parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp,
1263    u_int *secondsp, int *confirmp, char **sk_providerp,
1264    struct dest_constraint **dcsp, size_t *ndcsp,
1265    int *cert_onlyp, size_t *ncerts, struct sshkey ***certs)
1266{
1267	u_char ctype;
1268	int r;
1269	u_int seconds, maxsign = 0;
1270
1271	while (sshbuf_len(m)) {
1272		if ((r = sshbuf_get_u8(m, &ctype)) != 0) {
1273			error_fr(r, "parse constraint type");
1274			goto out;
1275		}
1276		switch (ctype) {
1277		case SSH_AGENT_CONSTRAIN_LIFETIME:
1278			if (*deathp != 0) {
1279				error_f("lifetime already set");
1280				r = SSH_ERR_INVALID_FORMAT;
1281				goto out;
1282			}
1283			if ((r = sshbuf_get_u32(m, &seconds)) != 0) {
1284				error_fr(r, "parse lifetime constraint");
1285				goto out;
1286			}
1287			*deathp = monotime() + seconds;
1288			*secondsp = seconds;
1289			break;
1290		case SSH_AGENT_CONSTRAIN_CONFIRM:
1291			if (*confirmp != 0) {
1292				error_f("confirm already set");
1293				r = SSH_ERR_INVALID_FORMAT;
1294				goto out;
1295			}
1296			*confirmp = 1;
1297			break;
1298		case SSH_AGENT_CONSTRAIN_MAXSIGN:
1299			if (k == NULL) {
1300				error_f("maxsign not valid here");
1301				r = SSH_ERR_INVALID_FORMAT;
1302				goto out;
1303			}
1304			if (maxsign != 0) {
1305				error_f("maxsign already set");
1306				r = SSH_ERR_INVALID_FORMAT;
1307				goto out;
1308			}
1309			if ((r = sshbuf_get_u32(m, &maxsign)) != 0) {
1310				error_fr(r, "parse maxsign constraint");
1311				goto out;
1312			}
1313			if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) {
1314				error_fr(r, "enable maxsign");
1315				goto out;
1316			}
1317			break;
1318		case SSH_AGENT_CONSTRAIN_EXTENSION:
1319			if ((r = parse_key_constraint_extension(m,
1320			    sk_providerp, dcsp, ndcsp,
1321			    cert_onlyp, certs, ncerts)) != 0)
1322				goto out; /* error already logged */
1323			break;
1324		default:
1325			error_f("Unknown constraint %d", ctype);
1326			r = SSH_ERR_FEATURE_UNSUPPORTED;
1327			goto out;
1328		}
1329	}
1330	/* success */
1331	r = 0;
1332 out:
1333	return r;
1334}
1335
1336static void
1337process_add_identity(SocketEntry *e)
1338{
1339	Identity *id;
1340	int success = 0, confirm = 0;
1341	char *fp, *comment = NULL, *sk_provider = NULL;
1342	char canonical_provider[PATH_MAX];
1343	time_t death = 0;
1344	u_int seconds = 0;
1345	struct dest_constraint *dest_constraints = NULL;
1346	size_t ndest_constraints = 0;
1347	struct sshkey *k = NULL;
1348	int r = SSH_ERR_INTERNAL_ERROR;
1349
1350	debug2_f("entering");
1351	if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
1352	    k == NULL ||
1353	    (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
1354		error_fr(r, "parse");
1355		goto out;
1356	}
1357	if (parse_key_constraints(e->request, k, &death, &seconds, &confirm,
1358	    &sk_provider, &dest_constraints, &ndest_constraints,
1359	    NULL, NULL, NULL) != 0) {
1360		error_f("failed to parse constraints");
1361		sshbuf_reset(e->request);
1362		goto out;
1363	}
1364	dump_dest_constraints(__func__, dest_constraints, ndest_constraints);
1365
1366	if (sk_provider != NULL) {
1367		if (!sshkey_is_sk(k)) {
1368			error("Cannot add provider: %s is not an "
1369			    "authenticator-hosted key", sshkey_type(k));
1370			goto out;
1371		}
1372		if (strcasecmp(sk_provider, "internal") == 0) {
1373			debug_f("internal provider");
1374		} else {
1375			if (socket_is_remote(e) && !remote_add_provider) {
1376				verbose("failed add of SK provider \"%.100s\": "
1377				    "remote addition of providers is disabled",
1378				    sk_provider);
1379				goto out;
1380			}
1381			if (realpath(sk_provider, canonical_provider) == NULL) {
1382				verbose("failed provider \"%.100s\": "
1383				    "realpath: %s", sk_provider,
1384				    strerror(errno));
1385				goto out;
1386			}
1387			free(sk_provider);
1388			sk_provider = xstrdup(canonical_provider);
1389			if (match_pattern_list(sk_provider,
1390			    allowed_providers, 0) != 1) {
1391				error("Refusing add key: "
1392				    "provider %s not allowed", sk_provider);
1393				goto out;
1394			}
1395		}
1396	}
1397	if ((r = sshkey_shield_private(k)) != 0) {
1398		error_fr(r, "shield private");
1399		goto out;
1400	}
1401	if (lifetime && !death)
1402		death = monotime() + lifetime;
1403	if ((id = lookup_identity(k)) == NULL) {
1404		id = xcalloc(1, sizeof(Identity));
1405		TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
1406		/* Increment the number of identities. */
1407		idtab->nentries++;
1408	} else {
1409		/* identity not visible, do not update */
1410		if (identity_permitted(id, e, NULL, NULL, NULL) != 0)
1411			goto out; /* error already logged */
1412		/* key state might have been updated */
1413		sshkey_free(id->key);
1414		free(id->comment);
1415		free(id->sk_provider);
1416		free_dest_constraints(id->dest_constraints,
1417		    id->ndest_constraints);
1418	}
1419	/* success */
1420	id->key = k;
1421	id->comment = comment;
1422	id->death = death;
1423	id->confirm = confirm;
1424	id->sk_provider = sk_provider;
1425	id->dest_constraints = dest_constraints;
1426	id->ndest_constraints = ndest_constraints;
1427
1428	if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT,
1429	    SSH_FP_DEFAULT)) == NULL)
1430		fatal_f("sshkey_fingerprint failed");
1431	debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) "
1432	    "(provider: %s) (destination constraints: %zu)",
1433	    sshkey_ssh_name(k), fp, comment, seconds, confirm,
1434	    sk_provider == NULL ? "none" : sk_provider, ndest_constraints);
1435	free(fp);
1436	/* transferred */
1437	k = NULL;
1438	comment = NULL;
1439	sk_provider = NULL;
1440	dest_constraints = NULL;
1441	ndest_constraints = 0;
1442	success = 1;
1443 out:
1444	free(sk_provider);
1445	free(comment);
1446	sshkey_free(k);
1447	free_dest_constraints(dest_constraints, ndest_constraints);
1448	send_status(e, success);
1449}
1450
1451/* XXX todo: encrypt sensitive data with passphrase */
1452static void
1453process_lock_agent(SocketEntry *e, int lock)
1454{
1455	int r, success = 0, delay;
1456	char *passwd;
1457	u_char passwdhash[LOCK_SIZE];
1458	static u_int fail_count = 0;
1459	size_t pwlen;
1460
1461	debug2_f("entering");
1462	/*
1463	 * This is deliberately fatal: the user has requested that we lock,
1464	 * but we can't parse their request properly. The only safe thing to
1465	 * do is abort.
1466	 */
1467	if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0)
1468		fatal_fr(r, "parse");
1469	if (pwlen == 0) {
1470		debug("empty password not supported");
1471	} else if (locked && !lock) {
1472		if (bcrypt_pbkdf(passwd, pwlen, (uint8_t *)lock_salt, sizeof(lock_salt),
1473		    (uint8_t *)passwdhash, sizeof(passwdhash), LOCK_ROUNDS) < 0)
1474			fatal("bcrypt_pbkdf");
1475		if (timingsafe_bcmp(passwdhash, lock_pwhash, LOCK_SIZE) == 0) {
1476			debug("agent unlocked");
1477			locked = 0;
1478			fail_count = 0;
1479			explicit_bzero(lock_pwhash, sizeof(lock_pwhash));
1480			success = 1;
1481		} else {
1482			/* delay in 0.1s increments up to 10s */
1483			if (fail_count < 100)
1484				fail_count++;
1485			delay = 100000 * fail_count;
1486			debug("unlock failed, delaying %0.1lf seconds",
1487			    (double)delay/1000000);
1488			usleep(delay);
1489		}
1490		explicit_bzero(passwdhash, sizeof(passwdhash));
1491	} else if (!locked && lock) {
1492		debug("agent locked");
1493		locked = 1;
1494		arc4random_buf(lock_salt, sizeof(lock_salt));
1495		if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt),
1496		    lock_pwhash, sizeof(lock_pwhash), LOCK_ROUNDS) < 0)
1497			fatal("bcrypt_pbkdf");
1498		success = 1;
1499	}
1500	freezero(passwd, pwlen);
1501	send_status(e, success);
1502}
1503
1504static void
1505no_identities(SocketEntry *e)
1506{
1507	struct sshbuf *msg;
1508	int r;
1509
1510	if ((msg = sshbuf_new()) == NULL)
1511		fatal_f("sshbuf_new failed");
1512	if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
1513	    (r = sshbuf_put_u32(msg, 0)) != 0 ||
1514	    (r = sshbuf_put_stringb(e->output, msg)) != 0)
1515		fatal_fr(r, "compose");
1516	sshbuf_free(msg);
1517}
1518
1519/* Add an identity to idlist; takes ownership of 'key' and 'comment' */
1520static void
1521add_p11_identity(struct sshkey *key, char *comment, const char *provider,
1522    time_t death, int confirm, struct dest_constraint *dest_constraints,
1523    size_t ndest_constraints)
1524{
1525	Identity *id;
1526
1527	if (lookup_identity(key) != NULL) {
1528		sshkey_free(key);
1529		free(comment);
1530		return;
1531	}
1532	id = xcalloc(1, sizeof(Identity));
1533	id->key = key;
1534	id->comment = comment;
1535	id->provider = xstrdup(provider);
1536	id->death = death;
1537	id->confirm = confirm;
1538	id->dest_constraints = dup_dest_constraints(dest_constraints,
1539	    ndest_constraints);
1540	id->ndest_constraints = ndest_constraints;
1541	TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
1542	idtab->nentries++;
1543}
1544
1545#ifdef ENABLE_PKCS11
1546static void
1547process_add_smartcard_key(SocketEntry *e)
1548{
1549	char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
1550	char **comments = NULL;
1551	int r, i, count = 0, success = 0, confirm = 0;
1552	u_int seconds = 0;
1553	time_t death = 0;
1554	struct sshkey **keys = NULL, *k;
1555	struct dest_constraint *dest_constraints = NULL;
1556	size_t j, ndest_constraints = 0, ncerts = 0;
1557	struct sshkey **certs = NULL;
1558	int cert_only = 0;
1559
1560	debug2_f("entering");
1561	if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
1562	    (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
1563		error_fr(r, "parse");
1564		goto send;
1565	}
1566	if (parse_key_constraints(e->request, NULL, &death, &seconds, &confirm,
1567	    NULL, &dest_constraints, &ndest_constraints, &cert_only,
1568	    &ncerts, &certs) != 0) {
1569		error_f("failed to parse constraints");
1570		goto send;
1571	}
1572	dump_dest_constraints(__func__, dest_constraints, ndest_constraints);
1573	if (socket_is_remote(e) && !remote_add_provider) {
1574		verbose("failed PKCS#11 add of \"%.100s\": remote addition of "
1575		    "providers is disabled", provider);
1576		goto send;
1577	}
1578	if (realpath(provider, canonical_provider) == NULL) {
1579		verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1580		    provider, strerror(errno));
1581		goto send;
1582	}
1583	if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) {
1584		verbose("refusing PKCS#11 add of \"%.100s\": "
1585		    "provider not allowed", canonical_provider);
1586		goto send;
1587	}
1588	debug_f("add %.100s", canonical_provider);
1589	if (lifetime && !death)
1590		death = monotime() + lifetime;
1591
1592	count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments);
1593	for (i = 0; i < count; i++) {
1594		if (comments[i] == NULL || comments[i][0] == '\0') {
1595			free(comments[i]);
1596			comments[i] = xstrdup(canonical_provider);
1597		}
1598		for (j = 0; j < ncerts; j++) {
1599			if (!sshkey_is_cert(certs[j]))
1600				continue;
1601			if (!sshkey_equal_public(keys[i], certs[j]))
1602				continue;
1603			if (pkcs11_make_cert(keys[i], certs[j], &k) != 0)
1604				continue;
1605			add_p11_identity(k, xstrdup(comments[i]),
1606			    canonical_provider, death, confirm,
1607			    dest_constraints, ndest_constraints);
1608			success = 1;
1609		}
1610		if (!cert_only && lookup_identity(keys[i]) == NULL) {
1611			add_p11_identity(keys[i], comments[i],
1612			    canonical_provider, death, confirm,
1613			    dest_constraints, ndest_constraints);
1614			keys[i] = NULL;		/* transferred */
1615			comments[i] = NULL;	/* transferred */
1616			success = 1;
1617		}
1618		/* XXX update constraints for existing keys */
1619		sshkey_free(keys[i]);
1620		free(comments[i]);
1621	}
1622send:
1623	free(pin);
1624	free(provider);
1625	free(keys);
1626	free(comments);
1627	free_dest_constraints(dest_constraints, ndest_constraints);
1628	for (j = 0; j < ncerts; j++)
1629		sshkey_free(certs[j]);
1630	free(certs);
1631	send_status(e, success);
1632}
1633
1634static void
1635process_remove_smartcard_key(SocketEntry *e)
1636{
1637	char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
1638	int r, success = 0;
1639	Identity *id, *nxt;
1640
1641	debug2_f("entering");
1642	if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
1643	    (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
1644		error_fr(r, "parse");
1645		goto send;
1646	}
1647	free(pin);
1648
1649	if (realpath(provider, canonical_provider) == NULL) {
1650		verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
1651		    provider, strerror(errno));
1652		goto send;
1653	}
1654
1655	debug_f("remove %.100s", canonical_provider);
1656	for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
1657		nxt = TAILQ_NEXT(id, next);
1658		/* Skip file--based keys */
1659		if (id->provider == NULL)
1660			continue;
1661		if (!strcmp(canonical_provider, id->provider)) {
1662			TAILQ_REMOVE(&idtab->idlist, id, next);
1663			free_identity(id);
1664			idtab->nentries--;
1665		}
1666	}
1667	if (pkcs11_del_provider(canonical_provider) == 0)
1668		success = 1;
1669	else
1670		error_f("pkcs11_del_provider failed");
1671send:
1672	free(provider);
1673	send_status(e, success);
1674}
1675#endif /* ENABLE_PKCS11 */
1676
1677static int
1678process_ext_session_bind(SocketEntry *e)
1679{
1680	int r, sid_match, key_match;
1681	struct sshkey *key = NULL;
1682	struct sshbuf *sid = NULL, *sig = NULL;
1683	char *fp = NULL;
1684	size_t i;
1685	u_char fwd = 0;
1686
1687	debug2_f("entering");
1688	e->session_bind_attempted = 1;
1689	if ((r = sshkey_froms(e->request, &key)) != 0 ||
1690	    (r = sshbuf_froms(e->request, &sid)) != 0 ||
1691	    (r = sshbuf_froms(e->request, &sig)) != 0 ||
1692	    (r = sshbuf_get_u8(e->request, &fwd)) != 0) {
1693		error_fr(r, "parse");
1694		goto out;
1695	}
1696	if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
1697	    SSH_FP_DEFAULT)) == NULL)
1698		fatal_f("fingerprint failed");
1699	/* check signature with hostkey on session ID */
1700	if ((r = sshkey_verify(key, sshbuf_ptr(sig), sshbuf_len(sig),
1701	    sshbuf_ptr(sid), sshbuf_len(sid), NULL, 0, NULL)) != 0) {
1702		error_fr(r, "sshkey_verify for %s %s", sshkey_type(key), fp);
1703		goto out;
1704	}
1705	/* check whether sid/key already recorded */
1706	for (i = 0; i < e->nsession_ids; i++) {
1707		if (!e->session_ids[i].forwarded) {
1708			error_f("attempt to bind session ID to socket "
1709			    "previously bound for authentication attempt");
1710			r = -1;
1711			goto out;
1712		}
1713		sid_match = buf_equal(sid, e->session_ids[i].sid) == 0;
1714		key_match = sshkey_equal(key, e->session_ids[i].key);
1715		if (sid_match && key_match) {
1716			debug_f("session ID already recorded for %s %s",
1717			    sshkey_type(key), fp);
1718			r = 0;
1719			goto out;
1720		} else if (sid_match) {
1721			error_f("session ID recorded against different key "
1722			    "for %s %s", sshkey_type(key), fp);
1723			r = -1;
1724			goto out;
1725		}
1726		/*
1727		 * new sid with previously-seen key can happen, e.g. multiple
1728		 * connections to the same host.
1729		 */
1730	}
1731	/* record new key/sid */
1732	if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) {
1733		error_f("too many session IDs recorded");
1734		goto out;
1735	}
1736	e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids,
1737	    e->nsession_ids + 1, sizeof(*e->session_ids));
1738	i = e->nsession_ids++;
1739	debug_f("recorded %s %s (slot %zu of %d)", sshkey_type(key), fp, i,
1740	    AGENT_MAX_SESSION_IDS);
1741	e->session_ids[i].key = key;
1742	e->session_ids[i].forwarded = fwd != 0;
1743	key = NULL; /* transferred */
1744	/* can't transfer sid; it's refcounted and scoped to request's life */
1745	if ((e->session_ids[i].sid = sshbuf_new()) == NULL)
1746		fatal_f("sshbuf_new");
1747	if ((r = sshbuf_putb(e->session_ids[i].sid, sid)) != 0)
1748		fatal_fr(r, "sshbuf_putb session ID");
1749	/* success */
1750	r = 0;
1751 out:
1752	free(fp);
1753	sshkey_free(key);
1754	sshbuf_free(sid);
1755	sshbuf_free(sig);
1756	return r == 0 ? 1 : 0;
1757}
1758
1759static void
1760process_extension(SocketEntry *e)
1761{
1762	int r, success = 0;
1763	char *name;
1764
1765	debug2_f("entering");
1766	if ((r = sshbuf_get_cstring(e->request, &name, NULL)) != 0) {
1767		error_fr(r, "parse");
1768		goto send;
1769	}
1770	if (strcmp(name, "session-bind@openssh.com") == 0)
1771		success = process_ext_session_bind(e);
1772	else
1773		debug_f("unsupported extension \"%s\"", name);
1774	free(name);
1775send:
1776	send_status(e, success);
1777}
1778/*
1779 * dispatch incoming message.
1780 * returns 1 on success, 0 for incomplete messages or -1 on error.
1781 */
1782static int
1783process_message(u_int socknum)
1784{
1785	u_int msg_len;
1786	u_char type;
1787	const u_char *cp;
1788	int r;
1789	SocketEntry *e;
1790
1791	if (socknum >= sockets_alloc)
1792		fatal_f("sock %u >= allocated %u", socknum, sockets_alloc);
1793	e = &sockets[socknum];
1794
1795	if (sshbuf_len(e->input) < 5)
1796		return 0;		/* Incomplete message header. */
1797	cp = sshbuf_ptr(e->input);
1798	msg_len = PEEK_U32(cp);
1799	if (msg_len > AGENT_MAX_LEN) {
1800		debug_f("socket %u (fd=%d) message too long %u > %u",
1801		    socknum, e->fd, msg_len, AGENT_MAX_LEN);
1802		return -1;
1803	}
1804	if (sshbuf_len(e->input) < msg_len + 4)
1805		return 0;		/* Incomplete message body. */
1806
1807	/* move the current input to e->request */
1808	sshbuf_reset(e->request);
1809	if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 ||
1810	    (r = sshbuf_get_u8(e->request, &type)) != 0) {
1811		if (r == SSH_ERR_MESSAGE_INCOMPLETE ||
1812		    r == SSH_ERR_STRING_TOO_LARGE) {
1813			error_fr(r, "parse");
1814			return -1;
1815		}
1816		fatal_fr(r, "parse");
1817	}
1818
1819	debug_f("socket %u (fd=%d) type %d", socknum, e->fd, type);
1820
1821	/* check whether agent is locked */
1822	if (locked && type != SSH_AGENTC_UNLOCK) {
1823		sshbuf_reset(e->request);
1824		switch (type) {
1825		case SSH2_AGENTC_REQUEST_IDENTITIES:
1826			/* send empty lists */
1827			no_identities(e);
1828			break;
1829		default:
1830			/* send a fail message for all other request types */
1831			send_status(e, 0);
1832		}
1833		return 1;
1834	}
1835
1836	switch (type) {
1837	case SSH_AGENTC_LOCK:
1838	case SSH_AGENTC_UNLOCK:
1839		process_lock_agent(e, type == SSH_AGENTC_LOCK);
1840		break;
1841	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
1842		process_remove_all_identities(e); /* safe for !WITH_SSH1 */
1843		break;
1844	/* ssh2 */
1845	case SSH2_AGENTC_SIGN_REQUEST:
1846		process_sign_request2(e);
1847		break;
1848	case SSH2_AGENTC_REQUEST_IDENTITIES:
1849		process_request_identities(e);
1850		break;
1851	case SSH2_AGENTC_ADD_IDENTITY:
1852	case SSH2_AGENTC_ADD_ID_CONSTRAINED:
1853		process_add_identity(e);
1854		break;
1855	case SSH2_AGENTC_REMOVE_IDENTITY:
1856		process_remove_identity(e);
1857		break;
1858	case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
1859		process_remove_all_identities(e);
1860		break;
1861#ifdef ENABLE_PKCS11
1862	case SSH_AGENTC_ADD_SMARTCARD_KEY:
1863	case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
1864		process_add_smartcard_key(e);
1865		break;
1866	case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
1867		process_remove_smartcard_key(e);
1868		break;
1869#endif /* ENABLE_PKCS11 */
1870	case SSH_AGENTC_EXTENSION:
1871		process_extension(e);
1872		break;
1873	default:
1874		/* Unknown message.  Respond with failure. */
1875		error("Unknown message %d", type);
1876		sshbuf_reset(e->request);
1877		send_status(e, 0);
1878		break;
1879	}
1880	return 1;
1881}
1882
1883static void
1884new_socket(sock_type type, int fd)
1885{
1886	u_int i, old_alloc, new_alloc;
1887
1888	debug_f("type = %s", type == AUTH_CONNECTION ? "CONNECTION" :
1889	    (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN"));
1890	set_nonblock(fd);
1891
1892	if (fd > max_fd)
1893		max_fd = fd;
1894
1895	for (i = 0; i < sockets_alloc; i++)
1896		if (sockets[i].type == AUTH_UNUSED) {
1897			sockets[i].fd = fd;
1898			if ((sockets[i].input = sshbuf_new()) == NULL ||
1899			    (sockets[i].output = sshbuf_new()) == NULL ||
1900			    (sockets[i].request = sshbuf_new()) == NULL)
1901				fatal_f("sshbuf_new failed");
1902			sockets[i].type = type;
1903			return;
1904		}
1905	old_alloc = sockets_alloc;
1906	new_alloc = sockets_alloc + 10;
1907	sockets = xrecallocarray(sockets, old_alloc, new_alloc,
1908	    sizeof(sockets[0]));
1909	for (i = old_alloc; i < new_alloc; i++)
1910		sockets[i].type = AUTH_UNUSED;
1911	sockets_alloc = new_alloc;
1912	sockets[old_alloc].fd = fd;
1913	if ((sockets[old_alloc].input = sshbuf_new()) == NULL ||
1914	    (sockets[old_alloc].output = sshbuf_new()) == NULL ||
1915	    (sockets[old_alloc].request = sshbuf_new()) == NULL)
1916		fatal_f("sshbuf_new failed");
1917	sockets[old_alloc].type = type;
1918}
1919
1920static int
1921handle_socket_read(u_int socknum)
1922{
1923	struct sockaddr_un sunaddr;
1924	socklen_t slen;
1925	uid_t euid;
1926	gid_t egid;
1927	int fd;
1928
1929	slen = sizeof(sunaddr);
1930	fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen);
1931	if (fd == -1) {
1932		error("accept from AUTH_SOCKET: %s", strerror(errno));
1933		return -1;
1934	}
1935	if (getpeereid(fd, &euid, &egid) == -1) {
1936		error("getpeereid %d failed: %s", fd, strerror(errno));
1937		close(fd);
1938		return -1;
1939	}
1940	if ((euid != 0) && (getuid() != euid)) {
1941		error("uid mismatch: peer euid %u != uid %u",
1942		    (u_int) euid, (u_int) getuid());
1943		close(fd);
1944		return -1;
1945	}
1946	new_socket(AUTH_CONNECTION, fd);
1947	return 0;
1948}
1949
1950static int
1951handle_conn_read(u_int socknum)
1952{
1953	char buf[AGENT_RBUF_LEN];
1954	ssize_t len;
1955	int r;
1956
1957	if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) {
1958		if (len == -1) {
1959			if (errno == EAGAIN || errno == EINTR)
1960				return 0;
1961			error_f("read error on socket %u (fd %d): %s",
1962			    socknum, sockets[socknum].fd, strerror(errno));
1963		}
1964		return -1;
1965	}
1966	if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0)
1967		fatal_fr(r, "compose");
1968	explicit_bzero(buf, sizeof(buf));
1969	for (;;) {
1970		if ((r = process_message(socknum)) == -1)
1971			return -1;
1972		else if (r == 0)
1973			break;
1974	}
1975	return 0;
1976}
1977
1978static int
1979handle_conn_write(u_int socknum)
1980{
1981	ssize_t len;
1982	int r;
1983
1984	if (sshbuf_len(sockets[socknum].output) == 0)
1985		return 0; /* shouldn't happen */
1986	if ((len = write(sockets[socknum].fd,
1987	    sshbuf_ptr(sockets[socknum].output),
1988	    sshbuf_len(sockets[socknum].output))) <= 0) {
1989		if (len == -1) {
1990			if (errno == EAGAIN || errno == EINTR)
1991				return 0;
1992			error_f("read error on socket %u (fd %d): %s",
1993			    socknum, sockets[socknum].fd, strerror(errno));
1994		}
1995		return -1;
1996	}
1997	if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0)
1998		fatal_fr(r, "consume");
1999	return 0;
2000}
2001
2002static void
2003after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds)
2004{
2005	size_t i;
2006	u_int socknum, activefds = npfd;
2007
2008	for (i = 0; i < npfd; i++) {
2009		if (pfd[i].revents == 0)
2010			continue;
2011		/* Find sockets entry */
2012		for (socknum = 0; socknum < sockets_alloc; socknum++) {
2013			if (sockets[socknum].type != AUTH_SOCKET &&
2014			    sockets[socknum].type != AUTH_CONNECTION)
2015				continue;
2016			if (pfd[i].fd == sockets[socknum].fd)
2017				break;
2018		}
2019		if (socknum >= sockets_alloc) {
2020			error_f("no socket for fd %d", pfd[i].fd);
2021			continue;
2022		}
2023		/* Process events */
2024		switch (sockets[socknum].type) {
2025		case AUTH_SOCKET:
2026			if ((pfd[i].revents & (POLLIN|POLLERR)) == 0)
2027				break;
2028			if (npfd > maxfds) {
2029				debug3("out of fds (active %u >= limit %u); "
2030				    "skipping accept", activefds, maxfds);
2031				break;
2032			}
2033			if (handle_socket_read(socknum) == 0)
2034				activefds++;
2035			break;
2036		case AUTH_CONNECTION:
2037			if ((pfd[i].revents & (POLLIN|POLLHUP|POLLERR)) != 0 &&
2038			    handle_conn_read(socknum) != 0)
2039				goto close_sock;
2040			if ((pfd[i].revents & (POLLOUT|POLLHUP)) != 0 &&
2041			    handle_conn_write(socknum) != 0) {
2042 close_sock:
2043				if (activefds == 0)
2044					fatal("activefds == 0 at close_sock");
2045				close_socket(&sockets[socknum]);
2046				activefds--;
2047				break;
2048			}
2049			break;
2050		default:
2051			break;
2052		}
2053	}
2054}
2055
2056static int
2057prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds)
2058{
2059	struct pollfd *pfd = *pfdp;
2060	size_t i, j, npfd = 0;
2061	time_t deadline;
2062	int r;
2063
2064	/* Count active sockets */
2065	for (i = 0; i < sockets_alloc; i++) {
2066		switch (sockets[i].type) {
2067		case AUTH_SOCKET:
2068		case AUTH_CONNECTION:
2069			npfd++;
2070			break;
2071		case AUTH_UNUSED:
2072			break;
2073		default:
2074			fatal("Unknown socket type %d", sockets[i].type);
2075			break;
2076		}
2077	}
2078	if (npfd != *npfdp &&
2079	    (pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL)
2080		fatal_f("recallocarray failed");
2081	*pfdp = pfd;
2082	*npfdp = npfd;
2083
2084	for (i = j = 0; i < sockets_alloc; i++) {
2085		switch (sockets[i].type) {
2086		case AUTH_SOCKET:
2087			if (npfd > maxfds) {
2088				debug3("out of fds (active %zu >= limit %u); "
2089				    "skipping arming listener", npfd, maxfds);
2090				break;
2091			}
2092			pfd[j].fd = sockets[i].fd;
2093			pfd[j].revents = 0;
2094			pfd[j].events = POLLIN;
2095			j++;
2096			break;
2097		case AUTH_CONNECTION:
2098			pfd[j].fd = sockets[i].fd;
2099			pfd[j].revents = 0;
2100			/*
2101			 * Only prepare to read if we can handle a full-size
2102			 * input read buffer and enqueue a max size reply..
2103			 */
2104			if ((r = sshbuf_check_reserve(sockets[i].input,
2105			    AGENT_RBUF_LEN)) == 0 &&
2106			    (r = sshbuf_check_reserve(sockets[i].output,
2107			    AGENT_MAX_LEN)) == 0)
2108				pfd[j].events = POLLIN;
2109			else if (r != SSH_ERR_NO_BUFFER_SPACE)
2110				fatal_fr(r, "reserve");
2111			if (sshbuf_len(sockets[i].output) > 0)
2112				pfd[j].events |= POLLOUT;
2113			j++;
2114			break;
2115		default:
2116			break;
2117		}
2118	}
2119	deadline = reaper();
2120	if (parent_alive_interval != 0)
2121		deadline = (deadline == 0) ? parent_alive_interval :
2122		    MINIMUM(deadline, parent_alive_interval);
2123	if (deadline == 0) {
2124		*timeoutp = -1; /* INFTIM */
2125	} else {
2126		if (deadline > INT_MAX / 1000)
2127			*timeoutp = INT_MAX / 1000;
2128		else
2129			*timeoutp = deadline * 1000;
2130	}
2131	return (1);
2132}
2133
2134static void
2135cleanup_socket(void)
2136{
2137	if (cleanup_pid != 0 && getpid() != cleanup_pid)
2138		return;
2139	debug_f("cleanup");
2140	if (socket_name[0])
2141		unlink(socket_name);
2142	if (socket_dir[0])
2143		rmdir(socket_dir);
2144}
2145
2146void
2147cleanup_exit(int i)
2148{
2149	cleanup_socket();
2150	_exit(i);
2151}
2152
2153/*ARGSUSED*/
2154__dead static void
2155cleanup_handler(int sig)
2156{
2157	cleanup_socket();
2158#ifdef ENABLE_PKCS11
2159	pkcs11_terminate();
2160#endif
2161	_exit(2);
2162}
2163
2164static void
2165check_parent_exists(void)
2166{
2167	/*
2168	 * If our parent has exited then getppid() will return (pid_t)1,
2169	 * so testing for that should be safe.
2170	 */
2171	if (parent_pid != -1 && getppid() != parent_pid) {
2172		/* printf("Parent has died - Authentication agent exiting.\n"); */
2173		cleanup_socket();
2174		_exit(2);
2175	}
2176}
2177
2178__dead static void
2179usage(void)
2180{
2181	fprintf(stderr,
2182	    "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
2183	    "                 [-O option] [-P allowed_providers] [-t life]\n"
2184	    "       ssh-agent [-a bind_address] [-E fingerprint_hash] [-O option]\n"
2185	    "                 [-P allowed_providers] [-t life] command [arg ...]\n"
2186	    "       ssh-agent [-c | -s] -k\n");
2187	exit(1);
2188}
2189
2190static void
2191csh_setenv(const char *name, const char *value)
2192{
2193	printf("setenv %s %s;\n", name, value);
2194}
2195
2196static void
2197csh_unsetenv(const char *name)
2198{
2199	printf("unsetenv %s;\n", name);
2200}
2201
2202static void
2203sh_setenv(const char *name, const char *value)
2204{
2205	printf("%s=%s; export %s;\n", name, value, name);
2206}
2207
2208static void
2209sh_unsetenv(const char *name)
2210{
2211	printf("unset %s;\n", name);
2212}
2213int
2214main(int ac, char **av)
2215{
2216	int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0;
2217	int sock, ch, result, saved_errno;
2218	char *shell, *pidstr, *agentsocket = NULL;
2219	struct rlimit rlim;
2220	void (*f_setenv)(const char *, const char *);
2221	void (*f_unsetenv)(const char *);
2222	extern int optind;
2223	extern char *optarg;
2224	pid_t pid;
2225	char pidstrbuf[1 + 3 * sizeof pid];
2226	size_t len;
2227	mode_t prev_mask;
2228	int timeout = -1; /* INFTIM */
2229	struct pollfd *pfd = NULL;
2230	size_t npfd = 0;
2231	u_int maxfds;
2232
2233	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2234	sanitise_stdfd();
2235
2236	/* drop */
2237	(void)setegid(getgid());
2238	(void)setgid(getgid());
2239
2240	if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
2241		fatal("%s: getrlimit: %s", __progname, strerror(errno));
2242
2243#ifdef WITH_OPENSSL
2244	OpenSSL_add_all_algorithms();
2245#endif
2246
2247	while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) {
2248		switch (ch) {
2249		case 'E':
2250			fingerprint_hash = ssh_digest_alg_by_name(optarg);
2251			if (fingerprint_hash == -1)
2252				fatal("Invalid hash algorithm \"%s\"", optarg);
2253			break;
2254		case 'c':
2255			if (s_flag)
2256				usage();
2257			c_flag++;
2258			break;
2259		case 'k':
2260			k_flag++;
2261			break;
2262		case 'O':
2263			if (strcmp(optarg, "no-restrict-websafe") == 0)
2264				restrict_websafe = 0;
2265			else if (strcmp(optarg, "allow-remote-pkcs11") == 0)
2266				remote_add_provider = 1;
2267			else
2268				fatal("Unknown -O option");
2269			break;
2270		case 'P':
2271			if (allowed_providers != NULL)
2272				fatal("-P option already specified");
2273			allowed_providers = xstrdup(optarg);
2274			break;
2275		case 's':
2276			if (c_flag)
2277				usage();
2278			s_flag++;
2279			break;
2280		case 'd':
2281			if (d_flag || D_flag)
2282				usage();
2283			d_flag++;
2284			break;
2285		case 'D':
2286			if (d_flag || D_flag)
2287				usage();
2288			D_flag++;
2289			break;
2290		case 'a':
2291			agentsocket = optarg;
2292			break;
2293		case 't':
2294			if ((lifetime = convtime(optarg)) == -1) {
2295				fprintf(stderr, "Invalid lifetime\n");
2296				usage();
2297			}
2298			break;
2299		default:
2300			usage();
2301		}
2302	}
2303	ac -= optind;
2304	av += optind;
2305
2306	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag))
2307		usage();
2308
2309	if (allowed_providers == NULL)
2310		allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS);
2311
2312	if (ac == 0 && !c_flag && !s_flag) {
2313		shell = getenv("SHELL");
2314		if (shell != NULL && (len = strlen(shell)) > 2 &&
2315		    strncmp(shell + len - 3, "csh", 3) == 0)
2316			c_flag = 1;
2317	}
2318	if (c_flag) {
2319		f_setenv = csh_setenv;
2320		f_unsetenv = csh_unsetenv;
2321	} else {
2322		f_setenv = sh_setenv;
2323		f_unsetenv = sh_unsetenv;
2324	}
2325	if (k_flag) {
2326		const char *errstr = NULL;
2327
2328		pidstr = getenv(SSH_AGENTPID_ENV_NAME);
2329		if (pidstr == NULL) {
2330			fprintf(stderr, "%s not set, cannot kill agent\n",
2331			    SSH_AGENTPID_ENV_NAME);
2332			exit(1);
2333		}
2334		pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr);
2335		if (errstr) {
2336			fprintf(stderr,
2337			    "%s=\"%s\", which is not a good PID: %s\n",
2338			    SSH_AGENTPID_ENV_NAME, pidstr, errstr);
2339			exit(1);
2340		}
2341		if (kill(pid, SIGTERM) == -1) {
2342			perror("kill");
2343			exit(1);
2344		}
2345		(*f_unsetenv)(SSH_AUTHSOCKET_ENV_NAME);
2346		(*f_unsetenv)(SSH_AGENTPID_ENV_NAME);
2347		printf("echo Agent pid %ld killed;\n", (long)pid);
2348		exit(0);
2349	}
2350
2351	/*
2352	 * Minimum file descriptors:
2353	 * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) +
2354	 * a few spare for libc / stack protectors / sanitisers, etc.
2355	 */
2356#define SSH_AGENT_MIN_FDS (3+1+1+1+4)
2357	if (rlim.rlim_cur < SSH_AGENT_MIN_FDS)
2358		fatal("%s: file descriptor rlimit %lld too low (minimum %u)",
2359		    __progname, (long long)rlim.rlim_cur, SSH_AGENT_MIN_FDS);
2360	maxfds = rlim.rlim_cur - SSH_AGENT_MIN_FDS;
2361
2362	parent_pid = getpid();
2363
2364	if (agentsocket == NULL) {
2365		/* Create private directory for agent socket */
2366		mktemp_proto(socket_dir, sizeof(socket_dir));
2367		if (mkdtemp(socket_dir) == NULL) {
2368			perror("mkdtemp: private socket dir");
2369			exit(1);
2370		}
2371		snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
2372		    (long)parent_pid);
2373	} else {
2374		/* Try to use specified agent socket */
2375		socket_dir[0] = '\0';
2376		strlcpy(socket_name, agentsocket, sizeof socket_name);
2377	}
2378
2379	/*
2380	 * Create socket early so it will exist before command gets run from
2381	 * the parent.
2382	 */
2383	prev_mask = umask(0177);
2384	sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0);
2385	if (sock < 0) {
2386		/* XXX - unix_listener() calls error() not perror() */
2387		*socket_name = '\0'; /* Don't unlink any existing file */
2388		cleanup_exit(1);
2389	}
2390	umask(prev_mask);
2391
2392	/*
2393	 * Fork, and have the parent execute the command, if any, or present
2394	 * the socket data.  The child continues as the authentication agent.
2395	 */
2396	if (D_flag || d_flag) {
2397		log_init(__progname,
2398		    d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO,
2399		    SYSLOG_FACILITY_AUTH, 1);
2400		if (c_flag)
2401			printf("setenv %s %s;\n",
2402			    SSH_AUTHSOCKET_ENV_NAME, socket_name);
2403		else
2404			printf("%s=%s; export %s;\n",
2405			    SSH_AUTHSOCKET_ENV_NAME, socket_name,
2406			    SSH_AUTHSOCKET_ENV_NAME);
2407		printf("echo Agent pid %ld;\n", (long)parent_pid);
2408		fflush(stdout);
2409		goto skip;
2410	}
2411	pid = fork();
2412	if (pid == -1) {
2413		perror("fork");
2414		cleanup_exit(1);
2415	}
2416	if (pid != 0) {		/* Parent - execute the given command. */
2417		close(sock);
2418		snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
2419		if (ac == 0) {
2420			(*f_setenv)(SSH_AUTHSOCKET_ENV_NAME, socket_name);
2421			(*f_setenv)(SSH_AGENTPID_ENV_NAME, pidstrbuf);
2422			printf("echo Agent pid %ld;\n", (long)pid);
2423			exit(0);
2424		}
2425		if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
2426		    setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
2427			perror("setenv");
2428			exit(1);
2429		}
2430		execvp(av[0], av);
2431		perror(av[0]);
2432		exit(1);
2433	}
2434	/* child */
2435	log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
2436
2437	if (setsid() == -1) {
2438		error("setsid: %s", strerror(errno));
2439		cleanup_exit(1);
2440	}
2441
2442	(void)chdir("/");
2443	if (stdfd_devnull(1, 1, 1) == -1)
2444		error_f("stdfd_devnull failed");
2445
2446	/* deny core dumps, since memory contains unencrypted private keys */
2447	rlim.rlim_cur = rlim.rlim_max = 0;
2448	if (setrlimit(RLIMIT_CORE, &rlim) == -1) {
2449		error("setrlimit RLIMIT_CORE: %s", strerror(errno));
2450		cleanup_exit(1);
2451	}
2452
2453skip:
2454
2455	cleanup_pid = getpid();
2456
2457#ifdef ENABLE_PKCS11
2458	pkcs11_init(0);
2459#endif
2460	new_socket(AUTH_SOCKET, sock);
2461	if (ac > 0)
2462		parent_alive_interval = 10;
2463	idtab_init();
2464	ssh_signal(SIGPIPE, SIG_IGN);
2465	ssh_signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN);
2466	ssh_signal(SIGHUP, cleanup_handler);
2467	ssh_signal(SIGTERM, cleanup_handler);
2468
2469#ifdef __OpenBSD__
2470	if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1)
2471		fatal("%s: pledge: %s", __progname, strerror(errno));
2472#endif
2473
2474	while (1) {
2475		prepare_poll(&pfd, &npfd, &timeout, maxfds);
2476		result = poll(pfd, npfd, timeout);
2477		saved_errno = errno;
2478		if (parent_alive_interval != 0)
2479			check_parent_exists();
2480		(void) reaper();	/* remove expired keys */
2481		if (result == -1) {
2482			if (saved_errno == EINTR)
2483				continue;
2484			fatal("poll: %s", strerror(saved_errno));
2485		} else if (result > 0)
2486			after_poll(pfd, npfd, maxfds);
2487	}
2488	/* NOTREACHED */
2489}
2490