// Copyright (C) 2000
//          by the Massachusetts Institute of Technology
//
//    Export of this software from the United States of America may
//    require a specific license from the United States Government.  It
//    is the responsibility of any person or organization contemplating
//    export to obtain such a license before exporting.
//
// WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
// distribute this software and its documentation for any purpose and
// without fee is hereby granted, provided that the above copyright
// notice appear in all copies and that both that copyright notice and
// this permission notice appear in supporting documentation, and that
// the name of M.I.T. not be used in advertising or publicity pertaining
// to distribution of the software without specific, written prior
// permission.  M.I.T. makes no representations about the suitability of
// this software for any purpose.  It is provided "as is" without express
// or implied warranty.

// ssh.h
// Generic SSH stuff

#ifndef SSH_H
#define SSH_H

#include "stdafx.h"
//#include <string.h>

//------------------------------------------------------
// SSH Version 1.5 Stuff

/* Cipher types.  */
#define SSH_CIPHER_NONE			0 /* no encryption */
#define SSH_CIPHER_IDEA			1 /* IDEA CFB */
#define SSH_CIPHER_DES			2 /* DES CBC */
#define SSH_CIPHER_3DES			3 /* 3DES CBC - MUST SUPPORT THIS */
#define SSH_CIPHER_TSS			4 /* TRI's Simple Stream encryption CBC */
#define SSH_CIPHER_ARCFOUR		5 /* Arcfour */
#define SSH_CIPHER_BLOWFISH	6 /* Bruce Schneier's Blowfish */

/* Authentication methods.  */
#define SSH_AUTH_RHOSTS			1
#define SSH_AUTH_RSA				2
#define SSH_AUTH_PASSWORD		3
#define SSH_AUTH_RHOSTS_RSA	4
#define SSH_AUTH_TIS				5
#define SSH_AUTH_KERBEROS		6
#define SSH_PASS_KERBEROS_TGT	7

/* If you add new methods add them after this using random number between 16-31
   so if someone else adds also new methods you dont use same number. */

/* Protocol flags.  These are bit masks. */
#define SSH_PROTOFLAG_SCREEN_NUMBER		1 /* X11 forwarding includes screen */
#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN	2 /* forwarding opens contain host */

/* Definition of message types. */
#define SSH_MSG_NONE									0	/* no message */
#define SSH_MSG_DISCONNECT							1	/* cause (string) */
#define SSH_SMSG_PUBLIC_KEY						2	/* ck,msk,srvk,hostk */
#define SSH_CMSG_SESSION_KEY						3	/* key (MP_INT) */
#define SSH_CMSG_USER								4	/* user (string) */
#define SSH_CMSG_AUTH_RHOSTS						5	/* user (string) */
#define SSH_CMSG_AUTH_RSA							6	/* modulus (MP_INT) */
#define SSH_SMSG_AUTH_RSA_CHALLENGE				7	/* int (MP_INT) */
#define SSH_CMSG_AUTH_RSA_RESPONSE				8	/* int (MP_INT) */
#define SSH_CMSG_AUTH_PASSWORD					9	/* pass (string) */
#define SSH_CMSG_REQUEST_PTY						10	/* TERM, tty modes */
#define SSH_CMSG_WINDOW_SIZE						11	/* row,col,xpix,ypix */
#define SSH_CMSG_EXEC_SHELL						12	/* */
#define SSH_CMSG_EXEC_CMD							13	/* cmd (string) */
#define SSH_SMSG_SUCCESS							14	/* */
#define SSH_SMSG_FAILURE							15	/* */
#define SSH_CMSG_STDIN_DATA						16	/* data (string) */
#define SSH_SMSG_STDOUT_DATA						17	/* data (string) */
#define SSH_SMSG_STDERR_DATA						18	/* data (string) */
#define SSH_CMSG_EOF									19	/* */
#define SSH_SMSG_EXITSTATUS						20	/* status (int) */
#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION		21	/* channel (int) */
#define SSH_MSG_CHANNEL_OPEN_FAILURE			22	/* channel (int) */
#define SSH_MSG_CHANNEL_DATA						23	/* ch,data (int,str) */
#define SSH_MSG_CHANNEL_CLOSE						24	/* channel (int) */
#define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION	25	/* channel (int) */

