diff options
Diffstat (limited to 'src')
122 files changed, 24004 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..f16461a --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,20 @@ +bin_PROGRAMS = afserver afclient +afserver_SOURCES = afserver.c network.c file.c stats.c buf_list_node_struct.c buf_list_struct.c \ + server_remoteadmin.c server_check.c server_set.c server_eval.c server_find.c \ + server_remove.c make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c \ + clientnames.c usernames.c http_proxy_functions.c http_proxy_server.c server_get.c \ + thread_management.c server_signals.c usage.c logging.c daemon.c ssl_fd_struct.c \ + user_stats_struct.c usr_cli_struct.c connect_user_struct.c string_functions.c \ + audit_list_node_struct.c audit_list_struct.c connect_client_struct.c timeval_functions.c \ + header_buffer_struct.c server_realm_struct.c server_configuration_struct.c file_server.c \ + task_struct.c task_list_node_struct.c task_scheduler_struct.c remove_client_task.c +afclient_LDFLAGS = ${USE_RDYNAMIC} ${LINKED_LDLIB} +afclient_SOURCES = afclient.c network.c file.c stats.c buf_list_node_struct.c buf_list_struct.c \ + module_struct.c client_remoteadmin.c make_ssl_handshake.c first_run.c inet_ntop.c \ + http_proxy_functions.c http_proxy_client.c http_proxy_options_struct.c \ + thread_management.c client_reverse_udp.c server_check.c client_initialization.c \ + client_shutdown.c client_signals.c usage.c logging.c daemon.c base64.c ssl_routines.c \ + connect_user_struct.c user_stats_struct.c string_functions.c ar_options_struct.c \ + audit_list_node_struct.c audit_list_struct.c ssl_fd_struct.c timeval_functions.c \ + usr_cli_struct.c header_buffer_struct.c client_configuration_struct.c file_client.c \ + client_realm_struct.c port_list_node_struct.c port_list_struct.c diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..23a517c --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,521 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +bin_PROGRAMS = afserver$(EXEEXT) afclient$(EXEEXT) +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_afclient_OBJECTS = afclient.$(OBJEXT) network.$(OBJEXT) \ + file.$(OBJEXT) stats.$(OBJEXT) buf_list_node_struct.$(OBJEXT) \ + buf_list_struct.$(OBJEXT) module_struct.$(OBJEXT) \ + client_remoteadmin.$(OBJEXT) make_ssl_handshake.$(OBJEXT) \ + first_run.$(OBJEXT) inet_ntop.$(OBJEXT) \ + http_proxy_functions.$(OBJEXT) http_proxy_client.$(OBJEXT) \ + http_proxy_options_struct.$(OBJEXT) \ + thread_management.$(OBJEXT) client_reverse_udp.$(OBJEXT) \ + server_check.$(OBJEXT) client_initialization.$(OBJEXT) \ + client_shutdown.$(OBJEXT) client_signals.$(OBJEXT) \ + usage.$(OBJEXT) logging.$(OBJEXT) daemon.$(OBJEXT) \ + base64.$(OBJEXT) ssl_routines.$(OBJEXT) \ + connect_user_struct.$(OBJEXT) user_stats_struct.$(OBJEXT) \ + string_functions.$(OBJEXT) ar_options_struct.$(OBJEXT) \ + audit_list_node_struct.$(OBJEXT) audit_list_struct.$(OBJEXT) \ + ssl_fd_struct.$(OBJEXT) timeval_functions.$(OBJEXT) \ + usr_cli_struct.$(OBJEXT) header_buffer_struct.$(OBJEXT) \ + client_configuration_struct.$(OBJEXT) file_client.$(OBJEXT) \ + client_realm_struct.$(OBJEXT) port_list_node_struct.$(OBJEXT) \ + port_list_struct.$(OBJEXT) +afclient_OBJECTS = $(am_afclient_OBJECTS) +afclient_LDADD = $(LDADD) +am_afserver_OBJECTS = afserver.$(OBJEXT) network.$(OBJEXT) \ + file.$(OBJEXT) stats.$(OBJEXT) buf_list_node_struct.$(OBJEXT) \ + buf_list_struct.$(OBJEXT) server_remoteadmin.$(OBJEXT) \ + server_check.$(OBJEXT) server_set.$(OBJEXT) \ + server_eval.$(OBJEXT) server_find.$(OBJEXT) \ + server_remove.$(OBJEXT) make_ssl_handshake.$(OBJEXT) \ + first_run.$(OBJEXT) inet_ntop.$(OBJEXT) realmnames.$(OBJEXT) \ + clientnames.$(OBJEXT) usernames.$(OBJEXT) \ + http_proxy_functions.$(OBJEXT) http_proxy_server.$(OBJEXT) \ + server_get.$(OBJEXT) thread_management.$(OBJEXT) \ + server_signals.$(OBJEXT) usage.$(OBJEXT) logging.$(OBJEXT) \ + daemon.$(OBJEXT) ssl_fd_struct.$(OBJEXT) \ + user_stats_struct.$(OBJEXT) usr_cli_struct.$(OBJEXT) \ + connect_user_struct.$(OBJEXT) string_functions.$(OBJEXT) \ + audit_list_node_struct.$(OBJEXT) audit_list_struct.$(OBJEXT) \ + connect_client_struct.$(OBJEXT) timeval_functions.$(OBJEXT) \ + header_buffer_struct.$(OBJEXT) server_realm_struct.$(OBJEXT) \ + server_configuration_struct.$(OBJEXT) file_server.$(OBJEXT) \ + task_struct.$(OBJEXT) task_list_node_struct.$(OBJEXT) \ + task_scheduler_struct.$(OBJEXT) remove_client_task.$(OBJEXT) +afserver_OBJECTS = $(am_afserver_OBJECTS) +afserver_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(afclient_SOURCES) $(afserver_SOURCES) +DIST_SOURCES = $(afclient_SOURCES) $(afserver_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +HAVE_OPENSSL = @HAVE_OPENSSL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LINKED_LDLIB = @LINKED_LDLIB@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_RDYNAMIC = @USE_RDYNAMIC@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +afserver_SOURCES = afserver.c network.c file.c stats.c buf_list_node_struct.c buf_list_struct.c \ + server_remoteadmin.c server_check.c server_set.c server_eval.c server_find.c \ + server_remove.c make_ssl_handshake.c first_run.c inet_ntop.c realmnames.c \ + clientnames.c usernames.c http_proxy_functions.c http_proxy_server.c server_get.c \ + thread_management.c server_signals.c usage.c logging.c daemon.c ssl_fd_struct.c \ + user_stats_struct.c usr_cli_struct.c connect_user_struct.c string_functions.c \ + audit_list_node_struct.c audit_list_struct.c connect_client_struct.c timeval_functions.c \ + header_buffer_struct.c server_realm_struct.c server_configuration_struct.c file_server.c \ + task_struct.c task_list_node_struct.c task_scheduler_struct.c remove_client_task.c + +afclient_LDFLAGS = ${USE_RDYNAMIC} ${LINKED_LDLIB} +afclient_SOURCES = afclient.c network.c file.c stats.c buf_list_node_struct.c buf_list_struct.c \ + module_struct.c client_remoteadmin.c make_ssl_handshake.c first_run.c inet_ntop.c \ + http_proxy_functions.c http_proxy_client.c http_proxy_options_struct.c \ + thread_management.c client_reverse_udp.c server_check.c client_initialization.c \ + client_shutdown.c client_signals.c usage.c logging.c daemon.c base64.c ssl_routines.c \ + connect_user_struct.c user_stats_struct.c string_functions.c ar_options_struct.c \ + audit_list_node_struct.c audit_list_struct.c ssl_fd_struct.c timeval_functions.c \ + usr_cli_struct.c header_buffer_struct.c client_configuration_struct.c file_client.c \ + client_realm_struct.c port_list_node_struct.c port_list_struct.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +afclient$(EXEEXT): $(afclient_OBJECTS) $(afclient_DEPENDENCIES) + @rm -f afclient$(EXEEXT) + $(LINK) $(afclient_LDFLAGS) $(afclient_OBJECTS) $(afclient_LDADD) $(LIBS) +afserver$(EXEEXT): $(afserver_OBJECTS) $(afserver_DEPENDENCIES) + @rm -f afserver$(EXEEXT) + $(LINK) $(afserver_LDFLAGS) $(afserver_OBJECTS) $(afserver_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afclient.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/afserver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ar_options_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit_list_node_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit_list_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buf_list_node_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buf_list_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_configuration_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_initialization.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_realm_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_remoteadmin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_reverse_udp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_shutdown.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_signals.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clientnames.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connect_client_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connect_user_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_client.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_server.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/first_run.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/header_buffer_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_proxy_client.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_proxy_functions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_proxy_options_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_proxy_server.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_ntop.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/make_ssl_handshake.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/module_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/port_list_node_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/port_list_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/realmnames.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remove_client_task.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_check.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_configuration_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_eval.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_find.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_get.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_realm_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_remoteadmin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_remove.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_set.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_signals.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl_fd_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ssl_routines.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_functions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_list_node_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_scheduler_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_management.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timeval_functions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/user_stats_struct.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usernames.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usr_cli_struct.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-binPROGRAMS uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/activefor.h b/src/activefor.h new file mode 100644 index 0000000..6a73c69 --- /dev/null +++ b/src/activefor.h @@ -0,0 +1,97 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_ACTIVEFOR_H +#define _JS_ACTIVEFOR_H + +#include "network.h" +#include "buf_list_struct.h" +#include "audit_list_struct.h" +#include "usr_cli_struct.h" +#include "connect_user_struct.h" +#include "ssl_fd_struct.h" +#include "connect_client_struct.h" + +#define AF_S_CONCLOSED 1 +#define AF_S_CONOPEN 2 +#define AF_S_MESSAGE 3 +#define AF_S_CLOSING 4 +#define AF_S_LOGIN 8 +#define AF_S_DONT_SEND 9 +#define AF_S_CAN_SEND 10 +#define AF_S_CANT_OPEN 12 +#define AF_S_ENABLE_MULTI 18 + +#define AF_S_WRONG 13 +#define AF_S_ADMIN_LOGIN 14 +#define AF_S_ADMIN_CMD 15 + +#define AF_S_KEEP_ALIVE 16 + +#define S_STATE_CLEAR 0 +#define S_STATE_CLOSING 5 +#define S_STATE_OPENING 6 +#define S_STATE_OPEN 7 +#define S_STATE_STOPPED 11 +#define S_STATE_OPENING_CLOSED 17 +#define S_STATE_KICKING 19 + +#define AF_VER(info) info" v0.8.4" + +#define TYPE_TCP 1 +#define TYPE_UDP 3 +#define TYPE_SSL 4 +#define TYPE_ZLIB 8 +#define TYPE_IPV4 16 +#define TYPE_IPV6 32 +#define TYPE_SUPPORTS_MULTI 64 +#define TYPE_COMP 0x4000 + +#define TYPE_SET_ZERO(type) (type=0) +#define TYPE_IS_SET(type) (type&1) +#define TYPE_IS_UDP(type) TYPE_IS_SET(type)&&(type&2) +#define TYPE_IS_TCP(type) TYPE_IS_SET(type)&&(!(type&2)) +#define TYPE_SET_UDP(type) (type|=TYPE_UDP) +#define TYPE_SET_TCP(type) (type|=TYPE_TCP) +#define TYPE_SET_SSL(type) (type|=TYPE_SSL) +#define TYPE_UNSET_SSL(type) (type&=(~TYPE_SSL)) +#define TYPE_IS_SSL(type) (type&TYPE_SSL) +#define TYPE_SET_ZLIB(type) (type|=TYPE_ZLIB) +#define TYPE_UNSET_ZLIB(type) (type&=(~TYPE_ZLIB)) +#define TYPE_IS_ZLIB(type) (type&TYPE_ZLIB) + +#define TYPE_SET_IPV4(type) (type|=TYPE_IPV4) +#define TYPE_UNSET_IPV4(type) (type&=(~TYPE_IPV4)) +#define TYPE_IS_IPV4(type) (type&TYPE_IPV4) +#define TYPE_SET_IPV6(type) (type|=TYPE_IPV6) +#define TYPE_UNSET_IPV6(type) (type&=(~TYPE_IPV6)) +#define TYPE_IS_IPV6(type) (type&TYPE_IPV6) +#define TYPE_SET_UNSPEC(type) (type&=(~(TYPE_IPV4|TYPE_IPV6))) +#define TYPE_IS_UNSPEC(type) (!(type&(TYPE_IPV4|TYPE_IPV6))) + +#define TYPE_SET_SUPPORTED_MULTI(type) (type|=TYPE_SUPPORTS_MULTI) +#define TYPE_UNSET_SUPPORTED_MULTI(type) (type&=(~TYPE_SUPPORTS_MULTI)) +#define TYPE_IS_SUPPORTED_MULTI(type) (type&TYPE_SUPPORTS_MULTI) + +#define TYPE_SET_COMP(type) (type|=TYPE_COMP) +#define TYPE_IS_COMP(type) (type&TYPE_COMP) + +#endif + diff --git a/src/afclient.c b/src/afclient.c new file mode 100644 index 0000000..fbafcc1 --- /dev/null +++ b/src/afclient.c @@ -0,0 +1,1500 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "afclient.h" + +static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"udpmode", 0, 0, 'u'}, + {"reverseudp", 0, 0, 'U'}, + {"servername", 1, 0, 'n'}, + {"manageport", 1, 0, 'm'}, + {"hostname", 1, 0, 'd'}, + {"portnum", 1, 0, 'p'}, + {"verbose", 0, 0, 'v'}, + {"keyfile", 1, 0, 'k'}, + {"cerfile", 1, 0, 'c'}, + {"storefile", 1, 0, 's'}, + {"cfgfile", 1, 0, 'f'}, + {"log", 1, 0, 'o'}, + {"pass", 1, 0, 301}, + {"ignorepkeys", 0, 0, 302}, +#ifdef AF_INET6 + {"ipv4", 0, 0, '4'}, + {"ipv6", 0, 0, '6'}, +#endif +#ifdef HAVE_LIBDL + {"load", 1, 0, 'l'}, + {"Load", 1, 0, 'L'}, +#endif + {"id", 1, 0, 'i'}, + {"dateformat", 1, 0, 'D'}, + {"remoteadmin", 0, 0, 'r'}, +#ifdef HAVE_LIBPTHREAD + {"use-https", 0, 0, 'S'}, + {"proxyname", 1, 0, 'P'}, + {"proxyport", 1, 0, 'X'}, + {"pa-t-basic", 0, 0, 'B'}, + {"pa-cred", 1, 0, 'C'}, +#endif + {"version", 0, 0, 'V'}, + {"keep-alive", 1, 0, 'K'}, + {"ar-tries", 1, 0, 'A'}, + {"ar-delay", 1, 0, 'T'}, + {"ar-start", 0, 0, 305}, + {"ar-quit", 0, 0, 306}, + {"noar", 0, 0, 307}, + {"localname", 1, 0, 311}, + {"localport", 1, 0, 312}, + {"localdesname", 1, 0, 313}, + {0, 0, 0, 0} +}; + +ClientConfiguration* cconfig; + +int +main(int argc, char **argv) +{ + + /* + * variables + */ + + int i, n, numofcon, length, buflength, temp, temp2 = 0; +#ifdef HAVE_LINUX_SOCKIOS_H + int notsent; + socklen_t aLength; +#endif + ConnectUser** usersTable = NULL; + unsigned char buff[9000]; + char hostname[100]; + int maxfdp1; + socklen_t addressLength; + struct sockaddr* clientAddress; + fd_set rset, allset, wset, tmpset; + struct timeval keepAlive; + char verbose = 0; + HttpProxyOptions* hpo = HttpProxyOptions_new(); + char hpoUsed = 0; + ArOptions* ao = ArOptions_new(); + ClientRealm* pointer; + char aoUsed = 0; + char passwordWasSet = 0; + char* realmId = NULL; + char* serverName = NULL; + char* managePort = NULL; + char* hostName = NULL; + PortList* destinationPorts = PortList_new(); + char* localName = NULL; + char* localPort = NULL; + char* localDestinationName = NULL; + char* keys = NULL; + char* certif = NULL; + char* store = NULL; + char* dateformat = NULL; + char* kaTimeout = NULL; + char* filenam = NULL; + char ipFamily = 0; + unsigned char password[4] = {1, 2, 3, 4}; + char udpMode = 0; + char reverseMode = 0; + char remoteMode = 0; + char realmType = 0; + char ignorePublicKeys = 0; + struct sigaction act; +#ifdef HAVE_LIBDL + Module *moduleA = Module_new(), *moduleB = Module_new(); +#endif + SSL_METHOD* method; + SSL_CTX* ctx = NULL; + + /* + * initialization + */ + +#ifdef HAVE_LIBPTHREAD + if (hpo == NULL) { + printf("Problems with memory allocation... exiting\n"); + exit(1); + } +#endif + + if (ao == NULL) { + printf("Problems with memory allocation... exiting\n"); + exit(1); + } + +#ifdef HAVE_LIBDL + if ((moduleA == NULL) || (moduleB == NULL)) { + printf("Problems with memory allocation... exiting\n"); + exit(1); + } +#endif + sigfillset(&(act.sa_mask)); + act.sa_flags = 0; + + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, NULL); + act.sa_handler = client_sig_int; + sigaction(SIGINT, &act, NULL); + sigaction(SIGTERM, &act, NULL); + act.sa_handler = client_sig_alrm; + sigaction(SIGALRM, &act, NULL); + +#ifdef HAVE_LIBPTHREAD + remember_mainthread(); +#endif + +#ifdef AF_INET6 +#define GETOPT_LONG_AF_INET6(x) "46"x +#else +#define GETOPT_LONG_AF_INET6(x) x +#endif +#ifdef HAVE_LIBPTHREAD +#define GETOPT_LONG_LIBPTHREAD(x) "SP:X:BC:"x +#else +#define GETOPT_LONG_LIBPTHREAD(x) x +#endif +#ifdef HAVE_LIBDL +#define GETOPT_LONG_LIBDL(x) "l:L:"x +#else +#define GETOPT_LONG_LIBDL(x) x +#endif + + while ((n = getopt_long(argc, argv, + GETOPT_LONG_LIBDL(GETOPT_LONG_LIBPTHREAD( + GETOPT_LONG_AF_INET6("huUn:m:d:p:vk:c:s:o:i:D:rP:X:VK:A:T:f:"))) + , long_options, 0)) != -1) { + switch (n) { + case 'h': { + client_long_usage(AF_VER("Active port forwarder (client)")); + break; + } + case 'n': { + serverName = optarg; + break; + } +#ifdef HAVE_LIBPTHREAD + case 'S': { + HttpProxyOptions_use_https(hpo); + hpoUsed = 1; + break; + } + case 'P': { + HttpProxyOptions_set_proxyname(hpo, optarg); + hpoUsed = 1; + break; + } + case 'X': { + HttpProxyOptions_set_proxyport(hpo, optarg); + hpoUsed = 1; + break; + } + case 'B': { + HttpProxyOptions_set_proxyauth_type(hpo, PROXYAUTH_TYPE_BASIC); + hpoUsed = 1; + break; + } + case 'C': { + HttpProxyOptions_set_proxyauth_cred(hpo, optarg); + hpoUsed = 1; + break; + } +#endif + case 'i': { + realmId = optarg; + break; + } + case 'm': { + managePort = optarg; + break; + } + case 'd': { + hostName = optarg; + break; + } + case 'p': { + PortList_insert_back(destinationPorts, PortListNode_new(optarg)); + break; + } + case 'v': { + ++verbose; + break; + } + case 'u': { + udpMode = 1; + break; + } + case 'U': { + reverseMode = 1; + break; + } + case 'k': { + keys = optarg; + break; + } + case 'c': { + certif = optarg; + break; + } + case 's': { + store = optarg; + break; + } + case 'f': { + filenam = optarg; + break; + } + case 'o': { + addlogtarget(optarg); + break; + } + case 301: { + n = strlen(optarg); + memset(password, 0, 4); + for (i = 0; i < n; ++i) { + password[i%4] += optarg[i]; + } + passwordWasSet = 1; + break; + } + case 302: { + ignorePublicKeys = 1; + break; + } + case 305: { + ArOptions_set_arStart(ao, AR_OPTION_ENABLED); + aoUsed = 1; + break; + } + case 306: { + ArOptions_set_arQuit(ao, AR_OPTION_ENABLED); + aoUsed = 1; + break; + } + case 307: { + ArOptions_set_arPremature(ao, AR_OPTION_DISABLED); + aoUsed = 1; + break; + } + case 311: { + localName = optarg; + break; + } + case 312: { + localPort = optarg; + break; + } + case 313: { + localDestinationName = optarg; + break; + } +#ifdef AF_INET6 + case '4': { + if (ipFamily != 0) { + ipFamily = -1; + } + else { + ipFamily = 4; + } + break; + } + case '6': { + if (ipFamily != 0) { + ipFamily = -1; + } + else { + ipFamily = 6; + } + break; + } +#endif +#ifdef HAVE_LIBDL + case 'l': { + Module_set_fileName(moduleA, optarg); + break; + } + case 'L': { + Module_set_fileName(moduleB, optarg); + break; + } +#endif + case 'D': { + dateformat = optarg; + break; + } + case 'r': { + remoteMode = 1; + break; + } + case 'V': { + printf("%s\n", (AF_VER("Active port forwarder (client)"))); + exit(0); + break; + } + case 'K': { + kaTimeout = optarg; + break; + } + case 'A': { + ArOptions_set_s_arTries(ao, optarg); + aoUsed = 1; + break; + } + case 'T': { + ArOptions_set_s_arDelay(ao, optarg); + aoUsed = 1; + break; + } + case '?': { + client_short_usage(""); + break; + } + } + } + + if (optind < argc) { + client_short_usage("Unrecognized non-option elements"); + } + + if (filenam != NULL) { + cconfig = cparsefile(filenam, &n); + if (n) { + printf("parsing failed! line:%d\n", n); + exit(1); + } + else { + if (keys == NULL) { + if (ClientConfiguration_get_keysFile(cconfig) == NULL) { + ClientConfiguration_set_keysFile(cconfig, "client.rsa"); + } + } + else { + ClientConfiguration_set_keysFile(cconfig, keys); + } + if (certif != NULL) { + ClientConfiguration_set_certificateFile(cconfig, certif); + } + if (store == NULL) { + if (ClientConfiguration_get_storeFile(cconfig) == NULL) { + ClientConfiguration_set_storeFile(cconfig, "known_hosts"); + } + } + else { + ClientConfiguration_set_storeFile(cconfig, store); + } + if (dateformat != NULL) { + ClientConfiguration_set_dateFormat(cconfig, dateformat); + } + if (ignorePublicKeys) { + ClientConfiguration_set_ignorePublicKeys(cconfig, ignorePublicKeys); + } + + initializelogging(verbose, ClientConfiguration_get_dateFormat(cconfig)); + + aflog(LOG_T_INIT, LOG_I_INFO, + "client's cfg file OK! (readed realms: %d)", ClientConfiguration_get_realmsNumber(cconfig)); + if ((ClientConfiguration_get_realmsNumber(cconfig) == 0) || + (ClientConfiguration_get_realmsTable(cconfig) == NULL) || + ((pointer = ClientConfiguration_get_realmsTable(cconfig)[0]) == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Working without sense is really without sense..."); + exit(1); + } + if (hpoUsed) { + ClientRealm_set_httpProxyOptions(pointer, hpo); + } + else { + HttpProxyOptions_free(&hpo); + } + if (aoUsed) { + ClientRealm_set_arOptions(pointer, ao); + } + else { + ArOptions_free(&ao); + } + if ((serverName != NULL) && (ClientRealm_get_serverName(pointer) == NULL)) { + ClientRealm_set_serverName(pointer, serverName); + } + if ((managePort != NULL) && (ClientRealm_get_managePort(pointer) == NULL)) { + ClientRealm_set_managePort(pointer, managePort); + } + if ((hostName != NULL) && (ClientRealm_get_hostName(pointer) == NULL)) { + ClientRealm_set_hostName(pointer, hostName); + } + if ((PortList_get_size(destinationPorts) != 0) && + (PortList_get_size(ClientRealm_get_destinationPorts(pointer)) == 0)) { + ClientRealm_set_destinationPorts(pointer, destinationPorts); + } + if ((realmId != NULL) && (ClientRealm_get_realmId(pointer) == NULL)) { + ClientRealm_set_realmId(pointer, realmId); + } + if ((localName != NULL) && (ClientRealm_get_localName(pointer) == NULL)) { + ClientRealm_set_localName(pointer, localName); + } + if ((localPort != NULL) && (ClientRealm_get_localPort(pointer) == NULL)) { + ClientRealm_set_localPort(pointer, localPort); + } + if ((localDestinationName != NULL) & (ClientRealm_get_localDestinationName(pointer) == NULL)) { + ClientRealm_set_localDestinationName(pointer, localDestinationName); + } + if ((kaTimeout != NULL) && (ClientRealm_get_sKeepAliveTimeout(pointer) == NULL)) { + ClientRealm_set_sKeepAliveTimeout(pointer, kaTimeout); + } + if (reverseMode) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: reverseudp will be ignored"); + } + if (udpMode) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: udpmode will be ignored"); + } + if (remoteMode) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: remoteadmin will be ignored"); + } + if (passwordWasSet) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: pass will be ignored"); + } +#ifdef HAVE_LIBDL + if (Module_get_fileName(moduleA)) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: load will be ignored"); + } + if (Module_get_fileName(moduleB)) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: Load will be ignored"); + } +#endif + } + } + else { + cconfig = ClientConfiguration_new(); + if (cconfig == NULL) { + printf("Can't allocate memory for client configuration... exiting\n"); + exit(1); + } + ClientConfiguration_set_keysFile(cconfig, keys); + ClientConfiguration_set_certificateFile(cconfig, certif); + ClientConfiguration_set_storeFile(cconfig, store); + ClientConfiguration_set_dateFormat(cconfig, dateformat); + ClientConfiguration_set_realmsNumber(cconfig, 1); + ClientConfiguration_set_ignorePublicKeys(cconfig, ignorePublicKeys); + + initializelogging(verbose, ClientConfiguration_get_dateFormat(cconfig)); + + if (ClientConfiguration_get_keysFile(cconfig) == NULL) { + ClientConfiguration_set_keysFile(cconfig, "client.rsa"); + } + if (ClientConfiguration_get_storeFile(cconfig) == NULL) { + ClientConfiguration_set_storeFile(cconfig, "known_hosts"); + } + ClientConfiguration_set_realmsTable(cconfig, + calloc(ClientConfiguration_get_realmsNumber(cconfig), sizeof(ClientRealm*))); + if (ClientConfiguration_get_realmsTable(cconfig) == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Can't allocate memory for ClientRealm* table... exiting"); + exit(1); + } + pointer = ClientRealm_new(); + if (pointer == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Can't allocate memory for ClientRealm structure... exiting"); + exit(1); + } + + ClientConfiguration_get_realmsTable(cconfig)[0] = pointer; + ClientRealm_set_serverName(pointer, serverName); + ClientRealm_set_managePort(pointer, managePort); + ClientRealm_set_hostName(pointer, hostName); + ClientRealm_set_destinationPorts(pointer, destinationPorts); + ClientRealm_set_realmId(pointer, realmId); + ClientRealm_set_httpProxyOptions(pointer, hpo); + ClientRealm_set_arOptions(pointer, ao); + ClientRealm_set_password(pointer, password); + ClientRealm_set_localName(pointer, localName); + ClientRealm_set_localPort(pointer, localPort); + ClientRealm_set_localDestinationName(pointer, localDestinationName); + ClientRealm_set_realmId(pointer, realmId); + ClientRealm_set_sKeepAliveTimeout(pointer, kaTimeout); +#ifdef HAVE_LIBDL + ClientRealm_set_userModule(pointer, moduleA); + ClientRealm_set_serviceModule(pointer, moduleB); +#endif + + if (reverseMode) { + if (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_TCP) { + ClientRealm_set_clientMode(pointer, CLIENTREALM_MODE_REVERSE); + } + else { + ClientRealm_set_clientMode(pointer, CLIENTREALM_MODE_UNKNOWN); + } + } + if (udpMode) { + if (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_TCP) { + ClientRealm_set_clientMode(pointer, CLIENTREALM_MODE_UDP); + } + else { + ClientRealm_set_clientMode(pointer, CLIENTREALM_MODE_UNKNOWN); + } + } + if (remoteMode) { + if (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_TCP) { + ClientRealm_set_clientMode(pointer, CLIENTREALM_MODE_REMOTE); + } + else { + ClientRealm_set_clientMode(pointer, CLIENTREALM_MODE_UNKNOWN); + } + } + } + + /* + * WARNING: we have only one ClientRealm at the moment + */ + + if (ClientRealm_get_serverName(pointer) == NULL) { + client_short_usage("Name of the server is required"); + } + if (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_UNKNOWN) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Conflicting/unknown client modes... exiting"); + exit(1); + } + if (ClientRealm_get_managePort(pointer) == NULL) { + ClientRealm_set_managePort(pointer, "50126"); + if (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_REVERSE) + client_short_usage("Port on the server is required in reverse mode"); + } +#ifdef HAVE_LIBPTHREAD + if ((HttpProxyOptions_get_proxyname(ClientRealm_get_httpProxyOptions(pointer))) || + (HttpProxyOptions_get_proxyport(ClientRealm_get_httpProxyOptions(pointer)))) { + if (ClientRealm_get_tunnelType(pointer) == CLIENTREALM_TUNNELTYPE_DIRECT) { + ClientRealm_set_tunnelType(pointer, CLIENTREALM_TUNNELTYPE_HTTPPROXY); + } + else { + ClientRealm_set_tunnelType(pointer, CLIENTREALM_TUNNELTYPE_UNKNOWN); + } + } + if (ClientRealm_get_tunnelType(pointer) == CLIENTREALM_TUNNELTYPE_HTTPPROXY) { + if (HttpProxyOptions_get_proxyport(ClientRealm_get_httpProxyOptions(pointer)) == NULL) { + HttpProxyOptions_set_proxyport(ClientRealm_get_httpProxyOptions(pointer), "8080"); + } + } +#endif + if ((ClientRealm_get_clientMode(pointer) != CLIENTREALM_MODE_REVERSE) && + (ClientRealm_get_clientMode(pointer) != CLIENTREALM_MODE_REMOTE) && + (ClientRealm_get_hostName(pointer) == NULL)) { + gethostname(hostname, 100); + ClientRealm_set_hostName(pointer, hostname); + } + if ((ClientRealm_get_clientMode(pointer) != CLIENTREALM_MODE_REMOTE) && + (PortList_get_size(ClientRealm_get_destinationPorts(pointer)) == 0)) { + client_short_usage("Destination port number is required"); + } + + if (ClientRealm_get_sKeepAliveTimeout(pointer)) { + ClientRealm_set_keepAliveTimeout(pointer, + check_value(ClientRealm_get_sKeepAliveTimeout(pointer), "Invalid timeout value")); + keepAlive.tv_sec = ClientRealm_get_keepAliveTimeout(pointer); + keepAlive.tv_usec = 0; + ClientRealm_set_keepAlive(pointer, keepAlive); + } + ArOptions_evaluate_values(ClientRealm_get_arOptions(pointer)); + + if (ignorePublicKeys) { + ClientConfiguration_set_ignorePublicKeys(cconfig, ignorePublicKeys); + } + +#ifdef HAVE_LIBDL + if (Module_loadModule(ClientRealm_get_userModule(pointer))) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Loading a module %s failed!", Module_get_fileName(ClientRealm_get_userModule(pointer))); + exit(1); + } + if (Module_loadModule(ClientRealm_get_serviceModule(pointer))) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Loading a module %s failed!", Module_get_fileName(ClientRealm_get_serviceModule(pointer))); + exit(1); + } +#endif + + TYPE_SET_ZERO(realmType); + TYPE_SET_SSL(realmType); + TYPE_SET_ZLIB(realmType); + +#ifdef AF_INET6 + if ((ipFamily != 0) && (ClientRealm_get_ipFamily(pointer) <= 0)) { + ClientRealm_set_ipFamily(pointer, ipFamily); + } + if (ClientRealm_get_ipFamily(pointer) == -1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Conflicting types of ip protocol family... exiting"); + exit(1); + } + else if (ClientRealm_get_ipFamily(pointer) == 4) { + TYPE_SET_IPV4(realmType); + } + else if (ClientRealm_get_ipFamily(pointer) == 6) { + TYPE_SET_IPV6(realmType); + } +#endif + ipFamily = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(realmType)) { + ipFamily |= 0x02; + } + else if (TYPE_IS_IPV6(realmType)) { + ipFamily |= 0x04; + } +#endif + + ClientRealm_set_ipFamily(pointer, ipFamily); + ClientRealm_set_realmType(pointer, realmType); + + if (ClientRealm_get_clientMode(pointer) != CLIENTREALM_MODE_REVERSE) { + SSL_library_init(); + method = SSLv3_client_method(); + ctx = SSL_CTX_new(method); + if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting cipher list failed... exiting"); + exit(1); + } + if ((temp2 = create_apf_dir(0))) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: Creating ~/.apf directory failed (%d)", temp2); + if ((temp2 = create_apf_dir(1))) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: Creating ./apf directory failed (%d)", temp2); + } + } + store = ClientConfiguration_get_storeFile(cconfig); + if ((temp2 = create_publickey_store(&store))) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: Something bad happened when creating public key store... (%d)", temp2); + } + ClientConfiguration_set_storeFile(cconfig, store); + keys = ClientConfiguration_get_keysFile(cconfig); + if ((temp2 = generate_rsa_key(&keys))) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: Something bad happened when generating rsa keys... (%d)", temp2); + } + ClientConfiguration_set_keysFile(cconfig, keys); + if (SSL_CTX_use_RSAPrivateKey_file(ctx, keys, SSL_FILETYPE_PEM) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting rsa key failed (%s)... exiting", keys); + exit(1); + } + + certif = ClientConfiguration_get_certificateFile(cconfig); + if (certif) { + if (SSL_CTX_use_certificate_file(ctx, certif, SSL_FILETYPE_PEM) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting certificate failed (%s)... exiting", certif); + exit(1); + } + } + + if ((ClientRealm_get_clientMode(pointer) != CLIENTREALM_MODE_REMOTE) && + (!verbose)) + daemon(0, 0); + + if (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_REMOTE) { + temp2 = -1; + if (PortList_get_size(ClientRealm_get_destinationPorts(pointer)) > 0) { + if (ip_listen(&n, ClientRealm_get_serverName(pointer), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(pointer), 0)), + &addressLength, + ClientRealm_get_ipFamily(pointer))) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_listen_%s error for %s, %s", + (ClientRealm_get_ipFamily(pointer) & 0x02) ? + "ipv4" : + (ClientRealm_get_ipFamily(pointer) & 0x04) ? + "ipv6" : + "unspec", + ClientRealm_get_serverName(pointer), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(pointer), 0))); +#else + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_listen error for %s, %s", ClientRealm_get_serverName(pointer), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(pointer), 0))); +#endif + exit(1); + } + clientAddress = malloc(addressLength); + if (clientAddress == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Can't allocate memory for sockaddr structure... exiting"); + exit(1); + } + ClientRealm_set_addressLength(pointer, addressLength); + ClientRealm_set_clientAddress(pointer, clientAddress); + temp2 = accept(n, ClientRealm_get_clientAddress(pointer), &addressLength); + } + } + + } + + i = ArOptions_get_arTries(ClientRealm_get_arOptions(pointer)); + SslFd_set_fd(ClientRealm_get_masterSslFd(pointer), -1); + + do { + temp = 0; + if (SslFd_get_fd(ClientRealm_get_masterSslFd(pointer)) != -1) { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(pointer))); + } + ClientRealm_closeUsersConnections(pointer); + SslFd_set_ssl(ClientRealm_get_masterSslFd(pointer), NULL); + + if (ClientRealm_get_clientMode(pointer) != CLIENTREALM_MODE_REVERSE) { + if (temp == 0) { + if (initialize_client_stage1(pointer, ctx, buff, + (ArOptions_get_arStart(ClientRealm_get_arOptions(pointer)) == AR_OPTION_ENABLED) ? 0 : 1, + ClientConfiguration_get_ignorePublicKeys(cconfig))) { + temp = 1; + } + } + + if ((temp == 0) && (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_REMOTE)) { + return client_admin(ClientRealm_get_realmType(pointer), + ClientRealm_get_masterSslFd(pointer), buff, temp2, + ClientRealm_get_realmId(pointer)); + } + + if (temp == 0) { + realmType = ClientRealm_get_realmType(pointer); + if (initialize_client_stage2(pointer, buff, + (ArOptions_get_arStart(ClientRealm_get_arOptions(pointer)) == AR_OPTION_ENABLED) ? 0 : 1)) { + temp = 1; + } + } + } /* !reverse */ + else { + if (initialize_client_reverse_udp(pointer)) { + temp = 1; + } + } + + if (temp == 0) { + if (initialize_client_stage3(pointer, &buflength, &allset, &wset, &maxfdp1, + (ArOptions_get_arStart(ClientRealm_get_arOptions(pointer)) == AR_OPTION_ENABLED) ? 0 : 1)) { + temp = 1; + } + } + + /* UDP REVERSE MODE */ + + if ((temp == 0) && (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_REVERSE)) { + client_reverse_udp(pointer, buff, buflength); + } + + if (i > 0) { + --i; + } + if ((i != 0) && (temp == 1)) { + aflog(LOG_T_INIT, LOG_I_INFO, + "Trying to reconnect..."); + mysleep(ArOptions_get_arDelay(ClientRealm_get_arOptions(pointer))); + ClientRealm_set_realmType(pointer, realmType); + } + if (temp == 0) { + break; + } + } while (i); + + /* NORMAL MODE */ + + aflog(LOG_T_CLIENT, LOG_I_INFO, + "CLIENT STARTED mode: %s", (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_UDP) ? "udp" : "tcp"); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "SERVER SSL: %s, ZLIB: %s, MODE: %s", (TYPE_IS_SSL(ClientRealm_get_realmType(pointer))) ? "yes" : "no", + (TYPE_IS_ZLIB(ClientRealm_get_realmType(pointer))) ? "yes" : "no", + (TYPE_IS_TCP(ClientRealm_get_realmType(pointer))) ? "tcp" : "udp"); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "SERVER MULTI: %s", (TYPE_IS_SUPPORTED_MULTI(ClientRealm_get_realmType(pointer))) ? "yes" : "no"); + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "CIPHER: %s VER: %s", SSL_get_cipher_name(SslFd_get_ssl(ClientRealm_get_masterSslFd(pointer))), + SSL_get_cipher_version(SslFd_get_ssl(ClientRealm_get_masterSslFd(pointer)))); +#ifdef HAVE_LIBDL + if (Module_isModuleLoaded(ClientRealm_get_userModule(pointer))) { + aflog(LOG_T_CLIENT, LOG_I_INFO, + "LOADED MODULE: %s INFO: %s", Module_get_fileName(ClientRealm_get_userModule(pointer)), + Module_function_info(ClientRealm_get_userModule(pointer))); + } + if (Module_isModuleLoaded(ClientRealm_get_serviceModule(pointer))) { + aflog(LOG_T_CLIENT, LOG_I_INFO, + "LOADED MODULE (ser): %s INFO: %s", Module_get_fileName(ClientRealm_get_serviceModule(pointer)), + Module_function_info(ClientRealm_get_serviceModule(pointer))); + } +#endif + + ClientRealm_send_realmId(pointer, buff); + ClientRealm_enable_multi(pointer); + + for ( ; ; ) { + rset = allset; + tmpset = wset; + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "select"); + if (ClientRealm_get_sKeepAliveTimeout(pointer)) { + if (select(maxfdp1, &rset, &tmpset, NULL, ClientRealm_get_keepAlivePointer(pointer)) == 0) { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "timeout: sending keep-alive packet"); + buff[0] = AF_S_KEEP_ALIVE; + SslFd_send_message(ClientRealm_get_realmType(pointer), + ClientRealm_get_masterSslFd(pointer), buff, 5); + keepAlive.tv_sec = ClientRealm_get_keepAliveTimeout(pointer); + keepAlive.tv_usec = 0; + ClientRealm_set_keepAlive(pointer, keepAlive); + } + } + else { + select(maxfdp1, &rset, &tmpset, NULL, NULL); + } + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "after select..."); + + usersTable = ClientRealm_get_usersTable(pointer); + for (i = 0; i < ClientRealm_get_usersLimit(pointer); ++i) { + if ((ConnectUser_get_state(usersTable[i]) == S_STATE_OPEN) || + (ConnectUser_get_state(usersTable[i]) == S_STATE_STOPPED) || + (ConnectUser_get_state(usersTable[i]) == S_STATE_KICKING)) { + if (FD_ISSET(ConnectUser_get_connFd(usersTable[i]), &rset)) { /* FD_ISSET CONTABLE[i].CONNFD RSET */ + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: FD_ISSET", i); + n = read(ConnectUser_get_connFd(usersTable[i]), &buff[5], 8091); + if (n == -1) { + if (errno == EAGAIN) { + continue; + } + aflog(LOG_T_USER, LOG_I_ERR, + "error (%d): while reading from service", errno); + n = 0; + } +#ifdef HAVE_LINUX_SOCKIOS_H +# ifdef SIOCOUTQ + if (ioctl(SslFd_get_fd(ClientRealm_get_masterSslFd(pointer)), SIOCOUTQ, ¬sent)) { + aflog(LOG_T_USER, LOG_I_CRIT, + "ioctl error -> exiting..."); + exit(1); + } + if (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_UDP) { + aLength = 4; + if (getsockopt(SslFd_get_fd(ClientRealm_get_masterSslFd(pointer)), + SOL_SOCKET, SO_SNDBUF, &temp2, &aLength) != -1) { + if (temp2 != buflength) { + buflength = temp2; + aflog(LOG_T_USER, LOG_I_WARNING, + "Send buffer size changed..."); + } + } + if (buflength <= notsent + n + 5) { /* when we can't send this */ + aflog(LOG_T_USER, LOG_I_WARNING, + "user[%d]: DROP size:%d, buf:%d, w:%d/%d", i, n+5, buflength, notsent, buflength); +# else + if (ioctl(master.commfd, TIOCOUTQ, ¬sent)) { + aflog(LOG_T_USER, LOG_I_CRIT, + "ioctl error -> exiting..."); + exit(1); + } + if (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_UDP) { + len = 4; + if (getsockopt(master.commfd, SOL_SOCKET, SO_SNDBUF, &temp2, &len) != -1) { + if (temp2 != buflength) { + buflength = temp2; + aflog(LOG_T_USER, LOG_I_WARNING, + "Send buffer size changed..."); + } + } + if (notsent <= n + 5) { /* when we can't send this */ + aflog(LOG_T_USER, LOG_I_WARNING, + "user[%d]: DROP size:%d, buf:%d, w:%d/%d", + i, n+5, buflength, buflength-notsent, buflength); +# endif + continue; /* drop this packet */ + } + } +#endif + if (n) { +#ifdef HAVE_LIBDL + if (Module_isModuleLoaded(ClientRealm_get_serviceModule(pointer))) { + switch ((temp2 = Module_function_filter(ClientRealm_get_serviceModule(pointer), + ConnectUser_get_nameBuf(usersTable[i]), &buff[5], &n))) { + case 1: case 4: { + aflog(LOG_T_USER, LOG_I_WARNING, + "user[%d] (by ser): PACKET IGNORED BY MODULE", i); + if (temp2 == 4) { + aflog(LOG_T_MAIN, LOG_I_INFO, + "RELEASED MODULE (ser): %s INFO: %s", + Module_get_fileName(ClientRealm_get_serviceModule(pointer)), + Module_function_info(ClientRealm_get_serviceModule(pointer))); + Module_releaseModule(ClientRealm_get_serviceModule(pointer)); + } + continue; + break; + } + case 2: case 5: { + aflog(LOG_T_USER, LOG_I_NOTICE, + "user[%d] (by ser): DROPPED BY MODULE", i); + close(ConnectUser_get_connFd(usersTable[i])); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: Closing connFd: %d", i, ConnectUser_get_connFd(usersTable[i])); + FD_CLR(ConnectUser_get_connFd(usersTable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(usersTable[i]), &wset); + ConnectUser_set_state(usersTable[i], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(usersTable[i])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + if (temp2 == 5) { + aflog(LOG_T_MAIN, LOG_I_INFO, + "RELEASED MODULE (ser): %s INFO: %s", + Module_get_fileName(ClientRealm_get_serviceModule(pointer)), + Module_function_info(ClientRealm_get_serviceModule(pointer))); + Module_releaseModule(ClientRealm_get_serviceModule(pointer)); + } + continue; + break; + } + case 3: { + aflog(LOG_T_MAIN, LOG_I_INFO, + "RELEASED MODULE (ser): %s INFO: %s", + Module_get_fileName(ClientRealm_get_serviceModule(pointer)), + Module_function_info(ClientRealm_get_serviceModule(pointer))); + Module_releaseModule(ClientRealm_get_serviceModule(pointer)); + break; + } + } + } +#endif + buff[0] = AF_S_MESSAGE; /* sending message */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ +#ifdef HAVE_LINUX_SOCKIOS_H + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: TO msglen: %d [%d/%d]", i, n, +# ifdef SIOCOUTQ + notsent +# else + buflength - notsent +# endif + , buflength); +#else + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: TO msglen: %d", i, n); +#endif + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, n+5); + } + else if (ClientRealm_get_clientMode(pointer) != CLIENTREALM_MODE_UDP) { + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: CLOSING", i); + close(ConnectUser_get_connFd(usersTable[i])); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: Closing connFd: %d", i, ConnectUser_get_connFd(usersTable[i])); + FD_CLR(ConnectUser_get_connFd(usersTable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(usersTable[i]), &wset); + if (ConnectUser_get_state(usersTable[i]) == S_STATE_KICKING) { + ConnectUser_set_state(usersTable[i], S_STATE_CLEAR); + } + else { + ConnectUser_set_state(usersTable[i], S_STATE_CLOSING); + } + BufList_clear(ConnectUser_get_bufList(usersTable[i])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + } + } /* - FD_ISSET CONTABLE[i].CONNFD RSET */ + } + } + for (i = 0; i < ClientRealm_get_usersLimit(pointer); ++i) { + if ((ConnectUser_get_state(usersTable[i]) == S_STATE_STOPPED) || + (ConnectUser_get_state(usersTable[i]) == S_STATE_KICKING)) { + if (FD_ISSET(ConnectUser_get_connFd(usersTable[i]), &tmpset)) { /* FD_ISSET CONTABLE[i].CONNFD TMPSET */ + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: FD_ISSET - WRITE", i); + n = BufListNode_readMessageLength(BufList_get_first(ConnectUser_get_bufList(usersTable[i]))); + temp2 = write(ConnectUser_get_connFd(usersTable[i]), + BufListNode_readMessage(BufList_get_first(ConnectUser_get_bufList(usersTable[i]))), n); + if ((temp2 > 0) && (temp2 != n)) { + BufListNode_set_actPtr(BufList_get_first(ConnectUser_get_bufList(usersTable[i])), + BufListNode_get_actPtr(BufList_get_first(ConnectUser_get_bufList(usersTable[i]))) + temp2); + } + else if ((temp2 == -1) && (errno == EAGAIN)) { + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: Couldn't write?", i); + } + else if (temp2 == -1) { + close(ConnectUser_get_connFd(usersTable[i])); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: Closing connFd: %d", i, ConnectUser_get_connFd(usersTable[i])); + FD_CLR(ConnectUser_get_connFd(usersTable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(usersTable[i]), &wset); + if (ConnectUser_get_state(usersTable[i]) == S_STATE_KICKING) { + ConnectUser_set_state(usersTable[i], S_STATE_CLEAR); + } + else { + ConnectUser_set_state(usersTable[i], S_STATE_CLOSING); + } + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), + ClientRealm_get_masterSslFd(pointer), buff, 5); + } + else { + BufList_delete_first(ConnectUser_get_bufList(usersTable[i])); + if (BufList_get_first(ConnectUser_get_bufList(usersTable[i])) == NULL) { + FD_CLR(ConnectUser_get_connFd(usersTable[i]), &wset); + buff[0] = AF_S_CAN_SEND; /* stopping transfer */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + aflog(LOG_T_USER, LOG_I_DDEBUG, + "FROM user[%d]: BUFFERING MESSAGE ENDED", i); + SslFd_send_message(ClientRealm_get_realmType(pointer), + ClientRealm_get_masterSslFd(pointer), buff, 5); + if (ConnectUser_get_state(usersTable[i]) == S_STATE_KICKING) { + close(ConnectUser_get_connFd(usersTable[i])); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: Closing connFd: %d", i, ConnectUser_get_connFd(usersTable[i])); + FD_CLR(ConnectUser_get_connFd(usersTable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(usersTable[i]), &wset); + ConnectUser_set_state(usersTable[i], S_STATE_CLEAR); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), + ClientRealm_get_masterSslFd(pointer), buff, 5); + } + else { + ConnectUser_set_state(usersTable[i], S_STATE_OPEN); + } + } + } + } /* - FD_ISSET CONTABLE[i].CONNFD TMPSET */ + } + } + if (FD_ISSET(SslFd_get_fd(ClientRealm_get_masterSslFd(pointer)), &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "masterfd: FD_ISSET"); + n = SslFd_get_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + if (n != 5) { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "FATAL ERROR! (%d)", n); + if (n == -1) { + if (TYPE_IS_SSL(ClientRealm_get_realmType(pointer))) { + get_ssl_error(ClientRealm_get_masterSslFd(pointer), "FE", n); + continue; /* what happened? */ + } + } + if (n != 0) + exit(1); + } + if (n == 0) { /* server quits -> we do the same... */ + i = ArOptions_get_arTries(ClientRealm_get_arOptions(pointer)); + if (ArOptions_get_arPremature(ClientRealm_get_arOptions(pointer)) == AR_OPTION_DISABLED) { + i = 0; + } + if (i) { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "SERVER: premature quit -> auto-reconnect enabled"); + } + while (i) { + ClientRealm_closeUsersConnections(pointer); + close(SslFd_get_fd(ClientRealm_get_masterSslFd(pointer))); + SslFd_set_ssl(ClientRealm_get_masterSslFd(pointer), NULL); + mysleep(ArOptions_get_arDelay(ClientRealm_get_arOptions(pointer))); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Trying to reconnect..."); + + temp2 = 0; + if (temp2 == 0) { + if (initialize_client_stage1(pointer, ctx, buff, 0, + ClientConfiguration_get_ignorePublicKeys(cconfig))) { + temp2 = 1; + } + } + if (temp2 == 0) { + if (initialize_client_stage2(pointer, buff, 0)) { + temp2 = 1; + } + } + if (temp2 == 0) { + if (initialize_client_stage3(pointer, &buflength, &allset, &wset, &maxfdp1, 0)) { + temp2 = 1; + } + } + + if (temp2 == 0) { + n = 1; + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Reconnected successfully..."); + usersTable = ClientRealm_get_usersTable(pointer); + + ClientRealm_send_realmId(pointer, buff); + ClientRealm_enable_multi(pointer); + + break; + } + + if (i > 0) { + --i; + } + } + if (n == 0) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "SERVER: premature quit -> exiting..."); + exit(1); + } + continue; + } + numofcon = buff[1]; + numofcon = numofcon << 8; + numofcon += buff[2]; /* this is id of user */ + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + switch (buff[0]) { + case AF_S_CONCLOSED : { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: AF_S_CONCLOSED", numofcon); + if ((numofcon>=0) && (numofcon<=ClientRealm_get_usersLimit(pointer))) { + if (ConnectUser_get_state(usersTable[numofcon]) == S_STATE_CLOSING) { + ConnectUser_set_state(usersTable[numofcon], S_STATE_CLEAR); + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: CLOSE CONFIRMED", numofcon); + } + else if (ConnectUser_get_state(usersTable[numofcon]) == S_STATE_OPEN) { + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: CLOSED", numofcon); + close(ConnectUser_get_connFd(usersTable[numofcon])); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: Closing connFd: %d", numofcon, ConnectUser_get_connFd(usersTable[numofcon])); + FD_CLR(ConnectUser_get_connFd(usersTable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(usersTable[numofcon]), &wset); + ConnectUser_set_state(usersTable[numofcon], S_STATE_CLEAR); + BufList_clear(ConnectUser_get_bufList(usersTable[numofcon])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + } + else if (ConnectUser_get_state(usersTable[numofcon]) == S_STATE_STOPPED) { + ConnectUser_set_state(usersTable[numofcon], S_STATE_KICKING); + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: CLOSING...", numofcon); + } + } + break; + } + case AF_S_CONOPEN : { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: AF_S_CONOPEN", numofcon); + if ((numofcon>=0) && (numofcon<=ClientRealm_get_usersLimit(pointer))) { + if (ConnectUser_get_state(usersTable[numofcon]) == S_STATE_CLEAR) { + n = SslFd_get_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, length); + ConnectUser_set_nameBuf(usersTable[numofcon], (char*) buff); + ConnectUser_set_portBuf(usersTable[numofcon], (char*) &buff[128]); + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: OPENING", numofcon); + aflog(LOG_T_USER, LOG_I_INFO, + "user[%d]: IP:%s PORT:%s", numofcon, + ConnectUser_get_nameBuf(usersTable[numofcon]), ConnectUser_get_portBuf(usersTable[numofcon])); +#ifdef HAVE_LIBDL + if (Module_isModuleLoaded(ClientRealm_get_userModule(pointer)) && + Module_function_allow(ClientRealm_get_userModule(pointer), + ConnectUser_get_nameBuf(usersTable[numofcon]), + ConnectUser_get_portBuf(usersTable[numofcon]))) { + aflog(LOG_T_USER, LOG_I_WARNING, + "user[%d]: IT'S NOT ALLOWED - DROPPING", numofcon); + buff[0] = AF_S_CANT_OPEN; /* not opening connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + continue; + } +#endif + if (ClientRealm_get_clientMode(pointer) == CLIENTREALM_MODE_UDP) { + ipFamily = 0; + } + else { + ipFamily = 0x01; + } +#ifdef AF_INET6 + if (TYPE_IS_IPV4(ClientRealm_get_realmType(pointer))) { + ipFamily |= 0x02; + } + else if (TYPE_IS_IPV6(ClientRealm_get_realmType(pointer))) { + ipFamily |= 0x04; + } +#endif + temp2 = 0; + if (n == 136) { + if (PortList_get_size(ClientRealm_get_destinationPorts(pointer)) == 1) { + temp2 = 0; + } + else { + temp2 = buff[135] % PortList_get_size(ClientRealm_get_destinationPorts(pointer)); + } + } + if (ip_connect(&temp, ClientRealm_get_hostName(pointer), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(pointer), temp2)), ipFamily, + ClientRealm_get_localDestinationName(pointer), NULL)) { + aflog(LOG_T_USER, LOG_I_WARNING, + "user[%d]: CAN'T CONNECT to %s:%s - DROPPING", numofcon, + ClientRealm_get_hostName(pointer), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(pointer), temp2))); + buff[0] = AF_S_CANT_OPEN; /* not opening connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + continue; + } + ConnectUser_set_connFd(usersTable[numofcon], temp); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: Setting connFd: %d", numofcon, temp); + temp2 = fcntl(ConnectUser_get_connFd(usersTable[numofcon]), F_GETFL, 0); + fcntl(ConnectUser_get_connFd(usersTable[numofcon]), F_SETFL, temp2 | O_NONBLOCK); + FD_SET(ConnectUser_get_connFd(usersTable[numofcon]), &allset); + maxfdp1 = (maxfdp1 > (ConnectUser_get_connFd(usersTable[numofcon]) + 1)) ? + maxfdp1 : (ConnectUser_get_connFd(usersTable[numofcon]) + 1); + buff[0] = AF_S_CONOPEN; /* opening connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + ConnectUser_set_state(usersTable[numofcon], S_STATE_OPEN); + } + } + break; + } + case AF_S_MESSAGE : { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: AF_S_MESSAGE", numofcon); + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: FROM msglen: %d", numofcon, length); + n = SslFd_get_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, length); + if ((numofcon>=0) && (numofcon<=ClientRealm_get_usersLimit(pointer))) { + if (ConnectUser_get_state(usersTable[numofcon]) == S_STATE_OPEN) { +#ifdef HAVE_LIBDL + if (Module_isModuleLoaded(ClientRealm_get_userModule(pointer))) { + switch ((temp2 = Module_function_filter(ClientRealm_get_userModule(pointer), + ConnectUser_get_nameBuf(usersTable[numofcon]), buff, &n))) { + case 1: case 4:{ + aflog(LOG_T_USER, LOG_I_WARNING, + "user[%d]: PACKET IGNORED BY MODULE", numofcon); + if (temp2 == 4) { + aflog(LOG_T_MAIN, LOG_I_INFO, + "RELEASED MODULE: %s INFO: %s", + Module_get_fileName(ClientRealm_get_userModule(pointer)), + Module_function_info(ClientRealm_get_userModule(pointer))); + Module_releaseModule(ClientRealm_get_userModule(pointer)); + } + continue; + break; + } + case 2: case 5:{ + aflog(LOG_T_USER, LOG_I_NOTICE, + "user[%d]: DROPPED BY MODULE", numofcon); + close(ConnectUser_get_connFd(usersTable[numofcon])); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: Closing connFd: %d", numofcon, ConnectUser_get_connFd(usersTable[numofcon])); + FD_CLR(ConnectUser_get_connFd(usersTable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(usersTable[numofcon]), &wset); + ConnectUser_set_state(usersTable[numofcon], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(usersTable[numofcon])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + if (temp2 == 5) { + aflog(LOG_T_MAIN, LOG_I_INFO, + "RELEASED MODULE: %s INFO: %s", + Module_get_fileName(ClientRealm_get_userModule(pointer)), + Module_function_info(ClientRealm_get_userModule(pointer))); + Module_releaseModule(ClientRealm_get_userModule(pointer)); + } + continue; + break; + } + case 3: { + aflog(LOG_T_MAIN, LOG_I_INFO, + "RELEASED MODULE: %s INFO: %s", + Module_get_fileName(ClientRealm_get_userModule(pointer)), + Module_function_info(ClientRealm_get_userModule(pointer))); + Module_releaseModule(ClientRealm_get_userModule(pointer)); + break; + } + } + } +#endif + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: FROM msglen: %d SENT", numofcon, n); + temp2 = write(ConnectUser_get_connFd(usersTable[numofcon]), buff, n); + if ((temp2 > 0) && (temp2 != n)) { + BufList_insert_back(ConnectUser_get_bufList(usersTable[numofcon]), + BufListNode_new_message(temp2, n, buff)); + ConnectUser_set_state(usersTable[numofcon], S_STATE_STOPPED); + FD_SET(ConnectUser_get_connFd(usersTable[numofcon]), &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(LOG_T_USER, LOG_I_DDEBUG, + "FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + } + else if ((temp2 == -1) && (errno == EAGAIN)) { + BufList_insert_back(ConnectUser_get_bufList(usersTable[numofcon]), + BufListNode_new_message(0, n, buff)); + ConnectUser_set_state(usersTable[numofcon], S_STATE_STOPPED); + FD_SET(ConnectUser_get_connFd(usersTable[numofcon]), &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + aflog(LOG_T_USER, LOG_I_DDEBUG, + "FROM user[%d]: BUFFERING MESSAGE STARTED", numofcon); + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + } + else if (temp2 == -1) { + close(ConnectUser_get_connFd(usersTable[numofcon])); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "user[%d]: Closing connFd: %d", numofcon, ConnectUser_get_connFd(usersTable[numofcon])); + FD_CLR(ConnectUser_get_connFd(usersTable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(usersTable[numofcon]), &wset); + ConnectUser_set_state(usersTable[numofcon], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(usersTable[numofcon])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = numofcon >> 8; /* high bits of user number */ + buff[2] = numofcon; /* low bits of user number */ + SslFd_send_message(ClientRealm_get_realmType(pointer), ClientRealm_get_masterSslFd(pointer), buff, 5); + } + } + else if (ConnectUser_get_state(usersTable[numofcon]) == S_STATE_STOPPED) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "FROM user[%d]: BUFFERING MESSAGE", numofcon); + BufList_insert_back(ConnectUser_get_bufList(usersTable[numofcon]), + BufListNode_new_message(0, n, buff)); + } + } + break; + } + case AF_S_CLOSING : { /* server shut down */ + n = 0; + i = ArOptions_get_arTries(ClientRealm_get_arOptions(pointer)); + if (ArOptions_get_arQuit(ClientRealm_get_arOptions(pointer)) == AR_OPTION_DISABLED) { + i = 0; + } + if (i) { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "SERVER: CLOSED -> auto-reconnect enabled"); + } + while (i) { + ClientRealm_closeUsersConnections(pointer); + close(SslFd_get_fd(ClientRealm_get_masterSslFd(pointer))); + SslFd_set_ssl(ClientRealm_get_masterSslFd(pointer), NULL); + mysleep(ArOptions_get_arDelay(ClientRealm_get_arOptions(pointer))); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Trying to reconnect..."); + + temp2 = 0; + if (temp2 == 0) { + if (initialize_client_stage1(pointer, ctx, buff, 0, + ClientConfiguration_get_ignorePublicKeys(cconfig))) { + temp2 = 1; + } + } + if (temp2 == 0) { + if (initialize_client_stage2(pointer, buff, 0)) { + temp2 = 1; + } + } + if (temp2 == 0) { + if (initialize_client_stage3(pointer, &buflength, &allset, &wset, &maxfdp1, 0)) { + temp2 = 1; + } + } + + if (temp2 == 0) { + n = 1; + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Reconnected successfully..."); + usersTable = ClientRealm_get_usersTable(pointer); + + ClientRealm_send_realmId(pointer, buff); + ClientRealm_enable_multi(pointer); + + break; + } + + if (i > 0) { + --i; + } + } + if (n == 0) { + aflog(LOG_T_CLIENT, LOG_I_INFO, + "SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); + exit(1); + } + break; + } + case AF_S_DONT_SEND: { + if ((ConnectUser_get_state(usersTable[numofcon]) == S_STATE_OPEN) || + (ConnectUser_get_state(usersTable[numofcon]) == S_STATE_STOPPED)) { + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: AF_S_DONT_SEND", numofcon); + FD_CLR(ConnectUser_get_connFd(usersTable[numofcon]), &allset); + } + else { + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: AF_S_DONT_SEND - ignored", numofcon); + } + break; + } + case AF_S_CAN_SEND: { + if ((ConnectUser_get_state(usersTable[numofcon]) == S_STATE_OPEN) || + (ConnectUser_get_state(usersTable[numofcon]) == S_STATE_STOPPED)) { + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: AF_S_CAN_SEND", numofcon); + FD_SET(ConnectUser_get_connFd(usersTable[numofcon]), &allset); + } + else { + aflog(LOG_T_USER, LOG_I_DEBUG, + "user[%d]: AF_S_CAN_SEND - ignored", numofcon); + } + break; + } + default : { /* unrecognized type of message -> exiting... */ + aflog(LOG_T_CLIENT, LOG_I_ERR, + "SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); + exit(1); + break; + } + } + } /* - FD_ISSET MASTER.COMMFD RSET */ + } +} diff --git a/src/afclient.h b/src/afclient.h new file mode 100644 index 0000000..1be222d --- /dev/null +++ b/src/afclient.h @@ -0,0 +1,63 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "network.h" +#include "file.h" +#include "stats.h" +#include "module_struct.h" +#include "client_remoteadmin.h" +#include "make_ssl_handshake.h" +#include "first_run.h" +#include "http_proxy_client.h" +#include "thread_management.h" +#include "client_reverse_udp.h" +#include "server_check.h" +#include "client_initialization.h" +#include "http_proxy_functions.h" +#include "http_proxy_options_struct.h" +#include "client_shutdown.h" +#include "client_signals.h" +#include "usage.h" +#include "logging.h" +#include "audit_list_struct.h" +#include "daemon.h" +#include "ar_options_struct.h" +#include "port_list_struct.h" + +#include <openssl/rsa.h> +#include <openssl/ssl.h> +#include <openssl/err.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#ifdef HAVE_LINUX_SOCKIOS_H +#include <linux/sockios.h> +#endif +#include <signal.h> +#include <string.h> +#include <fcntl.h> + +#include <getopt.h> + +#ifndef _JS_AFCLIENT_H +#define _JS_AFCLIENT_H + +#endif + diff --git a/src/afserver.c b/src/afserver.c new file mode 100644 index 0000000..f509404 --- /dev/null +++ b/src/afserver.c @@ -0,0 +1,2617 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "afserver.h" + +static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"hostname", 1, 0, 'n'}, + {"listenport", 1, 0, 'l'}, + {"manageport", 1, 0, 'm'}, + {"timeout", 1, 0, 't'}, + {"maxidle", 1, 0, 321}, + {"verbose", 0, 0, 'v'}, + {"users", 1, 0, 'u'}, + {"clients", 1, 0, 'C'}, + {"realm", 1, 0, 'r'}, + {"raclients", 1, 0, 'R'}, + {"usrpcli", 1, 0, 'U'}, + {"climode", 1, 0, 'M'}, + {"cerfile", 1, 0, 'c'}, + {"cacerfile", 1, 0, 'A'}, + {"cerdepth", 1, 0, 'd'}, + {"keyfile", 1, 0, 'k'}, + {"cfgfile", 1, 0, 'f'}, + {"proto", 1, 0, 'p'}, + {"log", 1, 0, 'o'}, + {"audit", 0, 0, 'a'}, + {"nossl", 0, 0, 301}, + {"nozlib", 0, 0, 302}, + {"pass", 1, 0, 303}, +#ifdef AF_INET6 + {"ipv4", 0, 0, '4'}, + {"ipv6", 0, 0, '6'}, +#endif + {"baseport", 0, 0, 'b'}, + {"dnslookups", 0, 0, 311}, + {"dateformat", 1, 0, 'D'}, +#ifdef HAVE_LIBPTHREAD + {"enableproxy", 0, 0, 'P'}, + /* FIXME: don't need it now + {"use-https", 0, 0, 'S'}, + */ +#endif + {"version", 0, 0, 'V'}, + {0, 0, 0, 0} +}; + +ServerConfiguration* config; + +int +main(int argc, char **argv) +{ + int i, j=0, k, l, n, flags, sent = 0, temp; + socklen_t len; + unsigned char buff[9000]; + int maxfdp1; + fd_set rset, allset, wset, tmpset; + int numofcon, length; + char* name = NULL; + char** listen = NULL; + int listencount = 0; + char** manage = NULL; + int managecount = 0; + char* amount = NULL; + char* clients = NULL; + char* raclients = NULL; + char* usrpcli = NULL; + char* clim = NULL; + char* filenam = NULL; + char* type = NULL; + char* timeout = NULL; + char* maxidle = NULL; + char* realmname = NULL; + unsigned char pass[4] = {1, 2, 3, 4}; + char verbose = 0; + char mode = 0; +#ifdef HAVE_LIBPTHREAD + char tunneltype = 0; +#endif + char ipfam = 0; + char baseport = 0; + char audit = 0; + char dnslookups = 0; + ServerRealm* pointer = NULL; + TaskScheduler* scheduler; + Task* task; + struct sigaction act; + time_t now; + ServerRealm** scRealmsTable; + UsrCli** srUsersClientsTable; + ConnectUser** srUsersTable; + ConnectClient** srClientsTable; + ConnectClient** srRaClientsTable; + + char* certif = NULL; + char* cacertif = NULL; + char* cerdepth = NULL; + char* keys = NULL; + char* dateformat = NULL; + static char* stemp = NULL; + + SSL_METHOD* method; + SSL_CTX* ctx; + SSL* tmp_ssl; + + sigfillset(&(act.sa_mask)); + act.sa_flags = 0; + + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, NULL); + act.sa_handler = server_sig_int; + sigaction(SIGINT, &act, NULL); + sigaction(SIGTERM, &act, NULL); + + TYPE_SET_SSL(mode); + TYPE_SET_ZLIB(mode); + TYPE_SET_SUPPORTED_MULTI(mode); + +#ifdef HAVE_LIBPTHREAD + remember_mainthread(); +#endif + +#ifdef AF_INET6 +#define GETOPT_LONG_AF_INET6(x) "46"x +#else +#define GETOPT_LONG_AF_INET6(x) x +#endif +#ifdef HAVE_LIBPTHREAD +/* FIXME: 'S' option is not needed now +#define GETOPT_LONG_LIBPTHREAD(x) "PS"x +*/ +#define GETOPT_LONG_LIBPTHREAD(x) "P"x +#else +#define GETOPT_LONG_LIBPTHREAD(x) x +#endif + + while ((n = getopt_long(argc, argv, + GETOPT_LONG_LIBPTHREAD(GETOPT_LONG_AF_INET6("hn:l:m:vu:c:A:d:k:f:p:o:t:C:U:M:abD:R:r:V")) + , long_options, 0)) != -1) { + switch (n) { + case 'h': { + server_long_usage(AF_VER("Active port forwarder (server)")); + break; + } + case 'n': { + name = optarg; + break; + } + case 'l': { + ++listencount; + listen = realloc(listen, sizeof(char*)); + listen[listencount-1] = optarg; + break; + } + case 'm': { + ++managecount; + manage = realloc(manage, sizeof(char*)); + manage[managecount-1] = optarg; + break; + } + case 't': { + timeout = optarg; + break; + } + case 321: { + maxidle = optarg; + break; + } + case 'v': { + ++verbose; + break; + } + case 'u': { + amount = optarg; + break; + } + case 'C': { + clients = optarg; + break; + } + case 'r': { + realmname = optarg; + break; + } + case 'R': { + raclients = optarg; + break; + } + case 'U': { + usrpcli = optarg; + break; + } + case 'M': { + clim = optarg; + break; + } + case 'c': { + certif = optarg; + break; + } + case 'A': { + cacertif = optarg; + break; + } + case 'd': { + cerdepth = optarg; + break; + } + case 'k': { + keys = optarg; + break; + } + case 'p': { + type = optarg; + break; + } + case 'f': { + filenam = optarg; + break; + } + case 'o': { + addlogtarget(optarg); + break; + } + case 301: { + TYPE_UNSET_SSL(mode); + break; + } + case 302: { + TYPE_UNSET_ZLIB(mode); + break; + } + case 303: { + n = strlen(optarg); + memset(pass, 0, 4); + for (i = 0; i < n; ++i) { + pass[i%4] += optarg[i]; + } + sent = 1; + break; + } +#ifdef AF_INET6 + case '4': { + if (ipfam != 0) { + ipfam = -1; + } + else { + ipfam = 4; + } + break; + } + case '6': { + if (ipfam != 0) { + ipfam = -1; + } + else { + ipfam = 6; + } + break; + } +#endif + case 'b': { + baseport = 1; + break; + } + case 'a': { + audit = 1; + break; + } + case 311: { + dnslookups = 1; + break; + } + case 'D': { + dateformat = optarg; + break; + } +#ifdef HAVE_LIBPTHREAD + case 'P': { + if ((tunneltype < 0) || (tunneltype > 2)) { + tunneltype = -1; + } + else { + if (tunneltype != 2) { + tunneltype = 1; + } + } + break; + } + /* FIXME: don't need it now + case 'S': { + if ((tunneltype < 0) || (tunneltype > 2)) { + tunneltype = -1; + } + else { + tunneltype = 2; + } + break; + } + */ +#endif + case 'V': { + printf("%s\n", (AF_VER("Active port forwarder (server)"))); + exit(0); + break; + } + case '?': { + server_short_usage(""); + break; + } + } + } + + if (optind < argc) { + server_short_usage("Unrecognized non-option elements"); + } + + if (filenam != NULL) { + config = parsefile(filenam, &n); + if (n) { + printf("parsing failed! line:%d\n", n); + exit(1); + } + else { + if (certif == NULL) { + if (ServerConfiguration_get_certificateFile(config) == NULL) { + ServerConfiguration_set_certificateFile(config, "server-cert.pem"); + } + } + else { + ServerConfiguration_set_certificateFile(config, certif); + } + if (cacertif != NULL) { + ServerConfiguration_set_cacertificateFile(config, cacertif); + } + if (cerdepth != NULL) { + ServerConfiguration_set_sCertificateDepth(config, cerdepth); + } + if (keys == NULL) { + if (ServerConfiguration_get_keysFile(config) == NULL) { + ServerConfiguration_set_keysFile(config, "server.rsa"); + } + } + else { + ServerConfiguration_set_keysFile(config, keys); + } + if (dateformat != NULL) { + ServerConfiguration_set_dateFormat(config, dateformat); + } + + initializelogging(verbose, ServerConfiguration_get_dateFormat(config)); + + aflog(LOG_T_INIT, LOG_I_INFO, + "cfg file OK! (readed realms: %d)", ServerConfiguration_get_realmsNumber(config)); + if (name != NULL) + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: hostname=%s will be ignored", name); + if (listen != NULL) + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: listenport will be ignored"); + if (manage != NULL) + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: manageport will be ignored"); + if (realmname != NULL) + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: realmname=%s will be ignored", realmname); + if (sent == 1) + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: password from command line will be ignored"); + } + } + else { + config = ServerConfiguration_new(); + if (config == NULL) { + printf("Can't allocate memory for server configuration... exiting\n"); + exit(1); + } + ServerConfiguration_set_certificateFile(config, certif); + ServerConfiguration_set_cacertificateFile(config, cacertif); + ServerConfiguration_set_sCertificateDepth(config, cerdepth); + ServerConfiguration_set_keysFile(config, keys); + ServerConfiguration_set_dateFormat(config, dateformat); + + initializelogging(verbose, ServerConfiguration_get_dateFormat(config)); + + if (listen == NULL) { + listencount = 1; + listen = calloc(1, sizeof(char*)); + listen[0] = "50127"; + } + if (manage == NULL) { + managecount = 1; + manage = calloc(1, sizeof(char*)); + manage[0] = "50126"; + } + if (managecount != listencount) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Number of listen and manage options are not the same... exiting"); + exit(1); + } + if (ServerConfiguration_get_certificateFile(config) == NULL) { + ServerConfiguration_set_certificateFile(config, "server-cert.pem"); + } + if (ServerConfiguration_get_keysFile(config) == NULL) { + ServerConfiguration_set_keysFile(config, "server.rsa"); + } + if (type == NULL) { + type = "tcp"; + } + ServerConfiguration_set_realmsNumber(config, 1); + scRealmsTable = calloc(1, sizeof(ServerRealm*)); + if (scRealmsTable == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problem with allocating memory for ServerRealm* table... exiting"); + exit(1); + } + ServerConfiguration_set_realmsTable(config, scRealmsTable); + pointer = ServerRealm_new(); + if (pointer == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problem with allocating memory for ServerRealm structure... exiting"); + exit(1); + } + scRealmsTable[0] = pointer; + ServerRealm_set_hostName(pointer, name); + ServerRealm_set_userClientPairs(pointer, managecount); + srUsersClientsTable = calloc(managecount, sizeof(UsrCli*)); + if (srUsersClientsTable == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problem with allocating memory for UsrCli* table... exiting"); + exit(1); + } + ServerRealm_set_usersClientsTable(pointer, srUsersClientsTable); + for (i = 0; i < managecount; ++i) { + srUsersClientsTable[i] = UsrCli_new(); + if (srUsersClientsTable[i] == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problem with allocating memory for UsrCli structure... exiting"); + exit(1); + } + UsrCli_set_listenPortName(srUsersClientsTable[i], listen[i]); + UsrCli_set_managePortName(srUsersClientsTable[i], manage[i]); + } + ServerRealm_set_sUsersLimit(pointer, amount); + ServerRealm_set_sClientsLimit(pointer, clients); + ServerRealm_set_sRaClientsLimit(pointer, raclients); + ServerRealm_set_sTimeout(pointer, timeout); + ServerRealm_set_sMaxIdle(pointer, maxidle); + ServerRealm_set_sUsersPerClient(pointer, usrpcli); + ServerRealm_set_sClientMode(pointer, clim); + ServerRealm_set_basePortOn(pointer, baseport); + ServerRealm_set_auditOn(pointer, audit); +#ifdef HAVE_LIBPTHREAD + ServerRealm_set_tunnelType(pointer, tunneltype); +#endif + ServerRealm_set_dnsLookupsOn(pointer, dnslookups); + ServerRealm_set_realmName(pointer, realmname); + ServerRealm_set_password(pointer, pass); + if (strcmp(type, "tcp") == 0) { + temp = ServerRealm_get_realmType(pointer); + TYPE_SET_TCP(temp); + ServerRealm_set_realmType(pointer, temp); + } + else if (strcmp(type, "udp") == 0) { + temp = ServerRealm_get_realmType(pointer); + TYPE_SET_UDP(temp); + ServerRealm_set_realmType(pointer, temp); + } + else { + temp = ServerRealm_get_realmType(pointer); + TYPE_SET_ZERO(temp); + ServerRealm_set_realmType(pointer, temp); + } +#ifdef AF_INET6 + if (ipfam == -1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Conflicting types of ip protocol family... exiting"); + exit(1); + } + else if (ipfam == 4) { + temp = ServerRealm_get_realmType(pointer); + TYPE_SET_IPV4(temp); + ServerRealm_set_realmType(pointer, temp); + } + else if (ipfam == 6) { + temp = ServerRealm_get_realmType(pointer); + TYPE_SET_IPV6(temp); + ServerRealm_set_realmType(pointer, temp); + } +#endif + temp = ServerRealm_get_realmType(pointer); + temp |= mode; + ServerRealm_set_realmType(pointer, temp); + } + + maxfdp1 = 0; + + SSL_library_init(); + method = SSLv3_server_method(); + ctx = SSL_CTX_new(method); + if (SSL_CTX_set_cipher_list(ctx, "ALL:@STRENGTH") == 0) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting ciphers list failed... exiting"); + exit(1); + } + if ((flags = create_apf_dir(0))) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: Creating ~/.apf directory failed (%d)", flags); + if ((flags = create_apf_dir(1))) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: Creating ./apf directory failed (%d)", flags); + } + } + keys = ServerConfiguration_get_keysFile(config); + if ((flags = generate_rsa_key(&keys))) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: Something bad happened when generating rsa keys... (%d)", flags); + } + ServerConfiguration_set_keysFile(config, keys); + if (SSL_CTX_use_RSAPrivateKey_file(ctx, ServerConfiguration_get_keysFile(config), SSL_FILETYPE_PEM) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting rsa key failed (%s)... exiting", ServerConfiguration_get_keysFile(config)); + exit(1); + } + certif = ServerConfiguration_get_certificateFile(config); + if ((flags = generate_certificate(&certif, ServerConfiguration_get_keysFile(config)))) { + aflog(LOG_T_INIT, LOG_I_WARNING, + "Warning: Something bad happened when generating certificate... (%d)", flags); + } + ServerConfiguration_set_certificateFile(config, certif); + if (SSL_CTX_use_certificate_file(ctx, + ServerConfiguration_get_certificateFile(config), SSL_FILETYPE_PEM) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting certificate failed (%s)... exiting", ServerConfiguration_get_certificateFile(config)); + exit(1); + } + + cacertif = ServerConfiguration_get_cacertificateFile(config); + if (cacertif) { + if (SSL_CTX_load_verify_locations(ctx, + cacertif, + NULL) + != 1) + { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Setting CA certificate failed (%s)... exiting", cacertif); + exit(1); + } + + SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + NULL); + + cerdepth = ServerConfiguration_get_sCertificateDepth (config); + if (cerdepth == NULL) { + cerdepth = "9"; + } + SSL_CTX_set_verify_depth(ctx, check_value_liberal (cerdepth, "Invalid max certificate-depth")); + } + + if (ServerConfiguration_get_realmsNumber(config) == 0) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Working without sense is really without sense..."); + exit(1); + } + + FD_ZERO(&allset); + FD_ZERO(&wset); + + if (!verbose) + daemon(0, 0); + + scheduler = TaskScheduler_new(); + if (scheduler == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problems with creating task scheduler... exiting"); + exit(1); + } + + scRealmsTable = ServerConfiguration_get_realmsTable(config); + for (i = 0; i < ServerConfiguration_get_realmsNumber(config); ++i) { + if (ServerRealm_get_userClientPairs(scRealmsTable[i]) == 0) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "You have to specify at least one listen port and one manage port in each realm"); + exit(1); + } + srUsersClientsTable = ServerRealm_get_usersClientsTable(scRealmsTable[i]); + for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) { + if ((UsrCli_get_listenPortName(srUsersClientsTable[j]) == NULL) || + (UsrCli_get_managePortName(srUsersClientsTable[j]) == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Missing some of the variables...\nRealm: %d\nlistenport[%d]: %s\nmanageport[%d]: %s", + i, j, UsrCli_get_listenPortName(srUsersClientsTable[j]), + j, UsrCli_get_managePortName(srUsersClientsTable[j])); + exit(1); + } + } + /* checking type of the realm */ + if (!TYPE_IS_SET(ServerRealm_get_realmType(scRealmsTable[i]))) { + if (type != NULL) { + if (strcmp(type, "tcp") == 0) { + temp = ServerRealm_get_realmType(scRealmsTable[i]); + TYPE_SET_TCP(temp); + ServerRealm_set_realmType(scRealmsTable[i], temp); + } + else if (strcmp(type, "udp") == 0) { + temp = ServerRealm_get_realmType(scRealmsTable[i]); + TYPE_SET_UDP(temp); + ServerRealm_set_realmType(scRealmsTable[i], temp); + } + else { + temp = ServerRealm_get_realmType(scRealmsTable[i]); + TYPE_SET_TCP(temp); + ServerRealm_set_realmType(scRealmsTable[i], temp); + } + } + else { + temp = ServerRealm_get_realmType(scRealmsTable[i]); + TYPE_SET_TCP(temp); + ServerRealm_set_realmType(scRealmsTable[i], temp); + } + } +#ifdef AF_INET6 + /* using user's value for ipfam*/ + if (TYPE_IS_UNSPEC(ServerRealm_get_realmType(scRealmsTable[i]))) { + if (ipfam == -1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Conflicting types of ip protocol family... exiting"); + exit(1); + } + else if (ipfam == 4) { + temp = ServerRealm_get_realmType(scRealmsTable[i]); + TYPE_SET_IPV4(temp); + ServerRealm_set_realmType(scRealmsTable[i], temp); + } + else if (ipfam == 6) { + temp = ServerRealm_get_realmType(scRealmsTable[i]); + TYPE_SET_IPV6(temp); + ServerRealm_set_realmType(scRealmsTable[i], temp); + } + } +#endif + /* using user's values for zlib and ssl mode*/ + if (!TYPE_IS_SSL(mode)) { + temp = ServerRealm_get_realmType(scRealmsTable[i]); + TYPE_UNSET_SSL(temp); + ServerRealm_set_realmType(scRealmsTable[i], temp); + } + if (!TYPE_IS_ZLIB(mode)) { + temp = ServerRealm_get_realmType(scRealmsTable[i]); + TYPE_UNSET_ZLIB(temp); + ServerRealm_set_realmType(scRealmsTable[i], temp); + } + /* using user's baseport value*/ + if (ServerRealm_get_basePortOn(scRealmsTable[i]) == 0) { + ServerRealm_set_basePortOn(scRealmsTable[i], baseport); + } + /* using user's audit value*/ + if (ServerRealm_get_auditOn(scRealmsTable[i]) == 0) { + ServerRealm_set_auditOn(scRealmsTable[i], audit); + } +#ifdef HAVE_LIBPTHREAD + /* using user's tunneltype value*/ + if (ServerRealm_get_tunnelType(scRealmsTable[i]) == 0) { + if (tunneltype == -1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Conflicting types of tunnel type... exiting"); + exit(1); + } + ServerRealm_set_tunnelType(scRealmsTable[i], tunneltype); + } +#endif + /* using user's dnslookups value*/ + if (ServerRealm_get_dnsLookupsOn(scRealmsTable[i]) == 0) { + ServerRealm_set_dnsLookupsOn(scRealmsTable[i], dnslookups); + } + /* checking users amount */ + stemp = ServerRealm_get_sUsersLimit(scRealmsTable[i]); + set_value(&stemp, amount, "5"); + ServerRealm_set_sUsersLimit(scRealmsTable[i], stemp); + ServerRealm_set_usersLimit(scRealmsTable[i], + check_value(ServerRealm_get_sUsersLimit(scRealmsTable[i]), "Invalid users amount")); + /* checking clients amount */ + stemp = ServerRealm_get_sClientsLimit(scRealmsTable[i]); + set_value(&stemp, clients, "1"); + ServerRealm_set_sClientsLimit(scRealmsTable[i], stemp); + ServerRealm_set_clientsLimit(scRealmsTable[i], + check_value(ServerRealm_get_sClientsLimit(scRealmsTable[i]), "Invalid clients amount")); + /* checking raclients amount */ + stemp = ServerRealm_get_sRaClientsLimit(scRealmsTable[i]); + set_value(&stemp, raclients, "1"); + ServerRealm_set_sRaClientsLimit(scRealmsTable[i], stemp); + ServerRealm_set_raClientsLimit(scRealmsTable[i], + check_value(ServerRealm_get_sRaClientsLimit(scRealmsTable[i]), "Invalid raclients amount")); + /* checking usrpcli value */ + stemp = ServerRealm_get_sUsersPerClient(scRealmsTable[i]); + set_value(&stemp, usrpcli, ServerRealm_get_sUsersLimit(scRealmsTable[i])); + ServerRealm_set_sUsersPerClient(scRealmsTable[i], stemp); + ServerRealm_set_usersPerClient(scRealmsTable[i], + check_value(ServerRealm_get_sUsersPerClient(scRealmsTable[i]), "Invalid usrpcli value")); + /* checking timeout value */ + stemp = ServerRealm_get_sTimeout(scRealmsTable[i]); + set_value(&stemp, timeout, "5"); + ServerRealm_set_sTimeout(scRealmsTable[i], stemp); + ServerRealm_set_timeout(scRealmsTable[i], + check_value(ServerRealm_get_sTimeout(scRealmsTable[i]), "Invalid timeout value")); + /* checking maxidle value */ + stemp = ServerRealm_get_sMaxIdle(scRealmsTable[i]); + set_value(&stemp, maxidle, "0"); + ServerRealm_set_sMaxIdle(scRealmsTable[i], stemp); + temp = check_value_liberal(ServerRealm_get_sMaxIdle(scRealmsTable[i]), "Invalid maxidle value"); + if (temp < 0) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Invalid maxidle value: %d\n", temp); + exit(1); + } + ServerRealm_set_maxIdle(scRealmsTable[i], temp); + /* checking climode value */ + stemp = ServerRealm_get_sClientMode(scRealmsTable[i]); + set_value(&stemp, clim, "1"); + ServerRealm_set_sClientMode(scRealmsTable[i], stemp); + ServerRealm_set_clientMode(scRealmsTable[i], + check_value(ServerRealm_get_sClientMode(scRealmsTable[i]), "Invalid climode value")); + /* allocating memory*/ + srUsersTable = calloc(ServerRealm_get_usersLimit(scRealmsTable[i]), sizeof(ConnectUser*)); + if (srUsersTable == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - try define smaller amount of users"); + exit(1); + } + ServerRealm_set_usersTable(scRealmsTable[i], srUsersTable); + for (j = 0; j < ServerRealm_get_usersLimit(scRealmsTable[i]); ++j) { + srUsersTable[j] = ConnectUser_new(); + if (srUsersTable[j] == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - try define smaller amount of users"); + exit(1); + } + } + srClientsTable = calloc(ServerRealm_get_clientsLimit(scRealmsTable[i]), sizeof(ConnectClient*)); + if (srClientsTable == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - try define smaller amount of clients"); + exit(1); + } + ServerRealm_set_clientsTable(scRealmsTable[i], srClientsTable); + for (j = 0; j < ServerRealm_get_clientsLimit(scRealmsTable[i]); ++j) { + srClientsTable[j] = ConnectClient_new(); + if (srClientsTable[j] == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - try define smaller amount of clients"); + exit(1); + } + } + srRaClientsTable = calloc(ServerRealm_get_raClientsLimit(scRealmsTable[i]), sizeof(ConnectClient*)); + if (srRaClientsTable == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - try define smaller amount of raclients"); + exit(1); + } + ServerRealm_set_raClientsTable(scRealmsTable[i], srRaClientsTable); + for (j = 0; j < ServerRealm_get_raClientsLimit(scRealmsTable[i]); ++j) { + srRaClientsTable[j] = ConnectClient_new(); + if (srRaClientsTable[j] == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - try define smaller amount of raclients"); + exit(1); + } + } + ipfam = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(ServerRealm_get_realmType(scRealmsTable[i]))) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(ServerRealm_get_realmType(scRealmsTable[i]))) { + ipfam |= 0x04; + } +#endif + if (ServerRealm_get_basePortOn(scRealmsTable[i]) == 0) { + for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) { + if (ip_listen(&temp, UsrCli_get_listenHostName(srUsersClientsTable[j]) ? + UsrCli_get_listenHostName(srUsersClientsTable[j]) : + ServerRealm_get_hostName(scRealmsTable[i]), + UsrCli_get_listenPortName(srUsersClientsTable[j]), + (&len), ipfam)) { + aflog(LOG_T_INIT, LOG_I_CRIT, +#ifdef AF_INET6 + "tcp_listen_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", +#else + "tcp_listen error for %s, %s", +#endif + UsrCli_get_listenHostName(srUsersClientsTable[j]) ? + UsrCli_get_listenHostName(srUsersClientsTable[j]) : + ServerRealm_get_hostName(scRealmsTable[i]), + UsrCli_get_listenPortName(srUsersClientsTable[j])); + exit(1); + } + ServerRealm_set_addressLength(scRealmsTable[i], len); + UsrCli_set_listenFd(srUsersClientsTable[j], temp); + flags = fcntl(UsrCli_get_listenFd(srUsersClientsTable[j]), F_GETFL, 0); + fcntl(UsrCli_get_listenFd(srUsersClientsTable[j]), F_SETFL, flags | O_NONBLOCK); + } + } + + for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) { + switch (ServerRealm_get_tunnelType(scRealmsTable[i])) { + case 0: { + temp = find_previousFd(srUsersClientsTable, j, + UsrCli_get_manageHostName(srUsersClientsTable[j]), + UsrCli_get_managePortName(srUsersClientsTable[j])); + if (temp == -1) { + if (ip_listen(&temp, UsrCli_get_manageHostName(srUsersClientsTable[j]) ? + UsrCli_get_manageHostName(srUsersClientsTable[j]) : + ServerRealm_get_hostName(scRealmsTable[i]), + UsrCli_get_managePortName(srUsersClientsTable[j]), + (&len), ipfam)) { + aflog(LOG_T_INIT, LOG_I_CRIT, +#ifdef AF_INET6 + "tcp_listen_%s error for %s, %s", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", +#else + "tcp_listen error for %s, %s", +#endif + UsrCli_get_manageHostName(srUsersClientsTable[j]) ? + UsrCli_get_manageHostName(srUsersClientsTable[j]) : + ServerRealm_get_hostName(scRealmsTable[i]), + UsrCli_get_managePortName(srUsersClientsTable[j])); + exit(1); + } + } + ServerRealm_set_addressLength(scRealmsTable[i], len); + UsrCli_set_manageFd(srUsersClientsTable[j], temp); + flags = fcntl(UsrCli_get_manageFd(srUsersClientsTable[j]), F_GETFL, 0); + fcntl(UsrCli_get_manageFd(srUsersClientsTable[j]), F_SETFL, flags | O_NONBLOCK); + UsrCli_set_number(srUsersClientsTable[j], eval_UsrCliPair(srUsersClientsTable, j, + UsrCli_get_manageHostName(srUsersClientsTable[j]), + UsrCli_get_managePortName(srUsersClientsTable[j]))); + break; + } +#ifdef HAVE_LIBPTHREAD + case 1: + case 2: { + temp = find_previousFd(srUsersClientsTable, j, + UsrCli_get_manageHostName(srUsersClientsTable[j]), + UsrCli_get_managePortName(srUsersClientsTable[j])); + if (temp == -1) { + if (initialize_http_proxy_server(&temp, + UsrCli_get_manageHostName(srUsersClientsTable[j]) ? + UsrCli_get_manageHostName(srUsersClientsTable[j]) : + ServerRealm_get_hostName(scRealmsTable[i]), + UsrCli_get_managePortName(srUsersClientsTable[j]), + (&len), ipfam, + ServerRealm_get_clientsLimit(scRealmsTable[i]) + + ServerRealm_get_raClientsLimit(scRealmsTable[i]), + (ServerRealm_get_tunnelType(scRealmsTable[i]) - 1), + ctx)) { + aflog(LOG_T_INIT, LOG_I_CRIT, +#ifdef AF_INET6 + "http%s_proxy_listen_%s error for %s, %s", + (ServerRealm_get_tunnelType(scRealmsTable[i]) == 2) ? "s" : "", + (ipfam & 0x02)?"ipv4":(ipfam & 0x04)?"ipv6":"unspec", +#else + "http%s_proxy_listen error for %s, %s", + (ServerRealm_get_tunnelType(scRealmsTable[i]) == 2) ? "s" : "", +#endif + UsrCli_get_manageHostName(srUsersClientsTable[j]) ? + UsrCli_get_manageHostName(srUsersClientsTable[j]) : + ServerRealm_get_hostName(scRealmsTable[i]), + UsrCli_get_managePortName(srUsersClientsTable[j])); + exit(1); + } + } + ServerRealm_set_addressLength(scRealmsTable[i], len); + UsrCli_set_manageFd(srUsersClientsTable[j], temp); + flags = fcntl(UsrCli_get_manageFd(srUsersClientsTable[j]), F_GETFL, 0); + fcntl(UsrCli_get_manageFd(srUsersClientsTable[j]), F_SETFL, flags | O_NONBLOCK); + UsrCli_set_number(srUsersClientsTable[j], eval_UsrCliPair(srUsersClientsTable, j, + UsrCli_get_manageHostName(srUsersClientsTable[j]), + UsrCli_get_managePortName(srUsersClientsTable[j]))); + break; + } +#endif + default: { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Unknown tunnel type"); + exit(1); + break; + } + } + } + + ServerRealm_set_clientAddress(scRealmsTable[i], malloc(ServerRealm_get_addressLength(scRealmsTable[i]))); + if (ServerRealm_get_clientAddress(scRealmsTable[i]) == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Allocating memory for client addresses failed... exiting"); + exit(1); + } + + for (j = 0; j < ServerRealm_get_clientsLimit(scRealmsTable[i]); ++j) { + SslFd_set_ssl(ConnectClient_get_sslFd(srClientsTable[j]), SSL_new(ctx)); + if (SslFd_get_ssl(ConnectClient_get_sslFd(srClientsTable[j])) == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Creation of ssl object failed... exiting"); + exit(1); + } + } + + for (j = 0; j < ServerRealm_get_raClientsLimit(scRealmsTable[i]); ++j) { + SslFd_set_ssl(ConnectClient_get_sslFd(srRaClientsTable[j]), SSL_new(ctx)); + if (SslFd_get_ssl(ConnectClient_get_sslFd(srRaClientsTable[j])) == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Creation of ssl object failed... exiting"); + exit(1); + } + } + + for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) { + FD_SET(UsrCli_get_manageFd(srUsersClientsTable[j]), &allset); + maxfdp1 = (maxfdp1 > (UsrCli_get_manageFd(srUsersClientsTable[j]) + 1)) ? + maxfdp1 : (UsrCli_get_manageFd(srUsersClientsTable[j]) + 1); + } + if (ServerRealm_get_basePortOn(scRealmsTable[i]) == 0) { + for (j = 0; j < ServerRealm_get_userClientPairs(scRealmsTable[i]); ++j) { + FD_SET(UsrCli_get_listenFd(srUsersClientsTable[j]), &allset); + maxfdp1 = (maxfdp1 > (UsrCli_get_listenFd(srUsersClientsTable[j]) + 1)) ? + maxfdp1 : (UsrCli_get_listenFd(srUsersClientsTable[j]) + 1); + } + } + ServerRealm_set_connectedUsers(scRealmsTable[i], 0); + ServerRealm_set_connectedClients(scRealmsTable[i], 0); + ServerRealm_set_connectedRaClients(scRealmsTable[i], 0); + for (j = 0; j < ServerRealm_get_clientsLimit(scRealmsTable[i]); ++j) { + ConnectClient_set_timer(srClientsTable[j], timeval_create(ServerRealm_get_timeout(scRealmsTable[i]), 0)); + ConnectClient_set_limit(srClientsTable[j], ServerRealm_get_usersPerClient(scRealmsTable[i])); + if (ConnectClient_create_users(srClientsTable[j])) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - try define smaller amount of usrpcli (or users)"); + exit(1); + } + } + for (j = 0; j < ServerRealm_get_raClientsLimit(scRealmsTable[i]); ++j) { + ConnectClient_set_timer(srRaClientsTable[j], + timeval_create(ServerRealm_get_timeout(scRealmsTable[i]), 0)); + } + } + + aflog(LOG_T_MAIN, LOG_I_INFO, + "SERVER STARTED realms: %d", ServerConfiguration_get_realmsNumber(config)); + time(&now); + ServerConfiguration_set_startTime(config, now); + + for ( ; ; ) { + rset = allset; + tmpset = wset; + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "select, maxfdp1: %d", maxfdp1); + if (TaskScheduler_hasMoreTasks(scheduler)) { + TaskScheduler_startWatching(scheduler); + select(maxfdp1, &rset, &tmpset, NULL, TaskScheduler_get_actualTimer(scheduler)); + TaskScheduler_stopWatching(scheduler); + } + else { + select(maxfdp1, &rset, &tmpset, NULL, NULL); + } + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "after select..."); + + for (j = 0; j < ServerConfiguration_get_realmsNumber(config); ++j) { + pointer = scRealmsTable[j]; + srUsersTable = ServerRealm_get_usersTable(pointer); + srClientsTable = ServerRealm_get_clientsTable(pointer); + srRaClientsTable = ServerRealm_get_raClientsTable(pointer); + srUsersClientsTable = ServerRealm_get_usersClientsTable(pointer); + for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) { + if ((ConnectUser_get_state(srUsersTable[i]) == S_STATE_OPEN) || + (ConnectUser_get_state(srUsersTable[i]) == S_STATE_STOPPED) || + (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING)) { + if (FD_ISSET(ConnectUser_get_connFd(srUsersTable[i]), &rset)) { + k = eval_usernum(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])], i); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: FD_ISSET", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer,i)); + if (TYPE_IS_TCP(ServerRealm_get_realmType(pointer))) { /* forwarding tcp packets */ + n = read(ConnectUser_get_connFd(srUsersTable[i]), &buff[5], 8091); + if (n == -1) { + if (errno == EAGAIN) { + continue; + } + aflog(LOG_T_USER, LOG_I_ERR, + "realm[%s]: Client[%s]: user[%d]: READ ERROR (%d)", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i), errno); + n = 0; + } + if (n) { + aflog(LOG_T_USER, LOG_I_DEBUG, + "realm[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i), n); + UserStats_add_upload(ConnectUser_get_stats(srUsersTable[i]), n); + if ((buff[5] == AF_S_MESSAGE) && (buff[6] == AF_S_LOGIN) && (buff[7] == AF_S_MESSAGE)) { + aflog(LOG_T_USER, LOG_I_WARNING, + "WARNING: got packet similiar to udp"); + } + buff[0] = AF_S_MESSAGE; /* sending message */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]), + buff, n+5); + } + else { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i), + ConnectUser_get_nameBuf(srUsersTable[i]), + ConnectUser_get_portBuf(srUsersTable[i]), + timeperiod(now - ConnectUser_get_connectTime(srUsersTable[i]))); + if (ServerRealm_get_auditOn(pointer)) { + AuditList_insert_back( + ConnectClient_get_auditList( + srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]), + AuditListNode_new_entry( + get_username(pointer, i), + ConnectUser_get_nameBuf(srUsersTable[i]), + ConnectUser_get_portBuf(srUsersTable[i]), + ConnectUser_get_connectTime(srUsersTable[i]), + now - ConnectUser_get_connectTime(srUsersTable[i])) + ); + } + close(ConnectUser_get_connFd(srUsersTable[i])); + FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset); + if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING) { + ConnectUser_set_state(srUsersTable[i], S_STATE_CLEAR); + ServerRealm_decrease_connectedUsers(pointer); + ConnectClient_decrease_connected(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]); + ConnectClient_get_users(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])])[k] = -1; + } + else { + ConnectUser_set_state(srUsersTable[i], S_STATE_CLOSING); + } + BufList_clear(ConnectUser_get_bufList(srUsersTable[i])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]), + buff, 5); + } + } + else { /* when forwarding udp packets */ + n = readn(ConnectUser_get_connFd(srUsersTable[i]), buff, 5 ); + if (n != 5) { + n = 0; + } + if (n) { + if ((buff[0] == AF_S_MESSAGE) && (buff[1] == AF_S_LOGIN) && (buff[2] == AF_S_MESSAGE)) { + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + if ((n = readn(ConnectUser_get_connFd(srUsersTable[i]), &buff[5], length)) != 0) { + aflog(LOG_T_USER, LOG_I_DEBUG, + "realm[%s]: Client[%s]: FROM user[%d]: MESSAGE length=%d", + get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i), n); + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]), + buff, n+5); + } + } + else { + n = 0; + } + } + + if (n == 0) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: user[%d]: CLOSED (udp mode)", get_realmname(config, j), + get_clientname(pointer, + ConnectUser_get_whatClient(srUsersTable[i])), get_username(pointer, i)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i), + ConnectUser_get_nameBuf(srUsersTable[i]), + ConnectUser_get_portBuf(srUsersTable[i]), + timeperiod(now - ConnectUser_get_connectTime(srUsersTable[i]))); + close(ConnectUser_get_connFd(srUsersTable[i])); + FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset); + ConnectUser_set_state(srUsersTable[i], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(srUsersTable[i])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]), + buff, 5); + } + + } + } + } + } + /* ------------------------------------ */ + for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) { + if ((ConnectUser_get_state(srUsersTable[i]) == S_STATE_STOPPED) || + (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING)) + if (FD_ISSET(ConnectUser_get_connFd(srUsersTable[i]), &tmpset)) { + k = eval_usernum(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])], i); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: FD_ISSET - WRITE", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i)); + n = BufListNode_readMessageLength(BufList_get_first(ConnectUser_get_bufList(srUsersTable[i]))); + sent = write(ConnectUser_get_connFd(srUsersTable[i]), + BufListNode_readMessage(BufList_get_first(ConnectUser_get_bufList(srUsersTable[i]))), n); + if ((sent > 0) && (sent != n)) { + BufListNode_set_actPtr(BufList_get_first(ConnectUser_get_bufList(srUsersTable[i])), + BufListNode_get_actPtr(BufList_get_first(ConnectUser_get_bufList(srUsersTable[i]))) + sent); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i), sent, n); + } + else if ((sent == -1) && (errno == EAGAIN)) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: EAGAIN", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i)); + } + else if (sent == -1) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: user[%d]: CLOSED", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i), + ConnectUser_get_nameBuf(srUsersTable[i]), + ConnectUser_get_portBuf(srUsersTable[i]), + timeperiod(now - ConnectUser_get_connectTime(srUsersTable[i]))); + close(ConnectUser_get_connFd(srUsersTable[i])); + FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset); + if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING) { + ConnectUser_set_state(srUsersTable[i], S_STATE_CLEAR); + ServerRealm_decrease_connectedUsers(pointer); + ConnectClient_decrease_connected(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]); + ConnectClient_get_users(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])])[k] = -1; + } + else { + ConnectUser_set_state(srUsersTable[i], S_STATE_CLOSING); + } + BufList_clear(ConnectUser_get_bufList(srUsersTable[i])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]), + buff, 5); + } + else { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: user[%d]: (%d/%d)", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i), sent, n); + BufList_delete_first(ConnectUser_get_bufList(srUsersTable[i])); + if (BufList_get_first(ConnectUser_get_bufList(srUsersTable[i])) == NULL) { + FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset); + buff[0] = AF_S_CAN_SEND; /* stopping transfer */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: TO user[%d]: BUFFERING MESSAGE ENDED", + get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i)); + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]), + buff, 5); + if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_KICKING) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: user[%d]: delayed CLOSED", get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s CLIENT: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(config, j), + get_clientname(pointer, ConnectUser_get_whatClient(srUsersTable[i])), + get_username(pointer, i), + ConnectUser_get_nameBuf(srUsersTable[i]), + ConnectUser_get_portBuf(srUsersTable[i]), + timeperiod(now - ConnectUser_get_connectTime(srUsersTable[i]))); + close(ConnectUser_get_connFd(srUsersTable[i])); + FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &allset); + FD_CLR(ConnectUser_get_connFd(srUsersTable[i]), &wset); + ConnectUser_set_state(srUsersTable[i], S_STATE_CLEAR); + ServerRealm_decrease_connectedUsers(pointer); + ConnectClient_decrease_connected(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]); + ConnectClient_get_users(srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])])[k] = -1; + BufList_clear(ConnectUser_get_bufList(srUsersTable[i])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = k >> 8; /* high bits of user number */ + buff[2] = k; /* low bits of user number */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[ConnectUser_get_whatClient(srUsersTable[i])]), + buff, 5); + } + else { + ConnectUser_set_state(srUsersTable[i], S_STATE_OPEN); + } + } + } + } + } + /* ------------------------------------ */ + if (ServerRealm_get_basePortOn(pointer) == 0) { + for (l = 0; l < ServerRealm_get_userClientPairs(pointer); ++l) { + if (FD_ISSET(UsrCli_get_listenFd(srUsersClientsTable[l]), &rset)) { + len = ServerRealm_get_addressLength(pointer); + sent = accept(UsrCli_get_listenFd(srUsersClientsTable[l]), ServerRealm_get_clientAddress(pointer), &len); + if (sent == -1) { + if (errno == EAGAIN) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(config, j)); + } + else { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> errno=%d", get_realmname(config, j), errno); + } + continue; + } + flags = fcntl(sent, F_GETFL, 0); + fcntl(sent, F_SETFL, flags | O_NONBLOCK); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET", get_realmname(config, j)); + k = find_client(pointer, ServerRealm_get_clientMode(pointer), l); + + if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_ACCEPTED) { + if (ServerRealm_get_connectedUsers(pointer) == ServerRealm_get_usersLimit(pointer)) { + close(sent); + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: user limit EXCEEDED", get_realmname(config, j)); + } + else if (ConnectClient_get_connected(srClientsTable[k]) == + ConnectClient_get_limit(srClientsTable[k])) { + close(sent); + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: Client[%s]: usrpcli limit EXCEEDED", + get_realmname(config, j), get_clientname(pointer, k)); + } + else { + for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) { + if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_CLEAR) { + ConnectUser_set_userId(srUsersTable[i], ServerRealm_get_usersCounter(pointer)); + ServerRealm_increase_usersCounter(pointer); + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: new user: CONNECTING from IP: %s", + get_realmname(config, j), get_clientname(pointer, k), + sock_ntop(ServerRealm_get_clientAddress(pointer), len, ConnectUser_get_nameBuf(srUsersTable[i]), + ConnectUser_get_portBuf(srUsersTable[i]), ServerRealm_get_dnsLookupsOn(pointer))); + ConnectUser_set_connFd(srUsersTable[i], sent); + ConnectUser_set_state(srUsersTable[i], S_STATE_OPENING); + ConnectUser_set_whatClient(srUsersTable[i], k); + time(&now); + ConnectUser_set_connectTime(srUsersTable[i], now); + UserStats_clear(ConnectUser_get_stats(srUsersTable[i])); + UserStats_set_lastActivity(ConnectUser_get_stats(srUsersTable[i]), now); + ServerRealm_increase_connectedUsers(pointer); + ConnectClient_increase_connected(srClientsTable[k]); + memcpy(&buff[5], ConnectUser_get_nameBuf(srUsersTable[i]), 128); + memcpy(&buff[133], ConnectUser_get_portBuf(srUsersTable[i]), 7); + n = 135; + if (ConnectClient_get_multi(srClientsTable[k]) == CONNECTCLIENT_MULTI_ENABLED) { + n = 136; + buff[140] = UsrCli_get_number(srUsersClientsTable[l]); + } + i = find_usernum(srClientsTable[k], i); + buff[0] = AF_S_CONOPEN; /* opening connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, n+5); + break; + } + } + } + } + else { + close(sent); + aflog(LOG_T_USER, LOG_I_ERR, + "realm[%s]: Client(%d) is NOT CONNECTED", + get_realmname(config, j), k); + } + } + } + } + /* ------------------------------------ */ + if (ServerRealm_get_basePortOn(pointer) == 1) { + for (k = 0; k < ServerRealm_get_clientsLimit(pointer); ++k) { + if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_ACCEPTED) { + if (FD_ISSET(ConnectClient_get_listenFd(srClientsTable[k]), &rset)) { + + len = ServerRealm_get_addressLength(pointer); + sent = accept(ConnectClient_get_listenFd(srClientsTable[k]), ServerRealm_get_clientAddress(pointer), &len); + if (sent == -1) { + if (errno == EAGAIN) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> EAGAIN", get_realmname(config, j)); + } + else { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: listenfd: FD_ISSET --> errno=%d", get_realmname(config, j), errno); + } + continue; + } + flags = fcntl(sent, F_GETFL, 0); + fcntl(sent, F_SETFL, flags | O_NONBLOCK); + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: listenfd: FD_ISSET", + get_realmname(config, j), get_clientname(pointer, k)); + if (ServerRealm_get_connectedUsers(pointer) == ServerRealm_get_usersLimit(pointer)) { + close(sent); + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: user limit EXCEEDED", get_realmname(config, j)); + } + else if(ConnectClient_get_connected(srClientsTable[k]) == + ConnectClient_get_limit(srClientsTable[k])) { + close(sent); + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: Client[%s]: usrpcli limit EXCEEDED", + get_realmname(config, j), get_clientname(pointer, k)); + } + else { + for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) { + if (ConnectUser_get_state(srUsersTable[i]) == S_STATE_CLEAR) { + ConnectUser_set_userId(srUsersTable[i], ServerRealm_get_usersCounter(pointer)); + ServerRealm_increase_usersCounter(pointer); + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: Client[%s]: new user: CONNECTING from IP: %s", + get_realmname(config, j), get_clientname(pointer, k), + sock_ntop(ServerRealm_get_clientAddress(pointer), len, + ConnectUser_get_nameBuf(srUsersTable[i]), + ConnectUser_get_portBuf(srUsersTable[i]), ServerRealm_get_dnsLookupsOn(pointer))); + ConnectUser_set_connFd(srUsersTable[i], sent); + ConnectUser_set_state(srUsersTable[i], S_STATE_OPENING); + ConnectUser_set_whatClient(srUsersTable[i], k); + time(&now); + ConnectUser_set_connectTime(srUsersTable[i], now); + UserStats_clear(ConnectUser_get_stats(srUsersTable[i])); + UserStats_set_lastActivity(ConnectUser_get_stats(srUsersTable[i]), now); + ServerRealm_increase_connectedUsers(pointer); + ConnectClient_increase_connected(srClientsTable[k]); + memcpy(&buff[5], ConnectUser_get_nameBuf(srUsersTable[i]), 128); + memcpy(&buff[133], ConnectUser_get_portBuf(srUsersTable[i]), 7); + n = 135; + i = find_usernum(srClientsTable[k], i); + buff[0] = AF_S_CONOPEN; /* opening connection */ + buff[1] = i >> 8; /* high bits of user number */ + buff[2] = i; /* low bits of user number */ + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, n+5); + break; + } + } + } + } + } + } + } + /* ------------------------------------ */ + for (k = 0; k < ServerRealm_get_clientsLimit(pointer); ++k) + if ((ConnectClient_get_state(srClientsTable[k]) > CONNECTCLIENT_STATE_FREE) && + (FD_ISSET(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])), &rset))) { + if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_CONNECTING) { + make_ssl_initialize(ConnectClient_get_sslFd(srClientsTable[k])); + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "realm[%s]: new Client[%s]: SSL_accept", + get_realmname(config, j), get_clientname(pointer, k)); + switch (make_ssl_accept(ConnectClient_get_sslFd(srClientsTable[k]))) { + case 2: { + close(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k]))); + FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])), &allset); + + /* This SSL-object is busted; don't reuse it + (SSL_clear isn't sufficient because ssl->new_session is set): */ + SslFd_set_ssl(ConnectClient_get_sslFd(srClientsTable[k]), + SSL_new (ctx)); + + ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_FREE); + if ((task = ConnectClient_get_task(srClientsTable[k]))) { + TaskScheduler_removeTask(scheduler, task); + ConnectClient_set_task(srClientsTable[k], NULL); + } + ServerRealm_decrease_connectedClients(pointer); + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: new Client[%s]: DENIED by SSL_accept", + get_realmname(config, j), get_clientname(pointer, k)); + } + case 1: { + continue; + } + default: { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: new Client[%s]: ACCEPTED by SSL_accept", + get_realmname(config, j), get_clientname(pointer, k)); + ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_AUTHORIZING); + continue; + } + } + } + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: commfd: FD_ISSET", + get_realmname(config, j), get_clientname(pointer, k)); + if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_AUTHORIZING) { + n = SslFd_get_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd(srClientsTable[k]), + buff, (-1) * HeaderBuffer_to_read(ConnectClient_get_header(srClientsTable[k]))); + } + else { + n = SslFd_get_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd(srClientsTable[k]), + buff, (-1) * HeaderBuffer_to_read(ConnectClient_get_header(srClientsTable[k]))); + } + if (n == -1) { + if (errno == EAGAIN) { + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "realm[%s]: Client[%s]: commfd: EAGAIN", + get_realmname(config, j), get_clientname(pointer, k)); + continue; + } + else { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: Client[%s]: commfd: ERROR: %d", + get_realmname(config, j), get_clientname(pointer, k), errno); + n = 0; + } + } + else if (n != 5) { + if (n != 0) { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: Client[%s]: header length = %d --> buffering", + get_realmname(config, j), get_clientname(pointer, k), n); + HeaderBuffer_store(ConnectClient_get_header(srClientsTable[k]), buff, n); + if (HeaderBuffer_to_read(ConnectClient_get_header(srClientsTable[k])) == 0) { + HeaderBuffer_restore(ConnectClient_get_header(srClientsTable[k]), buff); + n = 5; + } + else { + continue; + } + } + } + if (n==0) { + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s]: commfd: CLOSED", + get_realmname(config, j), get_clientname(pointer, k)); + time(&now); + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "REALM: %s CLIENT: %s IP: %s PORT: %s DURATION: %s", + get_realmname(config, j), + get_clientname(pointer, k), + ConnectClient_get_nameBuf(srClientsTable[k]), + ConnectClient_get_portBuf(srClientsTable[k]), + timeperiod(now - ConnectClient_get_connectTime(srClientsTable[k]))); + if (ServerRealm_get_auditOn(pointer)) { + while (AuditList_get_first(ConnectClient_get_auditList(srClientsTable[k]))) { + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "USERID: %d IP: %s PORT: %s CONNECTED: %s DURATION: %s", + AuditListNode_get_userId( + AuditList_get_first( + ConnectClient_get_auditList(srClientsTable[k]))), + AuditListNode_get_nameBuf( + AuditList_get_first( + ConnectClient_get_auditList(srClientsTable[k]))), + AuditListNode_get_portBuf( + AuditList_get_first( + ConnectClient_get_auditList(srClientsTable[k]))), + localdate(AuditListNode_get_connectTimep( + AuditList_get_first( + ConnectClient_get_auditList(srClientsTable[k])))), + timeperiod(AuditListNode_get_duration( + AuditList_get_first( + ConnectClient_get_auditList(srClientsTable[k]))))); + AuditList_delete_first(ConnectClient_get_auditList(srClientsTable[k])); + } + } + remove_client(pointer, k, &allset, &wset, scheduler); + continue; + } + + numofcon = buff[1]; + numofcon = numofcon << 8; + numofcon += buff[2]; /* this is id of user */ + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + if ((k == ServerRealm_get_clientsLimit(pointer)) && (buff[0] != AF_S_LOGIN) && + (buff[0] != AF_S_ADMIN_LOGIN) && (buff[0] != AF_S_ADMIN_CMD)) { + buff[0] = AF_S_WRONG; + } + if (ConnectClient_get_state(srClientsTable[k]) < CONNECTCLIENT_STATE_AUTHORIZING) { + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: Client[%s]: Impossible behaviour --> ignoring", + get_realmname(config, j), get_clientname(pointer, k)); + continue; + } + if ((ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_AUTHORIZING) && + (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) { + buff[0] = AF_S_WRONG; + } + + time(&now); + ConnectClient_set_lastActivity(srClientsTable[k], now); + if (ServerRealm_get_maxIdle(pointer)) { + ConnectClient_set_timer(srClientsTable[k], timeval_create(ServerRealm_get_maxIdle(pointer), 0)); + TaskScheduler_update(scheduler); + } + + switch (buff[0]) { + case AF_S_CONCLOSED : { + n = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(ServerRealm_get_usersLimit(pointer))) && + (ConnectClient_get_state(srClientsTable[k]) == + CONNECTCLIENT_STATE_ACCEPTED)) { + if (ConnectUser_get_state(srUsersTable[numofcon]) == + S_STATE_STOPPED) { + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_KICKING); + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: KICKING...", + get_realmname(config, j), get_username(pointer, numofcon)); + } + else { + ServerRealm_decrease_connectedUsers(pointer); + ConnectClient_decrease_connected(srClientsTable[k]); + ConnectClient_get_users(srClientsTable[k])[n] = -1; + if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_CLOSING) { + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLEAR); + aflog(LOG_T_USER, LOG_I_DEBUG, + "realm[%s]: user[%d]: CLOSE CONFIRMED", + get_realmname(config, j), get_username(pointer, numofcon)); + } + else if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_OPEN) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: KICKED", + get_realmname(config, j), get_username(pointer, numofcon)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(config, j), + get_username(pointer, numofcon), + ConnectUser_get_nameBuf(srUsersTable[numofcon]), + ConnectUser_get_portBuf(srUsersTable[numofcon]), + timeperiod(now - + ConnectUser_get_connectTime(srUsersTable[numofcon]))); + close(ConnectUser_get_connFd(srUsersTable[numofcon])); + FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset); + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLEAR); + BufList_clear(ConnectUser_get_bufList(srUsersTable[numofcon])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = n >> 8; /* high bits of user number */ + buff[2] = n; /* low bits of user number */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + } + } + } + else { + remove_client(pointer, k, &allset, &wset, scheduler); + } + break; + } + case AF_S_CONOPEN : { + n = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(ServerRealm_get_usersLimit(pointer))) && + (ConnectClient_get_state(srClientsTable[k]) == + CONNECTCLIENT_STATE_ACCEPTED)) { + if (ConnectUser_get_state(srUsersTable[numofcon]) == + S_STATE_OPENING) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: NEW", + get_realmname(config, j), get_username(pointer, numofcon)); + FD_SET(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset); + maxfdp1 = (maxfdp1 > (ConnectUser_get_connFd(srUsersTable[numofcon]) + 1)) ? + maxfdp1 : (ConnectUser_get_connFd(srUsersTable[numofcon]) + 1); + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_OPEN); + } + if (ConnectUser_get_state(srUsersTable[numofcon]) == + S_STATE_OPENING_CLOSED) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: delayed CLOSING", + get_realmname(config, j), get_username(pointer, numofcon)); + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLOSING); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = n >> 8; /* high bits of user number */ + buff[2] = n; /* low bits of user number */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + } + } + else { + remove_client(pointer, k, &allset, &wset, scheduler); + } + break; + } + case AF_S_CANT_OPEN : { + n = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(ServerRealm_get_usersLimit(pointer))) && + (ConnectClient_get_state(srClientsTable[k]) == + CONNECTCLIENT_STATE_ACCEPTED)) { + if ((ConnectUser_get_state(srUsersTable[numofcon]) == + S_STATE_OPENING) || + (ConnectUser_get_state(srUsersTable[numofcon]) == + S_STATE_OPENING_CLOSED)) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: DROPPED", + get_realmname(config, j), get_username(pointer, numofcon)); + ServerRealm_decrease_connectedUsers(pointer); + ConnectClient_decrease_connected(srClientsTable[k]); + ConnectClient_get_users(srClientsTable[k])[n] = -1; + if (ConnectUser_get_state(srUsersTable[numofcon]) == + S_STATE_OPENING) { + close(ConnectUser_get_connFd(srUsersTable[numofcon])); + } + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLEAR); + } + } + else { + remove_client(pointer, k, &allset, &wset, scheduler); + } + break; + } + case AF_S_MESSAGE : { + if (ConnectClient_get_state(srClientsTable[k]) != + CONNECTCLIENT_STATE_ACCEPTED) { + remove_client(pointer, k, &allset, &wset, scheduler); + break; + } + if (TYPE_IS_UDP(ServerRealm_get_realmType(pointer))) { /* udp */ + n = SslFd_get_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + &buff[5], length); + } + else { + n = SslFd_get_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, length); + } + temp = numofcon; + numofcon = eval_numofcon(pointer, k, numofcon); + if ((numofcon>=0) && (numofcon<(ServerRealm_get_usersLimit(pointer)))) { + if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_OPEN) { + aflog(LOG_T_USER, LOG_I_DEBUG, + "realm[%s]: TO user[%d]: MESSAGE length=%d", + get_realmname(config, j), get_username(pointer, numofcon), n); + UserStats_add_download(ConnectUser_get_stats(srUsersTable[numofcon]), n); + if (TYPE_IS_UDP(ServerRealm_get_realmType(pointer))) { /* udp */ + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + sent = write(ConnectUser_get_connFd(srUsersTable[numofcon]), buff, n+5); + if (sent == -1) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: CLOSED (write-udp)", + get_realmname(config, j), get_username(pointer, numofcon)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(config, j), + get_username(pointer, numofcon), + ConnectUser_get_nameBuf(srUsersTable[numofcon]), + ConnectUser_get_portBuf(srUsersTable[numofcon]), + timeperiod(now - ConnectUser_get_connectTime(srUsersTable[numofcon]))); + close(ConnectUser_get_connFd(srUsersTable[numofcon])); + FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset); + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(srUsersTable[numofcon])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = temp >> 8; /* high bits of user number */ + buff[2] = temp; /* low bits of user number */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + } + } + else { /* tcp */ + sent = write(ConnectUser_get_connFd(srUsersTable[numofcon]), buff, n); + if ((sent > 0) && (sent != n)) { + BufList_insert_back(ConnectUser_get_bufList(srUsersTable[numofcon]), + BufListNode_new_message(sent, n, buff)); + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_STOPPED); + FD_SET(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = temp >> 8; /* high bits of user number */ + buff[2] = temp; /* low bits of user number */ + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", + get_realmname(config, j), get_username(pointer, numofcon), sent, n); + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + } + else if ((sent == -1) && (errno == EAGAIN)) { + BufList_insert_back(ConnectUser_get_bufList(srUsersTable[numofcon]), + BufListNode_new_message(0, n, buff)); + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_STOPPED); + FD_SET(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset); + buff[0] = AF_S_DONT_SEND; /* stopping transfer */ + buff[1] = temp >> 8; /* high bits of user number */ + buff[2] = temp; /* low bits of user number */ + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: TO user[%d]: BUFFERING MESSAGE STARTED (%d/%d)", + get_realmname(config, j), get_username(pointer, numofcon), sent, n); + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + } + else if (sent == -1) { + aflog(LOG_T_USER, LOG_I_INFO, + "realm[%s]: user[%d]: CLOSED (write-tcp)", + get_realmname(config, j), get_username(pointer, numofcon)); + time(&now); + aflog(LOG_T_USER, LOG_I_NOTICE, + "REALM: %s USER: %d IP: %s PORT: %s DURATION: %s", + get_realmname(config, j), + get_username(pointer, numofcon), + ConnectUser_get_nameBuf(srUsersTable[numofcon]), + ConnectUser_get_portBuf(srUsersTable[numofcon]), + timeperiod(now - ConnectUser_get_connectTime(srUsersTable[numofcon]))); + close(ConnectUser_get_connFd(srUsersTable[numofcon])); + FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset); + FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &wset); + ConnectUser_set_state(srUsersTable[numofcon], S_STATE_CLOSING); + BufList_clear(ConnectUser_get_bufList(srUsersTable[numofcon])); + buff[0] = AF_S_CONCLOSED; /* closing connection */ + buff[1] = temp >> 8; /* high bits of user number */ + buff[2] = temp; /* low bits of user number */ + SslFd_send_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + } + } + } + else if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_STOPPED) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: TO user[%d]: BUFFERING MESSAGE (%d)", + get_realmname(config, j), get_username(pointer, numofcon), n); + if (TYPE_IS_UDP(ServerRealm_get_realmType(pointer))) { /* udp */ + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + BufList_insert_back(ConnectUser_get_bufList(srUsersTable[numofcon]), + BufListNode_new_message(0, n+5, buff)); + } + else { + BufList_insert_back(ConnectUser_get_bufList(srUsersTable[numofcon]), + BufListNode_new_message(0, n, buff)); + } + } + else if (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_CLOSING) { + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: TO user[%d]: IGNORED message length=%d", + get_realmname(config, j), get_username(pointer, numofcon), n); + } + else { + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: TO user[%d]: user in wrong state - IGNORED", + get_realmname(config, j), get_username(pointer, numofcon)); + } + } + else { + aflog(LOG_T_USER, LOG_I_WARNING, + "realm[%s]: message to non-existing user - IGNORED", + get_realmname(config, j)); + } + break; + } + case AF_S_LOGIN : { + if ((ConnectClient_get_state(srClientsTable[k]) == + CONNECTCLIENT_STATE_AUTHORIZING) && + (numofcon==(ServerRealm_get_password(pointer)[0]*256+ServerRealm_get_password(pointer)[1])) && + (length==(ServerRealm_get_password(pointer)[2]*256+ServerRealm_get_password(pointer)[3]))) { + ConnectClient_set_multi(srClientsTable[k], CONNECTCLIENT_MULTI_DISABLED); + if (k != ServerRealm_get_clientsLimit(pointer)) { + ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_ACCEPTED); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s]: pass ok - ACCESS GRANTED", + get_realmname(config, j), get_clientname(pointer, k)); + buff[0] = AF_S_LOGIN; /* sending message */ + buff[1] = ConnectClient_get_limit( + srClientsTable[k]) >> 8;/* high bits of user number */ + buff[2] = ConnectClient_get_limit( + srClientsTable[k]); /* low bits of user number */ + buff[3] = ServerRealm_get_realmType(pointer); /* type of connection */ + SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + if ((task = ConnectClient_get_task(srClientsTable[k]))) { + TaskScheduler_removeTask(scheduler, task); + ConnectClient_set_task(srClientsTable[k], NULL); + } + if (ServerRealm_get_maxIdle(pointer)) { + ConnectClient_set_timer(srClientsTable[k], + timeval_create(ServerRealm_get_maxIdle(pointer), 0)); + task = Task_new(ConnectClient_get_timerp(srClientsTable[k]), + RCTfunction, + RCTdata_new(config, j, k, 0, RCT_REASON_MAXIDLE, &allset, &wset), + RCTdata_free); + ConnectClient_set_task(srClientsTable[k], task); + TaskScheduler_addTask(scheduler, task); + } + if (ServerRealm_get_basePortOn(pointer) == 1) { + long tmp_val; + char tmp_tab[6]; + if (check_long( + UsrCli_get_listenPortName( + srUsersClientsTable[ + ConnectClient_get_usrCliPair(srClientsTable[k])]), + &tmp_val)) { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: INVALID listenport - removing Client[%s]", + get_realmname(config, j), get_clientname(pointer, k)); + remove_client(pointer, k, &allset, &wset, scheduler); + break; + } + tmp_val = tmp_val%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + ipfam = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(ServerRealm_get_realmType(pointer))) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(ServerRealm_get_realmType(pointer))) { + ipfam |= 0x04; + } +#endif + while (ip_listen(ConnectClient_get_listenFdp(srClientsTable[k]), + UsrCli_get_listenHostName(srUsersClientsTable[ + ConnectClient_get_usrCliPair(srClientsTable[k])]) ? + UsrCli_get_listenHostName(srUsersClientsTable[ + ConnectClient_get_usrCliPair(srClientsTable[k])]) : + ServerRealm_get_hostName(pointer), + tmp_tab, (&len), ipfam)) { + tmp_val = (tmp_val+1)%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + } + ServerRealm_set_addressLength(pointer, len); + FD_SET(ConnectClient_get_listenFd(srClientsTable[k]), &allset); + maxfdp1 = (maxfdp1>(ConnectClient_get_listenFd(srClientsTable[k])+1)) ? + maxfdp1 : (ConnectClient_get_listenFd(srClientsTable[k]) + 1); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s]: listenport=%s", + get_realmname(config, j), get_clientname(pointer, k), tmp_tab); + } + } + else { + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: client limit EXCEEDED", get_realmname(config, j)); + buff[0] = AF_S_CANT_OPEN; /* sending message */ + SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL, + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + remove_client(pointer, k, &allset, &wset, scheduler); + } + } + else if ((ConnectClient_get_state(srClientsTable[k]) == + CONNECTCLIENT_STATE_ACCEPTED) && (numofcon == 0)) { + n = SslFd_get_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, length); + buff[n] = 0; + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s]: ID received: %s", + get_realmname(config, j), get_clientname(pointer, k), buff); + ConnectClient_set_sClientId(srClientsTable[k], (char*) buff); + } + else { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: Client[%s]: Wrong password - CLOSING", + get_realmname(config, j), get_clientname(pointer, k)); + buff[0] = AF_S_WRONG; /* sending message */ + SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL, + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + remove_client(pointer, k, &allset, &wset, scheduler); + } + break; + } + case AF_S_DONT_SEND: { + if ((ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_OPEN) || + (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_STOPPED)) { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: user[%d]: STOP READING", + get_realmname(config, j), get_username(pointer, numofcon)); + FD_CLR(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset); + } + else { + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "realm[%s]: user[%d]: STOP READING - ignored", + get_realmname(config, j), get_username(pointer, numofcon)); + } + break; + } + case AF_S_CAN_SEND: { + if ((ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_OPEN) || + (ConnectUser_get_state(srUsersTable[numofcon]) == S_STATE_STOPPED)) { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: user[%d]: START READING", + get_realmname(config, j), get_username(pointer, numofcon)); + FD_SET(ConnectUser_get_connFd(srUsersTable[numofcon]), &allset); + } + else { + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "realm[%s]: user[%d]: START READING - ignored", + get_realmname(config, j), get_username(pointer, numofcon)); + } + break; + } + case AF_S_WRONG: { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: Client[%s]: Wrong message - CLOSING", + get_realmname(config, j), get_clientname(pointer, k)); + remove_client(pointer, k, &allset, &wset, scheduler); + break; + } + case AF_S_ADMIN_LOGIN: { + if ((ConnectClient_get_state(srClientsTable[k]) == + CONNECTCLIENT_STATE_AUTHORIZING) && + (numofcon == (ServerRealm_get_password(pointer)[0]*256 + ServerRealm_get_password(pointer)[1])) && + (length == (ServerRealm_get_password(pointer)[2]*256 + ServerRealm_get_password(pointer)[3]))) { + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: Client[%s]: NEW remote admin -- pass OK", + get_realmname(config, j), get_clientname(pointer, k)); + for (l = 0; l < ServerRealm_get_raClientsLimit(pointer); ++l) { + if (ConnectClient_get_state(srRaClientsTable[l]) == + CONNECTCLIENT_STATE_FREE) { + SslFd_set_fd( + ConnectClient_get_sslFd(srRaClientsTable[l]), + SslFd_get_fd( + ConnectClient_get_sslFd(srClientsTable[k]))); + ConnectClient_set_connectTime( + srRaClientsTable[l], + ConnectClient_get_connectTime(srClientsTable[k])); + ConnectClient_set_lastActivity( + srRaClientsTable[l], + ConnectClient_get_lastActivity(srClientsTable[k])); +#ifdef HAVE_LIBPTHREAD + ConnectClient_set_tunnelType( + srRaClientsTable[l], + ConnectClient_get_tunnelType(srClientsTable[k])); +#endif + ConnectClient_set_clientId( + srRaClientsTable[l], + ConnectClient_get_clientId(srClientsTable[k])); + ConnectClient_set_nameBuf( + srRaClientsTable[l], + ConnectClient_get_nameBuf(srClientsTable[k])); + ConnectClient_set_portBuf( + srRaClientsTable[l], + ConnectClient_get_portBuf(srClientsTable[k])); + tmp_ssl = SslFd_get_ssl( + ConnectClient_get_sslFd(srRaClientsTable[l])); + SslFd_set_ssl_nf( + ConnectClient_get_sslFd(srRaClientsTable[l]), + SslFd_get_ssl( + ConnectClient_get_sslFd(srClientsTable[k]))); + SslFd_set_ssl_nf( + ConnectClient_get_sslFd(srClientsTable[k]), + tmp_ssl); + ConnectClient_set_state( + srClientsTable[k], + CONNECTCLIENT_STATE_FREE); + break; + } + } + if (l != ServerRealm_get_raClientsLimit(pointer)) { + ConnectClient_set_state( + srRaClientsTable[l], + CONNECTCLIENT_STATE_ACCEPTED); + ServerRealm_increase_connectedRaClients(pointer); + if ((task = ConnectClient_get_task(srClientsTable[k]))) { + TaskScheduler_removeTask(scheduler, task); + ConnectClient_set_task(srClientsTable[k], NULL); + } + sprintf((char*) &buff[5], AF_VER("AFSERVER")); + n = strlen((char*) &buff[5]); + buff[0] = AF_S_ADMIN_LOGIN; /* sending message */ + buff[1] = ServerRealm_get_realmType(pointer); /* type of connection */ + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL, + ConnectClient_get_sslFd( + srRaClientsTable[l]), + buff, n+5); + } + else { + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: Client[%s]: remote admin -- limit EXCEEDED", + get_realmname(config, j), get_clientname(pointer, k)); + buff[0] = AF_S_CANT_OPEN; /* sending message */ + SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + srClientsTable[k]), + buff, 5); + remove_client(pointer, k, &allset, &wset, scheduler); + } + } + break; + } + case AF_S_KEEP_ALIVE: { + aflog(LOG_T_CLIENT, LOG_I_DEBUG, + "realm[%s]: Client[%s]: Keep alive packet", + get_realmname(config, j), get_clientname(pointer, k)); + break; + } + case AF_S_ENABLE_MULTI: { + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s]: MULTI enabled: %d", + get_realmname(config, j), get_clientname(pointer, k), buff[1]); + ConnectClient_set_multi(srClientsTable[k], CONNECTCLIENT_MULTI_ENABLED); + break; + } + default : { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: Client[%s]: Unrecognized message - CLOSING", + get_realmname(config, j), get_clientname(pointer, k)); + remove_client(pointer, k, &allset, &wset, scheduler); + } + } + } + /* ------------------------------------ */ + for (k = 0; k < ServerRealm_get_raClientsLimit(pointer); ++k) + if ((ConnectClient_get_state(srRaClientsTable[k]) > CONNECTCLIENT_STATE_FREE) && + (FD_ISSET(SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])), &rset))) { + if (ConnectClient_get_state(srRaClientsTable[k]) == CONNECTCLIENT_STATE_CONNECTING) { + make_ssl_initialize(ConnectClient_get_sslFd(srRaClientsTable[k])); + aflog(LOG_T_MANAGE, LOG_I_DDEBUG, + "realm[%s]: new Client[%s] (ra): SSL_accept", + get_realmname(config, j), get_raclientname(pointer, k)); + switch (make_ssl_accept(ConnectClient_get_sslFd(srRaClientsTable[k]))) { + case 2: { + close (SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k]))); + FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])), &allset); + SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(srRaClientsTable[k]))); + ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_FREE); + if ((task = ConnectClient_get_task(srRaClientsTable[k]))) { + TaskScheduler_removeTask(scheduler, task); + ConnectClient_set_task(srRaClientsTable[k], NULL); + } + ServerRealm_decrease_connectedClients(pointer); + aflog(LOG_T_MANAGE, LOG_I_ERR, + "realm[%s]: new Client[%s] (ra): DENIED by SSL_accept", + get_realmname(config, j), get_raclientname(pointer, k)); + } + case 1: { + continue; + } + default: { + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "realm[%s]: new Client[%s] (ra): ACCEPTED by SSL_accept", + get_realmname(config, j), get_raclientname(pointer, k)); + ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_AUTHORIZING); + continue; + } + } + } + aflog(LOG_T_MANAGE, LOG_I_DDEBUG, + "realm[%s]: Client[%s] (ra): commfd: FD_ISSET", + get_realmname(config, j), get_raclientname(pointer, k)); + n = SslFd_get_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + srRaClientsTable[k]), + buff, (-1) * HeaderBuffer_to_read(ConnectClient_get_header(srRaClientsTable[k]))); + if (n == -1) { + if (errno == EAGAIN) { + aflog(LOG_T_MANAGE, LOG_I_DDEBUG, + "realm[%s]: Client[%s] (ra): commfd: EAGAIN", + get_realmname(config, j), get_raclientname(pointer, k)); + continue; + } + else { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "realm[%s]: Client[%s] (ra): commfd: ERROR: %d", + get_realmname(config, j), get_raclientname(pointer, k), errno); + n = 0; + } + } + else if (n != 5) { + if (n != 0) { + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: Client[%s] (ra): header length = %d --> buffering", + get_realmname(config, j), get_raclientname(pointer, k), n); + HeaderBuffer_store(ConnectClient_get_header(srRaClientsTable[k]), buff, n); + if (HeaderBuffer_to_read(ConnectClient_get_header(srRaClientsTable[k])) == 0) { + HeaderBuffer_restore(ConnectClient_get_header(srRaClientsTable[k]), buff); + n = 5; + } + else { + continue; + } + } + } + if (n==0) { + remove_raclient(pointer, k, &allset, &wset, scheduler); + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: Client[%s] (ra): commfd: CLOSED", + get_realmname(config, j), get_raclientname(pointer, k)); + continue; + } + + numofcon = buff[1]; + numofcon = numofcon << 8; + numofcon += buff[2]; /* this is id of user */ + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + if (ConnectClient_get_state(srRaClientsTable[k]) < CONNECTCLIENT_STATE_AUTHORIZING) { + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: Client[%s] (ra): Impossible behaviour --> ignoring", + get_realmname(config, j), get_raclientname(pointer, k)); + continue; + } + if ((ConnectClient_get_state(srRaClientsTable[k]) == CONNECTCLIENT_STATE_AUTHORIZING) && + (buff[0] != AF_S_LOGIN) && (buff[0] != AF_S_ADMIN_LOGIN)) { + buff[0] = AF_S_WRONG; + } + + time(&now); + ConnectClient_set_lastActivity(srRaClientsTable[k], now); + + switch (buff[0]) { + case AF_S_LOGIN : { + if ((ConnectClient_get_state(srRaClientsTable[k]) == + CONNECTCLIENT_STATE_AUTHORIZING) && + (numofcon==(ServerRealm_get_password(pointer)[0]*256+ServerRealm_get_password(pointer)[1])) && + (length==(ServerRealm_get_password(pointer)[2]*256+ServerRealm_get_password(pointer)[3]))) { + ConnectClient_set_multi(srRaClientsTable[k], CONNECTCLIENT_MULTI_DISABLED); + for (l = 0; l < ServerRealm_get_clientsLimit(pointer); ++l) { + if (ConnectClient_get_state(srClientsTable[l]) == + CONNECTCLIENT_STATE_FREE) { + aflog(LOG_T_MANAGE | LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s] (ra) --> Client[%s]", + get_realmname(config, j), + get_raclientname(pointer, k), get_clientname(pointer, l)); + SslFd_set_fd( + ConnectClient_get_sslFd(srClientsTable[l]), + SslFd_get_fd( + ConnectClient_get_sslFd(srRaClientsTable[k]))); + ConnectClient_set_connectTime( + srClientsTable[l], + ConnectClient_get_connectTime(srRaClientsTable[k])); + ConnectClient_set_lastActivity( + srClientsTable[l], + ConnectClient_get_lastActivity(srRaClientsTable[k])); +#ifdef HAVE_LIBPTHREAD + ConnectClient_set_tunnelType( + srClientsTable[l], + ConnectClient_get_tunnelType(srRaClientsTable[k])); +#endif + ConnectClient_set_clientId( + srClientsTable[l], + ConnectClient_get_clientId(srRaClientsTable[k])); + ConnectClient_set_nameBuf( + srClientsTable[l], + ConnectClient_get_nameBuf(srRaClientsTable[k])); + ConnectClient_set_portBuf( + srClientsTable[l], + ConnectClient_get_portBuf(srRaClientsTable[k])); + tmp_ssl = SslFd_get_ssl( + ConnectClient_get_sslFd(srClientsTable[l])); + SslFd_set_ssl_nf( + ConnectClient_get_sslFd(srClientsTable[l]), + SslFd_get_ssl( + ConnectClient_get_sslFd(srRaClientsTable[k]))); + SslFd_set_ssl_nf( + ConnectClient_get_sslFd(srRaClientsTable[k]), + tmp_ssl); + ConnectClient_set_usrCliPair( + srClientsTable[l], + ConnectClient_get_usrCliPair(srRaClientsTable[k])); + ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_FREE); + break; + } + } + if (l != ServerRealm_get_clientsLimit(pointer)) { + ConnectClient_set_state(srClientsTable[l], CONNECTCLIENT_STATE_ACCEPTED); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s]: pass ok - ACCESS GRANTED", + get_realmname(config, j), get_clientname(pointer, l)); + buff[0] = AF_S_LOGIN; /* sending message */ + buff[1] = ConnectClient_get_limit( + srClientsTable[l]) >> 8;/* high bits of user number */ + buff[2] = ConnectClient_get_limit( + srClientsTable[l]); /* low bits of user number */ + buff[3] = ServerRealm_get_realmType(pointer); /* type of connection */ + SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + srClientsTable[l]), + buff, 5); + if ((task = ConnectClient_get_task(srRaClientsTable[k]))) { + TaskScheduler_removeTask(scheduler, task); + ConnectClient_set_task(srRaClientsTable[k], NULL); + } + if (ServerRealm_get_maxIdle(pointer)) { + ConnectClient_set_timer(srClientsTable[l], + timeval_create(ServerRealm_get_maxIdle(pointer), 0)); + task = Task_new(ConnectClient_get_timerp(srClientsTable[l]), + RCTfunction, + RCTdata_new(config, j, l, 0, RCT_REASON_MAXIDLE, &allset, &wset), + RCTdata_free); + ConnectClient_set_task(srClientsTable[l], task); + TaskScheduler_addTask(scheduler, task); + } + if (ServerRealm_get_basePortOn(pointer) == 1) { + long tmp_val; + char tmp_tab[6]; + if (check_long( + UsrCli_get_listenPortName( + srUsersClientsTable[ + ConnectClient_get_usrCliPair(srClientsTable[l])]), + &tmp_val)) { + aflog(LOG_T_CLIENT, LOG_I_ERR, + "realm[%s]: INVALID listenport - removing Client[%s]", + get_realmname(config, j), get_clientname(pointer, l)); + remove_client(pointer, l, &allset, &wset, scheduler); + break; + } + tmp_val = tmp_val%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + ipfam = 0x01; +#ifdef AF_INET6 + if (TYPE_IS_IPV4(ServerRealm_get_realmType(pointer))) { + ipfam |= 0x02; + } + else if (TYPE_IS_IPV6(ServerRealm_get_realmType(pointer))) { + ipfam |= 0x04; + } +#endif + while (ip_listen(ConnectClient_get_listenFdp(srClientsTable[l]), + UsrCli_get_listenHostName(srUsersClientsTable[ + ConnectClient_get_usrCliPair(srClientsTable[l])]) ? + UsrCli_get_listenHostName(srUsersClientsTable[ + ConnectClient_get_usrCliPair(srClientsTable[l])]) : + ServerRealm_get_hostName(pointer), + tmp_tab, (&len), ipfam)) { + tmp_val = (tmp_val+1)%65536; + memset(tmp_tab, 0, 6); + sprintf(tmp_tab, "%d", (int)tmp_val); + } + ServerRealm_set_addressLength(pointer, len); + FD_SET(ConnectClient_get_listenFd(srClientsTable[l]), &allset); + maxfdp1 = (maxfdp1>(ConnectClient_get_listenFd(srClientsTable[l])+1)) ? + maxfdp1 : (ConnectClient_get_listenFd(srClientsTable[l])+1); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: Client[%s]: listenport=%s", + get_realmname(config, j), get_clientname(pointer, l), tmp_tab); + } + } + else { + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: client limit EXCEEDED", get_realmname(config, j)); + buff[0] = AF_S_CANT_OPEN; /* sending message */ + SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + srRaClientsTable[k]), + buff, 5); + remove_raclient(pointer, k, &allset, &wset, scheduler); + } + } + else if ((ConnectClient_get_state(srRaClientsTable[k]) == + CONNECTCLIENT_STATE_ACCEPTED) && (numofcon == 0)) { + n = SslFd_get_message(ServerRealm_get_realmType(pointer), + ConnectClient_get_sslFd( + srRaClientsTable[k]), + buff, length); + buff[n] = 0; + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: Client[%s] (ra): ID received: %s", + get_realmname(config, j), get_raclientname(pointer, k), buff); + ConnectClient_set_sClientId(srRaClientsTable[k], (char*) buff); + } + else { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "realm[%s]: Client[%s] (ra): Wrong password - CLOSING", + get_realmname(config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, scheduler); + } + break; + } + case AF_S_WRONG: { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "realm[%s]: Client[%s] (ra): Wrong message - CLOSING", + get_realmname(config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, scheduler); + break; + } + case AF_S_ADMIN_LOGIN: { + if ((ConnectClient_get_state(srRaClientsTable[k]) == + CONNECTCLIENT_STATE_AUTHORIZING) && + (numofcon==(ServerRealm_get_password(pointer)[0]*256+ServerRealm_get_password(pointer)[1])) && + (length==(ServerRealm_get_password(pointer)[2]*256+ServerRealm_get_password(pointer)[3]))) { + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: Client[%s] (ra): NEW remote admin -- pass OK", + get_realmname(config, j), get_raclientname(pointer, k)); + ConnectClient_set_state( + srRaClientsTable[k], + CONNECTCLIENT_STATE_ACCEPTED); + ServerRealm_increase_connectedRaClients(pointer); + if ((task = ConnectClient_get_task(srRaClientsTable[k]))) { + TaskScheduler_removeTask(scheduler, task); + ConnectClient_set_task(srRaClientsTable[k], NULL); + } + sprintf((char*) &buff[5], AF_VER("AFSERVER")); + n = strlen((char*) &buff[5]); + buff[0] = AF_S_ADMIN_LOGIN; /* sending message */ + buff[1] = ServerRealm_get_realmType(pointer); /* type of connection */ + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB, + ConnectClient_get_sslFd( + srRaClientsTable[k]), + buff, n+5); + } + break; + } + case AF_S_ADMIN_CMD: { + if (ConnectClient_get_state(srRaClientsTable[k]) == + CONNECTCLIENT_STATE_ACCEPTED) { + if ((n = serve_admin(config, j, k, buff))) { + if (n == 1) { + aflog(LOG_T_MANAGE, LOG_I_NOTICE, + "realm[%s]: Client[%s] (ra): remote admin -- closing", + get_realmname(config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, scheduler); + } + else { + for (i = 0; i < ServerConfiguration_get_realmsNumber(config); ++i) { + srClientsTable = ServerRealm_get_clientsTable(scRealmsTable[i]); + l = get_clientnumber(scRealmsTable[i], n-2); + if (l != -1) { + aflog(LOG_T_MANAGE, LOG_I_NOTICE, + "realm[%s]: Client[%s] (ra): remote admin: KICKING realm[%s]: Client[%s]", + get_realmname(config, j), get_raclientname(pointer, k), + get_realmname(config, i), + get_clientname(scRealmsTable[i], l)); + buff[0] = AF_S_CLOSING; /* closing */ + SslFd_send_message(ServerRealm_get_realmType(scRealmsTable[i]), + ConnectClient_get_sslFd( + srClientsTable[l]), + buff, 5); + time(&now); + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "REALM: %s CLIENT: %s IP: %s PORT: %s DURATION: %s", + get_realmname(config, j), + get_clientname(scRealmsTable[i], l), + ConnectClient_get_nameBuf(srClientsTable[l]), + ConnectClient_get_portBuf(srClientsTable[l]), + timeperiod(now - ConnectClient_get_connectTime( + srClientsTable[l]))); + if (ServerRealm_get_auditOn(scRealmsTable[i])) { + while (AuditList_get_first( + ConnectClient_get_auditList( + srClientsTable[l]))) { + aflog(LOG_T_CLIENT, LOG_I_NOTICE, + "USERID: %d IP: %s PORT: %s CONNECTED: %s DURATION: %s", + AuditListNode_get_userId( + AuditList_get_first( + ConnectClient_get_auditList( + srClientsTable[l]))), + AuditListNode_get_nameBuf( + AuditList_get_first( + ConnectClient_get_auditList( + srClientsTable[l]))), + AuditListNode_get_portBuf( + AuditList_get_first( + ConnectClient_get_auditList( + srClientsTable[l]))), + localdate( + AuditListNode_get_connectTimep( + AuditList_get_first( + ConnectClient_get_auditList( + srClientsTable[l])))), + timeperiod( + AuditListNode_get_duration( + AuditList_get_first( + ConnectClient_get_auditList( + srClientsTable[l]))))); + AuditList_delete_first( + ConnectClient_get_auditList( + srClientsTable[l])); + } + } + remove_client(scRealmsTable[i], l, + &allset, &wset, scheduler); + break; + } + } + } + } + } + else { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "realm[%s]: Client[%s] (ra): remote admin -- security VIOLATION", + get_realmname(config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, scheduler); + } + break; + } + case AF_S_KEEP_ALIVE: { + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "realm[%s]: Client[%s] (ra): Keep alive packet", + get_realmname(config, j), get_raclientname(pointer, k)); + break; + } + default : { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "realm[%s]: Client[%s] (ra): Unrecognized message - CLOSING", + get_realmname(config, j), get_raclientname(pointer, k)); + remove_raclient(pointer, k, &allset, &wset, scheduler); + } + } + } + /* ------------------------------------ */ + for (l = 0; l < ServerRealm_get_userClientPairs(pointer); ++l) { + if (FD_ISSET(UsrCli_get_manageFd(srUsersClientsTable[l]), &rset)) { + + aflog(LOG_T_CLIENT, LOG_I_DDEBUG, + "realm[%s]: managefd: FD_ISSET", get_realmname(config, j)); + len = ServerRealm_get_addressLength(pointer); +#ifdef HAVE_LIBPTHREAD + sent = get_new_socket(UsrCli_get_manageFd(srUsersClientsTable[l]), + ServerRealm_get_tunnelType(pointer),ServerRealm_get_clientAddress(pointer), &len, &tunneltype); +#else + sent = accept(UsrCli_get_manageFd(srUsersClientsTable[l]), ServerRealm_get_clientAddress(pointer), &len); +#endif + if (sent == -1) { + if (errno == EAGAIN) { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: managefd: FD_ISSET --> EAGAIN", get_realmname(config, j)); + } + else { + aflog(LOG_T_USER, LOG_I_DDEBUG, + "realm[%s]: managefd: FD_ISSET --> errno=%d", get_realmname(config, j), errno); + } + break; + } + flags = fcntl(sent, F_GETFL, 0); + fcntl(sent, F_SETFL, flags | O_NONBLOCK); + for (k = 0; k < ServerRealm_get_clientsLimit(pointer); ++k) { + if (ConnectClient_get_state(srClientsTable[k]) == CONNECTCLIENT_STATE_FREE) { + ConnectClient_set_clientId(srClientsTable[k], ServerRealm_get_clientsCounter(pointer)); + ServerRealm_increase_clientsCounter(pointer); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: new Client[%s]: CONNECTING", + get_realmname(config, j), get_clientname(pointer, k)); + SslFd_set_fd(ConnectClient_get_sslFd(srClientsTable[k]), sent); + ConnectClient_set_usrCliPair(srClientsTable[k], l); + time(&now); + ConnectClient_set_connectTime(srClientsTable[k], now); + ConnectClient_set_lastActivity(srClientsTable[k], now); +#ifdef HAVE_LIBPTHREAD + ConnectClient_set_tunnelType(srClientsTable[k], tunneltype); +#endif + aflog(LOG_T_CLIENT, LOG_I_INFO, + "realm[%s]: new Client[%s] IP:%s", get_realmname(config, j), get_clientname(pointer, k), + sock_ntop(ServerRealm_get_clientAddress(pointer), len, ConnectClient_get_nameBuf(srClientsTable[k]), + ConnectClient_get_portBuf(srClientsTable[k]), ServerRealm_get_dnsLookupsOn(pointer))); + FD_SET(SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])), &allset); + maxfdp1 = (maxfdp1 > (SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])) + 1)) ? + maxfdp1 : (SslFd_get_fd(ConnectClient_get_sslFd(srClientsTable[k])) + 1); + ServerRealm_increase_connectedClients(pointer); + ConnectClient_set_timer(srClientsTable[k], timeval_create(ServerRealm_get_timeout(pointer), 0)); + task = Task_new(ConnectClient_get_timerp(srClientsTable[k]), + RCTfunction, + RCTdata_new(config, j, k, 0, RCT_REASON_TIMEOUT, &allset, &wset), + RCTdata_free); + ConnectClient_set_task(srClientsTable[k], task); + TaskScheduler_addTask(scheduler, task); + ConnectClient_set_state(srClientsTable[k], CONNECTCLIENT_STATE_CONNECTING); + break; + } + } + if (k == ServerRealm_get_clientsLimit(pointer)) { + for (k = 0; k < ServerRealm_get_raClientsLimit(pointer); ++k) { + if (ConnectClient_get_state(srRaClientsTable[k]) == + CONNECTCLIENT_STATE_FREE) { + ConnectClient_set_clientId(srRaClientsTable[k], ServerRealm_get_clientsCounter(pointer)); + ServerRealm_increase_clientsCounter(pointer); + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: new Client[%s] (ra): CONNECTING", + get_realmname(config, j), get_raclientname(pointer, k)); + SslFd_set_fd(ConnectClient_get_sslFd(srRaClientsTable[k]), sent); + ConnectClient_set_usrCliPair(srRaClientsTable[k], l); + time(&now); + ConnectClient_set_connectTime(srRaClientsTable[k], now); + ConnectClient_set_lastActivity(srRaClientsTable[k], now); +#ifdef HAVE_LIBPTHREAD + ConnectClient_set_tunnelType(srRaClientsTable[k], tunneltype); +#endif + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: new Client[%s] (ra) IP:%s", + get_realmname(config, j), get_raclientname(pointer, k), + sock_ntop(ServerRealm_get_clientAddress(pointer), len, + ConnectClient_get_nameBuf(srRaClientsTable[k]), + ConnectClient_get_portBuf(srRaClientsTable[k]), + ServerRealm_get_dnsLookupsOn(pointer))); + FD_SET(SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])), &allset); + maxfdp1 = (maxfdp1 > (SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])) + 1)) ? + maxfdp1 : (SslFd_get_fd(ConnectClient_get_sslFd(srRaClientsTable[k])) + 1); + ServerRealm_increase_connectedClients(pointer); + ConnectClient_set_timer(srRaClientsTable[k], + timeval_create(ServerRealm_get_timeout(pointer), 0)); + task = Task_new(ConnectClient_get_timerp(srRaClientsTable[k]), + RCTfunction, + RCTdata_new(config, j, k, 1, RCT_REASON_TIMEOUT, &allset, &wset), + RCTdata_free); + ConnectClient_set_task(srRaClientsTable[k], task); + TaskScheduler_addTask(scheduler, task); + ConnectClient_set_state(srRaClientsTable[k], CONNECTCLIENT_STATE_CONNECTING); + break; + } + } + if (k == ServerRealm_get_raClientsLimit(pointer)) { + aflog(LOG_T_CLIENT | LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: client limit EXCEEDED", get_realmname(config, j)); + close(sent); + } + } + break; + } + } + } /* realms loop */ + } +} diff --git a/src/afserver.h b/src/afserver.h new file mode 100644 index 0000000..bc23e75 --- /dev/null +++ b/src/afserver.h @@ -0,0 +1,57 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "network.h" +#include "file.h" +#include "stats.h" +#include "server_remoteadmin.h" +#include "server_check.h" +#include "server_set.h" +#include "server_eval.h" +#include "server_find.h" +#include "server_remove.h" +#include "make_ssl_handshake.h" +#include "first_run.h" +#include "realmnames.h" +#include "clientnames.h" +#include "usernames.h" +#include "server_get.h" +#include "http_proxy_server.h" +#include "thread_management.h" +#include "server_signals.h" +#include "usage.h" +#include "logging.h" +#include "daemon.h" +#include "timeval_functions.h" +#include "remove_client_task.h" + +#include <openssl/ssl.h> +#include <openssl/err.h> +#include <fcntl.h> +#include <signal.h> +#include <string.h> +#include <getopt.h> + +#ifndef _JS_AFSERVER_H +#define _JS_AFSERVER_H + +#endif + diff --git a/src/ar_options_struct.c b/src/ar_options_struct.c new file mode 100644 index 0000000..093ddb9 --- /dev/null +++ b/src/ar_options_struct.c @@ -0,0 +1,313 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "ar_options_struct.h" +#include "string_functions.h" +#include "server_check.h" + +/* + * Function name: ArOptions_new + * Description: Create and initialize new ArOptions structure. + * Returns: Pointer to newly created ArOptions structure. + */ + +ArOptions* +ArOptions_new() +{ + ArOptions* tmp = calloc(1, sizeof(ArOptions)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + tmp->premature = AR_OPTION_ENABLED; + tmp->delay = 5; + tmp->tries = -1; + return tmp; +} + +/* + * Function name: ArOptions_free + * Description: Free the memory allocated for ArOptions structure. + * Arguments: ao - pointer to pointer to ArOptions structure + */ + +void +ArOptions_free(ArOptions** ao) +{ + assert(ao != NULL); + if (ao == NULL) { + return; + } + assert((*ao) != NULL); + if ((*ao) == NULL) { + return; + } + if ((*ao)->artries) { + free((*ao)->artries); + (*ao)->artries = NULL; + } + if ((*ao)->ardelay) { + free((*ao)->ardelay); + (*ao)->ardelay = NULL; + } + free((*ao)); + (*ao) = NULL; +} + +/* + * Function name: ArOptions_set_asTries + * Description: Set how many times afclient will try to reconnect. + * Arguments: ao - pointer to ArOptions structure + * tries - how many times afclient will try to reconnect + * <0 - unlimited + * 0 - disabled + * >0 - exact number + */ + +void +ArOptions_set_arTries(ArOptions* ao, int tries) +{ + assert(ao != NULL); + if (ao == NULL) { + return; + } + ao->tries = tries; +} + +/* + * Function name: ArOptions_set_s_arTries + * Description: Set string describing how many times afclient will try to reconnect. + * This string has to be evaluated later in order to really set arTries value. + * Arguments: ao - pointer to ArOptions structure + * tries - string describing how many times afclient will try to reconnect. + */ + +void +ArOptions_set_s_arTries(ArOptions* ao, char* tries) +{ + assert(ao != NULL); + if (ao == NULL) { + return; + } + string_cp(&(ao->artries), tries); +} + +/* + * Function name: ArOptions_set_arDelay + * Description: Set how long afclient will wait between reconnect tries. + * Arguments: ao - pointer to ArOptions structure + * delay - how long afclient will wait between reconnect tries + */ + +void +ArOptions_set_arDelay(ArOptions* ao, int delay) +{ + assert(ao != NULL); + if (ao == NULL) { + return; + } + ao->delay = delay; +} + +/* + * Function name: ArOptions_set_s_arDelay + * Description: Set string describing how long afclient will wait between reconnect tries. + * This string has to be evaluated later in order to really set arDelay value. + * Arguments: ao - pointer to ArOptions structure + * delay - string describing how long afclient will wait between reconnect tries. + */ + +void +ArOptions_set_s_arDelay(ArOptions* ao, char* delay) +{ + assert(ao != NULL); + if (ao == NULL) { + return; + } + string_cp(&(ao->ardelay), delay); +} + +/* + * Function name: ArOptions_set_arStart + * Description: Enable/disable auto-reconnection when afserver is not reachable on start. + * Arguments: ao - pointer to ArOptions structure + * start - value which enable (AR_OPTION_ENABLED) or disable (AR_OPTION_DISABLED) + * auto-reconnection when afserver is not reachable on start + */ + +void +ArOptions_set_arStart(ArOptions* ao, char start) +{ + assert(ao != NULL); + if (ao == NULL) { + return; + } + ao->start = start; +} + +/* + * Function name: ArOptions_set_arQuit + * Description: Enable/disable auto-reconnection after normal afserver quit. + * Arguments: ao - pointer to ArOptions structure + * quit - value which enable (AR_OPTION_ENABLED) or disable (AR_OPTION_DISABLED) + * auto-reconnection after normal afserver quit + */ + +void +ArOptions_set_arQuit(ArOptions* ao, char quit) +{ + assert(ao != NULL); + if (ao == NULL) { + return; + } + ao->quit = quit; +} + +/* + * Function name: ArOptions_set_arPremature + * Description: Enable/disable auto-reconnection after premature afserver quit. + * Arguments: ao - pointer to ArOptions structure + * premature - value which enable (AR_OPTION_ENABLED) or disable (AR_OPTION_DISABLED) + * auto-reconnection after premature afserver quit + */ + +void +ArOptions_set_arPremature(ArOptions* ao, char premature) +{ + assert(ao != NULL); + if (ao == NULL) { + return; + } + ao->premature = premature; +} + +/* + * Function name: ArOptions_get_arTries + * Description: Get how many times afclient will try to reconnect. + * Arguments: ao - pointer to ArOptions structure + * Returns: How many times afclient will try to reconnect. + */ + +int +ArOptions_get_arTries(ArOptions* ao) +{ + assert(ao != NULL); + if (ao == NULL) { + return 0; + } + return ao->tries; +} + +/* + * Function name: ArOptions_get_arDelay + * Description: Get how long afclient will wait between reconnect tries. + * Arguments: ao - pointer to ArOptions structure + * Returns: How long afclient will wait between reconnect time. + */ + +int +ArOptions_get_arDelay(ArOptions* ao) +{ + assert(ao != NULL); + if (ao == NULL) { + return 0; + } + return ao->delay; +} + +/* + * Function name: ArOptions_get_arStart + * Description: Get status of the auto-reconnection when afserver is not reachable on start. + * Arguments: ao - pointer to ArOptions structure + * Returns: Status of the auto-reconnection when afserver is not reachable on start. + */ + +char +ArOptions_get_arStart(ArOptions* ao) +{ + assert(ao != NULL); + if (ao == NULL) { + return AR_OPTION_DISABLED; + } + return ao->start; +} + +/* + * Function name: ArOptions_get_arQuit + * Description: Get status of the auto-reconnection after normal afserver quit. + * Arguments: ao - pointer to ArOptions structure + * Returns: Status of the auto-reconnection after normal afserver quit. + */ + +char +ArOptions_get_arQuit(ArOptions* ao) +{ + assert(ao != NULL); + if (ao == NULL) { + return AR_OPTION_DISABLED; + } + return ao->quit; +} + +/* + * Function name: ArOptions_get_arPremature + * Description: Get status of the auto-reconnection after premature afserver quit. + * Arguments: ao - pointer to ArOptions structure + * Returns: Status of the auto-reconnection after premature afserver quit. + */ + +char +ArOptions_get_arPremature(ArOptions* ao) +{ + assert(ao != NULL); + if (ao == NULL) { + return AR_OPTION_DISABLED; + } + return ao->premature; +} + +/* + * Function name: ArOptions_evaluate_values + * Description: Evaluate arTries and arDelay values. These values are checked, when are not NULL. + * arTries have to be an integer, arDelay have to be an integer >0. If any of the + * variables is wrong, program terminates abnormally. + * Arguments: ao - pointer to ArOptions structure + */ + +void +ArOptions_evaluate_values(ArOptions* ao) +{ + assert(ao != NULL); + if (ao == NULL) { + return; + } + if (ao->artries) { + ao->tries = check_value_liberal(ao->artries, "Invalid ar-tries value"); + } + if (ao->ardelay) { + ao->delay = check_value(ao->ardelay, "Invalid ar-delay value"); + } +} diff --git a/src/ar_options_struct.h b/src/ar_options_struct.h new file mode 100644 index 0000000..2d0c59e --- /dev/null +++ b/src/ar_options_struct.h @@ -0,0 +1,59 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _JS_AR_OPTIONS_STRUCT_H +#define _JS_AR_OPTIONS_STRUCT_H + +#define AR_OPTION_DISABLED 0 +#define AR_OPTION_ENABLED 1 + +typedef struct { + char* artries; + int tries; + char* ardelay; + int delay; + char start; + char quit; + char premature; +} ArOptions; + +/* 'constructor' */ +ArOptions* ArOptions_new(); +/* 'destructor' */ +void ArOptions_free(ArOptions** ao); +/* setters */ +void ArOptions_set_arTries(ArOptions* ao, int tries); +void ArOptions_set_s_arTries(ArOptions* ao, char* tries); +void ArOptions_set_arDelay(ArOptions* ao, int delay); +void ArOptions_set_s_arDelay(ArOptions* ao, char* delay); +void ArOptions_set_arStart(ArOptions* ao, char start); +void ArOptions_set_arQuit(ArOptions* ao, char quit); +void ArOptions_set_arPremature(ArOptions* ao, char premature); +/* getters */ +int ArOptions_get_arTries(ArOptions* ao); +int ArOptions_get_arDelay(ArOptions* ao); +char ArOptions_get_arStart(ArOptions* ao); +char ArOptions_get_arQuit(ArOptions* ao); +char ArOptions_get_arPremature(ArOptions* ao); +/* other */ +void ArOptions_evaluate_values(ArOptions* ao); + +#endif diff --git a/src/audit_list_node_struct.c b/src/audit_list_node_struct.c new file mode 100644 index 0000000..5e7a674 --- /dev/null +++ b/src/audit_list_node_struct.c @@ -0,0 +1,316 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "audit_list_node_struct.h" + +/* + * Function name: AuditListNode_new + * Description: Create and initialize new AuditListNode structure. + * Returns: Newly created AuditListNode structure. + */ + +AuditListNode* +AuditListNode_new() +{ + AuditListNode* tmp = calloc(1, sizeof(AuditListNode)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: AuditListNode_new_entry + * Description: Create and initialize new AuditListNode structure from given arguments. + * Arguments: userId - identification number of the user + * nameBuf - name of the user + * portBuf - port from which user is connected + * connectTime - start time of the connection + * duration - duration of the connection + * Returns: Newly created and initialized AuditListNode structure. + */ + +AuditListNode* +AuditListNode_new_entry(int userId, char* nameBuf, char* portBuf, + time_t connectTime, time_t duration) +{ + AuditListNode* tmp = calloc(1, sizeof(AuditListNode)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + AuditListNode_set_userId(tmp, userId); + AuditListNode_set_nameBuf(tmp, nameBuf); + AuditListNode_set_portBuf(tmp, portBuf); + AuditListNode_set_connectTime(tmp, connectTime); + AuditListNode_set_duration(tmp, duration); + return tmp; +} + +/* + * Function name: AuditListNode_free + * Description: Free the memory allocated for AuditListNode structure. + * Arguments: aln - pointer to pointer to AuditListNode structure + */ + +void +AuditListNode_free(AuditListNode** aln) +{ + assert(aln != NULL); + if (aln == NULL) { + return; + } + assert((*aln) != NULL); + if ((*aln) == NULL) { + return; + } + free((*aln)); + (*aln) = NULL; +} + +/* + * Function name: AuditListNode_set_userId + * Description: Set user identification number. + * Arguments: aln - pointer to AuditListNode structure + * userId - user identification number + */ + +void +AuditListNode_set_userId(AuditListNode* aln, int userId) +{ + assert(aln != NULL); + if (aln == NULL) { + return; + } + aln->userId = userId; +} + +/* + * Function name: AuditListNode_set_nameBuf + * Description: Set user name. + * Arguments: aln - pointer to AuditListNode structure + * nameBuf - user name + */ + +void +AuditListNode_set_nameBuf(AuditListNode* aln, char* nameBuf) +{ + assert(aln != NULL); + if (aln == NULL) { + return; + } + memset(aln->nameBuf, 0, 7); + strncpy(aln->nameBuf, nameBuf, 6); +} + +/* + * Function name: AuditListNode_set_portBuf + * Description: Set port from which user is connected. + * Arguments: aln - pointer to AuditListNode structure + * portBuf - port from which user is connected + */ + +void +AuditListNode_set_portBuf(AuditListNode* aln, char* portBuf) +{ + assert(aln != NULL); + if (aln == NULL) { + return; + } + memset(aln->portBuf, 0, 7); + strncpy(aln->portBuf, portBuf, 6); +} + +/* + * Function name: AuditListNode_set_connectTime + * Description: Set start time of the connection. + * Arguments: aln - pointer to AuditListNode structure + * connectTime - start time of the connection + */ + +void +AuditListNode_set_connectTime(AuditListNode* aln, time_t connectTime) +{ + assert(aln != NULL); + if (aln == NULL) { + return; + } + aln->connectTime = connectTime; +} + +/* + * Function name: AuditListNode_set_duration + * Description: Set duration of the connection. + * Arguments: aln - pointer to AuditListNode structure + * duration - duration of the connection + */ + +void +AuditListNode_set_duration(AuditListNode* aln, time_t duration) +{ + assert(aln != NULL); + if (aln == NULL) { + return; + } + aln->duration = duration; +} + +/* + * Function name: AuditListNode_set_nextNode + * Description: Set next node pointer. + * Arguments: aln - pointer to AuditListNode structure + * nextNode - next node pointer + */ + +void +AuditListNode_set_nextNode(AuditListNode* aln, AuditListNode* nextNode) +{ + assert(aln != NULL); + if (aln == NULL) { + return; + } + aln->nextNode = nextNode; +} + +/* + * Function name: AuditListNode_get_userId + * Description: Get user identification number. + * Arguments: aln - pointer to AuditListNode structure + * Returns: User identification number. + */ + +int +AuditListNode_get_userId(AuditListNode* aln) +{ + assert(aln != NULL); + if (aln == NULL) { + return -1; + } + return aln->userId; +} + +/* + * Function name: AuditListNode_get_nameBuf + * Description: Get user name. + * Arguments: aln - pointer to AuditListNode structure + * Returns: User name. + */ + +char* +AuditListNode_get_nameBuf(AuditListNode* aln) +{ + assert(aln != NULL); + if (aln == NULL) { + return NULL; + } + return aln->nameBuf; +} + +/* + * Function name: AuditListNode_get_portBuf + * Description: Get port from which user is connected. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Port from which user is connected. + */ + +char* +AuditListNode_get_portBuf(AuditListNode* aln) +{ + assert(aln != NULL); + if (aln == NULL) { + return NULL; + } + return aln->portBuf; +} + +/* + * Function name: AuditListNode_get_connectTime + * Description: Get start time of the connection. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Start time of the connection. + */ + +time_t +AuditListNode_get_connectTime(AuditListNode* aln) +{ + assert(aln != NULL); + if (aln == NULL) { + return 0; + } + return aln->connectTime; +} + +/* + * Function name: AuditListNode_get_duration + * Description: Get duration of the connection. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Duration of the connection. + */ + +time_t +AuditListNode_get_duration(AuditListNode* aln) +{ + assert(aln != NULL); + if (aln == NULL) { + return 0; + } + return aln->duration; +} + +/* + * Function name: AuditListNode_get_nextNode + * Description: Get next node pointer. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Next node pointer. + */ + +AuditListNode* +AuditListNode_get_nextNode(AuditListNode* aln) +{ + assert(aln != NULL); + if (aln == NULL) { + return NULL; + } + return aln->nextNode; +} + +/* + * Function name: AuditListNode_get_connectTimep + * Description: Get pointer to time_t variable holding start time of the connection. + * Arguments: aln - pointer to AuditListNode structure + * Returns: Pointer to time_t variable holding start time of the connection. + */ + +time_t* +AuditListNode_get_connectTimep(AuditListNode* aln) +{ + assert(aln != NULL); + if (aln == NULL) { + return 0; + } + return (&(aln->connectTime)); +} diff --git a/src/audit_list_node_struct.h b/src/audit_list_node_struct.h new file mode 100644 index 0000000..37c085c --- /dev/null +++ b/src/audit_list_node_struct.h @@ -0,0 +1,58 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <time.h> + +#ifndef _JS_AUDIT_LIST_NODE_STRUCT_H +#define _JS_AUDIT_LIST_NODE_STRUCT_H + +typedef struct alnode { + int userId; + char nameBuf[128]; + char portBuf[7]; + time_t connectTime; + time_t duration; + struct alnode* nextNode; +} AuditListNode; + +/* 'constructors' */ +AuditListNode* AuditListNode_new(); +AuditListNode* AuditListNode_new_entry(int userId, char* nameBuf, char* portBuf, + time_t connectTime, time_t duration); +/* 'destructor' */ +void AuditListNode_free(AuditListNode** aln); +/* setters */ +void AuditListNode_set_userId(AuditListNode* aln, int userId); +void AuditListNode_set_nameBuf(AuditListNode* aln, char* nameBuf); +void AuditListNode_set_portBuf(AuditListNode* aln, char* portBuf); +void AuditListNode_set_connectTime(AuditListNode* aln, time_t connectTime); +void AuditListNode_set_duration(AuditListNode* aln, time_t duration); +void AuditListNode_set_nextNode(AuditListNode* aln, AuditListNode* nextNode); +/* getters */ +int AuditListNode_get_userId(AuditListNode* aln); +char* AuditListNode_get_nameBuf(AuditListNode* aln); +char* AuditListNode_get_portBuf(AuditListNode* aln); +time_t AuditListNode_get_connectTime(AuditListNode* aln); +time_t AuditListNode_get_duration(AuditListNode* aln); +AuditListNode* AuditListNode_get_nextNode(AuditListNode* aln); +/* other */ +time_t* AuditListNode_get_connectTimep(AuditListNode* aln); + +#endif diff --git a/src/audit_list_struct.c b/src/audit_list_struct.c new file mode 100644 index 0000000..dca58d3 --- /dev/null +++ b/src/audit_list_struct.c @@ -0,0 +1,152 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "audit_list_struct.h" + +/* + * Function name: AuditList_new + * Description: Create and initialize new AuditList structure. + * Returns: Newly created AuditList structure. + */ + +AuditList* +AuditList_new() +{ + AuditList* tmp = calloc(1, sizeof(AuditList)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: AuditList_free + * Description: Free the memory allocated for AuditList structure. + * Arguments: al - pointer to pointer to AuditList structure. + */ + +void +AuditList_free(AuditList** al) +{ + assert(al != NULL); + if (al == NULL) { + return; + } + assert((*al) != NULL); + if ((*al) == NULL) { + return; + } + AuditList_clear((*al)); + free((*al)); + (*al) = NULL; +} + +/* + * Function name: AuditList_insert_back + * Description: Insert new node at the end of the list. + * Arguments: al - pointer to AuditList structure + * aln - pointer to AuditListNode structure + */ + +void +AuditList_insert_back(AuditList* al, AuditListNode* aln) +{ + assert(al != NULL); + if (al == NULL) { + return; + } + assert(aln != NULL); + if (aln == NULL) { + return; + } + if (al->tail) { + al->tail->nextNode = aln; + } + else { + al->head = aln; + } + al->tail = aln; + aln->nextNode = NULL; +} + +/* + * Function name: AuditList_get_first + * Description: Get first node from the beginning of the list. + * Arguments: al - pointer to AuditList structure + * Returns: First node from the beginning of the list. + */ + +AuditListNode* +AuditList_get_first(AuditList* al) +{ + assert(al != NULL); + if (al == NULL) { + return NULL; + } + return al->head; +} + +/* + * Function name: AuditList_delete_first + * Description: Deletes first node from the beginning of the list. + * Arguments: al - pointer to AuditList structure + */ + +void +AuditList_delete_first(AuditList* al) +{ + AuditListNode* tmp = AuditList_get_first(al); + assert(tmp != NULL); + if (tmp == NULL) { + return; + } + if (tmp == al->tail) { /* this is the last node in the list */ + al->head = al->tail = NULL; + } + else { /* there are other nodes*/ + al->head = AuditListNode_get_nextNode(tmp); + } + AuditListNode_free(&tmp); +} + +/* + * Function name: AuditList_clear + * Description: Deletes all nodes from the list. + * Arguments: al - pointer to AuditList structure + */ + +void +AuditList_clear(AuditList* al) +{ + assert(al != NULL); + if (al == NULL) { + return; + } + while (AuditList_get_first(al)) { + AuditList_delete_first(al); + } +} diff --git a/src/audit_list_struct.h b/src/audit_list_struct.h new file mode 100644 index 0000000..c70f510 --- /dev/null +++ b/src/audit_list_struct.h @@ -0,0 +1,41 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_AUDIT_LIST_STRUCT_H +#define _JS_AUDIT_LIST_STRUCT_H + +#include "audit_list_node_struct.h" + +typedef struct auditlist { + AuditListNode* head; + AuditListNode* tail; +} AuditList; + +/* 'constructor' */ +AuditList* AuditList_new(); +/* 'destructor' */ +void AuditList_free(AuditList** al); +/* other */ +void AuditList_insert_back(AuditList* al, AuditListNode* aln); +AuditListNode* AuditList_get_first(AuditList* al); +void AuditList_delete_first(AuditList* al); +void AuditList_clear(AuditList* al); + +#endif diff --git a/src/base64.c b/src/base64.c new file mode 100644 index 0000000..42eb42c --- /dev/null +++ b/src/base64.c @@ -0,0 +1,250 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "base64.h" + +/* + * Copyright (c) 1996, 1998 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +int +b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) +{ + size_t datalength = 0; + uint8_t input[3]; + uint8_t output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + if (output[0] >= 64) return -1; + if (output[1] >= 64) return -1; + if (output[2] >= 64) return -1; + if (output[3] >= 64) return -1; + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = (uint8_t) '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + if (output[0] >= 64) return -1; + if (output[1] >= 64) return -1; + if (output[2] >= 64) return -1; + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (int) (datalength); +} + +int +b64_pton(char const *src, uint8_t *target, size_t targsize) +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) { + /* A non-base64 character. */ + return (-1); + } + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace((unsigned char)ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/src/base64.h b/src/base64.h new file mode 100644 index 0000000..442b550 --- /dev/null +++ b/src/base64.h @@ -0,0 +1,41 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef _JS_BASE64_H +#define _JS_BASE64_H + +/* routine to encode src with base64 algorithm */ +int b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize); +/* routine to decode src with base64 algorithm */ +int b64_pton(char const *src, uint8_t *target, size_t targsize); + +#endif diff --git a/src/buf_list_node_struct.c b/src/buf_list_node_struct.c new file mode 100644 index 0000000..5416ce3 --- /dev/null +++ b/src/buf_list_node_struct.c @@ -0,0 +1,289 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "buf_list_node_struct.h" + +/* + * Function name: BufListNode_new + * Description: Creates and initializes new BufListNode structure. + * Returns: Newly created BufListNode structure. + */ + +BufListNode* +BufListNode_new() +{ + BufListNode* tmp = calloc(1, sizeof(BufListNode)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: BufListNode_new_message + * Description: Create and initialize new BufListNode structure from given message + * with actual buffer pointer and message length. + * Arguments: actPtr - actual buffer pointer + * msgLen - length of the message + * message - message to be stored + * Returns: Newly created and initialized BufListNode structure. + */ + +BufListNode* +BufListNode_new_message(int actPtr, int msgLen, unsigned char* message) +{ + BufListNode* tmp = calloc(1, sizeof(BufListNode)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + BufListNode_set_message(tmp, message, msgLen); + BufListNode_set_actPtr(tmp, actPtr); + return tmp; +} + +/* + * Function name: BufListNode_free + * Description: Frees the memory allocated for BufListNode structure. + * Arguments: bln - pointer to pointer to BufListNode structure + */ + +void +BufListNode_free(BufListNode** bln) +{ + assert(bln != NULL); + if (bln == NULL) { + return; + } + assert((*bln) != NULL); + if ((*bln) == NULL) { + return; + } + if ((*bln)->message) { + free((*bln)->message); + (*bln)->message = NULL; + } + free((*bln)); + (*bln) = NULL; +} + +/* + * Function name: BufListNode_set_actPtr + * Description: Sets actual buffer pointer. + * Arguments: bln - pointer to BufListNode structure + * actPtr - actual buffer pointer + */ + +void +BufListNode_set_actPtr(BufListNode* bln, int actPtr) +{ + assert(bln != NULL); + if (bln == NULL) { + return; + } + bln->actPtr = actPtr; +} + +/* + * Function name: BufListNode_set_msgLen + * Description: Sets length of the message. + * Arguments: bln - pointer to BufListNode structure + * msgLen - length of the message + */ + +void +BufListNode_set_msgLen(BufListNode* bln, int msgLen) +{ + assert(bln != NULL); + if (bln == NULL) { + return; + } + bln->msgLen = msgLen; +} + +/* + * Function name: BufListNode_set_message + * Description: Sets message to be stored. + * Arguments: bln - pointer to BufListNode structure + * message - message to be stored + * msgLen - length of the message + */ + +void +BufListNode_set_message(BufListNode* bln, unsigned char* message, int msgLen) +{ + assert(bln != NULL); + if (bln == NULL) { + return; + } + if (bln->message) { + free(bln->message); + bln->message = NULL; + } + BufListNode_set_actPtr(bln, 0); + BufListNode_set_msgLen(bln, 0); + assert(message != NULL); + if (message == NULL) { + return; + } + bln->message = calloc(1, msgLen); + assert(bln->message != NULL); + if (bln->message == NULL) { + return; + } + memcpy(bln->message, message, msgLen); + BufListNode_set_msgLen(bln, msgLen); +} + +/* + * Function name: BufListNode_set_nextNode + * Description: Sets next node pointer. + * Arguments: bln - pointer to BufListNode structure + * nextNode - next node pointer + */ + +void +BufListNode_set_nextNode(BufListNode* bln, BufListNode* nextNode) +{ + assert(bln != NULL); + if (bln == NULL) { + return; + } + bln->nextNode = nextNode; +} + +/* + * Function name: BufListNode_get_actPtr + * Description: Gets actual buffer pointer. + * Aguments: bln - pointer to BufListNode structure + * Returns: Actual buffer pointer. + */ + +int +BufListNode_get_actPtr(BufListNode* bln) +{ + assert(bln != NULL); + if (bln == NULL) { + return -1; + } + return bln->actPtr; +} + +/* + * Function name: BufListNode_get_msgLen + * Description: Gets length of the message. + * Arguments: bln - pointer to BufListNode structure + * Returns: Length of the message. + */ + +int +BufListNode_get_msgLen(BufListNode* bln) +{ + assert(bln != NULL); + if (bln == NULL) { + return -1; + } + return bln->msgLen; +} + +/* + * Function name: BufListNode_get_message + * Description: Gets stored message. + * Arguments: bln - pointer to BufListNode structure + * Returns: Stored message. + */ + +unsigned char* +BufListNode_get_message(BufListNode* bln) +{ + assert(bln != NULL); + if (bln == NULL) { + return NULL; + } + return bln->message; +} + +/* + * Function name: BufListNode_get_nextNode + * Description: Gets next node pointer. + * Arguments: bln - pointer to BufListNode structure + * Returns: Next BufListNode structure pointer or NULL, if there is no next one. + */ + +BufListNode* +BufListNode_get_nextNode(BufListNode* bln) +{ + assert(bln != NULL); + if (bln == NULL) { + return NULL; + } + return bln->nextNode; +} + +/* + * Function name: BufListNode_readMessage + * Description: Reads the message from actual buffer pointer. + * Arguments: bln - pointer to BufListNode structure + * Returns: Tail of the message from actual buffer pointer. + */ + +unsigned char* +BufListNode_readMessage(BufListNode* bln) +{ + assert(bln != NULL); + if (bln == NULL) { + return NULL; + } + return (&bln->message[BufListNode_get_actPtr(bln)]); +} + +/* + * Function name: BufListNode_readMessageLength + * Description: Gets the amount of unread bytes in the message. + * Arguments: bln - pointer to BufListNode structure + * Returns: The amount of unread bytes in the message. + */ + +int +BufListNode_readMessageLength(BufListNode* bln) +{ + int tmp = 0; + assert(bln != NULL); + if (bln == NULL) { + return -1; + } + assert(BufListNode_get_message(bln) != NULL); + if (BufListNode_get_message(bln) == NULL) { + return -1; + } + tmp = BufListNode_get_msgLen(bln) - BufListNode_get_actPtr(bln); + assert(tmp >= 0); + if (tmp < 0) { + return 0; + } + return tmp; +} diff --git a/src/buf_list_node_struct.h b/src/buf_list_node_struct.h new file mode 100644 index 0000000..08a4cfb --- /dev/null +++ b/src/buf_list_node_struct.h @@ -0,0 +1,50 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_BUF_LIST_NODE_STRUCT_H +#define _JS_BUF_LIST_NODE_STRUCT_H + +typedef struct blnode { + int actPtr; + int msgLen; + unsigned char* message; + struct blnode* nextNode; +} BufListNode; + +/* 'constructors' */ +BufListNode* BufListNode_new(); +BufListNode* BufListNode_new_message(int actPtr, int msgLen, unsigned char* message); +/* 'destructor' */ +void BufListNode_free(BufListNode** bln); +/* setters */ +void BufListNode_set_actPtr(BufListNode* bln, int actPtr); +void BufListNode_set_msgLen(BufListNode* bln, int msgLen); +void BufListNode_set_message(BufListNode* bln, unsigned char* message, int msgLen); +void BufListNode_set_nextNode(BufListNode* bln, BufListNode* nextNode); +/* getters */ +int BufListNode_get_actPtr(BufListNode* bln); +int BufListNode_get_msgLen(BufListNode* bln); +unsigned char* BufListNode_get_message(BufListNode* bln); +BufListNode* BufListNode_get_nextNode(BufListNode* bln); +/* other methods */ +unsigned char* BufListNode_readMessage(BufListNode* bln); +int BufListNode_readMessageLength(BufListNode* bln); + +#endif diff --git a/src/buf_list_struct.c b/src/buf_list_struct.c new file mode 100644 index 0000000..cbdbe09 --- /dev/null +++ b/src/buf_list_struct.c @@ -0,0 +1,152 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "buf_list_struct.h" + +/* + * Function name: BufList_new + * Description: Creates and initializes new BufList structure. + * Returns: Newly created BufList structure. + */ + +BufList* +BufList_new() +{ + BufList* tmp = calloc(1, sizeof(BufList)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: BufList_free + * Description: Frees the memory allocated for BufList structure. + * Arguments: bl - pointer to pointer to BufList structure. + */ + +void +BufList_free(BufList** bl) +{ + assert(bl != NULL); + if (bl == NULL) { + return; + } + assert((*bl) != NULL); + if ((*bl) == NULL) { + return; + } + BufList_clear((*bl)); + free((*bl)); + (*bl) = NULL; +} + +/* + * Function name: BufList_insert_back + * Description: Inserts new node at the end of the list. + * Arguments: bl - pointer to BufList structure + * bln - pointer to BufListNode structure + */ + +void +BufList_insert_back(BufList* bl, BufListNode* bln) +{ + assert(bl != NULL); + if (bl == NULL) { + return; + } + assert(bln != NULL); + if (bln == NULL) { + return; + } + if (bl->tail) { + bl->tail->nextNode = bln; + } + else { + bl->head = bln; + } + bl->tail = bln; + bln->nextNode = NULL; +} + +/* + * Function name: BufList_get_first + * Description: Get first node from the beginning of the list. + * Arguments: bl - pointer to BufList structure + * Returns: First node from the beginning of the list. + */ + +BufListNode* +BufList_get_first(BufList* bl) +{ + assert(bl != NULL); + if (bl == NULL) { + return NULL; + } + return bl->head; +} + +/* + * Function name: BufList_delete_first + * Description: Deletes first node from the beginning of the list. + * Arguments: bl - pointer to BufList structure + */ + +void +BufList_delete_first(BufList* bl) +{ + BufListNode* tmp = BufList_get_first(bl); + assert(tmp != NULL); + if (tmp == NULL) { + return; + } + if (tmp == bl->tail) { /* this is the last node in the list */ + bl->head = bl->tail = NULL; + } + else { /* there are other nodes*/ + bl->head = BufListNode_get_nextNode(tmp); + } + BufListNode_free(&tmp); +} + +/* + * Function name: BufList_clear + * Description: Deletes all nodes from the list. + * Arguments: bl - pointer to BufList structure + */ + +void +BufList_clear(BufList* bl) +{ + assert(bl != NULL); + if (bl == NULL) { + return; + } + while (BufList_get_first(bl)) { + BufList_delete_first(bl); + } +} diff --git a/src/buf_list_struct.h b/src/buf_list_struct.h new file mode 100644 index 0000000..d2bce00 --- /dev/null +++ b/src/buf_list_struct.h @@ -0,0 +1,41 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_BUF_LIST_STRUCT_H +#define _JS_BUF_LIST_STRUCT_H + +#include "buf_list_node_struct.h" + +typedef struct buflist { + BufListNode* head; + BufListNode* tail; +} BufList; + +/* 'constructor' */ +BufList* BufList_new(); +/* 'destructor' */ +void BufList_free(BufList** bl); +/* other */ +void BufList_insert_back(BufList* bl, BufListNode* bln); +BufListNode* BufList_get_first(BufList* bl); +void BufList_delete_first(BufList* bl); +void BufList_clear(BufList* bl); + +#endif diff --git a/src/client_configuration_struct.c b/src/client_configuration_struct.c new file mode 100644 index 0000000..6edb6f1 --- /dev/null +++ b/src/client_configuration_struct.c @@ -0,0 +1,336 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "string_functions.h" +#include "client_configuration_struct.h" + +/* + * Function name: ClientConfiguration_new + * Description: Create and initialize new ClientConfiguration structure. + * Returns: Pointer to newly created ClientConfiguration structure. + */ + +ClientConfiguration* +ClientConfiguration_new() +{ + ClientConfiguration* tmp = calloc(1, sizeof(ClientConfiguration)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: ClientConfiguration_free + * Description: Free the memory allocated for ClientConfiguration structure. + * Arguments: cc - pointer to pointer to ClientConfiguration structure + */ + +void +ClientConfiguration_free(ClientConfiguration** cc) +{ + int i; + assert(cc != NULL); + if (cc == NULL) { + return; + } + assert((*cc) != NULL); + if ((*cc) == NULL) { + return; + } + if ((*cc)->keysFile) { + free((*cc)->keysFile); + (*cc)->keysFile = NULL; + } + if ((*cc)->certificateFile) { + free((*cc)->certificateFile); + (*cc)->certificateFile = NULL; + } + if ((*cc)->storeFile) { + free((*cc)->storeFile); + (*cc)->storeFile = NULL; + } + if ((*cc)->realmsTable) { + for (i = 0; i < (*cc)->realmsNumber; ++i) { + if ((*cc)->realmsTable[i]) { + ClientRealm_free(&((*cc)->realmsTable[i])); + } + } + free((*cc)->realmsTable); + (*cc)->realmsTable = NULL; + } + free((*cc)); + (*cc) = NULL; +} + +/* + * Function name: ClientConfiguration_set_keysFile + * Description: Set keys filename. + * Arguments: cc - pointer to ClientConfiguration structure + * keysFile - keys filename + */ + +void +ClientConfiguration_set_keysFile(ClientConfiguration* cc, char* keysFile) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + string_cp(&(cc->keysFile), keysFile); +} + +/* + * Function name: ClientConfiguration_set_certificateFile + * Description: Set certs filename. + * Arguments: cc - pointer to ClientConfiguration structure + * certificateFile - certs filename + */ + +void +ClientConfiguration_set_certificateFile(ClientConfiguration* cc, char* certificateFile) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + string_cp(&(cc->certificateFile), certificateFile); +} + +/* + * Function name: ClientConfiguration_set_storeFile + * Description: Set store filename. + * Arguments: cc - pointer to ClientConfiguration structure + * storeFile - store filename + */ + +void +ClientConfiguration_set_storeFile(ClientConfiguration* cc, char* storeFile) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + string_cp(&(cc->storeFile), storeFile); +} + +/* + * Function name: ClientConfiguration_set_dateFormat + * Description: Set format of the date string. + * Arguments: cc - pointer to ClientConfiguration structure + * dateFormat - format of the date string + */ + +void +ClientConfiguration_set_dateFormat(ClientConfiguration* cc, char* dateFormat) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + string_cp(&(cc->dateFormat), dateFormat); +} + +/* + * Function name: ClientConfiguration_set_realmsNumber + * Description: Set number of realms. + * Arguments: cc - pointer to ClientConfiguration structure + * realmsNumber - number of realms + */ + +void +ClientConfiguration_set_realmsNumber(ClientConfiguration* cc, int realmsNumber) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->realmsNumber = realmsNumber; +} + +/* + * Function name: ClientConfiguration_set_realmsTable + * Description: Set table of realms. + * Arguments: cc - pointer to ClientConfiguration structure + * realmsTable - table of realms + */ + +void +ClientConfiguration_set_realmsTable(ClientConfiguration* cc, ClientRealm** realmsTable) +{ + int i; + assert(cc != NULL); + if (cc == NULL) { + return; + } + if (cc->realmsTable) { + for (i = 0; i < cc->realmsNumber; ++i) { + if (cc->realmsTable[i]) { + ClientRealm_free(&(cc->realmsTable[i])); + } + } + free(cc->realmsTable); + cc->realmsTable = NULL; + } + cc->realmsTable = realmsTable; +} + +/* + * Function name: ClientConfiguration_set_ignorePublicKeys + * Description: Enable/disable the public keys checking. + * Arguments: cc - pointer to ClientConfiguration structure + * ignorePublicKeys - if the public keys checking is enabled/disabled + */ + +void +ClientConfiguration_set_ignorePublicKeys(ClientConfiguration* cc, char ignorePublicKeys) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->ignorePublicKeys = ignorePublicKeys; +} + +/* + * Function name: ClientConfiguration_get_keysFile + * Description: Get keys filename. + * Arguments: cc - pointer to ClientConfiguration structure + * Returns: Keys filename. + */ + +char* +ClientConfiguration_get_keysFile(ClientConfiguration* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->keysFile; +} + +/* + * Function name: ClientConfiguration_get_certificateFile + * Description: Get certs filename. + * Arguments: cc - pointer to ClientConfiguration structure + * Returns: Certs filename. + */ + +char* +ClientConfiguration_get_certificateFile(ClientConfiguration* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->certificateFile; +} + +/* + * Function name: ClientConfiguration_get_storeFile + * Description: Get store filename. + * Arguments: cc - pointer to ClientConfiguration structure + * Returns: Store filename. + */ + +char* +ClientConfiguration_get_storeFile(ClientConfiguration* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->storeFile; +} + +/* + * Function name: ClientConfiguration_get_dateFormat + * Description: Get format of the date string. + * Arguments: cc - pointer to ClientConfiguration structure + * Returns: Format of the date string. + */ + +char* +ClientConfiguration_get_dateFormat(ClientConfiguration* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->dateFormat; +} + +/* + * Function name: ClientConfiguration_get_realmsNumber + * Description: Get number of realms. + * Arguments: cc - pointer to ClientConfiguration structure + * Returns: Number of realms. + */ + +int +ClientConfiguration_get_realmsNumber(ClientConfiguration* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return -1; + } + return cc->realmsNumber; +} + +/* + * Function name: ClientConfiguration_get_realmsTable + * Description: Get table of realms. + * Arguments: cc - pointer to ClientConfiguration structure + * Returns: Table of realms. + */ + +ClientRealm** +ClientConfiguration_get_realmsTable(ClientConfiguration* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->realmsTable; +} + +/* + * Function name: ClientConfiguration_get_ignorePublicKeys + * Description: Check if the public keys checking is enabled/disabled + * Arguments: cc - pointer to ClientConfiguration structure + * Returns: If the public keys checking is enabled/disabled. + */ + +char +ClientConfiguration_get_ignorePublicKeys(ClientConfiguration* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return 0; + } + return cc->ignorePublicKeys; +} diff --git a/src/client_configuration_struct.h b/src/client_configuration_struct.h new file mode 100644 index 0000000..15e590d --- /dev/null +++ b/src/client_configuration_struct.h @@ -0,0 +1,58 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _JS_CLIENT_CONFIGURATION_STRUCT_H +#define _JS_CLIENT_CONFIGURATION_STRUCT_H + +#include "client_realm_struct.h" + +typedef struct { + char* keysFile; + char* certificateFile; + char* storeFile; + char* dateFormat; + int realmsNumber; + char ignorePublicKeys; + ClientRealm** realmsTable; +} ClientConfiguration; + +/* 'constructor' */ +ClientConfiguration* ClientConfiguration_new(); +/* 'destructor' */ +void ClientConfiguration_free(ClientConfiguration** cc); +/* setters */ +void ClientConfiguration_set_keysFile(ClientConfiguration* cc, char* keysFile); +void ClientConfiguration_set_certificateFile(ClientConfiguration* cc, char* certificateFile); +void ClientConfiguration_set_storeFile(ClientConfiguration* cc, char* storeFile); +void ClientConfiguration_set_dateFormat(ClientConfiguration* cc, char* dateFormat); +void ClientConfiguration_set_realmsNumber(ClientConfiguration* cc, int realmsNumber); +void ClientConfiguration_set_realmsTable(ClientConfiguration* cc, ClientRealm** realmsTable); +void ClientConfiguration_set_ignorePublicKeys(ClientConfiguration* cc, char ignorePublicKeys); +/* getters */ +char* ClientConfiguration_get_keysFile(ClientConfiguration* cc); +char* ClientConfiguration_get_certificateFile(ClientConfiguration* cc); +char* ClientConfiguration_get_storeFile(ClientConfiguration* cc); +char* ClientConfiguration_get_dateFormat(ClientConfiguration* cc); +int ClientConfiguration_get_realmsNumber(ClientConfiguration* cc); +ClientRealm** ClientConfiguration_get_realmsTable(ClientConfiguration* cc); +char ClientConfiguration_get_ignorePublicKeys(ClientConfiguration* cc); + +#endif diff --git a/src/client_initialization.c b/src/client_initialization.c new file mode 100644 index 0000000..efde9a9 --- /dev/null +++ b/src/client_initialization.c @@ -0,0 +1,343 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <assert.h> + +#include "client_initialization.h" +#include "first_run.h" +#include "network.h" +#include "base64.h" +#include "ssl_routines.h" +#include "client_configuration_struct.h" +#include "client_signals.h" + +int +initialize_client_stage1(ClientRealm* cr, SSL_CTX* ctx, unsigned char* buff, char wanttoexit, + char ignorePublicKeys) +{ + int n, nlen, elen, len, tmp; + unsigned int olen; + X509* server_cert; + const EVP_MD *md; + EVP_PKEY* pkey; + EVP_MD_CTX md_ctx; + unsigned char *encoded = NULL; + char b64_encoded[100]; + unsigned char *key_buf = NULL; + assert((ClientRealm_get_tunnelType(cr) == 0) || (ClientRealm_get_tunnelType(cr) == 1)); + switch (ClientRealm_get_tunnelType(cr)) { + case 0: { + if (ip_connect(&tmp, ClientRealm_get_serverName(cr), + ClientRealm_get_managePort(cr), + ClientRealm_get_ipFamily(cr), + ClientRealm_get_localName(cr), + ClientRealm_get_localPort(cr))) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect_%s error for %s, %s", + (ClientRealm_get_ipFamily(cr) & 0x02) ? + "ipv4":(ClientRealm_get_ipFamily(cr) & 0x04) ? + "ipv6":"unspec", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); +#else + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect error for %s, %s", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); +#endif + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } + SslFd_set_fd(ClientRealm_get_masterSslFd(cr), tmp); + break; + } +#ifdef HAVE_LIBPTHREAD + case 1: { + if (initialize_http_proxy_client(&tmp, cr, ctx)) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_CRIT, + "http_proxy_connect_%s error for %s, %s (proxy: %s, %s)", + (ClientRealm_get_ipFamily(cr) & 0x02) ? + "ipv4":(ClientRealm_get_ipFamily(cr) & 0x04) ? + "ipv6":"unspec", ClientRealm_get_serverName(cr), + ClientRealm_get_managePort(cr), + HttpProxyOptions_get_proxyname(ClientRealm_get_httpProxyOptions(cr)), + HttpProxyOptions_get_proxyport(ClientRealm_get_httpProxyOptions(cr))); +#else + aflog(LOG_T_INIT, LOG_I_CRIT, + "http_proxy_connect error for %s, %s (proxy: %s, %s)", ClientRealm_get_serverName(cr), + ClientRealm_get_managePort(cr), + HttpProxyOptions_get_proxyname(ClientRealm_get_httpProxyOptions(cr)), + HttpProxyOptions_get_proxyport(ClientRealm_get_httpProxyOptions(cr))); +#endif + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + } + SslFd_set_fd(ClientRealm_get_masterSslFd(cr), tmp); + break; + } +#endif + default: { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Unknown tunnel type"); + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + break; + } + } + + SslFd_set_ssl(ClientRealm_get_masterSslFd(cr), SSL_new(ctx)); + if (SSL_set_fd(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)), + SslFd_get_fd(ClientRealm_get_masterSslFd(cr))) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problem with initializing ssl... exiting"); + if (wanttoexit) { + exit(1); + } + else { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); + return 2; + } + } + + alarm(60); + + aflog(LOG_T_INIT, LOG_I_INFO, + "Trying SSL_connect"); + if ((n = SSL_connect(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)))) == 1) { + if ((server_cert = SSL_get_peer_certificate(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)))) == NULL) { + aflog(LOG_T_MAIN, LOG_I_CRIT, + "Server did not present a certificate... exiting"); + exit(1); + } + /* FIXME: change almost everything here */ + pkey = X509_get_pubkey(server_cert); + if (pkey == NULL) { + aflog(LOG_T_MAIN, LOG_I_CRIT, + "Server's public key is invalid... exiting"); + exit(1); + } + nlen = BN_num_bytes(pkey->pkey.rsa->n); + elen = BN_num_bytes(pkey->pkey.rsa->e); + len = nlen + elen; + key_buf = malloc(len); + if (key_buf == NULL) { + aflog(LOG_T_MAIN, LOG_I_CRIT, + "Cannot allocate memory for server's public key checking... exiting"); + exit(1); + } + BN_bn2bin(pkey->pkey.rsa->n, key_buf); + BN_bn2bin(pkey->pkey.rsa->e, key_buf + nlen); + md = EVP_md5(); + EVP_DigestInit(&md_ctx, md); + EVP_DigestUpdate(&md_ctx, key_buf, len); + encoded = calloc(1, EVP_MAX_MD_SIZE+1); + if (encoded == NULL) { + aflog(LOG_T_MAIN, LOG_I_CRIT, + "Cannot allocate memory for server's public key checking... exiting"); + exit(1); + } + EVP_DigestFinal(&md_ctx, encoded, &olen); + + if (b64_ntop(encoded, olen, b64_encoded, 100) == -1) { + aflog(LOG_T_MAIN, LOG_I_CRIT, + "Problem with base64 encoding... exiting"); + exit(1); + } + + switch (check_public_key(get_store_filename(), ClientRealm_get_serverName(cr), b64_encoded)) { + case SSL_PUBLIC_KEY_VALID: + /* public key is ok - do nothing */ + break; + case SSL_PUBLIC_KEY_NOT_KNOWN: + aflog(LOG_T_MAIN, LOG_I_WARNING, + "WARNING: implicitly added new server's public key to the list of known hosts"); + add_public_key(get_store_filename(), ClientRealm_get_serverName(cr), b64_encoded); + break; + default: + if (ignorePublicKeys) { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "WARNING: Invalid server's public key... ignoring"); + } + else { + aflog(LOG_T_MAIN, LOG_I_CRIT, + "Invalid server's public key... exiting"); + aflog(LOG_T_MAIN, LOG_I_CRIT, + "Please delete conflicting entry in %s or use '--ignorepkeys' option", + get_store_filename()); + exit(1); + } + } + + memset(key_buf, 0, len); + free(key_buf); + free(encoded); + + aflog(LOG_T_INIT, LOG_I_INFO, + "SSL_connect successful"); + } + else { + alarm(0); + aflog(LOG_T_INIT, LOG_I_CRIT, + "SSL_connect has failed (%d | %d)... exiting", n, + SSL_get_error(SslFd_get_ssl(ClientRealm_get_masterSslFd(cr)), n)); + if (wanttoexit) { + exit(1); + } + else { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); + return 3; + } + } + alarm(0); + + buff[0] = AF_S_LOGIN; + buff[1] = ClientRealm_get_password(cr)[0]; + buff[2] = ClientRealm_get_password(cr)[1]; + buff[3] = ClientRealm_get_password(cr)[2]; + buff[4] = ClientRealm_get_password(cr)[3]; + + return 0; +} + +int +initialize_client_stage2(ClientRealm* cr, unsigned char* buff, char wanttoexit) +{ + SslFd_send_message(ClientRealm_get_realmType(cr) | TYPE_SSL | TYPE_ZLIB, + ClientRealm_get_masterSslFd(cr), buff, 5); + buff[0] = 0; + SslFd_get_message(ClientRealm_get_realmType(cr) | TYPE_SSL | TYPE_ZLIB, + ClientRealm_get_masterSslFd(cr), buff, -5); + + if ( buff[0] == 0 ) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Connection with afserver failed"); + if (wanttoexit) { + exit(1); + } + else { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); + return 1; + } + } + if ( buff[0] == AF_S_WRONG ) { + aflog(LOG_T_INIT, LOG_I_ERR, + "Wrong password"); + if (wanttoexit) { + exit(1); + } + else { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); + return 1; + } + } + if ( buff[0] == AF_S_CANT_OPEN ) { + aflog(LOG_T_INIT, LOG_I_ERR, + "Server is full"); + if (wanttoexit) { + exit(1); + } + else { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); + return 1; + } + } + if ( buff[0] != AF_S_LOGIN ) { + aflog(LOG_T_INIT, LOG_I_ERR, + "Incompatible server type or server full"); + if (wanttoexit) { + exit(1); + } + else { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); + return 1; + } + } + + ClientRealm_set_realmType(cr, buff[3]); + ClientRealm_set_usersLimit(cr, buff[1] * 256 + buff[2]); + return 0; +} + +int +initialize_client_stage3(ClientRealm* cr, int* buflength, fd_set* allset, fd_set* wset, int* maxfdp1, + char wanttoexit) +{ + int i; + socklen_t len; + ConnectUser** usersTable; + usersTable = calloc(ClientRealm_get_usersLimit(cr), sizeof(ConnectUser*)); + if (usersTable == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - unable to successfully communicate with server"); + if (wanttoexit) { + exit(1); + } + else { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); + return 1; + } + } + ClientRealm_set_usersTable(cr, usersTable); + for (i = 0; i < ClientRealm_get_usersLimit(cr); ++i) { + usersTable[i] = ConnectUser_new(); + if (usersTable[i] == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Calloc error - unable to successfully communicate with server"); + if (wanttoexit) { + exit(1); + } + else { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); + return 1; + } + } + } + + len = 4; + if (getsockopt(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), SOL_SOCKET, SO_SNDBUF, buflength, &len) == -1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Can't get socket send buffer size - exiting..."); + if (wanttoexit) { + exit(1); + } + else { + close(SslFd_get_fd(ClientRealm_get_masterSslFd(cr))); + return 2; + } + } + + FD_ZERO(allset); + FD_ZERO(wset); + + FD_SET(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), allset); + (*maxfdp1) = SslFd_get_fd(ClientRealm_get_masterSslFd(cr)) + 1; + return 0; +} diff --git a/src/client_initialization.h b/src/client_initialization.h new file mode 100644 index 0000000..390568f --- /dev/null +++ b/src/client_initialization.h @@ -0,0 +1,42 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "activefor.h" +#include "stats.h" +#include "logging.h" +#include "http_proxy_client.h" +#include "http_proxy_options_struct.h" +#include "ssl_fd_struct.h" +#include "client_realm_struct.h" + +#include <openssl/ssl.h> + +#ifndef _JS_CLIENT_INITIALIZATION_H +#define _JS_CLIENT_INITIALIZATION_H + +int initialize_client_stage1(ClientRealm* cr, SSL_CTX* ctx, unsigned char* buff, char wanttoexit, + char ignorePublicKeys); +int initialize_client_stage2(ClientRealm* cr, unsigned char* buff, char wanttoexit); +int initialize_client_stage3(ClientRealm* cr, int* buflength, fd_set* allset, fd_set* wset, int* maxfdp1, + char wanttoexit); + +#endif diff --git a/src/client_realm_struct.c b/src/client_realm_struct.c new file mode 100644 index 0000000..5b4477e --- /dev/null +++ b/src/client_realm_struct.c @@ -0,0 +1,1205 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "string_functions.h" +#include "client_realm_struct.h" +#include "client_shutdown.h" +#include "logging.h" + +/* + * Function name: ClientRealm_new + * Description: Create and initialize new ClientRealm structure. + * Returns: Pointer to newly created ClientRealm structure. + */ + +ClientRealm* +ClientRealm_new() +{ + ClientRealm* tmp = calloc(1, sizeof(ClientRealm)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + tmp->password[0] = 1; + tmp->password[1] = 2; + tmp->password[2] = 3; + tmp->password[3] = 4; + tmp->masterSslFd = SslFd_new(); + assert(tmp->masterSslFd != NULL); + if (tmp->masterSslFd == NULL) { + ClientRealm_free(&tmp); + return NULL; + } + tmp->arOptions = ArOptions_new(); + assert(tmp->arOptions != NULL); + if (tmp->arOptions == NULL) { + ClientRealm_free(&tmp); + return NULL; + } + tmp->httpProxyOptions = HttpProxyOptions_new(); + assert(tmp->httpProxyOptions != NULL); + if (tmp->httpProxyOptions == NULL) { + ClientRealm_free(&tmp); + return NULL; + } +#ifdef HAVE_LIBDL + tmp->userModule = Module_new(); + assert(tmp->userModule != NULL); + if (tmp->userModule == NULL) { + ClientRealm_free(&tmp); + return NULL; + } + tmp->serviceModule = Module_new(); + assert(tmp->serviceModule != NULL); + if (tmp->serviceModule == NULL) { + ClientRealm_free(&tmp); + return NULL; + } +#endif + return tmp; +} + +/* + * Function name: ClientRealm_free + * Description: Free the memory allocated for ClientRealm structure. + * Arguments: cr - pointer to pointer to ClientRealm structure + */ + +void +ClientRealm_free(ClientRealm** cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + assert((*cr) != NULL); + if ((*cr) == NULL) { + return; + } + ClientRealm_set_serverName((*cr), NULL); + ClientRealm_set_managePort((*cr), NULL); + ClientRealm_set_hostName((*cr), NULL); + ClientRealm_set_realmName((*cr), NULL); + ClientRealm_set_sKeepAliveTimeout((*cr), NULL); + ClientRealm_set_realmId((*cr), NULL); + ClientRealm_set_localName((*cr), NULL); + ClientRealm_set_localPort((*cr), NULL); + ClientRealm_set_localDestinationName((*cr), NULL); + ClientRealm_set_clientAddress((*cr), NULL); + ClientRealm_set_masterSslFd((*cr), NULL); + ClientRealm_set_httpProxyOptions((*cr), NULL); + ClientRealm_set_arOptions((*cr), NULL); + ClientRealm_set_destinationPorts((*cr), NULL); + ClientRealm_set_usersTable((*cr), NULL); +#ifdef HAVE_LIBDL + ClientRealm_set_userModule((*cr), NULL); + ClientRealm_set_serviceModule((*cr), NULL); +#endif + free((*cr)); + (*cr) = NULL; +} + +/* + * Function name: ClientRealm_set_serverName + * Description: Set realm's server name. + * Arguments: cr - pointer to ClientRealm structure + * serverName - realm's host name + */ + +void +ClientRealm_set_serverName(ClientRealm* cr, char* serverName) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + string_cp(&(cr->serverName), serverName); +} + +/* + * Function name: ClientRealm_set_managePort + * Description: Set realm's manage port description. + * Arguments: cr - pointer to ClientRealm structure + * managePort - realm's manage port description + */ + +void +ClientRealm_set_managePort(ClientRealm* cr, char* managePort) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + string_cp(&(cr->managePort), managePort); +} + +/* + * Function name: ClientRealm_set_hostName + * Description: Set realm's host name. + * Arguments: cr - pointer to ClientRealm structure + * hostName - realm's host name + */ + +void +ClientRealm_set_hostName(ClientRealm* cr, char* hostName) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + string_cp(&(cr->hostName), hostName); +} + +/* + * Function name: ClientRealm_set_destinationPorts + * Description: Set realm's destination ports list. + * Arguments: cr - pointer to ClientRealm structure + * destinationPorts - realm's destination ports list + */ + +void +ClientRealm_set_destinationPorts(ClientRealm* cr, PortList* destinationPorts) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + if (cr->destinationPorts) { + PortList_free(&(cr->destinationPorts)); + } + cr->destinationPorts = destinationPorts; +} + +/* + * Function name: ClientRealm_set_sKeepAliveTimeout + * Description: Set keep-alive timeout value description. + * Arguments: cr - pointer to ClientRealm structure + * sKeepAliveTimeout - keep-alive timeout value description + */ + +void +ClientRealm_set_sKeepAliveTimeout(ClientRealm* cr, char* sKeepAliveTimeout) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + string_cp(&(cr->sKeepAliveTimeout), sKeepAliveTimeout); +} + +/* + * Function name: ClientRealm_set_realmName + * Description: Set realm's name. + * Arguments: cr - pointer to ClientRealm structure + * realmName - realm's name + */ + +void +ClientRealm_set_realmName(ClientRealm* cr, char* realmName) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + string_cp(&(cr->realmName), realmName); +} + +/* + * Function name: ClientRealm_set_realmId + * Description: Set realm's id. + * Arguments: cr - pointer to ClientRealm structure + * realmId - realm's id + */ + +void +ClientRealm_set_realmId(ClientRealm* cr, char* realmId) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + string_cp(&(cr->realmId), realmId); +} + +/* + * Function name: ClientRealm_set_localName + * Description: Set realm's local name. + * Arguments: cr - pointer to ClientRealm structure + * localName - realm's local name + */ + +void +ClientRealm_set_localName(ClientRealm* cr, char* localName) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + string_cp(&(cr->localName), localName); +} + +/* + * Function name: ClientRealm_set_localPort + * Description: Set realm's local port description. + * Arguments: cr - pointer to ClientRealm structure + * localPort - realm's local port description + */ + +void +ClientRealm_set_localPort(ClientRealm* cr, char* localPort) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + string_cp(&(cr->localPort), localPort); +} + +/* + * Function name: ClientRealm_set_localDestinationName + * Description: Set realm's local destination name. + * Arguments: cr - pointer to ClientRealm structure + * localDestinationName - realm's local destination name + */ + +void +ClientRealm_set_localDestinationName(ClientRealm* cr, char* localDestinationName) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + string_cp(&(cr->localDestinationName), localDestinationName); +} + +/* + * Function name: ClientRealm_set_password + * Description: Set realm's password. + * Arguments: cr - pointer to ClientRealm structure + * password - realm's password + */ + +void +ClientRealm_set_password(ClientRealm* cr, unsigned char* password) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + memcpy(cr->password, password, 4); +} + +/* + * Function name: ClientRealm_set_connectedUsers + * Description: Set number of connected users. + * Arguments: cr - pointer to ClientRealm structure + * connectedUsers - number of connected users + */ + +void +ClientRealm_set_connectedUsers(ClientRealm* cr, int connectedUsers) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + cr->connectedUsers = connectedUsers; +} + +/* + * Function name: ClientRealm_set_usersLimit + * Description: Set limit of connected users. + * Arguments: cr - pointer to ClientRealm structure + * usersLimit - limit of connected users + */ + +void +ClientRealm_set_usersLimit(ClientRealm* cr, int usersLimit) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + cr->usersLimit = usersLimit; +} + +/* + * Function name: ClientRealm_set_keepAliveTimeout + * Description: Set keep-alive timeout value. + * Arguments: cr - pointer to ClientRealm structure + * keepAliveTimeout - keep-alive timeout value + */ + +void +ClientRealm_set_keepAliveTimeout(ClientRealm* cr, int keepAliveTimeout) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + cr->keepAliveTimeout = keepAliveTimeout; +} + +/* + * Function name: ClientRealm_set_clientMode + * Description: Set client mode. + * Arguments: cr - pointer to ClientRealm structure + * clientMode - client mode + */ + +void +ClientRealm_set_clientMode(ClientRealm* cr, int clientMode) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + cr->clientMode = clientMode; +} + +/* + * Function name: ClientRealm_set_ipFamily + * Description: Set IP family. + * Arguments: cr - pointer to ClientRealm structure + * ipFamily - IP family + */ + +void +ClientRealm_set_ipFamily(ClientRealm* cr, char ipFamily) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + cr->ipFamily = ipFamily; +} + +/* + * Function name: ClientRealm_set_realmType + * Description: Set type of the realm. + * Arguments: cr - pointer to ClientRealm structure + * realmType - type of the realm + */ + +void +ClientRealm_set_realmType(ClientRealm* cr, char realmType) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + cr->realmType = realmType; +} + +/* + * Function name: ClientRealm_set_tunnelType + * Description: Set type of the tunnel. + * Arguments: cr - pointer to ClientRealm structure + * tunnelType - type of the tunnel + */ + +void +ClientRealm_set_tunnelType(ClientRealm* cr, char tunnelType) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + cr->tunnelType = tunnelType; +} + +/* + * Function name: ClientRealm_set_keepAlive + * Description: Set keep-alive timeval struct. + * Arguments: cr - pointer to ClientRealm structure + * keepAlive - keep-alive timeval struct + */ + +void +ClientRealm_set_keepAlive(ClientRealm* cr, struct timeval keepAlive) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + cr->keepAlive = keepAlive; +} + +/* + * Function name: ClientRealm_set_addressLength + * Description: Set client's address length. + * Arguments: cr - pointer to ClientRealm structure + * addressLength - client's address length + */ + +void +ClientRealm_set_addressLength(ClientRealm* cr, socklen_t addressLength) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + cr->addressLength = addressLength; +} + +/* + * Function name: ClientRealm_set_clientAddress + * Description: Set client's network address. + * Arguments: cr - pointer to ClientRealm structure + * clientAddress - client's network address + */ + +void +ClientRealm_set_clientAddress(ClientRealm* cr, struct sockaddr* clientAddress) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + if (cr->clientAddress) { + free(cr->clientAddress); + cr->clientAddress = NULL; + } + cr->clientAddress = clientAddress; +} + +/* + * Function name: ClientRealm_set_masterSslFd + * Description: Set client realm's master sslfd. + * Arguments: cr - pointer to ClientRealm structure + * masterSslFd - client realm's master sslfd + */ + +void +ClientRealm_set_masterSslFd(ClientRealm* cr, SslFd* masterSslFd) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + if (cr->masterSslFd) { + SslFd_free(&(cr->masterSslFd)); + } + cr->masterSslFd = masterSslFd; +} + +/* + * Function name: ClientRealm_set_httpProxyOptions + * Description: Set client realm's http proxy options. + * Arguments: cr - pointer to ClientRealm structure + * httpProxyOptions - client realm's http proxy options + */ + +void +ClientRealm_set_httpProxyOptions(ClientRealm* cr, HttpProxyOptions* httpProxyOptions) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + if (cr->httpProxyOptions) { + HttpProxyOptions_free(&(cr->httpProxyOptions)); + } + cr->httpProxyOptions = httpProxyOptions; +} + +/* + * Function name: ClientRealm_set_arOptions + * Description: Set client realm's auto-reconnect options. + * Arguments: cr - pointer to ClientRealm structure + * arOptions - client realm's auto-reconnect options + */ + +void +ClientRealm_set_arOptions(ClientRealm* cr, ArOptions* arOptions) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + if (cr->arOptions) { + ArOptions_free(&(cr->arOptions)); + } + cr->arOptions = arOptions; +} + +/* + * Function name: ClientRealm_set_usersTable + * Description: Set table of users. + * Arguments: cr - pointer to ClientRealm structure + * usersTable - table of users + */ + +void +ClientRealm_set_usersTable(ClientRealm* cr, ConnectUser** usersTable) +{ + int i; + assert(cr != NULL); + if (cr == NULL) { + return; + } + if (cr->usersTable) { + for (i = 0; i < cr->usersLimit; ++i) { + if (cr->usersTable[i]) { + ConnectUser_free(&(cr->usersTable[i])); + } + } + free(cr->usersTable); + cr->usersTable = NULL; + } + cr->usersTable = usersTable; +} + +#ifdef HAVE_LIBDL +/* + * Function name: ClientRealm_set_userModule + * Description: Set a module for user's packets filtering. + * Arguments: cr - pointer to ClientRealm structure + * userModule - module for user's packets filtering + */ + +void +ClientRealm_set_userModule(ClientRealm* cr, Module* userModule) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + if (cr->userModule) { + Module_free(&(cr->userModule)); + } + cr->userModule = userModule; +} + +/* + * Function name: ClientRealm_set_serviceModule + * Description: Set a module for service's packets filtering. + * Arguments: cr - pointer to ClientRealm structure + * serviceModule - module for service's packets filtering + */ + +void +ClientRealm_set_serviceModule(ClientRealm* cr, Module* serviceModule) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + if (cr->serviceModule) { + Module_free(&(cr->serviceModule)); + } + cr->serviceModule = serviceModule; +} +#endif + +/* + * Function name: ClientRealm_get_serverName + * Description: Get realm's server name. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Realm's server name. + */ + +char* +ClientRealm_get_serverName(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->serverName; +} + +/* + * Function name: ClientRealm_get_managePort + * Description: Get realm's manage port description. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Realm's manage port description. + */ + +char* +ClientRealm_get_managePort(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->managePort; +} + +/* + * Function name: ClientRealm_get_hostName + * Description: Get realm's host name. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Realm's host name. + */ + +char* +ClientRealm_get_hostName(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->hostName; +} + +/* + * Function name: ClientRealm_get_destinationPorts + * Description: Get realm's destination ports list. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Realm's destination ports list. + */ + +PortList* +ClientRealm_get_destinationPorts(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->destinationPorts; +} + +/* + * Function name: ClientRealm_get_sKeepAliveTimeout + * Description: Get keep-alive timeout value description. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Keep-alive timeout value description. + */ + +char* +ClientRealm_get_sKeepAliveTimeout(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->sKeepAliveTimeout; +} + +/* + * Function name: ClientRealm_get_realmName + * Description: Get realm's name. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Realm's name. + */ + +char* +ClientRealm_get_realmName(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->realmName; +} + +/* + * Function name: ClientRealm_get_realmId + * Description: Get realm's id. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Realm's id. + */ + +char* +ClientRealm_get_realmId(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->realmId; +} + + +/* + * Function name: ClientRealm_get_localName + * Description: Get realm's local name. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Realm's local name. + */ + +char* +ClientRealm_get_localName(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->localName; +} + + +/* + * Function name: ClientRealm_get_localPort + * Description: Get realm's local port description. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Realm's local port description. + */ + +char* +ClientRealm_get_localPort(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->localPort; +} + + +/* + * Function name: ClientRealm_get_localDestinationName + * Description: Get realm's local destination name. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Realm's local destination name. + */ + +char* +ClientRealm_get_localDestinationName(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->localDestinationName; +} + +/* + * Function name: ClientRealm_get_password + * Description: Get realm's password. + * Arguments: sr - pointer to ClientRealm structure + * Returns: Realm's password. + */ + +unsigned char* +ClientRealm_get_password(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->password; +} + +/* + * Function name: ClientRealm_get_connectedUsers + * Description: Get number of connected users. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Number of connected users. + */ + +int +ClientRealm_get_connectedUsers(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return -1; + } + return cr->connectedUsers; +} + +/* + * Function name: ClientRealm_get_usersLimit + * Description: Get limit of connected users. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Limit of connected users. + */ + +int +ClientRealm_get_usersLimit(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return -1; + } + return cr->usersLimit; +} + +/* + * Function name: ClientRealm_get_keepAliveTimeout + * Description: Get keep-alive timeout value. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Keep-alive timeout value. + */ + +int +ClientRealm_get_keepAliveTimeout(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return 0; + } + return cr->keepAliveTimeout; +} + +/* + * Function name: ClientRealm_get_clientMode + * Description: Get client mode. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Client mode. + */ + +int +ClientRealm_get_clientMode(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return 0; + } + return cr->clientMode; +} + +/* + * Function name: ClientRealm_get_ipFamily + * Description: Get IP family. + * Arguments: cr - pointer to ClientRealm structure + * Returns: IP family. + */ + +char +ClientRealm_get_ipFamily(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return 0; + } + return cr->ipFamily; +} + +/* + * Function name: ClientRealm_get_realmType + * Description: Get type of the realm. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Type of the realm. + */ + +char +ClientRealm_get_realmType(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return 0; + } + return cr->realmType; +} + +/* + * Function name: ClientRealm_get_tunnelType + * Description: Get type of the tunnel. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Type of the tunnel. + */ + +char +ClientRealm_get_tunnelType(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return 0; + } + return cr->tunnelType; +} + +/* + * Function name: ClientRealm_get_keepAlive + * Description: Get keep-alive timeval struct. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Keep-alive timeval struct. + */ + +struct timeval +ClientRealm_get_keepAlive(ClientRealm* cr) +{ + struct timeval tmp = {0, 0}; + assert(cr != NULL); + if (cr == NULL) { + return tmp; + } + return cr->keepAlive; +} + +/* + * Function name: ClientRealm_get_addressLength + * Description: Get client's address length. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Client's address length. + */ + +socklen_t +ClientRealm_get_addressLength(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return 0; + } + return cr->addressLength; +} + +/* + * Function name: ClientRealm_get_clientAddress + * Description: Get client's network address. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Client's network address. + */ + +struct sockaddr* +ClientRealm_get_clientAddress(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->clientAddress; +} + +/* + * Function name: ClientRealm_get_masterSslFd + * Description: Get client realm's master sslfd. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Client realm's master sslfd. + */ + +SslFd* +ClientRealm_get_masterSslFd(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->masterSslFd; +} + +/* + * Function name: ClientRealm_get_httpProxyOptions + * Description: Get client realm's http proxy options. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Client realm's http proxy options. + */ + +HttpProxyOptions* +ClientRealm_get_httpProxyOptions(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->httpProxyOptions; +} + +/* + * Function name: ClientRealm_get_arOptions + * Description: Get client realm's auto-reconnect options. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Client realm's auto-reconnect options. + */ + +ArOptions* +ClientRealm_get_arOptions(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->arOptions; +} + +/* + * Function name: ClientRealm_get_usersTable + * Description: Get table of users. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Table of users. + */ + +ConnectUser** +ClientRealm_get_usersTable(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->usersTable; +} + +#ifdef HAVE_LIBDL +/* + * Function name: ClientRealm_get_userModule + * Description: Get a module for user's packets filtering. + * Arguments: cr - pointer to ClientRealm structure + * Returns: A module for user's packets filtering. + */ + +Module* +ClientRealm_get_userModule(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->userModule; +} + +/* + * Function name: ClientRealm_get_serviceModule + * Description: Get a module for service's packets filtering. + * Arguments: cr - pointer to ClientRealm structure + * Returns: A module for service's packets filtering. + */ + +Module* +ClientRealm_get_serviceModule(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return cr->serviceModule; +} +#endif + +/* + * Function name: ClientRealm_increase_connectedUsers + * Description: Increase number of connected users. + * Arguments: cr - pointer to ClientRealm structure + */ + +void +ClientRealm_increase_connectedUsers(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + ClientRealm_set_connectedUsers(cr, ClientRealm_get_connectedUsers(cr) + 1); +} + +/* + * Function name: ClientRealm_decrease_connectedUsers + * Description: Decrease number of connected users. + * Arguments: cr - pointer to ClientRealm structure + */ + +void +ClientRealm_decrease_connectedUsers(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + ClientRealm_set_connectedUsers(cr, ClientRealm_get_connectedUsers(cr) - 1); +} + +/* + * Function name: ClientRealm_closeUsersConnections + * Description: Close all users' connections and free usersTable. + * Arguments: cr - pointer to ClientRealm structure + */ + +void +ClientRealm_closeUsersConnections(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return; + } + close_connections(ClientRealm_get_usersLimit(cr), &(cr->usersTable)); +} + +/* + * Function name: ClientRealm_get_keepAlivePointer + * Description: Get pointer to keep-alive structure. + * Arguments: cr - pointer to ClientRealm structure + * Returns: Pointer to keep-alive structure. + */ + +struct timeval* +ClientRealm_get_keepAlivePointer(ClientRealm* cr) +{ + assert(cr != NULL); + if (cr == NULL) { + return NULL; + } + return (&(cr->keepAlive)); +} + +/* + * Function name: ClientRealm_send_realmId + * Description: Sends the realm's id to the afserver. + * Arguments: cr - pointer to ClientRealm structure + * buff - buffer used for message creation + */ + +void +ClientRealm_send_realmId(ClientRealm* cr, unsigned char* buff) +{ + int n; + assert(cr != NULL); + if (cr == NULL) { + return; + } + assert(buff != NULL); + if (buff == NULL) { + return; + } + if (ClientRealm_get_realmId(cr) != NULL) { + buff[0] = AF_S_LOGIN; + buff[1] = buff[2] = 0; + n = strlen(ClientRealm_get_realmId(cr)); + memcpy(&buff[5], ClientRealm_get_realmId(cr), n); + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(ClientRealm_get_realmType(cr), + ClientRealm_get_masterSslFd(cr), buff, n+5); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "ID SENT: %s", ClientRealm_get_realmId(cr)); + } +} + +/* + * Function name: ClientRealm_enable_multi + * Description: Enables the MULTI mode on the afserver, if supported. + * Arguments: cr - pointer to ClientRealm structure + */ + +void +ClientRealm_enable_multi(ClientRealm* cr) +{ + unsigned char buff[5]; + assert(cr != NULL); + if (cr == NULL) { + return; + } + if ((TYPE_IS_SUPPORTED_MULTI(ClientRealm_get_realmType(cr))) && + (PortList_get_size(ClientRealm_get_destinationPorts(cr)) > 1)) { + buff[0] = AF_S_ENABLE_MULTI; + buff[1] = PortList_get_size(ClientRealm_get_destinationPorts(cr)); + buff[2] = buff[3] = buff[4] = 0; + SslFd_send_message(ClientRealm_get_realmType(cr), + ClientRealm_get_masterSslFd(cr), buff, 5); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "ENABLED: MULTI (multiple tunnels managed by one afclient)"); + } +} diff --git a/src/client_realm_struct.h b/src/client_realm_struct.h new file mode 100644 index 0000000..0fd1789 --- /dev/null +++ b/src/client_realm_struct.h @@ -0,0 +1,146 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "ssl_fd_struct.h" +#include "http_proxy_options_struct.h" +#include "ar_options_struct.h" +#include "module_struct.h" +#include "port_list_struct.h" + +#ifndef _JS_CLIENT_REALM_STRUCT_H +#define _JS_CLIENT_REALM_STRUCT_H + +#define CLIENTREALM_MODE_UNKNOWN -1 +#define CLIENTREALM_MODE_TCP 0 +#define CLIENTREALM_MODE_UDP 1 +#define CLIENTREALM_MODE_REMOTE 2 +#define CLIENTREALM_MODE_REVERSE 3 + +#define CLIENTREALM_TUNNELTYPE_UNKNOWN -1 +#define CLIENTREALM_TUNNELTYPE_DIRECT 0 +#define CLIENTREALM_TUNNELTYPE_HTTPPROXY 1 +#define CLIENTREALM_TUNNELTYPE_HTTPSPROXY 2 + +typedef struct { + char* serverName; + char* managePort; + char* hostName; + char* realmName; + char* sKeepAliveTimeout; + char* realmId; + char* localName; + char* localPort; + char* localDestinationName; + unsigned char password[4]; + int connectedUsers; + int usersLimit; + int clientMode; + int keepAliveTimeout; + char ipFamily; + char realmType; + char tunnelType; + struct timeval keepAlive; + socklen_t addressLength; + struct sockaddr* clientAddress; + SslFd* masterSslFd; + HttpProxyOptions* httpProxyOptions; + ArOptions* arOptions; + PortList* destinationPorts; + ConnectUser** usersTable; +#ifdef HAVE_LIBDL + Module* userModule; + Module* serviceModule; +#endif +} ClientRealm; + +/* 'constructor' */ +ClientRealm* ClientRealm_new(); +/* 'destructor' */ +void ClientRealm_free(ClientRealm** cr); +/* setters */ +void ClientRealm_set_serverName(ClientRealm* cr, char* serverName); +void ClientRealm_set_managePort(ClientRealm* cr, char* managePort); +void ClientRealm_set_hostName(ClientRealm* cr, char* hostName); +void ClientRealm_set_realmName(ClientRealm* cr, char* realmName); +void ClientRealm_set_sKeepAliveTimeout(ClientRealm* cr, char* sKeepAliveTimeout); +void ClientRealm_set_realmId(ClientRealm* cr, char* realmId); +void ClientRealm_set_localName(ClientRealm* cr, char* localName); +void ClientRealm_set_localPort(ClientRealm* cr, char* localPort); +void ClientRealm_set_localDestinationName(ClientRealm* cr, char* localDestinationName); +void ClientRealm_set_password(ClientRealm* cr, unsigned char* password); +void ClientRealm_set_connectedUsers(ClientRealm* cr, int connectedUsers); +void ClientRealm_set_usersLimit(ClientRealm* cr, int usersLimit); +void ClientRealm_set_keepAliveTimeout(ClientRealm* cr, int keepAliveTimeout); +void ClientRealm_set_clientMode(ClientRealm* cr, int clientMode); +void ClientRealm_set_ipFamily(ClientRealm* cr, char ipFamily); +void ClientRealm_set_realmType(ClientRealm* cr, char realmType); +void ClientRealm_set_tunnelType(ClientRealm* cr, char tunnelType); +void ClientRealm_set_keepAlive(ClientRealm* cr, struct timeval keepAlive); +void ClientRealm_set_addressLength(ClientRealm* cr, socklen_t addressLength); +void ClientRealm_set_clientAddress(ClientRealm* cr, struct sockaddr* clientAddress); +void ClientRealm_set_masterSslFd(ClientRealm* cr, SslFd* masterSslFd); +void ClientRealm_set_httpProxyOptions(ClientRealm* cr, HttpProxyOptions* httpProxyOptions); +void ClientRealm_set_arOptions(ClientRealm* cr, ArOptions* arOptions); +void ClientRealm_set_destinationPorts(ClientRealm* cr, PortList* destinationPorts); +void ClientRealm_set_usersTable(ClientRealm* cr, ConnectUser** usersTable); +#ifdef HAVE_LIBDL +void ClientRealm_set_userModule(ClientRealm* cr, Module* userModule); +void ClientRealm_set_serviceModule(ClientRealm* cr, Module* serviceModule); +#endif +/* getters */ +char* ClientRealm_get_serverName(ClientRealm* cr); +char* ClientRealm_get_managePort(ClientRealm* cr); +char* ClientRealm_get_hostName(ClientRealm* cr); +char* ClientRealm_get_realmName(ClientRealm* cr); +char* ClientRealm_get_sKeepAliveTimeout(ClientRealm* cr); +char* ClientRealm_get_realmId(ClientRealm* cr); +char* ClientRealm_get_localName(ClientRealm* cr); +char* ClientRealm_get_localPort(ClientRealm* cr); +char* ClientRealm_get_localDestinationName(ClientRealm* cr); +unsigned char* ClientRealm_get_password(ClientRealm* cr); +int ClientRealm_get_connectedUsers(ClientRealm* cr); +int ClientRealm_get_usersLimit(ClientRealm* cr); +int ClientRealm_get_keepAliveTimeout(ClientRealm* cr); +int ClientRealm_get_clientMode(ClientRealm* cr); +char ClientRealm_get_ipFamily(ClientRealm* cr); +char ClientRealm_get_realmType(ClientRealm* cr); +char ClientRealm_get_tunnelType(ClientRealm* cr); +struct timeval ClientRealm_get_keepAlive(ClientRealm* cr); +socklen_t ClientRealm_get_addressLength(ClientRealm* cr); +struct sockaddr* ClientRealm_get_clientAddress(ClientRealm* cr); +SslFd* ClientRealm_get_masterSslFd(ClientRealm* cr); +HttpProxyOptions* ClientRealm_get_httpProxyOptions(ClientRealm* cr); +ArOptions* ClientRealm_get_arOptions(ClientRealm* cr); +PortList* ClientRealm_get_destinationPorts(ClientRealm* cr); +ConnectUser** ClientRealm_get_usersTable(ClientRealm* cr); +#ifdef HAVE_LIBDL +Module* ClientRealm_get_userModule(ClientRealm* cr); +Module* ClientRealm_get_serviceModule(ClientRealm* cr); +#endif +/* other */ +void ClientRealm_increase_connectedUsers(ClientRealm* cr); +void ClientRealm_decrease_connectedUsers(ClientRealm* cr); +void ClientRealm_closeUsersConnections(ClientRealm* cr); +struct timeval* ClientRealm_get_keepAlivePointer(ClientRealm* cr); +void ClientRealm_send_realmId(ClientRealm* cr, unsigned char* buff); +void ClientRealm_enable_multi(ClientRealm* cr); + +#endif diff --git a/src/client_remoteadmin.c b/src/client_remoteadmin.c new file mode 100644 index 0000000..bcac860 --- /dev/null +++ b/src/client_remoteadmin.c @@ -0,0 +1,210 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "client_remoteadmin.h" + +/* + * Function name: client_admin + * Description: This function is responsible for client part of the admin panel. + * Arguments: type - the type of the realm + * master - pointer to the SslFd structure representing the connection with afserver + * buff - buffer which will be used for communication + * connectfd - the optional descriptor which can be used instead of the stdin + * id - the realm's id + * Returns: 0 - connection was closed normally, + * 1 - something went bad. + */ + +int +client_admin(char type, SslFd* master, unsigned char* buff, int connectfd, char* id) +{ + fd_set rset, allset; + int maxfdp1, n, length, infd; + FILE *outfp, *infp; + + buff[0] = AF_S_ADMIN_LOGIN; + SslFd_send_message(type, master, buff, 5); + buff[0] = 0; + SslFd_get_message(type, master, buff, -5); + + if ( buff[0] == 0 ) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Wrong password"); + return 1; + } + if ( buff[0] == AF_S_CANT_OPEN ) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Server is full"); + return 1; + } + if ( buff[0] != AF_S_ADMIN_LOGIN ) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Incompatible server type or server full"); + return 1; + } + + aflog(LOG_T_MAIN, LOG_I_INFO, + "CLIENT STARTED mode: remote administration"); + + if (connectfd > 0) { + outfp = fdopen(connectfd, "w"); + if (outfp == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Error in opening file descriptor for writing"); + return 1; + } + infd = connectfd; + } + else { + infd = STDIN_FILENO; + outfp = stdout; + } + infp = fdopen(infd, "r"); + if (infp == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Error in opening file descriptor for reading"); + return 1; + } + + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + n = SslFd_get_message(type, master, buff, length); + buff[n] = 0; + fprintf(outfp, "%s\n", (char*) buff); + fflush(outfp); + + FD_ZERO(&allset); + + FD_SET(SslFd_get_fd(master), &allset); + FD_SET(infd, &allset); + + maxfdp1 = (infd > SslFd_get_fd(master)) ? infd + 1 : SslFd_get_fd(master) + 1; + + if (id != NULL) { + buff[0] = AF_S_LOGIN; + buff[1] = buff[2] = 0; + n = strlen(id); + memcpy(&buff[5], id, n); + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(type, master, buff, n+5); + aflog(LOG_T_MANAGE, LOG_I_INFO, + "ID SENT: %s", id); + } + + while (1) { + rset = allset; + select(maxfdp1, &rset, NULL, NULL, NULL); + + if (FD_ISSET(SslFd_get_fd(master), &rset)) { + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "masterfd: FD_ISSET"); + n = SslFd_get_message(type, master, buff, 5); + if (n != 5) { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "FATAL ERROR! (%d)", n); + if (n == -1) { + if (TYPE_IS_SSL(type)) { + get_ssl_error(master, "FE", n); + continue; /* what happened? */ + } + } + if (n != 0) + return 1; + } + if (n == 0) { /* server quits -> we do the same... */ + aflog(LOG_T_MANAGE, LOG_I_CRIT, + "SERVER: premature quit --> exiting..."); + return 1; + } + if (buff[0] == AF_S_CLOSING) { + aflog(LOG_T_MANAGE, LOG_I_CRIT, + "SERVER: CLOSED -> exiting... cg: %ld bytes", getcg()); + return 0; + } + if (buff[0] != AF_S_ADMIN_CMD) { + aflog(LOG_T_MANAGE, LOG_I_CRIT, + "SERVER: wrong message --> exiting"); + return 1; + } + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + + switch (buff[1]) { + case AF_RA_STATUS_OK: { + aflog(LOG_T_MANAGE, LOG_I_INFO, + "SERVER: cmd successful"); + } + case AF_RA_FAILED: { + if (buff[1] == AF_RA_FAILED) { + aflog(LOG_T_MANAGE, LOG_I_INFO, + "SERVER: cmd failed"); + } + } + case AF_RA_UNDEFINED: { + if (buff[1] == AF_RA_UNDEFINED) { + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "SERVER: unknown cmd"); + } + n = SslFd_get_message(type, master, buff, length); + buff[n] = 0; + fprintf(outfp, "%s", (char*) buff); + fflush(outfp); + break; + } + case AF_RA_KICKED: { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "SERVER: kicked us -> exiting... cg: %ld bytes", getcg()); + return 1; + break; + } + default: { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "SERVER: unrecognized message -> exiting... cg: %ld bytes", getcg()); + return 1; + } + } + } + + if (FD_ISSET(infd, &rset)) { + aflog(LOG_T_MANAGE, LOG_I_DEBUG, + "infd: FD_ISSET"); + if (fgets((char*) &buff[5], 8091, infp) == NULL) { /* client quits --> exiting */ + aflog(LOG_T_MANAGE, LOG_I_NOTICE, + "CLIENT CLOSED cg: %ld bytes", getcg()); + return 0; + } + n = strlen((char*) &buff[5]); + if ((n > 0) && (buff[n+4] == '\n')) { + --n; + } + buff[0] = AF_S_ADMIN_CMD; + buff[1] = AF_RA_CMD; + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(type, master, buff, n+5); + } + } +} diff --git a/src/client_remoteadmin.h b/src/client_remoteadmin.h new file mode 100644 index 0000000..f20af13 --- /dev/null +++ b/src/client_remoteadmin.h @@ -0,0 +1,38 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_CLIENT_REMOTEADMIN_H +#define _JS_CLIENT_REMOTEADMIN_H + +#include <stdlib.h> +#include <string.h> + +#include "remoteadmin_codes.h" +#include "activefor.h" +#include "network.h" +#include "logging.h" +#include "stats.h" +#include "make_ssl_handshake.h" +#include "ssl_fd_struct.h" + +int client_admin(char, SslFd*, unsigned char*, int, char*); + +#endif + diff --git a/src/client_reverse_udp.c b/src/client_reverse_udp.c new file mode 100644 index 0000000..882a6f9 --- /dev/null +++ b/src/client_reverse_udp.c @@ -0,0 +1,213 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "client_reverse_udp.h" + +#include <stdlib.h> + +/* + * Function name: initialize_client_reverse_udp + * Description: Initializes the realm for reverse udp connection. + * Arguments: cr - pointer to ClientRealm structure + * Returns: 0 - connection was initialized successfully, + * 1 - connection initialization failed. + */ + +int +initialize_client_reverse_udp(ClientRealm* cr) +{ + int tmp; + int wanttoexit = (ArOptions_get_arStart(ClientRealm_get_arOptions(cr)) == AR_OPTION_ENABLED) ? 0 : 1; + ClientRealm_set_usersLimit(cr, 1); + if (ip_connect(&tmp, ClientRealm_get_serverName(cr), + ClientRealm_get_managePort(cr), + ClientRealm_get_ipFamily(cr), NULL, NULL)) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect_%s error for %s, %s", + (ClientRealm_get_ipFamily(cr) & 0x02) ? + "ipv4" : (ClientRealm_get_ipFamily(cr) & 0x04) ? + "ipv6":"unspec", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); +#else + aflog(LOG_T_INIT, LOG_I_CRIT, + "tcp_connect error for %s, %s", ClientRealm_get_serverName(cr), ClientRealm_get_managePort(cr)); +#endif + if (wanttoexit) { + exit(1); + } + else { + return 1; + } + + } + SslFd_set_fd(ClientRealm_get_masterSslFd(cr), tmp); + SslFd_set_ssl(ClientRealm_get_masterSslFd(cr), NULL); + return 0; +} + +/* + * Function name: client_reverse_udp + * Description: This function is responsible for the client part of the reverse udp tunnel. + * Arguments: cr - pointer to ClientRealm structure + * buff - buffer which will be used for communication + * buflength - socket send buffer size + */ + +void +client_reverse_udp(ClientRealm* cr, unsigned char* buff, int buflength) +{ + socklen_t len, addrlen; + int maxfdp1, temp, n, length; +#ifdef HAVE_LINUX_SOCKIOS_H + int notsent; +#endif + struct sockaddr* cliaddr; + fd_set rset, allset; + + if (ip_listen(&temp, ClientRealm_get_hostName(cr), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(cr), 0)), &addrlen, + ClientRealm_get_ipFamily(cr) & 0xfe)) { +#ifdef AF_INET6 + aflog(LOG_T_INIT, LOG_I_DEBUG, + "udp_listen_%s error for %s, %s", + (ClientRealm_get_ipFamily(cr) & 0x02) ? + "ipv4":(ClientRealm_get_ipFamily(cr) & 0x04) ? + "ipv6":"unspec", ClientRealm_get_hostName(cr), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(cr), 0))); +#else + aflog(LOG_T_INIT, LOG_I_DEBUG, + "udp_listen error for %s, %s", ClientRealm_get_hostName(cr), + PortListNode_get_portName(PortList_get_nth(ClientRealm_get_destinationPorts(cr), 0))); +#endif + exit(1); + } + ConnectUser_set_connFd(ClientRealm_get_usersTable(cr)[0], temp); + cliaddr = malloc(addrlen); + FD_ZERO(&allset); + + FD_SET(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), &allset); + maxfdp1 = SslFd_get_fd(ClientRealm_get_masterSslFd(cr)) + 1; + maxfdp1 = (maxfdp1 > (ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]) + 1)) ? + maxfdp1 : (ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]) + 1); + FD_SET(ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]), &allset); + aflog(LOG_T_CLIENT, LOG_I_INFO, + "CLIENT STARTED mode: udp reverse"); + for ( ; ; ) { + len = 4; + if (getsockopt(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), SOL_SOCKET, SO_SNDBUF, &temp, &len) != -1) { + if (temp != buflength) { + buflength = temp; + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "Send buffer size changed..."); + } + } + len = addrlen; + rset = allset; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "select"); + select(maxfdp1, &rset, NULL, NULL, NULL); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "after select..."); + + if (FD_ISSET(ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]), &rset)) { /* FD_ISSET CONTABLE[0].CONNFD RSET*/ + n = recvfrom(ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]), &buff[5], 8091, 0, cliaddr, &len); +#ifdef HAVE_LINUX_SOCKIOS_H +# ifdef SIOCOUTQ + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "SIOCOUTQ is defined"); + if (ioctl(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), SIOCOUTQ, ¬sent)) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "ioctl error -> exiting..."); + exit(1); + } + if (buflength <= notsent + n + 5) { /* when we can't do this */ + aflog(LOG_T_CLIENT, LOG_I_INFO, + "drop: size:%d, buf:%d, w:%d/%d", n, buflength, notsent, buflength); +# else + aflog(LOG_T_MAIN< LOG_I_DDEBUG, + "TIOCOUTQ is defined"); + if (ioctl(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), TIOCOUTQ, ¬sent)) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "ioctl error -> exiting..."); + exit(1); + } + if (notsent <= n + 5) { /* when we can't do this */ + aflog(LOG_T_CLIENT, LOG_I_INFO, + "drop: size:%d, buf:%d, w:%d/%d", n, buflength, buflength - notsent, buflength); +# endif + } + else { +#endif + if (n > 0) { +#ifdef HAVE_LINUX_SOCKIOS_H + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Sending %d bytes to service (w:%d/%d) (FROM:%s)", n, +# ifdef SIOCOUTQ + notsent +# else + buflength - notsent +# endif + , buflength, sock_ntop(cliaddr, len, NULL, NULL, 0)); +#else + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Sending %d bytes to service (FROM:%s)", n, sock_ntop(cliaddr, len, NULL, NULL, 0)); +#endif + buff[0] = AF_S_MESSAGE; + buff[1] = AF_S_LOGIN; + buff[2] = AF_S_MESSAGE; + buff[3] = n >> 8; + buff[4] = n; + writen(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), buff, n + 5); + } +#ifdef HAVE_LINUX_SOCKIOS_H + } +#endif + } /* - FD_ISSET CONTABLE[0].CONNFD RSET */ + + if (FD_ISSET(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), &rset)) { /* FD_ISSET MASTER.COMMFD RSET */ + n = readn(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), buff, 5); + if (n == 5) { + if ((buff[0] != AF_S_MESSAGE) || (buff[1] != AF_S_LOGIN) || (buff[2] != AF_S_MESSAGE)) { + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "Incompatible server type (not udp?) or data corruption -> exiting..."); + exit(1); + } + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is length of message */ + n = readn(SslFd_get_fd(ClientRealm_get_masterSslFd(cr)), buff, length); + } + else { + n = 0; + } + if (n == 0) { /* server quits -> we do the same... */ + aflog(LOG_T_CLIENT, LOG_I_CRIT, + "premature quit of the server -> exiting..."); + exit(1); + } + aflog(LOG_T_CLIENT, LOG_I_INFO, + "Sending %d bytes to user (TO:%s)", n, sock_ntop(cliaddr, addrlen, NULL, NULL, 0)); + sendto(ConnectUser_get_connFd(ClientRealm_get_usersTable(cr)[0]), buff, n, 0, cliaddr, addrlen); + } /* - FD_ISSET MASTER.COMMFD RSET */ + } + exit(0); /* we shouldn't get here */ +} diff --git a/src/client_reverse_udp.h b/src/client_reverse_udp.h new file mode 100644 index 0000000..b1f9590 --- /dev/null +++ b/src/client_reverse_udp.h @@ -0,0 +1,41 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#ifdef HAVE_LINUX_SOCKIOS_H +#include <linux/sockios.h> +#endif + +#ifndef _JS_CLIENT_REVERSE_UDP_H +#define _JS_CLIENT_REVERSE_UDP_H + +#include <sys/ioctl.h> + +#include "activefor.h" +#include "stats.h" +#include "logging.h" +#include "ssl_fd_struct.h" +#include "client_realm_struct.h" + +int initialize_client_reverse_udp(ClientRealm* cr); +void client_reverse_udp(ClientRealm* cr, unsigned char* buff, int buflength); + +#endif diff --git a/src/client_shutdown.c b/src/client_shutdown.c new file mode 100644 index 0000000..1847899 --- /dev/null +++ b/src/client_shutdown.c @@ -0,0 +1,48 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <assert.h> + +#include "client_shutdown.h" + +void +close_connections(int usernum, ConnectUser*** contable) +{ + int i; + + assert(contable != NULL); + if (contable == NULL) { + return; + } + + if (*contable) { + for (i = 0; i < usernum; ++i) { + if ((ConnectUser_get_state((*contable)[i]) == S_STATE_OPEN) || + (ConnectUser_get_state((*contable)[i]) == S_STATE_STOPPED)) { + close(ConnectUser_get_connFd((*contable)[i])); + } + ConnectUser_free(&(*contable)[i]); + } + free(*contable); + (*contable) = NULL; + } +} + diff --git a/src/client_shutdown.h b/src/client_shutdown.h new file mode 100644 index 0000000..959fae0 --- /dev/null +++ b/src/client_shutdown.h @@ -0,0 +1,30 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#ifndef _JS_CLIENT_SHUTDOWN_H +#define _JS_CLIENT_SHUTDOWN_H + +#include "activefor.h" + +void close_connections(int usernum, ConnectUser*** contable); + +#endif diff --git a/src/client_signals.c b/src/client_signals.c new file mode 100644 index 0000000..04c344e --- /dev/null +++ b/src/client_signals.c @@ -0,0 +1,60 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "client_signals.h" +#include "thread_management.h" +#include "stats.h" +#include "logging.h" + +#include <stdlib.h> + +/* + * Function name: client_sig_int + * Description: Function responsible for handling SIG_INT. + * Arguments: signo - the signal number + */ + +void +client_sig_int(int signo) +{ +#ifdef HAVE_LIBPTHREAD + if (!is_this_a_mainthread()) { + return; + } +#endif + aflog(LOG_T_MAIN, LOG_I_NOTICE, + "CLIENT CLOSED cg: %ld bytes", getcg()); + exit(0); +} + +/* + * Function name: client_sig_alrm + * Description: Function responsible for handling SIG_ALRM. + * Arguments: signo - the signal number + */ + +void +client_sig_alrm(int signo) +{ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "Received SIGALRM"); +} diff --git a/src/client_signals.h b/src/client_signals.h new file mode 100644 index 0000000..03c14cf --- /dev/null +++ b/src/client_signals.h @@ -0,0 +1,28 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_CLIENT_SIGNALS_H +#define _JS_CLIENT_SIGNALS_H + +void client_sig_int(int); /* INT signal handler for the afclient */ +void client_sig_alrm(int); /* ALRM signal handler for the afclient */ + +#endif + diff --git a/src/clientnames.c b/src/clientnames.c new file mode 100644 index 0000000..750b9c9 --- /dev/null +++ b/src/clientnames.c @@ -0,0 +1,173 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include "clientnames.h" + +char* +get_clientname(ServerRealm* pointer, int client) +{ + static char clientname[10]; + + assert(pointer != NULL); + if (pointer == NULL) { + return NULL; + } + + if (ConnectClient_get_sClientId(ServerRealm_get_clientsTable(pointer)[client]) == NULL) { + memset(clientname, 0, 10); + sprintf(clientname, "%d", ConnectClient_get_clientId(ServerRealm_get_clientsTable(pointer)[client])); + return clientname; + } + + return ConnectClient_get_sClientId(ServerRealm_get_clientsTable(pointer)[client]); +} + +int +get_clientid(ServerRealm* pointer, char* clientname) +{ + int i, n; + char guard; + + assert(pointer != NULL); + if (pointer == NULL) { + return -1; + } + + assert(clientname != NULL); + if (clientname == NULL) { + return -1; + } + + for (i = 0; i < ServerRealm_get_clientsLimit(pointer); ++i) { + if (ConnectClient_get_sClientId(ServerRealm_get_clientsTable(pointer)[i]) != NULL) { + if (strcmp(clientname, ConnectClient_get_sClientId(ServerRealm_get_clientsTable(pointer)[i])) == 0) { + return ConnectClient_get_clientId(ServerRealm_get_clientsTable(pointer)[i]); + } + } + } + + if (sscanf(clientname, "%d%c", &i, &guard) == 1) { + n = get_clientnumber(pointer, i); + if ((n >= 0) && (n < ServerRealm_get_clientsLimit(pointer))) { + if (ConnectClient_get_sClientId(ServerRealm_get_clientsTable(pointer)[n]) == NULL) { + return i; + } + } + } + return -1; +} + +int +get_clientnumber(ServerRealm* pointer, int clientid) +{ + int i; + + assert(pointer != NULL); + if (pointer == NULL) { + return -1; + } + + for (i = 0; i < ServerRealm_get_clientsLimit(pointer); ++i) { + if (ConnectClient_get_clientId(ServerRealm_get_clientsTable(pointer)[i]) == clientid) { + return i; + } + } + + return -1; +} + +char* +get_raclientname(ServerRealm* pointer, int client) +{ + static char clientname[10]; + + assert(pointer != NULL); + if (pointer == NULL) { + return NULL; + } + + if (ConnectClient_get_sClientId(ServerRealm_get_raClientsTable(pointer)[client]) == NULL) { + memset(clientname, 0, 10); + sprintf(clientname, "%d", ConnectClient_get_clientId(ServerRealm_get_raClientsTable(pointer)[client])); + return clientname; + } + + return ConnectClient_get_sClientId(ServerRealm_get_raClientsTable(pointer)[client]); +} + +int +get_raclientid(ServerRealm* pointer, char* clientname) +{ + int i, n; + char guard; + + assert(pointer != NULL); + if (pointer == NULL) { + return -1; + } + + assert(clientname != NULL); + if (clientname == NULL) { + return -1; + } + + for (i = 0; i < ServerRealm_get_raClientsLimit(pointer); ++i) { + if (ConnectClient_get_sClientId(ServerRealm_get_raClientsTable(pointer)[i]) != NULL) { + if (strcmp(clientname, ConnectClient_get_sClientId(ServerRealm_get_raClientsTable(pointer)[i])) == 0) { + return ConnectClient_get_clientId(ServerRealm_get_raClientsTable(pointer)[i]); + } + } + } + + if (sscanf(clientname, "%d%c", &i, &guard) == 1) { + n = get_raclientnumber(pointer, i); + if ((n >= 0) && (n < ServerRealm_get_raClientsLimit(pointer))) { + if (ConnectClient_get_sClientId(ServerRealm_get_raClientsTable(pointer)[n]) == NULL) { + return i; + } + } + } + + return -1; +} + +int +get_raclientnumber(ServerRealm* pointer, int clientid) +{ + int i; + + assert(pointer != NULL); + if (pointer == NULL) { + return -1; + } + + for (i = 0; i < ServerRealm_get_raClientsLimit(pointer); ++i) { + if (ConnectClient_get_clientId(ServerRealm_get_raClientsTable(pointer)[i]) == clientid) { + return i; + } + } + + return -1; +} diff --git a/src/clientnames.h b/src/clientnames.h new file mode 100644 index 0000000..9f93596 --- /dev/null +++ b/src/clientnames.h @@ -0,0 +1,36 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "server_realm_struct.h" + +#ifndef _JS_CLIENTNAMES_H +#define _JS_CLIENTNAMES_H + +char* get_clientname(ServerRealm*, int); +int get_clientid(ServerRealm*, char*); +int get_clientnumber(ServerRealm*, int); + +char* get_raclientname(ServerRealm*, int); +int get_raclientid(ServerRealm*, char*); +int get_raclientnumber(ServerRealm*, int); + +#endif + diff --git a/src/connect_client_struct.c b/src/connect_client_struct.c new file mode 100644 index 0000000..7d57b4b --- /dev/null +++ b/src/connect_client_struct.c @@ -0,0 +1,863 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "string_functions.h" +#include "timeval_functions.h" +#include "connect_client_struct.h" + +/* + * Function name: ConnectClient_new + * Description: Creates and initializes new ConnectClient structure. + * Returns: Pointer to newly created ConnectClient structure. + */ + +ConnectClient* +ConnectClient_new() +{ + ConnectClient* tmp = calloc(1, sizeof(ConnectClient)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + tmp->sslFd = SslFd_new(); + assert(tmp->sslFd != NULL); + if (tmp->sslFd == NULL) { + ConnectClient_free(&tmp); + return NULL; + } + tmp->auditList = AuditList_new(); + assert(tmp->auditList != NULL); + if (tmp->auditList == NULL) { + ConnectClient_free(&tmp); + return NULL; + } + tmp->header = HeaderBuffer_new(); + assert(tmp->header != NULL); + if (tmp->header == NULL) { + ConnectClient_free(&tmp); + return NULL; + } + return tmp; +} + +/* + * Function name: ConnectClient_free + * Description: Frees the memory allocated for ConnectClient structure. + * Arguments: cc - pointer to pointer to ConnectClient structure + */ + +void +ConnectClient_free(ConnectClient** cc) +{ + SslFd* sftmp; + AuditList* altmp; + assert(cc != NULL); + if (cc == NULL) { + return; + } + assert((*cc) != NULL); + if ((*cc) == NULL) { + return; + } + sftmp = ConnectClient_get_sslFd((*cc)); + altmp = ConnectClient_get_auditList((*cc)); + SslFd_free(&sftmp); + AuditList_free(&altmp); + if ((*cc)->users) { + free((*cc)->users); + (*cc)->users = NULL; + } + if ((*cc)->sClientId) { + free((*cc)->sClientId); + (*cc)->sClientId = NULL; + } + free((*cc)); + (*cc) = NULL; +} + +/* + * Function name: ConnectClient_set_state + * Description: Sets state of the connected client. + * Arguments: cc - pointer to ConnectClient structure + * state - state of the connected client + */ + +void +ConnectClient_set_state(ConnectClient* cc, char state) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->state = state; +} + +/* + * Function name: ConnectClient_set_sslFd + * Description: Sets SslFd structure. + * Arguments: cc - pointer to ConnectClient structure + * sf - SslFd structure + */ + +void +ConnectClient_set_sslFd(ConnectClient* cc, SslFd* sf) +{ + SslFd* sftmp; + assert(cc != NULL); + if (cc == NULL) { + return; + } + sftmp = ConnectClient_get_sslFd(cc); + SslFd_free(&sftmp); + cc->sslFd = sf; +} + +/* + * Function name: ConnectClient_set_timer + * Description: Sets timer of the client used for internal time counting. + * Arguments: cc - pointer to ConnectClient structure + * timer - timer of the client used for internal time counting + */ + +void +ConnectClient_set_timer(ConnectClient* cc, struct timeval timer) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->timer = timer; +} + +/* + * Function name: ConnectClient_set_users + * Description: Sets users descriptor table. + * Arguments: cc - pointer to ConnectClient structure + * users - users descriptor table + */ + +void +ConnectClient_set_users(ConnectClient* cc, int* users) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + if (cc->users) { + free(cc->users); + } + cc->users = users; +} + +/* + * Functions name: ConnectClient_set_connected + * Description: Sets number of connected users. + * Arguments: cc - pointer to ConnectClient structure + * connected - number of connected users + */ + +void +ConnectClient_set_connected(ConnectClient* cc, int connected) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->connected = connected; +} + +/* + * Function name: ConnectClient_set_limit + * Description: Sets limit of connected users. + * Arguments: cc - pointer to ConnectClient structure + * limit - limit of connected users + */ + +void +ConnectClient_set_limit(ConnectClient* cc, int limit) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->limit = limit; +} + +/* + * Function name: ConnectClient_set_listenFd + * Description: Sets listen socket descriptor. + * Arguments: cc - pointer to ConnectClient structure + * listenFd - listen socket descriptor + */ + +void +ConnectClient_set_listenFd(ConnectClient* cc, int listenFd) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->listenFd = listenFd; +} + +/* + * Function name: ConnectClient_set_usrCliPair + * Description: Sets user-client pair number. + * Arguments: cc - pointer to ConnectClient structure + * usrCliPair - user-client pair number + */ + +void +ConnectClient_set_usrCliPair(ConnectClient* cc, int usrCliPair) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->usrCliPair = usrCliPair; +} + +/* + * Function name: ConnectClient_set_clientId + * Description: Sets client identification number. + * Arguments: cc - pointer to ConnectClient structure + * clientId - client identification number + */ + +void +ConnectClient_set_clientId(ConnectClient* cc, int clientId) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->clientId = clientId; +} + +/* + * Function name: ConnectClient_set_connectTime + * Description: Sets start time of the connection. + * Arguments: cc - pointer to ConnectClient structure + * connectTime - start time of the connection + */ + +void +ConnectClient_set_connectTime(ConnectClient* cc, time_t connectTime) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->connectTime = connectTime; +} + +/* + * Function name: ConnectClient_set_lastActivity + * Description: Sets time of the last client activity (when last packet from afclient has arrived) + * Arguments: cc - pointer to ConnectClient structure + * lastActivity - time of the last client activity + */ + +void +ConnectClient_set_lastActivity(ConnectClient* cc, time_t lastActivity) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->lastActivity = lastActivity; +} + +/* + * Function name: ConnectClient_set_sClientId + * Description: Sets client identification string. + * Arguments: cc - pointer to ConnectClient structure + * sClientId - client identification string + */ + +void +ConnectClient_set_sClientId(ConnectClient* cc, char* sClientId) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + string_cp(&(cc->sClientId), sClientId); +} + +/* + * Function name: ConnectClient_set_nameBuf + * Description: Sets name of the client. + * Arguments: cc - pointer to ConnectClient structure + * nameBuf - name of the client + */ + +void +ConnectClient_set_nameBuf(ConnectClient* cc, char* nameBuf) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + memset(cc->nameBuf, 0, 128); + strncpy(cc->nameBuf, nameBuf, 127); +} + +/* + * Function name: ConnectClient_set_portBuf + * Description: Sets port from which client is connected. + * Arguments: cc - pointer to ConnectClient structure + * portBuf - port from which client is connected + */ + +void +ConnectClient_set_portBuf(ConnectClient* cc, char* portBuf) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + memset(cc->portBuf, 0, 7); + strncpy(cc->portBuf, portBuf, 6); +} + +/* + * Function name: ConnectClient_set_tunnelType + * Description: Sets tupe of the client tunnel. + * Arguments: cc - pointer to ConnectClient structure + * tunnelType - tupe of the client tunnel + */ + +void +ConnectClient_set_tunnelType(ConnectClient* cc, char tunnelType) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + cc->tunnelType = tunnelType; +} + +/* + * Function name: ConnectClient_set_multi + * Description: Sets the status of the multi option. + * Arguments: cc - pointer to ConnectClient structure + * multi - the status of the multi option + */ + +void +ConnectClient_set_multi(ConnectClient* cc, char multi) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + assert((multi == CONNECTCLIENT_MULTI_ENABLED) || (multi == CONNECTCLIENT_MULTI_DISABLED)); + cc->multi = multi; +} + +/* + * Function name: ConnectClient_set_auditList + * Description: Sets audit list for the audit feature. + * Arguments: cc - pointer to ConnectClient structure + * al - audit list for the audit feature + */ + +void +ConnectClient_set_auditList(ConnectClient* cc, AuditList* al) +{ + AuditList* altmp; + assert(cc != NULL); + if (cc == NULL) { + return; + } + altmp = ConnectClient_get_auditList(cc); + AuditList_free(&altmp); + cc->auditList = al; +} + +/* + * Function name: ConnectClient_set_header + * Description: Sets header buffer for incomplete headers. + * Arguments: cc - pointer to ConnectClient structure + * hb - header buffer for incomplete headers + */ + +void +ConnectClient_set_header(ConnectClient* cc, HeaderBuffer* hb) +{ + HeaderBuffer* hbtmp; + assert(cc != NULL); + if (cc == NULL) { + return; + } + hbtmp = ConnectClient_get_header(cc); + HeaderBuffer_free(&hbtmp); + cc->header = hb; +} + +/* + * Function name: ConnectClient_set_task + * Description: Sets the client task. + * Arguments: cc - pointer to ConnectClient structure + * task - the task to set + */ + +void +ConnectClient_set_task(ConnectClient* cc, Task* task) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + if (cc->task) { + Task_free(&(cc->task)); + } + cc->task = task; +} + +/* + * Function name: ConnectClient_get_state + * Description: Gets state of the connected client. + * Arguments: cc - pointer to ConnectClient structure + * Returns: State of the connected client. + */ + +char +ConnectClient_get_state(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return CONNECTCLIENT_STATE_UNKNOWN; + } + return cc->state; +} + +/* + * Function name: ConnectClient_get_sslFd + * Description: Gets SslFd structure. + * Arguments: cc - pointer to ConnectClient structure + * Returns: SslFd structure. + */ + +SslFd* +ConnectClient_get_sslFd(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->sslFd; +} + +/* + * Function name: ConnectClient_get_timer + * Description: Gets timer of the client used for internal time counting. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Timer of the client used for internal time counting. + */ + +struct timeval +ConnectClient_get_timer(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return timeval_create(0, 0); + } + return cc->timer; +} + +/* + * Function name: ConnectClient_get_users + * Description: Gets users descriptor table. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Users descriptor table. + */ + +int* +ConnectClient_get_users(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->users; +} + +/* + * Function name: ConnectClient_get_connected + * Description: Gets number of connected users. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Number of connected users. + */ + +int +ConnectClient_get_connected(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return -1; + } + return cc->connected; +} + +/* + * Function name: ConnectClient_get_limit + * Description: Gets limit of connected users. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Limit of connected users. + */ + +int +ConnectClient_get_limit(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return -1; + } + return cc->limit; +} + +/* + * Function name: ConnectClient_get_listenFd + * Description: Gets listen socket descriptor. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Listen socket descriptor. + */ + +int +ConnectClient_get_listenFd(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return -1; + } + return cc->listenFd; +} + +/* + * Function name: ConnectClient_get_usrCliPair + * Description: Gets user-client pair number. + * Arguments: cc - pointer to ConnectClient structure + * Returns: User-client pair number. + */ + +int +ConnectClient_get_usrCliPair(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return -1; + } + return cc->usrCliPair; +} + +/* + * Function name: ConnectClient_get_clientId + * Description: Gets client identification number. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Client identification number. + */ + +int +ConnectClient_get_clientId(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return -1; + } + return cc->clientId; +} + +/* + * Function name: ConnectClient_get_connectTime + * Description: Gets start time of the connection. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Start time of the connection. + */ + +time_t +ConnectClient_get_connectTime(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return 0; + } + return cc->connectTime; +} + +/* + * Function name: ConnectClient_get_lastActivity + * Description: Gets time of the last client activity (when last packet from afclient has arrived) + * Arguments: cc - pointer to ConnectClient structure + * Returns: Time of the last client activity. + */ + +time_t +ConnectClient_get_lastActivity(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return 0; + } + return cc->lastActivity; +} + +/* + * Function name: ConnectClient_get_sClientId + * Description: Gets client identification string. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Client identification string. + */ + +char* +ConnectClient_get_sClientId(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->sClientId; +} + +/* + * Function name: ConnectClient_get_nameBuf + * Description: Gets name of the client. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Name of the client. + */ + +char* +ConnectClient_get_nameBuf(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->nameBuf; +} + +/* + * Function name: ConnectClient_get_portBuf + * Description: Gets port from which client is connected. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Port from which client is connected. + */ + +char* +ConnectClient_get_portBuf(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->portBuf; +} + +/* + * Function name: ConnectClient_get_tunnelType + * Description: Gets tupe of the client tunnel. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Tupe of the client tunnel. + */ + +char +ConnectClient_get_tunnelType(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return CONNECTCLIENT_TUNNELTYPE_UNKNOWN; + } + return cc->tunnelType; +} + +/* + * Function name: ConnectClient_get_multi + * Description: Gets the status of the multi option. + * Arguments: cc - pointer to ConnectClient structure + * Returns: CONNECTCLIENT_MULTI_ENABLED - the option is enabled, + * CONNECTCLIENT_MULTI_DISABLED - the option is disabled. + */ + +char +ConnectClient_get_multi(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return CONNECTCLIENT_MULTI_DISABLED; + } + return cc->multi; +} + +/* + * Function name: ConnectClient_get_auditList + * Description: Gets audit list for the audit feature. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Audit list for the audit feature. + */ + +AuditList* +ConnectClient_get_auditList(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->auditList; +} + +/* + * Function name: ConnectClient_get_header + * Description: Gets header buffer for incomplete headers. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Header buffer for incomplete headers. + */ + +HeaderBuffer* +ConnectClient_get_header(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->header; +} + +/* + * Function name: ConnectClient_get_task + * Description: Gets the client task. + * Arguments: cc - pointer to ConnectClient structure + * Returns: The client task. + */ + +Task* +ConnectClient_get_task(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return cc->task; +} + +/* + * Function name: ConnectClient_create_users + * Description: Creates user descriptor table. Memory for the table is allocated according + * to the previously set 'limit' value. All the descriptors are set to -1. + * Arguments: cc - pointer to ConnectClient structure + * Returns: >0 - there were some problems with memory allocation + * 0 - everything was ok + */ + +int +ConnectClient_create_users(ConnectClient* cc) +{ + int i, limit; + assert(cc != NULL); + if (cc == NULL) { + return 1; + } + limit = ConnectClient_get_limit(cc); + assert(limit != -1); + if (limit == -1) { + return 2; + } + cc->users = malloc(limit * sizeof(int)); + assert(cc->users != NULL); + if (cc->users == NULL) { + return 3; + } + for (i = 0; i < limit; ++i) { + cc->users[i] = -1; + } + return 0; +} + +/* + * Function name: ConnectClient_get_timerp + * Description: Gets pointer to timer of the client used for internal time counting. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Pointer to timer of the client used for internal time counting. + */ + +struct timeval* +ConnectClient_get_timerp(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return (&(cc->timer)); +} + +/* + * Function name: ConnectClient_increase_connected + * Description: Increases number of connected users. + * Arguments: cc - pointer to ConnectClient structure + */ + +void +ConnectClient_increase_connected(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + ConnectClient_set_connected(cc, ConnectClient_get_connected(cc) + 1); +} + +/* + * Function name: ConnectClient_decrease_connected + * Description: Decreases number of connected users. + * Arguments: cc - pointer to ConnectClient structure + */ + +void +ConnectClient_decrease_connected(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return; + } + ConnectClient_set_connected(cc, ConnectClient_get_connected(cc) - 1); +} + +/* + * Function name: ConnectClient_get_listenFdp + * Description: Gets pointer to listen socket descriptor. + * Arguments: cc - pointer to ConnectClient structure + * Returns: Pointer to listen socket descriptor. + */ + +int* +ConnectClient_get_listenFdp(ConnectClient* cc) +{ + assert(cc != NULL); + if (cc == NULL) { + return NULL; + } + return (&(cc->listenFd)); +} diff --git a/src/connect_client_struct.h b/src/connect_client_struct.h new file mode 100644 index 0000000..9cf2e6d --- /dev/null +++ b/src/connect_client_struct.h @@ -0,0 +1,119 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _JS_CONNECT_CLIENT_STRUCT_H +#define _JS_CONNECT_CLIENT_STRUCT_H + +#include <time.h> + +#include "ssl_fd_struct.h" +#include "audit_list_struct.h" +#include "header_buffer_struct.h" +#include "task_struct.h" + +#define CONNECTCLIENT_STATE_UNKNOWN -1 +#define CONNECTCLIENT_STATE_FREE 0 +#define CONNECTCLIENT_STATE_CONNECTING 1 +#define CONNECTCLIENT_STATE_AUTHORIZING 2 +#define CONNECTCLIENT_STATE_ACCEPTED 3 + +#define CONNECTCLIENT_TUNNELTYPE_UNKNOWN -1 +#define CONNECTCLIENT_TUNNELTYPE_DIRECT 0 +#define CONNECTCLIENT_TUNNELTYPE_HTTPPROXY 1 +#define CONNECTCLIENT_TUNNELTYPE_HTTPSPROXY 2 + +#define CONNECTCLIENT_MULTI_ENABLED 1 +#define CONNECTCLIENT_MULTI_DISABLED 0 + +typedef struct { + char state; + SslFd* sslFd; + struct timeval timer; + int* users; + int connected; + int limit; + int listenFd; + int usrCliPair; + int clientId; + time_t connectTime; + time_t lastActivity; + char* sClientId; + char nameBuf[128]; + char portBuf[7]; + char tunnelType; + char multi; + AuditList* auditList; + HeaderBuffer* header; + Task* task; +} ConnectClient; + +/* 'constructor' */ +ConnectClient* ConnectClient_new(); +/* 'destructor' */ +void ConnectClient_free(ConnectClient** cc); +/* setters */ +void ConnectClient_set_state(ConnectClient* cc, char state); +void ConnectClient_set_sslFd(ConnectClient* cc, SslFd* sf); +void ConnectClient_set_timer(ConnectClient* cc, struct timeval timer); +void ConnectClient_set_users(ConnectClient* cc, int* users); +void ConnectClient_set_connected(ConnectClient* cc, int connected); +void ConnectClient_set_limit(ConnectClient* cc, int limit); +void ConnectClient_set_listenFd(ConnectClient* cc, int listenFd); +void ConnectClient_set_usrCliPair(ConnectClient* cc, int usrCliPair); +void ConnectClient_set_clientId(ConnectClient* cc, int clientId); +void ConnectClient_set_connectTime(ConnectClient* cc, time_t connectTime); +void ConnectClient_set_lastActivity(ConnectClient* cc, time_t lastActivity); +void ConnectClient_set_sClientId(ConnectClient* cc, char* sClientId); +void ConnectClient_set_nameBuf(ConnectClient* cc, char* nameBuf); +void ConnectClient_set_portBuf(ConnectClient* cc, char* portBuf); +void ConnectClient_set_tunnelType(ConnectClient* cc, char tunnelType); +void ConnectClient_set_multi(ConnectClient* cc, char multi); +void ConnectClient_set_auditList(ConnectClient* cc, AuditList* al); +void ConnectClient_set_header(ConnectClient* cc, HeaderBuffer* hb); +void ConnectClient_set_task(ConnectClient* cc, Task* task); +/* getters */ +char ConnectClient_get_state(ConnectClient* cc); +SslFd* ConnectClient_get_sslFd(ConnectClient* cc); +struct timeval ConnectClient_get_timer(ConnectClient* cc); +int* ConnectClient_get_users(ConnectClient* cc); +int ConnectClient_get_connected(ConnectClient* cc); +int ConnectClient_get_limit(ConnectClient* cc); +int ConnectClient_get_listenFd(ConnectClient* cc); +int ConnectClient_get_usrCliPair(ConnectClient* cc); +int ConnectClient_get_clientId(ConnectClient* cc); +time_t ConnectClient_get_connectTime(ConnectClient* cc); +time_t ConnectClient_get_lastActivity(ConnectClient* cc); +char* ConnectClient_get_sClientId(ConnectClient* cc); +char* ConnectClient_get_nameBuf(ConnectClient* cc); +char* ConnectClient_get_portBuf(ConnectClient* cc); +char ConnectClient_get_tunnelType(ConnectClient* cc); +char ConnectClient_get_multi(ConnectClient* cc); +AuditList* ConnectClient_get_auditList(ConnectClient* cc); +HeaderBuffer* ConnectClient_get_header(ConnectClient* cc); +Task* ConnectClient_get_task(ConnectClient* cc); +/* other */ +int ConnectClient_create_users(ConnectClient* cc); +struct timeval* ConnectClient_get_timerp(ConnectClient* cc); +void ConnectClient_increase_connected(ConnectClient* cc); +void ConnectClient_decrease_connected(ConnectClient* cc); +int* ConnectClient_get_listenFdp(ConnectClient* cc); + +#endif diff --git a/src/connect_user_struct.c b/src/connect_user_struct.c new file mode 100644 index 0000000..ac6fe3c --- /dev/null +++ b/src/connect_user_struct.c @@ -0,0 +1,398 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "activefor.h" +#include "connect_user_struct.h" + +/* + * Function name: ConnectUser_new + * Description: Create and initialize new ConnectUser structure. + * Returns: Newly created ConnectUser structure. + */ + +ConnectUser* +ConnectUser_new() +{ + ConnectUser* tmp = calloc(1, sizeof(ConnectUser)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + tmp->bufList = BufList_new(); + assert(tmp->bufList != NULL); + if (tmp->bufList == NULL) { + ConnectUser_free(&tmp); + return NULL; + } + tmp->stats = UserStats_new(); + assert(tmp->stats != NULL); + if (tmp->stats == NULL) { + ConnectUser_free(&tmp); + return NULL; + } + return tmp; +} + +/* + * Function name: ConnectUser_free + * Description: Free the memory allocated for ConnectUser structure. + * Arguments: cu - pointer to pointer to ConnectUser structure + */ + +void +ConnectUser_free(ConnectUser** cu) +{ + BufList* bftmp; + UserStats* ustmp; + assert(cu != NULL); + if (cu == NULL) { + return; + } + assert((*cu) != NULL); + if ((*cu) == NULL) { + return; + } + bftmp = ConnectUser_get_bufList((*cu)); + ustmp = ConnectUser_get_stats((*cu)); + BufList_free(&bftmp); + UserStats_free(&ustmp); + free((*cu)); + (*cu) = NULL; +} + +/* + * Function name: ConnectUser_set_state + * Description: Set state of the connected user. + * Arguments: cu - pointer to ConnectUser structure + * state - state of the connected User + */ + +void +ConnectUser_set_state(ConnectUser* cu, char state) +{ + assert(cu != NULL); + if (cu == NULL) { + return; + } + cu->state = state; +} + +/* + * Function name: ConnectUser_set_connFd + * Description: Set connection's file descriptor. + * Arguments: cu - pointer to ConnectUser structure + * connFd - connection's file descriptor + */ + +void +ConnectUser_set_connFd(ConnectUser* cu, int connFd) +{ + assert(cu != NULL); + if (cu == NULL) { + return; + } + cu->connFd = connFd; +} + +/* + * Function name: ConnectUser_set_whatClient + * Description: Set client number, to which this user is connected to. + * Arguments: cu - pointer to ConnectUser structure + * whatClient - client number, to which this user is connected to + */ + +void +ConnectUser_set_whatClient(ConnectUser* cu, int whatClient) +{ + assert(cu != NULL); + if (cu == NULL) { + return; + } + cu->whatClient = whatClient; +} + +/* + * Function name: ConnectUser_set_userId + * Description: Set user identification number. + * Arguments: cu - pointer to ConnectUser structure + * userId - user identification number + */ + +void +ConnectUser_set_userId(ConnectUser* cu, int userId) +{ + assert(cu != NULL); + if (cu == NULL) { + return; + } + cu->userId = userId; +} + +/* + * Function name: ConnectUser_set_connectTime + * Description: Set connect time of the user. + * Arguments: cu - pointer to ConnectUser structure + * connectTime - connect time of the user + */ + +void +ConnectUser_set_connectTime(ConnectUser* cu, time_t connectTime) +{ + assert(cu != NULL); + if (cu == NULL) { + return; + } + cu->connectTime = connectTime; +} + +/* + * Function name: ConnectUser_set_nameBuf + * Description: Set name of the user. + * Arguments: cu - pointer to ConnectUser structure + * nameBuf - name of the user + */ + +void +ConnectUser_set_nameBuf(ConnectUser* cu, char* nameBuf) +{ + assert(cu != NULL); + if (cu == NULL) { + return; + } + memset(cu->nameBuf, 0, 128); + strncpy(cu->nameBuf, nameBuf, 127); +} + +/* + * Function name: ConnectUser_set_portBuf + * Description: Set port from which user is connected. + * Arguments: cu - pointer to ConnectUser structure + * portBuf - port from which user is connected + */ + +void +ConnectUser_set_portBuf(ConnectUser* cu, char* portBuf) +{ + assert(cu != NULL); + if (cu == NULL) { + return; + } + memset(cu->portBuf, 0, 7); + strncpy(cu->portBuf, portBuf, 6); +} + +/* + * Function name: ConnectUser_set_bufList + * Description: Set buffer list for incoming packets. + * Arguments: cu - pointer to ConnectUser structure + * bufList - buffer list for incoming packets + */ + +void +ConnectUser_set_bufList(ConnectUser* cu, BufList* bufList) +{ + BufList* bftmp; + assert(cu != NULL); + if (cu == NULL) { + return; + } + bftmp = ConnectUser_get_bufList(cu); + BufList_free(&bftmp); + cu->bufList = bufList; +} + +/* + * Function name: ConnectUser_set_stats + * Description: Set stats object for this user. + * Arguments: cu - pointer to ConnectUser structure + * stats - stats object for this user + */ + +void +ConnectUser_set_stats(ConnectUser* cu, UserStats* stats) +{ + UserStats* ustmp; + assert(cu != NULL); + if (cu == NULL) { + return; + } + ustmp = ConnectUser_get_stats(cu); + UserStats_free(&ustmp); + cu->stats = stats; +} + +/* + * Function name: ConnectUser_get_state + * Description: Get state of the connected user. + * Arguments: cu - pointer to ConnectUser structure + * Returns: State of the connected user. + */ + +char +ConnectUser_get_state(ConnectUser* cu) +{ + assert(cu != NULL); + if (cu == NULL) { + return S_STATE_CLEAR; + } + return cu->state; +} + +/* + * Function name: ConnectUser_get_connFd + * Description: Get connection's file descriptor. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Connection's file descriptor. + */ + +int +ConnectUser_get_connFd(ConnectUser* cu) +{ + assert(cu != NULL); + if (cu == NULL) { + return -1; + } + return cu->connFd; +} + +/* + * Function name: ConnectUser_get_whatClient + * Description: Get client number, to which this user is connected to. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Client number, to which this user is connected to. + */ + +int +ConnectUser_get_whatClient(ConnectUser* cu) +{ + assert(cu != NULL); + if (cu == NULL) { + return -1; + } + return cu->whatClient; +} + +/* + * Function name: ConnectUser_get_userId + * Description: Get user identification number. + * Arguments: cu - pointer to ConnectUser structure + * Returns: User identification number. + */ + +int +ConnectUser_get_userId(ConnectUser* cu) +{ + assert(cu != NULL); + if (cu == NULL) { + return -1; + } + return cu->userId; +} + +/* + * Function name: ConnectUser_get_connectTime + * Description: Get connect time of the user. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Connect time of the user. + */ + +time_t +ConnectUser_get_connectTime(ConnectUser* cu) +{ + assert(cu != NULL); + if (cu == NULL) { + return 0; + } + return cu->connectTime; +} + +/* + * Function name: ConnectUser_get_nameBuf + * Description: Get name of the user. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Name of the user. + */ + +char* +ConnectUser_get_nameBuf(ConnectUser* cu) +{ + assert(cu != NULL); + if (cu == NULL) { + return NULL; + } + return cu->nameBuf; +} + +/* + * Function name: ConnectUser_get_portBuf + * Description: Get port from which user is connected. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Port from which user is connected. + */ + +char* +ConnectUser_get_portBuf(ConnectUser* cu) +{ + assert(cu != NULL); + if (cu == NULL) { + return NULL; + } + return cu->portBuf; +} + +/* + * Function name: ConnectUser_get_bufList + * Description: Get buffer list for incoming packets. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Buffer list for incoming packets. + */ + +BufList* +ConnectUser_get_bufList(ConnectUser* cu) +{ + assert(cu != NULL); + if (cu == NULL) { + return NULL; + } + return cu->bufList; +} + +/* + * Function name: ConnectUser_get_stats + * Description: Get stats object for this user. + * Arguments: cu - pointer to ConnectUser structure + * Returns: Stats object for this user. + */ + +UserStats* +ConnectUser_get_stats(ConnectUser* cu) +{ + assert(cu != NULL); + if (cu == NULL) { + return NULL; + } + return cu->stats; +} diff --git a/src/connect_user_struct.h b/src/connect_user_struct.h new file mode 100644 index 0000000..8e424d2 --- /dev/null +++ b/src/connect_user_struct.h @@ -0,0 +1,67 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _JS_CONNECT_USER_STRUCT_H +#define _JS_CONNECT_USER_STRUCT_H + +#include <sys/types.h> + +#include "buf_list_struct.h" +#include "user_stats_struct.h" + +typedef struct { + char state; + int connFd; + int whatClient; + int userId; + time_t connectTime; + char nameBuf[128]; + char portBuf[7]; + BufList* bufList; + UserStats* stats; +} ConnectUser; + +/* 'constructor' */ +ConnectUser* ConnectUser_new(); +/* 'destructor' */ +void ConnectUser_free(ConnectUser** cu); +/* setters */ +void ConnectUser_set_state(ConnectUser* cu, char state); +void ConnectUser_set_connFd(ConnectUser* cu, int connFd); +void ConnectUser_set_whatClient(ConnectUser* cu, int whatClient); +void ConnectUser_set_userId(ConnectUser* cu, int userId); +void ConnectUser_set_connectTime(ConnectUser* cu, time_t connectTime); +void ConnectUser_set_nameBuf(ConnectUser* cu, char* nameBuf); +void ConnectUser_set_portBuf(ConnectUser* cu, char* portBuf); +void ConnectUser_set_bufList(ConnectUser* cu, BufList* bufList); +void ConnectUser_set_stats(ConnectUser* cu, UserStats* stats); +/* getters */ +char ConnectUser_get_state(ConnectUser* cu); +int ConnectUser_get_connFd(ConnectUser* cu); +int ConnectUser_get_whatClient(ConnectUser* cu); +int ConnectUser_get_userId(ConnectUser* cu); +time_t ConnectUser_get_connectTime(ConnectUser* cu); +char* ConnectUser_get_nameBuf(ConnectUser* cu); +char* ConnectUser_get_portBuf(ConnectUser* cu); +BufList* ConnectUser_get_bufList(ConnectUser* cu); +UserStats* ConnectUser_get_stats(ConnectUser* cu); + +#endif diff --git a/src/daemon.c b/src/daemon.c new file mode 100644 index 0000000..db2195d --- /dev/null +++ b/src/daemon.c @@ -0,0 +1,73 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "daemon.h" + +#ifndef HAVE_DAEMON + +#ifndef HAVE_THIS_DAEMON +#define HAVE_THIS_DAEMON + +/* + * Function name: daemon + * Description: Enters into daemon mode. It's the emulation of the daemon + * function from the system. + * Arguments: nochdir - when 0, the directory will be changed to /, otherwise + * the directory will be unchanged + * noclose - when 0, the standard streams will be closed, otherwise + * the streams will be unchanged + * Returns: 0 - success, + * -1 - failure. + */ + +int +daemon(int nochdir, int noclose) +{ + int retval; + if ((retval = fork()) == 0) { + /* child process */ + setsid(); + if (nochdir == 0) { + chdir("/"); + } + if (noclose == 0) { + retval = open("/dev/null", O_RDWR); + if (retval == -1) { + return retval; + } + dup2(retval, STDIN_FILENO); + dup2(retval, STDOUT_FILENO); + dup2(retval, STDERR_FILENO); + close(retval); + } + } + else { + /* parent process */ + if (retval == -1) { + return retval; + } + _exit(0); + } + return 0; +} + +#endif + +#endif diff --git a/src/daemon.h b/src/daemon.h new file mode 100644 index 0000000..e2de517 --- /dev/null +++ b/src/daemon.h @@ -0,0 +1,39 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifndef HAVE_DAEMON + +#include <sys/types.h> +#include <unistd.h> +#include <sys/stat.h> +#include <fcntl.h> + +# ifndef _JS_DAEMON_H +# define _JS_DAEMON_H + +int daemon(int nochdir, int noclose); + +# endif + +#endif diff --git a/src/file.c b/src/file.c new file mode 100644 index 0000000..70080c8 --- /dev/null +++ b/src/file.c @@ -0,0 +1,117 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "file.h" +#include "activefor.h" +#include "logging.h" +#include "network.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <limits.h> +#include <ctype.h> + +/* + * Function name: parse_line + * Description: Splits the buffer into two parts: option and value. + * Arguments: buff - the buffer to split + * tab1 - the place where option part will be stored + * tab2 - the place where value part will be stored + * Returns: 0 - the buffer was empty, + * 1 - the buffer contains only option name, + * 2 - the buffer contains only value of the option. + */ + +int +parse_line(char* buff, char* tab1, char* tab2) +{ + int state, i, j, lastDot; + state = i = j = 0; + lastDot = -1; + while (buff[i] != 0) { + if (buff[i] == '#') { + if ((i > 0) && (buff[i-1] == '\\')) { + --j; + } + else { + break; + } + } + switch (state) { + case 0: { /* before option name */ + if (!isspace(buff[i])) { + tab1[j] = buff[i]; + j = 1; + state = 1; + } + break; + } + case 1: { /* option */ + if (isspace(buff[i])) { + tab1[j] = 0; + state = 2; + j = 0; + } + else { + tab1[j] = buff[i]; + ++j; + } + break; + } + case 2: { /* before option value */ + if (!isspace(buff[i])) { + if (buff[i] != '.') { + tab2[j] = buff[i]; + j = 1; + } + state = 3; + } + break; + } + case 3: { /* option value */ + if (buff[i] == '.') { + lastDot = j; + } + else if (!isspace(buff[i])) { + lastDot = -1; + } + else if (lastDot == -1) { + lastDot = j; + } + tab2[j] = buff[i]; + ++j; + break; + } + } + ++i; + } + if (lastDot != -1) { + tab2[lastDot] = 0; + } + if (state == 3) { + return 2; + } + if (state == 0) { + return 0; + } + return 1; +} diff --git a/src/file.h b/src/file.h new file mode 100644 index 0000000..8aada50 --- /dev/null +++ b/src/file.h @@ -0,0 +1,41 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "network.h" +#include "server_configuration_struct.h" +#include "client_configuration_struct.h" +#include <openssl/ssl.h> + +#ifndef _JS_FILE_H +#define _JS_FILE_H + +#define F_UNKNOWN 1 +#define F_IGNORE 2 +#define F_ROPTION 3 +#define F_RVALUE 4 +#define F_MIDDLE 5 + +int parse_line(char* buff, char* tab1, char* tab2); /* parse one line of the file */ +ServerConfiguration* parsefile(char*, int*); /* parse the cfg file */ +ClientConfiguration* cparsefile(char*, int*); /* parse the client's cfg file */ + +#endif + diff --git a/src/file_client.c b/src/file_client.c new file mode 100644 index 0000000..672eeaf --- /dev/null +++ b/src/file_client.c @@ -0,0 +1,281 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <limits.h> +#include <ctype.h> +#include <assert.h> + +#include "file.h" +#include "activefor.h" +#include "logging.h" +#include "network.h" + +/* + * Function name: cparsefile + * Description: Parses the client config file. + * Arguments: name - the name of the file with client's config + * status - the status returned from this function: + * 0 - file was parsed successfully + * n>0 - there was an error in the n-th line + * Returns: Pointer to ClientConfiguration structure. + */ + +ClientConfiguration* +cparsefile(char* name, int* status) +{ + ClientConfiguration* cfg; + FILE* file = NULL; + int state, i, n; +#ifdef AF_INET6 + int temp; +#endif + char buff[256]; + char helpbuf1[256]; + char helpbuf2[256]; + char* tmpbuf; + unsigned char pass[4] = {1, 2, 3, 4}; + + assert(name != NULL); + assert(status != NULL); + + *status = 1; + + memset(buff, 0, 256); + + cfg = ClientConfiguration_new(); + + if (cfg == NULL) { + printf("Can't allocate memory for client configuration... exiting\n"); + exit(1); + } + + state = F_UNKNOWN; + + file = fopen(name, "r"); + if (file == NULL) { + return cfg; + } + + ClientConfiguration_set_realmsNumber(cfg, 1); + + ClientConfiguration_set_realmsTable(cfg, + calloc(ClientConfiguration_get_realmsNumber(cfg), sizeof(ClientRealm*))); + if (ClientConfiguration_get_realmsTable(cfg) == NULL) { + printf("Can't allocate memory for ClientRealm* table... exiting\n"); + exit(1); + } + for (i = 0; i < ClientConfiguration_get_realmsNumber(cfg); ++i) { + ClientConfiguration_get_realmsTable(cfg)[i] = ClientRealm_new(); + if (ClientConfiguration_get_realmsTable(cfg)[i] == NULL) { + printf("Problem with allocating memory for ClientRealm structure... exiting"); + exit(1); + } + ClientRealm_set_password(ClientConfiguration_get_realmsTable(cfg)[i], pass); + ClientRealm_set_destinationPorts(ClientConfiguration_get_realmsTable(cfg)[i], PortList_new()); + } + *status = 0; + + while (fgets(buff, 256, file) != NULL) { /* loop - parsing file */ + (*status)++; + state = parse_line(buff, helpbuf1, helpbuf2); + if (helpbuf1[0] == '#') { + memset(buff, 0, 256); + continue; + } + if (state == 1) { + if (strcmp(helpbuf1, "ignorepkeys") == 0) { + ClientConfiguration_set_ignorePublicKeys(cfg, 1); + } + else if (strcmp(helpbuf1, "ar-start") == 0) { + ArOptions_set_arStart(ClientRealm_get_arOptions(ClientConfiguration_get_realmsTable(cfg)[0]), + AR_OPTION_ENABLED); + } + else if (strcmp(helpbuf1, "ar-quit") == 0) { + ArOptions_set_arQuit(ClientRealm_get_arOptions(ClientConfiguration_get_realmsTable(cfg)[0]), + AR_OPTION_ENABLED); + } + else if (strcmp(helpbuf1, "noar") == 0) { + ArOptions_set_arPremature(ClientRealm_get_arOptions(ClientConfiguration_get_realmsTable(cfg)[0]), + AR_OPTION_DISABLED); + } + else if ((strcmp(helpbuf1, "u") == 0) || (strcmp(helpbuf1, "udpmode") == 0)) { + if (ClientRealm_get_clientMode(ClientConfiguration_get_realmsTable(cfg)[0]) == CLIENTREALM_MODE_TCP) { + ClientRealm_set_clientMode(ClientConfiguration_get_realmsTable(cfg)[0], CLIENTREALM_MODE_UDP); + } + else { + ClientRealm_set_clientMode(ClientConfiguration_get_realmsTable(cfg)[0], CLIENTREALM_MODE_UNKNOWN); + } + } + else if ((strcmp(helpbuf1, "U") == 0) || (strcmp(helpbuf1, "reverseudp") == 0)) { + if (ClientRealm_get_clientMode(ClientConfiguration_get_realmsTable(cfg)[0]) == CLIENTREALM_MODE_TCP) { + ClientRealm_set_clientMode(ClientConfiguration_get_realmsTable(cfg)[0], CLIENTREALM_MODE_REVERSE); + } + else { + ClientRealm_set_clientMode(ClientConfiguration_get_realmsTable(cfg)[0], CLIENTREALM_MODE_UNKNOWN); + } + } + else if ((strcmp(helpbuf1, "r") == 0) || (strcmp(helpbuf1, "remoteadmin") == 0)) { + if (ClientRealm_get_clientMode(ClientConfiguration_get_realmsTable(cfg)[0]) == CLIENTREALM_MODE_TCP) { + ClientRealm_set_clientMode(ClientConfiguration_get_realmsTable(cfg)[0], CLIENTREALM_MODE_REMOTE); + } + else { + ClientRealm_set_clientMode(ClientConfiguration_get_realmsTable(cfg)[0], CLIENTREALM_MODE_UNKNOWN); + } + } + else if ((strcmp(helpbuf1, "S") == 0) || (strcmp(helpbuf1, "use-https") == 0)) { + HttpProxyOptions_use_https(ClientRealm_get_httpProxyOptions( + ClientConfiguration_get_realmsTable(cfg)[0])); + } + else if ((strcmp(helpbuf1, "B") == 0) || (strcmp(helpbuf1, "pa-t-basic") == 0)) { + HttpProxyOptions_set_proxyauth_type(ClientRealm_get_httpProxyOptions( + ClientConfiguration_get_realmsTable(cfg)[0]), PROXYAUTH_TYPE_BASIC); + } +#ifdef HAVE_LIBPTHREAD + else if (strcmp(helpbuf1, "enableproxy")==0) { + if (ClientRealm_get_tunnelType( + ClientConfiguration_get_realmsTable(cfg)[0]) == 0) { + ClientRealm_set_tunnelType( + ClientConfiguration_get_realmsTable(cfg)[0], + 1); + } + else { + return cfg; + } + } +#endif +#ifdef AF_INET6 + else if (strcmp(helpbuf1, "ipv4")==0) { + if (TYPE_IS_UNSPEC(ClientRealm_get_realmType( + ClientConfiguration_get_realmsTable(cfg)[0]))) { + temp = ClientRealm_get_realmType(ClientConfiguration_get_realmsTable(cfg)[0]); + TYPE_SET_IPV4(temp); + ClientRealm_set_realmType(ClientConfiguration_get_realmsTable(cfg)[0], temp); + } + else { + return cfg; + } + } + else if (strcmp(helpbuf1, "ipv6")==0) { + if (TYPE_IS_UNSPEC(ClientRealm_get_realmType( + ClientConfiguration_get_realmsTable(cfg)[0]))) { + temp = ClientRealm_get_realmType(ClientConfiguration_get_realmsTable(cfg)[0]); + TYPE_SET_IPV6(temp); + ClientRealm_set_realmType(ClientConfiguration_get_realmsTable(cfg)[0], temp); + } + else { + return cfg; + } + } +#endif + else { + return cfg; + } + } + else if (state == 2) { + if ((strcmp(helpbuf1, "k") == 0) || (strcmp(helpbuf1, "keyfile") == 0)) { + ClientConfiguration_set_keysFile(cfg, helpbuf2); + } + else if ((strcmp(helpbuf1, "c") == 0) || (strcmp(helpbuf1, "certificate") == 0) || (strcmp(helpbuf1, "cerfile") == 0)) { + ClientConfiguration_set_certificateFile(cfg, helpbuf2); + } + else if ((strcmp(helpbuf1, "s") == 0) || (strcmp(helpbuf1, "storefile") == 0)) { + ClientConfiguration_set_storeFile(cfg, helpbuf2); + } + else if ((strcmp(helpbuf1, "o") == 0) || (strcmp(helpbuf1, "log") == 0)) { + tmpbuf = calloc(strlen(helpbuf2)+1, sizeof(char)); + strcpy(tmpbuf, helpbuf2); + addlogtarget(tmpbuf); + } + else if ((strcmp(helpbuf1, "D") == 0) || (strcmp(helpbuf1, "dateformat") == 0)) { + ClientConfiguration_set_dateFormat(cfg, helpbuf2); + } + else if ((strcmp(helpbuf1, "n") == 0) || (strcmp(helpbuf1, "servername") == 0)) { + ClientRealm_set_serverName(ClientConfiguration_get_realmsTable(cfg)[0], helpbuf2); + } + else if ((strcmp(helpbuf1, "m") == 0) || (strcmp(helpbuf1, "manageport") == 0)) { + ClientRealm_set_managePort(ClientConfiguration_get_realmsTable(cfg)[0], helpbuf2); + } + else if ((strcmp(helpbuf1, "d") == 0) || (strcmp(helpbuf1, "hostname") == 0)) { + ClientRealm_set_hostName(ClientConfiguration_get_realmsTable(cfg)[0], helpbuf2); + } + else if ((strcmp(helpbuf1, "p") == 0) || (strcmp(helpbuf1, "portnum") == 0)) { + PortList_insert_back(ClientRealm_get_destinationPorts(ClientConfiguration_get_realmsTable(cfg)[0]), + PortListNode_new(helpbuf2)); + } + else if (strcmp(helpbuf1, "localname") == 0) { + ClientRealm_set_localName(ClientConfiguration_get_realmsTable(cfg)[0], helpbuf2); + } + else if (strcmp(helpbuf1, "localport") == 0) { + ClientRealm_set_localPort(ClientConfiguration_get_realmsTable(cfg)[0], helpbuf2); + } + else if (strcmp(helpbuf1, "localdesname") == 0) { + ClientRealm_set_localDestinationName(ClientConfiguration_get_realmsTable(cfg)[0], helpbuf2); + } + else if ((strcmp(helpbuf1, "i") == 0) || (strcmp(helpbuf1, "id") == 0)) { + ClientRealm_set_realmId(ClientConfiguration_get_realmsTable(cfg)[0], helpbuf2); + } + else if (strcmp(helpbuf1, "pass") == 0) { + n = strlen(helpbuf2); + memset(pass, 0, 4); + for (i = 0; i < n; ++i) { + pass[i%4] += helpbuf2[i]; + } + ClientRealm_set_password(ClientConfiguration_get_realmsTable(cfg)[0], pass); + } + else if ((strcmp(helpbuf1, "K") == 0) || (strcmp(helpbuf1, "keep-alive") == 0)) { + ClientRealm_set_sKeepAliveTimeout(ClientConfiguration_get_realmsTable(cfg)[0], helpbuf2); + } + else if ((strcmp(helpbuf1, "A") == 0) || (strcmp(helpbuf1, "ar-tries") == 0)) { + ArOptions_set_s_arTries(ClientRealm_get_arOptions(ClientConfiguration_get_realmsTable(cfg)[0]), + helpbuf2); + } + else if ((strcmp(helpbuf1, "T") == 0) || (strcmp(helpbuf1, "ar-delay") == 0)) { + ArOptions_set_s_arDelay(ClientRealm_get_arOptions(ClientConfiguration_get_realmsTable(cfg)[0]), + helpbuf2); + } + else if ((strcmp(helpbuf1, "P") == 0) || (strcmp(helpbuf1, "proxyname") == 0)) { + HttpProxyOptions_set_proxyname(ClientRealm_get_httpProxyOptions( + ClientConfiguration_get_realmsTable(cfg)[0]), helpbuf2); + } + else if ((strcmp(helpbuf1, "X") == 0) || (strcmp(helpbuf1, "proxyport") == 0)) { + HttpProxyOptions_set_proxyport(ClientRealm_get_httpProxyOptions( + ClientConfiguration_get_realmsTable(cfg)[0]), helpbuf2); + } + else if ((strcmp(helpbuf1, "C") == 0) || (strcmp(helpbuf1, "pa-cred") == 0)) { + HttpProxyOptions_set_proxyauth_cred(ClientRealm_get_httpProxyOptions( + ClientConfiguration_get_realmsTable(cfg)[0]), helpbuf2); + } + else { + return cfg; + } + } + memset(buff, 0, 256); + } + + fclose(file); + + *status = 0; + return cfg; +} diff --git a/src/file_server.c b/src/file_server.c new file mode 100644 index 0000000..3abfc57 --- /dev/null +++ b/src/file_server.c @@ -0,0 +1,390 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "file.h" +#include "activefor.h" +#include "logging.h" +#include "network.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <limits.h> +#include <ctype.h> + +/* + * Function name: parsefile + * Description: Parses the server config file. + * Arguments: name - the name of the file with client's config + * status - the status returned from this function: + * 0 - file was parsed successfully + * n>0 - there was an error in the n-th line + * Returns: Pointer to ServerConfiguration structure. + */ + +ServerConfiguration* +parsefile(char* name, int* status) +{ + ServerConfiguration* cfg; + FILE* file = NULL; + int state, i, j, n, listencount, managecount, temp; + char buff[256]; + char helpbuf1[256]; + char helpbuf2[256]; + char* tmpbuf; + unsigned char pass[4] = {1, 2, 3, 4}; + + *status = 1; + + memset(buff, 0, 256); + + cfg = ServerConfiguration_new(); + + if (cfg == NULL) { + printf("Can't allocate memory for server configuration... exiting\n"); + exit(1); + } + + state = F_UNKNOWN; + + file = fopen(name, "r"); + if (file == NULL) { + return cfg; + } + + while (fgets(buff, 256, file) != NULL) { /* first loop - counting realm */ + helpbuf1[0] = 0; + parse_line(buff, helpbuf1, helpbuf2); + if (strcmp(helpbuf1, "realm")==0) { + ServerConfiguration_set_realmsNumber(cfg, ServerConfiguration_get_realmsNumber(cfg) + 1); + } + } + rewind(file); + + ServerConfiguration_set_realmsTable(cfg, + calloc(ServerConfiguration_get_realmsNumber(cfg), sizeof(ServerRealm*))); + if (ServerConfiguration_get_realmsTable(cfg) == NULL) { + printf("Can't allocate memory for ServerRealm* table... exiting\n"); + exit(1); + } + for (i = 0; i < ServerConfiguration_get_realmsNumber(cfg); ++i) { + ServerConfiguration_get_realmsTable(cfg)[i] = ServerRealm_new(); + if (ServerConfiguration_get_realmsTable(cfg)[i] == NULL) { + printf("Problem with allocating memory for ServerRealm structure... exiting"); + exit(1); + } + ServerRealm_set_password(ServerConfiguration_get_realmsTable(cfg)[i], pass); + } + ServerConfiguration_set_realmsNumber(cfg, 0); + *status = 0; + + listencount = managecount = 0; + + + while (fgets(buff, 256, file) != NULL) { /* second loop - counting listen */ + (*status)++; + state = parse_line(buff, helpbuf1, helpbuf2); + if (state) { + if (strcmp(helpbuf1, "realm") == 0) { + ServerConfiguration_set_realmsNumber(cfg, ServerConfiguration_get_realmsNumber(cfg) + 1); + if (listencount != managecount) { + return cfg; + } + listencount = managecount = 0; + } + else if ((strcmp(helpbuf1, "listen") == 0) || (strcmp(helpbuf1, "listenport") == 0)) { + if (ServerConfiguration_get_realmsNumber(cfg) == 0) { + return cfg; + } + ServerRealm_set_userClientPairs( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + ServerRealm_get_userClientPairs(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1]) + + 1); + ++listencount; + } + else if ((strcmp(helpbuf1, "manage") == 0) || (strcmp(helpbuf1, "manageport") == 0)) { + if (ServerConfiguration_get_realmsNumber(cfg) == 0) { + return cfg; + } + ++managecount; + } + } + } + rewind(file); + + if (listencount != managecount) { + return cfg; + } + + for (i = 0; i < ServerConfiguration_get_realmsNumber(cfg); ++i) { + ServerRealm_set_usersClientsTable(ServerConfiguration_get_realmsTable(cfg)[i], + calloc(ServerRealm_get_userClientPairs(ServerConfiguration_get_realmsTable(cfg)[i]), sizeof(UsrCli*))); + if (ServerRealm_get_usersClientsTable(ServerConfiguration_get_realmsTable(cfg)[i]) == NULL) { + printf("Problem with allocating memory for UsrCli* table... exiting"); + return cfg; + } + for (j = 0; j < ServerRealm_get_userClientPairs(ServerConfiguration_get_realmsTable(cfg)[i]); ++j) { + ServerRealm_get_usersClientsTable(ServerConfiguration_get_realmsTable(cfg)[i])[j] = UsrCli_new(); + if (ServerRealm_get_usersClientsTable(ServerConfiguration_get_realmsTable(cfg)[i])[j] == NULL) { + printf("Problem with allocating memory for UsrCli structure... exiting"); + return cfg; + } + } + } + + ServerConfiguration_set_realmsNumber(cfg, 0); + *status = 0; + + + while (fgets(buff, 256, file) != NULL) { /* third loop - parsing file */ + (*status)++; + state = parse_line(buff, helpbuf1, helpbuf2); + if (helpbuf1[0] == '#') { + memset(buff, 0, 256); + continue; + } + if (state == 1) { + if (strcmp(helpbuf1, "realm")==0) { + ServerConfiguration_set_realmsNumber(cfg, ServerConfiguration_get_realmsNumber(cfg) + 1); + temp = ServerRealm_get_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1]); + TYPE_SET_SSL(temp); + TYPE_SET_ZLIB(temp); + TYPE_SET_SUPPORTED_MULTI(temp); + ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1], temp); + listencount = managecount = 0; + } + else if (ServerConfiguration_get_realmsNumber(cfg) == 0) { + return cfg; + } + else if (strcmp(helpbuf1, "nossl")==0) { + temp = ServerRealm_get_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1]); + TYPE_UNSET_SSL(temp); + ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1], temp); + } + else if (strcmp(helpbuf1, "nozlib")==0) { + temp = ServerRealm_get_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1]); + TYPE_UNSET_ZLIB(temp); + ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1], temp); + } + else if (strcmp(helpbuf1, "baseport")==0) { + ServerRealm_set_basePortOn( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + 1); + } + else if (strcmp(helpbuf1, "audit")==0) { + ServerRealm_set_auditOn( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + 1); + } + else if (strcmp(helpbuf1, "dnslookups")==0) { + ServerRealm_set_dnsLookupsOn( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + 1); + } +#ifdef HAVE_LIBPTHREAD + else if (strcmp(helpbuf1, "enableproxy")==0) { + if (ServerRealm_get_tunnelType( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1]) == 0) { + ServerRealm_set_tunnelType( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + 1); + } + else { + return cfg; + } + } +#endif +#ifdef AF_INET6 + else if (strcmp(helpbuf1, "ipv4")==0) { + if (TYPE_IS_UNSPEC(ServerRealm_get_realmType( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1]))) { + temp = ServerRealm_get_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1]); + TYPE_SET_IPV4(temp); + ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1], temp); + } + else { + return cfg; + } + } + else if (strcmp(helpbuf1, "ipv6")==0) { + if (TYPE_IS_UNSPEC(ServerRealm_get_realmType( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1]))) { + temp = ServerRealm_get_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1]); + TYPE_SET_IPV6(temp); + ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1], temp); + } + else { + return cfg; + } + } +#endif + else { + return cfg; + } + } + else if (state == 2) { + if (strcmp(helpbuf1, "realm")==0) { + ServerConfiguration_set_realmsNumber(cfg, ServerConfiguration_get_realmsNumber(cfg) + 1); + temp = ServerRealm_get_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1]); + TYPE_SET_SSL(temp); + TYPE_SET_ZLIB(temp); + TYPE_SET_SUPPORTED_MULTI(temp); + ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1], temp); + listencount = managecount = 0; + ServerRealm_set_realmName( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + helpbuf2); + } + else if ((strcmp(helpbuf1, "certificate") == 0) || (strcmp(helpbuf1, "cerfile") == 0)) { + ServerConfiguration_set_certificateFile(cfg, helpbuf2); + } + else if (strcmp(helpbuf1, "cacerfile") == 0) { + ServerConfiguration_set_cacertificateFile(cfg, helpbuf2); + } + else if (strcmp(helpbuf1, "cerdepth") == 0) { + ServerConfiguration_set_sCertificateDepth(cfg, helpbuf2); + } + else if ((strcmp(helpbuf1, "key") == 0) || (strcmp(helpbuf1, "keyfile") == 0)) { + ServerConfiguration_set_keysFile(cfg, helpbuf2); + } + else if (strcmp(helpbuf1, "log")==0) { + tmpbuf = calloc(strlen(helpbuf2)+1, sizeof(char)); + strcpy(tmpbuf, helpbuf2); + addlogtarget(tmpbuf); + } + else if (strcmp(helpbuf1, "dateformat")==0) { + ServerConfiguration_set_dateFormat(cfg, helpbuf2); + } + else if (ServerConfiguration_get_realmsNumber(cfg) == 0) { + return cfg; + } + else if (strcmp(helpbuf1, "hostname")==0) { + ServerRealm_set_hostName( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + helpbuf2); + } + else if ((strcmp(helpbuf1, "listen") == 0) || (strcmp(helpbuf1, "listenport") == 0)) { + UsrCli_set_listenPortName( + ServerRealm_get_usersClientsTable( + ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1])[listencount], helpbuf2); + ++listencount; + } + else if (strcmp(helpbuf1, "pass")==0) { + n = strlen(helpbuf2); + memset(pass, 0, 4); + for (i = 0; i < n; ++i) { + pass[i%4] += helpbuf2[i]; + } + ServerRealm_set_password( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + pass); + } + else if ((strcmp(helpbuf1, "manage") == 0) || (strcmp(helpbuf1, "manageport") == 0)) { + UsrCli_set_managePortName( + ServerRealm_get_usersClientsTable( + ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1])[managecount], helpbuf2); + ++managecount; + } + else if (strcmp(helpbuf1, "users")==0) { + ServerRealm_set_sUsersLimit( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + helpbuf2); + } + else if (strcmp(helpbuf1, "timeout")==0) { + ServerRealm_set_sTimeout( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + helpbuf2); + } + else if (strcmp(helpbuf1, "maxidle")==0) { + ServerRealm_set_sMaxIdle( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + helpbuf2); + } + else if (strcmp(helpbuf1, "clients")==0) { + ServerRealm_set_sClientsLimit( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + helpbuf2); + } + else if (strcmp(helpbuf1, "raclients")==0) { + ServerRealm_set_sRaClientsLimit( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + helpbuf2); + } + else if (strcmp(helpbuf1, "usrpcli")==0) { + ServerRealm_set_sUsersPerClient( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + helpbuf2); + } + else if (strcmp(helpbuf1, "climode")==0) { + ServerRealm_set_sClientMode( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1], + helpbuf2); + } + else if (strcmp(helpbuf1, "proto")==0) { + if (TYPE_IS_SET(ServerRealm_get_realmType( + ServerConfiguration_get_realmsTable(cfg)[ServerConfiguration_get_realmsNumber(cfg) - 1]))) { + return cfg; + } + if (strcmp(helpbuf2, "tcp")==0) { + temp = ServerRealm_get_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1]); + TYPE_SET_TCP(temp); + ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1], temp); + } + else if (strcmp(helpbuf2, "udp")==0) { + temp = ServerRealm_get_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1]); + TYPE_SET_UDP(temp); + ServerRealm_set_realmType(ServerConfiguration_get_realmsTable(cfg)[ + ServerConfiguration_get_realmsNumber(cfg) - 1], temp); + } + else { + return cfg; + } + } + else { + return cfg; + } + } + memset(buff, 0, 256); + } + + fclose(file); + + *status = 0; + return cfg; +} diff --git a/src/first_run.c b/src/first_run.c new file mode 100644 index 0000000..a023306 --- /dev/null +++ b/src/first_run.c @@ -0,0 +1,403 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <pwd.h> +#include <openssl/rsa.h> +#include <openssl/pem.h> +#include <assert.h> + +static char* home_dir = NULL; +static char* home_dir_store = NULL; +static char* home_dir_key = NULL; +static char* home_dir_cer = NULL; + +typedef struct entry +{ + char *key; + unsigned char *value; +} entryT; + +static +entryT entries[6] = { + {"countryName", (unsigned char*) "PL"}, + {"stateOrProvinceName", (unsigned char*) "War-Maz"}, + {"localityName", (unsigned char*) "Olsztyn"}, + {"organizationName", (unsigned char*) "gray-world.net"}, + {"organizationalUnitName", (unsigned char*) "APF team"}, + {"commonName", (unsigned char*) "Jeremian <jeremian [at] poczta [dot] fm>"}, +}; + +/* + * Function name: callback + * Description: Prints the info about rsa key generation events. + * Arguments: i, j, k - described in the manual page about RSA_generate_key + */ + +static void +callback(int i, int j, void* k) +{ + if (k == NULL) { + printf("%d", i); + fflush(stdout); + } +} + +/* + * Function name: create_apf_dir + * Description: Creates .apf directory in ~/ or apf directory locally. + * Arguments: type - type of the directory to create: + * 0 - .apf in ~/ + * 1 - apf in current dir + * Returns: 0 - success, + * 1 - problems with fetching user info, + * 2 - home directory is not set, + * 3 - calloc failure, + * 4 - directory creation failure. + */ + +int +create_apf_dir(char type) +{ + int length; + struct stat buf; + struct passwd *user = getpwuid(getuid()); + if (type == 0) { + if (user == NULL) { + return 1; /* some problems with fetching user info*/ + } + if (user->pw_dir == NULL) { + return 2; /* home directory is not set? */ + } + if (home_dir) { + free(home_dir); + home_dir = NULL; + } + length = strlen(user->pw_dir); + home_dir = calloc(1, length + 6); + if (home_dir == NULL) { + return 3; /* calloc failed */ + } + strcpy(home_dir, user->pw_dir); + if (home_dir[length] == '/') { + strcpy(&home_dir[length], ".apf"); + } + else { + strcpy(&home_dir[length], "/.apf"); + } + if (stat(home_dir, &buf)) { + if (mkdir(home_dir, 0700)) { + return 4; /* creating directory failed */ + } + } + } + else { + if (home_dir) { + free(home_dir); + home_dir = NULL; + } + home_dir = calloc(1, 4); + if (home_dir == NULL) { + return 3; /* calloc failed */ + } + strcpy(home_dir, "apf"); + if (stat(home_dir, &buf)) { + if (mkdir(home_dir, 0700)) { + return 4; /* creating directory failed */ + } + } + } + return 0; +} + +/* + * Function name: create_publickey_store + * Description: Creates the file to store information about public keys. + * Arguments: storefile - the pointer to filename + * Returns: 0 - success, + * >0 - failure. + */ + +int +create_publickey_store(char** storefile) +{ + int store_length, home_length; + struct stat buf; + FILE* store_file; + assert(storefile != NULL); + assert((*storefile) != NULL); + /* check in local directory first */ + if (stat(*storefile, &buf) == 0) { + return 0; + } + /* check in home_dir */ + store_length = strlen(*storefile); + home_length = strlen(home_dir); + if (home_dir_store) { + free(home_dir_store); + home_dir_store = NULL; + } + home_dir_store = calloc(1, home_length + store_length + 2); + if (home_dir_store == NULL) { + return 1; /* calloc failed */ + } + strcpy(home_dir_store, home_dir); + home_dir_store[home_length] = '/'; + strcpy(&home_dir_store[home_length+1], *storefile); + *storefile = home_dir_store; + store_file = fopen(home_dir_store, "a"); + if (store_file == NULL) { + return 1; + } + fclose(store_file); + if (stat(home_dir_store, &buf) == 0) { + return 0; + } + return 2; +} + +/* + * Function name: generate_rsa_key + * Description: Generates the RSA key. + * Arguments: keyfile - the pointer to filename + * Returns: 0 - success, + * >0 - failure. + */ + +int +generate_rsa_key(char** keyfile) +{ + int key_length, home_length; + RSA* rsa_key; + FILE* rsa_file; + struct stat buf; + assert(keyfile != NULL); + assert((*keyfile) != NULL); + /* check in local directory first */ + if (stat(*keyfile, &buf) == 0) { + return 0; + } + /* check in home_dir */ + key_length = strlen(*keyfile); + home_length = strlen(home_dir); + if (home_dir_key) { + free(home_dir_key); + home_dir_key = NULL; + } + home_dir_key = calloc(1, home_length + key_length + 2); + if (home_dir_key == NULL) { + return 1; /* calloc failed */ + } + strcpy(home_dir_key, home_dir); + home_dir_key[home_length] = '/'; + strcpy(&home_dir_key[home_length+1], *keyfile); + *keyfile = home_dir_key; + if (stat(home_dir_key, &buf) == 0) { + return 0; + } + /* have to generate the key */ + printf("generating rsa key: 2048 bits\n"); + rsa_key = RSA_generate_key(2048, 65537, callback, NULL); + if (RSA_check_key(rsa_key)==1) { + printf(" OK!\n"); + } + else { + printf(" FAILED!\n"); + return 1; + } + + rsa_file = fopen(home_dir_key, "a"); + PEM_write_RSAPrivateKey(rsa_file, rsa_key, NULL, NULL, 0, NULL, NULL); + fclose(rsa_file); + return 0; +} + +/* + * Function name: generate_certificate + * Description: Generates X509 certificate. + * Arguments: cerfile - the pointer to filename + * keyfile - the name of the file with key + * Returns: 0 - success, + * >0 - failure. + */ + +int +generate_certificate(char** cerfile, char* keyfile) +{ + int cer_length, home_length, i; + struct stat buf; + X509* cert; + X509_REQ* req; + X509_NAME* subj; + RSA* rsa_key; + EVP_PKEY* pkey; + const EVP_MD *digest; + FILE* fp; + assert(cerfile != NULL); + assert((*cerfile) != NULL); + assert(keyfile != NULL); + /* check in local directory first */ + if (stat(*cerfile, &buf) == 0) { + return 0; + } + /* check in home_dir */ + cer_length = strlen(*cerfile); + home_length = strlen(home_dir); + if (home_dir_cer) { + free(home_dir_cer); + home_dir_cer = NULL; + } + home_dir_cer = calloc(1, home_length + cer_length + 2); + if (home_dir_cer == NULL) { + return 1; /* calloc failed */ + } + strcpy(home_dir_cer, home_dir); + home_dir_cer[home_length] = '/'; + strcpy(&home_dir_cer[home_length+1], *cerfile); + *cerfile = home_dir_cer; + if (stat(home_dir_cer, &buf) == 0) { + return 0; + } + /* have to generate the certificate */ + printf("generating self signed certificate\n"); + fp = fopen(keyfile, "r"); + if (fp == NULL) { + return 2; /* can't open keyfile */ + } + rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + fclose(fp); + if (rsa_key == NULL) { + return 3; /* can't read RSAPrivateKey */ + } + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + return 4; /* creating new pkey failed */ + } + if (EVP_PKEY_set1_RSA(pkey, rsa_key) == 0) { + return 5; /* setting rsa key failed */ + } + req = X509_REQ_new(); + if (req == NULL) { + return 6; /* creating new request failed */ + } + X509_REQ_set_pubkey(req, pkey); + subj = X509_NAME_new(); + if (subj == NULL) { + return 7; /* creating new subject name failed */ + } + + for (i = 0; i < 6; i++) + { + int nid; + X509_NAME_ENTRY *ent; + + if ((nid = OBJ_txt2nid(entries[i].key)) == NID_undef) + { + return 8; /* finding NID for a key failed */ + } + ent = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,entries[i].value, -1); + if (ent == NULL) { + return 9; /* creating name entry from NID failed */ + } + if (X509_NAME_add_entry(subj, ent, -1, 0) == 0) { + return 10; /* adding entry to name failed */ + } + } + if (X509_REQ_set_subject_name(req, subj) == 0) { + return 11; /* adding subject to request failed */ + } + + digest = EVP_sha1(); + + if (X509_REQ_sign(req, pkey, digest) == 0) { + return 12; /* signing request failed */ + } + + cert = X509_REQ_to_X509(req, 1000, pkey); + + if (X509_set_version(cert, 2L) == 0) { + return 13; /* setting certificate version failed */ + } + ASN1_INTEGER_set(X509_get_serialNumber(cert), 1); + + if (cert == NULL) { + return 14; /* creating certificate failed */ + } + + if (X509_sign(cert, pkey, digest) == 0) { + return 15; /* signing failed */ + } + + fp = fopen(home_dir_cer, "w"); + if (fp == NULL) { + return 16; /* writing certificate failed */ + } + PEM_write_X509(fp, cert); + fclose(fp); + + EVP_PKEY_free(pkey); + X509_REQ_free(req); + X509_free(cert); + return 0; +} + +/* + * Function name: get_store_filename + * Description: Returns the name of the file for storing information about public keys. + * Returns: The name of the file for storing information about public keys. + */ + +char* +get_store_filename() +{ + return home_dir_store; +} + +/* + * Function name: get_key_filename + * Description: Returns the name of the file with key. + * Returns: The name of the file with key. + */ + +char* +get_key_filename() +{ + return home_dir_key; +} + +/* + * Function name: get_cer_filename + * Description: Returns the name of the file with certificate. + * Returns: The name of the file with certificate. + */ + +char* +get_cer_filename() +{ + return home_dir_cer; +} diff --git a/src/first_run.h b/src/first_run.h new file mode 100644 index 0000000..4fcb5d8 --- /dev/null +++ b/src/first_run.h @@ -0,0 +1,33 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_FIRST_RUN_H +#define _JS_FIRST_RUN_H + +int create_apf_dir(char type); +int create_publickey_store(char**); +int generate_rsa_key(char**); +int generate_certificate(char**, char*); +char* get_store_filename(); +char* get_key_filename(); +char* get_cer_filename(); + +#endif + diff --git a/src/header_buffer_struct.c b/src/header_buffer_struct.c new file mode 100644 index 0000000..94f852b --- /dev/null +++ b/src/header_buffer_struct.c @@ -0,0 +1,127 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "header_buffer_struct.h" + +/* + * Function name: HeaderBuffer_new + * Description: Create and initialize new HeaderBuffer structure. + * Returns: Pointer to newly created HeaderBuffer structure. + */ + +HeaderBuffer* +HeaderBuffer_new() +{ + HeaderBuffer* tmp = calloc(1, sizeof(HeaderBuffer)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: HeaderBuffer_free + * Description: Free the memory allocated for HeaderBuffer structure. + * Arguments: hb - pointer to pointer to HeaderBuffer structure + */ + +void +HeaderBuffer_free(HeaderBuffer** hb) +{ + assert(hb != NULL); + if (hb == NULL) { + return; + } + assert((*hb) != NULL); + if ((*hb) == NULL) { + return; + } + free((*hb)); + (*hb) = NULL; +} + +/* + * Function name: HeaderBuffer_to_read + * Description: Evaluate how much bytes are needed to fill the header buffer. + * Arguments: hb - pointer to HeaderBuffer structure + * Returns: How much bytes are needed to fill the header buffer. + */ + +int +HeaderBuffer_to_read(HeaderBuffer* hb) +{ + assert(hb != NULL); + if (hb == NULL) { + return -1; + } + return (5 - hb->readed); +} + +/* + * Function name: HeaderBuffer_store + * Description: Store readed part of the header in the buffer. + * Arguments: hb - pointer to HeaderBuffer structure + * buff - reader bytes + * n - how much bytes were readed + */ + +void +HeaderBuffer_store(HeaderBuffer* hb, unsigned char* buff, int n) +{ + assert(hb != NULL); + if (hb == NULL) { + return; + } + assert((hb->readed + n) <= 5); + if ((hb->readed + n) > 5) { + return; + } + assert(n > 0); + if (n <= 0) { + return; + } + memcpy(&hb->tab[hb->readed], buff, n); + hb->readed += n; +} + +/* + * Function name: HeaderBuffer_restore + * Description: Restore the full header from the buffer. It's not checked, if the full header is in the buffer. + * Arguments: hb - pointer to HeaderBuffer structure + * buff - place to restore the full header to + */ + +void +HeaderBuffer_restore(HeaderBuffer* hb, unsigned char* buff) +{ + assert(hb != NULL); + if (hb == NULL) { + return; + } + memcpy(buff, hb->tab, 5); + hb->readed = 0; +} diff --git a/src/header_buffer_struct.h b/src/header_buffer_struct.h new file mode 100644 index 0000000..f186dfd --- /dev/null +++ b/src/header_buffer_struct.h @@ -0,0 +1,39 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_HEADER_BUFFER_STRUCT_H +#define _JS_HEADER_BUFFER_STRUCT_H + +typedef struct { + unsigned char tab[5]; + int readed; +} HeaderBuffer; + +/* 'constructor' */ +HeaderBuffer* HeaderBuffer_new(); +/* 'destructor' */ +void HeaderBuffer_free(HeaderBuffer** hb); +/* other */ +int HeaderBuffer_to_read(HeaderBuffer* hb); +void HeaderBuffer_store(HeaderBuffer* hb, unsigned char* buff, int n); +void HeaderBuffer_restore(HeaderBuffer* hb, unsigned char* buff); + +#endif + diff --git a/src/http_proxy_client.c b/src/http_proxy_client.c new file mode 100644 index 0000000..157d009 --- /dev/null +++ b/src/http_proxy_client.c @@ -0,0 +1,565 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "http_proxy_functions.h" +#include "http_proxy_client.h" +#include "thread_management.h" +#include "network.h" +#include "stats.h" +#include "logging.h" +#include "base64.h" + +#ifdef HAVE_LIBPTHREAD +typedef struct { + int sockfd; + char *host; + char *serv; + HttpProxyOptions* hpo; + char type; + SSL_CTX* ctx; +} proxy_argT; + +/* + * Function name: clean_return + * Description: Closes the connection and exits the thread. + * Arguments: sockfd - the descriptor of the connection + */ + +static void +clean_return(int sockfd) +{ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: clean_return"); + close(sockfd); + pthread_exit(NULL); +} + +/* + * Function name: http_proxy_client + * Description: Function responsible for the client part of the http proxy connection. + * Arguments: vptr - the structure with all the information needed for http proxy tunnel + */ + +void* +http_proxy_client(void *vptr) +{ + char tab[9000]; + connection conn; + header hdr; + int j, n, maxfdp1; + fd_set rset, allset; + struct timeval tv; + int timeout = 5; + int tmp; + char *host, *serv, *proxyname, *proxyport, *credentials, *name = ""; + char b64cred[100]; + char type, authtype, https; + SSL_CTX* ctx; + proxy_argT *proxy_argptr; + + start_critical_section(); + proxy_argptr = (proxy_argT *) vptr; + + host = proxy_argptr->host; + serv = proxy_argptr->serv; + proxyname = HttpProxyOptions_get_proxyname(proxy_argptr->hpo); + proxyport = HttpProxyOptions_get_proxyport(proxy_argptr->hpo); + credentials = HttpProxyOptions_get_proxyauth_cred(proxy_argptr->hpo); + type = proxy_argptr->type; + authtype = HttpProxyOptions_get_proxyauth_type(proxy_argptr->hpo); + conn.sockfd = proxy_argptr->sockfd; + https = HttpProxyOptions_is_https(proxy_argptr->hpo); + ctx = proxy_argptr->ctx; + + broadcast_condition(); + end_critical_section(); + + conn.postFd = SslFd_new(); + conn.getFd = SslFd_new(); + conn.tmpFd = SslFd_new(); + if ((conn.postFd == NULL) || (conn.getFd == NULL) || (conn.tmpFd == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + + if (https) { + name = "s"; + SslFd_set_ssl(conn.postFd, SSL_new(ctx)); + SslFd_set_ssl(conn.getFd, SSL_new(ctx)); + SslFd_set_ssl(conn.tmpFd, SSL_new(ctx)); + if ((SslFd_get_ssl(conn.postFd) == NULL) || + (SslFd_get_ssl(conn.getFd) == NULL) || + (SslFd_get_ssl(conn.tmpFd) == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + } + + if (authtype == PROXYAUTH_TYPE_WRONG) { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "Wrong type of proxy authorizaton --> switching to no authorization"); + credentials = NULL; + } + + if (credentials) { + if (b64_ntop((unsigned char*)credentials, strlen(credentials), b64cred, 100) == -1) { + aflog(LOG_T_MAIN, LOG_I_ERR, + "Cannot encode credentials for proxy authorization"); + b64cred[0] = 0; + } + else { + if (authtype == PROXYAUTH_TYPE_NOTSET) { + authtype = PROXYAUTH_TYPE_BASIC; + } + } + } + + FD_ZERO(&allset); + tv.tv_usec = 0; + tv.tv_sec = timeout; + + memset(conn.id, 0, 10); + for (j = 0; j < 9; ++j) { + conn.id[j] = myrand(65, 90); + } + conn.id[9] = 0; + + /* postfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: connecting (postfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type, NULL, NULL)) { + clean_return(conn.sockfd); + } + SslFd_set_fd(conn.postFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.postFd), SslFd_get_fd(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + clean_return(conn.sockfd); + } + } + + memset(tab, 0, 9000); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + sprintf(tab, + "POST http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + sprintf(tab, + "POST http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + } + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: writing POST request...", name); + if (http_write(https, conn.postFd, (unsigned char*) tab, j) <= 0) { + clean_return(conn.sockfd); + } + + /* getfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: connecting (getfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type, NULL, NULL)) { + clean_return(conn.sockfd); + } + SslFd_set_fd(conn.getFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.getFd), SslFd_get_fd(conn.getFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.getFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + clean_return(conn.sockfd); + } + } + + memset(tab, 0, 9000); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + sprintf(tab, + "GET http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Connection: close\r\n" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + sprintf(tab, + "GET http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + } + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: writing GET request...", name); + if (http_write(https, conn.getFd, (unsigned char*) tab, j) <= 0) { + clean_return(conn.sockfd); + } + + set_fd(conn.sockfd, &maxfdp1, &allset); + set_fd(SslFd_get_fd(conn.postFd), &maxfdp1, &allset); + set_fd(SslFd_get_fd(conn.getFd), &maxfdp1, &allset); + conn.state = C_OPEN; + + memset(tab, 0, 9000); + + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: parsing header from getfd", name); + if (parse_header(conn.getFd, tab, &hdr, https)) { + clean_return(conn.sockfd); + } + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: checking hdr.type", name); + if (hdr.type != H_TYPE_OK) { + clean_return(conn.sockfd); + } + if (hdr.length) { + conn.received += hdr.length; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: reading message...", name); + if (read_message(conn.sockfd, hdr.length, &conn, tab, hdr.ptr)) { + clean_return(conn.sockfd); + } + } + + while (1) { + if ((conn.state == C_OPEN) && (!(FD_ISSET(conn.sockfd, &allset)))) { + FD_SET(conn.sockfd, &allset); + } + rset = allset; + + if (select(maxfdp1, &rset, NULL, NULL, &tv) == 0) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: timeout", name); + tv.tv_sec = timeout; + if (conn.sent_ptr+1 >= 90000) { + if (conn.state == C_CLOSED) { + continue; + } + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: send T", name); + http_write(https, conn.postFd, (unsigned char*) "T", 1); + conn.sent_ptr = 0; + clear_sslFd(conn.postFd, &allset); + /* postfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: connecting (postfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type, NULL, NULL)) { + clean_return(conn.sockfd); + } + SslFd_set_fd(conn.postFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.postFd), SslFd_get_fd(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + clean_return(conn.sockfd); + } + } + + memset(tab, 0, 9000); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + sprintf(tab, + "POST http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + sprintf(tab, + "POST http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + } + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: writing POST request...", name); + if (http_write(https, conn.postFd, (unsigned char *) tab, j) <= 0) { + clean_return(conn.sockfd); + } + conn.sent_ptr = 0; + conn.ptr = 0; + conn.length = 0; + conn.state = C_CLOSED; + + set_fd(SslFd_get_fd(conn.postFd), &maxfdp1, &allset); + } + else { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: send T", name); + http_write(https, conn.postFd, (unsigned char *) "T", 1); + conn.sent_ptr += 1; + } + continue; + } + + /* sockfd */ + if (FD_ISSET(conn.sockfd, &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: FD_ISSET(conn.sockfd)", name); + n = read(conn.sockfd, conn.buf+5, 8995); + if (n <= 0) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: send Q", name); + http_write(https, conn.postFd, (unsigned char *) "Q", 1); + clean_return(conn.sockfd); + } + if ((conn.state == C_CLOSED) && (conn.sent_ptr > 70000)) { + FD_CLR(conn.sockfd, &allset); + } + conn.buf[0] = 'M'; + tmp = htonl(n); + memcpy(&conn.buf[1], &tmp, 4); + if (conn.sent_ptr+5 + n >= 90000) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: send message", name); + http_write(https, conn.postFd, (unsigned char *) conn.buf, 90000 - conn.sent_ptr); + conn.ptr = 90000 - conn.sent_ptr; + conn.length = 5+n - conn.ptr; + conn.sent_ptr = 0; + clear_sslFd(conn.postFd, &allset); + + /* postfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: connecting (postfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type, NULL, NULL)) { + clean_return(conn.sockfd); + } + SslFd_set_fd(conn.postFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.postFd), SslFd_get_fd(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.postFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + clean_return(conn.sockfd); + } + } + + memset(tab, 0, 9000); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + sprintf(tab, + "POST http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + sprintf(tab, + "POST http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + } + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: writing POST request...", name); + if (http_write(https, conn.postFd, (unsigned char *) tab, j) <= 0) { + clean_return(conn.sockfd); + } + if (conn.length > 0) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: writing old data...", name); + if (http_write(https, conn.postFd, (unsigned char *) (conn.buf+conn.ptr), conn.length) <= 0) { + clean_return(conn.sockfd); + } + } + conn.sent_ptr = conn.length; + conn.ptr = 0; + conn.length = 0; + conn.state = C_CLOSED; + + set_fd(SslFd_get_fd(conn.postFd), &maxfdp1, &allset); + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: send message", name); + http_write(https, conn.postFd, (unsigned char *) conn.buf, 5+n); + conn.sent_ptr += 5+n; + } + } + + /* getfd */ + if (FD_ISSET(SslFd_get_fd(conn.getFd), &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: FD_ISSET(conn.getfd)", name); + n = http_read(https, conn.getFd, (unsigned char*) tab, 9000); + conn.received += n; + if (n == 0) { + conn.received = 0; + clear_sslFd(conn.getFd, &allset); + + /* getfd */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: connecting (getfd)...", name); + if (ip_connect(&tmp, proxyname, proxyport, type, NULL, NULL)) { + clean_return(conn.sockfd); + } + SslFd_set_fd(conn.getFd, tmp); + if (https) { + if (SSL_set_fd(SslFd_get_ssl(conn.getFd), SslFd_get_fd(conn.getFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: Problem with initializing ssl"); + clean_return(conn.sockfd); + } + if (SSL_connect(SslFd_get_ssl(conn.getFd)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "https proxy: SSL_connect has failed"); + clean_return(conn.sockfd); + } + } + + memset(tab, 0, 9000); + switch (authtype) { + case PROXYAUTH_TYPE_BASIC: + sprintf(tab, + "GET http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Connection: close\r\n" + "Proxy-Authorization: Basic %s\r\n\r\n", host, serv, conn.id, host, serv, b64cred); + break; + default: + sprintf(tab, + "GET http://%s:%s/yahpt.html?id=%s HTTP/1.1\r\n" + "Host: %s:%s\r\n" + "Connection: close\r\n\r\n", host, serv, conn.id, host, serv); + } + j = strlen (tab); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: writing GET request...", name); + if (http_write(https, conn.getFd, (unsigned char *) tab, j) <= 0) { + clean_return(conn.sockfd); + } + memset(tab, 0, 9000); + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: parsing header from getfd", name); + if (parse_header(conn.getFd, tab, &hdr, https)) { + clean_return(conn.sockfd); + } + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: checking hdr.type", name); + if (hdr.type != H_TYPE_OK) { + clean_return(conn.sockfd); + } + + set_fd(SslFd_get_fd(conn.getFd), &maxfdp1, &allset); + if (hdr.length) { + conn.received += hdr.length; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: reading message...", name); + if (read_message(conn.sockfd, hdr.length, &conn, tab, hdr.ptr)) { + clean_return(conn.sockfd); + } + } + } + else { + if (read_message(conn.sockfd, n, &conn, tab, 0)) { + clean_return(conn.sockfd); + } + } + } + + /* postfd */ + if (FD_ISSET(SslFd_get_fd(conn.postFd), &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: FD_ISSET(conn.postfd) --> clean_return", name); + clear_sslFd(conn.postFd, &allset); + clean_return(conn.sockfd); + } + } + clean_return(conn.sockfd); +} + +/* + * Function name: initialize_http_proxy_client + * Description: Initializes the thread responsible for http proxy connection. + * Arguments: sockfd - the new connection descriptor will be stored here + * cr - the pointer to ClientRealm structure + * ctx - the pointer to SSL_CTX structure + * Returns: 0 - success, + * !0 - failure. + */ + +int +initialize_http_proxy_client(int* sockfd, ClientRealm* cr, SSL_CTX* ctx) +{ + int retval; + int sockets[2]; + pthread_t proxy_thread; + static proxy_argT arg; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)) { + return 1; + } + (*sockfd) = sockets[0]; + + if (HttpProxyOptions_get_proxyname(ClientRealm_get_httpProxyOptions(cr)) == NULL) { + return 1; + } + + start_critical_section(); + + arg.host = ClientRealm_get_serverName(cr); + arg.serv = ClientRealm_get_managePort(cr); + arg.hpo = ClientRealm_get_httpProxyOptions(cr); + arg.type = ClientRealm_get_ipFamily(cr); + arg.sockfd = sockets[1]; + arg.ctx = ctx; + + retval = pthread_create(&proxy_thread, NULL, &http_proxy_client, &arg); + + wait_for_condition(); + + end_critical_section(); + + return retval; +} + +#endif diff --git a/src/http_proxy_client.h b/src/http_proxy_client.h new file mode 100644 index 0000000..15506c7 --- /dev/null +++ b/src/http_proxy_client.h @@ -0,0 +1,29 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "http_proxy_options_struct.h" +#include "client_realm_struct.h" + +#ifndef _JS_HTTP_PROXY_CLIENT_H +#define _JS_HTTP_PROXY_CLIENT_H + +int initialize_http_proxy_client(int* sockfd, ClientRealm* cr, SSL_CTX* ctx); + +#endif diff --git a/src/http_proxy_functions.c b/src/http_proxy_functions.c new file mode 100644 index 0000000..e7bef6f --- /dev/null +++ b/src/http_proxy_functions.c @@ -0,0 +1,410 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "http_proxy_functions.h" +#include "network.h" +#include "stats.h" +#include "logging.h" + +static char isseed; + +/* + * Function name: myrand + * Description: Returns the pseudo-random number from the given range. + * If the lower and upper bounds are the same, the pseudo-random + * number is returned from the range (-RAND_MAX, -RAND_MAX+down) + * or (down, RAND_MAX). + * Arguments: down - the lower bound of the range + * up - the upper bound of the range + * Returns: The pseudo-random number from the given range. + */ + +int +myrand(int down, int up) +{ + struct timeval tv; + if (!isseed) { + gettimeofday(&tv, 0); + srand(tv.tv_sec); + isseed = 1; + } + return ( down + ( rand() % (up - down + 1) ) ); +} + +/* + * Function name: mysleep + * Description: Sleeps for the given amount of milliseconds. + * Arguments: time - the amount of milliseconds to sleep for + */ + +void +mysleep(double time) +{ + struct timeval tv; + tv.tv_sec = (int) time; + tv.tv_usec = (int)(time * 1000000)%1000000; + select(0, NULL, NULL, NULL, &tv); +} + +/* + * Function name: delete_user + * Description: Deletes the user's connection from the http proxy connections. + * Arguments: cnts - the connection to remove + * i - the user's number + * allset - the set of file descriptors + */ + +void +delete_user(connection* cnts, int i, fd_set* allset) +{ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http proxy: delete_user(%d)", i); + clear_fd(&(cnts[i].sockfd), allset); + if (!(cnts[i].state & C_POST_WAIT)) { + clear_sslFd(cnts[i].postFd, allset); + } + if ((cnts[i].type == 0) && (!(cnts[i].state & C_GET_WAIT))) { + clear_sslFd(cnts[i].getFd, allset); + } + cnts[i].state = C_CLOSED; + cnts[i].sent_ptr = cnts[i].ptr = cnts[i].length = 0; + cnts[i].type = 0; +} + +/* + * Function name: parse_header + * Description: Reads and parses the http header. + * Arguments: sf - the pointer to SslFd structure + * tab - the buffer used for reading the data + * hdr - the pointer to header structure + * https - the flag indicating if the connection is http/https + * Returns: 0 - success, + * 1 - failure. + */ + +int +parse_header(SslFd* sf, char* tab, header* hdr, char https) +{ + int n, i, j, state = 0; + char tmpt[100]; + if (https) { + n = SSL_read(SslFd_get_ssl(sf), tab, 9000); + } + else { + n = read(SslFd_get_fd(sf), tab, 9000); + } + hdr->allreaded = n; + i = j = 0; + memset(tmpt, 0, 100); + hdr->ptr = 0; + hdr->length = 0; + while (i < n) { + if (j == 99) + return 1; + switch (state) { + case 0: + if ((tab[i] != ' ') && (tab[i] != '\t')) { + tmpt[j] = tab[i]; + ++j; + } + else { + tmpt[j] = 0; + if (strcmp(tmpt, "GET") == 0) { + hdr->type = H_TYPE_GET; + state = 1; + break; + } + if (strcmp(tmpt, "POST") == 0) { + hdr->type = H_TYPE_POST; + state = 1; + break; + } + if ((strcmp(tmpt, "HTTP/1.0") == 0) || (strcmp(tmpt, "HTTP/1.1") == 0)) { + hdr->type = H_TYPE_OK; + state = 6; + break; + } + return 1; + } + break; + case 1: + if ((tab[i] != ' ') && (tab[i] != '\t')) { + tmpt[0] = tab[i]; + j = 1; + state = 2; + } + break; + case 2: + if (tab[i] != '=') { + tmpt[j] = tab[i]; + ++j; + } + else { + tmpt[j] = 0; + if (strcmp(tmpt, "/yahpt.html?id")) { + return 1; + } + j = 0; + state = 3; + } + break; + case 3: + if ((tab[i] != ' ') && (tab[i] != '\t')) { + if (j == 9) { + return 1; + } + hdr->id[j] = tab[i]; + ++j; + } + else { + if (j != 9) { + return 1; + } + hdr->id[j] = 0; + state = 4; + } + break; + case 4: + if (tab[i] == '\n') + state = 5; + break; + case 5: + if (tab[i] == '\n') { + hdr->ptr = i+1; + hdr->length = n - hdr->ptr; + return 0; + } + if (tab[i] != '\r') { + state = 4; + } + break; + case 6: + if ((tab[i] != ' ') && (tab[i] != '\t')) { + tmpt[0] = tab[i]; + j = 1; + state = 7; + } + break; + case 7: + if ((tab[i] == ' ') || (tab[i] == '\t')) { + tmpt[j] = 0; + if (strcmp(tmpt, "200")) { + return 1; + } + state = 4; + } + else { + tmpt[j] = tab[i]; + ++j; + } + break; + } + ++i; + } + return 1; +} + +/* + * Function name: set_fd + * Description: Starts watching the file descriptor. + * Arguments: fd - the file descriptor + * maxfdp1 - the upper limit of the file descriptor numbers + * allset - the set of file descriptors + */ + +void +set_fd(int fd, int* maxfdp1, fd_set* allset) +{ + FD_SET(fd, allset); + (*maxfdp1) = ((*maxfdp1) > fd) ? (*maxfdp1) : (fd + 1); +} + +/* + * Function name: close_fd + * Description: Closes the file descriptor. + * Arguments: fd - the file descriptor to close + */ + +void +close_fd(int* fd) +{ + close(*fd); +} + +/* + * Function name: clear_fd + * Description: Removes the file descriptor from the set and closes it. + * Arguments: fd - the file descriptor to remove and close + * set - the set of file descriptors + */ + +void +clear_fd(int* fd, fd_set* set) +{ + FD_CLR(*fd, set); + close_fd(fd); +} + +/* + * Function name: read_message + * Description: Reads the message from the http proxy connection and writes it + * to the file descriptor. + * Arguments: fd - the file descriptor + * length - the length of the buffer + * client - the http proxy connection + * tab - the buffer with the readed data + * ptr - the offset from which the data reading will start + * Returns: 0 - success, + * 1 - failure. + */ + +int +read_message(int fd, int length, connection* client, char* tab, int ptr) +{ + int j = 0; + int tmp = 0; + while (j < length) { + if (client->curreceived + length-j > client->toreceive) { + if (client->toreceive - client->curreceived > 0) { + writen(fd, (unsigned char*) (tab+ptr+j), client->toreceive - client->curreceived); + j += client->toreceive - client->curreceived; + client->curreceived += client->toreceive - client->curreceived; + } + if (client->read_state == 0) { + switch (tab[ptr + j]) { + case 'M': { + if (j + 5 <= length) { + memcpy(&tmp, &tab[ptr + j + 1], 4); + client->toreceive = ntohl(tmp); + client->curreceived = 0; + j += 5; + } + else if (j + 1 < length) { + memcpy(client->readed_length, &tab[ptr + j + 1], length - j - 1); + client->read_state = length - j; + j += length - j; + } + else { + ++j; + client->read_state = 1; + } + break; + } + case 'T': { + ++j; + break; + } + case 'A': { + ++j; + if (client->state == C_CLOSED) { + client->state = C_OPEN; + } + break; + } + default: { + return 1; + } + } + } + else { + if (j + 5 - client->read_state <= length) { + memcpy(&client->readed_length[client->read_state-1], &tab[ptr + j], 5 - client->read_state); + memcpy(&tmp, client->readed_length, 4); + client->toreceive = ntohl(tmp); + client->curreceived = 0; + j += 5 - client->read_state; + client->read_state = 0; + } + else { + memcpy(&client->readed_length[client->read_state-1], &tab[ptr + j], length - j); + client->read_state += length - j; + j += length -j; + } + } + } + else if (length-j > 0) { + client->curreceived += length-j; + writen(fd, (unsigned char*) (tab+ptr+j), length-j); + j += length-j; + } + } + return 0; +} + +/* + * Function name: clear_sslFd + * Description: Close the socket encapsulated in SslFd structure, remove this file descriptor + * from fd_set and clear ssl structure. + * Arguments: sf - pointer to SslFd structure + * set - pointer to fd_set structure + */ + +void +clear_sslFd(SslFd* sf, fd_set* set) +{ + clear_fd((&(sf->fd)), set); + if (SslFd_get_ssl(sf)) { + SSL_clear(SslFd_get_ssl(sf)); + } +} + +/* + * Function name: http_write + * Description: Write the message via http/https proxy. + * Arguments: https - if the https proxy will be used instead of http proxy + * sf - pointer to SslFd structure + * buf - buffer containing the data to send + * amount - how much butes will be send + * Returns: The result of writen or SSL_writen function, depending on 'https' value. + */ + +int +http_write(char https, SslFd* sf, unsigned char* buf, int amount) +{ + if (https) { + return SSL_writen(SslFd_get_ssl(sf), buf, amount); + } + else { + return writen(SslFd_get_fd(sf), buf, amount); + } +} + +/* + * Function name: http_read + * Description: Read the message via http/https proxy. + * Arguments: https - if the https proxy will be used instead of http proxy + * sf - pointer to SslFd structure + * buf - buffer for the received data + * amount - how much bytes will be received + * Returns: The result of read or SSL_read function, depending on 'https' value. + */ + +int +http_read(char https, SslFd* sf, unsigned char* buf, int amount) +{ + if (https) { + return SSL_read(SslFd_get_ssl(sf), buf, amount); + } + else { + return read(SslFd_get_fd(sf), buf, amount); + } +} diff --git a/src/http_proxy_functions.h b/src/http_proxy_functions.h new file mode 100644 index 0000000..3d29699 --- /dev/null +++ b/src/http_proxy_functions.h @@ -0,0 +1,86 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <sys/select.h> +#include <unistd.h> + +#include "ssl_fd_struct.h" + +#ifndef _JS_HTTP_PROXY_FUNCTIONS_H +#define _JS_HTTP_PROXY_FUNCTIONS_H + +#define C_CLOSED 0 +#define C_POST_WAIT 1 +#define C_GET_WAIT 2 +#define C_OPEN 4 +#define C_DELAYED_A 8 + +#define H_TYPE_GET 0 +#define H_TYPE_POST 1 +#define H_TYPE_OK 2 +#define H_TYPE_ERROR 3 + +typedef struct { + char type; + char id[10]; + int ptr; + int length; + int allreaded; +} header; + +typedef struct { + char read_state; + char readed_length[4]; + char state; + char id[10]; + SslFd* postFd; + SslFd* getFd; + int sent_ptr; + int sockfd; + char buf[9000]; + char tmpbuf[9000]; + char tmpstate; + SslFd* tmpFd; + char type; + header tmpheader; + int ptr; + int length; + int curreceived; + int toreceive; + int received; +} connection; + +int myrand(int, int); +void mysleep(double); +int parse_header(SslFd*, char*, header*, char); +int read_message(int, int, connection*, char*, int); +void delete_user(connection*, int, fd_set*); +void set_fd(int, int*, fd_set*); +void close_fd(int*); +void clear_fd(int*, fd_set*); +void clear_sslFd(SslFd*, fd_set*); +int http_write(char, SslFd*, unsigned char*, int); +int http_read(char, SslFd*, unsigned char*, int); + +#endif diff --git a/src/http_proxy_options_struct.c b/src/http_proxy_options_struct.c new file mode 100644 index 0000000..e1dcc4d --- /dev/null +++ b/src/http_proxy_options_struct.c @@ -0,0 +1,254 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "http_proxy_options_struct.h" +#include "string_functions.h" + +/* + * Function name: HttpProxyOptions_new + * Description: Create and initialize new HttpProxyOptions structure. + * Returns: Pointer to newly created HttpProxyOptions structure. + */ + +HttpProxyOptions* +HttpProxyOptions_new() +{ + HttpProxyOptions* tmp = calloc(1, sizeof(HttpProxyOptions)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + tmp->proxyauth_type = PROXYAUTH_TYPE_NOTSET; + return tmp; +} + +/* + * Function name: HttpProxyOptions_free + * Description: Free the memory allocated for HttpProxyOptions structure. + * Arguments: hpo - pointer to pointer to HttpProxyOptions structure + */ + +void +HttpProxyOptions_free(HttpProxyOptions** hpo) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return; + } + assert((*hpo) != NULL); + if ((*hpo) == NULL) { + return; + } + if ((*hpo)->proxyname) { + free((*hpo)->proxyname); + (*hpo)->proxyname = NULL; + } + if ((*hpo)->proxyport) { + free((*hpo)->proxyport); + (*hpo)->proxyport = NULL; + } + if ((*hpo)->proxyauth_cred) { + free((*hpo)->proxyauth_cred); + (*hpo)->proxyauth_cred = NULL; + } + free((*hpo)); + (*hpo) = NULL; +} + +/* + * Function name: HttpProxyOptions_set_proxyname + * Description: Set name of the http proxy server. + * Arguments: hpo - pointer to HttpProxyOptions structure + * proxyname - name of the http proxy server + */ + +void +HttpProxyOptions_set_proxyname(HttpProxyOptions* hpo, char* proxyname) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return; + } + string_cp(&(hpo->proxyname), proxyname); +} + +/* + * Function name: HttpProxyOptions_set_proxyport + * Description: Set port on which http proxy server is listening. + * Arguments: hpo - pointer to HttpProxyOptions structure + * proxyport - port on which http proxy server is listening + */ + +void +HttpProxyOptions_set_proxyport(HttpProxyOptions* hpo, char* proxyport) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return; + } + string_cp(&(hpo->proxyport), proxyport); +} + +/* + * Function name: HttpProxyOptions_set_proxyauth_cred + * Description: Set credentials for http proxy server. + * Arguments: hpo - pointer to HttpProxyOptions structure + * proxyauth_cred - credentials for http proxy server + */ + +void +HttpProxyOptions_set_proxyauth_cred(HttpProxyOptions* hpo, char* proxyauth_cred) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return; + } + string_cp(&(hpo->proxyauth_cred), proxyauth_cred); +} + +/* + * Function name: HttpProxyOptions_set_proxyauth_type + * Description: Set type of the proxy authorization. + * Arguments: hpo - pointer to HttpProxyOptions structure + * proxyauth_type - type of the proxy authorization + */ + +void +HttpProxyOptions_set_proxyauth_type(HttpProxyOptions* hpo, char proxyauth_type) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return; + } + assert(hpo->proxyauth_type == PROXYAUTH_TYPE_NOTSET); + if (hpo->proxyauth_type != PROXYAUTH_TYPE_NOTSET) { + hpo->proxyauth_type = PROXYAUTH_TYPE_WRONG; + return; + } + hpo->proxyauth_type = proxyauth_type; +} + +/* + * Function name: HttpProxyOptions_get_proxyname + * Description: Get name of the http proxy server + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: Name of the http proxy server or NULL, if name not set. + */ + +char* +HttpProxyOptions_get_proxyname(HttpProxyOptions* hpo) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return NULL; + } + return hpo->proxyname; +} + +/* + * Function name: HttpProxyOptions_get_proxyport + * Description: Get port on which http proxy server is listening. + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: Port on which http proxy server is listening or NULL, if port not set. + */ + +char* +HttpProxyOptions_get_proxyport(HttpProxyOptions* hpo) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return NULL; + } + return hpo->proxyport; +} + +/* + * Function name: HttpProxyOptions_get_proxyauth_cred + * Description: Get credentials for http proxy server. + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: Credentials for http proxy server or NULL, if not set. + */ + +char* +HttpProxyOptions_get_proxyauth_cred(HttpProxyOptions* hpo) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return NULL; + } + return hpo->proxyauth_cred; +} + +/* + * Function name: HttpProxyOptions_get_proxyauth_type + * Description: Get type of the proxy authorization. + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: Type of the proxy authorization. + */ + +char +HttpProxyOptions_get_proxyauth_type(HttpProxyOptions* hpo) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return PROXYAUTH_TYPE_WRONG; + } + return hpo->proxyauth_type; +} + +/* + * Function name: HttpProxyOptions_use_https + * Description: Enable use of https proxy instead of http proxy. + * Arguments: hpo - pointer to HttpProxyOptions structure + */ + +void +HttpProxyOptions_use_https(HttpProxyOptions* hpo) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return; + } + hpo->useHttps = USEHTTPS_ON; +} + +/* + * Function name: HttpProxyOptions_is_https + * Description: Check if the use of https proxy is enabled. + * Arguments: hpo - pointer to HttpProxyOptions structure + * Returns: USEHTTPS_OFF - http proxy will be used + * USEHTTPS_ON - https proxy will be used + */ + +char +HttpProxyOptions_is_https(HttpProxyOptions* hpo) +{ + assert(hpo != NULL); + if (hpo == NULL) { + return USEHTTPS_OFF; + } + return hpo->useHttps; +} diff --git a/src/http_proxy_options_struct.h b/src/http_proxy_options_struct.h new file mode 100644 index 0000000..db0208c --- /dev/null +++ b/src/http_proxy_options_struct.h @@ -0,0 +1,58 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_HTTP_PROXY_OPTIONS_STRUCT_H +#define _JS_HTTP_PROXY_OPTIONS_STRUCT_H + +#define PROXYAUTH_TYPE_NOTSET 0 +#define PROXYAUTH_TYPE_WRONG -1 +#define PROXYAUTH_TYPE_BASIC 1 + +#define USEHTTPS_OFF 0 +#define USEHTTPS_ON 1 + +typedef struct { + char* proxyname; + char* proxyport; + char* proxyauth_cred; + char proxyauth_type; + char useHttps; +} HttpProxyOptions; + +/* 'constructor' */ +HttpProxyOptions* HttpProxyOptions_new(); +/* 'destructor' */ +void HttpProxyOptions_free(HttpProxyOptions** hpo); +/* setters */ +void HttpProxyOptions_set_proxyname(HttpProxyOptions* hpo, char* proxyname); +void HttpProxyOptions_set_proxyport(HttpProxyOptions* hpo, char* proxyport); +void HttpProxyOptions_set_proxyauth_cred(HttpProxyOptions* hpo, char* proxyauth_cred); +void HttpProxyOptions_set_proxyauth_type(HttpProxyOptions* hpo, char proxyauth_type); +/* getters */ +char* HttpProxyOptions_get_proxyname(HttpProxyOptions* hpo); +char* HttpProxyOptions_get_proxyport(HttpProxyOptions* hpo); +char* HttpProxyOptions_get_proxyauth_cred(HttpProxyOptions* hpo); +char HttpProxyOptions_get_proxyauth_type(HttpProxyOptions* hpo); +/* other */ +void HttpProxyOptions_use_https(HttpProxyOptions* hpo); +char HttpProxyOptions_is_https(HttpProxyOptions* hpo); + +#endif + diff --git a/src/http_proxy_server.c b/src/http_proxy_server.c new file mode 100644 index 0000000..17baf5a --- /dev/null +++ b/src/http_proxy_server.c @@ -0,0 +1,585 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "make_ssl_handshake.h" +#include "http_proxy_server.h" +#include "thread_management.h" +#include "stats.h" +#include "logging.h" +#include "network.h" + +#ifdef HAVE_LIBPTHREAD + +typedef struct { + int sockfd; + char *host; + char *serv; + socklen_t *addrlenp; + char type; + int limit; + char https; + SSL_CTX* ctx; +} sproxy_argT; + +/* + * Function name: afserver_connect + * Description: Connects new http proxy connection to the afserver. + * Arguments: sockfd - the file descriptor which will be used for communication with afserver + * afserverfd - the afserver's file descriptor + * cliaddr - pointer to sockaddr structure + * addrlenp - pointer to the length of the sockaddr structure + * type - the type of the connection + */ + +int +afserver_connect(int* sockfd, int afserverfd, struct sockaddr* cliaddr, socklen_t* addrlenp, char type) +{ + int sockets[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)) { + return 1; + } + if (write(afserverfd, &sockets[0], 4) != 4) { + return 2; + } + if (write(afserverfd, &type, 1) != 1) { + return 3; + } + if (write(afserverfd, addrlenp, 4) != 4) { + return 4; + } + if (write(afserverfd, cliaddr, *addrlenp) != *addrlenp) { + return 5; + } + (*sockfd) = sockets[1]; + return 0; +} + +/* + * Function name: http_proxy_server + * Description: Function responsible for the server part of the http proxy connection. + * Arguments: vptr - the structure with all the information needed for http proxy tunnel. + */ + +void* +http_proxy_server(void *vptr) +{ + int listenfd, afserverfd; + SslFd* connFd; + struct sockaddr* cliaddr; + char tab[9000]; + connection* table; + header hdr; + int i, n, maxfdp1; + fd_set rset, allset; + struct timeval tv; + int maxclients, tmp; + int timeout = 5; + socklen_t *addrlenp; + socklen_t addrlen; + char type, nothttp, https; + char *host, *serv, *name = ""; + SSL_CTX* ctx; + sproxy_argT *proxy_argptr; + + start_critical_section(); + proxy_argptr = (sproxy_argT *) vptr; + + afserverfd = proxy_argptr->sockfd; + host = proxy_argptr->host; + serv = proxy_argptr->serv; + addrlenp = proxy_argptr->addrlenp; + type = proxy_argptr->type; + maxclients = proxy_argptr->limit+1; + https = proxy_argptr->https; + ctx = proxy_argptr->ctx; + + if (https) { + name = "s"; + } + + table = calloc(maxclients, sizeof(connection)); + if (table == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + for (i = 0; i < maxclients; ++i) { + table[i].postFd = SslFd_new(); + table[i].getFd = SslFd_new(); + table[i].tmpFd = SslFd_new(); + if ((table[i].postFd == NULL) || (table[i].getFd == NULL) || (table[i].tmpFd == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + if (https) { + SslFd_set_ssl(table[i].postFd, SSL_new(ctx)); + SslFd_set_ssl(table[i].getFd, SSL_new(ctx)); + SslFd_set_ssl(table[i].tmpFd, SSL_new(ctx)); + if ((SslFd_get_ssl(table[i].postFd) == NULL) || + (SslFd_get_ssl(table[i].getFd) == NULL) || + (SslFd_get_ssl(table[i].tmpFd) == NULL)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + } + } + connFd = SslFd_new(); + if (connFd == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + if (https) { + SslFd_set_ssl(connFd, SSL_new(ctx)); + if (SslFd_get_ssl(connFd) == NULL) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't allocate memory... exiting.", name); + exit(1); + } + } + + if (ip_listen(&listenfd, host, serv, addrlenp, type)) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "http%s proxy: Can't listen on %s:%s", name, host, serv); + exit(1); + } + cliaddr = malloc(*addrlenp); + addrlen = (*addrlenp); + addrlenp = &addrlen; + + broadcast_condition(); + end_critical_section(); + + FD_ZERO(&allset); + FD_SET(listenfd, &allset); + maxfdp1 = listenfd + 1; + tv.tv_usec = 0; + tv.tv_sec = timeout; + + while (1) { + rset = allset; + + if (select(maxfdp1, &rset, NULL, NULL, &tv) == 0) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: timeout", name); + tv.tv_sec = timeout; + for (i = 0; i < maxclients; ++i) { + if ((table[i].state == C_CLOSED) || (table[i].state & C_GET_WAIT) || (table[i].type == 1)) { + continue; + } + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: send T to table[%d].getfd", name, i); + if (table[i].sent_ptr+1 >= 90000) { + http_write(https, table[i].getFd, (unsigned char*) "T", 1); + table[i].sent_ptr = 0; + clear_sslFd(table[i].getFd, &allset); + FD_CLR(table[i].sockfd, &allset); + table[i].state |= C_GET_WAIT; + } + else { + http_write(https, table[i].getFd, (unsigned char*) "T", 1); + table[i].sent_ptr += 1; + } + } + continue; + } + + /* http proxy tunnels */ + for (i = 0; i < maxclients; ++i) { + if ((table[i].state == C_CLOSED) || (table[i].type == 1)) { + continue; + } + + /* sockfd */ + if ((!(table[i].state & C_GET_WAIT)) && (FD_ISSET(table[i].sockfd, &rset))) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: FD_ISSET(table[%d].sockfd)", name, i); + n = read(table[i].sockfd, table[i].buf+5, 8995); + if (n <= 0) { + http_write(https, table[i].getFd, (unsigned char*) "Q", 1); + delete_user(table, i, &allset); + continue; + } + table[i].buf[0] = 'M'; + tmp = htonl(n); + memcpy(&table[i].buf[1], &tmp, 4); + if (table[i].sent_ptr+5 + n >= 90000) { + http_write(https, table[i].getFd, (unsigned char*) table[i].buf, 90000 - table[i].sent_ptr); + table[i].ptr = 90000 - table[i].sent_ptr; + table[i].length = 5+n - table[i].ptr; + table[i].sent_ptr = 0; + clear_sslFd(table[i].getFd, &allset); + FD_CLR(table[i].sockfd, &allset); + table[i].state |= C_GET_WAIT; + continue; + } + else { + http_write(https, table[i].getFd, (unsigned char*) table[i].buf, n+5); + table[i].sent_ptr += n+5; + } + } + + /* getfd */ + if (FD_ISSET(SslFd_get_fd(table[i].getFd), &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: FD_ISSET(table[%d].getfd)", name, i); + delete_user(table, i, &allset); + continue; + } + + /* postfd */ + if (FD_ISSET(SslFd_get_fd(table[i].postFd), &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: FD_ISSET(table[%d].postfd)", name, i); + n = http_read(https, table[i].postFd, (unsigned char*) tab, 9000); + if (n != 0) { + table[i].received += n; + if (read_message(table[i].sockfd, n, &table[i], tab, 0)) { + delete_user(table, i, &allset); + } + } + if ((n == 0) || (table[i].received == 90000)) { + table[i].received = 0; + clear_sslFd(table[i].postFd, &allset); + table[i].state |= C_POST_WAIT; + + if (!(table[i].state & C_GET_WAIT)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: send A to table[%d].getfd", name, i); + if (table[i].sent_ptr+1 >= 90000) { + http_write(https, table[i].getFd, (unsigned char*) "A", 1); + table[i].sent_ptr = 0; + clear_sslFd(table[i].getFd, &allset); + FD_CLR(table[i].sockfd, &allset); + table[i].state |= C_GET_WAIT; + } + else { + http_write(https, table[i].getFd, (unsigned char*) "A", 1); + table[i].sent_ptr += 1; + } + } + else { + table[i].state |= C_DELAYED_A; + } + + if (table[i].tmpstate == 1) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: get old POST request...", name); + table[i].state &= ~C_POST_WAIT; + SslFd_swap_content(table[i].postFd, table[i].tmpFd); + set_fd(SslFd_get_fd(table[i].postFd), &maxfdp1, &allset); + table[i].tmpstate = 0; + if (table[i].tmpheader.length) { + table[i].received += table[i].tmpheader.length; + if (read_message(table[i].sockfd, table[i].tmpheader.length, &table[i], + table[i].tmpbuf, table[i].tmpheader.ptr)) { + delete_user(table, i, &allset); + } + } + } + continue; + } + } + } + + /* direct tunnels */ + for (i = 0; i < maxclients; ++i) { + if ((table[i].state == C_OPEN) && (table[i].type == 1)) { + + if (FD_ISSET(table[i].sockfd, &rset)) { + n = read(table[i].sockfd, table[i].buf, 9000); + if (n > 0) { + writen(SslFd_get_fd(table[i].postFd), (unsigned char*) table[i].buf, n); + } + else { + delete_user(table, i, &allset); + continue; + } + } + + if (FD_ISSET(SslFd_get_fd(table[i].postFd), &rset)) { + n = read(SslFd_get_fd(table[i].postFd), tab, 9000); + if (n > 0) { + writen(table[i].sockfd, (unsigned char*) tab, n); + } + else { + delete_user(table, i, &allset); + continue; + } + } + + } + } + + /* listen */ + if (FD_ISSET(listenfd, &rset)) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: FD_ISSET(listenfd)", name); + tmp = accept(listenfd, cliaddr, addrlenp); + if (tmp != -1) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: New connection...", name); + SslFd_set_fd(connFd, tmp); + if (https) { + make_ssl_initialize(connFd); + if (make_ssl_accept(connFd)) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "https proxy: DENIED by SSL_accept"); + close(SslFd_get_fd(connFd)); + SSL_clear(SslFd_get_ssl(connFd)); + continue; + } + } + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: New connection --> EAGAIN", name); + continue; + } + memset(tab, 0, 9000); + nothttp = 0; + if (parse_header(connFd, tab, &hdr, https)) { + nothttp = 1; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: no http header...", name); + } + n = -1; + for (i = 0; i < maxclients; ++i) { + if (table[i].state == C_CLOSED) { + if (n == -1) + n = i; + } + else { + if ((!nothttp) && (strcmp(table[i].id, hdr.id) == 0)) { + break; + } + } + } + if (i < maxclients) { /* the client exists */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: the client exist...", name); + if (hdr.type == H_TYPE_GET) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: type GET...", name); + if (!(table[i].state & C_GET_WAIT)) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: not waiting for GET...", name); + table[i].sent_ptr = 0; + FD_CLR(table[i].sockfd, &allset); + clear_sslFd(table[i].getFd, &allset); + table[i].state |= C_GET_WAIT; + } + if (!(table[i].state & C_OPEN)) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: not opened...", name); + if (afserver_connect(&table[i].sockfd, afserverfd, cliaddr, addrlenp, 1)) { + memset(tab, 0, 9000); + sprintf(tab,"HTTP/1.1 400 Bad Request\r\n\r\n"); + n = strlen (tab); + http_write(https, connFd, (unsigned char*) tab, n); + close_fd((&(connFd->fd))); + SSL_clear(SslFd_get_ssl(connFd)); + clear_sslFd(table[i].postFd, &allset); + table[i].state = C_CLOSED; + continue; + } + table[i].state |= C_OPEN; + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: OPEN...", name); + } + table[i].state &= ~C_GET_WAIT; + table[i].sent_ptr = 0; + SslFd_swap_content(table[i].getFd, connFd); + set_fd(table[i].sockfd, &maxfdp1, &allset); + set_fd(SslFd_get_fd(table[i].getFd), &maxfdp1, &allset); + memset(tab, 0, 9000); + sprintf(tab, + "HTTP/1.1 200 OK\r\n" + "Content-Length: 90000\r\n" + "Connection: close\r\n" + "Pragma: no-cache\r\n" + "Cache-Control: no-cache, no-store, must-revalidate\r\n" + "Expires: 0\r\n" + "Content-Type: text/html\r\n\r\n"); + n = strlen(tab); + if (writen(SslFd_get_fd(table[i].getFd), (unsigned char*) tab, n) <= 0) { + delete_user(table, i, &allset); + continue; + } + if (table[i].length) { + if (writen(SslFd_get_fd(table[i].getFd), + (unsigned char*) (table[i].buf+table[i].ptr), table[i].length) <= 0) { + delete_user(table, i, &allset); + continue; + } + } + table[i].sent_ptr = table[i].length; + table[i].ptr = 0; + table[i].length = 0; + if (table[i].state & C_DELAYED_A) { + aflog(LOG_T_MAIN, LOG_I_DDEBUG, + "http%s proxy: send A to table[%d].getfd", name, i); + http_write(https, table[i].getFd, (unsigned char*) "A", 1); + table[i].sent_ptr += 1; + table[i].state &= ~C_DELAYED_A; + } + } + else if (hdr.type == H_TYPE_POST) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: type POST...", name); + if (!(table[i].state & C_POST_WAIT)) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: unexpected POST request...", name); + if (table[i].tmpstate == 0) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: buffering POST request...", name); + table[i].tmpstate = 1; + SslFd_swap_content(table[i].tmpFd, connFd); + memcpy(table[i].tmpbuf, tab, 9000); + table[i].tmpheader = hdr; + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: no space to buffer POST request (received from first postfd: %d)", name, + table[i].received); + delete_user(table, i, &allset); + } + } + else { + if (hdr.length) { + table[i].received += hdr.length; + if (read_message(table[i].sockfd, hdr.length, &table[i], tab, hdr.ptr)) { + delete_user(table, i, &allset); + } + } + table[i].state &= ~C_POST_WAIT; + SslFd_swap_content(table[i].postFd, connFd); + set_fd(SslFd_get_fd(table[i].postFd), &maxfdp1, &allset); + } + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: unrecognized type...", name); + delete_user(table, i, &allset); + } + } + else if (n != -1) { /* there are free slots */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: there are free slots...", name); + if (!nothttp) { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: http header...", name); + if (hdr.type == H_TYPE_POST) { /* POST request must be first */ + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: type POST...", name); + table[n].state = C_GET_WAIT; + memcpy(table[n].id,hdr.id, 9); + SslFd_swap_content(table[n].postFd, connFd); + set_fd(SslFd_get_fd(table[n].postFd), &maxfdp1, &allset); + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: closing this connection... (not POST type)", name); + close_fd((&(connFd->fd))); + if (https) { + SSL_clear(SslFd_get_ssl(connFd)); + } + continue; + } + } + else { + table[n].state = C_OPEN; + SslFd_set_fd(table[n].postFd, SslFd_get_fd(connFd)); + table[n].type = 1; + set_fd(SslFd_get_fd(table[n].postFd), &maxfdp1, &allset); + if (afserver_connect(&table[n].sockfd, afserverfd, cliaddr, addrlenp, 0)) { + clear_sslFd(table[n].postFd, &allset); + table[n].state = C_CLOSED; + continue; + } + set_fd(table[n].sockfd, &maxfdp1, &allset); + write(table[n].sockfd, tab, hdr.allreaded); + } + } + else { + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "http%s proxy: closing this connection... (no free slots)", name); + close_fd((&(connFd->fd))); + continue; + } + } + } + + return 0; +} + +/* + * Function name: initialize_http_proxy_server + * Description: Initializes the thread responsible for http proxy connection. + * Arguments: sockfd - the new connection descriptor will be stored here + * host - the name of the host on which we will be listening on + * serv - the port on which we will be listening on + * addrlenp - pointer to the length of the sockaddr structure + * type - the type of the connection + * limit - the limit for user's connections + * https - if the connection should be https instead of http + * ctx - the pointer to SSL_CTX structure + * Returns: 0 - success, + * !0 - failure. + */ + +int +initialize_http_proxy_server(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type, int limit, char https, SSL_CTX* ctx) +{ + int retval; + int sockets[2]; + pthread_t proxy_thread; + static sproxy_argT arg; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)) { + return 1; + } + (*sockfd) = sockets[0]; + + start_critical_section(); + + arg.host = (char*) host; + arg.serv = (char*) serv; + arg.addrlenp = addrlenp; + arg.limit = limit; + arg.type = (char) type; + arg.sockfd = sockets[1]; + arg.https = https; + arg.ctx = ctx; + + retval = pthread_create(&proxy_thread, NULL, &http_proxy_server, &arg); + + wait_for_condition(); + + end_critical_section(); + + return retval; +} + +#endif diff --git a/src/http_proxy_server.h b/src/http_proxy_server.h new file mode 100644 index 0000000..22c121c --- /dev/null +++ b/src/http_proxy_server.h @@ -0,0 +1,29 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_HTTP_PROXY_SERVER_H +#define _JS_HTTP_PROXY_SERVER_H + +#include "http_proxy_functions.h" +#include "network.h" + +int initialize_http_proxy_server(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type, int limit, char https, SSL_CTX* ctx); + +#endif diff --git a/src/inet_ntop.c b/src/inet_ntop.c new file mode 100644 index 0000000..77e3e40 --- /dev/null +++ b/src/inet_ntop.c @@ -0,0 +1,231 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* This is from the BIND 4.9.4 release, modified to compile by itself */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "inet_ntop.h" + +#ifndef HAVE_INET_NTOP + +#ifndef HAVE_THIS_INET_NTOP +#define HAVE_THIS_INET_NTOP + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_ntop.c,v 8.5 1996/05/22 04:56:30 vixie Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#define IN6ADDRSZ 16 +#define INT16SZ 2 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4(const u_char *src, char *dst, size_t size); +#ifdef AF_INET6 +static const char *inet_ntop6(const u_char *src, char *dst, size_t size); +#endif + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(af, src, dst, size) + int af; + const void *src; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); +#ifdef AF_INET6 + case AF_INET6: + return (inet_ntop6(src, dst, size)); +#endif + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + sprintf(tmp, fmt, src[0], src[1], src[2], src[3]); + if (strlen(tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +#ifdef AF_INET6 +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[IN6ADDRSZ / INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, 0, sizeof words); + for (i = 0; i < IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + sprintf(tp, "%x", words[i]); + tp += strlen(tp); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} +#endif + +#endif + +#endif diff --git a/src/inet_ntop.h b/src/inet_ntop.h new file mode 100644 index 0000000..e473896 --- /dev/null +++ b/src/inet_ntop.h @@ -0,0 +1,36 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifndef HAVE_INET_NTOP + +#include <sys/types.h> + +# ifndef _JS_INET_NTOP_H +# define _JS_INET_NTOP_H + +const char* inet_ntop(int af, const void *src, char *dst, size_t size); + +# endif + +#endif diff --git a/src/logging.c b/src/logging.c new file mode 100644 index 0000000..d1836cf --- /dev/null +++ b/src/logging.c @@ -0,0 +1,471 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "logging.h" +#include "network.h" +#include <stdio.h> +#include <time.h> +#include <string.h> +#include <stdarg.h> + +static llnodeT* head = NULL; +static char verlev; +static char format[51] = "%Y-%m-%d %H:%M:%S"; + +/* + * Function name: setdateformat + * Description: Sets the new date format based on the given string. + * Arguments: dateformat - the new date format + */ + +void +setdateformat(char* dateformat) +{ + if (dateformat) { + strncpy(format, dateformat, 50); + } +} + +/* + * Function name: getdateformat + * Description: Returns the date format. + * Returns: The date format. + */ + +char* +getdateformat() +{ + return format; +} + +/* + * Function name: localdate + * Description: Returns the formatted date string. + * Arguments: sec - the date in seconds + * Returns: The formatted date. + */ + +char* +localdate(time_t* sec) +{ + struct tm* tm; + static char localdat[31]; + tm = localtime(sec); + memset(localdat, 0, 31); + strftime(localdat, 30, format, tm); + return localdat; +} + +/* + * Function name: datum + * Description: Returns the formatted date string. + * Returns: The formatted date. + */ + +char* +datum(void) +{ + time_t sec; + struct tm* tm; + static char timedat[31]; + time(&sec); + tm = localtime(&sec); + memset(timedat, 0, 31); + strftime(timedat, 30, format, tm); + return timedat; +} + +/* + * Function name: getloglisthead + * Description: Returns the head of the log targets list. + * Returns: The head of the log targets list. + */ + +llnodeT* +getloglisthead() +{ + return head; +} + +/* + * Function name: checkmsgti + * Description: Adds the given msgtype/importance to the log target. + * Arguments: target - the log target + * tab - the name of the msttype/importance + * Returns: 0 - success, + * 1 - failure. + */ + +int +checkmsgti(llnodeT* target, char* tab) +{ + if (strcmp(tab, "LOG_T_ALL") == 0) { + target->msgtype |= LOG_T_ALL; + } + else if (strcmp(tab, "LOG_T_USER") == 0) { + target->msgtype |= LOG_T_USER; + } + else if (strcmp(tab, "LOG_T_CLIENT") == 0) { + target->msgtype |= LOG_T_CLIENT; + } + else if (strcmp(tab, "LOG_T_INIT") == 0) { + target->msgtype |= LOG_T_INIT; + } + else if (strcmp(tab, "LOG_T_MANAGE") == 0) { + target->msgtype |= LOG_T_MANAGE; + } + else if (strcmp(tab, "LOG_T_MAIN") == 0) { + target->msgtype |= LOG_T_MAIN; + } + else if (strcmp(tab, "LOG_I_ALL") == 0) { + target->importance |= LOG_I_ALL; + } + else if (strcmp(tab, "LOG_I_CRIT") == 0) { + target->importance |= LOG_I_CRIT; + } + else if (strcmp(tab, "LOG_I_DEBUG") == 0) { + target->importance |= LOG_I_DEBUG; + } + else if (strcmp(tab, "LOG_I_INFO") == 0) { + target->importance |= LOG_I_INFO; + } + else if (strcmp(tab, "LOG_I_NOTICE") == 0) { + target->importance |= LOG_I_NOTICE; + } + else if (strcmp(tab, "LOG_I_WARNING") == 0) { + target->importance |= LOG_I_WARNING; + } + else if (strcmp(tab, "LOG_I_ERR") == 0) { + target->importance |= LOG_I_ERR; + } + else { + return 1; /* unknown msgtype/importance */ + } + return 0; +} + +/* + * Function name: checklogtarget + * Description: Parses the command line and sets all the options. + * Arguments: target - the log target + * Returns 0 - success, + * !0 - failure. + */ + +int +checklogtarget(llnodeT* target) +{ + char* ptr; + char desc[100]; + char type = 0; + char tab[100]; + int tmpfd; + int state, i; + if ((target == NULL) || (target->cmdline == NULL)) { + return 1; /* some of the important data is NULL */ + } + state = 0; /* we are at the beginning of the cmdline */ + memset(tab, 0, 100); + i = 0; + ptr = target->cmdline; + while ((*ptr) != 0) { + switch (state) { + /* beginning of the cmdline */ + case 0: { + if ((*ptr) == ',') { + tab[i] = 0; + if (strcmp(tab, "file") == 0) { + type = LOG_L_FILE; + } + else if (strcmp(tab, "sock") == 0) { + type = LOG_L_SOCK; + } + else { + return 2; /* unknown type of the target */ + } + state = 1; /* we are at the beginning of the file/sock description */ + memset(tab, 0, 100); + memset(desc, 0, 100); + i = 0; + break; + } + if (i == 98) { + return 2; /* unknown type of the target (name too long) */ + } + tab[i] = (*ptr); + ++i; + break; + } + /* beginning of the file/sock description */ + case 1: { + if ((*ptr) == ',') { + tab[i] = 0; + switch (type) { + case LOG_L_FILE: { + target->logfd = fopen(tab, "a"); + if (target->logfd == NULL) { + return 4; /* logging to a non-opened file? */ + } + state = 3; /* we want to read msgtype and importance */ + break; + } + case LOG_L_SOCK: { + strncpy(desc, tab, 99); + state = 2; /* we want to open a socket (read port first) */ + break; + } + default: { + return 2; /* unknown type of the target */ + } + } + memset(tab, 0, 100); + i = 0; + break; + } + if (i == 98) { + return 3; /* wrong file/sock description (name too long) */ + } + tab[i] = (*ptr); + ++i; + break; + } + /* beginning of the sock port description */ + case 2: { + if ((*ptr) == ',') { + tab[i] = 0; + if (ip_connect(&tmpfd, desc, tab, 1, NULL, NULL)) { + return 5; /* can't connect to host:port */ + } + target->logfd = fdopen(tmpfd, "a"); + if (target->logfd == NULL) { + return 4; /* can't create FILE* to log to */ + } + state = 3; /* we want to read msgtype and importance */ + memset(tab, 0, 100); + i = 0; + break; + } + if (i == 98) { + return 3; /* wrong file/sock description (name too long) */ + } + tab[i] = (*ptr); + ++i; + break; + } + /* beginning of the msgtype and importance section */ + case 3: { + if ((*ptr) == ',') { + tab[i] = 0; + if (checkmsgti(target, tab)) { + return 6; + } + memset(tab, 0, 100); + i = 0; + break; + } + if (i == 98) { + return 6; /* wrong msgtype/importance description (name too long) */ + } + tab[i] = (*ptr); + ++i; + break; + } + } + ++ptr; + } + if (i != 0) { + if (state == 3) { + tab[i] = 0; + if (checkmsgti(target, tab)) { + return 6; + } + } + else { + return 1; + } + } + return 0; +} + +/* + * Function name: addlogtarget + * Description: Adds the new non-initialized log target with the specified command line. + * Arguments: cmdline - the command line + */ + +void +addlogtarget(char* cmdline) +{ + llnodeT* newnode = calloc(1, sizeof(llnodeT)); + newnode->cmdline = cmdline; + newnode->next = head; + head = newnode; +} + +/* + * Function name: loginit + * Description: Initializes the logging system. + * Arguments: verl - level of verbosity + * dateformat - date format + * Returns: 0 - success, + * !0 - failure. + */ + +int +loginit(char verl, char* dateformat) +{ + llnodeT* ptr; + int n; + + verlev = 0; + if (verl) { + switch (verl) { + case 1: { + verlev = LOG_I_NOTICE | LOG_I_CRIT; + break; + } + case 2: { + verlev = LOG_I_INFO | LOG_I_NOTICE | LOG_I_CRIT; + break; + } + case 3: { + verlev = LOG_I_INFO | LOG_I_NOTICE | LOG_I_WARNING | LOG_I_CRIT; + break; + } + case 4: { + verlev = LOG_I_INFO | LOG_I_NOTICE | LOG_I_WARNING | LOG_I_ERR | LOG_I_CRIT; + break; + } + case 5: { + verlev = LOG_I_INFO | LOG_I_NOTICE | LOG_I_WARNING | LOG_I_ERR | LOG_I_CRIT | LOG_I_DEBUG; + break; + } + default: { + verlev = LOG_I_ALL; + break; + } + } + } + + setdateformat(dateformat); + + ptr = head; + while (ptr) { + if ((n = checklogtarget(ptr)) != 0) { + return n; + } + ptr = ptr->next; + } + + return 0; +} + +/* + * Function name: initializelogging + * Description: The opaque function for loginit. If the logging initialization + * failed, it prints the appropriate message and exits. + * Arguments: verl - level of verbosity + * dateformat - date format + */ + +void +initializelogging(char verl, char* dateformat) +{ + int k; + if ((k = loginit(verl, dateformat)) != 0) { + switch (k) { + /* wrong format of the logcmd */ + case 1: { + printf("Wrong format of the logcmd\n"); + break; + } + /* unknown type of the logging target */ + case 2: { + printf("Unknown type of the logging target\n"); + break; + } + /* wrong description of the logging target (name too long) */ + case 3: { + printf("Wrong description of the logging target (name too long)\n"); + break; + } + /* can't open file to log to */ + case 4: { + printf("Can't open file to log to\n"); + break; + } + /* can't connect to target host */ + case 5: { + printf("Can't connect to target host\n"); + break; + } + /* wrong msgtype/importance description */ + case 6: { + printf("Wrong msgtype/importance description\n"); + break; + } + } + exit(1); + } +} + +/* + * Function name: aflog + * Description: Logs the given message. + * Arguments: type - the type of the message + * importance - the importance of the message + * form - the format of the message + * ... - the additional arguments + */ + +void +aflog(char type, char importance, const char* form, ...) +{ + llnodeT* ptr; + va_list ap; + + if (verlev & importance) { + if (format[0] != 0) { + printf("[%s] ", datum()); + } + va_start(ap, form); + vfprintf(stdout, form, ap); + va_end(ap); + printf("\n"); + } + + ptr = head; + while (ptr) { + if ((type & ptr->msgtype) && (importance & ptr->importance)) { + if (format[0] != 0) { + fprintf(ptr->logfd, "[%s] ", datum()); + } + va_start(ap, form); + vfprintf(ptr->logfd, form, ap); + va_end(ap); + fprintf(ptr->logfd, "\n"); + fflush(ptr->logfd); + } + ptr = ptr->next; + } +} + diff --git a/src/logging.h b/src/logging.h new file mode 100644 index 0000000..4db250e --- /dev/null +++ b/src/logging.h @@ -0,0 +1,78 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <stdio.h> +#include <time.h> + +#ifndef _JS_LOGGING_H +#define _JS_LOGGING_H + +/* some constants for logging functions */ + /* type of the message */ + +#define LOG_T_ALL (LOG_T_USER | LOG_T_CLIENT | LOG_T_INIT | LOG_T_MANAGE | LOG_T_MAIN) +#define LOG_T_USER 1 +#define LOG_T_CLIENT 2 +#define LOG_T_INIT 4 +#define LOG_T_MANAGE 8 +#define LOG_T_MAIN 16 + + /* importance of the message */ + +#define LOG_I_ALL (LOG_I_CRIT | LOG_I_DEBUG | LOG_I_DDEBUG | LOG_I_INFO | LOG_I_NOTICE | LOG_I_WARNING | LOG_I_ERR) +#define LOG_I_CRIT 1 +#define LOG_I_DEBUG 2 +#define LOG_I_DDEBUG 4 +#define LOG_I_INFO 8 +#define LOG_I_NOTICE 16 +#define LOG_I_WARNING 32 +#define LOG_I_ERR 64 + + /* type of the logging target */ + +#define LOG_L_FILE 1 +#define LOG_L_SOCK 2 + +/* a structure that keeps information about logging target */ +typedef struct llnode { + char* cmdline; + char msgtype; + char importance; + FILE* logfd; + struct llnode* next; +} llnodeT; + + /* set dateformat */ +void setdateformat(char* dateformat); + /* get dateformat */ +char* getdateformat(); + /* get llnodeT head */ +llnodeT* getloglisthead(); + /* add logging target */ +void addlogtarget(char* cmdline); + /* initialize logging routine */ +void initializelogging(char verlev, char* dateformat); + /* log to a file or|and screen */ +void aflog(char type, char importance, const char* format, ...); + /* get text representation of the date */ +char* localdate(time_t* sec); + +#endif + diff --git a/src/make_ssl_handshake.c b/src/make_ssl_handshake.c new file mode 100644 index 0000000..6ebb859 --- /dev/null +++ b/src/make_ssl_handshake.c @@ -0,0 +1,139 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "make_ssl_handshake.h" +#include "stats.h" +#include "logging.h" + +#include <errno.h> +#include <openssl/err.h> + +/* + * Function name: make_ssl_initialize + * Description: Initializes the file descriptor of the SSL connection. + * Arguments: sf - pointer to SslFd structure + */ + +void +make_ssl_initialize(SslFd* sf) +{ + if (SSL_set_fd(SslFd_get_ssl(sf), SslFd_get_fd(sf)) != 1) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "Problem with initializing ssl... exiting"); + exit(1); + } +} + +/* + * Function name: make_ssl_accept + * Description: Accepts new SSL connection. + * Arguments: sf - pointer to SslFd structure + * Returns: 0 - success, + * !0 - failure. + */ + +int +make_ssl_accept(SslFd* sf) +{ + int result; + if ((result = SSL_accept(SslFd_get_ssl(sf))) != 1) { + return get_ssl_error(sf, "SSL_accept has failed", result); + } + return 0; +} + +/* + * Function name: get_ssl_error + * Description: Decodes and logs SSL errors. + * Arguments: sf - pointer to SslFd structure + * info - the header of the warning message + * result - the result from the SSL_accept function + * Returns: 1 - more i/o operations are needed to accomplish handshake, + * 2 - the error was fatal for the handshake. + */ + +int +get_ssl_error(SslFd* sf, char* info, int result) +{ + int merror; +#ifdef HAVE_ERR_ERROR_STRING + char err_buff[200]; +#endif + merror = SSL_get_error(SslFd_get_ssl(sf), result); + switch (merror) { + case SSL_ERROR_NONE : { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): none", info, result); + break; + } + case SSL_ERROR_ZERO_RETURN : { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): zero", info, result); + break; + } + case SSL_ERROR_WANT_READ : { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): w_read", info, result); + break; + } + case SSL_ERROR_WANT_WRITE : { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): w_write", info, result); + break; + } + case SSL_ERROR_WANT_CONNECT : { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): w_connect", info, result); + break; + } + case SSL_ERROR_WANT_X509_LOOKUP : { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): w_x509_lookup", info, result); + break; + } + case SSL_ERROR_SYSCALL : { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): syscall", info, result); + break; + } + case SSL_ERROR_SSL : { + SSL_load_error_strings(); +#ifdef HAVE_ERR_ERROR_STRING + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): ssl:%s", info, result, + ERR_error_string(ERR_get_error(), err_buff)); +#else + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): ssl", info, result); +#endif + break; + } + default: { + aflog(LOG_T_MAIN, LOG_I_WARNING, + "%s(%d): unrecognized error (%d)", info, result, errno); + } + } + if ((merror == SSL_ERROR_WANT_READ) || (merror == SSL_ERROR_WANT_WRITE)) { + return 1; + } + return 2; +} diff --git a/src/make_ssl_handshake.h b/src/make_ssl_handshake.h new file mode 100644 index 0000000..b326968 --- /dev/null +++ b/src/make_ssl_handshake.h @@ -0,0 +1,32 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "network.h" +#include "ssl_fd_struct.h" + +#ifndef _JS_MAKE_SSL_HANDSHAKE_H +#define _JS_MAKE_SSL_HANDSHAKE_H + +void make_ssl_initialize(SslFd* sf); +int make_ssl_accept(SslFd* sf); +int get_ssl_error(SslFd* sf, char* info, int result); + +#endif + diff --git a/src/module_struct.c b/src/module_struct.c new file mode 100644 index 0000000..ab1d2f8 --- /dev/null +++ b/src/module_struct.c @@ -0,0 +1,224 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#ifdef HAVE_LIBDL + +#include "string_functions.h" +#include "module_struct.h" + +#include <stdlib.h> +#include <dlfcn.h> +#include <assert.h> + +/* + * Function name: Module_new + * Description: Create and initialize new Module structure. + * Returns: Pointer to newly created Module structure. + */ + +Module* +Module_new() +{ + Module* tmp = calloc(1, sizeof(Module)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: Module_free + * Description: Free the memory allocated for Module structure. + * Arguments: m - pointer to pointer to Module structure + */ + +void +Module_free(Module** m) +{ + assert(m != NULL); + if (m == NULL) { + return; + } + assert((*m) != NULL); + if ((*m) == NULL) { + return; + } + Module_releaseModule(*m); + if ((*m)->fileName) { + free((*m)->fileName); + (*m)->fileName = NULL; + } + free((*m)); + (*m) = NULL; +} + +/* + * Function name: Module_set_fileName + * Description: Set the filename of the module. + * Arguments: m - pointer to Module structure + * fileName - the filename of the module + */ + +void +Module_set_fileName(Module* m, char* fileName) +{ + assert(m != NULL); + if (m == NULL) { + return; + } + string_cp(&(m->fileName), fileName); +} + +/* + * Function name: Module_get_fileName + * Description: Get the filename of the module. + * Arguments: m - pointer to Module structure + * Returns: The filename of the module. + */ + +char* +Module_get_fileName(Module* m) +{ + assert(m != NULL); + if (m == NULL) { + return NULL; + } + return m->fileName; +} + +/* + * Function name: Module_loadModule + * Description: Load the module into the memory. + * Arguments: m - pointer to Module structure + * Returns: 0 - successful/filename not set + * 1/2 - some errors occured. + */ + +int +Module_loadModule(Module* m) +{ + if (Module_get_fileName(m)) { + m->handle = dlopen(Module_get_fileName(m), RTLD_NOW); + if (!m->handle) { + return 1; + } + dlerror(); + *(void**) (&m->info) = dlsym(m->handle, "info"); + *(void**) (&m->allow) = dlsym(m->handle, "allow"); + *(void**) (&m->filter) = dlsym(m->handle, "filter"); + if (dlerror() != NULL) { + return 2; + } + m->loaded = 1; + } + return 0; +} + +/* + * Function name: Module_releaseModule + * Description: Unload the module from the memory. + * Arguments: m - pointer to Module structure + * Returns: 0 - successful/module was not loaded + * !0 - some errors occured. + */ + +int +Module_releaseModule(Module* m) +{ + if (Module_isModuleLoaded(m)) { + m->loaded = 0; + m->info = NULL; + m->allow = NULL; + m->filter = NULL; + return dlclose(m->handle); + } + return 0; +} + +/* + * Function name: Module_isModuleLoaded + * Description: Check if the module is loaded into the memory. + * Arguments: m - pointer to Module structure + * Returns: 0 - module is not loaded + * 1 - module is loaded. + */ + +int +Module_isModuleLoaded(Module* m) +{ + assert(m != NULL); + if (m == NULL) { + return 0; + } + return m->loaded; +} + +/* + * Function name: Module_function_info + * Description: Exec the info function of the module. + * Arguments: m - pointer to Module structure + * Returns: Result of the info function of the module. + */ + +char* +Module_function_info(Module* m) +{ + if (!Module_isModuleLoaded(m)) { + return NULL; + } + return m->info(); +} + +/* + * Function name: Module_function_allow + * Description: Exec the allow function of the module. + * Arguments: m - pointer to Module structure + * Returns: Result of the allow function of the module. + */ + +int +Module_function_allow(Module* m, char* host, char* port) +{ + if (!Module_isModuleLoaded(m)) { + return 0; + } + return m->allow(host, port); +} + +/* + * Function name: Module_function_filter + * Description: Exec the filter function of the module. + * Arguments: m - pointer to Module structure + * Returns: Result of the filter function of the module. + */ + +int +Module_function_filter(Module* m, char* host, unsigned char* message, int* messageLength) +{ + if (!Module_isModuleLoaded(m)) { + return 0; + } + return m->filter(host, message, messageLength); +} + +#endif diff --git a/src/module_struct.h b/src/module_struct.h new file mode 100644 index 0000000..cd8ef10 --- /dev/null +++ b/src/module_struct.h @@ -0,0 +1,55 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#ifdef HAVE_LIBDL + +# ifndef _JS_MODULE_STRUCT_H +# define _JS_MODULE_STRUCT_H + +typedef struct { + char loaded; + char* fileName; + void* handle; + char* (*info)(void); + int (*allow)(char*, char*); + int (*filter)(char*, unsigned char*, int*); +} Module; + +/* 'constructor' */ +Module* Module_new(); +/* 'destructor' */ +void Module_free(Module** m); +/* setters */ +void Module_set_fileName(Module* m, char* fileName); +/* getters */ +char* Module_get_fileName(Module* m); +/* other */ +int Module_loadModule(Module* m); +int Module_releaseModule(Module* m); +int Module_isModuleLoaded(Module* m); +char* Module_function_info(Module* m); +int Module_function_allow(Module* m, char* host, char* port); +int Module_function_filter(Module* m, char* host, unsigned char* message, int* messageLength); + +# endif + +#endif diff --git a/src/network.c b/src/network.c new file mode 100644 index 0000000..4d2e051 --- /dev/null +++ b/src/network.c @@ -0,0 +1,561 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "inet_ntop.h" +#include "network.h" +#include "activefor.h" +#include "stats.h" +#include "logging.h" +#include <string.h> +#include <errno.h> +#include <zlib.h> +#include <assert.h> + +/* + * Function name: ip_listen + * Description: Creates the listening socket. + * Arguments: sockfd - the created socket + * host - the name of the host + * serv - the name of the service (port) + * addrlenp - pointer to the length of the sockaddr structure + * type - the type of the socket + * Returns: 0 - success, + * !0 - failure. + */ + +int +ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type) +{ + const int on = 1; +#if defined(HAVE_GETADDRINFO) && defined(AF_INET6) + int n; + struct addrinfo hints, *res, *ressave; + + aflog(LOG_T_INIT, LOG_I_DDEBUG, + "ip_listen: host=[%s] serv=[%s], type=[%d]", host, serv, type); + + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + if (type & 0x02) { + hints.ai_family = AF_INET; + } + else if (type & 0x04) { + hints.ai_family = AF_INET6; + } + else { + hints.ai_family = AF_UNSPEC; + } + + if (type & 0x01) { + hints.ai_socktype = SOCK_STREAM; + } + else { + hints.ai_socktype = SOCK_DGRAM; + } + + if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { + return n; + } + ressave = res; + + do { + (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if ((*sockfd) < 0) { + continue; /* error, try next one */ + } + + if (type & 0x01) { /* tcp_listen */ + setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + setsockopt((*sockfd), SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); + } + + if (bind((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { + break; /* success */ + } + + close((*sockfd)); /* bind error, close and try next one */ + } while ( (res = res->ai_next) != NULL); + + if (res == NULL) { /* errno from final socket() or bind() */ + return 1; + } + + if (type & 0x01) { /* tcp_listen */ + listen((*sockfd), 1); + } + + if (addrlenp) { + *addrlenp = res->ai_addrlen; /* return size of protocol address */ + } + + freeaddrinfo(ressave); +#else + struct sockaddr_in servaddr; + struct hostent* hostaddr = NULL; + int port; + + aflog(LOG_T_INIT, LOG_I_DDEBUG, + "ip_listen: host=[%s] serv=[%s], type=[%d]", host, serv, type); + + if (type & 0x01) { + (*sockfd) = socket(AF_INET, SOCK_STREAM, 0); + } + else { + (*sockfd) = socket(AF_INET, SOCK_DGRAM, 0); + } + + if ((*sockfd) == -1) { + return 1; + } + port = atoi(serv); + + if (host) { + hostaddr = gethostbyname(host); + if (hostaddr == NULL) { + return 2; + } + } + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + if (host) { + memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length); + } + else { + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + } + servaddr.sin_port = htons(port); + + if (type & 0x01) { /* tcp_listen */ + setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + setsockopt((*sockfd), SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); + } + + if (bind((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){ + printf("bind failed\n"); + return 4; + } + + if (type & 0x01) { /* tcp_listen */ + if (listen((*sockfd), 5)){ + return 5; + } + } + + if (addrlenp) { + *addrlenp = sizeof(servaddr); /* return size of protocol address */ + } +#endif + + return(0); +} + +/* + * Function name: ip_connect + * Description: Creates the connected socket. + * Arguments: sockfd - the connected socket + * host - the name of the host + * serv - the name of the service (port) + * type - the type of the socket + * lhost - the name of the local host (used for local bind of the socket) + * lserv - the name of the local service (port) (used for local bind of the socket) + * Returns: 0 - success, + * !0 - failure. + */ + +int +ip_connect(int* sockfd, const char *host, const char *serv, const char type, + const char *lhost, const char *lserv) +{ + const int on = 1; +#if defined(HAVE_GETADDRINFO) && defined(AF_INET6) + int n; + int bindFailed; + struct addrinfo hints, *res, *ressave; + struct addrinfo lhints, *lres, *lressave = NULL; + + aflog(LOG_T_INIT, LOG_I_DDEBUG, + "ip_connect: host=[%s] serv=[%s], type=[%d], lhost=[%s], lserv=[%s]", host, serv, type, lhost, lserv); + + bzero(&hints, sizeof(struct addrinfo)); + if (type & 0x02) { + hints.ai_family = AF_INET; + } + else if (type & 0x04) { + hints.ai_family = AF_INET6; + } + else { + hints.ai_family = AF_UNSPEC; + } + if (type & 0x01) { + hints.ai_socktype = SOCK_STREAM; + } + else { + hints.ai_socktype = SOCK_DGRAM; + } + + lhints = hints; + + if (lhost || lserv) { + if ( (n = getaddrinfo(lhost, lserv, &lhints, &lres)) != 0) { + return n; + } + lressave = lres; + } + + if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { + return n; + } + ressave = res; + + do { + (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if ((*sockfd) < 0) { + continue; /* ignore this one */ + } + + if (type & 0x01) { /* tcp_connect */ + setsockopt((*sockfd), SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); + } + + bindFailed = 0; + if (lhost || lserv) { + bindFailed = 1; + lres = lressave; + do { + if (bind((*sockfd), lres->ai_addr, lres->ai_addrlen) == 0) { + bindFailed = 0; + break; /* success */ + } + } while ( (lres = lres->ai_next) != NULL); + } + + if (bindFailed == 1) { + close((*sockfd)); /* ignore this one */ + continue; + } + + if (connect((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { + break; /* success */ + } + + close((*sockfd)); /* ignore this one */ + } while ( (res = res->ai_next) != NULL); + + if (res == NULL) { /* errno set from final connect() */ + return 1; + } + + if (lhost || lserv) { + freeaddrinfo(lressave); + } + freeaddrinfo(ressave); +#else + struct sockaddr_in servaddr, lservaddr; + struct hostent* hostaddr; + struct hostent* lhostaddr; + int port, lport; + + aflog(LOG_T_INIT, LOG_I_DDEBUG, + "ip_connect: host=[%s] serv=[%s], type=[%d], lhost=[%s], lserv=[%s]", host, serv, type, lhost, lserv); + + if (type & 0x01) { + (*sockfd) = socket(AF_INET, SOCK_STREAM, 0); + } + else { + (*sockfd) = socket(AF_INET, SOCK_DGRAM, 0); + } + + if ((*sockfd) == -1) { + return 1; + } + port = atoi(serv); + + hostaddr = gethostbyname(host); + if (hostaddr == NULL) { + return 2; + } + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length); + + if (type & 0x01) { /* tcp_connect */ + setsockopt((*sockfd), SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); + } + + if (lhost || lserv) { + memset(&lservaddr, 0, sizeof(lservaddr)); + lservaddr.sin_family = AF_INET; + if (lserv) { + lport = atoi(lserv); + lservaddr.sin_port = htons(lport); + } + if (lhost) { + lhostaddr = gethostbyname(lhost); + if (lhostaddr == NULL) { + return 3; + } + memcpy(&lservaddr.sin_addr.s_addr, lhostaddr->h_addr_list[0], lhostaddr->h_length); + } + else { + lservaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + if (bind((*sockfd), (struct sockaddr*) &lservaddr, sizeof(lservaddr))){ + return 4; + } + } + + if (connect((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){ + return 5; + } +#endif + + return(0); +} + +/* + * Function name: sock_ntop + * Description: Returns the string representing given socket address. + * Arguments: sa - pointer to sockaddr structure + * salen - size of the sockaddr structure + * namebuf - buffer for string representation of the host name + * portbuf - buffer for string representation of the host port + * type - if the socket address should be resolved to the the DNS name + * Returns: The string representing given socket address or NULL, if the address + * can't be established. + */ + +char * +sock_ntop(const struct sockaddr *sa, socklen_t salen, char* namebuf, char* portbuf, char type) +{ + char portstr[7]; + static char str[136]; /* Unix domain is largest */ + + switch (sa->sa_family) { + case AF_INET: { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + + if (type) { +#ifdef HAVE_GETNAMEINFO + if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) { + return NULL; + } +#else + struct hostent* hostname; + if ((hostname = gethostbyaddr((void*) &sin->sin_addr, sizeof(struct in_addr), AF_INET))) { + strncpy(str, hostname->h_name, 127); + str[127] = 0; + } + else { + if (inet_ntop(AF_INET, (void*) &sin->sin_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } +#endif + + } + else { + if (inet_ntop(AF_INET, (void*) &sin->sin_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } + if (namebuf) { + memcpy(namebuf, str, 128); + } + if (ntohs(sin->sin_port) != 0) { + snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port)); + if (portbuf) { + snprintf(portbuf, 7, "%d", ntohs(sin->sin_port)); + } + strcat(str, portstr); + } + return(str); + } +#ifdef AF_INET6 + case AF_INET6: { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + + if (type) { +#ifdef HAVE_GETNAMEINFO + if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) { + return NULL; + } +#else + struct hostent* hostname; + if ((hostname = gethostbyaddr(&sin6->sin6_addr, sizeof(struct in6_addr), AF_INET6))) { + strncpy(str, hostname->h_name, 127); + str[127] = 0; + } + else { + if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } +#endif + + } + else { + if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } + if (namebuf) { + memcpy(namebuf, str, 128); + } + if (ntohs(sin6->sin6_port) != 0) { + snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin6->sin6_port)); + if (portbuf) { + snprintf(portbuf, 7, "%d", ntohs(sin6->sin6_port)); + } + strcat(str, portstr); + } + return(str); + } +#endif + default: { + snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen); + return(str); + } + } + return NULL; +} + +/* + * Function name: SSL_writen + * Description: Writes the given amount of data to the SSL connection. + * Arguments: fd - the SSL connection + * buf - buffer with data to write + * amount - the size of the data + * Returns: The amount of bytes written to the SSL connection. + */ + +int +SSL_writen(SSL* fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + assert(amount > 0); + while (sent < amount) { + n = SSL_write(fd, buf+sent, amount - sent); + assert(n != 0); + if (n != -1) { + sent += n; + } + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; +} + +/* + * Function name: SSL_readn + * Description: Reads the given amount of data from the SSL connection. + * Arguments: fd - the SSL connection + * buf - buffer for data + * amount - the size of the data to read + * Returns: The amount of bytes read from the SSL connection. + */ + +int +SSL_readn(SSL* fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + assert(amount > 0); + while (sent < amount) { + n = SSL_read(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == 0) + return 0; + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; +} + +/* + * Function name: writen + * Description: Writes the given amount of data to the file descriptor. + * Arguments: fd - the file descriptor + * buf - buffer with data to write + * amount - the size of the data + * Returns: The amount of bytes written to the file descriptor + */ + +int +writen(int fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + assert(amount > 0); + while (sent < amount) { + n = write(fd, buf+sent, amount - sent); + assert(n != 0); + if (n != -1) { + sent += n; + } + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; +} + +/* + * Function name: readn + * Description: Reads the given amount of data from the file descriptor. + * Arguments: fd - the file descriptor + * buf - buffer for data + * amount - the size of the data to read + * Returns: The amount of bytes read from the file descriptor. + */ + +int +readn(int fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + assert(amount > 0); + while (sent < amount) { + n = read(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == 0) + return 0; + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; + +} diff --git a/src/network.h b/src/network.h new file mode 100644 index 0000000..b8c0273 --- /dev/null +++ b/src/network.h @@ -0,0 +1,49 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_NETWORK_H +#define _JS_NETWORK_H + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <unistd.h> +#ifdef HAVE_LIBPTHREAD +#include <pthread.h> +#endif +#include <netdb.h> +#include <openssl/ssl.h> + +int ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type); /* socket, bind, listen... */ +int ip_connect(int* sockfd, const char *host, const char *serv, const char type, + const char *lhost, const char *lserv); /* socket[, bind], connect... */ +char* sock_ntop(const struct sockaddr* sa, socklen_t salen, char* namebuf, char* portbuf, char type); /* return the IP of connected user */ + +int SSL_writen(SSL* fd, unsigned char* buf, int amount); +int SSL_readn(SSL* fd, unsigned char* buf, int amount); +int writen(int fd, unsigned char* buf, int amount); +int readn(int fd, unsigned char* buf, int amount); + +#endif diff --git a/src/port_list_node_struct.c b/src/port_list_node_struct.c new file mode 100644 index 0000000..cc171a4 --- /dev/null +++ b/src/port_list_node_struct.c @@ -0,0 +1,140 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <assert.h> + +#include "port_list_node_struct.h" +#include "string_functions.h" + +/* + * Function name: PortListNode_new + * Description: Creates and initializes new PortListNode structure from the + * given port name. + * Arguments: portName - the port name + * Returns: Newly created PortListNode structure. + */ + +PortListNode* +PortListNode_new(char* portName) +{ + PortListNode* tmp = calloc(1, sizeof(PortListNode)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + PortListNode_set_portName(tmp, portName); + return tmp; +} + +/* + * Function name: PortListNode_free + * Description: Frees the memory allocated for PortListNode structure. + * Arguments: pln - pointer to pointer to PortListNode structure + */ + +void +PortListNode_free(PortListNode** pln) +{ + assert(pln != NULL); + if (pln == NULL) { + return; + } + assert((*pln) != NULL); + if ((*pln) == NULL) { + return; + } + if ((*pln)->portName) { + free((*pln)->portName); + (*pln)->portName = NULL; + } + free((*pln)); + (*pln) = NULL; +} + +/* + * Function name: PortListNode_set_portName + * Description: Sets the port name. + * Arguments: pln - pointer to PortListNode structure + * portName - the port name + */ + +void +PortListNode_set_portName(PortListNode* pln, char* portName) +{ + assert(pln != NULL); + if (pln == NULL) { + return; + } + string_cp(&(pln->portName), portName); +} + +/* + * Function name: PortListNode_set_nextNode + * Description: Sets next node pointer. + * Arguments: pln - pointer to PortListNode structure + * nextNode - next node pointer + */ + +void +PortListNode_set_nextNode(PortListNode* pln, PortListNode* nextNode) +{ + assert(pln != NULL); + if (pln == NULL) { + return; + } + pln->nextNode = nextNode; +} + +/* + * Function name: PortListNode_get_portName + * Description: Gets the port name. + * Arguments: pln - pointer to PortListNode structure + * Returns: The port name. + */ + +char* +PortListNode_get_portName(PortListNode* pln) +{ + assert(pln != NULL); + if (pln == NULL) { + return NULL; + } + return pln->portName; +} + +/* + * Function name: PortListNode_get_nextNode + * Description: Gets next node pointer. + * Arguments: pln - pointer to PortListNode structure + * Returns: Next PortListNode structure pointer or NULL, if there is no next one. + */ + +PortListNode* +PortListNode_get_nextNode(PortListNode* pln) +{ + assert(pln != NULL); + if (pln == NULL) { + return NULL; + } + return pln->nextNode; +} diff --git a/src/port_list_node_struct.h b/src/port_list_node_struct.h new file mode 100644 index 0000000..f4b1de6 --- /dev/null +++ b/src/port_list_node_struct.h @@ -0,0 +1,40 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_PORT_LIST_NODE_STRUCT_H +#define _JS_PORT_LIST_NODE_STRUCT_H + +typedef struct plnode { + char* portName; + struct plnode* nextNode; +} PortListNode; + +/* 'constructor' */ +PortListNode* PortListNode_new(char* portName); +/* 'destructor' */ +void PortListNode_free(PortListNode** pln); +/* setters */ +void PortListNode_set_portName(PortListNode* pln, char* portName); +void PortListNode_set_nextNode(PortListNode* pln, PortListNode* nextNode); +/* getters */ +char* PortListNode_get_portName(PortListNode* pln); +PortListNode* PortListNode_get_nextNode(PortListNode* pln); + +#endif diff --git a/src/port_list_struct.c b/src/port_list_struct.c new file mode 100644 index 0000000..f464044 --- /dev/null +++ b/src/port_list_struct.c @@ -0,0 +1,167 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <assert.h> + +#include "port_list_struct.h" + +/* + * Function name: PortList_new + * Description: Creates and initialies new PortList structure. + * Returns: Newly created PortList structure. + */ + +PortList* +PortList_new() +{ + PortList* tmp = calloc(1, sizeof(PortList)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: PortList_free + * Description: Frees the memory allocated for PortList structure. + * Arguments: pl - pointer to pointer to PortList structure + */ + +void +PortList_free(PortList** pl) +{ + assert(pl != NULL); + if (pl == NULL) { + return; + } + assert((*pl) != NULL); + if ((*pl) == NULL) { + return; + } + PortList_clear((*pl)); + free((*pl)); + (*pl) = NULL; +} + +/* + * Function name: PortList_insert_back + * Description: Inserts new node at the end of the list. + * Arguments: pl - pointer to PortList structure + * pln - pointer to PortListNode structure + */ + +void +PortList_insert_back(PortList* pl, PortListNode* pln) +{ + assert(pl != NULL); + if (pl == NULL) { + return; + } + assert(pln != NULL); + if (pln == NULL) { + return; + } + if (pl->tail) { + pl->tail->nextNode = pln; + } + else { + pl->head = pln; + } + pl->tail = pln; + pln->nextNode = NULL; + pl->size += 1; +} + +/* + * Function name: PortList_get_nth + * Description: Get the nth node from the beginning of the list. + * Arguments: pl - pointer to PortList structure + * n - the number of the node + * Returns: Nth node from the beginning of the list. + */ + +PortListNode* +PortList_get_nth(PortList* pl, int n) +{ + PortListNode* tmp; + assert(pl != NULL); + if (pl == NULL) { + return NULL; + } + assert(n >= 0); + assert(n < PortList_get_size(pl)); + tmp = pl->head; + while (tmp) { + if (n <= 0) { + return tmp; + } + n -= 1; + tmp = PortListNode_get_nextNode(tmp); + } + return NULL; +} + +/* + * Function name: PortList_get_size + * Description: Returns the size of the list. + * Arguments: pl - pointer to PortList structure + * Returns: The size of the list. + */ + +int +PortList_get_size(PortList* pl) +{ + assert(pl != NULL); + if (pl == NULL) { + return -1; + } + return pl->size; +} + +/* + * Function name: PortList_clear + * Description: Deletes all nodes from the list. + * Arguments: pl - pointer to PortList structure + */ + +void +PortList_clear(PortList* pl) +{ + PortListNode* tmp; + assert(pl != NULL); + if (pl == NULL) { + return; + } + while (pl->head) { + tmp = pl->head; + if (tmp == pl->tail) { + pl->head = pl->tail = NULL; + } + else { + pl->head = PortListNode_get_nextNode(pl->head); + } + PortListNode_free(&tmp); + } + pl->size = 0; +} diff --git a/src/port_list_struct.h b/src/port_list_struct.h new file mode 100644 index 0000000..175f06b --- /dev/null +++ b/src/port_list_struct.h @@ -0,0 +1,42 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_PORT_LIST_STRUCT_H +#define _JS_PORT_LIST_STRUCT_H + +#include "port_list_node_struct.h" + +typedef struct portlist { + int size; + PortListNode* head; + PortListNode* tail; +} PortList; + +/* 'constructor' */ +PortList* PortList_new(); +/* 'destructor' */ +void PortList_free(PortList** pl); +/* other */ +void PortList_insert_back(PortList* pl, PortListNode* pln); +PortListNode* PortList_get_nth(PortList* pl, int n); +int PortList_get_size(PortList* pl); +void PortList_clear(PortList* pl); + +#endif diff --git a/src/realmnames.c b/src/realmnames.c new file mode 100644 index 0000000..db9cfdf --- /dev/null +++ b/src/realmnames.c @@ -0,0 +1,86 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include "realmnames.h" + +/* + * Function name: get_realmname + * Description: Returns the name of the realm. + * Arguments: config - the server configuration + * realm - the realm number + * Returns: The name of the realm. + */ + +char* +get_realmname(ServerConfiguration* config, int realm) +{ + static char realmname[10]; + + assert(config != NULL); + + if (ServerRealm_get_realmName(ServerConfiguration_get_realmsTable(config)[realm]) == NULL) { + memset(realmname, 0, 10); + sprintf(realmname, "%d", realm); + return realmname; + } + + return ServerRealm_get_realmName(ServerConfiguration_get_realmsTable(config)[realm]); +} + +/* + * Function name: get_realmnumber + * Description: Returns the realm number. + * Arguments: config - the server configuration + * realmname - the name of the realm + * Returns: The realm number or -1, if there is no realm with such name. + */ + +int +get_realmnumber(ServerConfiguration* config, char* realmname) +{ + int i; + char guard; + + assert(config != NULL); + assert(realmname != NULL); + + for (i = 0; i < ServerConfiguration_get_realmsNumber(config); ++i) { + if (ServerRealm_get_realmName(ServerConfiguration_get_realmsTable(config)[i]) != NULL) { + if (strcmp(realmname, ServerRealm_get_realmName(ServerConfiguration_get_realmsTable(config)[i])) == 0) { + return i; + } + } + } + + if (sscanf(realmname, "%d%c", &i, &guard) == 1) { + if ((i >= 0) && (i < ServerConfiguration_get_realmsNumber(config))) { + if (ServerRealm_get_realmName(ServerConfiguration_get_realmsTable(config)[i]) == NULL) { + return i; + } + } + } + + return -1; +} diff --git a/src/realmnames.h b/src/realmnames.h new file mode 100644 index 0000000..8974488 --- /dev/null +++ b/src/realmnames.h @@ -0,0 +1,31 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "server_configuration_struct.h" + +#ifndef _JS_REALMNAMES_H +#define _JS_REALMNAMES_H + +char* get_realmname(ServerConfiguration*, int); +int get_realmnumber(ServerConfiguration*, char*); + +#endif + diff --git a/src/remoteadmin_codes.h b/src/remoteadmin_codes.h new file mode 100644 index 0000000..65038eb --- /dev/null +++ b/src/remoteadmin_codes.h @@ -0,0 +1,32 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_REMOTEADMIN_CODES_H +#define _JS_REMOTEADMIN_CODES_H + +#define AF_RA_UNDEFINED 0 +#define AF_RA_CMD 1 +#define AF_RA_REPEAT 2 +#define AF_RA_STATUS_OK 3 +#define AF_RA_NOT_KNOWN 4 +#define AF_RA_FAILED 5 +#define AF_RA_KICKED 6 + +#endif diff --git a/src/remove_client_task.c b/src/remove_client_task.c new file mode 100644 index 0000000..a223c43 --- /dev/null +++ b/src/remove_client_task.c @@ -0,0 +1,134 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <assert.h> + +#include "logging.h" +#include "realmnames.h" +#include "clientnames.h" +#include "server_remove.h" +#include "remove_client_task.h" + +/* + * Function name: RCTdata_new + * Description: Creates and initializes new data for remove client task. + * Arguments: config - server configuration + * realm - the realm id + * client - the client id + * ra - if the client is in remote administration mode + * fdset - the descriptor set watched for read + * Returns: Pointer to newly created RCTdata structure. + */ + +RCTdata* +RCTdata_new(ServerConfiguration* config, int realm, int client, char ra, char reason, fd_set* set, fd_set* wset) +{ + RCTdata* tmp; + assert(config != NULL); + if (config == NULL) { + return NULL; + } + tmp = calloc(1, sizeof(RCTdata)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + tmp->config = config; + tmp->realm = realm; + tmp->client = client; + tmp->ra = ra; + tmp->reason = reason; + tmp->set = set; + tmp->wset = wset; + + return tmp; +} + +/* + * Function name: RCTdata_free + * Description: Frees the memory allocated for RCTdata structure. + * Arguments: ptr - pointer to pointer to RCTdata structure + */ + +void +RCTdata_free(void** ptr) +{ + RCTdata** data = (RCTdata**) ptr; + assert(data != NULL); + if (data == NULL) { + return; + } + assert((*data) != NULL); + if ((*data) == NULL) { + return; + } + free((*data)); + (*data) = NULL; +} + +/* + * Function name: RCTfunction + * Description: Function executed in the task by the task scheduler. + * Arguments: Pointer to the memory containing RCTdata structure. + */ + +void +RCTfunction(void* data) +{ + ConnectClient** clientsTable; + ServerRealm** realmsTable; + RCTdata* ptr; + assert(data != NULL); + if (data == NULL) { + return; + } + ptr = (RCTdata*) data; + realmsTable = ServerConfiguration_get_realmsTable(ptr->config); + if (ptr->ra) { + clientsTable = ServerRealm_get_raClientsTable(realmsTable[ptr->realm]); + } + else { + clientsTable = ServerRealm_get_clientsTable(realmsTable[ptr->realm]); + } + switch (ptr->reason) { + case RCT_REASON_TIMEOUT: + close(SslFd_get_fd(ConnectClient_get_sslFd(clientsTable[ptr->client]))); + FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(clientsTable[ptr->client])), ptr->set); + SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(clientsTable[ptr->client]))); + ConnectClient_set_state(clientsTable[ptr->client], CONNECTCLIENT_STATE_FREE); + ServerRealm_decrease_connectedClients(realmsTable[ptr->realm]); + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: Client[%s]%s: SSL_accept failed (timeout)", + get_realmname(ptr->config, ptr->realm), + ptr->ra ? get_raclientname(realmsTable[ptr->realm], ptr->client) : + get_clientname(realmsTable[ptr->realm], ptr->client), + ptr->ra ? " (ra)" : ""); + break; + case RCT_REASON_MAXIDLE: + aflog(LOG_T_CLIENT, LOG_I_WARNING, + "realm[%s]: Client[%s]: too long idle --> DROPPING", get_realmname(ptr->config, ptr->realm), + get_clientname(realmsTable[ptr->realm], ptr->client)); + remove_client(realmsTable[ptr->realm], ptr->client, ptr->set, ptr->wset, NULL); + } + ConnectClient_set_task(clientsTable[ptr->client], NULL); +} diff --git a/src/remove_client_task.h b/src/remove_client_task.h new file mode 100644 index 0000000..f229d2d --- /dev/null +++ b/src/remove_client_task.h @@ -0,0 +1,47 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_REMOVE_CLIENT_TASK_H +#define _JS_REMOVE_CLIENT_TASK_H + +#define RCT_REASON_TIMEOUT 0 +#define RCT_REASON_MAXIDLE 1 + +#include "server_configuration_struct.h" + +typedef struct { + ServerConfiguration* config; + int realm; + int client; + char ra; + char reason; + fd_set* set; + fd_set* wset; +} RCTdata; + +/* 'constructor' */ +RCTdata* RCTdata_new(ServerConfiguration* config, int realm, int client, char ra, char reason, + fd_set* set, fd_set* wset); +/* 'destructor' */ +void RCTdata_free(void** data); +/* other */ +void RCTfunction(void*); + +#endif diff --git a/src/server_check.c b/src/server_check.c new file mode 100644 index 0000000..4c20be1 --- /dev/null +++ b/src/server_check.c @@ -0,0 +1,112 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <assert.h> + +#include "server_check.h" +#include "stats.h" +#include "logging.h" + +/* + * Function name: check_value + * Description: Checks if the string is a valid positive int number. + * Arguments: what - the string representing number + * info - the information string printed on failure + * Returns: The decoded int number. + */ + +int +check_value(char* what, char* info) +{ + long tmp; + + assert(what != NULL); + assert(info != NULL); + + tmp = check_value_liberal(what, info); + + if (tmp <= 0) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "%s: %d\n", info, tmp); + exit(1); + } + return tmp; +} + +/* + * Function name: check_value_liberal + * Description: Checks if the string is a valid int number. + * Arguments: what - the string representing number + * info - the information string printed on failure + * Returns: The decoded int number. + */ + +int +check_value_liberal(char* what, char* info) +{ + char* znak; + long tmp; + + assert(what != NULL); + assert(info != NULL); + + if ((tmp = strtol(what, &znak, 10)) >= INT_MAX) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "%s: %s\n", info, what); + exit(1); + } + if (((*what) == '\0') || (*znak != '\0')) { + aflog(LOG_T_INIT, LOG_I_CRIT, + "%s: %s\n", info, what); + exit(1); + } + return tmp; +} + +/* + * Function name: check_long + * Description: Checks if the string is a valid long number. + * Arguments: text - the string representing number + * number - the pointer where decoded number will be stored + * Returns: 0 - success, + * 1 - value from outside the long number range, + * 2 - not the valid long number. + */ + +int +check_long(char* text, long* number) +{ + char* tmp; + if (((*number = strtol(text, &tmp, 10)) == LONG_MAX) || (*number == LONG_MIN)) { + return 1; + } + if ((*text != '\0') && (*tmp == '\0')) { + return 0; + } + else { + return 2; + } +} + diff --git a/src/server_check.h b/src/server_check.h new file mode 100644 index 0000000..fd4f03b --- /dev/null +++ b/src/server_check.h @@ -0,0 +1,29 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_SERVER_CHECK_H +#define _JS_SERVER_CHECK_H + +int check_value(char* what, char* info); +int check_value_liberal(char* what, char* info); +int check_long(char* text, long* number); + +#endif + diff --git a/src/server_configuration_struct.c b/src/server_configuration_struct.c new file mode 100644 index 0000000..7f88275 --- /dev/null +++ b/src/server_configuration_struct.c @@ -0,0 +1,421 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "string_functions.h" +#include "server_configuration_struct.h" + +/* + * Function name: ServerConfiguration_new + * Description: Create and initialize new ServerConfiguration structure. + * Returns: Pointer to newly created ServerConfiguration structure. + */ + +ServerConfiguration* +ServerConfiguration_new() +{ + ServerConfiguration* tmp = calloc(1, sizeof(ServerConfiguration)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: ServerConfiguration_free + * Description: Free the memory allocated for ServerConfiguration structure. + * Arguments: sc - pointer to pointer to ServerConfiguration structure + */ + +void +ServerConfiguration_free(ServerConfiguration** sc) +{ + int i; + assert(sc != NULL); + if (sc == NULL) { + return; + } + assert((*sc) != NULL); + if ((*sc) == NULL) { + return; + } + if ((*sc)->certificateFile) { + free((*sc)->certificateFile); + (*sc)->certificateFile = NULL; + } + if ((*sc)->cacertificateFile) { + free((*sc)->cacertificateFile); + (*sc)->cacertificateFile = NULL; + } + if ((*sc)->cacertificatePath) { + free((*sc)->cacertificatePath); + (*sc)->cacertificatePath = NULL; + } + if ((*sc)->sCertificateDepth) { + free((*sc)->sCertificateDepth); + (*sc)->sCertificateDepth = NULL; + } + if ((*sc)->keysFile) { + free((*sc)->keysFile); + (*sc)->keysFile = NULL; + } + if ((*sc)->dateFormat) { + free((*sc)->dateFormat); + (*sc)->dateFormat = NULL; + } + if ((*sc)->realmsTable) { + for (i = 0; i < (*sc)->realmsNumber; ++i) { + if ((*sc)->realmsTable[i]) { + ServerRealm_free(&((*sc)->realmsTable[i])); + } + } + free((*sc)->realmsTable); + (*sc)->realmsTable = NULL; + } + free((*sc)); + (*sc) = NULL; +} + +/* + * Function name: ServerConfiguration_set_certificateFile + * Description: Set certificate filename. + * Arguments: sc - pointer to ServerConfiguration structure + * certificateFile - certificate filename + */ + +void +ServerConfiguration_set_certificateFile(ServerConfiguration* sc, char* certificateFile) +{ + assert(sc != NULL); + if (sc == NULL) { + return; + } + string_cp(&(sc->certificateFile), certificateFile); +} + +/* + * Function name: ServerConfiguration_set_cacertificateFile + * Description: Set CA certificate filename. + * Arguments: sc - pointer to ServerConfiguration structure + * certificateFile - CA certificate filename + */ + +void +ServerConfiguration_set_cacertificateFile(ServerConfiguration* sc, char* cacertificateFile) +{ + assert(sc != NULL); + if (sc == NULL) { + return; + } + string_cp(&(sc->cacertificateFile), cacertificateFile); +} + +/* + * Function name: ServerConfiguration_set_cacertificatePath + * Description: Set CA certificate filename. + * Arguments: sc - pointer to ServerConfiguration structure + * cacertificateFile - CA certificate path + */ + +void +ServerConfiguration_set_cacertificatePath(ServerConfiguration* sc, char* cacertificatePath) +{ + assert(sc != NULL); + if (sc == NULL) { + return; + } + string_cp(&(sc->cacertificatePath), cacertificatePath); +} + +void +ServerConfiguration_set_sCertificateDepth(ServerConfiguration* sc, char* sCertificateDepth) +{ + assert(sc != NULL); + if (sc == NULL) { + return; + } + string_cp(&(sc->sCertificateDepth), sCertificateDepth); +} +void +ServerConfiguration_set_certificateDepth(ServerConfiguration* sc, int certificateDepth) +{ + assert(sc != NULL); + if (sc == NULL) { + return; + } + sc->certificateDepth = certificateDepth; +} + +/* + * Function name: ServerConfiguration_set_keysFile + * Description: Set keys filename. + * Arguments: sc - pointer to ServerConfiguration structure + * keysFile - keys filename + */ + +void +ServerConfiguration_set_keysFile(ServerConfiguration* sc, char* keysFile) +{ + assert(sc != NULL); + if (sc == NULL) { + return; + } + string_cp(&(sc->keysFile), keysFile); +} + +/* + * Function name: ServerConfiguration_set_dateFormat + * Description: Set format of the date string. + * Arguments: sc - pointer to ServerConfiguration structure + * dateFormat - format of the date string + */ + +void +ServerConfiguration_set_dateFormat(ServerConfiguration* sc, char* dateFormat) +{ + assert(sc != NULL); + if (sc == NULL) { + return; + } + string_cp(&(sc->dateFormat), dateFormat); +} + +/* + * Function name: ServerConfiguration_set_realmsNumber + * Description: Set number of realms. + * Arguments: sc - pointer to ServerConfiguration structure + * realmsNumber - number of realms + */ + +void +ServerConfiguration_set_realmsNumber(ServerConfiguration* sc, int realmsNumber) +{ + assert(sc != NULL); + if (sc == NULL) { + return; + } + sc->realmsNumber = realmsNumber; +} + +/* + * Function name: ServerConfiguration_set_startTime + * Description: Set start time of the server. + * Arguments: sc - pointer to ServerConfiguration structure + * startTime - start time of the server + */ + +void +ServerConfiguration_set_startTime(ServerConfiguration* sc, time_t startTime) +{ + assert(sc != NULL); + if (sc == NULL) { + return; + } + sc->startTime = startTime; +} + +/* + * Function name: ServerConfiguration_set_realmsTable + * Description: Set table of realms. + * Arguments: sc - pointer to ServerConfiguration structure + * realmsTable - table of realms + */ + +void +ServerConfiguration_set_realmsTable(ServerConfiguration* sc, ServerRealm** realmsTable) +{ + int i; + assert(sc != NULL); + if (sc == NULL) { + return; + } + if (sc->realmsTable) { + for (i = 0; i < sc->realmsNumber; ++i) { + if (sc->realmsTable[i]) { + ServerRealm_free(&(sc->realmsTable[i])); + } + } + free(sc->realmsTable); + sc->realmsTable = NULL; + } + sc->realmsTable = realmsTable; +} + +/* + * Function name: ServerConfiguration_get_certificateFile + * Description: Get certificate filename. + * Arguments: sc - pointer to ServerConfiguration structure + * Returns: Certificate filename. + */ + +char* +ServerConfiguration_get_certificateFile(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return NULL; + } + return sc->certificateFile; +} + +/* + * Function name: ServerConfiguration_get_cacertificateFile + * Description: Get CA certificate filename. + * Arguments: sc - pointer to ServerConfiguration structure + * Returns: CA Certificate filename. + */ + +char* +ServerConfiguration_get_cacertificateFile(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return NULL; + } + return sc->cacertificateFile; +} + +/* + * Function name: ServerConfiguration_get_cacertificatePath + * Description: Get CA certificate path + * Arguments: sc - pointer to ServerConfiguration structure + * Returns: CA Certificate path. + */ + +char* +ServerConfiguration_get_cacertificatePath(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return NULL; + } + return sc->cacertificatePath; +} + +char* +ServerConfiguration_get_sCertificateDepth(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return NULL; + } + return sc->sCertificateDepth; +} + +int +ServerConfiguration_get_certificateDepth(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return -1; + } + return sc->certificateDepth; +} + +/* + * Function name: ServerConfiguration_get_keysFile + * Description: Get keys filename. + * Arguments: sc - pointer to ServerConfiguration structure + * Returns: Keys filename. + */ + +char* +ServerConfiguration_get_keysFile(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return NULL; + } + return sc->keysFile; +} + +/* + * Function name: ServerConfiguration_get_dateFormat + * Description: Get format of the date string. + * Arguments: sc - pointer to ServerConfiguration structure + * Returns: Format of the date string. + */ + +char* +ServerConfiguration_get_dateFormat(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return NULL; + } + return sc->dateFormat; +} + +/* + * Function name: ServerConfiguration_get_realmsNumber + * Description: Get number of realms. + * Arguments: sc - pointer to ServerConfiguration structure + * Returns: Number of realms. + */ + +int +ServerConfiguration_get_realmsNumber(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return -1; + } + return sc->realmsNumber; +} + +/* + * Function name: ServerConfiguration_get_startTime + * Description: Get start time of the server. + * Arguments: sc - pointer to ServerConfiguration structure + * Returns: Start time of the server. + */ + +time_t +ServerConfiguration_get_startTime(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return 0; + } + return sc->startTime; +} + +/* + * Function name: ServerConfiguration_get_realmsTable + * Description: Get table of realms. + * Arguments: sc - pointer to ServerConfiguration structure + * Returns: Table of realms. + */ + +ServerRealm** +ServerConfiguration_get_realmsTable(ServerConfiguration* sc) +{ + assert(sc != NULL); + if (sc == NULL) { + return NULL; + } + return sc->realmsTable; +} diff --git a/src/server_configuration_struct.h b/src/server_configuration_struct.h new file mode 100644 index 0000000..caf7a9e --- /dev/null +++ b/src/server_configuration_struct.h @@ -0,0 +1,67 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _JS_SERVER_CONFIGURATION_STRUCT_H +#define _JS_SERVER_CONFIGURATION_STRUCT_H + +#include "server_realm_struct.h" + +typedef struct { + char* cacertificateFile; + char* cacertificatePath; + char* sCertificateDepth; + int certificateDepth; + char* certificateFile; + char* keysFile; + char* dateFormat; + int realmsNumber; + time_t startTime; + ServerRealm** realmsTable; +} ServerConfiguration; + +/* 'constructor' */ +ServerConfiguration* ServerConfiguration_new(); +/* 'destructor' */ +void ServerConfiguration_free(ServerConfiguration** sc); +/* setters */ +void ServerConfiguration_set_certificateFile(ServerConfiguration* sc, char* certificateFile); +void ServerConfiguration_set_cacertificateFile(ServerConfiguration* sc, char* cacertificateFile); +void ServerConfiguration_set_cacertificatePath(ServerConfiguration* sc, char* cacertificatePath); +void ServerConfiguration_set_sCertificateDepth(ServerConfiguration* sc, char* sCertificateDepth); +void ServerConfiguration_set_certificateDepth(ServerConfiguration* sc, int certificateDepth); +void ServerConfiguration_set_keysFile(ServerConfiguration* sc, char* keysFile); +void ServerConfiguration_set_dateFormat(ServerConfiguration* sc, char* dateFormat); +void ServerConfiguration_set_realmsNumber(ServerConfiguration* sc, int realmsNumber); +void ServerConfiguration_set_startTime(ServerConfiguration* sc, time_t startTime); +void ServerConfiguration_set_realmsTable(ServerConfiguration* sc, ServerRealm** realmsTable); +/* getters */ +char* ServerConfiguration_get_certificateFile(ServerConfiguration* sc); +char* ServerConfiguration_get_cacertificateFile(ServerConfiguration* sc); +char* ServerConfiguration_get_cacertificatePath(ServerConfiguration* sc); +char* ServerConfiguration_get_sCertificateDepth(ServerConfiguration* sc); +int ServerConfiguration_get_certificateDepth(ServerConfiguration* sc); +char* ServerConfiguration_get_keysFile(ServerConfiguration* sc); +char* ServerConfiguration_get_dateFormat(ServerConfiguration* sc); +int ServerConfiguration_get_realmsNumber(ServerConfiguration* sc); +time_t ServerConfiguration_get_startTime(ServerConfiguration* sc); +ServerRealm** ServerConfiguration_get_realmsTable(ServerConfiguration* sc); + +#endif diff --git a/src/server_eval.c b/src/server_eval.c new file mode 100644 index 0000000..c4c69ce --- /dev/null +++ b/src/server_eval.c @@ -0,0 +1,123 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <assert.h> +#include <string.h> + +#include "server_eval.h" + +/* + * Function name: eval_numofcon + * Description: Returns the real connection number on the afserver. + * Arguments: ptr - the server realm + * client - client number + * numofcon - the connection number on the afclient + * Returns: The real connection number on the afserver. + */ + +int +eval_numofcon(ServerRealm* ptr, int client, int numofcon) +{ + assert(ptr != NULL); + if ((numofcon >= 0) && (numofcon < ConnectClient_get_limit(ServerRealm_get_clientsTable(ptr)[client]))) { + numofcon = ConnectClient_get_users(ServerRealm_get_clientsTable(ptr)[client])[numofcon]; + } + else { + numofcon = -1; + } + return numofcon; +} + +/* + * Function name: eval_usernum + * Description: Returns the user number in the connected client on the afserver side. + * Arguments: ptr - the connected client + * usernum - the connection number on the afserver + * Returns: The user number in the connected client on the afserver side. + */ + +int +eval_usernum(ConnectClient* ptr, int usernum) +{ + int i; + assert(ptr != NULL); + for (i = 0; i < ConnectClient_get_limit(ptr); ++i) { + if (ConnectClient_get_users(ptr)[i] == usernum) + return i; + } + return -1; +} + +/* + * Function name: eval_UsrCliPair + * Description: Returns how many UsrCli structures are connected with the current manage port. + * Arguments: table - the table of UsrCli structures + * index - the current index of the evaluation + * host - the name of the host + * serv - the name of the service (port) + * Returns: How many UsrCli structures are connected with the current manage port. + */ + +int +eval_UsrCliPair(UsrCli** table, int index, char* host, char* serv) +{ + int i; + int result = 0; + assert(table != NULL); + assert(index >= 0); + for (i = 0; i < index; ++i) { + + if (UsrCli_get_manageHostName(table[i])) { + if (host) { + if (strcmp(UsrCli_get_listenHostName(table[i]), host)) { + continue; + } + } + else { + continue; + } + } + else { + if (host) { + continue; + } + } + + if (UsrCli_get_managePortName(table[i])) { + if (serv) { + if (strcmp(UsrCli_get_managePortName(table[i]), serv)) { + continue; + } + } + else { + continue; + } + } + else { + if (serv) { + continue; + } + } + + result++; + } + return result; +} diff --git a/src/server_eval.h b/src/server_eval.h new file mode 100644 index 0000000..a5471b1 --- /dev/null +++ b/src/server_eval.h @@ -0,0 +1,32 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "file.h" +#include "activefor.h" + +#ifndef _JS_SERVER_EVAL_H +#define _JS_SERVER_EVAL_H + +int eval_numofcon(ServerRealm*, int, int); +int eval_usernum(ConnectClient*, int); +int eval_UsrCliPair(UsrCli**, int, char*, char*); + +#endif + diff --git a/src/server_find.c b/src/server_find.c new file mode 100644 index 0000000..a2934a8 --- /dev/null +++ b/src/server_find.c @@ -0,0 +1,138 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <assert.h> +#include <string.h> + +#include "server_find.h" + +/* + * Function name: find_client + * Description: Returns the client number with free user slots. + * Arguments: ptr - the server realm + * mode - the strategy of client choosing + * usrclipair - the number of usrclipair + * Returns: The client number with free user slots. + */ + +int +find_client(ServerRealm* ptr, char mode, int usrclipair) +{ + int i; + assert(ptr != NULL); + switch(mode) { + case 1: { /* fill first client before go to next */ + for (i = 0; i < ServerRealm_get_clientsLimit(ptr); ++i) { + if ((ConnectClient_get_state(ServerRealm_get_clientsTable(ptr)[i]) == + CONNECTCLIENT_STATE_ACCEPTED) && + (ConnectClient_get_usrCliPair(ServerRealm_get_clientsTable(ptr)[i]) == usrclipair)) { + if (ConnectClient_get_connected(ServerRealm_get_clientsTable(ptr)[i]) < + ConnectClient_get_limit(ServerRealm_get_clientsTable(ptr)[i])) { + return i; + } + } + } + break; + } + default: { + return 0; + } + } + return 0; +} + +/* + * Function name: find_usernum + * Description: Finds the free user slot, fill it and returns its number. + * Arguments: ptr - the connected client + * usernum - the connection number on the afserver + * Returns: The user number in the connected client on the afserver side. + */ + +int +find_usernum(ConnectClient* ptr, int usernum) +{ + int i; + assert(ptr != NULL); + for (i = 0; i < ConnectClient_get_limit(ptr); ++i) { + if (ConnectClient_get_users(ptr)[i] == -1) { + ConnectClient_get_users(ptr)[i] = usernum; + return i; + } + } + return -1; +} + +/* + * Function name: find_previousFd + * Description: Finds the file descriptor bound previously to the given + * host:serv. + * Arguments: table - the table of UsrCli structures + * index - the current index of the search + * host - the name of the host + * serv - the name of the service (port) + * Returns: The previously bound file descriptor. + */ + +int +find_previousFd(UsrCli** table, int index, char* host, char* serv) +{ + int i; + assert(table != NULL); + assert(index >= 0); + for (i = 0; i < index; ++i) { + + if (UsrCli_get_manageHostName(table[i])) { + if (host) { + if (strcmp(UsrCli_get_listenHostName(table[i]), host)) { + continue; + } + } + else { + continue; + } + } + else { + if (host) { + continue; + } + } + + if (UsrCli_get_managePortName(table[i])) { + if (serv) { + if (strcmp(UsrCli_get_managePortName(table[i]), serv)) { + continue; + } + } + else { + continue; + } + } + else { + if (serv) { + continue; + } + } + + return UsrCli_get_manageFd(table[i]); + } + return -1; +} diff --git a/src/server_find.h b/src/server_find.h new file mode 100644 index 0000000..83ad4d4 --- /dev/null +++ b/src/server_find.h @@ -0,0 +1,32 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "file.h" + +#ifndef _JS_SERVER_FIND_H +#define _JS_SERVER_FIND_H + +int find_client(ServerRealm*, char, int); +int find_usernum(ConnectClient*, int); +int find_previousFd(UsrCli**, int, char*, char*); + +#endif + diff --git a/src/server_get.c b/src/server_get.c new file mode 100644 index 0000000..cd13a75 --- /dev/null +++ b/src/server_get.c @@ -0,0 +1,123 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "server_get.h" +#include <stdlib.h> +#include <errno.h> +#include <assert.h> + +/* + * Function name: get_new_socket + * Description: Returns new accepted socket. + * Arguments: sockfd - the file descriptor of the listening socket + * type - the type of the listening socket + * addr - pointer to sockaddr structure + * addrlen - pointer to the length of the sockaddr structure + * tunneltype - the type of the connection + * Returns: The new accepted socket. + */ + +int +get_new_socket(int sockfd, char type, struct sockaddr *addr, socklen_t *addrlen, char* tunneltype) +{ + int tmp; + int n, i; + + assert(addr != NULL); + assert(addrlen != NULL); + assert(tunneltype != NULL); + + switch (type) { + case 0: { + return accept(sockfd, addr, addrlen); + break; + } + case 1: { + i = 0; + while (i < 4) { + if ((n = read(sockfd, &tmp+i, 4-i)) != (4-i)) { + sleep(2); + if ((n > 0) && (n < 4)) { + i += n; + continue; + } + if ((n == -1) && (errno == EAGAIN)) { + continue; + } + return -1; + } + else { + break; + } + } + i = 0; + while (i < 1) { + if ((n = read(sockfd, tunneltype+i, 1-i)) != (1-i)) { + if ((n == -1) && (errno == EAGAIN)) { + continue; + } + return -1; + } + else { + break; + } + } + i = 0; + while (i < 4) { + if ((n = read(sockfd, addrlen+i, 4-i)) != (4-i)) { + if ((n > 0) && (n < 4)) { + i += n; + continue; + } + if ((n == -1) && (errno == EAGAIN)) { + continue; + } + return -1; + } + else { + break; + } + } + i = 0; + while (i < *addrlen) { + if ((n = read(sockfd, addr+i, (*addrlen)-i)) != ((*addrlen)-i)) { + if ((n > 0) && (n < *addrlen)) { + i += n; + continue; + } + if ((n == -1) && (errno == EAGAIN)) { + continue; + } + return -1; + } + else { + break; + } + } + return tmp; + break; + } + default: { + return -1; + } + } +} diff --git a/src/server_get.h b/src/server_get.h new file mode 100644 index 0000000..2ad2656 --- /dev/null +++ b/src/server_get.h @@ -0,0 +1,31 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_SERVER_GET_H +#define _JS_SERVER_GET_H + +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> + +int get_new_socket(int sockfd, char type, struct sockaddr *addr, socklen_t *addrlen, char* tunneltype); + +#endif + diff --git a/src/server_realm_struct.c b/src/server_realm_struct.c new file mode 100644 index 0000000..c816ae3 --- /dev/null +++ b/src/server_realm_struct.c @@ -0,0 +1,1471 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "string_functions.h" +#include "server_realm_struct.h" + +/* + * Function name: ServerRealm_new + * Description: Create and initialize new ServerRealm structure. + * Returns: Pointer to newly created ServerRealm structure. + */ + +ServerRealm* +ServerRealm_new() +{ + ServerRealm* tmp = calloc(1, sizeof(ServerRealm)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + tmp->password[0] = 1; + tmp->password[1] = 2; + tmp->password[2] = 3; + tmp->password[3] = 4; + return tmp; +} + +/* + * Function name: ServerRealm_free + * Description: Free the memory allocated for ServerRealm structure. + * Arguments: sr - pointer to pointer to ServerRealm structure + */ + +void +ServerRealm_free(ServerRealm** sr) +{ + int i; + assert(sr != NULL); + if (sr == NULL) { + return; + } + assert((*sr) != NULL); + if ((*sr) == NULL) { + return; + } + if ((*sr)->hostName) { + free((*sr)->hostName); + (*sr)->hostName = NULL; + } + if ((*sr)->sUsersLimit) { + free((*sr)->sUsersLimit); + (*sr)->sUsersLimit = NULL; + } + if ((*sr)->sClientsLimit) { + free((*sr)->sClientsLimit); + (*sr)->sClientsLimit = NULL; + } + if ((*sr)->sRaClientsLimit) { + free((*sr)->sRaClientsLimit); + (*sr)->sRaClientsLimit = NULL; + } + if ((*sr)->sUsersPerClient) { + free((*sr)->sUsersPerClient); + (*sr)->sUsersPerClient = NULL; + } + if ((*sr)->sClientMode) { + free((*sr)->sClientMode); + (*sr)->sClientMode = NULL; + } + if ((*sr)->sTimeout) { + free((*sr)->sTimeout); + (*sr)->sTimeout = NULL; + } + if ((*sr)->realmName) { + free((*sr)->realmName); + (*sr)->realmName = NULL; + } + if ((*sr)->clientAddress) { + free((*sr)->clientAddress); + (*sr)->clientAddress = NULL; + } + if ((*sr)->usersTable) { + for (i = 0; i < (*sr)->usersLimit; ++i) { + if ((*sr)->usersTable[i]) { + ConnectUser_free(&((*sr)->usersTable[i])); + } + } + free((*sr)->usersTable); + (*sr)->usersTable = NULL; + } + if ((*sr)->clientsTable) { + for (i = 0; i < (*sr)->clientsLimit; ++i) { + if ((*sr)->clientsTable[i]) { + ConnectClient_free(&((*sr)->clientsTable[i])); + } + } + free((*sr)->clientsTable); + (*sr)->clientsTable = NULL; + } + if ((*sr)->raClientsTable) { + for (i = 0; i < (*sr)->raClientsLimit; ++i) { + if ((*sr)->raClientsTable[i]) { + ConnectClient_free(&((*sr)->raClientsTable[i])); + } + } + free((*sr)->raClientsTable); + (*sr)->raClientsTable = NULL; + } + if ((*sr)->usersClientsTable) { + for (i = 0; i < (*sr)->userClientPairs; ++i) { + if ((*sr)->usersClientsTable[i]) { + UsrCli_free(&((*sr)->usersClientsTable[i])); + } + } + free((*sr)->usersClientsTable); + (*sr)->usersClientsTable = NULL; + } + free((*sr)); + (*sr) = NULL; +} + +/* + * Function name: ServerRealm_set_hostName + * Description: Set realm's host name. + * Arguments: sr - pointer to ServerRealm structure + * hostName - realm's host name + */ + +void +ServerRealm_set_hostName(ServerRealm* sr, char* hostName) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + string_cp(&(sr->hostName), hostName); +} + +/* + * Function name: ServerRealm_set_sUsersLimit + * Description: Set users limit description. + * Arguments: sr - pointer to ServerRealm structure + * sUsersLimit - users limit description + */ + +void +ServerRealm_set_sUsersLimit(ServerRealm* sr, char* sUsersLimit) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + string_cp(&(sr->sUsersLimit), sUsersLimit); +} + +/* + * Function name: ServerRealm_set_sClientsLimit + * Description: Set clients limit description. + * Arguments: sr - pointer to ServerRealm structure + * sClientsLimit - clients limit description + */ + +void +ServerRealm_set_sClientsLimit(ServerRealm* sr, char* sClientsLimit) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + string_cp(&(sr->sClientsLimit), sClientsLimit); +} + +/* + * Function name: ServerRealm_set_sRaClientsLimit + * Description: Set raClients limit description. + * Arguments: sr - pointer to ServerRealm structure + * sRaClientsLimit - raClients limit description + */ + +void +ServerRealm_set_sRaClientsLimit(ServerRealm* sr, char* sRaClientsLimit) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + string_cp(&(sr->sRaClientsLimit), sRaClientsLimit); +} + +/* + * Function name: ServerRealm_set_sUsersPerClient + * Description: Set users per client description. + * Arguments: sr - pointer to ServerRealm structure + * sUsersPerClient - users per client description + */ + +void +ServerRealm_set_sUsersPerClient(ServerRealm* sr, char* sUsersPerClient) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + string_cp(&(sr->sUsersPerClient), sUsersPerClient); +} + +/* + * Function name: ServerRealm_set_sClientMode + * Description: Set client mode description. + * Arguments: sr - pointer to ServerRealm structure + * sClientMode - client mode description + */ + +void +ServerRealm_set_sClientMode(ServerRealm* sr, char* sClientMode) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + string_cp(&(sr->sClientMode), sClientMode); +} + +/* + * Function name: ServerRealm_set_sTimeout + * Description: Set timeout value description. + * Arguments: sr - pointer to ServerRealm structure + * sTimeout - timeout value description + */ + +void +ServerRealm_set_sTimeout(ServerRealm* sr, char* sTimeout) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + string_cp(&(sr->sTimeout), sTimeout); +} + +/* + * Function name: ServerRealm_set_sMaxIdle + * Description: Sets max idle value description. + * Arguments: sr - pointer to ServerRealm structure + * sMaxIdle - max idle value description + */ + +void +ServerRealm_set_sMaxIdle(ServerRealm* sr, char* sMaxIdle) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + string_cp(&(sr->sMaxIdle), sMaxIdle); +} + +/* + * Function name: ServerRealm_set_realmName + * Description: Set realm's name. + * Arguments: sr - pointer to ServerRealm structure + * realmName - realm's name + */ + +void +ServerRealm_set_realmName(ServerRealm* sr, char* realmName) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + string_cp(&(sr->realmName), realmName); +} + +/* + * Function name: ServerRealm_set_password + * Description: Set realm's password. + * Arguments: sr - pointer to ServerRealm structure + * password - realm's password + */ + +void +ServerRealm_set_password(ServerRealm* sr, unsigned char* password) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + memcpy(sr->password, password, 4); +} + +/* + * Function name: ServerRealm_set_connectedUsers + * Description: Set number of connected users. + * Arguments: sr - pointer to ServerRealm structure + * connectedUsers - number of connected users + */ + +void +ServerRealm_set_connectedUsers(ServerRealm* sr, int connectedUsers) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->connectedUsers = connectedUsers; +} + +/* + * Function name: ServerRealm_set_usersLimit + * Description: Set limit of connected users. + * Arguments: sr - pointer to ServerRealm structure + * usersLimit - limit of connected users + */ + +void +ServerRealm_set_usersLimit(ServerRealm* sr, int usersLimit) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->usersLimit = usersLimit; +} + +/* + * Function name: ServerRealm_set_connectedClients + * Description: Set number of connected clients. + * Arguments: sr - pointer to ServerRealm structure + * connectedClients - number of connected clients + */ + +void +ServerRealm_set_connectedClients(ServerRealm* sr, int connectedClients) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->connectedClients = connectedClients; +} + +/* + * Function name: ServerRealm_set_clientsLimit + * Description: Set limit of connected clients. + * Arguments: sr - pointer to ServerRealm structure + * clientsLimit - limit of connected clients + */ + +void +ServerRealm_set_clientsLimit(ServerRealm* sr, int clientsLimit) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->clientsLimit = clientsLimit; +} + +/* + * Function name: ServerRealm_set_connectedRaClients + * Description: Set number of connected raClients. + * Arguments: sr - pointer to ServerRealm structure + * connectedRaClients - number of connected raClients + */ + +void +ServerRealm_set_connectedRaClients(ServerRealm* sr, int connectedRaClients) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->connectedRaClients = connectedRaClients; +} + +/* + * Function name: ServerRealm_set_raClientsLimit + * Description: Set limit of connected raClients. + * Arguments: sr - pointer to ServerRealm structure + * raClientsLimit - limit of connected raClients + */ + +void +ServerRealm_set_raClientsLimit(ServerRealm* sr, int raClientsLimit) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->raClientsLimit = raClientsLimit; +} + +/* + * Function name: ServerRealm_set_usersPerClient + * Description: Set users per client limit. + * Arguments: sr - pointer to ServerRealm structure + * usersPerClient - users per client limit + */ + +void +ServerRealm_set_usersPerClient(ServerRealm* sr, int usersPerClient) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->usersPerClient = usersPerClient; +} + +/* + * Function name: ServerRealm_set_timeout + * Description: Set timeout value. + * Arguments: sr - pointer to ServerRealm structure + * timeout - timeout value + */ + +void +ServerRealm_set_timeout(ServerRealm* sr, int timeout) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->timeout = timeout; +} + +/* + * Function name: ServerRealm_set_maxIdle + * Description: Sets mas idle value. + * Arguments: sr - pointer to ServerRealm structure + * maxIdle - max idle value + */ + +void +ServerRealm_set_maxIdle(ServerRealm* sr, int maxIdle) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->maxIdle = maxIdle; +} + +/* + * Function name: ServerRealm_set_clientMode + * Description: Set client mode. + * Arguments: sr - pointer to ServerRealm structure + * clientMode - client mode + */ + +void +ServerRealm_set_clientMode(ServerRealm* sr, int clientMode) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->clientMode = clientMode; +} + +/* + * Function name: ServerRealm_set_userClientPairs + * Description: Set user-client pairs amount. + * Arguments: sr - pointer to ServerRealm structure + * userClientPairs - user-client pairs amount + */ + +void +ServerRealm_set_userClientPairs(ServerRealm* sr, int userClientPairs) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->userClientPairs = userClientPairs; +} + +/* + * Function name: ServerRealm_set_clientsCounter + * Description: Set clients counter state. + * Arguments: sr - pointer to ServerRealm structure + * clientsCounter - clients counter state + */ + +void +ServerRealm_set_clientsCounter(ServerRealm* sr, int clientsCounter) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->clientsCounter = clientsCounter; +} + +/* + * Function name: ServerRealm_set_usersCounter + * Description: Set users counter state. + * Arguments: sr - pointer to ServerRealm structure + * usersCounter - users counter state + */ + +void +ServerRealm_set_usersCounter(ServerRealm* sr, int usersCounter) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->usersCounter = usersCounter; +} + +/* + * Function name: ServerRealm_set_realmType + * Description: Set type of the realm. + * Arguments: sr - pointer to ServerRealm structure + * realmType - type of the realm + */ + +void +ServerRealm_set_realmType(ServerRealm* sr, char realmType) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->realmType = realmType; +} + +/* + * Function name: ServerRealm_set_tunnelType + * Description: Set type of the tunnel. + * Arguments: sr - pointer to ServerRealm structure + * tunnelType - type of the tunnel + */ + +void +ServerRealm_set_tunnelType(ServerRealm* sr, char tunnelType) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->tunnelType = tunnelType; +} + +/* + * Function name: ServerRealm_set_dnsLookupsOn + * Description: Set dns lookups functionality on/off. + * Arguments: sr - pointer to ServerRealm structure + * dnsLookupsOn - dns lookups functionality on/off + */ + +void +ServerRealm_set_dnsLookupsOn(ServerRealm* sr, char dnsLookupsOn) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->dnsLookupsOn = dnsLookupsOn; +} + +/* + * Function name: ServerRealm_set_basePortOn + * Description: Set base port functionality on/off. + * Arguments: sr - pointer to ServerRealm structure + * basePortOn - base port functionality on/off + */ + +void +ServerRealm_set_basePortOn(ServerRealm* sr, char basePortOn) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->basePortOn = basePortOn; +} + +/* + * Function name: ServerRealm_set_auditOn + * Description: Set audit functionality on/off. + * Arguments: sr - pointer to ServerRealm structure + * auditOn - audit functionality on/off + */ + +void +ServerRealm_set_auditOn(ServerRealm* sr, char auditOn) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->auditOn = auditOn; +} + +/* + * Function name: ServerRealm_set_addressLength + * Description: Set client's address length. + * Arguments: sr - pointer to ServerRealm structure + * addressLength - client's address length + */ + +void +ServerRealm_set_addressLength(ServerRealm* sr, socklen_t addressLength) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + sr->addressLength = addressLength; +} + +/* + * Function name: ServerRealm_set_clientAddress + * Description: Set client's network address. + * Arguments: sr - pointer to ServerRealm structure + * clientAddress - client's network address + */ + +void +ServerRealm_set_clientAddress(ServerRealm* sr, struct sockaddr* clientAddress) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + if (sr->clientAddress) { + free(sr->clientAddress); + sr->clientAddress = NULL; + } + sr->clientAddress = clientAddress; +} + +/* + * Function name: ServerRealm_set_usersTable + * Description: Set table of users. + * Arguments: sr - pointer to ServerRealm structure + * usersTable - table of users + */ + +void +ServerRealm_set_usersTable(ServerRealm* sr, ConnectUser** usersTable) +{ + int i; + assert(sr != NULL); + if (sr == NULL) { + return; + } + if (sr->usersTable) { + for (i = 0; i < sr->usersLimit; ++i) { + if (sr->usersTable[i]) { + ConnectUser_free(&(sr->usersTable[i])); + } + } + free(sr->usersTable); + sr->usersTable = NULL; + } + sr->usersTable = usersTable; +} + +/* + * Function name: ServerRealm_set_clientsTable + * Description: Set table of clients. + * Arguments: sr - pointer to ServerRealm structure + * clientsTable - table of clients + */ + +void +ServerRealm_set_clientsTable(ServerRealm* sr, ConnectClient** clientsTable) +{ + int i; + assert(sr != NULL); + if (sr == NULL) { + return; + } + if (sr->clientsTable) { + for (i = 0; i < sr->clientsLimit; ++i) { + if (sr->clientsTable[i]) { + ConnectClient_free(&(sr->clientsTable[i])); + } + } + free(sr->clientsTable); + sr->clientsTable = NULL; + } + sr->clientsTable = clientsTable; +} + +/* + * Function name: ServerRealm_set_raClientsTable + * Description: Set table of raClients. + * Arguments: sr - pointer to ServerRealm structure + * raClientsTable - table of raClients + */ + +void +ServerRealm_set_raClientsTable(ServerRealm* sr, ConnectClient** raClientsTable) +{ + int i; + assert(sr != NULL); + if (sr == NULL) { + return; + } + if (sr->raClientsTable) { + for (i = 0; i < sr->raClientsLimit; ++i) { + if (sr->raClientsTable[i]) { + ConnectClient_free(&(sr->raClientsTable[i])); + } + } + free(sr->raClientsTable); + sr->raClientsTable = NULL; + } + sr->raClientsTable = raClientsTable; +} + +/* + * Function name: ServerRealm_set_usersClientsTable + * Description: Set table of user-client pairs. + * Arguments: sr - pointer to ServerRealm structure + * usersClientsTable - table of user-client pairs + */ + +void +ServerRealm_set_usersClientsTable(ServerRealm* sr, UsrCli** usersClientsTable) +{ + int i; + assert(sr != NULL); + if (sr == NULL) { + return; + } + if (sr->usersClientsTable) { + for (i = 0; i < sr->userClientPairs; ++i) { + if (sr->usersClientsTable[i]) { + UsrCli_free(&(sr->usersClientsTable[i])); + } + } + free(sr->usersClientsTable); + sr->usersClientsTable = NULL; + } + sr->usersClientsTable = usersClientsTable; +} + +/* + * Function name: ServerRealm_get_hostName + * Description: Get realm's host name. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Realm's host name. + */ + +char* +ServerRealm_get_hostName(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->hostName; +} + +/* + * Function name: ServerRealm_get_sUsersLimit + * Description: Get users limit description. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Users limit description. + */ + +char* +ServerRealm_get_sUsersLimit(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->sUsersLimit; +} + +/* + * Function name: ServerRealm_get_sClientsLimit + * Description: Get clients limit description. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Clients limit description. + */ + +char* +ServerRealm_get_sClientsLimit(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->sClientsLimit; +} + +/* + * Function name: ServerRealm_get_sRaClientsLimit + * Description: Get raClients limit description. + * Arguments: sr - pointer to ServerRealm structure + * Returns: RaClients limit description. + */ + +char* +ServerRealm_get_sRaClientsLimit(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->sRaClientsLimit; +} + +/* + * Function name: ServerRealm_get_sUsersPerClient + * Description: Get users per client description. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Users per client description. + */ + +char* +ServerRealm_get_sUsersPerClient(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->sUsersPerClient; +} + +/* + * Function name: ServerRealm_get_sClientMode + * Description: Get client mode description. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Client mode description. + */ + +char* +ServerRealm_get_sClientMode(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->sClientMode; +} + +/* + * Function name: ServerRealm_get_sTimeout + * Description: Get timeout value description. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Timeout value description. + */ + +char* +ServerRealm_get_sTimeout(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->sTimeout; +} + +/* + * Function name: ServerRealm_get_sMaxIdle + * Description: Gets max idle value description. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Max idle value description. + */ + +char* +ServerRealm_get_sMaxIdle(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->sMaxIdle; +} + +/* + * Function name: ServerRealm_get_realmName + * Description: Get realm's name. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Realm's name. + */ + +char* +ServerRealm_get_realmName(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->realmName; +} + +/* + * Function name: ServerRealm_get_password + * Description: Get realm's password. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Realm's password. + */ + +unsigned char* +ServerRealm_get_password(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->password; +} + +/* + * Function name: ServerRealm_get_connectedUsers + * Description: Get number of connected users. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Number of connected users. + */ + +int +ServerRealm_get_connectedUsers(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return -1; + } + return sr->connectedUsers; +} + +/* + * Function name: ServerRealm_get_usersLimit + * Description: Get limit of connected users. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Limit of connected users. + */ + +int +ServerRealm_get_usersLimit(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return -1; + } + return sr->usersLimit; +} + +/* + * Function name: ServerRealm_get_connectedClients + * Description: Get number of connected clients. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Number of connected clients. + */ + +int +ServerRealm_get_connectedClients(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return -1; + } + return sr->connectedClients; +} + +/* + * Function name: ServerRealm_get_clientsLimit + * Description: Get limit of connected clients. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Limit of connected clients. + */ + +int +ServerRealm_get_clientsLimit(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return -1; + } + return sr->clientsLimit; +} + +/* + * Function name: ServerRealm_get_connectedRaClients + * Description: Get number of connected raClients. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Number of connected raClients. + */ + +int +ServerRealm_get_connectedRaClients(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return -1; + } + return sr->connectedRaClients; +} + +/* + * Function name: ServerRealm_get_raClientsLimit + * Description: Get limit of connected raClients. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Limit of connected raClients. + */ + +int +ServerRealm_get_raClientsLimit(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return -1; + } + return sr->raClientsLimit; +} + +/* + * Function name: ServerRealm_get_usersPerClient + * Description: Get users per client limit. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Users per client limit. + */ + +int +ServerRealm_get_usersPerClient(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return -1; + } + return sr->usersPerClient; +} + +/* + * Function name: ServerRealm_get_timeout + * Description: Get timeout value. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Timeout value. + */ + +int +ServerRealm_get_timeout(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->timeout; +} + +/* + * Function name: ServerRealm_get_maxIdle + * Description: Gets max idle value. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Max idle value. + */ + +int +ServerRealm_get_maxIdle(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->maxIdle; +} + +/* + * Function name: ServerRealm_get_clientMode + * Description: Get client mode. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Client mode. + */ + +int +ServerRealm_get_clientMode(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->clientMode; +} + +/* + * Function name: ServerRealm_get_userClientPairs + * Description: Get user-client pairs amount. + * Arguments: sr - pointer to ServerRealm structure + * Returns: User-client pairs amount. + */ + +int +ServerRealm_get_userClientPairs(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->userClientPairs; +} + +/* + * Function name: ServerRealm_get_clientsCounter + * Description: Get clients counter state. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Clients counter state. + */ + +int +ServerRealm_get_clientsCounter(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return -1; + } + return sr->clientsCounter; +} + +/* + * Function name: ServerRealm_get_usersCounter + * Description: Get users counter state. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Users counter state. + */ + +int +ServerRealm_get_usersCounter(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return -1; + } + return sr->usersCounter; +} + +/* + * Function name: ServerRealm_get_realmType + * Description: Get type of the realm. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Type of the realm. + */ + +char +ServerRealm_get_realmType(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->realmType; +} + +/* + * Function name: ServerRealm_get_tunnelType + * Description: Get type of the tunnel. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Type of the tunnel. + */ + +char +ServerRealm_get_tunnelType(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->tunnelType; +} + +/* + * Function name: ServerRealm_get_dnsLookupsOn + * Description: Get dns lookups functionality on/off. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Dns lookups functionality on/off. + */ + +char +ServerRealm_get_dnsLookupsOn(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->dnsLookupsOn; +} + +/* + * Function name: ServerRealm_get_basePortOn + * Description: Get base port functionality on/off. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Base port functionality on/off. + */ + +char +ServerRealm_get_basePortOn(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->basePortOn; +} + +/* + * Function name: ServerRealm_get_auditOn + * Description: Get audit functionality on/off. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Audit functionality on/off. + */ + +char +ServerRealm_get_auditOn(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->auditOn; +} + +/* + * Function name: ServerRealm_get_addressLength + * Description: Get client's address length. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Client's address length. + */ + +socklen_t +ServerRealm_get_addressLength(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return 0; + } + return sr->addressLength; +} + +/* + * Function name: ServerRealm_get_clientAddress + * Description: Get client's network address. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Client's network address. + */ + +struct sockaddr* +ServerRealm_get_clientAddress(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->clientAddress; +} + +/* + * Function name: ServerRealm_get_usersTable + * Description: Get table of users. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Table of users. + */ + +ConnectUser** +ServerRealm_get_usersTable(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->usersTable; +} + +/* + * Function name: ServerRealm_get_clientsTable + * Description: Get table of clients. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Table of clients. + */ + +ConnectClient** +ServerRealm_get_clientsTable(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->clientsTable; +} + +/* + * Function name: ServerRealm_get_raClientsTable + * Description: Get table of raClients. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Table of raClients. + */ + +ConnectClient** +ServerRealm_get_raClientsTable(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->raClientsTable; +} + +/* + * Function name: ServerRealm_get_usersClientsTable + * Description: Get table of user-client pairs. + * Arguments: sr - pointer to ServerRealm structure + * Returns: Table of user-client pairs. + */ + +UsrCli** +ServerRealm_get_usersClientsTable(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return NULL; + } + return sr->usersClientsTable; +} + +/* + * Function name: ServerRealm_increase_connectedUsers + * Description: Increase number of connected users. + * Arguments: sr - pointer to ServerRealm structure + */ + +void +ServerRealm_increase_connectedUsers(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + ServerRealm_set_connectedUsers(sr, ServerRealm_get_connectedUsers(sr) + 1); +} + +/* + * Function name: ServerRealm_decrease_connectedUsers + * Description: Decrease number of connected users. + * Arguments: sr - pointer to ServerRealm structure + */ + +void +ServerRealm_decrease_connectedUsers(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + ServerRealm_set_connectedUsers(sr, ServerRealm_get_connectedUsers(sr) - 1); +} + +/* + * Function name: ServerRealm_increase_connectedClients + * Description: Increase number of connected clients. + * Arguments: sr - pointer to ServerRealm structure + */ + +void +ServerRealm_increase_connectedClients(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + ServerRealm_set_connectedClients(sr, ServerRealm_get_connectedClients(sr) + 1); +} + +/* + * Function name: ServerRealm_decrease_connectedClients + * Description: Decrease number of connected clients. + * Arguments: sr - pointer to ServerRealm structure + */ + +void +ServerRealm_decrease_connectedClients(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + ServerRealm_set_connectedClients(sr, ServerRealm_get_connectedClients(sr) - 1); +} + +/* + * Function name: ServerRealm_increase_connectedRaClients + * Description: Increase number of connected raClients. + * Arguments: sr - pointer to ServerRealm structure + */ + +void +ServerRealm_increase_connectedRaClients(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + ServerRealm_set_connectedRaClients(sr, ServerRealm_get_connectedRaClients(sr) + 1); +} + +/* + * Function name: ServerRealm_decrease_connectedRaClients + * Description: Decrease number of connected raClients. + * Arguments: sr - pointer to ServerRealm structure + */ + +void +ServerRealm_decrease_connectedRaClients(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + ServerRealm_set_connectedRaClients(sr, ServerRealm_get_connectedRaClients(sr) - 1); +} + +/* + * Function name: ServerRealm_increase_usersCounter + * Description: Increase users counter state. + * Arguments: sr - pointer to ServerRealm structure + */ + +void +ServerRealm_increase_usersCounter(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + ServerRealm_set_usersCounter(sr, ServerRealm_get_usersCounter(sr) + 1); +} + +/* + * Function name: ServerRealm_increase_clientsCounter + * Description: Increase clients counter state. + * Arguments: sr - pointer to ServerRealm structure + */ + +void +ServerRealm_increase_clientsCounter(ServerRealm* sr) +{ + assert(sr != NULL); + if (sr == NULL) { + return; + } + ServerRealm_set_clientsCounter(sr, ServerRealm_get_clientsCounter(sr) + 1); +} diff --git a/src/server_realm_struct.h b/src/server_realm_struct.h new file mode 100644 index 0000000..e057c99 --- /dev/null +++ b/src/server_realm_struct.h @@ -0,0 +1,147 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" + +#ifndef _JS_SERVER_REALM_STRUCT_H +#define _JS_SERVER_REALM_STRUCT_H + +typedef struct { + char* hostName; + char* sUsersLimit; + char* sClientsLimit; + char* sRaClientsLimit; + char* sUsersPerClient; + char* sClientMode; + char* sTimeout; + char* sMaxIdle; + char* realmName; + unsigned char password[4]; + int connectedUsers; + int usersLimit; + int connectedClients; + int clientsLimit; + int connectedRaClients; + int raClientsLimit; + int usersPerClient; + int timeout; + int maxIdle; + int clientMode; + int userClientPairs; + int clientsCounter; + int usersCounter; + char realmType; + char tunnelType; + char dnsLookupsOn; + char basePortOn; + char auditOn; + socklen_t addressLength; + struct sockaddr* clientAddress; + ConnectUser** usersTable; + ConnectClient** clientsTable; + ConnectClient** raClientsTable; + UsrCli** usersClientsTable; +} ServerRealm; + +/* 'constructor' */ +ServerRealm* ServerRealm_new(); +/* 'destructor' */ +void ServerRealm_free(ServerRealm** sr); +/* setters */ +void ServerRealm_set_hostName(ServerRealm* sr, char* hostName); +void ServerRealm_set_sUsersLimit(ServerRealm* sr, char* sUsersLimit); +void ServerRealm_set_sClientsLimit(ServerRealm* sr, char* sClientsLimit); +void ServerRealm_set_sRaClientsLimit(ServerRealm* sr, char* sRaClientsLimit); +void ServerRealm_set_sUsersPerClient(ServerRealm* sr, char* sUsersPerClient); +void ServerRealm_set_sClientMode(ServerRealm* sr, char* sClientMode); +void ServerRealm_set_sTimeout(ServerRealm* sr, char* sTimeout); +void ServerRealm_set_sMaxIdle(ServerRealm* sr, char* sMaxIdle); +void ServerRealm_set_realmName(ServerRealm* sr, char* realmName); +void ServerRealm_set_password(ServerRealm* sr, unsigned char* password); +void ServerRealm_set_connectedUsers(ServerRealm* sr, int connectedUsers); +void ServerRealm_set_usersLimit(ServerRealm* sr, int usersLimit); +void ServerRealm_set_connectedClients(ServerRealm* sr, int connectedClients); +void ServerRealm_set_clientsLimit(ServerRealm* sr, int clientsLimit); +void ServerRealm_set_connectedRaClients(ServerRealm* sr, int connectedRaClients); +void ServerRealm_set_raClientsLimit(ServerRealm* sr, int raClientsLimit); +void ServerRealm_set_usersPerClient(ServerRealm* sr, int usersPerClient); +void ServerRealm_set_timeout(ServerRealm* sr, int timeout); +void ServerRealm_set_maxIdle(ServerRealm* sr, int maxIdle); +void ServerRealm_set_clientMode(ServerRealm* sr, int clientMode); +void ServerRealm_set_userClientPairs(ServerRealm* sr, int userClientPairs); +void ServerRealm_set_clientsCounter(ServerRealm* sr, int clientsCounter); +void ServerRealm_set_usersCounter(ServerRealm* sr, int usersCounter); +void ServerRealm_set_realmType(ServerRealm* sr, char realmType); +void ServerRealm_set_tunnelType(ServerRealm* sr, char tunnelType); +void ServerRealm_set_dnsLookupsOn(ServerRealm* sr, char dnsLookupsOn); +void ServerRealm_set_basePortOn(ServerRealm* sr, char basePortOn); +void ServerRealm_set_auditOn(ServerRealm* sr, char auditOn); +void ServerRealm_set_addressLength(ServerRealm* sr, socklen_t addressLength); +void ServerRealm_set_clientAddress(ServerRealm* sr, struct sockaddr* clientAddress); +void ServerRealm_set_usersTable(ServerRealm* sr, ConnectUser** usersTable); +void ServerRealm_set_clientsTable(ServerRealm* sr, ConnectClient** clientsTable); +void ServerRealm_set_raClientsTable(ServerRealm* sr, ConnectClient** raClientsTable); +void ServerRealm_set_usersClientsTable(ServerRealm* sr, UsrCli** usersClientsTable); +/* getters */ +char* ServerRealm_get_hostName(ServerRealm* sr); +char* ServerRealm_get_sUsersLimit(ServerRealm* sr); +char* ServerRealm_get_sClientsLimit(ServerRealm* sr); +char* ServerRealm_get_sRaClientsLimit(ServerRealm* sr); +char* ServerRealm_get_sUsersPerClient(ServerRealm* sr); +char* ServerRealm_get_sClientMode(ServerRealm* sr); +char* ServerRealm_get_sTimeout(ServerRealm* sr); +char* ServerRealm_get_sMaxIdle(ServerRealm* sr); +char* ServerRealm_get_realmName(ServerRealm* sr); +unsigned char* ServerRealm_get_password(ServerRealm* sr); +int ServerRealm_get_connectedUsers(ServerRealm* sr); +int ServerRealm_get_usersLimit(ServerRealm* sr); +int ServerRealm_get_connectedClients(ServerRealm* sr); +int ServerRealm_get_clientsLimit(ServerRealm* sr); +int ServerRealm_get_connectedRaClients(ServerRealm* sr); +int ServerRealm_get_raClientsLimit(ServerRealm* sr); +int ServerRealm_get_usersPerClient(ServerRealm* sr); +int ServerRealm_get_timeout(ServerRealm* sr); +int ServerRealm_get_maxIdle(ServerRealm* sr); +int ServerRealm_get_clientMode(ServerRealm* sr); +int ServerRealm_get_userClientPairs(ServerRealm* sr); +int ServerRealm_get_clientsCounter(ServerRealm* sr); +int ServerRealm_get_usersCounter(ServerRealm* sr); +char ServerRealm_get_realmType(ServerRealm* sr); +char ServerRealm_get_tunnelType(ServerRealm* sr); +char ServerRealm_get_dnsLookupsOn(ServerRealm* sr); +char ServerRealm_get_basePortOn(ServerRealm* sr); +char ServerRealm_get_auditOn(ServerRealm* sr); +socklen_t ServerRealm_get_addressLength(ServerRealm* sr); +struct sockaddr* ServerRealm_get_clientAddress(ServerRealm* sr); +ConnectUser** ServerRealm_get_usersTable(ServerRealm* sr); +ConnectClient** ServerRealm_get_clientsTable(ServerRealm* sr); +ConnectClient** ServerRealm_get_raClientsTable(ServerRealm* sr); +UsrCli** ServerRealm_get_usersClientsTable(ServerRealm* sr); +/* other */ +void ServerRealm_increase_connectedUsers(ServerRealm* sr); +void ServerRealm_decrease_connectedUsers(ServerRealm* sr); +void ServerRealm_increase_connectedClients(ServerRealm* sr); +void ServerRealm_decrease_connectedClients(ServerRealm* sr); +void ServerRealm_increase_connectedRaClients(ServerRealm* sr); +void ServerRealm_decrease_connectedRaClients(ServerRealm* sr); +void ServerRealm_increase_usersCounter(ServerRealm* sr); +void ServerRealm_increase_clientsCounter(ServerRealm* sr); + +#endif diff --git a/src/server_remoteadmin.c b/src/server_remoteadmin.c new file mode 100644 index 0000000..1d10520 --- /dev/null +++ b/src/server_remoteadmin.c @@ -0,0 +1,762 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <assert.h> + +#include "server_remoteadmin.h" + +static char newmessage; + +/* + * Function name: parse_int + * Description: This function parses the string as an integer and updates the buffer's + * parse pointer. + * Arguments: buff - string to parse + * ret - buffer's parse pointer + * Returns: Parsed integer value or -1, if something went wrong. + */ + +static int +parse_int(unsigned char* buff, int* ret) +{ + int intarg, i; + char guard; + + assert(buff != NULL); + assert(ret != NULL); + + if (((i = sscanf((char*) &buff[*ret], "%d%c", &intarg, &guard)) == 2) || (i == 1)) { + if (i == 1) { + guard = ' '; + } + if (!isspace(guard)) { + return -1; + } + guard = 0; + i = (*ret); + while (buff[i] != 0) { + if (guard == 0) { + if (isspace(buff[i])) { + guard = 1; + } + } + else { + if (!isspace(buff[i])) { + break; + } + } + ++i; + } + if (buff[i] == '.') { + ++i; + } + (*ret) = i; + return intarg; + } + else { + return -1; + } +} + +/* + * Function name: parse_cmd + * Description: This function parses the string as a command and updates the buffer's + * parse pointer. + * Arguments: buff - string to parse + * ret - buffer's parse pointer + * Returns: Parsed command number or 0, if something went wrong. + */ + +static int +parse_cmd(unsigned char* buff, int* ret) +{ + int i, j, state; + char cmd[31]; + + assert(buff != NULL); + assert(ret != NULL); + + i = j = state = 0; + newmessage = 1; + while (buff[i] != 0) { + if (state == 1) { + if (isspace(buff[i])) { + break; + } + else { + if (j == 30) { + return 0; + } + cmd[j] = buff[i]; + ++j; + } + } + if (state == 0) { + if (!isspace(buff[i])) { + cmd[j] = buff[i]; + j = 1; + state = 1; + } + } + ++i; + } + if (state == 0) { + return 0; + } + while (isspace(buff[i])) { + ++i; + } + if (buff[i] == '.') { + ++i; + } + (*ret) = i; + cmd[j] = 0; + if (strcmp(cmd, "help") == 0) { return 1; } + if (strcmp(cmd, "lcmd") == 0) { return 2; } + if (strcmp(cmd, "info") == 0) { return 3; } + if (strcmp(cmd, "rshow") == 0) { return 4; } + if (strcmp(cmd, "cshow") == 0) { return 5; } + if (strcmp(cmd, "ushow") == 0) { return 6; } + if (strcmp(cmd, "quit") == 0) { return 7; } + if (strcmp(cmd, "timeout") == 0) { return 8; } + if (strcmp(cmd, "audit") == 0) { return 9; } + if (strcmp(cmd, "dnslookups") == 0) { return 10; } + if (strcmp(cmd, "dateformat") == 0) { return 11; } + if (strcmp(cmd, "kuser") == 0) { return 12; } + if (strcmp(cmd, "kclient") == 0) { return 13; } + return 0; +} + +/* + * Function name: send_adm_message + * Description: Sends the message via the network. + * Arguments: type - the type of the connection + * master - pointer to SslFd structure + * buff - the message to send + * st - the result of the command + */ + +static void +send_adm_message(char type, SslFd* master, unsigned char* buff, unsigned char st) +{ + int n; + + assert(master != NULL); + assert(buff != NULL); + + if (!newmessage) { + n = strlen((char*) &buff[5]); + } + else { + n = 0; + } + buff[0] = AF_S_ADMIN_CMD; + buff[1] = st; + buff[2] = AF_RA_UNDEFINED; + buff[3] = n >> 8; /* high bits of message length */ + buff[4] = n; /* low bits of message length */ + SslFd_send_message(type, master, buff, n+5); +} + +/* + * Function name: add_to_message + * Description: Adds text to the message. + * Arguments: buff - the message we are adding text to + * format - the format of the text + * ... - additional arguments + */ + +static void +add_to_message(unsigned char* buff, const char* format, ...) +{ + va_list ap; + int n; + + assert(buff != NULL); + assert(format != NULL); + + if (!newmessage) { + n = strlen((char*) &buff[5]); + } + else { + n = 0; + } + newmessage = 0; + va_start(ap, format); + + vsprintf((char*) &buff[5+n], format, ap); + n = strlen((char*) &buff[5]); + sprintf((char*) &buff[5+n], "\n"); + + va_end(ap); +} + +/* + * Function name: add_uptime_to_message + * Description: Adds the formatted time period to the message. + * Arguments: buff - the message we are adding formatted time period to + * info - the info which will be added to the message just before the time + * period - the time period we are adding to the message + */ + +static void +add_uptime_to_message(unsigned char* buff, char* info, time_t period) +{ + int hours, minutes, seconds; + + assert(buff != NULL); + assert(info != NULL); + + hours = period/3600; + minutes = (period/60)%60; + seconds = period%60; + + if (hours) { + add_to_message(buff, "%s: %d:%02d:%02d", info, hours, minutes, seconds); + } + else { + add_to_message(buff, "%s: %d:%02d", info, minutes, seconds); + } +} + +/* + * Function name: serve_admin + * Description: Function responsible for the reaction for user's admin commands. + * Arguments: config - the server configuration + * realm - the realm number + * client - the client number + * buff - buffer containing the user's command + * Returns: 0 - do nothing, + * 1 - kick this client, + * >1 - kick the specified client. + */ + +int +serve_admin(ServerConfiguration* config, int realm, int client, unsigned char* buff) +{ + int length, n, i, j, ret; + time_t now, tmp; + llnodeT* llptr; + AuditListNode* alptr; + char olddf[51], newdf[51]; + ConnectClient* cpointer; + ConnectUser* upointer; + ServerRealm* pointer = ServerConfiguration_get_realmsTable(config)[realm]; + char type = ServerRealm_get_realmType(pointer) | TYPE_SSL | TYPE_ZLIB; + SslFd* master = ConnectClient_get_sslFd(ServerRealm_get_raClientsTable(pointer)[client]); + + assert(config != NULL); + assert(buff != NULL); + + olddf[50] = newdf[50] = 0; + length = buff[3]; + length = length << 8; + length += buff[4]; /* this is the length of a message */ + + time(&now); + + switch (buff[1]) { + case AF_RA_CMD: { + n = SslFd_get_message(type, master, buff, length); + buff[n] = 0; + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: admin: message length = %d [%s]", + get_realmname(config, realm), n, buff); + switch (parse_cmd(buff, &ret)) { + case 1: { /* help */ + add_to_message(buff, AF_VER("AFSERVER")); + add_to_message(buff, "\nValid commands are:"); + add_to_message(buff, " help display help"); + add_to_message(buff, " lcmd lists available commands"); + add_to_message(buff, " info prints info about server"); + add_to_message(buff, " rshow display realms"); + add_to_message(buff, " cshow X display clients in X realm"); + add_to_message(buff, " ushow X display users in X realm"); + add_to_message(buff, " quit quit connection"); + add_to_message(buff, " timeout N X set timeout value in X realm"); + add_to_message(buff, " audit {0|1} X set audit mode in X realm"); + add_to_message(buff, " dnslookups {0|1} X set dnslookups mode in X realm"); + add_to_message(buff, " dateformat S set dateformat"); + add_to_message(buff, " kuser S kick user named S"); + add_to_message(buff, " kclient N kick client with number N"); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 2: { /* lcmd */ + add_to_message(buff, "help"); + add_to_message(buff, "lcmd"); + add_to_message(buff, "info"); + add_to_message(buff, "rshow"); + add_to_message(buff, "cshow"); + add_to_message(buff, "ushow"); + add_to_message(buff, "quit"); + add_to_message(buff, "timeout"); + add_to_message(buff, "audit"); + add_to_message(buff, "dnslookups"); + add_to_message(buff, "dateformat"); + add_to_message(buff, "kuser"); + add_to_message(buff, "kclient"); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 3: { /* info */ + add_to_message(buff, AF_VER("Version:")); + add_to_message(buff, "Realms: %d", + ServerConfiguration_get_realmsNumber(config)); + add_to_message(buff, "Certificate: %s", + ServerConfiguration_get_certificateFile(config)); + add_to_message(buff, "Key: %s", + ServerConfiguration_get_keysFile(config)); + llptr = getloglisthead(); + i = 0; + while (llptr) { + add_to_message(buff, "log[%d]: %s", i, llptr->cmdline); + llptr = llptr->next; + ++i; + } + tmp = now - ServerConfiguration_get_startTime(config); + add_uptime_to_message(buff, "Uptime", tmp); + add_to_message(buff, "Cg: %ld B", getcg()); + add_to_message(buff, "Dateformat: %s", getdateformat()); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 4: { /* rshow */ + for (i = 0; i < ServerConfiguration_get_realmsNumber(config); ++i) { + pointer = ServerConfiguration_get_realmsTable(config)[i]; + add_to_message(buff, "\nRealm[%s]:", get_realmname(config, i)); + add_to_message(buff, "hostname: %s", ServerRealm_get_hostName(pointer)); + add_to_message(buff, "users: %d (max: %d)", + ServerRealm_get_connectedUsers(pointer), + ServerRealm_get_usersLimit(pointer)); + add_to_message(buff, "clients: %d (max: %d)", + ServerRealm_get_connectedClients(pointer) - + ServerRealm_get_connectedRaClients(pointer), + ServerRealm_get_clientsLimit(pointer)); + add_to_message(buff, "raclients: %d (max: %d)", + ServerRealm_get_connectedRaClients(pointer), + ServerRealm_get_raClientsLimit(pointer)); + add_to_message(buff, "users per client: %s", + ServerRealm_get_sUsersPerClient(pointer)); + add_to_message(buff, "user-client pairs: %d", + ServerRealm_get_userClientPairs(pointer)); + for (j = 0; j < ServerRealm_get_userClientPairs(pointer); ++j) { + add_to_message(buff, " pair[%d]: listenport: %s, manageport: %s", j, + UsrCli_get_listenPortName( + ServerRealm_get_usersClientsTable(pointer)[j]), + UsrCli_get_managePortName( + ServerRealm_get_usersClientsTable(pointer)[j])); + } + add_to_message(buff, "climode: %s", ServerRealm_get_sClientMode(pointer)); + add_to_message(buff, "timeout: %d", ServerRealm_get_timeout(pointer)); + if (ServerRealm_get_maxIdle(pointer)) { + add_to_message(buff, "max idle: %d", ServerRealm_get_maxIdle(pointer)); + } + else { + add_to_message(buff, "max idle: disabled"); + } + add_to_message(buff, "baseport: %s", ServerRealm_get_basePortOn(pointer) ? + "yes" : "no"); + add_to_message(buff, "audit: %s", ServerRealm_get_auditOn(pointer) ? + "yes" : "no"); + add_to_message(buff, "dnslookups: %s", + ServerRealm_get_dnsLookupsOn(pointer) ? "yes" : "no"); + add_to_message(buff, "ssl: %s, zlib: %s, mode: %s", + (TYPE_IS_SSL(ServerRealm_get_realmType(pointer))) ? "yes" : "no", + (TYPE_IS_ZLIB(ServerRealm_get_realmType(pointer))) ? "yes" : "no", + (TYPE_IS_TCP(ServerRealm_get_realmType(pointer))) ? "tcp" : "udp"); + switch (ServerRealm_get_tunnelType(pointer)) { + case CONNECTCLIENT_TUNNELTYPE_DIRECT: { + add_to_message(buff, "tunneltype: direct"); + break; + } + case CONNECTCLIENT_TUNNELTYPE_HTTPPROXY: { + add_to_message(buff, "tunneltype: http proxy"); + break; + } + case CONNECTCLIENT_TUNNELTYPE_HTTPSPROXY: { + add_to_message(buff, "tunneltype: https proxy"); + break; + } + default: { + add_to_message(buff, "tunneltype: UNKNOWN"); + } + } + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 5: { /* cshow*/ + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < ServerConfiguration_get_realmsNumber(config))) { + pointer = ServerConfiguration_get_realmsTable(config)[n]; + for (i = 0; i < ServerRealm_get_clientsLimit(pointer); ++i) { + cpointer = ServerRealm_get_clientsTable(pointer)[i]; + if (ConnectClient_get_state(cpointer) != CONNECTCLIENT_STATE_FREE) { + add_to_message(buff, "\nClient[%s]:", + get_clientname(pointer, i)); + switch (ConnectClient_get_state(cpointer)) { + case CONNECTCLIENT_STATE_CONNECTING: { + add_to_message(buff, "state: ssl handshake"); + break; + } + case CONNECTCLIENT_STATE_AUTHORIZING: { + add_to_message(buff, "state: authorization"); + break; + } + case CONNECTCLIENT_STATE_ACCEPTED: { + add_to_message(buff, "state: running"); + break; + } + default: { + add_to_message(buff, "state: unknown"); + } + } + add_to_message(buff, "users: %d (max: %d)", + ConnectClient_get_connected(cpointer), + ConnectClient_get_limit(cpointer)); + add_to_message(buff, "user-client pair: %d", + ConnectClient_get_usrCliPair(cpointer)); + tmp = now - ConnectClient_get_connectTime(cpointer); + add_uptime_to_message(buff, "Connection time", tmp); + tmp = now - ConnectClient_get_lastActivity(cpointer); + add_uptime_to_message(buff, "Idle time", tmp); + add_to_message(buff, "Id: %s", + (ConnectClient_get_sClientId(cpointer) == NULL) ? "" : + ConnectClient_get_sClientId(cpointer)); + add_to_message(buff, "Number: %d", + ConnectClient_get_clientId(cpointer)); + add_to_message(buff, "IP: %s, port: %s", + ConnectClient_get_nameBuf(cpointer), + ConnectClient_get_portBuf(cpointer)); + switch (ConnectClient_get_tunnelType(cpointer)) { + case CONNECTCLIENT_TUNNELTYPE_DIRECT: { + add_to_message(buff, "tunneltype: direct"); + break; + } + case CONNECTCLIENT_TUNNELTYPE_HTTPPROXY: { + add_to_message(buff, "tunneltype: http proxy"); + break; + } + case CONNECTCLIENT_TUNNELTYPE_HTTPSPROXY: { + add_to_message(buff, "tunneltype: https proxy"); + break; + } + default: { + add_to_message(buff, "tunneltype: UNKNOWN"); + } + } + if (ServerRealm_get_auditOn(pointer)) { + add_to_message(buff, "auditlog:"); + alptr = AuditList_get_first( + ConnectClient_get_auditList(cpointer)); + while (alptr) { + add_to_message(buff, + "userid: %d ip: %s port: %s connected: %s duration: %s", + AuditListNode_get_userId(alptr), + AuditListNode_get_nameBuf(alptr), + AuditListNode_get_portBuf(alptr), + localdate(AuditListNode_get_connectTimep(alptr)), + timeperiod(AuditListNode_get_duration(alptr))); + alptr = AuditListNode_get_nextNode(alptr); + } + } + } + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + add_to_message(buff, "Usage: cshow X , X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 6: { /* ushow */ + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < ServerConfiguration_get_realmsNumber(config))) { + pointer = ServerConfiguration_get_realmsTable(config)[n]; + for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) { + upointer = ServerRealm_get_usersTable(pointer)[i]; + if (ConnectUser_get_state(upointer) != S_STATE_CLEAR) { + add_to_message(buff, "\nUser[%d]:", + get_username(pointer, i)); + switch (ConnectUser_get_state(upointer)) { + case S_STATE_CLOSING: { + add_to_message(buff, "state: closing"); + break; + } + case S_STATE_OPENING: { + add_to_message(buff, "state: opening"); + break; + } + case S_STATE_OPENING_CLOSED: { + add_to_message(buff, "state: opening (closed)"); + break; + } + case S_STATE_OPEN: { + add_to_message(buff, "state: running"); + break; + } + case S_STATE_STOPPED: { + add_to_message(buff, "state: stopped"); + break; + } + default: { + add_to_message(buff, "state: unknown"); + } + } + add_to_message(buff, "connected to: Client[%s]", + get_clientname(pointer, ConnectUser_get_whatClient(upointer))); + tmp = now-ConnectUser_get_connectTime(upointer); + add_uptime_to_message(buff, "Connection time", tmp); + tmp = now - UserStats_get_lastActivity( + ConnectUser_get_stats(upointer)); + add_uptime_to_message(buff, "Idle time", tmp); + add_to_message(buff, "IP: %s, port: %s", + ConnectUser_get_nameBuf(upointer), + ConnectUser_get_portBuf(upointer)); + add_to_message(buff, "Downloaded: %d bytes", + UserStats_get_totalDownloadedBytes( + ConnectUser_get_stats(upointer))); + add_to_message(buff, "download speed: %.2f B/s", + UserStats_get_downloadSpeed( + ConnectUser_get_stats(upointer))); + add_to_message(buff, "Uploaded: %d bytes", + UserStats_get_totalUploadedBytes( + ConnectUser_get_stats(upointer))); + add_to_message(buff, "upload speed: %.2f B/s", + UserStats_get_uploadSpeed( + ConnectUser_get_stats(upointer))); + } + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + add_to_message(buff, "Usage: ushow X , X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 7: { /* quit */ + aflog(LOG_T_MANAGE, LOG_I_INFO, + "realm[%s]: Client[%s] (ra): commfd: CLOSED", + get_realmname(config, realm), + get_raclientname(pointer, client)); + send_adm_message(type, master, buff, AF_RA_KICKED); + return 1; + } + case 8: { /* timeout */ + i = parse_int(buff, &ret); + if (i <= 0) { + add_to_message(buff, "Invalid timeout value"); + add_to_message(buff, + "Usage: timeout N X , N - new timeout value, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < ServerConfiguration_get_realmsNumber(config))) { + add_to_message(buff, "changed timeout: %d --> %d", + ServerRealm_get_timeout( + ServerConfiguration_get_realmsTable(config)[n]), i); + ServerRealm_set_timeout(ServerConfiguration_get_realmsTable(config)[n], i); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + add_to_message(buff, + "Usage: timeout N X , N - new timeout value, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 9: { /* audit */ + i = parse_int(buff, &ret); + if ((i != 0) && (i != 1)) { + add_to_message(buff, "Invalid audit value"); + add_to_message(buff, + "Usage: audit {0|1} X , N=0 off, N=1 on, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < ServerConfiguration_get_realmsNumber(config))) { + add_to_message(buff, "changed audit: %s --> %s", + ServerRealm_get_auditOn( + ServerConfiguration_get_realmsTable(config)[n]) ? "yes" : "no", + i ? "yes" : "no"); + ServerRealm_set_auditOn(ServerConfiguration_get_realmsTable(config)[n], i); + if (i == 0) { + for (i = 0; i < ServerRealm_get_clientsLimit( + ServerConfiguration_get_realmsTable(config)[n]); ++i) { + AuditList_clear( + ConnectClient_get_auditList( + ServerRealm_get_clientsTable( + ServerConfiguration_get_realmsTable(config)[n])[i])); + } + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + add_to_message(buff, + "Usage: audit {0|1} X , N=0 off, N=1 on, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 10: { /* dnslookups */ + i = parse_int(buff, &ret); + if ((i != 0) && (i != 1)) { + add_to_message(buff, "Invalid dnslookups value"); + add_to_message(buff, + "Usage: dnslookups {0|1} X , N=0 off, N=1 on, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + n = get_realmnumber(config, (char*) &buff[ret]); + if ((n >= 0) && (n < ServerConfiguration_get_realmsNumber(config))) { + add_to_message(buff, "changed dnslookups: %s --> %s", + ServerRealm_get_dnsLookupsOn( + ServerConfiguration_get_realmsTable(config)[n]) ? "yes" : "no", + i ? "yes" : "no"); + ServerRealm_set_dnsLookupsOn( + ServerConfiguration_get_realmsTable(config)[n], i); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + add_to_message(buff, "Wrong realm name"); + add_to_message(buff, + "Usage: dnslookups {0|1} X , N=0 off, N=1 on, X - realm name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + case 11: { /* dateformat */ + strncpy(olddf, getdateformat(), 50); + strncpy(newdf, (char*) &buff[ret], 50); + add_to_message(buff, "changed dateformat: %s --> %s", + olddf, newdf); + setdateformat(newdf); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + break; + } + case 12: { /* kuser */ + i = parse_int(buff, &ret); + if (buff[ret] != 0) { + add_to_message(buff, "Invalid user name"); + add_to_message(buff, + "Usage: kuser S , S - user name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + j = -1; + for (n = 0; n < ServerConfiguration_get_realmsNumber(config); ++n) { + pointer = ServerConfiguration_get_realmsTable(config)[n]; + j = get_usernumber(pointer, i); + if (j != (-1)) { + upointer = ServerRealm_get_usersTable(pointer)[j]; + if ((ConnectUser_get_state(upointer) == S_STATE_OPEN) || + (ConnectUser_get_state(upointer) == S_STATE_OPENING) || + (ConnectUser_get_state(upointer) == S_STATE_STOPPED)) { + add_to_message(buff, "kicked: realm[%s] user[%d]", + get_realmname(config, n), get_username(pointer, j)); + if (ConnectUser_get_state(upointer) == S_STATE_OPENING) { + ConnectUser_set_state(upointer, S_STATE_OPENING_CLOSED); + } + else { + close(ConnectUser_get_connFd(upointer)); + } + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + } + else { + add_to_message(buff, "Invalid user"); + add_to_message(buff, + "Usage: kuser S , S - user name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + } + break; + } + } + if (j == (-1)) { + add_to_message(buff, "Invalid user name"); + add_to_message(buff, + "Usage: kuser S , S - user name"); + send_adm_message(type, master, buff, AF_RA_FAILED); + } + break; + } + case 13: { /* kclient */ + i = parse_int(buff, &ret); + if (buff[ret] != 0) { + add_to_message(buff, "Invalid client number"); + add_to_message(buff, + "Usage: kclient N , N - client number"); + send_adm_message(type, master, buff, AF_RA_FAILED); + break; + } + j = -1; + for (n = 0; n < ServerConfiguration_get_realmsNumber(config); ++n) { + pointer = ServerConfiguration_get_realmsTable(config)[n]; + j = get_clientnumber(pointer, i); + if (j != (-1)) { + if (ConnectClient_get_state(ServerRealm_get_clientsTable(pointer)[j]) > + CONNECTCLIENT_STATE_FREE) { + add_to_message(buff, "kicked: realm[%s] client[%s]", + get_realmname(config, n), + get_clientname(pointer, j)); + send_adm_message(type, master, buff, AF_RA_STATUS_OK); + return (i+2); + } + else { + add_to_message(buff, "Invalid client"); + add_to_message(buff, + "Usage: kclient N , N - client number"); + send_adm_message(type, master, buff, AF_RA_FAILED); + } + break; + } + } + if (j == (-1)) { + add_to_message(buff, "Invalid client number"); + add_to_message(buff, + "Usage: kclient N , N - client number"); + send_adm_message(type, master, buff, AF_RA_FAILED); + } + break; + + } + default: { + aflog(LOG_T_MANAGE, LOG_I_WARNING, + "realm[%s]: admin: cmd ignored", get_realmname(config, realm)); + send_adm_message(type, master, buff, AF_RA_UNDEFINED); + } + } + break; + } + case AF_RA_REPEAT: { + break; + } + default: { + aflog(LOG_T_MANAGE, LOG_I_ERR, + "Unrecognized message from remote admin --> closing"); + return 1; + } + } + return 0; +} diff --git a/src/server_remoteadmin.h b/src/server_remoteadmin.h new file mode 100644 index 0000000..4b74b5d --- /dev/null +++ b/src/server_remoteadmin.h @@ -0,0 +1,37 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_SERVER_REMOTEADMIN_H +#define _JS_SERVER_REMOTEADMIN_H + +#include <ctype.h> +#include <string.h> + +#include "remoteadmin_codes.h" +#include "activefor.h" +#include "logging.h" +#include "stats.h" +#include "clientnames.h" +#include "realmnames.h" +#include "usernames.h" + +int serve_admin(ServerConfiguration*, int, int, unsigned char*); + +#endif diff --git a/src/server_remove.c b/src/server_remove.c new file mode 100644 index 0000000..c8f78f1 --- /dev/null +++ b/src/server_remove.c @@ -0,0 +1,121 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <assert.h> + +#include "server_remove.h" + +/* + * Function name: remove_client + * Description: Removes the client. + * Arguments: ptr - the server realm + * client - the client number + * set - the set of file descriptors for reading + * wset - the set of file descriptors for writing + * scheduler - the task scheduler + */ + +void +remove_client(ServerRealm* ptr, int client, fd_set* set, fd_set* wset, TaskScheduler* scheduler) +{ + int i; + Task* task; + + assert(ptr != NULL); + assert(client >= 0); + assert(set != NULL); + assert(wset != NULL); + + if (ConnectClient_get_state(ServerRealm_get_clientsTable(ptr)[client]) == CONNECTCLIENT_STATE_ACCEPTED) { + for (i = 0; i < ServerRealm_get_usersLimit(ptr); ++i) { + if (ConnectUser_get_whatClient(ServerRealm_get_usersTable(ptr)[i]) == client) { + if (ConnectUser_get_state(ServerRealm_get_usersTable(ptr)[i]) != S_STATE_CLEAR) { + ConnectUser_set_state(ServerRealm_get_usersTable(ptr)[i], S_STATE_CLEAR); + FD_CLR(ConnectUser_get_connFd(ServerRealm_get_usersTable(ptr)[i]), set); + FD_CLR(ConnectUser_get_connFd(ServerRealm_get_usersTable(ptr)[i]), wset); + close(ConnectUser_get_connFd(ServerRealm_get_usersTable(ptr)[i])); + ServerRealm_decrease_connectedUsers(ptr); + } + } + } + } + for (i = 0; i < ConnectClient_get_limit(ServerRealm_get_clientsTable(ptr)[client]); ++i) { + ConnectClient_get_users(ServerRealm_get_clientsTable(ptr)[client])[i] = -1; + } + if ((ServerRealm_get_clientsLimit(ptr) != client) && (ServerRealm_get_basePortOn(ptr) == 1)) { + close(ConnectClient_get_listenFd(ServerRealm_get_clientsTable(ptr)[client])); + FD_CLR(ConnectClient_get_listenFd(ServerRealm_get_clientsTable(ptr)[client]), set); + } + ConnectClient_set_sClientId(ServerRealm_get_clientsTable(ptr)[client], NULL); + ConnectClient_set_connected(ServerRealm_get_clientsTable(ptr)[client], 0); + close(SslFd_get_fd(ConnectClient_get_sslFd(ServerRealm_get_clientsTable(ptr)[client]))); + FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(ServerRealm_get_clientsTable(ptr)[client])), set); + if (scheduler) { + if ((task = ConnectClient_get_task(ServerRealm_get_clientsTable(ptr)[client]))) { + TaskScheduler_removeTask(scheduler, task); + ConnectClient_set_task(ServerRealm_get_clientsTable(ptr)[client], NULL); + } + } + SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(ServerRealm_get_clientsTable(ptr)[client]))); + ConnectClient_set_state(ServerRealm_get_clientsTable(ptr)[client], CONNECTCLIENT_STATE_FREE); + ServerRealm_decrease_connectedClients(ptr); +} + +/* + * Function name: remove_raclient + * Description: Removes the remote admin client. + * Arguments: ptr - the server realm + * client - the client number + * set - the set of file descriptors for reading + * wset - the set of file descriptors for writing + * scheduler - the task scheduler + */ + +void +remove_raclient(ServerRealm* ptr, int client, fd_set* set, fd_set* wset, TaskScheduler* scheduler) +{ + int i; + Task* task; + + assert(ptr != NULL); + assert(client >= 0); + assert(set != NULL); + assert(wset != NULL); + + for (i = 0; i < ConnectClient_get_limit(ServerRealm_get_raClientsTable(ptr)[client]); ++i) { + ConnectClient_get_users(ServerRealm_get_raClientsTable(ptr)[client])[i] = -1; + } + ConnectClient_set_sClientId(ServerRealm_get_raClientsTable(ptr)[client], NULL); + ConnectClient_set_connected(ServerRealm_get_raClientsTable(ptr)[client], 0); + close(SslFd_get_fd(ConnectClient_get_sslFd(ServerRealm_get_raClientsTable(ptr)[client]))); + FD_CLR(SslFd_get_fd(ConnectClient_get_sslFd(ServerRealm_get_raClientsTable(ptr)[client])), set); + if (scheduler) { + if ((task = ConnectClient_get_task(ServerRealm_get_raClientsTable(ptr)[client]))) { + TaskScheduler_removeTask(scheduler, task); + ConnectClient_set_task(ServerRealm_get_raClientsTable(ptr)[client], NULL); + } + } + SSL_clear(SslFd_get_ssl(ConnectClient_get_sslFd(ServerRealm_get_raClientsTable(ptr)[client]))); + ServerRealm_decrease_connectedClients(ptr); + if (ConnectClient_get_state(ServerRealm_get_raClientsTable(ptr)[client]) == CONNECTCLIENT_STATE_ACCEPTED) { + ServerRealm_decrease_connectedRaClients(ptr); + } + ConnectClient_set_state(ServerRealm_get_raClientsTable(ptr)[client], CONNECTCLIENT_STATE_FREE); +} diff --git a/src/server_remove.h b/src/server_remove.h new file mode 100644 index 0000000..65d4f99 --- /dev/null +++ b/src/server_remove.h @@ -0,0 +1,31 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "file.h" +#include "task_scheduler_struct.h" + +#ifndef _JS_SERVER_REMOVE_H +#define _JS_SERVER_REMOVE_H + +void remove_client(ServerRealm*, int, fd_set*, fd_set*, TaskScheduler* scheduler); +void remove_raclient(ServerRealm*, int, fd_set*, fd_set*, TaskScheduler* scheduler); + +#endif + diff --git a/src/server_set.c b/src/server_set.c new file mode 100644 index 0000000..07fa069 --- /dev/null +++ b/src/server_set.c @@ -0,0 +1,48 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <stdlib.h> +#include <assert.h> + +#include "string_functions.h" + +/* + * Function name: set_value + * Description: If the variable has no value, set it from the given string. + * If the given string is NULL, use default value. + * Arguments: dest - the destination variable + * from - the given string + * def - the default value + */ + +void +set_value(char** dest, char* from, char* def) +{ + assert(dest != NULL); + + if ((*dest) == NULL) { + if (from != NULL) { + string_cp(dest, from); + } + else { + (*dest) = def; + } + } +} diff --git a/src/server_set.h b/src/server_set.h new file mode 100644 index 0000000..7d74de9 --- /dev/null +++ b/src/server_set.h @@ -0,0 +1,27 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_SERVER_SET_H +#define _JS_SERVER_SET_H + +void set_value(char** dest, char* from, char* def); + +#endif + diff --git a/src/server_signals.c b/src/server_signals.c new file mode 100644 index 0000000..00f69bd --- /dev/null +++ b/src/server_signals.c @@ -0,0 +1,86 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "server_signals.h" +#include "activefor.h" +#include "thread_management.h" +#include "http_proxy_functions.h" +#include "stats.h" +#include "logging.h" +#include "server_configuration_struct.h" + +extern ServerConfiguration* config; + +/* + * Function name: server_sig_int + * Description: Function responsible for handling SIG_INT. + * Arguments: signo - the signal number + */ + +void +server_sig_int(int signo) +{ + int i, j; + unsigned char buff[5]; + ServerRealm** scRealmsTable; + +#ifdef HAVE_LIBPTHREAD + if (!is_this_a_mainthread()) { + return; + } +#endif + + for (j = 0; j < ServerConfiguration_get_realmsNumber(config); ++j) { + scRealmsTable = ServerConfiguration_get_realmsTable(config); + buff[0] = AF_S_CLOSING; /* closing */ + for (i = 0; i < ServerRealm_get_clientsLimit(scRealmsTable[j]); ++i) { + if (ConnectClient_get_state(ServerRealm_get_clientsTable(scRealmsTable[j])[i]) == + CONNECTCLIENT_STATE_ACCEPTED) { + SslFd_send_message(ServerRealm_get_realmType(scRealmsTable[j]), + ConnectClient_get_sslFd( + ServerRealm_get_clientsTable(scRealmsTable[j])[i]), + buff, 5); + close(SslFd_get_fd(ConnectClient_get_sslFd( + ServerRealm_get_clientsTable(scRealmsTable[j])[i]))); + } + } + for (i = 0; i < ServerRealm_get_raClientsLimit(scRealmsTable[j]); ++i) { + if (ConnectClient_get_state(ServerRealm_get_raClientsTable(scRealmsTable[j])[i]) == + CONNECTCLIENT_STATE_ACCEPTED) { + SslFd_send_message(ServerRealm_get_realmType(scRealmsTable[j]) | TYPE_SSL, + ConnectClient_get_sslFd( + ServerRealm_get_raClientsTable(scRealmsTable[j])[i]), + buff, 5); + close(SslFd_get_fd(ConnectClient_get_sslFd(ServerRealm_get_raClientsTable(scRealmsTable[j])[i]))); + } + } + + } + + /* FIXME: give a time to close all connections */ + mysleep(0.1); + + aflog(LOG_T_MAIN, LOG_I_NOTICE, + "SERVER CLOSED cg: %ld bytes", getcg()); + exit(0); +} + diff --git a/src/server_signals.h b/src/server_signals.h new file mode 100644 index 0000000..7a55a1c --- /dev/null +++ b/src/server_signals.h @@ -0,0 +1,27 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_SERVER_SIGNALS_H +#define _JS_SERVER_SIGNALS_H + +void server_sig_int(int); /* INT signal handler for the afserver */ + +#endif + diff --git a/src/ssl_fd_struct.c b/src/ssl_fd_struct.c new file mode 100644 index 0000000..056f089 --- /dev/null +++ b/src/ssl_fd_struct.c @@ -0,0 +1,329 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <zlib.h> +#include <assert.h> + +#include "activefor.h" +#include "stats.h" +#include "logging.h" +#include "ssl_fd_struct.h" + +/* + * Function name: SslFd_new + * Description: Create and initialize new SslFd structure. + * Returns: Pointer to newly created SslFd structure. + */ + +SslFd* +SslFd_new() +{ + SslFd* tmp = calloc(1, sizeof(SslFd)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: SslFd_free + * Description: Free the memory allocated for SslFd structure. + * Arguments: sf - pointer to pointer to SslFd structure + */ + +void +SslFd_free(SslFd** sf) +{ + assert(sf != NULL); + if (sf == NULL) { + return; + } + assert((*sf) != NULL); + if ((*sf) == NULL) { + return; + } + if ((*sf)->ssl) { + SSL_free((*sf)->ssl); + (*sf)->ssl = NULL; + } + free((*sf)); + (*sf) = NULL; +} + +/* + * Function name: SslFd_set_fd + * Description: Set file descriptor of the used socket. + * Arguments: sf - pointer to SslFd structure + * fd - file descriptor of the used socket + */ + +void +SslFd_set_fd(SslFd* sf, int fd) +{ + assert(sf != NULL); + if (sf == NULL) { + return; + } + sf->fd = fd; +} + +/* + * Function name: SslFd_set_ssl_general + * Description: Set ssl object for the used socket. Free previous ssl object if 'free' argument is not 0. + * Arguments: sf - pointer to SslFd structure + * fd - ssl object for the used socket + * free - free previous ssl object + */ + +void +SslFd_set_ssl_general(SslFd* sf, SSL* ssl, int free) +{ + assert(sf != NULL); + if (sf == NULL) { + return; + } + if ((free) && (sf->ssl)) { + SSL_free(sf->ssl); + } + sf->ssl = ssl; +} + + +/* + * Function name: SslFd_set_ssl + * Description: Set ssl object for the used socket. + * Arguments: sf - pointer to SslFd structure + * fd - ssl object for the used socket + */ + +void +SslFd_set_ssl(SslFd* sf, SSL* ssl) +{ + SslFd_set_ssl_general(sf, ssl, 1); +} + +/* + * Function name: SslFd_set_ssl_nf + * Description: Set ssl object for the used socket. Don't free previous ssl object + * Arguments: sf - pointer to SslFd structure + * fd - ssl object for the used socket + */ + +void +SslFd_set_ssl_nf(SslFd* sf, SSL* ssl) +{ + SslFd_set_ssl_general(sf, ssl, 0); +} + +/* + * Function name: SslFd_set_ssl + * Description: Get file descriptor of the used socket. + * Arguments: sf - pointer to SslFd structure + * Returns: File descriptor of the used socket. + */ + +int +SslFd_get_fd(SslFd* sf) +{ + assert(sf != NULL); + if (sf == NULL) { + return -1; + } + return sf->fd; +} + +/* + * Function name: SslFd_get_ssl + * Description: Get ssl object for the used socket. + * Arguments: sf - pointer to SslFd structure + * Returns: Ssl object for the used socket. + */ + +SSL* +SslFd_get_ssl(SslFd* sf) +{ + assert(sf != NULL); + if (sf == NULL) { + return NULL; + } + return sf->ssl; +} + +/* + * Function name: SslFd_send_message + * Description: Send message from 'buf' of the length 'amount' to the socket + * encapsulated in SslFd structure. 'type' is used to keep + * information about ip family, using of ssl, using of zlib and more. + * Arguments: type - type of the connection + * sf - pointer to SslFd structure + * buf - buffer which keeps data to send + * amount - amount of data to send + * Returns: Amount of bytes written or -1, if some error occured. + */ + +int +SslFd_send_message(char type, SslFd* sf, unsigned char* buf, int amount) +{ + unsigned long clen; + int length; + static unsigned char buffer[9000]; + + assert(sf != NULL); + assert(buf != NULL); + + if ((sf == NULL) || (buf == NULL)) { + return -1; + } + + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "send_message: ssl:%s zlib:%s length:%d", (TYPE_IS_SSL(type))?"yes":"no", + (TYPE_IS_ZLIB(type))?"yes":"no", amount); + clen = 8995; + length = amount - 5; + if (TYPE_IS_ZLIB(type)) { + memcpy(buffer, buf, 5); + if (amount > 5) { + compress(&buffer[5], &clen, &buf[5], length); + if (clen < length) { + length = clen; + TYPE_SET_COMP(length); + buffer[3] = length >> 8; /* high bits of message length */ + buffer[4] = length; /* low bits of message length */ + addtocg(amount-5 - clen); + } + } + if (TYPE_IS_SSL(type)) { + if (TYPE_IS_COMP(length)) { + return SSL_writen(sf->ssl, buffer, clen+5); + } + else { + return SSL_writen(sf->ssl, buf, amount); + } + } + else { + if (TYPE_IS_COMP(length)) { + return writen(sf->fd, buffer, clen+5); + } + else { + return writen(sf->fd, buf, amount); + } + } + } + else { + if (TYPE_IS_SSL(type)) { + return SSL_writen(sf->ssl, buf, amount); + } + else { + return writen(sf->fd, buf, amount); + } + } +} + +/* + * Function name: SslFd_get_message + * Description: Get message from the socket encapsulated in SslFd structure + * and write it to the 'buf'. Message is 'amount' butes long. + * 'type' is used to keep information about ip family, using of + * ssl, using of zlib and more. + * Arguments: type - type of the connection + * sf - pointer to SslFd structure + * buf - buffer which will keep received data + * amount - length of the message to receive + * Returns: Amount of bytes received or -1, if some error occured. + */ + +int +SslFd_get_message(char type, SslFd* sf, unsigned char* buf, int amount) +{ + int length; + unsigned long elen; + static unsigned char bufor[9000]; + + assert(sf != NULL); + assert(buf != NULL); + + if ((sf == NULL) || (buf == NULL)) { + return -1; + } + aflog(LOG_T_MAIN, LOG_I_DEBUG, + "get_message: ssl:%s zlib:%s length:%d", (TYPE_IS_SSL(type))?"yes":"no", + (TYPE_IS_ZLIB(type))?"yes":"no", amount); + if (amount < 0) { + if (TYPE_IS_SSL(type)) { + return SSL_read(sf->ssl, buf, -amount); + } + else { + return read(sf->fd, buf, -amount); + } + } + if (TYPE_IS_ZLIB(type)) { + if (TYPE_IS_SSL(type)) { + length = SSL_readn(sf->ssl, bufor, amount&0xBFFF); + } + else { + length = readn(sf->fd, bufor, amount&0xBFFF); + } + if (length <= 0) return length; + elen = 8096; + if (TYPE_IS_COMP(amount)) { + uncompress(buf, &elen, bufor, length); + } + else { + memcpy(buf, bufor, length); + elen = length; + } + return elen; + } + else + { + if (TYPE_IS_SSL(type)) { + return SSL_readn(sf->ssl, buf, amount); + } + else { + return readn(sf->fd, buf, amount); + } + } +} + +/* + * Function name: SslFd_swap_content + * Description: Swap the content of two SslFd structures. + * Arguments: sf1 - first pointer to SslFd structure + * sf2 - second pointer to SslFd structure + */ + +void +SslFd_swap_content(SslFd* sf1, SslFd* sf2) +{ + int tmpfd; + SSL* tmpssl; + + assert(sf1 != NULL); + assert(sf2 != NULL); + + tmpfd = SslFd_get_fd(sf1); + tmpssl = SslFd_get_ssl(sf2); + SslFd_set_fd(sf1, SslFd_get_fd(sf2)); + SslFd_set_ssl(sf1, SslFd_get_ssl(sf2)); + SslFd_set_fd(sf2, tmpfd); + SslFd_set_ssl(sf2, tmpssl); +} diff --git a/src/ssl_fd_struct.h b/src/ssl_fd_struct.h new file mode 100644 index 0000000..da3cc3f --- /dev/null +++ b/src/ssl_fd_struct.h @@ -0,0 +1,48 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _JS_SSL_FD_STRUCT_H +#define _JS_SSL_FD_STRUCT_H + +#include <openssl/ssl.h> + +typedef struct { + int fd; + SSL* ssl; +} SslFd; + +/* 'constructor' */ +SslFd* SslFd_new(); +/* 'destructor' */ +void SslFd_free(SslFd** sf); +/* setters */ +void SslFd_set_fd(SslFd* sf, int fd); +void SslFd_set_ssl(SslFd* sf, SSL* ssl); +void SslFd_set_ssl_nf(SslFd* sf, SSL* ssl); +/* getters */ +int SslFd_get_fd(SslFd* sf); +SSL* SslFd_get_ssl(SslFd* sf); +/* other */ +int SslFd_send_message(char type, SslFd* sf, unsigned char* buf, int amount); +int SslFd_get_message(char type, SslFd* sf, unsigned char* buf, int amount); +void SslFd_swap_content(SslFd* sf1, SslFd* sf2); + +#endif diff --git a/src/ssl_routines.c b/src/ssl_routines.c new file mode 100644 index 0000000..7275e92 --- /dev/null +++ b/src/ssl_routines.c @@ -0,0 +1,108 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "ssl_routines.h" + +/* + * Function name: check_public_key + * Description: Checks if the public key is trusted. + * Arguments: filename - the name of the file with stored keys + * hostname - the name of the host + * keyhash - the hash of the key + * Returns: The result of the check. + */ + +int +check_public_key(char* filename, char* hostname, char* keyhash) +{ + FILE* storefile; + char buff[256]; + int lspaceind, i; + + assert(filename != NULL); + assert(hostname != NULL); + assert(keyhash != NULL); + + memset(buff, 0, 256); + + storefile = fopen(filename, "r"); + if (storefile == NULL) { + return SSL_PUBLIC_KEY_NOT_KNOWN; + } + + while (fgets(buff, 256, storefile) != NULL) { + lspaceind = -1; + for (i = 0; i < 256; ++i) { + if (buff[i] == 0) { + break; + } + if (buff[i] == ' ') { + lspaceind = i; + } + } + if (lspaceind == -1) { + continue; + } + if (buff[strlen(buff)-1] == '\n') { + buff[strlen(buff)-1] = 0; + } + buff[lspaceind] = 0; + if (strcmp(buff, hostname) == 0) { + if (strcmp(&buff[lspaceind+1], keyhash) == 0) { + return SSL_PUBLIC_KEY_VALID; + } + else { + return SSL_PUBLIC_KEY_INVALID; + } + } + } + return SSL_PUBLIC_KEY_NOT_KNOWN; +} + +/* + * Function name: add_public_key + * Description: Adds the key to the store file. + * Arguments: filename - the name of the file with stored keys + * hostname - the name of the host + * keyhash - the hash of the key + */ + +void +add_public_key(char* filename, char* hostname, char* keyhash) +{ + FILE* storefile; + + assert(filename != NULL); + assert(hostname != NULL); + assert(keyhash != NULL); + + storefile = fopen(filename, "a"); + if (storefile == NULL) { + return; + } + fprintf(storefile, "%s %s\n", hostname, keyhash); + fclose(storefile); +} diff --git a/src/ssl_routines.h b/src/ssl_routines.h new file mode 100644 index 0000000..77a2fff --- /dev/null +++ b/src/ssl_routines.h @@ -0,0 +1,34 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#define SSL_PUBLIC_KEY_INVALID 0 +#define SSL_PUBLIC_KEY_VALID 1 +#define SSL_PUBLIC_KEY_NOT_KNOWN 2 + +#ifndef _JS_SSL_ROUTINES_H +#define _JS_SSL_ROUTINES_H + +/* check if hostname and keyhash is known */ +int check_public_key(char* filename, char* hostname, char* keyhash); +/* add hostname and keyhash to known_hosts file */ +void add_public_key(char* filename, char* hostname, char* keyhash); + +#endif + diff --git a/src/stats.c b/src/stats.c new file mode 100644 index 0000000..91f2611 --- /dev/null +++ b/src/stats.c @@ -0,0 +1,87 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "stats.h" + +static signed long compressgained; + +/* + * Function name: timeperiod + * Description: Returns the formatted time period string. + * Arguments: period - the time period + * Returns: The formatted time period string. + */ + +char* +timeperiod(time_t period) +{ + int hours, minutes, seconds; + static char timeper[41]; + memset(timeper, 0, 41); + + hours = period/3600; + minutes = (period/60)%60; + seconds = period%60; + + if (hours) { + sprintf(timeper, "%d:%02d:%02d", hours, minutes, seconds); + } + else { + sprintf(timeper, "%d:%02d", minutes, seconds); + } + return timeper; +} + +/* + * Function name: addtocg + * Description: Adds the given number to the bytes gained by the use of compression. + * Arguments: amount - the number to add + */ + +void +addtocg(int amount) +{ + compressgained += amount; +} + +/* + * Function name: getcg + * Description: Returns the number of bytes gained by the use of compression. + * Returns: The number of bytes gained by the use of compression. + */ + +signed long +getcg(void) +{ + return compressgained; +} + +/* + * Function name: resetcg + * Description: Resets the counter of bytes gained by the use of compression. + */ + +void +resetcg(void) +{ + compressgained = 0; +} diff --git a/src/stats.h b/src/stats.h new file mode 100644 index 0000000..009b047 --- /dev/null +++ b/src/stats.h @@ -0,0 +1,38 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <time.h> +#include <string.h> +#include <stdio.h> + +#ifndef _JS_STATS_H +#define _JS_STATS_H + + /* return time period description */ +char* timeperiod(time_t period); + /* add amount to compressgained value */ +void addtocg(int amount); + /* reset the compressgained value */ +void resetcg(void); + /* returns the compressgained value */ +signed long getcg(void); + +#endif + diff --git a/src/string_functions.c b/src/string_functions.c new file mode 100644 index 0000000..bcf42ae --- /dev/null +++ b/src/string_functions.c @@ -0,0 +1,72 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <stdlib.h> +#include <string.h> + +#include "string_functions.h" + +/* + * Function name: string_cp + * Description: Firstly, the memory allocated for *dest is released. After this, new memory is allocated + * and string from src is copied to newly created location. *dest is pointing to new string. + * Arguments: dest - pointer to pointer to string previously allocated by malloc family functions. + * If dest is NULL, memory will be allocated and returned from the function. In the + * latter case dest will be unchanged + * src - string containing data for copying. If src is NULL, new memory is not allocated, but + * the old one is still released. + * Returns: The newly allocated string. + */ + +char* +string_cp(char** dest, char* src) +{ + char* tmp; + int len = 0; + + /* 1. releasing memory allocated by *dest */ + if (dest != NULL) { + if ((*dest) != NULL) { + /* if *dest points to the same memory as src - we shouldn't do anything */ + if ((*dest) == src) { + return (*dest); + } + free((*dest)); + (*dest) = NULL; + } + } + /* if src is null, there is nothing more to do */ + if (src == NULL) { + return NULL; + } + /* 2. allocating new memory */ + len = strlen(src); + tmp = calloc(1, len + 1); + if (tmp == NULL) { + return NULL; + } + /* 3. copying data from src */ + strncpy(tmp, src, len); + if (dest != NULL) { + (*dest) = tmp; + } + return tmp; +} diff --git a/src/string_functions.h b/src/string_functions.h new file mode 100644 index 0000000..914935c --- /dev/null +++ b/src/string_functions.h @@ -0,0 +1,27 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_STRING_FUNCTIONS_H +#define _JS_STRING_FUNCTIONS_H + +char* string_cp(char** dest, char* src); + +#endif + diff --git a/src/task_list_node_struct.c b/src/task_list_node_struct.c new file mode 100644 index 0000000..eb80369 --- /dev/null +++ b/src/task_list_node_struct.c @@ -0,0 +1,124 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <assert.h> + +#include "task_list_node_struct.h" + +/* + * Function name: TaskListNode_new + * Description: Creates and initializes new task list node. The task must point + * at previously allocated Task structure. + * Arguments: task - pointer to Task structure, which must be previously initialized + * Returns: Pointer to newly created TaskListNode structure. + */ + +TaskListNode* +TaskListNode_new(Task* task) +{ + TaskListNode* tmp = calloc(1, sizeof(TaskListNode)); + assert(task != NULL); + if (task == NULL) { + return NULL; + } + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + tmp->task = task; + + return tmp; +} + +/* + * Function name: TaskListNode_free + * Description: Frees the memory allocated for TaskListNode structure. + * Arguments: node - pointer to pointer to TaskListNode structure + */ + +void +TaskListNode_free(TaskListNode** node) +{ + assert(node != NULL); + if (node == NULL) { + return; + } + assert((*node) != NULL); + if ((*node) == NULL) { + return; + } + + free((*node)); + (*node) = NULL; +} + +/* + * Function name: TaskListNode_set_next + * Description: Sets the next pointer of the task list node. + * Arguments: node - pointer to TaskListNode structure + * next - the new next pointer + */ + +void +TaskListNode_set_next(TaskListNode* node, TaskListNode* next) +{ + assert(node != NULL); + if (node == NULL) { + return; + } + node->next = next; +} + +/* + * Function name: TaskListNode_set_previous + * Description: Sets the previous pointer of the task list node. + * Arguments: node - pointer to TaskListNode structure + * next - the new previous pointer + */ + +void +TaskListNode_set_previous(TaskListNode* node, TaskListNode* previous) +{ + assert(node != NULL); + if (node == NULL) { + return; + } + node->previous = previous; +} + +/* + * Function name: TaskListNode_get_task + * Description: Returns the task contained in this node. + * Arguments: node - pointer to TaskListNode structure + * Returns: The task contained in this node. + */ + +Task* +TaskListNode_get_task(TaskListNode* node) +{ + assert(node != NULL); + if (node == NULL) { + return NULL; + } + return node->task; +} diff --git a/src/task_list_node_struct.h b/src/task_list_node_struct.h new file mode 100644 index 0000000..4588f13 --- /dev/null +++ b/src/task_list_node_struct.h @@ -0,0 +1,42 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_TASK_LIST_NODE_STRUCT_H +#define _JS_TASK_LIST_NODE_STRUCT_H + +#include "task_struct.h" + +typedef struct tlnode{ + Task* task; + struct tlnode* previous; + struct tlnode* next; +} TaskListNode; + +/* 'constructor' */ +TaskListNode* TaskListNode_new(Task* task); +/* 'destructor' */ +void TaskListNode_free(TaskListNode** node); +/* setters */ +void TaskListNode_set_next(TaskListNode* node, TaskListNode* next); +void TaskListNode_set_previous(TaskListNode* node, TaskListNode* previous); +/* getters */ +Task* TaskListNode_get_task(TaskListNode* node); + +#endif diff --git a/src/task_scheduler_struct.c b/src/task_scheduler_struct.c new file mode 100644 index 0000000..99b22bb --- /dev/null +++ b/src/task_scheduler_struct.c @@ -0,0 +1,321 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <assert.h> + +#include "timeval_functions.h" +#include "task_scheduler_struct.h" + +/* + * Function name: TaskScheduler_new + * Description: Creates and initializes task scheduler. + * Returns: Pointer to newly created TaskScheduler structure. + */ + +TaskScheduler* +TaskScheduler_new() +{ + TaskScheduler* tmp = calloc(1, sizeof(TaskScheduler)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + + return tmp; +} + +/* + * Function name: TaskScheduler_free + * Description: Frees the memory allocated for TaskScheduler structure. + * Arguments: scheduler - pointer to pointer to TaskScheduler structure + */ + +void +TaskScheduler_free(TaskScheduler** scheduler) +{ + assert(scheduler != NULL); + if (scheduler == NULL) { + return; + } + assert((*scheduler) != NULL); + if ((*scheduler) == NULL) { + return; + } + + while ((*scheduler)->head) { + TaskScheduler_removeTask((*scheduler), TaskListNode_get_task((*scheduler)->head)); + } + + free((*scheduler)); + (*scheduler) = NULL; +} + +/* + * Function name: TaskScheduler_get_actualTimer + * Description: Returns the smallest timeval structure in the scheduler. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: The smallest timeval structure in the scheduler. + */ + +struct timeval* +TaskScheduler_get_actualTimer(TaskScheduler* scheduler) +{ + assert(scheduler != NULL); + if (scheduler == NULL) { + return NULL; + } + return Task_get_timer(TaskListNode_get_task(scheduler->actualTask)); +} + +/* + * Function name: TaskScheduler_hasMoreTasks + * Description: Checks if there is more tasks in the scheduler. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: 0 - there is no more tasks in the scheduler, + * n>0 - there is more (n) tasks in the scheduler. + */ + +int +TaskScheduler_hasMoreTasks(TaskScheduler* scheduler) +{ + assert(scheduler != NULL); + if (scheduler == NULL) { + return 0; + } + return scheduler->numberOfTasks; +} + +/* + * Function name: TaskScheduler_addTask + * Description: Adds the task to the scheduler. + * Arguments: scheduler - pointer to TaskScheduler structure + * task - the task to add to the scheduler + * Returns: 0 - the task has been added successfully, + * 1 - the task has NOT been added. + */ + +int +TaskScheduler_addTask(TaskScheduler* scheduler, Task* task) +{ + TaskListNode* tmp; + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + assert(task != NULL); + if (task == NULL) { + return 1; + } + tmp = TaskListNode_new(task); + assert(tmp != NULL); + if (tmp == NULL) { + return 1; + } + if (scheduler->head) { + TaskListNode_set_next(tmp, scheduler->head); + TaskListNode_set_previous(scheduler->head, tmp); + } + scheduler->head = tmp; + scheduler->numberOfTasks += 1; + if (scheduler->actualTask) { + if (timeval_compare(TaskScheduler_get_actualTimer(scheduler), Task_get_timer(task)) > 0) { + scheduler->actualTask = tmp; + } + } + else { + scheduler->actualTask = tmp; + } + return 0; +} + +/* + * Function name: find_tasknode_with_minimal_timer + * Description: Finds the task list node with minimal timer. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: The task list node with minimal timer. + */ +static TaskListNode* +find_tasknode_with_minimal_timer(TaskScheduler* scheduler) +{ + TaskListNode* iterator; + TaskListNode* candidate; + assert(scheduler != NULL); + if (scheduler == NULL) { + return NULL; + } + if (scheduler->head == NULL) { + return NULL; + } + candidate = scheduler->head; + iterator = scheduler->head; + iterator = iterator->next; + while (iterator) { + if (timeval_compare(Task_get_timer(TaskListNode_get_task(iterator)), + Task_get_timer(TaskListNode_get_task(candidate))) == -1) { + candidate = iterator; + } + iterator = iterator->next; + } + return candidate; +} + +/* + * Function name: TaskScheduler_removeTask + * Description: Removes the task from the scheduler. + * Arguments: scheduler - pointer to TaskScheduler structure + * task - the task to remove from the scheduler + * Returns: 0 - the task has been removed successfully, + * 1 - the task has NOT been removed (probably there was no such task in the scheduler). + */ + +int +TaskScheduler_removeTask(TaskScheduler* scheduler, Task* task) +{ + TaskListNode* iterator; + Task* tmp; + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + assert(task != NULL); + if (task == NULL) { + return 1; + } + iterator = scheduler->head; + while (iterator) { + tmp = TaskListNode_get_task(iterator); + if (tmp == task) { + if (iterator->previous) { + TaskListNode_set_next(iterator->previous, iterator->next); + } + if (iterator->next) { + TaskListNode_set_previous(iterator->next, iterator->previous); + } + if (iterator == scheduler->head) { + scheduler->head = iterator->next; + } + if (iterator == scheduler->actualTask) { + scheduler->actualTask = find_tasknode_with_minimal_timer(scheduler); + } + scheduler->numberOfTasks -= 1; + TaskListNode_free(&iterator); + return 0; + } + iterator = iterator->next; + } + return 1; +} + +/* + * Function name: TaskScheduler_startWatching + * Description: Starts counting the time for the actual timer. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: 0 - success, + * 1 - failure. + */ + +int +TaskScheduler_startWatching(TaskScheduler* scheduler) +{ + struct timeval* tmp; + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + tmp = TaskScheduler_get_actualTimer(scheduler); + assert(tmp != NULL); + if (tmp == NULL) { + return 1; + } + scheduler->delta = *tmp; + return 0; +} + +/* + * Function name: TaskScheduler_stopWatching + * Description: Stops counting the time for the actual timer. + * Updates all the timers and destroys them if needed. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: 0 - success, + * 1 - failure. + */ + +int +TaskScheduler_stopWatching(TaskScheduler* scheduler) +{ + TaskListNode* iterator; + TaskListNode* actualTask; + Task* backup; + struct timeval* tmp; + int result; + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + tmp = TaskScheduler_get_actualTimer(scheduler); + assert(tmp != NULL); + if (tmp == NULL) { + return 1; + } + if (timeval_subtract(&(scheduler->delta), tmp)) { + return 1; + } + actualTask = scheduler->actualTask; + assert(scheduler->actualTask != NULL); + iterator = scheduler->head; + while (iterator) { + if (iterator != actualTask) { + result = timeval_subtract(Task_get_timer(TaskListNode_get_task(iterator)), &(scheduler->delta)); + assert(result == 0); + } + if (timeval_lq_zero(Task_get_timer(TaskListNode_get_task(iterator)))) { + Task_exec(TaskListNode_get_task(iterator)); + backup = TaskListNode_get_task(iterator); + iterator = iterator->next; + TaskScheduler_removeTask(scheduler, backup); + continue; + } + iterator = iterator->next; + } + TaskScheduler_update(scheduler); + return 0; +} + +/* + * Function name: TaskScheduler_update + * Description: Updates the actual timer. + * Arguments: scheduler - pointer to TaskScheduler structure + * Returns: 0 - success, + * 1 - failure. + */ + +int +TaskScheduler_update(TaskScheduler* scheduler) +{ + assert(scheduler != NULL); + if (scheduler == NULL) { + return 1; + } + scheduler->actualTask = find_tasknode_with_minimal_timer(scheduler); + return 0; +} diff --git a/src/task_scheduler_struct.h b/src/task_scheduler_struct.h new file mode 100644 index 0000000..d62405a --- /dev/null +++ b/src/task_scheduler_struct.h @@ -0,0 +1,47 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_TASK_SCHEDULER_STRUCT_H +#define _JS_TASK_SCHEDULER_STRUCT_H + +#include "task_list_node_struct.h" + +typedef struct { + TaskListNode* head; + int numberOfTasks; + TaskListNode* actualTask; + struct timeval delta; +} TaskScheduler; + +/* 'constructor' */ +TaskScheduler* TaskScheduler_new(); +/* 'destructor' */ +void TaskScheduler_free(TaskScheduler** scheduler); +/* getters */ +struct timeval* TaskScheduler_get_actualTimer(TaskScheduler* scheduler); +/* other */ +int TaskScheduler_hasMoreTasks(TaskScheduler* scheduler); +int TaskScheduler_addTask(TaskScheduler* scheduler, Task* task); +int TaskScheduler_removeTask(TaskScheduler* scheduler, Task* task); +int TaskScheduler_startWatching(TaskScheduler* scheduler); +int TaskScheduler_stopWatching(TaskScheduler* scheduler); +int TaskScheduler_update(TaskScheduler* scheduler); + +#endif diff --git a/src/task_struct.c b/src/task_struct.c new file mode 100644 index 0000000..283bbe8 --- /dev/null +++ b/src/task_struct.c @@ -0,0 +1,122 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <assert.h> + +#include "task_struct.h" + +/* + * Function name: Task_new + * Description: Creates and initializes new task. User is responsible for + * allocating/freeing memory pointed by the pointers. + * Arguments: timerp - pointer to timeval structure used to counte time (required) + * function - pointer to function executed when the time is out (optional) + * data - pointer to data passed to function executed when the time is out (optional) + * clean - pointer to function that frees the data + * Returns: Pointer to newly created Task structure. + */ + +Task* +Task_new(struct timeval* timerp, void (*function)(void*), void* data, void (*clean)(void**)) +{ + Task* tmp; + assert(timerp != NULL); + if (timerp == NULL) { + return NULL; + } + tmp = calloc(1, sizeof(Task)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + tmp->timerp = timerp; + tmp->function = function; + tmp->data = data; + tmp->clean = clean; + + return tmp; +} + +/* + * Function name: Task_free + * Description: Frees the memory allocated for Task structure. User has to free the memory at the + * pointers by his own. + * Arguments: task - pointer to pointer to Task structure + */ + +void +Task_free(Task** task) +{ + assert(task != NULL); + if (task == NULL) { + return; + } + assert((*task) != NULL); + if ((*task) == NULL) { + return; + } + + if ((*task)->clean) { + if ((*task)->data) { + (*task)->clean(&((*task)->data)); + } + } + + free((*task)); + (*task) = NULL; +} + +/* + * Function name: Task_get_timer + * Description: Returns the timer of the task. + * Arguments: task - pointer to Task structure + * Returns: The timer of the task. + */ + +struct timeval* +Task_get_timer(Task* task) +{ + assert(task != NULL); + if (task == NULL) { + return NULL; + } + return task->timerp; +} + +/* + * Function name: Task_exec + * Description: Executes the function encapsulated in the task. + * Arguments: task - pointer to Task structure + */ + +void +Task_exec(Task* task) +{ + assert(task != NULL); + if (task == NULL) { + return; + } + if (task->function) { + task->function(task->data); + } +} diff --git a/src/task_struct.h b/src/task_struct.h new file mode 100644 index 0000000..fac4582 --- /dev/null +++ b/src/task_struct.h @@ -0,0 +1,39 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_TASK_STRUCT_H +#define _JS_TASK_STRUCT_H + +typedef struct { + struct timeval* timerp; + void (*function)(void*); + void* data; + void (*clean)(void**); +} Task; + +/* 'constructor' */ +Task* Task_new(struct timeval*, void (*function)(void*), void*, void (*clean)(void**)); +/* 'destructor' */ +void Task_free(Task** task); +/* getters */ +struct timeval* Task_get_timer(Task* task); +void Task_exec(Task* task); + +#endif diff --git a/src/thread_management.c b/src/thread_management.c new file mode 100644 index 0000000..d423ca6 --- /dev/null +++ b/src/thread_management.c @@ -0,0 +1,102 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "thread_management.h" + +#ifdef HAVE_LIBPTHREAD + +static pthread_t mainthread; +static pthread_mutex_t mainmutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t maincond = PTHREAD_COND_INITIALIZER; + +/* + * Function name: remember_mainthread + * Description: Remembers the current thread as a main thread. + */ + +void +remember_mainthread(void) +{ + mainthread = pthread_self(); +} + +/* + * Function name: is_this_a_mainthread + * Description: Checks, if the current thread is a main thread. + * Returns: 0 - this is not a main thread, + * 1 - this is a main thread. + */ + +int +is_this_a_mainthread(void) +{ + if (pthread_self() == mainthread) { + return 1; + } + return 0; +} + +/* + * Function name: start_critical_section + * Description: Starts the critical section of the code by locking the mutex. + */ + +void +start_critical_section(void) +{ + pthread_mutex_lock( &mainmutex); +} + +/* + * Function name: end_critical_section + * Description: Ends the critical section of the code by unlocking the mutex. + */ + +void +end_critical_section(void) +{ + pthread_mutex_unlock( &mainmutex); +} + +/* + * Function name: wait_for_condition + * Description: Starts waiting for the condition. + */ + +void +wait_for_condition(void) +{ + pthread_cond_wait(&maincond, &mainmutex); +} + +/* + * Function name: broadcast_condition + * Description: Broadcast the met of the condition. + */ + +void +broadcast_condition(void) +{ + pthread_cond_broadcast(&maincond); +} + +#endif diff --git a/src/thread_management.h b/src/thread_management.h new file mode 100644 index 0000000..9ea87fb --- /dev/null +++ b/src/thread_management.h @@ -0,0 +1,34 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_THREAD_MANAGEMENT_H +#define _JS_THREAD_MANAGEMENT_H + +#include <pthread.h> + +void remember_mainthread(void); +int is_this_a_mainthread(void); +void start_critical_section(void); +void end_critical_section(void); +void wait_for_condition(void); +void broadcast_condition(void); + +#endif + diff --git a/src/timeval_functions.c b/src/timeval_functions.c new file mode 100644 index 0000000..122e03a --- /dev/null +++ b/src/timeval_functions.c @@ -0,0 +1,134 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <assert.h> + +#include "timeval_functions.h" + +/* + * Function name: timeval_create + * Description: Initialize and return timeval structure. + * Arguments: tv_sec - seconds + * tv_usec - microseconds + * Returns: Initialized timeval structure. + */ + +struct timeval +timeval_create(long tv_sec, long tv_usec) +{ + struct timeval tmp; + tmp.tv_sec = tv_sec; + tmp.tv_usec = tv_usec; + return tmp; +} + +/* + * Function name: timeval_compare + * Description: Compares two pointers to timeval structures. + * Arguments: first - the first timeval structure to compare + * second - the second timeval structure to compare + * Returns: -1 - the second structure is bigger + * 0 - structures are equals + * 1 - the first structure is bigger + */ + +int +timeval_compare(struct timeval* first, struct timeval* second) +{ + if (first == NULL) { + if (second == NULL) { + return 0; + } + else { + return -1; + } + } + if (second == NULL) { + return 1; + } + if (first->tv_sec < second->tv_sec) { + return -1; + } + if (first->tv_sec > second->tv_sec) { + return 1; + } + if (first->tv_usec < second->tv_usec) { + return -1; + } + if (first->tv_usec > second->tv_usec) { + return 1; + } + return 0; +} + +/* + * Function name: timeval_subtract + * Description: Substracts second timeval structure from the first, updating the latter one. + * Arguments: first - the first timeval structure to subtract operation + * second - the second timeval structure to subtract operation + * Returns: 0 - success, + * 1 - failure. + */ + +int +timeval_subtract(struct timeval* first, struct timeval* second) +{ + assert(first != NULL); + assert(second != NULL); + if ((first == NULL) || (second == NULL)) { + return 1; + } + if (first->tv_usec < second->tv_usec) { + first->tv_sec -= 1; + first->tv_usec = 1000000 - second->tv_usec + first->tv_usec; + } + else { + first->tv_usec -= second->tv_usec; + } + first->tv_sec -= second->tv_sec; + return 0; +} + +/* + * Function name: timeval_lq_zero + * Description: Checks if the timer is less or equiv zero. + * Arguments: timer - the timeval structure to check + * Returns: 1 - the timer is less or equiv zero, + * 0 - the timer is bigger than zero. + */ + +int +timeval_lq_zero(struct timeval* timer) +{ + assert(timer != NULL); + if (timer == NULL) { + return 0; + } + if (timer->tv_sec < 0) { + return 1; + } + if ((timer->tv_sec == 0) && (timer->tv_usec == 0)) { + return 1; + } + return 0; +} diff --git a/src/timeval_functions.h b/src/timeval_functions.h new file mode 100644 index 0000000..52b1582 --- /dev/null +++ b/src/timeval_functions.h @@ -0,0 +1,32 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_TIMEVAL_FUNCTIONS_H +#define _JS_TIMEVAL_FUNCTIONS_H + +#include <sys/time.h> + +struct timeval timeval_create(long tv_sec, long tv_usec); +int timeval_compare(struct timeval* first, struct timeval* second); +int timeval_subtract(struct timeval* first, struct timeval* second); +int timeval_lq_zero(struct timeval* timer); + +#endif + diff --git a/src/usage.c b/src/usage.c new file mode 100644 index 0000000..08a85b8 --- /dev/null +++ b/src/usage.c @@ -0,0 +1,227 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + +#include "usage.h" +#include "network.h" + +/* + * Function name: server_short_usage + * Description: Prints the short usage of the afserver. + * Arguments: info - the text printed in the first line + */ + +void +server_short_usage(char* info) +{ + assert(info != NULL); + printf("\n%s\n\n\n", info); + printf("Try `afserver --help' for more information.\n"); + + exit(1); +} + +/* + * Function name: server_long_usage + * Description: Prints the long usage of the afserver. + * Arguments: info - the text printed in the first line + */ + +void +server_long_usage(char* info) +{ + assert(info != NULL); + printf("\n%s\n\n\n", info); + printf(" Basic options:\n\n"); + printf(" -n, --hostname - it's used when creating listening sockets\n"); + printf(" (default: '')\n"); + printf(" -l, --listenport - listening [host:]port - users connect to it\n"); + printf(" (default: 50127)\n"); + printf(" -m, --manageport - manage [host:]port - afclient connects to it\n"); + printf(" (default: 50126)\n"); + printf(" -V, --version - display version number\n"); + printf(" -h, --help - prints this help\n\n"); + printf(" Authorization:\n\n"); + printf(" --pass - set the password used for client identification\n"); + printf(" (default: no password)\n\n"); + printf(" Configuration:\n\n"); + printf(" -c, --cerfile - the name of the file with certificate\n"); + printf(" (default: server-cert.pem)\n"); + printf(" -A, --cacerfile - the name of the file with CA certificates\n"); + printf(" (if used, require clients to have valid certificates)\n"); + printf(" -d, --cerdepth - the maximum depth of valid certificate-chains\n"); + printf(" -k, --keyfile - the name of the file with RSA key (default: server.rsa)\n"); + printf(" -f, --cfgfile - the name of the file with the configuration for the\n"); + printf(" active forwarder (server)\n"); + printf(" -D, --dateformat - format of the date printed in logs (see 'man strftime'\n"); + printf(" for details) (default: %%Y-%%m-%%d %%H:%%M:%%S)\n"); + printf(" -t, --timeout - the timeout value for the client's connection\n"); + printf(" (default: 5)\n"); + printf(" --maxidle - the maximum idle time for the client's connection\n"); + printf(" (default: disabled)\n"); + printf(" -u, --users - the amount of users allowed to use this server\n"); + printf(" (default: 5)\n"); + printf(" -C, --clients - the number of allowed clients to use this server\n"); + printf(" (default: 1)\n"); + printf(" -r, --realm - set the realm name (default: none)\n"); + printf(" -R, --raclients - the number of allowed clients in remote administration\n"); + printf(" mode to use this server (default: 1)\n"); + printf(" -U, --usrpcli - the number of allowed users per client (default: $users)\n"); + printf(" -M, --climode - strategy used to connect users with clients (default: 1)\n"); + printf(" Available strategies:\n"); + printf(" 1. fill first client before go to next\n\n"); + printf(" -p, --proto - type of server (tcp|udp) - what protocol it will be\n"); + printf(" operating for (default: tcp)\n"); + printf(" -b, --baseport - listenports are temporary and differ for each client\n"); + printf(" -a, --audit - additional information about connections are logged\n"); + printf(" --nossl - ssl is not used to transfer data (but it's still used\n"); + printf(" to establish a connection) (default: ssl is used)\n"); + printf(" --nozlib - zlib is not used to compress data (default: zlib is\n"); + printf(" used)\n"); + printf(" --dnslookups - try to obtain dns names of the computers rather than\n"); + printf(" their numeric IP\n\n"); + printf(" Logging:\n\n"); + printf(" -o, --log - log choosen information to file/socket\n"); + printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n"); + printf(" (use several times for greater effect)\n\n"); +#ifdef AF_INET6 + printf(" IP family:\n\n"); + printf(" -4, --ipv4 - use ipv4 only\n"); + printf(" -6, --ipv6 - use ipv6 only\n\n"); +#endif +#ifdef HAVE_LIBPTHREAD + printf(" HTTP PROXY:\n\n"); + printf(" -P, --enableproxy - enable http proxy mode\n\n"); + /* FIXME: afclient is always trying to get http page, so this option is not needed now + printf(" -S, --use-https - use https proxy instead of http proxy. '-P' option\n"); + printf(" will be set implicitly\n\n"); + */ +#endif + + exit(0); +} + +/* + * Function name: client_short_usage + * Description: Prints the short usage of the afclient. + * Arguments: info - the text printed in the first line + */ + +void +client_short_usage(char* info) +{ + assert(info != NULL); + printf("\n%s\n\n\n", info); + printf("Try `afclient --help' for more information.\n"); + + exit(1); +} + +/* + * Function name: client_long_usage + * Description: Prints the long usage of the afclient. + * Arguments: info - the text printed in the first line + */ + +void +client_long_usage(char* info) +{ + assert(info != NULL); + printf("\n%s\n\n\n", info); + printf(" Basic options:\n\n"); + printf(" -n, --servername - where the second part of the active\n"); + printf(" port forwarder is running (required)\n"); + printf(" -m, --manageport - manage port number - server must be\n"); + printf(" listening on it (default: 50126)\n"); + printf(" -d, --hostname - the name of this host/remote host - the final\n"); + printf(" destination of the packets (default: the name\n"); + printf(" returned by hostname function)\n"); + printf(" -p, --portnum - the port we are forwarding connection to (required)\n"); + printf(" --localname - local machine name for connection with afserver\n"); + printf(" (used to bind socket to different interfaces)\n"); + printf(" --localport - local port name for connection with afserver\n"); + printf(" (used to bind socket to different addressees)\n"); + printf(" --localdesname - local machine name for connections with destination\n"); + printf(" application (used to bind socket to different interfaces)\n"); + printf(" -V, --version - display version number\n"); + printf(" -h, --help - prints this help\n\n"); + printf(" Authorization:\n\n"); + printf(" -i, --id - sends the id string to afserver\n"); + printf(" --pass - set the password used for client identification\n"); + printf(" (default: no password)\n"); + printf(" --ignorepkeys - ignore invalid server's public keys\n\n"); + printf(" Configuration:\n\n"); + printf(" -k, --keyfile - the name of the file with RSA key (default: client.rsa)\n"); + printf(" -c, --cerfile - the name of the file with certificate\n"); + printf(" (default: no certificate used)\n"); + printf(" -f, --cfgfile - the name of the file with the configuration for the\n"); + printf(" active forwarder (client)\n"); + printf(" -s, --storefile - the name of the file with stored public keys\n"); + printf(" (default: known_hosts)\n"); + printf(" -D, --dateformat - format of the date printed in logs (see 'man strftime'\n"); + printf(" for details) (default: %%Y-%%m-%%d %%H:%%M:%%S)\n"); + printf(" -K, --keep-alive N - send keepalive packets every N seconds\n"); + printf(" (default: not send keepalive packets)\n\n"); + printf(" Auto-reconnection:\n\n"); + printf(" --ar-start - enable auto-reconnection when afserver is not\n"); + printf(" reachable on start (default: disabled)\n"); + printf(" --ar-quit - enable auto-reconnection after normal afserver quit\n"); + printf(" (default: disabled)\n"); + printf(" --noar - disable auto-reconnection after premature afserver\n"); + printf(" quit (default: enabled)\n"); + printf(" -A, --ar-tries N - try N times to reconnect (default: unlimited)\n"); + printf(" -T, --ar-delay N - wait N seconds between reconnect tries (default: 5)\n\n"); + printf(" Modes:\n\n"); + printf(" -u, --udpmode - udp mode - client will use udp protocol to\n"); + printf(" communicate with the hostname:portnum\n"); + printf(" -U, --reverseudp - reverse udp forwarding. Udp packets will be forwarded\n"); + printf(" from hostname:portnum to the server name:manageport\n"); + printf(" -r, --remoteadmin - remote administration mode. (using '-p #port' will\n"); + printf(" force afclient to use port rather than stdin-stdout)\n\n"); + printf(" Logging:\n\n"); + printf(" -o, --log - log choosen information to file/socket\n"); + printf(" -v, --verbose - to be verbose - program won't enter the daemon mode\n"); + printf(" (use several times for greater effect)\n\n"); +#ifdef AF_INET6 + printf(" IP family:\n\n"); + printf(" -4, --ipv4 - use ipv4 only\n"); + printf(" -6, --ipv6 - use ipv6 only\n\n"); +#endif +#ifdef HAVE_LIBDL + printf(" Modules:\n\n"); + printf(" -l, --load - load a module for user's packets filtering\n"); + printf(" -L, --Load - load a module for service's packets filtering\n\n"); +#endif +#ifdef HAVE_LIBPTHREAD + printf(" HTTP/HTTPS PROXY:\n\n"); + printf(" -S, --use-https - use https proxy instead of http proxy\n"); + printf(" -P, --proxyname - the name of the machine with proxy server\n"); + printf(" -X, --proxyport - the port used by proxy server (default: 8080)\n"); + printf(" -C, --pa-cred U:P - the user (U) and password (P) used in proxy\n"); + printf(" authorization\n"); + printf(" -B, --pa-t-basic - the Basic type of proxy authorization (default)\n\n"); +#endif + + exit(0); +} diff --git a/src/usage.h b/src/usage.h new file mode 100644 index 0000000..eded3fd --- /dev/null +++ b/src/usage.h @@ -0,0 +1,30 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _JS_USAGE_H +#define _JS_USAGE_H + +void server_short_usage(char* info); /* short usage info printed by afserver */ +void server_long_usage(char* info); /* long usage info printed by afserver */ +void client_short_usage(char* info); /* short usage info printed by afclient */ +void client_long_usage(char* info); /* long usage info printed by afclient */ + +#endif + diff --git a/src/user_stats_struct.c b/src/user_stats_struct.c new file mode 100644 index 0000000..0df384c --- /dev/null +++ b/src/user_stats_struct.c @@ -0,0 +1,391 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <time.h> +#include <assert.h> + +#include "user_stats_struct.h" + +/* + * Function name: UserStats_new + * Descriotion: Create and initialize new UserStats structure. + * Returns: Pointer to newly created UserStats structure. + */ + +UserStats* +UserStats_new() +{ + UserStats* tmp = calloc(1, sizeof(UserStats)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: UserStats_free + * Description: Free the memory allocated for UserStats structure. + * Arguments: us - pointer to pointer to UserStats structure + */ + +void +UserStats_free(UserStats** us) +{ + assert(us != NULL); + if (us == NULL) { + return; + } + assert((*us) != NULL); + if ((*us) == NULL) { + return; + } + free((*us)); + (*us) = NULL; +} + +/* + * Function name: UserStats_set_lastActivity + * Description: Set time of the last user activity (upload or download). + * Arguments: us - pointer to UserStats structure + * lastActivity - time of the last user activity + */ + +void +UserStats_set_lastActivity(UserStats* us, time_t lastActivity) +{ + assert(us != NULL); + if (us == NULL) { + return; + } + us->lastActivity = lastActivity; +} + +/* + * Function name: UserStats_set_totalDownloadedBytes + * Description: Set total amount of downloaded bytes by the user. + * Arguments: us - pointer to UserStats structure + * totalDownloadedBytes - total amount of downloaded bytes by the user + */ + +void +UserStats_set_totalDownloadedBytes(UserStats* us, int totalDownloadedBytes) +{ + assert(us != NULL); + if (us == NULL) { + return; + } + us->totalDownloadedBytes = totalDownloadedBytes; +} + +/* + * Function name: UserStats_set_totalUploadedBytes + * Description: Set total amount of uploaded byte by the user. + * Arguments: us - pointer to UserStats structure + * totalUploadedBytes - total amount of uploaded bytes by the user + */ + +void +UserStats_set_totalUploadedBytes(UserStats* us, int totalUploadedBytes) +{ + assert(us != NULL); + if (us == NULL) { + return; + } + us->totalUploadedBytes = totalUploadedBytes; +} + +/* + * Function name: UserStats_get_lastActivity + * Description: Get time of the last user activity (upload or download). + * Arguments: us - pointer to UserStats structure + * Returns: Time of the last user activity. + */ + +time_t +UserStats_get_lastActivity(UserStats* us) +{ + assert(us != NULL); + if (us == NULL) { + return 0; + } + return us->lastActivity; +} + +/* + * Function name: UserStats_get_totalDownloadedBytes + * Description: Get total amount of downloaded bytes by the user. + * Arguments: us - pointer to UserStats structure + * Returns: Total amount of downloaded bytes by the user. + */ + +int +UserStats_get_totalDownloadedBytes(UserStats* us) +{ + assert(us != NULL); + if (us == NULL) { + return 0; + } + return us->totalDownloadedBytes; +} + +/* + * Function name: UserStats_get_totalUploadedBytes + * Description: Get total amount of uploaded bytes by the user. + * Arguments: us - pointer to UserStats structure + * Returns: Total amount of uploaded bytes by the user. + */ + +int +UserStats_get_totalUploadedBytes(UserStats* us) +{ + assert(us != NULL); + if (us == NULL) { + return 0; + } + return us->totalUploadedBytes; +} + +/* + * Function name: UserStats_add_download + * Description: Add bytes to the totalDownloadedBytes, update the lastActivity + * and downloadSpeed. + * Arguments: us - pointer to UserStats structure + * bytes - amount of bytes to add + */ + +void +UserStats_add_download(UserStats* us, int bytes) +{ + time_t now; + + assert(us != NULL); + + if (us == NULL) { + return; + } + + /* get the current time */ + time(&now); + + /* update counters */ + switch (now - us->lastDSQChange) { + case 0: { + us->downloadSpeedQueue[us->downloadSQP] += bytes; + break; + } + case 2: { + us->downloadSQP = (us->downloadSQP + 1) % 3; + us->downloadSpeedQueue[us->downloadSQP] = 0; + } + case 1: { + us->downloadSQP = (us->downloadSQP + 1) % 3; + us->downloadSpeedQueue[us->downloadSQP] = bytes; + break; + } + default: { + us->downloadSpeedQueue[0] = us->downloadSpeedQueue[1] = us->downloadSpeedQueue[2] = 0; + us->downloadSpeedQueue[us->downloadSQP] = bytes; + } + } + + /* update total upload */ + us->totalDownloadedBytes += bytes; + + /* update last activity */ + us->lastActivity = now; + + /* update last speed queue change */ + us->lastDSQChange = now; +} + +/* + * Function name: UserStats_add_upload + * Description: Add bytes to the totalUploadedBytes, update the lastActivity + * and uploadSpeed. + * Arguments: us - pointer to UserStats structure + * bytes - amount of bytes to add + */ + +void +UserStats_add_upload(UserStats* us, int bytes) +{ + time_t now; + + assert(us != NULL); + + if (us == NULL) { + return; + } + + /* get the current time */ + time(&now); + + /* update counters */ + switch (now - us->lastUSQChange) { + case 0: { + us->uploadSpeedQueue[us->uploadSQP] += bytes; + break; + } + case 2: { + us->uploadSQP = (us->uploadSQP + 1) % 3; + us->uploadSpeedQueue[us->uploadSQP] = 0; + } + case 1: { + us->uploadSQP = (us->uploadSQP + 1) % 3; + us->uploadSpeedQueue[us->uploadSQP] = bytes; + break; + } + default: { + us->uploadSpeedQueue[0] = us->uploadSpeedQueue[1] = us->uploadSpeedQueue[2] = 0; + us->uploadSpeedQueue[us->uploadSQP] = bytes; + } + } + + /* update total upload */ + us->totalUploadedBytes += bytes; + + /* update last activity */ + us->lastActivity = now; + + /* update last speed queue change */ + us->lastUSQChange = now; +} + +/* + * Function name: UserStats_get_downloadSpeed + * Description: Get the average download speed from the last three seconds. + * Arguments: us - pointer to UserStats structure + * Returns: The average download speed from the last three seconds. + */ + +double +UserStats_get_downloadSpeed(UserStats* us) +{ + time_t now; + + assert(us != NULL); + + if (us == NULL) { + return 0.0; + } + + /* get the current time */ + time(&now); + + /* update pointer */ + switch (now - us->lastDSQChange) { + case 0: { + break; + } + case 2: { + us->downloadSQP = (us->downloadSQP + 1) % 3; + us->downloadSpeedQueue[us->downloadSQP] = 0; + } + case 1: { + us->downloadSQP = (us->downloadSQP + 1) % 3; + us->downloadSpeedQueue[us->downloadSQP] = 0; + break; + } + default: { + us->downloadSpeedQueue[0] = us->downloadSpeedQueue[1] = us->downloadSpeedQueue[2] = 0; + } + } + + /* update last speed queue change */ + us->lastDSQChange = now; + + /* return current download speed */ + return (((double)(us->downloadSpeedQueue[0] + us->downloadSpeedQueue[1] + us->downloadSpeedQueue[2])) / 3.0); +} + +/* + * Function name: UserStats_get_uploadSpeed + * Description: Get the average upload speed from the last three seconds. + * Arguments: us - pointer to UserStats structure + * Returns: The average upload speed from the last three seconds. + */ + +double +UserStats_get_uploadSpeed(UserStats* us) +{ + time_t now; + + assert(us != NULL); + + if (us == NULL) { + return 0.0; + } + + /* get the current time */ + time(&now); + + /* update pointer */ + switch (now - us->lastUSQChange) { + case 0: { + break; + } + case 2: { + us->uploadSQP = (us->uploadSQP + 1) % 3; + us->uploadSpeedQueue[us->uploadSQP] = 0; + } + case 1: { + us->uploadSQP = (us->uploadSQP + 1) % 3; + us->uploadSpeedQueue[us->uploadSQP] = 0; + break; + } + default: { + us->uploadSpeedQueue[0] = us->uploadSpeedQueue[1] = us->uploadSpeedQueue[2] = 0; + } + } + + /* update last speed queue change */ + us->lastUSQChange = now; + + /* return current download speed */ + return (((double)(us->uploadSpeedQueue[0] + us->uploadSpeedQueue[1] + us->uploadSpeedQueue[2])) / 3.0); +} + +/* + * Function name: UserStats_clear + * Description: Clear the UserStats structure. Set all variables to default values. + * Arguments: us - pointer to UserStats structure + */ + +void +UserStats_clear(UserStats* us) +{ + assert(us != NULL); + if (us == NULL) { + return; + } + us->lastActivity = 0; + us->lastUSQChange = 0; + us->lastDSQChange = 0; + us->totalDownloadedBytes = 0; + us->totalUploadedBytes = 0; + us->uploadSQP = 0; + us->uploadSpeedQueue[0] = us->uploadSpeedQueue[1] = us->uploadSpeedQueue[2] = 0; + us->downloadSQP = 0; + us->downloadSpeedQueue[0] = us->downloadSpeedQueue[1] = us->downloadSpeedQueue[2] = 0; +} diff --git a/src/user_stats_struct.h b/src/user_stats_struct.h new file mode 100644 index 0000000..dc33dd4 --- /dev/null +++ b/src/user_stats_struct.h @@ -0,0 +1,59 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _JS_USER_STATS_STRUCT_H +#define _JS_USER_STATS_STRUCT_H + +#include <sys/types.h> + +typedef struct { + time_t lastActivity; + time_t lastUSQChange; + time_t lastDSQChange; + int totalDownloadedBytes; + int totalUploadedBytes; + int uploadSQP; + int uploadSpeedQueue[3]; + int downloadSQP; + int downloadSpeedQueue[3]; +} UserStats; + +/* 'constructor' */ +UserStats* UserStats_new(); +/* 'destructor' */ +void UserStats_free(UserStats** us); +/* setters */ +void UserStats_set_lastActivity(UserStats* us, time_t lastActivity); +void UserStats_set_totalDownloadedBytes(UserStats* us, int totalDownloadedBytes); +void UserStats_set_totalUploadedBytes(UserStats* us, int totalUploadedBytes); +/* getters */ +time_t UserStats_get_lastActivity(UserStats* us); +int UserStats_get_totalDownloadedBytes(UserStats* us); +int UserStats_get_totalUploadedBytes(UserStats* us); +/* other methods */ +void UserStats_add_download(UserStats* us, int bytes); +void UserStats_add_upload(UserStats* us, int bytes); +double UserStats_get_downloadSpeed(UserStats* us); +double UserStats_get_uploadSpeed(UserStats* us); +/* other */ +void UserStats_clear(UserStats* us); + +#endif diff --git a/src/usernames.c b/src/usernames.c new file mode 100644 index 0000000..4f0b14d --- /dev/null +++ b/src/usernames.c @@ -0,0 +1,63 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> +#include <assert.h> + +#include "usernames.h" + +/* + * Function name: get_username + * Description: Returns the id of the user. + * Arguments: pointer - the server realm + * user - the number of the user + * Returns: The id of the user. + */ + +int +get_username(ServerRealm* pointer, int user) +{ + assert(pointer != NULL); + return ConnectUser_get_userId(ServerRealm_get_usersTable(pointer)[user]); +} + +/* + * Function name: get_usernumber + * Description: Returns the number of the user. + * Arguments: pointer - the server realm + * user - the id of the user + * Returns: The number of the user. + */ + +int +get_usernumber(ServerRealm* pointer, int userid) +{ + int i; + + assert(pointer != NULL); + + for (i = 0; i < ServerRealm_get_usersLimit(pointer); ++i) { + if (userid == ConnectUser_get_userId(ServerRealm_get_usersTable(pointer)[i])) { + return i; + } + } + + return -1; +} diff --git a/src/usernames.h b/src/usernames.h new file mode 100644 index 0000000..d7f358f --- /dev/null +++ b/src/usernames.h @@ -0,0 +1,31 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "activefor.h" +#include "server_realm_struct.h" + +#ifndef _JS_USERNAMES_H +#define _JS_USERNAMES_H + +int get_username(ServerRealm*, int); +int get_usernumber(ServerRealm*, int); + +#endif + diff --git a/src/usr_cli_struct.c b/src/usr_cli_struct.c new file mode 100644 index 0000000..439fb62 --- /dev/null +++ b/src/usr_cli_struct.c @@ -0,0 +1,299 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "usr_cli_struct.h" +#include "string_functions.h" + +/* + * Function name: UsrCli_new + * Description: Create and initialize new UsrCli structure. + * Returns: Newly created UsrCli structure. + */ + +UsrCli* +UsrCli_new() +{ + UsrCli* tmp = calloc(1, sizeof(UsrCli)); + assert(tmp != NULL); + if (tmp == NULL) { + return NULL; + } + return tmp; +} + +/* + * Function name: UsrCli_free + * Description: Free the memory allocated for UsrCli structure. + * Arguments: uc - pointer to pointer to UsrCli structure + */ + +void +UsrCli_free(UsrCli** uc) +{ + assert(uc != NULL); + if (uc == NULL) { + return; + } + assert((*uc) != NULL); + if ((*uc) == NULL) { + return; + } + if ((*uc)->listenPortName) { + free((*uc)->listenPortName); + (*uc)->listenPortName = NULL; + } + if ((*uc)->managePortName) { + free((*uc)->managePortName); + (*uc)->managePortName = NULL; + } + free((*uc)); + (*uc) = NULL; +} + +/* Function name: UsrCli_set_listenPortName + * Description: Set listen port name. + * Arguments: uc - pointer to UsrCli structure + * listenPortName - listen port name + */ + +void +UsrCli_set_listenPortName(UsrCli* uc, char* listenPortName) +{ + char* tmp; + + assert(uc != NULL); + + if (uc == NULL) { + return; + } + if ((tmp = rindex(listenPortName, ':')) != NULL) { + (*tmp) = 0; + ++tmp; + string_cp(&(uc->listenHostName), listenPortName); + string_cp(&(uc->listenPortName), tmp); + } + else { + string_cp(&(uc->listenPortName), listenPortName); + } +} + +/* + * Function name: UsrCli_set_managePortName + * Description: Set manage port name. + * Arguments: uc - pointer to UsrCli structure + * managePortName - manage port name + */ + +void +UsrCli_set_managePortName(UsrCli* uc, char* managePortName) +{ + char* tmp; + + assert(uc != NULL); + + if (uc == NULL) { + return; + } + if ((tmp = rindex(managePortName, ':')) != NULL) { + (*tmp) = 0; + ++tmp; + string_cp(&(uc->manageHostName), managePortName); + string_cp(&(uc->managePortName), tmp); + } + else { + string_cp(&(uc->managePortName), managePortName); + } +} + +/* + * Function name: UsrCli_set_listenFd + * Description: Set listen file descriptor. + * Arguments: uc - pointer to UsrCli structure + * listenFd - listen file descriptor + */ + +void +UsrCli_set_listenFd(UsrCli* uc, int listenFd) +{ + assert(uc != NULL); + if (uc == NULL) { + return; + } + uc->listenFd = listenFd; +} + +/* + * Function name: UsrCli_set_manageFd + * Description: Set manage file descriptor. + * Arguments: uc - pointer to UsrCli structure + * manageFd - manage file descriptor + */ + +void +UsrCli_set_manageFd(UsrCli* uc, int manageFd) +{ + assert(uc != NULL); + if (uc == NULL) { + return; + } + uc->manageFd = manageFd; +} + +/* + * Function name: UsrCli_set_number + * Description: Sets the UsrCli number in the structures connected with manage port. + * Arguments: uc - pointer to UsrCli structure + * number - the number of the UsrCli structure + */ + +void +UsrCli_set_number(UsrCli* uc, int number) +{ + assert(uc != NULL); + assert(number >= 0); + if (uc == NULL) { + return; + } + uc->number = number; +} + +/* Function name: UsrCli_get_listenPortName + * Description: Get listen port name. + * Arguments: uc - pointer to UsrCli structure + * Returns: Listen port name. + */ + +char* +UsrCli_get_listenPortName(UsrCli* uc) +{ + assert(uc != NULL); + if (uc == NULL) { + return NULL; + } + return uc->listenPortName; +} + +/* + * Function name: UsrCli_get_managePortName + * Description: Get manage port name. + * Arguments: uc - pointer to UsrCli structure + * Returns: Manage port name. + */ + +char* +UsrCli_get_managePortName(UsrCli* uc) +{ + assert(uc != NULL); + if (uc == NULL) { + return NULL; + } + return uc->managePortName; +} + +/* + * Function name: UsrCli_get_listenFd + * Description: Get listen file descriptor. + * Arguments: uc - pointer to UsrCli structure + * Returns: Listen file descriptor. + */ + +int +UsrCli_get_listenFd(UsrCli* uc) +{ + assert(uc != NULL); + if (uc == NULL) { + return -1; + } + return uc->listenFd; +} + +/* + * Function name: UsrCli_get_manageFd + * Description: Get manage file descriptor. + * Arguments: uc - pointer to UsrCli structure + * Returns: Manage file desciptor. + */ + +int +UsrCli_get_manageFd(UsrCli* uc) +{ + assert(uc != NULL); + if (uc == NULL) { + return -1; + } + return uc->manageFd; +} + +/* + * Function name: UsrCli_get_listenHostName + * Description: Get host name used for listenFd in ip_connect function or NULL, if not set. + * Arguments: uc - pointer to UsrCli structure + * Returns: Host name used for listenFd in ip_connect function or NULL, if not set. + */ + +char* +UsrCli_get_listenHostName(UsrCli* uc) +{ + assert(uc != NULL); + if (uc == NULL) { + return NULL; + } + return uc->listenHostName; +} + +/* + * Function name: UsrCli_get_manageHostName + * Description: Get host name used for manageFd in ip_connect function or NULL, if not set. + * Arguments: uc - pointer to UsrCli structure + * Returns: Host name used for manageFd in ip_connect function or NULL, if not set. + */ + +char* +UsrCli_get_manageHostName(UsrCli* uc) +{ + assert(uc != NULL); + if (uc == NULL) { + return NULL; + } + return uc->manageHostName; +} + +/* + * Function name: UsrCli_get_number + * Description: Gets the number of the UsrCli structure. + * Arguments: uc - pointer to UsrCli structure + * Returns: The number of the UsrCli structure. + */ + +int +UsrCli_get_number(UsrCli* uc) +{ + assert(uc != NULL); + if (uc == NULL) { + return -1; + } + return uc->number; +} diff --git a/src/usr_cli_struct.h b/src/usr_cli_struct.h new file mode 100644 index 0000000..ddbbe97 --- /dev/null +++ b/src/usr_cli_struct.h @@ -0,0 +1,54 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003-2007 jeremian <jeremian [at] poczta.fm> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _JS_USR_CLI_STRUCT_H +#define _JS_USR_CLI_STRUCT_H + +typedef struct { + char* listenHostName; + char* manageHostName; + char* listenPortName; + char* managePortName; + int listenFd; + int manageFd; + int number; +} UsrCli; + +/* 'constructor' */ +UsrCli* UsrCli_new(); +/* 'destructor' */ +void UsrCli_free(UsrCli** uc); +/* setters */ +void UsrCli_set_listenPortName(UsrCli* uc, char* listenPortName); +void UsrCli_set_managePortName(UsrCli* uc, char* managePortName); +void UsrCli_set_listenFd(UsrCli* uc, int listenFd); +void UsrCli_set_manageFd(UsrCli* uc, int manageFd); +void UsrCli_set_number(UsrCli* uc, int number); +/* getters */ +char* UsrCli_get_listenPortName(UsrCli* uc); +char* UsrCli_get_managePortName(UsrCli* uc); +int UsrCli_get_listenFd(UsrCli* uc); +int UsrCli_get_manageFd(UsrCli* uc); +char* UsrCli_get_listenHostName(UsrCli* uc); +char* UsrCli_get_manageHostName(UsrCli* uc); +int UsrCli_get_number(UsrCli* uc); + +#endif |