diff --git a/Makefile b/Makefile index 82c5dbd..cb666b0 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ OPTIMIZATION=-O3 HEADERS=-I LIBPATH=./build/modules/ BUILDFILES=start uFTP end -LIBS=-lpthread -lssl -lcrypto +#LIBS=-lpthread -lssl -lcrypto #ENABLE_LARGE_FILE_SUPPORT= @@ -19,8 +19,9 @@ LIBS=-lpthread -lssl -lcrypto ENABLE_LARGE_FILE_SUPPORT=-D LARGE_FILE_SUPPORT_ENABLED -D _LARGEFILE64_SOURCE #ENABLE_OPENSSL_SUPPORT= -#TO ENABLE OPENSSL SUPPORT UNCOMMENT THE NEXT LINE +#TO ENABLE OPENSSL SUPPORT UNCOMMENT NEXT 2 LINES ENABLE_OPENSSL_SUPPORT=-D OPENSSL_ENABLED +LIBS=-lpthread -lssl -lcrypto CFLAGS=$(CFLAGSTEMP) $(ENABLE_LARGE_FILE_SUPPORT) $(ENABLE_OPENSSL_SUPPORT) @@ -32,7 +33,7 @@ start: @echo CGI FILES: $(BUILDFILES) @rm -rf $(LIBPATH)*.o $(OUTPATH)uFTP @echo "Clean ok" - + end: @echo Build process end diff --git a/build/modules/configRead.o b/build/modules/configRead.o index 9988b76..f3564f6 100644 Binary files a/build/modules/configRead.o and b/build/modules/configRead.o differ diff --git a/build/modules/connection.o b/build/modules/connection.o index 62c0fac..f4273e9 100644 Binary files a/build/modules/connection.o and b/build/modules/connection.o differ diff --git a/build/modules/daemon.o b/build/modules/daemon.o index 1ac5dd6..d372df3 100644 Binary files a/build/modules/daemon.o and b/build/modules/daemon.o differ diff --git a/build/modules/fileManagement.o b/build/modules/fileManagement.o index 472014a..2dde5a0 100644 Binary files a/build/modules/fileManagement.o and b/build/modules/fileManagement.o differ diff --git a/build/modules/ftpCommandElaborate.o b/build/modules/ftpCommandElaborate.o index 43f07d5..4a73754 100644 Binary files a/build/modules/ftpCommandElaborate.o and b/build/modules/ftpCommandElaborate.o differ diff --git a/build/modules/ftpData.o b/build/modules/ftpData.o index 7e77937..edbf6e8 100644 Binary files a/build/modules/ftpData.o and b/build/modules/ftpData.o differ diff --git a/build/modules/ftpServer.o b/build/modules/ftpServer.o index 46125a5..59d273e 100644 Binary files a/build/modules/ftpServer.o and b/build/modules/ftpServer.o differ diff --git a/build/modules/openSsl.o b/build/modules/openSsl.o index b09b4bb..e67667f 100644 Binary files a/build/modules/openSsl.o and b/build/modules/openSsl.o differ diff --git a/build/uFTP b/build/uFTP index e611b60..410b758 100755 Binary files a/build/uFTP and b/build/uFTP differ diff --git a/ftpCommandElaborate.c b/ftpCommandElaborate.c index f49f7c6..8dafffc 100644 --- a/ftpCommandElaborate.c +++ b/ftpCommandElaborate.c @@ -220,56 +220,42 @@ int parseCommandPass(ftpDataType * data, int socketId) int parseCommandAuth(ftpDataType * data, int socketId) { - int returnCode; + int returnCode, returnCodeTls; #ifndef OPENSSL_ENABLED returnCode = socketPrintf(data, socketId, "s", "502 Security extensions not implemented.\r\n"); if (returnCode <= 0) return FTP_COMMAND_PROCESSED_WRITE_ERROR; - - return FTP_COMMAND_PROCESSED; #endif #ifdef OPENSSL_ENABLED + returnCode = socketPrintf(data, socketId, "s", "234 AUTH TLS OK..\r\n"); if (returnCode <= 0) return FTP_COMMAND_PROCESSED_WRITE_ERROR; - data->clients[socketId].tlsIsEnabled = 1; + returnCode = SSL_set_fd(data->clients[socketId].ssl, data->clients[socketId].socketDescriptor); - printf("\n SSL_set_fd"); - fflush(0); + if (returnCode == 0) + { + return FTP_COMMAND_PROCESSED_WRITE_ERROR; + } - SSL_set_fd(data->clients[socketId].ssl, data->clients[socketId].socketDescriptor); + returnCodeTls = SSL_accept(data->clients[socketId].ssl); + data->clients[socketId].tlsNegotiatingTimeStart = (int)time(NULL); - printf("\n SSL_set_fd OK"); - fflush(0); - - int sslAcceptTimeout = 0; - do { - returnCode = SSL_accept(data->clients[socketId].ssl); - - printf("\n SSL_accept"); - fflush(0); - - printf("\nSSL waiting handshake %d.. return code = %d", sslAcceptTimeout, returnCode); - fflush(0); - if (returnCode <= 0) { - printf("\nSSL ERRORS"); - fflush(0); - ERR_print_errors_fp(stderr); - } - else { - printf("\nSSL ACCEPTED"); - fflush(0); - } - sslAcceptTimeout++; - sleep(1); - } - while(returnCode <=0 && - sslAcceptTimeout < 3); - - return FTP_COMMAND_PROCESSED; + if (returnCodeTls <= 0) + { + printf("\nSSL NOT YET ACCEPTED: %d", returnCodeTls); + data->clients[socketId].tlsIsEnabled = 0; + data->clients[socketId].tlsIsNegotiating = 1; + } + else + { + printf("\nSSL ACCEPTED"); + data->clients[socketId].tlsIsEnabled = 1; + data->clients[socketId].tlsIsNegotiating = 0; + } #endif @@ -343,10 +329,15 @@ int parseCommandFeat(ftpDataType * data, int socketId) SPSV ESTP 211 End. - */ + int returnCode; - returnCode = socketPrintf(data, socketId, "s", "211-Extensions supported:\r\n PASV\r\nUTF8\r\nAUTH TLS\r\nPBSZ\r\nPROT\r\n211 End.\r\n"); + #ifdef OPENSSL_ENABLED + returnCode = socketPrintf(data, socketId, "s", "211-Extensions supported:\r\nPASV\r\nUTF8\r\nAUTH TLS\r\nPBSZ\r\nPROT\r\n211 End.\r\n"); + #endif + #ifndef OPENSSL_ENABLED + returnCode = socketPrintf(data, socketId, "s", "211-Extensions supported:\r\nPASV\r\nUTF8\r\n211 End.\r\n"); + #endif if (returnCode <= 0) return FTP_COMMAND_PROCESSED_WRITE_ERROR; @@ -395,9 +386,16 @@ int parseCommandCcc(ftpDataType * data, int socketId) if (returnCode <= 0) return FTP_COMMAND_PROCESSED_WRITE_ERROR; + #endif + + #ifdef OPENSSL_ENABLED + returnCode = socketPrintf(data, socketId, "s", "500 command not supported\r\n"); + + if (returnCode <= 0) + return FTP_COMMAND_PROCESSED_WRITE_ERROR; + #endif return FTP_COMMAND_PROCESSED; - #endif } int parseCommandPbsz(ftpDataType * data, int socketId) @@ -461,7 +459,7 @@ int parseCommandPasv(ftpDataType * data, int socketId) /* Create worker thread */ void *pReturn; int returnCode; - printf("\n data->clients[%d].workerData.workerThread = %d",socketId, (int)data->clients[socketId].workerData.workerThread); + //printf("\n data->clients[%d].workerData.workerThread = %d",socketId, (int)data->clients[socketId].workerData.workerThread); if (data->clients[socketId].workerData.threadIsAlive == 1) { @@ -491,7 +489,7 @@ int parseCommandPort(ftpDataType * data, int socketId) theIpAndPort = getFtpCommandArg("PORT", data->clients[socketId].theCommandReceived, 0); sscanf(theIpAndPort, "%d,%d,%d,%d,%d,%d", &ipAddressBytes[0], &ipAddressBytes[1], &ipAddressBytes[2], &ipAddressBytes[3], &portBytes[0], &portBytes[1]); data->clients[socketId].workerData.connectionPort = (portBytes[0]*256)+portBytes[1]; - sprintf(data->clients[socketId].workerData.activeIpAddress, "%d.%d.%d.%d", ipAddressBytes[0],ipAddressBytes[1],ipAddressBytes[2],ipAddressBytes[3]); + returnCode = snprintf(data->clients[socketId].workerData.activeIpAddress, CLIENT_BUFFER_STRING_SIZE, "%d.%d.%d.%d", ipAddressBytes[0],ipAddressBytes[1],ipAddressBytes[2],ipAddressBytes[3]); void *pReturn; if (data->clients[socketId].workerData.threadIsAlive == 1) @@ -574,9 +572,9 @@ int parseCommandList(ftpDataType * data, int socketId) theNameToList = getFtpCommandArg("LIST", data->clients[socketId].theCommandReceived, 1); getFtpCommandArgWithOptions("LIST", data->clients[socketId].theCommandReceived, &data->clients[socketId].workerData.ftpCommand); - printf("\nLIST COMMAND ARG: %s", data->clients[socketId].workerData.ftpCommand.commandArgs.text); - printf("\nLIST COMMAND OPS: %s", data->clients[socketId].workerData.ftpCommand.commandOps.text); - printf("\ntheNameToList: %s", theNameToList); + ///printf("\nLIST COMMAND ARG: %s", data->clients[socketId].workerData.ftpCommand.commandArgs.text); + //printf("\nLIST COMMAND OPS: %s", data->clients[socketId].workerData.ftpCommand.commandOps.text); + //printf("\ntheNameToList: %s", theNameToList); cleanDynamicStringDataType(&data->clients[socketId].workerData.ftpCommand.commandArgs, 0); cleanDynamicStringDataType(&data->clients[socketId].workerData.ftpCommand.commandOps, 0); @@ -714,7 +712,7 @@ int parseCommandCwd(ftpDataType * data, int socketId) if (isSafePath == 1) { - printf("\n The Path requested for CWD IS:%s", theSafePath.text); + //printf("\n The Path requested for CWD IS:%s", theSafePath.text); setDynamicStringDataType(&absolutePathPrevious, data->clients[socketId].login.absolutePath.text, data->clients[socketId].login.absolutePath.textLen); setDynamicStringDataType(&ftpPathPrevious, data->clients[socketId].login.ftpPath.text, data->clients[socketId].login.ftpPath.textLen); @@ -1235,7 +1233,13 @@ long long int writeRetrFile(ftpDataType * data, int theSocketId, long long int s } else { - writtenSize = SSL_write(data->clients[theSocketId].workerData.ssl, buffer, readen); + + #ifdef OPENSSL_ENABLED + if (data->clients[theSocketId].workerData.passiveModeOn == 1) + writtenSize = SSL_write(data->clients[theSocketId].workerData.serverSsl, buffer, readen); + else if (data->clients[theSocketId].workerData.activeModeOn == 1) + writtenSize = SSL_write(data->clients[theSocketId].workerData.clientSsl, buffer, readen); + #endif } if (writtenSize <= 0) @@ -1364,6 +1368,7 @@ int getFtpCommandArgWithOptions(char * theCommand, char *theCommandString, ftpCo int setPermissions(char * permissionsCommand, char * basePath, ownerShip_DataType ownerShip) { + #define MAXIMUM_FILENAME_LEN 4096 #define STATUS_INCREASE 0 #define STATUS_PERMISSIONS 1 #define STATUS_LOCAL_PATH 2 @@ -1372,14 +1377,14 @@ int setPermissions(char * permissionsCommand, char * basePath, ownerShip_DataTyp int returnCode = 0; int status = STATUS_INCREASE; - char thePermissionString[1024]; - char theLocalPath[1024]; - char theFinalFilename[2048]; + char thePermissionString[MAXIMUM_FILENAME_LEN]; + char theLocalPath[MAXIMUM_FILENAME_LEN]; + char theFinalFilename[MAXIMUM_FILENAME_LEN]; int returnCodeSetPermissions, returnCodeSetOwnership; - memset(theLocalPath, 0, 1024); - memset(thePermissionString, 0, 1024); - memset(theFinalFilename, 0, 2048); + memset(theLocalPath, 0, MAXIMUM_FILENAME_LEN); + memset(thePermissionString, 0, MAXIMUM_FILENAME_LEN); + memset(theFinalFilename, 0, MAXIMUM_FILENAME_LEN); int thePermissionStringCursor = 0, theLocalPathCursor = 0; while (permissionsCommand[permissionsCommandCursor] != '\r' && @@ -1401,14 +1406,14 @@ int setPermissions(char * permissionsCommand, char * basePath, ownerShip_DataTyp status = STATUS_LOCAL_PATH; break; } - if (thePermissionStringCursor < 1024 ) + if (thePermissionStringCursor < MAXIMUM_FILENAME_LEN ) thePermissionString[thePermissionStringCursor++] = permissionsCommand[permissionsCommandCursor]; else return FTP_CHMODE_COMMAND_RETURN_NAME_TOO_LONG; break; case STATUS_LOCAL_PATH: - if (theLocalPathCursor < 1024) + if (theLocalPathCursor < MAXIMUM_FILENAME_LEN) theLocalPath[theLocalPathCursor++] = permissionsCommand[permissionsCommandCursor]; else return FTP_CHMODE_COMMAND_RETURN_NAME_TOO_LONG; @@ -1418,20 +1423,24 @@ int setPermissions(char * permissionsCommand, char * basePath, ownerShip_DataTyp permissionsCommandCursor++; } - memset(theFinalFilename, 0, 2048); - - if ((strlen(basePath) + strlen(theLocalPath) + 2) >= 2048) + if ((strlen(basePath) + strlen(theLocalPath) + 2) >= MAXIMUM_FILENAME_LEN) { return FTP_CHMODE_COMMAND_RETURN_NAME_TOO_LONG; } if (basePath[strlen(basePath)-1] != '/') { - sprintf(theFinalFilename, "%s/%s", basePath, theLocalPath); + returnCode = snprintf(theFinalFilename, MAXIMUM_FILENAME_LEN, "%s/%s", basePath, theLocalPath); + + if (returnCode >= MAXIMUM_FILENAME_LEN) + return FTP_CHMODE_COMMAND_RETURN_NAME_TOO_LONG; } else { - sprintf(theFinalFilename, "%s%s", basePath, theLocalPath); + returnCode = snprintf(theFinalFilename, MAXIMUM_FILENAME_LEN, "%s%s", basePath, theLocalPath); + + if (returnCode >= MAXIMUM_FILENAME_LEN) + return FTP_CHMODE_COMMAND_RETURN_NAME_TOO_LONG; } if (FILE_IsFile(theFinalFilename) != 1 && diff --git a/ftpCommandsElaborate.h b/ftpCommandsElaborate.h index 1268617..a4a31cc 100644 --- a/ftpCommandsElaborate.h +++ b/ftpCommandsElaborate.h @@ -54,12 +54,9 @@ int parseCommandAuth(ftpDataType * data, int socketId); int parseCommandPwd(ftpDataType * data, int socketId); int parseCommandSyst(ftpDataType * data, int socketId); int parseCommandFeat(ftpDataType * data, int socketId); - int parseCommandProt(ftpDataType * data, int socketId); int parseCommandCcc(ftpDataType * data, int socketId); int parseCommandPbsz(ftpDataType * data, int socketId); - - int parseCommandStruF(ftpDataType * data, int socketId); int parseCommandTypeI(ftpDataType * data, int socketId); int parseCommandModeS(ftpDataType * data, int socketId); diff --git a/ftpData.c b/ftpData.c index b8b7f6d..e8d40e4 100644 --- a/ftpData.c +++ b/ftpData.c @@ -91,6 +91,7 @@ void setDynamicStringDataType(dynamicStringDataType *dynamicString, char *theStr int getSafePath(dynamicStringDataType *safePath, char *theDirectoryName, loginDataType *loginData) { + #define STRING_SIZE 4096 int theLen, i; char * theDirectoryNamePointer; theDirectoryNamePointer = theDirectoryName; @@ -124,9 +125,9 @@ int getSafePath(dynamicStringDataType *safePath, char *theDirectoryName, loginDa } //Check for /../ - char theDirectoryToCheck[2048]; + char theDirectoryToCheck[STRING_SIZE]; int theDirectoryToCheckIndex = 0; - memset(theDirectoryToCheck, 0, 2048); + memset(theDirectoryToCheck, 0, STRING_SIZE); for (i = 0; i< theLen; i++) { @@ -140,11 +141,11 @@ int getSafePath(dynamicStringDataType *safePath, char *theDirectoryName, loginDa } theDirectoryToCheckIndex = 0; - memset(theDirectoryToCheck, 0, 2048); + memset(theDirectoryToCheck, 0, STRING_SIZE); continue; } - if (theDirectoryToCheckIndex<2048) + if (theDirectoryToCheckIndexclients[socketPosition].workerData.connectionPort = randomicPort; - printf("data->clients[%d].workerData.connectionPort = %d", socketPosition, data->clients[socketPosition].workerData.connectionPort); + //printf("data->clients[%d].workerData.connectionPort = %d", socketPosition, data->clients[socketPosition].workerData.connectionPort); } int writeListDataInfoToSocket(ftpDataType *ftpData, int clientId, int *filesNumber, int commandType) @@ -404,7 +405,10 @@ int searchInLoginFailsVector(void * loginFailsVector, void *element) return i; } } - + void cleanup_openssl() + { + EVP_cleanup(); + } return -1; } @@ -590,7 +594,8 @@ void resetWorkerData(ftpDataType *data, int clientId, int isInitialization) } #ifdef OPENSSL_ENABLED - SSL_free(data->clients[clientId].workerData.ssl); + SSL_free(data->clients[clientId].workerData.serverSsl); + SSL_free(data->clients[clientId].workerData.clientSsl); #endif } else @@ -623,7 +628,8 @@ void resetWorkerData(ftpDataType *data, int clientId, int isInitialization) free(lastToDestroy); } #ifdef OPENSSL_ENABLED - data->clients[clientId].workerData.ssl = SSL_new(data->ctx); + data->clients[clientId].workerData.serverSsl = SSL_new(data->serverCtx); + data->clients[clientId].workerData.clientSsl = SSL_new(data->clientCtx); #endif } @@ -657,7 +663,7 @@ void resetClientData(ftpDataType *data, int clientId, int isInitialization) 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; @@ -694,11 +700,12 @@ void resetClientData(ftpDataType *data, int clientId, int isInitialization) cleanDynamicStringDataType(&data->clients[clientId].ftpCommand.commandOps, isInitialization); 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->ctx); + data->clients[clientId].ssl = SSL_new(data->serverCtx); #endif } diff --git a/ftpData.h b/ftpData.h index f50ee98..284fd0b 100644 --- a/ftpData.h +++ b/ftpData.h @@ -32,8 +32,9 @@ #include "library/dynamicVectors.h" -#define CLIENT_COMMAND_STRING_SIZE 2048 -#define CLIENT_BUFFER_STRING_SIZE 2048 +#define CLIENT_COMMAND_STRING_SIZE 4096 +#define CLIENT_BUFFER_STRING_SIZE 4096 +#define MAXIMUM_INODE_NAME 4096 #define LIST_DATA_TYPE_MODIFIED_DATA_STR_SIZE 1024 @@ -81,10 +82,11 @@ struct ftpParameters int singleInstanceModeOn; DYNV_VectorGenericDataType usersVector; int maximumIdleInactivity; - int maximumConnectionsPerIp; int maximumUserAndPassowrdLoginTries; - + + char certificatePath[MAXIMUM_INODE_NAME]; + char privateCertificatePath[MAXIMUM_INODE_NAME]; } typedef ftpParameters_DataType; struct dynamicStringData @@ -118,7 +120,8 @@ struct ipData struct workerData { #ifdef OPENSSL_ENABLED - SSL *ssl; + SSL *serverSsl; + SSL *clientSsl; #endif int threadIsAlive; @@ -157,6 +160,8 @@ struct clientData #endif int tlsIsEnabled; + int tlsIsNegotiating; + unsigned long long int tlsNegotiatingTimeStart; int dataChannelIsTls; pthread_mutex_t writeMutex; @@ -216,7 +221,8 @@ struct ConnectionParameters struct ftpData { #ifdef OPENSSL_ENABLED - SSL_CTX *ctx; + SSL_CTX *serverCtx; + SSL_CTX *clientCtx; #endif int connectedClients; @@ -258,10 +264,8 @@ int writeListDataInfoToSocket(ftpDataType *data, int clientId, int *filesNumber, int searchInLoginFailsVector(void *loginFailsVector, void *element); void deleteLoginFailsData(void *element); void deleteListDataInfoVector(void *TheElementToDelete); - void resetWorkerData(ftpDataType *data, int clientId, int isInitialization); void resetClientData(ftpDataType *data, int clientId, int isInitialization); - int compareStringCaseInsensitive(char *stringIn, char* stringRef, int stringLenght); int isCharInString(char *theString, int stringLen, char theChar); void destroyConfigurationVectorElement(void * data); diff --git a/ftpServer.c b/ftpServer.c index 2ecc256..4e92d8b 100644 --- a/ftpServer.c +++ b/ftpServer.c @@ -26,7 +26,6 @@ #include #include #include - #include #include #include @@ -59,21 +58,24 @@ void workerCleanup(void *socketId) #ifdef OPENSSL_ENABLED if (ftpData.clients[theSocketId].dataChannelIsTls == 1) { - printf("\nSSL worker Shutdown 1"); - returnCode = SSL_shutdown(ftpData.clients[theSocketId].workerData.ssl); - printf(" return code : %d", returnCode); - - if (returnCode < 0) + if(ftpData.clients[theSocketId].workerData.passiveModeOn == 1) { - printf("SSL_shutdown failed return code %d", returnCode); - } - else if (returnCode == 0) - { - returnCode = SSL_shutdown(ftpData.clients[theSocketId].workerData.ssl); + printf("\nSSL worker Shutdown 1"); + returnCode = SSL_shutdown(ftpData.clients[theSocketId].workerData.serverSsl); + printf(" return code : %d", returnCode); - if (returnCode <= 0) + if (returnCode < 0) { - printf("SSL_shutdown (2nd time) failed"); + printf("SSL_shutdown failed return code %d", returnCode); + } + else if (returnCode == 0) + { + returnCode = SSL_shutdown(ftpData.clients[theSocketId].workerData.serverSsl); + + if (returnCode <= 0) + { + printf("SSL_shutdown (2nd time) failed"); + } } } } @@ -109,6 +111,7 @@ void *connectionWorkerHandle(void * socketId) tries--; } + if (ftpData.clients[theSocketId].workerData.passiveListeningSocket == -1) { ftpData.clients[theSocketId].closeTheClient = 1; @@ -134,14 +137,24 @@ void *connectionWorkerHandle(void * socketId) if (ftpData.clients[theSocketId].dataChannelIsTls == 1) { - SSL_set_fd(ftpData.clients[theSocketId].workerData.ssl, ftpData.clients[theSocketId].workerData.socketConnection); - returnCode = SSL_accept(ftpData.clients[theSocketId].workerData.ssl); - if (returnCode <= 0) { - printf("\nSSL ERRORS ON WORKER"); - } - else { - printf("\nSSL ACCEPTED ON WORKER"); - } + returnCode = SSL_set_fd(ftpData.clients[theSocketId].workerData.serverSsl, ftpData.clients[theSocketId].workerData.socketConnection); + + if (returnCode == 0) + { + printf("\nSSL ERRORS ON WORKER SSL_set_fd"); + ftpData.clients[theSocketId].closeTheClient = 1; + } + + returnCode = SSL_accept(ftpData.clients[theSocketId].workerData.serverSsl); + if (returnCode <= 0) { + printf("\nSSL ERRORS ON WORKER"); + ERR_print_errors_fp(stderr); + ftpData.clients[theSocketId].closeTheClient = 1; + + } + else { + printf("\nSSL ACCEPTED ON WORKER"); + } } #endif } @@ -157,6 +170,31 @@ void *connectionWorkerHandle(void * socketId) { ftpData.clients[theSocketId].workerData.socketConnection = createActiveSocket(ftpData.clients[theSocketId].workerData.connectionPort, ftpData.clients[theSocketId].workerData.activeIpAddress); + #ifdef OPENSSL_ENABLED + if (ftpData.clients[theSocketId].dataChannelIsTls == 1) + { + returnCode = SSL_set_fd(ftpData.clients[theSocketId].workerData.clientSsl, ftpData.clients[theSocketId].workerData.socketConnection); + + if (returnCode == 0) + { + printf("\nSSL ERRORS ON WORKER SSL_set_fd"); + ftpData.clients[theSocketId].closeTheClient = 1; + } + + returnCode = SSL_connect(ftpData.clients[theSocketId].workerData.clientSsl); + if (returnCode <= 0) + { + printf("\nSSL ERRORS ON WORKER %d", returnCode); + ERR_print_errors_fp(stderr); + //ftpData.clients[theSocketId].closeTheClient = 1; + } + else + { + printf("\nSSL ACCEPTED ON WORKER"); + } + } + #endif + if (ftpData.clients[theSocketId].workerData.socketConnection < 0) { ftpData.clients[theSocketId].closeTheClient = 1; @@ -231,13 +269,20 @@ void *connectionWorkerHandle(void * socketId) while(1) { + if (ftpData.clients[theSocketId].dataChannelIsTls != 1) { ftpData.clients[theSocketId].workerData.bufferIndex = read(ftpData.clients[theSocketId].workerData.socketConnection, ftpData.clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE); } else if (ftpData.clients[theSocketId].dataChannelIsTls == 1) { - ftpData.clients[theSocketId].workerData.bufferIndex = SSL_read(ftpData.clients[theSocketId].workerData.ssl, ftpData.clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE); + + #ifdef OPENSSL_ENABLED + if (ftpData.clients[theSocketId].workerData.passiveModeOn == 1) + ftpData.clients[theSocketId].workerData.bufferIndex = SSL_read(ftpData.clients[theSocketId].workerData.serverSsl, ftpData.clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE); + else if(ftpData.clients[theSocketId].workerData.activeModeOn == 1) + ftpData.clients[theSocketId].workerData.bufferIndex = SSL_read(ftpData.clients[theSocketId].workerData.clientSsl, ftpData.clients[theSocketId].workerData.buffer, CLIENT_BUFFER_STRING_SIZE); + #endif } else { @@ -437,6 +482,36 @@ void runFtpServer(void) FD_ISSET(ftpData.clients[processingSock].socketDescriptor, &ftpData.connectionData.eset)) { + #ifdef OPENSSL_ENABLED + if (ftpData.clients[processingSock].tlsIsNegotiating == 1) + { + returnCode = SSL_accept(ftpData.clients[processingSock].ssl); + + if (returnCode <= 0) + { + printf("\nSSL NOT YET ACCEPTED: %d", returnCode); + ftpData.clients[processingSock].tlsIsEnabled = 0; + ftpData.clients[processingSock].tlsIsNegotiating = 1; + + if ( ((int)time(NULL) - ftpData.clients[processingSock].tlsNegotiatingTimeStart) > TLS_NEGOTIATING_TIMEOUT ) + { + ftpData.clients[processingSock].closeTheClient = 1; + printf("\nTLS timeout closing the client time:%lld, start time: %lls..", (int)time(NULL), ftpData.clients[processingSock].tlsNegotiatingTimeStart); + } + + } + else + { + printf("\nSSL ACCEPTED"); + ftpData.clients[processingSock].tlsIsEnabled = 1; + ftpData.clients[processingSock].tlsIsNegotiating = 0; + } + + + continue; + } + #endif + if (ftpData.clients[processingSock].tlsIsEnabled == 1) { #ifdef OPENSSL_ENABLED @@ -483,7 +558,7 @@ void runFtpServer(void) if (ftpData.clients[processingSock].buffer[i] == '\n') { ftpData.clients[processingSock].socketCommandReceived = 1; - printf("\n Processing the command: %s", ftpData.clients[processingSock].theCommandReceived); + //printf("\n Processing the command: %s", ftpData.clients[processingSock].theCommandReceived); commandProcessStatus = processCommand(processingSock); //Echo unrecognized commands if (commandProcessStatus == FTP_COMMAND_NOT_RECONIZED) @@ -539,8 +614,8 @@ void runFtpServer(void) static int processCommand(int processingElement) { int toReturn = 0; - printTimeStamp(); - printf ("Command received from (%d): %s", processingElement, ftpData.clients[processingElement].theCommandReceived); + //printTimeStamp(); + //printf ("Command received from (%d): %s", processingElement, ftpData.clients[processingElement].theCommandReceived); cleanDynamicStringDataType(&ftpData.clients[processingElement].ftpCommand.commandArgs, 0); cleanDynamicStringDataType(&ftpData.clients[processingElement].ftpCommand.commandOps, 0); @@ -752,8 +827,9 @@ static int processCommand(int processingElement) void deallocateMemory(void) { printf("\n Deallocating the memory.. "); - #ifndef OPENSSL_ENABLED - SSL_CTX_free(ftpData.ctx); - cleanup_openssl(); + + #ifdef OPENSSL_ENABLED + SSL_CTX_free(ftpData.serverCtx); + cleanupOpenssl(); #endif } diff --git a/ftpServer.h b/ftpServer.h index 583f20d..6b7b673 100644 --- a/ftpServer.h +++ b/ftpServer.h @@ -28,8 +28,7 @@ #define MAX_FTP_CLIENTS 10 #define UFTP_SERVER_VERSION "2.0.0 beta" -#warning remove in final release, must be specified by makefile -#define OPENSSL_ENABLED + void runFtpServer(void); void *connectionWorkerHandle(void * socketId); diff --git a/library/configRead.c b/library/configRead.c index 7a9af21..ab270ac 100644 --- a/library/configRead.c +++ b/library/configRead.c @@ -74,15 +74,11 @@ void configurationRead(ftpParameters_DataType *ftpParameters) { printf("\nReading configuration from \n -> %s \n", LOCAL_CONFIGURATION_FILENAME); returnCode = readConfigurationFile(LOCAL_CONFIGURATION_FILENAME, &configParameters); - printf("\nDONE\n"); - } else if (FILE_IsFile(DEFAULT_CONFIGURATION_FILENAME) == 1) { printf("\nReading configuration from \n -> %s\n", DEFAULT_CONFIGURATION_FILENAME); returnCode = readConfigurationFile(DEFAULT_CONFIGURATION_FILENAME, &configParameters); - printf("\nDONE\n"); - } if (returnCode == 1) @@ -128,10 +124,11 @@ void initFtpData(ftpDataType *ftpData) srand(time(NULL)); #ifdef OPENSSL_ENABLED - #warning OPENSSL ENABLED! initOpenssl(); - ftpData->ctx = createContext(); - configureContext(ftpData->ctx); + ftpData->serverCtx = createServerContext(); + ftpData->clientCtx = createClientContext(); + configureContext(ftpData->serverCtx, ftpData->ftpParameters.certificatePath, ftpData->ftpParameters.privateCertificatePath); + configureContext(ftpData->clientCtx, ftpData->ftpParameters.certificatePath, ftpData->ftpParameters.privateCertificatePath); #endif ftpData->connectedClients = 0; @@ -494,6 +491,31 @@ static int parseConfigurationFile(ftpParameters_DataType *ftpParameters, DYNV_Ve printf("\nFTP_SERVER_IP parameter not found in the configuration file, listening on all available networks"); } + + searchIndex = searchParameter("CERTIFICATE_PATH", parametersVector); + if (searchIndex != -1) + { + strcpy(ftpParameters->certificatePath, ((parameter_DataType *) parametersVector->Data[searchIndex])->value); + printf("\nCERTIFICATE_PATH: %s", ftpParameters->certificatePath); + } + else + { + strcpy(ftpParameters->certificatePath, "cert.pem"); + printf("\nCERTIFICATE_PATH parameter not found in the configuration file, using the default value: %s", ftpParameters->certificatePath); + } + + searchIndex = searchParameter("PRIVATE_CERTIFICATE_PATH", parametersVector); + if (searchIndex != -1) + { + strcpy(ftpParameters->privateCertificatePath, ((parameter_DataType *) parametersVector->Data[searchIndex])->value); + printf("\nPRIVATE_CERTIFICATE_PATH: %s", ftpParameters->certificatePath); + } + else + { + strcpy(ftpParameters->privateCertificatePath, "key.pem"); + printf("\nPRIVATE_CERTIFICATE_PATH parameter not found in the configuration file, using the default value: %s", ftpParameters->privateCertificatePath); + } + /* USER SETTINGS */ userIndex = 0; memset(userX, 0, PARAMETER_SIZE_LIMIT); @@ -505,14 +527,14 @@ static int parseConfigurationFile(ftpParameters_DataType *ftpParameters, DYNV_Ve DYNV_VectorGeneric_Init(&ftpParameters->usersVector); while(1) { - int searchUserIndex, searchPasswordIndex, searchHomeIndex, searchUserOwnerIndex, searchGroupOwnerIndex; + int searchUserIndex, searchPasswordIndex, searchHomeIndex, searchUserOwnerIndex, searchGroupOwnerIndex, returnCode; usersParameters_DataType userData; - sprintf(userX, "USER_%d", userIndex); - sprintf(passwordX, "PASSWORD_%d", userIndex); - sprintf(homeX, "HOME_%d", userIndex); - sprintf(groupOwnerX, "GROUP_NAME_OWNER_%d", userIndex); - sprintf(userOwnerX, "USER_NAME_OWNER_%d", userIndex); + returnCode = snprintf(userX, PARAMETER_SIZE_LIMIT, "USER_%d", userIndex); + returnCode = snprintf(passwordX, PARAMETER_SIZE_LIMIT, "PASSWORD_%d", userIndex); + returnCode = snprintf(homeX, PARAMETER_SIZE_LIMIT, "HOME_%d", userIndex); + returnCode = snprintf(groupOwnerX, PARAMETER_SIZE_LIMIT, "GROUP_NAME_OWNER_%d", userIndex); + returnCode = snprintf(userOwnerX, PARAMETER_SIZE_LIMIT, "USER_NAME_OWNER_%d", userIndex); userIndex++; searchUserIndex = searchParameter(userX, parametersVector); diff --git a/library/connection.c b/library/connection.c index 08212b3..864f0fa 100644 --- a/library/connection.c +++ b/library/connection.c @@ -47,10 +47,10 @@ int socketPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __f #define SOCKET_PRINTF_BUFFER 2048 int bytesWritten = 0; - char theBuffer[2048]; + char theBuffer[SOCKET_PRINTF_BUFFER]; int theStringSize = 0; memset(&theBuffer, 0, SOCKET_PRINTF_BUFFER); - printf("\nWriting to socket id %d, TLS %d: ", clientId, ftpData->clients[clientId].tlsIsEnabled); + //printf("\nWriting to socket id %d, TLS %d: ", clientId, ftpData->clients[clientId].tlsIsEnabled); va_list args; va_start(args, __fmt); @@ -132,7 +132,7 @@ int socketPrintf(ftpDataType * ftpData, int clientId, const char *__restrict __f #endif } - printf("%s", theBuffer); + //printf("%s", theBuffer); if (theReturnCode > 0) { @@ -162,10 +162,10 @@ int socketWorkerPrintf(ftpDataType * ftpData, int clientId, const char *__restri #define SOCKET_PRINTF_BUFFER 2048 int bytesWritten = 0; - char theBuffer[2048]; + 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); + //printf("\nWriting to worker socket id %dd, TLS %d: ", clientId, ftpData->clients[clientId].dataChannelIsTls); va_list args; va_start(args, __fmt); while (*__fmt != '\0') @@ -239,12 +239,16 @@ int socketWorkerPrintf(ftpDataType * ftpData, int clientId, const char *__restri } else if (ftpData->clients[clientId].dataChannelIsTls == 1) { + #ifdef OPENSSL_ENABLED - theReturnCode = SSL_write(ftpData->clients[clientId].workerData.ssl, theBuffer, theStringSize); + if (ftpData->clients[clientId].workerData.passiveModeOn == 1) + theReturnCode = SSL_write(ftpData->clients[clientId].workerData.serverSsl, theBuffer, theStringSize); + else if (ftpData->clients[clientId].workerData.activeModeOn == 1) + theReturnCode = SSL_write(ftpData->clients[clientId].workerData.clientSsl, theBuffer, theStringSize); #endif } - printf("%s", theBuffer); + //printf("%s", theBuffer); if (theReturnCode > 0) { diff --git a/library/daemon.c b/library/daemon.c index 28854f0..17b83af 100644 --- a/library/daemon.c +++ b/library/daemon.c @@ -44,7 +44,8 @@ int isProcessAlreadyRunning(void) { int fd; int returnCode; - char buf[16]; + char buf[30]; + memset(buf, 0,30); fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE); if (fd < 0) { @@ -66,8 +67,8 @@ int isProcessAlreadyRunning(void) //printf("\nFILE_LockFile returnCode = %d", returnCode); ftruncate(fd, 0); - sprintf(buf, "%ld", (long)getpid()); - write(fd, buf, strlen(buf)+1); + returnCode = snprintf(buf, 100, "%ld", (long)getpid()); + returnCode = write(fd, buf, strlen(buf)+1); return(0); } @@ -133,4 +134,4 @@ void daemonize(const char *cmd) fd0 = open("/dev/null", O_RDWR); fd1 = dup(0); fd2 = dup(0); - } \ No newline at end of file + } diff --git a/library/fileManagement.c b/library/fileManagement.c index a0a9398..c9fb21a 100644 --- a/library/fileManagement.c +++ b/library/fileManagement.c @@ -196,7 +196,7 @@ void FILE_GetDirectoryInodeList(char * DirectoryInodeName, char *** InodeList, i if (FILE_IsDirectory(DirectoryInodeName)) { - printf("\nReading directory: %s", DirectoryInodeName); + //printf("\nReading directory: %s", DirectoryInodeName); DIR *TheDirectory; struct dirent *dir; diff --git a/library/openSsl.c b/library/openSsl.c index dc0641a..342bca0 100644 --- a/library/openSsl.c +++ b/library/openSsl.c @@ -22,7 +22,6 @@ * THE SOFTWARE. */ #ifdef OPENSSL_ENABLED -#warning SSL ENABLED #include #include #include @@ -32,11 +31,24 @@ #include #include "openSsl.h" +#include "fileManagement.h" + +BIO *outbio; void initOpenssl() { + + outbio = NULL; + OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */ + SSL_load_error_strings(); /* Bring in and register error messages */ SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); + //OpenSSL_add_ssl_algorithms(); + ERR_load_BIO_strings(); + ERR_load_crypto_strings(); + SSL_load_error_strings(); + outbio = BIO_new(BIO_s_file()); + outbio = BIO_new_fp(stdout, BIO_NOCLOSE); + SSL_library_init(); } void cleanupOpenssl() @@ -44,36 +56,90 @@ void cleanupOpenssl() EVP_cleanup(); } -SSL_CTX *createContext() +SSL_CTX *createServerContext() { const SSL_METHOD *method; SSL_CTX *ctx; - method = SSLv23_server_method(); + method = TLS_server_method(); ctx = SSL_CTX_new(method); - if (!ctx) { - perror("Unable to create SSL context"); - ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); + if (!ctx) + { + perror("Unable to create server SSL context"); + ERR_print_errors_fp(stderr); + exit(0); } return ctx; } -void configureContext(SSL_CTX *ctx) +SSL_CTX *createClientContext(void) { + const SSL_METHOD *method; + SSL_CTX *ctx; + + method = TLS_client_method(); /* Create new client-method instance */ + ctx = SSL_CTX_new(method); /* Create new context */ + if ( ctx == NULL ) + { + perror("Unable to create server SSL context"); + ERR_print_errors_fp(stderr); + abort(); + exit(0); + } + return ctx; +} + + +void configureContext(SSL_CTX *ctx, char *certificatePath, char* privateCertificatePath) +{ + if (FILE_IsFile(certificatePath) != 1) + { + printf("\ncertificate file: %s not found!", certificatePath); + exit(0); + } + + if (FILE_IsFile(privateCertificatePath) != 1) + { + printf("\ncertificate file: %s not found!", privateCertificatePath); + exit(0); + } + SSL_CTX_set_ecdh_auto(ctx, 1); /* Set the key and cert */ - if (SSL_CTX_use_certificate_file(ctx, "/home/ugo/NetBeansProjects/uFTP/cert.pem", SSL_FILETYPE_PEM) <= 0) { + if (SSL_CTX_use_certificate_file(ctx, certificatePath, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } - if (SSL_CTX_use_PrivateKey_file(ctx, "/home/ugo/NetBeansProjects/uFTP/key.pem", SSL_FILETYPE_PEM) <= 0 ) { + if (SSL_CTX_use_PrivateKey_file(ctx, privateCertificatePath, SSL_FILETYPE_PEM) <= 0 ) { ERR_print_errors_fp(stderr); - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); } } + + +void ShowCerts(SSL* ssl) +{ X509 *cert; + char *line; + + cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */ + if ( cert != NULL ) + { + printf("Server certificates:\n"); + line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); + printf("Subject: %s\n", line); + free(line); /* free the malloc'ed string */ + line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); + printf("Issuer: %s\n", line); + free(line); /* free the malloc'ed string */ + X509_free(cert); /* free the malloc'ed certificate copy */ + } + else + printf("No certificates.\n"); +} + + #endif diff --git a/library/openSsl.h b/library/openSsl.h index 6503616..ade4753 100644 --- a/library/openSsl.h +++ b/library/openSsl.h @@ -22,23 +22,24 @@ * THE SOFTWARE. */ #ifdef OPENSSL_ENABLED -#warning SSL ENABLED #ifndef OPENSSL_H #define OPENSSL_H - #include #include +#define TLS_NEGOTIATING_TIMEOUT 30 + #ifdef __cplusplus extern "C" { #endif void initOpenssl(); void cleanupOpenssl(); -SSL_CTX *createContext(); -void configureContext(SSL_CTX *ctx); - +SSL_CTX *createServerContext(); +SSL_CTX *createClientContext(); +void configureContext(SSL_CTX *ctx, char *certificatePath, char* privateCertificatePath); +void ShowCerts(SSL* ssl); #ifdef __cplusplus } #endif diff --git a/uftpd.cfg b/uftpd.cfg index 3b65328..aac0155 100644 --- a/uftpd.cfg +++ b/uftpd.cfg @@ -32,6 +32,10 @@ MAX_CONNECTION_TRY_PER_IP = 10 #THE IP ADDRESS WILL BE BLOCKED FOR 5 MINUTES AFTER WRONG LOGIN USERNAME AND PASSWORD #0 TO DISABLE +#TLS CERTIFICATE FILE PATH +CERTIFICATE_PATH=/home/ugo/NetBeansProjects/uFTP/cert.pem +PRIVATE_CERTIFICATE_PATH=/home/ugo/NetBeansProjects/uFTP/key.pem + #USERS #START FROM USER 0 TO XXX USER_0 = username