diff --git a/build/modules/connection.o.orig b/build/modules/connection.o.orig new file mode 100644 index 0000000..48c4673 Binary files /dev/null and b/build/modules/connection.o.orig differ diff --git a/build/modules/connection_BACKUP_23916.o b/build/modules/connection_BACKUP_23916.o new file mode 100644 index 0000000..48c4673 Binary files /dev/null and b/build/modules/connection_BACKUP_23916.o differ diff --git a/build/modules/connection_BASE_23916.o b/build/modules/connection_BASE_23916.o new file mode 100644 index 0000000..2e929eb Binary files /dev/null and b/build/modules/connection_BASE_23916.o differ diff --git a/build/modules/connection_LOCAL_23916.o b/build/modules/connection_LOCAL_23916.o new file mode 100644 index 0000000..48c4673 Binary files /dev/null and b/build/modules/connection_LOCAL_23916.o differ diff --git a/build/modules/connection_REMOTE_23916.o b/build/modules/connection_REMOTE_23916.o new file mode 100644 index 0000000..ce51d49 Binary files /dev/null and b/build/modules/connection_REMOTE_23916.o differ diff --git a/build/modules/fileManagement.o.orig b/build/modules/fileManagement.o.orig new file mode 100644 index 0000000..824b9ac Binary files /dev/null and b/build/modules/fileManagement.o.orig differ diff --git a/build/modules/ftpCommandElaborate.o.orig b/build/modules/ftpCommandElaborate.o.orig new file mode 100644 index 0000000..cc16e16 Binary files /dev/null and b/build/modules/ftpCommandElaborate.o.orig differ diff --git a/build/modules/ftpData.o.orig b/build/modules/ftpData.o.orig new file mode 100644 index 0000000..f5d0152 Binary files /dev/null and b/build/modules/ftpData.o.orig differ diff --git a/build/modules/ftpServer.o.orig b/build/modules/ftpServer.o.orig new file mode 100644 index 0000000..d181e3e Binary files /dev/null and b/build/modules/ftpServer.o.orig differ diff --git a/build/uFTP.orig b/build/uFTP.orig new file mode 100755 index 0000000..8d16368 Binary files /dev/null and b/build/uFTP.orig differ diff --git a/ftpCommandElaborate.c b/ftpCommandElaborate.c index 239055e..8cfe40f 100644 --- a/ftpCommandElaborate.c +++ b/ftpCommandElaborate.c @@ -379,8 +379,10 @@ int parseCommandProt(ftpDataType * data, int socketId) int parseCommandCcc(ftpDataType * data, int socketId) { + int returnCode; + #ifdef OPENSSL_ENABLED - int returnCode; + returnCode = socketPrintf(data, socketId, "s", "200 TLS connection aborted\r\n"); SSL_set_shutdown(data->clients[socketId].ssl, SSL_SENT_SHUTDOWN); data->clients[socketId].tlsIsEnabled = 0; @@ -389,7 +391,7 @@ int parseCommandCcc(ftpDataType * data, int socketId) return FTP_COMMAND_PROCESSED_WRITE_ERROR; #endif - #ifdef OPENSSL_ENABLED + #ifndef OPENSSL_ENABLED returnCode = socketPrintf(data, socketId, "s", "500 command not supported\r\n"); if (returnCode <= 0) diff --git a/ftpData.c b/ftpData.c index 49b1ce4..c8f2ff2 100644 --- a/ftpData.c +++ b/ftpData.c @@ -91,8 +91,6 @@ void setDynamicStringDataType(dynamicStringDataType *dynamicString, char *theStr memcpy(dynamicString->text, theString, stringLen); dynamicString->textLen = stringLen; } - - //printf("\ndynamicString->text = %lld", dynamicString->text); } int getSafePath(dynamicStringDataType *safePath, char *theDirectoryName, loginDataType *loginData, DYNMEM_MemoryTable_DataType **memoryTable) @@ -645,9 +643,9 @@ void resetWorkerData(ftpDataType *data, int clientId, int isInitialization) void resetClientData(ftpDataType *data, int clientId, int isInitialization) { + if (isInitialization != 1) { - if (data->clients[clientId].workerData.threadIsAlive == 1) pthread_cancel(data->clients[clientId].workerData.workerThread); diff --git a/ftpData.c.orig b/ftpData.c.orig new file mode 100644 index 0000000..7860bd3 --- /dev/null +++ b/ftpData.c.orig @@ -0,0 +1,769 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include "ftpServer.h" +#include "ftpCommandsElaborate.h" +#include "ftpData.h" +#include "library/configRead.h" +#include "library/fileManagement.h" +#include "library/connection.h" +#include "library/dynamicMemory.h" + +void cleanDynamicStringDataType(dynamicStringDataType *dynamicString, int init, DYNMEM_MemoryTable_DataType **memoryTable) +{ + if (init == 1) + { + dynamicString->text = 0; + dynamicString->textLen = 0; + } + else + { + if (dynamicString->textLen != 0) + { + if (dynamicString->text != 0) { + DYNMEM_free(dynamicString->text, &*memoryTable); + } + } + + dynamicString->textLen = 0; + } +} + +void cleanLoginData(loginDataType *loginData, int init, DYNMEM_MemoryTable_DataType **memoryTable) +{ + loginData->userLoggedIn = 0; + cleanDynamicStringDataType(&loginData->homePath, init, &*memoryTable); + cleanDynamicStringDataType(&loginData->ftpPath, init, &*memoryTable); + cleanDynamicStringDataType(&loginData->name, init, &*memoryTable); + cleanDynamicStringDataType(&loginData->password, init, &*memoryTable); + cleanDynamicStringDataType(&loginData->absolutePath, init, &*memoryTable); +} + +void setDynamicStringDataType(dynamicStringDataType *dynamicString, char *theString, int stringLen, DYNMEM_MemoryTable_DataType **memoryTable) +{ + if (dynamicString->textLen == 0) + { + //printf("\nMemory data address before memset call : %lld", memoryTable); + dynamicString->text = (char *) DYNMEM_malloc (((sizeof(char) * stringLen) + 1), &*memoryTable); + //printf("\nMemory data address after memset call : %lld", memoryTable); + memset(dynamicString->text, 0, stringLen + 1); + memcpy(dynamicString->text, theString, stringLen); + dynamicString->textLen = stringLen; + } + else + { + if(stringLen != dynamicString->textLen) + { + dynamicString->text = (char *) DYNMEM_realloc (dynamicString->text, ((sizeof(char) * stringLen) + 1), &*memoryTable); + } + + memset(dynamicString->text, 0, stringLen + 1); + memcpy(dynamicString->text, theString, stringLen); + dynamicString->textLen = stringLen; + } + + //printf("\ndynamicString->text = %lld", dynamicString->text); +} + +int getSafePath(dynamicStringDataType *safePath, char *theDirectoryName, loginDataType *loginData, DYNMEM_MemoryTable_DataType **memoryTable) +{ + #define STRING_SIZE 4096 + int theLen, i; + char * theDirectoryNamePointer; + theDirectoryNamePointer = theDirectoryName; + + if (theDirectoryName == NULL) + return 0; + + theLen = strlen(theDirectoryName); + + if (theLen <= 0) + return 0; + + if (theLen == 2 && + theDirectoryName[0] == '.' && + theDirectoryName[1] == '.') + { + return 0; + } + + if (theLen == 3 && + ((theDirectoryName[0] == '.' && + theDirectoryName[1] == '.' && + theDirectoryName[2] == '/') || + (theDirectoryName[0] == '/' && + theDirectoryName[1] == '.' && + theDirectoryName[2] == '.') + ) + ) + { + return 0; + } + + //Check for /../ + char theDirectoryToCheck[STRING_SIZE]; + int theDirectoryToCheckIndex = 0; + memset(theDirectoryToCheck, 0, STRING_SIZE); + + for (i = 0; i< theLen; i++) + { + if (theDirectoryName[i] == '/') + { + if (theDirectoryToCheckIndex == 2 && + theDirectoryToCheck[0] == '.' && + theDirectoryToCheck[1] == '.') + { + return 0; + } + + theDirectoryToCheckIndex = 0; + memset(theDirectoryToCheck, 0, STRING_SIZE); + continue; + } + + if (theDirectoryToCheckIndexhomePath.text, loginData->homePath.textLen, &*memoryTable); + //printf("\nMemory data address 3rd call : %lld", memoryTable); + appendToDynamicStringDataType(safePath, theDirectoryNamePointer, strlen(theDirectoryNamePointer), &*memoryTable); + } + else + { + setDynamicStringDataType(safePath, loginData->absolutePath.text, loginData->absolutePath.textLen, &*memoryTable); + + if (loginData->absolutePath.text[loginData->absolutePath.textLen-1] != '/') + { + appendToDynamicStringDataType(safePath, "/", 1, &*memoryTable); + } + + appendToDynamicStringDataType(safePath, theDirectoryName, strlen(theDirectoryName), &*memoryTable); + } + + return 1; +} + +void appendToDynamicStringDataType(dynamicStringDataType *dynamicString, char *theString, int stringLen, DYNMEM_MemoryTable_DataType **memoryTable) +{ + //printf("\nRealloc dynamicString->text = %lld", dynamicString->text); + int theNewSize = dynamicString->textLen + stringLen; + + dynamicString->text = DYNMEM_realloc(dynamicString->text, theNewSize + 1, &*memoryTable); + + memset(dynamicString->text+dynamicString->textLen, 0, stringLen+1); + memcpy(dynamicString->text+dynamicString->textLen, theString, stringLen); + + dynamicString->text[theNewSize] = '\0'; + dynamicString->textLen = theNewSize; +} + +void setRandomicPort(ftpDataType *data, int socketPosition) +{ + static unsigned short int randomizeInteger = 0; + unsigned short int randomicPort = 5000; + int i; + + randomizeInteger += 1; + + if (randomizeInteger > 100 ) + randomizeInteger = 1; + + while(randomicPort < 10000) + randomicPort = ((rand() + socketPosition + randomizeInteger) % (50000)) + 10000; + i = 0; + + while (i < data->ftpParameters.maxClients) + { + if (randomicPort == data->clients[i].workerData.connectionPort || + randomicPort < 10000) + { + randomicPort = ((rand() + socketPosition + i + randomizeInteger) % (50000)) + 10000; + i = 0; + } + else + { + i++; + } + } + + + data->clients[socketPosition].workerData.connectionPort = randomicPort; + //printf("data->clients[%d].workerData.connectionPort = %d", socketPosition, data->clients[socketPosition].workerData.connectionPort); +} + +int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumber, int commandType, DYNMEM_MemoryTable_DataType **memoryTable) +{ + int i, x, returnCode; + int fileAndFoldersCount = 0; + char **fileList = NULL; + FILE_GetDirectoryInodeList(ftpData->clients[clientId].listPath.text, &fileList, &fileAndFoldersCount, 0); + *filesNumber = fileAndFoldersCount; + + returnCode = socketWorkerPrintf(ftpData, clientId, "sds", "total ", fileAndFoldersCount ,"\r\n"); + if (returnCode <= 0) + { + return -1; + } + + for (i = 0; i < fileAndFoldersCount; i++) + { + ftpListDataType data; + data.owner = NULL; + data.groupOwner = NULL; + data.inodePermissionString = NULL; + data.fileNameWithPath = NULL; + data.finalStringPath = NULL; + data.linkPath = NULL; + data.isFile = 0; + data.isDirectory = 0; + + //printf("\nPROCESSING: %s", fileList[i]); + + if (FILE_IsDirectory(fileList[i]) == 1) + { + //printf("\nis directory"); + //fflush(0); + data.isDirectory = 1; + data.isFile = 0; + data.isLink = 0; + data.fileSize = 4096; + data.numberOfSubDirectories = FILE_GetDirectoryInodeCount(fileList[i]); + } + else if (FILE_IsFile(fileList[i]) == 1) + { + //printf("\nis file"); + //fflush(0); + data.isDirectory = 0; + data.isFile = 1; + data.isLink = 0; + data.numberOfSubDirectories = 1; /* to Do*/ + data.fileSize = FILE_GetFileSizeFromPath(fileList[i]); + } + if (data.isDirectory == 0 && data.isFile == 0) + { + //printf("\nNot a directory, not a file, broken link"); + continue; + } + + + //printf("\nFILE SIZE : %lld", data.fileSize); + + data.owner = FILE_GetOwner(fileList[i]); + data.groupOwner = FILE_GetGroupOwner(fileList[i]); + data.fileNameWithPath = fileList[i]; + data.fileNameNoPath = FILE_GetFilenameFromPath(fileList[i]); + data.inodePermissionString = FILE_GetListPermissionsString(fileList[i]); + data.lastModifiedData = FILE_GetLastModifiedData(fileList[i]); + + if (strlen(data.fileNameNoPath) > 0) + { + data.finalStringPath = (char *) DYNMEM_malloc (strlen(data.fileNameNoPath)+1, &*memoryTable); + strcpy(data.finalStringPath, data.fileNameNoPath); + } + + if (data.inodePermissionString != NULL && + strlen(data.inodePermissionString) > 0 && + data.inodePermissionString[0] == 'l') + { + int len = 0; + data.isLink = 1; + data.linkPath = (char *) DYNMEM_malloc (CLIENT_COMMAND_STRING_SIZE*sizeof(char), &*memoryTable); + if ((len = readlink (fileList[i], data.linkPath, CLIENT_COMMAND_STRING_SIZE)) > 0) + { + data.linkPath[len] = 0; + FILE_AppendToString(&data.finalStringPath, " -> ", &*memoryTable); + FILE_AppendToString(&data.finalStringPath, data.linkPath, &*memoryTable); + } + } + + memset(data.lastModifiedDataString, 0, LIST_DATA_TYPE_MODIFIED_DATA_STR_SIZE); + strftime(data.lastModifiedDataString, LIST_DATA_TYPE_MODIFIED_DATA_STR_SIZE, "%b %d %Y", localtime(&data.lastModifiedData)); + + + switch (commandType) + { + case COMMAND_TYPE_LIST: + { + returnCode = socketWorkerPrintf(ftpData, clientId, "ssdssssslsssss", + data.inodePermissionString == NULL? "Unknown" : data.inodePermissionString + ," " + ,data.numberOfSubDirectories + ," " + ,data.owner == NULL? "Unknown" : data.owner + ," " + ,data.groupOwner == NULL? "Unknown" : data.groupOwner + ," " + ,data.fileSize + ," " + ,data.lastModifiedDataString == NULL? "Unknown" : data.lastModifiedDataString + ," " + ,data.finalStringPath == NULL? "Unknown" : data.finalStringPath + ,"\r\n"); + /* + returnCode = dprintf(theSocket, "%s %d %s %s %lld %s %s\r\n", + data.inodePermissionString == NULL? "Unknown" : data.inodePermissionString + ,data.numberOfSubDirectories + ,data.owner == NULL? "Unknown" : data.owner + ,data.groupOwner == NULL? "Unknown" : data.groupOwner + ,data.fileSize + ,data.lastModifiedDataString == NULL? "Unknown" : data.lastModifiedDataString + ,data.finalStringPath == NULL? "Unknown" : data.finalStringPath); + */ + } + break; + + case COMMAND_TYPE_NLST: + { + returnCode = socketWorkerPrintf(ftpData, clientId, "ss", data.fileNameNoPath, "\r\n"); + } + break; + + + default: + { + printf("\nWarning switch default in function writeListDataInfoToSocket (%d)", commandType); + } + break; + } + + + if (data.fileNameWithPath != NULL) + free(data.fileNameWithPath); + + if (data.linkPath != NULL) + free(data.linkPath); + + if (data.finalStringPath != NULL) + free(data.finalStringPath); + + if (data.owner != NULL) + free(data.owner); + + if (data.groupOwner != NULL) + free(data.groupOwner); + + if (data.inodePermissionString != NULL) + free(data.inodePermissionString); + + if (returnCode <= 0) + { + for (x = i+1; x < fileAndFoldersCount; x++) + free (fileList[x]); + free (fileList); + return -1; + } + + } + + if (fileList != NULL) + { + free (fileList); + } + + return 1; + } + +int searchInLoginFailsVector(void * loginFailsVector, void *element) +{ + int i = 0; + //printf("((DYNV_VectorGenericDataType *)loginFailsVector)->Size = %d", ((DYNV_VectorGenericDataType *)loginFailsVector)->Size); + + for (i = 0; i < ((DYNV_VectorGenericDataType *)loginFailsVector)->Size; i++) + { + if (strcmp( ((loginFailsDataType *) element)->ipAddress, (((loginFailsDataType *) ((DYNV_VectorGenericDataType *)loginFailsVector)->Data[i])->ipAddress)) == 0) + { + //printf("\n\n***IP address found: %s in %d", ((loginFailsDataType *) element)->ipAddress, i); + return i; + } + } + + return -1; +} + +void deleteLoginFailsData(void *element) +{ + ; //NOP +} + +void getListDataInfo(char * thePath, DYNV_VectorGenericDataType *directoryInfo, DYNMEM_MemoryTable_DataType **memoryTable) +{ + int i; + int fileAndFoldersCount = 0; + ftpListDataType data; + FILE_GetDirectoryInodeList(thePath, &data.fileList, &fileAndFoldersCount, 0); + + //printf("\nNUMBER OF FILES: %d", fileAndFoldersCount); + //fflush(0); + + for (i = 0; i < fileAndFoldersCount; i++) + { + data.owner = NULL; + data.groupOwner = NULL; + data.inodePermissionString = NULL; + data.fileNameWithPath = NULL; + data.finalStringPath = NULL; + data.linkPath = NULL; + + data.numberOfSubDirectories = 1; /* to Do*/ + data.isFile = 0; + data.isDirectory = 0; + + + //printf("\nPROCESSING: %s", data.fileList[i]); + //fflush(0); + + if (FILE_IsDirectory(data.fileList[i]) == 1) + { + //printf("\nis file"); + //fflush(0); + data.isDirectory = 1; + data.isFile = 0; + data.isLink = 0; + data.fileSize = 4096; + } + else if (FILE_IsFile(data.fileList[i]) == 1) + { + //printf("\nis file"); + //fflush(0); + data.isDirectory = 0; + data.isFile = 1; + data.isLink = 0; + data.fileSize = FILE_GetFileSizeFromPath(data.fileList[i]); + } + if (data.isDirectory == 0 && data.isFile == 0) + { + printf("\nNot a directory, not a file, broken link"); + continue; + } + + printf("\nFILE SIZE : %lld", data.fileSize); + + data.owner = FILE_GetOwner(data.fileList[i]); + data.groupOwner = FILE_GetGroupOwner(data.fileList[i]); + data.fileNameWithPath = data.fileList[i]; + data.fileNameNoPath = FILE_GetFilenameFromPath(data.fileList[i]); + data.inodePermissionString = FILE_GetListPermissionsString(data.fileList[i]); + data.lastModifiedData = FILE_GetLastModifiedData(data.fileList[i]); + + if (strlen(data.fileNameNoPath) > 0) + { + data.finalStringPath = (char *) DYNMEM_malloc (strlen(data.fileNameNoPath)+1, &*memoryTable); + strcpy(data.finalStringPath, data.fileNameNoPath); + } + + if (data.inodePermissionString != NULL && + strlen(data.inodePermissionString) > 0 && + data.inodePermissionString[0] == 'l') + { + int len = 0; + data.isLink = 1; + data.linkPath = (char *) DYNMEM_malloc (CLIENT_COMMAND_STRING_SIZE*sizeof(char), &*memoryTable); + if ((len = readlink (data.fileList[i], data.linkPath, CLIENT_COMMAND_STRING_SIZE)) > 0) + { + data.linkPath[len] = 0; + FILE_AppendToString(&data.finalStringPath, " -> ", &*memoryTable); + FILE_AppendToString(&data.finalStringPath, data.linkPath, &*memoryTable); + } + } + + memset(data.lastModifiedDataString, 0, LIST_DATA_TYPE_MODIFIED_DATA_STR_SIZE); + strftime(data.lastModifiedDataString, 80, "%b %d %Y", localtime(&data.lastModifiedData)); + + /* + -1 List one file per line + -A List all files except "." and ".." + -a List all files including those whose names start with "." + -C List entries by columns + -d List directory entries instead of directory contents + -F Append file type indicator (one of "*", "/", "=", "@" or "|") to names + -h Print file sizes in human-readable format (e.g. 1K, 234M, 2G) + -L List files pointed to by symlinks + -l Use a long listing format + -n List numeric UIDs/GIDs instead of user/group names + -R List subdirectories recursively + -r Sort filenames in reverse order + -S Sort by file size + -t Sort by modification time + */ + + directoryInfo->PushBack(directoryInfo, &data, sizeof(ftpListDataType)); + } +} + +void deleteListDataInfoVector(void *TheElementToDelete) +{ + ftpListDataType *data = (ftpListDataType *)TheElementToDelete; + + if (data->owner != NULL) + { + free(data->owner); + } + + if (data->groupOwner != NULL) + { + free(data->groupOwner); + } + + if (data->inodePermissionString != NULL) + { + free(data->inodePermissionString); + } + + if (data->fileNameWithPath != NULL) + { + free(data->fileNameWithPath); + } + + if (data->finalStringPath != NULL) + { + free(data->finalStringPath); + } + + if (data->linkPath != NULL) + { + free(data->linkPath); + } +} + +void resetWorkerData(ftpDataType *data, int clientId, int isInitialization) +{ + + data->clients[clientId].workerData.connectionPort = 0; + data->clients[clientId].workerData.passiveModeOn = 0; + data->clients[clientId].workerData.socketIsConnected = 0; + data->clients[clientId].workerData.commandIndex = 0; + data->clients[clientId].workerData.passiveListeningSocket = 0; + data->clients[clientId].workerData.socketConnection = 0; + data->clients[clientId].workerData.bufferIndex = 0; + data->clients[clientId].workerData.commandReceived = 0; + data->clients[clientId].workerData.retrRestartAtByte = 0; + data->clients[clientId].workerData.threadIsAlive = 0; + data->clients[clientId].workerData.activeModeOn = 0; + data->clients[clientId].workerData.passiveModeOn = 0; + data->clients[clientId].workerData.activeIpAddressIndex = 0; + + memset(data->clients[clientId].workerData.buffer, 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); + + 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); + + /* wait main for action */ + if (isInitialization != 1) + { + + printf("\n Operation is not an initialization! "); + + pthread_mutex_destroy(&data->clients[clientId].workerData.conditionMutex); + pthread_cond_destroy(&data->clients[clientId].workerData.conditionVariable); + + if (data->clients[clientId].workerData.theStorFile != NULL) + { + int returnCode = 0; + returnCode = fclose(data->clients[clientId].workerData.theStorFile); + data->clients[clientId].workerData.theStorFile = NULL; + } + + #ifdef OPENSSL_ENABLED + SSL_free(data->clients[clientId].workerData.serverSsl); + SSL_free(data->clients[clientId].workerData.clientSsl); + #endif + } + else + { + DYNV_VectorGeneric_Init(&data->clients[clientId].workerData.directoryInfo); + data->clients[clientId].workerData.theStorFile = NULL; + data->clients[clientId].workerData.threadHasBeenCreated = 0; + } + + if (pthread_mutex_init(&data->clients[clientId].workerData.conditionMutex, NULL) != 0) + { + printf("\ndata->clients[clientId].workerData.conditionMutex init failed\n"); + exit(0); + } + + + if (pthread_cond_init(&data->clients[clientId].workerData.conditionVariable, NULL) != 0) + { + printf("\ndata->clients[clientId].workerData.conditionVariable init failed\n"); + exit(0); + } + + //Clear the dynamic vector structure + int theSize = data->clients[clientId].workerData.directoryInfo.Size; + char ** lastToDestroy = NULL; + if (theSize > 0) + { + lastToDestroy = ((ftpListDataType *)data->clients[clientId].workerData.directoryInfo.Data[0])->fileList; + data->clients[clientId].workerData.directoryInfo.Destroy(&data->clients[clientId].workerData.directoryInfo, deleteListDataInfoVector); + free(lastToDestroy); + } + + #ifdef OPENSSL_ENABLED + data->clients[clientId].workerData.serverSsl = SSL_new(data->serverCtx); + data->clients[clientId].workerData.clientSsl = SSL_new(data->clientCtx); + #endif +} + +void resetClientData(ftpDataType *data, int clientId, int isInitialization) +{ + if (isInitialization != 1) + { +<<<<<<< HEAD + +======= +>>>>>>> master + if (data->clients[clientId].workerData.threadIsAlive == 1) + pthread_cancel(data->clients[clientId].workerData.workerThread); + + pthread_mutex_destroy(&data->clients[clientId].writeMutex); + + #ifdef OPENSSL_ENABLED + SSL_free(data->clients[clientId].ssl); + //SSL_free(data->clients[clientId].workerData.ssl); + #endif + } + + if (pthread_mutex_init(&data->clients[clientId].writeMutex, NULL) != 0) + { + printf("\nclientData->writeMutex init failed\n"); + exit(0); + } + + data->clients[clientId].tlsIsNegotiating = 0; + data->clients[clientId].tlsIsEnabled = 0; + data->clients[clientId].dataChannelIsTls = 0; + data->clients[clientId].socketDescriptor = -1; + data->clients[clientId].socketCommandReceived = 0; + data->clients[clientId].socketIsConnected = 0; + data->clients[clientId].bufferIndex = 0; + data->clients[clientId].commandIndex = 0; + data->clients[clientId].closeTheClient = 0; + data->clients[clientId].sockaddr_in_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].server_sockaddr_in, 0, data->clients[clientId].sockaddr_in_server_size); + memset(data->clients[clientId].clientIpAddress, 0, INET_ADDRSTRLEN); + memset(data->clients[clientId].buffer, 0, CLIENT_BUFFER_STRING_SIZE); + memset(data->clients[clientId].theCommandReceived, 0, CLIENT_COMMAND_STRING_SIZE); + cleanLoginData(&data->clients[clientId].login, isInitialization, &data->clients[clientId].memoryTable); + + //Rename from and to data init + cleanDynamicStringDataType(&data->clients[clientId].renameFromFile, isInitialization, &data->clients[clientId].memoryTable); + cleanDynamicStringDataType(&data->clients[clientId].renameToFile, isInitialization, &data->clients[clientId].memoryTable); + cleanDynamicStringDataType(&data->clients[clientId].fileToStor, isInitialization, &data->clients[clientId].memoryTable); + cleanDynamicStringDataType(&data->clients[clientId].fileToRetr, isInitialization, &data->clients[clientId].memoryTable); + cleanDynamicStringDataType(&data->clients[clientId].listPath, isInitialization, &data->clients[clientId].memoryTable); + cleanDynamicStringDataType(&data->clients[clientId].nlistPath, isInitialization, &data->clients[clientId].memoryTable); + cleanDynamicStringDataType(&data->clients[clientId].ftpCommand.commandArgs, isInitialization, &data->clients[clientId].memoryTable); + cleanDynamicStringDataType(&data->clients[clientId].ftpCommand.commandOps, isInitialization, &data->clients[clientId].memoryTable); + + data->clients[clientId].connectionTimeStamp = 0; + data->clients[clientId].tlsNegotiatingTimeStart = 0; + data->clients[clientId].lastActivityTimeStamp = 0; + + #ifdef OPENSSL_ENABLED + //data->clients[clientId].workerData.ssl = SSL_new(data->ctx); + data->clients[clientId].ssl = SSL_new(data->serverCtx); + #endif +} + +int compareStringCaseInsensitive(char * stringIn, char * stringRef, int stringLenght) +{ + int i = 0; + char * alfaLowerCase = "qwertyuiopasdfghjklzxcvbnm "; + char * alfaUpperCase = "QWERTYUIOPASDFGHJKLZXCVBNM "; + + int stringInIndex; + int stringRefIndex; + + for (i = 0; i ftpParameters.port); @@ -311,9 +315,25 @@ int createSocket(ftpDataType * ftpData) #endif //Bind socket errorCode = bind(sock,(struct sockaddr*) &temp,sizeof(temp)); + if (errorCode == -1) + { + if (sock != -1) + { + close(sock); + } + return -1; + } //Number of client allowed errorCode = listen(sock, ftpData->ftpParameters.maxClients + 1); + if (errorCode == -1) + { + if (sock != -1) + { + close(sock); + } + return -1; + } return sock; } @@ -325,6 +345,11 @@ int createPassiveSocket(int port) //Socket creation sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) + { + return -1; + } + temp.sin_family = AF_INET; temp.sin_addr.s_addr = INADDR_ANY; temp.sin_port = htons(port); @@ -345,13 +370,28 @@ int createPassiveSocket(int port) returnCode = bind(sock,(struct sockaddr*) &temp,sizeof(temp)); if (returnCode == -1) - return returnCode; + { + printf("\n Could not bind %d errno = %d", sock, errno); + + if (sock != -1) + { + close(sock); + } + return returnCode; + } //Number of client allowed returnCode = listen(sock, 1); if (returnCode == -1) - return returnCode; + { + printf("\n Could not listen %d errno = %d", sock, errno); + if (sock != -1) + { + close(sock); + } + return returnCode; + } return sock; } @@ -379,7 +419,7 @@ int createActiveSocket(int port, char *ipAddress) } else { - printf("\n sockfd = %d \n", sockfd); + printf("\ncreateActiveSocket created socket = %d \n", sockfd); } @@ -398,6 +438,12 @@ int createActiveSocket(int port, char *ipAddress) if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("\n3 Error : Connect Failed \n"); + + if (sockfd != -1) + { + close(sockfd); + } + return -1; } @@ -437,9 +483,41 @@ void fdRemove(ftpDataType * ftpData, int index) void closeSocket(ftpDataType * ftpData, int processingSocket) { + int theReturnCode = 0; + +#ifdef OPENSSL_ENABLED + /* + if (ftpData->clients[processingSocket].dataChannelIsTls == 1) + { + if(ftpData->clients[processingSocket].workerData.passiveModeOn == 1) + { + + printf("\nSSL worker Shutdown 1"); + returnCode = SSL_shutdown(ftpData->clients[processingSocket].ssl); + printf("\nnSSL worker Shutdown 1 return code : %d", returnCode); + + if (returnCode < 0) + { + printf("SSL_shutdown failed return code %d", returnCode); + } + else if (returnCode == 0) + { + printf("\nSSL worker Shutdown 2"); + returnCode = SSL_shutdown(ftpData->clients[processingSocket].ssl); + printf("\nnSSL worker Shutdown 2 return code : %d", returnCode); + + if (returnCode <= 0) + { + printf("SSL_shutdown (2nd time) failed"); + } + } + } + }*/ +#endif + //Close the socket shutdown(ftpData->clients[processingSocket].socketDescriptor, SHUT_RDWR); - close(ftpData->clients[processingSocket].socketDescriptor); + theReturnCode = close(ftpData->clients[processingSocket].socketDescriptor); resetClientData(ftpData, processingSocket, 0); resetWorkerData(ftpData, processingSocket, 0); @@ -462,9 +540,7 @@ void closeClient(ftpDataType * ftpData, int processingSocket) if (ftpData->clients[processingSocket].workerData.threadIsAlive == 1) { - pthread_cancel(ftpData->clients[processingSocket].workerData.workerThread); - //pthread_join(ftpData->clients[processingSocket].workerData.workerThread, &pReturn); printf("\nQuit command received the Pasv Thread has been cancelled."); } @@ -522,7 +598,6 @@ int selectWait(ftpDataType * ftpData) struct timeval selectMaximumLockTime; selectMaximumLockTime.tv_sec = 10; selectMaximumLockTime.tv_usec = 0; - ftpData->connectionData.rset = ftpData->connectionData.rsetAll; ftpData->connectionData.wset = ftpData->connectionData.wsetAll; ftpData->connectionData.eset = ftpData->connectionData.esetAll; @@ -640,10 +715,11 @@ int evaluateClientSocketConnection(ftpDataType * ftpData) struct sockaddr_in socketRefuse_sockaddr_in; if ((socketRefuseFd = accept(ftpData->connectionData.theMainSocket, (struct sockaddr *)&socketRefuse_sockaddr_in, (socklen_t*)&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); - close(socketRefuseFd); + theReturnCode = close(socketRefuseFd); } return 0; diff --git a/library/connection.c.orig b/library/connection.c.orig new file mode 100644 index 0000000..5d70364 --- /dev/null +++ b/library/connection.c.orig @@ -0,0 +1,733 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../ftpData.h" +#include "connection.h" + +int socketPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __fmt, ...) +{ + #define COMMAND_BUFFER 9600 + #define SOCKET_PRINTF_BUFFER 2048 + int bytesWritten = 0; + char theBuffer[SOCKET_PRINTF_BUFFER]; + char commandBuffer[COMMAND_BUFFER]; + int theStringSize = 0, theCommandSize = 0; + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + memset(&commandBuffer, 0, COMMAND_BUFFER); + printf("\nWriting to socket id %d, TLS %d: ", clientId, ftpData->clients[clientId].tlsIsEnabled); + + pthread_mutex_lock(&ftpData->clients[clientId].writeMutex); + + va_list args; + va_start(args, __fmt); + while (*__fmt != '\0') + { + int i = 0; + theStringSize = 0; + switch(*__fmt) + { + case 'd': + case 'D': + { + int theInteger = va_arg(args, int); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%d", theInteger); + } + break; + + case 'c': + case 'C': + { + int theCharInteger = va_arg(args, int); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%c", theCharInteger); + } + break; + + case 'f': + case 'F': + { + float theDouble = va_arg(args, double); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%f", theDouble); + } + break; + + case 's': + case 'S': + { + char * theString = va_arg(args, char *); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%s", theString); + } + break; + + case 'l': + case 'L': + { + long long int theLongLongInt = va_arg(args, long long int); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%lld", theLongLongInt); + } + break; + + default: + { + printf("\n Switch is default (%c)", *__fmt); + } + break; + } + + for (i = 0; i clients[clientId].tlsIsEnabled != 1) + { + bytesWritten = write(ftpData->clients[clientId].socketDescriptor, commandBuffer, theCommandSize); + } + else if (ftpData->clients[clientId].tlsIsEnabled == 1) + { + #ifdef OPENSSL_ENABLED + bytesWritten = SSL_write(ftpData->clients[clientId].ssl, commandBuffer, theCommandSize); + #endif + } + + printf("\n%s", commandBuffer); + + pthread_mutex_unlock(&ftpData->clients[clientId].writeMutex); + + return bytesWritten; +} + +int socketWorkerPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __fmt, ...) +{ + #define SOCKET_PRINTF_BUFFER 2048 + + int bytesWritten = 0; + char theBuffer[SOCKET_PRINTF_BUFFER]; + int theStringSize = 0; + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + //printf("\nWriting to worker socket id %dd, TLS %d: ", clientId, ftpData->clients[clientId].dataChannelIsTls); + va_list args; + va_start(args, __fmt); + while (*__fmt != '\0') + { + theStringSize = 0; + switch(*__fmt) + { + case 'd': + case 'D': + { + int theInteger = va_arg(args, int); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%d", theInteger); + } + break; + + case 'c': + case 'C': + { + int theCharInteger = va_arg(args, int); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%c", theCharInteger); + } + break; + + case 'f': + case 'F': + { + float theDouble = va_arg(args, double); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%f", theDouble); + } + break; + + case 's': + case 'S': + { + char * theString = va_arg(args, char *); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%s", theString); + } + break; + + case 'l': + case 'L': + { + long long int theLongLongInt = va_arg(args, long long int); + memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); + theStringSize = snprintf(theBuffer, SOCKET_PRINTF_BUFFER, "%lld", theLongLongInt); + } + break; + + default: + { + printf("\n Switch is default (%c)", *__fmt); + } + break; + } + + if (theStringSize >= SOCKET_PRINTF_BUFFER) { + printf("\n String buffer is full!"); + } + else if (theStringSize < SOCKET_PRINTF_BUFFER && + theStringSize > 0) + { + int theReturnCode = 0; + + if (ftpData->clients[clientId].dataChannelIsTls != 1) + { + theReturnCode = write(ftpData->clients[clientId].workerData.socketConnection, theBuffer, theStringSize); + } + else if (ftpData->clients[clientId].dataChannelIsTls == 1) + { + + #ifdef OPENSSL_ENABLED + if (ftpData->clients[clientId].workerData.passiveModeOn == 1){ + theReturnCode = SSL_write(ftpData->clients[clientId].workerData.serverSsl, theBuffer, theStringSize); + printf("%s", theBuffer); + } + else if (ftpData->clients[clientId].workerData.activeModeOn == 1){ + theReturnCode = SSL_write(ftpData->clients[clientId].workerData.clientSsl, theBuffer, theStringSize); + printf("%s", theBuffer); + } + #endif + } + + + + if (theReturnCode > 0) + { + bytesWritten += theReturnCode; + } + else + { + bytesWritten = theReturnCode; + break; + } + } + else if(theStringSize == 0) + { + printf("\n Nothing to write.. "); + } + + ++__fmt; + } + + va_end(args); + return bytesWritten; +} + +/* Return the higher socket available*/ +int getMaximumSocketFd(int mainSocket, ftpDataType * ftpData) +{ + int toReturn = mainSocket; + int i = 0; + + for (i = 0; i < ftpData->ftpParameters.maxClients; i++) + { + if (ftpData->clients[i].socketDescriptor > toReturn) { + toReturn = ftpData->clients[i].socketDescriptor; + } + } + //Must be incremented by one + toReturn++; + return toReturn; +} + +int createSocket(ftpDataType * ftpData) +{ + printf("\nCreating main socket on port %d", ftpData->ftpParameters.port); + int sock, errorCode; + struct sockaddr_in temp; + + //Socket creation + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) + { + return -1; + } + temp.sin_family = AF_INET; + temp.sin_addr.s_addr = INADDR_ANY; + temp.sin_port = htons(ftpData->ftpParameters.port); + + //No blocking socket + errorCode = fcntl(sock, F_SETFL, O_NONBLOCK); + + int reuse = 1; + +#ifdef SO_REUSEADDR + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) + perror("setsockopt(SO_REUSEADDR) failed"); +#endif + +#ifdef SO_REUSEPORT + if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0) + perror("setsockopt(SO_REUSEPORT) failed"); +#endif + //Bind socket + errorCode = bind(sock,(struct sockaddr*) &temp,sizeof(temp)); + if (errorCode == -1) + { + if (sock != -1) + { + close(sock); + } + return -1; + } + + //Number of client allowed + errorCode = listen(sock, ftpData->ftpParameters.maxClients + 1); + if (errorCode == -1) + { + if (sock != -1) + { + close(sock); + } + return -1; + } + + return sock; +} + +int createPassiveSocket(int port) +{ + int sock, returnCode; + struct sockaddr_in temp; + + //Socket creation + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) + { + return -1; + } + + temp.sin_family = AF_INET; + temp.sin_addr.s_addr = INADDR_ANY; + temp.sin_port = htons(port); + + int reuse = 1; + +#ifdef SO_REUSEADDR + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) + perror("setsockopt(SO_REUSEADDR) failed"); +#endif + +#ifdef SO_REUSEPORT + if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0) + perror("setsockopt(SO_REUSEPORT) failed"); +#endif + + //Bind socket + returnCode = bind(sock,(struct sockaddr*) &temp,sizeof(temp)); + + if (returnCode == -1) + { + printf("\n Could not bind %d errno = %d", sock, errno); + + if (sock != -1) + { + close(sock); + } + return returnCode; + } + + //Number of client allowed + returnCode = listen(sock, 1); + + if (returnCode == -1) + { + printf("\n Could not listen %d errno = %d", sock, errno); + if (sock != -1) + { + close(sock); + } + return returnCode; + } + + return sock; +} + +int createActiveSocket(int port, char *ipAddress) +{ + int sockfd; + struct sockaddr_in serv_addr; + + printf("\n Connection socket is going to start ip: %s:%d \n", ipAddress, port); + //sleep(100); + memset(&serv_addr, 0, sizeof(struct sockaddr_in)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(port); + if(inet_pton(AF_INET, ipAddress, &serv_addr.sin_addr)<=0) + { + printf("\n inet_pton error occured\n"); + return -1; + } + + if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + printf("\n2 Error : Could not create socket \n"); + return -1; + } + else + { + printf("\ncreateActiveSocket created socket = %d \n", sockfd); + } + + + int reuse = 1; +#ifdef SO_REUSEADDR + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) + perror("setsockopt(SO_REUSEADDR) failed"); +#endif + +#ifdef SO_REUSEPORT + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0) + perror("setsockopt(SO_REUSEPORT) failed"); +#endif + + + if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + { + printf("\n3 Error : Connect Failed \n"); + + if (sockfd != -1) + { + close(sockfd); + } + + return -1; + } + + printf("\n Connection socket %d is going to start ip: %s:%d \n",sockfd, ipAddress, port); + + return sockfd; +} + +void fdInit(ftpDataType * ftpData) +{ + FD_ZERO(&ftpData->connectionData.rset); + FD_ZERO(&ftpData->connectionData.wset); + FD_ZERO(&ftpData->connectionData.eset); + FD_ZERO(&ftpData->connectionData.rsetAll); + FD_ZERO(&ftpData->connectionData.wsetAll); + FD_ZERO(&ftpData->connectionData.esetAll); + + FD_SET(ftpData->connectionData.theMainSocket, &ftpData->connectionData.rsetAll); + FD_SET(ftpData->connectionData.theMainSocket, &ftpData->connectionData.wsetAll); + FD_SET(ftpData->connectionData.theMainSocket, &ftpData->connectionData.esetAll); +} + +void fdAdd(ftpDataType * ftpData, int index) +{ + FD_SET(ftpData->clients[index].socketDescriptor, &ftpData->connectionData.rsetAll); + FD_SET(ftpData->clients[index].socketDescriptor, &ftpData->connectionData.wsetAll); + FD_SET(ftpData->clients[index].socketDescriptor, &ftpData->connectionData.esetAll); + ftpData->connectionData.maxSocketFD = getMaximumSocketFd(ftpData->connectionData.theMainSocket, ftpData) + 1; +} + +void fdRemove(ftpDataType * ftpData, int index) +{ + FD_CLR(ftpData->clients[index].socketDescriptor, &ftpData->connectionData.rsetAll); + FD_CLR(ftpData->clients[index].socketDescriptor, &ftpData->connectionData.wsetAll); + FD_CLR(ftpData->clients[index].socketDescriptor, &ftpData->connectionData.esetAll); +} + +void closeSocket(ftpDataType * ftpData, int processingSocket) +{ + int theReturnCode = 0; + +#ifdef OPENSSL_ENABLED + /* + if (ftpData->clients[processingSocket].dataChannelIsTls == 1) + { + if(ftpData->clients[processingSocket].workerData.passiveModeOn == 1) + { + + printf("\nSSL worker Shutdown 1"); + returnCode = SSL_shutdown(ftpData->clients[processingSocket].ssl); + printf("\nnSSL worker Shutdown 1 return code : %d", returnCode); + + if (returnCode < 0) + { + printf("SSL_shutdown failed return code %d", returnCode); + } + else if (returnCode == 0) + { + printf("\nSSL worker Shutdown 2"); + returnCode = SSL_shutdown(ftpData->clients[processingSocket].ssl); + printf("\nnSSL worker Shutdown 2 return code : %d", returnCode); + + if (returnCode <= 0) + { + printf("SSL_shutdown (2nd time) failed"); + } + } + } + }*/ +#endif + + //Close the socket + shutdown(ftpData->clients[processingSocket].socketDescriptor, SHUT_RDWR); + theReturnCode = close(ftpData->clients[processingSocket].socketDescriptor); + + resetClientData(ftpData, processingSocket, 0); + resetWorkerData(ftpData, processingSocket, 0); + + //Update client connecteds + ftpData->connectedClients--; + if (ftpData->connectedClients < 0) + { + ftpData->connectedClients = 0; + } + + printf("Client id: %d disconnected", processingSocket); + printf("\nServer: Clients connected:%d", ftpData->connectedClients); + return; +} + +void closeClient(ftpDataType * ftpData, int processingSocket) +{ + printf("\nQUIT FLAG SET!\n"); + + if (ftpData->clients[processingSocket].workerData.threadIsAlive == 1) + { +<<<<<<< HEAD + +======= +>>>>>>> master + pthread_cancel(ftpData->clients[processingSocket].workerData.workerThread); + printf("\nQuit command received the Pasv Thread has been cancelled."); + } + + FD_CLR(ftpData->clients[processingSocket].socketDescriptor, &ftpData->connectionData.rsetAll); + FD_CLR(ftpData->clients[processingSocket].socketDescriptor, &ftpData->connectionData.wsetAll); + FD_CLR(ftpData->clients[processingSocket].socketDescriptor, &ftpData->connectionData.esetAll); + + closeSocket(ftpData, processingSocket); + + ftpData->connectionData.maxSocketFD = ftpData->connectionData.theMainSocket+1; + ftpData->connectionData.maxSocketFD = getMaximumSocketFd(ftpData->connectionData.theMainSocket, ftpData) + 1; + return; +} + +void checkClientConnectionTimeout(ftpDataType * ftpData) +{ + int processingSock; + for (processingSock = 0; processingSock < ftpData->ftpParameters.maxClients; processingSock++) + { + /* No connection active*/ + if (ftpData->clients[processingSock].socketDescriptor < 0 || + ftpData->clients[processingSock].socketIsConnected == 0) + { + continue; + } + + /* Max idle time check, close the connection if time is elapsed */ + if (ftpData->ftpParameters.maximumIdleInactivity != 0 && + (int)time(NULL) - ftpData->clients[processingSock].lastActivityTimeStamp > ftpData->ftpParameters.maximumIdleInactivity) + { + ftpData->clients[processingSock].closeTheClient = 1; + } + } +} + +void flushLoginWrongTriesData(ftpDataType * ftpData) +{ + int i; + //printf("\n flushLoginWrongTriesData size of the vector : %d", ftpData->loginFailsVector.Size); + + for (i = (ftpData->loginFailsVector.Size-1); i >= 0; i--) + { + //printf("\n last login fail attempt : %d", ((loginFailsDataType *) ftpData->loginFailsVector.Data[i])->failTimeStamp); + + if ( (time(NULL) - ((loginFailsDataType *) ftpData->loginFailsVector.Data[i])->failTimeStamp) > WRONG_PASSWORD_ALLOWED_RETRY_TIME) + { + //printf("\n Deleting element : %d", i); + ftpData->loginFailsVector.DeleteAt(&ftpData->loginFailsVector, i, deleteLoginFailsData); + } + } +} + +int selectWait(ftpDataType * ftpData) +{ + struct timeval selectMaximumLockTime; + selectMaximumLockTime.tv_sec = 10; + selectMaximumLockTime.tv_usec = 0; + ftpData->connectionData.rset = ftpData->connectionData.rsetAll; + ftpData->connectionData.wset = ftpData->connectionData.wsetAll; + ftpData->connectionData.eset = ftpData->connectionData.esetAll; + return select(ftpData->connectionData.maxSocketFD, &ftpData->connectionData.rset, NULL, &ftpData->connectionData.eset, &selectMaximumLockTime); +} + +int isClientConnected(ftpDataType * ftpData, int cliendId) +{ + if (ftpData->clients[cliendId].socketDescriptor < 0 || + ftpData->clients[cliendId].socketIsConnected == 0) + { + return 0; + } + + return 1; +} + +int getAvailableClientSocketIndex(ftpDataType * ftpData) +{ + int socketIndex; + for (socketIndex = 0; socketIndex < ftpData->ftpParameters.maxClients; socketIndex++) + { + if (isClientConnected(ftpData, socketIndex) == 0) + { + return socketIndex; + } + } + + /* no socket are available for a new client connection */ + return -1; +} + +int evaluateClientSocketConnection(ftpDataType * ftpData) +{ + 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); + + error = getsockname(ftpData->clients[availableSocketIndex].socketDescriptor, (struct sockaddr *)&ftpData->clients[availableSocketIndex].server_sockaddr_in, (socklen_t*)&ftpData->clients[availableSocketIndex].sockaddr_in_server_size); + inet_ntop(AF_INET, + &(ftpData->clients[availableSocketIndex].server_sockaddr_in.sin_addr), + ftpData->clients[availableSocketIndex].serverIpAddress, + INET_ADDRSTRLEN); + printf("\n Server IP: %s", ftpData->clients[availableSocketIndex].serverIpAddress); + printf("Server: New client connected with id: %d", availableSocketIndex); + printf("\nServer: Clients connected: %d", ftpData->connectedClients); + sscanf (ftpData->clients[availableSocketIndex].serverIpAddress,"%d.%d.%d.%d", &ftpData->clients[availableSocketIndex].serverIpAddressInteger[0], + &ftpData->clients[availableSocketIndex].serverIpAddressInteger[1], + &ftpData->clients[availableSocketIndex].serverIpAddressInteger[2], + &ftpData->clients[availableSocketIndex].serverIpAddressInteger[3]); + + inet_ntop(AF_INET, + &(ftpData->clients[availableSocketIndex].client_sockaddr_in.sin_addr), + ftpData->clients[availableSocketIndex].clientIpAddress, + INET_ADDRSTRLEN); + printf("\n Client IP: %s", ftpData->clients[availableSocketIndex].clientIpAddress); + ftpData->clients[availableSocketIndex].clientPort = (int) ntohs(ftpData->clients[availableSocketIndex].client_sockaddr_in.sin_port); + printf("\nClient port is: %d\n", ftpData->clients[availableSocketIndex].clientPort); + + ftpData->clients[availableSocketIndex].connectionTimeStamp = (int)time(NULL); + ftpData->clients[availableSocketIndex].lastActivityTimeStamp = (int)time(NULL); + + for (i = 0; i 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; + } + else + { + int returnCode = socketPrintf(ftpData, availableSocketIndex, "s", ftpData->welcomeMessage); + if (returnCode <= 0) + { + ftpData->clients[availableSocketIndex].closeTheClient = 1; + } + } + + return 1; + } + else + { + //Errors while accepting, socket will be closed + ftpData->clients[availableSocketIndex].closeTheClient = 1; + printf("\n2 Errno = %d", errno); + return 1; + } + } + else + { + int socketRefuseFd, socketRefuse_in_size; + socketRefuse_in_size = sizeof(struct sockaddr_in); + struct sockaddr_in socketRefuse_sockaddr_in; + if ((socketRefuseFd = accept(ftpData->connectionData.theMainSocket, (struct sockaddr *)&socketRefuse_sockaddr_in, (socklen_t*)&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; + } +} diff --git a/library/fileManagement.c b/library/fileManagement.c index f9c24ed..38d0db2 100644 --- a/library/fileManagement.c +++ b/library/fileManagement.c @@ -22,10 +22,6 @@ * THE SOFTWARE. */ - - - - #include #include #include @@ -37,6 +33,7 @@ #include #include #include +#include #include "fileManagement.h" #include "dynamicVectors.h" @@ -59,6 +56,11 @@ static int FILE_CompareStringParameter(const void * a, const void * b) return strcmp(typeA->Name, typeB->Name); } +int FILE_fdIsValid(int fd) +{ + return fcntl(fd, F_GETFD); +} + /* Check if inode is a directory */ int FILE_IsDirectory(char *DirectoryPath) { @@ -719,3 +721,57 @@ gid_t FILE_getGID(const char *group_name) return grp->gr_gid; } + + +void FILE_checkAllOpenedFD(void) +{ + int openedFd = 0, i,ret; + + struct rlimit rl; + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) + printf("%s: can’t get file limit", ""); + + if (rl.rlim_max == RLIM_INFINITY) + rl.rlim_max = 1024; + + for (i = 0; i < rl.rlim_max; i++) + { + ret = FILE_fdIsValid(i); + //printf("\nret = %d", ret); + if (ret != -1) + { + struct stat statbuf; + fstat(i, &statbuf); + if (S_ISSOCK(statbuf.st_mode)) + { + printf("\n fd %d is socket", i); + } + else if (S_ISDIR(statbuf.st_mode)) + { + printf("\n fd %d is dir", i); + } + + /* + else if (S_ISSOCK(statbuf.st_mode)) + { + printf("\n fd %d is socket", fd); + } + else if (S_ISSOCK(statbuf.st_mode)) + { + printf("\n fd %d is socket", fd); + } + else if (S_ISSOCK(statbuf.st_mode)) + { + printf("\n fd %d is socket", fd); + } + else if (S_ISSOCK(statbuf.st_mode)) + { + printf("\n fd %d is socket", fd); + } + */ + + openedFd++; + } + } + printf("\n\nOpened fd : %d", openedFd); +} diff --git a/library/fileManagement.h b/library/fileManagement.h index 06ff676..8d034ac 100644 --- a/library/fileManagement.h +++ b/library/fileManagement.h @@ -71,5 +71,7 @@ int FILE_doChownFromUidGid(const char *file_path, uid_t uid, gid_t gid); uid_t FILE_getUID(const char *user_name); gid_t FILE_getGID(const char *group_name); + void FILE_checkAllOpenedFD(void); + int fd_is_valid(int fd); #define GEN_FILE_MANAGEMENT_TYPES #endif diff --git a/uftpd.cfg b/uftpd.cfg index 04c1325..463e9ba 100644 --- a/uftpd.cfg +++ b/uftpd.cfg @@ -10,7 +10,7 @@ MAXIMUM_ALLOWED_FTP_CONNECTION = 30 FTP_PORT = 21 #TCP/IP PORT SETTINGS (DEFAULT 21) -SINGLE_INSTANCE = true +SINGLE_INSTANCE = false #Allow only one server instance (true or false) DAEMON_MODE = false