source: libabac/abac.c @ ba6027a

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

1) modified code all around to add support for encrypted private key for

ID credential

2) add new abac_key_t structure (abac_key.c)
3) add new keycheck option to creddy
4) add 2 new test suites

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