/*
 esp.h

 Author: Liraz Siri <liraz@bigfoot.com>

 Copyright (c) 1998 Liraz Siri <liraz@bigfoot.com>, Ariel, Israel
                    All rights reserved.

 Created: Tue Sep 15 IST 1998
 Last updated: Tue Sep 22 17:36:31 GMT 1998

 Code for the implementation of the esp data transfer protocol.
 The protocol handles (in coordination with ssh) the control of an
 encrypted data stream, via a covert method of delivery, spanning tcp,
 udp and icmp. The code handles intialization, data delivery and recovery,
 assuming a hostile network enviorment.
*/

#include "includes.h"
#include "buffer.h"

/* The minimum interval between two login attempts (in seconds). This 
   has several reasons for existing. Since we listen on more then one
   interface, it may be possible for one packet to be picked up on both,
   and that would inhibit esp to fork twice, and disrupt any login
   attempt. */
#define PHANTOM_MINIMUM_CONNECT_INTERVAL	3

/* Connection negotiation request maximum length. (it can be larger,
   but we ignore the rest of the packet) */
#define PHANTOM_RQST_LEN	4096

/* The default method of packet transmission, used by the esp_ssh
   client */
#define PHANTOM_DEFAULT_IPPROTO	IPPROTO_TCP

/* include independant IPPROTO macros */
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#define IPPROTO_ICMP 1

#define ICMP_ECHOREPLY	0
#define ICMP_ECHO	8

/* Supported covert channels */
#define TCP_SUPPORT
#define UDP_SUPPORT
#define ICMP_SUPPORT

/* icmp protocol transmit/receive data types. We delivery and receive
   icmp packets of type ECHOREPLY, to minimize unrelated network traffic */
#define ICMP_TRANSMIT_TYPE	ICMP_ECHOREPLY
#define ICMP_RECEIVE_TYPE	ICMP_ECHOREPLY

/* tcp protocol transmit/receive data types. We use TH_RST, since the tcp
   specifications do not reply to this type of packet. */
#define TCP_TRANSMIT_TYPE	TH_RST
#define TCP_RECEIVE_TYPE	TH_RST

/* Global response timeout, used in the packet_read_stimulate routine,
   and in the syncronization routine of serverloop.c and clientloop.c.
   This should be modified to adapt to the other sides real reponse time
   after several packets, in a way similair to tcp/ip */
#define ICMP_RESPONSE_TIMEOUT	esp_get_rtt()
#define PHANTOM_DEFAULT_RTT	1000000
#define PHANTOM_RTT_SAFEZONE    50000	/* amount of microseconds
				           artificially added to the real rtt*/ 
/* microseconds, minimum stimulate timeout timer packet_read_stimulate,
   and the like*/
#define PHANTOM_MIN_STIM_TIMEOUT 500000

#define ICMP_READ_ATTEMPTS	30	/* in seconds */

#define MAX_RTT_PACKETS		3	/* the maximum number of icmp echo
					   requests we send out (when 
					   calculating rtt before we give
					   up) */

/* just to keep our connection fluxing (in seconds) */
#define PHANTOM_KEEPALIVE_TIMEOUT	10

/* default delay before packet transmission. Since we assemble our packets
   on a raw socket, it is feasable that large amounts of information might
   overflow the kernel before it has a chance to deliver the packets, and
   it will drop them, (similair to the drop of icmp packets in ping -f 
   tranmission) */
#define PHANTOM_TRANSMIT_DELAY	100000

/* maximum idle time by client, before server closes connection.
   Note that this does not actually refer to idle time by the user of the 
   client, since the client sends an SSH_MSG_IGNORE msg every 
   maximum of PHANTOM_MAXIMUM_RANDOM_SEND_INTERVAL */
#define PHANTOM_SESSION_TIMEOUT	60

#define ICMP_HDR_SIZE		(sizeof(struct icmp_echo)+sizeof(struct iprec))
#define TCP_HDR_SIZE		(sizeof(struct tcprec)+sizeof(struct iprec))
#define UDP_HDR_SIZE		(sizeof(struct udprec)+sizeof(struct iprec))
#define ICMP_MIN_SIZE		150

