/*	$OpenBSD: ssh-agent.c,v 1.28 2000/04/14 10:30:33 markus Exp $	*/

/*
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 *                    All rights reserved
 * Created: Wed Mar 29 03:46:59 1995 ylo
 * The authentication agent program.
 */

#include "includes.h"
RCSID("$OpenBSD: ssh-agent.c,v 1.28 2000/04/14 10:30:33 markus Exp $");

#include "ssh.h"
#include "rsa.h"
#include "authfd.h"
#include "buffer.h"
#include "bufaux.h"
#include "xmalloc.h"
#include "packet.h"
#include "getput.h"
#include "mpaux.h"

#include <openssl/md5.h>

typedef struct {
	int fd;
	enum {
		AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION
	} type;
	Buffer input;
	Buffer output;
} SocketEntry;

unsigned int sockets_alloc = 0;
SocketEntry *sockets = NULL;

typedef struct {
	RSA *key;
	char *comment;
} Identity;

unsigned int num_identities = 0;
Identity *identities = NULL;

int max_fd = 0;

/* pid of shell == parent of agent */
int parent_pid = -1;

/* pathname and directory for AUTH_SOCKET */
char socket_name[1024];
char socket_dir[1024];

#ifdef HAVE___PROGNAME
extern char *__progname;
#else /* HAVE___PROGNAME */
const char *__progname = "ssh-agent";
#endif /* HAVE___PROGNAME */

void
process_request_identity(SocketEntry *e)
{
	Buffer msg;
	int i;

	buffer_init(&msg);
	buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER);
	buffer_put_int(&msg, num_identities);
	for (i = 0; i < num_identities; i++) {
		buffer_put_int(&msg, BN_num_bits(identities[i].key->n));
		buffer_put_bignum(&msg, identities[i].key->e);
		buffer_put_bignum(&msg, identities[i].key->n);
		buffer_put_string(&msg, identities[i].comment,
				  strlen(identities[i].comment));
	}
	buffer_put_int(&e->output, buffer_len(&msg));
	buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
	buffer_free(&msg);
}

void
process_authentication_challenge(SocketEntry *e)
{
	int i, pub_bits, len;
	BIGNUM *pub_e, *pub_n, *challenge;
	Buffer msg;
	MD5_CTX md;
	unsigned char buf[32], mdbuf[16], session_id[16];
	unsigned int response_type;

	buffer_init(&msg);
	pub_e = BN_new();
	pub_n = BN_new();
	challenge = BN_new();
	pub_bits = buffer_get_int(&e->input);
	buffer_get_bignum(&e->input, pub_e);
	buffer_get_bignum(&e->input, pub_n);
	buffer_get_bignum(&e->input, challenge);
	if (buffer_len(&e->input) == 0) {
		/* Compatibility code for old servers. */
		memset(session_id, 0, 16);
		response_type = 0;
	} else {
		/* New code. */
		buffer_get(&e->input, (char *) session_id, 16);
		response_type = buffer_get_int(&e->input);
	}
	for (i = 0; i < num_identities; i++)
		if (pub_bits == BN_num_bits(identities[i].key->n) &&
		    BN_cmp(pub_e, identities[i].key->e) == 0 &&
		    BN_cmp(pub_n, identities[i].key->n) == 0) {
			/* Decrypt the challenge using the private key. */
			rsa_private_decrypt(challenge, challenge, identities[i].key);

			/* Compute the desired response. */
			switch (response_type) {
			case 0:/* As of protocol 1.0 */
				/* This response type is no longer supported. */
				log("Compatibility with ssh protocol 1.0 no longer supported.");
				buffer_put_char(&msg, SSH_AGENT_FAILURE);
				goto send;

			case 1:/* As of protocol 1.1 */
				/* The response is MD5 of decrypted challenge plus session id. */
				len = BN_num_bytes(challenge);

				if (len <= 0 || len > 32) {
					fatal("process_authentication_challenge: "
					 "bad challenge length %d", len);
				}
				memset(buf, 0, 32);
				BN_bn2bin(challenge, buf + 32 - len);
				MD5_Init(&md);
				MD5_Update(&md, buf, 32);
				MD5_Update(&md, session_id, 16);
				MD5_Final(mdbuf, &md);
				break;

			default:
				fatal("process_authentication_challenge: bad response_type %d",
				      response_type);
				break;
			}

			/* Send the response. */
			buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
			for (i = 0; i < 16; i++)
				buffer_put_char(&msg, mdbuf[i]);

			goto send;
		}
	/* Unknown identity.  Send failure. */
	buffer_put_char(&msg, SSH_AGENT_FAILURE);
send:
	buffer_put_int(&e->output, buffer_len(&msg));
	buffer_append(&e->output, buffer_ptr(&msg),
		      buffer_len(&msg));
	buffer_free(&msg);
	BN_clear_free(pub_e);
	BN_clear_free(pub_n);
	BN_clear_free(challenge);
}

