// $Id: SSH.cc,v 1.11 2003/08/31 00:38:11 vern Exp $
//
// Copyright (c) 2001, 2002
//      The Regents of the University of California.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that: (1) source code distributions
// retain the above copyright notice and this paragraph in its entirety, (2)
// distributions including binary code include the above copyright notice and
// this paragraph in its entirety in the documentation or other materials
// provided with the distribution, and (3) all advertising materials mentioning
// features or use of this software display the following acknowledgement:
// ``This product includes software developed by the University of California,
// Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
// the University nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#include "config.h"

#include <ctype.h>

#include "NetVar.h"
#include "SSH.h"
#include "Event.h"

SSH_Conn::SSH_Conn(NetSessions* s, HashKey* k, double t, const ConnID* id,
		const struct tcphdr* tp)
: TCP_Connection(s, k, t, id, tp)
	{
	}

void SSH_Conn::BuildEndpoints()
	{
	orig = new TCP_EndpointLine(this, 1, 0, 1);
	resp = new TCP_EndpointLine(this, 0, 0, 1);
	}

void SSH_Conn::NewLine(TCP_Endpoint* s, int length, const char* line,
			int /* const_len */)
	{
	// We're all done processing this endpoint - flag it as such,
	// before we even determine whether we have any event generation
	// work to do, to make sure we don't do any further work on it.
	s->AsEndpointLine()->SetSkipDeliveries(1);

	EventHandlerPtr event = s == orig ? ssh_client_version : ssh_server_version;
	if ( ! event )
		return;

	val_list* vl = new val_list;
	vl->append(BuildConnVal());
	vl->append(new StringVal(length, line));

	ConnectionEvent(event, vl);

	if ( s != orig )
		{
		// The SSH identification looks like this:
		//
		//     SSH-<protocolmajor>.<protocolminor>-<version>\n
		//
		// We're interested in the "version" part here.
		int i;
		for ( i = 0; i < length && line[i] != '-'; ++i )
			;
		for ( ++i; i < length && line[i] != '-'; ++i )
			;

		if ( length > i )
			VersionFoundEvent(s->dst_addr, line + i, length - i);
		else
			Weird("malformed_ssh_identification");
		}
	}
