From be1f75c35b4459d9efdff09528a028b750634e0f Mon Sep 17 00:00:00 2001 From: mrkubax10 Date: Wed, 29 Apr 2026 22:40:52 +0200 Subject: [PATCH] Generate and send token to client if it's not present --- mod_webgate.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/mod_webgate.c b/mod_webgate.c index f7e3944..24185ed 100644 --- a/mod_webgate.c +++ b/mod_webgate.c @@ -3,12 +3,63 @@ SPDX-License-Identifier: AGPL-3.0-or-later Copyright (C) 2026 mrkubax10 */ +#include #include #include +#include +#include +#include #include +#include +#include +#include + +static const char* const TOKEN_COOKIE_NAME = "webgate_token"; + +// Returns true if user agent of client which performed the request looks like Git +static bool check_user_agent_exception(request_rec* r) { + static const char GIT_USER_AGENT_PREFIX[] = "git/"; + const char* const user_agent = apr_table_get(r->headers_in, "User-Agent"); + if(!user_agent || strncmp(user_agent, GIT_USER_AGENT_PREFIX, sizeof(GIT_USER_AGENT_PREFIX))!=0) + return false; + return apr_table_get(r->headers_in, "Git-Protocol"); +} + +static char* generate_token(apr_pool_t* pool) { + char rnd[32]; + apr_generate_random_bytes(rnd, sizeof(rnd)); + char rnd_md5[APR_MD5_DIGESTSIZE]; + apr_md5(rnd_md5, rnd, sizeof(rnd)); + + const apr_size_t encoded_size = apr_base64_encode_len(sizeof(rnd_md5)); + char* output = apr_palloc(pool, encoded_size); + apr_base64_encode(output, rnd_md5, sizeof(rnd_md5)); + return output; +} + +// Generates new token and sets HTTP cookie containing it then presents client with challenge +static void handle_challenge(request_rec* r) { + char* generated = generate_token(r->pool); + ap_cookie_write(r, TOKEN_COOKIE_NAME, generated, NULL, 0, r->headers_out, NULL); + ap_rprintf(r, "Token: %s\n", generated); +} + +static int request_check_handler(request_rec* r) { + // Provide exception for requests performed by Git + if(check_user_agent_exception(r)) + return DECLINED; + // Check if client already has the token + const char* token; + if(ap_cookie_read(r, TOKEN_COOKIE_NAME, &token, 0)!=APR_SUCCESS || !token) { + handle_challenge(r); + return OK; + } + + return OK; +} static void register_hooks(apr_pool_t* pool) { - printf("Registering hooks\n"); + ap_hook_handler(request_check_handler, NULL, NULL, APR_HOOK_FIRST); } module AP_MODULE_DECLARE_DATA webgate_module = {