1/* $OpenBSD: ssh-agent.c,v 1.172 2011/06/03 01:37:40 dtucker Exp $ */
2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 *                    All rights reserved
6 * The authentication agent program.
7 *
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose.  Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
13 *
14 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "includes.h"
38
39#include <sys/types.h>
40#include <sys/param.h>
41#include <sys/resource.h>
42#include <sys/stat.h>
43#include <sys/socket.h>
44#ifdef HAVE_SYS_TIME_H
45# include <sys/time.h>
46#endif
47#ifdef HAVE_SYS_UN_H
48# include <sys/un.h>
49#endif
50#include "openbsd-compat/sys-queue.h"
51
52#ifdef __APPLE_CRYPTO__
53#include "ossl-evp.h"
54#include "ossl-md5.h"
55#else
56#include <openssl/evp.h>
57#include <openssl/md5.h>
58#endif
59#include "openbsd-compat/openssl-compat.h"
60
61#include <errno.h>
62#include <fcntl.h>
63#ifdef HAVE_PATHS_H
64# include <paths.h>
65#endif
66#include <signal.h>
67#include <stdarg.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <time.h>
71#include <string.h>
72#include <unistd.h>
73#ifdef __APPLE_LAUNCHD__
74#include <launch.h>
75#endif
76
77#include "xmalloc.h"
78#include "ssh.h"
79#include "rsa.h"
80#include "buffer.h"
81#include "key.h"
82#include "authfd.h"
83#include "authfile.h"
84#include "compat.h"
85#include "log.h"
86#include "misc.h"
87#include "keychain.h"
88
89#ifdef ENABLE_PKCS11
90#include "ssh-pkcs11.h"
91#endif
92
93#if defined(HAVE_SYS_PRCTL_H)
94#include <sys/prctl.h>	/* For prctl() and PR_SET_DUMPABLE */
95#endif
96
97typedef enum {
98	AUTH_UNUSED,
99	AUTH_SOCKET,
100	AUTH_CONNECTION
101} sock_type;
102
103typedef struct {
104	int fd;
105	sock_type type;
106	Buffer input;
107	Buffer output;
108	Buffer request;
109} SocketEntry;
110
111u_int sockets_alloc = 0;
112SocketEntry *sockets = NULL;
113
114typedef struct identity {
115	TAILQ_ENTRY(identity) next;
116	Key *key;
117	char *comment;
118	char *provider;
119	u_int death;
120	u_int confirm;
121} Identity;
122
123typedef struct {
124	int nentries;
125	TAILQ_HEAD(idqueue, identity) idlist;
126} Idtab;
127
128/* private key table, one per protocol version */
129Idtab idtable[3];
130
131int max_fd = 0;
132
133/* pid of shell == parent of agent */
134pid_t parent_pid = -1;
135u_int parent_alive_interval = 0;
136
137/* pathname and directory for AUTH_SOCKET */
138char socket_name[MAXPATHLEN];
139char socket_dir[MAXPATHLEN];
140
141/* locking */
142int locked = 0;
143char *lock_passwd = NULL;
144
145extern char *__progname;
146
147/* Default lifetime (0 == forever) */
148static int lifetime = 0;
149
150static void
151close_socket(SocketEntry *e)
152{
153	close(e->fd);
154	e->fd = -1;
155	e->type = AUTH_UNUSED;
156	buffer_free(&e->input);
157	buffer_free(&e->output);
158	buffer_free(&e->request);
159}
160
161static void
162idtab_init(void)
163{
164	int i;
165
166	for (i = 0; i <=2; i++) {
167		TAILQ_INIT(&idtable[i].idlist);
168		idtable[i].nentries = 0;
169	}
170}
171
172/* return private key table for requested protocol version */
173static Idtab *
174idtab_lookup(int version)
175{
176	if (version < 1 || version > 2)
177		fatal("internal error, bad protocol version %d", version);
178	return &idtable[version];
179}
180
181static void
182free_identity(Identity *id)
183{
184	key_free(id->key);
185	if (id->provider != NULL)
186		xfree(id->provider);
187	xfree(id->comment);
188	xfree(id);
189}
190
191/* return matching private key for given public key */
192static Identity *
193lookup_identity(Key *key, int version)
194{
195	Identity *id;
196
197	Idtab *tab = idtab_lookup(version);
198	TAILQ_FOREACH(id, &tab->idlist, next) {
199		if (key_equal(key, id->key))
200			return (id);
201	}
202	return (NULL);
203}
204
205/* Check confirmation of keysign request */
206static int
207confirm_key(Identity *id)
208{
209	char *p;
210	int ret = -1;
211
212	p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
213	if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
214	    id->comment, p))
215		ret = 0;
216	xfree(p);
217
218	return (ret);
219}
220
221/* send list of supported public keys to 'client' */
222static void
223process_request_identities(SocketEntry *e, int version)
224{
225	Idtab *tab = idtab_lookup(version);
226	Identity *id;
227	Buffer msg;
228
229	buffer_init(&msg);
230	buffer_put_char(&msg, (version == 1) ?
231	    SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
232	buffer_put_int(&msg, tab->nentries);
233	TAILQ_FOREACH(id, &tab->idlist, next) {
234		if (id->key->type == KEY_RSA1) {
235			buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
236			buffer_put_bignum(&msg, id->key->rsa->e);
237			buffer_put_bignum(&msg, id->key->rsa->n);
238		} else {
239			u_char *blob;
240			u_int blen;
241			key_to_blob(id->key, &blob, &blen);
242			buffer_put_string(&msg, blob, blen);
243			xfree(blob);
244		}
245		buffer_put_cstring(&msg, id->comment);
246	}
247	buffer_put_int(&e->output, buffer_len(&msg));
248	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
249	buffer_free(&msg);
250}
251
252/* ssh1 only */
253static void
254process_authentication_challenge1(SocketEntry *e)
255{
256	u_char buf[32], mdbuf[16], session_id[16];
257	u_int response_type;
258	BIGNUM *challenge;
259	Identity *id;
260	int i, len;
261	Buffer msg;
262	MD5_CTX md;
263	Key *key;
264
265	buffer_init(&msg);
266	key = key_new(KEY_RSA1);
267	if ((challenge = BN_new()) == NULL)
268		fatal("process_authentication_challenge1: BN_new failed");
269
270	(void) buffer_get_int(&e->request);			/* ignored */
271	buffer_get_bignum(&e->request, key->rsa->e);
272	buffer_get_bignum(&e->request, key->rsa->n);
273	buffer_get_bignum(&e->request, challenge);
274
275	/* Only protocol 1.1 is supported */
276	if (buffer_len(&e->request) == 0)
277		goto failure;
278	buffer_get(&e->request, session_id, 16);
279	response_type = buffer_get_int(&e->request);
280	if (response_type != 1)
281		goto failure;
282
283	id = lookup_identity(key, 1);
284	if (id != NULL && (!id->confirm || confirm_key(id) == 0)) {
285		Key *private = id->key;
286		/* Decrypt the challenge using the private key. */
287		if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
288			goto failure;
289
290		/* The response is MD5 of decrypted challenge plus session id. */
291		len = BN_num_bytes(challenge);
292		if (len <= 0 || len > 32) {
293			logit("process_authentication_challenge: bad challenge length %d", len);
294			goto failure;
295		}
296		memset(buf, 0, 32);
297		BN_bn2bin(challenge, buf + 32 - len);
298		MD5_Init(&md);
299		MD5_Update(&md, buf, 32);
300		MD5_Update(&md, session_id, 16);
301		MD5_Final(mdbuf, &md);
302
303		/* Send the response. */
304		buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
305		for (i = 0; i < 16; i++)
306			buffer_put_char(&msg, mdbuf[i]);
307		goto send;
308	}
309
310failure:
311	/* Unknown identity or protocol error.  Send failure. */
312	buffer_put_char(&msg, SSH_AGENT_FAILURE);
313send:
314	buffer_put_int(&e->output, buffer_len(&msg));
315	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
316	key_free(key);
317	BN_clear_free(challenge);
318	buffer_free(&msg);
319}
320
321/* ssh2 only */
322static void
323process_sign_request2(SocketEntry *e)
324{
325	u_char *blob, *data, *signature = NULL;
326	u_int blen, dlen, slen = 0;
327	extern int datafellows;
328	int odatafellows;
329	int ok = -1, flags;
330	Buffer msg;
331	Key *key;
332
333	datafellows = 0;
334
335	blob = buffer_get_string(&e->request, &blen);
336	data = buffer_get_string(&e->request, &dlen);
337
338	flags = buffer_get_int(&e->request);
339	odatafellows = datafellows;
340	if (flags & SSH_AGENT_OLD_SIGNATURE)
341		datafellows = SSH_BUG_SIGBLOB;
342
343	key = key_from_blob(blob, blen);
344	if (key != NULL) {
345		Identity *id = lookup_identity(key, 2);
346		if (id != NULL && (!id->confirm || confirm_key(id) == 0))
347			ok = key_sign(id->key, &signature, &slen, data, dlen);
348		key_free(key);
349	}
350	buffer_init(&msg);
351	if (ok == 0) {
352		buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
353		buffer_put_string(&msg, signature, slen);
354	} else {
355		buffer_put_char(&msg, SSH_AGENT_FAILURE);
356	}
357	buffer_put_int(&e->output, buffer_len(&msg));
358	buffer_append(&e->output, buffer_ptr(&msg),
359	    buffer_len(&msg));
360	buffer_free(&msg);
361	xfree(data);
362	xfree(blob);
363	if (signature != NULL)
364		xfree(signature);
365	datafellows = odatafellows;
366}
367
368/* shared */
369static void
370process_remove_identity(SocketEntry *e, int version)
371{
372	u_int blen, bits;
373	int success = 0;
374	Key *key = NULL;
375	u_char *blob;
376
377	switch (version) {
378	case 1:
379		key = key_new(KEY_RSA1);
380		bits = buffer_get_int(&e->request);
381		buffer_get_bignum(&e->request, key->rsa->e);
382		buffer_get_bignum(&e->request, key->rsa->n);
383
384		if (bits != key_size(key))
385			logit("Warning: identity keysize mismatch: actual %u, announced %u",
386			    key_size(key), bits);
387		break;
388	case 2:
389		blob = buffer_get_string(&e->request, &blen);
390		key = key_from_blob(blob, blen);
391		xfree(blob);
392		break;
393	}
394	if (key != NULL) {
395		Identity *id = lookup_identity(key, version);
396		if (id != NULL) {
397			/*
398			 * We have this key.  Free the old key.  Since we
399			 * don't want to leave empty slots in the middle of
400			 * the array, we actually free the key there and move
401			 * all the entries between the empty slot and the end
402			 * of the array.
403			 */
404			Idtab *tab = idtab_lookup(version);
405			if (tab->nentries < 1)
406				fatal("process_remove_identity: "
407				    "internal error: tab->nentries %d",
408				    tab->nentries);
409			TAILQ_REMOVE(&tab->idlist, id, next);
410			free_identity(id);
411			tab->nentries--;
412			success = 1;
413		}
414		key_free(key);
415	}
416	buffer_put_int(&e->output, 1);
417	buffer_put_char(&e->output,
418	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
419}
420
421static void
422process_remove_all_identities(SocketEntry *e, int version)
423{
424	Idtab *tab = idtab_lookup(version);
425	Identity *id;
426
427	/* Loop over all identities and clear the keys. */
428	for (id = TAILQ_FIRST(&tab->idlist); id;
429	    id = TAILQ_FIRST(&tab->idlist)) {
430		TAILQ_REMOVE(&tab->idlist, id, next);
431		free_identity(id);
432	}
433
434	/* Mark that there are no identities. */
435	tab->nentries = 0;
436
437	/* Send success. */
438	buffer_put_int(&e->output, 1);
439	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
440}
441
442/* removes expired keys and returns number of seconds until the next expiry */
443static u_int
444reaper(void)
445{
446	u_int deadline = 0, now = time(NULL);
447	Identity *id, *nxt;
448	int version;
449	Idtab *tab;
450
451	for (version = 1; version < 3; version++) {
452		tab = idtab_lookup(version);
453		for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
454			nxt = TAILQ_NEXT(id, next);
455			if (id->death == 0)
456				continue;
457			if (now >= id->death) {
458				debug("expiring key '%s'", id->comment);
459				TAILQ_REMOVE(&tab->idlist, id, next);
460				free_identity(id);
461				tab->nentries--;
462			} else
463				deadline = (deadline == 0) ? id->death :
464				    MIN(deadline, id->death);
465		}
466	}
467	if (deadline == 0 || deadline <= now)
468		return 0;
469	else
470		return (deadline - now);
471}
472
473static void
474process_add_identity(SocketEntry *e, int version)
475{
476	Idtab *tab = idtab_lookup(version);
477	Identity *id;
478	int type, success = 0, death = 0, confirm = 0;
479	char *type_name, *comment;
480	Key *k = NULL;
481#ifdef OPENSSL_HAS_ECC
482	BIGNUM *exponent;
483	EC_POINT *q;
484	char *curve;
485#endif
486	u_char *cert;
487	u_int len;
488
489	switch (version) {
490	case 1:
491		k = key_new_private(KEY_RSA1);
492		(void) buffer_get_int(&e->request);		/* ignored */
493		buffer_get_bignum(&e->request, k->rsa->n);
494		buffer_get_bignum(&e->request, k->rsa->e);
495		buffer_get_bignum(&e->request, k->rsa->d);
496		buffer_get_bignum(&e->request, k->rsa->iqmp);
497
498		/* SSH and SSL have p and q swapped */
499		buffer_get_bignum(&e->request, k->rsa->q);	/* p */
500		buffer_get_bignum(&e->request, k->rsa->p);	/* q */
501
502		/* Generate additional parameters */
503		rsa_generate_additional_parameters(k->rsa);
504		break;
505	case 2:
506		type_name = buffer_get_string(&e->request, NULL);
507		type = key_type_from_name(type_name);
508		switch (type) {
509		case KEY_DSA:
510			k = key_new_private(type);
511			buffer_get_bignum2(&e->request, k->dsa->p);
512			buffer_get_bignum2(&e->request, k->dsa->q);
513			buffer_get_bignum2(&e->request, k->dsa->g);
514			buffer_get_bignum2(&e->request, k->dsa->pub_key);
515			buffer_get_bignum2(&e->request, k->dsa->priv_key);
516			break;
517		case KEY_DSA_CERT_V00:
518		case KEY_DSA_CERT:
519			cert = buffer_get_string(&e->request, &len);
520			if ((k = key_from_blob(cert, len)) == NULL)
521				fatal("Certificate parse failed");
522			xfree(cert);
523			key_add_private(k);
524			buffer_get_bignum2(&e->request, k->dsa->priv_key);
525			break;
526#ifdef OPENSSL_HAS_ECC
527		case KEY_ECDSA:
528			k = key_new_private(type);
529			k->ecdsa_nid = key_ecdsa_nid_from_name(type_name);
530			curve = buffer_get_string(&e->request, NULL);
531			if (k->ecdsa_nid != key_curve_name_to_nid(curve))
532				fatal("%s: curve names mismatch", __func__);
533			xfree(curve);
534			k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
535			if (k->ecdsa == NULL)
536				fatal("%s: EC_KEY_new_by_curve_name failed",
537				    __func__);
538			q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa));
539			if (q == NULL)
540				fatal("%s: BN_new failed", __func__);
541			if ((exponent = BN_new()) == NULL)
542				fatal("%s: BN_new failed", __func__);
543			buffer_get_ecpoint(&e->request,
544				EC_KEY_get0_group(k->ecdsa), q);
545			buffer_get_bignum2(&e->request, exponent);
546			if (EC_KEY_set_public_key(k->ecdsa, q) != 1)
547				fatal("%s: EC_KEY_set_public_key failed",
548				    __func__);
549			if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
550				fatal("%s: EC_KEY_set_private_key failed",
551				    __func__);
552			if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
553			    EC_KEY_get0_public_key(k->ecdsa)) != 0)
554				fatal("%s: bad ECDSA public key", __func__);
555			if (key_ec_validate_private(k->ecdsa) != 0)
556				fatal("%s: bad ECDSA private key", __func__);
557			BN_clear_free(exponent);
558			EC_POINT_free(q);
559			break;
560		case KEY_ECDSA_CERT:
561			cert = buffer_get_string(&e->request, &len);
562			if ((k = key_from_blob(cert, len)) == NULL)
563				fatal("Certificate parse failed");
564			xfree(cert);
565			key_add_private(k);
566			if ((exponent = BN_new()) == NULL)
567				fatal("%s: BN_new failed", __func__);
568			buffer_get_bignum2(&e->request, exponent);
569			if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
570				fatal("%s: EC_KEY_set_private_key failed",
571				    __func__);
572			if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
573			    EC_KEY_get0_public_key(k->ecdsa)) != 0 ||
574			    key_ec_validate_private(k->ecdsa) != 0)
575				fatal("%s: bad ECDSA key", __func__);
576			BN_clear_free(exponent);
577			break;
578#endif /* OPENSSL_HAS_ECC */
579		case KEY_RSA:
580			k = key_new_private(type);
581			buffer_get_bignum2(&e->request, k->rsa->n);
582			buffer_get_bignum2(&e->request, k->rsa->e);
583			buffer_get_bignum2(&e->request, k->rsa->d);
584			buffer_get_bignum2(&e->request, k->rsa->iqmp);
585			buffer_get_bignum2(&e->request, k->rsa->p);
586			buffer_get_bignum2(&e->request, k->rsa->q);
587
588			/* Generate additional parameters */
589			rsa_generate_additional_parameters(k->rsa);
590			break;
591		case KEY_RSA_CERT_V00:
592		case KEY_RSA_CERT:
593			cert = buffer_get_string(&e->request, &len);
594			if ((k = key_from_blob(cert, len)) == NULL)
595				fatal("Certificate parse failed");
596			xfree(cert);
597			key_add_private(k);
598			buffer_get_bignum2(&e->request, k->rsa->d);
599			buffer_get_bignum2(&e->request, k->rsa->iqmp);
600			buffer_get_bignum2(&e->request, k->rsa->p);
601			buffer_get_bignum2(&e->request, k->rsa->q);
602			break;
603		default:
604			xfree(type_name);
605			buffer_clear(&e->request);
606			goto send;
607		}
608		xfree(type_name);
609		break;
610	}
611	/* enable blinding */
612	switch (k->type) {
613	case KEY_RSA:
614	case KEY_RSA_CERT_V00:
615	case KEY_RSA_CERT:
616	case KEY_RSA1:
617		if (RSA_blinding_on(k->rsa, NULL) != 1) {
618			error("process_add_identity: RSA_blinding_on failed");
619			key_free(k);
620			goto send;
621		}
622		break;
623	}
624	comment = buffer_get_string(&e->request, NULL);
625	if (k == NULL) {
626		xfree(comment);
627		goto send;
628	}
629	while (buffer_len(&e->request)) {
630		switch ((type = buffer_get_char(&e->request))) {
631		case SSH_AGENT_CONSTRAIN_LIFETIME:
632			death = time(NULL) + buffer_get_int(&e->request);
633			break;
634		case SSH_AGENT_CONSTRAIN_CONFIRM:
635			confirm = 1;
636			break;
637		default:
638			error("process_add_identity: "
639			    "Unknown constraint type %d", type);
640			xfree(comment);
641			key_free(k);
642			goto send;
643		}
644	}
645	success = 1;
646	if (lifetime && !death)
647		death = time(NULL) + lifetime;
648	if ((id = lookup_identity(k, version)) == NULL) {
649		id = xcalloc(1, sizeof(Identity));
650		id->key = k;
651		TAILQ_INSERT_TAIL(&tab->idlist, id, next);
652		/* Increment the number of identities. */
653		tab->nentries++;
654	} else {
655		key_free(k);
656		xfree(id->comment);
657	}
658	id->comment = comment;
659	id->death = death;
660	id->confirm = confirm;
661send:
662	buffer_put_int(&e->output, 1);
663	buffer_put_char(&e->output,
664	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
665}
666
667/* XXX todo: encrypt sensitive data with passphrase */
668static void
669process_lock_agent(SocketEntry *e, int lock)
670{
671	int success = 0;
672	char *passwd;
673
674	passwd = buffer_get_string(&e->request, NULL);
675	if (locked && !lock && strcmp(passwd, lock_passwd) == 0) {
676		locked = 0;
677		memset(lock_passwd, 0, strlen(lock_passwd));
678		xfree(lock_passwd);
679		lock_passwd = NULL;
680		success = 1;
681	} else if (!locked && lock) {
682		locked = 1;
683		lock_passwd = xstrdup(passwd);
684		success = 1;
685	}
686	memset(passwd, 0, strlen(passwd));
687	xfree(passwd);
688
689	buffer_put_int(&e->output, 1);
690	buffer_put_char(&e->output,
691	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
692}
693
694static void
695no_identities(SocketEntry *e, u_int type)
696{
697	Buffer msg;
698
699	buffer_init(&msg);
700	buffer_put_char(&msg,
701	    (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ?
702	    SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
703	buffer_put_int(&msg, 0);
704	buffer_put_int(&e->output, buffer_len(&msg));
705	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
706	buffer_free(&msg);
707}
708
709#ifdef ENABLE_PKCS11
710static void
711process_add_smartcard_key(SocketEntry *e)
712{
713	char *provider = NULL, *pin;
714	int i, type, version, count = 0, success = 0, death = 0, confirm = 0;
715	Key **keys = NULL, *k;
716	Identity *id;
717	Idtab *tab;
718
719	provider = buffer_get_string(&e->request, NULL);
720	pin = buffer_get_string(&e->request, NULL);
721
722	while (buffer_len(&e->request)) {
723		switch ((type = buffer_get_char(&e->request))) {
724		case SSH_AGENT_CONSTRAIN_LIFETIME:
725			death = time(NULL) + buffer_get_int(&e->request);
726			break;
727		case SSH_AGENT_CONSTRAIN_CONFIRM:
728			confirm = 1;
729			break;
730		default:
731			error("process_add_smartcard_key: "
732			    "Unknown constraint type %d", type);
733			goto send;
734		}
735	}
736	if (lifetime && !death)
737		death = time(NULL) + lifetime;
738
739	count = pkcs11_add_provider(provider, pin, &keys);
740	for (i = 0; i < count; i++) {
741		k = keys[i];
742		version = k->type == KEY_RSA1 ? 1 : 2;
743		tab = idtab_lookup(version);
744		if (lookup_identity(k, version) == NULL) {
745			id = xcalloc(1, sizeof(Identity));
746			id->key = k;
747			id->provider = xstrdup(provider);
748			id->comment = xstrdup(provider); /* XXX */
749			id->death = death;
750			id->confirm = confirm;
751			TAILQ_INSERT_TAIL(&tab->idlist, id, next);
752			tab->nentries++;
753			success = 1;
754		} else {
755			key_free(k);
756		}
757		keys[i] = NULL;
758	}
759send:
760	if (pin)
761		xfree(pin);
762	if (provider)
763		xfree(provider);
764	if (keys)
765		xfree(keys);
766	buffer_put_int(&e->output, 1);
767	buffer_put_char(&e->output,
768	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
769}
770
771static void
772process_remove_smartcard_key(SocketEntry *e)
773{
774	char *provider = NULL, *pin = NULL;
775	int version, success = 0;
776	Identity *id, *nxt;
777	Idtab *tab;
778
779	provider = buffer_get_string(&e->request, NULL);
780	pin = buffer_get_string(&e->request, NULL);
781	xfree(pin);
782
783	for (version = 1; version < 3; version++) {
784		tab = idtab_lookup(version);
785		for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
786			nxt = TAILQ_NEXT(id, next);
787			if (!strcmp(provider, id->provider)) {
788				TAILQ_REMOVE(&tab->idlist, id, next);
789				free_identity(id);
790				tab->nentries--;
791			}
792		}
793	}
794	if (pkcs11_del_provider(provider) == 0)
795		success = 1;
796	else
797		error("process_remove_smartcard_key:"
798		    " pkcs11_del_provider failed");
799	xfree(provider);
800	buffer_put_int(&e->output, 1);
801	buffer_put_char(&e->output,
802	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
803}
804#endif /* ENABLE_PKCS11 */
805
806static int
807add_identity_callback(const char *filename, const char *passphrase)
808{
809	Key *k;
810	int version;
811	Idtab *tab;
812
813	if ((k = key_load_private(filename, passphrase, NULL)) == NULL)
814		return 1;
815	switch (k->type) {
816	case KEY_RSA:
817	case KEY_RSA1:
818		if (RSA_blinding_on(k->rsa, NULL) != 1) {
819			key_free(k);
820			return 1;
821		}
822		break;
823	}
824	version = k->type == KEY_RSA1 ? 1 : 2;
825	tab = idtab_lookup(version);
826	if (lookup_identity(k, version) == NULL) {
827		Identity *id = xcalloc(1, sizeof(Identity));
828		id->key = k;
829		id->comment = xstrdup(filename);
830		if (id->comment == NULL) {
831			key_free(k);
832			return 1;
833		}
834		TAILQ_INSERT_TAIL(&tab->idlist, id, next);
835		tab->nentries++;
836	} else {
837		key_free(k);
838		return 1;
839	}
840
841	return 0;
842}
843
844#ifdef KEYCHAIN
845static void
846process_add_from_keychain(SocketEntry *e)
847{
848	int result;
849
850	result = add_identities_using_keychain(&add_identity_callback);
851
852	/* Start thread to wait for keychain notifications. */
853	keychain_thread_init();
854
855	/* e will be NULL when ssh-agent adds keys on its own at startup */
856	if (e) {
857		buffer_put_int(&e->output, 1);
858		buffer_put_char(&e->output,
859		    result ? SSH_AGENT_FAILURE : SSH_AGENT_SUCCESS);
860	}
861}
862#endif /* KEYCHAIN */
863
864/* dispatch incoming messages */
865
866static void
867process_message(SocketEntry *e)
868{
869	u_int msg_len, type;
870	u_char *cp;
871
872	if (buffer_len(&e->input) < 5)
873		return;		/* Incomplete message. */
874	cp = buffer_ptr(&e->input);
875	msg_len = get_u32(cp);
876	if (msg_len > 256 * 1024) {
877		close_socket(e);
878		return;
879	}
880	if (buffer_len(&e->input) < msg_len + 4)
881		return;
882
883	/* move the current input to e->request */
884	buffer_consume(&e->input, 4);
885	buffer_clear(&e->request);
886	buffer_append(&e->request, buffer_ptr(&e->input), msg_len);
887	buffer_consume(&e->input, msg_len);
888	type = buffer_get_char(&e->request);
889
890	/* check wheter agent is locked */
891	if (locked && type != SSH_AGENTC_UNLOCK) {
892		buffer_clear(&e->request);
893		switch (type) {
894		case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
895		case SSH2_AGENTC_REQUEST_IDENTITIES:
896			/* send empty lists */
897			no_identities(e, type);
898			break;
899		default:
900			/* send a fail message for all other request types */
901			buffer_put_int(&e->output, 1);
902			buffer_put_char(&e->output, SSH_AGENT_FAILURE);
903		}
904		return;
905	}
906
907	debug("type %d", type);
908	switch (type) {
909	case SSH_AGENTC_LOCK:
910	case SSH_AGENTC_UNLOCK:
911		process_lock_agent(e, type == SSH_AGENTC_LOCK);
912		break;
913	/* ssh1 */
914	case SSH_AGENTC_RSA_CHALLENGE:
915		process_authentication_challenge1(e);
916		break;
917	case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
918		process_request_identities(e, 1);
919		break;
920	case SSH_AGENTC_ADD_RSA_IDENTITY:
921	case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
922		process_add_identity(e, 1);
923		break;
924	case SSH_AGENTC_REMOVE_RSA_IDENTITY:
925		process_remove_identity(e, 1);
926		break;
927	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
928		process_remove_all_identities(e, 1);
929		break;
930	/* ssh2 */
931	case SSH2_AGENTC_SIGN_REQUEST:
932		process_sign_request2(e);
933		break;
934	case SSH2_AGENTC_REQUEST_IDENTITIES:
935		process_request_identities(e, 2);
936		break;
937	case SSH2_AGENTC_ADD_IDENTITY:
938	case SSH2_AGENTC_ADD_ID_CONSTRAINED:
939		process_add_identity(e, 2);
940		break;
941	case SSH2_AGENTC_REMOVE_IDENTITY:
942		process_remove_identity(e, 2);
943		break;
944	case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
945		process_remove_all_identities(e, 2);
946		break;
947#ifdef ENABLE_PKCS11
948	case SSH_AGENTC_ADD_SMARTCARD_KEY:
949	case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
950		process_add_smartcard_key(e);
951		break;
952	case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
953		process_remove_smartcard_key(e);
954		break;
955#endif /* ENABLE_PKCS11 */
956#ifdef KEYCHAIN
957	case SSH_AGENTC_ADD_FROM_KEYCHAIN:
958		process_add_from_keychain(e);
959		break;
960#endif /* KEYCHAIN */
961	default:
962		/* Unknown message.  Respond with failure. */
963		error("Unknown message %d", type);
964		buffer_clear(&e->request);
965		buffer_put_int(&e->output, 1);
966		buffer_put_char(&e->output, SSH_AGENT_FAILURE);
967		break;
968	}
969}
970
971static void
972new_socket(sock_type type, int fd)
973{
974	u_int i, old_alloc, new_alloc;
975
976	set_nonblock(fd);
977
978	if (fd > max_fd)
979		max_fd = fd;
980
981	for (i = 0; i < sockets_alloc; i++)
982		if (sockets[i].type == AUTH_UNUSED) {
983			sockets[i].fd = fd;
984			buffer_init(&sockets[i].input);
985			buffer_init(&sockets[i].output);
986			buffer_init(&sockets[i].request);
987			sockets[i].type = type;
988			return;
989		}
990	old_alloc = sockets_alloc;
991	new_alloc = sockets_alloc + 10;
992	sockets = xrealloc(sockets, new_alloc, sizeof(sockets[0]));
993	for (i = old_alloc; i < new_alloc; i++)
994		sockets[i].type = AUTH_UNUSED;
995	sockets_alloc = new_alloc;
996	sockets[old_alloc].fd = fd;
997	buffer_init(&sockets[old_alloc].input);
998	buffer_init(&sockets[old_alloc].output);
999	buffer_init(&sockets[old_alloc].request);
1000	sockets[old_alloc].type = type;
1001}
1002
1003static int
1004prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
1005    struct timeval **tvpp)
1006{
1007	u_int i, sz, deadline;
1008	int n = 0;
1009	static struct timeval tv;
1010
1011	for (i = 0; i < sockets_alloc; i++) {
1012		switch (sockets[i].type) {
1013		case AUTH_SOCKET:
1014		case AUTH_CONNECTION:
1015			n = MAX(n, sockets[i].fd);
1016			break;
1017		case AUTH_UNUSED:
1018			break;
1019		default:
1020			fatal("Unknown socket type %d", sockets[i].type);
1021			break;
1022		}
1023	}
1024
1025	sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
1026	if (*fdrp == NULL || sz > *nallocp) {
1027		if (*fdrp)
1028			xfree(*fdrp);
1029		if (*fdwp)
1030			xfree(*fdwp);
1031		*fdrp = xmalloc(sz);
1032		*fdwp = xmalloc(sz);
1033		*nallocp = sz;
1034	}
1035	if (n < *fdl)
1036		debug("XXX shrink: %d < %d", n, *fdl);
1037	*fdl = n;
1038	memset(*fdrp, 0, sz);
1039	memset(*fdwp, 0, sz);
1040
1041	for (i = 0; i < sockets_alloc; i++) {
1042		switch (sockets[i].type) {
1043		case AUTH_SOCKET:
1044		case AUTH_CONNECTION:
1045			FD_SET(sockets[i].fd, *fdrp);
1046			if (buffer_len(&sockets[i].output) > 0)
1047				FD_SET(sockets[i].fd, *fdwp);
1048			break;
1049		default:
1050			break;
1051		}
1052	}
1053	deadline = reaper();
1054	if (parent_alive_interval != 0)
1055		deadline = (deadline == 0) ? parent_alive_interval :
1056		    MIN(deadline, parent_alive_interval);
1057	if (deadline == 0) {
1058		*tvpp = NULL;
1059	} else {
1060		tv.tv_sec = deadline;
1061		tv.tv_usec = 0;
1062		*tvpp = &tv;
1063	}
1064	return (1);
1065}
1066
1067static void
1068after_select(fd_set *readset, fd_set *writeset)
1069{
1070	struct sockaddr_un sunaddr;
1071	socklen_t slen;
1072	char buf[1024];
1073	int len, sock;
1074	u_int i, orig_alloc;
1075	uid_t euid;
1076	gid_t egid;
1077
1078	for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++)
1079		switch (sockets[i].type) {
1080		case AUTH_UNUSED:
1081			break;
1082		case AUTH_SOCKET:
1083			if (FD_ISSET(sockets[i].fd, readset)) {
1084				slen = sizeof(sunaddr);
1085				sock = accept(sockets[i].fd,
1086				    (struct sockaddr *)&sunaddr, &slen);
1087				if (sock < 0) {
1088					error("accept from AUTH_SOCKET: %s",
1089					    strerror(errno));
1090					break;
1091				}
1092				if (getpeereid(sock, &euid, &egid) < 0) {
1093					error("getpeereid %d failed: %s",
1094					    sock, strerror(errno));
1095					close(sock);
1096					break;
1097				}
1098				if ((euid != 0) && (getuid() != euid)) {
1099					error("uid mismatch: "
1100					    "peer euid %u != uid %u",
1101					    (u_int) euid, (u_int) getuid());
1102					close(sock);
1103					break;
1104				}
1105				new_socket(AUTH_CONNECTION, sock);
1106			}
1107			break;
1108		case AUTH_CONNECTION:
1109			if (buffer_len(&sockets[i].output) > 0 &&
1110			    FD_ISSET(sockets[i].fd, writeset)) {
1111				len = write(sockets[i].fd,
1112				    buffer_ptr(&sockets[i].output),
1113				    buffer_len(&sockets[i].output));
1114				if (len == -1 && (errno == EAGAIN ||
1115				    errno == EWOULDBLOCK ||
1116				    errno == EINTR))
1117					continue;
1118				if (len <= 0) {
1119					close_socket(&sockets[i]);
1120					break;
1121				}
1122				buffer_consume(&sockets[i].output, len);
1123			}
1124			if (FD_ISSET(sockets[i].fd, readset)) {
1125				len = read(sockets[i].fd, buf, sizeof(buf));
1126				if (len == -1 && (errno == EAGAIN ||
1127				    errno == EWOULDBLOCK ||
1128				    errno == EINTR))
1129					continue;
1130				if (len <= 0) {
1131					close_socket(&sockets[i]);
1132					break;
1133				}
1134				buffer_append(&sockets[i].input, buf, len);
1135				process_message(&sockets[i]);
1136			}
1137			break;
1138		default:
1139			fatal("Unknown type %d", sockets[i].type);
1140		}
1141}
1142
1143static void
1144cleanup_socket(void)
1145{
1146	if (socket_name[0])
1147		unlink(socket_name);
1148	if (socket_dir[0])
1149		rmdir(socket_dir);
1150}
1151
1152void
1153cleanup_exit(int i)
1154{
1155	cleanup_socket();
1156	_exit(i);
1157}
1158
1159/*ARGSUSED*/
1160static void
1161cleanup_handler(int sig)
1162{
1163	cleanup_socket();
1164#ifdef ENABLE_PKCS11
1165	pkcs11_terminate();
1166#endif
1167	_exit(2);
1168}
1169
1170static void
1171check_parent_exists(void)
1172{
1173	/*
1174	 * If our parent has exited then getppid() will return (pid_t)1,
1175	 * so testing for that should be safe.
1176	 */
1177	if (parent_pid != -1 && getppid() != parent_pid) {
1178		/* printf("Parent has died - Authentication agent exiting.\n"); */
1179		cleanup_socket();
1180		_exit(2);
1181	}
1182}
1183
1184static void
1185usage(void)
1186{
1187	fprintf(stderr, "usage: %s [options] [command [arg ...]]\n",
1188	    __progname);
1189	fprintf(stderr, "Options:\n");
1190	fprintf(stderr, "  -c          Generate C-shell commands on stdout.\n");
1191	fprintf(stderr, "  -s          Generate Bourne shell commands on stdout.\n");
1192	fprintf(stderr, "  -k          Kill the current agent.\n");
1193	fprintf(stderr, "  -d          Debug mode.\n");
1194	fprintf(stderr, "  -a socket   Bind agent socket to given name.\n");
1195	fprintf(stderr, "  -t life     Default identity lifetime (seconds).\n");
1196	exit(1);
1197}
1198
1199int
1200main(int ac, char **av)
1201{
1202#ifdef __APPLE_LAUNCHD__
1203	int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, l_flag = 0;
1204#else
1205	int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0;
1206#endif
1207	int sock, fd, ch, result, saved_errno;
1208	u_int nalloc;
1209	char *shell, *format, *pidstr, *agentsocket = NULL;
1210	fd_set *readsetp = NULL, *writesetp = NULL;
1211	struct sockaddr_un sunaddr;
1212#ifdef HAVE_SETRLIMIT
1213	struct rlimit rlim;
1214#endif
1215	int prev_mask;
1216	extern int optind;
1217	extern char *optarg;
1218	pid_t pid;
1219	char pidstrbuf[1 + 3 * sizeof pid];
1220	struct timeval *tvp = NULL;
1221	size_t len;
1222
1223	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1224	sanitise_stdfd();
1225
1226	/* drop */
1227	setegid(getgid());
1228	setgid(getgid());
1229
1230#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
1231	/* Disable ptrace on Linux without sgid bit */
1232	prctl(PR_SET_DUMPABLE, 0);
1233#endif
1234
1235	OpenSSL_add_all_algorithms();
1236
1237	__progname = ssh_get_progname(av[0]);
1238	seed_rng();
1239
1240#ifdef __APPLE_LAUNCHD__
1241	while ((ch = getopt(ac, av, "cdklsa:t:")) != -1) {
1242#else
1243	while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
1244#endif
1245		switch (ch) {
1246		case 'c':
1247			if (s_flag)
1248				usage();
1249			c_flag++;
1250			break;
1251		case 'k':
1252			k_flag++;
1253			break;
1254#ifdef __APPLE_LAUNCHD__
1255		case 'l':
1256			l_flag++;
1257			break;
1258#endif
1259		case 's':
1260			if (c_flag)
1261				usage();
1262			s_flag++;
1263			break;
1264		case 'd':
1265			if (d_flag)
1266				usage();
1267			d_flag++;
1268			break;
1269		case 'a':
1270			agentsocket = optarg;
1271			break;
1272		case 't':
1273			if ((lifetime = convtime(optarg)) == -1) {
1274				fprintf(stderr, "Invalid lifetime\n");
1275				usage();
1276			}
1277			break;
1278		default:
1279			usage();
1280		}
1281	}
1282	ac -= optind;
1283	av += optind;
1284
1285#ifdef __APPPLE_LAUNCHD__
1286	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || l_flag))
1287#else
1288	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
1289#endif
1290		usage();
1291
1292	if (ac == 0 && !c_flag && !s_flag) {
1293		shell = getenv("SHELL");
1294		if (shell != NULL && (len = strlen(shell)) > 2 &&
1295		    strncmp(shell + len - 3, "csh", 3) == 0)
1296			c_flag = 1;
1297	}
1298	if (k_flag) {
1299		const char *errstr = NULL;
1300
1301		pidstr = getenv(SSH_AGENTPID_ENV_NAME);
1302		if (pidstr == NULL) {
1303			fprintf(stderr, "%s not set, cannot kill agent\n",
1304			    SSH_AGENTPID_ENV_NAME);
1305			exit(1);
1306		}
1307		pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr);
1308		if (errstr) {
1309			fprintf(stderr,
1310			    "%s=\"%s\", which is not a good PID: %s\n",
1311			    SSH_AGENTPID_ENV_NAME, pidstr, errstr);
1312			exit(1);
1313		}
1314		if (kill(pid, SIGTERM) == -1) {
1315			perror("kill");
1316			exit(1);
1317		}
1318		format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
1319		printf(format, SSH_AUTHSOCKET_ENV_NAME);
1320		printf(format, SSH_AGENTPID_ENV_NAME);
1321		printf("echo Agent pid %ld killed;\n", (long)pid);
1322		exit(0);
1323	}
1324	parent_pid = getpid();
1325
1326	if (agentsocket == NULL) {
1327		/* Create private directory for agent socket */
1328		mktemp_proto(socket_dir, sizeof(socket_dir));
1329		if (mkdtemp(socket_dir) == NULL) {
1330			perror("mkdtemp: private socket dir");
1331			exit(1);
1332		}
1333		snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
1334		    (long)parent_pid);
1335	} else {
1336		/* Try to use specified agent socket */
1337		socket_dir[0] = '\0';
1338		strlcpy(socket_name, agentsocket, sizeof socket_name);
1339	}
1340
1341	/*
1342	 * Create socket early so it will exist before command gets run from
1343	 * the parent.
1344	 */
1345#ifdef __APPLE_LAUNCHD__
1346	if (l_flag) {
1347		launch_data_t resp, msg, tmp;
1348		size_t listeners_i;
1349
1350		msg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
1351
1352		resp = launch_msg(msg);
1353
1354		if (NULL == resp) {
1355			perror("launch_msg");
1356			exit(1);
1357		}
1358		launch_data_free(msg);
1359		switch (launch_data_get_type(resp)) {
1360		case LAUNCH_DATA_ERRNO:
1361			errno = launch_data_get_errno(resp);
1362			perror("launch_msg response");
1363			exit(1);
1364		case LAUNCH_DATA_DICTIONARY:
1365			break;
1366		default:
1367			fprintf(stderr, "launch_msg unknown response");
1368			exit(1);
1369		}
1370		tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS);
1371
1372		if (NULL == tmp) {
1373			fprintf(stderr, "no sockets\n");
1374			exit(1);
1375		}
1376
1377		tmp = launch_data_dict_lookup(tmp, "Listeners");
1378
1379		if (NULL == tmp) {
1380			fprintf(stderr, "no known listeners\n");
1381			exit(1);
1382		}
1383
1384		for (listeners_i = 0; listeners_i < launch_data_array_get_count(tmp); listeners_i++) {
1385			launch_data_t obj_at_ind = launch_data_array_get_index(tmp, listeners_i);
1386			new_socket(AUTH_SOCKET, launch_data_get_fd(obj_at_ind));
1387		}
1388
1389		launch_data_free(resp);
1390	} else {
1391#endif
1392	sock = socket(AF_UNIX, SOCK_STREAM, 0);
1393	if (sock < 0) {
1394		perror("socket");
1395		*socket_name = '\0'; /* Don't unlink any existing file */
1396		cleanup_exit(1);
1397	}
1398	memset(&sunaddr, 0, sizeof(sunaddr));
1399	sunaddr.sun_family = AF_UNIX;
1400	strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
1401	prev_mask = umask(0177);
1402	if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) {
1403		perror("bind");
1404		*socket_name = '\0'; /* Don't unlink any existing file */
1405		umask(prev_mask);
1406		cleanup_exit(1);
1407	}
1408	umask(prev_mask);
1409	if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
1410		perror("listen");
1411		cleanup_exit(1);
1412	}
1413#ifdef __APPLE_LAUNCHD__
1414	}
1415#endif
1416
1417#ifdef __APPLE_LAUNCHD__
1418	if (l_flag)
1419		goto skip2;
1420#endif
1421
1422	/*
1423	 * Fork, and have the parent execute the command, if any, or present
1424	 * the socket data.  The child continues as the authentication agent.
1425	 */
1426	if (d_flag) {
1427		log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1);
1428		format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
1429		printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
1430		    SSH_AUTHSOCKET_ENV_NAME);
1431		printf("echo Agent pid %ld;\n", (long)parent_pid);
1432		goto skip;
1433	}
1434	pid = fork();
1435	if (pid == -1) {
1436		perror("fork");
1437		cleanup_exit(1);
1438	}
1439	if (pid != 0) {		/* Parent - execute the given command. */
1440		close(sock);
1441		snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
1442		if (ac == 0) {
1443			format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
1444			printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
1445			    SSH_AUTHSOCKET_ENV_NAME);
1446			printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
1447			    SSH_AGENTPID_ENV_NAME);
1448			printf("echo Agent pid %ld;\n", (long)pid);
1449			exit(0);
1450		}
1451		if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
1452		    setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
1453			perror("setenv");
1454			exit(1);
1455		}
1456		execvp(av[0], av);
1457		perror(av[0]);
1458		exit(1);
1459	}
1460	/* child */
1461	log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
1462
1463	if (setsid() == -1) {
1464		error("setsid: %s", strerror(errno));
1465		cleanup_exit(1);
1466	}
1467
1468	(void)chdir("/");
1469	if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
1470		/* XXX might close listen socket */
1471		(void)dup2(fd, STDIN_FILENO);
1472		(void)dup2(fd, STDOUT_FILENO);
1473		(void)dup2(fd, STDERR_FILENO);
1474		if (fd > 2)
1475			close(fd);
1476	}
1477
1478#ifdef HAVE_SETRLIMIT
1479	/* deny core dumps, since memory contains unencrypted private keys */
1480	rlim.rlim_cur = rlim.rlim_max = 0;
1481	if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
1482		error("setrlimit RLIMIT_CORE: %s", strerror(errno));
1483		cleanup_exit(1);
1484	}
1485#endif
1486
1487skip:
1488
1489#ifdef ENABLE_PKCS11
1490	pkcs11_init(0);
1491#endif
1492	new_socket(AUTH_SOCKET, sock);
1493skip2:
1494	if (ac > 0)
1495		parent_alive_interval = 10;
1496	idtab_init();
1497	if (!d_flag)
1498		signal(SIGINT, SIG_IGN);
1499	signal(SIGPIPE, SIG_IGN);
1500	signal(SIGHUP, cleanup_handler);
1501	signal(SIGTERM, cleanup_handler);
1502	nalloc = 0;
1503
1504#ifdef KEYCHAIN
1505	process_add_from_keychain(NULL);
1506#endif
1507
1508	while (1) {
1509		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
1510		result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
1511		saved_errno = errno;
1512		if (parent_alive_interval != 0)
1513			check_parent_exists();
1514		(void) reaper();	/* remove expired keys */
1515		if (result < 0) {
1516			if (saved_errno == EINTR)
1517				continue;
1518			fatal("select: %s", strerror(saved_errno));
1519		} else if (result > 0)
1520			after_select(readsetp, writesetp);
1521	}
1522	/* NOTREACHED */
1523}
1524