/* the number of packets that should arrive before we retransmit
   our request for a lost packet. We assume the other side has lost
   our transmitted request, and is continuing transmission of higher
   sequenced packets */
#define PHANTOM_QUEUE_RESEND	1

/* This is part of the sync mechanism. The value is the ratio of 
   packets that will be sent for connection synchronization in a direct
   relationship to the size of the queue. For example:
   If our queue can hold 100 packets, and our ratio is 4, then 
   the sync mechanism sends a packet every 25 received packets. 
 
   The sync mechanism in the esp protocol is an important part of 
   the packet loss recovery feature. Basicly we ensure that packets
   have been received before we remove them from the queue in an
   orderly fashion */
#define PHANTOM_SYNC_RATIO_DEFAULT	1

/* This is the size of the transmission queue. The significance of this
   value is actually the number of packets after which a request_resend
   will not function anymore on that specific packet. 
   Values larger tend to work better with faster reliable network
   conditions, while smaller values tend to be more practical when dealing
   with a more unreliable network */
#define PHANTOM_WINDOW_SIZE_DEFAULT	1

/* ICMP codes, used to tag icmp_code */
#define PHANTOM_DATA_CODE		0  /* data packet */
#define PHANTOM_RESEND_CODE		1  /* request resend of packet */
#define PHANTOM_SYNC_CODE		2  /* syncronize connection, clear queue */
#define PHANTOM_REQUEST_SYNC_CODE	3  /* request syncronization */
#define PHANTOM_SEQ_CODE		4  /* sequence packet. */
#define PHANTOM_REQUEST_SEQ_CODE	5  /* request sequence packet */

/* These values represent the data payload size of the esp protocol
   packets. I'm not sure what benifits, if any, come out of this padding,
   but I'm more comfortable sending standard sized control packets */
#define ICMP_CONTROLMSG_SIZE	4	
#define TCP_CONTROLMSG_SIZE	4
#define UDP_CONTROLMSG_SIZE	4

/* TCP/UDP esp 'listen' ports. 80/53 where chosen to the effect
   of filtering through protective firewalls. ICMP_SERVER_PORT however
   is just an arbitrary constant */
#define TCP_SERVER_PORT	80
#define UDP_SERVER_PORT	53
#define ICMP_SERVER_PORT 2938

/* Arbitrary values, stating the 'srcport' the server side should expect
   when handling raw TCP/UDP packets, originating from the client side.
   This only applies to negotiation packets (esp_SYN). The technique
   is implemented in effort to minimize CPU usage by esp_sshd */
#define TCP_CLIENT_PORT	3283
#define UDP_CLIENT_PORT	9832
#define ICMP_CLIENT_PORT 3482

/* creates a raw esp 'proto' socket, and initializes a buffer for
   receive/transmit. Returns the raw socket on success, and -1 
   on failure. */ 
int esp_init(int proto);

/* shutdown all the esp sockets */
void esp_shutdown(void);

/* closes all the old raw sockets and returns a new one, note that we don't
   reinitialized the receive/transmit buffers, unless they haven't been
   previously initialized, return the new raw socket, -1 on failure */
int esp_reinit(int proto);

/* set the destination and the that will be used in esp_transmit,
   and while your at it, setting the protocol, reseting srcport and dstport. */
void esp_set_destination(struct sockaddr_in *destaddr, int proto);

/* set the esp protocol that will be used to send and receive
   esp's packets. This can be any of the three supported protocols,
   ICMP, UDP and TCP. This is of course crucail to esp's methodolagy */
void esp_set_proto(int proto);

/* Set the source of the transmission, the receive/transmis ids
  (srcport/dstport) of the specific protocol used. This does not set the
  id's used in the rest of esp, but will initialize values that will
  be later used by esp_set_proto. */
void esp_set_source(struct sockaddr_in *srcaddr, int receive_id,
			int transmit_id, int proto);

/* set the packet send delay. This is important for several functions:
   network enviorment simulation and data flow control */
void esp_set_delay(unsigned long microseconds);

/* set the maximum packet size. here we actually just resizes the receive
   buffers. note that we destroy any data in the receive packet
   buffer, so there shouldn't be any data in it. Come to think of it,
   there should never be any important data in receive packet, as it
   is always handled inside esp_receive. */

