/*
   3APA3A simpliest proxy server
   (c) 2002 by ZARAZA <3APA3A@security.nnov.ru>

   please read License Agreement

   $Id: proxy.h,v 1.5 2003/11/29 10:58:30 vlad Exp $
*/

#ifndef _3PROXY_H_
#define _3PROXY_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/timeb.h>


#define MAXUSERNAME 128
#define _PASSWORD_LEN 256
#define MAXNSERVERS 5
#define MAXBANDLIMS 10

#define ALLOW		0
#define DENY		1
#define REDIRECT	2
#define BANDLIM		3
#define NOBANDLIM	4
#define COUNT		5
#define NOCOUNT		6

#define CLOSE close


#ifdef _WIN32
#include <io.h>
#include <winsock2.h>
#define SASIZETYPE int
#define SHUT_RDWR SD_BOTH
#else
#include <errno.h>
#include <signal.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <syslog.h>
#define SASIZETYPE socklen_t
#define SOCKET int
#define INVALID_SOCKET  (-1)
#endif

#ifdef __CYGWIN__
#include <windows.h>
#define daemonize() FreeConsole()
#define SLEEPTIME 1000
#undef _WIN32
#elif _WIN32
#ifdef errno
#undef errno
#endif
#define errno WSAGetLastError()
#define EAGAIN WSAEWOULDBLOCK
#define SLEEPTIME 1
#define usleep Sleep
#define pthread_self GetCurrentThreadId
#define getpid GetCurrentProcessId
#define pthread_t DWORD
#define daemonize() FreeConsole()
#define close closesocket
#define socket(x, y, z) WSASocket(x, y, z, NULL, 0, 0)
#define accept(x, y, z) WSAAccept(x, y, z, NULL, 0)
#define pthread_mutex_t CRITICAL_SECTION
#define pthread_mutex_init(x, y) InitializeCriticalSection(x)
#define pthread_mutex_lock(x) EnterCriticalSection(x)
#define pthread_mutex_unlock(x) LeaveCriticalSection(x)
#define pthread_mutex_destroy(x) DeleteCriticalSection(x)
#else
#include <pthread.h>
#define daemonize() {if(fork())return(0);setsid();usleep(SLEEPTIME);}
#define SLEEPTIME 1000
#ifndef O_BINARY
#define O_BINARY 0
#endif
#endif

#ifndef NOODBC
#include <sql.h>
#include <sqlext.h>
#endif


#ifndef SOCKET_ERROR
#define SOCKET_ERROR -1
#endif

#ifndef isnumber
#define isnumber(n) (n >= '0' && n <= '9')
#endif

#ifndef ishex
#define ishex(n) ((n >= '0' && n <= '9') || (n >= 'a' && n<='f') || (n <= 'A' && n <= 'F'))
#endif

#define isallowed(n) ((n >= '0' && n <= '9') || (n >= 'a' && n <= 'z') || (n >= 'A' && n <= 'Z') || (n >= '*' && n <= '/') || n == '_')

#ifdef _WIN32
extern int strnicmp( const char *string1, const char *string2, size_t count );
extern int stricmp( const char *string1, const char *string2 );
#define strcasecmp stricmp
#define strncasecmp strnicmp
#endif


typedef enum {
	S_NONE,
	S_PROXY,
	S_TCPPM,
	S_POP3P,
	S_SOCKS4 = 4,	/* =4 */
	S_SOCKS5 = 5,	/* =5 */
	S_UDPPM,
	S_SOCKS,
	S_SOCKS45,
	S_ADMIN
}PROXYSERVICE;

struct clientparam;
typedef void (*LOGFUNC)(struct clientparam * param, const unsigned char *);
typedef int (*AUTHFUNC)(struct clientparam * param);
typedef void * (*REDIRECTFUNC)(void *);
typedef unsigned long (*RESOLVFUNC)(const unsigned char *);
typedef unsigned (*BANDLIMFUNC)(struct clientparam * param, unsigned nbytes);
typedef void (*TRAFCOUNTFUNC)(struct clientparam * param);

extern RESOLVFUNC resolvfunc;

struct iplist {
	unsigned long ip;
	unsigned long mask;
	struct iplist *next;
};

struct portlist {
	unsigned short startport;
	unsigned short endport;
	struct portlist * next;
};

struct userlist {
	unsigned char * user;
	struct userlist * next;
};

typedef enum {
	SYS,
	CL,
	CR,
	NT,
	LM
}PWTYPE;

struct passwords {
	unsigned char * user;
	unsigned char * password;
	int pwtype;
	struct passwords *next;
};

typedef enum {
	R_TCP,
	R_CONNECT,
	R_SOCKS4,
	R_SOCKS5,
	R_HTTP,
} REDIRTYPE;

struct chain {
	int type;
	unsigned long redirip;
	unsigned short redirport;
	unsigned short weight;
	unsigned char * extuser;
	unsigned char * extpass;
	struct chain * next;
};

#define CONNECT 	0x00000001
#define BIND		0x00000002
#define UDPASSOC	0x00000004
#define ICMPASSOC	0x00000008	/* reserver */
#define HTTP_GET	0x00000100
#define HTTP_PUT	0x00000200
#define HTTP_POST	0x00000400
#define HTTP_HEAD	0x00000800
#define HTTP_CONNECT	0x00001000
#define HTTP_OTHER	0x00008000
#define HTTP		0x0000EF00	/* all except HTTP_CONNECT */
#define HTTPS		HTTP_CONNECT
#define FTP_GET		0x00010000
#define FTP_PUT		0x00020000
#define FTP_LIST	0x00040000
#define FTP		0x000F0000