/* new channel protocol */
#define SSH_MSG_CHANNEL_INPUT_EOF            24
#define SSH_MSG_CHANNEL_OUTPUT_CLOSED        25

/*      SSH_CMSG_X11_REQUEST_FORWARDING         26         OBSOLETE */
#define SSH_SMSG_X11_OPEN							27	/* channel (int) */
#define SSH_CMSG_PORT_FORWARD_REQUEST			28	/* p,host,hp (i,s,i) */
#define SSH_MSG_PORT_OPEN							29	/* ch,h,p (i,s,i) */
#define SSH_CMSG_AGENT_REQUEST_FORWARDING		30	/* */
#define SSH_SMSG_AGENT_OPEN						31	/* port (int) */
#define SSH_MSG_IGNORE								32	/* string */
#define SSH_CMSG_EXIT_CONFIRMATION				33	/* */
#define SSH_CMSG_X11_REQUEST_FORWARDING		34	/* proto,data (s,s) */
#define SSH_CMSG_AUTH_RHOSTS_RSA					35	/* user,mod (s,mpi) */
#define SSH_MSG_DEBUG								36	/* string */
#define SSH_CMSG_REQUEST_COMPRESSION			37	/* level 1-9 (int) */
#define SSH_CMSG_MAX_PACKET_SIZE					38	/* max_size (int) */

/* Support for TIS authentication server
   Contributed by Andre April <Andre.April@cediti.be>. */
#define SSH_CMSG_AUTH_TIS							39	/* */
#define SSH_SMSG_AUTH_TIS_CHALLENGE				40	/* string */
#define SSH_CMSG_AUTH_TIS_RESPONSE				41	/* pass (string) */

/* Support for kerberos authentication by Glenn Machin and Dug Song
   <dugsong@umich.edu> */
#define SSH_CMSG_AUTH_KERBEROS                  42      /* string (KTEXT) */
#define SSH_SMSG_AUTH_KERBEROS_RESPONSE         43      /* string (KTEXT) */
#define SSH_CMSG_HAVE_KERBEROS_TGT              44      /* string (credentials) */

/* Reserved for official extensions, do not use these */
#define SSH_CMSG_RESERVED_START					45
#define SSH_CMSG_RESERVED_END						63
//------------------------------------------------------

//------------------------------------------------------
// Other SSH Specific
//
#define SSH_SESSION_KEY_LENGTH			32
//#define SSH_MAX_PACKET_LENGTH				262156		// Total Length including length + padding

// Ok In theory we're not conforming to the RFC since these are
// fixed size packets, but realistically the upper limit never gets hit
// in an interactive session so we're going to set these here for efficiency.
#define SSH_MAX_PACKET_LENGTH				65536		// Total Length including length + padding

//------------------------------------------------------
// WinSSH Specific
//
#define SSH_PROTOCOL_VERSION "SSH-1.5-1.0.00\n"

//-------------------------------------------------------------
// Crypto Library Includes
// Using Cryptlib library.
#define USE_CRYPTLIB
//#define USE_SSLEAY

#ifdef USE_CRYPTLIB
#include "cryptlib/capi.h"
#endif

#ifdef USE_SSLEAY
#include "ssleay/des.h"
#include "ssleay/md5.h"
#endif
//-----------------------------------------------------------


//------------------------------------------------------

class CSsh {

	public:
		CSsh();
		~CSsh();

		// Return the SSH Initialization String
		char *	pszGetProtocolVersion() { return szProtocolVersion; }

		//---------------------//
		// Setup class for use //
		//---------------------//

		// Set SSH Options
		void SetOptions (int iCipher, int iCompression, char * pszUsername, char *pszPassword)
		{	m_uiEncryptionMethod = iCipher; 
			m_uiCompressionLevel = iCompression; 
			strcpy(m_szUsername, pszUsername);	
			strcpy(m_szPassword, pszPassword); }

		// Set Buffer space for outgoing packets - this passes the memory allocation
		// to the invoking object's responsibility.
		void SetSendPacketBuffer(unsigned char * pucBuffer) { m_pucSendBuf = pucBuffer; }

		//----------------//
		// Accessing Data //
		//----------------//

		// Get Packet Length
		int	iGetPacketLength(unsigned char * pucBuffer) {return iGetWord(pucBuffer); }

