/*

trcommon.h

  Authors:
        Tatu Ylonen <ylo@ssh.fi>
        Markku-Juhani Saarinen <mjos@ssh.fi>
        Timo J. Rinne <tri@ssh.fi>
        Sami Lehtinen <sjl@ssh.fi>

  Copyright (C) 1996-1998 SSH Communications Security Oy, Espoo, Finland
  All rights reserved.

Common (client+server) internal definitions for the transport layer protocol.

*/

/*
 * $Id: trcommon.h,v 1.18 1998/10/19 13:20:27 sjl Exp $
 * $Log: trcommon.h,v $
 * $EndLog$
 */

#ifndef TRCOMMON_H
#define TRCOMMON_H

#include "sshtrans.h"
#include "sshcrypt.h"
#include "sshstream.h"
#include "sshbuffer.h"
#include "bufzip.h"
#include "gmp.h"

#define SSH_VERSION_STRING              "SSH-2.0-%.200s"
#define SSH_VERSION_STRING_COMPAT       "SSH-1.99-%.200s"

#define SSH_MAX_TOTAL_PACKET_LENGTH     35000
#define SSH_MAX_PAYLOAD_LENGTH          32768
#define SSH_CONTROL_RESERVE             5000  /* reserve for control packets */
#define SSH_BUFFERING_LIMIT             50000

typedef enum
{
  SENT_NOTHING,
  SENT_VERSION,
  SENT_KEXINIT,
  SENT_KEX1_FINAL,
  SENT_NEWKEYS,
  SENT_SERVICE_REQUEST,
  SENT_INTERACTIVE,
  SENT_DEAD
} SshSentState;

typedef enum
{
  RECEIVED_NOTHING,
  RECEIVED_VERSION,
  RECEIVED_KEXINIT,
  RECEIVED_KEX1_IGNORED,
  RECEIVED_KEX1_FINAL,
  RECEIVED_KEY_CHECK,
  RECEIVED_KEX2,
  RECEIVED_NEWKEYS,
  RECEIVED_SERVICE_REQUEST,
  RECEIVED_INTERACTIVE,
  RECEIVED_DEAD
} SshReceivedState;

typedef const struct SshKexTypeRec *SshKexType;

