Compare commits

...

17 Commits

Author SHA1 Message Date
Ugo
7869d55f95 config: changed default parameters and refactoring 2025-01-31 23:46:35 +00:00
root
4565a14d2c CWD / command fix 2024-09-29 21:28:41 +02:00
root
6db29a0f33 Adding ip type in port command 2024-07-29 22:28:22 +02:00
root
a2de9b1a7c Removed debug define 2024-06-06 21:10:10 +02:00
root
90f44e3a98 Possible memory leak fix 2024-05-12 14:15:48 +02:00
root
ec5c155ccb Updated version 2024-05-06 21:50:20 +02:00
root
63251ca3e4 FEAT updated 2024-05-06 21:35:11 +02:00
root
509910642d Disable ipv6 with makefile ok 2024-05-06 20:28:39 +02:00
root
2f355d91d8 ipv6 ok 2024-05-06 19:09:23 +02:00
root
8302e82366 Testing EPRT 2024-05-06 18:47:19 +02:00
root
998b720fa5 working ipv6 2024-05-06 15:52:59 +02:00
root
89e64c2ddc Ipv6 seems okay 2024-05-06 15:44:31 +02:00
root
5778081be9 Check if ipv4 or ipv6 2024-05-06 15:37:19 +02:00
root
8f78c9e7f1 Working on ipv6 2024-05-06 14:53:02 +02:00
root
38887ed633 Working on ipv6 2024-05-06 14:49:02 +02:00
root
4c0b19e6d6 working on ipv6 preliminary implementation okay 2024-05-06 14:33:35 +02:00
root
d0191ca20d Working on ipv6 implementation 2024-05-06 12:48:44 +02:00
18 changed files with 756 additions and 253 deletions

View File

@ -16,7 +16,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 +33,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)
all: $(BUILDFILES) all: $(BUILDFILES)
@ -83,7 +87,7 @@ 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:

View File

@ -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

View File

