source: libabac/abac.c @ b73c5d05

abac0-leakabac0-meimei-idtvf-new-xml
Last change on this file since b73c5d05 was 4721618, checked in by Mei <mei@…>, 11 years ago

1) tested out python and perl test scripts along with

abac_chunk_t calls in libabac's abac.hh

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