/** ** abac_attribute.c **/ #include #include #include #include #include #include "abac_internal.h" #include "abac_util.h" #define SHA1_LENGTH 40 extern char* abac_encode_string(char*); static int debug=0; struct _abac_attribute_t { abac_id_t *issuer_id; abac_aspect_t *head; abac_aspect_t *tail; int validity; certificate_t *cert; // NULL until baked certificate_t *issuer_cert; int refcount; }; /********************************************************************/ static char *_get_cred_encoding(abac_attribute_t *ptr) { char *encoding=NULL; /* must have a head aspect and tail aspect */ assert(ptr->head != NULL); assert(ptr->tail != NULL); char *head_string=abac_aspect_typed_string_with_condition(ptr->head); char *tail_string=abac_aspect_typed_string_with_condition(ptr->tail); asprintf(&encoding,"%s<-%s", head_string,tail_string); char* base64_encoding=abac_encode_string(encoding); if(debug) printf("XXX abac_attribute_bake (%s)\n", encoding); free(encoding); free(head_string); free(tail_string); return base64_encoding; } /********************************************************************/ abac_attribute_t *abac_attribute_new(abac_id_t *issuer, certificate_t *cert, certificate_t *issuer_cert) { abac_attribute_t *ptr = abac_xmalloc(sizeof(abac_attribute_t)); ptr->issuer_id = abac_id_dup(issuer); ptr->head = NULL; ptr->tail = NULL; ptr->validity= 365 * 86400; // default ptr->cert=cert; // already baked.. ptr->issuer_cert=issuer_cert; ptr->refcount=1; return ptr; } // validity is measured in seconds (as of 0.2.0) int abac_attribute_create(abac_attribute_t **ret, abac_aspect_t *head, abac_aspect_t *tail, int validity) { abac_id_t *issuer_id=abac_aspect_get_issuer_id(head); char *name=abac_aspect_aspect_name(head); if (abac_id_privkey(issuer_id) == NULL) return ABAC_ATTRIBUTE_ISSUER_NOKEY; if (!abac_validate_clean_aspect_name(name)) return ABAC_ATTRIBUTE_INVALID_ROLE; if (validity < 0) return ABAC_ATTRIBUTE_INVALID_VALIDITY; abac_attribute_t *ptr = abac_xmalloc(sizeof(abac_attribute_t)); ptr->issuer_id = abac_id_dup(issuer_id); ptr->head = abac_aspect_dup(head); ptr->tail = (tail!=NULL) ? abac_aspect_dup(tail):NULL; ptr->validity=(validity==0?(365 * 86400):validity); // NULL until baked ptr->cert=NULL; ptr->issuer_cert=NULL; ptr->refcount=1; *ret = ptr; return ABAC_ATTRIBUTE_SUCCESS; } // validity is measured in seconds (as of 0.2.0) int abac_attribute_create_creddy(abac_attribute_t **ret, abac_id_t *issuer, abac_aspect_t *head_aspect, abac_aspect_t *tail_aspect, char *name, int validity) { if (abac_id_privkey(issuer) == NULL) return ABAC_ATTRIBUTE_ISSUER_NOKEY; if (!abac_validate_clean_aspect_name(name)) return ABAC_ATTRIBUTE_INVALID_ROLE; if (validity < 0) return ABAC_ATTRIBUTE_INVALID_VALIDITY; abac_attribute_t *ptr = abac_xmalloc(sizeof(abac_attribute_t)); ptr->issuer_id = abac_id_dup(issuer); ptr->head=head_aspect; ptr->tail=tail_aspect; ptr->validity = validity; // NULL until baked ptr->cert = NULL; ptr->issuer_cert = NULL; *ret = ptr; return ABAC_ATTRIBUTE_SUCCESS; } int abac_attribute_bake(abac_attribute_t *ptr) { assert(ptr); char *cred_encoding = _get_cred_encoding(ptr); // create attribute cert time_t not_before = time(NULL); time_t not_after = not_before + ptr->validity; chunk_t serial = abac_generate_serial(); certificate_t *attr_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_AC, BUILD_CERT, abac_id_cert(ptr->issuer_id), BUILD_NOT_BEFORE_TIME, not_before, BUILD_NOT_AFTER_TIME, not_after, BUILD_SERIAL, serial, BUILD_IETF_GROUP_ATTR, cred_encoding, BUILD_SIGNING_CERT, abac_id_cert(ptr->issuer_id), BUILD_SIGNING_KEY, abac_id_privkey(ptr->issuer_id), BUILD_END ); if (attr_cert == NULL) return 0; ptr->cert = attr_cert; ptr->issuer_cert= attr_cert->get_ref(attr_cert); free(cred_encoding); free(serial.ptr); return 1; } abac_chunk_t abac_attribute_cert_chunk(abac_attribute_t *ptr) { assert(ptr->cert); chunk_t encoding = ptr->cert->get_encoding(ptr->cert); abac_chunk_t ret = { encoding.ptr, encoding.len }; return ret; } int abac_attribute_baked(abac_attribute_t *ptr) { return ptr->cert != NULL; } // returns 0 if the cert hasn't been baked int abac_attribute_write(abac_attribute_t *ptr, FILE *out) { assert(ptr != NULL); if (ptr->cert == NULL) return 0; // write to file chunk_t encoding = ptr->cert->get_encoding(ptr->cert); fwrite(encoding.ptr, encoding.len, 1, out); free(encoding.ptr); return 1; } abac_attribute_t *abac_attribute_dup(abac_attribute_t *ptr) { assert(ptr); ++ptr->refcount; return ptr; } void abac_attribute_free(abac_attribute_t *ptr) { int i; if (ptr == NULL) return; --ptr->refcount; if (ptr->refcount > 0) return; if(ptr->issuer_id) abac_id_free(ptr->issuer_id); if(ptr->head) abac_aspect_free(ptr->head); if(ptr->tail) abac_aspect_free(ptr->tail); if(ptr->cert) DESTROY_IF(ptr->cert); if(ptr->issuer_cert) DESTROY_IF(ptr->issuer_cert); free(ptr); } /********************************************************************/ certificate_t *abac_attribute_issuer_cert(abac_attribute_t *ptr) { assert(ptr); return ptr->issuer_cert; } abac_aspect_t *abac_attribute_head(abac_attribute_t *ptr) { assert(ptr); return ptr->head; } abac_attribute_t *abac_attribute_set_head(abac_attribute_t *ptr, abac_aspect_t *head) { assert(ptr); ptr->head=head; return ptr; } abac_aspect_t *abac_attribute_tail(abac_attribute_t *ptr) { assert(ptr); return ptr->tail; } abac_attribute_t *abac_attribute_add_tail(abac_attribute_t *ptr, abac_aspect_t *tail) { assert(ptr); assert(tail); /* type of head and tail has to match */ abac_aspect_t *head=abac_attribute_head(ptr); if(abac_aspect_is_intersecting(tail)) { if(debug) { printf("tail is intersection \n"); printf("tail is (%s)\n", abac_aspect_string_with_condition(tail)); } if(abac_aspect_intersecting_aspect_type(tail) != abac_aspect_aspect_type(head)) errx(1, "head and tail's aspect type does not match"); } else { if(abac_aspect_aspect_type(head) != abac_aspect_aspect_type(tail)) { if(debug) { printf("head->(%s)\n",abac_aspect_type_string(head)); printf("tail->(%s)\n",abac_aspect_type_string(tail)); printf("tail is (%s)\n", abac_aspect_string_with_condition(tail)); } errx(1, "head and tail's aspect type does not match"); } } /* special case.. if there is a tail there already and it is not an intersecting tail, need to turn this into an intersecting tails */ if(ptr->tail == NULL) { ptr->tail=abac_aspect_dup(tail); } else { if(abac_aspect_is_intersecting(ptr->tail)) { abac_aspect_add_intersecting_aspect(ptr->tail, tail); } else { /* special case.. if there is a tail there already and it is not an intersecting tail, need to turn this into an intersecting tails */ abac_aspect_t *nptr=abac_aspect_intersection_new(ptr->tail); abac_aspect_add_intersecting_aspect(nptr, tail); ptr->tail=nptr; } } return ptr; } certificate_t *abac_attribute_cert(abac_attribute_t *ptr) { assert(ptr); return ptr->cert; } int abac_attribute_lastone(abac_attribute_t *ptr) { assert(ptr); if(ptr->refcount == 1) return 1; return 0; } abac_aspect_t **abac_attribute_tail_vectorized(abac_attribute_t *ptr) { abac_aspect_t **tails=NULL; abac_aspect_t *tail=ptr->tail; abac_list_t *list=NULL; int cnt=0; if(tail != NULL) { if(!abac_aspect_is_intersecting(tail)) { tails = abac_xmalloc(sizeof(abac_aspect_t *) * 2); tails[0] = abac_aspect_dup(tail); tails[1] = NULL; if(debug) { printf("abac_attribute_tail_vectorized, only 1 tail\n"); } return tails; } else { abac_list_t *list=abac_aspect_prereqs(tail); cnt=abac_list_size(list); } } // 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 tails = abac_xmalloc(sizeof(abac_aspect_t *) * (cnt + 1)); abac_aspect_t *cur; int i = 0; if(i