source: libabac/abac.c @ e97d2e2

mei_rt2_fix_1
Last change on this file since e97d2e2 was e3c7769, checked in by Mei <mei@…>, 12 years ago

1) wrap up java interface with swig/jni/abac linkup
2) java regression tests
3) update doc related to new java implmentation

  • Property mode set to 100644
File size: 17.3 KB
Line 
1
2/* abac.c using prolog */
3
4#include <assert.h>
5#include <err.h>
6#include <glob.h>
7
8#include <chunk.h>
9
10#include "abac_internal.h"
11
12#include "abac_pl_yap.h"
13#include "abac_util.h"
14#include "abac_verifier.h"
15
16static int debug=0;
17
18struct _abac_context_t {
19    abac_pl_t *pl;
20};
21
22/**
23 * Init the library.
24 */
25void libabac_init(void) {
26
27    if(debug) fprintf(stderr, "libabac_init, calling init\n");
28    void libabac_deinit(void);
29    static int has_been_init = 0;
30
31    // called every time a context is created, so only do it once
32    if (!has_been_init) {
33        abac_verifier_init();
34        atexit(libabac_deinit);
35        has_been_init = 1;
36        } else {
37           if(debug) fprintf(stderr, "libabac_init, can only be called once\n");
38    }
39}
40
41/**
42 * Deinit the library.
43 */
44static int has_been_deinit = 0;
45void libabac_deinit(void) {
46    if(debug) fprintf(stderr, "libabac_deinit, calling take down (%d)\n", has_been_deinit);
47    if(!has_been_deinit) {
48        abac_verifier_deinit();
49        has_been_deinit = 1;
50        } else {
51           if(debug) fprintf(stderr, "libabac_deinit, can only be called once\n");
52    }
53}
54
55/**
56 * Create a new abac context.
57 */
58abac_context_t *abac_context_new(void) {
59    libabac_init();
60
61    abac_context_t *ctx = abac_xmalloc(sizeof(abac_context_t));
62    ctx->pl = abac_pl_new();
63    return ctx;
64}
65
66/**
67 * Deep copy an abac context. -- XXX dummy stub
68 */
69abac_context_t *abac_context_dup(abac_context_t *ctx) {
70    assert(ctx != NULL);
71    abac_context_t *dup = abac_xmalloc(sizeof(abac_context_t));
72    return dup;
73}
74
75/**
76 * Free an abac context.
77 */
78void abac_context_free(abac_context_t *ctx) {
79    assert(ctx != NULL);
80    abac_pl_free(ctx->pl);
81    free(ctx);
82}
83
84/* This is only used for swig/jni/abac setup, called from
85abac.hh's free_context_now(). Used by other setup actually
86could result in segfaults in libstrongswan if not careful */
87void abac_context_free_now(abac_context_t *ctx) {
88    assert(ctx != NULL);
89    abac_pl_free(ctx->pl);
90    free(ctx);
91    libabac_deinit();
92}
93
94/**
95 * Load an ID cert from an abac_id_t.
96 */
97int abac_context_load_id_id(abac_context_t *ctx, abac_id_t *id) {
98    assert(ctx != NULL); assert(id);
99    abac_id_credential_t *id_cert=NULL;
100    int ret = abac_verifier_load_id_id(id,&id_cert);
101    if(id_cert) {
102        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
103    }
104    return ret;
105}
106
107/**
108 * Load an ID cert from a file.
109 */
110int abac_context_load_id_id_file_key_file(abac_context_t *ctx, char *filename,
111char *keyfilename)
112{
113    assert(ctx != NULL); assert(filename != NULL); assert(keyfilename!=NULL);
114    abac_id_credential_t *id_cert=NULL;
115    int ret = abac_verifier_load_id_file_key_file(filename,keyfilename,&id_cert);
116    if(id_cert) {
117        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
118    }
119    return ret;
120}
121
122int abac_context_load_id_enc_id_file_key_file(abac_context_t *ctx, char *filename,
123char *keyfilename, char *pfile)
124{
125    assert(ctx != NULL); assert(filename != NULL); assert(keyfilename!=NULL);
126    abac_id_credential_t *id_cert=NULL;
127    int ret = abac_verifier_load_enc_id_file_key_file(filename,keyfilename, pfile, &id_cert);
128    if(id_cert) {
129        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
130    }
131    return ret;
132}
133
134/**
135 * Load an ID cert from a file, it may contain key part but not necessary.
136 */
137int abac_context_load_id_idkey_file(abac_context_t *ctx, char *filename) {
138    assert(ctx != NULL); assert(filename != NULL); 
139    abac_id_credential_t *id_cert=NULL;
140    int ret = abac_verifier_load_idkey_file(filename,&id_cert);
141    if(id_cert) {
142        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
143    }
144    return ret;
145}
146
147/**
148 * Load an ID cert from a file, it may contain encrypted key part but not necessary.
149 */
150int abac_context_load_id_enc_idkey_file(abac_context_t *ctx, char *filename, char *pfile) {
151    assert(ctx != NULL); assert(filename != NULL); 
152    abac_id_credential_t *id_cert=NULL;
153    int ret = abac_verifier_load_enc_idkey_file(filename, pfile,&id_cert);
154    if(id_cert) {
155        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
156    }
157    return ret;
158}
159
160/**
161 * Load an ID cert from a chunk.
162 */
163int abac_context_load_id_chunk(abac_context_t *ctx, abac_chunk_t cert) {
164    assert(ctx != NULL);
165    abac_id_credential_t *id_cert=NULL;
166    chunk_t cert_chunk = { cert.ptr, cert.len };
167    int ret=abac_verifier_load_id_chunk(cert_chunk,&id_cert);
168    if(id_cert) {
169        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
170    }
171    return ret;
172}
173
174
175/**
176 * Load an ID cert and privkey from chunks.
177 */
178int abac_context_load_id_privkey_chunk(abac_context_t *ctx, abac_chunk_t cert, abac_chunk_t privkey) {
179    assert(ctx != NULL);
180    abac_id_credential_t *id_cert=NULL;
181    chunk_t cert_chunk = { cert.ptr, cert.len };
182/*A HACK/SWIG, this is to work around the swig's stub that seems to
183  mess up the transformation from abac_chunk_t to chunk_t and calling of
184  load_id_chunks to here */
185/* BAD,  chunk_t privkey_chunk = { privkey.ptr, privkey.len }; */
186    chunk_t privkey_chunk = { strndup(privkey.ptr,privkey.len), privkey.len };
187/* another way,
188    chunk_t tmp = { privkey.ptr, privkey.len };
189    char *ptr = abac_xmalloc(sizeof(unsigned char) * privkey.len);
190    chunk_t privkey_chunk = chunk_create_clone(ptr,tmp);
191*/
192    if(debug) {
193        fprintf(stderr, "abac_context_load_id_privkey_chunk, privkey ptr, loc(%d)\n",
194                                                           (int)privkey.ptr);
195        fprintf(stderr, "abac_context_load_id_privkey_chunk, privkey_chunk ptr, loc(%d)\n",
196                                                           (int)privkey_chunk.ptr);
197    }
198    int ret=abac_verifier_load_id_privkey_chunk(cert_chunk, privkey_chunk, &id_cert);
199    if(id_cert) {
200        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
201    }
202    return ret;
203}
204
205/**
206 * Load an ID cert and privkey from chunks.
207 */
208int abac_context_load_id_enc_privkey_chunk(abac_context_t *ctx,
209abac_chunk_t cert, abac_chunk_t privkey, char *pfile) {
210    assert(ctx != NULL);
211    abac_id_credential_t *id_cert=NULL;
212    chunk_t cert_chunk = { cert.ptr, cert.len };
213/*A HACK/SWIG, this is to work around the swig's stub that seems to
214  mess up the transformation from abac_chunk_t to chunk_t and calling of
215  load_id_chunks to here */
216/* BAD,  chunk_t privkey_chunk = { privkey.ptr, privkey.len }; */
217    chunk_t privkey_chunk = { strndup(privkey.ptr,privkey.len), privkey.len };
218    int ret=abac_verifier_load_id_enc_privkey_chunk(cert_chunk, privkey_chunk, pfile, &id_cert);
219
220    if(id_cert) {
221        int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert);
222    }
223    return ret;
224}
225
226
227
228/**
229 * Load an attribute cert from an abac_attribute_t.
230 */
231int abac_context_load_attribute_attribute(abac_context_t *ctx, abac_attribute_t *ptr)
232{
233    int ret, add_ret;
234    abac_credential_t *cred=NULL;
235
236    assert(ctx != NULL);
237
238    ret = abac_verifier_load_attribute_cert_attribute(ptr, &cred);
239    if (ret == ABAC_CERT_SUCCESS) {
240        add_ret = abac_pl_add_credential(ctx->pl, cred);
241        assert(add_ret != ABAC_PL_CRED_INVALID);
242    }
243
244    return ret;
245
246}
247
248/**
249 * Load an attribute cert from a file.
250 */
251int abac_context_load_attribute_file(abac_context_t *ctx, char *filename) {
252    int ret, add_ret;
253    abac_credential_t *cred=NULL;
254
255    assert(ctx != NULL); assert(filename != NULL);
256
257    ret = abac_verifier_load_attribute_cert_file(filename, &cred);
258    if (ret == ABAC_CERT_SUCCESS) {
259        add_ret = abac_pl_add_credential(ctx->pl, cred);
260        assert(add_ret != ABAC_PL_CRED_INVALID);
261    }
262
263    return ret;
264}
265
266/**
267 * Load an attribute cert from a chunk.
268 */
269int abac_context_load_attribute_chunk(abac_context_t *ctx, abac_chunk_t cert) {
270    int ret, add_ret;
271    abac_credential_t *cred=NULL;
272
273    assert(ctx != NULL);
274
275    chunk_t cert_chunk = { cert.ptr, cert.len };
276
277    ret = abac_verifier_load_attribute_cert_chunk(cert_chunk, &cred);
278    if (ret == ABAC_CERT_SUCCESS) {
279        add_ret = abac_pl_add_credential(ctx->pl, cred);
280        assert(add_ret != ABAC_PL_CRED_INVALID);
281    }
282
283    return ret;
284}
285
286#define KEY_PAT "/*_private.{der,pem}"
287#define ID_PAT "/*_ID.{der,pem}"
288#define ATTR_PAT "/*_attr.der"
289#define IDKEY_PAT "/*_IDKEY.{der,pem}"
290
291char *_make_key_filename(char *cert_file)
292{
293    char *p=strstr(cert_file,"_ID.");
294    char *head=strndup(cert_file,p-cert_file);
295    char *tail=p+4;
296    char *keyfile=NULL;
297    asprintf(&keyfile,"%s_private.%s",head,tail);
298    free(head);
299    return keyfile;
300}
301
302/**
303 * Load a directory full of principal certs.
304 */
305void abac_context_load_principals(abac_context_t *ctx, char *path) {
306    char *glob_pat, *key_pat;
307    glob_t glob_buf;
308    int i, ret;
309
310    assert(ctx != NULL); assert(path != NULL);
311
312    int dirlen = strlen(path);
313
314    /* make sure pick the larger one */
315    glob_pat = abac_xmalloc(dirlen + sizeof(IDKEY_PAT));
316    memcpy(glob_pat, path, dirlen);
317
318    // load ID certs
319    memcpy(glob_pat + dirlen, ID_PAT, sizeof(ID_PAT));
320    glob(glob_pat, GLOB_BRACE, NULL, &glob_buf); // TODO check for error
321    for (i = 0; i < glob_buf.gl_pathc; ++i) {
322        /* blah_ID.pem */
323        char *cert_file = glob_buf.gl_pathv[i];
324        /* blah_private.pem */
325        char *key_file=_make_key_filename(cert_file);
326        if(debug) {
327            fprintf(stderr,"--> ID cert... %s\n", cert_file);
328            fprintf(stderr,"--> KEY cert... %s\n", key_file);
329        }
330        ret = abac_context_load_id_id_file_key_file(ctx, cert_file, key_file);
331        if (ret != ABAC_CERT_SUCCESS)
332            warnx("Couldn't load ID cert %s", cert_file);
333    }
334    globfree(&glob_buf);
335
336    // next load IDKEY certs
337    memcpy(glob_pat + dirlen, IDKEY_PAT, sizeof(IDKEY_PAT));
338    glob(glob_pat, GLOB_BRACE, NULL, &glob_buf); // TODO check for error
339    for (i = 0; i < glob_buf.gl_pathc; ++i) {
340        /* blah_IDKEY.pem */
341        char *certkey_file = glob_buf.gl_pathv[i];
342        if(debug) fprintf(stderr, "--> IDKEY certkey... %s\n", certkey_file);
343        ret = abac_context_load_id_idkey_file(ctx, certkey_file);
344        if (ret != ABAC_CERT_SUCCESS)
345            warnx("Couldn't load ID/KEY IDKEY cert %s", certkey_file);
346    }
347    globfree(&glob_buf);
348
349    free(glob_pat);
350}
351
352/**
353 * Load a directory full of certs.
354 */
355void abac_context_load_directory(abac_context_t *ctx, char *path) {
356    char *glob_pat, *key_pat;
357    glob_t glob_buf;
358    int i, ret;
359
360    abac_context_load_principals(ctx,path);
361    int dirlen = strlen(path);
362
363    /* make sure pick the larger one */
364    glob_pat = abac_xmalloc(dirlen + sizeof(IDKEY_PAT));
365    memcpy(glob_pat, path, dirlen);
366
367    memcpy(glob_pat + dirlen, ATTR_PAT, sizeof(ATTR_PAT));
368    glob(glob_pat, 0, NULL, &glob_buf); // TODO check for error
369    for (i = 0; i < glob_buf.gl_pathc; ++i) {
370        char *cert_file = glob_buf.gl_pathv[i];
371
372        if(debug) fprintf(stderr,"--> attr file... (%s)\n", cert_file);
373        ret = abac_context_load_attribute_file(ctx, cert_file);
374        if (ret != ABAC_CERT_SUCCESS)
375            warnx("Couldn't load attribute cert --%s", cert_file);
376        if(debug) fprintf(stderr,"Loaded.. (%s)\n", cert_file);
377    }
378    globfree(&glob_buf);
379
380    free(glob_pat);
381}
382
383/**
384 * Run a query on the data in an abac context. Returns a NULL-terminated array
385 * of abac_credential_t. Success/failure in *success.
386 * queryfor(either role or oset), with(either keyid or object type)
387 */
388abac_credential_t **abac_context_query(abac_context_t *ctx, char *queryfor, char *with, int *success) {
389    if(debug) fprintf(stderr,"abac_context_query about(%s) with(%s)\n", queryfor, with);
390    abac_credential_t **credentials = NULL, *cur;
391    assert(ctx != NULL); assert(queryfor != NULL);
392    assert(with != NULL); assert(success != NULL);
393
394    abac_stack_t *result = abac_pl_query(ctx->pl, queryfor, with);
395
396    int size = abac_stack_size(result);
397    if (size > 0) {
398       if(!abac_pl_returning_partial(ctx->pl))
399            *success = 1;
400            else *success = 0;
401    } else {
402        *success = 0;
403    }
404
405    // make the array (leave space to NULL terminate it)
406    //      n.b., even if the list is empty, we still return an array that
407    //            only contains the NULL terminator
408    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
409    int i = 0;
410    if(size) {
411        while(i<size) { 
412            cur=(abac_credential_t *) abac_stack_pop(result);
413            credentials[i++] = cur;
414        } 
415    }
416    credentials[i] = NULL;
417
418    if(result)
419        abac_stack_free(result);
420
421    return credentials;
422}
423
424/**
425 * Run a repeated query on the data in an abac context to get the next
426 * solution proof. Returns a NULL-terminated array
427 * of abac_credential_t. Success/failure in *success.
428 */
429abac_credential_t **abac_context_query_again(abac_context_t *ctx, int *success)
430{
431    if(debug) fprintf(stderr,"abac_context_query_again\n");
432    abac_credential_t **credentials = NULL, *cur;
433    assert(ctx != NULL);
434    assert(success != NULL);
435
436    abac_stack_t *result = abac_pl_query_again(ctx->pl);
437
438    int size = abac_stack_size(result);
439    if (size > 0) {
440        *success = 1;
441        } else {
442            *success = 0;
443    }
444
445    // make the array (leave space to NULL terminate it)
446    //      n.b., even if the list is empty, we still return an array that
447    //            only contains the NULL terminator
448    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
449    int i = 0;
450    if(size) {
451        while(i<size) { 
452            cur=(abac_credential_t *) abac_stack_pop(result);
453            credentials[i++] = cur;
454        } 
455    }
456    credentials[i] = NULL;
457
458    if(result)
459        abac_stack_free(result);
460
461    return credentials;
462}
463
464
465abac_credential_t **abac_context_query_with_structure(abac_context_t *ctx,
466abac_aspect_t *queryfor, abac_aspect_t *with, int *success)
467{
468    if(debug) fprintf(stderr,"abac_context_query_with_structure\n");
469    abac_credential_t **credentials = NULL, *cur;
470    assert(ctx != NULL); assert(queryfor != NULL);
471    assert(with != NULL); assert(success != NULL);
472
473    abac_stack_t *result = abac_pl_query_with_structure(ctx->pl, queryfor, with);
474
475    int size = abac_stack_size(result);
476    if (size > 0) {
477        *success = 1;
478    } else {
479    // XXX NOT SURE YET..
480    // return partial proof
481        *success = 0;
482    }
483
484    // make the array (leave space to NULL terminate it)
485    //      n.b., even if the list is empty, we still return an array that
486    //            only contains the NULL terminator
487    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
488    int i = 0;
489    if(size) {
490        while(i<size) { 
491            cur=(abac_credential_t *) abac_stack_pop(result);
492            credentials[i++] = cur;
493        } 
494    }
495    credentials[i] = NULL;
496
497    if(result)
498        abac_stack_free(result);
499
500    return credentials;
501}
502
503/**
504 * A NULL-terminated array of all the credentials in the context.
505 */
506abac_credential_t **abac_context_credentials(abac_context_t *ctx) {
507    abac_credential_t **credentials = NULL, *cur;
508    assert(ctx != NULL);
509
510    abac_stack_t *result = abac_pl_credentials(ctx->pl);
511    int size = abac_stack_size(result);
512
513    // make the array (leave space to NULL terminate it)
514    //      n.b., even if the list is empty, we still return an array that
515    //            only contains the NULL terminator
516    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
517    int i = 0;
518    if(size) {
519        while(i<size) { 
520            cur=(abac_credential_t *) abac_stack_pop(result);
521            /* if not in there yet, add into it */
522            credentials[i++] = cur;
523        } 
524    }
525    credentials[i] = NULL;
526
527    if(result)
528        abac_stack_free(result);
529    return credentials;
530}
531
532/**
533 * Frees a NULL-terminated list of credentials.
534 */
535void abac_context_credentials_free(abac_credential_t **credentials) {
536    int i;
537
538    if (credentials == NULL)
539        return;
540
541    for (i = 0; credentials[i] != NULL; ++i)
542        abac_credential_free(credentials[i]);
543    free(credentials);
544}
545
546/**
547 * A NULL-terminated array of all the principals in the context.
548 */
549abac_id_credential_t **abac_context_principals(abac_context_t *ctx) {
550    abac_id_credential_t **principals = NULL, *cur;
551    assert(ctx != NULL);
552
553    abac_stack_t *result = abac_pl_principals(ctx->pl);
554
555    int size = abac_stack_size(result);
556
557    // make the array (leave space to NULL terminate it)
558    //      n.b., even if the list is empty, we still return an array that
559    //            only contains the NULL terminator
560    principals = abac_xmalloc(sizeof(abac_id_credential_t *) * (size + 1));
561    int i = 0;
562    if(size) {
563        while(i<size) { 
564            cur=(abac_id_credential_t *) abac_stack_pop(result);
565            /* if not in there yet, add into it */
566            principals[i++] = cur;
567        } 
568    }
569    principals[i] = NULL;
570
571    if(result)
572        abac_stack_free(result);
573    return principals;
574}
575
576/**
577 * Frees a NULL-terminated list of principals.
578 */
579void abac_context_principals_free(abac_id_credential_t **principals) {
580    int i;
581
582    if (principals == NULL)
583        return;
584
585    for (i = 0; principals[i] != NULL; ++i)
586        abac_id_credential_free(principals[i]);
587    free(principals);
588}
589
590/**
591 *
592 */
593abac_id_credential_t *abac_context_principal_lookup(abac_context_t *ctx, char *name)
594{
595    assert(ctx != NULL);
596    abac_id_credential_t *principal=abac_id_credential_lookup(name);
597    return principal;
598}
599
600void abac_context_set_no_partial_proof(abac_context_t *ctx)
601{ abac_pl_set_no_partial(ctx->pl); }
602
603void abac_context_set_want_partial_proof(abac_context_t *ctx)
604{ abac_pl_set_want_partial(ctx->pl); }
605
Note: See TracBrowser for help on using the repository browser.