mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-10-12 01:26:48 +08:00
ip banning: entries hold in raw IP format rather than textual
This commit is contained in:
+2
-2
@@ -66,7 +66,7 @@ message id_req
|
||||
|
||||
message ban_info_rep
|
||||
{
|
||||
required string ip = 1;
|
||||
required bytes ip = 1;
|
||||
required uint32 score = 2;
|
||||
optional uint32 expires = 3;
|
||||
}
|
||||
@@ -78,6 +78,6 @@ message ban_list_rep
|
||||
|
||||
message unban_req
|
||||
{
|
||||
required string ip = 1;
|
||||
required bytes ip = 1;
|
||||
}
|
||||
|
||||
|
||||
+69
-31
@@ -40,14 +40,14 @@
|
||||
#include <tlslib.h>
|
||||
#include <main.h>
|
||||
#include <main-ban.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ccan/hash/hash.h>
|
||||
#include <ccan/htable/htable.h>
|
||||
|
||||
static size_t rehash(const void *_e, void *unused)
|
||||
{
|
||||
ban_entry_st *e = (void*)_e;
|
||||
return hash_any(e->ip, strlen(e->ip), 0);
|
||||
|
||||
return hash_any(e->ip.ip, e->ip.size, 0);
|
||||
}
|
||||
|
||||
/* The first argument is the entry from the hash, and
|
||||
@@ -58,7 +58,7 @@ static bool ban_entry_cmp(const void *_c1, void *_c2)
|
||||
const struct ban_entry_st *c1 = _c1;
|
||||
struct ban_entry_st *c2 = _c2;
|
||||
|
||||
if (strcmp(c1->ip, c2->ip) == 0)
|
||||
if (c1->ip.size == c2->ip.size && memcmp(c1->ip.ip, c2->ip.ip, c1->ip.size) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ struct htable *db = s->ban_db;
|
||||
}
|
||||
|
||||
/* returns -1 if the user is already banned, and zero otherwise */
|
||||
int add_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score)
|
||||
int add_ip_to_ban_list(main_server_st *s, const unsigned char *ip, unsigned ip_size, unsigned score)
|
||||
{
|
||||
struct htable *db = s->ban_db;
|
||||
struct ban_entry_st *e;
|
||||
@@ -109,12 +109,11 @@ int add_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score)
|
||||
int ret = 0;
|
||||
unsigned print_msg;
|
||||
|
||||
if (db == NULL || s->config->max_ban_score == 0 || ip == NULL || ip[0] == 0)
|
||||
if (db == NULL || s->config->max_ban_score == 0 || ip == NULL || (ip_size != 4 && ip_size != 16))
|
||||
return 0;
|
||||
|
||||
/* check if the IP is already there */
|
||||
/* pass the current time somehow */
|
||||
strlcpy(t.ip, ip, sizeof(t.ip));
|
||||
memcpy(t.ip.ip, ip, ip_size);
|
||||
t.ip.size = ip_size;
|
||||
|
||||
e = htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t);
|
||||
if (e == NULL) { /* new entry */
|
||||
@@ -123,7 +122,7 @@ int add_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score)
|
||||
return 0;
|
||||
}
|
||||
|
||||
strlcpy(e->ip, ip, sizeof(e->ip));
|
||||
memcpy(&e->ip, &t.ip, sizeof(e->ip));
|
||||
e->last_reset = now;
|
||||
|
||||
if (htable_add(db, rehash(e, NULL), e) == 0) {
|
||||
@@ -163,25 +162,55 @@ int add_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int add_str_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score)
|
||||
{
|
||||
struct htable *db = s->ban_db;
|
||||
ban_entry_st t;
|
||||
int ret = 0;
|
||||
|
||||
if (db == NULL || s->config->max_ban_score == 0 || ip == NULL || ip[0] == 0)
|
||||
return 0;
|
||||
|
||||
if (strchr(ip, ':') != 0) {
|
||||
ret = inet_pton(AF_INET6, ip, t.ip.ip);
|
||||
t.ip.size = 16;
|
||||
} else {
|
||||
ret = inet_pton(AF_INET, ip, t.ip.ip);
|
||||
t.ip.size = 4;
|
||||
}
|
||||
if (ret != 1) {
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"could not read IP: %s", ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return add_ip_to_ban_list(s, t.ip.ip, t.ip.size, score);
|
||||
}
|
||||
|
||||
/* returns non-zero if there is an IP removed */
|
||||
int remove_ip_from_ban_list(main_server_st *s, const char *ip)
|
||||
int remove_ip_from_ban_list(main_server_st *s, const uint8_t *ip, unsigned size)
|
||||
{
|
||||
struct htable *db = s->ban_db;
|
||||
struct ban_entry_st *e;
|
||||
ban_entry_st t;
|
||||
char txt_ip[MAX_IP_STR];
|
||||
|
||||
if (db == NULL || ip == NULL || ip[0] == 0)
|
||||
if (db == NULL || ip == NULL || size == 0)
|
||||
return 0;
|
||||
|
||||
/* check if the IP is already there */
|
||||
/* pass the current time somehow */
|
||||
strlcpy(t.ip, ip, sizeof(t.ip));
|
||||
if (size == 4 || size == 16) {
|
||||
if (inet_ntop(size==16?AF_INET6:AF_INET, ip, txt_ip, sizeof(txt_ip)) != NULL)
|
||||
mslog(s, NULL, LOG_INFO,
|
||||
"unbanning IP '%s'", txt_ip);
|
||||
|
||||
e = htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t);
|
||||
if (e != NULL) { /* new entry */
|
||||
e->score = 0;
|
||||
e->expires = 0;
|
||||
return 1;
|
||||
memcpy(&t.ip.ip, ip, size);
|
||||
|
||||
e = htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t);
|
||||
if (e != NULL) { /* new entry */
|
||||
e->score = 0;
|
||||
e->expires = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -192,24 +221,33 @@ unsigned check_if_banned(main_server_st *s, struct sockaddr_storage *addr, sockl
|
||||
struct htable *db = s->ban_db;
|
||||
time_t now;
|
||||
ban_entry_st t, *e;
|
||||
unsigned in_size;
|
||||
char txt[MAX_IP_STR];
|
||||
|
||||
if (db == NULL || s->config->max_ban_score == 0)
|
||||
return 0;
|
||||
|
||||
if (human_addr2((struct sockaddr*)addr, addr_size, t.ip, sizeof(t.ip), 0) != NULL) {
|
||||
/* add its current connection points */
|
||||
add_ip_to_ban_list(s, t.ip, s->config->ban_points_connect);
|
||||
in_size = SA_IN_SIZE(addr_size);
|
||||
if (in_size != 4 && in_size != 16) {
|
||||
mslog(s, NULL, LOG_ERR, "unknown address type for %s", human_addr2((struct sockaddr*)addr, addr_size, txt, sizeof(txt), NULL));
|
||||
return 0;
|
||||
}
|
||||
|
||||
now = time(0);
|
||||
e = htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t);
|
||||
if (e != NULL) {
|
||||
if (now > e->expires)
|
||||
return 0;
|
||||
memcpy(t.ip.ip, SA_IN_P_GENERIC(addr, addr_size), SA_IN_SIZE(addr_size));
|
||||
t.ip.size = SA_IN_SIZE(addr_size);
|
||||
|
||||
if (e->score >= s->config->max_ban_score) {
|
||||
mslog(s, NULL, LOG_INFO, "rejected connection from banned IP: %s", t.ip);
|
||||
return 1;
|
||||
}
|
||||
/* add its current connection points */
|
||||
add_ip_to_ban_list(s, t.ip.ip, t.ip.size, s->config->ban_points_connect);
|
||||
|
||||
now = time(0);
|
||||
e = htable_get(db, rehash(&t, NULL), ban_entry_cmp, &t);
|
||||
if (e != NULL) {
|
||||
if (now > e->expires)
|
||||
return 0;
|
||||
|
||||
if (e->score >= s->config->max_ban_score) {
|
||||
mslog(s, NULL, LOG_INFO, "rejected connection from banned IP: %s", human_addr2((struct sockaddr*)addr, addr_size, txt, sizeof(txt), NULL));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
+9
-3
@@ -23,8 +23,13 @@
|
||||
|
||||
# include "main.h"
|
||||
|
||||
typedef struct inaddr_st {
|
||||
uint8_t ip[16];
|
||||
unsigned size; /* 4 or 16 */
|
||||
} inaddr_st;
|
||||
|
||||
typedef struct ban_entry_st {
|
||||
char ip[MAX_IP_STR];
|
||||
inaddr_st ip;
|
||||
unsigned score;
|
||||
|
||||
time_t last_reset; /* the time its score counting started */
|
||||
@@ -33,8 +38,9 @@ typedef struct ban_entry_st {
|
||||
|
||||
void cleanup_banned_entries(main_server_st *s);
|
||||
unsigned check_if_banned(main_server_st *s, struct sockaddr_storage *addr, socklen_t addr_size);
|
||||
int add_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score);
|
||||
int remove_ip_from_ban_list(main_server_st *s, const char *ip);
|
||||
int add_ip_to_ban_list(main_server_st *s, const unsigned char *ip, unsigned ip_size, unsigned score);
|
||||
int add_str_ip_to_ban_list(main_server_st *s, const char *ip, unsigned score);
|
||||
int remove_ip_from_ban_list(main_server_st *s, const uint8_t *ip, unsigned size);
|
||||
unsigned main_ban_db_elems(main_server_st *s);
|
||||
void main_ban_db_deinit(main_server_st *s);
|
||||
void *main_ban_db_init(main_server_st *s);
|
||||
|
||||
+3
-5
@@ -466,7 +466,8 @@ static int append_ban_info(method_ctx *ctx,
|
||||
|
||||
ban_info_rep__init(rep);
|
||||
|
||||
rep->ip = e->ip;
|
||||
rep->ip.data = e->ip.ip;
|
||||
rep->ip.len = e->ip.size;
|
||||
rep->score = e->score;
|
||||
|
||||
if (ctx->s->config->max_ban_score > 0 && e->score >= ctx->s->config->max_ban_score) {
|
||||
@@ -621,10 +622,7 @@ static void method_unban_ip(method_ctx *ctx,
|
||||
return;
|
||||
}
|
||||
|
||||
if (remove_ip_from_ban_list(ctx->s, req->ip) != 0) {
|
||||
if (req->ip)
|
||||
mslog(ctx->s, NULL, LOG_INFO,
|
||||
"unbanning IP '%s' due to ctl request", req->ip);
|
||||
if (remove_ip_from_ban_list(ctx->s, req->ip.data, req->ip.len) != 0) {
|
||||
rep.status = 1;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -370,7 +370,7 @@ int handle_commands(main_server_st * s, struct proc_st *proc)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = add_ip_to_ban_list(s, tmsg->ip, tmsg->score);
|
||||
ret = add_str_ip_to_ban_list(s, tmsg->ip, tmsg->score);
|
||||
|
||||
ban_ip_msg__free_unpacked(tmsg, &pa);
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ int handle_sec_mod_commands(main_server_st * s)
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
ret = add_ip_to_ban_list(s, tmsg->ip, tmsg->score);
|
||||
ret = add_str_ip_to_ban_list(s, tmsg->ip, tmsg->score);
|
||||
if (ret < 0) {
|
||||
reply.reply =
|
||||
AUTH__REP__FAILED;
|
||||
|
||||
+23
-12
@@ -359,9 +359,8 @@ int handle_unban_ip_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *pa
|
||||
BoolMsg *rep;
|
||||
unsigned status;
|
||||
UnbanReq req = UNBAN_REQ__INIT;
|
||||
char txt[MAX_IP_STR];
|
||||
int af;
|
||||
struct sockaddr_storage st;
|
||||
unsigned char tmp[16];
|
||||
PROTOBUF_ALLOCATOR(pa, ctx);
|
||||
|
||||
if (arg == NULL || need_help(arg)) {
|
||||
@@ -378,12 +377,16 @@ int handle_unban_ip_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st *pa
|
||||
af = AF_INET;
|
||||
}
|
||||
|
||||
ret = inet_pton(af, arg, &st);
|
||||
ret = inet_pton(af, arg, tmp);
|
||||
if (ret == 1) {
|
||||
inet_ntop(af, &st, txt, sizeof(txt));
|
||||
req.ip = txt;
|
||||
req.ip.data = tmp;
|
||||
if (af == AF_INET)
|
||||
req.ip.len = 4;
|
||||
else
|
||||
req.ip.len = 16;
|
||||
} else {
|
||||
req.ip = (char*)arg;
|
||||
fprintf(stderr, "Cannot parse IP: %s", arg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = send_cmd(ctx, CTL_CMD_UNBAN_IP, &req,
|
||||
@@ -628,6 +631,8 @@ int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
PROTOBUF_ALLOCATOR(pa, ctx);
|
||||
char txt_ip[MAX_IP_STR];
|
||||
const char *tmp_str;
|
||||
|
||||
init_reply(&raw);
|
||||
|
||||
@@ -647,9 +652,15 @@ int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st
|
||||
print_array_block(out, params);
|
||||
|
||||
for (i=0;i<rep->n_info;i++) {
|
||||
if (rep->info[i]->ip == NULL)
|
||||
if (rep->info[i]->ip.len <= 4)
|
||||
continue;
|
||||
|
||||
if (rep->info[i]->ip.len == 16)
|
||||
tmp_str = inet_ntop(AF_INET6, rep->info[i]->ip.data, txt_ip, sizeof(txt_ip));
|
||||
else
|
||||
tmp_str = inet_ntop(AF_INET, rep->info[i]->ip.data, txt_ip, sizeof(txt_ip));
|
||||
if (tmp_str == NULL)
|
||||
strlcpy(txt_ip, "(unknown)", sizeof(txt_ip));
|
||||
|
||||
/* add header */
|
||||
if (points == 0) {
|
||||
@@ -670,12 +681,12 @@ int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st
|
||||
print_time_ival7(tmpbuf, t, time(0));
|
||||
|
||||
if (HAVE_JSON(params)) {
|
||||
print_single_value(out, params, "IP", rep->info[i]->ip, 1);
|
||||
print_single_value(out, params, "IP", txt_ip, 1);
|
||||
print_single_value_ex(out, params, "Since", str_since, tmpbuf, 1);
|
||||
print_single_value_int(out, params, "Score", rep->info[i]->score, 0);
|
||||
} else {
|
||||
fprintf(out, "%14s %14u %30s (%s)\n",
|
||||
rep->info[i]->ip, (unsigned)rep->info[i]->score, str_since, tmpbuf);
|
||||
txt_ip, (unsigned)rep->info[i]->score, str_since, tmpbuf);
|
||||
}
|
||||
} else {
|
||||
if (i == 0 && NO_JSON(params)) {
|
||||
@@ -685,17 +696,17 @@ int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg, cmd_params_st
|
||||
print_start_block(out, params);
|
||||
|
||||
if (HAVE_JSON(params)) {
|
||||
print_single_value(out, params, "IP", rep->info[i]->ip, 1);
|
||||
print_single_value(out, params, "IP", txt_ip, 1);
|
||||
print_single_value_int(out, params, "Score", rep->info[i]->score, 0);
|
||||
} else {
|
||||
fprintf(out, "%14s %14u\n",
|
||||
rep->info[i]->ip, (unsigned)rep->info[i]->score);
|
||||
txt_ip, (unsigned)rep->info[i]->score);
|
||||
}
|
||||
}
|
||||
|
||||
print_end_block(out, params, i<(rep->n_info-1)?1:0);
|
||||
|
||||
ip_entries_add(ctx, rep->info[i]->ip, strlen(rep->info[i]->ip));
|
||||
ip_entries_add(ctx, txt_ip, strlen(txt_ip));
|
||||
}
|
||||
|
||||
print_end_array_block(out, params);
|
||||
|
||||
Reference in New Issue
Block a user