/* $Id: ssh.h,v 1.28 1999/06/22 12:36:32 levitte Exp $ */
#ifndef __SSH_H__
#define __SSH_H__

#include <openssl/rsa.h>
#include <zlib.h>
#include "erf.h"
#include "user_info.h"
#include "userkey.h"
#include "buffer.h"

typedef enum {
    SSH_INTERNAL=-1,
    SSH_MSG_NONE=0, SSH_MSG_DISCONNECT, SSH_SMSG_PUBLIC_KEY,
    SSH_CMSG_SESSION_KEY, SSH_CMSG_USER, SSH_CMSG_AUTH_RHOSTS,
    SSH_CMSG_AUTH_RSA, SSH_SMSG_AUTH_RSA_CHALLENGE,
    SSH_CMSG_AUTH_RSA_RESPONSE, SSH_CMSG_AUTH_PASSWORD,
    SSH_CMSG_REQUEST_PTY, SSH_CMSG_WINDOW_SIZE, SSH_CMSG_EXEC_SHELL,
    SSH_CMSG_EXEC_CMD, SSH_SMSG_SUCCESS, SSH_SMSG_FAILURE,
    SSH_CMSG_STDIN_DATA, SSH_SMSG_STDOUT_DATA, SSH_SMSG_STDERR_DATA,
    SSH_CMSG_EOF, SSH_SMSG_EXITSTATUS,
    SSH_MSG_CHANNEL_OPEN_CONFIRMATION, SSH_MSG_CHANNEL_OPEN_FAILURE,
    SSH_MSG_CHANNEL_DATA, SSH_MSG_CHANNEL_CLOSE,
    SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, SSH_MSG_OBSOLETED0,
    SSH_SMSG_X11_OPEN, SSH_CMSG_PORT_FORWARD_REQUEST, SSH_MSG_PORT_OPEN,
    SSH_CMSG_AGENT_REQUEST_FORWARDING, SSH_SMSG_AGENT_OPEN,
    SSH_MSG_IGNORE, SSH_CMSG_EXIT_CONFIRMATION,
    SSH_CMSG_X11_REQUEST_FORWARDING, SSH_CMSG_AUTH_RHOSTS_RSA,
    SSH_MSG_DEBUG, SSH_CMSG_REQUEST_COMPRESSION,
    SSH_CMSG_MAX_PACKET_SIZE, SSH_CMSG_AUTH_TIS,
    SSH_SMSG_AUTH_TIS_CHALLENGE, SSH_CMSG_AUTH_TIS_RESPONSE,
    SSH_CMSG_AUTH_KERBEROS, SSH_SMSG_AUTH_KERBEROS_RESPONSE
} ssh_msg_type;

typedef enum {
    SSH_PHASE_NONE, SSH_PHASE_VERSION_WAIT, SSH_PHASE_GET_KEYS,
    SSH_PHASE_AUTH, SSH_PHASE_PREP, SSH_PHASE_PREP_NOTERM, SSH_PHASE_PREP_END,
    SSH_PHASE_INTERACTIVE
} ssh_phase;

typedef enum {
    SSH_CIPHER_NONE, SSH_CIPHER_IDEA, SSH_CIPHER_DES, SSH_CIPHER_3DES,
    SSH_CIPHER_TSS, SSH_CIPHER_RC4, SSH_CIPHER_BLOWFISH
} ssh_cipher_type;

typedef enum {
    SSH_AUTH_NONE, SSH_AUTH_RHOSTS, SSH_AUTH_RSA, SSH_AUTH_PASSWORD,
    SSH_AUTH_RHOSTS_RSA, SSH_AUTH_TIS, SSH_AUTH_KERBEROS,
    SSH_PASS_KERBEROS_TGT,
    SSH_PASS_AFS_TOKENS=21
} ssh_auth_type;

typedef enum {
    SSH_PREP_COMPRESSION, SSH_PREP_PTY, SSH_PREP_X11, SSH_PREP_PORT_FORWARD,
    SSH_PREP_AGENT_FORWARD, SSH_PREP_SHELL_OR_CMD
} ssh_prep_type;

typedef struct {
    enum { CONNECT, KEYGEN, KEYCHANGE } whattodo;

#define CH_COMMENT	0x00000001
#define CH_BITS		0x00000002
#define CH_CIPHER_TYPE	0x00000004
#define CH_PASSPHRASE	0x00000008
    unsigned int todo_flags;

    char *host;
    int port;
    char *username;
    char *password;
    char *commands;
    char *infile;
    char inmode;
    char *outfile;
    char outmode;
    unsigned char debug;
    unsigned long ciphers;
    unsigned long auths;
    struct user_info uai;
    char *default_directory;
    char *identity_file;
    unsigned char *ttymodes;
    int ttymodelen;
    unsigned char force_tty;
    unsigned char compress_p;

    /* This is extra stuff used for managing identities */
    char *comment;
    unsigned int bits;
    ssh_cipher_type cipher_type;
} ssh_prefs;

