/* abac.c using prolog */ #include #include #include #include #include "abac_internal.h" #include "abac_pl_yap.h" #include "abac_util.h" #include "abac_verifier.h" static int debug=0; struct _abac_context_t { abac_pl_t *pl; }; /** * Init the library. */ void libabac_init(void) { void libabac_deinit(void); static int has_been_init = 0; // called every time a context is created, so only do it once if (!has_been_init) { abac_verifier_init(); atexit(libabac_deinit); has_been_init = 1; } } /** * Deinit the library. */ void libabac_deinit(void) { abac_verifier_deinit(); } /** * Create a new abac context. */ abac_context_t *abac_context_new(void) { libabac_init(); abac_context_t *ctx = abac_xmalloc(sizeof(abac_context_t)); ctx->pl = abac_pl_new(); return ctx; } /** * Deep copy an abac context. -- XXX dummy stub */ abac_context_t *abac_context_dup(abac_context_t *ctx) { assert(ctx != NULL); abac_context_t *dup = abac_xmalloc(sizeof(abac_context_t)); return dup; } /** * Free an abac context. */ void abac_context_free(abac_context_t *ctx) { assert(ctx != NULL); abac_pl_free(ctx->pl); free(ctx); } /** * Load an ID cert from an abac_id_t. */ int abac_context_load_id_id(abac_context_t *ctx, abac_id_t *id) { assert(ctx != NULL); assert(id); abac_id_credential_t *id_cert=NULL; int ret = abac_verifier_load_id_id(id,&id_cert); if(id_cert) { int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert); } return ret; } /** * Load an ID cert from a file. */ int abac_context_load_id_id_file_key_file(abac_context_t *ctx, char *filename, char *keyfilename) { assert(ctx != NULL); assert(filename != NULL); assert(keyfilename!=NULL); abac_id_credential_t *id_cert=NULL; int ret = abac_verifier_load_id_file_key_file(filename,keyfilename,&id_cert); if(id_cert) { int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert); } return ret; } /** * Load an ID cert from a file, it may contain key part but not necessary. */ int abac_context_load_id_idkey_file(abac_context_t *ctx, char *filename) { assert(ctx != NULL); assert(filename != NULL); abac_id_credential_t *id_cert=NULL; int ret = abac_verifier_load_idkey_file(filename,&id_cert); if(id_cert) { int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert); } return ret; } /** * Load an ID cert from a chunk. */ int abac_context_load_id_chunk(abac_context_t *ctx, abac_chunk_t cert) { assert(ctx != NULL); abac_id_credential_t *id_cert=NULL; chunk_t cert_chunk = { cert.ptr, cert.len }; int ret=abac_verifier_load_id_chunk(cert_chunk,&id_cert); if(id_cert) { int add_ret = abac_pl_add_type_credential(ctx->pl, id_cert); } return ret; } /** * Load an attribute cert from an abac_attribute_t. */ int abac_context_load_attribute_attribute(abac_context_t *ctx, abac_attribute_t *ptr) { /* XXX */ int ret=0; return ret; } /** * Load an attribute cert from a file. */ int abac_context_load_attribute_file(abac_context_t *ctx, char *filename) { int ret, add_ret; abac_credential_t *cred=NULL; assert(ctx != NULL); assert(filename != NULL); ret = abac_verifier_load_attribute_cert_file(filename, &cred); if (ret == ABAC_CERT_SUCCESS) { add_ret = abac_pl_add_credential(ctx->pl, cred); assert(add_ret != ABAC_PL_CRED_INVALID); } return ret; } /** * Load an attribute cert from a chunk. */ int abac_context_load_attribute_chunk(abac_context_t *ctx, abac_chunk_t cert) { int ret, add_ret; abac_credential_t *cred=NULL; assert(ctx != NULL); chunk_t cert_chunk = { cert.ptr, cert.len }; ret = abac_verifier_load_attribute_cert_chunk(cert_chunk, &cred); if (ret == ABAC_CERT_SUCCESS) { add_ret = abac_pl_add_credential(ctx->pl, cred); assert(add_ret != ABAC_PL_CRED_INVALID); abac_credential_free(cred); } return ret; } #define KEY_PAT "/*_private.{der,pem}" #define ID_PAT "/*_ID.{der,pem}" #define ATTR_PAT "/*_attr.der" #define IDKEY_PAT "/*_IDKEY.{der,pem}" char *_make_key_filename(char *cert_file) { char *p=strstr(cert_file,"_ID."); char *head=strndup(cert_file,p-cert_file); char *tail=p+4; char *keyfile=NULL; asprintf(&keyfile,"%s_private.%s",head,tail); free(head); return keyfile; } /** * Load a directory full of certs. */ void abac_context_load_directory(abac_context_t *ctx, char *path) { char *glob_pat, *key_pat; glob_t glob_buf; int i, ret; assert(ctx != NULL); assert(path != NULL); int dirlen = strlen(path); /* make sure pick the larger one */ glob_pat = abac_xmalloc(dirlen + sizeof(IDKEY_PAT)); memcpy(glob_pat, path, dirlen); // first load ID certs memcpy(glob_pat + dirlen, ID_PAT, sizeof(ID_PAT)); glob(glob_pat, GLOB_BRACE, NULL, &glob_buf); // TODO check for error for (i = 0; i < glob_buf.gl_pathc; ++i) { /* blah_ID.pem */ char *cert_file = glob_buf.gl_pathv[i]; /* blah_private.pem */ char *key_file=_make_key_filename(cert_file); if(debug) { printf("--> ID cert... %s\n", cert_file); printf("--> KEY cert... %s\n", key_file); } ret = abac_context_load_id_id_file_key_file(ctx, cert_file, key_file); if (ret != ABAC_CERT_SUCCESS) warnx("Couldn't load ID cert %s", cert_file); } globfree(&glob_buf); // first load IDKEY certs memcpy(glob_pat + dirlen, IDKEY_PAT, sizeof(IDKEY_PAT)); glob(glob_pat, GLOB_BRACE, NULL, &glob_buf); // TODO check for error for (i = 0; i < glob_buf.gl_pathc; ++i) { /* blah_IDKEY.pem */ char *certkey_file = glob_buf.gl_pathv[i]; if(debug) { printf("--> IDKEY certkey... %s\n", certkey_file); } ret = abac_context_load_id_idkey_file(ctx, certkey_file); if (ret != ABAC_CERT_SUCCESS) warnx("Couldn't load ID/KEY IDKEY cert %s", certkey_file); } globfree(&glob_buf); memcpy(glob_pat + dirlen, ATTR_PAT, sizeof(ATTR_PAT)); glob(glob_pat, 0, NULL, &glob_buf); // TODO check for error for (i = 0; i < glob_buf.gl_pathc; ++i) { char *cert_file = glob_buf.gl_pathv[i]; if(debug) printf("--> attr file... %s\n", cert_file); ret = abac_context_load_attribute_file(ctx, cert_file); if (ret != ABAC_CERT_SUCCESS) warnx("Couldn't load attribute cert %s", cert_file); if(debug) printf("Loaded.. %s\n", cert_file); } globfree(&glob_buf); free(glob_pat); } /** * Run a query on the data in an abac context. Returns a NULL-terminated array * of abac_credential_t. Success/failure in *success. * queryfor(either role or oset), with(either keyid or object type) */ abac_credential_t **abac_context_query(abac_context_t *ctx, char *queryfor, char *with, int *success) { if(debug) { printf("abac_context_query about(%s) with(%s)\n", queryfor, with); } abac_credential_t **credentials = NULL, *cur; assert(ctx != NULL); assert(queryfor != NULL); assert(with != NULL); assert(success != NULL); abac_stack_t *result = abac_pl_query(ctx->pl, queryfor, with); int size = abac_stack_size(result); if (size > 0) { *success = 1; } else { // XXX NOT SURE YET.. // return partial proof *success = 0; } // make the array (leave space to NULL terminate it) // n.b., even if the list is empty, we still return an array that // only contains the NULL terminator credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1)); int i = 0; if(size) { while(ipl); int size = abac_stack_size(result); // make the array (leave space to NULL terminate it) // n.b., even if the list is empty, we still return an array that // only contains the NULL terminator credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1)); int i = 0; if(size) { while(ipl); int size = abac_stack_size(result); // make the array (leave space to NULL terminate it) // n.b., even if the list is empty, we still return an array that // only contains the NULL terminator principals = abac_xmalloc(sizeof(abac_id_credential_t *) * (size + 1)); int i = 0; if(size) { while(i