xref: /openbsd-src/usr.bin/ssh/ssh-agent.c (revision 1fc27e414118cd8922c6b93fbaeb7a5246bfd593)
1 /*	$OpenBSD: ssh-agent.c,v 1.25 2000/01/02 21:51:03 markus 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  * Created: Wed Mar 29 03:46:59 1995 ylo
8  * The authentication agent program.
9  */
10 
11 #include "includes.h"
12 RCSID("$OpenBSD: ssh-agent.c,v 1.25 2000/01/02 21:51:03 markus Exp $");
13 
14 #include "ssh.h"
15 #include "rsa.h"
16 #include "authfd.h"
17 #include "buffer.h"
18 #include "bufaux.h"
19 #include "xmalloc.h"
20 #include "packet.h"
21 #include "getput.h"
22 #include "mpaux.h"
23 
24 #include <ssl/md5.h>
25 
26 typedef struct {
27 	int fd;
28 	enum {
29 		AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION
30 	} type;
31 	Buffer input;
32 	Buffer output;
33 } SocketEntry;
34 
35 unsigned int sockets_alloc = 0;
36 SocketEntry *sockets = NULL;
37 
38 typedef struct {
39 	RSA *key;
40 	char *comment;
41 } Identity;
42 
43 unsigned int num_identities = 0;
44 Identity *identities = NULL;
45 
46 int max_fd = 0;
47 
48 /* pid of shell == parent of agent */
49 int parent_pid = -1;
50 
51 /* pathname and directory for AUTH_SOCKET */
52 char socket_name[1024];
53 char socket_dir[1024];
54 
55 extern char *__progname;
56 
57 void
58 process_request_identity(SocketEntry *e)
59 {
60 	Buffer msg;
61 	int i;
62 
63 	buffer_init(&msg);
64 	buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER);
65 	buffer_put_int(&msg, num_identities);
66 	for (i = 0; i < num_identities; i++) {
67 		buffer_put_int(&msg, BN_num_bits(identities[i].key->n));
68 		buffer_put_bignum(&msg, identities[i].key->e);
69 		buffer_put_bignum(&msg, identities[i].key->n);
70 		buffer_put_string(&msg, identities[i].comment,
71 				  strlen(identities[i].comment));
72 	}
73 	buffer_put_int(&e->output, buffer_len(&msg));
74 	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
75 	buffer_free(&msg);
76 }
77 
78 void
79 process_authentication_challenge(SocketEntry *e)
80 {
81 	int i, pub_bits, len;
82 	BIGNUM *pub_e, *pub_n, *challenge;
83 	Buffer msg;
84 	MD5_CTX md;
85 	unsigned char buf[32], mdbuf[16], session_id[16];
86 	unsigned int response_type;
87 
88 	buffer_init(&msg);
89 	pub_e = BN_new();
90 	pub_n = BN_new();
91 	challenge = BN_new();
92 	pub_bits = buffer_get_int(&e->input);
93 	buffer_get_bignum(&e->input, pub_e);
94 	buffer_get_bignum(&e->input, pub_n);
95 	buffer_get_bignum(&e->input, challenge);
96 	if (buffer_len(&e->input) == 0) {
97 		/* Compatibility code for old servers. */
98 		memset(session_id, 0, 16);
99 		response_type = 0;
100 	} else {
101 		/* New code. */
102 		buffer_get(&e->input, (char *) session_id, 16);
103 		response_type = buffer_get_int(&e->input);
104 	}
105 	for (i = 0; i < num_identities; i++)
106 		if (pub_bits == BN_num_bits(identities[i].key->n) &&
107 		    BN_cmp(pub_e, identities[i].key->e) == 0 &&
108 		    BN_cmp(pub_n, identities[i].key->n) == 0) {
109 			/* Decrypt the challenge using the private key. */
110 			rsa_private_decrypt(challenge, challenge, identities[i].key);
111 
112 			/* Compute the desired response. */
113 			switch (response_type) {
114 			case 0:/* As of protocol 1.0 */
115 				/* This response type is no longer supported. */
116 				log("Compatibility with ssh protocol 1.0 no longer supported.");
117 				buffer_put_char(&msg, SSH_AGENT_FAILURE);
118 				goto send;
119 
120 			case 1:/* As of protocol 1.1 */
121 				/* The response is MD5 of decrypted challenge plus session id. */
122 				len = BN_num_bytes(challenge);
123 
124 				if (len <= 0 || len > 32) {
125 					fatal("process_authentication_challenge: "
126 					 "bad challenge length %d", len);
127 				}
128 				memset(buf, 0, 32);
129 				BN_bn2bin(challenge, buf + 32 - len);
130 				MD5_Init(&md);
131 				MD5_Update(&md, buf, 32);
132 				MD5_Update(&md, session_id, 16);
133 				MD5_Final(mdbuf, &md);
134 				break;
135 
136 			default:
137 				fatal("process_authentication_challenge: bad response_type %d",
138 				      response_type);
139 				break;
140 			}
141 
142 			/* Send the response. */
143 			buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
144 			for (i = 0; i < 16; i++)
145 				buffer_put_char(&msg, mdbuf[i]);
146 
147 			goto send;
148 		}
149 	/* Unknown identity.  Send failure. */
150 	buffer_put_char(&msg, SSH_AGENT_FAILURE);
151 send:
152 	buffer_put_int(&e->output, buffer_len(&msg));
153 	buffer_append(&e->output, buffer_ptr(&msg),
154 		      buffer_len(&msg));
155 	buffer_free(&msg);
156 	BN_clear_free(pub_e);
157 	BN_clear_free(pub_n);
158 	BN_clear_free(challenge);
159 }
160 
161 void
162 process_remove_identity(SocketEntry *e)
163 {
164 	unsigned int bits;
165 	unsigned int i;
166 	BIGNUM *dummy, *n;
167 
168 	dummy = BN_new();
169 	n = BN_new();
170 
171 	/* Get the key from the packet. */
172 	bits = buffer_get_int(&e->input);
173 	buffer_get_bignum(&e->input, dummy);
174 	buffer_get_bignum(&e->input, n);
175 
176 	if (bits != BN_num_bits(n))
177 		error("Warning: identity keysize mismatch: actual %d, announced %d",
178 		      BN_num_bits(n), bits);
179 
180 	/* Check if we have the key. */
181 	for (i = 0; i < num_identities; i++)
182 		if (BN_cmp(identities[i].key->n, n) == 0) {
183 			/*
184 			 * We have this key.  Free the old key.  Since we
185 			 * don\'t want to leave empty slots in the middle of
186 			 * the array, we actually free the key there and copy
187 			 * data from the last entry.
188 			 */
189 			RSA_free(identities[i].key);
190 			xfree(identities[i].comment);
191 			if (i < num_identities - 1)
192 				identities[i] = identities[num_identities - 1];
193 			num_identities--;
194 			BN_clear_free(dummy);
195 			BN_clear_free(n);
196 
197 			/* Send success. */
198 			buffer_put_int(&e->output, 1);
199 			buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
200 			return;
201 		}
202 	/* We did not have the key. */
203 	BN_clear(dummy);
204 	BN_clear(n);
205 
206 	/* Send failure. */
207 	buffer_put_int(&e->output, 1);
208 	buffer_put_char(&e->output, SSH_AGENT_FAILURE);
209 }
210 
211 /*
212  * Removes all identities from the agent.
213  */
214 void
215 process_remove_all_identities(SocketEntry *e)
216 {
217 	unsigned int i;
218 
219 	/* Loop over all identities and clear the keys. */
220 	for (i = 0; i < num_identities; i++) {
221 		RSA_free(identities[i].key);
222 		xfree(identities[i].comment);
223 	}
224 
225 	/* Mark that there are no identities. */
226 	num_identities = 0;
227 
228 	/* Send success. */
229 	buffer_put_int(&e->output, 1);
230 	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
231 	return;
232 }
233 
234 /*
235  * Adds an identity to the agent.
236  */
237 void
238 process_add_identity(SocketEntry *e)
239 {
240 	RSA *k;
241 	int i;
242 	BIGNUM *aux;
243 	BN_CTX *ctx;
244 
245 	if (num_identities == 0)
246 		identities = xmalloc(sizeof(Identity));
247 	else
248 		identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity));
249 
250 	identities[num_identities].key = RSA_new();
251 	k = identities[num_identities].key;
252 	buffer_get_int(&e->input);	/* bits */
253 	k->n = BN_new();
254 	buffer_get_bignum(&e->input, k->n);
255 	k->e = BN_new();
256 	buffer_get_bignum(&e->input, k->e);
257 	k->d = BN_new();
258 	buffer_get_bignum(&e->input, k->d);
259 	k->iqmp = BN_new();
260 	buffer_get_bignum(&e->input, k->iqmp);
261 	/* SSH and SSL have p and q swapped */
262 	k->q = BN_new();
263 	buffer_get_bignum(&e->input, k->q);	/* p */
264 	k->p = BN_new();
265 	buffer_get_bignum(&e->input, k->p);	/* q */
266 
267 	/* Generate additional parameters */
268 	aux = BN_new();
269 	ctx = BN_CTX_new();
270 
271 	BN_sub(aux, k->q, BN_value_one());
272 	k->dmq1 = BN_new();
273 	BN_mod(k->dmq1, k->d, aux, ctx);
274 
275 	BN_sub(aux, k->p, BN_value_one());
276 	k->dmp1 = BN_new();
277 	BN_mod(k->dmp1, k->d, aux, ctx);
278 
279 	BN_clear_free(aux);
280 	BN_CTX_free(ctx);
281 
282 	identities[num_identities].comment = buffer_get_string(&e->input, NULL);
283 
284 	/* Check if we already have the key. */
285 	for (i = 0; i < num_identities; i++)
286 		if (BN_cmp(identities[i].key->n, k->n) == 0) {
287 			/*
288 			 * We already have this key.  Clear and free the new
289 			 * data and return success.
290 			 */
291 			RSA_free(k);
292 			xfree(identities[num_identities].comment);
293 
294 			/* Send success. */
295 			buffer_put_int(&e->output, 1);
296 			buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
297 			return;
298 		}
299 	/* Increment the number of identities. */
300 	num_identities++;
301 
302 	/* Send a success message. */
303 	buffer_put_int(&e->output, 1);
304 	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
305 }
306 
307 void
308 process_message(SocketEntry *e)
309 {
310 	unsigned int msg_len;
311 	unsigned int type;
312 	unsigned char *cp;
313 	if (buffer_len(&e->input) < 5)
314 		return;		/* Incomplete message. */
315 	cp = (unsigned char *) buffer_ptr(&e->input);
316 	msg_len = GET_32BIT(cp);
317 	if (msg_len > 256 * 1024) {
318 		shutdown(e->fd, SHUT_RDWR);
319 		close(e->fd);
320 		e->type = AUTH_UNUSED;
321 		return;
322 	}
323 	if (buffer_len(&e->input) < msg_len + 4)
324 		return;
325 	buffer_consume(&e->input, 4);
326 	type = buffer_get_char(&e->input);
327 
328 	switch (type) {
329 	case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
330 		process_request_identity(e);
331 		break;
332 	case SSH_AGENTC_RSA_CHALLENGE:
333 		process_authentication_challenge(e);
334 		break;
335 	case SSH_AGENTC_ADD_RSA_IDENTITY:
336 		process_add_identity(e);
337 		break;
338 	case SSH_AGENTC_REMOVE_RSA_IDENTITY:
339 		process_remove_identity(e);
340 		break;
341 	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
342 		process_remove_all_identities(e);
343 		break;
344 	default:
345 		/* Unknown message.  Respond with failure. */
346 		error("Unknown message %d", type);
347 		buffer_clear(&e->input);
348 		buffer_put_int(&e->output, 1);
349 		buffer_put_char(&e->output, SSH_AGENT_FAILURE);
350 		break;
351 	}
352 }
353 
354 void
355 new_socket(int type, int fd)
356 {
357 	unsigned int i, old_alloc;
358 	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
359 		error("fcntl O_NONBLOCK: %s", strerror(errno));
360 
361 	if (fd > max_fd)
362 		max_fd = fd;
363 
364 	for (i = 0; i < sockets_alloc; i++)
365 		if (sockets[i].type == AUTH_UNUSED) {
366 			sockets[i].fd = fd;
367 			sockets[i].type = type;
368 			buffer_init(&sockets[i].input);
369 			buffer_init(&sockets[i].output);
370 			return;
371 		}
372 	old_alloc = sockets_alloc;
373 	sockets_alloc += 10;
374 	if (sockets)
375 		sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
376 	else
377 		sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
378 	for (i = old_alloc; i < sockets_alloc; i++)
379 		sockets[i].type = AUTH_UNUSED;
380 	sockets[old_alloc].type = type;
381 	sockets[old_alloc].fd = fd;
382 	buffer_init(&sockets[old_alloc].input);
383 	buffer_init(&sockets[old_alloc].output);
384 }
385 
386 void
387 prepare_select(fd_set *readset, fd_set *writeset)
388 {
389 	unsigned int i;
390 	for (i = 0; i < sockets_alloc; i++)
391 		switch (sockets[i].type) {
392 		case AUTH_SOCKET:
393 		case AUTH_CONNECTION:
394 			FD_SET(sockets[i].fd, readset);
395 			if (buffer_len(&sockets[i].output) > 0)
396 				FD_SET(sockets[i].fd, writeset);
397 			break;
398 		case AUTH_UNUSED:
399 			break;
400 		default:
401 			fatal("Unknown socket type %d", sockets[i].type);
402 			break;
403 		}
404 }
405 
406 void
407 after_select(fd_set *readset, fd_set *writeset)
408 {
409 	unsigned int i;
410 	int len, sock;
411 	char buf[1024];
412 	struct sockaddr_un sunaddr;
413 
414 	for (i = 0; i < sockets_alloc; i++)
415 		switch (sockets[i].type) {
416 		case AUTH_UNUSED:
417 			break;
418 		case AUTH_SOCKET:
419 			if (FD_ISSET(sockets[i].fd, readset)) {
420 				len = sizeof(sunaddr);
421 				sock = accept(sockets[i].fd, (struct sockaddr *) & sunaddr, &len);
422 				if (sock < 0) {
423 					perror("accept from AUTH_SOCKET");
424 					break;
425 				}
426 				new_socket(AUTH_CONNECTION, sock);
427 			}
428 			break;
429 		case AUTH_CONNECTION:
430 			if (buffer_len(&sockets[i].output) > 0 &&
431 			    FD_ISSET(sockets[i].fd, writeset)) {
432 				len = write(sockets[i].fd, buffer_ptr(&sockets[i].output),
433 					 buffer_len(&sockets[i].output));
434 				if (len <= 0) {
435 					shutdown(sockets[i].fd, SHUT_RDWR);
436 					close(sockets[i].fd);
437 					sockets[i].type = AUTH_UNUSED;
438 					break;
439 				}
440 				buffer_consume(&sockets[i].output, len);
441 			}
442 			if (FD_ISSET(sockets[i].fd, readset)) {
443 				len = read(sockets[i].fd, buf, sizeof(buf));
444 				if (len <= 0) {
445 					shutdown(sockets[i].fd, SHUT_RDWR);
446 					close(sockets[i].fd);
447 					sockets[i].type = AUTH_UNUSED;
448 					break;
449 				}
450 				buffer_append(&sockets[i].input, buf, len);
451 				process_message(&sockets[i]);
452 			}
453 			break;
454 		default:
455 			fatal("Unknown type %d", sockets[i].type);
456 		}
457 }
458 
459 void
460 check_parent_exists(int sig)
461 {
462 	if (kill(parent_pid, 0) < 0) {
463 		/* printf("Parent has died - Authentication agent exiting.\n"); */
464 		exit(1);
465 	}
466 	signal(SIGALRM, check_parent_exists);
467 	alarm(10);
468 }
469 
470 void
471 cleanup_socket(void)
472 {
473 	remove(socket_name);
474 	rmdir(socket_dir);
475 }
476 
477 void
478 cleanup_exit(int i)
479 {
480 	cleanup_socket();
481 	exit(i);
482 }
483 
484 void
485 usage()
486 {
487 	fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION);
488 	fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n",
489 		__progname);
490 	exit(1);
491 }
492 
493 int
494 main(int ac, char **av)
495 {
496 	fd_set readset, writeset;
497 	int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch;
498 	struct sockaddr_un sunaddr;
499 	pid_t pid;
500 	char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
501 
502 	/* check if RSA support exists */
503 	if (rsa_alive() == 0) {
504 		fprintf(stderr,
505 			"%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
506 			__progname);
507 		exit(1);
508 	}
509 	while ((ch = getopt(ac, av, "cks")) != -1) {
510 		switch (ch) {
511 		case 'c':
512 			if (s_flag)
513 				usage();
514 			c_flag++;
515 			break;
516 		case 'k':
517 			k_flag++;
518 			break;
519 		case 's':
520 			if (c_flag)
521 				usage();
522 			s_flag++;
523 			break;
524 		default:
525 			usage();
526 		}
527 	}
528 	ac -= optind;
529 	av += optind;
530 
531 	if (ac > 0 && (c_flag || k_flag || s_flag))
532 		usage();
533 
534 	if (ac == 0 && !c_flag && !k_flag && !s_flag) {
535 		shell = getenv("SHELL");
536 		if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
537 			c_flag = 1;
538 	}
539 	if (k_flag) {
540 		pidstr = getenv(SSH_AGENTPID_ENV_NAME);
541 		if (pidstr == NULL) {
542 			fprintf(stderr, "%s not set, cannot kill agent\n",
543 				SSH_AGENTPID_ENV_NAME);
544 			exit(1);
545 		}
546 		pid = atoi(pidstr);
547 		if (pid < 1) {	/* XXX PID_MAX check too */
548 			fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
549 				SSH_AGENTPID_ENV_NAME, pidstr);
550 			exit(1);
551 		}
552 		if (kill(pid, SIGTERM) == -1) {
553 			perror("kill");
554 			exit(1);
555 		}
556 		format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
557 		printf(format, SSH_AUTHSOCKET_ENV_NAME);
558 		printf(format, SSH_AGENTPID_ENV_NAME);
559 		printf("echo Agent pid %d killed;\n", pid);
560 		exit(0);
561 	}
562 	parent_pid = getpid();
563 
564 	/* Create private directory for agent socket */
565 	strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
566 	if (mkdtemp(socket_dir) == NULL) {
567 		perror("mkdtemp: private socket dir");
568 		exit(1);
569 	}
570 	snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
571 		 parent_pid);
572 
573 	/*
574 	 * Create socket early so it will exist before command gets run from
575 	 * the parent.
576 	 */
577 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
578 	if (sock < 0) {
579 		perror("socket");
580 		cleanup_exit(1);
581 	}
582 	memset(&sunaddr, 0, sizeof(sunaddr));
583 	sunaddr.sun_family = AF_UNIX;
584 	strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
585 	if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
586 		perror("bind");
587 		cleanup_exit(1);
588 	}
589 	if (listen(sock, 5) < 0) {
590 		perror("listen");
591 		cleanup_exit(1);
592 	}
593 	/*
594 	 * Fork, and have the parent execute the command, if any, or present
595 	 * the socket data.  The child continues as the authentication agent.
596 	 */
597 	pid = fork();
598 	if (pid == -1) {
599 		perror("fork");
600 		exit(1);
601 	}
602 	if (pid != 0) {		/* Parent - execute the given command. */
603 		close(sock);
604 		snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
605 		if (ac == 0) {
606 			format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
607 			printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
608 			       SSH_AUTHSOCKET_ENV_NAME);
609 			printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
610 			       SSH_AGENTPID_ENV_NAME);
611 			printf("echo Agent pid %d;\n", pid);
612 			exit(0);
613 		}
614 		setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1);
615 		setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1);
616 		execvp(av[0], av);
617 		perror(av[0]);
618 		exit(1);
619 	}
620 	close(0);
621 	close(1);
622 	close(2);
623 
624 	if (setsid() == -1) {
625 		perror("setsid");
626 		cleanup_exit(1);
627 	}
628 	if (atexit(cleanup_socket) < 0) {
629 		perror("atexit");
630 		cleanup_exit(1);
631 	}
632 	new_socket(AUTH_SOCKET, sock);
633 	if (ac > 0) {
634 		signal(SIGALRM, check_parent_exists);
635 		alarm(10);
636 	}
637 	signal(SIGINT, SIG_IGN);
638 	signal(SIGPIPE, SIG_IGN);
639 	signal(SIGHUP, cleanup_exit);
640 	signal(SIGTERM, cleanup_exit);
641 	while (1) {
642 		FD_ZERO(&readset);
643 		FD_ZERO(&writeset);
644 		prepare_select(&readset, &writeset);
645 		if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0) {
646 			if (errno == EINTR)
647 				continue;
648 			exit(1);
649 		}
650 		after_select(&readset, &writeset);
651 	}
652 	/* NOTREACHED */
653 }
654