This commit is contained in:
Ugo Cirmignani
2018-12-25 11:51:33 +01:00
19 changed files with 1659 additions and 21 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
build/uFTP.orig Executable file

Binary file not shown.

View File

@ -379,8 +379,10 @@ int parseCommandProt(ftpDataType * data, int socketId)
int parseCommandCcc(ftpDataType * data, int socketId) int parseCommandCcc(ftpDataType * data, int socketId)
{ {
#ifdef OPENSSL_ENABLED
int returnCode; int returnCode;
#ifdef OPENSSL_ENABLED
returnCode = socketPrintf(data, socketId, "s", "200 TLS connection aborted\r\n"); returnCode = socketPrintf(data, socketId, "s", "200 TLS connection aborted\r\n");
SSL_set_shutdown(data->clients[socketId].ssl, SSL_SENT_SHUTDOWN); SSL_set_shutdown(data->clients[socketId].ssl, SSL_SENT_SHUTDOWN);
data->clients[socketId].tlsIsEnabled = 0; data->clients[socketId].tlsIsEnabled = 0;
@ -389,7 +391,7 @@ int parseCommandCcc(ftpDataType * data, int socketId)
return FTP_COMMAND_PROCESSED_WRITE_ERROR; return FTP_COMMAND_PROCESSED_WRITE_ERROR;
#endif #endif
#ifdef OPENSSL_ENABLED #ifndef OPENSSL_ENABLED
returnCode = socketPrintf(data, socketId, "s", "500 command not supported\r\n"); returnCode = socketPrintf(data, socketId, "s", "500 command not supported\r\n");
if (returnCode <= 0) if (returnCode <= 0)

View File

@ -91,8 +91,6 @@ void setDynamicStringDataType(dynamicStringDataType *dynamicString, char *theStr
memcpy(dynamicString->text, theString, stringLen); memcpy(dynamicString->text, theString, stringLen);
dynamicString->textLen = stringLen; dynamicString->textLen = stringLen;
} }
//printf("\ndynamicString->text = %lld", dynamicString->text);
} }
int getSafePath(dynamicStringDataType *safePath, char *theDirectoryName, loginDataType *loginData, DYNMEM_MemoryTable_DataType **memoryTable) 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) void resetClientData(ftpDataType *data, int clientId, int isInitialization)
{ {
if (isInitialization != 1) if (isInitialization != 1)
{ {
if (data->clients[clientId].workerData.threadIsAlive == 1) if (data->clients[clientId].workerData.threadIsAlive == 1)
pthread_cancel(data->clients[clientId].workerData.workerThread); pthread_cancel(data->clients[clientId].workerData.workerThread);

769
ftpData.c.orig Normal file
View File

@ -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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <netinet/in.h>
#include <unistd.h>
#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 (theDirectoryToCheckIndex<STRING_SIZE)
{
theDirectoryToCheck[theDirectoryToCheckIndex++] = theDirectoryName[i];
}
else
return 0; /* Directory size too long */
}
if (theDirectoryName[0] == '/')
{
while (theDirectoryNamePointer[0] == '/')
theDirectoryNamePointer++;
//printf("\nMemory data address 2nd call : %lld", memoryTable);
setDynamicStringDataType(safePath, loginData->homePath.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 <stringLenght; i++)
{
stringInIndex = isCharInString(alfaUpperCase, strlen(alfaUpperCase), stringIn[i]);
if (stringInIndex == -1)
{
stringInIndex = isCharInString(alfaLowerCase, strlen(alfaLowerCase), stringIn[i]);
}
stringRefIndex = isCharInString(alfaUpperCase, strlen(alfaUpperCase), stringRef[i]);
if (stringRefIndex == -1)
{
stringRefIndex = isCharInString(alfaLowerCase, strlen(alfaLowerCase), stringRef[i]);
}
if (stringRefIndex == -1 || stringInIndex == -1)
{
return 0;
}
if (stringRefIndex != stringInIndex)
{
return 0;
}
}
return 1;
}
int isCharInString(char *theString, int stringLen, char theChar)
{
int i;
for (i = 0; i < stringLen; i++)
{
if (theString[i] == theChar)
{
return i;
}
}
return -1;
}

View File

@ -111,8 +111,8 @@ void workerCleanup(void *socketId)
shutdown(ftpData.clients[theSocketId].workerData.socketConnection, SHUT_RDWR); shutdown(ftpData.clients[theSocketId].workerData.socketConnection, SHUT_RDWR);
shutdown(ftpData.clients[theSocketId].workerData.passiveListeningSocket, SHUT_RDWR); shutdown(ftpData.clients[theSocketId].workerData.passiveListeningSocket, SHUT_RDWR);
close(ftpData.clients[theSocketId].workerData.socketConnection); returnCode = close(ftpData.clients[theSocketId].workerData.socketConnection);
close(ftpData.clients[theSocketId].workerData.passiveListeningSocket); returnCode = close(ftpData.clients[theSocketId].workerData.passiveListeningSocket);
resetWorkerData(&ftpData, theSocketId, 0); resetWorkerData(&ftpData, theSocketId, 0);
printf("\nWorker cleaned!"); printf("\nWorker cleaned!");
} }
@ -342,7 +342,9 @@ void *connectionWorkerHandle(void * socketId)
break; break;
} }
} }
fclose(ftpData.clients[theSocketId].workerData.theStorFile);
int theReturnCode;
theReturnCode = fclose(ftpData.clients[theSocketId].workerData.theStorFile);
ftpData.clients[theSocketId].workerData.theStorFile = NULL; ftpData.clients[theSocketId].workerData.theStorFile = NULL;
if (ftpData.clients[theSocketId].login.ownerShip.ownerShipSet == 1) if (ftpData.clients[theSocketId].login.ownerShip.ownerShipSet == 1)