		// Current Total Buffer Size (this is not Length as specified in the RFC)
		// PacketType begins at m_pucSendBuf[12].  Offset points to element after CRC Bytes.
		// (offset points to end of packet) Offest + 12 - 4 (length) - (padding) 
		int	iGetPacketBufferLength() 
				{return m_iSendBufOffset;}	// Get Send packet's length

		int	iGetServerAuthenticationMethods() { return m_uiServerAuthenticationMethods; }
		int	iGetServerEncryptionMethods() { return m_uiServerEncryptionMethods; }

		//--------------------------------//
		// Server and Client Packet Usage //
		//--------------------------------//
		int	iProcessIncomingPacket(int iExpectedPacket, unsigned char * pucPacket);

		void			CmsgUser();
		void			CmsgAuthPassword();
		void			CmsgRequestPty(char * pszTermType, unsigned int iTermRows, 
						unsigned int iTermCols, unsigned int iTermWidth = 0, unsigned int iTermHeight=0);

		void			CmsgX11RequestForwarding();

		void			CmsgExecShell();
	
		void			CmsgStdinData(unsigned char * pucString, int iStringLength);

		unsigned char *	pucGetStdoutString() { return m_pucStdout; }
		int					iGetStdoutLength() { return m_iStdoutLength; }
		//void	CmsgUsername(LPCSTR szPacket);
		//void	CmsgAuthenticate(LPCSTR szPacket);

		// Cleanup
		void CleanSessionData();

		//--------------//
		// Data Members //
		//--------------//
		unsigned int	m_uiEncryptionMethod;
		unsigned int	m_uiCompressionLevel;

	protected:

		//-------------------//
		// Protected Methods //
		//-------------------//

		// Inits Crypto Contexts
		void	SetSessionContexts();

		// Specific packet handlers
		int 	SmsgPublicKey(unsigned char * szPacket);


		// Packet Crackers
		int				DecryptData(unsigned char * pszCipherText);
		unsigned int	iGetWord (unsigned char * szPacketSegment);
		unsigned int	iGetNibble (unsigned char * szPacketSegment);
		unsigned char	*pszGetMpInt(unsigned char * szPacketSegment, int *iMpBitSize);

		// Packet Creators
		unsigned char cGetRandomChar();
		void	CreateRsaMpInt(unsigned char *pszInt, int iIntLength, unsigned char *pszData, int iDataLength);
	
		void	StartPacket(int iMessage);
		void	AddWord(unsigned int iWord);
		void	AddNibble(unsigned int iNibble);
		void	AddByte(unsigned int iByte);
		void	AddMpInt(unsigned char *pszMpInt, int iMpByteSize);
		void	EncryptPacket();
		void	FinishPacket();

		//--------------//
		// Data Members //
		//--------------//

		// Initial Init String "SSH-1.5-1.0.00\n"
		char 				szProtocolVersion[15];

		// SSH Specific Options
		unsigned int	m_uiServerEncryptionMethods;
		unsigned int	m_uiServerAuthenticationMethods;

		unsigned char	*m_pucSessionKey;

		char				m_szUsername[36];
		char				m_szPassword[36];

		// Flags
		int				m_iStartEncryptionFlag;

		// Send Packet Buffer.
		unsigned char	*m_pucSendBuf;
		int				m_iSendBufOffset;

		// Receive Packet info
		// Current Receive Memory Offset Location
		int				m_iRecvBufOffset;		
		
		int				m_iStdoutLength;
		unsigned char	*m_pucStdout;

		unsigned char	m_pucErrorMessage[512];
		
		// Specific Stuff for Cryptographic Libraries
#ifdef USE_CRYPTLIB
		CRYPT_CONTEXT	m_cryptcontextRecv;
		CRYPT_CONTEXT	m_cryptcontextSend;
		unsigned char	m_pucInitVectorRecv[8];
		unsigned char	m_pucInitVectorSend[8];


#endif // end USE_CRYPTLIB

#ifdef USE_SSLEAY
		
		des_key_schedule	deskeyscheduleOne;
		des_key_schedule	deskeyscheduleTwo;
		des_key_schedule	deskeyscheduleThree;
		des_cblock			m_descblockInitVector;

#endif // end USE_SSLEAY

};


#endif
