source: libabac/abac.c @ bec30b5

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

1) change abac_context_load_directory to check on every regular files

and try to extract id id/privkey and then attribute in turn.

2) move id_certs to be context based instead of shared globally

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