Implement few configuration options for module
This commit is contained in:
+82
-21
@@ -15,28 +15,63 @@ Copyright (C) 2026 mrkubax10 <mrkubax10@onet.pl>
|
|||||||
#include <util_md5.h>
|
#include <util_md5.h>
|
||||||
|
|
||||||
#define MAX_TOKEN_LENGTH 30
|
#define MAX_TOKEN_LENGTH 30
|
||||||
#define TRACKED_TOKEN_COUNT 1000 // TODO: Allow changing this in server configuration
|
|
||||||
|
static void register_hooks(apr_pool_t* pool);
|
||||||
|
static void* create_directory_configuration(apr_pool_t* pool, char* context);
|
||||||
|
static void* merge_directory_configuration(apr_pool_t* pool, void* p_base, void* p_override);
|
||||||
|
static const char* global_config_set_tracked_token_count(cmd_parms* cmd, void* cfg, const char* count);
|
||||||
|
static const char* context_config_set_enabled(cmd_parms* cmd, void* cfg, const char* enabled);
|
||||||
|
|
||||||
|
static const command_rec config_directives[] = {
|
||||||
|
AP_INIT_TAKE1("webgateTrackedTokenCount", global_config_set_tracked_token_count, NULL, RSRC_CONF, "Set maximum amount of verified or blocked access tokens which module will track"),
|
||||||
|
AP_INIT_TAKE1("webgateEnabled", context_config_set_enabled, NULL, ACCESS_CONF, "Configure whether mod_webgate is supposed to be enabled for this location or directory"),
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
module AP_MODULE_DECLARE_DATA webgate_module = {
|
||||||
|
STANDARD20_MODULE_STUFF,
|
||||||
|
create_directory_configuration,
|
||||||
|
merge_directory_configuration,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
config_directives,
|
||||||
|
register_hooks,
|
||||||
|
AP_MODULE_FLAG_NONE
|
||||||
|
};
|
||||||
|
|
||||||
static const char* const TOKEN_COOKIE_NAME = "webgate_token";
|
static const char* const TOKEN_COOKIE_NAME = "webgate_token";
|
||||||
|
|
||||||
|
typedef struct ModuleGlobalConfig {
|
||||||
|
// Maximum amount of access tokens which module will keep track of
|
||||||
|
size_t tracked_token_count;
|
||||||
|
} ModuleGlobalConfig;
|
||||||
|
|
||||||
|
static ModuleGlobalConfig g_global_config;
|
||||||
|
|
||||||
|
// Context aware configuration
|
||||||
|
typedef struct ModuleContextConfig {
|
||||||
|
// Whether module is enabled in current context (for example directory)
|
||||||
|
bool enabled;
|
||||||
|
} ModuleContextConfig;
|
||||||
|
|
||||||
typedef struct TokenArray {
|
typedef struct TokenArray {
|
||||||
char* tokens;
|
char* tokens;
|
||||||
size_t count;
|
size_t count;
|
||||||
} TokenArray;
|
} TokenArray;
|
||||||
|
|
||||||
static void token_array_init(TokenArray* self) {
|
static void token_array_init(TokenArray* self) {
|
||||||
self->tokens = calloc(TRACKED_TOKEN_COUNT, MAX_TOKEN_LENGTH);
|
self->tokens = calloc(g_global_config.tracked_token_count, MAX_TOKEN_LENGTH);
|
||||||
memset(self->tokens, 0, TRACKED_TOKEN_COUNT*MAX_TOKEN_LENGTH);
|
memset(self->tokens, 0, g_global_config.tracked_token_count*MAX_TOKEN_LENGTH);
|
||||||
self->count = 0;
|
self->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void token_array_push(TokenArray* self, const char* token) {
|
static void token_array_push(TokenArray* self, const char* token) {
|
||||||
|
// Wrap around when array gets full
|
||||||
|
if(self->count>=g_global_config.tracked_token_count)
|
||||||
|
self->count = 0;
|
||||||
|
|
||||||
strncpy(&self->tokens[self->count*MAX_TOKEN_LENGTH], token, MAX_TOKEN_LENGTH);
|
strncpy(&self->tokens[self->count*MAX_TOKEN_LENGTH], token, MAX_TOKEN_LENGTH);
|
||||||
self->count++;
|
self->count++;
|
||||||
|
|
||||||
// Wrap around when array gets full
|
|
||||||
if(self->count>=TRACKED_TOKEN_COUNT)
|
|
||||||
self->count = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if token array contains token
|
// Checks if token array contains token
|
||||||
@@ -61,14 +96,14 @@ static bool check_user_agent_exception(request_rec* r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char* generate_token(apr_pool_t* pool) {
|
static const char* generate_token(apr_pool_t* pool) {
|
||||||
char rnd[32];
|
unsigned char rnd[32];
|
||||||
apr_generate_random_bytes(rnd, sizeof(rnd));
|
apr_generate_random_bytes(rnd, sizeof(rnd));
|
||||||
char rnd_md5[APR_MD5_DIGESTSIZE];
|
unsigned char rnd_md5[APR_MD5_DIGESTSIZE];
|
||||||
apr_md5(rnd_md5, rnd, sizeof(rnd));
|
apr_md5(rnd_md5, rnd, sizeof(rnd));
|
||||||
|
|
||||||
const apr_size_t encoded_size = apr_base64_encode_len(sizeof(rnd_md5));
|
const apr_size_t encoded_size = apr_base64_encode_len(sizeof(rnd_md5));
|
||||||
char* output = apr_palloc(pool, encoded_size);
|
char* output = apr_palloc(pool, encoded_size);
|
||||||
apr_base64_encode(output, rnd_md5, sizeof(rnd_md5));
|
apr_base64_encode(output, (char*)rnd_md5, sizeof(rnd_md5));
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +134,7 @@ static void handle_challenge(request_rec* r) {
|
|||||||
|
|
||||||
// Randomize options order
|
// Randomize options order
|
||||||
for(size_t i = 0; i<sizeof(option_order); i++) {
|
for(size_t i = 0; i<sizeof(option_order); i++) {
|
||||||
char swap_index;
|
unsigned char swap_index;
|
||||||
apr_generate_random_bytes(&swap_index, 1);
|
apr_generate_random_bytes(&swap_index, 1);
|
||||||
swap_index%=sizeof(option_order);
|
swap_index%=sizeof(option_order);
|
||||||
if(swap_index==0)
|
if(swap_index==0)
|
||||||
@@ -162,6 +197,10 @@ static apr_status_t post_config_hook(apr_pool_t* pool, apr_pool_t* pool_log, apr
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int request_check_handler(request_rec* r) {
|
static int request_check_handler(request_rec* r) {
|
||||||
|
// Check if module is enabled for current context
|
||||||
|
const ModuleContextConfig* config = (ModuleContextConfig*)ap_get_module_config(r->per_dir_config, &webgate_module);
|
||||||
|
if(!config->enabled)
|
||||||
|
return DECLINED;
|
||||||
// Provide exception for requests performed by Git
|
// Provide exception for requests performed by Git
|
||||||
if(check_user_agent_exception(r))
|
if(check_user_agent_exception(r))
|
||||||
return DECLINED;
|
return DECLINED;
|
||||||
@@ -200,16 +239,38 @@ static int request_check_handler(request_rec* r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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);
|
// Initialize global config
|
||||||
|
g_global_config.tracked_token_count = 1000;
|
||||||
|
ap_hook_post_config(post_config_hook, NULL, NULL, APR_HOOK_LAST);
|
||||||
ap_hook_handler(request_check_handler, NULL, NULL, APR_HOOK_FIRST);
|
ap_hook_handler(request_check_handler, NULL, NULL, APR_HOOK_FIRST);
|
||||||
}
|
}
|
||||||
|
|
||||||
module AP_MODULE_DECLARE_DATA webgate_module = {
|
static void* create_directory_configuration(apr_pool_t* pool, char* context) {
|
||||||
STANDARD20_MODULE_STUFF,
|
ModuleContextConfig* config = apr_palloc(pool, sizeof(ModuleContextConfig));
|
||||||
NULL,
|
if(config)
|
||||||
NULL,
|
config->enabled = false;
|
||||||
NULL,
|
return config;
|
||||||
NULL,
|
}
|
||||||
NULL,
|
|
||||||
register_hooks
|
// Merges configuration of parent directory and subdirectory and produces new configuration
|
||||||
};
|
static void* merge_directory_configuration(apr_pool_t* pool, void* p_base, void* p_override) {
|
||||||
|
const ModuleContextConfig* base = (ModuleContextConfig*)p_base;
|
||||||
|
const ModuleContextConfig* override = (ModuleContextConfig*)p_override;
|
||||||
|
ModuleContextConfig* result = create_directory_configuration(pool, NULL);
|
||||||
|
if(result)
|
||||||
|
result->enabled = base->enabled || override->enabled;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* global_config_set_tracked_token_count(cmd_parms* cmd, void* cfg, const char* count) {
|
||||||
|
g_global_config.tracked_token_count = atol(count);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* context_config_set_enabled(cmd_parms* cmd, void* cfg, const char* enabled) {
|
||||||
|
if(!cfg)
|
||||||
|
return NULL;
|
||||||
|
ModuleContextConfig* config = (ModuleContextConfig*)cfg;
|
||||||
|
config->enabled = strcmp(enabled, "on")==0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user