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
|
||||
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))
|
||||
|
||||
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 <mutex>
|
||||
|
||||
mail::mail(std::string filename, std::string subject, std::string sender) :
|
||||
filename(filename),
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#include "ip_ban.h"
|
||||
#include "user.h"
|
||||
#include "user_handler.h"
|
||||
|
||||
@ -71,7 +72,7 @@ std::string getSha1(const std::string& p_arg);
|
||||
void *clientCommunication(void *data);
|
||||
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 cmdLIST(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 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[])
|
||||
{
|
||||
if (argc < 3 ||
|
||||
@ -106,6 +114,8 @@ int main (int argc, char* argv[])
|
||||
|
||||
user_handler::getInstance().setSpoolDir(spool_dir);
|
||||
|
||||
ip_ban::getInstance().loadFile(spool_dir / "bans.json");
|
||||
|
||||
std::atexit(exiting);
|
||||
|
||||
char* p;
|
||||
@ -181,7 +191,7 @@ int main (int argc, char* argv[])
|
||||
ntohs(cliaddress.sin_port));
|
||||
// clientCommunication(&new_socket); // returnValue can be ignored
|
||||
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);
|
||||
new_socket = -1;
|
||||
}
|
||||
@ -219,9 +229,12 @@ void printUsage()
|
||||
|
||||
void *clientCommunication(void *data)
|
||||
{
|
||||
args* args = (struct args*) data;
|
||||
|
||||
char buffer[BUF];
|
||||
int size;
|
||||
int *current_socket = (int *)data;
|
||||
int *current_socket = &args->socket;
|
||||
std::string ip = args->ip;
|
||||
|
||||
std::string incomplete_message = "";
|
||||
|
||||
@ -275,7 +288,7 @@ void *clientCommunication(void *data)
|
||||
|
||||
switch (cmd) {
|
||||
case LOGIN:
|
||||
response = cmdLOGIN(lines, loggedInUsername);
|
||||
response = cmdLOGIN(lines, loggedInUsername, ip);
|
||||
break;
|
||||
case SEND:
|
||||
if (lines.size() < 5 || lines.back().compare(".") != 0) {
|
||||
@ -320,7 +333,7 @@ void *clientCommunication(void *data)
|
||||
*current_socket = -1;
|
||||
}
|
||||
|
||||
delete(current_socket);
|
||||
delete(args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -394,7 +407,7 @@ inline void exiting()
|
||||
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) {
|
||||
return "ERR\n";
|
||||
@ -428,6 +441,12 @@ std::string cmdLOGIN(std::vector<std::string>& received, std::string& loggedInUs
|
||||
bindCredentials.bv_len = ldapBindPassword.length();
|
||||
rc = ldap_sasl_bind_s(ldapHandle, ldapBindUser.c_str(), LDAP_SASL_SIMPLE, &bindCredentials, NULL, NULL, NULL);
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
ip_ban::getInstance().failedAttempt(received.at(1), ip);
|
||||
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
|
||||
return "ERR\n";
|
||||
}
|
||||
|
||||
if (ip_ban::getInstance().checkBanned(ip)) {
|
||||
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
|
||||
return "ERR\n";
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user