/***************************************************************************
 *
 * Copyright (c) 2000 BalaBit IT Ltd, Budapest, Hungary
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: ftp.h,v 1.24.4.3 2001/09/04 09:49:00 bazsi Exp $
 *
 * Author:  Andras Kis-Szabo <kisza@sch.bme.hu>
 * Author:  Attila SZALAY <sasa@balabit.hu>
 * Auditor:
 * Notes:
 *
 ***************************************************************************/

#ifndef ZORP_MODULES_FTP_H_INCLUDED
#define ZORP_MODULES_FTP_H_INCLUDED

#include <zorp/proxy.h>
#include <zorp/readline.h>
#include <zorp/sockaddr.h>
#include <zorp/poll.h>
#include <zorp/dimhash.h>

#include "ftphash.h"
#include "ftpolicy.h"
#include "ftpmsg.h"

#define FTP_LINE_MAX_LEN  2048

#define FTP_DEBUG   "ftp.debug"
#define FTP_ERROR   "ftp.error"
#define FTP_REQUEST "ftp.request"
#define FTP_REPLY   "ftp.reply"
#define FTP_PPOLICY  "ftp.policy"

/* telnet processor states */
#define FTP_TELNET            (0)
#define FTP_TELNET_IAC        (1)
#define FTP_TELNET_IAC_DW     (2)
#define FTP_TELNET_IAC_FUNC   (3)

/* parser function return values */
#define FTP_REQ_ACCEPT  1   /* Allow command                               */
#define FTP_REQ_REJECT  3   /* Does'n allow, connection will remain        */
#define FTP_REQ_ABORT   4   /* Doesn't allow, connection will dropped      */
#define FTP_REQ_POLICY  6   /* Put the command up to policy                */

#define FTP_NOOP      101   /* Do nothing, but not alert.                  */
#define FTP_PROXY_ANS 102   /* In non-transparent mode, proxy is answering */

#define FTP_RSP_ACCEPT 1   /* Allow answer                                */
#define FTP_RSP_REJECT 3   /* Does'n allow, connection will remain        */
#define FTP_RSP_ABORT  4   /* Doesn't allow, connection will dropped      */
#define FTP_RSP_POLICY 6   /* Put the answer up to policy                 */

//
// FTP statemachine states
//
#define FTP_STATE_CONNECT             0
#define FTP_STATE_LOGIN               1
#define FTP_STATE_LOGIN_U             11
#define FTP_STATE_LOGIN_P             12
#define FTP_STATE_LOGIN_A             13
#define FTP_STATE_PRECONNECT          2
#define FTP_STATE_PRECONNECT_LOGIN    20
#define FTP_STATE_PRECONNECT_LOGIN_U  21
#define FTP_STATE_PRECONNECT_LOGIN_P  22
#define FTP_STATE_PRECONNECT_QUIT     23
#define FTP_STATE_LOGINAUTH           3
#define FTP_STATE_CONVERSATION        4
#define FTP_STATE_RENAME              5
#define FTP_STATE_DATA                6
#define FTP_STATE_QUIT                9

#define FTP_INIT_TRANSPARENT        0
#define FTP_INIT_NONTRANSPARENT     1
#define FTP_SERVER_TO_CLIENT        2
#define FTP_CLIENT_TO_SERVER        3
#define FTP_BOTH_SIDE               4
#define FTP_NT_CLIENT_TO_PROXY      5
#define FTP_NT_SERVER_TO_PROXY      6
#define FTP_QUIT                    7

#define FTP_DATA_SERVER_START       (0x01)
#define FTP_DATA_SERVER_READY       (0x02)
#define FTP_DATA_SERVER_SAID        (0x04)
#define FTP_DATA_CLIENT_START       (0x08)
#define FTP_DATA_CLIENT_READY       (0x10)

#define FTP_SERVER_FIRST_READY      (FTP_DATA_SERVER_START|FTP_DATA_SERVER_READY|FTP_DATA_SERVER_SAID)
#define FTP_SERVER_CONNECT_READY    (FTP_SERVER_FIRST_READY|FTP_DATA_CLIENT_START|FTP_DATA_CLIENT_READY)

#define FTP_SIDE_CLIENT             0
#define FTP_SIDE_SERVER             1