void
process_remove_identity(SocketEntry *e)
{
	unsigned int bits;
	unsigned int i;
	BIGNUM *dummy, *n;

	dummy = BN_new();
	n = BN_new();

	/* Get the key from the packet. */
	bits = buffer_get_int(&e->input);
	buffer_get_bignum(&e->input, dummy);
	buffer_get_bignum(&e->input, n);

	if (bits != BN_num_bits(n))
		error("Warning: identity keysize mismatch: actual %d, announced %d",
		      BN_num_bits(n), bits);

	/* Check if we have the key. */
	for (i = 0; i < num_identities; i++)
		if (BN_cmp(identities[i].key->n, n) == 0) {
			/*
			 * We have this key.  Free the old key.  Since we
			 * don\'t want to leave empty slots in the middle of
			 * the array, we actually free the key there and copy
			 * data from the last entry.
			 */
			RSA_free(identities[i].key);
			xfree(identities[i].comment);
			if (i < num_identities - 1)
				identities[i] = identities[num_identities - 1];
			num_identities--;
			BN_clear_free(dummy);
			BN_clear_free(n);

			/* Send success. */
			buffer_put_int(&e->output, 1);
			buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
			return;
		}
	/* We did not have the key. */
	BN_clear(dummy);
	BN_clear(n);

	/* Send failure. */
	buffer_put_int(&e->output, 1);
	buffer_put_char(&e->output, SSH_AGENT_FAILURE);
}

/*
 * Removes all identities from the agent.
 */
void
process_remove_all_identities(SocketEntry *e)
{
	unsigned int i;

	/* Loop over all identities and clear the keys. */
	for (i = 0; i < num_identities; i++) {
		RSA_free(identities[i].key);
		xfree(identities[i].comment);
	}

	/* Mark that there are no identities. */
	num_identities = 0;

	/* Send success. */
	buffer_put_int(&e->output, 1);
	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
	return;
}

/*
 * Adds an identity to the agent.
 */
void
process_add_identity(SocketEntry *e)
{
	RSA *k;
	int i;
	BIGNUM *aux;
	BN_CTX *ctx;

	if (num_identities == 0)
		identities = xmalloc(sizeof(Identity));
	else
		identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity));

	identities[num_identities].key = RSA_new();
	k = identities[num_identities].key;
	buffer_get_int(&e->input);	/* bits */
	k->n = BN_new();
	buffer_get_bignum(&e->input, k->n);
	k->e = BN_new();
	buffer_get_bignum(&e->input, k->e);
	k->d = BN_new();
	buffer_get_bignum(&e->input, k->d);
	k->iqmp = BN_new();
	buffer_get_bignum(&e->input, k->iqmp);
	/* SSH and SSL have p and q swapped */
	k->q = BN_new();
	buffer_get_bignum(&e->input, k->q);	/* p */
	k->p = BN_new();
	buffer_get_bignum(&e->input, k->p);	/* q */

	/* Generate additional parameters */
	aux = BN_new();
	ctx = BN_CTX_new();

	BN_sub(aux, k->q, BN_value_one());
	k->dmq1 = BN_new();
	BN_mod(k->dmq1, k->d, aux, ctx);

	BN_sub(aux, k->p, BN_value_one());
	k->dmp1 = BN_new();
	BN_mod(k->dmp1, k->d, aux, ctx);

	BN_clear_free(aux);
	BN_CTX_free(ctx);

	identities[num_identities].comment = buffer_get_string(&e->input, NULL);

	/* Check if we already have the key. */
	for (i = 0; i < num_identities; i++)
		if (BN_cmp(identities[i].key->n, k->n) == 0) {
			/*
			 * We already have this key.  Clear and free the new
			 * data and return success.
			 */
			RSA_free(k);
			xfree(identities[num_identities].comment);

			/* Send success. */
			buffer_put_int(&e->output, 1);
			buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
			return;
		}
	/* Increment the number of identities. */
	num_identities++;

	/* Send a success message. */
	buffer_put_int(&e->output, 1);
	buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
}

