source: libabac/abac.c @ 94d1dae

abac0-leakabac0-meimei-idmei-rt0-nmei_rt0tvf-new-xml
Last change on this file since 94d1dae 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
Line 
1/* abac.c */
2
3#include <assert.h>
4#include <err.h>
5#include <glob.h>
6
7#include "abac.h"
8#include "abac_list.h"
9#include "abac_graph.h"
10#include "abac_util.h"
11#include "abac_verifier.h"
12
13struct _abac_context_t {
14    abac_graph_t *graph;
15};
16
17/**
18 * Init the library.
19 */
20void libabac_init(void) {
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    }
30}
31
32/**
33 * Deinit the library.
34 */
35void libabac_deinit(void) {
36    abac_verifier_deinit();
37}
38
39/**
40 * Create a new abac context.
41 */
42abac_context_t *abac_context_new(void) {
43    libabac_init();
44
45    abac_context_t *ctx = abac_xmalloc(sizeof(abac_context_t));
46    ctx->graph = abac_graph_new();
47    return ctx;
48}
49
50/**
51 * Deep copy an abac context.
52 */
53abac_context_t *abac_context_dup(abac_context_t *ctx) {
54    assert(ctx != NULL);
55
56    abac_context_t *dup = abac_xmalloc(sizeof(abac_context_t));
57    dup->graph = abac_graph_dup(ctx->graph);
58
59    return dup;
60}
61
62/**
63 * Free an abac context.
64 */
65void abac_context_free(abac_context_t *ctx) {
66    assert(ctx != NULL);
67
68    abac_graph_free(ctx->graph);
69    free(ctx);
70}
71
72/**
73 * Load an ID cert from a file.
74 */
75int abac_context_load_id_file(abac_context_t *ctx, char *filename) {
76    assert(ctx != NULL); assert(filename != NULL);
77    return abac_verifier_load_id_file(filename);
78}
79
80/**
81 * Load an ID cert from a chunk.
82 */
83int abac_context_load_id_chunk(abac_context_t *ctx, abac_chunk_t cert_chunk) {
84    assert(ctx != NULL);
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_list_t *cred_list=abac_list_new(); // could be more than 1
94    abac_credential_t *cred;
95
96    assert(ctx != NULL); assert(filename != NULL);
97
98    ret = abac_verifier_load_attribute_cert_file(filename, cred_list);
99
100    if (ret == ABAC_CERT_SUCCESS) {
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        }
110    }
111    return ret;
112}
113
114/**
115 * Load an attribute cert from a chunk.
116 */
117int abac_context_load_attribute_chunk(abac_context_t *ctx, abac_chunk_t cert_chunk) {
118    int ret, add_ret;
119    abac_list_t  *cred_list=abac_list_new(); // could be more than 1
120    abac_credential_t *cred;
121
122    assert(ctx != NULL);
123
124    ret = abac_verifier_load_attribute_cert_chunk(cert_chunk, cred_list);
125    if (ret == ABAC_CERT_SUCCESS) {
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        }
135    }
136
137    return ret;
138}
139
140#define ID_PAT "/*_ID.{der,pem}"
141#define ATTR_PAT "/*_attr.xml"
142
143/**
144 * Load a directory full of certs.
145 */
146void abac_context_load_directory(abac_context_t *ctx, char *path) {
147    char *glob_pat;
148    glob_t glob_buf;
149    int i, ret;
150
151    assert(ctx != NULL); assert(path != NULL);
152
153    int dirlen = strlen(path);
154    glob_pat = abac_xmalloc(dirlen + sizeof(ID_PAT));
155    memcpy(glob_pat, path, dirlen);
156
157    // first load ID certs
158    memcpy(glob_pat + dirlen, ID_PAT, sizeof(ID_PAT));
159    glob(glob_pat, GLOB_BRACE, 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_id_file(ctx, cert_file);
164        if (ret != ABAC_CERT_SUCCESS)
165            warnx("Couldn't load ID cert %s", cert_file);
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
175        ret = abac_context_load_attribute_file(ctx, cert_file);
176        if (ret != ABAC_CERT_SUCCESS)
177            warnx("Couldn't load attribute cert %s", cert_file);
178    }
179    globfree(&glob_buf);
180
181    free(glob_pat);
182}
183
184/**
185 * Run a query on the data in an abac context. Returns a NULL-terminated array
186 * of abac_credential_t. Success/failure in *success.
187 */
188abac_credential_t **abac_context_query(abac_context_t *ctx, char *role, char *principal, int *success) {
189    abac_credential_t **credentials = NULL, *cur;
190    int i = 0;
191
192    assert(ctx != NULL); assert(role != NULL); assert(principal != NULL); assert(success != NULL);
193
194    abac_graph_t *result_graph = abac_graph_query(ctx->graph, role, principal);
195    abac_list_t *result = abac_graph_credentials(result_graph);
196
197    abac_graph_free(result_graph);
198
199    int size = abac_list_size(result);
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);
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);
231
232        size = abac_list_size(result);
233    }
234
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;
243
244    abac_list_free(result);
245
246    return credentials;
247}
248
249/**
250 * A NULL-terminated array of all the credentials in the context.
251 */
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) {
276    int i;
277
278    if (credentials == NULL)
279        return;
280
281    for (i = 0; credentials[i] != NULL; ++i)
282        abac_credential_free(credentials[i]);
283    free(credentials);
284}
Note: See TracBrowser for help on using the repository browser.