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