Skip to content

Commit dfc8495

Browse files
committed
feat: blacklist ips
1 parent 919e985 commit dfc8495

7 files changed

+116
-47
lines changed

blacklist.txt

Whitespace-only changes.

include/base_exceptions.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ namespace tpt
2121
return "Error - JSON parsing error";
2222
}
2323
};
24+
25+
class IPBlackListedException : public std::exception
26+
{
27+
public:
28+
const char *what() const throw()
29+
{
30+
return "Error - IP is blacklisted";
31+
}
32+
};
2433
}
2534

2635
#endif

include/unix_socket.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
#include <sys/socket.h>
1212
#include <unistd.h>
1313
#include <errno.h>
14+
#include <vector>
1415
#include "socket.hpp"
16+
#include "utils.hpp"
17+
#include "base_exceptions.hpp"
1518

1619
namespace tpt
1720
{
@@ -24,6 +27,7 @@ namespace tpt
2427
unsigned int max_connections;
2528
std::string ip_address;
2629
std::string client_ip;
30+
std::vector<std::string> ip_blacklist;
2731

2832
public:
2933
UnixSocket();

include/utils.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace tpt
2424
static std::string &formatJSON(std::string &json);
2525
static bool isValidJSON(const std::string &str);
2626
static std::string sanitizePath(const std::string &path);
27+
static void fillIPBlacklist(std::vector<std::string> &ip_blacklist);
2728
};
2829
}
2930

src/teapot.cpp

+62-47
Original file line numberDiff line numberDiff line change
@@ -73,68 +73,76 @@ void Teapot::mainEventLoop(SOCKET client_socket)
7373
std::string content_type;
7474
unsigned int status_code = 500; // Default to internal server error in case of early failure
7575

76-
if (request)
76+
try
7777
{
78-
context->request = &(*request);
79-
this->sanitizer_middleware.handle(context.get());
80-
std::string uri = request->getUri();
81-
if (uri == "/")
82-
uri = "/index.html"; // Normalize root access to a specific file, e.g., index.html
83-
std::string method = request->getMethod();
84-
content_type = determineContentType(uri); // Determine content type early based on URI
85-
86-
std::cout << "[" << request->getDate() << "] " << this->socket.getClientIp() + " " << method << " " << uri << " HTTP/1.1 ";
87-
88-
if (method == "GET")
78+
if (request)
8979
{
90-
// Check for predefined routes or responses before attempting to read a file
91-
auto routeIt = this->routes.find(uri);
92-
auto jsonIt = this->json_responses.find(uri);
93-
auto htmlIt = this->html_responses.find(uri);
80+
context->request = &(*request);
81+
this->sanitizer_middleware.handle(context.get());
82+
std::string uri = request->getUri();
83+
if (uri == "/")
84+
uri = "/index.html"; // Normalize root access to a specific file, e.g., index.html
85+
std::string method = request->getMethod();
86+
content_type = determineContentType(uri); // Determine content type early based on URI
9487

95-
if (routeIt != this->routes.end())
96-
{
97-
body = Utils::readFileToBuffer(this->static_files_dir + routeIt->second);
98-
status_code = 200;
99-
}
100-
else if (jsonIt != this->json_responses.end())
101-
{
102-
body = jsonIt->second;
103-
status_code = 200;
104-
content_type = "application/json";
105-
}
106-
else if (htmlIt != this->html_responses.end())
107-
{
108-
body = htmlIt->second;
109-
status_code = 200;
110-
content_type = "text/html";
111-
}
112-
else
88+
std::cout << "[" << request->getDate() << "] " << this->socket.getClientIp() + " " << method << " " << uri << " HTTP/1.1 ";
89+
90+
if (method == "GET")
11391
{
114-
try
92+
// Check for predefined routes or responses before attempting to read a file
93+
auto routeIt = this->routes.find(uri);
94+
auto jsonIt = this->json_responses.find(uri);
95+
auto htmlIt = this->html_responses.find(uri);
96+
97+
if (routeIt != this->routes.end())
11598
{
116-
body = Utils::readFileToBuffer(this->static_files_dir + uri);
99+
body = Utils::readFileToBuffer(this->static_files_dir + routeIt->second);
117100
status_code = 200;
118101
}
119-
catch (FileNotFoundException &)
102+
else if (jsonIt != this->json_responses.end())
120103
{
121-
body = Utils::readFileToBuffer(this->static_files_dir + "/404.html");
104+
body = jsonIt->second;
105+
status_code = 200;
106+
content_type = "application/json";
107+
}
108+
else if (htmlIt != this->html_responses.end())
109+
{
110+
body = htmlIt->second;
111+
status_code = 200;
122112
content_type = "text/html";
123-
status_code = 404;
113+
}
114+
else
115+
{
116+
try
117+
{
118+
body = Utils::readFileToBuffer(this->static_files_dir + uri);
119+
status_code = 200;
120+
}
121+
catch (FileNotFoundException &)
122+
{
123+
body = Utils::readFileToBuffer(this->static_files_dir + "/404.html");
124+
content_type = "text/html";
125+
status_code = 404;
126+
}
124127
}
125128
}
129+
else
130+
{
131+
// If not GET, assume method not supported
132+
body = Utils::readFileToBuffer(this->static_files_dir + "/405.html");
133+
content_type = "text/html";
134+
status_code = 405;
135+
}
126136
}
127137
else
128138
{
129-
// If not GET, assume method not supported
130-
body = Utils::readFileToBuffer(this->static_files_dir + "/405.html");
139+
// Handle parsing failure by responding with 500 Internal Server Error
140+
body = Utils::readFileToBuffer(this->static_files_dir + "/500.html");
131141
content_type = "text/html";
132-
status_code = 405;
133142
}
134143
}
135-
else
144+
catch (...)
136145
{
137-
// Handle parsing failure by responding with 500 Internal Server Error
138146
body = Utils::readFileToBuffer(this->static_files_dir + "/500.html");
139147
content_type = "text/html";
140148
}
@@ -210,9 +218,16 @@ void Teapot::run()
210218
SOCKET client_socket;
211219
void *client_addr = nullptr;
212220