View File

@ -291,6 +291,10 @@ int createSocket(ftpDataType * ftpData)
//Socket creation //Socket creation
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
return -1;
}
temp.sin_family = AF_INET; temp.sin_family = AF_INET;
temp.sin_addr.s_addr = INADDR_ANY; temp.sin_addr.s_addr = INADDR_ANY;
temp.sin_port = htons(ftpData->ftpParameters.port); temp.sin_port = htons(ftpData->ftpParameters.port);
@ -311,9 +315,25 @@ int createSocket(ftpDataType * ftpData)
#endif #endif
//Bind socket //Bind socket
errorCode = bind(sock,(struct sockaddr*) &temp,sizeof(temp)); errorCode = bind(sock,(struct sockaddr*) &temp,sizeof(temp));
if (errorCode == -1)
{
if (sock != -1)
{
close(sock);
}
return -1;
}
//Number of client allowed //Number of client allowed
errorCode = listen(sock, ftpData->ftpParameters.maxClients + 1); errorCode = listen(sock, ftpData->ftpParameters.maxClients + 1);
if (errorCode == -1)
{
if (sock != -1)
{
close(sock);
}
return -1;
}
return sock; return sock;
} }
@ -325,6 +345,11 @@ int createPassiveSocket(int port)
//Socket creation //Socket creation
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
return -1;
}
temp.sin_family = AF_INET; temp.sin_family = AF_INET;
temp.sin_addr.s_addr = INADDR_ANY; temp.sin_addr.s_addr = INADDR_ANY;
temp.sin_port = htons(port); temp.sin_port = htons(port);
@ -345,13 +370,28 @@ int createPassiveSocket(int port)
returnCode = bind(sock,(struct sockaddr*) &temp,sizeof(temp)); returnCode = bind(sock,(struct sockaddr*) &temp,sizeof(temp));
if (returnCode == -1) if (returnCode == -1)
{
printf("\n Could not bind %d errno = %d", sock, errno);
if (sock != -1)
{
close(sock);
}
return returnCode; return returnCode;
}
//Number of client allowed //Number of client allowed
returnCode = listen(sock, 1); returnCode = listen(sock, 1);
if (returnCode == -1) if (returnCode == -1)
{
printf("\n Could not listen %d errno = %d", sock, errno);
if (sock != -1)
{
close(sock);
}
return returnCode; return returnCode;
}
return sock; return sock;
} }
@ -379,7 +419,7 @@ int createActiveSocket(int port, char *ipAddress)
} }
else 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) if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{ {
printf("\n3 Error : Connect Failed \n"); printf("\n3 Error : Connect Failed \n");
if (sockfd != -1)
{
close(sockfd);
}
return -1; return -1;
} }
@ -437,9 +483,41 @@ void fdRemove(ftpDataType * ftpData, int index)
void closeSocket(ftpDataType * ftpData, int processingSocket) 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 //Close the socket
shutdown(ftpData->clients[processingSocket].socketDescriptor, SHUT_RDWR); shutdown(ftpData->clients[processingSocket].socketDescriptor, SHUT_RDWR);
close(ftpData->clients[processingSocket].socketDescriptor); theReturnCode = close(ftpData->clients[processingSocket].socketDescriptor);
resetClientData(ftpData, processingSocket, 0); resetClientData(ftpData, processingSocket, 0);
resetWorkerData(ftpData, processingSocket, 0); resetWorkerData(ftpData, processingSocket, 0);
@ -462,9 +540,7 @@ void closeClient(ftpDataType * ftpData, int processingSocket)
if (ftpData->clients[processingSocket].workerData.threadIsAlive == 1) if (ftpData->clients[processingSocket].workerData.threadIsAlive == 1)
{ {
pthread_cancel(ftpData->clients[processingSocket].workerData.workerThread); 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."); printf("\nQuit command received the Pasv Thread has been cancelled.");
} }
@ -522,7 +598,6 @@ int selectWait(ftpDataType * ftpData)
struct timeval selectMaximumLockTime; struct timeval selectMaximumLockTime;
selectMaximumLockTime.tv_sec = 10; selectMaximumLockTime.tv_sec = 10;
selectMaximumLockTime.tv_usec = 0; selectMaximumLockTime.tv_usec = 0;
ftpData->connectionData.rset = ftpData->connectionData.rsetAll; ftpData->connectionData.rset = ftpData->connectionData.rsetAll;
ftpData->connectionData.wset = ftpData->connectionData.wsetAll; ftpData->connectionData.wset = ftpData->connectionData.wsetAll;
ftpData->connectionData.eset = ftpData->connectionData.esetAll; ftpData->connectionData.eset = ftpData->connectionData.esetAll;
@ -640,10 +715,11 @@ int evaluateClientSocketConnection(ftpDataType * ftpData)
struct sockaddr_in socketRefuse_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) 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"; char *messageToWrite = "10068 Server reached the maximum number of connection, please try later.\r\n";
write(socketRefuseFd, messageToWrite, strlen(messageToWrite)); write(socketRefuseFd, messageToWrite, strlen(messageToWrite));
shutdown(socketRefuseFd, SHUT_RDWR); shutdown(socketRefuseFd, SHUT_RDWR);
close(socketRefuseFd); theReturnCode = close(socketRefuseFd);
} }
return 0; return 0;