@ -48,6 +48,9 @@
#include "ftpCommandsElaborate.h" #include "ftpCommandsElaborate.h"
#include "debugHelper.h" #include "debugHelper.h"
#include "library/log.h"
static int parse_eprt(const char *eprt_str, int *address_type, char *address, int *port);
/* Elaborate the User login command */ /* Elaborate the User login command */
int parseCommandUser(ftpDataType * data, int socketId) int parseCommandUser(ftpDataType * data, int socketId)
@ -179,7 +182,7 @@ int parseCommandPass(ftpDataType *data, int socketId)
data->clients[socketId].closeTheClient = 1; data->clients[socketId].closeTheClient = 1;
returnCode = socketPrintf(data, socketId, "s", "430 Too many login failure detected, your ip will be blacklisted for 5 minutes\r\n"); returnCode = socketPrintf(data, socketId, "s", "430 Too many login failure detected, your ip will be blacklisted for 5 minutes\r\n");
char *theLogString[STRING_SZ_LARGE]; char theLogString[STRING_SZ_LARGE];
memset(theLogString, 0, STRING_SZ_LARGE); memset(theLogString, 0, STRING_SZ_LARGE);
snprintf(theLogString, STRING_SZ_LARGE, "An ip %s has been blacklisted due too many password errors. Trying to login as user: %s ", data->clients[socketId].clientIpAddress, data->clients[socketId].login.name.text); snprintf(theLogString, STRING_SZ_LARGE, "An ip %s has been blacklisted due too many password errors. Trying to login as user: %s ", data->clients[socketId].clientIpAddress, data->clients[socketId].login.name.text);
addLog(theLogString, CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC); addLog(theLogString, CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
@ -391,10 +394,10 @@ int parseCommandFeat(ftpDataType *data, int socketId)
int returnCode; int returnCode;
#ifdef OPENSSL_ENABLED #ifdef OPENSSL_ENABLED
returnCode = socketPrintf(data, socketId, "s", "211-Extensions supported:\r\nPASV\r\nEPSV\r\nUTF8\r\nAUTH TLS\r\nPBSZ\r\nPROT\r\nSIZE\r\nMDTM\r\nREST\r\n211 End.\r\n"); returnCode = socketPrintf(data, socketId, "s", "211-Extensions supported:\r\nPASV\r\nEPSV\r\nEPRT\r\nUTF8\r\nAUTH TLS\r\nPBSZ\r\nPROT\r\nSIZE\r\nMDTM\r\nREST\r\n211 End.\r\n");
#endif #endif
#ifndef OPENSSL_ENABLED #ifndef OPENSSL_ENABLED
returnCode = socketPrintf(data, socketId, "s", "211-Extensions supported:\r\nPASV\r\nEPSV\r\nUTF8\r\nSIZE\r\nMDTM\r\nREST\r\n211 End.\r\n"); returnCode = socketPrintf(data, socketId, "s", "211-Extensions supported:\r\nPASV\r\nEPSV\r\nEPRT\r\nUTF8\r\nSIZE\r\nMDTM\r\nREST\r\n211 End.\r\n");
#endif #endif
if (returnCode <= 0) if (returnCode <= 0)
@ -545,8 +548,21 @@ int parseCommandPasv(ftpDataType *data, int socketId)
void *pReturn; void *pReturn;
int returnCode; int returnCode;
// my_printf("\n data->clients[%d].workerData.workerThread = %d",socketId, (int)data->clients[socketId].workerData.workerThread); // my_printf("\n data->clients[%d].workerData.workerThread = %d",socketId, (int)data->clients[socketId].workerData.workerThread);
// my_printf("\n data->clients[%d].workerData.threadHasBeenCreated = %d", socketId, data->clients[socketId].workerData.threadHasBeenCreated); // my_printf("\n data->clients[%d].workerData.threadHasBeenCreated = %d", socketId, data->clients[socketId].workerData.threadHasBeenCreated);
if(data->clients[socketId].isIpV6 == 1)
{
returnCode = socketPrintf(data, socketId, "s", "500 Server use IPV6, use EPSV instead.\r\n");
if (returnCode <= 0)
{
addLog("socketPrintfError ", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
return FTP_COMMAND_PROCESSED_WRITE_ERROR;
}
return FTP_COMMAND_PROCESSED;
}
if (data->clients[socketId].workerData.threadIsAlive == 1) if (data->clients[socketId].workerData.threadIsAlive == 1)
{ {
cancelWorker(data, socketId); cancelWorker(data, socketId);
@ -618,6 +634,9 @@ int parseCommandPort(ftpDataType *data, int socketId)
int ipAddressBytes[4]; int ipAddressBytes[4];
int portBytes[2]; int portBytes[2];
theIpAndPort = getFtpCommandArg("PORT", data->clients[socketId].theCommandReceived, 0); theIpAndPort = getFtpCommandArg("PORT", data->clients[socketId].theCommandReceived, 0);
data->clients[socketId].workerData.addressType = 1;
sscanf(theIpAndPort, "%d,%d,%d,%d,%d,%d", &ipAddressBytes[0], &ipAddressBytes[1], &ipAddressBytes[2], &ipAddressBytes[3], &portBytes[0], &portBytes[1]); sscanf(theIpAndPort, "%d,%d,%d,%d,%d,%d", &ipAddressBytes[0], &ipAddressBytes[1], &ipAddressBytes[2], &ipAddressBytes[3], &portBytes[0], &portBytes[1]);
data->clients[socketId].workerData.connectionPort = (portBytes[0] * 256) + portBytes[1]; data->clients[socketId].workerData.connectionPort = (portBytes[0] * 256) + portBytes[1];
returnCode = snprintf(data->clients[socketId].workerData.activeIpAddress, CLIENT_BUFFER_STRING_SIZE, "%d.%d.%d.%d", ipAddressBytes[0], ipAddressBytes[1], ipAddressBytes[2], ipAddressBytes[3]); returnCode = snprintf(data->clients[socketId].workerData.activeIpAddress, CLIENT_BUFFER_STRING_SIZE, "%d.%d.%d.%d", ipAddressBytes[0], ipAddressBytes[1], ipAddressBytes[2], ipAddressBytes[3]);
@ -638,6 +657,8 @@ int parseCommandPort(ftpDataType *data, int socketId)
data->clients[socketId].workerData.extendedPassiveModeOn = 0; data->clients[socketId].workerData.extendedPassiveModeOn = 0;
data->clients[socketId].workerData.activeModeOn = 1; data->clients[socketId].workerData.activeModeOn = 1;
my_printf("\n Port command received port: %d", data->clients[socketId].workerData.connectionPort);
returnCode = pthread_create(&data->clients[socketId].workerData.workerThread, NULL, connectionWorkerHandle, (void *)&data->clients[socketId].clientProgressiveNumber); returnCode = pthread_create(&data->clients[socketId].workerData.workerThread, NULL, connectionWorkerHandle, (void *)&data->clients[socketId].clientProgressiveNumber);
if (returnCode != 0) if (returnCode != 0)
@ -1023,7 +1044,7 @@ int parseCommandRetr(ftpDataType *data, int socketId)
{ {
int isSafePath = 0; int isSafePath = 0;
char *theNameToRetr; char *theNameToRetr;
int returnCode; int returnCode = 0;
if(!data->clients[socketId].workerData.socketIsReadyForConnection) if(!data->clients[socketId].workerData.socketIsReadyForConnection)
{ {
@ -1317,11 +1338,8 @@ int parseCommandCwd(ftpDataType *data, int socketId)
cleanDynamicStringDataType(&data->clients[socketId].login.absolutePath, 0, &data->clients[socketId].memoryTable); cleanDynamicStringDataType(&data->clients[socketId].login.absolutePath, 0, &data->clients[socketId].memoryTable);
setDynamicStringDataType(&data->clients[socketId].login.absolutePath, theSafePath.text, theSafePath.textLen, &data->clients[socketId].memoryTable); setDynamicStringDataType(&data->clients[socketId].login.absolutePath, theSafePath.text, theSafePath.textLen, &data->clients[socketId].memoryTable);
if (data->clients[socketId].login.absolutePath.textLen == data->clients[socketId].login.homePath.textLen)
{ if (data->clients[socketId].login.absolutePath.textLen > data->clients[socketId].login.homePath.textLen)
setDynamicStringDataType(&data->clients[socketId].login.ftpPath, "/", 1, &data->clients[socketId].memoryTable);
}
else if (data->clients[socketId].login.absolutePath.textLen > data->clients[socketId].login.homePath.textLen)
{ {
char *theFtpPathPointer = data->clients[socketId].login.absolutePath.text; char *theFtpPathPointer = data->clients[socketId].login.absolutePath.text;
theFtpPathPointer += data->clients[socketId].login.homePath.textLen; theFtpPathPointer += data->clients[socketId].login.homePath.textLen;
@ -1335,6 +1353,10 @@ int parseCommandCwd(ftpDataType *data, int socketId)
setDynamicStringDataType(&data->clients[socketId].login.ftpPath, theFtpPathPointer, strlen(theFtpPathPointer), &data->clients[socketId].memoryTable); setDynamicStringDataType(&data->clients[socketId].login.ftpPath, theFtpPathPointer, strlen(theFtpPathPointer), &data->clients[socketId].memoryTable);
} }
} }
else
{
setDynamicStringDataType(&data->clients[socketId].login.ftpPath, "/", 1, &data->clients[socketId].memoryTable);
}
// my_printf("\ndata->clients[socketId].login.absolutePath = %s", data->clients[socketId].login.absolutePath.text); // my_printf("\ndata->clients[socketId].login.absolutePath = %s", data->clients[socketId].login.absolutePath.text);
// my_printf("\ndata->clients[socketId].login.ftpPath = %s", data->clients[socketId].login.ftpPath.text); // my_printf("\ndata->clients[socketId].login.ftpPath = %s", data->clients[socketId].login.ftpPath.text);
@ -2488,3 +2510,104 @@ int setPermissions(char *permissionsCommand, char *basePath, ownerShip_DataType
return FTP_CHMODE_COMMAND_RETURN_CODE_OK; return FTP_CHMODE_COMMAND_RETURN_CODE_OK;
} }
int parseCommandEprt(ftpDataType *data, int socketId)
{
int returnCode;
returnCode = parse_eprt(data->clients[socketId].theCommandReceived, &data->clients[socketId].workerData.addressType, data->clients[socketId].workerData.activeIpAddress, &data->clients[socketId].workerData.connectionPort);
if (returnCode < 0)
{
addLog("Error parsing EPRT", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
returnCode = socketPrintf(data, socketId, "s", "501 command syntax error\r\n");
if (returnCode <= 0)
{
addLog("socketPrintfError ", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
return FTP_COMMAND_PROCESSED_WRITE_ERROR;
}
else
{
return FTP_COMMAND_PROCESSED;
}
}
#ifndef IPV6_ENABLED
if(data->clients[socketId].workerData.addressType == 2)
{
addLog("Error parsing EPRT", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
returnCode = socketPrintf(data, socketId, "s", "501 command syntax error no ipv6 supported in this version.\r\n");
if (returnCode <= 0)
{
addLog("socketPrintfError ", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
return FTP_COMMAND_PROCESSED_WRITE_ERROR;
}
else
{
return FTP_COMMAND_PROCESSED;
}
}
#endif
void *pReturn;
if (data->clients[socketId].workerData.threadIsAlive == 1)
{
cancelWorker(data, socketId);
}
if (data->clients[socketId].workerData.threadHasBeenCreated == 1)
{
returnCode = pthread_join(data->clients[socketId].workerData.workerThread, &pReturn);
my_printf("\nPORT JOIN RETURN STATUS %d", returnCode);
}
data->clients[socketId].workerData.passiveModeOn = 0;
data->clients[socketId].workerData.extendedPassiveModeOn = 0;
data->clients[socketId].workerData.activeModeOn = 1;
returnCode = pthread_create(&data->clients[socketId].workerData.workerThread, NULL, connectionWorkerHandle, (void *)&data->clients[socketId].clientProgressiveNumber);
if (returnCode != 0)
{
my_printfError("\nError in pthread_create %d", returnCode);
addLog("Pthead create error restarting the server", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
exit(0);
return FTP_COMMAND_PROCESSED_WRITE_ERROR;
}
return FTP_COMMAND_PROCESSED;
}
static int parse_eprt(const char *eprt_str, int *address_type, char *address, int *port)
{
if (eprt_str == NULL || address_type == NULL || address == NULL || port == NULL)
{
return -1; // Error: null pointer provided
}
// Check for valid EPRT format: "EPRT |<address-type>| <address> | <port>"
int scanned_items = sscanf(eprt_str, "EPRT |%d|%[^|]|%d", address_type, address, port);
if (scanned_items != 3)
{
return -2; // Error: invalid EPRT format
}
// Check for valid address type (1 or 2)
if (*address_type != 1 && *address_type != 2)
{
return -3; // Error: invalid address type
}
// Check for valid port number (positive integer)
if (*port <= 0)
{
return -4; // Error: invalid port number
}
return 0; // Success
}

View File

@ -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);

View File

@ -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);
@ -299,6 +301,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 +351,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 +376,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 +390,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 +399,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 +500,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)
@ -811,10 +818,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);

View File

@ -87,7 +87,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 +150,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;
@ -184,6 +185,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 +216,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;

View File

@ -129,7 +129,7 @@ void *connectionWorkerHandle(void * socketId)
ftpData.clients[theSocketId].workerData.threadHasBeenCreated = 1; ftpData.clients[theSocketId].workerData.threadHasBeenCreated = 1;
int returnCode; int returnCode;
my_printf("\nWORKER CREATED!"); my_printf("\n ----------------- WORKER CREATED --------------!");
//Passive data connection mode //Passive data connection mode
if (ftpData.clients[theSocketId].workerData.passiveModeOn == 1) if (ftpData.clients[theSocketId].workerData.passiveModeOn == 1)
@ -167,7 +167,7 @@ void *connectionWorkerHandle(void * socketId)
else else
{ {
my_printf("\n Using server ip: %s", ftpData.ftpParameters.natIpAddress); 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"); 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) else if (ftpData.clients[theSocketId].workerData.passiveModeOn == 1 && ftpData.clients[theSocketId].workerData.extendedPassiveModeOn == 1)
@ -237,7 +237,13 @@ void *connectionWorkerHandle(void * socketId)
} }
else if (ftpData.clients[theSocketId].workerData.activeModeOn == 1) 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); 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 #ifdef OPENSSL_ENABLED
if (ftpData.clients[theSocketId].dataChannelIsTls == 1) if (ftpData.clients[theSocketId].dataChannelIsTls == 1)
@ -567,7 +573,7 @@ void runFtpServer(void)
//Update watchdog timer //Update watchdog timer
updateWatchDogTime((int)time(NULL)); updateWatchDogTime((int)time(NULL));
/*
my_printf("\nUsed memory : %lld", DYNMEM_GetTotalMemory()); my_printf("\nUsed memory : %lld", DYNMEM_GetTotalMemory());
int memCount = 0; int memCount = 0;
for (memCount = 0; memCount < ftpData.ftpParameters.maxClients; memCount++) for (memCount = 0; memCount < ftpData.ftpParameters.maxClients; memCount++)
@ -586,7 +592,6 @@ void runFtpServer(void)
my_printf("\nftpData.clients[%d].workerData.directoryInfo.memoryTable = %s", memCount, ftpData.clients[memCount].workerData.directoryInfo.memoryTable->theName); 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 */ /* waits for socket activity, if no activity then checks for client socket timeouts */
if (selectWait(&ftpData) == 0) if (selectWait(&ftpData) == 0)
@ -595,8 +600,6 @@ void runFtpServer(void)
flushLoginWrongTriesData(&ftpData); flushLoginWrongTriesData(&ftpData);
} }
/*Main loop handle client commands */ /*Main loop handle client commands */
for (processingSock = 0; processingSock < ftpData.ftpParameters.maxClients; processingSock++) for (processingSock = 0; processingSock < ftpData.ftpParameters.maxClients; processingSock++)
{ {
@ -650,7 +653,6 @@ void runFtpServer(void)
ftpData.clients[processingSock].tlsIsNegotiating = 0; ftpData.clients[processingSock].tlsIsNegotiating = 0;
} }
continue; continue;
} }
#endif #endif
@ -863,9 +865,14 @@ static int processCommand(int processingElement)
} }
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PORT", strlen("PORT")) == 1) else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "PORT", strlen("PORT")) == 1)
{ {
//my_printf("\nPORT COMMAND RECEIVED"); my_printf("\nPORT COMMAND RECEIVED");
toReturn = parseCommandPort(&ftpData, processingElement); toReturn = parseCommandPort(&ftpData, processingElement);
} }
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "EPRT", strlen("EPRT")) == 1)
{
my_printf("\nEPRT COMMAND RECEIVED");
toReturn = parseCommandEprt(&ftpData, processingElement);
}
else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "LIST", strlen("LIST")) == 1) else if(compareStringCaseInsensitive(ftpData.clients[processingElement].theCommandReceived, "LIST", strlen("LIST")) == 1)
{ {
//my_printf("\nLIST COMMAND RECEIVED"); //my_printf("\nLIST COMMAND RECEIVED");

View File

@ -27,7 +27,7 @@
#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 "v3.0.0 stable"
void runFtpServer(void); void runFtpServer(void);

View File

@ -528,7 +528,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 +552,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 +563,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");
} }

