/*
 *
 * authfd.c
 *
 * 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 01:30:28 1995 ylo
 *
 * Functions for connecting the local authentication agent.
 *
 */

#include "includes.h"
RCSID("$OpenBSD: authfd.c,v 1.20 2000/06/20 01:39:38 markus Exp $");

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

#include <openssl/rsa.h>

/* Returns the number of the authentication fd, or -1 if there is none. */

int
ssh_get_authentication_socket()
{
	const char *authsocket;
	int sock;
	struct sockaddr_un sunaddr;

	authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
	if (!authsocket)
		return -1;

	sunaddr.sun_family = AF_UNIX;
	strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));

	sock = socket(AF_UNIX, SOCK_STREAM, 0);
	if (sock < 0)
		return -1;

	/* close on exec */
	if (fcntl(sock, F_SETFD, 1) == -1) {
		close(sock);
		return -1;
	}
	if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
		close(sock);
		return -1;
	}
	return sock;
}

/*
 * Closes the agent socket if it should be closed (depends on how it was
 * obtained).  The argument must have been returned by
 * ssh_get_authentication_socket().
 */

void
ssh_close_authentication_socket(int sock)
{
	if (getenv(SSH_AUTHSOCKET_ENV_NAME))
		close(sock);
}

/*
 * Opens and connects a private socket for communication with the
 * authentication agent.  Returns the file descriptor (which must be
 * shut down and closed by the caller when no longer needed).
 * Returns NULL if an error occurred and the connection could not be
 * opened.
 */

AuthenticationConnection *
ssh_get_authentication_connection()
{
	AuthenticationConnection *auth;
	int sock;

	sock = ssh_get_authentication_socket();

	/*
	 * Fail if we couldn't obtain a connection.  This happens if we
	 * exited due to a timeout.
	 */
	if (sock < 0)
		return NULL;

	auth = xmalloc(sizeof(*auth));
	auth->fd = sock;
	buffer_init(&auth->packet);
	buffer_init(&auth->identities);
	auth->howmany = 0;

	return auth;
}

/*
 * Closes the connection to the authentication agent and frees any associated
 * memory.
 */

void
ssh_close_authentication_connection(AuthenticationConnection *ac)
{
	buffer_free(&ac->packet);
	buffer_free(&ac->identities);
	close(ac->fd);
	xfree(ac);
}

/*
 * Returns the first authentication identity held by the agent.
 * Returns true if an identity is available, 0 otherwise.
 * The caller must initialize the integers before the call, and free the
 * comment after a successful call (before calling ssh_get_next_identity).
 */

int
ssh_get_first_identity(AuthenticationConnection *auth,
		       BIGNUM *e, BIGNUM *n, char **comment)
{
	unsigned char msg[8192];
	int len, l;

	/*
	 * Send a message to the agent requesting for a list of the
	 * identities it can represent.
	 */
	msg[0] = 0;
	msg[1] = 0;
	msg[2] = 0;
	msg[3] = 1;
	msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
	if (atomicio(write, auth->fd, msg, 5) != 5) {
		error("write auth->fd: %.100s", strerror(errno));
		return 0;
	}
	/* Read the length of the response.  XXX implement timeouts here. */
	len = 4;
	while (len > 0) {
		l = read(auth->fd, msg + 4 - len, len);
		if (l <= 0) {
			error("read auth->fd: %.100s", strerror(errno));
			return 0;
		}
		len -= l;
	}

	/*
	 * Extract the length, and check it for sanity.  (We cannot trust
	 * authentication agents).
	 */
	len = GET_32BIT(msg);
	if (len < 1 || len > 256 * 1024)
		fatal("Authentication reply message too long: %d\n", len);

	/* Read the packet itself. */
	buffer_clear(&auth->identities);
	while (len > 0) {
		l = len;
		if (l > sizeof(msg))
			l = sizeof(msg);
		l = read(auth->fd, msg, l);
		if (l <= 0)
			fatal("Incomplete authentication reply.");
		buffer_append(&auth->identities, (char *) msg, l);
		len -= l;
	}

	/* Get message type, and verify that we got a proper answer. */
	buffer_get(&auth->identities, (char *) msg, 1);
	if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
		fatal("Bad authentication reply message type: %d", msg[0]);

	/* Get the number of entries in the response and check it for sanity. */
	auth->howmany = buffer_get_int(&auth->identities);
	if (auth->howmany > 1024)
		fatal("Too many identities in authentication reply: %d\n", auth->howmany);

	/* Return the first entry (if any). */
	return ssh_get_next_identity(auth, e, n, comment);
}

