source: libabac/abac.c @ af36abb

abac0-leakabac0-meicompt_changesmei-idmei-rt0-nmei_rt0tvf-new-xml
Last change on this file since af36abb was d4b3b52, checked in by Ted Faber <faber@…>, 12 years ago

Better partial proofs

  • Property mode set to 100644
File size: 6.9 KB
Line 
1#include <assert.h>
2#include <err.h>
3#include <glob.h>
4
5#include <chunk.h>
6
7#include "abac.h"
8#include "abac_graph.h"
9#include "abac_util.h"
10#include "abac_verifier.h"
11
12struct _abac_context_t {
13    abac_graph_t *graph;
14};
15
16/**
17 * Init the library.
18 */
19void libabac_init(void) {
20    void libabac_deinit(void);
21    static int has_been_init = 0;
22
23    // called every time a context is created, so only do it once
24    if (!has_been_init) {
25        abac_verifier_init();
26        atexit(libabac_deinit);
27        has_been_init = 1;
28    }
29}
30
31/**
32 * Deinit the library.
33 */
34void libabac_deinit(void) {
35    abac_verifier_deinit();
36}
37
38/**
39 * Create a new abac context.
40 */
41abac_context_t *abac_context_new(void) {
42    libabac_init();
43
44    abac_context_t *ctx = abac_xmalloc(sizeof(abac_context_t));
45    ctx->graph = abac_graph_new();
46    return ctx;
47}
48
49/**
50 * Deep copy an abac context.
51 */
52abac_context_t *abac_context_dup(abac_context_t *ctx) {
53    assert(ctx != NULL);
54
55    abac_context_t *dup = abac_xmalloc(sizeof(abac_context_t));
56    dup->graph = abac_graph_dup(ctx->graph);
57
58    return dup;
59}
60
61/**
62 * Free an abac context.
63 */
64void abac_context_free(abac_context_t *ctx) {
65    assert(ctx != NULL);
66
67    abac_graph_free(ctx->graph);
68    free(ctx);
69}
70
71/**
72 * Load an ID cert from a file.
73 */
74int abac_context_load_id_file(abac_context_t *ctx, char *filename) {
75    assert(ctx != NULL); assert(filename != NULL);
76    return abac_verifier_load_id_file(filename);
77}
78
79/**
80 * Load an ID cert from a chunk.
81 */
82int abac_context_load_id_chunk(abac_context_t *ctx, abac_chunk_t cert) {
83    assert(ctx != NULL);
84    chunk_t cert_chunk = { cert.ptr, cert.len };
85    return abac_verifier_load_id_chunk(cert_chunk);
86}
87
88/**
89 * Load an attribute cert from a file.
90 */
91int abac_context_load_attribute_file(abac_context_t *ctx, char *filename) {
92    int ret, add_ret;
93    abac_credential_t *cred;
94
95    assert(ctx != NULL); assert(filename != NULL);
96
97    ret = abac_verifier_load_attribute_cert_file(filename, &cred);
98    if (ret == ABAC_CERT_SUCCESS) {
99        add_ret = abac_graph_add_credential(ctx->graph, cred);
100        assert(add_ret != ABAC_GRAPH_CRED_INVALID);
101        abac_credential_free(cred);
102    }
103
104    return ret;
105}
106
107/**
108 * Load an attribute cert from a chunk.
109 */
110int abac_context_load_attribute_chunk(abac_context_t *ctx, abac_chunk_t cert) {
111    int ret, add_ret;
112    abac_credential_t *cred;
113
114    assert(ctx != NULL);
115
116    chunk_t cert_chunk = { cert.ptr, cert.len };
117
118    ret = abac_verifier_load_attribute_cert_chunk(cert_chunk, &cred);
119    if (ret == ABAC_CERT_SUCCESS) {
120        add_ret = abac_graph_add_credential(ctx->graph, cred);
121        assert(add_ret != ABAC_GRAPH_CRED_INVALID);
122        abac_credential_free(cred);
123    }
124
125    return ret;
126}
127
128#define ID_PAT "/*_ID.{der,pem}"
129#define ATTR_PAT "/*_attr.der"
130
131/**
132 * Load a directory full of certs.
133 */
134void abac_context_load_directory(abac_context_t *ctx, char *path) {
135    char *glob_pat;
136    glob_t glob_buf;
137    int i, ret;
138
139    assert(ctx != NULL); assert(path != NULL);
140
141    int dirlen = strlen(path);
142    glob_pat = abac_xmalloc(dirlen + sizeof(ID_PAT));
143    memcpy(glob_pat, path, dirlen);
144
145    // first load ID certs
146    memcpy(glob_pat + dirlen, ID_PAT, sizeof(ID_PAT));
147    glob(glob_pat, GLOB_BRACE, NULL, &glob_buf); // TODO check for error
148    for (i = 0; i < glob_buf.gl_pathc; ++i) {
149        char *cert_file = glob_buf.gl_pathv[i];
150
151        ret = abac_context_load_id_file(ctx, cert_file);
152        if (ret != ABAC_CERT_SUCCESS)
153            warnx("Couldn't load ID cert %s", cert_file);
154    }
155    globfree(&glob_buf);
156
157    // then load attr certs
158    memcpy(glob_pat + dirlen, ATTR_PAT, sizeof(ATTR_PAT));
159    glob(glob_pat, 0, NULL, &glob_buf); // TODO check for error
160    for (i = 0; i < glob_buf.gl_pathc; ++i) {
161        char *cert_file = glob_buf.gl_pathv[i];
162
163        ret = abac_context_load_attribute_file(ctx, cert_file);
164        if (ret != ABAC_CERT_SUCCESS)
165            warnx("Couldn't load attribute cert %s", cert_file);
166    }
167    globfree(&glob_buf);
168
169    free(glob_pat);
170}
171
172/**
173 * Run a query on the data in an abac context. Returns a NULL-terminated array
174 * of abac_credential_t. Success/failure in *success.
175 */
176abac_credential_t **abac_context_query(abac_context_t *ctx, char *role, char *principal, int *success) {
177    abac_credential_t **credentials = NULL, *cur;
178    int i = 0;
179
180    assert(ctx != NULL); assert(role != NULL); assert(principal != NULL); assert(success != NULL);
181
182    abac_graph_t *result_graph = abac_graph_query(ctx->graph, role, principal);
183    abac_list_t *result = abac_graph_credentials(result_graph);
184
185    abac_graph_free(result_graph);
186
187    int size = abac_list_size(result);
188    if (size > 0)
189        *success = 1;
190
191    // if there is no actual path, return everything that can reach the role
192    else {
193        *success = 0;
194        abac_list_free(result);
195        result_graph = abac_graph_new();
196
197        // TODO: This can probably be better, but it now returns an
198        // approximation of a partial proof.  It returns all the attributes the
199        // principal can reach and all the attributes that will lead to a
200        // success.
201
202        /* Get all the attributes of the principal.  This calls sub-queries to
203         * flesh out the indirect proofs. */
204        result_graph = abac_graph_principal_creds(ctx->graph, principal);
205
206        /* This gets all the attributes linked to the target en route to the
207         * principal. */
208        result = abac_graph_postorder_credentials(ctx->graph, role);
209
210        /* Merge responses */
211        abac_list_foreach(result, cur,
212            abac_graph_add_credential(result_graph, cur);
213        );
214        abac_list_free(result);
215        abac_graph_derive_links(result_graph);
216
217        result = abac_graph_credentials(result_graph);
218        abac_graph_free(result_graph);
219
220        size = abac_list_size(result);
221    }
222
223    // make the array (leave space to NULL terminate it)
224    //      n.b., even if the list is empty, we still return an array that
225    //            only contains the NULL terminator
226    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
227    abac_list_foreach(result, cur,
228        credentials[i++] = cur;
229    );
230    credentials[i] = NULL;
231
232    abac_list_free(result);
233
234    return credentials;
235}
236
237/**
238 * A NULL-terminated array of all the credentials in the context.
239 */
240abac_credential_t **abac_context_credentials(abac_context_t *ctx) {
241    abac_credential_t *cred;
242    int i = 0;
243
244    assert(ctx != NULL);
245
246    abac_list_t *cred_list = abac_graph_credentials(ctx->graph);
247    int size = abac_list_size(cred_list);
248
249    abac_credential_t **credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
250    abac_list_foreach(cred_list, cred,
251        credentials[i++] = cred;
252    );
253    credentials[i] = NULL;
254
255    abac_list_free(cred_list);
256
257    return credentials;
258}
259
260/**
261 * Frees a NULL-terminated list of credentials.
262 */
263void abac_context_credentials_free(abac_credential_t **credentials) {
264    int i;
265
266    if (credentials == NULL)
267        return;
268
269    for (i = 0; credentials[i] != NULL; ++i)
270        abac_credential_free(credentials[i]);
271    free(credentials);
272}
Note: See TracBrowser for help on using the repository browser.