mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 08:46:58 +08:00
occtl: added ability to list banned, and unban IPs
This commit is contained in:
@@ -12,6 +12,8 @@ enum {
|
||||
CTL_CMD_ID_INFO,
|
||||
CTL_CMD_DISCONNECT_NAME,
|
||||
CTL_CMD_DISCONNECT_ID,
|
||||
CTL_CMD_LIST_BANNED,
|
||||
CTL_CMD_UNBAN_IP,
|
||||
|
||||
CTL_CMD_STATUS_REP = 101,
|
||||
CTL_CMD_RELOAD_REP,
|
||||
@@ -19,6 +21,8 @@ enum {
|
||||
CTL_CMD_LIST_REP,
|
||||
CTL_CMD_DISCONNECT_NAME_REP,
|
||||
CTL_CMD_DISCONNECT_ID_REP,
|
||||
CTL_CMD_UNBAN_IP_REP,
|
||||
CTL_CMD_LIST_BANNED_REP,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -61,3 +61,21 @@ message id_req
|
||||
{
|
||||
required sint32 id = 1;
|
||||
}
|
||||
|
||||
message ban_info_rep
|
||||
{
|
||||
required string ip = 1;
|
||||
required uint32 score = 2;
|
||||
optional uint32 expires = 3;
|
||||
}
|
||||
|
||||
message ban_list_rep
|
||||
{
|
||||
repeated ban_info_rep info = 1;
|
||||
}
|
||||
|
||||
message unban_req
|
||||
{
|
||||
required string ip = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,14 +43,6 @@
|
||||
#include <ccan/hash/hash.h>
|
||||
#include <ccan/htable/htable.h>
|
||||
|
||||
typedef struct ban_entry_st {
|
||||
char ip[MAX_IP_STR];
|
||||
unsigned score;
|
||||
|
||||
time_t last_reset; /* the time its score counting started */
|
||||
time_t expires; /* the time after the client is allowed to login */
|
||||
} ban_entry_st;
|
||||
|
||||
static size_t rehash(const void *_e, void *unused)
|
||||
{
|
||||
ban_entry_st *e = (void*)_e;
|
||||
@@ -232,3 +224,4 @@ void cleanup_banned_entries(main_server_st *s)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
|
||||
# include "main.h"
|
||||
|
||||
typedef struct ban_entry_st {
|
||||
char ip[MAX_IP_STR];
|
||||
unsigned score;
|
||||
|
||||
time_t last_reset; /* the time its score counting started */
|
||||
time_t expires; /* the time after the client is allowed to login */
|
||||
} 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);
|
||||
|
||||
@@ -50,6 +50,8 @@ static void method_disconnect_user_name(method_ctx *ctx, int cfd,
|
||||
uint8_t * msg, unsigned msg_size);
|
||||
static void method_disconnect_user_id(method_ctx *ctx, int cfd,
|
||||
uint8_t * msg, unsigned msg_size);
|
||||
static void method_unban_ip(method_ctx *ctx, int cfd,
|
||||
uint8_t * msg, unsigned msg_size);
|
||||
static void method_stop(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_reload(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
@@ -58,6 +60,8 @@ static void method_user_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_id_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
static void method_list_banned(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
|
||||
typedef void (*method_func) (method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size);
|
||||
@@ -76,8 +80,10 @@ static const ctl_method_st methods[] = {
|
||||
ENTRY(CTL_CMD_RELOAD, method_reload),
|
||||
ENTRY(CTL_CMD_STOP, method_stop),
|
||||
ENTRY(CTL_CMD_LIST, method_list_users),
|
||||
ENTRY(CTL_CMD_LIST_BANNED, method_list_banned),
|
||||
ENTRY(CTL_CMD_USER_INFO, method_user_info),
|
||||
ENTRY(CTL_CMD_ID_INFO, method_id_info),
|
||||
ENTRY(CTL_CMD_UNBAN_IP, method_unban_ip),
|
||||
ENTRY(CTL_CMD_DISCONNECT_NAME, method_disconnect_user_name),
|
||||
ENTRY(CTL_CMD_DISCONNECT_ID, method_disconnect_user_id),
|
||||
{NULL, 0, NULL}
|
||||
@@ -425,6 +431,68 @@ static void method_list_users(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
return;
|
||||
}
|
||||
|
||||
static int append_ban_info(method_ctx *ctx,
|
||||
BanListRep *list,
|
||||
struct ban_entry_st *e)
|
||||
{
|
||||
BanInfoRep *rep;
|
||||
|
||||
list->info =
|
||||
talloc_realloc(ctx->pool, list->info, BanInfoRep *, (1 + list->n_info));
|
||||
if (list->info == NULL)
|
||||
return -1;
|
||||
|
||||
rep = list->info[list->n_info] = talloc(ctx->pool, BanInfoRep);
|
||||
if (rep == NULL)
|
||||
return -1;
|
||||
list->n_info++;
|
||||
|
||||
ban_info_rep__init(rep);
|
||||
|
||||
rep->ip = e->ip;
|
||||
rep->score = e->score;
|
||||
|
||||
if (ctx->s->config->max_ban_score > 0 && e->score >= ctx->s->config->max_ban_score) {
|
||||
rep->expires = e->expires;
|
||||
rep->has_expires = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void method_list_banned(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
{
|
||||
BanListRep rep = BAN_LIST_REP__INIT;
|
||||
struct ban_entry_st *e = NULL;
|
||||
struct htable *db = ctx->s->ban_db;
|
||||
int ret;
|
||||
struct htable_iter iter;
|
||||
|
||||
mslog(ctx->s, NULL, LOG_DEBUG, "ctl: list-banned-ips");
|
||||
|
||||
e = htable_first(db, &iter);
|
||||
while (e != NULL) {
|
||||
ret = append_ban_info(ctx, &rep, e);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR,
|
||||
"error appending ban info to reply");
|
||||
goto error;
|
||||
}
|
||||
e = htable_next(db, &iter);
|
||||
}
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_LIST_BANNED_REP, &rep,
|
||||
(pack_size_func) ban_list_rep__get_packed_size,
|
||||
(pack_func) ban_list_rep__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending ban list reply");
|
||||
}
|
||||
|
||||
error:
|
||||
return;
|
||||
}
|
||||
|
||||
static void single_info_common(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
unsigned msg_size, const char *user, unsigned id)
|
||||
{
|
||||
@@ -519,6 +587,42 @@ static void method_id_info(method_ctx *ctx, int cfd, uint8_t * msg,
|
||||
return;
|
||||
}
|
||||
|
||||
static void method_unban_ip(method_ctx *ctx,
|
||||
int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
{
|
||||
UnbanReq *req;
|
||||
BoolMsg rep = BOOL_MSG__INIT;
|
||||
int ret;
|
||||
|
||||
mslog(ctx->s, NULL, LOG_DEBUG, "ctl: unban IP");
|
||||
|
||||
req = unban_req__unpack(NULL, msg_size, msg);
|
||||
if (req == NULL) {
|
||||
mslog(ctx->s, NULL, LOG_ERR,
|
||||
"error parsing unban IP request");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req->ip) {
|
||||
remove_ip_from_ban_list(ctx->s, req->ip);
|
||||
rep.status = 1;
|
||||
mslog(ctx->s, NULL, LOG_INFO,
|
||||
"unbanning IP '%s' due to ctl request", req->ip);
|
||||
}
|
||||
|
||||
unban_req__free_unpacked(req, NULL);
|
||||
|
||||
ret = send_msg(ctx->pool, cfd, CTL_CMD_UNBAN_IP_REP, &rep,
|
||||
(pack_size_func) bool_msg__get_packed_size,
|
||||
(pack_func) bool_msg__pack);
|
||||
if (ret < 0) {
|
||||
mslog(ctx->s, NULL, LOG_ERR, "error sending unban IP ctl reply");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void method_disconnect_user_name(method_ctx *ctx,
|
||||
int cfd, uint8_t * msg,
|
||||
unsigned msg_size)
|
||||
|
||||
116
src/occtl-unix.c
116
src/occtl-unix.c
@@ -50,10 +50,12 @@ static uint8_t msg_map[] = {
|
||||
[CTL_CMD_RELOAD] = CTL_CMD_RELOAD_REP,
|
||||
[CTL_CMD_STOP] = CTL_CMD_STOP_REP,
|
||||
[CTL_CMD_LIST] = CTL_CMD_LIST_REP,
|
||||
[CTL_CMD_LIST_BANNED] = CTL_CMD_LIST_BANNED_REP,
|
||||
[CTL_CMD_USER_INFO] = CTL_CMD_LIST_REP,
|
||||
[CTL_CMD_ID_INFO] = CTL_CMD_LIST_REP,
|
||||
[CTL_CMD_DISCONNECT_NAME] = CTL_CMD_DISCONNECT_NAME_REP,
|
||||
[CTL_CMD_DISCONNECT_ID] = CTL_CMD_DISCONNECT_ID_REP,
|
||||
[CTL_CMD_UNBAN_IP] = CTL_CMD_UNBAN_IP_REP,
|
||||
};
|
||||
|
||||
struct cmd_reply_st {
|
||||
@@ -339,6 +341,56 @@ int handle_stop_cmd(struct unix_ctx *ctx, const char *arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_unban_ip_cmd(struct unix_ctx *ctx, const char *arg)
|
||||
{
|
||||
int ret;
|
||||
struct cmd_reply_st raw;
|
||||
BoolMsg *rep;
|
||||
unsigned status;
|
||||
UnbanReq req = UNBAN_REQ__INIT;
|
||||
PROTOBUF_ALLOCATOR(pa, ctx);
|
||||
|
||||
if (arg == NULL || need_help(arg)) {
|
||||
check_cmd_help(rl_line_buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
init_reply(&raw);
|
||||
|
||||
req.ip = (void*)arg;
|
||||
|
||||
ret = send_cmd(ctx, CTL_CMD_UNBAN_IP, &req,
|
||||
(pack_size_func)unban_req__get_packed_size,
|
||||
(pack_func)unban_req__pack, &raw);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rep = bool_msg__unpack(&pa, raw.data_size, raw.data);
|
||||
if (rep == NULL)
|
||||
goto error;
|
||||
|
||||
status = rep->status;
|
||||
bool_msg__free_unpacked(rep, &pa);
|
||||
|
||||
if (status != 0) {
|
||||
printf("IP '%s' was unbanned\n", arg);
|
||||
} else {
|
||||
printf("could not unban IP '%s'\n", arg);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
|
||||
error:
|
||||
fprintf(stderr, ERR_SERVER_UNREACHABLE);
|
||||
ret = 1;
|
||||
cleanup:
|
||||
free_reply(&raw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_disconnect_user_cmd(struct unix_ctx *ctx, const char *arg)
|
||||
{
|
||||
int ret;
|
||||
@@ -533,6 +585,70 @@ int handle_list_users_cmd(struct unix_ctx *ctx, const char *arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_list_banned_cmd(struct unix_ctx *ctx, const char *arg)
|
||||
{
|
||||
int ret;
|
||||
struct cmd_reply_st raw;
|
||||
BanListRep *rep = NULL;
|
||||
unsigned i;
|
||||
char str_since[64];
|
||||
FILE *out;
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
PROTOBUF_ALLOCATOR(pa, ctx);
|
||||
|
||||
init_reply(&raw);
|
||||
|
||||
out = pager_start();
|
||||
|
||||
ret = send_cmd(ctx, CTL_CMD_LIST_BANNED, NULL, NULL, NULL, &raw);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rep = ban_list_rep__unpack(&pa, raw.data_size, raw.data);
|
||||
if (rep == NULL)
|
||||
goto error;
|
||||
|
||||
for (i=0;i<rep->n_info;i++) {
|
||||
if (rep->info[i]->ip == NULL)
|
||||
continue;
|
||||
|
||||
/* add header */
|
||||
if (i == 0) {
|
||||
fprintf(out, "%14s %14s %30s\n",
|
||||
"IP", "score", "expires");
|
||||
}
|
||||
|
||||
if (rep->info[i]->has_expires) {
|
||||
t = rep->info[i]->expires;
|
||||
tm = localtime(&t);
|
||||
strftime(str_since, sizeof(str_since), DATE_TIME_FMT, tm);
|
||||
} else {
|
||||
str_since[0] = 0;
|
||||
}
|
||||
|
||||
fprintf(out, "%14s %14u %30s\n",
|
||||
rep->info[i]->ip, (unsigned)rep->info[i]->score, str_since);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
|
||||
error:
|
||||
ret = 1;
|
||||
fprintf(stderr, ERR_SERVER_UNREACHABLE);
|
||||
|
||||
cleanup:
|
||||
if (rep != NULL)
|
||||
ban_list_rep__free_unpacked(rep, &pa);
|
||||
|
||||
free_reply(&raw);
|
||||
pager_stop(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int print_list_entries(FILE* out, const char* name, char **val, unsigned vsize)
|
||||
{
|
||||
const char * tmp;
|
||||
|
||||
@@ -51,12 +51,16 @@ static const commands_st commands[] = {
|
||||
"Disconnect the specified user", 1, 1),
|
||||
ENTRY("disconnect id", "[ID]", handle_disconnect_id_cmd,
|
||||
"Disconnect the specified ID", 1, 1),
|
||||
ENTRY("unban", "[IP]", handle_unban_ip_cmd,
|
||||
"Unban the specified IP", 1, 1),
|
||||
ENTRY("reload", NULL, handle_reload_cmd,
|
||||
"Reloads the server configuration", 1, 1),
|
||||
ENTRY("show status", NULL, handle_status_cmd,
|
||||
"Prints the status of the server", 1, 1),
|
||||
ENTRY("show users", NULL, handle_list_users_cmd,
|
||||
"Prints the connected users", 1, 1),
|
||||
ENTRY("show banned", NULL, handle_list_banned_cmd,
|
||||
"Prints the banned IP addresses", 1, 1),
|
||||
ENTRY("show user", "[NAME]", handle_show_user_cmd,
|
||||
"Prints information on the specified user", 1, 1),
|
||||
ENTRY("show id", "[ID]", handle_show_id_cmd,
|
||||
|
||||
@@ -53,9 +53,11 @@ typedef int (*cmd_func) (CONN_TYPE * conn, const char *arg);
|
||||
|
||||
int handle_status_cmd(CONN_TYPE * conn, const char *arg);
|
||||
int handle_list_users_cmd(CONN_TYPE * conn, const char *arg);
|
||||
int handle_list_banned_cmd(CONN_TYPE * conn, const char *arg);
|
||||
int handle_show_user_cmd(CONN_TYPE * conn, const char *arg);
|
||||
int handle_show_id_cmd(CONN_TYPE * conn, const char *arg);
|
||||
int handle_disconnect_user_cmd(CONN_TYPE * conn, const char *arg);
|
||||
int handle_unban_ip_cmd(CONN_TYPE * conn, const char *arg);
|
||||
int handle_disconnect_id_cmd(CONN_TYPE * conn, const char *arg);
|
||||
int handle_reload_cmd(CONN_TYPE * conn, const char *arg);
|
||||
int handle_stop_cmd(CONN_TYPE * conn, const char *arg);
|
||||
|
||||
Reference in New Issue
Block a user