Skip to content

Commit bff908a

Browse files
author
Sebastiano Merlino
committed
Added support to class ip ban
1 parent af16844 commit bff908a

File tree

6 files changed

+206
-6
lines changed

6 files changed

+206
-6
lines changed

src/HttpUtils.cpp

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@
2424
#include <stdlib.h>
2525
#include <string.h>
2626
#include <arpa/inet.h>
27+
#include <sstream>
28+
#include <iomanip>
2729
//#include <boost/xpressive/xpressive.hpp>
2830

31+
using namespace std;
32+
2933
namespace httpserver {
3034
namespace http {
3135

@@ -201,6 +205,20 @@ std::string get_ip_str(const struct sockaddr *sa, socklen_t maxlen)
201205
return std::string(res);
202206
}
203207

208+
const struct sockaddr str_to_ip(const std::string& src)
209+
{
210+
struct sockaddr s;
211+
if(src.find(":") != std::string::npos)
212+
{
213+
inet_pton(AF_INET6, src.c_str(), (void*) &s);
214+
}
215+
else
216+
{
217+
inet_pton(AF_INET, src.c_str(), (void*) &s);
218+
}
219+
return s;
220+
}
221+
204222
short get_port(const struct sockaddr* sa)
205223
{
206224
switch(sa->sa_family)
@@ -252,5 +270,158 @@ size_t http_unescape (char *val)
252270
return wpos - val; /* = strlen(val) */
253271
}
254272

273+
ip_representation::ip_representation(const struct sockaddr* ip)
274+
{
275+
std::fill(pieces, pieces + 16, 0);
276+
if(ip->sa_family == AF_INET)
277+
{
278+
ip_version = HttpUtils::IPV4;
279+
for(int i=0;i<4;i++)
280+
{
281+
pieces[12+i] = ((u_char*)&(((struct sockaddr_in *)ip)->sin_addr))[i];
282+
}
283+
}
284+
else
285+
{
286+
ip_version = HttpUtils::IPV6;
287+
for(int i=0;i<32;i+=2)
288+
{
289+
pieces[i/2] = ip->sa_data[i] + 16 * ip->sa_data[i+1];
290+
}
291+
}
292+
std::fill(mask, mask + 16, 1);
293+
}
294+
295+
ip_representation::ip_representation(const std::string& ip)
296+
{
297+
std::vector<std::string> parts;
298+
std::fill(mask, mask + 16, 1);
299+
std::fill(pieces, pieces + 16, 0);
300+
if(ip.find(':') != std::string::npos) //IPV6
301+
{
302+
ip_version = HttpUtils::IPV6;
303+
parts = string_utilities::string_split(ip, ':', false);
304+
int y = 0;
305+
for(unsigned int i = 0; i < parts.size(); i++)
306+
{
307+
if(parts[i] != "*" && parts[i] != "")
308+
{
309+
if(parts[i].size() < 4)
310+
{
311+
stringstream ss;
312+
ss << setfill('0') << setw(4) << parts[i];
313+
parts[i] = ss.str();
314+
}
315+
if(parts[i].size() == 4)
316+
{
317+
pieces[y] = strtol((parts[i].substr(0,2)).c_str(),NULL,16);
318+
pieces[y+1] = strtol((parts[i].substr(2,2)).c_str(), NULL, 16);
319+
y += 2;
320+
}
321+
else
322+
{
323+
if(y != 12)
324+
{
325+
//errore
326+
}
327+
if(parts[i].find('.') != std::string::npos)
328+
{
329+
vector<string> subparts = string_utilities::string_split(parts[i], '.');
330+
if(subparts.size() == 4)
331+
{
332+
for(unsigned int ii = 0; ii < subparts.size(); ii++)
333+
{
334+
if(subparts[ii] != "*")
335+
{
336+
pieces[y+ii] = strtol(subparts[ii].c_str(), NULL, 10);
337+
}
338+
else
339+
{
340+
mask[y+ii] = 0;
341+
}
342+
y++;
343+
}
344+
}
345+
else
346+
{
347+
//errore
348+
}
349+
}
350+
else
351+
{
352+
//errore
353+
}
354+
}
355+
}
356+
else if(parts[i] == "*")
357+
{
358+
mask[y] = 0;
359+
y++;
360+
}
361+
else
362+
{
363+
if(parts.size() <= 8)
364+
{
365+
int covered_pieces = 1 + (8 - parts.size());
366+
if(parts[parts.size() - 1].find('.') != std::string::npos)
367+
{
368+
covered_pieces -= 2;
369+
}
370+
for(int k = 0; k < covered_pieces; k++)
371+
{
372+
pieces[y] = 0;
373+
y++;
374+
}
375+
}
376+
else
377+
{
378+
//errore
379+
}
380+
}
381+
}
382+
}
383+
else //IPV4
384+
{
385+
ip_version = HttpUtils::IPV4;
386+
parts = string_utilities::string_split(ip, '.');
387+
if(parts.size() == 4)
388+
{
389+
for(unsigned int i = 0; i < parts.size(); i++)
390+
{
391+
if(parts[i] != "*")
392+
{
393+
pieces[12+i] = strtol(parts[i].c_str(), NULL, 10);
394+
}
395+
else
396+
{
397+
mask[12+i] = 0;
398+
}
399+
}
400+
}
401+
else
402+
{
403+
//errore
404+
}
405+
}
406+
}
407+
408+
bool ip_representation::operator <(const ip_representation& b) const
409+
{
410+
int VAL = 16;
411+
if(this->ip_version == HttpUtils::IPV4 && this->ip_version == b.ip_version)
412+
{
413+
VAL = this->ip_version;
414+
}
415+
for(int i = 16 - VAL; i < 16; i++)
416+
{
417+
if(this->mask[i] == 1 && b.mask[i] == 1 && this->pieces[i] < b.pieces[i])
418+
{
419+
return true;
420+
}
421+
}
422+
return false;
423+
}
424+
425+
255426
};
256427
};

