diff --git a/CMakeLists.txt b/CMakeLists.txt index c0cb87b..e048d30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() diff --git a/src/amduatd.c b/src/amduatd.c index e2429d0..677e3ec 100644 --- a/src/amduatd.c +++ b/src/amduatd.c @@ -35,6 +35,7 @@ #include "amduat/hash/asl1.h" #include "amduatd_ui.h" #include "amduatd_caps.h" +#include "amduatd_space.h" #include #include @@ -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)) { diff --git a/src/amduatd_caps.c b/src/amduatd_caps.c index 51063cf..bf5da80 100644 --- a/src/amduatd_caps.c +++ b/src/amduatd_caps.c @@ -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) { diff --git a/src/amduatd_caps.h b/src/amduatd_caps.h index ab0a542..3cd1eb5 100644 --- a/src/amduatd_caps.h +++ b/src/amduatd_caps.h @@ -2,6 +2,7 @@ #define AMDUATD_CAPS_H #include "amduatd_ui.h" +#include "amduatd_space.h" #include #include @@ -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 { diff --git a/src/amduatd_space.c b/src/amduatd_space.c new file mode 100644 index 0000000..3802862 --- /dev/null +++ b/src/amduatd_space.c @@ -0,0 +1,268 @@ +#include "amduatd_space.h" + +#include "amduat/util/log.h" + +#include +#include +#include +#include + +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; +} diff --git a/src/amduatd_space.h b/src/amduatd_space.h new file mode 100644 index 0000000..949cecc --- /dev/null +++ b/src/amduatd_space.h @@ -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 +#include + +#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 */