/*
 * Dropbear - a SSH2 server
 * 
 * Copyright (c) 2005 Matt Johnston
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. */

#include "includes.h"

#ifdef ENABLE_CLI_AGENTFWD

#include "agentfwd.h"
#include "session.h"
#include "ssh.h"
#include "dbutil.h"
#include "chansession.h"
#include "channel.h"
#include "packet.h"
#include "buffer.h"
#include "dbrandom.h"
#include "listener.h"
#include "runopts.h"
#include "atomicio.h"
#include "signkey.h"
#include "auth.h"

/* The protocol implemented to talk to OpenSSH's SSH2 agent is documented in
   PROTOCOL.agent in recent OpenSSH source distributions (5.1p1 has it). */

static int new_agent_chan(struct Channel * channel);

const struct ChanType cli_chan_agent = {
	0, /* sepfds */
	"auth-agent@openssh.com",
	new_agent_chan,
	NULL,
	NULL,
	NULL
};

static int connect_agent() {

	int fd = -1;
	char* agent_sock = NULL;

	agent_sock = getenv("SSH_AUTH_SOCK");
	if (agent_sock == NULL)
		return -1;

	fd = connect_unix(agent_sock);

	if (fd < 0) {
		dropbear_log(LOG_INFO, "Failed to connect to agent");
	}

	return fd;
}

/* handle a request for a connection to the locally running ssh-agent
   or forward. */
static int new_agent_chan(struct Channel * channel) {

	int fd = -1;

	if (!cli_opts.agent_fwd)
		return SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;

	fd = connect_agent();
	if (fd < 0) {
		return SSH_OPEN_CONNECT_FAILED;
	}

	setnonblocking(fd);

	ses.maxfd = MAX(ses.maxfd, fd);

	channel->readfd = fd;
	channel->writefd = fd;

	return 0;
}

/* Sends a request to the agent, returning a newly allocated buffer
 * with the response */
/* This function will block waiting for a response - it will
 * only be used by client authentication (not for forwarded requests)
 * won't cause problems for interactivity. */
/* Packet format (from draft-ylonen)
   4 bytes     Length, msb first.  Does not include length itself.
   1 byte      Packet type.  The value 255 is reserved for future extensions.
   data        Any data, depending on packet type.  Encoding as in the ssh packet
               protocol.
*/
static buffer * agent_request(unsigned char type, buffer *data) {

	buffer * payload = NULL;
	buffer * inbuf = NULL;
	size_t readlen = 0;
	ssize_t ret;
	const int fd = cli_opts.agent_fd;
	unsigned int data_len = 0;
	if (data)
	{
		data_len = data->len;
	}

	payload = buf_new(4 + 1 + data_len);

	buf_putint(payload, 1 + data_len);
	buf_putbyte(payload, type);
	if (data) {
		buf_putbytes(payload, data->data, data->len);
	}
	buf_setpos(payload, 0);

	ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len);
	if ((size_t)ret != payload->len) {
		TRACE(("write failed fd %d for agent_request, %s", fd, strerror(errno)))
		goto out;
	}

	buf_free(payload);
	payload = NULL;
	TRACE(("Wrote out bytes for agent_request"))
	/* Now we read the response */
	inbuf = buf_new(4);
	ret = atomicio(read, fd, buf_getwriteptr(inbuf, 4), 4);
	if (ret != 4) {
		TRACE(("read of length failed for agent_request"))
		goto out;
	}
	buf_setpos(inbuf, 0);
	buf_setlen(inbuf, ret);

	readlen = buf_getint(inbuf);
	if (readlen > MAX_AGENT_REPLY) {
		TRACE(("agent reply is too big"));
		goto out;
	}
	
	buf_resize(inbuf, readlen);
	buf_setpos(inbuf, 0);
	ret = atomicio(read, fd, buf_getwriteptr(inbuf, readlen), readlen);
	if ((size_t)ret != readlen) {
		TRACE(("read of data failed for agent_request"))
		goto out;
	}
	buf_incrwritepos(inbuf, readlen);
	buf_setpos(inbuf, 0);

