source: libabac/abac_graph.c @ ea38d81

abac0-leak
Last change on this file since ea38d81 was ea38d81, checked in by Ted Faber <faber@…>, 11 years ago

Memory leak in queries, and a couple other incidental ones.

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