/*
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 *                    All rights reserved
 * Created: Thu Apr  6 00:52:24 1995 ylo
 * Adds an identity to the authentication server, or removes an identity.
 */

#include "includes.h"
RCSID("$OpenBSD: ssh-add.c,v 1.17 2000/06/20 01:39:44 markus Exp $");

#include <openssl/rsa.h>
#include <openssl/dsa.h>

#include "rsa.h"
#include "ssh.h"
#include "xmalloc.h"
#include "authfd.h"
#include "fingerprint.h"
#include "key.h"
#include "authfile.h"

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

void
delete_file(AuthenticationConnection *ac, const char *filename)
{
	Key *public;
	char *comment;

	public = key_new(KEY_RSA);
	if (!load_public_key(filename, public, &comment)) {
		printf("Bad key file %s: %s\n", filename, strerror(errno));
		return;
	}
	if (ssh_remove_identity(ac, public->rsa))
		fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
	else
		fprintf(stderr, "Could not remove identity: %s\n", filename);
	key_free(public);
	xfree(comment);
}

void
delete_all(AuthenticationConnection *ac)
{
	/* Send a request to remove all identities. */
	if (ssh_remove_all_identities(ac))
		fprintf(stderr, "All identities removed.\n");
	else
		fprintf(stderr, "Failed to remove all identitities.\n");
}

char *
ssh_askpass(char *askpass, char *msg)
{
	pid_t pid;
	size_t len;
	char *nl, *pass;
	int p[2], status;
	char buf[1024];

	if (askpass == NULL)
		fatal("internal error: askpass undefined");
	if (pipe(p) < 0)
		fatal("ssh_askpass: pipe: %s", strerror(errno));
	if ((pid = fork()) < 0)
		fatal("ssh_askpass: fork: %s", strerror(errno));
	if (pid == 0) {
		close(p[0]);
		if (dup2(p[1], STDOUT_FILENO) < 0)
			fatal("ssh_askpass: dup2: %s", strerror(errno));
		execlp(askpass, askpass, msg, (char *) 0);
		fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
	}
	close(p[1]);
	len = read(p[0], buf, sizeof buf);
	close(p[0]);
	while (waitpid(pid, &status, 0) < 0)
		if (errno != EINTR)
			break;
	if (len <= 1)
		return xstrdup("");
	nl = strchr(buf, '\n');
	if (nl)
		*nl = '\0';
	pass = xstrdup(buf);
	memset(buf, 0, sizeof(buf));
	return pass;
}

void
add_file(AuthenticationConnection *ac, const char *filename)
{
	Key *public;
	Key *private;
	char *saved_comment, *comment, *askpass = NULL;
	char buf[1024], msg[1024];
	int success;
	int interactive = isatty(STDIN_FILENO);

	public = key_new(KEY_RSA);
	if (!load_public_key(filename, public, &saved_comment)) {
		printf("Bad key file %s: %s\n", filename, strerror(errno));
		return;
	}
	key_free(public);

	if (!interactive && getenv("DISPLAY")) {
		if (getenv(SSH_ASKPASS_ENV))
			askpass = getenv(SSH_ASKPASS_ENV);
		else
			askpass = SSH_ASKPASS_DEFAULT;
	}

	/* At first, try empty passphrase */
	private = key_new(KEY_RSA);
	success = load_private_key(filename, "", private, &comment);
	if (!success) {
		printf("Need passphrase for %.200s\n", filename);
		if (!interactive && askpass == NULL) {
			xfree(saved_comment);
			return;
		}
		snprintf(msg, sizeof msg, "Enter passphrase for %.200s", saved_comment);
		for (;;) {
			char *pass;
			if (interactive) {
				snprintf(buf, sizeof buf, "%s: ", msg);
				pass = read_passphrase(buf, 1);
			} else {
				pass = ssh_askpass(askpass, msg);
			}
			if (strcmp(pass, "") == 0) {
				xfree(pass);
				xfree(saved_comment);
				return;
			}
			success = load_private_key(filename, pass, private, &comment);
			memset(pass, 0, strlen(pass));
			xfree(pass);
			if (success)
				break;
			strlcpy(msg, "Bad passphrase, try again", sizeof msg);
		}
	}
	xfree(saved_comment);

	if (ssh_add_identity(ac, private->rsa, comment))
		fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
	else
		fprintf(stderr, "Could not add identity: %s\n", filename);
	key_free(private);
	xfree(comment);
}

void
list_identities(AuthenticationConnection *ac, int fp)
{
	BIGNUM *e, *n;
	int status;
	char *comment;
	int had_identities;

	e = BN_new();
	n = BN_new();
	had_identities = 0;
	for (status = ssh_get_first_identity(ac, e, n, &comment);
	     status;
	     status = ssh_get_next_identity(ac, e, n, &comment)) {
		unsigned int bits = BN_num_bits(n);
		had_identities = 1;
		if (fp) {
			printf("%d %s %s\n", bits, fingerprint(e, n), comment);
		} else {
			char *ebuf, *nbuf;
			ebuf = BN_bn2dec(e);
			if (ebuf == NULL) {
				error("list_identities: BN_bn2dec(e) failed.");
			} else {
				nbuf = BN_bn2dec(n);
				if (nbuf == NULL) {
					error("list_identities: BN_bn2dec(n) failed.");
				} else {
					printf("%d %s %s %s\n", bits, ebuf, nbuf, comment);
					free(nbuf);
				}
				free(ebuf);
			}
		}
		xfree(comment);
	}
	BN_clear_free(e);
	BN_clear_free(n);
	if (!had_identities)
		printf("The agent has no identities.\n");
}

int
main(int argc, char **argv)
{
	AuthenticationConnection *ac = NULL;
	struct passwd *pw;
	char buf[1024];
	int no_files = 1;
	int i;
	int deleting = 0;

	/* 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);
	}
	/* At first, get a connection to the authentication agent. */
	ac = ssh_get_authentication_connection();
	if (ac == NULL) {
		fprintf(stderr, "Could not open a connection to your authentication agent.\n");
		exit(1);
	}
	for (i = 1; i < argc; i++) {
		if ((strcmp(argv[i], "-l") == 0) ||
		    (strcmp(argv[i], "-L") == 0)) {
			list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
			/* Don't default-add/delete if -l. */
			no_files = 0;
			continue;
		}
		if (strcmp(argv[i], "-d") == 0) {
			deleting = 1;
			continue;
		}
		if (strcmp(argv[i], "-D") == 0) {
			delete_all(ac);
			no_files = 0;
			continue;
		}
		no_files = 0;
		if (deleting)
			delete_file(ac, argv[i]);
		else
			add_file(ac, argv[i]);
	}
	if (no_files) {
		pw = getpwuid(getuid());
		if (!pw) {
			fprintf(stderr, "No user found with uid %d\n", (int) getuid());
			ssh_close_authentication_connection(ac);
			exit(1);
		}
		snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
		if (deleting)
			delete_file(ac, buf);
		else
			add_file(ac, buf);
	}
	ssh_close_authentication_connection(ac);
	exit(0);
}
