Skip to content

Commit

Permalink
fixup! oc_acl: refactor and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Danielius1922 committed May 14, 2024
1 parent e96fce1 commit f1894d6
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 97 deletions.
8 changes: 3 additions & 5 deletions include/oc_acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,9 @@ typedef enum {
*/
typedef struct oc_ace_res_t
{
struct oc_ace_res_t *next; ///< pointer to next entry
oc_string_t href; ///< href
oc_interface_mask_t interfaces; ///< applicable interfaces (as bit mask)
oc_string_array_t types; ///< resource types (rt)
oc_ace_wildcard_t wildcard; ///< wildcard info
struct oc_ace_res_t *next; ///< pointer to next entry
oc_string_t href; ///< href
oc_ace_wildcard_t wildcard; ///< wildcard info
} oc_ace_res_t;

/**
Expand Down
86 changes: 76 additions & 10 deletions security/oc_ace.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@ oc_ace_wildcard_to_string(oc_ace_wildcard_t wc)
return OC_STRING_VIEW_NULL;
}

int
oc_ace_wildcard_from_string(oc_string_view_t str)
{
if (oc_string_view_is_equal(str, OC_STRING_VIEW(OC_ACE_WC_ALL_STR))) {
return OC_ACE_WC_ALL;
}
if (oc_string_view_is_equal(str, OC_STRING_VIEW(OC_ACE_WC_ALL_SECURED_STR))) {
return OC_ACE_WC_ALL_SECURED;
}
if (oc_string_view_is_equal(str, OC_STRING_VIEW(OC_ACE_WC_ALL_PUBLIC_STR))) {
return OC_ACE_WC_ALL_PUBLIC;
}
return -1;
}

#if OC_DBG_IS_ENABLED
static void
log_new_ace(const oc_sec_ace_t *ace)
Expand Down Expand Up @@ -228,18 +243,18 @@ oc_sec_free_ace(oc_sec_ace_t *ace)
oc_memb_free(&g_ace_l, ace);
}

static bool
ace_has_matching_tag(const oc_sec_ace_t *ace, oc_string_view_t tag)
bool
oc_ace_has_matching_tag(const oc_sec_ace_t *ace, oc_string_view_t tag)
{
if (tag.data == NULL) {
return oc_string(ace->tag) == NULL;
}
return oc_string_is_cstr_equal(&ace->tag, tag.data, tag.length);
}

static bool
ace_has_matching_subject(const oc_sec_ace_t *ace, oc_ace_subject_type_t type,
oc_ace_subject_view_t subject)
bool
oc_ace_has_matching_subject(const oc_sec_ace_t *ace, oc_ace_subject_type_t type,
oc_ace_subject_view_t subject)
{
if (ace->subject_type != type) {
return false;
Expand Down Expand Up @@ -272,10 +287,10 @@ oc_sec_ace_find_subject(oc_sec_ace_t *ace, oc_ace_subject_type_t type,
if (permission != 0 && ace->permission != permission) {
continue;
}
if (match_tag && !ace_has_matching_tag(ace, tag)) {
if (match_tag && !oc_ace_has_matching_tag(ace, tag)) {
continue;
}
if (ace_has_matching_subject(ace, type, subject)) {
if (oc_ace_has_matching_subject(ace, type, subject)) {
return ace;
}
}
Expand Down Expand Up @@ -536,7 +551,7 @@ ace_decode_subject(const oc_rep_t *rep, oc_ace_subject_view_t *subject)
OC_ERR("ACE decode subject: conntype cannot be used with role");
return -1;
}
subject->role = (struct oc_ace_subject_role_view_t){
subject->role = (oc_ace_subject_role_view_t){
.role = oc_string_view2(role),
.authority = oc_string_view2(authority),
};
Expand Down Expand Up @@ -630,9 +645,60 @@ oc_sec_decode_ace(const oc_rep_t *rep, oc_sec_ace_decode_t *acedecode)
(int)rep->type);
return false;
}
OC_DBG("aceid: %d, permission: %d, subject_type: %d", acedecode->aceid,
acedecode->permission, acedecode->subject_type);
OC_DBG("aceid: %d, permission: %" PRIu16 ", subject_type: % d ",
acedecode->aceid, acedecode->permission, acedecode->subject_type);
}
return true;
}

bool
oc_sec_decode_ace_res(const oc_rep_t *rep,
oc_sec_ace_res_decode_t *aceresdecode)
{
int wc = OC_ACE_NO_WC;
const oc_string_t *href = NULL;
for (const oc_rep_t *resource = rep->value.object; resource != NULL;
resource = resource->next) {
if (resource->type == OC_REP_STRING) {
if (oc_rep_is_property(resource, OC_ACE_PROP_RESOURCE_HREF,
OC_CHAR_ARRAY_LEN(OC_ACE_PROP_RESOURCE_HREF))) {
href = &resource->value.string;
continue;
}
if (oc_rep_is_property(
resource, OC_ACE_PROP_RESOURCE_WILDCARD,
OC_CHAR_ARRAY_LEN(OC_ACE_PROP_RESOURCE_WILDCARD))) {
wc =
oc_ace_wildcard_from_string(oc_string_view2(&resource->value.string));
if (wc == -1) {
OC_ERR("ACE decode resource: wildcard(%s) is invalid",
oc_string(resource->value.string));
return false;
}
continue;
}
}
OC_ERR("ACE decode resource: unknown property (name=%s, type=%d)",
oc_string(resource->name) != NULL ? oc_string(resource->name)
: "(null)",
(int)resource->type);
}

aceresdecode->href = href;
aceresdecode->wildcard = (oc_ace_wildcard_t)wc;

#if 0
#ifdef OC_SERVER
oc_resource_properties_t wc_r = 0;
if (wc == OC_ACE_WC_ALL || wc == OC_ACE_WC_ALL_SECURED) {
wc_r = ~0;
}
if (wc == OC_ACE_WC_ALL_PUBLIC) {
wc_r = ~OC_DISCOVERABLE;
}
#endif /* OC_SERVER */
#endif

return true;
}

