mirror of
https://github.com/kingk85/uFTP.git
synced 2025-07-03 04:38:41 +03:00
Compare commits
36 Commits
v2.6.0stab
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
646404da3a | ||
![]() |
74d319f6bb | ||
![]() |
e8894937a3 | ||
![]() |
b8a37c88ec | ||
![]() |
e84a649ebd | ||
![]() |
6159ba6268 | ||
![]() |
48b4430c17 | ||
![]() |
de7ff6a710 | ||
![]() |
a35737d02a | ||
![]() |
94f7b75d6a | ||
![]() |
d3be2eafde | ||
![]() |
bd17059c41 | ||
![]() |
2f62192b6c | ||
![]() |
cdc4e4adc9 | ||
![]() |
5b6919a7b1 | ||
![]() |
b926a26b22 | ||
![]() |
358c409996 | ||
![]() |
5d95b42456 | ||
![]() |
e4ea93a280 | ||
![]() |
7869d55f95 | ||
![]() |
4565a14d2c | ||
![]() |
6db29a0f33 | ||
![]() |
a2de9b1a7c | ||
![]() |
90f44e3a98 | ||
![]() |
ec5c155ccb | ||
![]() |
63251ca3e4 | ||
![]() |
509910642d | ||
![]() |
2f355d91d8 | ||
![]() |
8302e82366 | ||
![]() |
998b720fa5 | ||
![]() |
89e64c2ddc | ||
![]() |
5778081be9 | ||
![]() |
8f78c9e7f1 | ||
![]() |
38887ed633 | ||
![]() |
4c0b19e6d6 | ||
![]() |
d0191ca20d |
38
Makefile
38
Makefile
@ -8,6 +8,11 @@ CC=gcc
|
|||||||
OUTPATH=./build/
|
OUTPATH=./build/
|
||||||
SOURCE_MODULES_PATH=./library/
|
SOURCE_MODULES_PATH=./library/
|
||||||
|
|
||||||
|
#uncommend next lines to enable printf
|
||||||
|
ENABLE_PRINTF=
|
||||||
|
#uncommend next lines to enable printf
|
||||||
|
#ENABLE_PRINTF=-D ENABLE_PRINTF -D ENABLE_PRINTF_ERROR
|
||||||
|
|
||||||
#FOR DEBUG PURPOSE
|
#FOR DEBUG PURPOSE
|
||||||
#CFLAGSTEMP=-c -Wall -I. -g -O0
|
#CFLAGSTEMP=-c -Wall -I. -g -O0
|
||||||
|
|
||||||
@ -16,7 +21,7 @@ ENDFLAG=
|
|||||||
#ENDFLAG=-static
|
#ENDFLAG=-static
|
||||||
|
|
||||||
#FOR RELEASE
|
#FOR RELEASE
|
||||||
CFLAGSTEMP=-c -Wall -I.
|
CFLAGSTEMP=-c -Wall -Wno-unused-variable -Wno-unused-but-set-variable -I.
|
||||||
|
|
||||||
OPTIMIZATION=-O3
|
OPTIMIZATION=-O3
|
||||||
HEADERS=-I
|
HEADERS=-I
|
||||||
@ -33,13 +38,17 @@ ENABLE_OPENSSL_SUPPORT=
|
|||||||
#ENABLE_OPENSSL_SUPPORT=-D OPENSSL_ENABLED
|
#ENABLE_OPENSSL_SUPPORT=-D OPENSSL_ENABLED
|
||||||
#LIBS=-lpthread -lssl -lcrypto
|
#LIBS=-lpthread -lssl -lcrypto
|
||||||
|
|
||||||
|
ENABLE_IPV6_SUPPORT=
|
||||||
|
#TO ENABLE IPV6 support uncomment next line
|
||||||
|
ENABLE_IPV6_SUPPORT=-D IPV6_ENABLED
|
||||||
|
|
||||||
ENABLE_PAM_SUPPORT=
|
ENABLE_PAM_SUPPORT=
|
||||||
PAM_AUTH_LIB=
|
PAM_AUTH_LIB=
|
||||||
#TO ENABLE PAM AUTH UNCOMMENT NEXT TWO LINES
|
#TO ENABLE PAM AUTH UNCOMMENT NEXT TWO LINES
|
||||||
#ENABLE_PAM_SUPPORT= -D PAM_SUPPORT_ENABLED
|
#ENABLE_PAM_SUPPORT= -D PAM_SUPPORT_ENABLED
|
||||||
#PAM_AUTH_LIB= -lpam
|
#PAM_AUTH_LIB= -lpam
|
||||||
|
|
||||||
CFLAGS=$(CFLAGSTEMP) $(ENABLE_LARGE_FILE_SUPPORT) $(ENABLE_OPENSSL_SUPPORT) $(ENABLE_PAM_SUPPORT)
|
CFLAGS=$(CFLAGSTEMP) $(ENABLE_LARGE_FILE_SUPPORT) $(ENABLE_OPENSSL_SUPPORT) $(ENABLE_IPV6_SUPPORT) $(ENABLE_PAM_SUPPORT) $(ENABLE_PRINTF)
|
||||||
|
|
||||||
all: $(BUILDFILES)
|
all: $(BUILDFILES)
|
||||||
|
|
||||||
@ -53,8 +62,15 @@ start:
|
|||||||
end:
|
end:
|
||||||
@echo Build process end
|
@echo Build process end
|
||||||
|
|
||||||
uFTP: uFTP.c fileManagement.o configRead.o logFunctions.o ftpCommandElaborate.o ftpData.o ftpServer.o daemon.o signals.o connection.o openSsl.o dynamicMemory.o errorHandling.o auth.o log.o
|
uFTP: uFTP.c fileManagement.o configRead.o ftpCommandElaborate.o \
|
||||||
@$(CC) $(ENABLE_LARGE_FILE_SUPPORT) $(ENABLE_OPENSSL_SUPPORT) uFTP.c $(LIBPATH)dynamicVectors.o $(LIBPATH)fileManagement.o $(LIBPATH)configRead.o $(LIBPATH)logFunctions.o $(LIBPATH)ftpCommandElaborate.o $(LIBPATH)ftpData.o $(LIBPATH)ftpServer.o $(LIBPATH)daemon.o $(LIBPATH)signals.o $(LIBPATH)connection.o $(LIBPATH)openSsl.o $(LIBPATH)dynamicMemory.o $(LIBPATH)errorHandling.o $(LIBPATH)auth.o $(LIBPATH)log.o -o $(OUTPATH)uFTP $(LIBS) $(PAM_AUTH_LIB) $(ENDFLAG)
|
ftpData.o ftpServer.o daemon.o signals.o connection.o openSsl.o \
|
||||||
|
dynamicMemory.o errorHandling.o auth.o log.o controlChannel.o dataChannel.o serverHelpers.o
|
||||||
|
@$(CC) $(ENABLE_LARGE_FILE_SUPPORT) $(ENABLE_OPENSSL_SUPPORT) uFTP.c \
|
||||||
|
$(LIBPATH)dynamicVectors.o $(LIBPATH)fileManagement.o $(LIBPATH)configRead.o \
|
||||||
|
$(LIBPATH)ftpCommandElaborate.o $(LIBPATH)ftpData.o $(LIBPATH)ftpServer.o $(LIBPATH)daemon.o $(LIBPATH)signals.o \
|
||||||
|
$(LIBPATH)connection.o $(LIBPATH)openSsl.o $(LIBPATH)dynamicMemory.o $(LIBPATH)errorHandling.o $(LIBPATH)auth.o \
|
||||||
|
$(LIBPATH)log.o $(LIBPATH)controlChannel.o $(LIBPATH)dataChannel.o $(LIBPATH)serverHelpers.o \
|
||||||
|
-o $(OUTPATH)uFTP $(LIBS) $(PAM_AUTH_LIB) $(ENDFLAG)
|
||||||
|
|
||||||
daemon.o:
|
daemon.o:
|
||||||
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)daemon.c -o $(LIBPATH)daemon.o
|
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)daemon.c -o $(LIBPATH)daemon.o
|
||||||
@ -83,14 +99,14 @@ fileManagement.o:
|
|||||||
signals.o:
|
signals.o:
|
||||||
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)signals.c -o $(LIBPATH)signals.o
|
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)signals.c -o $(LIBPATH)signals.o
|
||||||
|
|
||||||
connection.o:
|
connection.o: log.o
|
||||||
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)connection.c -o $(LIBPATH)connection.o
|
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)connection.c -o $(LIBPATH)connection.o
|
||||||
|
|
||||||
log.o:
|
log.o:
|
||||||
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)log.c -o $(LIBPATH)log.o
|
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)log.c -o $(LIBPATH)log.o
|
||||||
|
|
||||||
logFunctions.o:
|
serverHelpers.o:
|
||||||
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)logFunctions.c -o $(LIBPATH)logFunctions.o
|
@$(CC) $(CFLAGS) $(SOURCE_MODULES_PATH)serverHelpers.c -o $(LIBPATH)serverHelpers.o
|
||||||
|
|
||||||
ftpCommandElaborate.o:
|
ftpCommandElaborate.o:
|
||||||
@$(CC) $(CFLAGS) ftpCommandElaborate.c -o $(LIBPATH)ftpCommandElaborate.o
|
@$(CC) $(CFLAGS) ftpCommandElaborate.c -o $(LIBPATH)ftpCommandElaborate.o
|
||||||
@ -98,7 +114,13 @@ ftpCommandElaborate.o:
|
|||||||
ftpData.o:
|
ftpData.o:
|
||||||
@$(CC) $(CFLAGS) ftpData.c -o $(LIBPATH)ftpData.o
|
@$(CC) $(CFLAGS) ftpData.c -o $(LIBPATH)ftpData.o
|
||||||
|
|
||||||
ftpServer.o: openSsl.o
|
controlChannel.o:
|
||||||
|
@$(CC) $(CFLAGS) ./controlChannel/controlChannel.c -o $(LIBPATH)controlChannel.o
|
||||||
|
|
||||||
|
dataChannel.o:
|
||||||
|
@$(CC) $(CFLAGS) ./dataChannel/dataChannel.c -o $(LIBPATH)dataChannel.o
|
||||||
|
|
||||||
|
ftpServer.o: openSsl.o controlChannel.o dataChannel.o
|
||||||
@$(CC) $(CFLAGS) ftpServer.c -o $(LIBPATH)ftpServer.o
|
@$(CC) $(CFLAGS) ftpServer.c -o $(LIBPATH)ftpServer.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
128
MakefileNetBeans
128
MakefileNetBeans
@ -1,128 +0,0 @@
|
|||||||
#
|
|
||||||
# There exist several targets which are by default empty and which can be
|
|
||||||
# used for execution of your targets. These targets are usually executed
|
|
||||||
# before and after some main targets. They are:
|
|
||||||
#
|
|
||||||
# .build-pre: called before 'build' target
|
|
||||||
# .build-post: called after 'build' target
|
|
||||||
# .clean-pre: called before 'clean' target
|
|
||||||
# .clean-post: called after 'clean' target
|
|
||||||
# .clobber-pre: called before 'clobber' target
|
|
||||||
# .clobber-post: called after 'clobber' target
|
|
||||||
# .all-pre: called before 'all' target
|
|
||||||
# .all-post: called after 'all' target
|
|
||||||
# .help-pre: called before 'help' target
|
|
||||||
# .help-post: called after 'help' target
|
|
||||||
#
|
|
||||||
# Targets beginning with '.' are not intended to be called on their own.
|
|
||||||
#
|
|
||||||
# Main targets can be executed directly, and they are:
|
|
||||||
#
|
|
||||||
# build build a specific configuration
|
|
||||||
# clean remove built files from a configuration
|
|
||||||
# clobber remove all built files
|
|
||||||
# all build all configurations
|
|
||||||
# help print help mesage
|
|
||||||
#
|
|
||||||
# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
|
|
||||||
# .help-impl are implemented in nbproject/makefile-impl.mk.
|
|
||||||
#
|
|
||||||
# Available make variables:
|
|
||||||
#
|
|
||||||
# CND_BASEDIR base directory for relative paths
|
|
||||||
# CND_DISTDIR default top distribution directory (build artifacts)
|
|
||||||
# CND_BUILDDIR default top build directory (object files, ...)
|
|
||||||
# CONF name of current configuration
|
|
||||||
# CND_PLATFORM_${CONF} platform name (current configuration)
|
|
||||||
# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
|
|
||||||
# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
|
|
||||||
# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
|
|
||||||
# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
|
|
||||||
# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
|
|
||||||
# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
|
|
||||||
#
|
|
||||||
# NOCDDL
|
|
||||||
|
|
||||||
|
|
||||||
# Environment
|
|
||||||
MKDIR=mkdir
|
|
||||||
CP=cp
|
|
||||||
CCADMIN=CCadmin
|
|
||||||
|
|
||||||
|
|
||||||
# build
|
|
||||||
build: .build-post
|
|
||||||
|
|
||||||
.build-pre:
|
|
||||||
# Add your pre 'build' code here...
|
|
||||||
|
|
||||||
.build-post: .build-impl
|
|
||||||
# Add your post 'build' code here...
|
|
||||||
|
|
||||||
|
|
||||||
# clean
|
|
||||||
clean: .clean-post
|
|
||||||
|
|
||||||
.clean-pre:
|
|
||||||
# Add your pre 'clean' code here...
|
|
||||||
|
|
||||||
.clean-post: .clean-impl
|
|
||||||
# Add your post 'clean' code here...
|
|
||||||
|
|
||||||
|
|
||||||
# clobber
|
|
||||||
clobber: .clobber-post
|
|
||||||
|
|
||||||
.clobber-pre:
|
|
||||||
# Add your pre 'clobber' code here...
|
|
||||||
|
|
||||||
.clobber-post: .clobber-impl
|
|
||||||
# Add your post 'clobber' code here...
|
|
||||||
|
|
||||||
|
|
||||||
# all
|
|
||||||
all: .all-post
|
|
||||||
|
|
||||||
.all-pre:
|
|
||||||
# Add your pre 'all' code here...
|
|
||||||
|
|
||||||
.all-post: .all-impl
|
|
||||||
# Add your post 'all' code here...
|
|
||||||
|
|
||||||
|
|
||||||
# build tests
|
|
||||||
build-tests: .build-tests-post
|
|
||||||
|
|
||||||
.build-tests-pre:
|
|
||||||
# Add your pre 'build-tests' code here...
|
|
||||||
|
|
||||||
.build-tests-post: .build-tests-impl
|
|
||||||
# Add your post 'build-tests' code here...
|
|
||||||
|
|
||||||
|
|
||||||
# run tests
|
|
||||||
test: .test-post
|
|
||||||
|
|
||||||
.test-pre: build-tests
|
|
||||||
# Add your pre 'test' code here...
|
|
||||||
|
|
||||||
.test-post: .test-impl
|
|
||||||
# Add your post 'test' code here...
|
|
||||||
|
|
||||||
|
|
||||||
# help
|
|
||||||
help: .help-post
|
|
||||||
|
|
||||||
.help-pre:
|
|
||||||
# Add your pre 'help' code here...
|
|
||||||
|
|
||||||
.help-post: .help-impl
|
|
||||||
# Add your post 'help' code here...
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# include project implementation makefile
|
|
||||||
include nbproject/Makefile-impl.mk
|
|
||||||
|
|
||||||
# include project make variables
|
|
||||||
include nbproject/Makefile-variables.mk
|
|
@ -1,6 +1,6 @@
|
|||||||
cd ..
|
cd ..
|
||||||
make clean
|
make clean
|
||||||
make
|
make -j 8
|
||||||
cd build
|
cd build
|
||||||
sudo killall uFTP
|
sudo killall uFTP
|
||||||
./uFTP
|
./uFTP
|
||||||
|
@ -7,5 +7,5 @@ cp build/uFTP /var/www/html/uftpserver.com/downloads/binaries/latest/armhf/uFTP
|
|||||||
make clean
|
make clean
|
||||||
make CC=musl-gcc ENDFLAG=-static
|
make CC=musl-gcc ENDFLAG=-static
|
||||||
cp build/uFTP /var/www/html/uftpserver.com/downloads/binaries/latest/x64/uFTP
|
cp build/uFTP /var/www/html/uftpserver.com/downloads/binaries/latest/x64/uFTP
|
||||||
|
cp uftpd.cfg /var/www/html/uftpserver.com/downloads/configuration_sample/uftpd.cfg
|
||||||
cd build
|
cd build
|
325
controlChannel/controlChannel.c
Normal file
325
controlChannel/controlChannel.c
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2018 Ugo Cirmignani.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* FTP LIBS */
|
||||||
|
#include "library/fileManagement.h"
|
||||||
|
#include "library/configRead.h"
|
||||||
|
#include "library/signals.h"
|
||||||
|
#include "library/openSsl.h"
|
||||||
|
#include "library/connection.h"
|
||||||
|
#include "library/dynamicMemory.h"
|
||||||
|
#include "library/errorHandling.h"
|
||||||
|
#include "library/daemon.h"
|
||||||
|
#include "library/log.h"
|
||||||
|
|
||||||
|
#include "ftpServer.h"
|
||||||
|
#include "ftpData.h"
|
||||||
|
#include "ftpCommandsElaborate.h"
|
||||||
|
#include "debugHelper.h"
|
||||||
|
#include "controlChannel.h"
|
||||||
|
|
||||||
|
/* Private function definition */
|
||||||
|
static int processCommand(int processingElement, ftpDataType *ftpData);
|
||||||
|
static void memoryDebug(ftpDataType *ftpData);
|
||||||
|
|
||||||
|
void evaluateControlChannel(ftpDataType *ftpData)
|
||||||
|
{
|
||||||
|
int returnCode = 0;
|
||||||
|
|
||||||
|
//Update watchdog timer
|
||||||
|
updateWatchDogTime((int)time(NULL));
|
||||||
|
|
||||||
|
//debug memory usage
|
||||||
|
memoryDebug(ftpData);
|
||||||
|
|
||||||
|
/* waits for socket activity, if no activity then checks for client socket timeouts */
|
||||||
|
if (selectWait(ftpData) == 0)
|
||||||
|
{
|
||||||
|
checkClientConnectionTimeout(ftpData);
|
||||||
|
flushLoginWrongTriesData(ftpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Main loop handle client commands */
|
||||||
|
for (int processingSock = 0; processingSock < ftpData->ftpParameters.maxClients; processingSock++)
|
||||||
|
{
|
||||||
|
/* close the connection if quit flag has been set */
|
||||||
|
if (ftpData->clients[processingSock].closeTheClient == 1)
|
||||||
|
{
|
||||||
|
closeClient(ftpData, processingSock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there are client pending connections, accept the connection if possible otherwise reject */
|
||||||
|
if ((returnCode = evaluateClientSocketConnection(ftpData)) == 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no data to check client is not connected, continue to check other clients */
|
||||||
|
if (isClientConnected(ftpData, processingSock) == 0)
|
||||||
|
{
|
||||||
|
/* socket is not conneted */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(ftpData->clients[processingSock].socketDescriptor, &ftpData->connectionData.rset) ||
|
||||||
|
FD_ISSET(ftpData->clients[processingSock].socketDescriptor, &ftpData->connectionData.eset))
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef OPENSSL_ENABLED
|
||||||
|
if (ftpData->clients[processingSock].tlsIsNegotiating == 1)
|
||||||
|
{
|
||||||
|
returnCode = SSL_accept(ftpData->clients[processingSock].ssl);
|
||||||
|
|
||||||
|
if (returnCode <= 0)
|
||||||
|
{
|
||||||
|
//my_printf("\nSSL NOT YET ACCEPTED: %d", returnCode);
|
||||||
|
ftpData->clients[processingSock].tlsIsEnabled = 0;
|
||||||
|
ftpData->clients[processingSock].tlsIsNegotiating = 1;
|
||||||
|
|
||||||
|
if ( ((int)time(NULL) - ftpData->clients[processingSock].tlsNegotiatingTimeStart) > TLS_NEGOTIATING_TIMEOUT )
|
||||||
|
{
|
||||||
|
ftpData->clients[processingSock].closeTheClient = 1;
|
||||||
|
LOGF("%sTLS timeout closing the client time:%lld, start time: %lld..", LOG_DEBUG_PREFIX, (int)time(NULL), ftpData->clients[processingSock].tlsNegotiatingTimeStart);
|
||||||
|
//my_printf("\nTLS timeout closing the client time:%lld, start time: %lld..", (int)time(NULL), ftpData->clients[processingSock].tlsNegotiatingTimeStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//my_printf("\nSSL ACCEPTED");
|
||||||
|
ftpData->clients[processingSock].tlsIsEnabled = 1;
|
||||||
|
ftpData->clients[processingSock].tlsIsNegotiating = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ftpData->clients[processingSock].tlsIsEnabled == 1)
|
||||||
|
{
|
||||||
|
#ifdef OPENSSL_ENABLED
|
||||||
|
ftpData->clients[processingSock].bufferIndex = SSL_read(ftpData->clients[processingSock].ssl, ftpData->clients[processingSock].buffer, CLIENT_BUFFER_STRING_SIZE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ftpData->clients[processingSock].bufferIndex = read(ftpData->clients[processingSock].socketDescriptor, ftpData->clients[processingSock].buffer, CLIENT_BUFFER_STRING_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//The client is not connected anymore
|
||||||
|
if ((ftpData->clients[processingSock].bufferIndex) == 0)
|
||||||
|
{
|
||||||
|
closeClient(ftpData, processingSock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Some commands has been received
|
||||||
|
if (ftpData->clients[processingSock].bufferIndex > 0)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int commandProcessStatus = 0;
|
||||||
|
for (i = 0; i < ftpData->clients[processingSock].bufferIndex; i++)
|
||||||
|
{
|
||||||
|
if (ftpData->clients[processingSock].commandIndex < CLIENT_COMMAND_STRING_SIZE)
|
||||||
|
{
|
||||||
|
if (ftpData->clients[processingSock].buffer[i] != '\r' && ftpData->clients[processingSock].buffer[i] != '\n')
|
||||||
|
{
|
||||||
|
ftpData->clients[processingSock].theCommandReceived[ftpData->clients[processingSock].commandIndex++] = ftpData->clients[processingSock].buffer[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftpData->clients[processingSock].buffer[i] == '\n')
|
||||||
|
{
|
||||||
|
ftpData->clients[processingSock].socketCommandReceived = 1;
|
||||||
|
//my_printf("\n Processing the command: %s", ftpData->clients[processingSock].theCommandReceived);
|
||||||
|
commandProcessStatus = processCommand(processingSock, ftpData);
|
||||||
|
//Echo unrecognized commands
|
||||||
|
if (commandProcessStatus == FTP_COMMAND_NOT_RECONIZED)
|
||||||
|
{
|
||||||
|
int returnCode = 0;
|
||||||
|
returnCode = socketPrintf(ftpData, processingSock, "s", "500 Unknown command\r\n");
|
||||||
|
if (returnCode < 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[processingSock].closeTheClient = 1;
|
||||||
|
LOG_ERROR("socketPrintf");
|
||||||
|
}
|
||||||
|
my_printf("\n COMMAND NOT SUPPORTED ********* %s", ftpData->clients[processingSock].buffer);
|
||||||
|
LOGF("%sCommand not supported: %s", LOG_DEBUG_PREFIX, ftpData->clients[processingSock].buffer);
|
||||||
|
}
|
||||||
|
else if (commandProcessStatus == FTP_COMMAND_PROCESSED)
|
||||||
|
{
|
||||||
|
ftpData->clients[processingSock].lastActivityTimeStamp = (int)time(NULL);
|
||||||
|
}
|
||||||
|
else if (commandProcessStatus == FTP_COMMAND_PROCESSED_WRITE_ERROR)
|
||||||
|
{
|
||||||
|
ftpData->clients[processingSock].closeTheClient = 1;
|
||||||
|
LOG_ERROR("ftp command processed error");
|
||||||
|
my_printf("\n Write error WARNING!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Command overflow can't be processed
|
||||||
|
int returnCode;
|
||||||
|
ftpData->clients[processingSock].commandIndex = 0;
|
||||||
|
memset(ftpData->clients[processingSock].theCommandReceived, 0, CLIENT_COMMAND_STRING_SIZE+1);
|
||||||
|
returnCode = socketPrintf(ftpData, processingSock, "s", "500 Unknown command\r\n");
|
||||||
|
if (returnCode <= 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[processingSock].closeTheClient = 1;
|
||||||
|
LOG_ERROR("socketPrintf");
|
||||||
|
}
|
||||||
|
my_printf("\n Command too long closing the client.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(ftpData->clients[processingSock].buffer, 0, CLIENT_BUFFER_STRING_SIZE+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Private static functions */
|
||||||
|
static void memoryDebug(ftpDataType *ftpData)
|
||||||
|
{
|
||||||
|
my_printf("\nUsed memory : %lld", DYNMEM_GetTotalMemory());
|
||||||
|
for (int memCount = 0; memCount < ftpData->ftpParameters.maxClients; memCount++)
|
||||||
|
{
|
||||||
|
if (ftpData->clients[memCount].memoryTable != NULL)
|
||||||
|
{
|
||||||
|
my_printf("\nftpData->clients[%d].memoryTable = %s", memCount, ftpData->clients[memCount].memoryTable->theName);
|
||||||
|
}
|
||||||
|
if (ftpData->clients[memCount].workerData.memoryTable != NULL)
|
||||||
|
{
|
||||||
|
my_printf("\nftpData->clients[%d].workerData.memoryTable = %s", memCount, ftpData->clients[memCount].workerData.memoryTable->theName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftpData->clients[memCount].workerData.directoryInfo.memoryTable != NULL)
|
||||||
|
{
|
||||||
|
my_printf("\nftpData->clients[%d].workerData.directoryInfo.memoryTable = %s", memCount, ftpData->clients[memCount].workerData.directoryInfo.memoryTable->theName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int processCommand(int processingElement, ftpDataType *ftpData)
|
||||||
|
{
|
||||||
|
//command handler structure
|
||||||
|
static CommandMapEntry commandMap[] = {
|
||||||
|
{"USER", parseCommandUser},
|
||||||
|
{"PASS", parseCommandPass},
|
||||||
|
{"SITE", parseCommandSite},
|
||||||
|
{"AUTH TLS", parseCommandAuth},
|
||||||
|
{"PROT", parseCommandProt},
|
||||||
|
{"PBSZ", parseCommandPbsz},
|
||||||
|
{"CCC", parseCommandCcc},
|
||||||
|
{"PWD", parseCommandPwd},
|
||||||
|
{"XPWD", parseCommandPwd},
|
||||||
|
{"SYST", parseCommandSyst},
|
||||||
|
{"FEAT", parseCommandFeat},
|
||||||
|
{"TYPE I", parseCommandTypeI},
|
||||||
|
{"TYPE A", parseCommandTypeI},
|
||||||
|
{"STRU F", parseCommandStruF},
|
||||||
|
{"MODE S", parseCommandModeS},
|
||||||
|
{"EPSV", parseCommandEpsv},
|
||||||
|
{"PASV", parseCommandPasv},
|
||||||
|
{"PORT", parseCommandPort},
|
||||||
|
{"EPRT", parseCommandEprt},
|
||||||
|
{"LIST", parseCommandList},
|
||||||
|
{"STAT", parseCommandStat},
|
||||||
|
{"CDUP", parseCommandCdup},
|
||||||
|
{"XCUP", parseCommandCdup},
|
||||||
|
{"CWD ..", parseCommandCdup},
|
||||||
|
{"CWD", parseCommandCwd},
|
||||||
|
{"REST", parseCommandRest},
|
||||||
|
{"RETR", parseCommandRetr},
|
||||||
|
{"STOR", parseCommandStor},
|
||||||
|
{"MKD", parseCommandMkd},
|
||||||
|
{"XMKD", parseCommandMkd},
|
||||||
|
{"ABOR", parseCommandAbor},
|
||||||
|
{"DELE", parseCommandDele},
|
||||||
|
{"OPTS", parseCommandOpts},
|
||||||
|
{"MDTM", parseCommandMdtm},
|
||||||
|
{"NLST", parseCommandNlst},
|
||||||
|
{"QUIT", parseCommandQuit},
|
||||||
|
{"RMD", parseCommandRmd},
|
||||||
|
{"XRMD", parseCommandRmd},
|
||||||
|
{"RNFR", parseCommandRnfr},
|
||||||
|
{"RNTO", parseCommandRnto},
|
||||||
|
{"SIZE", parseCommandSize},
|
||||||
|
{"APPE", parseCommandAppe},
|
||||||
|
{"NOOP", parseCommandNoop},
|
||||||
|
{"ACCT", parseCommandAcct}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define COMMAND_MAP_SIZE (sizeof(commandMap) / sizeof(CommandMapEntry))
|
||||||
|
|
||||||
|
int toReturn = 0;
|
||||||
|
//printTimeStamp();
|
||||||
|
my_printf("\nCommand received from (%d): %s", processingElement, ftpData->clients[processingElement].theCommandReceived);
|
||||||
|
|
||||||
|
cleanDynamicStringDataType(&ftpData->clients[processingElement].ftpCommand.commandArgs, 0, ftpData->clients[processingElement].memoryTable);
|
||||||
|
cleanDynamicStringDataType(&ftpData->clients[processingElement].ftpCommand.commandOps, 0, ftpData->clients[processingElement].memoryTable);
|
||||||
|
|
||||||
|
if (ftpData->clients[processingElement].login.userLoggedIn == 0 &&
|
||||||
|
(IS_NOT_CMD(ftpData->clients[processingElement].theCommandReceived, "USER") &&
|
||||||
|
IS_NOT_CMD(ftpData->clients[processingElement].theCommandReceived, "PASS") &&
|
||||||
|
IS_NOT_CMD(ftpData->clients[processingElement].theCommandReceived, "QUIT") &&
|
||||||
|
IS_NOT_CMD(ftpData->clients[processingElement].theCommandReceived, "PBSZ") &&
|
||||||
|
IS_NOT_CMD(ftpData->clients[processingElement].theCommandReceived, "PROT") &&
|
||||||
|
IS_NOT_CMD(ftpData->clients[processingElement].theCommandReceived, "CCC") &&
|
||||||
|
IS_NOT_CMD(ftpData->clients[processingElement].theCommandReceived, "AUTH TLS")))
|
||||||
|
{
|
||||||
|
toReturn = notLoggedInMessage(ftpData, processingElement);
|
||||||
|
ftpData->clients[processingElement].commandIndex = 0;
|
||||||
|
memset(ftpData->clients[processingElement].theCommandReceived, 0, CLIENT_COMMAND_STRING_SIZE+1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < COMMAND_MAP_SIZE; ++i)
|
||||||
|
{
|
||||||
|
if (IS_CMD(ftpData->clients[processingElement].theCommandReceived, commandMap[i].command))
|
||||||
|
{
|
||||||
|
my_printf("\n%s COMMAND RECEIVED", commandMap[i].command);
|
||||||
|
toReturn = commandMap[i].handler(ftpData, processingElement);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ftpData->clients[processingElement].commandIndex = 0;
|
||||||
|
memset(ftpData->clients[processingElement].theCommandReceived, 0, CLIENT_COMMAND_STRING_SIZE+1);
|
||||||
|
return toReturn;
|
||||||
|
}
|
16
controlChannel/controlChannel.h
Normal file
16
controlChannel/controlChannel.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef CTRL_CHANNEL_H
|
||||||
|
#define CTRL_CHANNEL_H
|
||||||
|
|
||||||
|
#include "ftpData.h"
|
||||||
|
|
||||||
|
typedef int (*CommandHandler)(struct FtpDataType*, int);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* command;
|
||||||
|
CommandHandler handler;
|
||||||
|
} CommandMapEntry;
|
||||||
|
|
||||||
|
void evaluateControlChannel(ftpDataType *ftpData);
|
||||||
|
|
||||||
|
#endif /* DATA_CHANNEL_H */
|
||||||
|
|
523
dataChannel/dataChannel.c
Normal file
523
dataChannel/dataChannel.c
Normal file
@ -0,0 +1,523 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2018 Ugo Cirmignani.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
/* FTP LIBS */
|
||||||
|
#include "library/fileManagement.h"
|
||||||
|
#include "library/configRead.h"
|
||||||
|
#include "library/signals.h"
|
||||||
|
#include "library/openSsl.h"
|
||||||
|
#include "library/connection.h"
|
||||||
|
#include "library/dynamicMemory.h"
|
||||||
|
#include "library/errorHandling.h"
|
||||||
|
#include "library/daemon.h"
|
||||||
|
#include "library/log.h"
|
||||||
|
|
||||||
|
#include "ftpServer.h"
|
||||||
|
#include "ftpData.h"
|
||||||
|
#include "ftpCommandsElaborate.h"
|
||||||
|
#include "debugHelper.h"
|
||||||
|
#include "dataChannel.h"
|
||||||
|
|
||||||
|
static int acceptConnection(cleanUpWorkerArgs *args);
|
||||||
|
static int processStorAppe(cleanUpWorkerArgs *args);
|
||||||
|
static int processListNlst(cleanUpWorkerArgs *args);
|
||||||
|
static int processRetr(cleanUpWorkerArgs *args);
|
||||||
|
|
||||||
|
void workerCleanup(cleanUpWorkerArgs *args)
|
||||||
|
{
|
||||||
|
ftpDataType *ftpData = args->ftpData;
|
||||||
|
int theSocketId = args->socketId;
|
||||||
|
int returnCode = 0;
|
||||||
|
|
||||||
|
//my_printf("\nWorker %d cleanup", theSocketId);
|
||||||
|
|
||||||
|
#ifdef OPENSSL_ENABLED
|
||||||
|
int error;
|
||||||
|
error = fcntl(ftpData->clients[theSocketId].workerData.socketConnection, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].dataChannelIsTls == 1)
|
||||||
|
{
|
||||||
|
if(ftpData->clients[theSocketId].workerData.passiveModeOn == 1)
|
||||||
|
{
|
||||||
|
//my_printf("\nSSL worker Shutdown 1");
|
||||||
|
returnCode = SSL_shutdown(ftpData->clients[theSocketId].workerData.serverSsl);
|
||||||
|
//my_printf("\nnSSL worker Shutdown 1 return code : %d", returnCode);
|
||||||
|
|
||||||
|
if (!returnCode)
|
||||||
|
{
|
||||||
|
shutdown(ftpData->clients[theSocketId].workerData.socketConnection, SHUT_RDWR);
|
||||||
|
shutdown(ftpData->clients[theSocketId].workerData.passiveListeningSocket, SHUT_RDWR);
|
||||||
|
|
||||||
|
//my_printf("\nSSL worker Shutdown 2");
|
||||||
|
returnCode = SSL_shutdown(ftpData->clients[theSocketId].workerData.serverSsl);
|
||||||
|
//my_printf("\nnSSL worker Shutdown 2 return code : %d", returnCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ftpData->clients[theSocketId].workerData.activeModeOn == 1)
|
||||||
|
{
|
||||||
|
returnCode = SSL_shutdown(ftpData->clients[theSocketId].workerData.clientSsl);
|
||||||
|
|
||||||
|
if (!returnCode)
|
||||||
|
{
|
||||||
|
shutdown(ftpData->clients[theSocketId].workerData.socketConnection, SHUT_RDWR);
|
||||||
|
shutdown(ftpData->clients[theSocketId].workerData.passiveListeningSocket, SHUT_RDWR);
|
||||||
|
returnCode = SSL_shutdown(ftpData->clients[theSocketId].workerData.clientSsl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
shutdown(ftpData->clients[theSocketId].workerData.socketConnection, SHUT_RDWR);
|
||||||
|
|
||||||
|
shutdown(ftpData->clients[theSocketId].workerData.passiveListeningSocket, SHUT_RDWR);
|
||||||
|
|
||||||
|
returnCode = close(ftpData->clients[theSocketId].workerData.socketConnection);
|
||||||
|
returnCode = close(ftpData->clients[theSocketId].workerData.passiveListeningSocket);
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.commandProcessed)
|
||||||
|
{
|
||||||
|
returnCode = socketPrintf(ftpData, theSocketId, "s", ftpData->clients[theSocketId].workerData.theCommandResponse);
|
||||||
|
if (returnCode <= 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("socketPrintf");
|
||||||
|
my_printf("\n Closing the client 10");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetWorkerData(ftpData, theSocketId, 0);
|
||||||
|
|
||||||
|
DYNMEM_free(args, &ftpData->clients[theSocketId].workerData.memoryTable);
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.memoryTable != NULL)
|
||||||
|
DYNMEM_dump(ftpData->clients[theSocketId].workerData.memoryTable);//my_printf("\nMemory table element label: %s", ftpData->clients[theSocketId].workerData.memoryTable->theName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int processStorAppe(cleanUpWorkerArgs *args)
|
||||||
|
{
|
||||||
|
ftpDataType *ftpData = args->ftpData;
|
||||||
|
int theSocketId = args->socketId;
|
||||||
|
int returnCode = 0;
|
||||||
|
|
||||||
|
if (compareStringCaseInsensitive(ftpData->clients[theSocketId].workerData.theCommandReceived, "APPE", strlen("APPE")) == 1)
|
||||||
|
{
|
||||||
|
#ifdef LARGE_FILE_SUPPORT_ENABLED
|
||||||
|
//#warning LARGE FILE SUPPORT IS ENABLED!
|
||||||
|
ftpData->clients[theSocketId].workerData.theStorFile = fopen64(ftpData->clients[theSocketId].fileToStor.text, "ab");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LARGE_FILE_SUPPORT_ENABLED
|
||||||
|
#warning LARGE FILE SUPPORT IS NOT ENABLED!
|
||||||
|
ftpData->clients[theSocketId].workerData.theStorFile = fopen(ftpData->clients[theSocketId].fileToStor.text, "ab");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef LARGE_FILE_SUPPORT_ENABLED
|
||||||
|
//#warning LARGE FILE SUPPORT IS ENABLED!
|
||||||
|
ftpData->clients[theSocketId].workerData.theStorFile = fopen64(ftpData->clients[theSocketId].fileToStor.text, "wb");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LARGE_FILE_SUPPORT_ENABLED
|
||||||
|
#warning LARGE FILE SUPPORT IS NOT ENABLED!
|
||||||
|
ftpData->clients[theSocketId].workerData.theStorFile = fopen(ftpData->clients[theSocketId].fileToStor.text, "wb");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.theStorFile == NULL)
|
||||||
|
{
|
||||||
|
returnCode = socketPrintf(ftpData, theSocketId, "s", "553 Unable to write the file\r\n");
|
||||||
|
|
||||||
|
if (returnCode <= 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("socketPrintf");
|
||||||
|
my_printf("\n Closing the client 6");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if (ftpData->clients[theSocketId].dataChannelIsTls != 1)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].workerData.bufferIndex = read(ftpData->clients[theSocketId].workerData.socketConnection, ftpData->clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE);
|
||||||
|
}
|
||||||
|
else if (ftpData->clients[theSocketId].dataChannelIsTls == 1)
|
||||||
|
{
|
||||||
|
#ifdef OPENSSL_ENABLED
|
||||||
|
if (ftpData->clients[theSocketId].workerData.passiveModeOn == 1)
|
||||||
|
ftpData->clients[theSocketId].workerData.bufferIndex = SSL_read(ftpData->clients[theSocketId].workerData.serverSsl, ftpData->clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE);
|
||||||
|
else if(ftpData->clients[theSocketId].workerData.activeModeOn == 1)
|
||||||
|
ftpData->clients[theSocketId].workerData.bufferIndex = SSL_read(ftpData->clients[theSocketId].workerData.clientSsl, ftpData->clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_printf("\nError state");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.bufferIndex == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (ftpData->clients[theSocketId].workerData.bufferIndex > 0)
|
||||||
|
{
|
||||||
|
fwrite(ftpData->clients[theSocketId].workerData.buffer, ftpData->clients[theSocketId].workerData.bufferIndex, 1, ftpData->clients[theSocketId].workerData.theStorFile);
|
||||||
|
usleep(100);
|
||||||
|
ftpData->clients[theSocketId].lastActivityTimeStamp = (int)time(NULL);
|
||||||
|
}
|
||||||
|
else if (ftpData->clients[theSocketId].workerData.bufferIndex < 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int theReturnCode;
|
||||||
|
theReturnCode = fclose(ftpData->clients[theSocketId].workerData.theStorFile);
|
||||||
|
ftpData->clients[theSocketId].workerData.theStorFile = NULL;
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].login.ownerShip.ownerShipSet == 1)
|
||||||
|
{
|
||||||
|
FILE_doChownFromUidGid(ftpData->clients[theSocketId].fileToStor.text, ftpData->clients[theSocketId].login.ownerShip.uid, ftpData->clients[theSocketId].login.ownerShip.gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
ftpData->clients[theSocketId].workerData.commandProcessed = 1;
|
||||||
|
snprintf(ftpData->clients[theSocketId].workerData.theCommandResponse, STRING_SZ_SMALL, "226 file stor ok\r\n");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int acceptConnection(cleanUpWorkerArgs *args)
|
||||||
|
{
|
||||||
|
ftpDataType *ftpData = args->ftpData;
|
||||||
|
int theSocketId = args->socketId;
|
||||||
|
int returnCode;
|
||||||
|
|
||||||
|
//Passive data connection mode
|
||||||
|
if (ftpData->clients[theSocketId].workerData.passiveModeOn == 1)
|
||||||
|
{
|
||||||
|
int tries = 30;
|
||||||
|
|
||||||
|
while (tries > 0)
|
||||||
|
{
|
||||||
|
setRandomicPort(ftpData, theSocketId);
|
||||||
|
ftpData->clients[theSocketId].workerData.passiveListeningSocket = createPassiveSocket(ftpData->clients[theSocketId].workerData.connectionPort);
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.passiveListeningSocket != -1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tries--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.passiveListeningSocket == -1)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
my_printf("\n Closing the client 1");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.socketIsConnected == 0)
|
||||||
|
{
|
||||||
|
if (ftpData->clients[theSocketId].workerData.passiveModeOn == 1 && ftpData->clients[theSocketId].workerData.extendedPassiveModeOn == 0)
|
||||||
|
{
|
||||||
|
if(strnlen(ftpData->ftpParameters.natIpAddress, STRING_SZ_SMALL) > 0)
|
||||||
|
{
|
||||||
|
my_printf("\n Using nat ip: %s", ftpData->ftpParameters.natIpAddress);
|
||||||
|
returnCode = socketPrintf(ftpData, theSocketId, "sssdsds", "227 Entering Passive Mode (", ftpData->ftpParameters.natIpAddress, ",", (ftpData->clients[theSocketId].workerData.connectionPort / 256), ",", (ftpData->clients[theSocketId].workerData.connectionPort % 256), ")\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_printf("\n Using server ip: %s", ftpData->ftpParameters.natIpAddress);
|
||||||
|
returnCode = socketPrintf(ftpData, theSocketId, "sdsdsdsdsdsds", "227 Entering Passive Mode (", ftpData->clients[theSocketId].serverIpV4AddressInteger[0], ",", ftpData->clients[theSocketId].serverIpV4AddressInteger[1], ",", ftpData->clients[theSocketId].serverIpV4AddressInteger[2], ",", ftpData->clients[theSocketId].serverIpV4AddressInteger[3], ",", (ftpData->clients[theSocketId].workerData.connectionPort / 256), ",", (ftpData->clients[theSocketId].workerData.connectionPort % 256), ")\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ftpData->clients[theSocketId].workerData.passiveModeOn == 1 && ftpData->clients[theSocketId].workerData.extendedPassiveModeOn == 1)
|
||||||
|
{
|
||||||
|
returnCode = socketPrintf(ftpData, theSocketId, "sds", "229 Entering Extended Passive Mode (|||", ftpData->clients[theSocketId].workerData.connectionPort, "|)\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
returnCode = -1;
|
||||||
|
my_printfError("\nUnknown passive state, should be PASV or EPSV");
|
||||||
|
perror("Unknown passive state, should be PASV or EPSV");
|
||||||
|
}
|
||||||
|
|
||||||
|
ftpData->clients[theSocketId].workerData.socketIsReadyForConnection = 1;
|
||||||
|
|
||||||
|
if (returnCode <= 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("socketPrintf");
|
||||||
|
my_printf("\n Closing the client 2");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Wait for sockets
|
||||||
|
if ((ftpData->clients[theSocketId].workerData.socketConnection = accept(ftpData->clients[theSocketId].workerData.passiveListeningSocket, 0, 0))!=-1)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].workerData.socketIsConnected = 1;
|
||||||
|
#ifdef OPENSSL_ENABLED
|
||||||
|
if (ftpData->clients[theSocketId].dataChannelIsTls == 1)
|
||||||
|
{
|
||||||
|
if (acceptSSLConnection(theSocketId, ftpData) < 0)
|
||||||
|
{
|
||||||
|
my_printf("\nSSL_Accept failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("Socket error");
|
||||||
|
my_printf("\n Closing the client 3");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
my_printf("\n Socket already connected");
|
||||||
|
}
|
||||||
|
else if (ftpData->clients[theSocketId].workerData.activeModeOn == 1)
|
||||||
|
{
|
||||||
|
my_printf("\n ----------------- CREATING ACTIVE SOCKET --------------!");
|
||||||
|
if (ftpData->clients[theSocketId].workerData.addressType == 1)
|
||||||
|
ftpData->clients[theSocketId].workerData.socketConnection = createActiveSocket(ftpData->clients[theSocketId].workerData.connectionPort, ftpData->clients[theSocketId].workerData.activeIpAddress);
|
||||||
|
#ifdef IPV6_ENABLED
|
||||||
|
else if (ftpData->clients[theSocketId].workerData.addressType == 2)
|
||||||
|
ftpData->clients[theSocketId].workerData.socketConnection = createActiveSocketV6(ftpData->clients[theSocketId].workerData.connectionPort, ftpData->clients[theSocketId].workerData.activeIpAddress);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPENSSL_ENABLED
|
||||||
|
if (ftpData->clients[theSocketId].dataChannelIsTls == 1)
|
||||||
|
{
|
||||||
|
returnCode = SSL_set_fd(ftpData->clients[theSocketId].workerData.clientSsl, ftpData->clients[theSocketId].workerData.socketConnection);
|
||||||
|
|
||||||
|
if (returnCode == 0)
|
||||||
|
{
|
||||||
|
my_printf("\nSSL ERRORS ON WORKER SSL_set_fd");
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("SSL ERRORS ON WORKER SSL_set_fd");
|
||||||
|
}
|
||||||
|
|
||||||
|
//SSL_set_connect_state(ftpData->clients[theSocketId].workerData.clientSsl);
|
||||||
|
returnCode = SSL_connect(ftpData->clients[theSocketId].workerData.clientSsl);
|
||||||
|
if (returnCode <= 0)
|
||||||
|
{
|
||||||
|
my_printf("\nSSL ERRORS ON WORKER %d error code: %d", returnCode, SSL_get_error(ftpData->clients[theSocketId].workerData.clientSsl, returnCode));
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//my_printf("\nSSL ACCEPTED ON WORKER");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.socketConnection < 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("Socket error");
|
||||||
|
my_printf("\n Closing the client 4");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnCode = socketPrintf(ftpData, theSocketId, "s", "200 connection accepted\r\n");
|
||||||
|
ftpData->clients[theSocketId].workerData.socketIsReadyForConnection = 1;
|
||||||
|
|
||||||
|
if (returnCode <= 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("socketPrintf");
|
||||||
|
my_printf("\n Closing the client 5");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftpData->clients[theSocketId].workerData.socketIsConnected = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int processRetr(cleanUpWorkerArgs *args)
|
||||||
|
{
|
||||||
|
ftpDataType *ftpData = args->ftpData;
|
||||||
|
int theSocketId = args->socketId;
|
||||||
|
int returnCode = 0;
|
||||||
|
long long int writenSize = 0, writeReturn = 0;
|
||||||
|
|
||||||
|
writenSize = writeRetrFile(ftpData, theSocketId, ftpData->clients[theSocketId].workerData.retrRestartAtByte, ftpData->clients[theSocketId].workerData.theStorFile);
|
||||||
|
ftpData->clients[theSocketId].workerData.retrRestartAtByte = 0;
|
||||||
|
|
||||||
|
if (writenSize <= -1)
|
||||||
|
{
|
||||||
|
writeReturn = socketPrintf(ftpData, theSocketId, "s", "550 unable to open the file for reading\r\n");
|
||||||
|
|
||||||
|
if (writeReturn <= 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("socketPrintf");
|
||||||
|
my_printf("\n Closing the client 12");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftpData->clients[theSocketId].workerData.commandProcessed = 1;
|
||||||
|
snprintf(ftpData->clients[theSocketId].workerData.theCommandResponse, STRING_SZ_SMALL, "226-File successfully transferred\r\n226 done\r\n");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int processListNlst(cleanUpWorkerArgs *args)
|
||||||
|
{
|
||||||
|
ftpDataType *ftpData = args->ftpData;
|
||||||
|
int theSocketId = args->socketId;
|
||||||
|
int returnCode = 0;
|
||||||
|
|
||||||
|
int theFiles = 0, theCommandType = 0;
|
||||||
|
|
||||||
|
if (compareStringCaseInsensitive(ftpData->clients[theSocketId].workerData.theCommandReceived, "LIST", strlen("LIST")) == 1)
|
||||||
|
theCommandType = COMMAND_TYPE_LIST;
|
||||||
|
else if (compareStringCaseInsensitive(ftpData->clients[theSocketId].workerData.theCommandReceived, "NLST", strlen("NLST")) == 1)
|
||||||
|
theCommandType = COMMAND_TYPE_NLST;
|
||||||
|
|
||||||
|
returnCode = writeListDataInfoToSocket(ftpData, theSocketId, &theFiles, theCommandType, &ftpData->clients[theSocketId].workerData.memoryTable);
|
||||||
|
if (returnCode <= 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("writeListDataInfoToSocket");
|
||||||
|
my_printf("\n Closing the client 9");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftpData->clients[theSocketId].workerData.commandProcessed = 1;
|
||||||
|
snprintf(ftpData->clients[theSocketId].workerData.theCommandResponse, STRING_SZ_SMALL, "226 %d matches total\r\n", theFiles);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *connectionWorkerHandle(cleanUpWorkerArgs *args)
|
||||||
|
{
|
||||||
|
ftpDataType *ftpData = args->ftpData;
|
||||||
|
int theSocketId = args->socketId;
|
||||||
|
int returnCode = 0;
|
||||||
|
|
||||||
|
// Enable cancellation for this thread
|
||||||
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||||
|
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
|
||||||
|
|
||||||
|
pthread_cleanup_push(workerCleanup, args);
|
||||||
|
ftpData->clients[theSocketId].workerData.threadIsAlive = 1;
|
||||||
|
ftpData->clients[theSocketId].workerData.threadHasBeenCreated = 1;
|
||||||
|
int returnCode;
|
||||||
|
|
||||||
|
my_printf("\n ----------------- WORKER CREATED --------------!");
|
||||||
|
|
||||||
|
// deal with connections
|
||||||
|
if (acceptConnection(args) != 1)
|
||||||
|
{
|
||||||
|
my_printf("\n Connection error on the worker, exit from thread.");
|
||||||
|
goto data_channel_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Endless loop ftp process
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.socketIsConnected > 0)
|
||||||
|
{
|
||||||
|
my_printf("\nWorker %d is waiting for commands!", theSocketId);
|
||||||
|
//Conditional lock on tconditionVariablehread actions
|
||||||
|
pthread_mutex_lock(&ftpData->clients[theSocketId].conditionMutex);
|
||||||
|
while (ftpData->clients[theSocketId].workerData.commandReceived == 0)
|
||||||
|
{
|
||||||
|
pthread_cond_wait(&ftpData->clients[theSocketId].conditionVariable, &ftpData->clients[theSocketId].conditionMutex);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&ftpData->clients[theSocketId].conditionMutex);
|
||||||
|
|
||||||
|
if (ftpData->clients[theSocketId].workerData.commandReceived == 1 &&
|
||||||
|
(compareStringCaseInsensitive(ftpData->clients[theSocketId].workerData.theCommandReceived, "STOR", strlen("STOR")) == 1 ||
|
||||||
|
compareStringCaseInsensitive(ftpData->clients[theSocketId].workerData.theCommandReceived, "APPE", strlen("APPE")) == 1) &&
|
||||||
|
ftpData->clients[theSocketId].fileToStor.textLen > 0)
|
||||||
|
{
|
||||||
|
if (processStorAppe(args) != 1)
|
||||||
|
{
|
||||||
|
my_printf("\nWorker %d errors on STOR APPE!", theSocketId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (ftpData->clients[theSocketId].workerData.commandReceived == 1 &&
|
||||||
|
( (compareStringCaseInsensitive(ftpData->clients[theSocketId].workerData.theCommandReceived, "LIST", strlen("LIST")) == 1)
|
||||||
|
|| (compareStringCaseInsensitive(ftpData->clients[theSocketId].workerData.theCommandReceived, "NLST", strlen("NLST")) == 1)))
|
||||||
|
{
|
||||||
|
if (processListNlst(args) != 1)
|
||||||
|
{
|
||||||
|
my_printf("\nWorker %d errors on LIST NLST!", theSocketId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (ftpData->clients[theSocketId].workerData.commandReceived == 1 &&
|
||||||
|
compareStringCaseInsensitive(ftpData->clients[theSocketId].workerData.theCommandReceived, "RETR", strlen("RETR")) == 1)
|
||||||
|
{
|
||||||
|
if (processRetr(args) != 1)
|
||||||
|
{
|
||||||
|
my_printf("\nWorker %d errors on RETR!", theSocketId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data_channel_exit:
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
pthread_exit((void *)1);
|
||||||
|
}
|
15
dataChannel/dataChannel.h
Normal file
15
dataChannel/dataChannel.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef DATA_CHANNEL_H
|
||||||
|
#define DATA_CHANNEL_H
|
||||||
|
|
||||||
|
#include "ftpData.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ftpDataType *ftpData;
|
||||||
|
int socketId;
|
||||||
|
} cleanUpWorkerArgs;
|
||||||
|
|
||||||
|
void workerCleanup(cleanUpWorkerArgs *args);
|
||||||
|
void *connectionWorkerHandle(cleanUpWorkerArgs *args);
|
||||||
|
|
||||||
|
#endif /* DATA_CHANNEL_H */
|
||||||
|
|
@ -1,9 +1,5 @@
|
|||||||
#ifndef ENABLE_PRINTF_MODULE
|
#ifndef ENABLE_PRINTF_MODULE
|
||||||
|
|
||||||
// Uncomment next line to enable debug printf
|
|
||||||
// #define ENABLE_PRINTF
|
|
||||||
// #define ENABLE_PRINTF_ERROR
|
|
||||||
|
|
||||||
#define CURRENT_FILE __FILE__
|
#define CURRENT_FILE __FILE__
|
||||||
#define CURRENT_LINE __LINE__
|
#define CURRENT_LINE __LINE__
|
||||||
#define CURRENT_FUNC __func__
|
#define CURRENT_FUNC __func__
|
||||||
|
0
debug_defines.h
Normal file
0
debug_defines.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -90,7 +90,7 @@ int parseCommandOpts(ftpDataType * data, int socketId);
|
|||||||
int parseCommandRnfr(ftpDataType * data, int socketId);
|
int parseCommandRnfr(ftpDataType * data, int socketId);
|
||||||
int parseCommandRnto(ftpDataType * data, int socketId);
|
int parseCommandRnto(ftpDataType * data, int socketId);
|
||||||
int parseCommandAcct(ftpDataType * data, int socketId);
|
int parseCommandAcct(ftpDataType * data, int socketId);
|
||||||
|
int parseCommandEprt(ftpDataType *data, int socketId);
|
||||||
|
|
||||||
long long int writeRetrFile(ftpDataType * data, int theSocketId, long long int startFrom, FILE *retrFP);
|
long long int writeRetrFile(ftpDataType * data, int theSocketId, long long int startFrom, FILE *retrFP);
|
||||||
char *getFtpCommandArg(char * theCommand, char *theCommandString, int skipArgs);
|
char *getFtpCommandArg(char * theCommand, char *theCommandString, int skipArgs);
|
||||||
|
139
ftpData.c
139
ftpData.c
@ -42,6 +42,8 @@
|
|||||||
#include "library/dynamicMemory.h"
|
#include "library/dynamicMemory.h"
|
||||||
|
|
||||||
#include "debugHelper.h"
|
#include "debugHelper.h"
|
||||||
|
#include "library/log.h"
|
||||||
|
|
||||||
|
|
||||||
static int is_prefix(const char *str, const char *prefix);
|
static int is_prefix(const char *str, const char *prefix);
|
||||||
static char *my_realpath(const char *path, char *resolved_path);
|
static char *my_realpath(const char *path, char *resolved_path);
|
||||||
@ -60,7 +62,7 @@ static char *my_realpath(const char *path, char *resolved_path)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
my_printfError("getcwd");
|
my_printfError("getcwd");
|
||||||
addLog("getcwd error ", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("getcwd");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,13 +226,13 @@ int getSafePath(dynamicStringDataType *safePath, char *theDirectoryName, loginDa
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
my_printfError("\nPath check error: %s check if is in: %s",loginData->homePath.text, real_path);
|
my_printfError("\nPath check error: %s check if is in: %s",loginData->homePath.text, real_path);
|
||||||
addLog("Path check error ", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOGF("%sPath check error: %s check if is in: %s", LOG_DEBUG_PREFIX, loginData->homePath.text, real_path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addLog("Realpath error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOGF("%sRealpath error: %s", LOG_DEBUG_PREFIX, theDirectoryName);
|
||||||
my_printfError("\nRealpath error input %s", theDirectoryName);
|
my_printfError("\nRealpath error input %s", theDirectoryName);
|
||||||
my_printfError("\ntheDirectoryToCheck error input %s", theDirectoryToCheck);
|
my_printfError("\ntheDirectoryToCheck error input %s", theDirectoryToCheck);
|
||||||
return 0;
|
return 0;
|
||||||
@ -255,28 +257,45 @@ void appendToDynamicStringDataType(dynamicStringDataType *dynamicString, char *t
|
|||||||
|
|
||||||
void setRandomicPort(ftpDataType *data, int socketPosition)
|
void setRandomicPort(ftpDataType *data, int socketPosition)
|
||||||
{
|
{
|
||||||
unsigned short int randomicPort = 5000;
|
unsigned short int randomicPort;
|
||||||
int i = 0;
|
int maxAttempts = data->ftpParameters.connectionPortMax - data->ftpParameters.connectionPortMin +1;
|
||||||
|
int attempt = 0;
|
||||||
|
int conflict;
|
||||||
|
|
||||||
randomicPort = data->ftpParameters.connectionPortMin + (rand()%(data->ftpParameters.connectionPortMax - data->ftpParameters.connectionPortMin));
|
while (attempt++ < maxAttempts)
|
||||||
|
{
|
||||||
|
// Generate a random port in range
|
||||||
|
randomicPort = data->ftpParameters.connectionPortMin +
|
||||||
|
(rand() % (data->ftpParameters.connectionPortMax - data->ftpParameters.connectionPortMin + 1));
|
||||||
|
|
||||||
while (i < data->ftpParameters.maxClients)
|
// Check against other clients
|
||||||
{
|
conflict = 0;
|
||||||
if (randomicPort == data->clients[i].workerData.connectionPort)
|
for (int i = 0; i < data->ftpParameters.maxClients; ++i)
|
||||||
{
|
{
|
||||||
randomicPort = data->ftpParameters.connectionPortMin + (rand()%(data->ftpParameters.connectionPortMax - data->ftpParameters.connectionPortMin));
|
if (i != socketPosition &&
|
||||||
i = 0;
|
data->clients[i].workerData.connectionPort == randomicPort)
|
||||||
}
|
{
|
||||||
else
|
conflict = 1;
|
||||||
{
|
break;
|
||||||
i++;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
data->clients[socketPosition].workerData.connectionPort = randomicPort;
|
if (conflict)
|
||||||
|
continue;
|
||||||
|
|
||||||
my_printf("\n data->clients[%d].workerData.connectionPort = %d", socketPosition, data->clients[socketPosition].workerData.connectionPort);
|
// Check if port is in use on the system
|
||||||
|
if (!isPortInUse(randomicPort))
|
||||||
|
{
|
||||||
|
data->clients[socketPosition].workerData.connectionPort = randomicPort;
|
||||||
|
my_printf("\n data->clients[%d].workerData.connectionPort = %d",
|
||||||
|
socketPosition, randomicPort);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we’re here, we failed to find a port
|
||||||
|
LOG_ERROR("Failed to find available random port");
|
||||||
|
data->clients[socketPosition].workerData.connectionPort = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumber, int commandType, DYNMEM_MemoryTable_DataType **memoryTable)
|
int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumber, int commandType, DYNMEM_MemoryTable_DataType **memoryTable)
|
||||||
@ -299,6 +318,11 @@ int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumb
|
|||||||
returnCode = socketWorkerPrintf(ftpData, clientId, "sds", "total ", fileAndFoldersCount ,"\r\n");
|
returnCode = socketWorkerPrintf(ftpData, clientId, "sds", "total ", fileAndFoldersCount ,"\r\n");
|
||||||
if (returnCode <= 0)
|
if (returnCode <= 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
for (x = 0; x < fileAndFoldersCount; x++)
|
||||||
|
DYNMEM_free (fileList[x], memoryTable);
|
||||||
|
|
||||||
|
DYNMEM_free (fileList, memoryTable);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -344,6 +368,7 @@ int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumb
|
|||||||
|
|
||||||
if (data.isDirectory == 0 && data.isFile == 0 && data.isLink == 0)
|
if (data.isDirectory == 0 && data.isFile == 0 && data.isLink == 0)
|
||||||
{
|
{
|
||||||
|
DYNMEM_free (fileList[i], memoryTable);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +393,7 @@ int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumb
|
|||||||
my_printf("\n ********************** void inode permission string");
|
my_printf("\n ********************** void inode permission string");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.isLink = 1 &&
|
if (data.isLink == 1 &&
|
||||||
data.inodePermissionString != NULL &&
|
data.inodePermissionString != NULL &&
|
||||||
strlen(data.inodePermissionString) > 0 &&
|
strlen(data.inodePermissionString) > 0 &&
|
||||||
data.inodePermissionString[0] == 'l')
|
data.inodePermissionString[0] == 'l')
|
||||||
@ -382,6 +407,7 @@ int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumb
|
|||||||
FILE_AppendToString(&data.finalStringPath, " -> ", memoryTable);
|
FILE_AppendToString(&data.finalStringPath, " -> ", memoryTable);
|
||||||
FILE_AppendToString(&data.finalStringPath, data.linkPath, memoryTable);
|
FILE_AppendToString(&data.finalStringPath, data.linkPath, memoryTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(data.lastModifiedDataString, 0, LIST_DATA_TYPE_MODIFIED_DATA_STR_SIZE);
|
memset(data.lastModifiedDataString, 0, LIST_DATA_TYPE_MODIFIED_DATA_STR_SIZE);
|
||||||
@ -390,7 +416,6 @@ int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumb
|
|||||||
localtime_r(&data.lastModifiedData, &newtime);
|
localtime_r(&data.lastModifiedData, &newtime);
|
||||||
strftime(data.lastModifiedDataString, LIST_DATA_TYPE_MODIFIED_DATA_STR_SIZE, "%b %d %Y", &newtime);
|
strftime(data.lastModifiedDataString, LIST_DATA_TYPE_MODIFIED_DATA_STR_SIZE, "%b %d %Y", &newtime);
|
||||||
|
|
||||||
|
|
||||||
switch (commandType)
|
switch (commandType)
|
||||||
{
|
{
|
||||||
case COMMAND_TYPE_LIST:
|
case COMMAND_TYPE_LIST:
|
||||||
@ -492,7 +517,6 @@ int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumb
|
|||||||
DYNMEM_free (fileList, memoryTable);
|
DYNMEM_free (fileList, memoryTable);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileList != NULL)
|
if (fileList != NULL)
|
||||||
@ -635,8 +659,7 @@ void getListDataInfo(char * thePath, DYNV_VectorGenericDataType *directoryInfo,
|
|||||||
|
|
||||||
void deleteListDataInfoVector(DYNV_VectorGenericDataType *theVector)
|
void deleteListDataInfoVector(DYNV_VectorGenericDataType *theVector)
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < theVector->Size; i++)
|
||||||
for (i = 0; i < theVector->Size; i++)
|
|
||||||
{
|
{
|
||||||
ftpListDataType *data = (ftpListDataType *)theVector->Data[i];
|
ftpListDataType *data = (ftpListDataType *)theVector->Data[i];
|
||||||
|
|
||||||
@ -667,20 +690,6 @@ void deleteListDataInfoVector(DYNV_VectorGenericDataType *theVector)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancelWorker(ftpDataType *data, int clientId)
|
|
||||||
{
|
|
||||||
void *pReturn;
|
|
||||||
addLog("Cancelling thread because is busy", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
int returnCode = pthread_cancel(data->clients[clientId].workerData.workerThread);
|
|
||||||
if (returnCode != 0)
|
|
||||||
{
|
|
||||||
addLog("Cancelling thread ERROR", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
}
|
|
||||||
returnCode = pthread_join(data->clients[clientId].workerData.workerThread, &pReturn);
|
|
||||||
|
|
||||||
data->clients[clientId].workerData.threadHasBeenCreated = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetWorkerData(ftpDataType *data, int clientId, int isInitialization)
|
void resetWorkerData(ftpDataType *data, int clientId, int isInitialization)
|
||||||
{
|
{
|
||||||
my_printf("\nReset of worker id: %d", clientId);
|
my_printf("\nReset of worker id: %d", clientId);
|
||||||
@ -698,11 +707,12 @@ void resetWorkerData(ftpDataType *data, int clientId, int isInitialization)
|
|||||||
data->clients[clientId].workerData.activeModeOn = 0;
|
data->clients[clientId].workerData.activeModeOn = 0;
|
||||||
data->clients[clientId].workerData.extendedPassiveModeOn = 0;
|
data->clients[clientId].workerData.extendedPassiveModeOn = 0;
|
||||||
data->clients[clientId].workerData.activeIpAddressIndex = 0;
|
data->clients[clientId].workerData.activeIpAddressIndex = 0;
|
||||||
data->clients[clientId].workerData.threadHasBeenCreated = 0;
|
data->clients[clientId].workerData.commandProcessed = 0;
|
||||||
|
|
||||||
memset(data->clients[clientId].workerData.buffer, 0, CLIENT_BUFFER_STRING_SIZE+1);
|
memset(data->clients[clientId].workerData.buffer, 0, CLIENT_BUFFER_STRING_SIZE+1);
|
||||||
memset(data->clients[clientId].workerData.activeIpAddress, 0, CLIENT_BUFFER_STRING_SIZE);
|
memset(data->clients[clientId].workerData.activeIpAddress, 0, CLIENT_BUFFER_STRING_SIZE);
|
||||||
memset(data->clients[clientId].workerData.theCommandReceived, 0, CLIENT_BUFFER_STRING_SIZE+1);
|
memset(data->clients[clientId].workerData.theCommandReceived, 0, CLIENT_BUFFER_STRING_SIZE+1);
|
||||||
|
memset(data->clients[clientId].workerData.theCommandResponse, 0, STRING_SZ_SMALL+1);
|
||||||
|
|
||||||
cleanDynamicStringDataType(&data->clients[clientId].workerData.ftpCommand.commandArgs, isInitialization, &data->clients[clientId].workerData.memoryTable);
|
cleanDynamicStringDataType(&data->clients[clientId].workerData.ftpCommand.commandArgs, isInitialization, &data->clients[clientId].workerData.memoryTable);
|
||||||
cleanDynamicStringDataType(&data->clients[clientId].workerData.ftpCommand.commandOps, isInitialization, &data->clients[clientId].workerData.memoryTable);
|
cleanDynamicStringDataType(&data->clients[clientId].workerData.ftpCommand.commandOps, isInitialization, &data->clients[clientId].workerData.memoryTable);
|
||||||
@ -724,14 +734,12 @@ void resetWorkerData(ftpDataType *data, int clientId, int isInitialization)
|
|||||||
data->clients[clientId].workerData.serverSsl = NULL;
|
data->clients[clientId].workerData.serverSsl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (data->clients[clientId].workerData.clientSsl != NULL)
|
if (data->clients[clientId].workerData.clientSsl != NULL)
|
||||||
{
|
{
|
||||||
SSL_free(data->clients[clientId].workerData.clientSsl);
|
SSL_free(data->clients[clientId].workerData.clientSsl);
|
||||||
data->clients[clientId].workerData.clientSsl = NULL;
|
data->clients[clientId].workerData.clientSsl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -752,33 +760,30 @@ void resetWorkerData(ftpDataType *data, int clientId, int isInitialization)
|
|||||||
DYNMEM_free(lastToDestroy, &data->clients[clientId].workerData.memoryTable);
|
DYNMEM_free(lastToDestroy, &data->clients[clientId].workerData.memoryTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OPENSSL_ENABLED
|
#ifdef OPENSSL_ENABLED
|
||||||
data->clients[clientId].workerData.serverSsl = SSL_new(data->serverCtx);
|
data->clients[clientId].workerData.serverSsl = SSL_new(data->serverCtx);
|
||||||
data->clients[clientId].workerData.clientSsl = SSL_new(data->clientCtx);
|
data->clients[clientId].workerData.clientSsl = SSL_new(data->serverCtx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetClientData(ftpDataType *data, int clientId, int isInitialization)
|
void resetClientData(ftpDataType *data, int clientId, int isInitialization)
|
||||||
{
|
{
|
||||||
if (isInitialization != 1)
|
if (isInitialization != 1)
|
||||||
{
|
{
|
||||||
if (data->clients[clientId].workerData.threadIsAlive == 1)
|
|
||||||
{
|
|
||||||
cancelWorker(data, clientId);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_destroy(&data->clients[clientId].conditionMutex);
|
handleThreadReuse(data, clientId);
|
||||||
pthread_cond_destroy(&data->clients[clientId].conditionVariable);
|
|
||||||
|
pthread_mutex_destroy(&data->clients[clientId].conditionMutex);
|
||||||
|
pthread_cond_destroy(&data->clients[clientId].conditionVariable);
|
||||||
|
pthread_mutex_destroy(&data->clients[clientId].writeMutex);
|
||||||
|
|
||||||
pthread_mutex_destroy(&data->clients[clientId].writeMutex);
|
#ifdef OPENSSL_ENABLED
|
||||||
|
if (data->clients[clientId].ssl != NULL)
|
||||||
#ifdef OPENSSL_ENABLED
|
{
|
||||||
if (data->clients[clientId].ssl != NULL)
|
SSL_free(data->clients[clientId].ssl);
|
||||||
{
|
data->clients[clientId].ssl = NULL;
|
||||||
SSL_free(data->clients[clientId].ssl);
|
}
|
||||||
data->clients[clientId].ssl = NULL;
|
#endif
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -811,10 +816,6 @@ void resetClientData(ftpDataType *data, int clientId, int isInitialization)
|
|||||||
data->clients[clientId].closeTheClient = 0;
|
data->clients[clientId].closeTheClient = 0;
|
||||||
data->clients[clientId].sockaddr_in_size = sizeof(struct sockaddr_in);
|
data->clients[clientId].sockaddr_in_size = sizeof(struct sockaddr_in);
|
||||||
data->clients[clientId].sockaddr_in_server_size = sizeof(struct sockaddr_in);
|
data->clients[clientId].sockaddr_in_server_size = sizeof(struct sockaddr_in);
|
||||||
data->clients[clientId].serverIpAddressInteger[0] = 0;
|
|
||||||
data->clients[clientId].serverIpAddressInteger[1] = 0;
|
|
||||||
data->clients[clientId].serverIpAddressInteger[2] = 0;
|
|
||||||
data->clients[clientId].serverIpAddressInteger[3] = 0;
|
|
||||||
|
|
||||||
|
|
||||||
memset(&data->clients[clientId].client_sockaddr_in, 0, data->clients[clientId].sockaddr_in_size);
|
memset(&data->clients[clientId].client_sockaddr_in, 0, data->clients[clientId].sockaddr_in_size);
|
||||||
@ -839,7 +840,6 @@ void resetClientData(ftpDataType *data, int clientId, int isInitialization)
|
|||||||
data->clients[clientId].lastActivityTimeStamp = 0;
|
data->clients[clientId].lastActivityTimeStamp = 0;
|
||||||
|
|
||||||
#ifdef OPENSSL_ENABLED
|
#ifdef OPENSSL_ENABLED
|
||||||
//data->clients[clientId].workerData.ssl = SSL_new(data->ctx);
|
|
||||||
data->clients[clientId].ssl = SSL_new(data->serverCtx);
|
data->clients[clientId].ssl = SSL_new(data->serverCtx);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -849,8 +849,8 @@ void resetClientData(ftpDataType *data, int clientId, int isInitialization)
|
|||||||
int compareStringCaseInsensitive(char * stringIn, char * stringRef, int stringLenght)
|
int compareStringCaseInsensitive(char * stringIn, char * stringRef, int stringLenght)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char * alfaLowerCase = "qwertyuiopasdfghjklzxcvbnm .";
|
char *alfaLowerCase = "qwertyuiopasdfghjklzxcvbnm .";
|
||||||
char * alfaUpperCase = "QWERTYUIOPASDFGHJKLZXCVBNM .";
|
char *alfaUpperCase = "QWERTYUIOPASDFGHJKLZXCVBNM .";
|
||||||
|
|
||||||
int stringInIndex;
|
int stringInIndex;
|
||||||
int stringRefIndex;
|
int stringRefIndex;
|
||||||
@ -888,8 +888,7 @@ int compareStringCaseInsensitive(char * stringIn, char * stringRef, int stringLe
|
|||||||
|
|
||||||
int isCharInString(char *theString, int stringLen, char theChar)
|
int isCharInString(char *theString, int stringLen, char theChar)
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < stringLen; i++)
|
||||||
for (i = 0; i < stringLen; i++)
|
|
||||||
{
|
{
|
||||||
if (theString[i] == theChar)
|
if (theString[i] == theChar)
|
||||||
{
|
{
|
||||||
|
28
ftpData.h
28
ftpData.h
@ -54,6 +54,10 @@
|
|||||||
#define COMMAND_TYPE_STAT 2
|
#define COMMAND_TYPE_STAT 2
|
||||||
#define WRONG_PASSWORD_ALLOWED_RETRY_TIME 60
|
#define WRONG_PASSWORD_ALLOWED_RETRY_TIME 60
|
||||||
|
|
||||||
|
|
||||||
|
#define IS_CMD(str, cmd) (compareStringCaseInsensitive(str, cmd, strlen(cmd)) == 1)
|
||||||
|
#define IS_NOT_CMD(str, cmd) (compareStringCaseInsensitive(str, cmd, strlen(cmd)) != 1)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -87,7 +91,7 @@ struct usersParameters
|
|||||||
|
|
||||||
struct ftpParameters
|
struct ftpParameters
|
||||||
{
|
{
|
||||||
int ftpIpAddress[4];
|
int ftpIpAddressV4[4];
|
||||||
int port;
|
int port;
|
||||||
int maxClients;
|
int maxClients;
|
||||||
int daemonModeOn;
|
int daemonModeOn;
|
||||||
@ -150,6 +154,7 @@ struct workerData
|
|||||||
int threadIsAlive;
|
int threadIsAlive;
|
||||||
int threadHasBeenCreated;
|
int threadHasBeenCreated;
|
||||||
int connectionPort;
|
int connectionPort;
|
||||||
|
int addressType;
|
||||||
int passiveModeOn;
|
int passiveModeOn;
|
||||||
int extendedPassiveModeOn;
|
int extendedPassiveModeOn;
|
||||||
int activeModeOn;
|
int activeModeOn;
|
||||||
@ -169,6 +174,9 @@ struct workerData
|
|||||||
char theCommandReceived[CLIENT_COMMAND_STRING_SIZE+1];
|
char theCommandReceived[CLIENT_COMMAND_STRING_SIZE+1];
|
||||||
int commandReceived;
|
int commandReceived;
|
||||||
|
|
||||||
|
int commandProcessed;
|
||||||
|
char theCommandResponse[STRING_SZ_SMALL+1];
|
||||||
|
|
||||||
long long int retrRestartAtByte;
|
long long int retrRestartAtByte;
|
||||||
|
|
||||||
/* The PASV thread will wait the signal before start */
|
/* The PASV thread will wait the signal before start */
|
||||||
@ -184,6 +192,7 @@ struct clientData
|
|||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int isIpV6;
|
||||||
int tlsIsEnabled;
|
int tlsIsEnabled;
|
||||||
int tlsIsNegotiating;
|
int tlsIsNegotiating;
|
||||||
unsigned long long int tlsNegotiatingTimeStart;
|
unsigned long long int tlsNegotiatingTimeStart;
|
||||||
@ -214,15 +223,20 @@ struct clientData
|
|||||||
loginDataType login;
|
loginDataType login;
|
||||||
workerDataType workerData;
|
workerDataType workerData;
|
||||||
|
|
||||||
int sockaddr_in_size, sockaddr_in_server_size;
|
socklen_t sockaddr_in_size, sockaddr_in_server_size;
|
||||||
|
|
||||||
|
#ifdef IPV6_ENABLED
|
||||||
|
struct sockaddr_in6 client_sockaddr_in, server_sockaddr_in;
|
||||||
|
#else
|
||||||
struct sockaddr_in client_sockaddr_in, server_sockaddr_in;
|
struct sockaddr_in client_sockaddr_in, server_sockaddr_in;
|
||||||
|
#endif
|
||||||
|
|
||||||
int clientPort;
|
int clientPort;
|
||||||
char clientIpAddress[INET_ADDRSTRLEN];
|
char clientIpAddress[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
int serverPort;
|
int serverPort;
|
||||||
char serverIpAddress[INET_ADDRSTRLEN];
|
char serverIpAddress[INET6_ADDRSTRLEN];
|
||||||
int serverIpAddressInteger[4];
|
int serverIpV4AddressInteger[4];
|
||||||
ftpCommandDataType ftpCommand;
|
ftpCommandDataType ftpCommand;
|
||||||
int closeTheClient;
|
int closeTheClient;
|
||||||
|
|
||||||
@ -252,7 +266,6 @@ struct ftpData
|
|||||||
{
|
{
|
||||||
#ifdef OPENSSL_ENABLED
|
#ifdef OPENSSL_ENABLED
|
||||||
SSL_CTX *serverCtx;
|
SSL_CTX *serverCtx;
|
||||||
SSL_CTX *clientCtx;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int connectedClients;
|
int connectedClients;
|
||||||
@ -301,7 +314,6 @@ int searchInLoginFailsVector(void *loginFailsVector, void *element);
|
|||||||
void deleteLoginFailsData(void *element);
|
void deleteLoginFailsData(void *element);
|
||||||
void deleteListDataInfoVector(DYNV_VectorGenericDataType *theVector);
|
void deleteListDataInfoVector(DYNV_VectorGenericDataType *theVector);
|
||||||
void resetWorkerData(ftpDataType *data, int clientId, int isInitialization);
|
void resetWorkerData(ftpDataType *data, int clientId, int isInitialization);
|
||||||
void cancelWorker(ftpDataType *data, int clientId);
|
|
||||||
void resetClientData(ftpDataType *data, int clientId, int isInitialization);
|
void resetClientData(ftpDataType *data, int clientId, int isInitialization);
|
||||||
int compareStringCaseInsensitive(char *stringIn, char* stringRef, int stringLenght);
|
int compareStringCaseInsensitive(char *stringIn, char* stringRef, int stringLenght);
|
||||||
int isCharInString(char *theString, int stringLen, char theChar);
|
int isCharInString(char *theString, int stringLen, char theChar);
|
||||||
|
913
ftpServer.c
913
ftpServer.c
@ -37,7 +37,6 @@
|
|||||||
|
|
||||||
/* FTP LIBS */
|
/* FTP LIBS */
|
||||||
#include "library/fileManagement.h"
|
#include "library/fileManagement.h"
|
||||||
#include "library/logFunctions.h"
|
|
||||||
#include "library/configRead.h"
|
#include "library/configRead.h"
|
||||||
#include "library/signals.h"
|
#include "library/signals.h"
|
||||||
#include "library/openSsl.h"
|
#include "library/openSsl.h"
|
||||||
@ -51,477 +50,17 @@
|
|||||||
#include "ftpData.h"
|
#include "ftpData.h"
|
||||||
#include "ftpCommandsElaborate.h"
|
#include "ftpCommandsElaborate.h"
|
||||||
#include "debugHelper.h"
|
#include "debugHelper.h"
|
||||||
|
#include "controlChannel/controlChannel.h"
|
||||||
|
|
||||||
ftpDataType ftpData;
|
ftpDataType ftpData;
|
||||||
pthread_t watchDogThread;
|
pthread_t watchDogThread;
|
||||||
|
|
||||||
static int processCommand(int processingElement);
|
void initFtpServer(void)
|
||||||
|
|
||||||
void workerCleanup(void *socketId)
|
|
||||||
{
|
{
|
||||||
int theSocketId = *(int *)socketId;
|
int returnCode = 0;
|
||||||
int returnCode = 0;
|
|
||||||
|
|
||||||
//my_printf("\nWorker %d cleanup", theSocketId);
|
|
||||||
|
|
||||||
#ifdef OPENSSL_ENABLED
|
|
||||||
int error;
|
|
||||||
error = fcntl(ftpData.clients[theSocketId].workerData.socketConnection, F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].dataChannelIsTls == 1)
|
|
||||||
{
|
|
||||||
if(ftpData.clients[theSocketId].workerData.passiveModeOn == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nSSL worker Shutdown 1");
|
|
||||||
returnCode = SSL_shutdown(ftpData.clients[theSocketId].workerData.serverSsl);
|
|
||||||
//my_printf("\nnSSL worker Shutdown 1 return code : %d", returnCode);
|
|
||||||
|
|
||||||
if (!returnCode)
|
|
||||||
{
|
|
||||||
shutdown(ftpData.clients[theSocketId].workerData.socketConnection, SHUT_RDWR);
|
|
||||||
shutdown(ftpData.clients[theSocketId].workerData.passiveListeningSocket, SHUT_RDWR);
|
|
||||||
|
|
||||||
//my_printf("\nSSL worker Shutdown 2");
|
|
||||||
returnCode = SSL_shutdown(ftpData.clients[theSocketId].workerData.serverSsl);
|
|
||||||
//my_printf("\nnSSL worker Shutdown 2 return code : %d", returnCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ftpData.clients[theSocketId].workerData.activeModeOn == 1)
|
|
||||||
{
|
|
||||||
returnCode = SSL_shutdown(ftpData.clients[theSocketId].workerData.clientSsl);
|
|
||||||
|
|
||||||
if (!returnCode)
|
|
||||||
{
|
|
||||||
shutdown(ftpData.clients[theSocketId].workerData.socketConnection, SHUT_RDWR);
|
|
||||||
shutdown(ftpData.clients[theSocketId].workerData.passiveListeningSocket, SHUT_RDWR);
|
|
||||||
returnCode = SSL_shutdown(ftpData.clients[theSocketId].workerData.clientSsl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
shutdown(ftpData.clients[theSocketId].workerData.socketConnection, SHUT_RDWR);
|
|
||||||
|
|
||||||
shutdown(ftpData.clients[theSocketId].workerData.passiveListeningSocket, SHUT_RDWR);
|
|
||||||
|
|
||||||
returnCode = close(ftpData.clients[theSocketId].workerData.socketConnection);
|
|
||||||
returnCode = close(ftpData.clients[theSocketId].workerData.passiveListeningSocket);
|
|
||||||
|
|
||||||
resetWorkerData(&ftpData, theSocketId, 0);
|
|
||||||
|
|
||||||
// my_printf("\nWorker cleaned!");
|
|
||||||
//my_printf("\nWorker memory table :%lld", ftpData.clients[theSocketId].workerData.memoryTable);
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].workerData.memoryTable != NULL)
|
|
||||||
;//my_printf("\nMemory table element label: %s", ftpData.clients[theSocketId].workerData.memoryTable->theName);
|
|
||||||
else
|
|
||||||
;//my_printf("\nNo data to print");
|
|
||||||
}
|
|
||||||
|
|
||||||
void *connectionWorkerHandle(void * socketId)
|
|
||||||
{
|
|
||||||
int theSocketId = *(int *)socketId;
|
|
||||||
// Enable cancellation for this thread
|
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
|
||||||
pthread_cleanup_push(workerCleanup, (void *) &theSocketId);
|
|
||||||
ftpData.clients[theSocketId].workerData.threadIsAlive = 1;
|
|
||||||
ftpData.clients[theSocketId].workerData.threadHasBeenCreated = 1;
|
|
||||||
int returnCode;
|
|
||||||
|
|
||||||
my_printf("\nWORKER CREATED!");
|
|
||||||
|
|
||||||
//Passive data connection mode
|
|
||||||
if (ftpData.clients[theSocketId].workerData.passiveModeOn == 1)
|
|
||||||
{
|
|
||||||
int tries = 30;
|
|
||||||
while (tries > 0)
|
|
||||||
{
|
|
||||||
setRandomicPort(&ftpData, theSocketId);
|
|
||||||
ftpData.clients[theSocketId].workerData.passiveListeningSocket = createPassiveSocket(ftpData.clients[theSocketId].workerData.connectionPort);
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].workerData.passiveListeningSocket != -1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tries--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].workerData.passiveListeningSocket == -1)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
my_printf("\n Closing the client 1");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].workerData.socketIsConnected == 0)
|
|
||||||
{
|
|
||||||
if (ftpData.clients[theSocketId].workerData.passiveModeOn == 1 && ftpData.clients[theSocketId].workerData.extendedPassiveModeOn == 0)
|
|
||||||
{
|
|
||||||
if(strnlen(ftpData.ftpParameters.natIpAddress, STRING_SZ_SMALL) > 0)
|
|
||||||
{
|
|
||||||
my_printf("\n Using nat ip: %s", ftpData.ftpParameters.natIpAddress);
|
|
||||||
returnCode = socketPrintf(&ftpData, theSocketId, "sssdsds", "227 Entering Passive Mode (", ftpData.ftpParameters.natIpAddress, ",", (ftpData.clients[theSocketId].workerData.connectionPort / 256), ",", (ftpData.clients[theSocketId].workerData.connectionPort % 256), ")\r\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
my_printf("\n Using server ip: %s", ftpData.ftpParameters.natIpAddress);
|
|
||||||
returnCode = socketPrintf(&ftpData, theSocketId, "sdsdsdsdsdsds", "227 Entering Passive Mode (", ftpData.clients[theSocketId].serverIpAddressInteger[0], ",", ftpData.clients[theSocketId].serverIpAddressInteger[1], ",", ftpData.clients[theSocketId].serverIpAddressInteger[2], ",", ftpData.clients[theSocketId].serverIpAddressInteger[3], ",", (ftpData.clients[theSocketId].workerData.connectionPort / 256), ",", (ftpData.clients[theSocketId].workerData.connectionPort % 256), ")\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ftpData.clients[theSocketId].workerData.passiveModeOn == 1 && ftpData.clients[theSocketId].workerData.extendedPassiveModeOn == 1)
|
|
||||||
{
|
|
||||||
returnCode = socketPrintf(&ftpData, theSocketId, "sds", "229 Entering Extended Passive Mode (|||", ftpData.clients[theSocketId].workerData.connectionPort, "|)\r\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
returnCode = -1;
|
|
||||||
my_printfError("\nUnknown passive state, should be PASV or EPSV");
|
|
||||||
perror("Unknown passive state, should be PASV or EPSV");
|
|
||||||
}
|
|
||||||
|
|
||||||
ftpData.clients[theSocketId].workerData.socketIsReadyForConnection = 1;
|
|
||||||
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 2");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Wait for sockets
|
|
||||||
if ((ftpData.clients[theSocketId].workerData.socketConnection = accept(ftpData.clients[theSocketId].workerData.passiveListeningSocket, 0, 0))!=-1)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].workerData.socketIsConnected = 1;
|
|
||||||
#ifdef OPENSSL_ENABLED
|
|
||||||
if (ftpData.clients[theSocketId].dataChannelIsTls == 1)
|
|
||||||
{
|
|
||||||
|
|
||||||
returnCode = SSL_set_fd(ftpData.clients[theSocketId].workerData.serverSsl, ftpData.clients[theSocketId].workerData.socketConnection);
|
|
||||||
|
|
||||||
if (returnCode == 0)
|
|
||||||
{
|
|
||||||
my_printf("\nSSL ERRORS ON WORKER SSL_set_fd");
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
}
|
|
||||||
|
|
||||||
returnCode = SSL_accept(ftpData.clients[theSocketId].workerData.serverSsl);
|
|
||||||
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
my_printf("\nSSL ERRORS ON WORKER");
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//my_printf("\nSSL ACCEPTED ON WORKER");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 3");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
my_printf("\n Socket already connected");
|
|
||||||
}
|
|
||||||
else if (ftpData.clients[theSocketId].workerData.activeModeOn == 1)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].workerData.socketConnection = createActiveSocket(ftpData.clients[theSocketId].workerData.connectionPort, ftpData.clients[theSocketId].workerData.activeIpAddress);
|
|
||||||
|
|
||||||
#ifdef OPENSSL_ENABLED
|
|
||||||
if (ftpData.clients[theSocketId].dataChannelIsTls == 1)
|
|
||||||
{
|
|
||||||
returnCode = SSL_set_fd(ftpData.clients[theSocketId].workerData.clientSsl, ftpData.clients[theSocketId].workerData.socketConnection);
|
|
||||||
|
|
||||||
if (returnCode == 0)
|
|
||||||
{
|
|
||||||
my_printf("\nSSL ERRORS ON WORKER SSL_set_fd");
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
}
|
|
||||||
//SSL_set_connect_state(ftpData.clients[theSocketId].workerData.clientSsl);
|
|
||||||
returnCode = SSL_connect(ftpData.clients[theSocketId].workerData.clientSsl);
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
my_printf("\nSSL ERRORS ON WORKER %d error code: %d", returnCode, SSL_get_error(ftpData.clients[theSocketId].workerData.clientSsl, returnCode));
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//my_printf("\nSSL ACCEPTED ON WORKER");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].workerData.socketConnection < 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 4");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
returnCode = socketPrintf(&ftpData, theSocketId, "s", "200 connection accepted\r\n");
|
|
||||||
ftpData.clients[theSocketId].workerData.socketIsReadyForConnection = 1;
|
|
||||||
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 5");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ftpData.clients[theSocketId].workerData.socketIsConnected = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//my_printf("\nftpData.clients[theSocketId].workerData.socketIsConnected = %d", ftpData.clients[theSocketId].workerData.socketIsConnected);
|
|
||||||
|
|
||||||
//Endless loop ftp process
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].workerData.socketIsConnected > 0)
|
|
||||||
{
|
|
||||||
my_printf("\nWorker %d is waiting for commands!", theSocketId);
|
|
||||||
//Conditional lock on tconditionVariablehread actions
|
|
||||||
pthread_mutex_lock(&ftpData.clients[theSocketId].conditionMutex);
|
|
||||||
while (ftpData.clients[theSocketId].workerData.commandReceived == 0)
|
|
||||||
{
|
|
||||||
pthread_cond_wait(&ftpData.clients[theSocketId].conditionVariable, &ftpData.clients[theSocketId].conditionMutex);
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&ftpData.clients[theSocketId].conditionMutex);
|
|
||||||
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].workerData.commandReceived == 1 &&
|
|
||||||
(compareStringCaseInsensitive(ftpData.clients[theSocketId].workerData.theCommandReceived, "STOR", strlen("STOR")) == 1 || compareStringCaseInsensitive(ftpData.clients[theSocketId].workerData.theCommandReceived, "APPE", strlen("APPE")) == 1) &&
|
|
||||||
ftpData.clients[theSocketId].fileToStor.textLen > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (compareStringCaseInsensitive(ftpData.clients[theSocketId].workerData.theCommandReceived, "APPE", strlen("APPE")) == 1)
|
|
||||||
{
|
|
||||||
#ifdef LARGE_FILE_SUPPORT_ENABLED
|
|
||||||
//#warning LARGE FILE SUPPORT IS ENABLED!
|
|
||||||
ftpData.clients[theSocketId].workerData.theStorFile = fopen64(ftpData.clients[theSocketId].fileToStor.text, "ab");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LARGE_FILE_SUPPORT_ENABLED
|
|
||||||
#warning LARGE FILE SUPPORT IS NOT ENABLED!
|
|
||||||
ftpData.clients[theSocketId].workerData.theStorFile = fopen(ftpData.clients[theSocketId].fileToStor.text, "ab");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef LARGE_FILE_SUPPORT_ENABLED
|
|
||||||
//#warning LARGE FILE SUPPORT IS ENABLED!
|
|
||||||
ftpData.clients[theSocketId].workerData.theStorFile = fopen64(ftpData.clients[theSocketId].fileToStor.text, "wb");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LARGE_FILE_SUPPORT_ENABLED
|
|
||||||
#warning LARGE FILE SUPPORT IS NOT ENABLED!
|
|
||||||
ftpData.clients[theSocketId].workerData.theStorFile = fopen(ftpData.clients[theSocketId].fileToStor.text, "wb");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].workerData.theStorFile == NULL)
|
|
||||||
{
|
|
||||||
returnCode = socketPrintf(&ftpData, theSocketId, "s", "553 Unable to write the file\r\n");
|
|
||||||
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 6");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
returnCode = socketPrintf(&ftpData, theSocketId, "s", "150 Accepted data connection\r\n");
|
|
||||||
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 7");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].dataChannelIsTls != 1)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].workerData.bufferIndex = read(ftpData.clients[theSocketId].workerData.socketConnection, ftpData.clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE);
|
|
||||||
}
|
|
||||||
else if (ftpData.clients[theSocketId].dataChannelIsTls == 1)
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef OPENSSL_ENABLED
|
|
||||||
if (ftpData.clients[theSocketId].workerData.passiveModeOn == 1)
|
|
||||||
ftpData.clients[theSocketId].workerData.bufferIndex = SSL_read(ftpData.clients[theSocketId].workerData.serverSsl, ftpData.clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE);
|
|
||||||
else if(ftpData.clients[theSocketId].workerData.activeModeOn == 1)
|
|
||||||
ftpData.clients[theSocketId].workerData.bufferIndex = SSL_read(ftpData.clients[theSocketId].workerData.clientSsl, ftpData.clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
my_printf("\nError state");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].workerData.bufferIndex == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (ftpData.clients[theSocketId].workerData.bufferIndex > 0)
|
|
||||||
{
|
|
||||||
fwrite(ftpData.clients[theSocketId].workerData.buffer, ftpData.clients[theSocketId].workerData.bufferIndex, 1, ftpData.clients[theSocketId].workerData.theStorFile);
|
|
||||||
usleep(100);
|
|
||||||
}
|
|
||||||
else if (ftpData.clients[theSocketId].workerData.bufferIndex < 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int theReturnCode;
|
|
||||||
theReturnCode = fclose(ftpData.clients[theSocketId].workerData.theStorFile);
|
|
||||||
ftpData.clients[theSocketId].workerData.theStorFile = NULL;
|
|
||||||
|
|
||||||
if (ftpData.clients[theSocketId].login.ownerShip.ownerShipSet == 1)
|
|
||||||
{
|
|
||||||
FILE_doChownFromUidGid(ftpData.clients[theSocketId].fileToStor.text, ftpData.clients[theSocketId].login.ownerShip.uid, ftpData.clients[theSocketId].login.ownerShip.gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
returnCode = socketPrintf(&ftpData, theSocketId, "s", "226 file stor ok\r\n");
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 8");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (ftpData.clients[theSocketId].workerData.commandReceived == 1 &&
|
|
||||||
( (compareStringCaseInsensitive(ftpData.clients[theSocketId].workerData.theCommandReceived, "LIST", strlen("LIST")) == 1)
|
|
||||||
|| (compareStringCaseInsensitive(ftpData.clients[theSocketId].workerData.theCommandReceived, "NLST", strlen("NLST")) == 1))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
int theFiles = 0, theCommandType = 0;
|
|
||||||
|
|
||||||
if (compareStringCaseInsensitive(ftpData.clients[theSocketId].workerData.theCommandReceived, "LIST", strlen("LIST")) == 1)
|
|
||||||
theCommandType = COMMAND_TYPE_LIST;
|
|
||||||
else if (compareStringCaseInsensitive(ftpData.clients[theSocketId].workerData.theCommandReceived, "NLST", strlen("NLST")) == 1)
|
|
||||||
theCommandType = COMMAND_TYPE_NLST;
|
|
||||||
|
|
||||||
returnCode = socketPrintf(&ftpData, theSocketId, "s", "150 Accepted data connection\r\n");
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 8");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
returnCode = writeListDataInfoToSocket(&ftpData, theSocketId, &theFiles, theCommandType, &ftpData.clients[theSocketId].workerData.memoryTable);
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 9");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
returnCode = socketPrintf(&ftpData, theSocketId, "sds", "226 ", theFiles, " matches total\r\n");
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 10");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (ftpData.clients[theSocketId].workerData.commandReceived == 1 &&
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[theSocketId].workerData.theCommandReceived, "RETR", strlen("RETR")) == 1)
|
|
||||||
{
|
|
||||||
long long int writenSize = 0, writeReturn = 0;
|
|
||||||
writeReturn = socketPrintf(&ftpData, theSocketId, "s", "150 Accepted data connection\r\n");
|
|
||||||
if (writeReturn <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 11");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
writenSize = writeRetrFile(&ftpData, theSocketId, ftpData.clients[theSocketId].workerData.retrRestartAtByte, ftpData.clients[theSocketId].workerData.theStorFile);
|
|
||||||
ftpData.clients[theSocketId].workerData.retrRestartAtByte = 0;
|
|
||||||
|
|
||||||
if (writenSize <= -1)
|
|
||||||
{
|
|
||||||
writeReturn = socketPrintf(&ftpData, theSocketId, "s", "550 unable to open the file for reading\r\n");
|
|
||||||
|
|
||||||
if (writeReturn <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 12");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeReturn = socketPrintf(&ftpData, theSocketId, "s", "226-File successfully transferred\r\n226 done\r\n");
|
|
||||||
|
|
||||||
if (writeReturn <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[theSocketId].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Closing the client 13");
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_exit((void *)1);
|
|
||||||
pthread_cleanup_pop(0);
|
|
||||||
pthread_exit((void *)2);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void runFtpServer(void)
|
|
||||||
{
|
|
||||||
printf("\nHello uFTP server %s starting..\n", UFTP_SERVER_VERSION);
|
printf("\nHello uFTP server %s starting..\n", UFTP_SERVER_VERSION);
|
||||||
|
|
||||||
/* Needed for Select*/
|
|
||||||
static int processingSock = 0, returnCode = 0;
|
|
||||||
|
|
||||||
/* Handle signals */
|
/* Handle signals */
|
||||||
signalHandlerInstall();
|
signalHandlerInstall();
|
||||||
|
|
||||||
@ -544,6 +83,7 @@ void runFtpServer(void)
|
|||||||
|
|
||||||
//Socket main creator
|
//Socket main creator
|
||||||
ftpData.connectionData.theMainSocket = createSocket(&ftpData);
|
ftpData.connectionData.theMainSocket = createSocket(&ftpData);
|
||||||
|
|
||||||
printf("\nuFTP server starting..");
|
printf("\nuFTP server starting..");
|
||||||
|
|
||||||
/* init fd set needed for select */
|
/* init fd set needed for select */
|
||||||
@ -556,445 +96,36 @@ void runFtpServer(void)
|
|||||||
if(returnCode != 0)
|
if(returnCode != 0)
|
||||||
{
|
{
|
||||||
my_printf("pthread_create WatchDog Error %d", returnCode);
|
my_printf("pthread_create WatchDog Error %d", returnCode);
|
||||||
addLog("Pthead create error restarting the server", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("Pthead create error restarting the server");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Endless loop ftp process
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
|
|
||||||
//Update watchdog timer
|
|
||||||
updateWatchDogTime((int)time(NULL));
|
|
||||||
|
|
||||||
/*
|
|
||||||
my_printf("\nUsed memory : %lld", DYNMEM_GetTotalMemory());
|
|
||||||
int memCount = 0;
|
|
||||||
for (memCount = 0; memCount < ftpData.ftpParameters.maxClients; memCount++)
|
|
||||||
{
|
|
||||||
if (ftpData.clients[memCount].memoryTable != NULL)
|
|
||||||
{
|
|
||||||
my_printf("\nftpData.clients[%d].memoryTable = %s", memCount, ftpData.clients[memCount].memoryTable->theName);
|
|
||||||
}
|
|
||||||
if (ftpData.clients[memCount].workerData.memoryTable != NULL)
|
|
||||||
{
|
|
||||||
my_printf("\nftpData.clients[%d].workerData.memoryTable = %s", memCount, ftpData.clients[memCount].workerData.memoryTable->theName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ftpData.clients[memCount].workerData.directoryInfo.memoryTable != NULL)
|
|
||||||
{
|
|
||||||
my_printf("\nftpData.clients[%d].workerData.directoryInfo.memoryTable = %s", memCount, ftpData.clients[memCount].workerData.directoryInfo.memoryTable->theName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* waits for socket activity, if no activity then checks for client socket timeouts */
|
|
||||||
if (selectWait(&ftpData) == 0)
|
|
||||||
{
|
|
||||||
checkClientConnectionTimeout(&ftpData);
|
|
||||||
flushLoginWrongTriesData(&ftpData);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*Main loop handle client commands */
|
|
||||||
for (processingSock = 0; processingSock < ftpData.ftpParameters.maxClients; processingSock++)
|
|
||||||
{
|
|
||||||
/* close the connection if quit flag has been set */
|
|
||||||
if (ftpData.clients[processingSock].closeTheClient == 1)
|
|
||||||
{
|
|
||||||
closeClient(&ftpData, processingSock);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if there are client pending connections, accept the connection if possible otherwise reject */
|
|
||||||
if ((returnCode = evaluateClientSocketConnection(&ftpData)) == 1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no data to check client is not connected, continue to check other clients */
|
|
||||||
if (isClientConnected(&ftpData, processingSock) == 0)
|
|
||||||
{
|
|
||||||
/* socket is not conneted */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FD_ISSET(ftpData.clients[processingSock].socketDescriptor, &ftpData.connectionData.rset) ||
|
|
||||||
FD_ISSET(ftpData.clients[processingSock].socketDescriptor, &ftpData.connectionData.eset))
|
|
||||||
{
|
|
||||||
|
|
||||||
#ifdef OPENSSL_ENABLED
|
|
||||||
if (ftpData.clients[processingSock].tlsIsNegotiating == 1)
|
|
||||||
{
|
|
||||||
returnCode = SSL_accept(ftpData.clients[processingSock].ssl);
|
|
||||||
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
//my_printf("\nSSL NOT YET ACCEPTED: %d", returnCode);
|
|
||||||
ftpData.clients[processingSock].tlsIsEnabled = 0;
|
|
||||||
ftpData.clients[processingSock].tlsIsNegotiating = 1;
|
|
||||||
|
|
||||||
if ( ((int)time(NULL) - ftpData.clients[processingSock].tlsNegotiatingTimeStart) > TLS_NEGOTIATING_TIMEOUT )
|
|
||||||
{
|
|
||||||
ftpData.clients[processingSock].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
//my_printf("\nTLS timeout closing the client time:%lld, start time: %lld..", (int)time(NULL), ftpData.clients[processingSock].tlsNegotiatingTimeStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//my_printf("\nSSL ACCEPTED");
|
|
||||||
ftpData.clients[processingSock].tlsIsEnabled = 1;
|
|
||||||
ftpData.clients[processingSock].tlsIsNegotiating = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ftpData.clients[processingSock].tlsIsEnabled == 1)
|
|
||||||
{
|
|
||||||
#ifdef OPENSSL_ENABLED
|
|
||||||
ftpData.clients[processingSock].bufferIndex = SSL_read(ftpData.clients[processingSock].ssl, ftpData.clients[processingSock].buffer, CLIENT_BUFFER_STRING_SIZE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ftpData.clients[processingSock].bufferIndex = read(ftpData.clients[processingSock].socketDescriptor, ftpData.clients[processingSock].buffer, CLIENT_BUFFER_STRING_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//The client is not connected anymore
|
|
||||||
if ((ftpData.clients[processingSock].bufferIndex) == 0)
|
|
||||||
{
|
|
||||||
//addLog("Client not connected anymore", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
closeClient(&ftpData, processingSock);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Debug print errors
|
|
||||||
if (ftpData.clients[processingSock].bufferIndex < 0)
|
|
||||||
{
|
|
||||||
//ftpData.clients[processingSock].closeTheClient = 1;
|
|
||||||
//addLog("Socket write error ", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
//my_printfError("\n1 Errno = %d", errno);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Some commands has been received
|
|
||||||
if (ftpData.clients[processingSock].bufferIndex > 0)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
int commandProcessStatus = 0;
|
|
||||||
for (i = 0; i < ftpData.clients[processingSock].bufferIndex; i++)
|
|
||||||
{
|
|
||||||
if (ftpData.clients[processingSock].commandIndex < CLIENT_COMMAND_STRING_SIZE)
|
|
||||||
{
|
|
||||||
if (ftpData.clients[processingSock].buffer[i] != '\r' && ftpData.clients[processingSock].buffer[i] != '\n')
|
|
||||||
{
|
|
||||||
ftpData.clients[processingSock].theCommandReceived[ftpData.clients[processingSock].commandIndex++] = ftpData.clients[processingSock].buffer[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ftpData.clients[processingSock].buffer[i] == '\n')
|
|
||||||
{
|
|
||||||
ftpData.clients[processingSock].socketCommandReceived = 1;
|
|
||||||
//my_printf("\n Processing the command: %s", ftpData.clients[processingSock].theCommandReceived);
|
|
||||||
commandProcessStatus = processCommand(processingSock);
|
|
||||||
//Echo unrecognized commands
|
|
||||||
if (commandProcessStatus == FTP_COMMAND_NOT_RECONIZED)
|
|
||||||
{
|
|
||||||
int returnCode = 0;
|
|
||||||
returnCode = socketPrintf(&ftpData, processingSock, "s", "500 Unknown command\r\n");
|
|
||||||
if (returnCode < 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[processingSock].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
}
|
|
||||||
my_printf("\n COMMAND NOT SUPPORTED ********* %s", ftpData.clients[processingSock].buffer);
|
|
||||||
}
|
|
||||||
else if (commandProcessStatus == FTP_COMMAND_PROCESSED)
|
|
||||||
{
|
|
||||||
ftpData.clients[processingSock].lastActivityTimeStamp = (int)time(NULL);
|
|
||||||
}
|
|
||||||
else if (commandProcessStatus == FTP_COMMAND_PROCESSED_WRITE_ERROR)
|
|
||||||
{
|
|
||||||
ftpData.clients[processingSock].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
my_printf("\n Write error WARNING!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Command overflow can't be processed
|
|
||||||
int returnCode;
|
|
||||||
ftpData.clients[processingSock].commandIndex = 0;
|
|
||||||
memset(ftpData.clients[processingSock].theCommandReceived, 0, CLIENT_COMMAND_STRING_SIZE+1);
|
|
||||||
returnCode = socketPrintf(&ftpData, processingSock, "s", "500 Unknown command\r\n");
|
|
||||||
if (returnCode <= 0)
|
|
||||||
{
|
|
||||||
ftpData.clients[processingSock].closeTheClient = 1;
|
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
}
|
|
||||||
my_printf("\n Command too long closing the client.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
usleep(100);
|
|
||||||
memset(ftpData.clients[processingSock].buffer, 0, CLIENT_BUFFER_STRING_SIZE+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Server Close
|
|
||||||
shutdown(ftpData.connectionData.theMainSocket, SHUT_RDWR);
|
|
||||||
close(ftpData.connectionData.theMainSocket);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int processCommand(int processingElement)
|
void runFtpServer(void)
|
||||||
{
|
{
|
||||||
int toReturn = 0;
|
initFtpServer();
|
||||||
//printTimeStamp();
|
|
||||||
my_printf ("\nCommand received from (%d): %s", processingElement, ftpData.clients[processingElement].theCommandReceived);
|
|
||||||
|
|
||||||
cleanDynamicStringDataType(&ftpData.clients[processingElement].ftpCommand.commandArgs, 0, &ftpData.clients[processingElement].memoryTable);
|
//Endless loop ftp process
|
||||||
cleanDynamicStringDataType(&ftpData.clients[processingElement].ftpCommand.commandOps, 0, &ftpData.clients[processingElement].memoryTable);
|
while (1)
|
||||||
|
|
||||||
if (ftpData.clients[processingElement].login.userLoggedIn == 0 &&
|
|
||||||
(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "USER", strlen("USER")) != 1 &&
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PASS", strlen("PASS")) != 1 &&
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "QUIT", strlen("QUIT")) != 1 &&
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PBSZ", strlen("PBSZ")) != 1 &&
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PROT", strlen("PROT")) != 1 &&
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "CCC", strlen("CCC")) != 1 &&
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "AUTH", strlen("AUTH")) != 1))
|
|
||||||
{
|
|
||||||
toReturn = notLoggedInMessage(&ftpData, processingElement);
|
|
||||||
ftpData.clients[processingElement].commandIndex = 0;
|
|
||||||
memset(ftpData.clients[processingElement].theCommandReceived, 0, CLIENT_COMMAND_STRING_SIZE+1);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Process Command
|
|
||||||
if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "USER", strlen("USER")) == 1)
|
|
||||||
{
|
{
|
||||||
//my_printf("\nUSER COMMAND RECEIVED");
|
evaluateControlChannel(&ftpData);
|
||||||
toReturn = parseCommandUser(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PASS", strlen("PASS")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nPASS COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandPass(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "SITE", strlen("SITE")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nSITE COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandSite(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "AUTH", strlen("AUTH")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nAUTH COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandAuth(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PROT", strlen("PROT")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nPROT COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandProt(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PBSZ", strlen("PBSZ")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nPBSZ COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandPbsz(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "CCC", strlen("CCC")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nCCC COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandCcc(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PWD", strlen("PWD")) == 1 ||
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "XPWD", strlen("XPWD")) == 1)
|
|
||||||
{
|
|
||||||
// XPWD
|
|
||||||
//my_printf("\nPWD COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandPwd(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "SYST", strlen("SYST")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nSYST COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandSyst(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "FEAT", strlen("FEAT")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nFEAT COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandFeat(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "TYPE I", strlen("TYPE I")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nTYPE I COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandTypeI(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "STRU F", strlen("STRU F")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nTYPE I COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandStruF(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "MODE S", strlen("MODE S")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nMODE S COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandModeS(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "TYPE A", strlen("TYPE A")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nTYPE A COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandTypeI(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "EPSV", strlen("EPSV")) == 1)
|
|
||||||
{
|
|
||||||
my_printf("\nEPSV COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandEpsv(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PASV", strlen("PASV")) == 1)
|
|
||||||
{
|
|
||||||
my_printf("\nPASV COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandPasv(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PORT", strlen("PORT")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nPORT COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandPort(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "LIST", strlen("LIST")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nLIST COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandList(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "STAT", strlen("STAT")) == 1)
|
|
||||||
{
|
|
||||||
my_printf("\nSTAT COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandStat(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "CDUP", strlen("CDUP")) == 1 ||
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "XCUP", strlen("XCUP")) == 1 ||
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "CWD ..", strlen("CWD ..")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nCDUP COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandCdup(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "CWD", strlen("CWD")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nCWD COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandCwd(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "REST", strlen("REST")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nREST COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandRest(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "RETR", strlen("RETR")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nRETR COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandRetr(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "STOR", strlen("STOR")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nSTOR COMMAND RECEIVED");
|
|
||||||
toReturn = parseCommandStor(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "MKD", strlen("MKD")) == 1 ||
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "XMKD", strlen("XMKD")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nMKD command received");
|
|
||||||
toReturn = parseCommandMkd(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "ABOR", strlen("ABOR")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nABOR command received");
|
|
||||||
toReturn = parseCommandAbor(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "DELE", strlen("DELE")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nDELE comman200 OKd received");
|
|
||||||
toReturn = parseCommandDele(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "OPTS", strlen("OPTS")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nOPTS command received");
|
|
||||||
toReturn = parseCommandOpts(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "MDTM", strlen("MDTM")) == 1)
|
|
||||||
{
|
|
||||||
my_printf("\nMTDM command received");
|
|
||||||
toReturn = parseCommandMdtm(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "NLST", strlen("NLST")) == 1)
|
|
||||||
{
|
|
||||||
// my_printf("\nNLST command received");
|
|
||||||
toReturn = parseCommandNlst(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "QUIT", strlen("QUIT")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nQUIT command received");
|
|
||||||
toReturn = parseCommandQuit(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "RMD", strlen("RMD")) == 1 ||
|
|
||||||
compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "XRMD", strlen("XRMD")) == 1)
|
|
||||||
{
|
|
||||||
// XRMD
|
|
||||||
// my_printf("\nRMD command received");
|
|
||||||
toReturn = parseCommandRmd(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "RNFR", strlen("RNFR")) == 1)
|
|
||||||
{
|
|
||||||
// my_printf("\nRNFR command received");
|
|
||||||
toReturn = parseCommandRnfr(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "RNTO", strlen("RNTO")) == 1)
|
|
||||||
{
|
|
||||||
// my_printf("\nRNTO command received");
|
|
||||||
toReturn = parseCommandRnto(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "SIZE", strlen("SIZE")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nSIZE command received");
|
|
||||||
toReturn = parseCommandSize(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "APPE", strlen("APPE")) == 1)
|
|
||||||
{
|
|
||||||
// my_printf("\nAPPE command received");
|
|
||||||
toReturn = parseCommandAppe(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "NOOP", strlen("NOOP")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nNOOP command received");
|
|
||||||
toReturn = parseCommandNoop(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "ACCT", strlen("ACCT")) == 1)
|
|
||||||
{
|
|
||||||
//my_printf("\nNOOP command received");
|
|
||||||
toReturn = parseCommandAcct(&ftpData, processingElement);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
; //Parse unsupported command not needed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ftpData.clients[processingElement].commandIndex = 0;
|
//Server Close
|
||||||
memset(ftpData.clients[processingElement].theCommandReceived, 0, CLIENT_COMMAND_STRING_SIZE+1);
|
shutdown(ftpData.connectionData.theMainSocket, SHUT_RDWR);
|
||||||
return toReturn;
|
close(ftpData.connectionData.theMainSocket);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocateMemory(void)
|
void deallocateMemory(void)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// my_printf("\n Deallocating the memory.. ");
|
my_printf("\nDeallocating server memory ..");
|
||||||
// my_printf("\nDYNMEM_freeAll called");
|
my_printf("\nDYNMEM_freeAll called");
|
||||||
// my_printf("\nElement size: %ld", ftpData.generalDynamicMemoryTable->size);
|
my_printf("\nMemory Table size: %ld", ftpData.generalDynamicMemoryTable->size);
|
||||||
// my_printf("\nElement address: %ld", (long int) ftpData.generalDynamicMemoryTable->address);
|
my_printf("\nMemory Table: %ld", (long int) ftpData.generalDynamicMemoryTable->address);
|
||||||
// my_printf("\nElement nextElement: %ld",(long int) ftpData.generalDynamicMemoryTable->nextElement);
|
my_printf("\nMemory Table: %ld",(long int) ftpData.generalDynamicMemoryTable->nextElement);
|
||||||
// my_printf("\nElement previousElement: %ld",(long int) ftpData.generalDynamicMemoryTable->previousElement);
|
my_printf("\nMemory Table: %ld",(long int) ftpData.generalDynamicMemoryTable->previousElement);
|
||||||
|
|
||||||
for (i = 0; i < ftpData.ftpParameters.maxClients; i++)
|
for (i = 0; i < ftpData.ftpParameters.maxClients; i++)
|
||||||
{
|
{
|
||||||
@ -1006,9 +137,9 @@ void deallocateMemory(void)
|
|||||||
DYNMEM_freeAll(&ftpData.ftpParameters.usersVector.memoryTable);
|
DYNMEM_freeAll(&ftpData.ftpParameters.usersVector.memoryTable);
|
||||||
DYNMEM_freeAll(&ftpData.generalDynamicMemoryTable);
|
DYNMEM_freeAll(&ftpData.generalDynamicMemoryTable);
|
||||||
|
|
||||||
//my_printf("\n\nUsed memory at end: %lld", DYNMEM_GetTotalMemory());
|
my_printf("\n\nUsed memory at end: %lld", DYNMEM_GetTotalMemory());
|
||||||
|
my_printf("\n ftpData.generalDynamicMemoryTable = %ld", ftpData.generalDynamicMemoryTable);
|
||||||
|
|
||||||
//my_printf("\n ftpData.generalDynamicMemoryTable = %ld", ftpData.generalDynamicMemoryTable);
|
|
||||||
#ifdef OPENSSL_ENABLED
|
#ifdef OPENSSL_ENABLED
|
||||||
SSL_CTX_free(ftpData.serverCtx);
|
SSL_CTX_free(ftpData.serverCtx);
|
||||||
cleanupOpenssl();
|
cleanupOpenssl();
|
||||||
|
@ -27,12 +27,10 @@
|
|||||||
#define FTPSERVER_H
|
#define FTPSERVER_H
|
||||||
|
|
||||||
#define MAX_FTP_CLIENTS 10
|
#define MAX_FTP_CLIENTS 10
|
||||||
#define UFTP_SERVER_VERSION "v2.6.0 stable"
|
#define UFTP_SERVER_VERSION "v4.0.0 stable"
|
||||||
|
|
||||||
|
|
||||||
|
void initFtpServer(void);
|
||||||
void runFtpServer(void);
|
void runFtpServer(void);
|
||||||
void *connectionWorkerHandle(void * socketId);
|
|
||||||
void workerCleanup(void *socketId);
|
|
||||||
void signal_callback_handler(int signum);
|
void signal_callback_handler(int signum);
|
||||||
void deallocateMemory(void);
|
void deallocateMemory(void);
|
||||||
|
|
||||||
|
79
ftpSpecs.h
79
ftpSpecs.h
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* The MIT License
|
|
||||||
*
|
|
||||||
* Copyright 2018 Ugo Cirmignani.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
USER <SP> <username> <CRLF>
|
|
||||||
PASS <SP> <password> <CRLF>
|
|
||||||
ACCT <SP> <account-information> <CRLF>
|
|
||||||
CWD <SP> <pathname> <CRLF>
|
|
||||||
CDUP <CRLF>
|
|
||||||
SMNT <SP> <pathname> <CRLF>
|
|
||||||
QUIT <CRLF>
|
|
||||||
REIN <CRLF>
|
|
||||||
PORT <SP> <host-port> <CRLF>
|
|
||||||
PASV <CRLF>
|
|
||||||
TYPE <SP> <type-code> <CRLF>
|
|
||||||
STRU <SP> <structure-code> <CRLF>
|
|
||||||
MODE <SP> <mode-code> <CRLF>
|
|
||||||
RETR <SP> <pathname> <CRLF>
|
|
||||||
STOR <SP> <pathname> <CRLF>
|
|
||||||
STOU <CRLF>
|
|
||||||
APPE <SP> <pathname> <CRLF>
|
|
||||||
ALLO <SP> <decimal-integer>
|
|
||||||
[<SP> R <SP> <decimal-integer>] <CRLF>
|
|
||||||
REST <SP> <marker> <CRLF>
|
|
||||||
RNFR <SP> <pathname> <CRLF>
|
|
||||||
RNTO <SP> <pathname> <CRLF>
|
|
||||||
ABOR <CRLF>
|
|
||||||
DELE <SP> <pathname> <CRLF>
|
|
||||||
RMD <SP> <pathname> <CRLF>
|
|
||||||
MKD <SP> <pathname> <CRLF>
|
|
||||||
PWD <CRLF>
|
|
||||||
LIST [<SP> <pathname>] <CRLF>
|
|
||||||
NLST [<SP> <pathname>] <CRLF>
|
|
||||||
SITE <SP> <string> <CRLF>
|
|
||||||
SYST <CRLF>
|
|
||||||
STAT [<SP> <pathname>] <CRLF>
|
|
||||||
HELP [<SP> <string>] <CRLF>
|
|
||||||
NOOP <CRLF>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FTPSPECS_H
|
|
||||||
#define FTPSPECS_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* FTPSPECS_H */
|
|
||||||
|
|
@ -143,9 +143,7 @@ void initFtpData(ftpDataType *ftpData)
|
|||||||
#ifdef OPENSSL_ENABLED
|
#ifdef OPENSSL_ENABLED
|
||||||
initOpenssl();
|
initOpenssl();
|
||||||
ftpData->serverCtx = createServerContext();
|
ftpData->serverCtx = createServerContext();
|
||||||
ftpData->clientCtx = createClientContext();
|
|
||||||
configureContext(ftpData->serverCtx, ftpData->ftpParameters.certificatePath, ftpData->ftpParameters.privateCertificatePath);
|
configureContext(ftpData->serverCtx, ftpData->ftpParameters.certificatePath, ftpData->ftpParameters.privateCertificatePath);
|
||||||
configureClientContext(ftpData->clientCtx, ftpData->ftpParameters.certificatePath, ftpData->ftpParameters.privateCertificatePath);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ftpData->connectedClients = 0;
|
ftpData->connectedClients = 0;
|
||||||
@ -528,7 +526,7 @@ static int parseConfigurationFile(ftpParameters_DataType *ftpParameters, DYNV_Ve
|
|||||||
searchIndex = searchParameter("SERVER_IP", parametersVector);
|
searchIndex = searchParameter("SERVER_IP", parametersVector);
|
||||||
if (searchIndex != -1)
|
if (searchIndex != -1)
|
||||||
{
|
{
|
||||||
strncpy(&ftpParameters->natIpAddress, ((parameter_DataType *) parametersVector->Data[searchIndex])->value, STRING_SZ_SMALL);
|
strncpy(ftpParameters->natIpAddress, ((parameter_DataType *) parametersVector->Data[searchIndex])->value, STRING_SZ_SMALL);
|
||||||
my_printf("\n SERVER_IP parameter:%s", ftpParameters->natIpAddress);
|
my_printf("\n SERVER_IP parameter:%s", ftpParameters->natIpAddress);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -552,10 +550,10 @@ static int parseConfigurationFile(ftpParameters_DataType *ftpParameters, DYNV_Ve
|
|||||||
searchIndex = searchParameter("FTP_SERVER_IP", parametersVector);
|
searchIndex = searchParameter("FTP_SERVER_IP", parametersVector);
|
||||||
if (searchIndex != -1)
|
if (searchIndex != -1)
|
||||||
{
|
{
|
||||||
sscanf (((parameter_DataType *) parametersVector->Data[searchIndex])->value,"%d.%d.%d.%d", &ftpParameters->ftpIpAddress[0],
|
sscanf (((parameter_DataType *) parametersVector->Data[searchIndex])->value,"%d.%d.%d.%d", &ftpParameters->ftpIpAddressV4[0],
|
||||||
&ftpParameters->ftpIpAddress[1],
|
&ftpParameters->ftpIpAddressV4[1],
|
||||||
&ftpParameters->ftpIpAddress[2],
|
&ftpParameters->ftpIpAddressV4[2],
|
||||||
&ftpParameters->ftpIpAddress[3]);
|
&ftpParameters->ftpIpAddressV4[3]);
|
||||||
//my_printf("\nFTP_SERVER_IP value: %d.%d.%d.%d", ftpParameters->ftpIpAddress[0],
|
//my_printf("\nFTP_SERVER_IP value: %d.%d.%d.%d", ftpParameters->ftpIpAddress[0],
|
||||||
// ftpParameters->ftpIpAddress[1],
|
// ftpParameters->ftpIpAddress[1],
|
||||||
// ftpParameters->ftpIpAddress[2],
|
// ftpParameters->ftpIpAddress[2],
|
||||||
@ -563,10 +561,10 @@ static int parseConfigurationFile(ftpParameters_DataType *ftpParameters, DYNV_Ve
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ftpParameters->ftpIpAddress[0] = 127;
|
ftpParameters->ftpIpAddressV4[0] = 127;
|
||||||
ftpParameters->ftpIpAddress[1] = 0;
|
ftpParameters->ftpIpAddressV4[1] = 0;
|
||||||
ftpParameters->ftpIpAddress[2] = 0;
|
ftpParameters->ftpIpAddressV4[2] = 0;
|
||||||
ftpParameters->ftpIpAddress[3] = 1;
|
ftpParameters->ftpIpAddressV4[3] = 1;
|
||||||
//my_printf("\nFTP_SERVER_IP parameter not found in the configuration file, listening on all available networks");
|
//my_printf("\nFTP_SERVER_IP parameter not found in the configuration file, listening on all available networks");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,23 @@
|
|||||||
#include "../debugHelper.h"
|
#include "../debugHelper.h"
|
||||||
#include "../ftpData.h"
|
#include "../ftpData.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "debug_defines.h"
|
||||||
|
|
||||||
|
static int is_ipv4_mapped_ipv6(const char *ip);
|
||||||
|
|
||||||
|
int is_ipv4_mapped_ipv6(const char *ip) {
|
||||||
|
size_t prefix_len = strlen("::ffff:");
|
||||||
|
|
||||||
|
// Check if the address starts with the mapped address prefix
|
||||||
|
if (strncmp(ip, "::ffff:", prefix_len) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the remaining part is a valid IPv4 address using existing logic
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int socketPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __fmt, ...)
|
int socketPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __fmt, ...)
|
||||||
{
|
{
|
||||||
@ -343,6 +360,226 @@ int getMaximumSocketFd(int mainSocket, ftpDataType * ftpData)
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef IPV6_ENABLED
|
||||||
|
|
||||||
|
int isPortInUse(int port) {
|
||||||
|
int sockfd;
|
||||||
|
struct sockaddr_in6 addr;
|
||||||
|
|
||||||
|
sockfd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
|
if (sockfd < 0) {
|
||||||
|
perror("socket");
|
||||||
|
return 1; // Assume port is in use if we can't create a socket
|
||||||
|
}
|
||||||
|
|
||||||
|
int reuse = 1;
|
||||||
|
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin6_family = AF_INET6;
|
||||||
|
addr.sin6_port = htons(port);
|
||||||
|
addr.sin6_addr = in6addr_any;
|
||||||
|
|
||||||
|
int result = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
|
||||||
|
close(sockfd); // Always close after test
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
return 0; // Port is free
|
||||||
|
} else if (errno == EADDRINUSE) {
|
||||||
|
return 1; // Port is in use
|
||||||
|
} else {
|
||||||
|
perror("bind");
|
||||||
|
return 1; // Other error, treat as in-use
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int createSocket(ftpDataType * ftpData)
|
||||||
|
{
|
||||||
|
//my_printf("\nCreating main socket on port %d", ftpData->ftpParameters.port);
|
||||||
|
int sock = -1, errorCode = -1;
|
||||||
|
struct sockaddr_in6 serveraddr;
|
||||||
|
|
||||||
|
//Socket creation IPV6
|
||||||
|
if ((sock = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
|
||||||
|
{
|
||||||
|
perror("socket() failed");
|
||||||
|
LOG_ERROR("Socket creation failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//No blocking socket
|
||||||
|
errorCode = fcntl(sock, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
int reuse = 1;
|
||||||
|
|
||||||
|
#ifdef SO_REUSEADDR
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0)
|
||||||
|
{
|
||||||
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
|
LOG_ERROR("socketopt failed");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
reuse = 1;
|
||||||
|
#ifdef SO_REUSEPORT
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
|
||||||
|
{
|
||||||
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
|
LOG_ERROR("setsocket error");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
memset(&serveraddr, 0, sizeof(serveraddr));
|
||||||
|
serveraddr.sin6_family = AF_INET6;
|
||||||
|
serveraddr.sin6_port = htons(ftpData->ftpParameters.port);
|
||||||
|
serveraddr.sin6_addr = in6addr_any;
|
||||||
|
|
||||||
|
if (bind(sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
|
||||||
|
{
|
||||||
|
close(sock);
|
||||||
|
perror("bind() failed");
|
||||||
|
LOG_ERROR("bind failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Number of client allowed
|
||||||
|
errorCode = listen(sock, ftpData->ftpParameters.maxClients + 1);
|
||||||
|
if (errorCode < 0)
|
||||||
|
{
|
||||||
|
LOG_ERROR("listen error");
|
||||||
|
if (sock != -1)
|
||||||
|
{
|
||||||
|
close(sock);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int createPassiveSocket(int port)
|
||||||
|
{
|
||||||
|
int sock, returnCode;
|
||||||
|
struct sockaddr_in6 serveraddr;
|
||||||
|
int max_retries = 12; // number of bind retries
|
||||||
|
int retry_delay_sec = 1; // delay between retries
|
||||||
|
|
||||||
|
if ((sock = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
|
||||||
|
{
|
||||||
|
perror("socket() failed");
|
||||||
|
LOG_ERROR("socket failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&serveraddr, 0, sizeof(serveraddr));
|
||||||
|
serveraddr.sin6_family = AF_INET6;
|
||||||
|
serveraddr.sin6_port = htons(port);
|
||||||
|
serveraddr.sin6_addr = in6addr_any;
|
||||||
|
|
||||||
|
int reuse = 1;
|
||||||
|
#ifdef SO_REUSEADDR
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
|
||||||
|
{
|
||||||
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
|
LOG_ERROR("setsocketerror");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SO_REUSEPORT
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
|
||||||
|
{
|
||||||
|
perror("setsockopt(SO_REUSEPORT) failed");
|
||||||
|
my_printfError("setsockopt(SO_REUSEPORT) failed");
|
||||||
|
LOG_ERROR("setsocketerror");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Retry bind if fails with EADDRINUSE
|
||||||
|
for (int i = 0; i < max_retries; i++)
|
||||||
|
{
|
||||||
|
returnCode = bind(sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
|
||||||
|
if (returnCode == 0)
|
||||||
|
{
|
||||||
|
if(i > 0)
|
||||||
|
printf("\n Success After: %d attempts", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno == EADDRINUSE)
|
||||||
|
{
|
||||||
|
my_printf("Bind failed with EADDRINUSE on port: %d, retrying %d/%d...\n",port, i + 1, max_retries);
|
||||||
|
sleep(retry_delay_sec); // wait before retrying
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Other bind errors: fail immediately
|
||||||
|
perror("bind() failed");
|
||||||
|
LOG_ERROR("bind failed");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnCode != 0)
|
||||||
|
{
|
||||||
|
my_printf("Bind failed after %d retries, errno=%d\n", max_retries, errno);
|
||||||
|
LOGF("%sBind failed after %d retries, errno=%d\n", LOG_ERROR_PREFIX, max_retries, errno);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen
|
||||||
|
returnCode = listen(sock, 1);
|
||||||
|
if (returnCode == -1)
|
||||||
|
{
|
||||||
|
LOG_ERROR("listen failed");
|
||||||
|
my_printf("\nCould not listen %d errno = %d", sock, errno);
|
||||||
|
if (sock != -1)
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int isPortInUse(int port) {
|
||||||
|
int sockfd;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
|
||||||
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (sockfd < 0) {
|
||||||
|
perror("socket");
|
||||||
|
return 1; // Assume port is in use if we can't create a socket
|
||||||
|
}
|
||||||
|
|
||||||
|
int reuse = 1;
|
||||||
|
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
int result = bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
|
||||||
|
close(sockfd); // Always close after test
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
return 0; // Port is free
|
||||||
|
} else if (errno == EADDRINUSE) {
|
||||||
|
return 1; // Port is in use
|
||||||
|
} else {
|
||||||
|
perror("bind");
|
||||||
|
return 1; // Other error, treat as in-use
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int createSocket(ftpDataType * ftpData)
|
int createSocket(ftpDataType * ftpData)
|
||||||
{
|
{
|
||||||
//my_printf("\nCreating main socket on port %d", ftpData->ftpParameters.port);
|
//my_printf("\nCreating main socket on port %d", ftpData->ftpParameters.port);
|
||||||
@ -369,7 +606,7 @@ int createSocket(ftpDataType * ftpData)
|
|||||||
{
|
{
|
||||||
perror("setsockopt(SO_REUSEADDR) failed");
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
addLog("socketopt failed", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("socketopt failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -379,7 +616,7 @@ int createSocket(ftpDataType * ftpData)
|
|||||||
{
|
{
|
||||||
perror("setsockopt(SO_REUSEADDR) failed");
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
addLog("setsocket error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("setsocket error");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
//Bind socket
|
//Bind socket
|
||||||
@ -409,82 +646,162 @@ int createSocket(ftpDataType * ftpData)
|
|||||||
|
|
||||||
int createPassiveSocket(int port)
|
int createPassiveSocket(int port)
|
||||||
{
|
{
|
||||||
int sock, returnCode;
|
int sock, returnCode;
|
||||||
struct sockaddr_in temp;
|
struct sockaddr_in serveraddr;
|
||||||
|
int max_retries = 12; // number of bind retries
|
||||||
|
int retry_delay_sec = 1; // delay between retries
|
||||||
|
|
||||||
//Socket creation
|
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
||||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
{
|
||||||
if (sock == -1)
|
perror("socket() failed");
|
||||||
{
|
LOG_ERROR("socket failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp.sin_family = AF_INET;
|
memset(&serveraddr, 0, sizeof(serveraddr));
|
||||||
temp.sin_addr.s_addr = INADDR_ANY;
|
serveraddr.sin_family = AF_INET;
|
||||||
temp.sin_port = htons(port);
|
serveraddr.sin_port = htons(port);
|
||||||
|
serveraddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
int reuse = 1;
|
||||||
|
#ifdef SO_REUSEADDR
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
|
||||||
|
{
|
||||||
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
|
LOG_ERROR("setsocketerror");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SO_REUSEPORT
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
|
||||||
|
{
|
||||||
|
perror("setsockopt(SO_REUSEPORT) failed");
|
||||||
|
my_printfError("setsockopt(SO_REUSEPORT) failed");
|
||||||
|
LOG_ERROR("setsocketerror");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Retry bind if it fails with EADDRINUSE
|
||||||
|
for (int i = 0; i < max_retries; i++)
|
||||||
|
{
|
||||||
|
returnCode = bind(sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
|
||||||
|
if (returnCode == 0)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
printf("\n Success After: %d attempts", i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno == EADDRINUSE)
|
||||||
|
{
|
||||||
|
my_printf("Bind failed with EADDRINUSE on port: %d, retrying %d/%d...\n", port, i + 1, max_retries);
|
||||||
|
sleep(retry_delay_sec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
perror("bind() failed");
|
||||||
|
LOG_ERROR("bind failed");
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (returnCode != 0)
|
||||||
|
{
|
||||||
|
my_printf("bind failed after %d retries, errno=%d\n", max_retries, errno);
|
||||||
|
LOGF("%sbind failed after %d retries, errno=%d\n", LOG_ERROR_PREFIX, max_retries, errno);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start listening
|
||||||
|
returnCode = listen(sock, 1);
|
||||||
|
if (returnCode == -1)
|
||||||
|
{
|
||||||
|
LOG_ERROR("listen failed");
|
||||||
|
my_printf("\nCould not listen %d errno = %d", sock, errno);
|
||||||
|
close(sock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef IPV6_ENABLED
|
||||||
|
int createActiveSocketV6(int port, char *ipAddress)
|
||||||
|
{
|
||||||
|
int sockfd;
|
||||||
|
struct sockaddr_in6 serv_addr6;
|
||||||
|
struct sockaddr *serv_addr_any;
|
||||||
|
|
||||||
|
// Creating socket
|
||||||
|
if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
|
||||||
|
{
|
||||||
|
my_printfError("Socket creation failed");
|
||||||
|
LOG_ERROR("Socket creation failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int reuse = 1;
|
int reuse = 1;
|
||||||
|
|
||||||
#ifdef SO_REUSEADDR
|
#ifdef SO_REUSEADDR
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
|
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
|
||||||
{
|
{
|
||||||
perror("setsockopt(SO_REUSEADDR) failed");
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
addLog("setsocketerror", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("set socket error");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SO_REUSEPORT
|
#ifdef SO_REUSEPORT
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
|
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
|
||||||
{
|
{
|
||||||
perror("setsockopt(SO_REUSEADDR) failed");
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
addLog("set socket error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("setsockopt error");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Bind socket
|
// Prepare the sockaddr structure
|
||||||
returnCode = bind(sock,(struct sockaddr*) &temp,sizeof(temp));
|
if (inet_pton(AF_INET6, ipAddress, &serv_addr6.sin6_addr) == 1)
|
||||||
|
{
|
||||||
|
serv_addr6.sin6_family = AF_INET6;
|
||||||
|
serv_addr6.sin6_port = htons(port);
|
||||||
|
serv_addr_any = (struct sockaddr *)&serv_addr6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_printfError("Invalid ip address");
|
||||||
|
LOG_ERROR("Invalid ip address");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (returnCode == -1)
|
// Connect to server
|
||||||
{
|
if (connect(sockfd, serv_addr_any, sizeof(serv_addr6)) < 0)
|
||||||
my_printf("\n Could not bind %d errno = %d", sock, errno);
|
{
|
||||||
|
my_printfError("Connection failed");
|
||||||
|
LOG_ERROR("Connection failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (sock != -1)
|
return sockfd;
|
||||||
{
|
|
||||||
close(sock);
|
|
||||||
}
|
|
||||||
return returnCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Number of client allowed
|
|
||||||
returnCode = listen(sock, 1);
|
|
||||||
|
|
||||||
if (returnCode == -1)
|
|
||||||
{
|
|
||||||
my_printf("\n Could not listen %d errno = %d", sock, errno);
|
|
||||||
if (sock != -1)
|
|
||||||
{
|
|
||||||
close(sock);
|
|
||||||
}
|
|
||||||
return returnCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sock;
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int createActiveSocket(int port, char *ipAddress)
|
int createActiveSocket(int port, char *ipAddress)
|
||||||
{
|
{
|
||||||
int sockfd;
|
int sockfd;
|
||||||
struct sockaddr_in serv_addr;
|
struct sockaddr_in serv_addr;
|
||||||
|
|
||||||
//my_printf("\n Connection socket is going to start ip: %s:%d \n", ipAddress, port);
|
my_printf("\n Connection socket is going to start ip: %s:%d \n", ipAddress, port);
|
||||||
memset(&serv_addr, 0, sizeof(struct sockaddr_in));
|
memset(&serv_addr, 0, sizeof(struct sockaddr_in));
|
||||||
serv_addr.sin_family = AF_INET;
|
serv_addr.sin_family = AF_INET;
|
||||||
serv_addr.sin_port = htons(port);
|
serv_addr.sin_port = htons(port);
|
||||||
if(inet_pton(AF_INET, ipAddress, &serv_addr.sin_addr)<=0)
|
if(inet_pton(AF_INET, ipAddress, &serv_addr.sin_addr)<=0)
|
||||||
{
|
{
|
||||||
my_printf("\n inet_pton error occured\n");
|
my_printf("\n inet_pton error occured at address: %s:%d\n", ipAddress, port);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +822,7 @@ int createActiveSocket(int port, char *ipAddress)
|
|||||||
{
|
{
|
||||||
perror("setsockopt(SO_REUSEADDR) failed");
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
addLog("set socket error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("set socket error");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -514,7 +831,7 @@ int createActiveSocket(int port, char *ipAddress)
|
|||||||
{
|
{
|
||||||
perror("setsockopt(SO_REUSEADDR) failed");
|
perror("setsockopt(SO_REUSEADDR) failed");
|
||||||
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
my_printfError("setsockopt(SO_REUSEADDR) failed");
|
||||||
addLog("setsockopt error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("setsockopt error");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -623,7 +940,7 @@ void closeClient(ftpDataType * ftpData, int processingSocket)
|
|||||||
|
|
||||||
if (ftpData->clients[processingSocket].workerData.threadIsAlive == 1)
|
if (ftpData->clients[processingSocket].workerData.threadIsAlive == 1)
|
||||||
{
|
{
|
||||||
cancelWorker(ftpData, processingSocket);
|
handleThreadReuse(ftpData, processingSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
FD_CLR(ftpData->clients[processingSocket].socketDescriptor, &ftpData->connectionData.rsetAll);
|
FD_CLR(ftpData->clients[processingSocket].socketDescriptor, &ftpData->connectionData.rsetAll);
|
||||||
@ -654,7 +971,7 @@ void checkClientConnectionTimeout(ftpDataType * ftpData)
|
|||||||
(int)time(NULL) - ftpData->clients[processingSock].lastActivityTimeStamp > ftpData->ftpParameters.maximumIdleInactivity)
|
(int)time(NULL) - ftpData->clients[processingSock].lastActivityTimeStamp > ftpData->ftpParameters.maximumIdleInactivity)
|
||||||
{
|
{
|
||||||
ftpData->clients[processingSock].closeTheClient = 1;
|
ftpData->clients[processingSock].closeTheClient = 1;
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_DEBUG("timeout, closing the connection for inactivity");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -713,6 +1030,139 @@ int getAvailableClientSocketIndex(ftpDataType * ftpData)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef IPV6_ENABLED
|
||||||
|
|
||||||
|
#warning IPV6 IS ENABLED
|
||||||
|
int evaluateClientSocketConnection(ftpDataType * ftpData)
|
||||||
|
{
|
||||||
|
char str[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
|
if (FD_ISSET(ftpData->connectionData.theMainSocket, &ftpData->connectionData.rset))
|
||||||
|
{
|
||||||
|
int availableSocketIndex;
|
||||||
|
if ((availableSocketIndex = getAvailableClientSocketIndex(ftpData)) != -1) //get available socket
|
||||||
|
{
|
||||||
|
if ((ftpData->clients[availableSocketIndex].socketDescriptor = accept(ftpData->connectionData.theMainSocket, (struct sockaddr *)&ftpData->clients[availableSocketIndex].client_sockaddr_in, (socklen_t*)&ftpData->clients[availableSocketIndex].sockaddr_in_size)) !=- 1)
|
||||||
|
{
|
||||||
|
int error, numberOfConnectionFromSameIp, i;
|
||||||
|
numberOfConnectionFromSameIp = 0;
|
||||||
|
ftpData->connectedClients++;
|
||||||
|
ftpData->clients[availableSocketIndex].socketIsConnected = 1;
|
||||||
|
|
||||||
|
error = fcntl(ftpData->clients[availableSocketIndex].socketDescriptor, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
fdAdd(ftpData, availableSocketIndex);
|
||||||
|
|
||||||
|
// - - //
|
||||||
|
ftpData->clients[availableSocketIndex].sockaddr_in_server_size = sizeof(ftpData->clients[availableSocketIndex].server_sockaddr_in);
|
||||||
|
ftpData->clients[availableSocketIndex].sockaddr_in_size = sizeof(ftpData->clients[availableSocketIndex].client_sockaddr_in);
|
||||||
|
|
||||||
|
getpeername(ftpData->clients[availableSocketIndex].socketDescriptor, (struct sockaddr *)&ftpData->clients[availableSocketIndex].client_sockaddr_in, &ftpData->clients[availableSocketIndex].sockaddr_in_size);
|
||||||
|
if(inet_ntop(AF_INET6, &ftpData->clients[availableSocketIndex].client_sockaddr_in.sin6_addr, ftpData->clients[availableSocketIndex].clientIpAddress, sizeof(ftpData->clients[availableSocketIndex].clientIpAddress)))
|
||||||
|
{
|
||||||
|
ftpData->clients[availableSocketIndex].clientPort = (int) ntohs(ftpData->clients[availableSocketIndex].client_sockaddr_in.sin6_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getsockname(ftpData->clients[availableSocketIndex].socketDescriptor, (struct sockaddr *)&ftpData->clients[availableSocketIndex].server_sockaddr_in, &ftpData->clients[availableSocketIndex].sockaddr_in_server_size);
|
||||||
|
if(inet_ntop(AF_INET6, &ftpData->clients[availableSocketIndex].server_sockaddr_in.sin6_addr, ftpData->clients[availableSocketIndex].serverIpAddress, sizeof(ftpData->clients[availableSocketIndex].serverIpAddress)))
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_ipv4_mapped_ipv6(ftpData->clients[availableSocketIndex].clientIpAddress))
|
||||||
|
{
|
||||||
|
|
||||||
|
sscanf (ftpData->clients[availableSocketIndex].serverIpAddress,"::ffff:%d.%d.%d.%d", &ftpData->clients[availableSocketIndex].serverIpV4AddressInteger[0],
|
||||||
|
&ftpData->clients[availableSocketIndex].serverIpV4AddressInteger[1],
|
||||||
|
&ftpData->clients[availableSocketIndex].serverIpV4AddressInteger[2],
|
||||||
|
&ftpData->clients[availableSocketIndex].serverIpV4AddressInteger[3]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's an IPv4-mapped address
|
||||||
|
if (is_ipv4_mapped_ipv6(ftpData->clients[availableSocketIndex].clientIpAddress))
|
||||||
|
{
|
||||||
|
ftpData->clients[availableSocketIndex].isIpV6 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ftpData->clients[availableSocketIndex].isIpV6 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ftpData->clients[availableSocketIndex].connectionTimeStamp = (int)time(NULL);
|
||||||
|
ftpData->clients[availableSocketIndex].lastActivityTimeStamp = (int)time(NULL);
|
||||||
|
|
||||||
|
for (i = 0; i <ftpData->ftpParameters.maxClients; i++)
|
||||||
|
{
|
||||||
|
if (i == availableSocketIndex)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(ftpData->clients[availableSocketIndex].clientIpAddress, ftpData->clients[i].clientIpAddress) == 0) {
|
||||||
|
numberOfConnectionFromSameIp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ftpData->ftpParameters.maximumConnectionsPerIp > 0 &&
|
||||||
|
numberOfConnectionFromSameIp >= ftpData->ftpParameters.maximumConnectionsPerIp)
|
||||||
|
{
|
||||||
|
int theReturnCode = socketPrintf(ftpData, availableSocketIndex, "sss", "530 too many connection from your ip address ", ftpData->clients[availableSocketIndex].clientIpAddress, " \r\n");
|
||||||
|
ftpData->clients[availableSocketIndex].closeTheClient = 1;
|
||||||
|
LOGF("%stoo many connection from ip address: %s maximum allowed: %d", LOG_SECURITY_PREFIX, ftpData->clients[availableSocketIndex].clientIpAddress, ftpData->ftpParameters.maximumConnectionsPerIp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int returnCode = socketPrintf(ftpData, availableSocketIndex, "s", ftpData->welcomeMessage);
|
||||||
|
if (returnCode <= 0)
|
||||||
|
{
|
||||||
|
ftpData->clients[availableSocketIndex].closeTheClient = 1;
|
||||||
|
LOG_ERROR("socketPrintf");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Errors while accepting, socket will be closed
|
||||||
|
ftpData->clients[availableSocketIndex].closeTheClient = 1;
|
||||||
|
LOG_ERROR("Errors while accepting, socket will be closed");
|
||||||
|
//my_printf("\n2 Errno = %d", errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int socketRefuseFd;
|
||||||
|
struct sockaddr_in6 socketRefuse_sockaddr_in;
|
||||||
|
socklen_t socketRefuse_in_size = sizeof(socketRefuse_sockaddr_in);
|
||||||
|
if ((socketRefuseFd = accept(ftpData->connectionData.theMainSocket, (struct sockaddr *)&socketRefuse_sockaddr_in, &socketRefuse_in_size))!=-1)
|
||||||
|
{
|
||||||
|
int theReturnCode = 0;
|
||||||
|
char *messageToWrite = "10068 Server reached the maximum number of connection, please try later.\r\n";
|
||||||
|
write(socketRefuseFd, messageToWrite, strlen(messageToWrite));
|
||||||
|
shutdown(socketRefuseFd, SHUT_RDWR);
|
||||||
|
theReturnCode = close(socketRefuseFd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//No new socket
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
int evaluateClientSocketConnection(ftpDataType * ftpData)
|
int evaluateClientSocketConnection(ftpDataType * ftpData)
|
||||||
{
|
{
|
||||||
if (FD_ISSET(ftpData->connectionData.theMainSocket, &ftpData->connectionData.rset))
|
if (FD_ISSET(ftpData->connectionData.theMainSocket, &ftpData->connectionData.rset))
|
||||||
@ -739,10 +1189,10 @@ int evaluateClientSocketConnection(ftpDataType * ftpData)
|
|||||||
//my_printf("\n Server IP: %s", ftpData->clients[availableSocketIndex].serverIpAddress);
|
//my_printf("\n Server IP: %s", ftpData->clients[availableSocketIndex].serverIpAddress);
|
||||||
//my_printf("Server: New client connected with id: %d", availableSocketIndex);
|
//my_printf("Server: New client connected with id: %d", availableSocketIndex);
|
||||||
//my_printf("\nServer: Clients connected: %d", ftpData->connectedClients);
|
//my_printf("\nServer: Clients connected: %d", ftpData->connectedClients);
|
||||||
sscanf (ftpData->clients[availableSocketIndex].serverIpAddress,"%d.%d.%d.%d", &ftpData->clients[availableSocketIndex].serverIpAddressInteger[0],
|
sscanf (ftpData->clients[availableSocketIndex].serverIpAddress,"%d.%d.%d.%d", &ftpData->clients[availableSocketIndex].serverIpV4AddressInteger[0],
|
||||||
&ftpData->clients[availableSocketIndex].serverIpAddressInteger[1],
|
&ftpData->clients[availableSocketIndex].serverIpV4AddressInteger[1],
|
||||||
&ftpData->clients[availableSocketIndex].serverIpAddressInteger[2],
|
&ftpData->clients[availableSocketIndex].serverIpV4AddressInteger[2],
|
||||||
&ftpData->clients[availableSocketIndex].serverIpAddressInteger[3]);
|
&ftpData->clients[availableSocketIndex].serverIpV4AddressInteger[3]);
|
||||||
|
|
||||||
inet_ntop(AF_INET,
|
inet_ntop(AF_INET,
|
||||||
&(ftpData->clients[availableSocketIndex].client_sockaddr_in.sin_addr),
|
&(ftpData->clients[availableSocketIndex].client_sockaddr_in.sin_addr),
|
||||||
@ -771,7 +1221,8 @@ int evaluateClientSocketConnection(ftpDataType * ftpData)
|
|||||||
{
|
{
|
||||||
int theReturnCode = socketPrintf(ftpData, availableSocketIndex, "sss", "530 too many connection from your ip address ", ftpData->clients[availableSocketIndex].clientIpAddress, " \r\n");
|
int theReturnCode = socketPrintf(ftpData, availableSocketIndex, "sss", "530 too many connection from your ip address ", ftpData->clients[availableSocketIndex].clientIpAddress, " \r\n");
|
||||||
ftpData->clients[availableSocketIndex].closeTheClient = 1;
|
ftpData->clients[availableSocketIndex].closeTheClient = 1;
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
char
|
||||||
|
LOGF("%sToo many connection from %s max per ip is %d", LOG_SECURITY_PREFIX, ftpData->clients[availableSocketIndex].clientIpAddress, ftpData->ftpParameters.maximumConnectionsPerIp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -779,7 +1230,7 @@ int evaluateClientSocketConnection(ftpDataType * ftpData)
|
|||||||
if (returnCode <= 0)
|
if (returnCode <= 0)
|
||||||
{
|
{
|
||||||
ftpData->clients[availableSocketIndex].closeTheClient = 1;
|
ftpData->clients[availableSocketIndex].closeTheClient = 1;
|
||||||
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("socketPrintf");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,7 +1240,7 @@ int evaluateClientSocketConnection(ftpDataType * ftpData)
|
|||||||
{
|
{
|
||||||
//Errors while accepting, socket will be closed
|
//Errors while accepting, socket will be closed
|
||||||
ftpData->clients[availableSocketIndex].closeTheClient = 1;
|
ftpData->clients[availableSocketIndex].closeTheClient = 1;
|
||||||
//addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_ERROR("Errors while accepting, socket will be closed");
|
||||||
//my_printf("\n2 Errno = %d", errno);
|
//my_printf("\n2 Errno = %d", errno);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -817,3 +1268,118 @@ int evaluateClientSocketConnection(ftpDataType * ftpData)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPENSSL_ENABLED
|
||||||
|
int acceptSSLConnection(int theSocketId, ftpDataType * ftpData)
|
||||||
|
{
|
||||||
|
SSL *ssl = ftpData->clients[theSocketId].workerData.serverSsl;
|
||||||
|
int sockfd = ftpData->clients[theSocketId].workerData.socketConnection;
|
||||||
|
|
||||||
|
my_printf("\nSSL SSL_set_fd start");
|
||||||
|
|
||||||
|
int rc = SSL_set_fd(ssl, sockfd);
|
||||||
|
if (rc == 0)
|
||||||
|
{
|
||||||
|
my_printf("\nSSL ERRORS ON SSL_set_fd");
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("Closing client SSL_set_fd");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
my_printf("\nSSL SSL_set_fd end");
|
||||||
|
|
||||||
|
int flags = fcntl(sockfd, F_GETFL, 0);
|
||||||
|
if (flags == -1)
|
||||||
|
{
|
||||||
|
perror("fcntl get flags");
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||||
|
{
|
||||||
|
perror("fcntl set nonblocking");
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_printf("\nSSL accept start");
|
||||||
|
|
||||||
|
// Reuse the session from control connection
|
||||||
|
SSL_SESSION *session = SSL_get_session(ftpData->clients[theSocketId].ssl);
|
||||||
|
|
||||||
|
if (session != NULL)
|
||||||
|
{
|
||||||
|
unsigned int len;
|
||||||
|
const unsigned char *id = SSL_SESSION_get_id(session, &len);
|
||||||
|
|
||||||
|
my_printf("Trying to reuse SSL Session ID: ");
|
||||||
|
for (unsigned int i = 0; i < len; i++) {
|
||||||
|
my_printf("\n%02X", id[i]);
|
||||||
|
}
|
||||||
|
my_printf("\n");
|
||||||
|
|
||||||
|
SSL_set_session(ssl, session);
|
||||||
|
} else {
|
||||||
|
my_printf("\nNo session available for reuse. Accepting fresh handshake.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SSL_set_accept_state(ssl);
|
||||||
|
|
||||||
|
int max_attempts = 500; // 500*10ms = 5 sec timeout
|
||||||
|
while (max_attempts--)
|
||||||
|
{
|
||||||
|
rc = SSL_accept(ssl);
|
||||||
|
|
||||||
|
if (rc == 1)
|
||||||
|
{
|
||||||
|
my_printf("\n------------------------------------------- SSL_accept success");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = SSL_get_error(ssl, rc);
|
||||||
|
//my_printf("\nSSL_accept err: %d\n", err);
|
||||||
|
|
||||||
|
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
||||||
|
{
|
||||||
|
usleep(10000); // 10 ms
|
||||||
|
//my_printf("\nSSL_accept waiting ...");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_printf("\n-------------------------------------------SSL_accept failed:");
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
LOG_ERROR("Closing client SSL_accept");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_attempts <= 0)
|
||||||
|
{
|
||||||
|
my_printf("\nSSL_accept timeout");
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSL_session_reused(ssl)) {
|
||||||
|
my_printf("\n**** FTPS data connection reused control TLS session.\n");
|
||||||
|
} else {
|
||||||
|
my_printf("\n**** FTPS data connection did NOT reuse TLS session.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fcntl(sockfd, F_SETFL, flags) == -1)
|
||||||
|
{
|
||||||
|
perror("fcntl set blocking");
|
||||||
|
ftpData->clients[theSocketId].closeTheClient = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
@ -36,6 +36,15 @@ int getMaximumSocketFd(int mainSocket, ftpDataType * data);
|
|||||||
int createSocket(ftpDataType * ftpData);
|
int createSocket(ftpDataType * ftpData);
|
||||||
int createPassiveSocket(int port);
|
int createPassiveSocket(int port);
|
||||||
int createActiveSocket(int port, char *ipAddress);
|
int createActiveSocket(int port, char *ipAddress);
|
||||||
|
|
||||||
|
#ifdef IPV6_ENABLED
|
||||||
|
int createActiveSocketV6(int port, char *ipAddress);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPENSSL_ENABLED
|
||||||
|
int acceptSSLConnection(int theSocketId, ftpDataType * ftpData);
|
||||||
|
#endif
|
||||||
|
|
||||||
void fdInit(ftpDataType * ftpData);
|
void fdInit(ftpDataType * ftpData);
|
||||||
void fdAdd(ftpDataType * ftpData, int index);
|
void fdAdd(ftpDataType * ftpData, int index);
|
||||||
void fdRemove(ftpDataType * ftpData, int index);
|
void fdRemove(ftpDataType * ftpData, int index);
|
||||||
@ -51,7 +60,6 @@ int evaluateClientSocketConnection(ftpDataType * ftpData);
|
|||||||
int socketPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __fmt, ...);
|
int socketPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __fmt, ...);
|
||||||
int socketWorkerPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __fmt, ...);
|
int socketWorkerPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,7 +37,10 @@ void DYNMEM_Init(void)
|
|||||||
|
|
||||||
unsigned long long int DYNMEM_GetTotalMemory(void)
|
unsigned long long int DYNMEM_GetTotalMemory(void)
|
||||||
{
|
{
|
||||||
return theTotalMemory;
|
pthread_mutex_lock(&memoryCountMutex);
|
||||||
|
unsigned long long int mem = theTotalMemory;
|
||||||
|
pthread_mutex_unlock(&memoryCountMutex);
|
||||||
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long int DYNMEM_IncreaseMemoryCounter(unsigned long long int theSize)
|
unsigned long long int DYNMEM_IncreaseMemoryCounter(unsigned long long int theSize)
|
||||||
@ -79,7 +82,8 @@ void *DYNMEM_malloc(size_t bytes, DYNMEM_MemoryTable_DataType **memoryListHead,
|
|||||||
newItem->size = bytes;
|
newItem->size = bytes;
|
||||||
newItem->nextElement = NULL;
|
newItem->nextElement = NULL;
|
||||||
newItem->previousElement = NULL;
|
newItem->previousElement = NULL;
|
||||||
strncpy(newItem->theName, theName, 20);
|
strncpy(newItem->theName, theName, sizeof(newItem->theName) - 1);
|
||||||
|
newItem->theName[sizeof(newItem->theName) - 1] = '\0';
|
||||||
|
|
||||||
if( (*memoryListHead) != NULL)
|
if( (*memoryListHead) != NULL)
|
||||||
{
|
{
|
||||||
@ -140,7 +144,6 @@ void *DYNMEM_realloc(void *theMemoryAddress, size_t bytes, DYNMEM_MemoryTable_Da
|
|||||||
//strcpy(theData, "NOOOOOOOOOOOOOOOO");
|
//strcpy(theData, "NOOOOOOOOOOOOOOOO");
|
||||||
|
|
||||||
report_error_q("Unable to reallocate memory not previously allocated",__FILE__,__LINE__, 0);
|
report_error_q("Unable to reallocate memory not previously allocated",__FILE__,__LINE__, 0);
|
||||||
free(newMemory);
|
|
||||||
// Report this as an error
|
// Report this as an error
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -238,3 +241,27 @@ void DYNMEM_freeAll(DYNMEM_MemoryTable_DataType **memoryListHead)
|
|||||||
(*memoryListHead) = temp;
|
(*memoryListHead) = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DYNMEM_dump(DYNMEM_MemoryTable_DataType *memoryListHead)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
unsigned long long int total = 0;
|
||||||
|
|
||||||
|
my_printf("\n==== DYNMEM Memory Dump ====\n");
|
||||||
|
|
||||||
|
for (DYNMEM_MemoryTable_DataType *current = memoryListHead; current != NULL; current = current->nextElement)
|
||||||
|
{
|
||||||
|
my_printf("Block %d:\n", count + 1);
|
||||||
|
my_printf(" Address : %p\n", current->address);
|
||||||
|
my_printf(" Size : %zu bytes\n", current->size);
|
||||||
|
my_printf(" Label : %s\n", current->theName);
|
||||||
|
my_printf(" Block MetaSize: %zu bytes\n", sizeof(DYNMEM_MemoryTable_DataType));
|
||||||
|
total += current->size + sizeof(DYNMEM_MemoryTable_DataType);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_printf("\nTotal blocks : %d\n", count);
|
||||||
|
my_printf("Total memory used : %llu bytes (including metadata)\n", total);
|
||||||
|
my_printf("Global counter : %llu bytes\n", DYNMEM_GetTotalMemory());
|
||||||
|
my_printf("=============================\n");
|
||||||
|
}
|
||||||
|
@ -26,6 +26,6 @@ void *DYNMEM_malloc(size_t bytes, DYNMEM_MemoryTable_DataType ** memoryListHead,
|
|||||||
void *DYNMEM_realloc(void *theMemoryAddress, size_t bytes, DYNMEM_MemoryTable_DataType **memoryListHead);
|
void *DYNMEM_realloc(void *theMemoryAddress, size_t bytes, DYNMEM_MemoryTable_DataType **memoryListHead);
|
||||||
void DYNMEM_free(void *f_address, DYNMEM_MemoryTable_DataType ** memoryListHead);
|
void DYNMEM_free(void *f_address, DYNMEM_MemoryTable_DataType ** memoryListHead);
|
||||||
void DYNMEM_freeAll(DYNMEM_MemoryTable_DataType ** memoryListHead);
|
void DYNMEM_freeAll(DYNMEM_MemoryTable_DataType ** memoryListHead);
|
||||||
|
void DYNMEM_dump(DYNMEM_MemoryTable_DataType *memoryListHead);
|
||||||
|
|
||||||
#endif /* LIBRARY_DYNAMICMEMORY_H_ */
|
#endif /* LIBRARY_DYNAMICMEMORY_H_ */
|
||||||
|
@ -204,7 +204,7 @@ int FILE_IsLink( char* path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if a file is valid */
|
/* Check if a file is valid */
|
||||||
int FILE_IsFile(const char *TheFileName, int checkExist)
|
int FILE_IsFile(char *TheFileName, int checkExist)
|
||||||
{
|
{
|
||||||
FILE *TheFile;
|
FILE *TheFile;
|
||||||
|
|
||||||
@ -257,23 +257,23 @@ void FILE_GetDirectoryInodeList(char * DirectoryInodeName, char *** InodeList, i
|
|||||||
|
|
||||||
//
|
//
|
||||||
if ((dir->d_name[0] == '.' && dir->d_name[1] == '.' && strnlen(dir->d_name, 3) == 2) && (commandOps == NULL || commandOps[0] != 'a'))
|
if ((dir->d_name[0] == '.' && dir->d_name[1] == '.' && strnlen(dir->d_name, 3) == 2) && (commandOps == NULL || commandOps[0] != 'a'))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//Skips all files and dir starting with .
|
//Skips all files and dir starting with .
|
||||||
if ((dir->d_name[0] == '.' && commandOps == NULL) || (dir->d_name[0] == '.' && commandOps[0] != 'a' && commandOps[0] != 'A'))
|
if ((dir->d_name[0] == '.' && commandOps == NULL) || (dir->d_name[0] == '.' && commandOps[0] != 'a' && commandOps[0] != 'A'))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
char *thePathToCheck[PATH_MAX];
|
char thePathToCheck[PATH_MAX];
|
||||||
memset(thePathToCheck, 0, PATH_MAX);
|
memset(thePathToCheck, 0, PATH_MAX);
|
||||||
|
|
||||||
strcpy(thePathToCheck, DirectoryInodeName);
|
strcpy(thePathToCheck, DirectoryInodeName);
|
||||||
strcat(thePathToCheck, "/");
|
strcat(thePathToCheck, "/");
|
||||||
strcat(thePathToCheck, dir->d_name);
|
strcat(thePathToCheck, dir->d_name);
|
||||||
|
|
||||||
printf("\n ************* thePathToCheck = %s", thePathToCheck);
|
|
||||||
if (checkIfInodeExist == 1 && FILE_CheckIfLinkExist(thePathToCheck) == 0)
|
if (checkIfInodeExist == 1 && FILE_CheckIfLinkExist(thePathToCheck) == 0)
|
||||||
{
|
{
|
||||||
printf("--> Not valid!");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,7 +341,7 @@ int FILE_GetDirectoryInodeCount(char * DirectoryInodeName)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( dir->d_name[0] == '.' && dir->d_name[1] == '.' && strnlen(dir->d_name, 3) == 2)
|
if ( dir->d_name[0] == '.' && dir->d_name[1] == '.' && strnlen(dir->d_name, 3) == 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FileAndFolderIndex++;
|
FileAndFolderIndex++;
|
||||||
|
|
||||||
@ -749,8 +749,7 @@ char * FILE_GetGroupOwner(char *fileName, DYNMEM_MemoryTable_DataType **memoryTa
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FILE_AppendStringToFile(char *fileName, char *theString)
|
||||||
char * FILE_AppendStringToFile(char *fileName, char *theString)
|
|
||||||
{
|
{
|
||||||
FILE *fp = fopen(fileName, "a");
|
FILE *fp = fopen(fileName, "a");
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
@ -758,7 +757,7 @@ char * FILE_AppendStringToFile(char *fileName, char *theString)
|
|||||||
my_printfError("\nError while opening file %s.", fileName);
|
my_printfError("\nError while opening file %s.", fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "\n%s", theString);
|
fprintf(fp, "\n%s", theString);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@
|
|||||||
long long int FILE_GetFileSize(FILE *theFilePointer);
|
long long int FILE_GetFileSize(FILE *theFilePointer);
|
||||||
long int FILE_GetAvailableSpace(const char* ThePath);
|
long int FILE_GetAvailableSpace(const char* ThePath);
|
||||||
long long int FILE_GetFileSizeFromPath(char *TheFileName);
|
long long int FILE_GetFileSizeFromPath(char *TheFileName);
|
||||||
int FILE_IsFile(const char *theFileName, int checkExist);
|
int FILE_IsFile(char *theFileName, int checkExist);
|
||||||
int FILE_IsDirectory (char *directory_path, int checkExist);
|
int FILE_IsDirectory (char *directory_path, int checkExist);
|
||||||
int FILE_IsLink (char *directory_path);
|
int FILE_IsLink (char *directory_path);
|
||||||
void FILE_GetDirectoryInodeList(char * DirectoryInodeName, char *** InodeList, int * filesandfolders, int recursive, char* commandOps, int checkIfInodeExist, DYNMEM_MemoryTable_DataType ** memoryTable);
|
void FILE_GetDirectoryInodeList(char * DirectoryInodeName, char *** InodeList, int * filesandfolders, int recursive, char* commandOps, int checkIfInodeExist, DYNMEM_MemoryTable_DataType ** memoryTable);
|
||||||
@ -71,7 +71,7 @@
|
|||||||
char * FILE_GetListPermissionsString(char *file, DYNMEM_MemoryTable_DataType ** memoryTable);
|
char * FILE_GetListPermissionsString(char *file, DYNMEM_MemoryTable_DataType ** memoryTable);
|
||||||
char * FILE_GetOwner(char *fileName, DYNMEM_MemoryTable_DataType ** memoryTable);
|
char * FILE_GetOwner(char *fileName, DYNMEM_MemoryTable_DataType ** memoryTable);
|
||||||
char * FILE_GetGroupOwner(char *fileName, DYNMEM_MemoryTable_DataType ** memoryTable);
|
char * FILE_GetGroupOwner(char *fileName, DYNMEM_MemoryTable_DataType ** memoryTable);
|
||||||
char * FILE_AppendStringToFile(char *fileName, char *theString);
|
void FILE_AppendStringToFile(char *fileName, char *theString);
|
||||||
time_t FILE_GetLastModifiedData(char *path);
|
time_t FILE_GetLastModifiedData(char *path);
|
||||||
void FILE_AppendToString(char ** sourceString, char *theString, DYNMEM_MemoryTable_DataType ** memoryTable);
|
void FILE_AppendToString(char ** sourceString, char *theString, DYNMEM_MemoryTable_DataType ** memoryTable);
|
||||||
void FILE_DirectoryToParent(char ** sourceString, DYNMEM_MemoryTable_DataType ** memoryTable);
|
void FILE_DirectoryToParent(char ** sourceString, DYNMEM_MemoryTable_DataType ** memoryTable);
|
||||||
|
354
library/log.c
354
library/log.c
@ -1,308 +1,170 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "../debugHelper.h"
|
#include "../debugHelper.h"
|
||||||
#include "dynamicVectors.h"
|
#include "dynamicVectors.h"
|
||||||
#include "fileManagement.h"
|
#include "fileManagement.h"
|
||||||
|
|
||||||
#define LOG_LINE_SIZE 1024 + PATH_MAX
|
#define LOG_LINE_SIZE (1024 + PATH_MAX)
|
||||||
#define LOG_FILENAME_PREFIX "uftpLog_"
|
#define LOG_FILENAME_PREFIX "uftpLog_"
|
||||||
|
#define MAX_FILENAME_LENGTH 256
|
||||||
|
|
||||||
static void logThread(void * arg);
|
static void* logThread(void* arg);
|
||||||
|
static int deleteOldLogs(const char* folderPath, int daysToKeep);
|
||||||
|
static long long getDateNumeric(const char* str);
|
||||||
|
|
||||||
static DYNV_VectorString_DataType logQueue;
|
static DYNV_VectorString_DataType logQueue;
|
||||||
static DYNV_VectorString_DataType workerQueue;
|
static DYNV_VectorString_DataType workerQueue;
|
||||||
static sem_t logsem; // Semaphore for controlling log to write
|
|
||||||
|
|
||||||
static pthread_t pLogThread;
|
static sem_t logSem;
|
||||||
static pthread_mutex_t mutex;
|
static pthread_t logThreadId;
|
||||||
|
static pthread_mutex_t logMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
static int logFilesNumber;
|
static int maxLogFiles = 0;
|
||||||
static char logFolder[PATH_MAX];
|
static char logFolder[PATH_MAX] = {0};
|
||||||
|
|
||||||
#define MAX_FILENAME_LENGTH 256
|
// Convert YYYY-MM-DD to comparable numeric
|
||||||
|
static long long getDateNumeric(const char* str) {
|
||||||
|
if (strlen(str) != 10 || str[4] != '-' || str[7] != '-') return 0;
|
||||||
|
char year[5] = {0}, month[3] = {0}, day[3] = {0};
|
||||||
|
|
||||||
|
strncpy(year, str, 4);
|
||||||
|
strncpy(month, str + 5, 2);
|
||||||
|
strncpy(day, str + 8, 2);
|
||||||
|
|
||||||
static long long is_date_format(const char* str);
|
return atoll(year) * 365 + (atoll(month) - 1) * 31 + atoll(day);
|
||||||
static int delete_old_logs(const char* folder_path, int days_to_keep);
|
}
|
||||||
|
|
||||||
static long long is_date_format(const char* str)
|
static int deleteOldLogs(const char* folderPath, int daysToKeep) {
|
||||||
{
|
DIR* dir = opendir(folderPath);
|
||||||
char year[5];
|
if (!dir) {
|
||||||
char month[3];
|
perror("opendir");
|
||||||
char day[3];
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
memset(year, 0, 5);
|
time_t now = time(NULL);
|
||||||
memset(month, 0, 3);
|
struct tm* today = localtime(&now);
|
||||||
memset(day, 0, 3);
|
char todayStr[11];
|
||||||
|
strftime(todayStr, sizeof(todayStr), "%Y-%m-%d", today);
|
||||||
|
long long todayNumeric = getDateNumeric(todayStr);
|
||||||
|
|
||||||
if (strlen(str) != 10 || str[4] != '-' || str[7] != '-')
|
struct dirent* entry;
|
||||||
{
|
char filePath[PATH_MAX];
|
||||||
|
struct stat fileStat;
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (entry->d_type != DT_REG) continue;
|
||||||
|
if (strncmp(entry->d_name, LOG_FILENAME_PREFIX, strlen(LOG_FILENAME_PREFIX)) != 0) continue;
|
||||||
|
|
||||||
|
snprintf(filePath, sizeof(filePath), "%s%s", folderPath, entry->d_name);
|
||||||
|
if (stat(filePath, &fileStat) != 0) continue;
|
||||||
|
|
||||||
|
long long fileDate = getDateNumeric(entry->d_name + strlen(LOG_FILENAME_PREFIX));
|
||||||
|
if (fileDate > 0 && (fileDate + daysToKeep < todayNumeric)) {
|
||||||
|
my_printf("\nRemoving old log file: %s", filePath);
|
||||||
|
remove(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
// Check for valid digits in year, month, and day components
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
if (!isdigit(str[i])) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
year[i] = str[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 5; i < 7; i++) {
|
|
||||||
if (!isdigit(str[i])) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 8; i < 10; i++) {
|
|
||||||
if (!isdigit(str[i])) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
month[0] = str[5];
|
|
||||||
month[1] = str[6];
|
|
||||||
|
|
||||||
day[0] = str[8];
|
|
||||||
day[1] = str[9];
|
|
||||||
|
|
||||||
return atoll(year)*365+(atoll(month)-1)*31+atoll(day);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int delete_old_logs(const char* folder_path, int days_to_keep)
|
static void* logThread(void* arg) {
|
||||||
{
|
int lastDay = -1;
|
||||||
unsigned long long n_of_day_file;
|
|
||||||
unsigned long long n_of_day_today;
|
|
||||||
|
|
||||||
struct stat statbuf;
|
while (1) {
|
||||||
DIR* dir;
|
sem_wait(&logSem);
|
||||||
struct dirent* entry;
|
|
||||||
char full_path[PATH_MAX];
|
|
||||||
|
|
||||||
dir = opendir(folder_path);
|
|
||||||
if (dir == NULL)
|
|
||||||
{
|
|
||||||
perror("opendir");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t now = time(NULL);
|
|
||||||
struct tm *info = localtime(&now);
|
|
||||||
char timeToday[11];
|
|
||||||
if (strftime(timeToday, sizeof(timeToday), "%Y-%m-%d", info) == 0)
|
|
||||||
{
|
|
||||||
my_printfError("strftime error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
n_of_day_today = is_date_format(timeToday);
|
|
||||||
|
|
||||||
while ((entry = readdir(dir)) != NULL)
|
|
||||||
{
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
|
||||||
continue; // Skip . and .. entries
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(full_path, sizeof(full_path), "%s%s", folder_path, entry->d_name);
|
|
||||||
|
|
||||||
if (stat(full_path, &statbuf) == -1)
|
|
||||||
{
|
|
||||||
perror("stat");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!S_ISREG(statbuf.st_mode))
|
|
||||||
{
|
|
||||||
continue; // Not a regular file
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(entry->d_name, LOG_FILENAME_PREFIX, strlen(LOG_FILENAME_PREFIX)) != 0)
|
|
||||||
{
|
|
||||||
continue; // Not a log file
|
|
||||||
}
|
|
||||||
|
|
||||||
n_of_day_file = is_date_format(entry->d_name + strlen(LOG_FILENAME_PREFIX));
|
|
||||||
|
|
||||||
if (!n_of_day_file)
|
|
||||||
{
|
|
||||||
continue; // Invalid date format
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n_of_day_file+days_to_keep < n_of_day_today)
|
|
||||||
{
|
|
||||||
my_printf("\nRemoving old log file: %s", full_path);
|
|
||||||
|
|
||||||
// File is older than specified days
|
|
||||||
if (remove(full_path) == -1)
|
|
||||||
{
|
|
||||||
perror("remove");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// STATIC SECTION
|
|
||||||
static void logThread(void * arg)
|
|
||||||
{
|
|
||||||
|
|
||||||
int lastDay;
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
if (sem_wait(&logsem) == 0)
|
|
||||||
{
|
|
||||||
char theLogFilename[PATH_MAX];
|
|
||||||
int day = 0;
|
|
||||||
|
|
||||||
// write the logs to the file
|
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
struct tm *info = localtime(&now);
|
struct tm* tm_now = localtime(&now);
|
||||||
char logName[50];
|
|
||||||
char dayString[50];
|
|
||||||
|
|
||||||
memset(theLogFilename, 0, PATH_MAX);
|
char dateStr[11], logFilePath[PATH_MAX];
|
||||||
|
strftime(dateStr, sizeof(dateStr), "%Y-%m-%d", tm_now);
|
||||||
|
snprintf(logFilePath, sizeof(logFilePath), "%s%s%s", logFolder, LOG_FILENAME_PREFIX, dateStr);
|
||||||
|
|
||||||
if (strftime(dayString, sizeof(dayString), "%d", info) == 0)
|
int currentDay = tm_now->tm_mday;
|
||||||
{
|
if (currentDay != lastDay) {
|
||||||
my_printfError("strftime error");
|
deleteOldLogs(logFolder, maxLogFiles);
|
||||||
return;
|
lastDay = currentDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
day = atoi(dayString);
|
pthread_mutex_lock(&logMutex);
|
||||||
|
for (int i = 0; i < logQueue.Size; ++i) {
|
||||||
if (day != lastDay)
|
workerQueue.PushBack(&workerQueue, logQueue.Data[i], strnlen(logQueue.Data[i], LOG_LINE_SIZE));
|
||||||
{
|
|
||||||
delete_old_logs(logFolder, logFilesNumber);
|
|
||||||
lastDay = day;
|
|
||||||
}
|
}
|
||||||
|
while (logQueue.Size > 0) logQueue.PopBack(&logQueue);
|
||||||
|
pthread_mutex_unlock(&logMutex);
|
||||||
|
|
||||||
if (strftime(logName, sizeof(logName), LOG_FILENAME_PREFIX"%Y-%m-%d", info) == 0)
|
for (int i = 0; i < workerQueue.Size; ++i) {
|
||||||
{
|
FILE_AppendStringToFile(logFilePath, workerQueue.Data[i]);
|
||||||
my_printfError("strftime error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(theLogFilename, logFolder, PATH_MAX);
|
|
||||||
strncat(theLogFilename, logName, PATH_MAX);
|
|
||||||
|
|
||||||
// Fill the worker queue
|
|
||||||
pthread_mutex_lock(&mutex);
|
|
||||||
for(int i = 0; i <logQueue.Size; i++)
|
|
||||||
{
|
|
||||||
workerQueue.PushBack(&workerQueue, logQueue.Data[i], strnlen(logQueue.Data[i], LOG_LINE_SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
// empty the log vector
|
|
||||||
while (logQueue.Size > 0)
|
|
||||||
{
|
|
||||||
logQueue.PopBack(&logQueue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release the mutex to let the log queue be available
|
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
|
|
||||||
for(int i = 0; i <workerQueue.Size; i++)
|
|
||||||
{
|
|
||||||
FILE_AppendStringToFile(theLogFilename, workerQueue.Data[i]);
|
|
||||||
my_printf("\n Log at %d : %s", i, workerQueue.Data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// empty the log vector
|
|
||||||
while (workerQueue.Size > 0)
|
|
||||||
{
|
|
||||||
workerQueue.PopBack(&workerQueue);
|
|
||||||
}
|
}
|
||||||
|
while (workerQueue.Size > 0) workerQueue.PopBack(&workerQueue);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int logInit(char * folder, int numberOfLogFiles)
|
int logInit(const char* folder, int numberOfLogFiles) {
|
||||||
{
|
if (numberOfLogFiles <= 0 || !folder) return -1;
|
||||||
int returnCode;
|
|
||||||
my_printf("\n Init logging system..");
|
|
||||||
|
|
||||||
logFilesNumber = numberOfLogFiles;
|
maxLogFiles = numberOfLogFiles;
|
||||||
|
snprintf(logFolder, sizeof(logFolder), "%s", folder);
|
||||||
if (logFilesNumber <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delete_old_logs(folder, numberOfLogFiles);
|
|
||||||
|
|
||||||
DYNV_VectorString_Init(&logQueue);
|
DYNV_VectorString_Init(&logQueue);
|
||||||
DYNV_VectorString_Init(&workerQueue);
|
DYNV_VectorString_Init(&workerQueue);
|
||||||
|
|
||||||
sem_init(&logsem, 0, 0); // Initialize semaphore with number of printers
|
sem_init(&logSem, 0, 0);
|
||||||
|
|
||||||
// Initialize the mutex
|
if (pthread_create(&logThreadId, NULL, logThread, NULL) != 0) {
|
||||||
pthread_mutex_init(&mutex, NULL);
|
LOG_ERROR("Failed to create log thread");
|
||||||
|
return -1;
|
||||||
returnCode = pthread_create(&pLogThread, NULL, &logThread, NULL);
|
|
||||||
if (returnCode != 0)
|
|
||||||
{
|
|
||||||
addLog("Pthead create error restarting the server", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
exit(0);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//addLog("Log init ", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
deleteOldLogs(logFolder, maxLogFiles);
|
||||||
|
my_printf("\nLog system initialized in folder: %s", logFolder);
|
||||||
memset(logFolder, 0, PATH_MAX);
|
|
||||||
strncpy(logFolder, folder, PATH_MAX);
|
|
||||||
|
|
||||||
my_printf("\n Log init LogFolder: %s ", logFolder);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addLog(char* logString, char * currFile, int currLine, char * currFunction)
|
void logMessage(const char* message, const char* file, int line, const char* function) {
|
||||||
{
|
if (maxLogFiles <= 0 || !message) return;
|
||||||
|
|
||||||
if (logFilesNumber <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char theLogString[LOG_LINE_SIZE];
|
|
||||||
char debugInfo[LOG_LINE_SIZE];
|
|
||||||
memset(theLogString, 0, LOG_LINE_SIZE);
|
|
||||||
memset(debugInfo, 0, LOG_LINE_SIZE);
|
|
||||||
|
|
||||||
|
char logEntry[LOG_LINE_SIZE] = {0};
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
struct tm *info = localtime(&now);
|
struct tm* tm_now = localtime(&now);
|
||||||
|
|
||||||
if (strftime(theLogString, sizeof(theLogString), "%Y-%m-%d_%H:%M: ", info) == 0)
|
strftime(logEntry, sizeof(logEntry), "%Y-%m-%d_%H:%M:%S: ", tm_now);
|
||||||
{
|
strncat(logEntry, message, LOG_LINE_SIZE - strlen(logEntry) - 1);
|
||||||
my_printfError("strftime error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(debugInfo, LOG_LINE_SIZE, " - File %s at line %d - fun %s() ", currFile, currLine, currFunction);
|
char metaInfo[256];
|
||||||
strncat(theLogString, logString, LOG_LINE_SIZE);
|
snprintf(metaInfo, sizeof(metaInfo), " - File %s at line %d - fun %s()", file, line, function);
|
||||||
strncat(theLogString, debugInfo, LOG_LINE_SIZE);
|
strncat(logEntry, metaInfo, LOG_LINE_SIZE - strlen(logEntry) - 1);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&logMutex);
|
||||||
// Acquire the mutex lock before accessing count
|
logQueue.PushBack(&logQueue, logEntry, strlen(logEntry));
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_unlock(&logMutex);
|
||||||
//Add a string to the log
|
sem_post(&logSem);
|
||||||
logQueue.PushBack(&logQueue, theLogString, strnlen(theLogString, LOG_LINE_SIZE));
|
|
||||||
// Acquire the mutex lock before accessing count
|
|
||||||
|
|
||||||
//Count log available
|
|
||||||
sem_post(&logsem);
|
|
||||||
pthread_mutex_unlock(&mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printf-style log function
|
||||||
|
void logMessagef(const char* file, int line, const char* function, const char* fmt, ...) {
|
||||||
|
if (maxLogFiles <= 0 || !fmt) return;
|
||||||
|
|
||||||
|
char messageBuffer[LOG_LINE_SIZE] = {0};
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(messageBuffer, sizeof(messageBuffer), fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
logMessage(messageBuffer, file, line, function);
|
||||||
|
}
|
||||||
|
@ -25,7 +25,20 @@
|
|||||||
#ifndef LOG_H
|
#ifndef LOG_H
|
||||||
#define LOG_H
|
#define LOG_H
|
||||||
|
|
||||||
int logInit(char * folder, int numberOfLogFiles);
|
#define LOG_INFO_PREFIX "[INFO] "
|
||||||
void addLog(char* logString, char * currFile, int currLine, char * currFunction);
|
#define LOG_DEBUG_PREFIX "[DEBUG] "
|
||||||
|
#define LOG_ERROR_PREFIX "[ERROR] "
|
||||||
|
#define LOG_SECURITY_PREFIX "[SECURITY] "
|
||||||
|
|
||||||
|
#define LOG(msg) logMessage(msg, __FILE__, __LINE__, __func__)
|
||||||
|
#define LOG_INFO(msg) logMessage(LOG_INFO_PREFIX msg, __FILE__, __LINE__, __func__)
|
||||||
|
#define LOG_DEBUG(msg) logMessage(LOG_DEBUG_PREFIX msg, __FILE__, __LINE__, __func__)
|
||||||
|
#define LOG_ERROR(msg) logMessage(LOG_ERROR_PREFIX msg, __FILE__, __LINE__, __func__)
|
||||||
|
#define LOG_SECURITY(msg) logMessage(LOG_SECURITY_PREFIX msg, __FILE__, __LINE__, __func__)
|
||||||
|
#define LOGF(fmt, ...) logMessagef(__FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
int logInit(const char* folder, int numberOfLogFiles);
|
||||||
|
void logMessage(const char* message, const char* file, int line, const char* function);
|
||||||
|
void logMessagef(const char* file, int line, const char* function, const char* fmt, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* The MIT License
|
|
||||||
*
|
|
||||||
* Copyright 2018 Ugo Cirmignani.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include "logFunctions.h"
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "../debugHelper.h"
|
|
||||||
|
|
||||||
void printTimeStamp(void)
|
|
||||||
{
|
|
||||||
// time_t ltime; calendar time
|
|
||||||
// ltime=time(NULL); get current cal time
|
|
||||||
// my_printf("\n\n %s -->",asctime( localtime(<ime) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeTimeout(struct timespec *tsp, long seconds)
|
|
||||||
{
|
|
||||||
struct timeval now;
|
|
||||||
/* get the current time */
|
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
tsp->tv_sec = now.tv_sec;
|
|
||||||
tsp->tv_nsec = now.tv_usec * 1000; /* usec to nsec */
|
|
||||||
/* add the offset to get timeout value */
|
|
||||||
tsp->tv_sec += seconds;
|
|
||||||
}
|
|
@ -21,6 +21,12 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
* Copyright 2018 Ugo Cirmignani.
|
||||||
|
* [license text unchanged...]
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef OPENSSL_ENABLED
|
#ifdef OPENSSL_ENABLED
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -29,204 +35,161 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
|
||||||
#include "openSsl.h"
|
#include "openSsl.h"
|
||||||
#include "fileManagement.h"
|
#include "fileManagement.h"
|
||||||
#include "../debugHelper.h"
|
#include "../debugHelper.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
|
#define NEED_OPENSSL_THREADING 1
|
||||||
|
#else
|
||||||
|
#define NEED_OPENSSL_THREADING 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NEED_OPENSSL_THREADING
|
||||||
#define MUTEX_TYPE pthread_mutex_t
|
#define MUTEX_TYPE pthread_mutex_t
|
||||||
#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
|
#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL)
|
||||||
#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
|
#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
|
||||||
#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
|
#define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
|
||||||
#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
|
#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
|
||||||
#define THREAD_ID pthread_self()
|
#define THREAD_ID pthread_self()
|
||||||
|
|
||||||
/* This array will store all of the mutexes available to OpenSSL. */
|
|
||||||
static MUTEX_TYPE *mutex_buf = NULL;
|
static MUTEX_TYPE *mutex_buf = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
void initOpenssl()
|
void initOpenssl()
|
||||||
{
|
{
|
||||||
OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
|
#if NEED_OPENSSL_THREADING
|
||||||
SSL_load_error_strings(); /* Bring in and register error messages */
|
|
||||||
ERR_load_BIO_strings();
|
|
||||||
ERR_load_crypto_strings();
|
|
||||||
SSL_library_init();
|
|
||||||
thread_setup();
|
thread_setup();
|
||||||
|
#endif
|
||||||
|
// No longer needed in OpenSSL >= 1.1.0
|
||||||
|
// OpenSSL_add_all_algorithms();
|
||||||
|
// SSL_load_error_strings();
|
||||||
|
// ERR_load_BIO_strings();
|
||||||
|
// ERR_load_crypto_strings();
|
||||||
|
// SSL_library_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanupOpenssl()
|
void cleanupOpenssl()
|
||||||
{
|
{
|
||||||
thread_cleanup();
|
#if NEED_OPENSSL_THREADING
|
||||||
EVP_cleanup();
|
thread_cleanup();
|
||||||
|
#endif
|
||||||
|
// Deprecated in OpenSSL >= 1.1.0
|
||||||
|
// EVP_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX *createServerContext()
|
SSL_CTX *createServerContext()
|
||||||
{
|
{
|
||||||
const SSL_METHOD *method;
|
const SSL_METHOD *method = TLS_server_method();
|
||||||
SSL_CTX *ctx;
|
SSL_CTX *ctx = SSL_CTX_new(method);
|
||||||
|
if (!ctx) {
|
||||||
method = TLS_server_method();
|
perror("Unable to create server SSL context");
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
ctx = SSL_CTX_new(method);
|
exit(EXIT_FAILURE);
|
||||||
if (!ctx)
|
|
||||||
{
|
|
||||||
perror("Unable to create server SSL context");
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSL_CTX *createClientContext(void)
|
|
||||||
{
|
|
||||||
const SSL_METHOD *method;
|
|
||||||
SSL_CTX *ctx;
|
|
||||||
method = TLS_client_method(); /* Create new client-method instance */
|
|
||||||
ctx = SSL_CTX_new(method); /* Create new context */
|
|
||||||
//SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
|
|
||||||
//SSL_CTX_set_options(ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE| SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
|
|
||||||
//SSL_CTX_set_ecdh_auto(ctx, 1);
|
|
||||||
|
|
||||||
if (ctx == NULL)
|
|
||||||
{
|
|
||||||
perror("Unable to create server SSL context");
|
|
||||||
my_printfError("Unable to create server SSL context");
|
|
||||||
addLog("Unable to create server SSL context", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
abort();
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void configureClientContext(SSL_CTX *ctx, char *certificatePath, char* privateCertificatePath)
|
void configureContext(SSL_CTX *ctx, const char *certPath, const char *keyPath)
|
||||||
{/*
|
|
||||||
if (FILE_IsFile(certificatePath) != 1)
|
|
||||||
{
|
|
||||||
my_printf("\ncertificate file: %s not found!", certificatePath);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FILE_IsFile(privateCertificatePath) != 1)
|
|
||||||
{
|
|
||||||
my_printf("\ncertificate file: %s not found!", privateCertificatePath);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Set the key and cert
|
|
||||||
if (SSL_CTX_use_certificate_file(ctx, certificatePath, SSL_FILETYPE_PEM) <= 0) {
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SSL_CTX_use_PrivateKey_file(ctx, privateCertificatePath, SSL_FILETYPE_PEM) <= 0 ) {
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} */
|
|
||||||
}
|
|
||||||
|
|
||||||
void configureContext(SSL_CTX *ctx, char *certificatePath, char* privateCertificatePath)
|
|
||||||
{
|
{
|
||||||
if (FILE_IsFile(certificatePath, 1) != 1)
|
if (!FILE_IsFile(certPath, 1)) {
|
||||||
{
|
my_printf("\nCertificate file not found: %s", certPath);
|
||||||
my_printf("\ncertificate file: %s not found!", certificatePath);
|
exit(EXIT_FAILURE);
|
||||||
exit(0);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (FILE_IsFile(privateCertificatePath, 1) != 1)
|
if (!FILE_IsFile(keyPath, 1)) {
|
||||||
{
|
my_printf("\nPrivate key file not found: %s", keyPath);
|
||||||
my_printf("\ncertificate file: %s not found!", privateCertificatePath);
|
exit(EXIT_FAILURE);
|
||||||
exit(0);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SSL_CTX_set_ecdh_auto(ctx, 1);
|
// Removed SSL_CTX_set_ecdh_auto (no-op since OpenSSL 1.1.0)
|
||||||
|
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
|
||||||
|
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!MD5");
|
||||||
|
|
||||||
/* Set the key and cert */
|
if (SSL_CTX_use_certificate_file(ctx, certPath, SSL_FILETYPE_PEM) <= 0) {
|
||||||
if (SSL_CTX_use_certificate_file(ctx, certificatePath, SSL_FILETYPE_PEM) <= 0) {
|
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SSL_CTX_use_PrivateKey_file(ctx, privateCertificatePath, SSL_FILETYPE_PEM) <= 0 ) {
|
if (SSL_CTX_use_PrivateKey_file(ctx, keyPath, SSL_FILETYPE_PEM) <= 0) {
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable session cache on server side
|
||||||
|
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowCerts(SSL *ssl)
|
||||||
void ShowCerts(SSL* ssl)
|
{
|
||||||
{ X509 *cert;
|
X509 *cert = SSL_get_peer_certificate(ssl);
|
||||||
char *line;
|
if (cert) {
|
||||||
|
char *line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
|
||||||
cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
|
|
||||||
if ( cert != NULL )
|
|
||||||
{
|
|
||||||
my_printf("Server certificates:\n");
|
|
||||||
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
|
|
||||||
my_printf("Subject: %s\n", line);
|
my_printf("Subject: %s\n", line);
|
||||||
free(line); /* free the malloc'ed string */
|
free(line);
|
||||||
|
|
||||||
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
|
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
|
||||||
my_printf("Issuer: %s\n", line);
|
my_printf("Issuer: %s\n", line);
|
||||||
free(line); /* free the malloc'ed string */
|
free(line);
|
||||||
X509_free(cert); /* free the malloc'ed certificate copy */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
my_printf("No certificates.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
X509_free(cert);
|
||||||
|
} else {
|
||||||
|
my_printf("No certificates.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handle_error(const char *file, int lineno, const char *msg)
|
void handle_error(const char *file, int lineno, const char *msg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "** %s:%d %s\n", file, lineno, msg);
|
fprintf(stderr, "** %s:%d %s\n", file, lineno, msg);
|
||||||
ERR_print_errors_fp(stderr);
|
ERR_print_errors_fp(stderr);
|
||||||
/* exit(-1); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if NEED_OPENSSL_THREADING
|
||||||
static void locking_function(int mode, int n, const char *file, int line)
|
static void locking_function(int mode, int n, const char *file, int line)
|
||||||
{
|
{
|
||||||
if(mode & CRYPTO_LOCK)
|
if (mode & CRYPTO_LOCK)
|
||||||
MUTEX_LOCK(mutex_buf[n]);
|
MUTEX_LOCK(mutex_buf[n]);
|
||||||
else
|
else
|
||||||
MUTEX_UNLOCK(mutex_buf[n]);
|
MUTEX_UNLOCK(mutex_buf[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long id_function(void)
|
static unsigned long id_function(void)
|
||||||
{
|
{
|
||||||
return ((unsigned long)THREAD_ID);
|
return (unsigned long)THREAD_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
int thread_setup(void)
|
int thread_setup(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
mutex_buf = malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE));
|
||||||
|
if (!mutex_buf) return 0;
|
||||||
|
|
||||||
mutex_buf = malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE));
|
for (i = 0; i < CRYPTO_num_locks(); i++)
|
||||||
if(!mutex_buf)
|
MUTEX_SETUP(mutex_buf[i]);
|
||||||
return 0;
|
|
||||||
for(i = 0; i < CRYPTO_num_locks(); i++)
|
CRYPTO_set_id_callback(id_function);
|
||||||
MUTEX_SETUP(mutex_buf[i]);
|
CRYPTO_set_locking_callback(locking_function);
|
||||||
CRYPTO_set_id_callback(id_function);
|
return 1;
|
||||||
CRYPTO_set_locking_callback(locking_function);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int thread_cleanup(void)
|
int thread_cleanup(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
if (!mutex_buf) return 0;
|
||||||
|
|
||||||
if(!mutex_buf)
|
CRYPTO_set_id_callback(NULL);
|
||||||
return 0;
|
CRYPTO_set_locking_callback(NULL);
|
||||||
CRYPTO_set_id_callback(NULL);
|
|
||||||
CRYPTO_set_locking_callback(NULL);
|
for (i = 0; i < CRYPTO_num_locks(); i++)
|
||||||
for(i = 0; i < CRYPTO_num_locks(); i++)
|
MUTEX_CLEANUP(mutex_buf[i]);
|
||||||
MUTEX_CLEANUP(mutex_buf[i]);
|
|
||||||
free(mutex_buf);
|
free(mutex_buf);
|
||||||
mutex_buf = NULL;
|
mutex_buf = NULL;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,9 +40,7 @@ int thread_cleanup(void);
|
|||||||
int thread_setup(void);
|
int thread_setup(void);
|
||||||
void handle_error(const char *file, int lineno, const char *msg);
|
void handle_error(const char *file, int lineno, const char *msg);
|
||||||
SSL_CTX *createServerContext();
|
SSL_CTX *createServerContext();
|
||||||
SSL_CTX *createClientContext();
|
void configureContext(SSL_CTX *ctx, const char *certificatePath, const char* privateCertificatePath);
|
||||||
void configureContext(SSL_CTX *ctx, char *certificatePath, char* privateCertificatePath);
|
|
||||||
void configureClientContext(SSL_CTX *ctx, char *certificatePath, char* privateCertificatePath);
|
|
||||||
void ShowCerts(SSL* ssl);
|
void ShowCerts(SSL* ssl);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
67
library/serverHelpers.c
Normal file
67
library/serverHelpers.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "../ftpData.h"
|
||||||
|
#include "../ftpServer.h"
|
||||||
|
#include "library/fileManagement.h"
|
||||||
|
#include "library/configRead.h"
|
||||||
|
#include "library/openSsl.h"
|
||||||
|
#include "library/connection.h"
|
||||||
|
#include "library/dynamicMemory.h"
|
||||||
|
#include "library/auth.h"
|
||||||
|
#include "library/serverHelpers.h"
|
||||||
|
#include "dataChannel/dataChannel.h"
|
||||||
|
#include "ftpCommandsElaborate.h"
|
||||||
|
|
||||||
|
#include "debugHelper.h"
|
||||||
|
#include "library/log.h"
|
||||||
|
|
||||||
|
int handleThreadReuse(ftpDataType *data, int socketId)
|
||||||
|
{
|
||||||
|
void *pReturn;
|
||||||
|
int returnCode = 0;
|
||||||
|
|
||||||
|
if (data->clients[socketId].workerData.threadHasBeenCreated == 1)
|
||||||
|
{
|
||||||
|
if (data->clients[socketId].workerData.threadIsAlive == 1)
|
||||||
|
{
|
||||||
|
cancelWorker(data, socketId);
|
||||||
|
}
|
||||||
|
|
||||||
|
returnCode = pthread_join(data->clients[socketId].workerData.workerThread, &pReturn);
|
||||||
|
my_printf("\njoin thread status %d", returnCode);
|
||||||
|
if (returnCode != 0)
|
||||||
|
{
|
||||||
|
LOGF("%sJoining thread error: %d", LOG_ERROR_PREFIX, returnCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->clients[socketId].workerData.threadHasBeenCreated = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancelWorker(ftpDataType *data, int clientId)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("Cancelling thread because it is busy");
|
||||||
|
|
||||||
|
int returnCode = pthread_cancel(data->clients[clientId].workerData.workerThread);
|
||||||
|
if (returnCode != 0) {
|
||||||
|
LOGF("%sCancel thread error: %d", LOG_ERROR_PREFIX, returnCode);
|
||||||
|
}
|
||||||
|
}
|
20
library/logFunctions.h → library/serverHelpers.h
Executable file → Normal file
20
library/logFunctions.h → library/serverHelpers.h
Executable file → Normal file
@ -22,20 +22,10 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LOGFUNCTIONS_H
|
#ifndef SERVER_HELPERS_H
|
||||||
#define LOGFUNCTIONS_H
|
#define SERVER_HELPERS_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
int handleThreadReuse(ftpDataType *data, int socketId);
|
||||||
extern "C" {
|
void cancelWorker(ftpDataType *data, int clientId);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void printTimeStamp(void);
|
|
||||||
void makeTimeout(struct timespec *tsp, long minutes);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LOGFUNCTIONS_H */
|
|
||||||
|
|
||||||
|
#endif
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "../ftpServer.h"
|
#include "../ftpServer.h"
|
||||||
#include "../debugHelper.h"
|
#include "../debugHelper.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static void ignore_sigpipe(void);
|
static void ignore_sigpipe(void);
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ static void ignore_sigpipe(void)
|
|||||||
{
|
{
|
||||||
perror("Could not ignore the SIGPIPE signal");
|
perror("Could not ignore the SIGPIPE signal");
|
||||||
my_printfError("Could not ignore the SIGPIPE signal");
|
my_printfError("Could not ignore the SIGPIPE signal");
|
||||||
addLog("Could not ignore the SIGPIPE signal", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
|
LOG_INFO("Could not ignore the SIGPIPE signal");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
#OPENSSL TEST COMMANDS
|
#OPENSSL TEST COMMANDS
|
||||||
|
|
||||||
#Required packages to compile with TLS
|
#Required packages to compile with TLS
|
||||||
sudo apt-get install libssl-devù
|
sudo apt-get install libssl-dev
|
||||||
|
|
||||||
#Required packages to compile with PAM
|
#Required packages to compile with PAM
|
||||||
sudo apt-get install libpam0g-dev
|
sudo apt-get install libpam0g-dev
|
||||||
|
|
||||||
@ -12,8 +13,6 @@ openssl rsa -in key.pem -out newkey.pem
|
|||||||
handle SIGPIPE nostop noprint pass
|
handle SIGPIPE nostop noprint pass
|
||||||
thread apply all where
|
thread apply all where
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Testing ssl
|
#Testing ssl
|
||||||
openssl s_client -starttls ftp -connect 192.168.1.237:21
|
openssl s_client -starttls ftp -connect 192.168.1.237:21
|
||||||
sudo openssl s_server -key key.pem -cert cert.pem -accept 123
|
sudo openssl s_server -key key.pem -cert cert.pem -accept 123
|
||||||
@ -23,3 +22,7 @@ PASS password
|
|||||||
PROT P
|
PROT P
|
||||||
PORT 192,168,1,237,0,123
|
PORT 192,168,1,237,0,123
|
||||||
LIST
|
LIST
|
||||||
|
|
||||||
|
|
||||||
|
PASV EXAMPLE:
|
||||||
|
openssl s_client -connect localhost:10000
|
||||||
|
2
uFTP.c
2
uFTP.c
@ -25,12 +25,10 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
#include "ftpServer.h"
|
#include "ftpServer.h"
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
runFtpServer();
|
runFtpServer();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
65
uftpd.cfg
65
uftpd.cfg
@ -1,67 +1,68 @@
|
|||||||
#FTP CONFIGURATION SAMPLE "/etc/uftpd.cfg"
|
# FTP CONFIGURATION SAMPLE "/etc/uftpd.cfg"
|
||||||
|
|
||||||
#######################################################
|
#######################################################
|
||||||
# UFTP SERVER SETTINGS #
|
# UFTP SERVER SETTINGS #
|
||||||
#######################################################
|
#######################################################
|
||||||
|
|
||||||
#MAXIMUM ALLOWED CONNECTIONS ON THE SERVER
|
# NOTES:
|
||||||
MAXIMUM_ALLOWED_FTP_CONNECTION = 30
|
# restart uFTP to apply the configuration after changing parameters
|
||||||
|
|
||||||
#TCP/IP PORT SETTINGS (DEFAULT 21)
|
# Maximum allowed FTP connections on the server
|
||||||
|
MAXIMUM_ALLOWED_FTP_CONNECTION = 50
|
||||||
|
|
||||||
|
# TCP/IP port settings (default: 21)
|
||||||
FTP_PORT = 21
|
FTP_PORT = 21
|
||||||
|
|
||||||
#Allow only one server instance (true or false)
|
# Allow only one server instance (true or false)
|
||||||
SINGLE_INSTANCE = true
|
SINGLE_INSTANCE = true
|
||||||
|
|
||||||
#Run in background, daemon mode ok
|
# Run in background daemon mode (true or false)
|
||||||
DAEMON_MODE = true
|
DAEMON_MODE = true
|
||||||
|
|
||||||
# Folder where to save the logs, use the same format below, the folder must terminate with /
|
# Folder where logs are saved; must end with a '/'
|
||||||
LOG_FOLDER = /var/log/
|
LOG_FOLDER = /var/log/
|
||||||
|
|
||||||
# Maximum number of logs to keep, if 0 log functionality is disabled
|
# Maximum number of logs to keep; set to 0 to disable logging
|
||||||
MAXIMUM_LOG_FILES = 0
|
MAXIMUM_LOG_FILES = 0
|
||||||
|
|
||||||
# Idle timeout in seconds, client are disconnected for inactivity after the
|
# Idle timeout in seconds; clients are disconnected after this period of inactivity; set to 0 to disable
|
||||||
# specified amount of time in seconds, set to 0 to disable
|
# some clients may fail if the timeout is too high https://github.com/kingk85/uFTP/issues/29
|
||||||
IDLE_MAX_TIMEOUT = 3600
|
IDLE_MAX_TIMEOUT = 330
|
||||||
|
|
||||||
#MAX CONNECTIONS PER IP
|
# Maximum connections per IP address; set to 0 to disable
|
||||||
#LIMIT THE MAXIMUM NUMBER OF CONNECTION FOR EACH IP ADDRESS
|
|
||||||
# 0 TO DISABLE
|
|
||||||
MAX_CONNECTION_NUMBER_PER_IP = 10
|
MAX_CONNECTION_NUMBER_PER_IP = 10
|
||||||
|
|
||||||
#MAX LOGIN TRY PER IP
|
# Maximum login attempts per IP (anti bruteforce feature); IP will be blocked for 5 minutes after exceeding this number of failed login attempts; set to 0 to disable
|
||||||
#THE IP ADDRESS WILL BE BLOCKED FOR 5 MINUTES AFTER WRONG LOGIN USERNAME AND PASSWORD
|
|
||||||
#0 TO DISABLE
|
|
||||||
MAX_CONNECTION_TRY_PER_IP = 10
|
MAX_CONNECTION_TRY_PER_IP = 10
|
||||||
|
|
||||||
#USE THE SERVER IP PARAMETER IF THE FTP SERVER IS UNDER NAT
|
# Server IP address for NAT configurations; use commas instead of periods (e.g., 192,168,1,1); leave commented or blank if not used
|
||||||
#SERVER IP SHOULD BE SET TO ROUTER IP IN THIS CASE
|
|
||||||
#IF NOT IN USE LEAVE IT COMMENTED OR BLANK
|
|
||||||
#USE , instad of . eg: 192,168,1,1
|
|
||||||
#SERVER_IP = 192,168,1,1
|
#SERVER_IP = 192,168,1,1
|
||||||
|
|
||||||
#TLS CERTIFICATE FILE PATH
|
# TLS certificate file paths
|
||||||
CERTIFICATE_PATH=/etc/uFTP/cert.pem
|
CERTIFICATE_PATH=/etc/uFTP/cert.pem
|
||||||
PRIVATE_CERTIFICATE_PATH=/etc/uFTP/key.pem
|
PRIVATE_CERTIFICATE_PATH=/etc/uFTP/key.pem
|
||||||
|
|
||||||
#Enable system authentication based on /etc/passwd
|
# Enable system authentication based on /etc/passwd and /etc/shadow (true or false)
|
||||||
#and /etc/shadow
|
|
||||||
ENABLE_PAM_AUTH = false
|
ENABLE_PAM_AUTH = false
|
||||||
|
|
||||||
# Force usage of the TLS
|
# Force usage of TLS; if enabled, only TLS connections are allowed (true or false)
|
||||||
# If enabled, only TLS connections will be allowed
|
|
||||||
FORCE_TLS = false
|
FORCE_TLS = false
|
||||||
|
|
||||||
#
|
# Random port range for passive FTP connections
|
||||||
# Random port for passive FTP connections range
|
|
||||||
#
|
|
||||||
RANDOM_PORT_START = 10000
|
RANDOM_PORT_START = 10000
|
||||||
RANDOM_PORT_END = 50000
|
RANDOM_PORT_END = 50000
|
||||||
|
|
||||||
#USERS
|
#######################################################
|
||||||
#START FROM USER 0 TO XXX
|
# USER SETTINGS #
|
||||||
|
#######################################################
|
||||||
|
|
||||||
|
# Define users with the following parameters:
|
||||||
|
# USER_<n> = username
|
||||||
|
# PASSWORD_<n> = password
|
||||||
|
# HOME_<n> = home directory
|
||||||
|
# GROUP_NAME_OWNER_<n> = group ownership for new files (optional)
|
||||||
|
# USER_NAME_OWNER_<n> = user ownership for new files (optional)
|
||||||
|
|
||||||
USER_0 = username
|
USER_0 = username
|
||||||
PASSWORD_0 = password
|
PASSWORD_0 = password
|
||||||
HOME_0 = /
|
HOME_0 = /
|
||||||
@ -78,7 +79,7 @@ USER_2 = anotherUsername
|
|||||||
PASSWORD_2 = anotherPassowrd
|
PASSWORD_2 = anotherPassowrd
|
||||||
HOME_2 = /
|
HOME_2 = /
|
||||||
|
|
||||||
#blocked user that are not allowed to login
|
# Blocked users who are not allowed to log in
|
||||||
BLOCK_USER_0 = user1
|
BLOCK_USER_0 = user1
|
||||||
BLOCK_USER_1 = user2
|
BLOCK_USER_1 = user2
|
||||||
BLOCK_USER_2 = user3
|
BLOCK_USER_2 = user3
|
||||||
|
Reference in New Issue
Block a user