/
keys/
obj/
sys/
# include <kernel/kernel.h>
# include <kernel/user.h>
# include <kernel/rsrc.h>

inherit LIB_CONN;
inherit rsrc API_RSRC;

# define SSH		"/usr/System/obj/ssh"


object userd;		/* user daemon */
string version;		/* version string */
string host_key;	/* private host key */
string pub_host_key;	/* public host key */

# define BASE64 ("...........................................\x3e..." +   \
		 "\x3f\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d...=..." +  \
		 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c" + \
		 "\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19" + \
		 "......" +                                               \
		 "\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26" + \
		 "\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33" + \
		 "...................................................." + \
		 "...................................................." + \
		 ".............................")

/*
 * NAME:	base64_decode()
 * DESCRIPTION:	decode a base64 string
 */
private string base64_decode(string str)
{
    string result, bits;
    int i, len, b1, b2, b3, b4;

    result = "";
    bits = "...";
    for (i = 0, len = strlen(str); i < len; i += 4) {
	b1 = BASE64[str[i]];
	b2 = BASE64[str[i + 1]];
	b3 = BASE64[str[i + 2]];
	b4 = BASE64[str[i + 3]];
	bits[0] = (b1 << 2) | (b2 >> 4);
	bits[1] = (b2 << 4) | (b3 >> 2);
	bits[2] = (b3 << 6) | b4;
	result += bits;
    }

    if (b3 == '=') {
	return result[.. strlen(result) - 3];
    } else if (b4 == '=') {
	return result[.. strlen(result) - 2];
    }
    return result;
}

/*
 * NAME:	create()
 * DESCRIPTION:	initialize ssh connection daemon
 */
static create()
{
    string str;

    /*
     * read private host key
     */
    str = read_file("~/keys/id_dsa");
    if (!str) {
	error("No host key");
    }
    if (sscanf(str, "-----BEGIN DSA PRIVATE KEY-----%s" +
		    "-----END DSA PRIVATE KEY-----", str) == 0) {
	error("Bad host key");
    }
    str = implode(explode(str, "\r"), "");
    sscanf(str, "%*s\n\n%s", str);	/* skip possible comments */
    host_key = base64_decode(implode(explode(str, "\n"), ""));

    /*
     * read public host key
     */
    str = read_file("~/keys/id_dsa.pub");
    if (!str) {
	error("No public host key");
    }
    if (sscanf(str, "ssh-dss %s ", str) == 0) {
	error("Bad public host key");
    }
    pub_host_key = base64_decode(str);

    if (hash_crc32(host_key, pub_host_key) == 6922236) {
	DRIVER->message("*WARNING*\n\nYou are using pre-configured host keys.  To install your own host keys, run the\ncommand 'ssh-keygen -t dsa' and save the files in mudlib directory\n/usr/System/keys.\n\n");
    }

    /*
     * initialize
     */
    rsrc::create();
    rsrc::rsrc_set_limit("System", "ticks", 3000000);
    compile_object(SSH);
    userd = find_object(USERD);
    userd->set_binary_manager(0, this_object());
    version = "SSH-2.0-LPCssh_1.0";
}


/*
 * NAME:	select()
 * DESCRIPTION:	select protocol
 */
object select(string protocol)
{
    if (previous_object() == userd && sscanf(protocol, "SSH-2.0-%*s") != 0) {
	return clone_object(SSH);
    }
    return this_object();
}

/*
 * NAME:	login()
 * DESCRIPTION:	display an errormessage and disconnect
 */
int login(string str)
{
    previous_object()->message("Protocol mismatch.\r\n");
    return MODE_DISCONNECT;
}


/*
 * NAME:	query_timeout()
 * DESCRIPTION:	return login timeout
 */
int query_timeout(object obj)
{
    return 30;
}

/*
 * NAME:	query_banner()
 * DESCRIPTION:	return login banner
 */
string query_banner(object obj)
{
    return version + "\r\n";
}

/*
 * NAME:	query_version()
 * DESCRIPTION:	return the version string
 */
string query_version()
{
    return version;
}

/*
 * NAME:	query_host_key()
 * DESCRIPTION:	return the (private) host key
 */
string query_host_key()
{
    if (previous_program() == SSH) {
	return host_key;
    }
}

/*
 * NAME:	query_pub_host_key()
 * DESCRIPTION:	return the public host key
 */
string query_pub_host_key()
{
    return pub_host_key;
}