xref: /openbsd-src/usr.bin/ssh/ssh-agent.c (revision ce7e0fc6a9d74d25b78fb6ad846387717f5172b6)
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * The authentication agent program.
6  *
7  * As far as I am concerned, the code I have written for this software
8  * can be used freely for any purpose.  Any derived versions of this
9  * software must be clearly marked as such, and if the derived work is
10  * incompatible with the protocol description in the RFC file, it must be
11  * called by a name other than "ssh" or "Secure Shell".
12  *
13  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "includes.h"
37 #include <sys/queue.h>
38 RCSID("$OpenBSD: ssh-agent.c,v 1.85 2002/04/02 11:49:39 markus Exp $");
39 
40 #include <openssl/evp.h>
41 #include <openssl/md5.h>
42 
43 #include "ssh.h"
44 #include "rsa.h"
45 #include "buffer.h"
46 #include "bufaux.h"
47 #include "xmalloc.h"
48 #include "getput.h"
49 #include "key.h"
50 #include "authfd.h"
51 #include "compat.h"
52 #include "log.h"
53 
54 #ifdef SMARTCARD
55 #include "scard.h"
56 #endif
57 
58 typedef enum {
59 	AUTH_UNUSED,
60 	AUTH_SOCKET,
61 	AUTH_CONNECTION
62 } sock_type;
63 
64 typedef struct {
65 	int fd;
66 	sock_type type;
67 	Buffer input;
68 	Buffer output;
69 } SocketEntry;
70 
71 u_int sockets_alloc = 0;
72 SocketEntry *sockets = NULL;
73 
74 typedef struct identity {
75 	TAILQ_ENTRY(identity) next;
76 	Key *key;
77 	char *comment;
78 } Identity;
79 
80 typedef struct {
81 	int nentries;
82 	TAILQ_HEAD(idqueue, identity) idlist;
83 } Idtab;
84 
85 /* private key table, one per protocol version */
86 Idtab idtable[3];
87 
88 int max_fd = 0;
89 
90 /* pid of shell == parent of agent */
91 pid_t parent_pid = -1;
92 
93 /* pathname and directory for AUTH_SOCKET */
94 char socket_name[1024];
95 char socket_dir[1024];
96 
97 extern char *__progname;
98 
99 static void
100 idtab_init(void)
101 {
102 	int i;
103 	for (i = 0; i <=2; i++) {
104 		TAILQ_INIT(&idtable[i].idlist);
105 		idtable[i].nentries = 0;
106 	}
107 }
108 
109 /* return private key table for requested protocol version */
110 static Idtab *
111 idtab_lookup(int version)
112 {
113 	if (version < 1 || version > 2)
114 		fatal("internal error, bad protocol version %d", version);
115 	return &idtable[version];
116 }
117 
118 /* return matching private key for given public key */
119 static Identity *
120 lookup_identity(Key *key, int version)
121 {
122 	Identity *id;
123 
124 	Idtab *tab = idtab_lookup(version);
125 	TAILQ_FOREACH(id, &tab->idlist, next) {
126 		if (key_equal(key, id->key))
127 			return (id);
128 	}
129 	return (NULL);
130 }
131 
132 static void
133 free_identity(Identity *id)
134 {
135 	key_free(id->key);
136 	xfree(id->comment);
137 	xfree(id);
138 }
139 
140 /* send list of supported public keys to 'client' */
141 static void
142 process_request_identities(SocketEntry *e, int version)
143 {
144 	Idtab *tab = idtab_lookup(version);
145 	Buffer msg;
146 	Identity *id;
147 
148 	buffer_init(&msg);
149 	buffer_put_char(&msg, (version == 1) ?
150 	    SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
151 	buffer_put_int(&msg, tab->nentries);
152 	TAILQ_FOREACH(id, &tab->idlist, next) {
153 		if (id->key->type == KEY_RSA1) {
154 			buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
155 			buffer_put_bignum(&msg, id->key->rsa->e);
156 			buffer_put_bignum(&msg, id->key->rsa->n);
157 		} else {
158 			u_char *blob;
159 			u_int blen;
160 			key_to_blob(id->key, &blob, &blen);
161 			buffer_put_string(&msg, blob, blen);
162 			xfree(blob);
163 		}
164 		buffer_put_cstring(&msg, id->comment);
165 	}
166 	buffer_put_int(&e->output, buffer_len(&msg));
167 	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
168 	buffer_free(&msg);
169 }
170 
171 /* ssh1 only */
172 static void
173 process_authentication_challenge1(SocketEntry *e)
174 {
175 	Identity *id;
176 	Key *key;
177 	BIGNUM *challenge;
178 	int i, len;
179 	Buffer msg;
180 	MD5_CTX md;
181 	u_char buf[32], mdbuf[16], session_id[16];
182 	u_int response_type;
183 
184 	buffer_init(&msg);
185 	key = key_new(KEY_RSA1);
186 	if ((challenge = BN_new()) == NULL)
187 		fatal("process_authentication_challenge1: BN_new failed");
188 
189 	buffer_get_int(&e->input);				/* ignored */
190 	buffer_get_bignum(&e->input, key->rsa->e);
191 	buffer_get_bignum(&e->input, key->rsa->n);
192 	buffer_get_bignum(&e->input, challenge);
193 
194 	/* Only protocol 1.1 is supported */
195 	if (buffer_len(&e->input) == 0)
196 		goto failure;
197 	buffer_get(&e->input, session_id, 16);
198 	response_type = buffer_get_int(&e->input);
199 	if (response_type != 1)
200 		goto failure;
201 
202 	id = lookup_identity(key, 1);
203 	if (id != NULL) {
204 		Key *private = id->key;
205 		/* Decrypt the challenge using the private key. */
206 		if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
207 			goto failure;
208 
209 		/* The response is MD5 of decrypted challenge plus session id. */
210 		len = BN_num_bytes(challenge);
211 		if (len <= 0 || len > 32) {
212 			log("process_authentication_challenge: bad challenge length %d", len);
213 			goto failure;
214 		}
215 		memset(buf, 0, 32);
216 		BN_bn2bin(challenge, buf + 32 - len);
217 		MD5_Init(&md);
218 		MD5_Update(&md, buf, 32);
219 		MD5_Update(&md, session_id, 16);
220 		MD5_Final(mdbuf, &md);
221 
222 		/* Send the response. */
223 		buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
224 		for (i = 0; i < 16; i++)
225 			buffer_put_char(&msg, mdbuf[i]);
226 		goto send;
227 	}
228 
229 failure:
230 	/* Unknown identity or protocol error.  Send failure. */
231 	buffer_put_char(&msg, SSH_AGENT_FAILURE);
232 send:
233 	buffer_put_int(&e->output, buffer_len(&msg));
234 	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
235 	key_free(key);
236 	BN_clear_free(challenge);
237 	buffer_free(&msg);
238 }
239 
240 /* ssh2 only */
241 static void
242 process_sign_request2(SocketEntry *e)
243 {
244 	extern int datafellows;
245 	Key *key;
246 	u_char *blob, *data, *signature = NULL;
247 	u_int blen, dlen, slen = 0;
248 	int flags;
249 	Buffer msg;
250 	int ok = -1;
251 
252 	datafellows = 0;
253 
254 	blob = buffer_get_string(&e->input, &blen);
255 	data = buffer_get_string(&e->input, &dlen);
256 
257 	flags = buffer_get_int(&e->input);
258 	if (flags & SSH_AGENT_OLD_SIGNATURE)
259 		datafellows = SSH_BUG_SIGBLOB;
260 
261 	key = key_from_blob(blob, blen);
262 	if (key != NULL) {
263 		Identity *id = lookup_identity(key, 2);
264 		if (id != NULL)
265 			ok = key_sign(id->key, &signature, &slen, data, dlen);
266 	}
267 	key_free(key);
268 	buffer_init(&msg);
269 	if (ok == 0) {
270 		buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
271 		buffer_put_string(&msg, signature, slen);
272 	} else {
273 		buffer_put_char(&msg, SSH_AGENT_FAILURE);
274 	}
275 	buffer_put_int(&e->output, buffer_len(&msg));
276 	buffer_append(&e->output, buffer_ptr(&msg),
277 	    buffer_len(&msg));
278 	buffer_free(&msg);
279 	xfree(data);
280 	xfree(blob);
281 	if (signature != NULL)
282 		xfree(signature);
283 }
284 
285 /* shared */
286 static void
287 process_remove_identity(SocketEntry *e, int version)
288 {
289 	Key *key = NULL;
290 	u_char *blob;
291 	u_int blen;
292 	u_int bits;
293 	int success = 0;
294 
295 	switch (version) {
296 	case 1:
297 		key = key_new(KEY_RSA1);
298 		bits = buffer_get_int(&e->input);
299 		buffer_get_bignum(&e->input, key->rsa->e);
300 		buffer_get_bignum(&e->input, key->rsa->n);
301 
302 		if (bits != key_size(key))
303 			log("Warning: identity keysize mismatch: actual %d, announced %d",
304 			    key_size(key), bits);
305 		break;
306 	case 2:
307 		blob = buffer_get_string(&e->input, &blen);
308 		key = key_from_blob(blob, blen);
309 		xfree(blob);
310 		break;
311 	}
312 	if (key != NULL) {
313 		Identity *id = lookup_identity(key, version);
314 		if (id != NULL) {
315 			/*
316 			 * We have this key.  Free the old key.  Since we
317 			 * don\'t want to leave empty slots in the middle of
318 			 * the array, we actually free the key there and move
319 			 * all the entries between the empty slot and the end
320 			 * of the array.
321 			 */
322 			Idtab *tab = idtab_lookup(version);
323 			if (tab->nentries < 1)
324 				fatal("process_remove_identity: "
325 				    "internal error: tab->nentries %d",
326 				    tab->nentries);
327 			TAILQ_REMOVE(&tab->idlist, id, next);
328 			free_identity(id);
329 			tab->nentries--;
330 			success = 1;
331 		}
332 		key_free(key);
333 	}
334 	buffer_put_int(&e->output, 1);
335 	buffer_put_char(&e->output,
336 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
337 }
338 
339 static void
340 process_remove_all_identities(SocketEntry *e, int version)
341 {
342 	Idtab *tab = idtab_lookup(version);
343 	Identity *id;
344 
345 	/* Loop over all identities and clear the keys. */
346 	for (id = TAILQ_FIRST(&tab->idlist); id;
347 	    id = TAILQ_FIRST(&tab->idlist)) {
348 		TAILQ_REMOVE(&tab->idlist, id, next);
349 		free_identity(id);
350 	}
351 
352 	/* Mark that there are no identities. */
353 	tab->nentries = 0;
354 
355 	/* Send success. */
356 	buffer_put_int(&e->output, 1);
357 	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
358 	return;
359 }
360 
361 static void
362 process_add_identity(SocketEntry *e, int version)
363 {
364 	Key *k = NULL;
365 	char *type_name;
366 	char *comment;
367 	int type, success = 0;
368 	Idtab *tab = idtab_lookup(version);
369 
370 	switch (version) {
371 	case 1:
372 		k = key_new_private(KEY_RSA1);
373 		buffer_get_int(&e->input);			/* ignored */
374 		buffer_get_bignum(&e->input, k->rsa->n);
375 		buffer_get_bignum(&e->input, k->rsa->e);
376 		buffer_get_bignum(&e->input, k->rsa->d);
377 		buffer_get_bignum(&e->input, k->rsa->iqmp);
378 
379 		/* SSH and SSL have p and q swapped */
380 		buffer_get_bignum(&e->input, k->rsa->q);	/* p */
381 		buffer_get_bignum(&e->input, k->rsa->p);	/* q */
382 
383 		/* Generate additional parameters */
384 		rsa_generate_additional_parameters(k->rsa);
385 		break;
386 	case 2:
387 		type_name = buffer_get_string(&e->input, NULL);
388 		type = key_type_from_name(type_name);
389 		xfree(type_name);
390 		switch (type) {
391 		case KEY_DSA:
392 			k = key_new_private(type);
393 			buffer_get_bignum2(&e->input, k->dsa->p);
394 			buffer_get_bignum2(&e->input, k->dsa->q);
395 			buffer_get_bignum2(&e->input, k->dsa->g);
396 			buffer_get_bignum2(&e->input, k->dsa->pub_key);
397 			buffer_get_bignum2(&e->input, k->dsa->priv_key);
398 			break;
399 		case KEY_RSA:
400 			k = key_new_private(type);
401 			buffer_get_bignum2(&e->input, k->rsa->n);
402 			buffer_get_bignum2(&e->input, k->rsa->e);
403 			buffer_get_bignum2(&e->input, k->rsa->d);
404 			buffer_get_bignum2(&e->input, k->rsa->iqmp);
405 			buffer_get_bignum2(&e->input, k->rsa->p);
406 			buffer_get_bignum2(&e->input, k->rsa->q);
407 
408 			/* Generate additional parameters */
409 			rsa_generate_additional_parameters(k->rsa);
410 			break;
411 		default:
412 			buffer_clear(&e->input);
413 			goto send;
414 		}
415 		break;
416 	}
417 	comment = buffer_get_string(&e->input, NULL);
418 	if (k == NULL) {
419 		xfree(comment);
420 		goto send;
421 	}
422 	success = 1;
423 	if (lookup_identity(k, version) == NULL) {
424 		Identity *id = xmalloc(sizeof(Identity));
425 		id->key = k;
426 		id->comment = comment;
427 		TAILQ_INSERT_TAIL(&tab->idlist, id, next);
428 		/* Increment the number of identities. */
429 		tab->nentries++;
430 	} else {
431 		key_free(k);
432 		xfree(comment);
433 	}
434 send:
435 	buffer_put_int(&e->output, 1);
436 	buffer_put_char(&e->output,
437 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
438 }
439 
440 
441 #ifdef SMARTCARD
442 static void
443 process_add_smartcard_key (SocketEntry *e)
444 {
445 	Identity *id;
446 	Idtab *tab;
447 	Key **keys, *k;
448 	char *sc_reader_id = NULL, *pin;
449 	int i, version, success = 0;
450 
451 	sc_reader_id = buffer_get_string(&e->input, NULL);
452 	pin = buffer_get_string(&e->input, NULL);
453 	keys = sc_get_keys(sc_reader_id, pin);
454 	xfree(sc_reader_id);
455 	xfree(pin);
456 
457 	if (keys == NULL || keys[0] == NULL) {
458 		error("sc_get_keys failed");
459 		goto send;
460 	}
461 	for (i = 0; keys[i] != NULL; i++) {
462 		k = keys[i];
463 		version = k->type == KEY_RSA1 ? 1 : 2;
464 		tab = idtab_lookup(version);
465 		if (lookup_identity(k, version) == NULL) {
466 			id = xmalloc(sizeof(Identity));
467 			id->key = k;
468 			id->comment = xstrdup("smartcard key");
469 			TAILQ_INSERT_TAIL(&tab->idlist, id, next);
470 			tab->nentries++;
471 			success = 1;
472 		} else {
473 			key_free(k);
474 		}
475 		keys[i] = NULL;
476 	}
477 	xfree(keys);
478 send:
479 	buffer_put_int(&e->output, 1);
480 	buffer_put_char(&e->output,
481 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
482 }
483 
484 static void
485 process_remove_smartcard_key(SocketEntry *e)
486 {
487 	Identity *id;
488 	Idtab *tab;
489 	Key **keys, *k = NULL;
490 	char *sc_reader_id = NULL, *pin;
491 	int i, version, success = 0;
492 
493 	sc_reader_id = buffer_get_string(&e->input, NULL);
494 	pin = buffer_get_string(&e->input, NULL);
495 	keys = sc_get_keys(sc_reader_id, pin);
496 	xfree(sc_reader_id);
497 	xfree(pin);
498 
499 	if (keys == NULL || keys[0] == NULL) {
500 		error("sc_get_keys failed");
501 		goto send;
502 	}
503 	for (i = 0; keys[i] != NULL; i++) {
504 		k = keys[i];
505 		version = k->type == KEY_RSA1 ? 1 : 2;
506 		if ((id = lookup_identity(k, version)) != NULL) {
507 			tab = idtab_lookup(version);
508                         TAILQ_REMOVE(&tab->idlist, id, next);
509 			tab->nentries--;
510 			free_identity(id);
511 			success = 1;
512 		}
513 		key_free(k);
514 		keys[i] = NULL;
515 	}
516 	xfree(keys);
517 send:
518 	buffer_put_int(&e->output, 1);
519 	buffer_put_char(&e->output,
520 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
521 }
522 #endif /* SMARTCARD */
523 
524 /* dispatch incoming messages */
525 
526 static void
527 process_message(SocketEntry *e)
528 {
529 	u_int msg_len;
530 	u_int type;
531 	u_char *cp;
532 	if (buffer_len(&e->input) < 5)
533 		return;		/* Incomplete message. */
534 	cp = buffer_ptr(&e->input);
535 	msg_len = GET_32BIT(cp);
536 	if (msg_len > 256 * 1024) {
537 		shutdown(e->fd, SHUT_RDWR);
538 		close(e->fd);
539 		e->type = AUTH_UNUSED;
540 		return;
541 	}
542 	if (buffer_len(&e->input) < msg_len + 4)
543 		return;
544 	buffer_consume(&e->input, 4);
545 	type = buffer_get_char(&e->input);
546 
547 	debug("type %d", type);
548 	switch (type) {
549 	/* ssh1 */
550 	case SSH_AGENTC_RSA_CHALLENGE:
551 		process_authentication_challenge1(e);
552 		break;
553 	case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
554 		process_request_identities(e, 1);
555 		break;
556 	case SSH_AGENTC_ADD_RSA_IDENTITY:
557 		process_add_identity(e, 1);
558 		break;
559 	case SSH_AGENTC_REMOVE_RSA_IDENTITY:
560 		process_remove_identity(e, 1);
561 		break;
562 	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
563 		process_remove_all_identities(e, 1);
564 		break;
565 	/* ssh2 */
566 	case SSH2_AGENTC_SIGN_REQUEST:
567 		process_sign_request2(e);
568 		break;
569 	case SSH2_AGENTC_REQUEST_IDENTITIES:
570 		process_request_identities(e, 2);
571 		break;
572 	case SSH2_AGENTC_ADD_IDENTITY:
573 		process_add_identity(e, 2);
574 		break;
575 	case SSH2_AGENTC_REMOVE_IDENTITY:
576 		process_remove_identity(e, 2);
577 		break;
578 	case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
579 		process_remove_all_identities(e, 2);
580 		break;
581 #ifdef SMARTCARD
582 	case SSH_AGENTC_ADD_SMARTCARD_KEY:
583 		process_add_smartcard_key(e);
584 		break;
585 	case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
586 		process_remove_smartcard_key(e);
587 		break;
588 #endif /* SMARTCARD */
589 	default:
590 		/* Unknown message.  Respond with failure. */
591 		error("Unknown message %d", type);
592 		buffer_clear(&e->input);
593 		buffer_put_int(&e->output, 1);
594 		buffer_put_char(&e->output, SSH_AGENT_FAILURE);
595 		break;
596 	}
597 }
598 
599 static void
600 new_socket(sock_type type, int fd)
601 {
602 	u_int i, old_alloc;
603 	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
604 		error("fcntl O_NONBLOCK: %s", strerror(errno));
605 
606 	if (fd > max_fd)
607 		max_fd = fd;
608 
609 	for (i = 0; i < sockets_alloc; i++)
610 		if (sockets[i].type == AUTH_UNUSED) {
611 			sockets[i].fd = fd;
612 			sockets[i].type = type;
613 			buffer_init(&sockets[i].input);
614 			buffer_init(&sockets[i].output);
615 			return;
616 		}
617 	old_alloc = sockets_alloc;
618 	sockets_alloc += 10;
619 	if (sockets)
620 		sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
621 	else
622 		sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
623 	for (i = old_alloc; i < sockets_alloc; i++)
624 		sockets[i].type = AUTH_UNUSED;
625 	sockets[old_alloc].type = type;
626 	sockets[old_alloc].fd = fd;
627 	buffer_init(&sockets[old_alloc].input);
628 	buffer_init(&sockets[old_alloc].output);
629 }
630 
631 static int
632 prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, int *nallocp)
633 {
634 	u_int i, sz;
635 	int n = 0;
636 
637 	for (i = 0; i < sockets_alloc; i++) {
638 		switch (sockets[i].type) {
639 		case AUTH_SOCKET:
640 		case AUTH_CONNECTION:
641 			n = MAX(n, sockets[i].fd);
642 			break;
643 		case AUTH_UNUSED:
644 			break;
645 		default:
646 			fatal("Unknown socket type %d", sockets[i].type);
647 			break;
648 		}
649 	}
650 
651 	sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
652 	if (*fdrp == NULL || sz > *nallocp) {
653 		if (*fdrp)
654 			xfree(*fdrp);
655 		if (*fdwp)
656 			xfree(*fdwp);
657 		*fdrp = xmalloc(sz);
658 		*fdwp = xmalloc(sz);
659 		*nallocp = sz;
660 	}
661 	if (n < *fdl)
662 		debug("XXX shrink: %d < %d", n, *fdl);
663 	*fdl = n;
664 	memset(*fdrp, 0, sz);
665 	memset(*fdwp, 0, sz);
666 
667 	for (i = 0; i < sockets_alloc; i++) {
668 		switch (sockets[i].type) {
669 		case AUTH_SOCKET:
670 		case AUTH_CONNECTION:
671 			FD_SET(sockets[i].fd, *fdrp);
672 			if (buffer_len(&sockets[i].output) > 0)
673 				FD_SET(sockets[i].fd, *fdwp);
674 			break;
675 		default:
676 			break;
677 		}
678 	}
679 	return (1);
680 }
681 
682 static void
683 after_select(fd_set *readset, fd_set *writeset)
684 {
685 	u_int i;
686 	int len, sock;
687 	socklen_t slen;
688 	char buf[1024];
689 	struct sockaddr_un sunaddr;
690 
691 	for (i = 0; i < sockets_alloc; i++)
692 		switch (sockets[i].type) {
693 		case AUTH_UNUSED:
694 			break;
695 		case AUTH_SOCKET:
696 			if (FD_ISSET(sockets[i].fd, readset)) {
697 				slen = sizeof(sunaddr);
698 				sock = accept(sockets[i].fd,
699 				    (struct sockaddr *) &sunaddr, &slen);
700 				if (sock < 0) {
701 					error("accept from AUTH_SOCKET: %s",
702 					    strerror(errno));
703 					break;
704 				}
705 				new_socket(AUTH_CONNECTION, sock);
706 			}
707 			break;
708 		case AUTH_CONNECTION:
709 			if (buffer_len(&sockets[i].output) > 0 &&
710 			    FD_ISSET(sockets[i].fd, writeset)) {
711 				do {
712 					len = write(sockets[i].fd,
713 					    buffer_ptr(&sockets[i].output),
714 					    buffer_len(&sockets[i].output));
715 					if (len == -1 && (errno == EAGAIN ||
716 					    errno == EINTR))
717 						continue;
718 					break;
719 				} while (1);
720 				if (len <= 0) {
721 					shutdown(sockets[i].fd, SHUT_RDWR);
722 					close(sockets[i].fd);
723 					sockets[i].type = AUTH_UNUSED;
724 					buffer_free(&sockets[i].input);
725 					buffer_free(&sockets[i].output);
726 					break;
727 				}
728 				buffer_consume(&sockets[i].output, len);
729 			}
730 			if (FD_ISSET(sockets[i].fd, readset)) {
731 				do {
732 					len = read(sockets[i].fd, buf, sizeof(buf));
733 					if (len == -1 && (errno == EAGAIN ||
734 					    errno == EINTR))
735 						continue;
736 					break;
737 				} while (1);
738 				if (len <= 0) {
739 					shutdown(sockets[i].fd, SHUT_RDWR);
740 					close(sockets[i].fd);
741 					sockets[i].type = AUTH_UNUSED;
742 					buffer_free(&sockets[i].input);
743 					buffer_free(&sockets[i].output);
744 					break;
745 				}
746 				buffer_append(&sockets[i].input, buf, len);
747 				process_message(&sockets[i]);
748 			}
749 			break;
750 		default:
751 			fatal("Unknown type %d", sockets[i].type);
752 		}
753 }
754 
755 static void
756 cleanup_socket(void *p)
757 {
758 	if (socket_name[0])
759 		unlink(socket_name);
760 	if (socket_dir[0])
761 		rmdir(socket_dir);
762 }
763 
764 static void
765 cleanup_exit(int i)
766 {
767 	cleanup_socket(NULL);
768 	exit(i);
769 }
770 
771 static void
772 cleanup_handler(int sig)
773 {
774 	cleanup_socket(NULL);
775 	_exit(2);
776 }
777 
778 static void
779 check_parent_exists(int sig)
780 {
781 	int save_errno = errno;
782 
783 	if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
784 		/* printf("Parent has died - Authentication agent exiting.\n"); */
785 		cleanup_handler(sig); /* safe */
786 	}
787 	signal(SIGALRM, check_parent_exists);
788 	alarm(10);
789 	errno = save_errno;
790 }
791 
792 static void
793 usage(void)
794 {
795 	fprintf(stderr, "Usage: %s [options] [command [args ...]]\n",
796 	    __progname);
797 	fprintf(stderr, "Options:\n");
798 	fprintf(stderr, "  -c          Generate C-shell commands on stdout.\n");
799 	fprintf(stderr, "  -s          Generate Bourne shell commands on stdout.\n");
800 	fprintf(stderr, "  -k          Kill the current agent.\n");
801 	fprintf(stderr, "  -d          Debug mode.\n");
802 	exit(1);
803 }
804 
805 int
806 main(int ac, char **av)
807 {
808 	int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc;
809 	struct sockaddr_un sunaddr;
810 	struct rlimit rlim;
811 	pid_t pid;
812 	char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
813 	extern int optind;
814 	fd_set *readsetp = NULL, *writesetp = NULL;
815 
816 	SSLeay_add_all_algorithms();
817 
818 	while ((ch = getopt(ac, av, "cdks")) != -1) {
819 		switch (ch) {
820 		case 'c':
821 			if (s_flag)
822 				usage();
823 			c_flag++;
824 			break;
825 		case 'k':
826 			k_flag++;
827 			break;
828 		case 's':
829 			if (c_flag)
830 				usage();
831 			s_flag++;
832 			break;
833 		case 'd':
834 			if (d_flag)
835 				usage();
836 			d_flag++;
837 			break;
838 		default:
839 			usage();
840 		}
841 	}
842 	ac -= optind;
843 	av += optind;
844 
845 	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
846 		usage();
847 
848 	if (ac == 0 && !c_flag && !s_flag) {
849 		shell = getenv("SHELL");
850 		if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
851 			c_flag = 1;
852 	}
853 	if (k_flag) {
854 		pidstr = getenv(SSH_AGENTPID_ENV_NAME);
855 		if (pidstr == NULL) {
856 			fprintf(stderr, "%s not set, cannot kill agent\n",
857 			    SSH_AGENTPID_ENV_NAME);
858 			exit(1);
859 		}
860 		pid = atoi(pidstr);
861 		if (pid < 1) {
862 			fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
863 			    SSH_AGENTPID_ENV_NAME, pidstr);
864 			exit(1);
865 		}
866 		if (kill(pid, SIGTERM) == -1) {
867 			perror("kill");
868 			exit(1);
869 		}
870 		format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
871 		printf(format, SSH_AUTHSOCKET_ENV_NAME);
872 		printf(format, SSH_AGENTPID_ENV_NAME);
873 		printf("echo Agent pid %d killed;\n", pid);
874 		exit(0);
875 	}
876 	parent_pid = getpid();
877 
878 	/* Create private directory for agent socket */
879 	strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
880 	if (mkdtemp(socket_dir) == NULL) {
881 		perror("mkdtemp: private socket dir");
882 		exit(1);
883 	}
884 	snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
885 	    parent_pid);
886 
887 	/*
888 	 * Create socket early so it will exist before command gets run from
889 	 * the parent.
890 	 */
891 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
892 	if (sock < 0) {
893 		perror("socket");
894 		cleanup_exit(1);
895 	}
896 	memset(&sunaddr, 0, sizeof(sunaddr));
897 	sunaddr.sun_family = AF_UNIX;
898 	strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
899 	if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
900 		perror("bind");
901 		cleanup_exit(1);
902 	}
903 	if (listen(sock, 5) < 0) {
904 		perror("listen");
905 		cleanup_exit(1);
906 	}
907 
908 	/*
909 	 * Fork, and have the parent execute the command, if any, or present
910 	 * the socket data.  The child continues as the authentication agent.
911 	 */
912 	if (d_flag) {
913 		log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1);
914 		format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
915 		printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
916 		    SSH_AUTHSOCKET_ENV_NAME);
917 		printf("echo Agent pid %d;\n", parent_pid);
918 		goto skip;
919 	}
920 	pid = fork();
921 	if (pid == -1) {
922 		perror("fork");
923 		cleanup_exit(1);
924 	}
925 	if (pid != 0) {		/* Parent - execute the given command. */
926 		close(sock);
927 		snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
928 		if (ac == 0) {
929 			format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
930 			printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
931 			    SSH_AUTHSOCKET_ENV_NAME);
932 			printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
933 			    SSH_AGENTPID_ENV_NAME);
934 			printf("echo Agent pid %d;\n", pid);
935 			exit(0);
936 		}
937 		if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
938 		    setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
939 			perror("setenv");
940 			exit(1);
941 		}
942 		execvp(av[0], av);
943 		perror(av[0]);
944 		exit(1);
945 	}
946 	/* child */
947 	log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
948 
949 	if (setsid() == -1) {
950 		error("setsid: %s", strerror(errno));
951 		cleanup_exit(1);
952 	}
953 
954 	(void)chdir("/");
955 	close(0);
956 	close(1);
957 	close(2);
958 
959 	/* deny core dumps, since memory contains unencrypted private keys */
960 	rlim.rlim_cur = rlim.rlim_max = 0;
961 	if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
962 		error("setrlimit RLIMIT_CORE: %s", strerror(errno));
963 		cleanup_exit(1);
964 	}
965 
966 skip:
967 	fatal_add_cleanup(cleanup_socket, NULL);
968 	new_socket(AUTH_SOCKET, sock);
969 	if (ac > 0) {
970 		signal(SIGALRM, check_parent_exists);
971 		alarm(10);
972 	}
973 	idtab_init();
974 	if (!d_flag)
975 		signal(SIGINT, SIG_IGN);
976 	signal(SIGPIPE, SIG_IGN);
977 	signal(SIGHUP, cleanup_handler);
978 	signal(SIGTERM, cleanup_handler);
979 	nalloc = 0;
980 
981 	while (1) {
982 		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc);
983 		if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) {
984 			if (errno == EINTR)
985 				continue;
986 			fatal("select: %s", strerror(errno));
987 		}
988 		after_select(readsetp, writesetp);
989 	}
990 	/* NOTREACHED */
991 }
992