/*
 * Dropbear - a SSH2 server
 * 
 * Copyright (c) 2002,2003 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. */

/* This file (agentfwd.c) handles authentication agent forwarding, for OpenSSH
 * style agents. */

#include "includes.h"

#ifndef DISABLE_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 "random.h"
#include "listener.h"

#define AGENTDIRPREFIX "/tmp/dropbear-"

static int send_msg_channel_open_agent(int fd);
static int bindagent(int fd, struct ChanSess * chansess);
static void agentaccept(struct Listener * listener, int sock);

/* Handles client requests to start agent forwarding, sets up listening socket.
 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
int agentreq(struct ChanSess * chansess) {

	int fd;

	if (chansess->agentlistener != NULL) {
		return DROPBEAR_FAILURE;
	}

	/* create listening socket */
	fd = socket(PF_UNIX, SOCK_STREAM, 0);
	if (fd < 0) {
		goto fail;
	}

	/* create the unix socket dir and file */
	if (bindagent(fd, chansess) == DROPBEAR_FAILURE) {
		goto fail;
	}

	/* listen */
	if (listen(fd, 20) < 0) {
		goto fail;
	}

	/* set non-blocking */
	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
		goto fail;
	}

	/* pass if off to listener */
	chansess->agentlistener = new_listener( &fd, 1, 0, chansess, 
								agentaccept, NULL);

	if (chansess->agentlistener == NULL) {
		goto fail;
	}

	return DROPBEAR_SUCCESS;

fail:
	/* cleanup */
	agentcleanup(chansess);

	return DROPBEAR_FAILURE;
}

/* accepts a connection on the forwarded socket and opens a new channel for it
 * back to the client */
/* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static void agentaccept(struct Listener * listener, int sock) {

	int fd;

	fd = accept(sock, NULL, NULL);
	if (fd < 0) {
		TRACE(("accept failed"));
		return;
	}

	if (send_msg_channel_open_agent(fd) != DROPBEAR_SUCCESS) {
		close(fd);
	}

}

/* set up the environment variable pointing to the socket. This is called
 * just before command/shell execution, after dropping priveleges */
void agentset(struct ChanSess * chansess) {

	char *path = NULL;
	int len;

	if (chansess->agentlistener == NULL) {
		return;
	}

	/* 2 for "/" and "\0" */
	len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2;

	path = m_malloc(len);
	snprintf(path, len, "%s/%s", chansess->agentdir, chansess->agentfile);
	addnewvar("SSH_AUTH_SOCK", path);
	m_free(path);
}

/* close the socket, remove the socket-file */
void agentcleanup(struct ChanSess * chansess) {

	char *path = NULL;
	uid_t uid;
	gid_t gid;
	int len;

	if (chansess->agentlistener != NULL) {
		remove_listener(chansess->agentlistener);
		chansess->agentlistener = NULL;
	}

	if (chansess->agentfile != NULL && chansess->agentdir != NULL) {

		/* Remove the dir as the user. That way they can't cause problems except
		 * for themselves */
		uid = getuid();
		gid = getgid();
		if ((setegid(ses.authstate.pw->pw_gid)) < 0 ||
			(seteuid(ses.authstate.pw->pw_uid)) < 0) {
			dropbear_exit("failed to set euid");
		}

		/* 2 for "/" and "\0" */
		len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2;

		path = m_malloc(len);
		snprintf(path, len, "%s/%s", chansess->agentdir, chansess->agentfile);
		unlink(path);
		m_free(path);

		rmdir(chansess->agentdir);

		if ((seteuid(uid)) < 0 ||
			(setegid(gid)) < 0) {
			dropbear_exit("failed to revert euid");
		}

		m_free(chansess->agentfile);
		m_free(chansess->agentdir);
	}

}

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


/* helper for accepting an agent request */
static int send_msg_channel_open_agent(int fd) {

	if (send_msg_channel_open_init(fd, &chan_agent) == DROPBEAR_SUCCESS) {
		encrypt_packet();
		return DROPBEAR_SUCCESS;
	} else {
		return DROPBEAR_FAILURE;
	}
}

/* helper for creating the agent socket-file
   returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int bindagent(int fd, struct ChanSess * chansess) {

	struct sockaddr_un addr;
	unsigned int prefix;
	char path[sizeof(addr.sun_path)], sockfile[sizeof(addr.sun_path)];
	mode_t mode;
	int i;
	uid_t uid;
	gid_t gid;
	int ret = DROPBEAR_FAILURE;

	/* drop to user privs to make the dir/file */
	uid = getuid();
	gid = getgid();
	if ((setegid(ses.authstate.pw->pw_gid)) < 0 ||
		(seteuid(ses.authstate.pw->pw_uid)) < 0) {
		dropbear_exit("failed to set euid");
	}

	memset((void*)&addr, 0x0, sizeof(addr));
	addr.sun_family = AF_UNIX;

	mode = S_IRWXU;

	for (i = 0; i < 20; i++) {
		genrandom((unsigned char*)&prefix, sizeof(prefix));
		/* we want 32 bits (8 hex digits) - "/tmp/dropbear-f19c62c0" */
		snprintf(path, sizeof(path), AGENTDIRPREFIX "%.8x", prefix);

		if (mkdir(path, mode) == 0) {
			goto bindsocket;
		}
		if (errno != EEXIST) {
			break;
		}
	}
	/* couldn't make a dir */
	goto out;

bindsocket:
	/* Format is "/tmp/dropbear-0246dead/auth-d00f7654-23".
	 * The "23" is the file desc, the random data is to avoid collisions
	 * between subsequent user processes reusing socket fds (odds are now
	 * 1/(2^64) */
	genrandom((unsigned char*)&prefix, sizeof(prefix));
	snprintf(sockfile, sizeof(sockfile), "auth-%.8x-%d", prefix, fd);
			
	snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", path, sockfile);

	if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
		chansess->agentdir = m_strdup(path);
		chansess->agentfile = m_strdup(sockfile);
		ret = DROPBEAR_SUCCESS;
	}


out:
	if ((seteuid(uid)) < 0 ||
		(setegid(gid)) < 0) {
		dropbear_exit("failed to revert euid");
	}
	return ret;
}

#endif