out:
	if (payload)
		buf_free(payload);

	return inbuf;
}

static void agent_get_key_list(m_list * ret_list)
{
	buffer * inbuf = NULL;
	unsigned int num = 0;
	unsigned char packet_type;
	unsigned int i;
	int ret;

	inbuf = agent_request(SSH2_AGENTC_REQUEST_IDENTITIES, NULL);
	if (!inbuf) {
		TRACE(("agent_request failed returning identities"))
		goto out;
	}

	/* The reply has a format of:
		byte			SSH2_AGENT_IDENTITIES_ANSWER
		uint32			num_keys
  	   Followed by zero or more consecutive keys, encoded as:
       	 string			key_blob
    	 string			key_comment
	 */
	packet_type = buf_getbyte(inbuf);
	if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) {
		goto out;
	}

	num = buf_getint(inbuf);
	for (i = 0; i < num; i++) {
		sign_key * pubkey = NULL;
		enum signkey_type key_type = DROPBEAR_SIGNKEY_ANY;
		buffer * key_buf;

		/* each public key is encoded as a string */
		key_buf = buf_getstringbuf(inbuf);
		pubkey = new_sign_key();
		ret = buf_get_pub_key(key_buf, pubkey, &key_type);
		buf_free(key_buf);
		if (ret != DROPBEAR_SUCCESS) {
			/* This is slack, properly would cleanup vars etc */
			dropbear_exit("Bad pubkey received from agent");
		}
		pubkey->type = key_type;
		pubkey->source = SIGNKEY_SOURCE_AGENT;

		list_append(ret_list, pubkey);

		/* We'll ignore the comment for now. might want it later.*/
		buf_eatstring(inbuf);
	}

out:
	if (inbuf) {
		buf_free(inbuf);
		inbuf = NULL;
	}
}

void cli_setup_agent(struct Channel *channel) {
	if (!getenv("SSH_AUTH_SOCK")) {
		return;
	}
	
	cli_start_send_channel_request(channel, "auth-agent-req@openssh.com");
	/* Don't want replies */
	buf_putbyte(ses.writepayload, 0);
	encrypt_packet();
}

/* Returned keys are prepended to ret_list, which will
   be updated. */
void cli_load_agent_keys(m_list *ret_list) {
	/* agent_fd will be closed after successful auth */
	cli_opts.agent_fd = connect_agent();
	if (cli_opts.agent_fd < 0) {
		return;
	}

	agent_get_key_list(ret_list);
}

void agent_buf_sign(buffer *sigblob, sign_key *key, 
		buffer *data_buf) {
	buffer *request_data = NULL;
	buffer *response = NULL;
	unsigned int siglen;
	int packet_type;
	
	/* Request format
	byte			SSH2_AGENTC_SIGN_REQUEST
	string			key_blob
	string			data
	uint32			flags
	*/
	request_data = buf_new(MAX_PUBKEY_SIZE + data_buf->len + 12);
	buf_put_pub_key(request_data, key, key->type);
	
	buf_putbufstring(request_data, data_buf);
	buf_putint(request_data, 0);
	
	response = agent_request(SSH2_AGENTC_SIGN_REQUEST, request_data);
	
	if (!response) {
		goto fail;
	}
	
	packet_type = buf_getbyte(response);
	if (packet_type != SSH2_AGENT_SIGN_RESPONSE) {
		goto fail;
	}
	
	/* Response format
	byte			SSH2_AGENT_SIGN_RESPONSE
	string			signature_blob
	*/
	siglen = buf_getint(response);
	buf_putbytes(sigblob, buf_getptr(response, siglen), siglen);
	goto cleanup;
	
fail:
	/* XXX don't fail badly here. instead propagate a failure code back up to
	   the cli auth pubkey code, and just remove this key from the list of 
	   ones to try. */
	dropbear_exit("Agent failed signing key");

cleanup:
	if (request_data) {
		buf_free(request_data);
	}
	if (response) {
		buf_free(response);
	}
}

#endif
