From 4a045630945e8a63fd3ae74c3f8b7b4c42699f84 Mon Sep 17 00:00:00 2001 From: hfiref0x Date: Fri, 15 May 2020 19:55:03 +0700 Subject: [PATCH 1/4] v 2.0.2.2005 Bugfixes --- LICENSE.md | 2 +- README.md | 4 +- Source.sha256 | 19 ++--- Source/Debug/subdir.mk | 3 + Source/Release/subdir.mk | 3 + Source/cfgparse.c | 11 +-- Source/cfgparse.h | 6 +- Source/changelog.txt | 3 + Source/ftpconst.c | 23 ++++++ Source/ftpserv.c | 58 +++++++++----- Source/ftpserv.h | 125 +++++++++++++++-------------- Source/main.c | 165 +++++++++++++++++++-------------------- 12 files changed, 232 insertions(+), 190 deletions(-) create mode 100644 Source/ftpconst.c diff --git a/LICENSE.md b/LICENSE.md index 6831fea..15178e1 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) LightFTP 2007 - 2019 Project authors +Copyright (c) LightFTP 2007 - 2020 Project authors Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index 2261aba..28b3482 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ Example of configuration file can be found in Source directory as fftp.conf. * In order to build from source in Linux you need GCC C compiler, run make command in the Release directory. LigthFTP uses GnuTLS, make sure you have headers (libgnutls-dev or gnutls-dev) installed; * Old Windows Visual Studio source code and project files located in Source/Deprecated directory, in order to build from this source you need Microsoft Visual Studio 2013/2015 and later versions. -### Example for Linux Mint 19.1/Ubuntu 18.04 +### Example for Linux Mint 19.3/Ubuntu 18.04 You need GCC and Make installed. If they are not installed you can install them as part of build-essential package: @@ -131,4 +131,4 @@ Result binary is fftp. Next setup ftp config, example config file is Source/fftp # Authors -(c) 2007 - 2019 LightFTP Project +(c) 2007 - 2020 LightFTP Project diff --git a/Source.sha256 b/Source.sha256 index 47c676f..a6c84e2 100644 --- a/Source.sha256 +++ b/Source.sha256 @@ -1,16 +1,17 @@ -52989e3efcc842d7f1c07cc6d49a20b2981e46599bdd74e067a070b154c00a22 *Source\cfgparse.c -8214f7f15adb8eab19a336b9e867ce35c2cc11317c6b8b612204e90a1ab9ccd8 *Source\cfgparse.h -8925cd669e8c4b3696d27e8fa98c9e20010e7058c685aecf50669a4190383bb6 *Source\changelog.txt +18364d8691f4bb9ec5f684940e05ddd70de658446417c1f6071a21ad7f4b3717 *Source\cfgparse.c +fb951da7cb5aa17b79cc455bbcb3d7a3ef09182db34298a921138bdd9950cd17 *Source\cfgparse.h +d6991972944b42bfb5474daf0790ce0e3ea4f3ad91624266a6023ab7360dd13f *Source\changelog.txt 5f60ff45d21faa296673f793d6afef8a0c2c9b97a7b0aa51134750f7158f15c2 *Source\fftp.conf -44f52ba4091e99b60e06fad1c973ce95012c274eaa3bc0010d589540e3f264bc *Source\ftpserv.c -de11d783b7cdea34ef90eca2f957333cf17485b537fd9a4d6b24a8d9f357d82f *Source\ftpserv.h -8dc0b4a40e2bac991a7d878aa80d53d9bf175b739a6c591e9401a77b285fca1c *Source\main.c -31f77f2c56d71b285cb689af8e7400602af0adaf0df8cfe3bc9ae57a1e79c5f1 *Source\x_malloc.c +552be952422a3e3959e4f130be0c7fdff6ab0ef124eb161df21b0a264b0b2a32 *Source\ftpconst.c +aa77de70e59e57b66e40af615b1667396f4b9ec621f33534eeb37240dcdcc155 *Source\ftpserv.c +550e697017735ff7bcca2d3d54748dc18aeba488c935867333e66426df22529e *Source\ftpserv.h +4bc1fd1c591407b485d6f3af44d06b07682a342cc1c43a47ff04c465182204a6 *Source\main.c +c152edb89faf8a2b57039ce1507b57025d2fa91ae7076b7f0bb6dd066dbe7cfd *Source\x_malloc.c 79876657549a772e6e48fdacc83f18352ad9a23529cab840e169fdfe62d6a01e *Source\x_malloc.h 65c2c882ead0e9266325893b457b8506db2a081eb3936939dedfce52c22c31ea *Source\Debug\makefile fa3d96ba5c45cb2b0004c8ea687045e16768ec90ec788f0958905083164e52f1 *Source\Debug\objects.mk 45bf7584af2acb3c6c806bd48b0774c661e081efdaff00d735554cde1ed76fbb *Source\Debug\sources.mk -09c8a40d264228fad831f5995ca698c522f812ac9c8e1658ce7a371b47ae6eff *Source\Debug\subdir.mk +0a6c6e465f4cfe0596e63b325d6170a9eab1598880005d4f7e41749899769ee3 *Source\Debug\subdir.mk 71f29f165b2554ec548bc56a113f38c0c993c2b34265acfd6d4c64a05f3db1ef *Source\Deprecated\Windows\fftp.sln 8708f082b6072e0ab2c55984c2bd252f80049f2d4dceabf6fd8cf4815331cf7f *Source\Deprecated\Windows\fftp\debug.conf 6315323d32acdc93160ed785f82631e686645370ae62082199f5c8000fc98e08 *Source\Deprecated\Windows\fftp\fftp.vcxproj @@ -38,6 +39,6 @@ ef1b18997ea473ac8d516ef60efc64b9175418b8f078e088d783fdaef2544969 *Source\Depreca 65c2c882ead0e9266325893b457b8506db2a081eb3936939dedfce52c22c31ea *Source\Release\makefile fa3d96ba5c45cb2b0004c8ea687045e16768ec90ec788f0958905083164e52f1 *Source\Release\objects.mk 45bf7584af2acb3c6c806bd48b0774c661e081efdaff00d735554cde1ed76fbb *Source\Release\sources.mk -871ea443b36ccdc99c0676567a58fe71051f2f2654e6227b311238f4d643398f *Source\Release\subdir.mk +ba65327d3b42305556a1dbcb6d4329148a245a2d02e00ae332d8a3825fade5d1 *Source\Release\subdir.mk f7d0ab874ee47ea673ddcdd3dfd9662646f9c1a796b94f3e1b33e1321baf52c3 *Source\TLS-cert\gencert.sh f3c8e1fdc3b05facb5e87ef1fc11b5fc1ee4d1d4832578f4fc1c23ecd488bab4 *Source\TLS-cert\mycert-req.txt diff --git a/Source/Debug/subdir.mk b/Source/Debug/subdir.mk index 87450f7..5f57e0c 100644 --- a/Source/Debug/subdir.mk +++ b/Source/Debug/subdir.mk @@ -5,18 +5,21 @@ # Add inputs and outputs from these tool invocations to the build variables C_SRCS += \ ../cfgparse.c \ +../ftpconst.c \ ../ftpserv.c \ ../main.c \ ../x_malloc.c OBJS += \ ./cfgparse.o \ +./ftpconst.o \ ./ftpserv.o \ ./main.o \ ./x_malloc.o C_DEPS += \ ./cfgparse.d \ +./ftpconst.d \ ./ftpserv.d \ ./main.d \ ./x_malloc.d diff --git a/Source/Release/subdir.mk b/Source/Release/subdir.mk index f520c4d..cc9764b 100644 --- a/Source/Release/subdir.mk +++ b/Source/Release/subdir.mk @@ -5,18 +5,21 @@ # Add inputs and outputs from these tool invocations to the build variables C_SRCS += \ ../cfgparse.c \ +../ftpconst.c \ ../ftpserv.c \ ../main.c \ ../x_malloc.c OBJS += \ ./cfgparse.o \ +./ftpconst.o \ ./ftpserv.o \ ./main.o \ ./x_malloc.o C_DEPS += \ ./cfgparse.d \ +./ftpconst.d \ ./ftpserv.d \ ./main.d \ ./x_malloc.d diff --git a/Source/cfgparse.c b/Source/cfgparse.c index dc6d26f..98e4aff 100644 --- a/Source/cfgparse.c +++ b/Source/cfgparse.c @@ -9,15 +9,12 @@ */ #include -#include #include #include -#include -#include #include #include "x_malloc.h" -char * skip_comments_and_blanks(char *p) +char *skip_comments_and_blanks(char *p) { while (*p != 0) { @@ -47,9 +44,9 @@ char * skip_comments_and_blanks(char *p) return p; } -/* TODO: Refactor this function */ +/* TODO: Rewrite this function */ -int ParseConfig( +int config_parse( const char *pcfg, const char *section_name, const char *key_name, @@ -202,7 +199,7 @@ int ParseConfig( return 0; } -char *InitConfig(char *cfg_filename) +char *config_init(char *cfg_filename) { int f_config; char *buffer = NULL; diff --git a/Source/cfgparse.h b/Source/cfgparse.h index bd865fc..b416bcd 100644 --- a/Source/cfgparse.h +++ b/Source/cfgparse.h @@ -3,7 +3,7 @@ * * Created on: Aug 20, 2016 * -* Modified on: Feb 09, 2018 +* Modified on: May 15, 2020 * * Author: lightftp */ @@ -11,7 +11,7 @@ #ifndef CFGPARSE_H_ #define CFGPARSE_H_ -char *InitConfig(char *cfg_filename); -int ParseConfig(const char *pcfg, const char *section_name, const char *key_name, char *value, unsigned long value_size_max); +char *config_init(char *cfg_filename); +int config_parse(const char *pcfg, const char *section_name, const char *key_name, char *value, unsigned long value_size_max); #endif /* CFGPARSE_H_ */ diff --git a/Source/changelog.txt b/Source/changelog.txt index 6879651..c7dc387 100644 --- a/Source/changelog.txt +++ b/Source/changelog.txt @@ -2,6 +2,9 @@ - Removed * Fixed/Changed +May 15, 2020, v2.0b +* bugfixes + Jun 28, 2018, v2.0a + simplify path processing functions diff --git a/Source/ftpconst.c b/Source/ftpconst.c new file mode 100644 index 0000000..caa8461 --- /dev/null +++ b/Source/ftpconst.c @@ -0,0 +1,23 @@ +/* + * ftpconst.c + * + * Created : May 15, 2020 + * Modified : May 15, 2020 + * Author : lightftp + */ + +const char shortmonths[12][4] = { + "Jan\0", "Feb\0", "Mar\0", "Apr\0", "May\0", "Jun\0", + "Jul\0", "Aug\0", "Sep\0", "Oct\0", "Nov\0", "Dec\0"}; + +const char success211[] = + "211-Extensions supported:\r\n PASV\r\n UTF8\r\n TVFS\r\n REST STREAM\r\n " + "SIZE\r\n MLSD\r\n AUTH TLS\r\n PBSZ\r\n PROT\r\n EPSV\r\n" + "211 End.\r\n"; + +const char success214[] = + "214-The following commands are recognized.\r\n" + " ABOR APPE AUTH CDUP CWD DELE EPSV FEAT HELP LIST MKD MLSD NOOP OPTS\r\n" + " PASS PASV PBSZ PORT PROT PWD QUIT REST RETR RMD RNFR RNTO SITE SIZE\r\n" + " STOR SYST TYPE USER\r\n" + "214 Help OK.\r\n"; diff --git a/Source/ftpserv.c b/Source/ftpserv.c index ad27c08..2daa723 100644 --- a/Source/ftpserv.c +++ b/Source/ftpserv.c @@ -3,7 +3,7 @@ * * Created on: Aug 20, 2016 * -* Modified on: Sep 01, 2019 +* Modified on: May 15, 2020 * * Author: lightftp */ @@ -217,7 +217,7 @@ ssize_t sendstring_plaintext(SOCKET s, const char *Buffer) return (send(s, Buffer, strlen(Buffer), MSG_NOSIGNAL) >= 0); } -int InitTLSSession(gnutls_session_t *session, SOCKET s, int send_success_string) +int ftp_init_tls_session(gnutls_session_t *session, SOCKET s, int send_success_string) { int ret; @@ -370,7 +370,7 @@ int writelogentry(PFTPCONTEXT context, const char *logtext1, const char *logtext return writeconsolestr(text); } -void WorkerThreadCleanup(PFTPCONTEXT context) +void ftp_worker_thread_cleanup(PFTPCONTEXT context) { int err; void *retv = NULL; @@ -405,7 +405,6 @@ void WorkerThreadCleanup(PFTPCONTEXT context) context->DataIPv4 = 0; context->DataPort = 0; - //writelogentry(context, "WorkerThreadCleanup complete", ""); } int ftpUSER(PFTPCONTEXT context, const char *params) @@ -663,7 +662,7 @@ void *list_thread(PFTPCONTEXT context) while (clientsocket != INVALID_SOCKET) { if (context->TLS_session != NULL) - InitTLSSession(&TLS_datasession, clientsocket, 0); + ftp_init_tls_session(&TLS_datasession, clientsocket, 0); pdir = opendir(context->GPBuffer); if (pdir == NULL) @@ -830,7 +829,7 @@ void *retr_thread(PFTPCONTEXT context) if (context->TLS_session != NULL) { - InitTLSSession(&TLS_datasession, clientsocket, 0); + ftp_init_tls_session(&TLS_datasession, clientsocket, 0); buffer_size = gnutls_record_get_max_size(TLS_datasession); if (buffer_size > TRANSMIT_BUFFER_SIZE) buffer_size = TRANSMIT_BUFFER_SIZE; @@ -863,6 +862,7 @@ void *retr_thread(PFTPCONTEXT context) } /* heartbeat to control channel */ + /* clock_gettime(CLOCK_MONOTONIC, &t); if (t.tv_sec >= dtx) { @@ -870,6 +870,7 @@ void *retr_thread(PFTPCONTEXT context) sendstring(context, "\r\n"); writelogentry(context, "keepalive sent", ""); } + */ } /* calculating performance */ @@ -971,7 +972,7 @@ int ftpABOR(PFTPCONTEXT context, const char *params) return sendstring(context, error530); writelogentry(context, " ABORT command", NULL); - WorkerThreadCleanup(context); + ftp_worker_thread_cleanup(context); return sendstring(context, success226); } @@ -1122,7 +1123,7 @@ int ftpPASS(PFTPCONTEXT context, const char *params) /* * we have username saved in context->GPBuffer from USER command */ - if (!ParseConfig(g_cfg.ConfigFile, context->GPBuffer, "pswd", temptext, sizeof(temptext))) + if (!config_parse(g_cfg.ConfigFile, context->GPBuffer, "pswd", temptext, sizeof(temptext))) return sendstring(context, error530_r); if ( (strcmp(temptext, params) == 0) || (temptext[0] == '*') ) @@ -1130,8 +1131,8 @@ int ftpPASS(PFTPCONTEXT context, const char *params) memset(context->RootDir, 0, sizeof(context->RootDir)); memset(temptext, 0, sizeof(temptext)); - ParseConfig(g_cfg.ConfigFile, context->GPBuffer, "root", context->RootDir, sizeof(context->RootDir)); - ParseConfig(g_cfg.ConfigFile, context->GPBuffer, "accs", temptext, sizeof(temptext)); + config_parse(g_cfg.ConfigFile, context->GPBuffer, "root", context->RootDir, sizeof(context->RootDir)); + config_parse(g_cfg.ConfigFile, context->GPBuffer, "accs", temptext, sizeof(temptext)); context->Access = FTP_ACCESS_NOT_LOGGED_IN; do { @@ -1285,7 +1286,7 @@ void *stor_thread(PFTPCONTEXT context) if (context->TLS_session != NULL) { - InitTLSSession(&TLS_datasession, clientsocket, 0); + ftp_init_tls_session(&TLS_datasession, clientsocket, 0); buffer_size = gnutls_record_get_max_size(TLS_datasession); if (buffer_size > TRANSMIT_BUFFER_SIZE) buffer_size = TRANSMIT_BUFFER_SIZE; @@ -1309,6 +1310,7 @@ void *stor_thread(PFTPCONTEXT context) break; /* heartbeat to control channel */ + /* clock_gettime(CLOCK_MONOTONIC, &t); if (t.tv_sec >= dtx) { @@ -1316,6 +1318,7 @@ void *stor_thread(PFTPCONTEXT context) sendstring(context, "\r\n"); writelogentry(context, "keepalive sent", ""); } + */ } /* calculating performance */ @@ -1324,7 +1327,7 @@ void *stor_thread(PFTPCONTEXT context) lt1 = t.tv_sec*1e9 + t.tv_nsec; dtx = lt1 - lt0; snprintf(buffer, buffer_size, " STOR complete. %zd bytes (%f MBytes) total sent in %f seconds (%f MBytes/s)", - sz_total, sz_total/1048576.0, dtx/1000000000.0, (1000000000.0*sz_total)/dtx/1048576); + sz_total, sz_total/1048576.0, dtx/1000000000.0, (1000000000.0*sz_total)/dtx/1048576); writelogentry(context, buffer, ""); break; @@ -1466,7 +1469,7 @@ void *append_thread(PFTPCONTEXT context) if (context->TLS_session != NULL) { - InitTLSSession(&TLS_datasession, clientsocket, 0); + ftp_init_tls_session(&TLS_datasession, clientsocket, 0); buffer_size = gnutls_record_get_max_size(TLS_datasession); if (buffer_size > TRANSMIT_BUFFER_SIZE) buffer_size = TRANSMIT_BUFFER_SIZE; @@ -1492,6 +1495,7 @@ void *append_thread(PFTPCONTEXT context) break; /* heartbeat to control channel */ + /* clock_gettime(CLOCK_MONOTONIC, &t); if (t.tv_sec >= dtx) { @@ -1499,6 +1503,7 @@ void *append_thread(PFTPCONTEXT context) sendstring(context, "\r\n"); writelogentry(context, "keepalive sent", ""); } + */ } /* calculating performance */ @@ -1507,7 +1512,7 @@ void *append_thread(PFTPCONTEXT context) lt1 = t.tv_sec*1e9 + t.tv_nsec; dtx = lt1 - lt0; snprintf(buffer, buffer_size, " APPE complete. %zd bytes (%f MBytes) total sent in %f seconds (%f MBytes/s)", - sz_total, sz_total/1048576.0, dtx/1000000000.0, (1000000000.0*sz_total)/dtx/1048576); + sz_total, sz_total/1048576.0, dtx/1000000000.0, (1000000000.0*sz_total)/dtx/1048576); writelogentry(context, buffer, ""); break; @@ -1681,7 +1686,7 @@ int ftpAUTH(PFTPCONTEXT context, const char *params) if ( strcasecmp(params, "TLS") == 0 ) /* InitTLSSession will send reply */ - return InitTLSSession(&context->TLS_session, context->ControlSocket, 1); + return ftp_init_tls_session(&context->TLS_session, context->ControlSocket, 1); else return sendstring(context, error504); } @@ -1794,7 +1799,7 @@ void *msld_thread(PFTPCONTEXT context) while (clientsocket != INVALID_SOCKET) { if (context->TLS_session != NULL) - InitTLSSession(&TLS_datasession, clientsocket, 0); + ftp_init_tls_session(&TLS_datasession, clientsocket, 0); pdir = opendir(context->GPBuffer); if (pdir == NULL) @@ -1915,7 +1920,7 @@ int recvcmd(PFTPCONTEXT context, char *buffer, size_t buffer_size) void *ftp_client_thread(SOCKET *s) { FTPCONTEXT ctx __attribute__ ((aligned (16))); - char *cmd, *params, rcvbuf[FTP_PATH_MAX*2]; + char *cmd, *params, rcvbuf[SIZE_OF_RCVBUFFER]; int c, cmdno, rv; size_t i, cmdlen; socklen_t asz; @@ -2012,7 +2017,7 @@ void *ftp_client_thread(SOCKET *s) break; }; - WorkerThreadCleanup(&ctx); + ftp_worker_thread_cleanup(&ctx); pthread_mutex_destroy(&ctx.MTLock); pthread_mutexattr_destroy(&m_attr); @@ -2029,6 +2034,20 @@ void *ftp_client_thread(SOCKET *s) return NULL; } +void socket_set_keepalive(int s) { + int opt = 1; + setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt)); + + opt = 16; /* set idle status after 16 seconds since last data transfer */; + setsockopt(s, IPPROTO_TCP, TCP_KEEPIDLE, &opt, sizeof(opt)); + + opt = 8; /* send keep alive packet every eight seconds */ + setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, &opt, sizeof(opt)); + + opt = 8; /* drop after eight unanswered packets */ + setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, &opt, sizeof(opt)); +} + void *ftpmain(void *p) { struct sockaddr_in laddr; @@ -2081,6 +2100,9 @@ void *ftpmain(void *p) for (i=0; i #include #include -#include +#include #include #include +#ifdef __CYGWIN__ +#define TCP_KEEPCNT 8 +#define TCP_KEEPINTVL 150 +#define TCP_KEEPIDLE 14400 +#endif + typedef struct _FTP_CONFIG { char *ConfigFile; unsigned int MaxUsers; + unsigned int EnableKeepalive; in_port_t Port; in_port_t PasvPortBase; in_port_t PasvPortMax; @@ -44,15 +51,15 @@ typedef struct _FTP_CONFIG { in_addr_t LocalIPMask; } FTP_CONFIG, *PFTP_CONFIG; -#define CONFIG_FILE_NAME "fftp.conf" -#define CONFIG_SECTION_NAME "ftpconfig" -#define DEFAULT_FTP_PORT 21 +#define CONFIG_FILE_NAME "fftp.conf" +#define CONFIG_SECTION_NAME "ftpconfig" +#define DEFAULT_FTP_PORT 21 -#define INVALID_SOCKET -1 -#define SOCKET int +#define INVALID_SOCKET -1 +#define SOCKET int -#define MODE_NORMAL 0 -#define MODE_PASSIVE 1 +#define MODE_NORMAL 0 +#define MODE_PASSIVE 1 /* * NOT_LOGGED_IN = "banned" in config. Not logged in or banned. @@ -68,9 +75,8 @@ typedef struct _FTP_CONFIG { #define TRANSMIT_BUFFER_SIZE 65536 -static const unsigned long int FTP_PATH_MAX = PATH_MAX; - -#define SIZE_OF_GPBUFFER 4*FTP_PATH_MAX +#define SIZE_OF_RCVBUFFER 2*PATH_MAX +#define SIZE_OF_GPBUFFER 4*PATH_MAX typedef struct _FTPCONTEXT { pthread_mutex_t MTLock; @@ -110,6 +116,8 @@ extern void *ftpmain(void *p); extern gnutls_certificate_credentials_t x509_cred; extern gnutls_priority_t priority_cache; +extern const char shortmonths[12][4]; + #define MAX_CMDS 32 int ftpUSER (PFTPCONTEXT context, const char *params); @@ -145,57 +153,46 @@ int ftpEPSV (PFTPCONTEXT context, const char *params); int ftpHELP (PFTPCONTEXT context, const char *params); int ftpSITE (PFTPCONTEXT context, const char *params); -static const char success200[] = "200 Command okay.\r\n"; -static const char success200_1[] = "200 Type set to A.\r\n"; -static const char success200_2[] = "200 Type set to I.\r\n"; -static const char success211[] = - "211-Extensions supported:\r\n PASV\r\n UTF8\r\n TVFS\r\n REST STREAM\r\n " - "SIZE\r\n MLSD\r\n AUTH TLS\r\n PBSZ\r\n PROT\r\n EPSV\r\n" - "211 End.\r\n"; - -static const char success214[] = - "214-The following commands are recognized.\r\n" - " ABOR APPE AUTH CDUP CWD DELE EPSV FEAT HELP LIST MKD MLSD NOOP OPTS\r\n" - " PASS PASV PBSZ PORT PROT PWD QUIT REST RETR RMD RNFR RNTO SITE SIZE\r\n" - " STOR SYST TYPE USER\r\n" - "214 Help OK.\r\n"; - -static const char success215[] = "215 UNIX Type: L8\r\n"; -static const char success220[] = "220 LightFTP server v2.0a ready\r\n"; -static const char success221[] = "221 Goodbye!\r\n"; -static const char success226[] = "226 Transfer complete. Closing data connection.\r\n"; -static const char success227[] = "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n"; -static const char success229[] = "229 Entering Extended Passive Mode (|||%u|)\r\n"; -static const char success230[] = "230 User logged in, proceed.\r\n"; -static const char success234[] = "234 AUTH command OK. Initializing TLS connection.\r\n"; -static const char success250[] = "250 Requested file action okay, completed.\r\n"; -static const char success257[] = "257 Directory created.\r\n"; -static const char error425[] = "425 Can not open data connection.\r\n"; -static const char error426[] = "426 Connection closed; transfer aborted.\r\n"; -static const char error451[] = "451 Requested action aborted. Local error in processing.\r\n"; -static const char error500[] = "500 Syntax error, command unrecognized.\r\n"; -static const char error500_auth[] = "500 AUTH unsuccessful.\r\n"; -static const char error501[] = "501 Syntax error in parameters or arguments.\r\n"; -static const char error503[] = "503 Invalid sequence of commands (AUTH TLS required prior to authentication).\r\n"; -static const char error504[] = "504 Command not implemented for that parameter.\r\n"; -static const char error530[] = "530 Please login with USER and PASS.\r\n"; -static const char error530_b[] = "530 This account is disabled.\r\n"; -static const char error530_r[] = "530 Invalid user name or password.\r\n"; -static const char error550[] = "550 File or directory unavailable.\r\n"; -static const char error550_r[] = "550 Permission denied.\r\n"; -static const char error550_a[] = "550 Data channel was closed by ABOR command from client.\r\n"; -static const char error550_t[] = "550 Another action is in progress, use ABOR command first.\r\n"; -static const char error550_m[] = "550 Insufficient resources.\r\n"; -static const char interm125[] = "125 Data connection already open; Transfer starting.\r\n"; -static const char interm150[] = "150 File status okay; about to open data connection.\r\n"; -static const char interm350[] = "350 REST supported. Ready to resume at byte offset "; -static const char interm350_ren[] = "350 File exists. Ready to rename.\r\n"; -static const char interm331[] = "331 User "; -static const char interm331_tail[] = " OK. Password required\r\n"; -static const char NOSLOTS[] = "MAXIMUM ALLOWED USERS CONNECTED\r\n"; - -static const char shortmonths[12][4] = { - "Jan\0", "Feb\0", "Mar\0", "Apr\0", "May\0", "Jun\0", - "Jul\0", "Aug\0", "Sep\0", "Oct\0", "Nov\0", "Dec\0"}; +#define success200 "200 Command okay.\r\n" +#define success200_1 "200 Type set to A.\r\n" +#define success200_2 "200 Type set to I.\r\n" + +extern const char success211[]; +extern const char success214[]; + +#define success215 "215 UNIX Type: L8\r\n" +#define success220 "220 LightFTP server v2.0b ready\r\n" +#define success221 "221 Goodbye!\r\n" +#define success226 "226 Transfer complete. Closing data connection.\r\n" +#define success227 "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n" +#define success229 "229 Entering Extended Passive Mode (|||%u|)\r\n" +#define success230 "230 User logged in, proceed.\r\n" +#define success234 "234 AUTH command OK. Initializing TLS connection.\r\n" +#define success250 "250 Requested file action okay, completed.\r\n" +#define success257 "257 Directory created.\r\n" +#define error425 "425 Can not open data connection.\r\n" +#define error426 "426 Connection closed; transfer aborted.\r\n" +#define error451 "451 Requested action aborted. Local error in processing.\r\n" +#define error500 "500 Syntax error, command unrecognized.\r\n" +#define error500_auth "500 AUTH unsuccessful.\r\n" +#define error501 "501 Syntax error in parameters or arguments.\r\n" +#define error503 "503 Invalid sequence of commands (AUTH TLS required prior to authentication).\r\n" +#define error504 "504 Command not implemented for that parameter.\r\n" +#define error530 "530 Please login with USER and PASS.\r\n" +#define error530_b "530 This account is disabled.\r\n" +#define error530_r "530 Invalid user name or password.\r\n" +#define error550 "550 File or directory unavailable.\r\n" +#define error550_r "550 Permission denied.\r\n" +#define error550_a "550 Data channel was closed by ABOR command from client.\r\n" +#define error550_t "550 Another action is in progress, use ABOR command first.\r\n" +#define error550_m "550 Insufficient resources.\r\n" +#define interm125 "125 Data connection already open; Transfer starting.\r\n" +#define interm150 "150 File status okay; about to open data connection.\r\n" +#define interm350 "350 REST supported. Ready to resume at byte offset " +#define interm350_ren "350 File exists. Ready to rename.\r\n" +#define interm331 "331 User " +#define interm331_tail " OK. Password required\r\n" + +#define NOSLOTS "MAXIMUM ALLOWED USERS CONNECTED\r\n" #endif /* FTPSERV_H_ */ diff --git a/Source/main.c b/Source/main.c index eaa1a55..41f7e51 100644 --- a/Source/main.c +++ b/Source/main.c @@ -3,7 +3,7 @@ * * Created on: Aug 20, 2016 * -* Modified on: Jun 06, 2018 +* Modified on: May 15, 2020 * * Author: lightftp */ @@ -12,64 +12,19 @@ #include "cfgparse.h" #include "x_malloc.h" -FTP_CONFIG g_cfg; -int g_log = -1; +FTP_CONFIG g_cfg; +int g_log = -1; + +static char CAFILE[PATH_MAX], CERTFILE[PATH_MAX], KEYFILE[PATH_MAX], KEYFILE_PASS[256]; gnutls_dh_params_t dh_params = NULL; gnutls_certificate_credentials_t x509_cred = NULL; gnutls_priority_t priority_cache = NULL; -static char CAFILE[PATH_MAX], - CERTFILE[PATH_MAX], - KEYFILE[PATH_MAX], - KEYFILE_PASS[256]; - -void TLSInit() -{ - while (gnutls_global_init() >= 0) - { - if (gnutls_certificate_allocate_credentials(&x509_cred) < 0) - break; - - if (gnutls_certificate_set_x509_trust_file(x509_cred, CAFILE, - GNUTLS_X509_FMT_PEM) < 0) - break; - - if (gnutls_certificate_set_x509_key_file2(x509_cred, CERTFILE, - KEYFILE, GNUTLS_X509_FMT_PEM, KEYFILE_PASS, 0) < 0) - break; - - if (gnutls_priority_init(&priority_cache, NULL, NULL) < 0) - break; - -#if GNUTLS_VERSION_NUMBER >= 0x030506 - gnutls_certificate_set_known_dh_params(x509_cred, GNUTLS_SEC_PARAM_HIGH); -#else - gnutls_dh_params_init(&dh_params); - gnutls_dh_params_generate2(dh_params, - gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_HIGH)); - gnutls_certificate_set_dh_params(x509_cred, dh_params); -#endif - break; - } -} - -void TLSCleanup() -{ -#if GNUTLS_VERSION_NUMBER < 0x030506 - if ( dh_params != NULL) - gnutls_dh_params_deinit(dh_params); -#endif - - if ( x509_cred != NULL ) - gnutls_certificate_free_credentials(x509_cred); - - if ( priority_cache != NULL ) - gnutls_priority_deinit(priority_cache); - - gnutls_global_deinit(); -} +void ftp_tls_init(); +void ftp_tls_cleanup(); +/* Program entry point */ int main(int argc, char *argv[]) { char *cfg = NULL, *textbuf = NULL; @@ -77,6 +32,8 @@ int main(int argc, char *argv[]) uint32_t bufsize = 65536; pthread_t thid; + struct in_addr na; + if (sizeof (off_t) != 8) { printf("off_t is not 64 bits long"); @@ -84,9 +41,9 @@ int main(int argc, char *argv[]) } if (argc > 1) - cfg = InitConfig(argv[1]); + cfg = config_init(argv[1]); else - cfg = InitConfig(CONFIG_FILE_NAME); + cfg = config_init(CONFIG_FILE_NAME); while (cfg != NULL) { @@ -95,40 +52,44 @@ int main(int argc, char *argv[]) g_cfg.ConfigFile = cfg; g_cfg.BindToInterface = inet_addr("127.0.0.1"); - if (ParseConfig(cfg, CONFIG_SECTION_NAME, "interface", textbuf, bufsize)) + if (config_parse(cfg, CONFIG_SECTION_NAME, "interface", textbuf, bufsize)) g_cfg.BindToInterface = inet_addr(textbuf); g_cfg.ExternalInterface = inet_addr("0.0.0.0"); - if (ParseConfig(cfg, CONFIG_SECTION_NAME, "external_ip", textbuf, bufsize)) + if (config_parse(cfg, CONFIG_SECTION_NAME, "external_ip", textbuf, bufsize)) g_cfg.ExternalInterface = inet_addr(textbuf); g_cfg.LocalIPMask = inet_addr("255.255.255.0"); - if (ParseConfig(cfg, CONFIG_SECTION_NAME, "local_mask", textbuf, bufsize)) + if (config_parse(cfg, CONFIG_SECTION_NAME, "local_mask", textbuf, bufsize)) g_cfg.LocalIPMask = inet_addr(textbuf); g_cfg.Port = DEFAULT_FTP_PORT; - if (ParseConfig(cfg, CONFIG_SECTION_NAME, "port", textbuf, bufsize)) + if (config_parse(cfg, CONFIG_SECTION_NAME, "port", textbuf, bufsize)) g_cfg.Port = strtoul(textbuf, NULL, 10); g_cfg.MaxUsers = 1; - if (ParseConfig(cfg, CONFIG_SECTION_NAME, "maxusers", textbuf, bufsize)) + if (config_parse(cfg, CONFIG_SECTION_NAME, "maxusers", textbuf, bufsize)) g_cfg.MaxUsers = strtoul(textbuf, NULL, 10); + g_cfg.EnableKeepalive = 0; + if (config_parse(cfg, CONFIG_SECTION_NAME, "keepalive", textbuf, bufsize)) + g_cfg.EnableKeepalive = strtoul(textbuf, NULL, 10); + g_cfg.PasvPortBase = 1024; - if (ParseConfig(cfg, CONFIG_SECTION_NAME, "minport", textbuf, bufsize)) + if (config_parse(cfg, CONFIG_SECTION_NAME, "minport", textbuf, bufsize)) g_cfg.PasvPortBase = strtoul(textbuf, NULL, 10); g_cfg.PasvPortMax = 65535; - if (ParseConfig(cfg, CONFIG_SECTION_NAME, "maxport", textbuf, bufsize)) + if (config_parse(cfg, CONFIG_SECTION_NAME, "maxport", textbuf, bufsize)) g_cfg.PasvPortMax = strtoul(textbuf, NULL, 10); - ParseConfig(cfg, CONFIG_SECTION_NAME, "CATrustFile", CAFILE, sizeof(CAFILE)); - ParseConfig(cfg, CONFIG_SECTION_NAME, "ServerCertificate", CERTFILE, sizeof(CERTFILE)); - ParseConfig(cfg, CONFIG_SECTION_NAME, "Keyfile", KEYFILE, sizeof(KEYFILE)); - ParseConfig(cfg, CONFIG_SECTION_NAME, "KeyfilePassword", KEYFILE_PASS, sizeof(KEYFILE_PASS)); + config_parse(cfg, CONFIG_SECTION_NAME, "CATrustFile", CAFILE, sizeof(CAFILE)); + config_parse(cfg, CONFIG_SECTION_NAME, "ServerCertificate", CERTFILE, sizeof(CERTFILE)); + config_parse(cfg, CONFIG_SECTION_NAME, "Keyfile", KEYFILE, sizeof(KEYFILE)); + config_parse(cfg, CONFIG_SECTION_NAME, "KeyfilePassword", KEYFILE_PASS, sizeof(KEYFILE_PASS)); memset(textbuf, 0, bufsize); - if (ParseConfig(cfg, CONFIG_SECTION_NAME, "logfilepath", textbuf, bufsize)) + if (config_parse(cfg, CONFIG_SECTION_NAME, "logfilepath", textbuf, bufsize)) { g_log = open(textbuf, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR); if (g_log == -1) @@ -155,23 +116,12 @@ int main(int argc, char *argv[]) else printf("Config file : %s/%s\r\n", textbuf, CONFIG_FILE_NAME); - printf("Interface ipv4 : %u.%u.%u.%u\r\n", - g_cfg.BindToInterface & 0xff, - (g_cfg.BindToInterface >> 8) & 0xff, - (g_cfg.BindToInterface >> 16) & 0xff, - (g_cfg.BindToInterface >> 24) & 0xff); - - printf("Interface mask : %u.%u.%u.%u\r\n", - g_cfg.LocalIPMask & 0xff, - (g_cfg.LocalIPMask >> 8) & 0xff, - (g_cfg.LocalIPMask >> 16) & 0xff, - (g_cfg.LocalIPMask >> 24) & 0xff); - - printf("External ipv4 : %u.%u.%u.%u\r\n", - g_cfg.ExternalInterface & 0xff, - (g_cfg.ExternalInterface >> 8) & 0xff, - (g_cfg.ExternalInterface >> 16) & 0xff, - (g_cfg.ExternalInterface >> 24) & 0xff); + na.s_addr = g_cfg.BindToInterface; + printf("Interface ipv4 : %s\r\n", inet_ntoa(na)); + na.s_addr = g_cfg.LocalIPMask; + printf("Interface mask : %s\r\n", inet_ntoa(na)); + na.s_addr = g_cfg.ExternalInterface; + printf("External ipv4 : %s\r\n", inet_ntoa(na)); printf("Port : %u\r\n", g_cfg.Port); printf("Max users : %u\r\n", g_cfg.MaxUsers); @@ -179,7 +129,7 @@ int main(int argc, char *argv[]) printf("\r\n TYPE q or Ctrl+C to terminate >\r\n"); - TLSInit(); + ftp_tls_init(); thid = (pthread_t)0; if (pthread_create(&thid, NULL, &ftpmain, NULL) != 0) @@ -208,7 +158,50 @@ int main(int argc, char *argv[]) if (textbuf != NULL) free(textbuf); - TLSCleanup(); + ftp_tls_cleanup(); exit(2); } + +void ftp_tls_init() +{ + while (gnutls_global_init() >= 0) + { + if (gnutls_certificate_allocate_credentials(&x509_cred) < 0) + break; + + if (gnutls_certificate_set_x509_trust_file(x509_cred, CAFILE, GNUTLS_X509_FMT_PEM) < 0) + break; + + if (gnutls_certificate_set_x509_key_file2(x509_cred, CERTFILE, KEYFILE, GNUTLS_X509_FMT_PEM, KEYFILE_PASS, 0) < 0) + break; + + if (gnutls_priority_init(&priority_cache, NULL, NULL) < 0) + break; + +#if GNUTLS_VERSION_NUMBER >= 0x030506 + gnutls_certificate_set_known_dh_params(x509_cred, GNUTLS_SEC_PARAM_HIGH); +#else + gnutls_dh_params_init(&dh_params); + gnutls_dh_params_generate2(dh_params, gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_HIGH)); + gnutls_certificate_set_dh_params(x509_cred, dh_params); +#endif + break; + } +} + +void ftp_tls_cleanup() +{ +#if GNUTLS_VERSION_NUMBER < 0x030506 + if ( dh_params != NULL) + gnutls_dh_params_deinit(dh_params); +#endif + + if ( x509_cred != NULL ) + gnutls_certificate_free_credentials(x509_cred); + + if ( priority_cache != NULL ) + gnutls_priority_deinit(priority_cache); + + gnutls_global_deinit(); +} From eed1be1e5a514cbc9dc5c360496d879b6ff44492 Mon Sep 17 00:00:00 2001 From: hfiref0x Date: Sun, 17 May 2020 16:57:56 +0700 Subject: [PATCH 2/4] v 2.1.0.2005 Refactoring as of 17/05/20 --- Source.sha256 | 20 +- Source/Debug/makefile | 2 +- Source/Debug/subdir.mk | 5 +- Source/Release/makefile | 2 +- Source/Release/subdir.mk | 5 +- Source/changelog.txt | 4 +- Source/fspathtools.c | 200 ++++++++++++++++ Source/fspathtools.h | 16 ++ Source/ftpserv.c | 489 +++++++++------------------------------ Source/ftpserv.h | 229 +++++++++--------- Source/main.c | 2 +- Source/x_malloc.c | 8 +- 12 files changed, 470 insertions(+), 512 deletions(-) create mode 100644 Source/fspathtools.c create mode 100644 Source/fspathtools.h diff --git a/Source.sha256 b/Source.sha256 index a6c84e2..2c36f96 100644 --- a/Source.sha256 +++ b/Source.sha256 @@ -1,17 +1,19 @@ 18364d8691f4bb9ec5f684940e05ddd70de658446417c1f6071a21ad7f4b3717 *Source\cfgparse.c fb951da7cb5aa17b79cc455bbcb3d7a3ef09182db34298a921138bdd9950cd17 *Source\cfgparse.h -d6991972944b42bfb5474daf0790ce0e3ea4f3ad91624266a6023ab7360dd13f *Source\changelog.txt +e0013dc69f2e46b70c360611463886be20b382709ef7c3c954bd3ab8963370b3 *Source\changelog.txt 5f60ff45d21faa296673f793d6afef8a0c2c9b97a7b0aa51134750f7158f15c2 *Source\fftp.conf +c02df4fe98511859d400a4357c66720254f8b7053f8655f26e6842ba6022227a *Source\fspathtools.c +6a6f5df59cb19f62a964312a5efc1d285eba1d1a97563e4214c5b41666baf0ee *Source\fspathtools.h 552be952422a3e3959e4f130be0c7fdff6ab0ef124eb161df21b0a264b0b2a32 *Source\ftpconst.c -aa77de70e59e57b66e40af615b1667396f4b9ec621f33534eeb37240dcdcc155 *Source\ftpserv.c -550e697017735ff7bcca2d3d54748dc18aeba488c935867333e66426df22529e *Source\ftpserv.h -4bc1fd1c591407b485d6f3af44d06b07682a342cc1c43a47ff04c465182204a6 *Source\main.c -c152edb89faf8a2b57039ce1507b57025d2fa91ae7076b7f0bb6dd066dbe7cfd *Source\x_malloc.c +a8f896fe8fc640aa71335d1a6269ff790d9b7a4ed6379eeed86d2deca7234c7c *Source\ftpserv.c +111269c386d9c6a34ebc12b4d51785ade70cc606d67d5840ab4e8c65d279e837 *Source\ftpserv.h +eaff0ee73df59a2c5b53d12d65a62bc74023296099b93869c2192f69c21b1a93 *Source\main.c +106d68ea37dd580b94c15cf1ca800929ccf92168d5b4794ea884916c8cc440bf *Source\x_malloc.c 79876657549a772e6e48fdacc83f18352ad9a23529cab840e169fdfe62d6a01e *Source\x_malloc.h -65c2c882ead0e9266325893b457b8506db2a081eb3936939dedfce52c22c31ea *Source\Debug\makefile +2850a07ea90193cc0206674ad1b62a0df01b343c7b5e548f7ecaca616ffb3a07 *Source\Debug\makefile fa3d96ba5c45cb2b0004c8ea687045e16768ec90ec788f0958905083164e52f1 *Source\Debug\objects.mk 45bf7584af2acb3c6c806bd48b0774c661e081efdaff00d735554cde1ed76fbb *Source\Debug\sources.mk -0a6c6e465f4cfe0596e63b325d6170a9eab1598880005d4f7e41749899769ee3 *Source\Debug\subdir.mk +7f0e62dea14799046248c445771acf51b0e1015cb8512449ddf8c681a01bfa5c *Source\Debug\subdir.mk 71f29f165b2554ec548bc56a113f38c0c993c2b34265acfd6d4c64a05f3db1ef *Source\Deprecated\Windows\fftp.sln 8708f082b6072e0ab2c55984c2bd252f80049f2d4dceabf6fd8cf4815331cf7f *Source\Deprecated\Windows\fftp\debug.conf 6315323d32acdc93160ed785f82631e686645370ae62082199f5c8000fc98e08 *Source\Deprecated\Windows\fftp\fftp.vcxproj @@ -36,9 +38,9 @@ ef1b18997ea473ac8d516ef60efc64b9175418b8f078e088d783fdaef2544969 *Source\Depreca 60f19c6b805801e13824c4d9d44748da8245cd936971411d3d36b873121888eb *Source\Deprecated\Windows\fftp\minirtl\_strlen.c 87cc72bb8e3f1534bee09ee278ecd928d975ebb94aeffc767b67249815a0bf3a *Source\Deprecated\Windows\fftp\minirtl\_strncmpi.c 0434d69daa20fbf87d829ffc17e43dcc2db3386aff434af888011fdec2f645a4 *Source\Deprecated\Windows\fftp\minirtl\_strncpy.c -65c2c882ead0e9266325893b457b8506db2a081eb3936939dedfce52c22c31ea *Source\Release\makefile +2850a07ea90193cc0206674ad1b62a0df01b343c7b5e548f7ecaca616ffb3a07 *Source\Release\makefile fa3d96ba5c45cb2b0004c8ea687045e16768ec90ec788f0958905083164e52f1 *Source\Release\objects.mk 45bf7584af2acb3c6c806bd48b0774c661e081efdaff00d735554cde1ed76fbb *Source\Release\sources.mk -ba65327d3b42305556a1dbcb6d4329148a245a2d02e00ae332d8a3825fade5d1 *Source\Release\subdir.mk +c8a7f73c7aa597f350c40cb64a7dd4b51ad68862f46cc7ee8d3d5a0ea77f7e47 *Source\Release\subdir.mk f7d0ab874ee47ea673ddcdd3dfd9662646f9c1a796b94f3e1b33e1321baf52c3 *Source\TLS-cert\gencert.sh f3c8e1fdc3b05facb5e87ef1fc11b5fc1ee4d1d4832578f4fc1c23ecd488bab4 *Source\TLS-cert\mycert-req.txt diff --git a/Source/Debug/makefile b/Source/Debug/makefile index 2241106..97fa904 100644 --- a/Source/Debug/makefile +++ b/Source/Debug/makefile @@ -28,7 +28,7 @@ all: fftp fftp: $(OBJS) $(USER_OBJS) @echo 'Building target: $@' @echo 'Invoking: GCC C Linker' - gcc -o "fftp" $(OBJS) $(USER_OBJS) $(LIBS) + gcc -pthread -o "fftp" $(OBJS) $(USER_OBJS) $(LIBS) @echo 'Finished building target: $@' @echo ' ' diff --git a/Source/Debug/subdir.mk b/Source/Debug/subdir.mk index 5f57e0c..604a440 100644 --- a/Source/Debug/subdir.mk +++ b/Source/Debug/subdir.mk @@ -5,6 +5,7 @@ # Add inputs and outputs from these tool invocations to the build variables C_SRCS += \ ../cfgparse.c \ +../fspathtools.c \ ../ftpconst.c \ ../ftpserv.c \ ../main.c \ @@ -12,6 +13,7 @@ C_SRCS += \ OBJS += \ ./cfgparse.o \ +./fspathtools.o \ ./ftpconst.o \ ./ftpserv.o \ ./main.o \ @@ -19,6 +21,7 @@ OBJS += \ C_DEPS += \ ./cfgparse.d \ +./fspathtools.d \ ./ftpconst.d \ ./ftpserv.d \ ./main.d \ @@ -29,7 +32,7 @@ C_DEPS += \ %.o: ../%.c @echo 'Building file: $<' @echo 'Invoking: GCC C Compiler' - gcc -std=c99 -O0 -g3 -Wall -pthread -c -fmessage-length=0 -fno-ident -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + gcc -std=c99 -D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -O0 -g3 -pedantic -Wall -Wextra -Wno-unused-parameter -c -fmessage-length=0 -fno-ident -D_GNU_SOURCE -v -pthread -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" @echo 'Finished building: $<' @echo ' ' diff --git a/Source/Release/makefile b/Source/Release/makefile index 2241106..97fa904 100644 --- a/Source/Release/makefile +++ b/Source/Release/makefile @@ -28,7 +28,7 @@ all: fftp fftp: $(OBJS) $(USER_OBJS) @echo 'Building target: $@' @echo 'Invoking: GCC C Linker' - gcc -o "fftp" $(OBJS) $(USER_OBJS) $(LIBS) + gcc -pthread -o "fftp" $(OBJS) $(USER_OBJS) $(LIBS) @echo 'Finished building target: $@' @echo ' ' diff --git a/Source/Release/subdir.mk b/Source/Release/subdir.mk index cc9764b..8818522 100644 --- a/Source/Release/subdir.mk +++ b/Source/Release/subdir.mk @@ -5,6 +5,7 @@ # Add inputs and outputs from these tool invocations to the build variables C_SRCS += \ ../cfgparse.c \ +../fspathtools.c \ ../ftpconst.c \ ../ftpserv.c \ ../main.c \ @@ -12,6 +13,7 @@ C_SRCS += \ OBJS += \ ./cfgparse.o \ +./fspathtools.o \ ./ftpconst.o \ ./ftpserv.o \ ./main.o \ @@ -19,6 +21,7 @@ OBJS += \ C_DEPS += \ ./cfgparse.d \ +./fspathtools.d \ ./ftpconst.d \ ./ftpserv.d \ ./main.d \ @@ -29,7 +32,7 @@ C_DEPS += \ %.o: ../%.c @echo 'Building file: $<' @echo 'Invoking: GCC C Compiler' - gcc -std=c99 -O3 -Wall -Wextra -c -fmessage-length=0 -Wno-unused-parameter -Wno-unused-result -fno-ident -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" + gcc -std=c99 -D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -O3 -pedantic -Wall -Wextra -c -fmessage-length=0 -Wno-unused-parameter -Wno-unused-result -fno-ident -v -pthread -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" @echo 'Finished building: $<' @echo ' ' diff --git a/Source/changelog.txt b/Source/changelog.txt index c7dc387..d54ef2c 100644 --- a/Source/changelog.txt +++ b/Source/changelog.txt @@ -2,8 +2,8 @@ - Removed * Fixed/Changed -May 15, 2020, v2.0b -* bugfixes +May 17, 2020, v2.1 +* bugfixes and refactoring Jun 28, 2018, v2.0a diff --git a/Source/fspathtools.c b/Source/fspathtools.c new file mode 100644 index 0000000..f141e7a --- /dev/null +++ b/Source/fspathtools.c @@ -0,0 +1,200 @@ +/* + * fspathtools.c + * + * Created on: May 17, 2020 + * Author: lightftp + */ + +#include +#include +#include +#include + +#include "x_malloc.h" + +char *filepath(char *s) +{ + char *p = s; + + if (*s == 0) + return s; +/* + * leave root directory sign untouched + */ + if (*s == '/') + { + ++s; + ++p; + } + + while (*s != 0) { + if (*s == '/') + p = s; + ++s; + } + + *p = 0; + + return p; +} + +typedef struct _ftp_path_node { + char *value; + size_t length; + struct _ftp_path_node *next; + struct _ftp_path_node *prev; +} ftp_path_node, *pftp_path_node; + +/* + Path normalization routine: + Removes garbage like "/", "///" or "." etc. and correctly resolves ".." +*/ + +int ftp_normalize_path(char* path, size_t npath_len, char* npath) +{ + char* p0; + size_t node_len; + int status = 1; + pftp_path_node nodes = NULL, newnode; + + if ((path == NULL) || (npath == NULL) || (npath_len < 2)) + return 0; + + if (*path == '/') + { + *npath = '/'; + ++path; + ++npath; + --npath_len; + } + + p0 = path; + + while (*path != 0) + { + while ((*path != '/') && (*path != '\0')) + ++path; + + node_len = path - p0; + + while (node_len > 0) + { + /* we have a "this dir" sign: just skip it */ + if (strncmp(p0, ".", node_len) == 0) + break; + + if (strncmp(p0, "..", node_len) == 0) + { + /* we have a "dir-up" sign: unlink and free prev node */ + if (nodes) + { + newnode = nodes->prev; + free(nodes); + if (newnode) + newnode->next = NULL; + nodes = newnode; + } + } + else + { + newnode = x_malloc(sizeof(ftp_path_node)); + newnode->value = p0; + newnode->length = node_len; + newnode->next = NULL; + newnode->prev = nodes; + + if (nodes) + nodes->next = newnode; + + nodes = newnode; + } + + break; + } + + if (*path != 0) + ++path; + + p0 = path; + } + + /* return to head */ + newnode = nodes; + while (newnode) + { + nodes = newnode; + newnode = newnode->prev; + } + + while (nodes) + { + if (npath_len < nodes->length + 1) + { + status = 0; + break; + } + + strncpy(npath, nodes->value, nodes->length); + npath += nodes->length; + *npath = '/'; + ++npath; + npath_len -= nodes->length + 1; + + newnode = nodes; + nodes = newnode->next; + free(newnode); + } + + /* free the remaining nodes in case of break */ + while (nodes) + { + newnode = nodes; + nodes = newnode->next; + free(newnode); + } + + if ((npath_len == 0) || (status == 0)) + return 0; + + *npath = '\0'; + return 1; +} + +int ftp_effective_path(char *root_path, char *current_path, + char *file_path, size_t result_size, char *result) +{ + char path[PATH_MAX], npath[PATH_MAX]; + int status; + size_t len; + + memset(result, 0, result_size); + + if (file_path == NULL) + file_path = ""; + + if (*file_path == '/') + { + status = ftp_normalize_path(file_path, PATH_MAX, npath); + } + else + { + snprintf(path, PATH_MAX, "%s/%s", current_path, file_path); + status = ftp_normalize_path(path, PATH_MAX, npath); + } + + if (status == 0) + return 0; + + snprintf(path, PATH_MAX, "%s/%s", root_path, npath); + status = ftp_normalize_path(path, result_size, result); + + /* delete last slash */ + len = strlen(result); + if (len >= 2) + { + if (result[len-1] == '/') + result[len-1] = '\0'; + } + + return status; +} diff --git a/Source/fspathtools.h b/Source/fspathtools.h new file mode 100644 index 0000000..25ed539 --- /dev/null +++ b/Source/fspathtools.h @@ -0,0 +1,16 @@ +/* + * fspathtools.h + * + * Created on: May 17, 2020 + * Author: lightftp + */ + +#ifndef FSPATHTOOLS_H_ +#define FSPATHTOOLS_H_ + +char *filepath(char *s); +int ftp_normalize_path(char* path, size_t npath_len, char* npath); +int ftp_effective_path(char *root_path, char *current_path, + const char *file_path, size_t result_size, char *result); + +#endif /* FSPATHTOOLS_H_ */ diff --git a/Source/ftpserv.c b/Source/ftpserv.c index 2daa723..7d69774 100644 --- a/Source/ftpserv.c +++ b/Source/ftpserv.c @@ -11,200 +11,27 @@ #include "ftpserv.h" #include "cfgparse.h" #include "x_malloc.h" - -static const FTPROUTINE ftpprocs[MAX_CMDS] = { - ftpUSER, ftpQUIT, ftpNOOP, ftpPWD, ftpTYPE, ftpPORT, ftpLIST, ftpCDUP, - ftpCWD, ftpRETR, ftpABOR, ftpDELE, ftpPASV, ftpPASS, ftpREST, ftpSIZE, - ftpMKD, ftpRMD, ftpSTOR, ftpSYST, ftpFEAT, ftpAPPE, ftpRNFR, ftpRNTO, - ftpOPTS, ftpMLSD, ftpAUTH, ftpPBSZ, ftpPROT, ftpEPSV, ftpHELP, ftpSITE -}; - -static const char *ftpcmds[MAX_CMDS] = { - "USER", "QUIT", "NOOP", "PWD", "TYPE", "PORT", "LIST", "CDUP", - "CWD", "RETR", "ABOR", "DELE", "PASV", "PASS", "REST", "SIZE", - "MKD", "RMD", "STOR", "SYST", "FEAT", "APPE", "RNFR", "RNTO", - "OPTS", "MLSD", "AUTH", "PBSZ", "PROT", "EPSV", "HELP", "SITE" +#include "fspathtools.h" + +static const FTPROUTINE_ENTRY ftpprocs[MAX_CMDS] = { + {"USER", ftpUSER}, {"QUIT", ftpQUIT}, {"NOOP", ftpNOOP}, {"PWD", ftpPWD }, + {"TYPE", ftpTYPE}, {"PORT", ftpPORT}, {"LIST", ftpLIST}, {"CDUP", ftpCDUP}, + {"CWD", ftpCWD }, {"RETR", ftpRETR}, {"ABOR", ftpABOR}, {"DELE", ftpDELE}, + {"PASV", ftpPASV}, {"PASS", ftpPASS}, {"REST", ftpREST}, {"SIZE", ftpSIZE}, + {"MKD", ftpMKD }, {"RMD", ftpRMD }, {"STOR", ftpSTOR}, {"SYST", ftpSYST}, + {"FEAT", ftpFEAT}, {"APPE", ftpAPPE}, {"RNFR", ftpRNFR}, {"RNTO", ftpRNTO}, + {"OPTS", ftpOPTS}, {"MLSD", ftpMLSD}, {"AUTH", ftpAUTH}, {"PBSZ", ftpPBSZ}, + {"PROT", ftpPROT}, {"EPSV", ftpEPSV}, {"HELP", ftpHELP}, {"SITE", ftpSITE} }; /* * FTP_PASSCMD_INDEX - * must be in sync with ftpprocs & ftpcmds "PASS" index + * must be in sync with ftpprocs "PASS" index */ -#define FTP_PASSCMD_INDEX 13 +#define FTP_PASSCMD_INDEX 13 unsigned int g_newid = 0; -void delete_last_slash(char *s) -{ - if (*s != 0) - { - /* - * don't remove root directory sign as special case - */ - if ((s[0] == '/') && (s[1] == 0)) - return; - - while (s[1] != 0) - ++s; - - if (*s == '/') - *s = 0; - } -} - -void add_last_slash(char *s) -{ - if (*s != 0) - { - while (s[1] != 0) - ++s; - - if (*s != '/') - { - s[1] = '/'; - s[2] = 0; - } - } -} - -/* - * Cuts off filename from string leaving only path. - * Return value: pointer to a terminating null character at the end of path - */ -char *filepath(char *s) -{ - char *p = s; - - if (*s == 0) - return s; -/* - * leave root directory sign untouched - */ - if (*s == '/') - { - ++s; - ++p; - } - - while (*s != 0) { - if (*s == '/') - p = s; - ++s; - } - - *p = 0; - - return p; -} - -/* - * This function filters the path out of ".." members - * not allowing user to escape the home directory - */ -void format_path(char *input_path, char *filtered_path) -{ - char *p0, *pnext, *fp0; - size_t sl; - - if (*input_path == '/') - { - ++input_path; - *filtered_path = '/'; - ++filtered_path; - } - - p0 = input_path; - pnext = input_path; - fp0 = filtered_path; - *fp0 = 0; - - while (1) - { - while ((*pnext != '/') && (*pnext != 0)) - ++pnext; - - sl = pnext - p0; - - while (sl > 0) - { - if (sl == 1) - if (*p0 == '.') - break; - - if (sl == 2) - if ((p0[0] == '.') && (p0[1] == '.')) - { - delete_last_slash(filtered_path); - fp0 = filepath(filtered_path); - if (fp0 != filtered_path) - { - *fp0 = '/'; - ++fp0; - *fp0 = 0; - } - break; - } - - strncpy(fp0, p0, sl); - fp0 += sl; - if (*pnext != 0) - { - *fp0 = '/'; - ++fp0; - } - *fp0 = 0; - - break; - } - - if (*pnext == 0) - break; - - ++pnext; - p0 = pnext; - } -} - -char *finalpath(char *root_dir, char *current_dir, char *params, char *result_path) -{ - char *tmp, *user_root; - size_t total_len; - - total_len = strlen(root_dir)+strlen(current_dir); - if (params != NULL) - total_len += strlen(params); - - if (total_len >= SIZE_OF_GPBUFFER) - return NULL; - - tmp = x_malloc(SIZE_OF_GPBUFFER); - - strcpy(result_path, root_dir); - add_last_slash(result_path); - user_root = result_path+strlen(result_path); - - do { - if ( params == NULL ) - { - strcpy(tmp, current_dir); - add_last_slash(tmp); - break; - } - - if ( params[0] != '/' ) - { - strcpy(tmp, current_dir); - add_last_slash(tmp); - } - - strcat(tmp, params); - } while (0); - - format_path(tmp, user_root); - free(tmp); - return result_path; -} - static void cleanup_handler(void *arg) { PFTPCONTEXT context = (PFTPCONTEXT)arg; @@ -347,7 +174,7 @@ ssize_t writeconsolestr(const char *Buffer) int writelogentry(PFTPCONTEXT context, const char *logtext1, const char *logtext2) { - char text[SIZE_OF_GPBUFFER]; + char text[2*PATH_MAX]; time_t itm = time(NULL); struct tm ltm; @@ -414,18 +241,12 @@ int ftpUSER(PFTPCONTEXT context, const char *params) context->Access = FTP_ACCESS_NOT_LOGGED_IN; - /* - * Save username in GPBuffer for next PASS command - */ - writelogentry(context, " USER: ", (char *)params); + snprintf(context->FileName, sizeof(context->FileName), "331 User %s OK. Password required\r\n", params); + sendstring(context, context->FileName); - strcpy(context->GPBuffer, interm331); - strcat(context->GPBuffer, params); - strcat(context->GPBuffer, interm331_tail); - sendstring(context, context->GPBuffer); - - strcpy(context->GPBuffer, params); + /* Save login name to FileName for the next PASS command */ + strcpy(context->FileName, params); return 1; } @@ -433,9 +254,8 @@ int ftpQUIT(PFTPCONTEXT context, const char *params) { writelogentry(context, " QUIT", ""); sendstring(context, success221); - /* - * retrun 0 to break command processing loop - */ + + /* return 0 to break command processing loop */ return 0; } @@ -449,10 +269,9 @@ int ftpPWD(PFTPCONTEXT context, const char *params) if ( context->Access == FTP_ACCESS_NOT_LOGGED_IN ) return sendstring(context, error530); - strcpy(context->GPBuffer, "257 \""); - strcat(context->GPBuffer, context->CurrentDir); - strcat(context->GPBuffer, "\" is a current directory.\r\n"); - return sendstring(context, context->GPBuffer); + /* ftp_effective_path("/", context->CurrentDir, NULL, sizeof(context->FileName), context->FileName); */ + snprintf(context->FileName, sizeof(context->FileName), "257 \"%s\" is a current directory.\r\n", context->CurrentDir); + return sendstring(context, context->FileName); } int ftpTYPE(PFTPCONTEXT context, const char *params) @@ -597,9 +416,7 @@ strmode (mode_t mode, char *str) int list_sub (char *dirname, SOCKET s, gnutls_session_t session, struct dirent *entry) { - char text[SIZE_OF_GPBUFFER], - sacl[12]; - + char text[2*PATH_MAX], sacl[12]; struct stat filestats; struct tm ftm_fields; time_t deltatime; @@ -609,9 +426,7 @@ int list_sub (char *dirname, SOCKET s, gnutls_session_t session, struct dirent * if (strcmp(entry->d_name, "..") == 0) return 1; - strcpy(text, dirname); - add_last_slash(text); - strcat(text, entry->d_name); + snprintf(text, sizeof(text), "%s/%s", dirname, entry->d_name); if ( lstat(text, &filestats) == 0 ) { @@ -664,12 +479,12 @@ void *list_thread(PFTPCONTEXT context) if (context->TLS_session != NULL) ftp_init_tls_session(&TLS_datasession, clientsocket, 0); - pdir = opendir(context->GPBuffer); + pdir = opendir(context->FileName); if (pdir == NULL) break; while ((entry = readdir(pdir)) != NULL) { - ret = list_sub(context->GPBuffer, clientsocket, TLS_datasession, entry); + ret = list_sub(context->FileName, clientsocket, TLS_datasession, entry); if ( (ret == 0) || (context->WorkerThreadAbort != 0 )) break; } @@ -721,13 +536,9 @@ int ftpLIST(PFTPCONTEXT context, const char *params) params = NULL; } - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - while (stat(context->GPBuffer, &filestats) == 0) + while (stat(context->FileName, &filestats) == 0) { if ( !S_ISDIR(filestats.st_mode) ) break; @@ -738,7 +549,7 @@ int ftpLIST(PFTPCONTEXT context, const char *params) pthread_mutex_lock(&context->MTLock); - context->WorkerThreadValid = pthread_create(&tid, NULL, (__ptr_thread_start_routine)&list_thread, context); + context->WorkerThreadValid = pthread_create(&tid, NULL, (void * (*)(void *))list_thread, context); if ( context->WorkerThreadValid == 0 ) context->WorkerThreadId = tid; else @@ -752,6 +563,11 @@ int ftpLIST(PFTPCONTEXT context, const char *params) return sendstring(context, error550); } +/* + * Cuts off filename from string leaving only path. + * Return value: pointer to a terminating null character at the end of path + */ + int ftpCDUP(PFTPCONTEXT context, const char *params) { if ( context->Access == FTP_ACCESS_NOT_LOGGED_IN ) @@ -760,7 +576,6 @@ int ftpCDUP(PFTPCONTEXT context, const char *params) if ( strcmp(context->CurrentDir, "/") == 0 ) return sendstring(context, success250); - delete_last_slash(context->CurrentDir); filepath(context->CurrentDir); writelogentry(context, " CDUP", ""); @@ -770,7 +585,6 @@ int ftpCDUP(PFTPCONTEXT context, const char *params) int ftpCWD(PFTPCONTEXT context, const char *params) { struct stat filestats; - size_t rl; if ( context->Access == FTP_ACCESS_NOT_LOGGED_IN ) return sendstring(context, error530); @@ -778,17 +592,13 @@ int ftpCWD(PFTPCONTEXT context, const char *params) if ( params == NULL ) return sendstring(context, error501); - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - if ( stat(context->GPBuffer, &filestats) == 0 ) + if ( stat(context->FileName, &filestats) == 0 ) if ( S_ISDIR(filestats.st_mode) ) { - rl = strlen(context->RootDir); - strcpy(context->CurrentDir, context->GPBuffer+rl); + ftp_effective_path("/", context->CurrentDir, params, sizeof(context->FileName), context->FileName); + strcpy(context->CurrentDir, context->FileName); writelogentry(context, " CWD: ", context->CurrentDir); return sendstring(context, success250); } @@ -837,7 +647,7 @@ void *retr_thread(PFTPCONTEXT context) else buffer_size = TRANSMIT_BUFFER_SIZE; - f = open(context->GPBuffer, O_RDONLY); + f = open(context->FileName, O_RDONLY); context->File = f; if (f == -1) break; @@ -860,17 +670,6 @@ void *retr_thread(PFTPCONTEXT context) sent_ok = 0; break; } - - /* heartbeat to control channel */ - /* - clock_gettime(CLOCK_MONOTONIC, &t); - if (t.tv_sec >= dtx) - { - dtx += 120; - sendstring(context, "\r\n"); - writelogentry(context, "keepalive sent", ""); - } - */ } /* calculating performance */ @@ -879,7 +678,7 @@ void *retr_thread(PFTPCONTEXT context) lt1 = t.tv_sec*1e9 + t.tv_nsec; dtx = lt1 - lt0; snprintf(buffer, buffer_size, " RETR complete. %zd bytes (%f MBytes) total sent in %f seconds (%f MBytes/s)", - sz_total, sz_total/1048576.0, dtx/1000000000.0, (1000000000.0*sz_total)/dtx/1048576); + sz_total, sz_total/1048576.0f, dtx/1000000000.0f, (1000000000.0f*sz_total)/dtx/1048576.0f); writelogentry(context, buffer, ""); break; @@ -935,13 +734,9 @@ int ftpRETR(PFTPCONTEXT context, const char *params) context->File = -1; } - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - while (stat(context->GPBuffer, &filestats) == 0) + while (stat(context->FileName, &filestats) == 0) { if ( S_ISDIR(filestats.st_mode) ) break; @@ -952,7 +747,7 @@ int ftpRETR(PFTPCONTEXT context, const char *params) pthread_mutex_lock(&context->MTLock); - context->WorkerThreadValid = pthread_create(&tid, NULL, (__ptr_thread_start_routine)&retr_thread, context); + context->WorkerThreadValid = pthread_create(&tid, NULL, (void * (*)(void *))retr_thread, context); if ( context->WorkerThreadValid == 0 ) context->WorkerThreadId = tid; else @@ -985,13 +780,9 @@ int ftpDELE(PFTPCONTEXT context, const char *params) if ( params == NULL ) return sendstring(context, error501); - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - if ( unlink(context->GPBuffer) == 0 ) { + if ( unlink(context->FileName) == 0 ) { sendstring(context, success250); writelogentry(context, " DELE: ", (char *)params); } @@ -1085,20 +876,22 @@ int ftpEPSV (PFTPCONTEXT context, const char *params) if (pasv(context) == 0) return 1; - snprintf(context->GPBuffer, SIZE_OF_GPBUFFER, success229, + snprintf(context->FileName, sizeof(context->FileName), + "229 Entering Extended Passive Mode (|||%u|)\r\n", ntohs(context->DataPort)); writelogentry(context, " entering extended passive mode", ""); - return sendstring(context, context->GPBuffer); + return sendstring(context, context->FileName); } int ftpPASV(PFTPCONTEXT context, const char *params) { - if (pasv(context) == 0) + if (pasv(context) == 0) return 1; - snprintf(context->GPBuffer, SIZE_OF_GPBUFFER, success227, + snprintf(context->FileName, sizeof(context->FileName), + "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n", context->DataIPv4 & 0xff, (context->DataIPv4 >> 8) & 0xff, (context->DataIPv4 >> 16) & 0xff, @@ -1108,7 +901,7 @@ int ftpPASV(PFTPCONTEXT context, const char *params) writelogentry(context, " entering passive mode", ""); - return sendstring(context, context->GPBuffer); + return sendstring(context, context->FileName); } int ftpPASS(PFTPCONTEXT context, const char *params) @@ -1121,9 +914,9 @@ int ftpPASS(PFTPCONTEXT context, const char *params) memset(temptext, 0, sizeof(temptext)); /* - * we have username saved in context->GPBuffer from USER command + * we have login name saved in context->FileName from USER command */ - if (!config_parse(g_cfg.ConfigFile, context->GPBuffer, "pswd", temptext, sizeof(temptext))) + if (!config_parse(g_cfg.ConfigFile, context->FileName, "pswd", temptext, sizeof(temptext))) return sendstring(context, error530_r); if ( (strcmp(temptext, params) == 0) || (temptext[0] == '*') ) @@ -1131,8 +924,8 @@ int ftpPASS(PFTPCONTEXT context, const char *params) memset(context->RootDir, 0, sizeof(context->RootDir)); memset(temptext, 0, sizeof(temptext)); - config_parse(g_cfg.ConfigFile, context->GPBuffer, "root", context->RootDir, sizeof(context->RootDir)); - config_parse(g_cfg.ConfigFile, context->GPBuffer, "accs", temptext, sizeof(temptext)); + config_parse(g_cfg.ConfigFile, context->FileName, "root", context->RootDir, sizeof(context->RootDir)); + config_parse(g_cfg.ConfigFile, context->FileName, "accs", temptext, sizeof(temptext)); context->Access = FTP_ACCESS_NOT_LOGGED_IN; do { @@ -1172,10 +965,11 @@ int ftpREST(PFTPCONTEXT context, const char *params) return sendstring(context, error501); context->RestPoint = strtoull(params, NULL, 10); - snprintf(context->GPBuffer, SIZE_OF_GPBUFFER, "%s %llu\r\n", - interm350, (unsigned long long int)context->RestPoint); + snprintf(context->FileName, sizeof(context->FileName), + "350 REST supported. Ready to resume at byte offset %llu\r\n", + (unsigned long long int)context->RestPoint); - return sendstring(context, context->GPBuffer); + return sendstring(context, context->FileName); } int ftpSIZE(PFTPCONTEXT context, const char *params) @@ -1187,17 +981,13 @@ int ftpSIZE(PFTPCONTEXT context, const char *params) if ( params == NULL ) return sendstring(context, error501); - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - if ( stat(context->GPBuffer, &filestats) == 0 ) + if ( stat(context->FileName, &filestats) == 0 ) { - snprintf(context->GPBuffer, SIZE_OF_GPBUFFER, "213 %llu\r\n", + snprintf(context->FileName, sizeof(context->FileName), "213 %llu\r\n", (unsigned long long int)filestats.st_size); - sendstring(context, context->GPBuffer); + sendstring(context, context->FileName); } else sendstring(context, error550); @@ -1214,13 +1004,9 @@ int ftpMKD(PFTPCONTEXT context, const char *params) if ( params == NULL ) return sendstring(context, error501); - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - if ( mkdir(context->GPBuffer, 0755) == 0 ) { + if ( mkdir(context->FileName, 0755) == 0 ) { sendstring(context, success257); writelogentry(context, " MKD: ", (char *)params); } @@ -1239,13 +1025,9 @@ int ftpRMD(PFTPCONTEXT context, const char *params) if ( params == NULL ) return sendstring(context, error501); - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - if ( rmdir(context->GPBuffer) == 0 ) { + if ( rmdir(context->FileName) == 0 ) { sendstring(context, success250); writelogentry(context, " DELE: ", (char *)params); } @@ -1294,7 +1076,7 @@ void *stor_thread(PFTPCONTEXT context) else buffer_size = TRANSMIT_BUFFER_SIZE; - f = open(context->GPBuffer, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRGRP | S_IROTH); + f = open(context->FileName, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRGRP | S_IROTH); context->File = f; if (f == -1) break; @@ -1308,17 +1090,6 @@ void *stor_thread(PFTPCONTEXT context) } else break; - - /* heartbeat to control channel */ - /* - clock_gettime(CLOCK_MONOTONIC, &t); - if (t.tv_sec >= dtx) - { - dtx += 120; - sendstring(context, "\r\n"); - writelogentry(context, "keepalive sent", ""); - } - */ } /* calculating performance */ @@ -1327,7 +1098,7 @@ void *stor_thread(PFTPCONTEXT context) lt1 = t.tv_sec*1e9 + t.tv_nsec; dtx = lt1 - lt0; snprintf(buffer, buffer_size, " STOR complete. %zd bytes (%f MBytes) total sent in %f seconds (%f MBytes/s)", - sz_total, sz_total/1048576.0, dtx/1000000000.0, (1000000000.0*sz_total)/dtx/1048576); + sz_total, sz_total/1048576.0f, dtx/1000000000.0f, (1000000000.0f*sz_total)/dtx/1048576.0f); writelogentry(context, buffer, ""); break; @@ -1385,13 +1156,9 @@ int ftpSTOR(PFTPCONTEXT context, const char *params) context->File = -1; } - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - if ( stat(context->GPBuffer, &filestats) == 0 ) + if ( stat(context->FileName, &filestats) == 0 ) { if ( context->Access != FTP_ACCESS_FULL ) return sendstring(context, error550_r); @@ -1403,7 +1170,7 @@ int ftpSTOR(PFTPCONTEXT context, const char *params) pthread_mutex_lock(&context->MTLock); - context->WorkerThreadValid = pthread_create(&tid, NULL, (__ptr_thread_start_routine)&stor_thread, context); + context->WorkerThreadValid = pthread_create(&tid, NULL, (void * (*)(void *))stor_thread, context); if ( context->WorkerThreadValid == 0 ) context->WorkerThreadId = tid; else @@ -1477,7 +1244,7 @@ void *append_thread(PFTPCONTEXT context) else buffer_size = TRANSMIT_BUFFER_SIZE; - f = open(context->GPBuffer, O_RDWR); + f = open(context->FileName, O_RDWR); context->File = f; if (f == -1) break; @@ -1493,17 +1260,6 @@ void *append_thread(PFTPCONTEXT context) } else break; - - /* heartbeat to control channel */ - /* - clock_gettime(CLOCK_MONOTONIC, &t); - if (t.tv_sec >= dtx) - { - dtx += 120; - sendstring(context, "\r\n"); - writelogentry(context, "keepalive sent", ""); - } - */ } /* calculating performance */ @@ -1512,7 +1268,7 @@ void *append_thread(PFTPCONTEXT context) lt1 = t.tv_sec*1e9 + t.tv_nsec; dtx = lt1 - lt0; snprintf(buffer, buffer_size, " APPE complete. %zd bytes (%f MBytes) total sent in %f seconds (%f MBytes/s)", - sz_total, sz_total/1048576.0, dtx/1000000000.0, (1000000000.0*sz_total)/dtx/1048576); + sz_total, sz_total/1048576.0f, dtx/1000000000.0f, (1000000000.0f*sz_total)/dtx/1048576.0f); writelogentry(context, buffer, ""); break; @@ -1570,20 +1326,12 @@ int ftpAPPE(PFTPCONTEXT context, const char *params) context->File = -1; } - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - /* - * stat must NOT fail - */ - while (stat(context->GPBuffer, &filestats) == 0) + /* stat must NOT fail */ + while (stat(context->FileName, &filestats) == 0) { - /* - * do not try to "append" for directories - */ + /* do not try to "append" for directories */ if ( S_ISDIR(filestats.st_mode) ) break; @@ -1593,7 +1341,7 @@ int ftpAPPE(PFTPCONTEXT context, const char *params) pthread_mutex_lock(&context->MTLock); - context->WorkerThreadValid = pthread_create(&tid, NULL, (__ptr_thread_start_routine)&append_thread, context); + context->WorkerThreadValid = pthread_create(&tid, NULL, (void * (*)(void *))append_thread, context); if ( context->WorkerThreadValid == 0 ) context->WorkerThreadId = tid; else @@ -1618,15 +1366,11 @@ int ftpRNFR(PFTPCONTEXT context, const char *params) if ( params == NULL ) return sendstring(context, error501); - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->RnFrom), context->RnFrom); - if ( stat(context->GPBuffer, &filestats) == 0 ) + if ( stat(context->RnFrom, &filestats) == 0 ) { - writelogentry(context, " RNFR: ", context->GPBuffer); + writelogentry(context, " RNFR: ", context->RnFrom); sendstring(context, interm350_ren); } else @@ -1637,8 +1381,6 @@ int ftpRNFR(PFTPCONTEXT context, const char *params) int ftpRNTO(PFTPCONTEXT context, const char *params) { - char *_text; - if ( context->Access == FTP_ACCESS_NOT_LOGGED_IN ) return sendstring(context, error530); if ( context->Access < FTP_ACCESS_FULL ) @@ -1646,26 +1388,16 @@ int ftpRNTO(PFTPCONTEXT context, const char *params) if ( params == NULL ) return sendstring(context, error501); - _text = x_malloc(SIZE_OF_GPBUFFER); - - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, _text) == NULL) + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); + if ( rename(context->RnFrom, context->FileName) == 0 ) { - free(_text); - return 0; - } - - if ( rename(context->GPBuffer, _text) == 0 ) - { - writelogentry(context, " RNTO: ", _text); + writelogentry(context, " RNTO: ", context->FileName); sendstring(context, success250); } else sendstring(context, error550); - free(_text); + memset(&context->RnFrom, 0, sizeof(context->RnFrom)); return 1; } @@ -1733,7 +1465,7 @@ int ftpPROT (PFTPCONTEXT context, const char *params) int mlsd_sub (char *dirname, SOCKET s, gnutls_session_t session, struct dirent *entry) { - char text[SIZE_OF_GPBUFFER], *entrytype, *sizetype; + char text[2*PATH_MAX], *entrytype, *sizetype; struct stat filestats; struct tm ftm_fields; @@ -1742,9 +1474,7 @@ int mlsd_sub (char *dirname, SOCKET s, gnutls_session_t session, struct dirent * if (strcmp(entry->d_name, "..") == 0) return 1; - strcpy(text, dirname); - add_last_slash(text); - strcat(text, entry->d_name); + snprintf(text, sizeof(text), "%s/%s", dirname, entry->d_name); if ( lstat(text, &filestats) == 0 ) { @@ -1782,7 +1512,7 @@ int mlsd_sub (char *dirname, SOCKET s, gnutls_session_t session, struct dirent * return sendstring_auto(s, session, text); } -void *msld_thread(PFTPCONTEXT context) +void *mlsd_thread(PFTPCONTEXT context) { SOCKET clientsocket; gnutls_session_t TLS_datasession; @@ -1801,12 +1531,12 @@ void *msld_thread(PFTPCONTEXT context) if (context->TLS_session != NULL) ftp_init_tls_session(&TLS_datasession, clientsocket, 0); - pdir = opendir(context->GPBuffer); + pdir = opendir(context->FileName); if (pdir == NULL) break; while ((entry = readdir(pdir)) != NULL) { - ret = mlsd_sub(context->GPBuffer, clientsocket, TLS_datasession, entry); + ret = mlsd_sub(context->FileName, clientsocket, TLS_datasession, entry); if ( (ret == 0) || (context->WorkerThreadAbort != 0 )) break; } @@ -1852,13 +1582,9 @@ int ftpMLSD(PFTPCONTEXT context, const char *params) if (context->WorkerThreadValid == 0) return sendstring(context, error550_t); - if (finalpath( - context->RootDir, - context->CurrentDir, - (char *)params, context->GPBuffer) == NULL) - return 0; + ftp_effective_path(context->RootDir, context->CurrentDir, params, sizeof(context->FileName), context->FileName); - while (stat(context->GPBuffer, &filestats) == 0) + while (stat(context->FileName, &filestats) == 0) { if ( !S_ISDIR(filestats.st_mode) ) break; @@ -1869,7 +1595,7 @@ int ftpMLSD(PFTPCONTEXT context, const char *params) pthread_mutex_lock(&context->MTLock); - context->WorkerThreadValid = pthread_create(&tid, NULL, (__ptr_thread_start_routine)&msld_thread, context); + context->WorkerThreadValid = pthread_create(&tid, NULL, (void * (*)(void *))mlsd_thread, context); if ( context->WorkerThreadValid == 0 ) context->WorkerThreadId = tid; else @@ -1920,7 +1646,7 @@ int recvcmd(PFTPCONTEXT context, char *buffer, size_t buffer_size) void *ftp_client_thread(SOCKET *s) { FTPCONTEXT ctx __attribute__ ((aligned (16))); - char *cmd, *params, rcvbuf[SIZE_OF_RCVBUFFER]; + char *cmd, *params, rcvbuf[PATH_MAX]; int c, cmdno, rv; size_t i, cmdlen; socklen_t asz; @@ -1930,7 +1656,6 @@ void *ftp_client_thread(SOCKET *s) memset(&ctx, 0, sizeof(ctx)); ctx.Access = FTP_ACCESS_NOT_LOGGED_IN; ctx.ControlSocket = *s; - ctx.GPBuffer = x_malloc(SIZE_OF_GPBUFFER); memset(&laddr, 0, sizeof(laddr)); asz = sizeof(laddr); @@ -1998,10 +1723,10 @@ void *ftp_client_thread(SOCKET *s) cmdno = -1; rv = 1; for (c=0; c #include @@ -33,31 +42,30 @@ #include #include -#ifdef __CYGWIN__ -#define TCP_KEEPCNT 8 -#define TCP_KEEPINTVL 150 -#define TCP_KEEPIDLE 14400 +#if defined __CYGWIN__ +#define TCP_KEEPALIVE 3 +#define TCP_KEEPCNT 16 +#define TCP_KEEPIDLE TCP_KEEPALIVE +#define TCP_KEEPINTVL 17 #endif typedef struct _FTP_CONFIG { - char *ConfigFile; - unsigned int MaxUsers; - unsigned int EnableKeepalive; - in_port_t Port; - in_port_t PasvPortBase; - in_port_t PasvPortMax; - in_addr_t BindToInterface; - in_addr_t ExternalInterface; - in_addr_t LocalIPMask; + char* ConfigFile; + unsigned int MaxUsers; + unsigned int EnableKeepalive; + in_port_t Port; + in_port_t PasvPortBase; + in_port_t PasvPortMax; + in_addr_t BindToInterface; + in_addr_t ExternalInterface; + in_addr_t LocalIPMask; } FTP_CONFIG, *PFTP_CONFIG; -#define CONFIG_FILE_NAME "fftp.conf" -#define CONFIG_SECTION_NAME "ftpconfig" -#define DEFAULT_FTP_PORT 21 - +#define CONFIG_FILE_NAME "fftp.conf" +#define CONFIG_SECTION_NAME "ftpconfig" +#define DEFAULT_FTP_PORT 21 #define INVALID_SOCKET -1 #define SOCKET int - #define MODE_NORMAL 0 #define MODE_PASSIVE 1 @@ -68,104 +76,104 @@ typedef struct _FTP_CONFIG { * FULL = "admin" in config. All access features enabled. */ -#define FTP_ACCESS_NOT_LOGGED_IN 0 -#define FTP_ACCESS_READONLY 1 -#define FTP_ACCESS_CREATENEW 2 -#define FTP_ACCESS_FULL 3 - -#define TRANSMIT_BUFFER_SIZE 65536 - -#define SIZE_OF_RCVBUFFER 2*PATH_MAX -#define SIZE_OF_GPBUFFER 4*PATH_MAX - -typedef struct _FTPCONTEXT { - pthread_mutex_t MTLock; - SOCKET ControlSocket; - SOCKET DataSocket; - pthread_t WorkerThreadId; - /* - * WorkerThreadValid is output of pthread_create - * therefore zero is VALID indicator and -1 is invalid. - */ - int WorkerThreadValid; - int WorkerThreadAbort; - in_addr_t ServerIPv4; - in_addr_t ClientIPv4; - in_addr_t DataIPv4; - in_port_t DataPort; - int File; - int Mode; - int Access; - int SessionID; - int DataProtectionLevel; - off_t RestPoint; - unsigned long int BlockSize; - char CurrentDir[PATH_MAX]; - char RootDir[PATH_MAX]; - char *GPBuffer; - gnutls_session_t TLS_session; +#define FTP_ACCESS_NOT_LOGGED_IN 0 +#define FTP_ACCESS_READONLY 1 +#define FTP_ACCESS_CREATENEW 2 +#define FTP_ACCESS_FULL 3 + +#define TRANSMIT_BUFFER_SIZE 65536 + +typedef struct _FTPCONTEXT { + pthread_mutex_t MTLock; + SOCKET ControlSocket; + SOCKET DataSocket; + pthread_t WorkerThreadId; + /* + * WorkerThreadValid is output of pthread_create + * therefore zero is VALID indicator and -1 is invalid. + */ + int WorkerThreadValid; + int WorkerThreadAbort; + in_addr_t ServerIPv4; + in_addr_t ClientIPv4; + in_addr_t DataIPv4; + in_port_t DataPort; + int File; + int Mode; + int Access; + int SessionID; + int DataProtectionLevel; + off_t RestPoint; + unsigned long int BlockSize; + char CurrentDir[PATH_MAX]; + char RootDir[PATH_MAX]; + char RnFrom[PATH_MAX]; + char FileName[2*PATH_MAX]; + gnutls_session_t TLS_session; } FTPCONTEXT, *PFTPCONTEXT; -typedef int (*FTPROUTINE) (PFTPCONTEXT context, const char *params); -typedef void *(__thread_start_routine)(void *), *__ptr_thread_start_routine; - -extern FTP_CONFIG g_cfg; -extern int g_log; -extern void *ftpmain(void *p); - -extern gnutls_certificate_credentials_t x509_cred; -extern gnutls_priority_t priority_cache; - -extern const char shortmonths[12][4]; - -#define MAX_CMDS 32 - -int ftpUSER (PFTPCONTEXT context, const char *params); -int ftpQUIT (PFTPCONTEXT context, const char *params); -int ftpNOOP (PFTPCONTEXT context, const char *params); -int ftpPWD (PFTPCONTEXT context, const char *params); -int ftpTYPE (PFTPCONTEXT context, const char *params); -int ftpPORT (PFTPCONTEXT context, const char *params); -int ftpLIST (PFTPCONTEXT context, const char *params); -int ftpAPPE (PFTPCONTEXT context, const char *params); -int ftpCDUP (PFTPCONTEXT context, const char *params); -int ftpCWD (PFTPCONTEXT context, const char *params); -int ftpRETR (PFTPCONTEXT context, const char *params); -int ftpABOR (PFTPCONTEXT context, const char *params); -int ftpDELE (PFTPCONTEXT context, const char *params); -int ftpPASV (PFTPCONTEXT context, const char *params); -int ftpPASS (PFTPCONTEXT context, const char *params); -int ftpREST (PFTPCONTEXT context, const char *params); -int ftpSIZE (PFTPCONTEXT context, const char *params); -int ftpMKD (PFTPCONTEXT context, const char *params); -int ftpRMD (PFTPCONTEXT context, const char *params); -int ftpSTOR (PFTPCONTEXT context, const char *params); -int ftpSYST (PFTPCONTEXT context, const char *params); -int ftpFEAT (PFTPCONTEXT context, const char *params); -int ftpRNFR (PFTPCONTEXT context, const char *params); -int ftpRNTO (PFTPCONTEXT context, const char *params); -int ftpOPTS (PFTPCONTEXT context, const char *params); -int ftpMLSD (PFTPCONTEXT context, const char *params); -int ftpAUTH (PFTPCONTEXT context, const char *params); -int ftpPBSZ (PFTPCONTEXT context, const char *params); -int ftpPROT (PFTPCONTEXT context, const char *params); -int ftpEPSV (PFTPCONTEXT context, const char *params); -int ftpHELP (PFTPCONTEXT context, const char *params); -int ftpSITE (PFTPCONTEXT context, const char *params); - -#define success200 "200 Command okay.\r\n" -#define success200_1 "200 Type set to A.\r\n" -#define success200_2 "200 Type set to I.\r\n" +typedef int (*FTPROUTINE) (PFTPCONTEXT context, const char* params); + +typedef struct _FTPROUTINE_ENTRY { + const char* Name; + FTPROUTINE Proc; +} FTPROUTINE_ENTRY, *PFTPROUTINE_ENTRY; + +extern FTP_CONFIG g_cfg; +extern int g_log; +extern void* ftpmain(void* p); + +extern gnutls_certificate_credentials_t x509_cred; +extern gnutls_priority_t priority_cache; + +#define FTP_COMMAND(cmdname) int cmdname(PFTPCONTEXT context, const char* params) +#define MAX_CMDS 32 +extern const char shortmonths[12][4]; + +FTP_COMMAND(ftpUSER); +FTP_COMMAND(ftpQUIT); +FTP_COMMAND(ftpNOOP); +FTP_COMMAND(ftpPWD); +FTP_COMMAND(ftpTYPE); +FTP_COMMAND(ftpPORT); +FTP_COMMAND(ftpLIST); +FTP_COMMAND(ftpAPPE); +FTP_COMMAND(ftpCDUP); +FTP_COMMAND(ftpCWD); +FTP_COMMAND(ftpRETR); +FTP_COMMAND(ftpABOR); +FTP_COMMAND(ftpDELE); +FTP_COMMAND(ftpPASV); +FTP_COMMAND(ftpPASS); +FTP_COMMAND(ftpREST); +FTP_COMMAND(ftpSIZE); +FTP_COMMAND(ftpMKD); +FTP_COMMAND(ftpRMD); +FTP_COMMAND(ftpSTOR); +FTP_COMMAND(ftpSYST); +FTP_COMMAND(ftpFEAT); +FTP_COMMAND(ftpRNFR); +FTP_COMMAND(ftpRNTO); +FTP_COMMAND(ftpOPTS); +FTP_COMMAND(ftpMLSD); +FTP_COMMAND(ftpAUTH); +FTP_COMMAND(ftpPBSZ); +FTP_COMMAND(ftpPROT); +FTP_COMMAND(ftpEPSV); +FTP_COMMAND(ftpHELP); +FTP_COMMAND(ftpSITE); + +#define success200 "200 Command okay.\r\n" +#define success200_1 "200 Type set to A.\r\n" +#define success200_2 "200 Type set to I.\r\n" extern const char success211[]; extern const char success214[]; #define success215 "215 UNIX Type: L8\r\n" -#define success220 "220 LightFTP server v2.0b ready\r\n" +#define success220 "220 LightFTP server v2.1 ready\r\n" #define success221 "221 Goodbye!\r\n" #define success226 "226 Transfer complete. Closing data connection.\r\n" -#define success227 "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n" -#define success229 "229 Entering Extended Passive Mode (|||%u|)\r\n" #define success230 "230 User logged in, proceed.\r\n" #define success234 "234 AUTH command OK. Initializing TLS connection.\r\n" #define success250 "250 Requested file action okay, completed.\r\n" @@ -188,11 +196,8 @@ extern const char success214[]; #define error550_m "550 Insufficient resources.\r\n" #define interm125 "125 Data connection already open; Transfer starting.\r\n" #define interm150 "150 File status okay; about to open data connection.\r\n" -#define interm350 "350 REST supported. Ready to resume at byte offset " #define interm350_ren "350 File exists. Ready to rename.\r\n" -#define interm331 "331 User " -#define interm331_tail " OK. Password required\r\n" -#define NOSLOTS "MAXIMUM ALLOWED USERS CONNECTED\r\n" +#define NOSLOTS "MAXIMUM ALLOWED USERS CONNECTED\r\n" #endif /* FTPSERV_H_ */ diff --git a/Source/main.c b/Source/main.c index 41f7e51..3068429 100644 --- a/Source/main.c +++ b/Source/main.c @@ -105,7 +105,7 @@ int main(int argc, char *argv[]) if (g_log != -1) lseek(g_log, 0L, SEEK_END); - printf("\r\n [ LightFTP server v2.0 ]\r\n\r\n"); + printf("\r\n [ LightFTP server v2.1 ]\r\n\r\n"); printf("Log file : %s\r\n", textbuf); getcwd(textbuf, bufsize); diff --git a/Source/x_malloc.c b/Source/x_malloc.c index c0271df..e146db8 100644 --- a/Source/x_malloc.c +++ b/Source/x_malloc.c @@ -9,15 +9,15 @@ #include #include -void * x_malloc(size_t size) +void *x_malloc(size_t size) { - void *result; + void *result; result = malloc(size); if (result == NULL) { - printf("\r\nOut of memory\r\n"); - abort(); + printf("\r\nOut of memory\r\n"); + abort(); } memset(result, 0, size); From 16e1fae3e43f605726e04a2a17e9e21d20b5dfb4 Mon Sep 17 00:00:00 2001 From: hfiref0x Date: Thu, 21 May 2020 21:14:08 +0700 Subject: [PATCH 3/4] Update readme and fftp example config Add keepalive setting with description. --- README.md | 8 +++++++- Source.sha256 | 2 +- Source/fftp.conf | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 28b3482..452a2c6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # System Requirements * x86-32/x64 POSIX compliant OS, e.g. Linux. -* x86-32/x64 Windows Vista/7/8/8.1/10 with Cygwin (see Build section of this readme). +* x86-32/x64 Windows 7/8/8.1/10 with Cygwin (see Build section of this readme). * No admin/root privileges required. FTP server must be allowed in firewall. # Configuration @@ -69,6 +69,12 @@ Path to PEM private key file for your certificate. Password to decrypt private key. + keepalive + +Send keepalive packets (some NATs may require this). +Default: 1 (enabled) + + # User sections Note for "accs" field: diff --git a/Source.sha256 b/Source.sha256 index 2c36f96..27377ae 100644 --- a/Source.sha256 +++ b/Source.sha256 @@ -1,7 +1,7 @@ 18364d8691f4bb9ec5f684940e05ddd70de658446417c1f6071a21ad7f4b3717 *Source\cfgparse.c fb951da7cb5aa17b79cc455bbcb3d7a3ef09182db34298a921138bdd9950cd17 *Source\cfgparse.h e0013dc69f2e46b70c360611463886be20b382709ef7c3c954bd3ab8963370b3 *Source\changelog.txt -5f60ff45d21faa296673f793d6afef8a0c2c9b97a7b0aa51134750f7158f15c2 *Source\fftp.conf +89f8ce6af9377236e226c810e228947c27fc1b233b0f164104ad26bbfe8ecda6 *Source\fftp.conf c02df4fe98511859d400a4357c66720254f8b7053f8655f26e6842ba6022227a *Source\fspathtools.c 6a6f5df59cb19f62a964312a5efc1d285eba1d1a97563e4214c5b41666baf0ee *Source\fspathtools.h 552be952422a3e3959e4f130be0c7fdff6ab0ef124eb161df21b0a264b0b2a32 *Source\ftpconst.c diff --git a/Source/fftp.conf b/Source/fftp.conf index eafa4af..2026b62 100644 --- a/Source/fftp.conf +++ b/Source/fftp.conf @@ -53,6 +53,9 @@ Keyfile=/home/user/certificate/privkey.pem # Password to decrypt private key. KeyfilePassword=pemkeypassword +# Send keepalive packets (some NATs may require this) +keepalive=1 + # USERS SECTIONS # # Note for "accs" field: From f0d4c4d5eba05389fd3e5e0c13bcfbd614b745c3 Mon Sep 17 00:00:00 2001 From: hfiref0x Date: Thu, 21 May 2020 21:16:48 +0700 Subject: [PATCH 4/4] Update README.md Replace setting --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 452a2c6..1ed726c 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Password to decrypt private key. keepalive Send keepalive packets (some NATs may require this). -Default: 1 (enabled) +Default: 0 (disabled) # User sections