void
process_message(SocketEntry *e)
{
	unsigned int msg_len;
	unsigned int type;
	unsigned char *cp;
	if (buffer_len(&e->input) < 5)
		return;		/* Incomplete message. */
	cp = (unsigned char *) buffer_ptr(&e->input);
	msg_len = GET_32BIT(cp);
	if (msg_len > 256 * 1024) {
		shutdown(e->fd, SHUT_RDWR);
		close(e->fd);
		e->type = AUTH_UNUSED;
		return;
	}
	if (buffer_len(&e->input) < msg_len + 4)
		return;
	buffer_consume(&e->input, 4);
	type = buffer_get_char(&e->input);

	switch (type) {
	case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
		process_request_identity(e);
		break;
	case SSH_AGENTC_RSA_CHALLENGE:
		process_authentication_challenge(e);
		break;
	case SSH_AGENTC_ADD_RSA_IDENTITY:
		process_add_identity(e);
		break;
	case SSH_AGENTC_REMOVE_RSA_IDENTITY:
		process_remove_identity(e);
		break;
	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
		process_remove_all_identities(e);
		break;
	default:
		/* Unknown message.  Respond with failure. */
		error("Unknown message %d", type);
		buffer_clear(&e->input);
		buffer_put_int(&e->output, 1);
		buffer_put_char(&e->output, SSH_AGENT_FAILURE);
		break;
	}
}

void
new_socket(int type, int fd)
{
	unsigned int i, old_alloc;
	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
		error("fcntl O_NONBLOCK: %s", strerror(errno));

	if (fd > max_fd)
		max_fd = fd;

	for (i = 0; i < sockets_alloc; i++)
		if (sockets[i].type == AUTH_UNUSED) {
			sockets[i].fd = fd;
			sockets[i].type = type;
			buffer_init(&sockets[i].input);
			buffer_init(&sockets[i].output);
			return;
		}
	old_alloc = sockets_alloc;
	sockets_alloc += 10;
	if (sockets)
		sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
	else
		sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
	for (i = old_alloc; i < sockets_alloc; i++)
		sockets[i].type = AUTH_UNUSED;
	sockets[old_alloc].type = type;
	sockets[old_alloc].fd = fd;
	buffer_init(&sockets[old_alloc].input);
	buffer_init(&sockets[old_alloc].output);
}

void
prepare_select(fd_set *readset, fd_set *writeset)
{
	unsigned int i;
	for (i = 0; i < sockets_alloc; i++)
		switch (sockets[i].type) {
		case AUTH_SOCKET:
		case AUTH_CONNECTION:
			FD_SET(sockets[i].fd, readset);
			if (buffer_len(&sockets[i].output) > 0)
				FD_SET(sockets[i].fd, writeset);
			break;
		case AUTH_UNUSED:
			break;
		default:
			fatal("Unknown socket type %d", sockets[i].type);
			break;
		}
}

void
after_select(fd_set *readset, fd_set *writeset)
{
	unsigned int i;
	int len, sock;
	socklen_t slen;
	char buf[1024];
	struct sockaddr_un sunaddr;

	for (i = 0; i < sockets_alloc; i++)
		switch (sockets[i].type) {
		case AUTH_UNUSED:
			break;
		case AUTH_SOCKET:
			if (FD_ISSET(sockets[i].fd, readset)) {
				slen = sizeof(sunaddr);
				sock = accept(sockets[i].fd, (struct sockaddr *) & sunaddr, &slen);
				if (sock < 0) {
					perror("accept from AUTH_SOCKET");
					break;
				}
				new_socket(AUTH_CONNECTION, sock);
			}
			break;
		case AUTH_CONNECTION:
			if (buffer_len(&sockets[i].output) > 0 &&
			    FD_ISSET(sockets[i].fd, writeset)) {
				len = write(sockets[i].fd, buffer_ptr(&sockets[i].output),
					 buffer_len(&sockets[i].output));
				if (len <= 0) {
					shutdown(sockets[i].fd, SHUT_RDWR);
					close(sockets[i].fd);
					sockets[i].type = AUTH_UNUSED;
					break;
				}
				buffer_consume(&sockets[i].output, len);
			}
			if (FD_ISSET(sockets[i].fd, readset)) {
				len = read(sockets[i].fd, buf, sizeof(buf));
				if (len <= 0) {
					shutdown(sockets[i].fd, SHUT_RDWR);
					close(sockets[i].fd);
					sockets[i].type = AUTH_UNUSED;
					break;
				}
				buffer_append(&sockets[i].input, buf, len);
				process_message(&sockets[i]);
			}
			break;
		default:
			fatal("Unknown type %d", sockets[i].type);
		}
}

