Heavily overhauled client command handling and changed motd to use multi-line text.
This commit is contained in:
368
src/client.cpp
368
src/client.cpp
@@ -39,10 +39,6 @@ public:
|
||||
submit(230, conf_format(server_name, (std::map<std::string, std::string>){{std::string(APPNAME_VAR),std::string(APPNAME)},{std::string(VERSION_VAR),std::string(VERSION)}}));
|
||||
}
|
||||
|
||||
void addOption(std::string name, bool toggle) {
|
||||
this->options[name] = toggle;
|
||||
}
|
||||
|
||||
int receive(std::string cmd, std::string argstr) {
|
||||
if (control_sock <= 0) return 1;
|
||||
|
||||
@@ -69,97 +65,127 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cmd == "AUTH") {
|
||||
if (cmd == "USER") {
|
||||
if (state == FTP_STATE_GUEST) {
|
||||
if (argstr.length() >= sizeof(auth_data->username))
|
||||
throw std::runtime_error("Username too long");
|
||||
std::strncpy(auth_data->username, argstr.c_str(), sizeof(auth_data->username) - 1);
|
||||
auth_data->username[sizeof(auth_data->username) - 1] = '\0';
|
||||
if (auth->isPasswordRequired())
|
||||
submit(331, "Password required");
|
||||
else authedInit();
|
||||
} else submit(503, "Already logged in");
|
||||
} else if (cmd == "PASS") {
|
||||
if (state == FTP_STATE_GUEST) {
|
||||
if (strlen(auth_data->username) > 0) {
|
||||
std::strncpy(auth_data->password, argstr.c_str(), sizeof(auth_data->password) - 1);
|
||||
auth_data->password[sizeof(auth_data->password) - 1] = '\0';
|
||||
if (auth->authenticate(auth_data))
|
||||
authedInit();
|
||||
else {
|
||||
auth_data->username[0] = {};
|
||||
submit(530, "Invalid Credentials.");
|
||||
}
|
||||
} else submit(503, "Bad sequence of commands");
|
||||
} else submit(503, "Already logged in");
|
||||
} else if (cmd == "REIN") {
|
||||
if (state == FTP_STATE_ONDATA) data_close();
|
||||
auth_data = new ClientAuthDetails{};
|
||||
filer = default_filer_factory();
|
||||
// Reset features
|
||||
for (const auto &x : features)
|
||||
features[x.first] = "OFF";
|
||||
state = FTP_STATE_GUEST;
|
||||
submit(220, "Service ready for user");
|
||||
} else if (cmd == "AUTH") {
|
||||
if (argstr == "TLS" || argstr == "SSL") {
|
||||
if (setupControlSSL()) {
|
||||
submit(234, "AUTH TLS successful");
|
||||
is_secure = true;
|
||||
return 0;
|
||||
} else {
|
||||
submit(431, "AUTH TLS failed");
|
||||
}
|
||||
} else {
|
||||
submit(504, "AUTH type not supported");
|
||||
}
|
||||
return 0;
|
||||
} else submit(431, "AUTH TLS failed");
|
||||
} else submit(504, "AUTH type not supported");
|
||||
} else if (cmd == "PBSZ") {
|
||||
if (!is_secure) {
|
||||
submit(503, "PBSZ not allowed on insecure control connection");
|
||||
} else {
|
||||
submit(200, "PBSZ=0");
|
||||
}
|
||||
if (!is_secure) submit(503, "PBSZ not allowed on insecure control connection");
|
||||
else submit(200, "PBSZ=0");
|
||||
return 0;
|
||||
} else if (cmd == "PROT") {
|
||||
if (!is_secure) {
|
||||
submit(503, "PROT not allowed on insecure control connection");
|
||||
} else if (argstr == "P") {
|
||||
if (!is_secure) submit(503, "PROT not allowed on insecure control connection");
|
||||
else if (argstr == "P") {
|
||||
protect_data = true;
|
||||
submit(200, "Protection level set to Private");
|
||||
} else if (argstr == "C") {
|
||||
protect_data = false;
|
||||
submit(200, "Protection level set to Clear");
|
||||
} else {
|
||||
submit(504, "PROT level not supported");
|
||||
}
|
||||
return 0;
|
||||
} else if (cmd == "QUIT") {
|
||||
state = FTP_STATE_CLOSE;
|
||||
submit(250, "Goodbye!");
|
||||
shutdown(control_sock, SHUT_RDWR); // Add immediate shutdown
|
||||
return 1; // Signal thread to terminate
|
||||
} else if (state >= FTP_STATE_AUTHED) {
|
||||
if (cmd == "SYST") {
|
||||
submit(215, "UNIX Type: L8");
|
||||
} else if (cmd == "TYPE") {
|
||||
} else submit(504, "PROT level not supported");
|
||||
} else if (cmd == "FEAT") {
|
||||
submit("211-Extensions supported:");
|
||||
for (const auto &s : global_features)
|
||||
submit(" "+toUpper(s));
|
||||
submit(211, "END");
|
||||
} else if (cmd == "OPTS") {
|
||||
std::vector<std::string> args = parseArgs(argstr);
|
||||
if (args.size() > 0) {
|
||||
std::string name = toUpper(args[0]);
|
||||
if (args.size() > 1) {
|
||||
if (features.find(name) == features.end())
|
||||
features[name] = toUpper(args[1]);
|
||||
else submit(451, "Unknown feature "+name);
|
||||
} else {
|
||||
if (features.find(name) == features.end())
|
||||
submit(200, name+" is set to "+features[name]);
|
||||
else submit(501, "Unknown feature "+name);
|
||||
}
|
||||
} else submit(550, "Malformed Request");
|
||||
} else if (cmd == "NOOP") {
|
||||
submit(226, "OK");
|
||||
} else if (cmd == "SYST") {
|
||||
submit(215, "UNIX Type: L8");
|
||||
} else if (cmd == "TYPE") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
char type = 0;
|
||||
sscanf(argstr.c_str(), "%c", &(type));
|
||||
filer->setTransferMode(type);
|
||||
submit(226, "OK");
|
||||
} else if (cmd == "OPTS") {
|
||||
std::vector<std::string> args = parseArgs(argstr);
|
||||
if (args.size() > 0) {
|
||||
std::string name = toUpper(args[0]);
|
||||
int rc = false;
|
||||
|
||||
if (args.size() > 1) rc = toggleOption(name, toUpper(args[1])=="ON");
|
||||
else rc = toggleOption(name, true);
|
||||
|
||||
if (rc == 0) submit(200, "OK");
|
||||
else if (rc == 1) submit(451, "Option not enabled or not recognized");
|
||||
else submit(550, "Unknown error");
|
||||
} else submit(550, "Malformed Request");
|
||||
} else if (cmd == "PWD") {
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "PWD") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
submit(257, "'"+filer->getCWD().string()+"'");
|
||||
} else if (cmd == "CWD") {
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "CWD") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
struct file_data fd = filer->traverse(argstr);
|
||||
if (fd.error.code == 0) submit(250, "OK");
|
||||
else submit(431, std::string(fd.error.msg));
|
||||
} else if (cmd == "CDUP") {
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "CDUP") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
struct file_data fd = filer->traverse("..");
|
||||
if (fd.error.code == 0) submit(250, "OK");
|
||||
else submit(431, std::string(fd.error.msg));
|
||||
} else if (cmd == "MKD") {
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "MKD") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
struct file_data fd = filer->createDirectory(argstr);
|
||||
if (fd.error.code == 0) submit(257, "\""+std::string(fd.path)+"\" directory created");
|
||||
else if (fd.error.code == FilerStatusCodes::FileExists) submit(521, std::string(fd.error.msg));
|
||||
else submit(550, std::string(fd.error.msg));
|
||||
} else if (cmd == "SIZE") {
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "SIZE") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
struct file_data fd = filer->fileSize(argstr);
|
||||
if (fd.error.code == 0) submit(213, std::to_string(fd.size));
|
||||
else submit(550, std::string(fd.error.msg));
|
||||
} else if (cmd == "FEAT") {
|
||||
submit("211-Extensions supported:");
|
||||
for (const auto &opt : options) {
|
||||
submit(" "+toUpper(opt.first));
|
||||
}
|
||||
submit(211, "END");
|
||||
} else if (cmd == "NOOP") {
|
||||
submit(226, "OK");
|
||||
} else if (cmd == "DELE" || cmd == "RMD") {
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "DELE" || cmd == "RMD") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
struct file_data fd = filer->deleteFile(argstr);
|
||||
if (fd.error.code == 0) submit(250, "OK");
|
||||
else submit(550, std::string(fd.error.msg));
|
||||
} else if (cmd == "PASV") {
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "PASV") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
if (state == FTP_STATE_ONDATA) data_close();
|
||||
if ((data_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
perror("pasv socket() failed");
|
||||
return 1;
|
||||
@@ -233,9 +259,11 @@ public:
|
||||
submit(425, "Can't open data connection");
|
||||
data_close();
|
||||
}
|
||||
} else if (cmd == "RNFR") {
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "RNFR") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
if (argstr.empty()) {
|
||||
submit(501, "Syntax error in parameters or arguments.");
|
||||
submit(501, "Syntax error in parameters or arguments");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -250,15 +278,17 @@ public:
|
||||
// Store the source path and mark rename as pending
|
||||
rename_from = argstr;
|
||||
rename_pending = true;
|
||||
submit(350, "Ready for RNTO.");
|
||||
} else if (cmd == "RNTO") {
|
||||
submit(350, "Ready for RNTO");
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "RNTO") {
|
||||
if (state >= FTP_STATE_AUTHED) {
|
||||
if (!rename_pending) {
|
||||
submit(503, "RNFR required first.");
|
||||
submit(503, "RNFR required first");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argstr.empty()) {
|
||||
submit(501, "Syntax error in parameters or arguments.");
|
||||
submit(501, "Syntax error in parameters or arguments");
|
||||
rename_pending = false;
|
||||
return 0;
|
||||
}
|
||||
@@ -267,136 +297,97 @@ public:
|
||||
struct file_data fd = filer->renameFile(rename_from, argstr);
|
||||
rename_pending = false; // Reset rename state
|
||||
|
||||
if (fd.error.code == 0) {
|
||||
submit(250, "Rename successful.");
|
||||
} else {
|
||||
submit(550, std::string(fd.error.msg));
|
||||
}
|
||||
} else if (state == FTP_STATE_ONDATA) {
|
||||
if (data_sock <= 0) return 1;
|
||||
if (cmd == "LIST" || cmd == "NLST") {
|
||||
if (fd.error.code == 0) submit(250, "Rename successful");
|
||||
else submit(550, std::string(fd.error.msg));
|
||||
} else submit(530, "Not logged in");
|
||||
} else if (cmd == "LIST" || cmd == "NLST") {
|
||||
if (state == FTP_STATE_ONDATA && data_sock > 0) {
|
||||
submit(150, "Transferring");
|
||||
|
||||
std::string dirname = "";
|
||||
if (argstr.find_first_of('/') != std::string::npos)
|
||||
dirname = argstr.substr(argstr.find_first_of('/'));
|
||||
struct file_data fd = filer->list(dirname);
|
||||
data_submit(fd.bin, fd.size);
|
||||
|
||||
submit(226, "OK");
|
||||
data_close();
|
||||
} else submit(425, "No data connection");
|
||||
} else if (cmd == "RETR") {
|
||||
if (state == FTP_STATE_ONDATA && data_sock > 0) {
|
||||
struct file_data fd = filer->readFile(argstr);
|
||||
if (fd.error.code == 0 && fd.stream && fd.stream->is_open()) {
|
||||
submit(150, "Transferring");
|
||||
|
||||
std::string dirname = "";
|
||||
if (argstr.find_first_of('/') != std::string::npos)
|
||||
dirname = argstr.substr(argstr.find_first_of('/'));
|
||||
struct file_data fd = filer->list(dirname);
|
||||
data_submit(fd.bin, fd.size);
|
||||
char buffer[8192];
|
||||
bool transfer_ok = true;
|
||||
|
||||
submit(226, "OK");
|
||||
} else if (cmd == "RETR") {
|
||||
struct file_data fd = filer->readFile(argstr);
|
||||
if (fd.error.code == 0 && fd.stream && fd.stream->is_open()) {
|
||||
submit(150, "Transferring");
|
||||
while (!fd.stream->eof()) {
|
||||
fd.stream->read(buffer, sizeof(buffer));
|
||||
size_t bytes_read = fd.stream->gcount();
|
||||
|
||||
char buffer[8192];
|
||||
bool transfer_ok = true;
|
||||
|
||||
while (!fd.stream->eof()) {
|
||||
fd.stream->read(buffer, sizeof(buffer));
|
||||
size_t bytes_read = fd.stream->gcount();
|
||||
|
||||
if (bytes_read > 0) {
|
||||
if (data_submit(buffer, bytes_read) != 0) {
|
||||
submit(426, "Transfer failed");
|
||||
transfer_ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd.stream->fail() && !fd.stream->eof()) {
|
||||
submit(426, "Read error");
|
||||
if (bytes_read > 0) {
|
||||
if (data_submit(buffer, bytes_read) != 0) {
|
||||
submit(426, "Transfer failed");
|
||||
transfer_ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (transfer_ok) {
|
||||
submit(226, "OK");
|
||||
}
|
||||
} else {
|
||||
submit(550, std::string(fd.error.msg));
|
||||
}
|
||||
data_close();
|
||||
} else if (cmd == "STOR") {
|
||||
unsigned char inbuf[BUFFERSIZE] = {0};
|
||||
submit(150, "Transferring");
|
||||
int psize;
|
||||
struct file_data fd = filer->writeFile(argstr, inbuf, 0);
|
||||
|
||||
while (true) {
|
||||
if (is_secure && protect_data && data_ssl) {
|
||||
psize = SSL_read(data_ssl, inbuf, sizeof(inbuf));
|
||||
if (psize <= 0) {
|
||||
int err = SSL_get_error(data_ssl, psize);
|
||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
psize = recv(data_sock, inbuf, sizeof(inbuf), 0);
|
||||
if (psize <= 0) break;
|
||||
}
|
||||
|
||||
fd = filer->writeFile(argstr, inbuf, psize, true);
|
||||
if (fd.error.code != 0) {
|
||||
submit(550, "Access Denied: "+std::string(fd.error.msg));
|
||||
data_close();
|
||||
if (fd.stream->fail() && !fd.stream->eof()) {
|
||||
submit(426, "Read error");
|
||||
transfer_ok = false;
|
||||
break;
|
||||
}
|
||||
memset(inbuf, 0, BUFFERSIZE);
|
||||
}
|
||||
submit(226, "OK");
|
||||
} else {
|
||||
submit(502, "Command not implemented");
|
||||
}
|
||||
if (transfer_ok) submit(226, "OK");
|
||||
} else submit(550, std::string(fd.error.msg));
|
||||
data_close();
|
||||
} else {
|
||||
submit(502, "Command not implemented");
|
||||
}
|
||||
} else {
|
||||
state = FTP_STATE_GUEST; // If we reach here, force state to zero just in case.
|
||||
if (cmd == "USER") {
|
||||
if (argstr.length() >= sizeof(auth_data->username)) {
|
||||
throw std::runtime_error("Username too long");
|
||||
} else submit(425, "No data connection");
|
||||
} else if (cmd == "STOR") {
|
||||
if (state == FTP_STATE_ONDATA && data_sock > 0) {
|
||||
unsigned char inbuf[BUFFERSIZE] = {0};
|
||||
submit(150, "Transferring");
|
||||
int psize;
|
||||
struct file_data fd = filer->writeFile(argstr, inbuf, 0);
|
||||
|
||||
while (true) {
|
||||
if (is_secure && protect_data && data_ssl) {
|
||||
psize = SSL_read(data_ssl, inbuf, sizeof(inbuf));
|
||||
if (psize <= 0) {
|
||||
int err = SSL_get_error(data_ssl, psize);
|
||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
psize = recv(data_sock, inbuf, sizeof(inbuf), 0);
|
||||
if (psize <= 0) break;
|
||||
}
|
||||
|
||||
fd = filer->writeFile(argstr, inbuf, psize, true);
|
||||
if (fd.error.code != 0) {
|
||||
submit(550, "Access Denied: "+std::string(fd.error.msg));
|
||||
data_close();
|
||||
break;
|
||||
}
|
||||
memset(inbuf, 0, BUFFERSIZE);
|
||||
}
|
||||
std::strncpy(auth_data->username, argstr.c_str(), sizeof(auth_data->username) - 1);
|
||||
auth_data->username[sizeof(auth_data->username) - 1] = '\0';
|
||||
if (auth->isPasswordRequired())
|
||||
submit(331, "Password required");
|
||||
else authedInit();
|
||||
} else if (cmd == "PASS") {
|
||||
std::strncpy(auth_data->password, argstr.c_str(), sizeof(auth_data->password) - 1);
|
||||
auth_data->password[sizeof(auth_data->password) - 1] = '\0';
|
||||
if (auth->authenticate(auth_data)) authedInit();
|
||||
else {
|
||||
auth_data->username[0] = {};
|
||||
submit(530, "Invalid Credentials.");
|
||||
}
|
||||
} else {
|
||||
submit(332, "Not Logged In!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
submit(226, "OK");
|
||||
data_close();
|
||||
} else submit(425, "No data connection");
|
||||
} else if (cmd == "QUIT") {
|
||||
state = FTP_STATE_CLOSE;
|
||||
submit(250, "Goodbye!");
|
||||
shutdown(control_sock, SHUT_RDWR); // Add immediate shutdown
|
||||
return 1; // Signal thread to terminate
|
||||
} else submit(502, "Command not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toggleOption(std::string name, bool toggle) {
|
||||
auto feat_it = options.find(name);
|
||||
if (feat_it != options.end()) {
|
||||
feat_it->second = toggle;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool getOption(std::string name) {
|
||||
auto feat_it = options.find(name);
|
||||
if (feat_it != options.end()) {
|
||||
return feat_it->second;
|
||||
}
|
||||
return false;
|
||||
void addFeature(std::string name, std::string value) {
|
||||
this->features[name] = value.empty()?"OFF":value;
|
||||
}
|
||||
|
||||
int submit(std::string msg) {
|
||||
@@ -445,6 +436,15 @@ public:
|
||||
logger->print(LOGLEVEL_DEBUG, "C(%i) << %d %s", control_sock, code, msg.c_str());
|
||||
}
|
||||
|
||||
void submit(int code, const std::vector<std::string>& msgs) {
|
||||
for(int i = 0; i < msgs.size(); i++){
|
||||
if (i+1 == msgs.size())
|
||||
submit(std::to_string(code) + " " + msgs[i]);
|
||||
else
|
||||
submit(std::to_string(code) + "-" + msgs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int data_submit(char* out, size_t size) {
|
||||
size_t total_sent = 0;
|
||||
while (total_sent < size) {
|
||||
@@ -514,7 +514,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, bool> options;
|
||||
std::map<std::string, std::string> features;
|
||||
ClientAuthDetails* auth_data = new ClientAuthDetails{};
|
||||
Filer* filer = {};
|
||||
const int opt = 1;
|
||||
@@ -634,6 +634,7 @@ private:
|
||||
struct file_data fd;
|
||||
std::string root;
|
||||
std::string home = "/";
|
||||
std::vector<std::string> auth_response;
|
||||
if (auth->isChroot()) {
|
||||
root = std::string(this->auth_data->home_dir);
|
||||
logger->print(LOGLEVEL_INFO, "C(%i) Set chrooted root of '%s' to '%s'", control_sock, auth_data->username, root.c_str());
|
||||
@@ -647,15 +648,16 @@ private:
|
||||
((struct file_data)filer->setCWD(home)).error.code == 0
|
||||
) {
|
||||
state = FTP_STATE_AUTHED;
|
||||
submit(230, "Login OK");
|
||||
auth_response.push_back("Login OK");
|
||||
std::string user_motd = getMotD();
|
||||
if (user_motd.size() > 0) {
|
||||
std::stringstream motd_stream(user_motd);
|
||||
std::string line;
|
||||
while(std::getline(motd_stream, line)) {
|
||||
submit(230, line);
|
||||
auth_response.push_back(line);
|
||||
}
|
||||
}
|
||||
submit(230, auth_response);
|
||||
return;
|
||||
}
|
||||
submit(530, "An error occured setting root and/or cwd");
|
||||
|
||||
18
src/main.cpp
18
src/main.cpp
@@ -248,7 +248,9 @@ int main(int argc , char *argv[]) {
|
||||
logger->openFileOnLevel(LOGLEVEL_ERROR, config->getValue("logging", "error", mainLogFile).c_str());
|
||||
logger->openFileOnLevel(LOGLEVEL_CRITICAL, config->getValue("logging", "critical", mainLogFile).c_str());
|
||||
|
||||
if (config->getBool("net", "ssl", false)) {
|
||||
bool ssl_enable = config->getBool("net", "ssl", true);
|
||||
bool ssl_flags = SSL_OP_NO_TICKET;
|
||||
if (ssl_enable) {
|
||||
std::string cert_file = config->getValue("ssl", "certificate", "cert.pem");
|
||||
if (cert_file[0] != '/')
|
||||
cert_file = concatPath(std::string(CONFIG_DIR), cert_file);
|
||||
@@ -264,7 +266,6 @@ int main(int argc , char *argv[]) {
|
||||
// set configured ciphers
|
||||
SSLManager::getInstance().setCiphers(config->getValue("ssl", "ciphers", "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH").c_str());
|
||||
// handle configured flags
|
||||
bool ssl_flags = SSL_OP_NO_TICKET;
|
||||
if (!config->getBool("ssl", "ssl_v2", false))
|
||||
ssl_flags+=SSL_OP_NO_SSLv2;
|
||||
if (!config->getBool("ssl", "ssl_v3", false))
|
||||
@@ -278,6 +279,15 @@ int main(int argc , char *argv[]) {
|
||||
if (!config->getBool("ssl", "tls_v1_3", true))
|
||||
ssl_flags+=SSL_OP_NO_TLSv1_3;
|
||||
|
||||
if (!(ssl_flags & SSL_OP_NO_SSLv2) || !(ssl_flags & SSL_OP_NO_SSLv3))
|
||||
global_features.push_back("AUTH SSL");
|
||||
if (!(ssl_flags & SSL_OP_NO_TLSv1) || !(ssl_flags & SSL_OP_NO_TLSv1_1) ||
|
||||
!(ssl_flags & SSL_OP_NO_TLSv1_2) || !(ssl_flags & SSL_OP_NO_TLSv1_3))
|
||||
global_features.push_back("AUTH TLS");
|
||||
|
||||
global_features.push_back("PBSZ");
|
||||
global_features.push_back("PROT");
|
||||
|
||||
if ((ssl_flags & SSL_OP_NO_SSLv2) && (ssl_flags & SSL_OP_NO_SSLv3) &&
|
||||
(ssl_flags & SSL_OP_NO_TLSv1) && (ssl_flags & SSL_OP_NO_TLSv1_1) &&
|
||||
(ssl_flags & SSL_OP_NO_TLSv1_2) && (ssl_flags & SSL_OP_NO_TLSv1_3))
|
||||
@@ -413,8 +423,8 @@ int main(int argc , char *argv[]) {
|
||||
fds[slot].revents = 0;
|
||||
|
||||
fdc[slot].client = new Client(newsock);
|
||||
fdc[slot].client->addOption("SIZE", true);
|
||||
fdc[slot].client->addOption("UTF8", config->getBool("features", "utf8", true));
|
||||
for (const auto &o : client_options)
|
||||
fdc[slot].client->addFeature(o, "");
|
||||
fdc[slot].thread = new std::thread(runClient, &fdc[slot]);
|
||||
fdc[slot].close = false;
|
||||
|
||||
|
||||
@@ -25,5 +25,13 @@ Logger* logger;
|
||||
static typename PluginTraits<Filer>::CreateFunc default_filer_factory = nullptr;
|
||||
bool runServer;
|
||||
bool runCompression;
|
||||
std::vector<std::string> global_features = {
|
||||
"SIZE",
|
||||
"UTF8",
|
||||
"PASV"
|
||||
};
|
||||
std::vector<std::string> client_options = {
|
||||
"UTF8"
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user