update to target nrf52840
Diff: main.cpp
- Revision:
- 0:ecd06432fb4b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Aug 13 12:23:41 2020 +0000 @@ -0,0 +1,672 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef MBED_MAJOR_VERSION +#include "mbed.h" +Serial pc(P0_25, P0_8); +#endif + +// definitions +#include "abac_them.h" + +// policy constructors + +attr_v2 new_attr_integer(char *name, int value) +{ + attr_v2 at; + at.data_type = abac_integer; + at.name = name; + at.integer = value; + return at; +} + +attr_v2 new_attr_real(char *name, float value) +{ + attr_v2 at; + at.data_type = abac_real; + at.name = name; + at.real = value; + return at; +} + +attr_v2 new_attr_integer_range(char *name, int min, int max) +{ + attr_v2 at; + at.data_type = abac_integer_range; + at.name = name; + at.ran.integer_min = min; + at.ran.integer_max = max; + return at; +} + +attr_v2 new_attr_real_range(char *name, float min, float max) +{ + attr_v2 at; + at.data_type = abac_real_range; + at.name = name; + at.ran.real_min = min; + at.ran.real_max = max; + return at; +} + +attr_v2 new_attr_string(char *name, char *value) +{ + attr_v2 at; + at.data_type = abac_string; + at.name = name; + at.string = value; + return at; +} + +attr_v2 new_attr_string_list(char *name, size_t len) +{ + attr_v2 at; + at.data_type = abac_string_list; + at.name = name; + at.inner_list_len = len; + at.string_list = (char **) malloc(sizeof(char *) * len); + return at; +} + +attr_v2 new_attr_dictionary(char *name, attr_v2 **value, size_t len) +{ + attr_v2 at; + at.data_type = abac_dictionary; + at.name = name; + at.inner_list_len = len; + at.inner_attrs = value; + return at; +} + +attr_v2 **new_attr_list(size_t len) +{ + attr_v2 **list = (attr_v2**) malloc(sizeof(attr_v2 *) * len); + return list; +} + +char **new_operations_list(size_t len) +{ + char **list = (char**) malloc(sizeof(char *) * len); + return list; +} + +// graph constructors + +node new_graph_node(char *value) +{ + node n; + n.value = value; + n.next = NULL; + return n; +} + +void create_directed_edge(node *a, node *b) +{ + a->next = b; +} + +graph new_graph(size_t len) +{ + graph g; + g.len = len; + g.list = (node **) malloc(sizeof(node *) * len); + return g; +} + +// graph algorithms + +int is_node_in(node k, node *list, size_t v_len) +{ + for (int i = 0; i < v_len; ++i) + if (strcmp(k.value, list[i].value) == 0) + return 1; + return 0; +} + +node *find_ancestors_dfs(graph g, node n, size_t *v_len) +{ + node *visited = (node *) malloc(sizeof(node) * g.len); // allocate max number of nodes for simplicity + node **stack = (node **) malloc(sizeof(node *) * g.len); + node k; + size_t s_head = 0, the_len = 0; + stack[s_head++] = &n; + while (s_head > 0) { + k = *stack[--s_head]; + if (!is_node_in(k, visited, the_len)) { + visited[the_len++] = k; + // walk over k.next and add to stack + while (k.next) { + stack[s_head++] = k.next; + k = *k.next; + } + } + } + + *v_len = the_len; + return visited; +} + +node *find_in_graph(attr_v2 *at, graph g) +{ + for (int j = 0; j < g.len; ++j) + if (strcmp(at->string, g.list[j]->value) == 0) + return g.list[j]; + return NULL; +} + +void expand_attr(attr_v2 **at_orig, graph g) +{ + if ((*at_orig)->data_type != abac_string) + return; + size_t v_len = 0; + node *n; + n = find_in_graph(*at_orig, g); + if (n == NULL) + return; + node *visited = find_ancestors_dfs(g, *n, &v_len); + attr_v2 *at = (attr_v2 *) malloc(sizeof(attr_v2)); + *at = new_attr_string_list((*at_orig)->name, v_len); + for (int j = 0; j < v_len; ++j) + at->string_list[j] = visited[j].value; + + *at_orig = at; +} + +void expand_attrs(rule *req, graph g) +{ + for (int i = 0; i < req->users_len; ++i) + expand_attr(&req->users[i], g); + for (int i = 0; i < req->objects_len; ++i) + expand_attr(&req->objects[i], g); + for (int i = 0; i < req->contexts_len; ++i) + expand_attr(&req->contexts[i], g); +} + +// authorization + +int is_subset(char **ro, size_t ro_len, char **po, size_t po_len) +{ + for (int i = 0; i < ro_len; i++) { + int ok = 0; + for (int j = 0; j < po_len; j++) + if (strcmp(ro[i], po[j]) == 0) + ok = 1; + if (!ok) + return 0; + } + return 1; +} + +int is_string_in(char *a, char **b, size_t b_len) +{ + for (int i = 0; i < b_len; ++i) + if (strcmp(a, b[i]) == 0) + return 1; + return 0; +} + +int match_attr_v2(attr_v2 ra, attr_v2 pa) +{ + if (strcmp(ra.name, pa.name) != 0) + return 0; + + switch(pa.data_type) { + case abac_integer: + if (ra.integer == pa.integer) + return 1; + break; + case abac_real: + if (ra.real == pa.real) + return 1; + break; + case abac_integer_range: + if (ra.integer >= pa.ran.integer_min && ra.integer <= pa.ran.integer_max) + return 1; + break; + case abac_real_range: + if (ra.real >= pa.ran.real_min && ra.real <= pa.ran.real_max) + return 1; + break; + case abac_string: + if (ra.data_type == abac_string && strcmp(ra.string, pa.string) == 0) + return 1; + else if (ra.data_type == abac_string_list && is_string_in(pa.string, ra.string_list, ra.inner_list_len)) + return 1; + break; + case abac_dictionary: + return match_attrs_v2(ra.inner_attrs, ra.inner_list_len, pa.inner_attrs, pa.inner_list_len); + } + return 0; +} + +int match_attrs_v2(attr_v2 **ras, size_t ras_len, attr_v2 **pas, size_t pas_len) +{ + int any_r; + for (int i = 0; i < pas_len; i++) + { + any_r = 0; + for (int j = 0; j < ras_len; j++) + if (match_attr_v2(*(ras[i]), *(pas[i]))) + any_r = 1; + if (!any_r) + return 0; + } + if (any_r) + return 1; + else + return 0; +} + +int match_permission(rule r, rule perm) +{ + return + is_subset(r.operations, r.operations_len, perm.operations, perm.operations_len) && + match_attrs_v2(r.users, r.users_len, perm.users, perm.users_len) && + match_attrs_v2(r.objects, r.objects_len, perm.objects, perm.objects_len) && + match_attrs_v2(r.contexts, r.contexts_len, perm.contexts, perm.contexts_len); +} + +int authorize_permissions(rule req, rule *perms, size_t p_len) +{ + for (int i = 0; i < p_len; i++) + if (match_permission(req, perms[i])) + return 1; + return 0; +} + +int authorize_permissions_expand(rule req, rule *perms, size_t p_len, graph g) +{ + expand_attrs(&req, g); + for (int i = 0; i < p_len; i++) + if (match_permission(req, perms[i])) + return 1; + return 0; +} + +// debug + +void show_attr_v2(attr_v2 at) +{ + switch(at.data_type) { + case abac_integer: + printf("%s: %d\n", at.name, at.integer); + break; + case abac_real: + printf("%s: %.2f\n", at.name, at.real); + break; + case abac_integer_range: + printf("%s: %d..%d\n", at.name, at.ran.integer_min, at.ran.integer_max); + break; + case abac_real_range: + printf("%s: %.2f..%.2f\n", at.name, at.ran.real_min, at.ran.real_max); + break; + case abac_string: + printf("%s: %s\n", at.name, at.string); + break; + case abac_string_list: + printf("%s: ", at.name); + for (int i = 0; i < at.inner_list_len; ++i) + printf("%s ", at.string_list[i]); + printf("\n"); + break; + case abac_dictionary: + printf("[%s:\n", at.name); + for (int i = 0; i < at.inner_list_len; i++) + show_attr_v2(*(at.inner_attrs[i])); + printf("]\n"); + break; + } +} + +void show_operations(char **ops, size_t len) +{ + for (int i = 0; i < len; i++) + printf("%s ", ops[i]); + printf("\n"); +} + +void show_rule(rule r, char *desc) +{ + printf("\n>%s\n", desc); + printf("#users:\n"); + for (int i = 0; i < r.users_len; i++) + show_attr_v2(*(r.users[i])); + printf("#objects:\n"); + for (int i = 0; i < r.objects_len; i++) + show_attr_v2(*(r.objects[i])); + printf("#contexts:\n"); + for (int i = 0; i < r.contexts_len; i++) + show_attr_v2(*(r.contexts[i])); + printf("#operations:\n"); + show_operations(r.operations, r.operations_len); +} + +void show_visited(node *visited, size_t v_len) +{ + printf("visited: "); + for (int i = 0; i < v_len; ++i) + printf("%s ", visited[i].value); + printf("\n"); +} + +void show_node_list(node *list, size_t len, char *desc) +{ + printf("%s: ", desc); + for (int i = 0; i < len; ++i) + printf("%s ", list[i].value); + printf("\n"); +} + + + +int main() { + + attr_v2 **at_list; + + attr_v2 id_alice = new_attr_string("id", "alice"); + attr_v2 id_camera1 = new_attr_string("id", "camera1"); + attr_v2 id_lamp1 = new_attr_string("id", "lamp1"); + attr_v2 id_some_device_x = new_attr_string("id", "some-device-x"); + attr_v2 owner_alice = new_attr_string("owner", "alice"); + attr_v2 year_2020 = new_attr_integer("year", 2020); + attr_v2 month_6 = new_attr_integer("month", 6); + attr_v2 day_30 = new_attr_integer("day", 30); + attr_v2 hour_17 = new_attr_integer("hour", 17); + attr_v2 luminosity_25 = new_attr_integer("outdoorLuminosity", 25); + attr_v2 age_min18 = new_attr_integer_range("age", 18, 120); + attr_v2 minute_20_25 = new_attr_integer_range("minute", 20, 25); + attr_v2 luminosity_max33 = new_attr_integer_range("outdoorLuminosity", 0, 33); + attr_v2 reputation_min4 = new_attr_real_range("reputation", 4, 5); + attr_v2 type_security = new_attr_string("type", "securityAppliance"); + attr_v2 type_lighting = new_attr_string("type", "lightingAppliance"); + attr_v2 household_role_child = new_attr_string("role", "child"); + attr_v2 household_id_home1 = new_attr_string("id", "home-1"); + attr_v2 type_camera = new_attr_string("type", "securityCamera"); + attr_v2 location_outdoor = new_attr_string("location", "outdoor"); + + at_list = new_attr_list(1); + at_list[0] = &household_id_home1; + attr_v2 household_with_id = new_attr_dictionary("household", at_list, 1); + + at_list = new_attr_list(2); + at_list[0] = &household_id_home1; + at_list[1] = &household_role_child; + attr_v2 household_with_id_role = new_attr_dictionary("household", at_list, 2); + + // p1 + rule perm1; + perm1.users = new_attr_list(1); + perm1.users_len = 1; + perm1.users[0] = &id_alice; + + perm1.objects = new_attr_list(1); + perm1.objects_len = 1; + perm1.objects[0] = &owner_alice; + + perm1.contexts_len = 0; + + perm1.operations = new_operations_list(4); + perm1.operations_len = 4; + perm1.operations[0] = "create"; + perm1.operations[1] = "read"; + perm1.operations[2] = "update"; + perm1.operations[3] = "delete"; + show_rule(perm1, "perm1\0"); + + // p2, authorizes req_e + rule perm2; + perm2.users = new_attr_list(2); + perm2.users_len = 2; + perm2.users[0] = &age_min18; + perm2.users[1] = &household_with_id; + + perm2.objects = new_attr_list(2); + perm2.objects_len = 2; + perm2.objects[0] = &type_security; + perm2.objects[1] = &household_with_id; + + perm2.contexts_len = 0; + + perm2.operations = new_operations_list(2); + perm2.operations_len = 2; + perm2.operations[0] = "read"; + perm2.operations[1] = "update"; + show_rule(perm2, "perm2\0"); + + // p3, authorizes req + rule perm3; + perm3.users = new_attr_list(1); + perm3.users_len = 1; + perm3.users[0] = &household_with_id_role; + + perm3.objects = new_attr_list(2); + perm3.objects_len = 2; + perm3.objects[0] = &type_lighting; + perm3.objects[1] = &household_with_id; + + perm3.contexts = new_attr_list(1); + perm3.contexts_len = 1; + perm3.contexts[0] = &luminosity_max33; + + perm3.operations = new_operations_list(2); + perm3.operations_len = 2; + perm3.operations[0] = "read"; + perm3.operations[1] = "update"; + show_rule(perm3, "perm3\0"); + + // p4 + rule perm4; + perm4.users = new_attr_list(1); + perm4.users_len = 1; + perm4.users[0] = &id_camera1; + + perm4.objects = new_attr_list(1); + perm4.objects_len = 1; + perm4.objects[0] = &id_lamp1; + + perm4.contexts_len = 0; + + perm4.operations = new_operations_list(2); + perm4.operations_len = 2; + perm4.operations[0] = "read"; + perm4.operations[1] = "update"; + show_rule(perm4, "perm4\0"); + + // p5 + rule perm5; + perm5.users = new_attr_list(1); + perm5.users_len = 1; + perm5.users[0] = &reputation_min4; + + perm5.objects = new_attr_list(3); + perm5.objects_len = 3; + perm5.objects[0] = &type_camera; + perm5.objects[1] = &household_with_id; + perm5.objects[2] = &location_outdoor; + + perm5.contexts = new_attr_list(1); + perm5.contexts_len = 1; + perm5.contexts[0] = &luminosity_max33; + + perm5.operations = new_operations_list(1); + perm5.operations_len = 1; + perm5.operations[0] = "contract"; + show_rule(perm5, "perm5\0"); + + // p6 + rule perm6; + perm6.users = new_attr_list(1); + perm6.users_len = 1; + perm6.users[0] = &id_some_device_x; + + perm6.objects = new_attr_list(5); + perm6.objects_len = 5; + perm6.objects[0] = &year_2020; + perm6.objects[1] = &month_6; + perm6.objects[2] = &day_30; + perm6.objects[3] = &hour_17; + perm6.objects[4] = &minute_20_25; + + perm6.contexts = new_attr_list(1); + perm6.contexts_len = 1; + perm6.contexts[0] = &luminosity_max33; + + perm6.operations = new_operations_list(1); + perm6.operations_len = 1; + perm6.operations[0] = "contract"; + show_rule(perm6, "perm6\0"); + + // list of perms + rule *perms = (rule *) malloc(sizeof(rule) * 6); + perms[0] = perm1; + perms[1] = perm2; + perms[2] = perm3; + perms[3] = perm4; + perms[4] = perm5; + perms[5] = perm6; + + // a request + rule req; + req.users = new_attr_list(1); + req.users_len = 1; + req.users[0] = &household_with_id_role; + + req.objects = new_attr_list(2); + req.objects_len = 2; + req.objects[0] = &type_lighting; + req.objects[1] = &household_with_id; + + req.contexts = new_attr_list(1); + req.contexts_len = 1; + req.contexts[0] = &luminosity_25; + + req.operations = new_operations_list(1); + req.operations_len = 1; + req.operations[0] = "read"; + show_rule(req, "request\0"); + + if (authorize_permissions(req, perms, 6)) + printf("\nauthorized request for policy #3\n"); + + // creating a graph + + node n_child = new_graph_node("child"); + node n_father = new_graph_node("father"); + node n_mother = new_graph_node("mother"); + node n_adultFamilyMember = new_graph_node("adultFamilyMember"); + node n_family_member = new_graph_node("familyMember"); + node n_person = new_graph_node("person"); + create_directed_edge(&n_child, &n_family_member); + create_directed_edge(&n_father, &n_adultFamilyMember); + create_directed_edge(&n_mother, &n_adultFamilyMember); + create_directed_edge(&n_adultFamilyMember, &n_family_member); + create_directed_edge(&n_family_member, &n_person); + + node n_securityCamera = new_graph_node("securityCamera"); + node n_intrusionAlarm = new_graph_node("intrusionAlarm"); + node n_securityAppliance = new_graph_node("securityAppliance"); + create_directed_edge(&n_securityCamera, &n_securityAppliance); + create_directed_edge(&n_intrusionAlarm, &n_securityAppliance); + + graph g = new_graph(6+3); + g.list[0] = &n_child; + g.list[1] = &n_father; + g.list[2] = &n_mother; + g.list[3] = &n_adultFamilyMember; + g.list[4] = &n_family_member; + g.list[5] = &n_person; + g.list[6] = &n_securityCamera; + g.list[7] = &n_intrusionAlarm; + g.list[8] = &n_securityAppliance; + + // a request to expand + rule req_e; + req_e.users = new_attr_list(2); + req_e.users_len = 2; + attr_v2 age_25 = new_attr_integer("age", 25); + req_e.users[0] = &age_25; + req_e.users[1] = &household_with_id; + + req_e.objects = new_attr_list(2); + req_e.objects_len = 2; + req_e.objects[0] = &type_camera; + req_e.objects[1] = &household_with_id; + + req_e.contexts_len = 0; + + req_e.operations = new_operations_list(1); + req_e.operations_len = 1; + req_e.operations[0] = "read"; + show_rule(req_e, "request that will be expanded\0"); + + if (!authorize_permissions(req_e, perms, 6)) + printf("\ndenied non-expanded request for policy #2\n"); + if (authorize_permissions_expand(req_e, perms, 6, g)) + printf("\nauthorized expanded request for policy #2\n\n"); + + // many policies + int n_perms = 3000, median; + median = (int) (n_perms / 2); + rule *many_perms = (rule *) malloc(sizeof(rule) * n_perms); + for (int i = 0; i < n_perms; ++i) + many_perms[i] = perm5; + many_perms[median] = perm2; + + // benchmark + + int runs = 3000; +#ifdef MBED_MAJOR_VERSION + Timer t; + t.start(); + for (int i = 0; i < runs; i++) + authorize_permissions_expand(req_e, perms, 6, g); + t.stop(); + pc.printf("The time taken to authorize 1 request against 6 policies, %d times, was %f ms\n", runs, t.read() * 1000); + printf("> The time taken to authorize 1 request against 6 policies, %d times, was %f ms\n", runs, t.read() * 1000); + + t.start(); + authorize_permissions_expand(req_e, many_perms, n_perms, g); + t.stop(); + pc.printf("The time taken to authorize 1 request against %d policies was %f ms\n", n_perms, t.read() * 1000); + printf("> The time taken to authorize 1 request against %d policies was %f ms\n", n_perms, t.read() * 1000); +#elif defined(ESP32) + unsigned long startTime, endTime; + startTime = millis(); + for (int i = 0; i < runs; i++) + authorize_permissions_expand(req_e, perms, 6, g); + endTime = millis(); + Serial.print("The time taken to authorize 1 request against 6 policies, "); + Serial.print(runs); + Serial.print(" times, was "); + Serial.print(endTime - startTime); + Serial.println(" ms"); + + startTime = millis(); + authorize_permissions_expand(req_e, many_perms, n_perms, g); + endTime = millis(); + Serial.print("The time taken to authorize 1 request against "); + Serial.print(n_perms); + Serial.print(" policies was "); + Serial.print(endTime - startTime); + Serial.println(" ms"); +#elif defined(__unix__) + #include <time.h> + clock_t t; + t = clock(); + double elapsed; + for (int i = 0; i < runs; i++) + authorize_permissions_expand(req_e, perms, 6, g); + t = clock() - t; + elapsed = ((double) t) / CLOCKS_PER_SEC; + printf("The time taken to authorize 1 request against 6 policies, %d times, was %f ms\n", runs, elapsed * 1000); + + t = clock(); + authorize_permissions_expand(req_e, many_perms, n_perms, g); + t = clock() - t; + elapsed = ((double) t) / CLOCKS_PER_SEC; + printf("The time taken to authorize 1 request against %d policies was %f ms\n", n_perms, elapsed * 1000); +#endif + + free(many_perms); +}