Skip to content

Commit

Permalink
feat: blacklist ips
Browse files Browse the repository at this point in the history
  • Loading branch information
araujo88 committed Mar 25, 2024
1 parent 919e985 commit dfc8495
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 47 deletions.
Empty file added blacklist.txt
Empty file.
9 changes: 9 additions & 0 deletions include/base_exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ namespace tpt
return "Error - JSON parsing error";
}
};

class IPBlackListedException : public std::exception
{
public:
const char *what() const throw()
{
return "Error - IP is blacklisted";
}
};
}

#endif
4 changes: 4 additions & 0 deletions include/unix_socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include <vector>
#include "socket.hpp"
#include "utils.hpp"
#include "base_exceptions.hpp"

namespace tpt
{
Expand All @@ -24,6 +27,7 @@ namespace tpt
unsigned int max_connections;
std::string ip_address;
std::string client_ip;
std::vector<std::string> ip_blacklist;

public:
UnixSocket();
Expand Down
1 change: 1 addition & 0 deletions include/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace tpt
static std::string &formatJSON(std::string &json);
static bool isValidJSON(const std::string &str);
static std::string sanitizePath(const std::string &path);
static void fillIPBlacklist(std::vector<std::string> &ip_blacklist);
};
}

Expand Down
109 changes: 62 additions & 47 deletions src/teapot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,68 +73,76 @@ void Teapot::mainEventLoop(SOCKET client_socket)
std::string content_type;
unsigned int status_code = 500; // Default to internal server error in case of early failure

if (request)
try
{
context->request = &(*request);
this->sanitizer_middleware.handle(context.get());
std::string uri = request->getUri();
if (uri == "/")
uri = "/index.html"; // Normalize root access to a specific file, e.g., index.html
std::string method = request->getMethod();
content_type = determineContentType(uri); // Determine content type early based on URI

std::cout << "[" << request->getDate() << "] " << this->socket.getClientIp() + " " << method << " " << uri << " HTTP/1.1 ";

if (method == "GET")
if (request)
{
// Check for predefined routes or responses before attempting to read a file
auto routeIt = this->routes.find(uri);
auto jsonIt = this->json_responses.find(uri);
auto htmlIt = this->html_responses.find(uri);
context->request = &(*request);
this->sanitizer_middleware.handle(context.get());
std::string uri = request->getUri();
if (uri == "/")
uri = "/index.html"; // Normalize root access to a specific file, e.g., index.html
std::string method = request->getMethod();
content_type = determineContentType(uri); // Determine content type early based on URI

if (routeIt != this->routes.end())
{
body = Utils::readFileToBuffer(this->static_files_dir + routeIt->second);
status_code = 200;
}
else if (jsonIt != this->json_responses.end())
{
body = jsonIt->second;
status_code = 200;
content_type = "application/json";
}
else if (htmlIt != this->html_responses.end())
{
body = htmlIt->second;
status_code = 200;
content_type = "text/html";
}
else
std::cout << "[" << request->getDate() << "] " << this->socket.getClientIp() + " " << method << " " << uri << " HTTP/1.1 ";

if (method == "GET")
{
try
// Check for predefined routes or responses before attempting to read a file
auto routeIt = this->routes.find(uri);
auto jsonIt = this->json_responses.find(uri);
auto htmlIt = this->html_responses.find(uri);

if (routeIt != this->routes.end())
{
body = Utils::readFileToBuffer(this->static_files_dir + uri);
body = Utils::readFileToBuffer(this->static_files_dir + routeIt->second);
status_code = 200;
}
catch (FileNotFoundException &)
else if (jsonIt != this->json_responses.end())
{
body = Utils::readFileToBuffer(this->static_files_dir + "/404.html");
body = jsonIt->second;
status_code = 200;
content_type = "application/json";
}
else if (htmlIt != this->html_responses.end())
{
body = htmlIt->second;
status_code = 200;
content_type = "text/html";
status_code = 404;
}
else
{
try
{
body = Utils::readFileToBuffer(this->static_files_dir + uri);
status_code = 200;
}
catch (FileNotFoundException &)
{
body = Utils::readFileToBuffer(this->static_files_dir + "/404.html");
content_type = "text/html";
status_code = 404;
}
}
}
else
{
// If not GET, assume method not supported
body = Utils::readFileToBuffer(this->static_files_dir + "/405.html");
content_type = "text/html";
status_code = 405;
}
}
else
{
// If not GET, assume method not supported
body = Utils::readFileToBuffer(this->static_files_dir + "/405.html");
// Handle parsing failure by responding with 500 Internal Server Error
body = Utils::readFileToBuffer(this->static_files_dir + "/500.html");
content_type = "text/html";
status_code = 405;
}
}
else
catch (...)
{
// Handle parsing failure by responding with 500 Internal Server Error
body = Utils::readFileToBuffer(this->static_files_dir + "/500.html");
content_type = "text/html";
}
Expand Down Expand Up @@ -210,9 +218,16 @@ void Teapot::run()
SOCKET client_socket;
void *client_addr = nullptr;