#define FTP_DATA_KEEP               0   // keep connection mode
#define FTP_DATA_PASSIVE            1   // convert to passive mode
#define FTP_DATA_ACTIVE             2   // convert to active mode

//
// Command groups
// 

typedef struct _FtpProxy
{
  ZProxy super;
  ZReadLine *readline[EP_MAX];
  
  int state;		/* I/O state in the proxy */
  int oldstate;         /* Where to go out from both side listening */
  int ftp_state;	/* our state in the FTP protocol */
  unsigned long data_state;	/* data connection state */
  ZPoll *poll;
  int wake_who;         /* What side woke up poll? */

  /* local permitted command & answer tables */
  GHashTable *policy_command_hash;
  ZDimHashTable *policy_answer_hash;
  
  /* command and answer buffer */
  gchar *line;          /* unparsed command */
  guint line_length;    /* length of line */
  guint max_line_length;

  /* command part */
//  gchar command[5];     /* command, NULL terminated */
  FtpInternalCommand *command_desc;
//  gchar *command_param;     /* parameter, NULL terminated */
  GString *request_cmd;
  GString *request_param;

  /* answer parts */
  guint answer_code;
  guint answer_handle;
  GString *answer_cmd;
  GString *answer_param;
  gboolean answer_cont;
  
  /* protocol state variables */
  GString *username;
  guint max_username_length;
  GString *password;
  guint max_password_length;

  gchar *hostname;      /* the name of the host to connect to in non-transparent mode */
  guint hostport;
  guint max_hostname_length;

  ZSockAddr *client_data;
  ZSockAddr *server_data;
  ZSockAddr *fw_client_data;
  ZSockAddr *fw_server_data;

  /* config variables accessible from Python */
  gboolean transparent_mode;
  gint data_mode;
  gboolean permit_empty_command;
  gboolean permit_unknown_command;

  gboolean response_strip_msg;

  /* Timeout in both client and server side */
  guint timeout;

  GString *target_port_range;
  
  /* Data connection protect */
  GMutex *lock;

} FtpProxy;  

#define MSG_USERNAME_FORMAT_INVALID     0
#define MSG_HOSTNAME_TOO_LONG           1
#define MSG_USER_ALREADY_LOGGED_IN      2
#define MSG_CONNECTION_ABORTED          3
#define MSG_NON_TRANSPARENT_GREETING    4
#define MSG_LINE_TOO_LONG               5
#define MSG_LINE_TERM_CRLF              6
#define MSG_USERNAME_TOO_LONG           7
#define MSG_USER_FIRST                  8
#define MSG_PASSWORD_TOO_LONG           9
#define MSG_USER_OKAY                  10
#define MSG_COMMAND_NOT_ALLOWED_HERE   11
#define MSG_INVALID_PARAMETER          12
#define MSG_GOODBYE                    13
#define MSG_MISSING_PARAMETER          14
#define MSG_COMMAND_NOT_IMPLEMENTED    15
#define MSG_COMMAND_NOT_RECOGNIZED     16
#define MSG_ANSWER_ERROR               17
#define MSG_ERROR_PARSING_PORT         18
#define MSG_ERROR_PARAMETER_PASV       19
#define MSG_ERROR_PARSING_PASV         20
#define MSG_ERROR_PARAMETER_PORT       21
#define MSG_PORT_SUCCESFULL            22
#define MSG_RNFR_RNTO                  23
#define MSG_ERROR_PARSING_COMMAND      24
#define MSG_TIMED_OUT                  25
extern Ftp_message ftp_know_messages[];

gboolean ftp_data_prepare(FtpProxy *self, gint side, gchar mode);
gboolean ftp_data_start(FtpProxy *self, gint side1, gint side2, gint way);
gboolean ftp_data_next_step(FtpProxy *self);
gboolean ftp_data_reset(FtpProxy *self);
/* static ZPolicyObj *ftp_data_wakeup(ZProxy *s, ZPolicyObj *args); */

void ftp_listen_both_side_start(FtpProxy *self);
void ftp_listen_both_side_stop(FtpProxy *self);


#define SET_ANSWER(answer) {\
	g_string_assign(self->answer_cmd, ftp_know_messages[answer].code);\
	g_string_assign(self->answer_param, ftp_know_messages[answer].long_desc); }

#endif