struct ace {
	int action;
	int operation;
	struct userlist *users;
	struct iplist *src, *dst;
	struct portlist *ports;
	struct chain *chains;
	struct ace *next;
};

struct bandlim {
	struct ace *ace;
	long unsigned basetime;
	long unsigned rate;
	double nexttime;
	struct bandlim *next;
};

typedef enum {NONE, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, NEVER} ROTATION;

struct trafcount {
	struct ace *ace;
	unsigned number;
	ROTATION type;
	unsigned long traf;
	unsigned long trafgb;
	unsigned long traflim;
	unsigned long traflimgb;
	time_t cleared;
	time_t updated;
	char * comment;
	int disabled;
	struct trafcount *next;
};

extern struct bandlim * bandlimiter;	

struct clientparam {
	int demon;
	PROXYSERVICE service;
	LOGFUNC logfunc;
	AUTHFUNC authfunc;
	REDIRECTFUNC redirectfunc;
	BANDLIMFUNC bandlimfunc;
	TRAFCOUNTFUNC trafcountfunc;
	SOCKET srvsock;
	int * childcount;
	SOCKET clisock;
	SOCKET remsock;
	SOCKET ctrlsock;
	REDIRTYPE redirtype;
	int redirected;
	int operation;
	unsigned char * target;
	unsigned short targetport;
	fd_set * srvfds;
	unsigned long intip;
	unsigned long extip;
	unsigned short intport;
	unsigned short extport;
	struct ace *acl;
	struct passwords *pwl;
	unsigned char * hostname;
	unsigned char * username;
	unsigned char * password;
	unsigned char * extusername;
	unsigned char * extpassword;
	struct sockaddr_in sinc;
	struct sockaddr_in sins;
	int res;
	unsigned long statscli;
	unsigned long statssrv;
	int singlepacket;
	int waitclient;
	int waitserver;
	unsigned char * logformat;
	pthread_mutex_t * counter_mutex;
	struct bandlim * bandlims[MAXBANDLIMS];
};

struct extparam {
	int demon;
	int maxchild;
	unsigned long intip;
	unsigned long extip;
	unsigned short intport;
	unsigned short extport;
	int singlepacket;
	struct clientset *rules;
	struct ace *acl;
	struct passwords *pwl;
	AUTHFUNC authfunc;
	LOGFUNC logfunc;
	BANDLIMFUNC bandlimfunc;
	unsigned char * logformat;
};

typedef enum {
	UNKNOWN,
	INTTABLE,
	INTPAIRTABLE,
	STRINGTABLE,
	STRINGPAIRTABLE,
	STRINGREPLACETABLE,
	IPTABLE,
	IPRANGETABLE,
	ACLTABLE,
}TABLETYPE;

struct datatable {
	TABLETYPE type;
	int	n;
	void * data;
};

extern struct extparam conf;


int sockmap(struct clientparam * param, int timeo);
int sockgetchar(SOCKET sock, int timeosec, int timeousec);
int sockgetline(SOCKET sock, unsigned char * buf, int bufsize, int delim, int to);

int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s);
void logstdout(struct clientparam * param, const unsigned char *s);
void logsyslog(struct clientparam * param, const unsigned char *s);
void lognone(struct clientparam * param, const unsigned char *s);
#ifdef _WIN32
#ifndef NOSQL
void logsql(struct clientparam * param, const unsigned char *s);
int init_sql(char * s);
void close_sql();
#endif
#endif
int doconnect(struct clientparam * param);
int nbnameauth(struct clientparam * param);
int alwaysauth(struct clientparam * param);
int ipauth(struct clientparam * param);
int strongauth(struct clientparam * param);

int scanaddr(const unsigned char *s, unsigned long * ip, unsigned long * mask);
int myinet_ntoa(struct in_addr in, char * buf);
extern unsigned long nservers[MAXNSERVERS];
unsigned long getip(unsigned char *name);
unsigned long myresolver(const unsigned char *);
int inithashtable(unsigned nhashsize);
void hashadd(const unsigned char* name, unsigned long value, time_t expires);
void freeparam(struct clientparam * param);

int proxymain(int, char**);
int pop3pmain(int, char**);
int socksmain(int, char**);
int tcppmmain(int, char**);
int udppmmain(int, char**);
int adminmain(int, char**);

void * proxychild(void * data);

extern char* demanddialprog;

extern int paused;
extern int demon;

typedef enum {
	SINGLEBYTE_S,
	SINGLEBYTE_L,
	STRING_S,
	STRING_L,
	CONNECTION_S,
	CONNECTION_L,
	DNS_TO,
	CHAIN_TO
}TIMEOUT;

extern int timeouts[];

unsigned char * mycrypt(const unsigned char *key, const unsigned char *salt, unsigned char *buf);
unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword);
int de64 (const unsigned char *in, unsigned char *out, int maxlen);
unsigned char* en64 (const unsigned char *in, unsigned char *out, int inlen);

extern unsigned char **stringtable;

int ftplogin(struct clientparam *param);
int ftpcd(struct clientparam *param, unsigned char* path);
int ftpsyst(struct clientparam *param, unsigned char *buf, unsigned len);
int ftppwd(struct clientparam *param, unsigned char *buf, unsigned len);
int ftptype(struct clientparam *param, unsigned char* f_type);
int ftpres(struct clientparam *param);
SOCKET ftpcommand(struct clientparam *param, unsigned char * command, unsigned char  *arg);

extern char *copyright;


#define SERVICES 5


#endif
