Generate and send token to client if it's not present
This commit is contained in:
+52
-1
@@ -3,12 +3,63 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|||||||
Copyright (C) 2026 mrkubax10 <mrkubax10@onet.pl>
|
Copyright (C) 2026 mrkubax10 <mrkubax10@onet.pl>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <apr_base64.h>
|
||||||
#include <httpd.h>
|
#include <httpd.h>
|
||||||
#include <http_core.h>
|
#include <http_core.h>
|
||||||
|
#include <http_protocol.h>
|
||||||
|
#include <http_log.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <util_cookies.h>
|
||||||
|
#include <util_md5.h>
|
||||||
|
|
||||||
|
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) {
|
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 = {
|
module AP_MODULE_DECLARE_DATA webgate_module = {
|
||||||
|
|||||||
Reference in New Issue
Block a user