213-
socket.acceptConnection(client_socket, client_addr);
214-
215-
std::jthread th(&Teapot::mainEventLoop, this, client_socket);
221+
try
222+
{
223+
socket.acceptConnection(client_socket, client_addr);
224+
std::jthread th(&Teapot::mainEventLoop, this, client_socket);
225+
}
226+
catch (IPBlackListedException &e)
227+
{
228+
std::cout << e.what();
229+
this->socket.closeSocket(client_socket);
230+
}
216231
}
217232
}
218233

src/unix_socket.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ UnixSocket::UnixSocket()
1717
std::cout << "Error code: " + errno << std::endl;
1818
exit(EXIT_FAILURE);
1919
}
20+
std::cout << "Socket created!" << std::endl;
2021

2122
this->server_address.sin_family = AF_INET;
2223
this->server_address.sin_port = htons(this->port);
2324
this->server_address.sin_addr.s_addr = inet_addr(this->ip_address.c_str());
25+
26+
Utils::fillIPBlacklist(this->ip_blacklist);
2427
}
2528

2629
UnixSocket::UnixSocket(unsigned int port)
@@ -37,10 +40,13 @@ UnixSocket::UnixSocket(unsigned int port)
3740
std::cout << "Error code: " + errno << std::endl;
3841
exit(EXIT_FAILURE);
3942
}
43+
std::cout << "Socket created!" << std::endl;
4044

4145
this->server_address.sin_family = AF_INET;
4246
this->server_address.sin_port = htons(this->port);
4347
this->server_address.sin_addr.s_addr = inet_addr(this->ip_address.c_str());
48+
49+
Utils::fillIPBlacklist(this->ip_blacklist);
4450
}
4551

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

6168
this->server_address.sin_family = AF_INET;
6269
this->server_address.sin_port = htons(this->port);
6370
this->server_address.sin_addr.s_addr = inet_addr(this->ip_address.c_str());
71+
72+
Utils::fillIPBlacklist(this->ip_blacklist);
6473
}
6574

6675
UnixSocket::UnixSocket(std::string ip_address, unsigned int port, unsigned int max_connections)
@@ -82,6 +91,8 @@ UnixSocket::UnixSocket(std::string ip_address, unsigned int port, unsigned int m
8291
this->server_address.sin_family = AF_INET;
8392
this->server_address.sin_port = htons(this->port);
8493
this->server_address.sin_addr.s_addr = inet_addr(this->ip_address.c_str());
94+
95+
Utils::fillIPBlacklist(this->ip_blacklist);
8596
}
8697

8798
void UnixSocket::bindSocket()
@@ -141,6 +152,14 @@ void UnixSocket::acceptConnection(SOCKET &client_socket, void *client_address)
141152
}
142153

143154
this->client_ip = std::string(ip_str);
155+
156+
for (auto it : this->ip_blacklist)
157+
{
158+
if (this->client_ip == it)
159+
{
160+
throw IPBlackListedException();
161+
}
162+
}
144163
}
145164

146165
ssize_t UnixSocket::receiveData(SOCKET client_socket, char *buffer, unsigned int buffer_size)

src/utils.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,24 @@ std::string Utils::sanitizePath(const std::string &path)
126126
}
127127
return sanitized;
128128
}
129+
130+
void Utils::fillIPBlacklist(std::vector<std::string> &ip_blacklist)
131+
{
132+
std::ifstream file("blacklist.txt");
133+
std::string ip;
134+
135+
if (!file)
136+
{
137+
std::cerr << "Unable to open blacklist.txt for reading." << std::endl;
138+
}
139+
140+
while (std::getline(file, ip))
141+
{
142+
// Assuming each line in the file contains one IP address.
143+
// You might want to add validation here to ensure the line actually
144+
// contains an IP address or matches your criteria.
145+
ip_blacklist.push_back(ip);
146+
}
147+
148+
file.close();
149+
}

0 commit comments

Comments
 (0)