socket.acceptConnection(client_socket, client_addr);

std::jthread th(&Teapot::mainEventLoop, this, client_socket);
try
{
socket.acceptConnection(client_socket, client_addr);
std::jthread th(&Teapot::mainEventLoop, this, client_socket);
}
catch (IPBlackListedException &e)
{
std::cout << e.what();
this->socket.closeSocket(client_socket);
}
}
}

Expand Down
19 changes: 19 additions & 0 deletions src/unix_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ UnixSocket::UnixSocket()
std::cout << "Error code: " + errno << std::endl;
exit(EXIT_FAILURE);
}
std::cout << "Socket created!" << std::endl;

this->server_address.sin_family = AF_INET;
this->server_address.sin_port = htons(this->port);
this->server_address.sin_addr.s_addr = inet_addr(this->ip_address.c_str());

Utils::fillIPBlacklist(this->ip_blacklist);
}

UnixSocket::UnixSocket(unsigned int port)
Expand All @@ -37,10 +40,13 @@ UnixSocket::UnixSocket(unsigned int port)
std::cout << "Error code: " + errno << std::endl;
exit(EXIT_FAILURE);
}
std::cout << "Socket created!" << std::endl;

this->server_address.sin_family = AF_INET;
this->server_address.sin_port = htons(this->port);
this->server_address.sin_addr.s_addr = inet_addr(this->ip_address.c_str());

Utils::fillIPBlacklist(this->ip_blacklist);
}

UnixSocket::UnixSocket(std::string ip_address, unsigned int port)
Expand All @@ -57,10 +63,13 @@ UnixSocket::UnixSocket(std::string ip_address, unsigned int port)
std::cout << "Error code: " + errno << std::endl;
exit(EXIT_FAILURE);
}
std::cout << "Socket created!" << std::endl;

this->server_address.sin_family = AF_INET;
this->server_address.sin_port = htons(this->port);
this->server_address.sin_addr.s_addr = inet_addr(this->ip_address.c_str());

Utils::fillIPBlacklist(this->ip_blacklist);
}

UnixSocket::UnixSocket(std::string ip_address, unsigned int port, unsigned int max_connections)
Expand All @@ -82,6 +91,8 @@ UnixSocket::UnixSocket(std::string ip_address, unsigned int port, unsigned int m
this->server_address.sin_family = AF_INET;
this->server_address.sin_port = htons(this->port);
this->server_address.sin_addr.s_addr = inet_addr(this->ip_address.c_str());

Utils::fillIPBlacklist(this->ip_blacklist);
}

void UnixSocket::bindSocket()
Expand Down Expand Up @@ -141,6 +152,14 @@ void UnixSocket::acceptConnection(SOCKET &client_socket, void *client_address)
}

this->client_ip = std::string(ip_str);

for (auto it : this->ip_blacklist)
{
if (this->client_ip == it)
{
throw IPBlackListedException();
}
}
}

ssize_t UnixSocket::receiveData(SOCKET client_socket, char *buffer, unsigned int buffer_size)
Expand Down
21 changes: 21 additions & 0 deletions src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,24 @@ std::string Utils::sanitizePath(const std::string &path)
}
return sanitized;
}

void Utils::fillIPBlacklist(std::vector<std::string> &ip_blacklist)
{
std::ifstream file("blacklist.txt");
std::string ip;

if (!file)
{
std::cerr << "Unable to open blacklist.txt for reading." << std::endl;
}

while (std::getline(file, ip))
{
// Assuming each line in the file contains one IP address.
// You might want to add validation here to ensure the line actually
// contains an IP address or matches your criteria.
ip_blacklist.push_back(ip);
}

file.close();
}

0 comments on commit dfc8495

Please sign in to comment.