View File

@ -40,6 +40,21 @@
#include "../debugHelper.h" #include "../debugHelper.h"
#include "../ftpData.h" #include "../ftpData.h"
#include "connection.h" #include "connection.h"
#include "log.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 +358,146 @@ int getMaximumSocketFd(int mainSocket, ftpDataType * ftpData)
return toReturn; return toReturn;
} }
#ifdef IPV6_ENABLED
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");
addLog("Socket creation failed", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
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");
addLog("socketopt failed", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
}
#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");
addLog("setsocket error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
}
#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");
addLog("bind failed", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
return -1;
}
//Number of client allowed
errorCode = listen(sock, ftpData->ftpParameters.maxClients + 1);
if (errorCode < 0)
{
addLog("listen error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
if (sock != -1)
{
close(sock);
}
return -1;
}
return sock;
}
int createPassiveSocket(int port)
{
int sock, returnCode;
struct sockaddr_in6 serveraddr;
//Socket creation IPV6
if ((sock = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
{
perror("socket() failed");
addLog("socket failed", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
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");
addLog("setsocketerror", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
}
#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");
addLog("set socket error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
}
#endif
//Bind socket
if (bind(sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
close(sock);
perror("bind() failed");
addLog("bind failed", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
return -1;
}
//Number of client allowed
returnCode = listen(sock, 1);
if (returnCode == -1)
{
addLog("bind failed", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
my_printf("\n Could not listen %d errno = %d", sock, errno);
if (sock != -1)
{
close(sock);
}
return returnCode;
}
return sock;
}
#else
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);
@ -473,18 +628,80 @@ int createPassiveSocket(int port)
return sock; 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");
addLog("Socket creation failed", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
return -1;
}
int reuse = 1;
#ifdef SO_REUSEADDR
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
{
perror("setsockopt(SO_REUSEADDR) failed");
my_printfError("setsockopt(SO_REUSEADDR) failed");
addLog("set socket error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
}
#endif
#ifdef SO_REUSEPORT
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
{
perror("setsockopt(SO_REUSEADDR) failed");
my_printfError("setsockopt(SO_REUSEADDR) failed");
addLog("setsockopt error", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
}
#endif
// Prepare the sockaddr structure
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");
addLog("Invalid ip address", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
return -1;
}
// Connect to server
if (connect(sockfd, serv_addr_any, sizeof(serv_addr6)) < 0)
{
my_printfError("Connection failed");
addLog("Connection failed", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
return -1;
}
return sockfd;
}
#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;
} }
@ -713,6 +930,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;
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
}
else
{
int returnCode = socketPrintf(ftpData, availableSocketIndex, "s", ftpData->welcomeMessage);
if (returnCode <= 0)
{
ftpData->clients[availableSocketIndex].closeTheClient = 1;
addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
}
}
return 1;
}
else
{
//Errors while accepting, socket will be closed
ftpData->clients[availableSocketIndex].closeTheClient = 1;
//addLog("Closing the client", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
//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 +1089,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),
@ -817,3 +1167,5 @@ int evaluateClientSocketConnection(ftpDataType * ftpData)
return 0; return 0;
} }
} }
#endif

View File

@ -36,6 +36,11 @@ 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
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);

View File

@ -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;
@ -263,17 +263,17 @@ void FILE_GetDirectoryInodeList(char * DirectoryInodeName, char *** InodeList, i
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;
} }
@ -750,7 +750,7 @@ char * FILE_GetGroupOwner(char *fileName, DYNMEM_MemoryTable_DataType **memoryTa
} }
char * FILE_AppendStringToFile(char *fileName, char *theString) void FILE_AppendStringToFile(char *fileName, char *theString)
{ {
FILE *fp = fopen(fileName, "a"); FILE *fp = fopen(fileName, "a");
if (fp == NULL) if (fp == NULL)

View File

@ -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);

View File

@ -19,7 +19,7 @@
#define LOG_LINE_SIZE 1024 + PATH_MAX #define LOG_LINE_SIZE 1024 + PATH_MAX
#define LOG_FILENAME_PREFIX "uftpLog_" #define LOG_FILENAME_PREFIX "uftpLog_"
static void logThread(void * arg); static void *logThread(void * arg);
static DYNV_VectorString_DataType logQueue; static DYNV_VectorString_DataType logQueue;
static DYNV_VectorString_DataType workerQueue; static DYNV_VectorString_DataType workerQueue;
@ -104,7 +104,7 @@ static int delete_old_logs(const char* folder_path, int days_to_keep)
if (strftime(timeToday, sizeof(timeToday), "%Y-%m-%d", info) == 0) if (strftime(timeToday, sizeof(timeToday), "%Y-%m-%d", info) == 0)
{ {
my_printfError("strftime error"); my_printfError("strftime error");
return; return -1;
} }
n_of_day_today = is_date_format(timeToday); n_of_day_today = is_date_format(timeToday);
@ -158,7 +158,7 @@ static int delete_old_logs(const char* folder_path, int days_to_keep)
} }
// STATIC SECTION // STATIC SECTION
static void logThread(void * arg) static void *logThread(void * arg)
{ {
int lastDay; int lastDay;
@ -181,7 +181,7 @@ static void logThread(void * arg)
if (strftime(dayString, sizeof(dayString), "%d", info) == 0) if (strftime(dayString, sizeof(dayString), "%d", info) == 0)
{ {
my_printfError("strftime error"); my_printfError("strftime error");
return; return NULL;
} }
day = atoi(dayString); day = atoi(dayString);
@ -195,7 +195,7 @@ static void logThread(void * arg)
if (strftime(logName, sizeof(logName), LOG_FILENAME_PREFIX"%Y-%m-%d", info) == 0) if (strftime(logName, sizeof(logName), LOG_FILENAME_PREFIX"%Y-%m-%d", info) == 0)
{ {
my_printfError("strftime error"); my_printfError("strftime error");
return; return NULL;
} }
strncpy(theLogFilename, logFolder, PATH_MAX); strncpy(theLogFilename, logFolder, PATH_MAX);
@ -240,7 +240,7 @@ int logInit(char * folder, int numberOfLogFiles)
logFilesNumber = numberOfLogFiles; logFilesNumber = numberOfLogFiles;
if (logFilesNumber <= 0) if (logFilesNumber <= 0)
return; return -1;
delete_old_logs(folder, numberOfLogFiles); delete_old_logs(folder, numberOfLogFiles);
@ -252,7 +252,7 @@ int logInit(char * folder, int numberOfLogFiles)
// Initialize the mutex // Initialize the mutex
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
returnCode = pthread_create(&pLogThread, NULL, &logThread, NULL); returnCode = pthread_create(&pLogThread, NULL, logThread, NULL);
if (returnCode != 0) if (returnCode != 0)
{ {
addLog("Pthead create error restarting the server", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC); addLog("Pthead create error restarting the server", CURRENT_FILE, CURRENT_LINE, CURRENT_FUNC);
@ -270,7 +270,7 @@ int logInit(char * folder, int numberOfLogFiles)
return 1; return 1;
} }
void addLog(char* logString, char * currFile, int currLine, char * currFunction) void addLog(char* logString, char * currFile, int currLine, const char * currFunction)
{ {
if (logFilesNumber <= 0) if (logFilesNumber <= 0)

View File

@ -26,6 +26,6 @@
#define LOG_H #define LOG_H
int logInit(char * folder, int numberOfLogFiles); int logInit(char * folder, int numberOfLogFiles);
void addLog(char* logString, char * currFile, int currLine, char * currFunction); void addLog(char* logString, char * currFile, int currLine, const char * currFunction);
#endif #endif

View File

@ -33,7 +33,7 @@
#include "openSsl.h" #include "openSsl.h"
#include "fileManagement.h" #include "fileManagement.h"
#include "../debugHelper.h" #include "../debugHelper.h"
#include "log.h"
#define MUTEX_TYPE pthread_mutex_t #define MUTEX_TYPE pthread_mutex_t

View File

@ -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);

View File

@ -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