src/Webserver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ int Webserver::buildRequestArgs (void *cls, enum MHD_ValueKind kind, const char
446446

447447
int policyCallback (void *cls, const struct sockaddr* addr, socklen_t addrlen)
448448
{
449-
if(((Webserver*)cls)->bans.count(get_ip_str(addr, addrlen)))
449+
if(((Webserver*)cls)->bans.count(ip_representation(addr)))
450450
return MHD_NO;
451451
#ifdef DEBUG
452452
cout << "IP: " << get_ip_str(addr, addrlen) << " - " << "IP-LEN: " << addrlen << endl;

src/httpserver/HttpUtils.hpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <string>
2626
#include <ctype.h>
2727
#include <vector>
28+
#include <algorithm>
2829
#include <gnutls/gnutls.h>
2930

3031
namespace httpserver {
@@ -51,6 +52,11 @@ class HttpUtils
5152
POOL = MHD_USE_POLL
5253
};
5354

55+
enum IPVersion_T
56+
{
57+
IPV4 = 4, IPV6 = 16
58+
};
59+
5460
#ifdef SWIG
5561
%immutable;
5662
#endif
@@ -242,6 +248,24 @@ class ArgComparator {
242248
}
243249
};
244250

251+
struct ip_representation
252+
{
253+
HttpUtils::IPVersion_T ip_version;
254+
unsigned short pieces[16];
255+
unsigned short mask[16];
256+
257+
ip_representation(HttpUtils::IPVersion_T ip_version) : ip_version(ip_version)
258+
{
259+
std::fill(mask, mask + 16, 1);
260+
std::fill(pieces, pieces + 16, 0);
261+
}
262+
263+
ip_representation(const std::string& ip);
264+
ip_representation(const struct sockaddr* ip);
265+
266+
bool operator <(const ip_representation& b) const;
267+
};
268+
245269
/**
246270
* Method used to get an ip in form of string from a sockaddr structure
247271
* @param sa The sockaddr object to find the ip address from
@@ -266,6 +290,7 @@ short get_port(const struct sockaddr* sa);
266290
*/
267291
size_t http_unescape (char *val);
268292

293+
const struct sockaddr str_to_ip(const std::string& src);
269294
};
270295
};
271296
#endif

src/httpserver/Webserver.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class HttpEndpoint;
5555

5656
using namespace http;
5757

58+
namespace http {
59+
struct ip_representation;
60+
};
61+
5862
/**
5963
* Delegate class used to wrap callbacks dedicated to logging.
6064
**/
@@ -245,9 +249,9 @@ class Webserver
245249

246250
std::map<HttpEndpoint, HttpResource* > registeredResources;
247251
#ifdef USE_CPP_ZEROX
248-
std::unordered_set<std::string> bans;
252+
std::unordered_set<ip_representation> bans;
249253
#else
250-
std::set<std::string> bans;
254+
std::set<ip_representation> bans;
251255
#endif
252256
struct MHD_Daemon *daemon;
253257
static int not_found_page

src/httpserver/string_utilities.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace string_utilities
3636
**/
3737
std::string to_upper_copy(std::string str);
3838
std::string to_lower_copy(std::string str);
39-
std::vector<std::string> string_split(std::string s, char sep);
39+
std::vector<std::string> string_split(std::string s, char sep = ' ', bool collapse = true);
4040
std::string regex_replace(std::string str, std::string pattern, std::string replace_str);
4141

4242
};

src/string_utilities.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ std::string to_lower_copy(std::string str)
5353
return str;
5454
}
5555

56-
std::vector<std::string> string_split(std::string s, char sep)
56+
std::vector<std::string> string_split(std::string s, char sep, bool collapse)
5757
{
5858
std::vector<std::string> v;
5959
std::istringstream buf(s);
6060
for(std::string token; getline(buf, token, sep); )
6161
{
62-
if(token != "")
62+
if((collapse && token != "") || !collapse)
6363
v.push_back(token);
6464
}
6565
return v;

0 commit comments

Comments
 (0)