source: libabac/abac.c @ 461541a

abac0-leakabac0-meimei-idmei-rt0-nmei_rt0tvf-new-xml
Last change on this file since 461541a was 461541a, checked in by Mei <mei@…>, 11 years ago

1) updated original rt0 to remove libstrongswan dependency

a) identity credential being made/accessed with openssl api calls

(X509/EVP_PKEY pem)

b) attribute credential being made/access via xmlsec1 (custom XML

structure)

2) refactored libcreddy into libabac and now one ABAC namespace for

libabac

3) added attribute_rule suboption to creddy's attribute as another way

to insert access rule

4) added some regression tests into example directory
5) updated some docs.

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