733
library/connection.c.orig Normal file
View File

@ -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 <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdarg.h>
#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 <theStringSize; i++)
{
if (theCommandSize < COMMAND_BUFFER)
{
commandBuffer[theCommandSize++] = theBuffer[i];
}
}
++__fmt;
}
va_end(args);
if (ftpData->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 <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;
}
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;
}
}

View File

@ -22,10 +22,6 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
#include <stdio.h> #include <stdio.h>
@ -37,6 +33,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/resource.h>
#include "fileManagement.h" #include "fileManagement.h"
#include "dynamicVectors.h" #include "dynamicVectors.h"
@ -59,6 +56,11 @@ static int FILE_CompareStringParameter(const void * a, const void * b)
return strcmp(typeA->Name, typeB->Name); return strcmp(typeA->Name, typeB->Name);
} }
int FILE_fdIsValid(int fd)
{
return fcntl(fd, F_GETFD);
}
/* Check if inode is a directory */ /* Check if inode is a directory */
int FILE_IsDirectory(char *DirectoryPath) int FILE_IsDirectory(char *DirectoryPath)
{ {
@ -719,3 +721,57 @@ gid_t FILE_getGID(const char *group_name)
return grp->gr_gid; return grp->gr_gid;
} }
void FILE_checkAllOpenedFD(void)
{
int openedFd = 0, i,ret;
struct rlimit rl;
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
printf("%s: cant 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);
}

View File

@ -71,5 +71,7 @@
int FILE_doChownFromUidGid(const char *file_path, uid_t uid, gid_t gid); int FILE_doChownFromUidGid(const char *file_path, uid_t uid, gid_t gid);
uid_t FILE_getUID(const char *user_name); uid_t FILE_getUID(const char *user_name);
gid_t FILE_getGID(const char *group_name); gid_t FILE_getGID(const char *group_name);
void FILE_checkAllOpenedFD(void);
int fd_is_valid(int fd);
#define GEN_FILE_MANAGEMENT_TYPES #define GEN_FILE_MANAGEMENT_TYPES
#endif #endif

View File

@ -10,7 +10,7 @@ MAXIMUM_ALLOWED_FTP_CONNECTION = 30
FTP_PORT = 21 FTP_PORT = 21
#TCP/IP PORT SETTINGS (DEFAULT 21) #TCP/IP PORT SETTINGS (DEFAULT 21)
SINGLE_INSTANCE = true SINGLE_INSTANCE = false
#Allow only one server instance (true or false) #Allow only one server instance (true or false)
DAEMON_MODE = false DAEMON_MODE = false