typedef struct
{
  /* General state information. */
  Boolean server;                   /* Are we running as server? */
  Boolean version_compatibility;    /* Support compatibility with old ssh. */
  Boolean doing_rekey;              /* Are we doing rekey? */
  Boolean rekey_request_sent;       /* Have we sent rekey request. */
  Boolean destroy_after_disconnect; /* Destroy this context after disconnect */
  Boolean read_has_blocked;         /* We are not receiving read callbacks. */
  SshSentState sent_state;          /* Send state. */
  SshReceivedState received_state;  /* Receive state. */
  SshStream connection;             /* Connection to other side. */
  SshRandomState random_state;      /* Random state to use. */
  SshTransportParams params;        /* Configuration parameters. */

  /* Packet sequence numbers. */
  unsigned long incoming_sequence_number;
  unsigned long outgoing_sequence_number;
  
  /* State for data going out to the connection. */
  SshBuffer outgoing;               /* Pending outgoing data. */
  Boolean outgoing_eof;             /* Send EOF when buffer empty. */

  /* State for packets coming from the connection. */
  SshBuffer *incoming_packet;       /* Received packet. */
  size_t incoming_packet_index;     /* How much data has been received? */
  size_t incoming_packet_len;       /* Total length of incoming packet. */

  /* State for data going upwards. */
  SshStream up_stream;              /* The upward stream (ourself). */
  SshStreamCallback up_callback;    /* The application callback. */
  void *up_context;                 /* The application context. */
  SshBuffer up_outgoing;            /* Pending outgoing data upwards. */
  Boolean up_outgoing_eof;          /* Send EOF after current data. */
  SshBuffer up_incoming;            /* SshBuffer for incoming packets.*/
  Boolean up_write_blocked;         /* Write from up has failed. */
  Boolean up_read_blocked;          /* Read from up has failed. */
  
  /* Data for processing version number. */
  char *own_version;                /* Does not include crlf. */
  char remote_version[256];         /* Will not include crlf. */
  size_t remote_version_index;

  /* Version callback.  This is called when remote version string has been
     received. */
  SshVersionCallback version_callback;
  void *version_context;
  
  /* Guessed algorithms. */
  char *guessed_kex;
  char *guessed_host_key;
  
  /* Current selected algorithms (names).  The ciphers/macs are not actually
     taken into use (the objects below updated) until NEWKEYS is sent or
     received. */
  char *kex_name;
  char *host_key_name;  /* Negotiated `default' public key algorithm */
  char *host_key_names; /* List of common host key algorithms */
  struct SideKexInfo {
    char *cipher_name;
    char *mac_name;
    char *compression_name;
    unsigned char encryption_key[32];
    unsigned char iv[32];
    unsigned char integrity_key[32];
  } c_to_s, s_to_c;

  /* Internal objects for the algorithms currently in use. */
  SshKexType kex;                   /* Note: statically allocated, const. */
  SshHash hash;                     /* The hash algorithm is implied by
                                     * the key exchange algorithm. */
  SshCipher outgoing_cipher;
  size_t incoming_granularity;
  SshCipher incoming_cipher;
  size_t outgoing_granularity;
  SshMac outgoing_mac;
  SshMac incoming_mac;

  /* Compression streams for both incoming and outgoing data. */
  SshCompression compression_outgoing;
  SshCompression compression_incoming;
  
  /* Shared buffer for all types of compression.  This is always allocated,
     even if no compression is in use. */
  SshBuffer *compression_buffer;

  /* Statistics for compression. */
  /* XXX need 64 bit its here! */
  unsigned long compressed_incoming_bytes;
  unsigned long uncompressed_incoming_bytes;
  unsigned long compressed_outgoing_bytes;
  unsigned long uncompressed_outgoing_bytes;
  
  /* Copies of key exchange packets.  These are used in computing the session
     identifier (which, in turn, is used to check the integrity of the
     key exchange). */
  SshBuffer *client_kexinit_packet;
  SshBuffer *server_kexinit_packet;
  SshBuffer *client_kex1_packet;
  SshBuffer *server_kex1_packet;

  /* The unique session identifier for this session.  This is not changed
     even if keys are re-exchanged. */
  unsigned char session_identifier[SSH_MAX_HASH_DIGEST_LENGTH];
  size_t session_identifier_len;

  /* This is the validation hash computed from this particular key exchange.
     In the first exchange, this is the same as the session identifier. */
  unsigned char exchange_hash[SSH_MAX_HASH_DIGEST_LENGTH];
  size_t exchange_hash_len;

  /* Service name.  The name to send for client, the received name for
     server. */
  char *service_name;

  /* This is used by both server and client. */
  SshBuffer *public_host_key_blob;
  
  /* For client only. */
  SshPublicKey public_host_key;
  SshPublicKey public_server_key;
  char *server_host_name;
  SshKeyCheckCallback key_check;
  void *key_check_context;
  Boolean key_check_returned;
  Boolean key_check_result;

  /* For server only. */
  SshPrivateKey private_host_key;
  SshPrivateKey private_server_key;
  SshBuffer *public_server_key_blob;

  /* Compatibility with older ssh-2.0.x versions */

  /* MAC-bug, which is in versions ssh-2.0.9 and earlier (here our
     implementation was conflicting with the draft) */
  Boolean ssh_old_mac_bug_compat;
  
  /* For dh methods: the group, "secret" and the exchange buffer */

  mpz_t dh_p;
  mpz_t dh_g;
  mpz_t dh_e;
  mpz_t dh_f;
  mpz_t dh_k;
  mpz_t dh_secret;

} *SshTransportCommon;


/* Creates the SshTransportCommon object, and performs initializations that
   are common to client and server.  Initialization should continue with
   client or server specific initializations, and finally a call to
   ssh_tr_create_final. */
SshTransportCommon ssh_tr_create(SshStream connection, Boolean server,
                                 Boolean compatibility,
                                 Boolean fake_old_version,
                                 const char *application_version,
                                 SshRandomState random_state,
                                 SshTransportParams params);

/* Prepares the client side for key exchange. */
void ssh_tr_client_init_kex(SshTransportCommon tr,
                            const char *service_name,
                            const char *server_host_name,
                            SshKeyCheckCallback key_check,
                            void *key_check_context);

/* Prepares the server side for key exchange. */
void ssh_tr_server_init_kex(SshTransportCommon tr,
                            SshPrivateKey private_host_key,
                            SshPrivateKey private_server_key,
                            const unsigned char *public_host_key_blob,
                            size_t public_host_key_blob_len);

/* Finalizes the creation of the transport layer protocol.  Wraps it into
   a stream, and returns the stream.  The lower-level object should not
   be accessed after this call; the object will be automatically destroyed
   when the stream is destroyed. */
SshStream ssh_tr_create_final(SshTransportCommon tr);

/* Disconnects, and optionally sends a disconnect message to the other side. */
void ssh_tr_up_disconnect(SshTransportCommon tr, Boolean locally_generated,
                          Boolean send_to_other_side,
                          unsigned int reason, const char *fmt, ...);

/* Methods table for transport streams. */
extern const SshStreamMethodsTable ssh_tr_methods;

#endif /* TRCOMMON_H */