void esp_set_max_packet_size(unsigned int len);

/* get the maximum icmp packet size. I'm not sure I have a use for this. */
unsigned int esp_get_max_packet_size(void);

/* get the maximum response timeout. esp_get_timeout isn't really
   used directly by the esp mechanism, but by packet.c, which
   uses esp_get_timeout to determine how long to wait for a packet
   to arrive. This SHOULD be used in the data flow mechanism. 

   *** NO NO NO *** this has nothing to do with how long we wait for
		     packets, this turns out to be the session timeout */
unsigned int esp_get_timeout(void);

/* return our round trip time. */
unsigned long esp_get_rtt(void);

/* set our round trip time */
void esp_set_rtt(unsigned long rtt);

/* turn packet syncronization on/off (useless/wastefull at negotiation, 
   needed for flow control/packet loss recovery in the main connection loops */
void esp_set_sync(int onoff);

/* set our packet window size */
void esp_set_window_size(int window_size);

/* get our packet window size */
int esp_get_window_size(void);

/* set sync ratio */
void esp_set_sync_ratio(int sync_ratio);

/* get sync ratio */
int esp_get_sync_ratio(void);

/* set the maximum response timeout. This is actually kind of important. 
   Should be used as part of the data flow mechanism. We get 10 packets,
   and measure the highest response time, and use it for future
   reference, when waiting for packets to arrive. 

   *** NO NO NO *** this has nothing to do with how long we wait for
                    packets, this turns out to be the session timeout. 
   session timeout - the time that goes by before we 'disconnect' from
   the remote side */
void esp_set_timeout(unsigned int timeout);

/* assemble a esp DATA packet. We build the packet according to 
   esp_proto, and tag it with the protocol marks... sequence,
   receive_id, transmit_id. Of course we also calculate a checksum. 
   Note the sequence is incremented each time we transmit as part of the
   packet recovery system.

   But that's more on the technical side of the esp protocol. What we
   actually do is get one standard SSH packet from outgoing, and send it  
   through WHATEVER protocol (ala raw socket). 

   esp_transmit needs to have esp_set_destination called first.
   duh, so we know where to send our packets.  
*/
int esp_transmit(Buffer *outgoing);

/* wrapper for sendto that simulates packet loss */
int PL_sendto(int s, const void *msg, int len, unsigned int flags,
              const struct sockaddr *to, int tolen);

/* esp_receive is kind of the centerplace where alot of the work
   gets done. We handle protocol messages here. This includes data flow
   syncronization, packet loss recovery and ignore messages (which are
   ironicly ignore and not used by esp or any other part of
   esp_ssh. We kind of preform a double edge job, and also transmit
   protocol messages regarding packet loss, data flow syncronization.
   whatever. this is actually a headache to work out. */
int esp_receive(Buffer *incoming);

/* Receive a raw ip packet (from the esp_pcap), determine wether or
   not to relay it over to the packet_receive mechanism */
int esp_receive_raw(Buffer *incoming, const u_char *packet, u_int len);

/* copy the address of the last incoming packet to from. note that the
   packet address is only copied when accept_any is true, so calling
   icmp_get_source will return the address of the last global packet
   received. Returns false if no packets have yet been received */
void esp_get_source(struct sockaddr_in *from);

/* return the session protocol. This actually isn't used any more.
   But I'm not removing it since I may find it comes usefull later */
int esp_get_proto(void);

/* Returns true is there are any queued packets, ready for reading in the
   received packet queue buffer. This is used in both serverloop.c 
   and clientloop.c to substitute socket data availability in select. 
   Both clientloop.c and serverloop.c will read any queued packets
   available for reading (say, after we finish a read sequence)
   immediately */ 
int esp_packets_available(void);

/* Returns true if our queue has reached maximum size and we need to 
   clear it before we transmit any new packets */
int esp_transmit_blocked(void);

/* request the resend of the last packet with the sequence of seq */
int esp_request_resend(u_short seq);

/* send a esp sequence request. basicly, we transmit our last
transmitted sequence, and request the other side to do the same */
int esp_request_seq(void);

/* resend the last packet with the sequence of seq. Returns true if 
   we actually found the packet in queued_transmitted_packets_buffer,
   otherwise returns -1 */
