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
Line 
1/* abac.c */
2
3#include <assert.h>
4#include <err.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <unistd.h>
8#include <dirent.h>
9
10#include "abac.h"
11#include "abac_list.h"
12#include "abac_graph.h"
13#include "abac_util.h"
14#include "abac_verifier.h"
15
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
20struct _abac_context_t {
21/* list of principal id credentials, abac_id_cert_t */
22    abac_list_t *id_certs;
23    abac_graph_t *graph;
24};
25
26/**
27 * Init the library.
28 */
29void libabac_init(void) {
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    }
39}
40
41/**
42 * Deinit the library.
43 */
44void libabac_deinit(void) {
45    abac_verifier_deinit();
46}
47
48/**
49 * Create a new abac context.
50 */
51abac_context_t *abac_context_new(void) {
52    libabac_init();
53
54    abac_context_t *ctx = abac_xmalloc(sizeof(abac_context_t));
55    ctx->graph = abac_graph_new();
56    ctx->id_certs=abac_list_new();
57    return ctx;
58}
59
60/**
61 * Deep copy an abac context.
62 */
63abac_context_t *abac_context_dup(abac_context_t *ctx) {
64    assert(ctx != NULL);
65   
66    abac_context_t *dup = abac_xmalloc(sizeof(abac_context_t));
67    dup->graph = abac_graph_dup(ctx->graph);
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    );
74
75    return dup;
76}
77
78/**
79 * Free an abac context.
80 */
81void abac_context_free(abac_context_t *ctx) {
82    assert(ctx != NULL);
83
84    abac_graph_free(ctx->graph);
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);
91    free(ctx);
92}
93
94/**
95 * Load an ID cert from a file.
96 */
97int abac_context_load_id_file(abac_context_t *ctx, char *filename) {
98    assert(ctx != NULL); assert(filename != NULL);
99    return abac_verifier_load_id_file(ctx->id_certs,filename);
100}
101
102/**
103 * Load an ID cert from a chunk.
104 */
105int abac_context_load_id_chunk(abac_context_t *ctx, abac_chunk_t cert_chunk) {
106    assert(ctx != NULL);
107    return abac_verifier_load_id_chunk(ctx->id_certs,cert_chunk);
108}
109
110/**
111 * Load an attribute cert from a file.
112 */
113int abac_context_load_attribute_file(abac_context_t *ctx, char *filename) {
114    int ret, add_ret;
115    abac_list_t *cred_list=abac_list_new(); // could be more than 1
116    abac_credential_t *cred;
117
118    assert(ctx != NULL); assert(filename != NULL);
119
120    ret = abac_verifier_load_attribute_cert_file(ctx->id_certs, filename, cred_list);
121
122    if (ret == ABAC_CERT_SUCCESS) {
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        }
132    }
133    return ret;
134}
135
136/**
137 * Load an attribute cert from a chunk.
138 */
139int abac_context_load_attribute_chunk(abac_context_t *ctx, abac_chunk_t cert_chunk) {
140    int ret, add_ret;
141    abac_list_t  *cred_list=abac_list_new(); // could be more than 1
142    abac_credential_t *cred;
143
144    assert(ctx != NULL);
145
146    ret = abac_verifier_load_attribute_cert_chunk(ctx->id_certs, cert_chunk, cred_list);
147    if (ret == ABAC_CERT_SUCCESS) {
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        }
157    }
158
159    return ret;
160}
161
162#define ID_PAT "/*_ID.{der,pem}"
163#define ATTR_PAT "/*_attr.xml"
164
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
175/**
176 * Load a directory full of certs.
177 */
178void abac_context_load_directory(abac_context_t *ctx, char *path) {
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");
199}
200
201/**
202 * Run a query on the data in an abac context. Returns a NULL-terminated array
203 * of abac_credential_t. Success/failure in *success.
204 */
205abac_credential_t **abac_context_query(abac_context_t *ctx, char *role, char *principal, int *success) {
206    abac_credential_t **credentials = NULL, *cur;
207    int i = 0;
208
209    assert(ctx != NULL); assert(role != NULL); assert(principal != NULL); assert(success != NULL);
210
211    abac_graph_t *result_graph = abac_graph_query(ctx->graph, role, principal);
212    abac_list_t *result = abac_graph_credentials(result_graph);
213
214    abac_graph_free(result_graph);
215
216    int size = abac_list_size(result);
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);
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);
248
249        size = abac_list_size(result);
250    }
251
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;
260
261    abac_list_free(result);
262
263    return credentials;
264}
265
266
267/**
268 * A NULL-terminated array of all the credentials in the context.
269 */
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
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
298    return credentials;
299}
300
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
327/**
328 * Frees a NULL-terminated list of credentials.
329 */
330void abac_context_credentials_free(abac_credential_t **credentials) {
331    int i;
332
333    if (credentials == NULL)
334        return;
335
336    for (i = 0; credentials[i] != NULL; ++i)
337        abac_credential_free(credentials[i]);
338    free(credentials);
339}
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.