void
check_parent_exists(int sig)
{
	if (kill(parent_pid, 0) < 0) {
		/* printf("Parent has died - Authentication agent exiting.\n"); */
		exit(1);
	}
	signal(SIGALRM, check_parent_exists);
	alarm(10);
}

void
cleanup_socket(void)
{
	remove(socket_name);
	rmdir(socket_dir);
}

void
cleanup_exit(int i)
{
	cleanup_socket();
	exit(i);
}

void
usage()
{
	fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION);
	fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n",
		__progname);
	exit(1);
}

int
main(int ac, char **av)
{
	fd_set readset, writeset;
	int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch;
	struct sockaddr_un sunaddr;
	pid_t pid;
	char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];

	/* check if RSA support exists */
	if (rsa_alive() == 0) {
		fprintf(stderr,
			"%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
			__progname);
		exit(1);
	}
	while ((ch = getopt(ac, av, "cks")) != -1) {
		switch (ch) {
		case 'c':
			if (s_flag)
				usage();
			c_flag++;
			break;
		case 'k':
			k_flag++;
			break;
		case 's':
			if (c_flag)
				usage();
			s_flag++;
			break;
		default:
			usage();
		}
	}
	ac -= optind;
	av += optind;

	if (ac > 0 && (c_flag || k_flag || s_flag))
		usage();

	if (ac == 0 && !c_flag && !k_flag && !s_flag) {
		shell = getenv("SHELL");
		if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
			c_flag = 1;
	}
	if (k_flag) {
		pidstr = getenv(SSH_AGENTPID_ENV_NAME);
		if (pidstr == NULL) {
			fprintf(stderr, "%s not set, cannot kill agent\n",
				SSH_AGENTPID_ENV_NAME);
			exit(1);
		}
		pid = atoi(pidstr);
		if (pid < 1) {	/* XXX PID_MAX check too */
			fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
				SSH_AGENTPID_ENV_NAME, pidstr);
			exit(1);
		}
		if (kill(pid, SIGTERM) == -1) {
			perror("kill");
			exit(1);
		}
		format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
		printf(format, SSH_AUTHSOCKET_ENV_NAME);
		printf(format, SSH_AGENTPID_ENV_NAME);
		printf("echo Agent pid %d killed;\n", pid);
		exit(0);
	}
	parent_pid = getpid();

	/* Create private directory for agent socket */
	strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
	if (mkdtemp(socket_dir) == NULL) {
		perror("mkdtemp: private socket dir");
		exit(1);
	}
	snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
		 parent_pid);

	/*
	 * Create socket early so it will exist before command gets run from
	 * the parent.
	 */
	sock = socket(AF_UNIX, SOCK_STREAM, 0);
	if (sock < 0) {
		perror("socket");
		cleanup_exit(1);
	}
	memset(&sunaddr, 0, sizeof(sunaddr));
	sunaddr.sun_family = AF_UNIX;
	strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
	if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
		perror("bind");
		cleanup_exit(1);
	}
	if (listen(sock, 5) < 0) {
		perror("listen");
		cleanup_exit(1);
	}
	/*
	 * Fork, and have the parent execute the command, if any, or present
	 * the socket data.  The child continues as the authentication agent.
	 */
	pid = fork();
	if (pid == -1) {
		perror("fork");
		exit(1);
	}
	if (pid != 0) {		/* Parent - execute the given command. */
		close(sock);
		snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
		if (ac == 0) {
			format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
			printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
			       SSH_AUTHSOCKET_ENV_NAME);
			printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
			       SSH_AGENTPID_ENV_NAME);
			printf("echo Agent pid %d;\n", pid);
			exit(0);
		}
		setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1);
		setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1);
		execvp(av[0], av);
		perror(av[0]);
		exit(1);
	}
	close(0);
	close(1);
	close(2);

	if (setsid() == -1) {
		perror("setsid");
		cleanup_exit(1);
	}
	if (atexit(cleanup_socket) < 0) {
		perror("atexit");
		cleanup_exit(1);
	}
	new_socket(AUTH_SOCKET, sock);
	if (ac > 0) {
		signal(SIGALRM, check_parent_exists);
		alarm(10);
	}
	signal(SIGINT, SIG_IGN);
	signal(SIGPIPE, SIG_IGN);
	signal(SIGHUP, cleanup_exit);
	signal(SIGTERM, cleanup_exit);
	while (1) {
		FD_ZERO(&readset);
		FD_ZERO(&writeset);
		prepare_select(&readset, &writeset);
		if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0) {
			if (errno == EINTR)
				continue;
			exit(1);
		}
		after_select(&readset, &writeset);
	}
	/* NOTREACHED */
}
