/*
 *
 * 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.22 2000/07/16 08:27:20 markus Exp $");

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

#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include "key.h"
#include "authfd.h"
#include "kex.h"

/* helper */
int ssh_agent_get_reply(AuthenticationConnection *auth);

/* 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.
	 */
	PUT_32BIT(msg, 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;
}

/* Encode key for a message to the agent. */

void
ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
{
	buffer_clear(b);
	buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
	buffer_put_int(b, BN_num_bits(key->n));
	buffer_put_bignum(b, key->n);
	buffer_put_bignum(b, key->e);
	buffer_put_bignum(b, key->d);
	/* To keep within the protocol: p < q for ssh. in SSL p > q */
	buffer_put_bignum(b, key->iqmp);	/* ssh key->u */
	buffer_put_bignum(b, key->q);	/* ssh key->p, SSL key->q */
	buffer_put_bignum(b, key->p);	/* ssh key->q, SSL key->p */
	buffer_put_string(b, comment, strlen(comment));
}

void
ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
{
	buffer_clear(b);
	buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
	buffer_put_cstring(b, KEX_DSS);
	buffer_put_bignum2(b, key->p);
	buffer_put_bignum2(b, key->q);
	buffer_put_bignum2(b, key->g);
	buffer_put_bignum2(b, key->pub_key);
	buffer_put_bignum2(b, key->priv_key);
	buffer_put_string(b, comment, strlen(comment));
}

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

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

	buffer_init(&buffer);

	switch (key->type) {
	case KEY_RSA:
		ssh_encode_identity_rsa(&buffer, key->rsa, comment);
		break;
	case KEY_DSA:
		ssh_encode_identity_dsa(&buffer, key->dsa, comment);
		break;
	default:
		buffer_free(&buffer);
		return 0;
		break;
	}

	/* 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.");
		buffer_free(&buffer);
		return 0;
	}
	buffer_free(&buffer);
	return ssh_agent_get_reply(auth);
}

/*
 * 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[5];
	int len;

	/* 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.");
		buffer_free(&buffer);
		return 0;
	}
	buffer_free(&buffer);
	return ssh_agent_get_reply(auth);
}

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

int
ssh_remove_all_identities(AuthenticationConnection *auth)
{
	unsigned char buf[5];

	/* 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;
	}
	return ssh_agent_get_reply(auth);
}

/*
 * Read for reply from agent. returns 1 for success, 0 on error
 */

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

	/*
	 * 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.");
			buffer_free(&buffer);
			return 0;
		}
		len -= l;
	}

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

	/* Read the rest of the response in to 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);
	buffer_free(&buffer);
	switch (type) {
	case SSH_AGENT_FAILURE:
log("SSH_AGENT_FAILURE");
		return 0;
	case SSH_AGENT_SUCCESS:
		return 1;
	default:
		fatal("Bad response from authentication agent: %d", type);
	}
	/* NOTREACHED */
	return 0;
}