/*
 * Returns the next authentication identity for the agent.  Other functions
 * can be called between this and ssh_get_first_identity or two calls of this
 * function.  This returns 0 if there are no more identities.  The caller
 * must free comment after a successful return.
 */

int
ssh_get_next_identity(AuthenticationConnection *auth,
		      BIGNUM *e, BIGNUM *n, char **comment)
{
	unsigned int bits;

	/* Return failure if no more entries. */
	if (auth->howmany <= 0)
		return 0;

	/*
	 * Get the next entry from the packet.  These will abort with a fatal
	 * error if the packet is too short or contains corrupt data.
	 */
	bits = buffer_get_int(&auth->identities);
	buffer_get_bignum(&auth->identities, e);
	buffer_get_bignum(&auth->identities, n);
	*comment = buffer_get_string(&auth->identities, NULL);

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

	/* Decrement the number of remaining entries. */
	auth->howmany--;

	return 1;
}

/*
 * Generates a random challenge, sends it to the agent, and waits for
 * response from the agent.  Returns true (non-zero) if the agent gave the
 * correct answer, zero otherwise.  Response type selects the style of
 * response desired, with 0 corresponding to protocol version 1.0 (no longer
 * supported) and 1 corresponding to protocol version 1.1.
 */

int
ssh_decrypt_challenge(AuthenticationConnection *auth,
		      BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
		      unsigned char session_id[16],
		      unsigned int response_type,
		      unsigned char response[16])
{
	Buffer buffer;
	unsigned char buf[8192];
	int len, l, i;

	/* Response type 0 is no longer supported. */
	if (response_type == 0)
		fatal("Compatibility with ssh protocol version 1.0 no longer supported.");

	/* Format a message to the agent. */
	buf[0] = SSH_AGENTC_RSA_CHALLENGE;
	buffer_init(&buffer);
	buffer_append(&buffer, (char *) buf, 1);
	buffer_put_int(&buffer, BN_num_bits(n));
	buffer_put_bignum(&buffer, e);
	buffer_put_bignum(&buffer, n);
	buffer_put_bignum(&buffer, challenge);
	buffer_append(&buffer, (char *) session_id, 16);
	buffer_put_int(&buffer, response_type);

	/* Get the length of the message, and format it in the buffer. */
	len = buffer_len(&buffer);
	PUT_32BIT(buf, len);

	/* Send the length and then the packet to the agent. */
	if (atomicio(write, auth->fd, buf, 4) != 4 ||
	    atomicio(write, auth->fd, buffer_ptr(&buffer),
	    buffer_len(&buffer)) != buffer_len(&buffer)) {
		error("Error writing to authentication socket.");
error_cleanup:
		buffer_free(&buffer);
		return 0;
	}
	/*
	 * Wait for response from the agent.  First read the length of the
	 * response packet.
	 */
	len = 4;
	while (len > 0) {
		l = read(auth->fd, buf + 4 - len, len);
		if (l <= 0) {
			error("Error reading response length from authentication socket.");
			goto error_cleanup;
		}
		len -= l;
	}

	/* Extract the length, and check it for sanity. */
	len = GET_32BIT(buf);
	if (len > 256 * 1024)
		fatal("Authentication response too long: %d", len);

	/* Read the rest of the response in tothe buffer. */
	buffer_clear(&buffer);
	while (len > 0) {
		l = len;
		if (l > sizeof(buf))
			l = sizeof(buf);
		l = read(auth->fd, buf, l);
		if (l <= 0) {
			error("Error reading response from authentication socket.");
			goto error_cleanup;
		}
		buffer_append(&buffer, (char *) buf, l);
		len -= l;
	}

	/* Get the type of the packet. */
	buffer_get(&buffer, (char *) buf, 1);

	/* Check for agent failure message. */
	if (buf[0] == SSH_AGENT_FAILURE) {
		log("Agent admitted failure to authenticate using the key.");
		goto error_cleanup;
	}
	/* Now it must be an authentication response packet. */
	if (buf[0] != SSH_AGENT_RSA_RESPONSE)
		fatal("Bad authentication response: %d", buf[0]);

	/*
	 * Get the response from the packet.  This will abort with a fatal
	 * error if the packet is corrupt.
	 */
	for (i = 0; i < 16; i++)
		response[i] = buffer_get_char(&buffer);

	/* The buffer containing the packet is no longer needed. */
	buffer_free(&buffer);

	/* Correct answer. */
	return 1;
}

