source: libabac/abac_graph.c @ f6576c4

abac0-leak
Last change on this file since f6576c4 was f6576c4, checked in by Mei-Hui Su <mei@…>, 11 years ago

1) more leak tweak for abac_graph_add_credential

  • Property mode set to 100644
File size: 20.1 KB
RevLine 
[fc1a6b4]1
2/* abac_graph.c */
3
[d4cbf71]4#include <assert.h>
[379a53f]5#include <stdlib.h>
[d4cbf71]6
[06293d1]7#include "abac_graph.h"
[cb0f2b2]8
[2fd24c7]9#include "abac_set.h"
[3c251d0]10#include "abac_util.h"
[d4cbf71]11
[f46412c]12#include "uthash.h"
13
14// vertex
[06293d1]15struct _abac_vertex_t {
[1743825]16    abac_role_t *role;
[f46412c]17    char *name;
[06ef09c]18    int refcount;
[f46412c]19
[6d5623e]20    abac_list_t *edges;
[d4b3b52]21    abac_list_t *reverse_edges;
[f46412c]22
[0eb4a8e]23    // only relevant to intersection edges
24    abac_list_t *prereqs;
25
[f46412c]26    UT_hash_handle hh;
27};
28
[ae72c5d]29// edge
[06293d1]30typedef struct _abac_edge_t {
[06ef09c]31    int refcount;
[06293d1]32    abac_vertex_t *vertex;
[d4b3b52]33    abac_vertex_t *reverse_vertex;
[401a054]34    abac_credential_t *credential;
[06293d1]35} abac_edge_t;
[ae72c5d]36
[f46412c]37// derived edge
[06293d1]38typedef struct _abac_derived_key_t {
39    abac_vertex_t *head;
40    abac_edge_t *tail;
41} abac_derived_key_t;
[f46412c]42
[06293d1]43typedef struct _abac_derived_t {
44    abac_derived_key_t key;
[f46412c]45    UT_hash_handle hh;
[06293d1]46} abac_derived_t;
[f46412c]47
48// graph
[06293d1]49struct _abac_graph_t {
50    abac_vertex_t *vertices;
51    abac_derived_t *derived;
[f46412c]52    int dirty;
53};
[0ec9e25]54
[0eb4a8e]55// ugghhhghhhghh need this for intersections
[9a411d7]56abac_list_t *abac_role_prereqs(abac_role_t *);
[0eb4a8e]57
[f2622ee]58static abac_vertex_t *_dup_vertex(abac_vertex_t *v);
[fc1a6b4]59int abac_graph_add_credential(abac_graph_t *graph, abac_credential_t *cred);
[f2622ee]60
[0ec9e25]61/**
62 * Create a new graph.
63 */
[06293d1]64abac_graph_t *abac_graph_new(void) {
[3c251d0]65    abac_graph_t *graph = abac_xmalloc(sizeof(abac_graph_t));
[82aeefa]66
67    graph->vertices = NULL;
[6188f4e]68    graph->derived = NULL;
[82aeefa]69    graph->dirty = 0;
70
71    return graph;
72}
[d4cbf71]73
[b26942d]74/**
75 * Deep copy a graph.
76 */
[06293d1]77abac_graph_t *abac_graph_dup(abac_graph_t *graph) {
78    abac_vertex_t *vertex;
79    abac_edge_t *edge;
[b26942d]80
[06293d1]81    abac_graph_t *clone = abac_graph_new();
[b26942d]82
83    // copy the vertices edge by edge
84    for (vertex = graph->vertices; vertex != NULL; vertex = vertex->hh.next)
[6d5623e]85        abac_list_foreach(vertex->edges, edge,
[b26942d]86            // only copy non-derived edges
[401a054]87            if (edge->credential != NULL)
88                abac_graph_add_credential(clone, edge->credential);
[b26942d]89        );
90
91    return clone;
92}
[d4cbf71]93/**
[06ef09c]94 * Add a vertex to the graph. Should only be called by
95 * abac_graph_add_credential. This returns an existing vertex with the refcount
96 * bumped, or a new vertex with a refcount of 1.  Either way it gets and
97 * references the vertex.
[d4cbf71]98 */
[06293d1]99static abac_vertex_t *_get_vertex(abac_graph_t *graph, abac_role_t *role) {
100    abac_vertex_t *vertex;
[c28bd8b]101    char *string;
102   
[cb135e1]103    string =abac_role_string(role);
[82aeefa]104    HASH_FIND_STR(graph->vertices, string, vertex);
[c28bd8b]105
106    // add the vertex if it doesn't exist
107    if (vertex == NULL) {
[3c251d0]108        vertex = abac_xmalloc(sizeof(abac_vertex_t));
[f2622ee]109        vertex->refcount = 1;
[dcc1a8e]110        vertex->role = abac_role_dup(role);
111        vertex->name = abac_role_string(vertex->role);
[d4cbf71]112
[379a53f]113        // create the list of edges
[6d5623e]114        vertex->edges = abac_list_new();
[d4b3b52]115        vertex->reverse_edges = abac_list_new();
[d4cbf71]116
[0eb4a8e]117        // for intersections, always NULL on normal vertices
[9a411d7]118        if (abac_role_is_intersection(role)) {
119            abac_role_t *prereq;
120            vertex->prereqs = abac_list_new();
121
122            // add each prereq to the vertex
123            abac_list_foreach(abac_role_prereqs(role), prereq,
124                abac_vertex_t *tail_vertex = _get_vertex(graph, prereq);
[fc1a6b4]125/*??? */
[4571abc]126                abac_list_add(vertex->prereqs, _dup_vertex(tail_vertex));
[9a411d7]127            );
128        }
[0eb4a8e]129
[9a411d7]130        // normal edges have no prereqs
131        else
132            vertex->prereqs = NULL;
[0eb4a8e]133
[c28bd8b]134        // add it to the vertices
[82aeefa]135        HASH_ADD_KEYPTR(hh, graph->vertices, vertex->name, strlen(vertex->name), vertex);
[f2622ee]136
137        } else {
[fc1a6b4]138          return vertex;
139/* ??? return _dup_vertex(vertex); */ 
[c28bd8b]140    }
[d4cbf71]141
142    return vertex;
143}
144
[06ef09c]145/* forward decl */
146static void _free_edge(abac_edge_t *edge);
[fc1a6b4]147
[06ef09c]148/*
149 * Reduce the vertex reference count and free it if this is the last reference
150 */
151static void _free_vertex(abac_vertex_t *vertex) {
152    abac_edge_t *edge=NULL;
153    abac_vertex_t *pre=NULL;
154
155    --vertex->refcount;
[fc1a6b4]156
[06ef09c]157    if ( vertex->refcount > 0) return;
158
159    abac_role_free(vertex->role);
160
161    abac_list_foreach(vertex->edges, edge,
162        _free_edge(edge);
163    );
164    abac_list_free(vertex->edges);
165
166    abac_list_foreach(vertex->reverse_edges, edge,
167        _free_edge(edge);
168    );
169    abac_list_free(vertex->reverse_edges);
170
171    // Free the prereqs
172    if (vertex->prereqs != NULL) {
173        abac_list_foreach(vertex->prereqs, pre,
174            if (pre != NULL) {
175                _free_vertex(pre);
176            }
177        );
178        abac_list_free(vertex->prereqs);
179    }
180
181    free(vertex);
182}
183
184/*
185 * Increment vertex reference count
186 */
187static abac_vertex_t *_dup_vertex(abac_vertex_t *v) {
188    v->refcount++;
189    return v;
190}
191
192
193/*
194 * create a new edge from the given head, tail and credential
195 */
196
197static abac_edge_t *_get_edge(abac_vertex_t *h, abac_vertex_t *t,
198        abac_credential_t *c) {
199
200    /* An edge does not own it's vertices.  Do not delete them from an edge
201     * reference. */
202    abac_edge_t *edge = abac_xmalloc(sizeof(abac_edge_t));
203    edge->refcount = 1;
204    edge->vertex = t;
205    edge->reverse_vertex = h;
206    /* Don't dup a null credential */
207    edge->credential = (c) ? abac_credential_dup(c): NULL;
208
209    return edge;
210}
211
212
213/**
214 * Increment the reference count
215 */
216static abac_edge_t *_dup_edge(abac_edge_t *e) {
217    e->refcount++;
218    return e;
219}
220
221/**
222 * Decerement the refcount and free it if this was the last reference.  NB
223 * edges do not own teh vertices, so they must be deleted elsewhere.
224 */
225static void _free_edge(abac_edge_t *edge) {
226    assert(edge && edge->refcount > 0);
227    if ( --edge->refcount > 0) return;
228    if (edge->credential) abac_credential_free(edge->credential);
229    free(edge);
230}
231
[d4cbf71]232/**
[401a054]233 * Add a credential to the credential graph.
[d4cbf71]234 */
[401a054]235int abac_graph_add_credential(abac_graph_t *graph, abac_credential_t *cred) {
[06293d1]236    abac_vertex_t *head_vertex, *tail_vertex;
[314869f]237    abac_edge_t *edge;
[d4cbf71]238
[401a054]239    assert(cred != NULL);
[ae72c5d]240
[401a054]241    abac_role_t *head = abac_credential_head(cred);
242    abac_role_t *tail = abac_credential_tail(cred);
[d4cbf71]243
[401a054]244    // a valid credential must have a role for the head
[dcc1a8e]245    if (!abac_role_is_role(head)) return 0;
[d4cbf71]246
[82aeefa]247    head_vertex = _get_vertex(graph, head);
[9a411d7]248    tail_vertex = _get_vertex(graph, tail);
[d4cbf71]249
[314869f]250    // make sure we don't insert the same edge twice (ugh)
251    abac_list_foreach(head_vertex->edges, edge,
[06ef09c]252        if (edge->vertex == tail_vertex) {
[fc1a6b4]253/*
[06ef09c]254            _free_vertex(head_vertex);
255            _free_vertex(tail_vertex);
[fc1a6b4]256*/
[314869f]257            return 0;
[06ef09c]258        }
[314869f]259    );
260
[ae72c5d]261    // create the edge and add it
[06ef09c]262    edge = _get_edge(head_vertex, tail_vertex, cred);
[ae72c5d]263
[6d5623e]264    abac_list_add(head_vertex->edges, edge);
[06ef09c]265    abac_list_add(tail_vertex->reverse_edges, _dup_edge(edge));
[d4cbf71]266
[82aeefa]267    // must re-derive edges
268    graph->dirty = 1;
269
[d4cbf71]270    return 1;
271}
272
[ebde9dd]273// find the principals that have a role
[06293d1]274static abac_set_t *_find_principals(abac_graph_t *graph, abac_vertex_t *start_vertex) {
[2fd24c7]275    abac_set_t *principals = abac_set_new();
[d4cbf71]276
[06293d1]277    abac_list_t *traversal = abac_graph_postorder(graph, start_vertex->role);
278    abac_vertex_t *vertex;
[d4cbf71]279
[6d5623e]280    abac_list_foreach(traversal, vertex,
[9a411d7]281        if (abac_role_is_principal(vertex->role))
282            abac_set_add(principals, abac_role_string(vertex->role));
[ebde9dd]283    );
[d4cbf71]284
[6d5623e]285    abac_list_free(traversal);
[ebde9dd]286    return principals;
287}
[d4cbf71]288
[6188f4e]289// remove any derived edges from the graph
[06293d1]290void _clear_derived(abac_graph_t *graph) {
291    abac_derived_t *current;
[6188f4e]292
293    while (graph->derived) {
294        current = graph->derived;
295
296        HASH_DEL(graph->derived, current);
297
[06293d1]298        abac_vertex_t *head = current->key.head;
299        abac_edge_t *tail = current->key.tail;
[401a054]300        assert(tail->credential == NULL);
[6188f4e]301
302        // this can fail, but we assume the data structures are consistent
[6d5623e]303        abac_list_remove(head->edges, tail);
[d4b3b52]304        abac_list_remove(tail->reverse_vertex->edges, tail);
[6188f4e]305
[06ef09c]306        _free_edge(tail);
[fc1a6b4]307        free(current);
[6188f4e]308    }
309}
310
[704fde7]311// add a derived edge, returns 1 if added 0 if dup
312static int _derived_edge(abac_graph_t *graph, abac_vertex_t *head, abac_vertex_t *tail) {
313    abac_edge_t *edge;
314
315    // don't add duplicate edges
316    abac_list_foreach(head->edges, edge,
317        if (edge->vertex == tail)
318            return 0;
319    );
320
321    debug_printf("derived edge %s <- %s\n", head->name, tail->name);
322
[06ef09c]323    edge = _get_edge(head, tail, NULL);
[e2a0f26]324    abac_list_add(head->edges, edge);
[06ef09c]325    abac_list_add(tail->reverse_edges, _dup_edge(edge));
[e2a0f26]326
327    // add to list of derived edges
328    abac_derived_t *derived = abac_xmalloc(sizeof(abac_derived_t));
329    derived->key.head = head;
330    derived->key.tail = edge;
331    HASH_ADD(hh, graph->derived, key, sizeof(abac_derived_key_t), derived);
[704fde7]332
333    return 1;
[e2a0f26]334}
335
336// find a vertex by name
337abac_vertex_t *_find_vertex(abac_graph_t *graph, char *name) {
338    abac_vertex_t *ret = NULL;
339    HASH_FIND_STR(graph->vertices, name, ret);
340    return ret;
341}
342
[704fde7]343/**
344 * Single iteration of deriving new edges. Returns the number of new edges
345 * added.
346 */
347static int _derive_links_iter(abac_graph_t *graph) {
348    int count = 0;
[06293d1]349    abac_vertex_t *vertex;
[d4cbf71]350
[ebde9dd]351    for (vertex = graph->vertices; vertex != NULL; vertex = vertex->hh.next) {
[0eb4a8e]352        // intersection
[9a411d7]353        if (abac_role_is_intersection(vertex->role)) {
[0eb4a8e]354            // for each prereq edge:
355            //     find principals that have the edge
356            // find intersection of all sets
357            // for each principal B in intersection:
358            //     add link
[e2a0f26]359
360            char *name;
361            abac_vertex_t *prereq;
362            abac_set_t *principals = NULL;
363
364            abac_list_foreach(vertex->prereqs, prereq,
365                abac_set_t *cur = _find_principals(graph, prereq);
366
367                if (principals == NULL)
368                    principals = cur;
369                else {
370                    abac_set_intersect(principals, cur);
371                    abac_set_free(cur);
372                }
373
374                if (abac_set_size(principals) == 0)
375                    goto isect_done;
376            );
377
378            abac_list_t *prin_names = abac_set_elements(principals);
379            abac_list_foreach(prin_names, name,
380                abac_vertex_t *principal = _find_vertex(graph, name);
[704fde7]381                count += _derived_edge(graph, vertex, principal);
[e2a0f26]382            );
383
384            abac_list_free(prin_names);
385isect_done:
386            abac_set_free(principals);
[0eb4a8e]387        }
388
389        // linking role
390        else if (abac_role_is_linking(vertex->role)) {
391            // linking roles take the form A.r1.r2
392            char *A_r1 = abac_role_linked_role(vertex->role);
393            char *r2 = abac_role_role_name(vertex->role);
394
395            // find the linked role in the graph
396            abac_vertex_t *A_r1_vertex;
397            HASH_FIND_STR(graph->vertices, A_r1, A_r1_vertex);
398            if (A_r1_vertex == NULL)
399                continue;
400
401            // find the principals that have A.r1
402            abac_set_t *principals = _find_principals(graph, A_r1_vertex);
403            char *B;
404
405            abac_list_t *elts = abac_set_elements(principals);
406
407            // and add a link for each B.r2 to A.r1.r2
408            abac_list_foreach(elts, B,
409                int B_len = strlen(B);
410                int r2_len = strlen(r2);
411
412                // create the string B.r2, thx C
413                char *B_r2 = malloc(B_len + r2_len + 2);
414                memcpy(B_r2, B, B_len);
415                B_r2[B_len] = '.';
416                memcpy(B_r2 + B_len + 1, r2, r2_len);
417                B_r2[B_len + r2_len + 1] = 0;
418
419                // add an edge if the principal's granted it to someone
[e2a0f26]420                abac_vertex_t *B_r2_vertex = _find_vertex(graph, B_r2);
[0eb4a8e]421                if (B_r2_vertex) {
422                    debug_printf("adding edge from %s to %s\n", B_r2, abac_role_string(vertex->role));
[704fde7]423                    count += _derived_edge(graph, vertex, B_r2_vertex);
[0eb4a8e]424                }
[ebde9dd]425
[dbbf777]426#ifdef DEBUG
[0eb4a8e]427                debug_printf("    incoming edges for %s\n", abac_role_string(vertex->role));
428                abac_edge_t *cur;
429                abac_list_foreach(vertex->edges, cur,
430                    debug_printf("        %s (%s)\n", abac_role_string(cur->vertex->role), cur->vertex->name);
431                );
[dbbf777]432#endif
[d4cbf71]433
[0eb4a8e]434                free(B_r2);
435            );
[ebde9dd]436
[0eb4a8e]437            abac_list_free(elts);
438            abac_set_free(principals);
439        }
[ebde9dd]440    }
[6188f4e]441
[704fde7]442    return count;
443}
444
445/**
446 * Derive all implied edges in the graph. These can come from linking roles
447 * and intersections.
448 *
449 * We have to do it iteratively because derived edges can imply new edges.
450 */
451void abac_graph_derive_links(abac_graph_t *graph) {
452    if (!graph->dirty)
453        return;
454
455    // iterate as long as new links are derived
456    while (_derive_links_iter(graph) > 0)
457        ;
458
[6188f4e]459    graph->dirty = 0;
[d4cbf71]460}
[cb0f2b2]461
[d4b3b52]462static void _reverse_order_recurse(abac_vertex_t *vertex, abac_set_t *seen, int preorder, abac_list_t *stack) {
463    abac_edge_t *outgoing;
464
465    // don't revisit nodes
466    if (!abac_set_add(seen, abac_role_string(vertex->role)))
467        return;
468
[fc1a6b4]469    if (preorder) {
[d4b3b52]470        abac_list_add(stack, vertex);
[fc1a6b4]471    }
[d4b3b52]472
473    // recurse along the incoming vertices
474    abac_list_foreach(vertex->reverse_edges, outgoing,
475        _reverse_order_recurse(outgoing->reverse_vertex, seen, preorder, stack);
476    );
477
[fc1a6b4]478    if (!preorder) {
[d4b3b52]479        abac_list_add(stack, vertex);
[fc1a6b4]480    }
[d4b3b52]481}
482
483static abac_list_t *_reverse_order(abac_graph_t *graph, abac_role_t *start, int preorder) {
484    debug_printf("%sorder at %s\n", preorder ? "pre" : "post", abac_role_string(start));
485
[fc1a6b4]486
[d4b3b52]487    abac_vertex_t *start_vertex = _get_vertex(graph, start);
[fc1a6b4]488
[d4b3b52]489    abac_set_t *seen = abac_set_new();
490
491    // create the return list
492    abac_list_t *stack = abac_list_new();
493
494    _reverse_order_recurse(start_vertex, seen, preorder, stack);
495
496    abac_set_free(seen);
497
[fc1a6b4]498
[d4b3b52]499    return stack;
500}
501
[06293d1]502static void _order_recurse(abac_vertex_t *vertex, abac_set_t *seen, int preorder, abac_list_t *stack) {
503    abac_edge_t *incoming;
[cb0f2b2]504
505    // don't revisit nodes
[9a411d7]506    if (!abac_set_add(seen, abac_role_string(vertex->role)))
[cb0f2b2]507        return;
508
[fc1a6b4]509    if (preorder) {
[6d5623e]510        abac_list_add(stack, vertex);
[fc1a6b4]511    }
[cb0f2b2]512
[9536712]513    // recurse along the incoming vertices
[6d5623e]514    abac_list_foreach(vertex->edges, incoming,
[ae72c5d]515        _order_recurse(incoming->vertex, seen, preorder, stack);
[379a53f]516    );
[cb0f2b2]517
[fc1a6b4]518    if (!preorder) {
[6d5623e]519        abac_list_add(stack, vertex);
[fc1a6b4]520    }
[cb0f2b2]521}
522
[06293d1]523static abac_list_t *_order(abac_graph_t *graph, abac_role_t *start, int preorder) {
[dcc1a8e]524    debug_printf("%sorder at %s\n", preorder ? "pre" : "post", abac_role_string(start));
[ebde9dd]525
[06293d1]526    abac_vertex_t *start_vertex = _get_vertex(graph, start);
[fc1a6b4]527
[2fd24c7]528    abac_set_t *seen = abac_set_new();
[cb0f2b2]529
[379a53f]530    // create the return list
[6d5623e]531    abac_list_t *stack = abac_list_new();
[cb0f2b2]532
533    _order_recurse(start_vertex, seen, preorder, stack);
534
[2fd24c7]535    abac_set_free(seen);
[be963dc]536
[cb0f2b2]537    return stack;
538}
539
[06293d1]540abac_list_t *abac_graph_postorder(abac_graph_t *graph, abac_role_t *start) {
[82aeefa]541    return _order(graph, start, 0);
[cb0f2b2]542}
[97a5e13]543
[4e426c9]544/**
545 * Postorder traverse the graph and return all the credentials within.
546 */
547abac_list_t *abac_graph_postorder_credentials(abac_graph_t *graph, char *start) {
548    abac_vertex_t *vertex;
549    abac_edge_t *incoming;
550
551    // get the postorder of vertices
552    abac_role_t *role = abac_role_from_string(start);
553    abac_list_t *order = abac_graph_postorder(graph, role);
554
555    // go through the list and dup all the credentials
556    abac_list_t *credentials = abac_list_new();
557    abac_list_foreach(order, vertex,
558        abac_list_foreach(vertex->edges, incoming,
[fc1a6b4]559            if (incoming->credential != NULL) {
560/* ??? do we need to duplicate this?? */
[4e426c9]561                abac_list_add(credentials, abac_credential_dup(incoming->credential));
[fc1a6b4]562            }
[4e426c9]563        );
564    );
565
566    abac_role_free(role);
567    abac_list_free(order);
568
569    return credentials;
570}
571
[d4b3b52]572
573abac_list_t *abac_graph_postorder_reverse(abac_graph_t *graph, abac_role_t *start) {
574    return _reverse_order(graph, start, 0);
575}
576
577/**
578 * Postorder traverse the graph and return all the credentials within.
579 */
580abac_list_t *abac_graph_postorder_reverse_credentials(abac_graph_t *graph, char *start) {
581    abac_vertex_t *vertex;
582    abac_edge_t *outgoing;
583
584    // get the postorder of vertices
585    abac_role_t *role = abac_role_from_string(start);
586    abac_list_t *order = abac_graph_postorder_reverse(graph, role);
587
588    // go through the list and dup all the credentials
589    abac_list_t *credentials = abac_list_new();
[fc1a6b4]590
[d4b3b52]591    abac_list_foreach(order, vertex,
592        abac_list_foreach(vertex->reverse_edges, outgoing,
[fc1a6b4]593            if (outgoing->credential != NULL) {
[d4b3b52]594                abac_list_add(credentials, abac_credential_dup(outgoing->credential));
[fc1a6b4]595            }
[d4b3b52]596        );
597    );
598
599    abac_role_free(role);
600    abac_list_free(order);
601
602    return credentials;
603}
604
[401a054]605static void _query(abac_graph_t *graph, char *role_name, char *principal, abac_graph_t *return_graph) {
[06293d1]606    abac_vertex_t *vertex;
607    abac_edge_t *incoming;
[401a054]608    abac_role_t *role = abac_role_from_string(role_name);
[dcc1a8e]609    abac_role_t *prin_role = abac_role_from_string(principal);
[97a5e13]610
[675cbea]611    // give up on bogus roles
612    if (role == NULL || prin_role == NULL) {
[f2622ee]613        abac_role_free(role);
614        abac_role_free(prin_role);
[675cbea]615        return;
616    }
617
[2fd24c7]618    abac_set_t *on_path = abac_set_new();
[dcc1a8e]619    abac_set_add(on_path, abac_role_string(prin_role));
[97a5e13]620
[401a054]621    abac_list_t *traversal = abac_graph_postorder(graph, role);
[6d5623e]622    abac_list_foreach(traversal, vertex,
[1743825]623        abac_role_t *role = vertex->role;
[97a5e13]624
[6d5623e]625        abac_list_foreach(vertex->edges, incoming,
[1743825]626            abac_role_t *incoming_role = incoming->vertex->role;
[97a5e13]627
[9a411d7]628            if (!abac_set_contains(on_path, abac_role_string(incoming_role)))
[ae72c5d]629                continue;
[97a5e13]630
[9a411d7]631            abac_set_add(on_path, abac_role_string(role));
[97a5e13]632
[ebe824c]633            // get implying edges for intersection vertices
[9a411d7]634            if (abac_role_is_intersection(role)) {
[ebe824c]635                abac_vertex_t *prereq;
636                abac_list_foreach(vertex->prereqs, prereq,
637                    _query(graph, prereq->name, principal, return_graph);
638                );
[e2a0f26]639            }
[97a5e13]640
641            // recursively find linked roles
[e2a0f26]642            else if (abac_role_is_linking(role)) {
[401a054]643                char *linked_role = abac_role_linked_role(role);
[dcc1a8e]644                char *principal = abac_role_principal(incoming_role);
[97a5e13]645
[401a054]646                _query(graph, linked_role, principal, return_graph);
[97a5e13]647            }
[e2a0f26]648
649            // add non-derived edges to the proof graph
650            else
651                abac_graph_add_credential(return_graph, incoming->credential);
[97a5e13]652        );
653    );
654
[6d5623e]655    abac_list_free(traversal);
[2fd24c7]656    abac_set_free(on_path);
[401a054]657    abac_role_free(role);
[dcc1a8e]658    abac_role_free(prin_role);
[97a5e13]659}
660
[401a054]661abac_graph_t *abac_graph_query(abac_graph_t *graph, char *role, char *principal) {
[06293d1]662    abac_graph_derive_links(graph);
[97a5e13]663
[06293d1]664    abac_graph_t *return_graph = abac_graph_new();
[401a054]665    _query(graph, role, principal, return_graph);
[06293d1]666    abac_graph_derive_links(return_graph);
[97a5e13]667    return return_graph;
668}
[be963dc]669
[d4b3b52]670abac_graph_t *abac_graph_principal_creds(abac_graph_t *graph, char *principal) {
671    abac_graph_derive_links(graph);
672    abac_graph_t *result_graph = abac_graph_new();
[fc1a6b4]673
[d4b3b52]674    abac_list_t *result = abac_graph_postorder_reverse_credentials(graph, 
675            principal);
[fc1a6b4]676
[d4b3b52]677    abac_credential_t *cur = NULL;
[f6576c4]678    int add_ret;
[d4b3b52]679    abac_list_foreach(result, cur,
[f6576c4]680        add_ret=abac_graph_add_credential(result_graph, cur);
681        assert(add_ret != ABAC_GRAPH_CRED_INVALID);
682        abac_credential_free(cur);
[d4b3b52]683    );
684    abac_list_free(result);
685    /* For each terminal role that the principal can reach, roll a proof into
686       the result_graph. */
[fc1a6b4]687
[d4b3b52]688    abac_vertex_t *vertex = NULL;
689    for (vertex = result_graph->vertices; vertex != NULL; 
690            vertex = vertex->hh.next) {
691        if ( abac_list_size(vertex->reverse_edges) == 0) 
692            _query(graph, vertex->name, principal, result_graph);
693    }
694    abac_graph_derive_links(result_graph);
[fc1a6b4]695
[d4b3b52]696    return result_graph;
697}
698
699
[902d079]700/**
[401a054]701 * Get all the credentials (attribute/issuer cert pairs) from the graph.
[902d079]702 */
[401a054]703abac_list_t *abac_graph_credentials(abac_graph_t *graph) {
704    abac_list_t *credentials = abac_list_new();
[902d079]705
[06293d1]706    abac_vertex_t *vertex;
[902d079]707
708    for (vertex = graph->vertices; vertex != NULL; vertex = vertex->hh.next) {
[06293d1]709        abac_edge_t *edge;
[6d5623e]710        abac_list_foreach(vertex->edges, edge,
[401a054]711            if (edge->credential != NULL)
712                abac_list_add(credentials, abac_credential_dup(edge->credential));
[902d079]713        );
714    }
715
[401a054]716    return credentials;
[902d079]717}
718
[06293d1]719void abac_graph_free(abac_graph_t *graph) {
720    abac_vertex_t *vertex;
721    abac_edge_t *edge;
[be963dc]722
723    // kill derived edges
724    _clear_derived(graph);
725
726    // delete vertices
727    while ((vertex = graph->vertices) != NULL) {
728        HASH_DEL(graph->vertices, vertex);
[06ef09c]729        _free_vertex(vertex);
[be963dc]730    }
731
732    free(graph);
733}
[f46412c]734
[06293d1]735abac_role_t *abac_vertex_role(abac_vertex_t *vertex) {
[f46412c]736    return vertex->role;
737}
Note: See TracBrowser for help on using the repository browser.