int esp_resend_packet(u_short seq);

/* Transmit a control protocol msg. The packet is taged with the icmp_code
   of type, and the icmp_seq of sequence.
int esp_transmit_proto_msg(int type, int sequence);

/* Transmit our connection sync. Transmitted is the last sequence
   received. We tag the packet with the ICMP_SYNC_CODE. We keep it very
   simple, assemble a new packet, mark it, and send it along. we tag
   the packet with the sequence of the last transmitted DATA packet. */
int esp_transmit_sync(void);

/* Transmit a sequence packet that should be ignore. We tag the packet
   with the sequence of the last transmitted DATA packet. esp_receive
   should be prepared to handle the situation that would occur if the
   sequence is higher then expected, unless already waiting for a
   resend. */
int esp_transmit_seq(void);

/* Request sync from the other side of the connection. We do this when
   reaching the unfortunate event a full queue. We block, and remind
   the other side to send us sync */
int esp_request_sync(void);


/* Synchronize data flow. this basicly means we 'sychronize' transmission,
   removing confirmed received packets from the transmit queue, allowing
   new data to be transmitted. Note that when the transmit queue is full
   we don't make any new packets */
void esp_sync(u_short seq);

/* return icmp_receive_id */
int esp_get_receive_id(void);

/* return icmp_transmit_id */
int esp_get_transmit_id(void);

/*
 * in_cksum --
 *      Checksum routine for Internet Protocol family headers (C Version)
 */
int esp_in_cksum(u_short *addr, int len);

/*
 *  ICMP_ECHO / ICMP_ECHOREPLY header prototype
 */

struct icmp_echo
{
    u_char  icmp_type;          /* 1 byte type              */
    u_char  icmp_code;          /* 1 byte code              */
    u_short icmp_cksum;         /* 2 byte checksum          */
    u_short icmp_dstport;       /* 2 byte identification    */
    u_short icmp_seq;           /* 2 byte sequence number   */
    u_short icmp_srcport;       /* 2 byte hack at a tcp/udp style srcport */
};

/* Ok, so maybe this isn't exactly a standard udp packet... TOUGH.
   Still complies with the UDP rfcs though. */

struct udprec
{
 u_short udp_srcport; 
 u_short udp_dstport;
 u_short udp_len;
 u_short udp_cksum;
 u_short udp_seq;
 u_char  udp_code;
};

#define TH_FIN  0x01
#define TH_SYN  0x02
#define TH_RST  0x04
#define TH_PUSH 0x08
#define TH_ACK  0x10
#define TH_URG  0x20

/* What a long, wastefull disgusting structure... all those fields
   to fill in... no wonder tcp is so weak */

struct tcprec {
 u_short tcp_srcport;
 u_short tcp_dstport;
 u_long  tcp_seq;
 u_long  tcp_ack;
 u_char  tcp_code;
 u_char  tcp_type;
 u_short tcp_win;                 /* window */
 u_short tcp_cksum;               /* checksum */
 u_short tcp_urp;                 /* urgent pointer */
};

/*
 * Structure of an internet header, naked of options.
 *
 * We declare ip_len and ip_off to be short, rather than u_short
 * pragmatically since otherwise unsigned comparisons can result
 * against negative integers quite easily, and fail in subtle ways.
 */
struct iprec {
#if BYTE_ORDER == LITTLE_ENDIAN
        u_char  ip_hl:4,                /* header length */
                ip_v:4;                 /* version */
#endif
#if BYTE_ORDER == BIG_ENDIAN
        u_char  ip_v:4,                 /* version */
                ip_hl:4;                /* header length */
#endif
        u_char  ip_tos;                 /* type of service */
        short   ip_len;                 /* total length */
        u_short ip_id;                  /* identification */
        short   ip_off;                 /* fragment offset field */
#define IP_DF 0x4000                    /* dont fragment flag */
#define IP_MF 0x2000                    /* more fragments flag */
#define IP_OFFMASK 0x1fff               /* mask for fragmenting bits */
        u_char  ip_ttl;                 /* time to live */
        u_char  ip_p;                   /* protocol */
        u_short ip_sum;                 /* checksum */
        struct  in_addr ip_src,ip_dst;  /* source and dest address */
};