/*
 * Adds an identity to the authentication server.  This call is not meant to
 * be used by normal applications.
 */

int
ssh_add_identity(AuthenticationConnection *auth,
		 RSA * key, const char *comment)
{
	Buffer buffer;
	unsigned char buf[8192];
	int len, l, type;

	/* Format a message to the agent. */
	buffer_init(&buffer);
	buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
	buffer_put_int(&buffer, BN_num_bits(key->n));
	buffer_put_bignum(&buffer, key->n);
	buffer_put_bignum(&buffer, key->e);
	buffer_put_bignum(&buffer, key->d);
	/* To keep within the protocol: p < q for ssh. in SSL p > q */
	buffer_put_bignum(&buffer, key->iqmp);	/* ssh key->u */
	buffer_put_bignum(&buffer, key->q);	/* ssh key->p, SSL key->q */
	buffer_put_bignum(&buffer, key->p);	/* ssh key->q, SSL key->p */
	buffer_put_string(&buffer, comment, strlen(comment));

	/* Get the length of the message, and format it in the buffer. */
	len = buffer_len(&buffer);
	PUT_32BIT(buf, len);

	/* Send the length and then the packet to the agent. */
	if (atomicio(write, auth->fd, buf, 4) != 4 ||
	    atomicio(write, auth->fd, buffer_ptr(&buffer),
	    buffer_len(&buffer)) != buffer_len(&buffer)) {
		error("Error writing to authentication socket.");
error_cleanup:
		buffer_free(&buffer);
		return 0;
	}
	/* Wait for response from the agent.  First read the length of the
	   response packet. */
	len = 4;
	while (len > 0) {
		l = read(auth->fd, buf + 4 - len, len);
		if (l <= 0) {
			error("Error reading response length from authentication socket.");
			goto error_cleanup;
		}
		len -= l;
	}

	/* Extract the length, and check it for sanity. */
	len = GET_32BIT(buf);
	if (len > 256 * 1024)
		fatal("Add identity response too long: %d", len);

	/* Read the rest of the response in tothe buffer. */
	buffer_clear(&buffer);
	while (len > 0) {
		l = len;
		if (l > sizeof(buf))
			l = sizeof(buf);
		l = read(auth->fd, buf, l);
		if (l <= 0) {
			error("Error reading response from authentication socket.");
			goto error_cleanup;
		}
		buffer_append(&buffer, (char *) buf, l);
		len -= l;
	}

	/* Get the type of the packet. */
	type = buffer_get_char(&buffer);
	switch (type) {
	case SSH_AGENT_FAILURE:
		buffer_free(&buffer);
		return 0;
	case SSH_AGENT_SUCCESS:
		buffer_free(&buffer);
		return 1;
	default:
		fatal("Bad response to add identity from authentication agent: %d",
		      type);
	}
	/* NOTREACHED */
	return 0;
}

/*
 * Removes an identity from the authentication server.  This call is not
 * meant to be used by normal applications.
 */

