Files
MythEclipse c6fd9ec268 feat: challenge registry-driven platform + XVI/XVII imports + admin toggle + domain rename
- Rename repo/domain: attack-defense-platform / attackdefense.imrnes.team (all refs replaced)
- challenge_registry.json: single source of truth (28 challs across gemastik18/xvi/xvii)
- teams.py: registry-driven CHALLENGES, set_challenge_enabled, sync_challenge_runtime
  (apply enable/disable to live teams: build/up or stop/remove + receiver restart)
- compose_gen.py: render per-team compose from canonical per-challenge templates
  (image reuse, per-team ports 30xxx, flag mounts, passwords)
- gen_canonical_composes.py: canonical docker-compose.yml for all services
- import_new_challenges.py: import XVI/XVII services + EOL base image fixes
  (debian:buster→bookworm, node:14→20, python:3.7-slim→3.11)
- receiver: xvi package (10 checkers) + xvii package (12 generic checkers),
  Challenge base reads PASSWORD_<team_port> from env; gen_receiver_main.py
  generates per-team main.py from registry
- main.py: /api/challenges returns full registry; PATCH /api/challenges/<name>
  toggles enabled + applies to live teams
- index.html: 🏗️ Challenge Manager tab (toggle per challenge, grouped by set)
- SLA bonus now dynamic (all enabled challenges, not hardcoded 6)
2026-09-25 14:04:33 +08:00

164 lines
4.8 KiB
C

#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <sodium.h>
#include <string.h>
#include <time.h>
#include "kauth.h"
#define kauth_token_claim_BYTES \
(sodium_base64_ENCODED_LEN(sizeof(struct kauth_user), \
sodium_base64_VARIANT_URLSAFE_NO_PADDING))
#define kauth_token_sign_BYTES \
(sodium_base64_ENCODED_LEN(crypto_auth_hmacsha256_BYTES, \
sodium_base64_VARIANT_URLSAFE_NO_PADDING))
#define kauth_token_BYTES (kauth_token_claim_BYTES + kauth_token_sign_BYTES) - 1
static int encode(lua_State *L) {
int typ;
struct kauth_user claim;
unsigned char h[crypto_auth_hmacsha256_BYTES];
unsigned char token[kauth_token_BYTES];
memset(h, 0, crypto_auth_hmacsha256_BYTES);
memset(token, 0, kauth_token_BYTES);
memset(&claim, 0, sizeof(struct kauth_user));
size_t keylen = 0;
const char *key = luaL_checklstring(L, 1, &keylen);
if (keylen != crypto_auth_hmacsha256_KEYBYTES) {
lua_pushstring(L, "invalid key len");
return lua_error(L);
}
luaL_checktype(L, 2, LUA_TTABLE);
if ((typ = lua_getfield(L, 2, "id")) != LUA_TNUMBER) {
lua_pop(L, 1);
lua_pushstring(L, "invalid type id (number expected)");
return lua_error(L);
}
lua_Integer id = lua_tointeger(L, -1);
lua_pop(L, 1);
claim.id = id;
if ((typ = lua_getfield(L, 2, "name")) != LUA_TSTRING) {
lua_pop(L, 1);
lua_pushstring(L, "invalid type name (string expected)");
return lua_error(L);
}
const char *name = lua_tostring(L, -1);
lua_pop(L, 1);
strcpy((char *)claim.name, name);
claim.exp = time(0) + 1800; // 30 min
crypto_auth_hmacsha256(h, (const unsigned char *)&claim,
sizeof(struct kauth_user), (const unsigned char *)key);
sodium_bin2base64((char *)token, kauth_token_claim_BYTES,
(const unsigned char *)&claim, sizeof(struct kauth_user),
sodium_base64_VARIANT_URLSAFE_NO_PADDING);
sodium_bin2base64((char *)(token + kauth_token_claim_BYTES),
kauth_token_sign_BYTES, h, crypto_auth_hmacsha256_BYTES,
sodium_base64_VARIANT_URLSAFE_NO_PADDING);
token[kauth_token_claim_BYTES - 1] = '.';
lua_pushlstring(L, (char *)token, kauth_token_BYTES);
return 1;
}
static int decode(lua_State *L) {
struct kauth_user claim;
const char name[129];
const unsigned char h[crypto_auth_hmacsha256_BYTES];
memset(&claim, 0, sizeof(struct kauth_user));
memset((void *)name, 0, sizeof(name));
memset((void *)h, 0, sizeof(h));
size_t keylen = 0;
const char *key = luaL_checklstring(L, 1, &keylen);
if (keylen != crypto_auth_hmacsha256_BYTES) {
lua_pushstring(L, "invalid key len");
return lua_error(L);
}
size_t tokenlen = 0;
const char *token = luaL_checklstring(L, 2, &tokenlen);
if (tokenlen != kauth_token_BYTES) {
lua_pushstring(L, "invalid token len");
return lua_error(L);
}
if (token[kauth_token_claim_BYTES - 1] != '.') {
lua_pushstring(L, "invalid token");
return lua_error(L);
}
size_t clen = 0;
const char *b64_end = NULL;
if (sodium_base642bin((unsigned char *)&claim, sizeof(struct kauth_user),
token, kauth_token_claim_BYTES, NULL, &clen, &b64_end,
sodium_base64_VARIANT_URLSAFE_NO_PADDING) != 0) {
lua_pushstring(L, "invalid token: failed to decode claim");
return lua_error(L);
}
strncpy((char *)name, claim.name, sizeof(name));
clen = 0;
b64_end = NULL;
if (sodium_base642bin((unsigned char *)h, crypto_auth_hmacsha256_BYTES,
token + kauth_token_claim_BYTES, kauth_token_sign_BYTES,
NULL, &clen, &b64_end,
sodium_base64_VARIANT_URLSAFE_NO_PADDING) != 0) {
lua_pushstring(L, "invalid token: failed to decode hash");
return lua_error(L);
}
if (crypto_auth_hmacsha256_verify(h, (const unsigned char *)&claim,
sizeof(struct kauth_user),
(const unsigned char *)key) != 0) {
lua_pushstring(L, "invalid token: failed to verify");
return lua_error(L);
}
if (claim.exp <= time(0)) {
lua_pushstring(L, "invalid token: expired");
return lua_error(L);
}
lua_newtable(L);
lua_pushstring(L, name);
lua_setfield(L, -2, "name");
lua_pushinteger(L, claim.id);
lua_setfield(L, -2, "id");
return 1;
}
static const struct luaL_Reg luakauth_lib[] = {
{"encode", encode},
{"decode", decode},
{NULL, NULL},
};
LUALIB_API int luaopen_kauth(lua_State *L) {
if (sodium_init() == -1) {
lua_pushstring(L, "crypto init failed");
return lua_error(L);
}
luaL_newlib(L, luakauth_lib);
return 1;
}