xref: /openbsd-src/usr.bin/ssh/ssh-agent.c (revision 47911bd667ac77dc523b8a13ef40b012dbffa741)
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.105 2002/10/01 20:34:12 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 	Buffer request;
70 } SocketEntry;
71 
72 u_int sockets_alloc = 0;
73 SocketEntry *sockets = NULL;
74 
75 typedef struct identity {
76 	TAILQ_ENTRY(identity) next;
77 	Key *key;
78 	char *comment;
79 	u_int death;
80 } Identity;
81 
82 typedef struct {
83 	int nentries;
84 	TAILQ_HEAD(idqueue, identity) idlist;
85 } Idtab;
86 
87 /* private key table, one per protocol version */
88 Idtab idtable[3];
89 
90 int max_fd = 0;
91 
92 /* pid of shell == parent of agent */
93 pid_t parent_pid = -1;
94 
95 /* pathname and directory for AUTH_SOCKET */
96 char socket_name[1024];
97 char socket_dir[1024];
98 
99 /* locking */
100 int locked = 0;
101 char *lock_passwd = NULL;
102 
103 extern char *__progname;
104 
105 static void
106 close_socket(SocketEntry *e)
107 {
108 	close(e->fd);
109 	e->fd = -1;
110 	e->type = AUTH_UNUSED;
111 	buffer_free(&e->input);
112 	buffer_free(&e->output);
113 	buffer_free(&e->request);
114 }
115 
116 static void
117 idtab_init(void)
118 {
119 	int i;
120 
121 	for (i = 0; i <=2; i++) {
122 		TAILQ_INIT(&idtable[i].idlist);
123 		idtable[i].nentries = 0;
124 	}
125 }
126 
127 /* return private key table for requested protocol version */
128 static Idtab *
129 idtab_lookup(int version)
130 {
131 	if (version < 1 || version > 2)
132 		fatal("internal error, bad protocol version %d", version);
133 	return &idtable[version];
134 }
135 
136 static void
137 free_identity(Identity *id)
138 {
139 	key_free(id->key);
140 	xfree(id->comment);
141 	xfree(id);
142 }
143 
144 /* return matching private key for given public key */
145 static Identity *
146 lookup_identity(Key *key, int version)
147 {
148 	Identity *id;
149 
150 	Idtab *tab = idtab_lookup(version);
151 	TAILQ_FOREACH(id, &tab->idlist, next) {
152 		if (key_equal(key, id->key))
153 			return (id);
154 	}
155 	return (NULL);
156 }
157 
158 /* send list of supported public keys to 'client' */
159 static void
160 process_request_identities(SocketEntry *e, int version)
161 {
162 	Idtab *tab = idtab_lookup(version);
163 	Identity *id;
164 	Buffer msg;
165 
166 	buffer_init(&msg);
167 	buffer_put_char(&msg, (version == 1) ?
168 	    SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
169 	buffer_put_int(&msg, tab->nentries);
170 	TAILQ_FOREACH(id, &tab->idlist, next) {
171 		if (id->key->type == KEY_RSA1) {
172 			buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
173 			buffer_put_bignum(&msg, id->key->rsa->e);
174 			buffer_put_bignum(&msg, id->key->rsa->n);
175 		} else {
176 			u_char *blob;
177 			u_int blen;
178 			key_to_blob(id->key, &blob, &blen);
179 			buffer_put_string(&msg, blob, blen);
180 			xfree(blob);
181 		}
182 		buffer_put_cstring(&msg, id->comment);
183 	}
184 	buffer_put_int(&e->output, buffer_len(&msg));
185 	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
186 	buffer_free(&msg);
187 }
188 
189 /* ssh1 only */
190 static void
191 process_authentication_challenge1(SocketEntry *e)
192 {
193 	u_char buf[32], mdbuf[16], session_id[16];
194 	u_int response_type;
195 	BIGNUM *challenge;
196 	Identity *id;
197 	int i, len;
198 	Buffer msg;
199 	MD5_CTX md;
200 	Key *key;
201 
202 	buffer_init(&msg);
203 	key = key_new(KEY_RSA1);
204 	if ((challenge = BN_new()) == NULL)
205 		fatal("process_authentication_challenge1: BN_new failed");
206 
207 	(void) buffer_get_int(&e->request);			/* ignored */
208 	buffer_get_bignum(&e->request, key->rsa->e);
209 	buffer_get_bignum(&e->request, key->rsa->n);
210 	buffer_get_bignum(&e->request, challenge);
211 
212 	/* Only protocol 1.1 is supported */
213 	if (buffer_len(&e->request) == 0)
214 		goto failure;
215 	buffer_get(&e->request, session_id, 16);
216 	response_type = buffer_get_int(&e->request);
217 	if (response_type != 1)
218 		goto failure;
219 
220 	id = lookup_identity(key, 1);
221 	if (id != NULL) {
222 		Key *private = id->key;
223 		/* Decrypt the challenge using the private key. */
224 		if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
225 			goto failure;
226 
227 		/* The response is MD5 of decrypted challenge plus session id. */
228 		len = BN_num_bytes(challenge);
229 		if (len <= 0 || len > 32) {
230 			log("process_authentication_challenge: bad challenge length %d", len);
231 			goto failure;
232 		}
233 		memset(buf, 0, 32);
234 		BN_bn2bin(challenge, buf + 32 - len);
235 		MD5_Init(&md);
236 		MD5_Update(&md, buf, 32);
237 		MD5_Update(&md, session_id, 16);
238 		MD5_Final(mdbuf, &md);
239 
240 		/* Send the response. */
241 		buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
242 		for (i = 0; i < 16; i++)
243 			buffer_put_char(&msg, mdbuf[i]);
244 		goto send;
245 	}
246 
247 failure:
248 	/* Unknown identity or protocol error.  Send failure. */
249 	buffer_put_char(&msg, SSH_AGENT_FAILURE);
250 send:
251 	buffer_put_int(&e->output, buffer_len(&msg));
252 	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
253 	key_free(key);
254 	BN_clear_free(challenge);
255 	buffer_free(&msg);
256 }
257 
258 /* ssh2 only */
259 static void
260 process_sign_request2(SocketEntry *e)
261 {
262 	u_char *blob, *data, *signature = NULL;
263 	u_int blen, dlen, slen = 0;
264 	extern int datafellows;
265 	int ok = -1, flags;
266 	Buffer msg;
267 	Key *key;
268 
269 	datafellows = 0;
270 
271 	blob = buffer_get_string(&e->request, &blen);
272 	data = buffer_get_string(&e->request, &dlen);
273 
274 	flags = buffer_get_int(&e->request);
275 	if (flags & SSH_AGENT_OLD_SIGNATURE)
276 		datafellows = SSH_BUG_SIGBLOB;
277 
278 	key = key_from_blob(blob, blen);
279 	if (key != NULL) {
280 		Identity *id = lookup_identity(key, 2);
281 		if (id != NULL)
282 			ok = key_sign(id->key, &signature, &slen, data, dlen);
283 	}
284 	key_free(key);
285 	buffer_init(&msg);
286 	if (ok == 0) {
287 		buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
288 		buffer_put_string(&msg, signature, slen);
289 	} else {
290 		buffer_put_char(&msg, SSH_AGENT_FAILURE);
291 	}
292 	buffer_put_int(&e->output, buffer_len(&msg));
293 	buffer_append(&e->output, buffer_ptr(&msg),
294 	    buffer_len(&msg));
295 	buffer_free(&msg);
296 	xfree(data);
297 	xfree(blob);
298 	if (signature != NULL)
299 		xfree(signature);
300 }
301 
302 /* shared */
303 static void
304 process_remove_identity(SocketEntry *e, int version)
305 {
306 	u_int blen, bits;
307 	int success = 0;
308 	Key *key = NULL;
309 	u_char *blob;
310 
311 	switch (version) {
312 	case 1:
313 		key = key_new(KEY_RSA1);
314 		bits = buffer_get_int(&e->request);
315 		buffer_get_bignum(&e->request, key->rsa->e);
316 		buffer_get_bignum(&e->request, key->rsa->n);
317 
318 		if (bits != key_size(key))
319 			log("Warning: identity keysize mismatch: actual %u, announced %u",
320 			    key_size(key), bits);
321 		break;
322 	case 2:
323 		blob = buffer_get_string(&e->request, &blen);
324 		key = key_from_blob(blob, blen);
325 		xfree(blob);
326 		break;
327 	}
328 	if (key != NULL) {
329 		Identity *id = lookup_identity(key, version);
330 		if (id != NULL) {
331 			/*
332 			 * We have this key.  Free the old key.  Since we
333 			 * don\'t want to leave empty slots in the middle of
334 			 * the array, we actually free the key there and move
335 			 * all the entries between the empty slot and the end
336 			 * of the array.
337 			 */
338 			Idtab *tab = idtab_lookup(version);
339 			if (tab->nentries < 1)
340 				fatal("process_remove_identity: "
341 				    "internal error: tab->nentries %d",
342 				    tab->nentries);
343 			TAILQ_REMOVE(&tab->idlist, id, next);
344 			free_identity(id);
345 			tab->nentries--;
346 			success = 1;
347 		}
348 		key_free(key);
349 	}
350 	buffer_put_int(&e->output, 1);
351 	buffer_put_char(&e->output,
352 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
353 }
354 
355 static void
356 process_remove_all_identities(SocketEntry *e, int version)
357 {
358 	Idtab *tab = idtab_lookup(version);
359 	Identity *id;
360 
361 	/* Loop over all identities and clear the keys. */
362 	for (id = TAILQ_FIRST(&tab->idlist); id;
363 	    id = TAILQ_FIRST(&tab->idlist)) {
364 		TAILQ_REMOVE(&tab->idlist, id, next);
365 		free_identity(id);
366 	}
367 
368 	/* Mark that there are no identities. */
369 	tab->nentries = 0;
370 
371 	/* Send success. */
372 	buffer_put_int(&e->output, 1);
373 	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
374 }
375 
376 static void
377 reaper(void)
378 {
379 	u_int now = time(NULL);
380 	Identity *id, *nxt;
381 	int version;
382 	Idtab *tab;
383 
384 	for (version = 1; version < 3; version++) {
385 		tab = idtab_lookup(version);
386 		for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
387 			nxt = TAILQ_NEXT(id, next);
388 			if (id->death != 0 && now >= id->death) {
389 				TAILQ_REMOVE(&tab->idlist, id, next);
390 				free_identity(id);
391 				tab->nentries--;
392 			}
393 		}
394 	}
395 }
396 
397 static void
398 process_add_identity(SocketEntry *e, int version)
399 {
400 	Idtab *tab = idtab_lookup(version);
401 	int type, success = 0, death = 0;
402 	char *type_name, *comment;
403 	Key *k = NULL;
404 
405 	switch (version) {
406 	case 1:
407 		k = key_new_private(KEY_RSA1);
408 		(void) buffer_get_int(&e->request);		/* ignored */
409 		buffer_get_bignum(&e->request, k->rsa->n);
410 		buffer_get_bignum(&e->request, k->rsa->e);
411 		buffer_get_bignum(&e->request, k->rsa->d);
412 		buffer_get_bignum(&e->request, k->rsa->iqmp);
413 
414 		/* SSH and SSL have p and q swapped */
415 		buffer_get_bignum(&e->request, k->rsa->q);	/* p */
416 		buffer_get_bignum(&e->request, k->rsa->p);	/* q */
417 
418 		/* Generate additional parameters */
419 		rsa_generate_additional_parameters(k->rsa);
420 		break;
421 	case 2:
422 		type_name = buffer_get_string(&e->request, NULL);
423 		type = key_type_from_name(type_name);
424 		xfree(type_name);
425 		switch (type) {
426 		case KEY_DSA:
427 			k = key_new_private(type);
428 			buffer_get_bignum2(&e->request, k->dsa->p);
429 			buffer_get_bignum2(&e->request, k->dsa->q);
430 			buffer_get_bignum2(&e->request, k->dsa->g);
431 			buffer_get_bignum2(&e->request, k->dsa->pub_key);
432 			buffer_get_bignum2(&e->request, k->dsa->priv_key);
433 			break;
434 		case KEY_RSA:
435 			k = key_new_private(type);
436 			buffer_get_bignum2(&e->request, k->rsa->n);
437 			buffer_get_bignum2(&e->request, k->rsa->e);
438 			buffer_get_bignum2(&e->request, k->rsa->d);
439 			buffer_get_bignum2(&e->request, k->rsa->iqmp);
440 			buffer_get_bignum2(&e->request, k->rsa->p);
441 			buffer_get_bignum2(&e->request, k->rsa->q);
442 
443 			/* Generate additional parameters */
444 			rsa_generate_additional_parameters(k->rsa);
445 			break;
446 		default:
447 			buffer_clear(&e->request);
448 			goto send;
449 		}
450 		break;
451 	}
452 	comment = buffer_get_string(&e->request, NULL);
453 	if (k == NULL) {
454 		xfree(comment);
455 		goto send;
456 	}
457 	success = 1;
458 	while (buffer_len(&e->request)) {
459 		switch (buffer_get_char(&e->request)) {
460 		case SSH_AGENT_CONSTRAIN_LIFETIME:
461 			death = time(NULL) + buffer_get_int(&e->request);
462 			break;
463 		default:
464 			break;
465 		}
466 	}
467 	if (lookup_identity(k, version) == NULL) {
468 		Identity *id = xmalloc(sizeof(Identity));
469 		id->key = k;
470 		id->comment = comment;
471 		id->death = death;
472 		TAILQ_INSERT_TAIL(&tab->idlist, id, next);
473 		/* Increment the number of identities. */
474 		tab->nentries++;
475 	} else {
476 		key_free(k);
477 		xfree(comment);
478 	}
479 send:
480 	buffer_put_int(&e->output, 1);
481 	buffer_put_char(&e->output,
482 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
483 }
484 
485 /* XXX todo: encrypt sensitive data with passphrase */
486 static void
487 process_lock_agent(SocketEntry *e, int lock)
488 {
489 	int success = 0;
490 	char *passwd;
491 
492 	passwd = buffer_get_string(&e->request, NULL);
493 	if (locked && !lock && strcmp(passwd, lock_passwd) == 0) {
494 		locked = 0;
495 		memset(lock_passwd, 0, strlen(lock_passwd));
496 		xfree(lock_passwd);
497 		lock_passwd = NULL;
498 		success = 1;
499 	} else if (!locked && lock) {
500 		locked = 1;
501 		lock_passwd = xstrdup(passwd);
502 		success = 1;
503 	}
504 	memset(passwd, 0, strlen(passwd));
505 	xfree(passwd);
506 
507 	buffer_put_int(&e->output, 1);
508 	buffer_put_char(&e->output,
509 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
510 }
511 
512 static void
513 no_identities(SocketEntry *e, u_int type)
514 {
515 	Buffer msg;
516 
517 	buffer_init(&msg);
518 	buffer_put_char(&msg,
519 	    (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ?
520 	    SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
521 	buffer_put_int(&msg, 0);
522 	buffer_put_int(&e->output, buffer_len(&msg));
523 	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
524 	buffer_free(&msg);
525 }
526 
527 #ifdef SMARTCARD
528 static void
529 process_add_smartcard_key (SocketEntry *e)
530 {
531 	char *sc_reader_id = NULL, *pin;
532 	int i, version, success = 0;
533 	Key **keys, *k;
534 	Identity *id;
535 	Idtab *tab;
536 
537 	sc_reader_id = buffer_get_string(&e->request, NULL);
538 	pin = buffer_get_string(&e->request, NULL);
539 	keys = sc_get_keys(sc_reader_id, pin);
540 	xfree(sc_reader_id);
541 	xfree(pin);
542 
543 	if (keys == NULL || keys[0] == NULL) {
544 		error("sc_get_keys failed");
545 		goto send;
546 	}
547 	for (i = 0; keys[i] != NULL; i++) {
548 		k = keys[i];
549 		version = k->type == KEY_RSA1 ? 1 : 2;
550 		tab = idtab_lookup(version);
551 		if (lookup_identity(k, version) == NULL) {
552 			id = xmalloc(sizeof(Identity));
553 			id->key = k;
554 			id->comment = xstrdup("smartcard key");
555 			id->death = 0;
556 			TAILQ_INSERT_TAIL(&tab->idlist, id, next);
557 			tab->nentries++;
558 			success = 1;
559 		} else {
560 			key_free(k);
561 		}
562 		keys[i] = NULL;
563 	}
564 	xfree(keys);
565 send:
566 	buffer_put_int(&e->output, 1);
567 	buffer_put_char(&e->output,
568 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
569 }
570 
571 static void
572 process_remove_smartcard_key(SocketEntry *e)
573 {
574 	char *sc_reader_id = NULL, *pin;
575 	int i, version, success = 0;
576 	Key **keys, *k = NULL;
577 	Identity *id;
578 	Idtab *tab;
579 
580 	sc_reader_id = buffer_get_string(&e->request, NULL);
581 	pin = buffer_get_string(&e->request, NULL);
582 	keys = sc_get_keys(sc_reader_id, pin);
583 	xfree(sc_reader_id);
584 	xfree(pin);
585 
586 	if (keys == NULL || keys[0] == NULL) {
587 		error("sc_get_keys failed");
588 		goto send;
589 	}
590 	for (i = 0; keys[i] != NULL; i++) {
591 		k = keys[i];
592 		version = k->type == KEY_RSA1 ? 1 : 2;
593 		if ((id = lookup_identity(k, version)) != NULL) {
594 			tab = idtab_lookup(version);
595 			TAILQ_REMOVE(&tab->idlist, id, next);
596 			tab->nentries--;
597 			free_identity(id);
598 			success = 1;
599 		}
600 		key_free(k);
601 		keys[i] = NULL;
602 	}
603 	xfree(keys);
604 send:
605 	buffer_put_int(&e->output, 1);
606 	buffer_put_char(&e->output,
607 	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
608 }
609 #endif /* SMARTCARD */
610 
611 /* dispatch incoming messages */
612 
613 static void
614 process_message(SocketEntry *e)
615 {
616 	u_int msg_len, type;
617 	u_char *cp;
618 
619 	/* kill dead keys */
620 	reaper();
621 
622 	if (buffer_len(&e->input) < 5)
623 		return;		/* Incomplete message. */
624 	cp = buffer_ptr(&e->input);
625 	msg_len = GET_32BIT(cp);
626 	if (msg_len > 256 * 1024) {
627 		close_socket(e);
628 		return;
629 	}
630 	if (buffer_len(&e->input) < msg_len + 4)
631 		return;
632 
633 	/* move the current input to e->request */
634 	buffer_consume(&e->input, 4);
635 	buffer_clear(&e->request);
636 	buffer_append(&e->request, buffer_ptr(&e->input), msg_len);
637 	buffer_consume(&e->input, msg_len);
638 	type = buffer_get_char(&e->request);
639 
640 	/* check wheter agent is locked */
641 	if (locked && type != SSH_AGENTC_UNLOCK) {
642 		buffer_clear(&e->request);
643 		switch (type) {
644 		case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
645 		case SSH2_AGENTC_REQUEST_IDENTITIES:
646 			/* send empty lists */
647 			no_identities(e, type);
648 			break;
649 		default:
650 			/* send a fail message for all other request types */
651 			buffer_put_int(&e->output, 1);
652 			buffer_put_char(&e->output, SSH_AGENT_FAILURE);
653 		}
654 		return;
655 	}
656 
657 	debug("type %d", type);
658 	switch (type) {
659 	case SSH_AGENTC_LOCK:
660 	case SSH_AGENTC_UNLOCK:
661 		process_lock_agent(e, type == SSH_AGENTC_LOCK);
662 		break;
663 	/* ssh1 */
664 	case SSH_AGENTC_RSA_CHALLENGE:
665 		process_authentication_challenge1(e);
666 		break;
667 	case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
668 		process_request_identities(e, 1);
669 		break;
670 	case SSH_AGENTC_ADD_RSA_IDENTITY:
671 	case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
672 		process_add_identity(e, 1);
673 		break;
674 	case SSH_AGENTC_REMOVE_RSA_IDENTITY:
675 		process_remove_identity(e, 1);
676 		break;
677 	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
678 		process_remove_all_identities(e, 1);
679 		break;
680 	/* ssh2 */
681 	case SSH2_AGENTC_SIGN_REQUEST:
682 		process_sign_request2(e);
683 		break;
684 	case SSH2_AGENTC_REQUEST_IDENTITIES:
685 		process_request_identities(e, 2);
686 		break;
687 	case SSH2_AGENTC_ADD_IDENTITY:
688 	case SSH2_AGENTC_ADD_ID_CONSTRAINED:
689 		process_add_identity(e, 2);
690 		break;
691 	case SSH2_AGENTC_REMOVE_IDENTITY:
692 		process_remove_identity(e, 2);
693 		break;
694 	case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
695 		process_remove_all_identities(e, 2);
696 		break;
697 #ifdef SMARTCARD
698 	case SSH_AGENTC_ADD_SMARTCARD_KEY:
699 		process_add_smartcard_key(e);
700 		break;
701 	case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
702 		process_remove_smartcard_key(e);
703 		break;
704 #endif /* SMARTCARD */
705 	default:
706 		/* Unknown message.  Respond with failure. */
707 		error("Unknown message %d", type);
708 		buffer_clear(&e->request);
709 		buffer_put_int(&e->output, 1);
710 		buffer_put_char(&e->output, SSH_AGENT_FAILURE);
711 		break;
712 	}
713 }
714 
715 static void
716 new_socket(sock_type type, int fd)
717 {
718 	u_int i, old_alloc;
719 
720 	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
721 		error("fcntl O_NONBLOCK: %s", strerror(errno));
722 
723 	if (fd > max_fd)
724 		max_fd = fd;
725 
726 	for (i = 0; i < sockets_alloc; i++)
727 		if (sockets[i].type == AUTH_UNUSED) {
728 			sockets[i].fd = fd;
729 			sockets[i].type = type;
730 			buffer_init(&sockets[i].input);
731 			buffer_init(&sockets[i].output);
732 			buffer_init(&sockets[i].request);
733 			return;
734 		}
735 	old_alloc = sockets_alloc;
736 	sockets_alloc += 10;
737 	if (sockets)
738 		sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
739 	else
740 		sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
741 	for (i = old_alloc; i < sockets_alloc; i++)
742 		sockets[i].type = AUTH_UNUSED;
743 	sockets[old_alloc].type = type;
744 	sockets[old_alloc].fd = fd;
745 	buffer_init(&sockets[old_alloc].input);
746 	buffer_init(&sockets[old_alloc].output);
747 	buffer_init(&sockets[old_alloc].request);
748 }
749 
750 static int
751 prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, int *nallocp)
752 {
753 	u_int i, sz;
754 	int n = 0;
755 
756 	for (i = 0; i < sockets_alloc; i++) {
757 		switch (sockets[i].type) {
758 		case AUTH_SOCKET:
759 		case AUTH_CONNECTION:
760 			n = MAX(n, sockets[i].fd);
761 			break;
762 		case AUTH_UNUSED:
763 			break;
764 		default:
765 			fatal("Unknown socket type %d", sockets[i].type);
766 			break;
767 		}
768 	}
769 
770 	sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
771 	if (*fdrp == NULL || sz > *nallocp) {
772 		if (*fdrp)
773 			xfree(*fdrp);
774 		if (*fdwp)
775 			xfree(*fdwp);
776 		*fdrp = xmalloc(sz);
777 		*fdwp = xmalloc(sz);
778 		*nallocp = sz;
779 	}
780 	if (n < *fdl)
781 		debug("XXX shrink: %d < %d", n, *fdl);
782 	*fdl = n;
783 	memset(*fdrp, 0, sz);
784 	memset(*fdwp, 0, sz);
785 
786 	for (i = 0; i < sockets_alloc; i++) {
787 		switch (sockets[i].type) {
788 		case AUTH_SOCKET:
789 		case AUTH_CONNECTION:
790 			FD_SET(sockets[i].fd, *fdrp);
791 			if (buffer_len(&sockets[i].output) > 0)
792 				FD_SET(sockets[i].fd, *fdwp);
793 			break;
794 		default:
795 			break;
796 		}
797 	}
798 	return (1);
799 }
800 
801 static void
802 after_select(fd_set *readset, fd_set *writeset)
803 {
804 	struct sockaddr_un sunaddr;
805 	socklen_t slen;
806 	char buf[1024];
807 	int len, sock;
808 	u_int i;
809 	uid_t euid;
810 	gid_t egid;
811 
812 	for (i = 0; i < sockets_alloc; i++)
813 		switch (sockets[i].type) {
814 		case AUTH_UNUSED:
815 			break;
816 		case AUTH_SOCKET:
817 			if (FD_ISSET(sockets[i].fd, readset)) {
818 				slen = sizeof(sunaddr);
819 				sock = accept(sockets[i].fd,
820 				    (struct sockaddr *) &sunaddr, &slen);
821 				if (sock < 0) {
822 					error("accept from AUTH_SOCKET: %s",
823 					    strerror(errno));
824 					break;
825 				}
826 				if (getpeereid(sock, &euid, &egid) < 0) {
827 					error("getpeereid %d failed: %s",
828 					    sock, strerror(errno));
829 					close(sock);
830 					break;
831 				}
832 				if ((euid != 0) && (getuid() != euid)) {
833 					error("uid mismatch: "
834 					    "peer euid %u != uid %u",
835 					    (u_int) euid, (u_int) getuid());
836 					close(sock);
837 					break;
838 				}
839 				new_socket(AUTH_CONNECTION, sock);
840 			}
841 			break;
842 		case AUTH_CONNECTION:
843 			if (buffer_len(&sockets[i].output) > 0 &&
844 			    FD_ISSET(sockets[i].fd, writeset)) {
845 				do {
846 					len = write(sockets[i].fd,
847 					    buffer_ptr(&sockets[i].output),
848 					    buffer_len(&sockets[i].output));
849 					if (len == -1 && (errno == EAGAIN ||
850 					    errno == EINTR))
851 						continue;
852 					break;
853 				} while (1);
854 				if (len <= 0) {
855 					close_socket(&sockets[i]);
856 					break;
857 				}
858 				buffer_consume(&sockets[i].output, len);
859 			}
860 			if (FD_ISSET(sockets[i].fd, readset)) {
861 				do {
862 					len = read(sockets[i].fd, buf, sizeof(buf));
863 					if (len == -1 && (errno == EAGAIN ||
864 					    errno == EINTR))
865 						continue;
866 					break;
867 				} while (1);
868 				if (len <= 0) {
869 					close_socket(&sockets[i]);
870 					break;
871 				}
872 				buffer_append(&sockets[i].input, buf, len);
873 				process_message(&sockets[i]);
874 			}
875 			break;
876 		default:
877 			fatal("Unknown type %d", sockets[i].type);
878 		}
879 }
880 
881 static void
882 cleanup_socket(void *p)
883 {
884 	if (socket_name[0])
885 		unlink(socket_name);
886 	if (socket_dir[0])
887 		rmdir(socket_dir);
888 }
889 
890 static void
891 cleanup_exit(int i)
892 {
893 	cleanup_socket(NULL);
894 	exit(i);
895 }
896 
897 static void
898 cleanup_handler(int sig)
899 {
900 	cleanup_socket(NULL);
901 	_exit(2);
902 }
903 
904 static void
905 check_parent_exists(int sig)
906 {
907 	int save_errno = errno;
908 
909 	if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
910 		/* printf("Parent has died - Authentication agent exiting.\n"); */
911 		cleanup_handler(sig); /* safe */
912 	}
913 	signal(SIGALRM, check_parent_exists);
914 	alarm(10);
915 	errno = save_errno;
916 }
917 
918 static void
919 usage(void)
920 {
921 	fprintf(stderr, "Usage: %s [options] [command [args ...]]\n",
922 	    __progname);
923 	fprintf(stderr, "Options:\n");
924 	fprintf(stderr, "  -c          Generate C-shell commands on stdout.\n");
925 	fprintf(stderr, "  -s          Generate Bourne shell commands on stdout.\n");
926 	fprintf(stderr, "  -k          Kill the current agent.\n");
927 	fprintf(stderr, "  -d          Debug mode.\n");
928 	fprintf(stderr, "  -a socket   Bind agent socket to given name.\n");
929 	exit(1);
930 }
931 
932 int
933 main(int ac, char **av)
934 {
935 	int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc;
936 	char *shell, *format, *pidstr, *agentsocket = NULL;
937 	fd_set *readsetp = NULL, *writesetp = NULL;
938 	struct sockaddr_un sunaddr;
939 	struct rlimit rlim;
940 	extern int optind;
941 	extern char *optarg;
942 	pid_t pid;
943 	char pidstrbuf[1 + 3 * sizeof pid];
944 
945 	/* drop */
946 	setegid(getgid());
947 	setgid(getgid());
948 
949 	SSLeay_add_all_algorithms();
950 
951 	while ((ch = getopt(ac, av, "cdksa:")) != -1) {
952 		switch (ch) {
953 		case 'c':
954 			if (s_flag)
955 				usage();
956 			c_flag++;
957 			break;
958 		case 'k':
959 			k_flag++;
960 			break;
961 		case 's':
962 			if (c_flag)
963 				usage();
964 			s_flag++;
965 			break;
966 		case 'd':
967 			if (d_flag)
968 				usage();
969 			d_flag++;
970 			break;
971 		case 'a':
972 			agentsocket = optarg;
973 			break;
974 		default:
975 			usage();
976 		}
977 	}
978 	ac -= optind;
979 	av += optind;
980 
981 	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
982 		usage();
983 
984 	if (ac == 0 && !c_flag && !s_flag) {
985 		shell = getenv("SHELL");
986 		if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
987 			c_flag = 1;
988 	}
989 	if (k_flag) {
990 		pidstr = getenv(SSH_AGENTPID_ENV_NAME);
991 		if (pidstr == NULL) {
992 			fprintf(stderr, "%s not set, cannot kill agent\n",
993 			    SSH_AGENTPID_ENV_NAME);
994 			exit(1);
995 		}
996 		pid = atoi(pidstr);
997 		if (pid < 1) {
998 			fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
999 			    SSH_AGENTPID_ENV_NAME, pidstr);
1000 			exit(1);
1001 		}
1002 		if (kill(pid, SIGTERM) == -1) {
1003 			perror("kill");
1004 			exit(1);
1005 		}
1006 		format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
1007 		printf(format, SSH_AUTHSOCKET_ENV_NAME);
1008 		printf(format, SSH_AGENTPID_ENV_NAME);
1009 		printf("echo Agent pid %ld killed;\n", (long)pid);
1010 		exit(0);
1011 	}
1012 	parent_pid = getpid();
1013 
1014 	if (agentsocket == NULL) {
1015 		/* Create private directory for agent socket */
1016 		strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
1017 		if (mkdtemp(socket_dir) == NULL) {
1018 			perror("mkdtemp: private socket dir");
1019 			exit(1);
1020 		}
1021 		snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
1022 		    (long)parent_pid);
1023 	} else {
1024 		/* Try to use specified agent socket */
1025 		socket_dir[0] = '\0';
1026 		strlcpy(socket_name, agentsocket, sizeof socket_name);
1027 	}
1028 
1029 	/*
1030 	 * Create socket early so it will exist before command gets run from
1031 	 * the parent.
1032 	 */
1033 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
1034 	if (sock < 0) {
1035 		perror("socket");
1036 		cleanup_exit(1);
1037 	}
1038 	memset(&sunaddr, 0, sizeof(sunaddr));
1039 	sunaddr.sun_family = AF_UNIX;
1040 	strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
1041 	if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
1042 		perror("bind");
1043 		cleanup_exit(1);
1044 	}
1045 	if (listen(sock, 128) < 0) {
1046 		perror("listen");
1047 		cleanup_exit(1);
1048 	}
1049 
1050 	/*
1051 	 * Fork, and have the parent execute the command, if any, or present
1052 	 * the socket data.  The child continues as the authentication agent.
1053 	 */
1054 	if (d_flag) {
1055 		log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1);
1056 		format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
1057 		printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
1058 		    SSH_AUTHSOCKET_ENV_NAME);
1059 		printf("echo Agent pid %ld;\n", (long)parent_pid);
1060 		goto skip;
1061 	}
1062 	pid = fork();
1063 	if (pid == -1) {
1064 		perror("fork");
1065 		cleanup_exit(1);
1066 	}
1067 	if (pid != 0) {		/* Parent - execute the given command. */
1068 		close(sock);
1069 		snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
1070 		if (ac == 0) {
1071 			format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
1072 			printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
1073 			    SSH_AUTHSOCKET_ENV_NAME);
1074 			printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
1075 			    SSH_AGENTPID_ENV_NAME);
1076 			printf("echo Agent pid %ld;\n", (long)pid);
1077 			exit(0);
1078 		}
1079 		if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
1080 		    setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
1081 			perror("setenv");
1082 			exit(1);
1083 		}
1084 		execvp(av[0], av);
1085 		perror(av[0]);
1086 		exit(1);
1087 	}
1088 	/* child */
1089 	log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
1090 
1091 	if (setsid() == -1) {
1092 		error("setsid: %s", strerror(errno));
1093 		cleanup_exit(1);
1094 	}
1095 
1096 	(void)chdir("/");
1097 	close(0);
1098 	close(1);
1099 	close(2);
1100 
1101 	/* deny core dumps, since memory contains unencrypted private keys */
1102 	rlim.rlim_cur = rlim.rlim_max = 0;
1103 	if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
1104 		error("setrlimit RLIMIT_CORE: %s", strerror(errno));
1105 		cleanup_exit(1);
1106 	}
1107 
1108 skip:
1109 	fatal_add_cleanup(cleanup_socket, NULL);
1110 	new_socket(AUTH_SOCKET, sock);
1111 	if (ac > 0) {
1112 		signal(SIGALRM, check_parent_exists);
1113 		alarm(10);
1114 	}
1115 	idtab_init();
1116 	if (!d_flag)
1117 		signal(SIGINT, SIG_IGN);
1118 	signal(SIGPIPE, SIG_IGN);
1119 	signal(SIGHUP, cleanup_handler);
1120 	signal(SIGTERM, cleanup_handler);
1121 	nalloc = 0;
1122 
1123 	while (1) {
1124 		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc);
1125 		if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) {
1126 			if (errno == EINTR)
1127 				continue;
1128 			fatal("select: %s", strerror(errno));
1129 		}
1130 		after_select(readsetp, writesetp);
1131 	}
1132 	/* NOTREACHED */
1133 }
1134