typedef struct ssh_state_s {
    /* Communication */
    long (*down_write)(unsigned char *buf, long len, void *writestate,
		       Erf,void*);
    void *down_state;
    void (*up_dispatch)(unsigned char *data, long len, void *dispatchstate,
			Erf,void*);
    void (*up_setconnid)(char *connid, void *state, Erf,void*);
    void *up_state;
    unsigned long dispatchsize;
    int dispatchpadamt;
    unsigned long dispatchread;
    unsigned char *dispatchpkt;
    int dispatchsizeread;
    unsigned char dispatchsizebuf[4];

    int infd, outfd;

    /* Preferenses */
    ssh_prefs *sshprefs;
    unsigned char compress;

    /* Phase state */
    ssh_phase protophase;
    ssh_auth_type authphase;
    ssh_prep_type prepphase;
    ssh_cipher_type used_cipher;

    /* Encryption/Decryption state */
    void (*encrypt)(unsigned char *in, unsigned char *out, long len,
			void *encryptstate);
    void *encryptstate;
    void (*decrypt)(unsigned char *in, unsigned char *out, long len,
			void *decryptstate);
    void *decryptstate;
    void (*cryptclean)(struct ssh_state_s *state);

    /* Terminal settings */
    char *term;
    int termrows, termcols, termx, termy;
    char *connid;

    /* Session */
    unsigned char sessid[16];
    unsigned char sesskey[32];

    /* Authentication */
    unsigned long auth_mask;
    /* RSA */
    struct userkey userkey;
#define TRIED_RSA	0x1
#define TRIED_PASSWD	0x2
#define TRIED_TIS	0x4
    char triedpw;

    char *info;
} ssh_state;

typedef struct ssh_iob {
    z_stream *zstream;
    char c_level;
} ssh_iob;

#define MAX_SSH_PACKET_LEN 4096

#define SSH_DEF_TERM "vt220"
#define SSH_DEF_TTYMODES (unsigned char *)"\x01\x03\x02\x1c\x03\x08\x04\x15\x05\x04"
#define SSH_DEF_TTYMODELEN 11

void *ssh_init(long (*down_write)(unsigned char *,long,void *,Erf,void*),
	       void *down_state, Erf,void*);
long ssh_write(void *data, long amt, void *state, Erf,void*);
void ssh_dispatch(unsigned char *data, long amt, void *state, Erf,void*);

void ssh_setterm(char *term, int rows, int cols, int x, int y, void *state,
		 Erf,void*);
void ssh_setconnid(char *connid, void *state, Erf,void*);

void ssh_initprefs(ssh_prefs *p);
void ssh_set_prefs(ssh_prefs *prefs, void *state, Erf erf, void* erfp);
void ssh_clearprefs(ssh_prefs *p);
void ssh_set_dispatch(void (*up_dispatch)(unsigned char *,long,void *,
					  Erf,void*),
		      void *up_state, void *state, Erf,void*);
void ssh_set_setconnid(void (*up_setconnid)(char *, void *, Erf,void*),
		       void *state, Erf,void*);

long ssh_write_type(ssh_msg_type type, general_buffer *data,
		    void *state_, Erf,void*);
int ssh_handle_packet_type(ssh_msg_type type, general_buffer_reader *inbuf, 
			   ssh_state *state, Erf,void*);
void ssh_crypto_setup(ssh_cipher_type cipher, ssh_state *state, int keylen,
		      Erf erf, void *efp);

void ssh_3des_encrypt(unsigned char *in, unsigned char *out, long len,
		      void *encryptstate);
void ssh_3des_decrypt(unsigned char *in, unsigned char *out, long len,
		      void *decryptstate);
void ssh_3des_clean(ssh_state *state);
void *ssh_3des_encryptstate(ssh_state *state, int keylen, Erf erf, void *erfp);
void *ssh_3des_decryptstate(ssh_state *state, int keylen, Erf erf, void *erfp);

void ssh_des_encrypt(unsigned char *in, unsigned char *out, long len,
		     void *encryptstate);
void ssh_des_decrypt(unsigned char *in, unsigned char *out, long len,
		     void *decryptstate);
void ssh_des_clean(ssh_state *state);
void *ssh_des_encryptstate(ssh_state *state, int keylen, Erf erf, void *erfp);
void *ssh_des_decryptstate(ssh_state *state, int keylen, Erf erf, void *erfp);

void ssh_idea_encrypt(unsigned char *in, unsigned char *out, long len,
		      void *encryptstate);
void ssh_idea_decrypt(unsigned char *in, unsigned char *out, long len,
		      void *decryptstate);
void ssh_idea_clean(ssh_state *state);
void *ssh_idea_encryptstate(ssh_state *state, int keylen, Erf erf, void *erfp);
void *ssh_idea_decryptstate(ssh_state *state, int keylen, Erf erf, void *erfp);

void ssh_rc4_encrypt(unsigned char *in, unsigned char *out, long len,
		     void *encryptstate);
void ssh_rc4_decrypt(unsigned char *in, unsigned char *out, long len,
		     void *decryptstate);
void ssh_rc4_clean(ssh_state *state);
void *ssh_rc4_encryptstate(ssh_state *state, int keylen, Erf erf, void *erfp);
void *ssh_rc4_decryptstate(ssh_state *state, int keylen, Erf erf, void *erfp);

void ssh_blowfish_encrypt(unsigned char *in, unsigned char *out, long len,
			  void *encryptstate);
void ssh_blowfish_decrypt(unsigned char *in, unsigned char *out, long len,
			  void *decryptstate);
void ssh_blowfish_clean(ssh_state *state);
void *ssh_blowfish_encryptstate(ssh_state *state, int keylen,
				Erf erf, void *erfp);
void *ssh_blowfish_decryptstate(ssh_state *state, int keylen,
				Erf erf, void *erfp);

void connected(ssh_state *state, Erf erf, void *erfp);

#endif

/* Emacs local variables

Local variables:
eval: (set-c-style "BSD")
end:

*/
