Keep track of verified and blocked tokens
This commit is contained in:
+106
-2
@@ -14,8 +14,43 @@ Copyright (C) 2026 mrkubax10 <mrkubax10@onet.pl>
|
|||||||
#include <util_cookies.h>
|
#include <util_cookies.h>
|
||||||
#include <util_md5.h>
|
#include <util_md5.h>
|
||||||
|
|
||||||
|
#define MAX_TOKEN_LENGTH 30
|
||||||
|
#define TRACKED_TOKEN_COUNT 1000 // TODO: Allow changing this in server configuration
|
||||||
|
|
||||||
static const char* const TOKEN_COOKIE_NAME = "webgate_token";
|
static const char* const TOKEN_COOKIE_NAME = "webgate_token";
|
||||||
|
|
||||||
|
typedef struct TokenArray {
|
||||||
|
char* tokens;
|
||||||
|
size_t count;
|
||||||
|
} TokenArray;
|
||||||
|
|
||||||
|
static void token_array_init(TokenArray* self) {
|
||||||
|
self->tokens = calloc(TRACKED_TOKEN_COUNT, MAX_TOKEN_LENGTH);
|
||||||
|
memset(self->tokens, 0, TRACKED_TOKEN_COUNT*MAX_TOKEN_LENGTH);
|
||||||
|
self->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void token_array_push(TokenArray* self, const char* token) {
|
||||||
|
strncpy(&self->tokens[self->count*MAX_TOKEN_LENGTH], token, MAX_TOKEN_LENGTH);
|
||||||
|
self->count++;
|
||||||
|
|
||||||
|
// Wrap around when array gets full
|
||||||
|
if(self->count>=TRACKED_TOKEN_COUNT)
|
||||||
|
self->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if token array contains token
|
||||||
|
static bool token_array_contains(const TokenArray* self, const char* token) {
|
||||||
|
for(size_t i = 0; i<self->count; i++) {
|
||||||
|
if(strcmp(&self->tokens[i*MAX_TOKEN_LENGTH], token)==0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TokenArray g_allowed_tokens = {0};
|
||||||
|
static TokenArray g_blocked_tokens = {0};
|
||||||
|
|
||||||
// Returns true if user agent of client which performed the request looks like Git
|
// Returns true if user agent of client which performed the request looks like Git
|
||||||
static bool check_user_agent_exception(request_rec* r) {
|
static bool check_user_agent_exception(request_rec* r) {
|
||||||
static const char GIT_USER_AGENT_PREFIX[] = "git/";
|
static const char GIT_USER_AGENT_PREFIX[] = "git/";
|
||||||
@@ -50,7 +85,9 @@ static void handle_challenge(request_rec* r) {
|
|||||||
"<title>mod_webgate</title>"
|
"<title>mod_webgate</title>"
|
||||||
"</head>"
|
"</head>"
|
||||||
"<body>"
|
"<body>"
|
||||||
"<h5>mod_webgate: Please select appropriate option</h5>", NULL);
|
"<h5>mod_webgate: Please select appropriate option</h5>",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
static const char* OPTION_STRINGS[] = {
|
static const char* OPTION_STRINGS[] = {
|
||||||
"<a href=\"/fail\">I would like to access this server</a><br>",
|
"<a href=\"/fail\">I would like to access this server</a><br>",
|
||||||
@@ -79,7 +116,49 @@ static void handle_challenge(request_rec* r) {
|
|||||||
|
|
||||||
// Finish page
|
// Finish page
|
||||||
ap_rvputs(r, "</body>"
|
ap_rvputs(r, "</body>"
|
||||||
"</html>", NULL);
|
"</html>",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_verification(request_rec* r) {
|
||||||
|
// Send information about access granted
|
||||||
|
ap_set_content_type(r, "text/html");
|
||||||
|
ap_rvputs(r, "<!DOCTYPE HTML>"
|
||||||
|
"<html lang=\"en\">"
|
||||||
|
"<head>"
|
||||||
|
"<title>mod_webgate</title>"
|
||||||
|
"</head>"
|
||||||
|
"<body>"
|
||||||
|
"<h5>mod_webgate: Challenge successful</h5>"
|
||||||
|
"<a href=\"/\">Click here to go to main page</a>"
|
||||||
|
"</body>"
|
||||||
|
"</html>",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_blocked(request_rec* r) {
|
||||||
|
// Send information about access rejection
|
||||||
|
ap_set_content_type(r, "text/html");
|
||||||
|
ap_rvputs(r, "<!DOCTYPE HTML>"
|
||||||
|
"<html lang=\"en\">"
|
||||||
|
"<head>"
|
||||||
|
"<title>mod_webgate</title>"
|
||||||
|
"</head>"
|
||||||
|
"<body>"
|
||||||
|
"Fuck off clanker"
|
||||||
|
"</body>"
|
||||||
|
"</html>",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static apr_status_t post_config_hook(apr_pool_t* pool, apr_pool_t* pool_log, apr_pool_t* pool_temp, server_rec* s) {
|
||||||
|
// Initialize global variables
|
||||||
|
token_array_init(&g_allowed_tokens);
|
||||||
|
token_array_init(&g_blocked_tokens);
|
||||||
|
return APR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int request_check_handler(request_rec* r) {
|
static int request_check_handler(request_rec* r) {
|
||||||
@@ -93,10 +172,35 @@ static int request_check_handler(request_rec* r) {
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if client was blocked
|
||||||
|
if(token_array_contains(&g_blocked_tokens, token)) {
|
||||||
|
handle_blocked(r);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if client is verified
|
||||||
|
if(token_array_contains(&g_allowed_tokens, token))
|
||||||
|
return DECLINED;
|
||||||
|
|
||||||
|
// If client is not blocked and not verified then perhaps they are trying to verify
|
||||||
|
if(strcmp(r->uri, "/fail")==0) {
|
||||||
|
token_array_push(&g_allowed_tokens, token);
|
||||||
|
handle_verification(r);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
if(strcmp(r->uri, "/success")==0) {
|
||||||
|
token_array_push(&g_blocked_tokens, token);
|
||||||
|
handle_blocked(r);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's something else redirect to challenge page
|
||||||
|
handle_challenge(r);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void register_hooks(apr_pool_t* pool) {
|
static void register_hooks(apr_pool_t* pool) {
|
||||||
|
ap_hook_post_config(post_config_hook, NULL, NULL, APR_HOOK_FIRST);
|
||||||
ap_hook_handler(request_check_handler, NULL, NULL, APR_HOOK_FIRST);
|
ap_hook_handler(request_check_handler, NULL, NULL, APR_HOOK_FIRST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user