int
ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
{
	Buffer buffer;
	unsigned char buf[8192];
	int len, l, type;

	/* Format a message to the agent. */
	buffer_init(&buffer);
	buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
	buffer_put_int(&buffer, BN_num_bits(key->n));
	buffer_put_bignum(&buffer, key->e);
	buffer_put_bignum(&buffer, key->n);

	/* Get the length of the message, and format it in the buffer. */
	len = buffer_len(&buffer);
	PUT_32BIT(buf, len);

	/* Send the length and then the packet to the agent. */
	if (atomicio(write, auth->fd, buf, 4) != 4 ||
	    atomicio(write, auth->fd, buffer_ptr(&buffer),
	    buffer_len(&buffer)) != buffer_len(&buffer)) {
		error("Error writing to authentication socket.");
error_cleanup:
		buffer_free(&buffer);
		return 0;
	}
	/*
	 * Wait for response from the agent.  First read the length of the
	 * response packet.
	 */
	len = 4;
	while (len > 0) {
		l = read(auth->fd, buf + 4 - len, len);
		if (l <= 0) {
			error("Error reading response length from authentication socket.");
			goto error_cleanup;
		}
		len -= l;
	}

	/* Extract the length, and check it for sanity. */
	len = GET_32BIT(buf);
	if (len > 256 * 1024)
		fatal("Remove identity response too long: %d", len);

	/* Read the rest of the response in tothe buffer. */
	buffer_clear(&buffer);
	while (len > 0) {
		l = len;
		if (l > sizeof(buf))
			l = sizeof(buf);
		l = read(auth->fd, buf, l);
		if (l <= 0) {
			error("Error reading response from authentication socket.");
			goto error_cleanup;
		}
		buffer_append(&buffer, (char *) buf, l);
		len -= l;
	}

	/* Get the type of the packet. */
	type = buffer_get_char(&buffer);
	switch (type) {
	case SSH_AGENT_FAILURE:
		buffer_free(&buffer);
		return 0;
	case SSH_AGENT_SUCCESS:
		buffer_free(&buffer);
		return 1;
	default:
		fatal("Bad response to remove identity from authentication agent: %d",
		      type);
	}
	/* NOTREACHED */
	return 0;
}

/*
 * Removes all identities from the agent.  This call is not meant to be used
 * by normal applications.
 */

int
ssh_remove_all_identities(AuthenticationConnection *auth)
{
	Buffer buffer;
	unsigned char buf[8192];
	int len, l, type;

	/* Get the length of the message, and format it in the buffer. */
	PUT_32BIT(buf, 1);
	buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;

	/* Send the length and then the packet to the agent. */
	if (atomicio(write, auth->fd, buf, 5) != 5) {
		error("Error writing to authentication socket.");
		return 0;
	}
	/*
	 * Wait for response from the agent.  First read the length of the
	 * response packet.
	 */
	len = 4;
	while (len > 0) {
		l = read(auth->fd, buf + 4 - len, len);
		if (l <= 0) {
			error("Error reading response length from authentication socket.");
			return 0;
		}
		len -= l;
	}

	/* Extract the length, and check it for sanity. */
	len = GET_32BIT(buf);
	if (len > 256 * 1024)
		fatal("Remove identity response too long: %d", len);

	/* Read the rest of the response into the buffer. */
	buffer_init(&buffer);
	while (len > 0) {
		l = len;
		if (l > sizeof(buf))
			l = sizeof(buf);
		l = read(auth->fd, buf, l);
		if (l <= 0) {
			error("Error reading response from authentication socket.");
			buffer_free(&buffer);
			return 0;
		}
		buffer_append(&buffer, (char *) buf, l);
		len -= l;
	}

	/* Get the type of the packet. */
	type = buffer_get_char(&buffer);
	switch (type) {
	case SSH_AGENT_FAILURE:
		buffer_free(&buffer);
		return 0;
	case SSH_AGENT_SUCCESS:
		buffer_free(&buffer);
		return 1;
	default:
		fatal("Bad response to remove identity from authentication agent: %d",
		      type);
	}
	/* NOTREACHED */
	return 0;
}
