Index: libabac/abac_attribute.c
===================================================================
--- libabac/abac_attribute.c	(revision 13b087a33287e7fae4072c6dd6d18725903f3183)
+++ libabac/abac_attribute.c	(revision ab63eceb06621c07f91c4149186478052657e2dd)
@@ -30,7 +30,8 @@
     char *role;
     long validity;
+    int ntails;
 
     char *head_string;
-    char *tail_string;
+    char **tail_strings;
 
     abac_chunk_t cert; // the XML chunk
@@ -77,5 +78,6 @@
     attr->head_string = NULL;
     asprintf(&attr->head_string,"%s.%s",abac_id_keyid(issuer_id),role);
-    attr->tail_string = NULL;
+    attr->ntails = 0;
+    attr->tail_strings = NULL;
 
     // NULL until baked
@@ -120,4 +122,19 @@
 }
 
+int abac_attribute_add_tail(abac_attribute_t *attr, char *string) {
+    assert(attr);
+
+    char **old_tail = attr->tail_strings;
+    int newsize = (attr->ntails+1)*sizeof(char *);
+
+    if ( !(attr->tail_strings = realloc(attr->tail_strings, newsize))) {
+	attr->tail_strings = old_tail;
+	return 0;
+    }
+    attr->tail_strings[attr->ntails++] = abac_xstrdup(string);
+    return 1;
+}
+
+
 void abac_attribute_set_head(abac_attribute_t *attr, char *string)
 {
@@ -131,5 +148,5 @@
     return attr->head_string;
 }
-
+/*
 void abac_attribute_set_tail(abac_attribute_t *attr, char *string)
 {
@@ -143,4 +160,5 @@
     return attr->tail_string;
 }
+*/
 
 /* A.b->C, return copy of a A */
@@ -151,5 +169,5 @@
     char *tmp=strdup(role_string);
     char *head_tail[2];
-    int ret;
+    int ret = 2;
     abac_split(tmp, "<-", head_tail, &ret);
     if (ret != 2) goto err;
@@ -170,6 +188,5 @@
         return 0;
 
-    abac_attribute_set_tail(attr,copy);
-    return 1;
+    return abac_attribute_add_tail(attr,copy);
 }
 
@@ -179,20 +196,11 @@
 
     char *copy = _validate_principal(keyid);
+    char *newcopy=NULL;
     if (copy == NULL)
         return 0;
 
-    /* if there is a tail already, this is intersection */
-    char *oldtail=abac_attribute_get_tail(attr);
-    char *newcopy=NULL;
-    if(oldtail) {
-        asprintf(&newcopy,"%s & %s.%s", oldtail, copy,role);
-        free(oldtail);
-        } else {
-            asprintf(&newcopy,"%s.%s", copy,role);
-    }
+    asprintf(&newcopy,"%s.%s", copy,role);
     free(copy);
-
-    abac_attribute_set_tail(attr,newcopy);
-    return 1;
+    return abac_attribute_add_tail(attr, newcopy);
 }
 
@@ -205,17 +213,8 @@
         return 0;
 
-    /* if there is a tail already, this is intersection */
-    char *oldtail=abac_attribute_get_tail(attr);
     char *newcopy=NULL;
-    if(oldtail) {
-        asprintf(&newcopy,"%s & %s.%s.%s", oldtail, copy,role,linked);
-        free(oldtail);
-        } else {
-            asprintf(&newcopy,"%s.%s.%s", copy,role,linked);
-    }
+    asprintf(&newcopy,"%s.%s.%s", copy,role,linked);
     free(copy);
-
-    abac_attribute_set_tail(attr,newcopy);
-    return 1;
+    return abac_attribute_add_tail(attr, newcopy);
 }
 
@@ -226,5 +225,5 @@
     assert(attr);
     assert(attr->head_string);
-    assert(attr->tail_string);
+    assert(attr->tail_strings);
 
     abac_chunk_t id_chunk = { NULL, 0 };
@@ -277,5 +276,6 @@
 
     char *head_tail[2];
-    int ret;
+    char *role_rest[2];
+    int ret = 2;
     abac_split(role_string, "<-", head_tail, &ret);
     if (ret != 2) return NULL; 
@@ -293,5 +293,11 @@
 
     attr->head_string = abac_xstrdup(head_tail[0]);
-    attr->tail_string = abac_xstrdup(head_tail[1]);
+    do {
+	ret = 2;
+	abac_split(head_tail[1], " & ", role_rest, &ret);
+	abac_attribute_add_tail(attr, abac_xstrdup(role_rest[0]));
+	head_tail[1] =role_rest[1];
+    } while (ret == 2);
+
     char *tmp=strstr(attr->head_string,".");
     attr->role =abac_xstrdup(tmp+1);
@@ -392,4 +398,5 @@
 
 if(debug) fprintf(stderr,"calling abac_attribute_free on %s\n", attr->head_string);
+    int i = 0;
 
     if (attr == NULL)
@@ -400,5 +407,7 @@
     free(attr->role);
     free(attr->head_string);
-    free(attr->tail_string);
+    for (i=0; i < attr->ntails; i++) 
+	free(attr->tail_strings[i]);
+    free(attr->tail_strings);
 
 /* XXX this can not be free as if it is a char string
@@ -439,12 +448,40 @@
 }
 
+static int abac_attribute_role_string_size(abac_attribute_t *attr) {
+    int sz = 3; /* Start with the end of string character and <-*/
+    int i;	/* Scratch */
+
+    if ( !attr) return sz;
+    if ( attr->head_string) 
+	sz += strlen(attr->head_string);
+    for (i = 0; i < attr->ntails; i++) 
+	if ( attr->tail_strings[i]) 
+	    sz += strlen(attr->tail_strings[i]);
+    /* " & " between each pair of tails */
+    sz += 3 * (attr->ntails-1);
+    return sz;
+}
+
 // combine up the attribute's rule string, explicit copy
 char *abac_attribute_role_string(abac_attribute_t *attr) {
     assert(attr);
 
-    char *role_string=NULL;
-    asprintf(&role_string,"%s<-%s",attr->head_string,attr->tail_string);
+    int sz = abac_attribute_role_string_size(attr);
+    char *role_string=abac_xmalloc(sz);
+    int i;
+
+    if ( !role_string) return NULL;
+
+    sz -= snprintf(role_string, sz, "%s<-", attr->head_string);
+    for ( i = 0 ; i < attr->ntails; i++ ) {
+	if ( i > 0 ) {
+	    strncat(role_string, " & ", 3);
+	    sz -= 3;
+	}
+	strncat(role_string,attr->tail_strings[i], sz); 
+
+	sz -= strlen(attr->tail_strings[i]);
+	if (sz < 0 ) return NULL;
+    }
     return role_string;
 }
-
-
