11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: ssh-agent.c,v 1.172 2011/06/03 01:37:40 dtucker Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Author: Tatu Ylonen <ylo@cs.hut.fi>
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *                    All rights reserved
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * The authentication agent program.
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * As far as I am concerned, the code I have written for this software
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be used freely for any purpose.  Any derived versions of this
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * software must be clearly marked as such, and if the derived work is
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * incompatible with the protocol description in the RFC file, it must be
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called by a name other than "ssh" or "Secure Shell".
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h>
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/resource.h>
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/stat.h>
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_TIME_H
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/time.h>
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_UN_H
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/un.h>
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h"
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/evp.h>
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/md5.h>
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/openssl-compat.h"
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <fcntl.h>
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PATHS_H
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <paths.h>
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h>
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h>
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <time.h>
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h>
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh.h"
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "rsa.h"
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "authfd.h"
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "compat.h"
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef ENABLE_PKCS11
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh-pkcs11.h"
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(HAVE_SYS_PRCTL_H)
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/prctl.h>	/* For prctl() and PR_SET_DUMPABLE */
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef enum {
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	AUTH_UNUSED,
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	AUTH_SOCKET,
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	AUTH_CONNECTION
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} sock_type;
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef struct {
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int fd;
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sock_type type;
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer input;
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer output;
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer request;
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} SocketEntry;
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_int sockets_alloc = 0;
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodSocketEntry *sockets = NULL;
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef struct identity {
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_ENTRY(identity) next;
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *key;
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *comment;
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *provider;
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int death;
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int confirm;
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} Identity;
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef struct {
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int nentries;
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_HEAD(idqueue, identity) idlist;
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} Idtab;
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* private key table, one per protocol version */
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodIdtab idtable[3];
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint max_fd = 0;
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* pid of shell == parent of agent */
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpid_t parent_pid = -1;
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_int parent_alive_interval = 0;
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* pathname and directory for AUTH_SOCKET */
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar socket_name[MAXPATHLEN];
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar socket_dir[MAXPATHLEN];
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* locking */
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint locked = 0;
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *lock_passwd = NULL;
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern char *__progname;
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Default lifetime (0 == forever) */
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int lifetime = 0;
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodclose_socket(SocketEntry *e)
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(e->fd);
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	e->fd = -1;
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	e->type = AUTH_UNUSED;
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&e->input);
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&e->output);
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&e->request);
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodidtab_init(void)
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i <=2; i++) {
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_INIT(&idtable[i].idlist);
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		idtable[i].nentries = 0;
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* return private key table for requested protocol version */
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Idtab *
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodidtab_lookup(int version)
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (version < 1 || version > 2)
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("internal error, bad protocol version %d", version);
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return &idtable[version];
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfree_identity(Identity *id)
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_free(id->key);
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (id->provider != NULL)
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(id->provider);
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(id->comment);
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(id);
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* return matching private key for given public key */
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Identity *
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodlookup_identity(Key *key, int version)
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id;
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Idtab *tab = idtab_lookup(version);
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_FOREACH(id, &tab->idlist, next) {
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key_equal(key, id->key))
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (id);
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (NULL);
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Check confirmation of keysign request */
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconfirm_key(Identity *id)
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *p;
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret = -1;
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    id->comment, p))
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ret = 0;
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(p);
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (ret);
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* send list of supported public keys to 'client' */
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_request_identities(SocketEntry *e, int version)
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Idtab *tab = idtab_lookup(version);
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id;
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer msg;
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&msg);
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&msg, (version == 1) ?
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&msg, tab->nentries);
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_FOREACH(id, &tab->idlist, next) {
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (id->key->type == KEY_RSA1) {
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_bignum(&msg, id->key->rsa->e);
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_bignum(&msg, id->key->rsa->n);
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			u_char *blob;
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			u_int blen;
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_to_blob(id->key, &blob, &blen);
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_string(&msg, blob, blen);
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(blob);
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&msg, id->comment);
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, buffer_len(&msg));
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&msg);
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ssh1 only */
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_authentication_challenge1(SocketEntry *e)
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char buf[32], mdbuf[16], session_id[16];
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int response_type;
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BIGNUM *challenge;
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id;
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i, len;
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer msg;
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	MD5_CTX md;
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *key;
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&msg);
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key = key_new(KEY_RSA1);
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((challenge = BN_new()) == NULL)
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("process_authentication_challenge1: BN_new failed");
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	(void) buffer_get_int(&e->request);			/* ignored */
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_get_bignum(&e->request, key->rsa->e);
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_get_bignum(&e->request, key->rsa->n);
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_get_bignum(&e->request, challenge);
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Only protocol 1.1 is supported */
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&e->request) == 0)
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto failure;
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_get(&e->request, session_id, 16);
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	response_type = buffer_get_int(&e->request);
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (response_type != 1)
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto failure;
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	id = lookup_identity(key, 1);
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (id != NULL && (!id->confirm || confirm_key(id) == 0)) {
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Key *private = id->key;
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Decrypt the challenge using the private key. */
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto failure;
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* The response is MD5 of decrypted challenge plus session id. */
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		len = BN_num_bytes(challenge);
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len <= 0 || len > 32) {
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			logit("process_authentication_challenge: bad challenge length %d", len);
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto failure;
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(buf, 0, 32);
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		BN_bn2bin(challenge, buf + 32 - len);
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		MD5_Init(&md);
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		MD5_Update(&md, buf, 32);
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		MD5_Update(&md, session_id, 16);
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		MD5_Final(mdbuf, &md);
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Send the response. */
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < 16; i++)
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_char(&msg, mdbuf[i]);
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto send;
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfailure:
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Unknown identity or protocol error.  Send failure. */
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&msg, SSH_AGENT_FAILURE);
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsend:
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, buffer_len(&msg));
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_free(key);
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BN_clear_free(challenge);
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&msg);
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ssh2 only */
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_sign_request2(SocketEntry *e)
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *blob, *data, *signature = NULL;
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int blen, dlen, slen = 0;
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	extern int datafellows;
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int odatafellows;
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ok = -1, flags;
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer msg;
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *key;
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	datafellows = 0;
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	blob = buffer_get_string(&e->request, &blen);
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	data = buffer_get_string(&e->request, &dlen);
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	flags = buffer_get_int(&e->request);
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	odatafellows = datafellows;
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (flags & SSH_AGENT_OLD_SIGNATURE)
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		datafellows = SSH_BUG_SIGBLOB;
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key = key_from_blob(blob, blen);
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key != NULL) {
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Identity *id = lookup_identity(key, 2);
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (id != NULL && (!id->confirm || confirm_key(id) == 0))
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ok = key_sign(id->key, &signature, &slen, data, dlen);
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_free(key);
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&msg);
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ok == 0) {
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_string(&msg, signature, slen);
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_char(&msg, SSH_AGENT_FAILURE);
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, buffer_len(&msg));
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&e->output, buffer_ptr(&msg),
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_len(&msg));
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&msg);
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(data);
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(blob);
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (signature != NULL)
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(signature);
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	datafellows = odatafellows;
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* shared */
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_remove_identity(SocketEntry *e, int version)
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int blen, bits;
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int success = 0;
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *key = NULL;
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *blob;
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (version) {
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 1:
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key = key_new(KEY_RSA1);
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		bits = buffer_get_int(&e->request);
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_get_bignum(&e->request, key->rsa->e);
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_get_bignum(&e->request, key->rsa->n);
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (bits != key_size(key))
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			logit("Warning: identity keysize mismatch: actual %u, announced %u",
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    key_size(key), bits);
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 2:
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		blob = buffer_get_string(&e->request, &blen);
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key = key_from_blob(blob, blen);
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(blob);
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key != NULL) {
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Identity *id = lookup_identity(key, version);
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (id != NULL) {
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * We have this key.  Free the old key.  Since we
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * don't want to leave empty slots in the middle of
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * the array, we actually free the key there and move
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * all the entries between the empty slot and the end
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * of the array.
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			Idtab *tab = idtab_lookup(version);
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (tab->nentries < 1)
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("process_remove_identity: "
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    "internal error: tab->nentries %d",
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    tab->nentries);
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			TAILQ_REMOVE(&tab->idlist, id, next);
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			free_identity(id);
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			tab->nentries--;
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = 1;
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_free(key);
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, 1);
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&e->output,
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_remove_all_identities(SocketEntry *e, int version)
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Idtab *tab = idtab_lookup(version);
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id;
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Loop over all identities and clear the keys. */
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (id = TAILQ_FIRST(&tab->idlist); id;
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    id = TAILQ_FIRST(&tab->idlist)) {
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_REMOVE(&tab->idlist, id, next);
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		free_identity(id);
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Mark that there are no identities. */
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	tab->nentries = 0;
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Send success. */
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, 1);
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* removes expired keys and returns number of seconds until the next expiry */
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic u_int
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodreaper(void)
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int deadline = 0, now = time(NULL);
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id, *nxt;
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int version;
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Idtab *tab;
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (version = 1; version < 3; version++) {
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tab = idtab_lookup(version);
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			nxt = TAILQ_NEXT(id, next);
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (id->death == 0)
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (now >= id->death) {
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("expiring key '%s'", id->comment);
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				TAILQ_REMOVE(&tab->idlist, id, next);
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				free_identity(id);
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				tab->nentries--;
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				deadline = (deadline == 0) ? id->death :
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    MIN(deadline, id->death);
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (deadline == 0 || deadline <= now)
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (deadline - now);
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_add_identity(SocketEntry *e, int version)
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Idtab *tab = idtab_lookup(version);
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id;
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int type, success = 0, death = 0, confirm = 0;
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *type_name, *comment;
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *k = NULL;
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BIGNUM *exponent;
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EC_POINT *q;
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *curve;
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *cert;
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len;
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (version) {
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 1:
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k = key_new_private(KEY_RSA1);
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void) buffer_get_int(&e->request);		/* ignored */
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_get_bignum(&e->request, k->rsa->n);
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_get_bignum(&e->request, k->rsa->e);
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_get_bignum(&e->request, k->rsa->d);
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_get_bignum(&e->request, k->rsa->iqmp);
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* SSH and SSL have p and q swapped */
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_get_bignum(&e->request, k->rsa->q);	/* p */
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_get_bignum(&e->request, k->rsa->p);	/* q */
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Generate additional parameters */
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rsa_generate_additional_parameters(k->rsa);
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case 2:
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		type_name = buffer_get_string(&e->request, NULL);
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		type = key_type_from_name(type_name);
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (type) {
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_DSA:
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k = key_new_private(type);
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->dsa->p);
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->dsa->q);
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->dsa->g);
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->dsa->pub_key);
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->dsa->priv_key);
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_DSA_CERT_V00:
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_DSA_CERT:
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cert = buffer_get_string(&e->request, &len);
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((k = key_from_blob(cert, len)) == NULL)
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("Certificate parse failed");
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(cert);
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_add_private(k);
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->dsa->priv_key);
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_ECDSA:
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k = key_new_private(type);
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k->ecdsa_nid = key_ecdsa_nid_from_name(type_name);
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			curve = buffer_get_string(&e->request, NULL);
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (k->ecdsa_nid != key_curve_name_to_nid(curve))
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: curve names mismatch", __func__);
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(curve);
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (k->ecdsa == NULL)
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: EC_KEY_new_by_curve_name failed",
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    __func__);
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa));
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (q == NULL)
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: BN_new failed", __func__);
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((exponent = BN_new()) == NULL)
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: BN_new failed", __func__);
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_ecpoint(&e->request,
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				EC_KEY_get0_group(k->ecdsa), q);
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, exponent);
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (EC_KEY_set_public_key(k->ecdsa, q) != 1)
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: EC_KEY_set_public_key failed",
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    __func__);
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: EC_KEY_set_private_key failed",
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    __func__);
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    EC_KEY_get0_public_key(k->ecdsa)) != 0)
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: bad ECDSA public key", __func__);
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (key_ec_validate_private(k->ecdsa) != 0)
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: bad ECDSA private key", __func__);
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			BN_clear_free(exponent);
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			EC_POINT_free(q);
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_ECDSA_CERT:
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cert = buffer_get_string(&e->request, &len);
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((k = key_from_blob(cert, len)) == NULL)
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("Certificate parse failed");
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(cert);
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_add_private(k);
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((exponent = BN_new()) == NULL)
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: BN_new failed", __func__);
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, exponent);
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: EC_KEY_set_private_key failed",
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    __func__);
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    EC_KEY_get0_public_key(k->ecdsa)) != 0 ||
5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    key_ec_validate_private(k->ecdsa) != 0)
5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("%s: bad ECDSA key", __func__);
5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			BN_clear_free(exponent);
5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */
5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_RSA:
5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k = key_new_private(type);
5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->n);
5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->e);
5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->d);
5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->iqmp);
5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->p);
5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->q);
5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* Generate additional parameters */
5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			rsa_generate_additional_parameters(k->rsa);
5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_RSA_CERT_V00:
5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case KEY_RSA_CERT:
5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cert = buffer_get_string(&e->request, &len);
5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((k = key_from_blob(cert, len)) == NULL)
5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("Certificate parse failed");
5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(cert);
5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_add_private(k);
5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->d);
5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->iqmp);
5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->p);
5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_get_bignum2(&e->request, k->rsa->q);
5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(type_name);
5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_clear(&e->request);
5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto send;
5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(type_name);
5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* enable blinding */
6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT_V00:
6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA_CERT:
6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (RSA_blinding_on(k->rsa, NULL) != 1) {
6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("process_add_identity: RSA_blinding_on failed");
6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_free(k);
6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto send;
6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	comment = buffer_get_string(&e->request, NULL);
6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (k == NULL) {
6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(comment);
6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto send;
6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (buffer_len(&e->request)) {
6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch ((type = buffer_get_char(&e->request))) {
6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_AGENT_CONSTRAIN_LIFETIME:
6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			death = time(NULL) + buffer_get_int(&e->request);
6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_AGENT_CONSTRAIN_CONFIRM:
6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			confirm = 1;
6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("process_add_identity: "
6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "Unknown constraint type %d", type);
6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(comment);
6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_free(k);
6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto send;
6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	success = 1;
6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (lifetime && !death)
6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		death = time(NULL) + lifetime;
6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((id = lookup_identity(k, version)) == NULL) {
6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		id = xcalloc(1, sizeof(Identity));
6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		id->key = k;
6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_INSERT_TAIL(&tab->idlist, id, next);
6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Increment the number of identities. */
6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tab->nentries++;
6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_free(k);
6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(id->comment);
6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	id->comment = comment;
6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	id->death = death;
6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	id->confirm = confirm;
6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsend:
6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, 1);
6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&e->output,
6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* XXX todo: encrypt sensitive data with passphrase */
6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_lock_agent(SocketEntry *e, int lock)
6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int success = 0;
6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *passwd;
6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	passwd = buffer_get_string(&e->request, NULL);
6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (locked && !lock && strcmp(passwd, lock_passwd) == 0) {
6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		locked = 0;
6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(lock_passwd, 0, strlen(lock_passwd));
6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(lock_passwd);
6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		lock_passwd = NULL;
6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		success = 1;
6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (!locked && lock) {
6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		locked = 1;
6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		lock_passwd = xstrdup(passwd);
6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		success = 1;
6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(passwd, 0, strlen(passwd));
6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(passwd);
6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, 1);
6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&e->output,
6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodno_identities(SocketEntry *e, u_int type)
6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer msg;
6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&msg);
6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&msg,
6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ?
6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&msg, 0);
6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, buffer_len(&msg));
6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&msg);
6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef ENABLE_PKCS11
7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_add_smartcard_key(SocketEntry *e)
7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *provider = NULL, *pin;
7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i, type, version, count = 0, success = 0, death = 0, confirm = 0;
7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key **keys = NULL, *k;
7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id;
7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Idtab *tab;
7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	provider = buffer_get_string(&e->request, NULL);
7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pin = buffer_get_string(&e->request, NULL);
7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (buffer_len(&e->request)) {
7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch ((type = buffer_get_char(&e->request))) {
7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_AGENT_CONSTRAIN_LIFETIME:
7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			death = time(NULL) + buffer_get_int(&e->request);
7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_AGENT_CONSTRAIN_CONFIRM:
7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			confirm = 1;
7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("process_add_smartcard_key: "
7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "Unknown constraint type %d", type);
7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			goto send;
7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (lifetime && !death)
7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		death = time(NULL) + lifetime;
7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	count = pkcs11_add_provider(provider, pin, &keys);
7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < count; i++) {
7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		k = keys[i];
7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		version = k->type == KEY_RSA1 ? 1 : 2;
7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tab = idtab_lookup(version);
7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (lookup_identity(k, version) == NULL) {
7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			id = xcalloc(1, sizeof(Identity));
7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			id->key = k;
7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			id->provider = xstrdup(provider);
7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			id->comment = xstrdup(provider); /* XXX */
7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			id->death = death;
7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			id->confirm = confirm;
7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			TAILQ_INSERT_TAIL(&tab->idlist, id, next);
7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			tab->nentries++;
7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			success = 1;
7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_free(k);
7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		keys[i] = NULL;
7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsend:
7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pin)
7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(pin);
7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (provider)
7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(provider);
7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (keys)
7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(keys);
7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, 1);
7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&e->output,
7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_remove_smartcard_key(SocketEntry *e)
7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *provider = NULL, *pin = NULL;
7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int version, success = 0;
7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id, *nxt;
7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Idtab *tab;
7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	provider = buffer_get_string(&e->request, NULL);
7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pin = buffer_get_string(&e->request, NULL);
7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(pin);
7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (version = 1; version < 3; version++) {
7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tab = idtab_lookup(version);
7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			nxt = TAILQ_NEXT(id, next);
7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!strcmp(provider, id->provider)) {
7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				TAILQ_REMOVE(&tab->idlist, id, next);
7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				free_identity(id);
7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				tab->nentries--;
7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pkcs11_del_provider(provider) == 0)
7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		success = 1;
7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("process_remove_smartcard_key:"
7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    " pkcs11_del_provider failed");
7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(provider);
7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&e->output, 1);
7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&e->output,
7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* ENABLE_PKCS11 */
7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* dispatch incoming messages */
7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_message(SocketEntry *e)
8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int msg_len, type;
8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *cp;
8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&e->input) < 5)
8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;		/* Incomplete message. */
8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cp = buffer_ptr(&e->input);
8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	msg_len = get_u32(cp);
8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (msg_len > 256 * 1024) {
8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close_socket(e);
8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&e->input) < msg_len + 4)
8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* move the current input to e->request */
8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_consume(&e->input, 4);
8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_clear(&e->request);
8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&e->request, buffer_ptr(&e->input), msg_len);
8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_consume(&e->input, msg_len);
8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	type = buffer_get_char(&e->request);
8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* check wheter agent is locked */
8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (locked && type != SSH_AGENTC_UNLOCK) {
8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_clear(&e->request);
8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (type) {
8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case SSH2_AGENTC_REQUEST_IDENTITIES:
8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* send empty lists */
8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			no_identities(e, type);
8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* send a fail message for all other request types */
8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_int(&e->output, 1);
8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_char(&e->output, SSH_AGENT_FAILURE);
8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("type %d", type);
8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (type) {
8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_LOCK:
8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_UNLOCK:
8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_lock_agent(e, type == SSH_AGENTC_LOCK);
8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* ssh1 */
8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_RSA_CHALLENGE:
8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_authentication_challenge1(e);
8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_request_identities(e, 1);
8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_ADD_RSA_IDENTITY:
8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_add_identity(e, 1);
8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_REMOVE_RSA_IDENTITY:
8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_remove_identity(e, 1);
8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_remove_all_identities(e, 1);
8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* ssh2 */
8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH2_AGENTC_SIGN_REQUEST:
8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_sign_request2(e);
8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH2_AGENTC_REQUEST_IDENTITIES:
8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_request_identities(e, 2);
8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH2_AGENTC_ADD_IDENTITY:
8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH2_AGENTC_ADD_ID_CONSTRAINED:
8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_add_identity(e, 2);
8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH2_AGENTC_REMOVE_IDENTITY:
8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_remove_identity(e, 2);
8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_remove_all_identities(e, 2);
8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef ENABLE_PKCS11
8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_ADD_SMARTCARD_KEY:
8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_add_smartcard_key(e);
8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		process_remove_smartcard_key(e);
8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* ENABLE_PKCS11 */
8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Unknown message.  Respond with failure. */
8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Unknown message %d", type);
8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_clear(&e->request);
8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_int(&e->output, 1);
8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_char(&e->output, SSH_AGENT_FAILURE);
8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodnew_socket(sock_type type, int fd)
9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, old_alloc, new_alloc;
9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	set_nonblock(fd);
9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fd > max_fd)
9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		max_fd = fd;
9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sockets_alloc; i++)
9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (sockets[i].type == AUTH_UNUSED) {
9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			sockets[i].fd = fd;
9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_init(&sockets[i].input);
9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_init(&sockets[i].output);
9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_init(&sockets[i].request);
9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			sockets[i].type = type;
9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	old_alloc = sockets_alloc;
9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	new_alloc = sockets_alloc + 10;
9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sockets = xrealloc(sockets, new_alloc, sizeof(sockets[0]));
9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = old_alloc; i < new_alloc; i++)
9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sockets[i].type = AUTH_UNUSED;
9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sockets_alloc = new_alloc;
9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sockets[old_alloc].fd = fd;
9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&sockets[old_alloc].input);
9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&sockets[old_alloc].output);
9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&sockets[old_alloc].request);
9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sockets[old_alloc].type = type;
9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    struct timeval **tvpp)
9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, sz, deadline;
9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int n = 0;
9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static struct timeval tv;
9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sockets_alloc; i++) {
9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (sockets[i].type) {
9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case AUTH_SOCKET:
9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case AUTH_CONNECTION:
9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			n = MAX(n, sockets[i].fd);
9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case AUTH_UNUSED:
9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
9471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("Unknown socket type %d", sockets[i].type);
9481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
9531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*fdrp == NULL || sz > *nallocp) {
9541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*fdrp)
9551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(*fdrp);
9561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*fdwp)
9571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(*fdwp);
9581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*fdrp = xmalloc(sz);
9591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*fdwp = xmalloc(sz);
9601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*nallocp = sz;
9611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n < *fdl)
9631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("XXX shrink: %d < %d", n, *fdl);
9641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*fdl = n;
9651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(*fdrp, 0, sz);
9661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(*fdwp, 0, sz);
9671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sockets_alloc; i++) {
9691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (sockets[i].type) {
9701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case AUTH_SOCKET:
9711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case AUTH_CONNECTION:
9721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			FD_SET(sockets[i].fd, *fdrp);
9731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (buffer_len(&sockets[i].output) > 0)
9741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				FD_SET(sockets[i].fd, *fdwp);
9751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
9771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
9781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	deadline = reaper();
9811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (parent_alive_interval != 0)
9821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		deadline = (deadline == 0) ? parent_alive_interval :
9831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    MIN(deadline, parent_alive_interval);
9841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (deadline == 0) {
9851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*tvpp = NULL;
9861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
9871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tv.tv_sec = deadline;
9881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		tv.tv_usec = 0;
9891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*tvpp = &tv;
9901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (1);
9921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
9951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodafter_select(fd_set *readset, fd_set *writeset)
9961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_un sunaddr;
9981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	socklen_t slen;
9991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char buf[1024];
10001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int len, sock;
10011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i, orig_alloc;
10021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	uid_t euid;
10031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gid_t egid;
10041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++)
10061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (sockets[i].type) {
10071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case AUTH_UNUSED:
10081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
10091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case AUTH_SOCKET:
10101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (FD_ISSET(sockets[i].fd, readset)) {
10111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				slen = sizeof(sunaddr);
10121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				sock = accept(sockets[i].fd,
10131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    (struct sockaddr *)&sunaddr, &slen);
10141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (sock < 0) {
10151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("accept from AUTH_SOCKET: %s",
10161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    strerror(errno));
10171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
10181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (getpeereid(sock, &euid, &egid) < 0) {
10201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("getpeereid %d failed: %s",
10211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    sock, strerror(errno));
10221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					close(sock);
10231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
10241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if ((euid != 0) && (getuid() != euid)) {
10261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					error("uid mismatch: "
10271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    "peer euid %u != uid %u",
10281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					    (u_int) euid, (u_int) getuid());
10291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					close(sock);
10301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
10311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				new_socket(AUTH_CONNECTION, sock);
10331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
10341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
10351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case AUTH_CONNECTION:
10361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (buffer_len(&sockets[i].output) > 0 &&
10371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    FD_ISSET(sockets[i].fd, writeset)) {
10381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				len = write(sockets[i].fd,
10391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    buffer_ptr(&sockets[i].output),
10401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    buffer_len(&sockets[i].output));
10411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (len == -1 && (errno == EAGAIN ||
10421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    errno == EWOULDBLOCK ||
10431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    errno == EINTR))
10441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					continue;
10451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (len <= 0) {
10461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					close_socket(&sockets[i]);
10471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
10481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_consume(&sockets[i].output, len);
10501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
10511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (FD_ISSET(sockets[i].fd, readset)) {
10521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				len = read(sockets[i].fd, buf, sizeof(buf));
10531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (len == -1 && (errno == EAGAIN ||
10541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    errno == EWOULDBLOCK ||
10551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    errno == EINTR))
10561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					continue;
10571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (len <= 0) {
10581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					close_socket(&sockets[i]);
10591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
10601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
10611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(&sockets[i].input, buf, len);
10621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				process_message(&sockets[i]);
10631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
10641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
10651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
10661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("Unknown type %d", sockets[i].type);
10671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
10681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
10711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcleanup_socket(void)
10721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (socket_name[0])
10741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		unlink(socket_name);
10751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (socket_dir[0])
10761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rmdir(socket_dir);
10771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
10801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcleanup_exit(int i)
10811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cleanup_socket();
10831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	_exit(i);
10841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*ARGSUSED*/
10871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
10881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcleanup_handler(int sig)
10891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cleanup_socket();
10911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef ENABLE_PKCS11
10921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pkcs11_terminate();
10931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
10941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	_exit(2);
10951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
10981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcheck_parent_exists(void)
10991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
11011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * If our parent has exited then getppid() will return (pid_t)1,
11021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * so testing for that should be safe.
11031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
11041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (parent_pid != -1 && getppid() != parent_pid) {
11051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* printf("Parent has died - Authentication agent exiting.\n"); */
11061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cleanup_socket();
11071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		_exit(2);
11081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
11121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodusage(void)
11131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "usage: %s [options] [command [arg ...]]\n",
11151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    __progname);
11161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "Options:\n");
11171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "  -c          Generate C-shell commands on stdout.\n");
11181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "  -s          Generate Bourne shell commands on stdout.\n");
11191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "  -k          Kill the current agent.\n");
11201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "  -d          Debug mode.\n");
11211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "  -a socket   Bind agent socket to given name.\n");
11221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "  -t life     Default identity lifetime (seconds).\n");
11231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	exit(1);
11241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
11271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmain(int ac, char **av)
11281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0;
11301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int sock, fd, ch, result, saved_errno;
11311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int nalloc;
11321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *shell, *format, *pidstr, *agentsocket = NULL;
11331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fd_set *readsetp = NULL, *writesetp = NULL;
11341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_un sunaddr;
11351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SETRLIMIT
11361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct rlimit rlim;
11371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
11381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int prev_mask;
11391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	extern int optind;
11401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	extern char *optarg;
11411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pid_t pid;
11421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char pidstrbuf[1 + 3 * sizeof pid];
11431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct timeval *tvp = NULL;
11441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t len;
11451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
11471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sanitise_stdfd();
11481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* drop */
11501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	setegid(getgid());
11511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	setgid(getgid());
11521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
11541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Disable ptrace on Linux without sgid bit */
11551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	prctl(PR_SET_DUMPABLE, 0);
11561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
11571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	OpenSSL_add_all_algorithms();
11591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	__progname = ssh_get_progname(av[0]);
11611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	seed_rng();
11621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
11641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		switch (ch) {
11651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'c':
11661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (s_flag)
11671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				usage();
11681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			c_flag++;
11691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
11701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'k':
11711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			k_flag++;
11721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
11731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 's':
11741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (c_flag)
11751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				usage();
11761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			s_flag++;
11771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
11781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'd':
11791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (d_flag)
11801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				usage();
11811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			d_flag++;
11821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
11831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 'a':
11841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			agentsocket = optarg;
11851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
11861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		case 't':
11871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if ((lifetime = convtime(optarg)) == -1) {
11881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fprintf(stderr, "Invalid lifetime\n");
11891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				usage();
11901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
11911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
11921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		default:
11931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			usage();
11941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
11951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ac -= optind;
11971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	av += optind;
11981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
12001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		usage();
12011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ac == 0 && !c_flag && !s_flag) {
12031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		shell = getenv("SHELL");
12041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (shell != NULL && (len = strlen(shell)) > 2 &&
12051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strncmp(shell + len - 3, "csh", 3) == 0)
12061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			c_flag = 1;
12071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (k_flag) {
12091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		const char *errstr = NULL;
12101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pidstr = getenv(SSH_AGENTPID_ENV_NAME);
12121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (pidstr == NULL) {
12131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "%s not set, cannot kill agent\n",
12141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    SSH_AGENTPID_ENV_NAME);
12151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
12161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
12171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr);
12181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (errstr) {
12191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr,
12201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "%s=\"%s\", which is not a good PID: %s\n",
12211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    SSH_AGENTPID_ENV_NAME, pidstr, errstr);
12221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
12231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
12241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (kill(pid, SIGTERM) == -1) {
12251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("kill");
12261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
12271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
12281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
12291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		printf(format, SSH_AUTHSOCKET_ENV_NAME);
12301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		printf(format, SSH_AGENTPID_ENV_NAME);
12311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		printf("echo Agent pid %ld killed;\n", (long)pid);
12321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exit(0);
12331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	parent_pid = getpid();
12351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (agentsocket == NULL) {
12371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Create private directory for agent socket */
12381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		mktemp_proto(socket_dir, sizeof(socket_dir));
12391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (mkdtemp(socket_dir) == NULL) {
12401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("mkdtemp: private socket dir");
12411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
12421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
12431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
12441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    (long)parent_pid);
12451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
12461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Try to use specified agent socket */
12471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		socket_dir[0] = '\0';
12481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		strlcpy(socket_name, agentsocket, sizeof socket_name);
12491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
12521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Create socket early so it will exist before command gets run from
12531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the parent.
12541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
12551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sock = socket(AF_UNIX, SOCK_STREAM, 0);
12561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sock < 0) {
12571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		perror("socket");
12581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*socket_name = '\0'; /* Don't unlink any existing file */
12591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cleanup_exit(1);
12601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(&sunaddr, 0, sizeof(sunaddr));
12621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sunaddr.sun_family = AF_UNIX;
12631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
12641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	prev_mask = umask(0177);
12651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) {
12661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		perror("bind");
12671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*socket_name = '\0'; /* Don't unlink any existing file */
12681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		umask(prev_mask);
12691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cleanup_exit(1);
12701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	umask(prev_mask);
12721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
12731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		perror("listen");
12741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cleanup_exit(1);
12751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
12781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Fork, and have the parent execute the command, if any, or present
12791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the socket data.  The child continues as the authentication agent.
12801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
12811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (d_flag) {
12821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1);
12831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
12841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
12851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    SSH_AUTHSOCKET_ENV_NAME);
12861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		printf("echo Agent pid %ld;\n", (long)parent_pid);
12871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto skip;
12881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pid = fork();
12901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pid == -1) {
12911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		perror("fork");
12921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cleanup_exit(1);
12931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pid != 0) {		/* Parent - execute the given command. */
12951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(sock);
12961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
12971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (ac == 0) {
12981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
12991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
13001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    SSH_AUTHSOCKET_ENV_NAME);
13011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
13021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    SSH_AGENTPID_ENV_NAME);
13031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			printf("echo Agent pid %ld;\n", (long)pid);
13041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(0);
13051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
13061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
13071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
13081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			perror("setenv");
13091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			exit(1);
13101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
13111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		execvp(av[0], av);
13121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		perror(av[0]);
13131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		exit(1);
13141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* child */
13161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
13171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (setsid() == -1) {
13191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("setsid: %s", strerror(errno));
13201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cleanup_exit(1);
13211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	(void)chdir("/");
13241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
13251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* XXX might close listen socket */
13261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void)dup2(fd, STDIN_FILENO);
13271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void)dup2(fd, STDOUT_FILENO);
13281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void)dup2(fd, STDERR_FILENO);
13291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (fd > 2)
13301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			close(fd);
13311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SETRLIMIT
13341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* deny core dumps, since memory contains unencrypted private keys */
13351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	rlim.rlim_cur = rlim.rlim_max = 0;
13361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
13371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("setrlimit RLIMIT_CORE: %s", strerror(errno));
13381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		cleanup_exit(1);
13391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
13411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodskip:
13431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef ENABLE_PKCS11
13451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pkcs11_init(0);
13461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
13471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	new_socket(AUTH_SOCKET, sock);
13481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ac > 0)
13491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		parent_alive_interval = 10;
13501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	idtab_init();
13511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!d_flag)
13521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		signal(SIGINT, SIG_IGN);
13531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGPIPE, SIG_IGN);
13541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGHUP, cleanup_handler);
13551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGTERM, cleanup_handler);
13561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	nalloc = 0;
13571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (1) {
13591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
13601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
13611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		saved_errno = errno;
13621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (parent_alive_interval != 0)
13631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			check_parent_exists();
13641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void) reaper();	/* remove expired keys */
13651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (result < 0) {
13661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (saved_errno == EINTR)
13671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				continue;
13681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("select: %s", strerror(saved_errno));
13691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (result > 0)
13701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			after_select(readsetp, writesetp);
13711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* NOTREACHED */
13731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1374