Extract amduatd space scoping module

This commit is contained in:
Carl Niklas Rydberg 2026-01-24 03:21:14 +01:00
parent 578aa09860
commit 5e36cb6e5c
6 changed files with 392 additions and 268 deletions

View file

@ -24,7 +24,7 @@ target_link_libraries(amduat_federation
PRIVATE amduat_asl amduat_enc amduat_util amduat_fed
)
set(amduatd_sources src/amduatd.c src/amduatd_caps.c)
set(amduatd_sources src/amduatd.c src/amduatd_caps.c src/amduatd_space.c)
if(AMDUATD_ENABLE_UI)
list(APPEND amduatd_sources src/amduatd_ui.c)
endif()

View file

@ -35,6 +35,7 @@
#include "amduat/hash/asl1.h"
#include "amduatd_ui.h"
#include "amduatd_caps.h"
#include "amduatd_space.h"
#include <errno.h>
#include <signal.h>
@ -1160,214 +1161,6 @@ bool amduatd_read_urandom(uint8_t *out, size_t len) {
return true;
}
static bool amduatd_name_valid(const char *name) {
size_t i;
size_t len;
if (name == NULL) {
return false;
}
len = strlen(name);
if (len == 0 || len > 64) {
return false;
}
for (i = 0; i < len; ++i) {
unsigned char c = (unsigned char)name[i];
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' ||
c == '-' || c == '.' || c == '/') {
continue;
}
return false;
}
return true;
}
static bool amduatd_strdup_cstr(const char *s, char **out) {
size_t len;
char *buf;
if (out == NULL) {
return false;
}
*out = NULL;
if (s == NULL) {
return false;
}
len = strlen(s);
if (len > SIZE_MAX - 1u) {
return false;
}
buf = (char *)malloc(len + 1u);
if (buf == NULL) {
return false;
}
if (len != 0) {
memcpy(buf, s, len);
}
buf[len] = '\0';
*out = buf;
return true;
}
static bool amduatd_space_id_valid(const char *space_id) {
if (space_id == NULL || space_id[0] == '\0') {
return false;
}
if (strchr(space_id, '/') != NULL) {
return false;
}
return amduat_asl_pointer_name_is_valid(space_id);
}
static void amduatd_log_scoped_name(const amduatd_cfg_t *cfg,
const char *user_name,
const char *scoped_name) {
if (cfg == NULL || !cfg->space_enabled) {
return;
}
if (user_name == NULL || scoped_name == NULL) {
return;
}
amduat_log(AMDUAT_LOG_DEBUG, "%s -> %s", user_name, scoped_name);
}
static bool amduatd_scope_name(const amduatd_cfg_t *cfg,
const char *user_name,
amduat_octets_t *out_scoped_name) {
char *buf = NULL;
size_t user_len = 0;
size_t space_len = 0;
size_t total_len = 0;
size_t offset = 0;
if (out_scoped_name != NULL) {
*out_scoped_name = amduat_octets(NULL, 0u);
}
if (user_name == NULL || out_scoped_name == NULL) {
return false;
}
if (cfg == NULL || !cfg->space_enabled || cfg->space_id == NULL) {
if (!amduatd_name_valid(user_name)) {
return false;
}
if (!amduatd_strdup_cstr(user_name, &buf)) {
return false;
}
*out_scoped_name = amduat_octets((const uint8_t *)buf, strlen(buf));
return true;
}
if (strncmp(user_name, "space/", 6) == 0) {
return false;
}
if (!amduat_asl_pointer_name_is_valid(user_name)) {
return false;
}
if (!amduatd_space_id_valid(cfg->space_id)) {
return false;
}
user_len = strlen(user_name);
space_len = strlen(cfg->space_id);
if (space_len > SIZE_MAX - 7u ||
user_len > SIZE_MAX - (7u + space_len)) {
return false;
}
total_len = 6u + space_len + 1u + user_len;
buf = (char *)malloc(total_len + 1u);
if (buf == NULL) {
return false;
}
memcpy(buf + offset, "space/", 6u);
offset += 6u;
memcpy(buf + offset, cfg->space_id, space_len);
offset += space_len;
buf[offset++] = '/';
if (user_len != 0) {
memcpy(buf + offset, user_name, user_len);
offset += user_len;
}
buf[offset] = '\0';
if (!amduat_asl_pointer_name_is_valid(buf)) {
free(buf);
return false;
}
*out_scoped_name = amduat_octets((const uint8_t *)buf, total_len);
return true;
}
static bool amduatd_scope_name_cstr(const amduatd_cfg_t *cfg,
const char *user_name,
char **out_scoped_name) {
amduat_octets_t scoped;
if (out_scoped_name != NULL) {
*out_scoped_name = NULL;
}
if (out_scoped_name == NULL) {
return false;
}
if (!amduatd_scope_name(cfg, user_name, &scoped)) {
return false;
}
*out_scoped_name = (char *)scoped.data;
return *out_scoped_name != NULL;
}
static bool amduatd_unscoped_name(const amduatd_cfg_t *cfg,
const char *scoped_name,
char *out,
size_t cap) {
const char *suffix = NULL;
size_t suffix_len = 0;
if (out != NULL && cap != 0) {
out[0] = '\0';
}
if (out == NULL || cap == 0 || scoped_name == NULL) {
return false;
}
if (cfg == NULL || !cfg->space_enabled || cfg->space_id == NULL) {
size_t len = strlen(scoped_name);
if (!amduatd_name_valid(scoped_name)) {
return false;
}
if (len >= cap) {
return false;
}
memcpy(out, scoped_name, len);
out[len] = '\0';
return true;
}
if (!amduatd_space_id_valid(cfg->space_id)) {
return false;
}
{
size_t space_len = strlen(cfg->space_id);
size_t prefix_len = 6u + space_len + 1u;
if (strncmp(scoped_name, "space/", 6u) != 0) {
return false;
}
if (strncmp(scoped_name + 6u, cfg->space_id, space_len) != 0) {
return false;
}
if (scoped_name[6u + space_len] != '/') {
return false;
}
suffix = scoped_name + prefix_len;
}
if (suffix == NULL || suffix[0] == '\0') {
return false;
}
if (!amduat_asl_pointer_name_is_valid(suffix)) {
return false;
}
suffix_len = strlen(suffix);
if (suffix_len >= cap) {
return false;
}
memcpy(out, suffix, suffix_len);
out[suffix_len] = '\0';
return true;
}
static bool amduatd_build_prefixed_bytes(const char *prefix,
const char *text,
uint8_t **out,
@ -1413,7 +1206,9 @@ static bool amduatd_concepts_seed_relation(amduat_asl_store_t *store,
size_t bytes_len = 0;
amduat_artifact_t artifact;
char *scoped_name = NULL;
amduat_octets_t scoped_bytes = amduat_octets(NULL, 0u);
bool ok = false;
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
if (out_ref == NULL) {
return false;
@ -1422,13 +1217,10 @@ static bool amduatd_concepts_seed_relation(amduat_asl_store_t *store,
if (store == NULL || cfg == NULL || relation_name == NULL) {
return false;
}
if (dcfg != NULL && dcfg->space_enabled) {
if (!amduatd_scope_name_cstr(dcfg, relation_name, &scoped_name)) {
return false;
}
} else if (!amduatd_strdup_cstr(relation_name, &scoped_name)) {
if (!amduatd_space_scope_name(space, relation_name, &scoped_bytes)) {
return false;
}
scoped_name = (char *)scoped_bytes.data;
if (!amduatd_build_prefixed_bytes("AMDUATD/RELATION/1", scoped_name, &bytes,
&bytes_len)) {
goto seed_cleanup;
@ -1460,7 +1252,9 @@ static bool amduatd_concepts_ensure_alias(amduatd_concepts_t *c,
amduat_reference_t name_ref;
amduat_reference_t edge_ref;
char *scoped_name = NULL;
amduat_octets_t scoped_bytes = amduat_octets(NULL, 0u);
bool ok = false;
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
memset(&existing, 0, sizeof(existing));
memset(&name_ref, 0, sizeof(name_ref));
@ -1469,11 +1263,12 @@ static bool amduatd_concepts_ensure_alias(amduatd_concepts_t *c,
if (c == NULL || store == NULL || cfg == NULL || alias_name == NULL) {
return false;
}
if (!amduatd_scope_name_cstr(dcfg, alias_name, &scoped_name)) {
if (!amduatd_space_scope_name(space, alias_name, &scoped_bytes)) {
amduat_log(AMDUAT_LOG_ERROR,
"ensure alias: scope failed for %s", alias_name);
return false;
}
scoped_name = (char *)scoped_bytes.data;
if (amduatd_concepts_lookup_alias(store, cfg, c, scoped_name, &existing)) {
amduat_reference_free(&existing);
ok = true;
@ -1890,6 +1685,7 @@ static bool amduatd_concepts_init(amduatd_concepts_t *c,
const amduatd_cfg_t *dcfg,
const char *root_path) {
amduat_octets_t scoped_collection = amduat_octets(NULL, 0u);
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
if (c == NULL || store == NULL || cfg == NULL || root_path == NULL) {
return false;
@ -1898,7 +1694,7 @@ static bool amduatd_concepts_init(amduatd_concepts_t *c,
c->root_path = root_path;
(void)snprintf(c->edges_path, sizeof(c->edges_path), "%s/%s", root_path,
AMDUATD_EDGES_FILE);
if (!amduatd_scope_name(dcfg, AMDUATD_EDGE_COLLECTION, &scoped_collection)) {
if (!amduatd_space_edges_collection_name(space, &scoped_collection)) {
amduat_log(AMDUAT_LOG_ERROR, "concepts init: scope edges failed");
return false;
}
@ -1992,8 +1788,8 @@ static bool amduatd_concepts_init(amduatd_concepts_t *c,
return false;
}
if (c->edges.len == 0u) {
if (dcfg != NULL && dcfg->space_enabled) {
if (dcfg->migrate_unscoped_edges) {
if (space != NULL && space->enabled) {
if (amduatd_space_should_migrate_unscoped_edges(space)) {
if (!amduatd_concepts_migrate_unscoped_edges(
c,
store,
@ -2224,6 +2020,8 @@ static bool amduatd_parse_name_artifact(amduat_artifact_t artifact,
size_t i;
size_t name_len;
char scoped[AMDUAT_ASL_POINTER_NAME_MAX + 1u];
amduat_octets_t unscoped = amduat_octets(NULL, 0u);
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
if (out != NULL && cap != 0) {
out[0] = '\0';
@ -2254,7 +2052,19 @@ static bool amduatd_parse_name_artifact(amduat_artifact_t artifact,
}
memcpy(scoped, bytes + prefix_len + 1u, name_len);
scoped[name_len] = '\0';
return amduatd_unscoped_name(dcfg, scoped, out, cap);
if (!amduatd_space_unscoped_name(space, scoped, &unscoped)) {
return false;
}
if (unscoped.len >= cap) {
free((void *)unscoped.data);
return false;
}
if (unscoped.len != 0u) {
memcpy(out, unscoped.data, unscoped.len);
}
out[unscoped.len] = '\0';
free((void *)unscoped.data);
return true;
}
static bool amduatd_handle_get_concepts(int fd,
@ -2401,6 +2211,8 @@ static bool amduatd_handle_get_concept(int fd,
char *concept_hex = NULL;
char *latest_hex = NULL;
char *scoped_name = NULL;
amduat_octets_t scoped_bytes = amduat_octets(NULL, 0u);
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
bool have_latest = false;
size_t i;
size_t version_count = 0;
@ -2413,10 +2225,11 @@ static bool amduatd_handle_get_concept(int fd,
return amduatd_send_json_error(fd, 500, "Internal Server Error",
"internal error");
}
if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) {
if (!amduatd_space_scope_name(space, name, &scoped_bytes)) {
return amduatd_send_json_error(fd, 400, "Bad Request", "invalid name");
}
amduatd_log_scoped_name(dcfg, name, scoped_name);
scoped_name = (char *)scoped_bytes.data;
amduatd_space_log_mapping(space, name, scoped_name);
if (!amduatd_concepts_lookup_alias(store, cfg, concepts, scoped_name,
&concept_ref)) {
free(scoped_name);
@ -3496,6 +3309,8 @@ amduatd_ref_status_t amduatd_decode_ref_or_name_latest(
amduat_reference_t concept_ref;
char *tmp = NULL;
char *scoped_name = NULL;
amduat_octets_t scoped_bytes = amduat_octets(NULL, 0u);
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
if (out_ref != NULL) {
memset(out_ref, 0, sizeof(*out_ref));
@ -3512,11 +3327,12 @@ amduatd_ref_status_t amduatd_decode_ref_or_name_latest(
if (!amduatd_copy_json_str(s, len, &tmp)) {
return AMDUATD_REF_ERR_INTERNAL;
}
if (!amduatd_scope_name_cstr(dcfg, tmp, &scoped_name)) {
if (!amduatd_space_scope_name(space, tmp, &scoped_bytes)) {
free(tmp);
return AMDUATD_REF_ERR_INVALID;
}
amduatd_log_scoped_name(dcfg, tmp, scoped_name);
scoped_name = (char *)scoped_bytes.data;
amduatd_space_log_mapping(space, tmp, scoped_name);
memset(&concept_ref, 0, sizeof(concept_ref));
if (!amduatd_concepts_lookup_alias(store,
cfg,
@ -3797,6 +3613,8 @@ static bool amduatd_seed_concept_if_missing(
amduat_reference_t concept_ref;
amduat_reference_t edge_ref;
char *scoped_name = NULL;
amduat_octets_t scoped_bytes = amduat_octets(NULL, 0u);
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
bool ok = false;
if (out_concept_ref != NULL) {
@ -3806,9 +3624,10 @@ static bool amduatd_seed_concept_if_missing(
out_concept_ref == NULL) {
return false;
}
if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) {
if (!amduatd_space_scope_name(space, name, &scoped_bytes)) {
return false;
}
scoped_name = (char *)scoped_bytes.data;
if (amduatd_concepts_lookup_alias(store, cfg, concepts, scoped_name,
out_concept_ref)) {
ok = true;
@ -6887,6 +6706,8 @@ static bool amduatd_handle_post_concepts(int fd,
amduat_reference_t edge_ref;
char *concept_hex = NULL;
char *scoped_name = NULL;
amduat_octets_t scoped_bytes = amduat_octets(NULL, 0u);
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
char json[4096];
bool ok = false;
amduat_octets_t actor = amduat_octets(NULL, 0u);
@ -6982,11 +6803,12 @@ static bool amduatd_handle_post_concepts(int fd,
goto concepts_cleanup;
}
if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) {
if (!amduatd_space_scope_name(space, name, &scoped_bytes)) {
ok = amduatd_send_json_error(fd, 400, "Bad Request", "invalid name");
goto concepts_cleanup;
}
amduatd_log_scoped_name(dcfg, name, scoped_name);
scoped_name = (char *)scoped_bytes.data;
amduatd_space_log_mapping(space, name, scoped_name);
if (!amduatd_concepts_put_name_artifact(store, scoped_name, &name_ref)) {
ok = amduatd_send_json_error(fd, 500, "Internal Server Error",
@ -7670,6 +7492,8 @@ static bool amduatd_handle_post_concept_publish(int fd,
bool ok = false;
amduat_octets_t actor = amduat_octets(NULL, 0u);
char *scoped_name = NULL;
amduat_octets_t scoped_bytes = amduat_octets(NULL, 0u);
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
memset(&target_ref, 0, sizeof(target_ref));
memset(&concept_ref, 0, sizeof(concept_ref));
@ -7683,10 +7507,11 @@ static bool amduatd_handle_post_concept_publish(int fd,
if (req->has_actor) {
actor = req->actor;
}
if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) {
if (!amduatd_space_scope_name(space, name, &scoped_bytes)) {
return amduatd_send_json_error(fd, 400, "Bad Request", "invalid name");
}
amduatd_log_scoped_name(dcfg, name, scoped_name);
scoped_name = (char *)scoped_bytes.data;
amduatd_space_log_mapping(space, name, scoped_name);
if (req->content_length == 0) {
free(scoped_name);
return amduatd_send_json_error(fd, 400, "Bad Request", "missing body");
@ -7805,6 +7630,8 @@ static bool amduatd_handle_get_resolve(int fd,
char json[2048];
int n;
char *scoped_name = NULL;
amduat_octets_t scoped_bytes = amduat_octets(NULL, 0u);
const amduatd_space_t *space = dcfg != NULL ? &dcfg->space : NULL;
memset(&concept_ref, 0, sizeof(concept_ref));
memset(&latest_ref, 0, sizeof(latest_ref));
@ -7813,10 +7640,11 @@ static bool amduatd_handle_get_resolve(int fd,
return amduatd_send_json_error(fd, 500, "Internal Server Error",
"internal error");
}
if (!amduatd_scope_name_cstr(dcfg, name, &scoped_name)) {
if (!amduatd_space_scope_name(space, name, &scoped_bytes)) {
return amduatd_send_json_error(fd, 400, "Bad Request", "invalid name");
}
amduatd_log_scoped_name(dcfg, name, scoped_name);
scoped_name = (char *)scoped_bytes.data;
amduatd_space_log_mapping(space, name, scoped_name);
if (!amduatd_concepts_lookup_alias(store, cfg, concepts, scoped_name,
&concept_ref)) {
free(scoped_name);
@ -8126,7 +7954,7 @@ int main(int argc, char **argv) {
return 2;
}
space_id = argv[++i];
if (!amduatd_space_id_valid(space_id)) {
if (!amduatd_space_space_id_is_valid(space_id)) {
fprintf(stderr, "error: invalid --space\n");
return 2;
}
@ -8174,9 +8002,10 @@ int main(int argc, char **argv) {
}
}
dcfg.space_id = space_id;
dcfg.space_enabled = (space_id != NULL);
dcfg.migrate_unscoped_edges = migrate_unscoped_edges;
if (!amduatd_space_init(&dcfg.space, space_id, migrate_unscoped_edges)) {
fprintf(stderr, "error: invalid --space\n");
return 2;
}
memset(&cfg, 0, sizeof(cfg));
if (!amduat_asl_store_fs_load_config(root, &cfg)) {

View file

@ -519,31 +519,6 @@ static void amduatd_cap_token_free(amduatd_cap_token_t *token) {
memset(token, 0, sizeof(*token));
}
static bool amduatd_pointer_name_scoped_for_space(const amduatd_cfg_t *dcfg,
const char *name) {
size_t space_len;
if (dcfg == NULL || name == NULL) {
return false;
}
if (!amduat_asl_pointer_name_is_valid(name)) {
return false;
}
if (!dcfg->space_enabled || dcfg->space_id == NULL) {
return true;
}
space_len = strlen(dcfg->space_id);
if (strncmp(name, "space/", 6u) != 0) {
return false;
}
if (strncmp(name + 6u, dcfg->space_id, space_len) != 0) {
return false;
}
if (name[6u + space_len] != '/') {
return false;
}
return true;
}
static const char *amduatd_cap_kind_name(uint8_t kind) {
switch (kind) {
case AMDUATD_CAP_KIND_ARTIFACT_REF:
@ -1142,9 +1117,10 @@ static bool amduatd_cap_verify_token(const amduatd_caps_t *cap,
return false;
}
if (dcfg->space_enabled) {
if (dcfg->space.enabled) {
if (token.space_len == 0u || token.space == NULL ||
strcmp(token.space, dcfg->space_id) != 0) {
dcfg->space.space_id.data == NULL ||
strcmp(token.space, (const char *)dcfg->space.space_id.data) != 0) {
if (out_reason != NULL) {
*out_reason = "wrong-space";
}
@ -1161,7 +1137,7 @@ static bool amduatd_cap_verify_token(const amduatd_caps_t *cap,
}
}
if (token.kind == AMDUATD_CAP_KIND_POINTER_NAME &&
!amduatd_pointer_name_scoped_for_space(dcfg, token.pointer_name)) {
!amduatd_space_is_scoped(&dcfg->space, token.pointer_name)) {
if (out_reason != NULL) {
*out_reason = "wrong-space";
}
@ -1548,7 +1524,7 @@ static bool amduatd_handle_post_capabilities(
} else if (strcmp(kind, "pointer_name") == 0) {
token.kind = AMDUATD_CAP_KIND_POINTER_NAME;
if (token.pointer_name == NULL ||
!amduatd_pointer_name_scoped_for_space(dcfg, token.pointer_name)) {
!amduatd_space_is_scoped(&dcfg->space, token.pointer_name)) {
ok = amduatd_send_json_error(fd, 400, "Bad Request",
"invalid name");
goto cap_mint_cleanup;
@ -1571,8 +1547,8 @@ static bool amduatd_handle_post_capabilities(
goto cap_mint_cleanup;
}
if (dcfg->space_enabled && dcfg->space_id != NULL) {
space = dcfg->space_id;
if (dcfg->space.enabled && dcfg->space.space_id.data != NULL) {
space = (const char *)dcfg->space.space_id.data;
space_len = strlen(space);
token.space = (char *)malloc(space_len + 1u);
if (token.space == NULL) {

View file

@ -2,6 +2,7 @@
#define AMDUATD_CAPS_H
#include "amduatd_ui.h"
#include "amduatd_space.h"
#include <stdbool.h>
#include <stddef.h>
@ -11,9 +12,7 @@ extern "C" {
#endif
typedef struct amduatd_cfg_t {
const char *space_id;
bool space_enabled;
bool migrate_unscoped_edges;
amduatd_space_t space;
} amduatd_cfg_t;
typedef enum {

268
src/amduatd_space.c Normal file
View file

@ -0,0 +1,268 @@
#include "amduatd_space.h"
#include "amduat/util/log.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static bool amduatd_space_name_valid(const char *name) {
size_t i;
size_t len;
if (name == NULL) {
return false;
}
len = strlen(name);
if (len == 0 || len > 64) {
return false;
}
for (i = 0; i < len; ++i) {
unsigned char c = (unsigned char)name[i];
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' ||
c == '-' || c == '.' || c == '/') {
continue;
}
return false;
}
return true;
}
static bool amduatd_space_strdup_cstr(const char *s, char **out) {
size_t len;
char *buf;
if (out == NULL) {
return false;
}
*out = NULL;
if (s == NULL) {
return false;
}
len = strlen(s);
if (len > SIZE_MAX - 1u) {
return false;
}
buf = (char *)malloc(len + 1u);
if (buf == NULL) {
return false;
}
if (len != 0) {
memcpy(buf, s, len);
}
buf[len] = '\0';
*out = buf;
return true;
}
bool amduatd_space_space_id_is_valid(const char *space_id) {
if (space_id == NULL || space_id[0] == '\0') {
return false;
}
if (strchr(space_id, '/') != NULL) {
return false;
}
return amduat_asl_pointer_name_is_valid(space_id);
}
bool amduatd_space_init(amduatd_space_t *sp,
const char *space_id_or_null,
bool migrate_unscoped_edges) {
size_t space_len = 0u;
if (sp == NULL) {
return false;
}
memset(sp, 0, sizeof(*sp));
sp->migrate_unscoped_edges = migrate_unscoped_edges;
if (space_id_or_null == NULL) {
return true;
}
if (!amduatd_space_space_id_is_valid(space_id_or_null)) {
return false;
}
space_len = strlen(space_id_or_null);
if (space_len > AMDUAT_ASL_POINTER_NAME_MAX) {
return false;
}
memcpy(sp->space_id_buf, space_id_or_null, space_len);
sp->space_id_buf[space_len] = '\0';
sp->space_id = amduat_octets(sp->space_id_buf, space_len);
sp->enabled = true;
return true;
}
void amduatd_space_free(amduatd_space_t *sp) {
if (sp == NULL) {
return;
}
memset(sp, 0, sizeof(*sp));
}
void amduatd_space_log_mapping(const amduatd_space_t *sp,
const char *user_name,
const char *scoped_name) {
if (sp == NULL || !sp->enabled) {
return;
}
if (user_name == NULL || scoped_name == NULL) {
return;
}
amduat_log(AMDUAT_LOG_DEBUG, "%s -> %s", user_name, scoped_name);
}
bool amduatd_space_scope_name(const amduatd_space_t *sp,
const char *user_name,
amduat_octets_t *out_scoped) {
char *buf = NULL;
size_t user_len = 0u;
size_t space_len = 0u;
size_t total_len = 0u;
size_t offset = 0u;
const char *space_id = NULL;
if (out_scoped != NULL) {
*out_scoped = amduat_octets(NULL, 0u);
}
if (user_name == NULL || out_scoped == NULL) {
return false;
}
if (sp == NULL || !sp->enabled || sp->space_id.data == NULL) {
if (!amduatd_space_name_valid(user_name)) {
return false;
}
if (!amduatd_space_strdup_cstr(user_name, &buf)) {
return false;
}
*out_scoped = amduat_octets((const uint8_t *)buf, strlen(buf));
return true;
}
if (strncmp(user_name, "space/", 6u) == 0) {
return false;
}
if (!amduat_asl_pointer_name_is_valid(user_name)) {
return false;
}
space_id = (const char *)sp->space_id.data;
if (!amduatd_space_space_id_is_valid(space_id)) {
return false;
}
user_len = strlen(user_name);
space_len = strlen(space_id);
if (space_len > SIZE_MAX - 7u ||
user_len > SIZE_MAX - (7u + space_len)) {
return false;
}
total_len = 6u + space_len + 1u + user_len;
buf = (char *)malloc(total_len + 1u);
if (buf == NULL) {
return false;
}
memcpy(buf + offset, "space/", 6u);
offset += 6u;
memcpy(buf + offset, space_id, space_len);
offset += space_len;
buf[offset++] = '/';
if (user_len != 0) {
memcpy(buf + offset, user_name, user_len);
offset += user_len;
}
buf[offset] = '\0';
if (!amduat_asl_pointer_name_is_valid(buf)) {
free(buf);
return false;
}
*out_scoped = amduat_octets((const uint8_t *)buf, total_len);
return true;
}
bool amduatd_space_unscoped_name(const amduatd_space_t *sp,
const char *scoped_name,
amduat_octets_t *out_unscoped) {
const char *suffix = NULL;
size_t suffix_len = 0u;
char *buf = NULL;
const char *space_id = NULL;
if (out_unscoped != NULL) {
*out_unscoped = amduat_octets(NULL, 0u);
}
if (out_unscoped == NULL || scoped_name == NULL) {
return false;
}
if (sp == NULL || !sp->enabled || sp->space_id.data == NULL) {
if (!amduatd_space_name_valid(scoped_name)) {
return false;
}
if (!amduatd_space_strdup_cstr(scoped_name, &buf)) {
return false;
}
*out_unscoped = amduat_octets((const uint8_t *)buf, strlen(buf));
return true;
}
space_id = (const char *)sp->space_id.data;
if (!amduatd_space_space_id_is_valid(space_id)) {
return false;
}
{
size_t space_len = strlen(space_id);
size_t prefix_len = 6u + space_len + 1u;
if (strncmp(scoped_name, "space/", 6u) != 0) {
return false;
}
if (strncmp(scoped_name + 6u, space_id, space_len) != 0) {
return false;
}
if (scoped_name[6u + space_len] != '/') {
return false;
}
suffix = scoped_name + prefix_len;
}
if (suffix == NULL || suffix[0] == '\0') {
return false;
}
if (!amduat_asl_pointer_name_is_valid(suffix)) {
return false;
}
suffix_len = strlen(suffix);
if (!amduatd_space_strdup_cstr(suffix, &buf)) {
return false;
}
*out_unscoped = amduat_octets((const uint8_t *)buf, suffix_len);
return true;
}
bool amduatd_space_is_scoped(const amduatd_space_t *sp, const char *name) {
size_t space_len;
const char *space_id = NULL;
if (sp == NULL || name == NULL) {
return false;
}
if (!amduat_asl_pointer_name_is_valid(name)) {
return false;
}
if (!sp->enabled || sp->space_id.data == NULL) {
return true;
}
space_id = (const char *)sp->space_id.data;
space_len = strlen(space_id);
if (strncmp(name, "space/", 6u) != 0) {
return false;
}
if (strncmp(name + 6u, space_id, space_len) != 0) {
return false;
}
if (name[6u + space_len] != '/') {
return false;
}
return true;
}
bool amduatd_space_edges_collection_name(const amduatd_space_t *sp,
amduat_octets_t *out_collection_name) {
return amduatd_space_scope_name(sp, "daemon/edges", out_collection_name);
}
bool amduatd_space_should_migrate_unscoped_edges(const amduatd_space_t *sp) {
return sp != NULL && sp->enabled && sp->migrate_unscoped_edges;
}

52
src/amduatd_space.h Normal file
View file

@ -0,0 +1,52 @@
#ifndef AMDUATD_SPACE_H
#define AMDUATD_SPACE_H
#include "amduat/asl/asl_pointer_fs.h"
#include "amduat/asl/core.h"
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
bool enabled;
amduat_octets_t space_id;
bool migrate_unscoped_edges;
char space_id_buf[AMDUAT_ASL_POINTER_NAME_MAX + 1u];
} amduatd_space_t;
bool amduatd_space_init(amduatd_space_t *sp,
const char *space_id_or_null,
bool migrate_unscoped_edges);
void amduatd_space_free(amduatd_space_t *sp);
bool amduatd_space_scope_name(const amduatd_space_t *sp,
const char *user_name,
amduat_octets_t *out_scoped);
bool amduatd_space_unscoped_name(const amduatd_space_t *sp,
const char *scoped_name,
amduat_octets_t *out_unscoped);
bool amduatd_space_is_scoped(const amduatd_space_t *sp, const char *name);
bool amduatd_space_space_id_is_valid(const char *space_id);
void amduatd_space_log_mapping(const amduatd_space_t *sp,
const char *user_name,
const char *scoped_name);
bool amduatd_space_edges_collection_name(const amduatd_space_t *sp,
amduat_octets_t *out_collection_name);
bool amduatd_space_should_migrate_unscoped_edges(const amduatd_space_t *sp);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* AMDUATD_SPACE_H */