added ip banning
This commit is contained in:
parent
f66d895326
commit
61c41aefeb
2
Makefile
2
Makefile
@ -10,7 +10,7 @@ BUILD_DIR = build
|
|||||||
SOURCES_CLIENT = client.cpp
|
SOURCES_CLIENT = client.cpp
|
||||||
OBJS_CLIENT = $(addprefix $(BUILD_DIR)/,$(SOURCES_CLIENT:.cpp=.o))
|
OBJS_CLIENT = $(addprefix $(BUILD_DIR)/,$(SOURCES_CLIENT:.cpp=.o))
|
||||||
|
|
||||||
SOURCES_SERVER = server.cpp user.cpp user_handler.cpp mail.cpp
|
SOURCES_SERVER = server.cpp user.cpp user_handler.cpp mail.cpp ip_ban.cpp
|
||||||
OBJS_SERVER = $(addprefix $(BUILD_DIR)/,$(SOURCES_SERVER:.cpp=.o))
|
OBJS_SERVER = $(addprefix $(BUILD_DIR)/,$(SOURCES_SERVER:.cpp=.o))
|
||||||
|
|
||||||
all: $(BUILD_DIR) $(TARGET)
|
all: $(BUILD_DIR) $(TARGET)
|
||||||
|
|||||||
54
server/ip_ban.cpp
Normal file
54
server/ip_ban.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "ip_ban.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <iterator>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
ip_ban::ip_ban() : m_ban()
|
||||||
|
{
|
||||||
|
this->file = fs::path();
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_ban::~ip_ban()
|
||||||
|
{
|
||||||
|
if (this->file.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
json jsonfile = this->ban_list;
|
||||||
|
|
||||||
|
std::ofstream ofs(this->file, std::ofstream::out | std::ofstream::trunc);
|
||||||
|
ofs << jsonfile.dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ip_ban::loadFile(fs::path file)
|
||||||
|
{
|
||||||
|
this->file = file;
|
||||||
|
|
||||||
|
if (fs::exists(file)) {
|
||||||
|
std::ifstream ifs(file);
|
||||||
|
this->ban_list = json::parse(ifs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ip_ban::failedAttempt(std::string username, std::string ip)
|
||||||
|
{
|
||||||
|
printf("%s\n", username.c_str());
|
||||||
|
std::unique_lock<std::shared_mutex> lock(this->m_ban);
|
||||||
|
|
||||||
|
std::map<std::string, std::pair<std::map<std::string, ushort>, time_t>>::iterator it = this->ban_list.insert({ip, {{}, 0}}).first;
|
||||||
|
if (++it->second.first.insert({username, 0}).first->second >= MAX_ATTEMPTS) { // increase attempt count && check if reached MAX_ATTEMPTS
|
||||||
|
for (auto& pair : it->second.first ) { // reset attempts to 0 for all names
|
||||||
|
pair.second = 0;
|
||||||
|
}
|
||||||
|
(*it).second.second = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) + BAN_TIME; // set unban time to current time + BAN_TIME seconds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ip_ban::checkBanned(std::string ip)
|
||||||
|
{
|
||||||
|
std::shared_lock<std::shared_mutex> lock(this->m_ban);
|
||||||
|
|
||||||
|
std::map<std::string, std::pair<std::map<std::string, ushort>, time_t>>::iterator it;
|
||||||
|
return (it = this->ban_list.find(ip)) != this->ban_list.end() && (*it).second.second > std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||||
|
}
|
||||||
47
server/ip_ban.h
Normal file
47
server/ip_ban.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <shared_mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#define BAN_TIME 60
|
||||||
|
#define MAX_ATTEMPTS 3
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
class ip_ban {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static ip_ban& getInstance() {
|
||||||
|
static ip_ban instance;
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
ip_ban(ip_ban const&) = delete;
|
||||||
|
ip_ban(ip_ban&&) = delete;
|
||||||
|
ip_ban& operator=(ip_ban const&) = delete;
|
||||||
|
ip_ban& operator=(ip_ban &&) = delete;
|
||||||
|
|
||||||
|
void loadFile(fs::path file);
|
||||||
|
|
||||||
|
void failedAttempt(std::string username, std::string ip);
|
||||||
|
bool checkBanned(std::string ip);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
ip_ban();
|
||||||
|
~ip_ban();
|
||||||
|
|
||||||
|
std::shared_mutex m_ban;
|
||||||
|
|
||||||
|
fs::path file;
|
||||||
|
std::map<std::string, std::pair<std::map<std::string, ushort>, time_t>> ban_list;
|
||||||
|
|
||||||
|
};
|
||||||
@ -1,5 +1,4 @@
|
|||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
mail::mail(std::string filename, std::string subject, std::string sender) :
|
mail::mail(std::string filename, std::string subject, std::string sender) :
|
||||||
filename(filename),
|
filename(filename),
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include "ip_ban.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
#include "user_handler.h"
|
#include "user_handler.h"
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ std::string getSha1(const std::string& p_arg);
|
|||||||
void *clientCommunication(void *data);
|
void *clientCommunication(void *data);
|
||||||
void signalHandler(int sig);
|
void signalHandler(int sig);
|
||||||
|
|
||||||
std::string cmdLOGIN(std::vector<std::string>& received, std::string& loggedInUsername);
|
std::string cmdLOGIN(std::vector<std::string>& received, std::string& loggedInUsername, const std::string& ip);
|
||||||
std::string cmdSEND(std::vector<std::string>& received, const std::string& loggedInUsername);
|
std::string cmdSEND(std::vector<std::string>& received, const std::string& loggedInUsername);
|
||||||
std::string cmdLIST(std::vector<std::string>& received, const std::string& loggedInUsername);
|
std::string cmdLIST(std::vector<std::string>& received, const std::string& loggedInUsername);
|
||||||
std::string cmdREAD(std::vector<std::string>& received, const std::string& loggedInUsername);
|
std::string cmdREAD(std::vector<std::string>& received, const std::string& loggedInUsername);
|
||||||
@ -81,6 +82,13 @@ std::string cmdDEL(std::vector<std::string>& received, const std::string& logged
|
|||||||
inline void exiting();
|
inline void exiting();
|
||||||
inline std::string read_file(std::string_view path);
|
inline std::string read_file(std::string_view path);
|
||||||
|
|
||||||
|
struct args
|
||||||
|
{
|
||||||
|
int socket;
|
||||||
|
std::string ip;
|
||||||
|
fs::path spool_dir;
|
||||||
|
};
|
||||||
|
|
||||||
int main (int argc, char* argv[])
|
int main (int argc, char* argv[])
|
||||||
{
|
{
|
||||||
if (argc < 3 ||
|
if (argc < 3 ||
|
||||||
@ -106,6 +114,8 @@ int main (int argc, char* argv[])
|
|||||||
|
|
||||||
user_handler::getInstance().setSpoolDir(spool_dir);
|
user_handler::getInstance().setSpoolDir(spool_dir);
|
||||||
|
|
||||||
|
ip_ban::getInstance().loadFile(spool_dir / "bans.json");
|
||||||
|
|
||||||
std::atexit(exiting);
|
std::atexit(exiting);
|
||||||
|
|
||||||
char* p;
|
char* p;
|
||||||
@ -181,7 +191,7 @@ int main (int argc, char* argv[])
|
|||||||
ntohs(cliaddress.sin_port));
|
ntohs(cliaddress.sin_port));
|
||||||
// clientCommunication(&new_socket); // returnValue can be ignored
|
// clientCommunication(&new_socket); // returnValue can be ignored
|
||||||
pthread_t tid;
|
pthread_t tid;
|
||||||
pthread_create(&tid, NULL, clientCommunication, (void *)new int(new_socket));
|
pthread_create(&tid, NULL, clientCommunication, static_cast<void *>(new args{new_socket, inet_ntoa(cliaddress.sin_addr), spool_dir}));
|
||||||
threads.push_back(tid);
|
threads.push_back(tid);
|
||||||
new_socket = -1;
|
new_socket = -1;
|
||||||
}
|
}
|
||||||
@ -219,9 +229,12 @@ void printUsage()
|
|||||||
|
|
||||||
void *clientCommunication(void *data)
|
void *clientCommunication(void *data)
|
||||||
{
|
{
|
||||||
|
args* args = (struct args*) data;
|
||||||
|
|
||||||
char buffer[BUF];
|
char buffer[BUF];
|
||||||
int size;
|
int size;
|
||||||
int *current_socket = (int *)data;
|
int *current_socket = &args->socket;
|
||||||
|
std::string ip = args->ip;
|
||||||
|
|
||||||
std::string incomplete_message = "";
|
std::string incomplete_message = "";
|
||||||
|
|
||||||
@ -275,7 +288,7 @@ void *clientCommunication(void *data)
|
|||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case LOGIN:
|
case LOGIN:
|
||||||
response = cmdLOGIN(lines, loggedInUsername);
|
response = cmdLOGIN(lines, loggedInUsername, ip);
|
||||||
break;
|
break;
|
||||||
case SEND:
|
case SEND:
|
||||||
if (lines.size() < 5 || lines.back().compare(".") != 0) {
|
if (lines.size() < 5 || lines.back().compare(".") != 0) {
|
||||||
@ -320,7 +333,7 @@ void *clientCommunication(void *data)
|
|||||||
*current_socket = -1;
|
*current_socket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(current_socket);
|
delete(args);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +407,7 @@ inline void exiting()
|
|||||||
printf("Saving... \n");
|
printf("Saving... \n");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cmdLOGIN(std::vector<std::string>& received, std::string& loggedInUsername)
|
std::string cmdLOGIN(std::vector<std::string>& received, std::string& loggedInUsername, const std::string& ip)
|
||||||
{
|
{
|
||||||
if (received.size() < 3) {
|
if (received.size() < 3) {
|
||||||
return "ERR\n";
|
return "ERR\n";
|
||||||
@ -428,10 +441,16 @@ std::string cmdLOGIN(std::vector<std::string>& received, std::string& loggedInUs
|
|||||||
bindCredentials.bv_len = ldapBindPassword.length();
|
bindCredentials.bv_len = ldapBindPassword.length();
|
||||||
rc = ldap_sasl_bind_s(ldapHandle, ldapBindUser.c_str(), LDAP_SASL_SIMPLE, &bindCredentials, NULL, NULL, NULL);
|
rc = ldap_sasl_bind_s(ldapHandle, ldapBindUser.c_str(), LDAP_SASL_SIMPLE, &bindCredentials, NULL, NULL, NULL);
|
||||||
if (rc != LDAP_SUCCESS) {
|
if (rc != LDAP_SUCCESS) {
|
||||||
|
ip_ban::getInstance().failedAttempt(received.at(1), ip);
|
||||||
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
|
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
|
||||||
return "ERR\n";
|
return "ERR\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ip_ban::getInstance().checkBanned(ip)) {
|
||||||
|
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
|
||||||
|
return "ERR\n";
|
||||||
|
}
|
||||||
|
|
||||||
loggedInUsername = received.at(1);
|
loggedInUsername = received.at(1);
|
||||||
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
|
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user