Expand Down
47 changes: 39 additions & 8 deletions security/oc_ace_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,25 @@ extern "C" {
/** Convert wildcard to string representation */
oc_string_view_t oc_ace_wildcard_to_string(oc_ace_wildcard_t wc);

/** Convert string to wildcard */
int oc_ace_wildcard_from_string(oc_string_view_t str);

/** Convert connection type to string */
oc_string_view_t oc_ace_connection_type_to_string(
oc_ace_connection_type_t conn);

/** Convert string to connection type */
int oc_ace_connection_type_from_string(oc_string_view_t str);

typedef struct
{
oc_string_view_t role;
oc_string_view_t authority;
} oc_ace_subject_role_view_t;

typedef union {
oc_uuid_t uuid;
struct oc_ace_subject_role_view_t
{
oc_string_view_t role;
oc_string_view_t authority;
} role;
oc_ace_subject_role_view_t role;
oc_ace_connection_type_t conn;
} oc_ace_subject_view_t;

Expand All @@ -67,6 +72,15 @@ oc_sec_ace_t *oc_sec_new_ace(oc_ace_subject_type_t type,
/** Free an ACE */
void oc_sec_free_ace(oc_sec_ace_t *ace) OC_NONNULL();

/** Check if ACE has mathing tag */
bool oc_ace_has_matching_tag(const oc_sec_ace_t *ace, oc_string_view_t tag)
OC_NONNULL();

/** Check if ACE has matching subject */
bool oc_ace_has_matching_subject(const oc_sec_ace_t *ace,
oc_ace_subject_type_t type,
oc_ace_subject_view_t subject) OC_NONNULL();

/** Find ACE in a list */
oc_sec_ace_t *oc_sec_ace_find_subject(oc_sec_ace_t *ace,
oc_ace_subject_type_t type,
Expand Down Expand Up @@ -94,19 +108,36 @@ oc_ace_res_t *oc_sec_ace_find_resource(oc_ace_res_t *start,

/** Encode an ACE to encoder */
void oc_sec_encode_ace(CborEncoder *encoder, const oc_sec_ace_t *sub,
bool to_storage);
bool to_storage) OC_NONNULL();

typedef struct
{
int aceid;
int32_t permission; // uint16_t or -1
uint16_t permission;
oc_ace_subject_view_t subject;
oc_ace_subject_type_t subject_type;
const oc_rep_t *resources;
const oc_string_t *tag;
} oc_sec_ace_decode_t;

bool oc_sec_decode_ace(const oc_rep_t *rep, oc_sec_ace_decode_t *acedecode);
/** Decode representation to struct */
bool oc_sec_decode_ace(const oc_rep_t *rep, oc_sec_ace_decode_t *acedecode)
OC_NONNULL(2);

typedef struct
{
oc_ace_wildcard_t wildcard;
const oc_string_t *href;
#if 0
#ifdef OC_SERVER
oc_resource_properties_t wc_r;
#endif /* OC_SERVER */
#endif
} oc_sec_ace_res_decode_t;

/** Decode representation to struct */
bool oc_sec_decode_ace_res(const oc_rep_t *rep,
oc_sec_ace_res_decode_t *aceresdecode) OC_NONNULL(2);

#ifdef __cplusplus
}
Expand Down
70 changes: 15 additions & 55 deletions security/oc_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,67 +347,27 @@ oc_sec_decode_acl(const oc_rep_t *rep, bool from_storage, size_t device,

const oc_rep_t *resources = ace_decode.resources;
while (resources != NULL) {
oc_ace_wildcard_t wc = OC_ACE_NO_WC;
const oc_rep_t *resource = resources->value.object;
const oc_string_t *href = NULL;
/*
#ifdef OC_SERVER
oc_resource_properties_t wc_r = 0;
#endif
*/

while (resource != NULL) {
switch (resource->type) {
case OC_REP_STRING:
if (oc_string_len(resource->name) == 4 &&
memcmp(oc_string(resource->name), "href", 4) == 0) {
href = &resource->value.string;
} else if (oc_string_len(resource->name) == 2 &&
memcmp(oc_string(resource->name), "wc", 2) == 0) {
if (oc_string(resource->value.string)[0] == '*') {
wc = OC_ACE_WC_ALL;
/*
#ifdef OC_SERVER
wc_r = ~0;
#endif
*/
}
if (oc_string(resource->value.string)[0] == '+') {
wc = OC_ACE_WC_ALL_SECURED;
/*
#ifdef OC_SERVER
wc_r = ~0;
#endif
*/
}
if (oc_string(resource->value.string)[0] == '-') {
wc = OC_ACE_WC_ALL_PUBLIC;
/*
#ifdef OC_SERVER
wc_r = ~OC_DISCOVERABLE;
#endif
*/
}
}
break;
default:
break;
}

resource = resource->next;
oc_sec_ace_res_decode_t aceres_decode;
memset(&aceres_decode, 0, sizeof(oc_sec_ace_res_decode_t));
if (!oc_sec_decode_ace_res(resources->value.object, &aceres_decode)) {
OC_ERR("oc_acl: error decoding ACE resources");
return false;
}

oc_sec_ace_update_data_t ace_upd = { NULL, false, false };
if (oc_sec_acl_update_res(
ace_decode.subject_type, ace_decode.subject, ace_decode.aceid,
ace_decode.permission, oc_string_view2(ace_decode.tag),
oc_string_view2(href), wc, device, &ace_upd)) {
if (oc_sec_acl_update_res(ace_decode.subject_type, ace_decode.subject,
ace_decode.aceid, ace_decode.permission,
oc_string_view2(ace_decode.tag),
oc_string_view2(aceres_decode.href),
aceres_decode.wildcard, device, &ace_upd)) {
upd_ace = ace_upd.ace;
created |= ace_upd.created;
created_resource |= ace_upd.created_resource;
} else {
OC_WRN("failed to create resource(href:%s wildcard:%d)",
href != NULL ? oc_string(*href) : "", wc);
aceres_decode.href != NULL ? oc_string(*aceres_decode.href)
: "",
aceres_decode.wildcard);
}

/* The following code block attaches "coap" endpoints to
Expand All @@ -426,8 +386,8 @@ oc_sec_decode_acl(const oc_rep_t *rep, bool from_storage, size_t device,
} else {
oc_resource_t *r = oc_ri_get_app_resources();
while (r != NULL) {
if ((r->properties & wc_r) == r->properties) {
oc_resource_make_public(r);
if ((r->properties & aceres_decode->wc_r) ==
r->properties) { oc_resource_make_public(r);
}
r = r->next;
}
Expand Down
2 changes: 1 addition & 1 deletion security/oc_acl_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ get_role_permissions(const oc_sec_cred_t *role_cred,
do {
oc_ace_subject_view_t role_subject = {
.role =
(struct oc_ace_subject_role_view_t){
(oc_ace_subject_role_view_t){
.role = oc_string_view2(&role_cred->role.role),
.authority = oc_string_view2(&role_cred->role.authority),
}
Expand Down
Loading

0 comments on commit f1894d6

Please sign in to comment.