xref: /freebsd/crypto/openssh/ssh-agent.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
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  * SSH2 implementation,
14  * Copyright (c) 2000 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 RCSID("$OpenBSD: ssh-agent.c,v 1.35 2000/09/07 20:27:54 deraadt Exp $");
39 RCSID("$FreeBSD$");
40 
41 #include "ssh.h"
42 #include "rsa.h"
43 #include "buffer.h"
44 #include "bufaux.h"
45 #include "xmalloc.h"
46 #include "packet.h"
47 #include "getput.h"
48 #include "mpaux.h"
49 
50 #include <openssl/evp.h>
51 #include <openssl/md5.h>
52 #include <openssl/dsa.h>
53 #include <openssl/rsa.h>
54 #include "key.h"
55 #include "authfd.h"
56 #include "dsa.h"
57 #include "kex.h"
58 
59 typedef struct {
60 	int fd;
61 	enum {
62 		AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION
63 	} type;
64 	Buffer input;
65 	Buffer output;
66 } SocketEntry;
67 
68 unsigned int sockets_alloc = 0;
69 SocketEntry *sockets = NULL;
70 
71 typedef struct {
72 	Key *key;
73 	char *comment;
74 } Identity;
75 
76 typedef struct {
77 	int nentries;
78 	Identity *identities;
79 } Idtab;
80 
81 /* private key table, one per protocol version */
82 Idtab idtable[3];
83 
84 int max_fd = 0;
85 
86 /* pid of shell == parent of agent */
87 pid_t parent_pid = -1;
88 
89 /* pathname and directory for AUTH_SOCKET */
90 char socket_name[1024];
91 char socket_dir[1024];
92 
93 extern char *__progname;
94 
95 void
96 idtab_init(void)
97 {
98 	int i;
99 	for (i = 0; i <=2; i++){
100 		idtable[i].identities = NULL;
101 		idtable[i].nentries = 0;
102 	}
103 }
104 
105 /* return private key table for requested protocol version */
106 Idtab *
107 idtab_lookup(int version)
108 {
109 	if (version < 1 || version > 2)
110 		fatal("internal error, bad protocol version %d", version);
111 	return &idtable[version];
112 }
113 
114 /* return matching private key for given public key */
115 Key *
116 lookup_private_key(Key *key, int *idx, int version)
117 {
118 	int i;
119 	Idtab *tab = idtab_lookup(version);
120 	for (i = 0; i < tab->nentries; i++) {
121 		if (key_equal(key, tab->identities[i].key)) {
122 			if (idx != NULL)
123 				*idx = i;
124 			return tab->identities[i].key;
125 		}
126 	}
127 	return NULL;
128 }
129 
130 /* send list of supported public keys to 'client' */
131 void
132 process_request_identities(SocketEntry *e, int version)
133 {
134 	Idtab *tab = idtab_lookup(version);
135 	Buffer msg;
136 	int i;
137 
138 	buffer_init(&msg);
139 	buffer_put_char(&msg, (version == 1) ?
140 	    SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
141 	buffer_put_int(&msg, tab->nentries);
142 	for (i = 0; i < tab->nentries; i++) {
143 		Identity *id = &tab->identities[i];
144 		if (id->key->type == KEY_RSA) {
145 			buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
146 			buffer_put_bignum(&msg, id->key->rsa->e);
147 			buffer_put_bignum(&msg, id->key->rsa->n);
148 		} else {
149 			unsigned char *blob;
150 			unsigned int blen;
151 			dsa_make_key_blob(id->key, &blob, &blen);
152 			buffer_put_string(&msg, blob, blen);
153 			xfree(blob);
154 		}
155 		buffer_put_cstring(&msg, id->comment);
156 	}
157 	buffer_put_int(&e->output, buffer_len(&msg));
158 	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
159 	buffer_free(&msg);
160 }
161 
162 /* ssh1 only */
163 void
164 process_authentication_challenge1(SocketEntry *e)
165 {
166 	Key *key, *private;
167 	BIGNUM *challenge;
168 	int i, len;
169 	Buffer msg;
170 	MD5_CTX md;
171 	unsigned char buf[32], mdbuf[16], session_id[16];
172 	unsigned int response_type;
173 
174 	buffer_init(&msg);
175 	key = key_new(KEY_RSA);
176 	challenge = BN_new();
177 
178 	buffer_get_int(&e->input);				/* ignored */
179 	buffer_get_bignum(&e->input, key->rsa->e);
180 	buffer_get_bignum(&e->input, key->rsa->n);
181 	buffer_get_bignum(&e->input, challenge);
182 
183 	/* Only protocol 1.1 is supported */
184 	if (buffer_len(&e->input) == 0)
185 		goto failure;
186 	buffer_get(&e->input, (char *) session_id, 16);
187 	response_type = buffer_get_int(&e->input);
188 	if (response_type != 1)
189 		goto failure;
190 
191 	private = lookup_private_key(key, NULL, 1);
192 	if (private != NULL) {
193 		/* Decrypt the challenge using the private key. */
194 		rsa_private_decrypt(challenge, challenge, private->rsa);
195 
196 		/* The response is MD5 of decrypted challenge plus session id. */
197 		len = BN_num_bytes(challenge);
198 		if (len <= 0 || len > 32) {
199 			log("process_authentication_challenge: bad challenge length %d", len);
200 			goto failure;
201 		}
202 		memset(buf, 0, 32);
203 		BN_bn2bin(challenge, buf + 32 - len);
204 		MD5_Init(&md);
205 		MD5_Update(&md, buf, 32);
206 		MD5_Update(&md, session_id, 16);
207 		MD5_Final(mdbuf, &md);
208 
209 		/* Send the response. */
210 		buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
211 		for (i = 0; i < 16; i++)
212 			buffer_put_char(&msg, mdbuf[i]);
213 		goto send;
214 	}
215 
216 failure:
217 	/* Unknown identity or protocol error.  Send failure. */
218 	buffer_put_char(&msg, SSH_AGENT_FAILURE);
219 send:
220 	buffer_put_int(&e->output, buffer_len(&msg));
221 	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
222 	key_free(key);
223 	BN_clear_free(challenge);
224 	buffer_free(&msg);
225 }
226 
227 /* ssh2 only */
228 void
229 process_sign_request2(SocketEntry *e)
230 {
231 	extern int datafellows;
232 	Key *key, *private;
233 	unsigned char *blob, *data, *signature = NULL;
234 	unsigned int blen, dlen, slen = 0;
235 	Buffer msg;
236 	int ok = -1;
237 
238 	datafellows = 0;
239 
240 	blob = buffer_get_string(&e->input, &blen);
241 	data = buffer_get_string(&e->input, &dlen);
242 	buffer_get_int(&e->input);			/* flags, unused */
243 
244 	key = dsa_key_from_blob(blob, blen);
245 	if (key != NULL) {
246 		private = lookup_private_key(key, NULL, 2);
247 		if (private != NULL)
248 			ok = dsa_sign(private, &signature, &slen, data, dlen);
249 	}
250 	key_free(key);
251 	buffer_init(&msg);
252 	if (ok == 0) {
253 		buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
254 		buffer_put_string(&msg, signature, slen);
255 	} else {
256 		buffer_put_char(&msg, SSH_AGENT_FAILURE);
257 	}
258 	buffer_put_int(&e->output, buffer_len(&msg));
259 	buffer_append(&e->output, buffer_ptr(&msg),
260 	    buffer_len(&msg));
261 	buffer_free(&msg);
262 	xfree(data);
263 	xfree(blob);
264 	if (signature != NULL)
265 		xfree(signature);
266 }
267 
268 /* shared */
269 void
270 process_remove_identity(SocketEntry *e, int version)
271 {
272 	Key *key = NULL, *private;
273 	unsigned char *blob;
274 	unsigned int blen;
275 	unsigned int bits;
276 	int success = 0;
277 
278 	switch(version){
279 	case 1:
280 		key = key_new(KEY_RSA);
281 		bits = buffer_get_int(&e->input);
282 		buffer_get_bignum(&e->input, key->rsa->e);
283 		buffer_get_bignum(&e->input, key->rsa->n);
284 
285 		if (bits != key_size(key))
286 			log("Warning: identity keysize mismatch: actual %d, announced %d",
287 			      key_size(key), bits);
288 		break;
289 	case 2:
290 		blob = buffer_get_string(&e->input, &blen);
291 		key = dsa_key_from_blob(blob, blen);
292 		xfree(blob);
293 		break;
294 	}
295 	if (key != NULL) {
296 		int idx;
297 		private = lookup_private_key(key, &idx, version);
298 		if (private != NULL) {
299 			/*
300 			 * We have this key.  Free the old key.  Since we
301 			 * don\'t want to leave empty slots in the middle of
302 			 * the array, we actually free the key there and copy
303 			 * data from the last entry.
304 			 */
305 			Idtab *tab = idtab_lookup(version);
306 			key_free(tab->identities[idx].key);
307 			xfree(tab->identities[idx].comment);
308 			if (idx != tab->nentries)
309 				tab->identities[idx] = tab->identities[tab->nentries];
310 			tab->nentries--;
311 			success = 1;
312 		}
313 		key_free(key);
314 	}
315 	buffer_put_int(&e->output, 1);
316 	buffer_put_char(&e->output,
317 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
318 }
319 
320 void
321 process_remove_all_identities(SocketEntry *e, int version)
322 {
323 	unsigned int i;
324 	Idtab *tab = idtab_lookup(version);
325 
326 	/* Loop over all identities and clear the keys. */
327 	for (i = 0; i < tab->nentries; i++) {
328 		key_free(tab->identities[i].key);
329 		xfree(tab->identities[i].comment);
330 	}
331 
332 	/* Mark that there are no identities. */
333 	tab->nentries = 0;
334 
335 	/* Send success. */
336 	buffer_put_int(&e->output, 1);
337 	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
338 	return;
339 }
340 
341 void
342 process_add_identity(SocketEntry *e, int version)
343 {
344 	Key *k = NULL;
345 	RSA *rsa;
346 	BIGNUM *aux;
347 	BN_CTX *ctx;
348 	char *type;
349 	char *comment;
350 	int success = 0;
351 	Idtab *tab = idtab_lookup(version);
352 
353 	switch (version) {
354 	case 1:
355 		k = key_new(KEY_RSA);
356 		rsa = k->rsa;
357 
358 		/* allocate mem for private key */
359 		/* XXX rsa->n and rsa->e are already allocated */
360 		rsa->d = BN_new();
361 		rsa->iqmp = BN_new();
362 		rsa->q = BN_new();
363 		rsa->p = BN_new();
364 		rsa->dmq1 = BN_new();
365 		rsa->dmp1 = BN_new();
366 
367 		buffer_get_int(&e->input);		 /* ignored */
368 
369 		buffer_get_bignum(&e->input, rsa->n);
370 		buffer_get_bignum(&e->input, rsa->e);
371 		buffer_get_bignum(&e->input, rsa->d);
372 		buffer_get_bignum(&e->input, rsa->iqmp);
373 
374 		/* SSH and SSL have p and q swapped */
375 		buffer_get_bignum(&e->input, rsa->q);	/* p */
376 		buffer_get_bignum(&e->input, rsa->p);	/* q */
377 
378 		/* Generate additional parameters */
379 		aux = BN_new();
380 		ctx = BN_CTX_new();
381 
382 		BN_sub(aux, rsa->q, BN_value_one());
383 		BN_mod(rsa->dmq1, rsa->d, aux, ctx);
384 
385 		BN_sub(aux, rsa->p, BN_value_one());
386 		BN_mod(rsa->dmp1, rsa->d, aux, ctx);
387 
388 		BN_clear_free(aux);
389 		BN_CTX_free(ctx);
390 
391 		break;
392 	case 2:
393 		type = buffer_get_string(&e->input, NULL);
394 		if (strcmp(type, KEX_DSS)) {
395 			buffer_clear(&e->input);
396 			xfree(type);
397 			goto send;
398 		}
399 		xfree(type);
400 
401 		k = key_new(KEY_DSA);
402 
403 		/* allocate mem for private key */
404 		k->dsa->priv_key = BN_new();
405 
406 		buffer_get_bignum2(&e->input, k->dsa->p);
407 		buffer_get_bignum2(&e->input, k->dsa->q);
408 		buffer_get_bignum2(&e->input, k->dsa->g);
409 		buffer_get_bignum2(&e->input, k->dsa->pub_key);
410 		buffer_get_bignum2(&e->input, k->dsa->priv_key);
411 
412 		break;
413 	}
414 
415 	comment = buffer_get_string(&e->input, NULL);
416 	if (k == NULL) {
417 		xfree(comment);
418 		goto send;
419 	}
420 	success = 1;
421 	if (lookup_private_key(k, NULL, version) == NULL) {
422 		if (tab->nentries == 0)
423 			tab->identities = xmalloc(sizeof(Identity));
424 		else
425 			tab->identities = xrealloc(tab->identities,
426 			    (tab->nentries + 1) * sizeof(Identity));
427 		tab->identities[tab->nentries].key = k;
428 		tab->identities[tab->nentries].comment = comment;
429 		/* Increment the number of identities. */
430 		tab->nentries++;
431 	} else {
432 		key_free(k);
433 		xfree(comment);
434 	}
435 send:
436 	buffer_put_int(&e->output, 1);
437 	buffer_put_char(&e->output,
438 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
439 }
440 
441 /* dispatch incoming messages */
442 
443 void
444 process_message(SocketEntry *e)
445 {
446 	unsigned int msg_len;
447 	unsigned int type;
448 	unsigned char *cp;
449 	if (buffer_len(&e->input) < 5)
450 		return;		/* Incomplete message. */
451 	cp = (unsigned char *) buffer_ptr(&e->input);
452 	msg_len = GET_32BIT(cp);
453 	if (msg_len > 256 * 1024) {
454 		shutdown(e->fd, SHUT_RDWR);
455 		close(e->fd);
456 		e->type = AUTH_UNUSED;
457 		return;
458 	}
459 	if (buffer_len(&e->input) < msg_len + 4)
460 		return;
461 	buffer_consume(&e->input, 4);
462 	type = buffer_get_char(&e->input);
463 
464 	switch (type) {
465 	/* ssh1 */
466 	case SSH_AGENTC_RSA_CHALLENGE:
467 		process_authentication_challenge1(e);
468 		break;
469 	case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
470 		process_request_identities(e, 1);
471 		break;
472 	case SSH_AGENTC_ADD_RSA_IDENTITY:
473 		process_add_identity(e, 1);
474 		break;
475 	case SSH_AGENTC_REMOVE_RSA_IDENTITY:
476 		process_remove_identity(e, 1);
477 		break;
478 	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
479 		process_remove_all_identities(e, 1);
480 		break;
481 	/* ssh2 */
482 	case SSH2_AGENTC_SIGN_REQUEST:
483 		process_sign_request2(e);
484 		break;
485 	case SSH2_AGENTC_REQUEST_IDENTITIES:
486 		process_request_identities(e, 2);
487 		break;
488 	case SSH2_AGENTC_ADD_IDENTITY:
489 		process_add_identity(e, 2);
490 		break;
491 	case SSH2_AGENTC_REMOVE_IDENTITY:
492 		process_remove_identity(e, 2);
493 		break;
494 	case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
495 		process_remove_all_identities(e, 2);
496 		break;
497 	default:
498 		/* Unknown message.  Respond with failure. */
499 		error("Unknown message %d", type);
500 		buffer_clear(&e->input);
501 		buffer_put_int(&e->output, 1);
502 		buffer_put_char(&e->output, SSH_AGENT_FAILURE);
503 		break;
504 	}
505 }
506 
507 void
508 new_socket(int type, int fd)
509 {
510 	unsigned int i, old_alloc;
511 	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
512 		error("fcntl O_NONBLOCK: %s", strerror(errno));
513 
514 	if (fd > max_fd)
515 		max_fd = fd;
516 
517 	for (i = 0; i < sockets_alloc; i++)
518 		if (sockets[i].type == AUTH_UNUSED) {
519 			sockets[i].fd = fd;
520 			sockets[i].type = type;
521 			buffer_init(&sockets[i].input);
522 			buffer_init(&sockets[i].output);
523 			return;
524 		}
525 	old_alloc = sockets_alloc;
526 	sockets_alloc += 10;
527 	if (sockets)
528 		sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
529 	else
530 		sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
531 	for (i = old_alloc; i < sockets_alloc; i++)
532 		sockets[i].type = AUTH_UNUSED;
533 	sockets[old_alloc].type = type;
534 	sockets[old_alloc].fd = fd;
535 	buffer_init(&sockets[old_alloc].input);
536 	buffer_init(&sockets[old_alloc].output);
537 }
538 
539 void
540 prepare_select(fd_set *readset, fd_set *writeset)
541 {
542 	unsigned int i;
543 	for (i = 0; i < sockets_alloc; i++)
544 		switch (sockets[i].type) {
545 		case AUTH_SOCKET:
546 		case AUTH_CONNECTION:
547 			FD_SET(sockets[i].fd, readset);
548 			if (buffer_len(&sockets[i].output) > 0)
549 				FD_SET(sockets[i].fd, writeset);
550 			break;
551 		case AUTH_UNUSED:
552 			break;
553 		default:
554 			fatal("Unknown socket type %d", sockets[i].type);
555 			break;
556 		}
557 }
558 
559 void
560 after_select(fd_set *readset, fd_set *writeset)
561 {
562 	unsigned int i;
563 	int len, sock;
564 	socklen_t slen;
565 	char buf[1024];
566 	struct sockaddr_un sunaddr;
567 
568 	for (i = 0; i < sockets_alloc; i++)
569 		switch (sockets[i].type) {
570 		case AUTH_UNUSED:
571 			break;
572 		case AUTH_SOCKET:
573 			if (FD_ISSET(sockets[i].fd, readset)) {
574 				slen = sizeof(sunaddr);
575 				sock = accept(sockets[i].fd, (struct sockaddr *) & sunaddr, &slen);
576 				if (sock < 0) {
577 					perror("accept from AUTH_SOCKET");
578 					break;
579 				}
580 				new_socket(AUTH_CONNECTION, sock);
581 			}
582 			break;
583 		case AUTH_CONNECTION:
584 			if (buffer_len(&sockets[i].output) > 0 &&
585 			    FD_ISSET(sockets[i].fd, writeset)) {
586 				len = write(sockets[i].fd, buffer_ptr(&sockets[i].output),
587 					 buffer_len(&sockets[i].output));
588 				if (len <= 0) {
589 					shutdown(sockets[i].fd, SHUT_RDWR);
590 					close(sockets[i].fd);
591 					sockets[i].type = AUTH_UNUSED;
592 					buffer_free(&sockets[i].input);
593 					buffer_free(&sockets[i].output);
594 					break;
595 				}
596 				buffer_consume(&sockets[i].output, len);
597 			}
598 			if (FD_ISSET(sockets[i].fd, readset)) {
599 				len = read(sockets[i].fd, buf, sizeof(buf));
600 				if (len <= 0) {
601 					shutdown(sockets[i].fd, SHUT_RDWR);
602 					close(sockets[i].fd);
603 					sockets[i].type = AUTH_UNUSED;
604 					buffer_free(&sockets[i].input);
605 					buffer_free(&sockets[i].output);
606 					break;
607 				}
608 				buffer_append(&sockets[i].input, buf, len);
609 				process_message(&sockets[i]);
610 			}
611 			break;
612 		default:
613 			fatal("Unknown type %d", sockets[i].type);
614 		}
615 }
616 
617 void
618 check_parent_exists(int sig)
619 {
620 	if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
621 		/* printf("Parent has died - Authentication agent exiting.\n"); */
622 		exit(1);
623 	}
624 	signal(SIGALRM, check_parent_exists);
625 	alarm(10);
626 }
627 
628 void
629 cleanup_socket(void)
630 {
631 	remove(socket_name);
632 	rmdir(socket_dir);
633 }
634 
635 void
636 cleanup_exit(int i)
637 {
638 	cleanup_socket();
639 	exit(i);
640 }
641 
642 void
643 usage()
644 {
645 	fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION);
646 	fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n",
647 		__progname);
648 	exit(1);
649 }
650 
651 int
652 main(int ac, char **av)
653 {
654 	fd_set readset, writeset;
655 	int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch;
656 	struct sockaddr_un sunaddr;
657 	pid_t pid;
658 	char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
659 
660 	/* check if RSA support exists */
661 	if (rsa_alive() == 0) {
662 		fprintf(stderr,
663 			"%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
664 			__progname);
665 		exit(1);
666 	}
667 	while ((ch = getopt(ac, av, "cks")) != -1) {
668 		switch (ch) {
669 		case 'c':
670 			if (s_flag)
671 				usage();
672 			c_flag++;
673 			break;
674 		case 'k':
675 			k_flag++;
676 			break;
677 		case 's':
678 			if (c_flag)
679 				usage();
680 			s_flag++;
681 			break;
682 		default:
683 			usage();
684 		}
685 	}
686 	ac -= optind;
687 	av += optind;
688 
689 	if (ac > 0 && (c_flag || k_flag || s_flag))
690 		usage();
691 
692 	if (ac == 0 && !c_flag && !k_flag && !s_flag) {
693 		shell = getenv("SHELL");
694 		if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
695 			c_flag = 1;
696 	}
697 	if (k_flag) {
698 		pidstr = getenv(SSH_AGENTPID_ENV_NAME);
699 		if (pidstr == NULL) {
700 			fprintf(stderr, "%s not set, cannot kill agent\n",
701 				SSH_AGENTPID_ENV_NAME);
702 			exit(1);
703 		}
704 		pid = atoi(pidstr);
705 		if (pid < 1) {	/* XXX PID_MAX check too */
706 		/* Yes, PID_MAX check please */
707 			fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
708 				SSH_AGENTPID_ENV_NAME, pidstr);
709 			exit(1);
710 		}
711 		if (kill(pid, SIGTERM) == -1) {
712 			perror("kill");
713 			exit(1);
714 		}
715 		format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
716 		printf(format, SSH_AUTHSOCKET_ENV_NAME);
717 		printf(format, SSH_AGENTPID_ENV_NAME);
718 		printf("echo Agent pid %d killed;\n", pid);
719 		exit(0);
720 	}
721 	parent_pid = getpid();
722 
723 	/* Create private directory for agent socket */
724 	strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
725 	if (mkdtemp(socket_dir) == NULL) {
726 		perror("mkdtemp: private socket dir");
727 		exit(1);
728 	}
729 	snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
730 		 parent_pid);
731 
732 	/*
733 	 * Create socket early so it will exist before command gets run from
734 	 * the parent.
735 	 */
736 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
737 	if (sock < 0) {
738 		perror("socket");
739 		cleanup_exit(1);
740 	}
741 	memset(&sunaddr, 0, sizeof(sunaddr));
742 	sunaddr.sun_family = AF_UNIX;
743 	strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
744 	if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
745 		perror("bind");
746 		cleanup_exit(1);
747 	}
748 	if (listen(sock, 5) < 0) {
749 		perror("listen");
750 		cleanup_exit(1);
751 	}
752 	/*
753 	 * Fork, and have the parent execute the command, if any, or present
754 	 * the socket data.  The child continues as the authentication agent.
755 	 */
756 	pid = fork();
757 	if (pid == -1) {
758 		perror("fork");
759 		exit(1);
760 	}
761 	if (pid != 0) {		/* Parent - execute the given command. */
762 		close(sock);
763 		snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
764 		if (ac == 0) {
765 			format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
766 			printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
767 			       SSH_AUTHSOCKET_ENV_NAME);
768 			printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
769 			       SSH_AGENTPID_ENV_NAME);
770 			printf("echo Agent pid %d;\n", pid);
771 			exit(0);
772 		}
773 		setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1);
774 		setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1);
775 		execvp(av[0], av);
776 		perror(av[0]);
777 		exit(1);
778 	}
779 	close(0);
780 	close(1);
781 	close(2);
782 
783 	if (setsid() == -1) {
784 		perror("setsid");
785 		cleanup_exit(1);
786 	}
787 	if (atexit(cleanup_socket) < 0) {
788 		perror("atexit");
789 		cleanup_exit(1);
790 	}
791 	new_socket(AUTH_SOCKET, sock);
792 	if (ac > 0) {
793 		signal(SIGALRM, check_parent_exists);
794 		alarm(10);
795 	}
796 	idtab_init();
797 	signal(SIGINT, SIG_IGN);
798 	signal(SIGPIPE, SIG_IGN);
799 	signal(SIGHUP, cleanup_exit);
800 	signal(SIGTERM, cleanup_exit);
801 	while (1) {
802 		FD_ZERO(&readset);
803 		FD_ZERO(&writeset);
804 		prepare_select(&readset, &writeset);
805 		if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0) {
806 			if (errno == EINTR)
807 				continue;
808 			exit(1);
809 		}
810 		after_select(&readset, &writeset);
811 	}
812 	/* NOTREACHED */
813 }
814