return -EINVAL;
return prefix_length_decode(text, value, max_value);
}
+/*
+ * Any unknown members should be treated as errors, RFC8416 3.1:
+ * "JSON members that are not defined here MUST NOT be used in SLURM
+ * files. An RP MUST consider any deviations from the specifications to
+ * be errors."
+ */
+static bool
+valid_members_count(json_t *object, size_t expected_size)
+{
+ return json_object_size(object) == expected_size;
+}
static int
set_asn(json_t *object, bool is_assertion, u_int32_t *result,
- u_int8_t *flag)
+ u_int8_t *flag, size_t *members_loaded)
{
json_int_t int_tmp;
int error;
}
*flag = *flag | SLURM_COM_FLAG_ASN;
*result = (u_int32_t) int_tmp;
+ (*members_loaded)++;
return 0;
}
static int
-set_comment(json_t *object, char const **comment, u_int8_t *flag)
+set_comment(json_t *object, char const **comment, u_int8_t *flag,
+ size_t *members_loaded)
{
char const *tmp;
int error;
*comment = strdup(tmp);
*flag = *flag | SLURM_COM_FLAG_COMMENT;
+ (*members_loaded)++;
return 0;
}
static int
-set_prefix(json_t *object, bool is_assertion, struct slurm_prefix *result)
+set_prefix(json_t *object, bool is_assertion, struct slurm_prefix *result,
+ size_t *members_loaded)
{
struct ipv4_prefix prefixv4;
struct ipv6_prefix prefixv6;
result->prefix_length = prefixv6.len;
}
result->data_flag |= SLURM_PFX_FLAG_PREFIX;
+ (*members_loaded)++;
return 0;
}
static int
set_max_prefix_length(json_t *object, bool is_assertion, u_int8_t addr_fam,
- u_int8_t *result, u_int8_t *flag)
+ u_int8_t *result, u_int8_t *flag, size_t *members_loaded)
{
json_int_t int_tmp;
int error;
}
*flag = *flag | SLURM_PFX_FLAG_MAX_LENGTH;
*result = (u_int8_t) int_tmp;
+ (*members_loaded)++;
return 0;
}
-static int
-validate_encoded(const char *encoded)
+int
+validate_base64url_encoded(const char *encoded)
{
/*
* RFC 8416, sections 3.3.2 (SKI member), and 3.4.2 (SKI and
}
static int
-set_ski(json_t *object, bool is_assertion, struct slurm_bgpsec *result)
+set_ski(json_t *object, bool is_assertion, struct slurm_bgpsec *result,
+ size_t *members_loaded)
{
char const *str_encoded;
int error;
return 0;
}
- error = validate_encoded(str_encoded);
+ error = validate_base64url_encoded(str_encoded);
if (error)
return error;
}
result->data_flag = result->data_flag | SLURM_BGPS_FLAG_SKI;
+ (*members_loaded)++;
return 0;
}
static int
set_router_pub_key(json_t *object, bool is_assertion,
- struct slurm_bgpsec *result)
+ struct slurm_bgpsec *result, size_t *members_loaded)
{
char const *str_encoded;
int error;
return -EINVAL;
}
- error = validate_encoded(str_encoded);
+ error = validate_base64url_encoded(str_encoded);
if (error)
return error;
- /* TODO The public key may contain NULL chars as part of the string */
error = base64url_decode(str_encoded, &result->router_public_key,
&result->router_public_key_len);
if (error)
*/
result->data_flag = result->data_flag | SLURM_BGPS_FLAG_ROUTER_KEY;
+ (*members_loaded)++;
return 0;
}
slurm_prefix->prefix_length = 0;
slurm_prefix->max_prefix_length = 0;
slurm_prefix->addr_fam = 0;
+ slurm_prefix->comment = NULL;
}
static int
load_single_prefix(json_t *object, bool is_assertion)
{
struct slurm_prefix result;
+ size_t member_count;
int error;
if (!json_is_object(object)) {
}
init_slurm_prefix(&result);
+ member_count = 0;
- error = set_asn(object, is_assertion, &result.asn, &result.data_flag);
+ error = set_asn(object, is_assertion, &result.asn, &result.data_flag,
+ &member_count);
if (error)
return error;
- error = set_prefix(object, is_assertion, &result);
+ error = set_prefix(object, is_assertion, &result, &member_count);
if (error)
return error;
error = set_max_prefix_length(object, is_assertion, result.addr_fam,
- &result.max_prefix_length, &result.data_flag);
+ &result.max_prefix_length, &result.data_flag, &member_count);
if (error)
return error;
- error = set_comment(object, &result.comment, &result.data_flag);
+ error = set_comment(object, &result.comment, &result.data_flag,
+ &member_count);
if (error)
return error;
goto release_comment;
}
+ /* Validate expected members */
+ if (!valid_members_count(object, member_count)) {
+ warnx("Prefix filter has unknown members (see RFC 8416 section 3.3.1");
+ error = -EINVAL;
+ goto release_comment;
+ }
+
error = slurm_db_add_prefix_filter(&result);
if (error)
goto release_comment;
goto release_comment;
}
+ /* Validate expected members */
+ if (!valid_members_count(object, member_count)) {
+ warnx("Prefix assertion has unknown members (see RFC 8416 section 3.4.1");
+ error = -EINVAL;
+ goto release_comment;
+ }
+
error = slurm_db_add_prefix_assertion(&result);
if (error)
goto release_comment;
slurm_bgpsec->ski_len = 0;
slurm_bgpsec->router_public_key = NULL;
slurm_bgpsec->router_public_key_len = 0;
+ slurm_bgpsec->comment = NULL;
}
static int
load_single_bgpsec(json_t *object, bool is_assertion)
{
struct slurm_bgpsec result;
+ size_t member_count;
int error;
if (!json_is_object(object)) {
}
init_slurm_bgpsec(&result);
+ member_count = 0;
- error = set_asn(object, is_assertion, &result.asn, &result.data_flag);
+ error = set_asn(object, is_assertion, &result.asn, &result.data_flag,
+ &member_count);
if (error)
return error;
- error = set_ski(object, is_assertion, &result);
+ error = set_ski(object, is_assertion, &result, &member_count);
if (error)
return error;
- error = set_router_pub_key(object, is_assertion, &result);
+ error = set_router_pub_key(object, is_assertion, &result,
+ &member_count);
if (error)
goto release_ski;
- error = set_comment(object, &result.comment, &result.data_flag);
+ error = set_comment(object, &result.comment, &result.data_flag,
+ &member_count);
if (error)
goto release_router_key;
goto release_comment;
}
+ /* Validate expected members */
+ if (!valid_members_count(object, member_count)) {
+ warnx("BGPsec filter has unknown members (see RFC 8416 section 3.3.2");
+ error = -EINVAL;
+ goto release_comment;
+ }
+
error = slurm_db_add_bgpsec_filter(&result);
if (error)
goto release_comment;
return 0;
}
+ /* Validate expected members */
+ if (!valid_members_count(object, member_count)) {
+ warnx("BGPsec assertion has unknown members (see RFC 8416 section 3.4.2");
+ error = -EINVAL;
+ goto release_comment;
+ }
+
error = slurm_db_add_bgpsec_assertion(&result);
if (error)
goto release_comment;
load_filters(json_t *root)
{
json_t *filters, *prefix, *bgpsec;
+ size_t expected_members;
int error;
filters = json_get_object(root, VALIDATION_OUTPUT_FILTERS);
bgpsec = json_get_array(filters, BGPSEC_FILTERS);
CHECK_REQUIRED(bgpsec, BGPSEC_FILTERS)
+ expected_members = 2;
+ if (!valid_members_count(filters, expected_members)) {
+ warnx(
+ "SLURM '%s' must contain only %lu members (RFC 8416 section 3.2)",
+ VALIDATION_OUTPUT_FILTERS,
+ expected_members);
+ return -EINVAL;
+ }
+
/* Arrays loaded, now iterate */
error = load_prefix_array(prefix, false);
if (error)
load_assertions(json_t *root)
{
json_t *assertions, *prefix, *bgpsec;
+ size_t expected_members;
int error;
assertions = json_get_object(root, LOCALLY_ADDED_ASSERTIONS);
bgpsec = json_get_array(assertions, BGPSEC_ASSERTIONS);
CHECK_REQUIRED(bgpsec, BGPSEC_ASSERTIONS)
+ expected_members = 2;
+ if (!valid_members_count(assertions, expected_members)) {
+ warnx(
+ "SLURM '%s' must contain only %lu members (RFC 8416 section 3.2)",
+ LOCALLY_ADDED_ASSERTIONS,
+ expected_members);
+ return -EINVAL;
+ }
+
error = load_prefix_array(prefix, true);
if (error)
return error;
static int
handle_json(json_t *root)
{
+ size_t expected_members;
int error;
if (!json_is_object(root)) {
if (error)
return error;
- /*
- * TODO Any unknown members should be treated as errors, RFC8416 3.1:
- * "JSON members that are not defined here MUST NOT be used in SLURM
- * files. An RP MUST consider any deviations from the specifications to
- * be errors."
- */
+ expected_members = 3;
+ if (!valid_members_count(root, expected_members)) {
+ warnx(
+ "SLURM root must have only %lu members (RFC 8416 section 3.2)",
+ expected_members);
+ return -EINVAL;
+ }
return 0;
}