#include #include #include #include #include "abac.h" #include "abac_graph.h" #include "abac_util.h" #include "abac_verifier.h" struct _abac_context_t { abac_graph_t *graph; }; /** * Init the library. */ void libabac_init(void) { abac_verifier_init(); } /** * Deinit the library. */ void libabac_deinit(void) { abac_verifier_deinit(); } /** * Create a new abac context. */ abac_context_t *abac_context_new(void) { abac_context_t *ctx = abac_xmalloc(sizeof(abac_context_t)); ctx->graph = abac_graph_new(); return ctx; } /** * Deep copy an abac context. */ abac_context_t *abac_context_dup(abac_context_t *ctx) { assert(ctx != NULL); abac_context_t *dup = abac_xmalloc(sizeof(abac_context_t)); dup->graph = abac_graph_dup(ctx->graph); return dup; } /** * Free an abac context. */ void abac_context_free(abac_context_t *ctx) { assert(ctx != NULL); abac_graph_free(ctx->graph); free(ctx); } /** * Load an ID cert from a file. */ int abac_context_load_id_file(abac_context_t *ctx, char *filename) { assert(ctx != NULL); assert(filename != NULL); return abac_verifier_load_id_file(filename); } /** * Load an ID cert from a chunk. */ int abac_context_load_id_chunk(abac_context_t *ctx, abac_chunk_t cert) { assert(ctx != NULL); chunk_t cert_chunk = { cert.ptr, cert.len }; return abac_verifier_load_id_chunk(cert_chunk); } /** * 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; assert(ctx != NULL); assert(filename != NULL); ret = abac_verifier_load_attribute_cert_file(filename, &cred); if (ret == ABAC_CERT_SUCCESS) { add_ret = abac_graph_add_credential(ctx->graph, cred); assert(add_ret != ABAC_GRAPH_CRED_INVALID); abac_credential_free(cred); } 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; 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_graph_add_credential(ctx->graph, cred); assert(add_ret != ABAC_GRAPH_CRED_INVALID); abac_credential_free(cred); } return ret; } #define ID_PAT "/*_ID.der" #define ATTR_PAT "/*_attr.der" /** * Load a directory full of certs. */ void abac_context_load_directory(abac_context_t *ctx, char *path) { char *glob_pat; glob_t glob_buf; int i, ret; assert(ctx != NULL); assert(path != NULL); int dirlen = strlen(path); glob_pat = abac_xmalloc(dirlen + sizeof(ATTR_PAT)); memcpy(glob_pat, path, dirlen); // first load ID certs memcpy(glob_pat + dirlen, ID_PAT, sizeof(ID_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]; ret = abac_context_load_id_file(ctx, cert_file); if (ret != ABAC_CERT_SUCCESS) warnx("Couldn't load ID cert %s\n", cert_file); } globfree(&glob_buf); // then load attr certs 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]; ret = abac_context_load_attribute_file(ctx, cert_file); if (ret != ABAC_CERT_SUCCESS) warnx("Couldn't load attribute cert %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. */ abac_credential_t **abac_context_query(abac_context_t *ctx, char *role, char *principal, int *success) { abac_credential_t **credentials = NULL, *cur; int i = 0; assert(ctx != NULL); assert(role != NULL); assert(principal != NULL); assert(success != NULL); abac_graph_t *result_graph = abac_graph_query(ctx->graph, role, principal); abac_list_t *result = abac_graph_credentials(result_graph); abac_graph_free(result_graph); int size = abac_list_size(result); if (size > 0) *success = 1; // if there is no actual path, return everything that can reach the role else { *success = 0; abac_list_free(result); result = abac_graph_postorder_credentials(ctx->graph, role); size = abac_list_size(result); } if (size > 0) { // make the array (leave space to NULL terminate it) credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1)); abac_list_foreach(result, cur, credentials[i++] = cur; ); credentials[i] = NULL; } abac_list_free(result); return credentials; } /** * Frees the result of an abac query. */ void abac_context_query_free(abac_credential_t **credentials) { int i; if (credentials == NULL) return; for (i = 0; credentials[i] != NULL; ++i) abac_credential_free(credentials[i]); free(credentials); }