Index: libabac/abac.hh
===================================================================
--- libabac/abac.hh	(revision 99373511400af88ff4c987810ba7e85b3bbb615c)
+++ libabac/abac.hh	(revision 8bd77b59df89993868555d3b87f91fc241b09228)
@@ -10,132 +10,581 @@
     }
 
+    static int debug=0;
+
+    class Role;
+    class Oset;
+
+    class Constraint {
+        public:
+            Constraint() : m_constraint(NULL) { } // do not use: here for swig
+            Constraint(abac_condition_t *constraint): 
+              m_constraint(abac_condition_dup(constraint))
+              { }
+            Constraint(const Constraint &constraint) { 
+                m_constraint =abac_condition_dup(constraint.m_constraint);
+              }
+            ~Constraint() { 
+                if(m_constraint) abac_condition_free(m_constraint);
+              }
+            /* range constraint */
+            Constraint(char *constraint) {
+                m_constraint=abac_condition_from_string(constraint); 
+              }
+            /* role constraint */
+            Constraint(Role *role);
+            /* oset constraint */
+            Constraint(Oset *oset);
+            char *string() const { 
+                return abac_condition_string(m_constraint);
+              }
+            char *typed_string() const { 
+                return abac_condition_typed_string(m_constraint);
+              }
+            abac_condition_t *constraint()
+              { return m_constraint; }
+        private:
+            abac_condition_t *m_constraint;
+    };
+
+    /* XXX need to track the principal [keyid:alice] so can generate
+       the id_type_clause within attribute clause */
+    class DataTerm {
+        public:
+            DataTerm() : m_term(NULL) { } // do not use: here for swig
+            DataTerm(abac_term_t *term) { 
+                m_term=abac_term_dup(term);
+                abac_condition_t *constraint=abac_term_constraint(m_term);
+                if(constraint) m_cond=new Constraint(constraint);
+                  else m_cond=NULL;
+              }
+            DataTerm(const DataTerm &term) { 
+                m_term =abac_term_dup(term.m_term);
+                abac_condition_t *constraint=abac_term_constraint(m_term);
+                if(constraint) m_cond=new Constraint(constraint);
+                  else m_cond=NULL;
+              }
+            ~DataTerm() { 
+                if(m_term) abac_term_free(m_term);
+                if(m_cond) free(m_cond);
+              }
+
+            DataTerm(int type, char *name, Constraint *cond=NULL) {
+                if(debug) printf("adding a Dataterm (%s)\n",name);
+                if(cond) {
+                  m_cond=cond;
+                  m_term=abac_term_create(type,name,cond->constraint());
+                  } else {
+                      m_cond=NULL;
+                      m_term=abac_term_create(type,name,NULL);
+                }
+              }
+            char *string() const { 
+                return abac_term_string(m_term);
+              }
+            char *typed_string() const { 
+                return abac_term_typed_string(m_term);
+              }
+            bool is_time() const {
+                return abac_term_is_time_type(m_term);
+              }
+            bool is_string() const {
+                return abac_term_is_string_type(m_term);
+              }
+            bool is_urn() const {
+                return abac_term_is_urn_type(m_term);
+              }
+            bool is_integer() const {
+                return abac_term_is_integer_type(m_term);
+              }
+/* Add a constraint to this term. */
+            int add_constraint(Constraint& cond) {
+                m_cond=new Constraint(cond);
+                abac_term_add_constraint(m_term, m_cond->constraint());
+              }
+            int type() {
+                abac_term_type(m_term);
+              }
+            char *name() {
+                return abac_term_name(m_term);
+              }
+            char *value() {
+/* ??? value XXX */
+              }
+            Constraint *constraint() {
+                return m_cond;
+              }
+            abac_term_t *term() {
+                return m_term;
+              }
+
+        private:
+            abac_term_t *m_term;
+            Constraint *m_cond;
+    };
+
+
     class Role {
         public:
-            Role() : m_role(NULL), m_oset(NULL) { } // do not use: here for swig
-            Role(abac_role_t *role): m_role(abac_role_dup(role)), m_oset(NULL)
-	    	{ }
-            Role(abac_oset_t *oset): m_role(NULL), m_oset(abac_oset_dup(oset)) 
-		{ }
-            Role(char *role_name) : m_role(abac_role_from_string(role_name)), 
-		m_oset(NULL) { }
+            Role() : m_role(NULL) { } // do not use: here for swig
+            Role(abac_aspect_t *role): m_role(abac_aspect_dup(role))
+              { }
+            Role(char *principal_name) : 
+               m_role(abac_aspect_role_principal_create(principal_name)) 
+              { }
+            Role(char *principal_name, char *role_name) : 
+               m_role(abac_aspect_role_create(principal_name, role_name)) 
+              { }
             Role(const Role &role) { 
-		if ( role.m_role ) {
-		    m_role = abac_role_dup(role.m_role);
-		    m_oset = NULL;
-		}
-		else {
-		    m_role =  NULL;
-		    m_oset =abac_oset_dup(role.m_oset);
-		}
-	    }
+                m_role = abac_aspect_dup(role.m_role);
+              }
             ~Role() { 
-		if ( m_role) abac_role_free(m_role);
-		if ( m_oset) abac_oset_free(m_oset);
-	    }
-
+                if (m_role) abac_aspect_free(m_role);
+              }
             bool is_principal() const { 
-		if (m_role) return abac_role_is_principal(m_role); 
-		else return abac_oset_is_principal(m_oset); 
-	    }
-            bool is_role() const { 
-		if (m_role) return abac_role_is_role(m_role); 
-		else return abac_oset_is_oset(m_oset); 
-	    }
+                return abac_aspect_is_principal(m_role); 
+              }
             bool is_linking() const { 
-		if (m_role) return abac_role_is_linking(m_role); 
-		else return abac_oset_is_linking(m_oset); 
-	    }
-	    bool is_oset() const { return m_oset; }
-
+                return abac_aspect_is_linking(m_role); 
+              }
             char *string() const { 
-		if ( m_role) return abac_role_string(m_role);
-		else return abac_oset_string(m_oset);
-	    }
+                return abac_aspect_string(m_role);
+              }
+            char *typed_string() {
+                char* string=abac_aspect_typed_string(m_role);
+                return string;
+              }
             char *linked_role() const { 
-		if (m_role) return abac_role_linked_role(m_role);
-		else return abac_oset_linked_role(m_oset);
-	    }
+                return abac_aspect_linked_role_name(m_role);
+              }
             char *role_name() const { 
-		if (m_role) return abac_role_role_name(m_role);
-		else return abac_oset_oset_name(m_oset);
-	    }
+                return abac_aspect_aspect_name(m_role);
+              }
             char *principal() const { 
-		if (m_role) return abac_role_principal_name(m_role);
-		else return abac_oset_principal_name(m_oset);
-	    }
-
+                return abac_aspect_principal_name(m_role);
+              }
+/* Add a data term to this name. */
+            int add_data_term(DataTerm& d) {
+                abac_aspect_add_param(m_role, d.term());
+                return 1;
+              }
+/* Return the DataTerms bound to this name.  If the name is returned
+   in a proof, these will all have values. */
+            std::vector<DataTerm> get_data_terms() {
+                abac_term_t **terms, **end;
+                int i, success_int;
+                terms = abac_param_list_vectorize(abac_aspect_aspect_params(m_role));
+                for (i = 0; terms[i] != NULL; ++i)
+                    ;
+                end = &terms[i];
+                std::vector<DataTerm> dataterms = std::vector<DataTerm>(terms, end);
+                abac_terms_free(terms);
+                return dataterms;
+              }
+            int add_linking_data_term(DataTerm& d) {
+                abac_aspect_add_linked_param(m_role, d.term());
+                return 1;
+              }
+            std::vector<DataTerm> get_linked_data_terms() {
+                abac_term_t **terms, **end;
+                int i, success_int;
+                terms = abac_param_list_vectorize(abac_aspect_linked_role_params(m_role));
+                for (i = 0; terms[i] != NULL; ++i)
+                    ;
+                end = &terms[i];
+                std::vector<DataTerm> dataterms = std::vector<DataTerm>(terms, end);
+                abac_terms_free(terms);
+                return dataterms;
+              }
+            abac_aspect_t *role() {return m_role;}
         private:
-            abac_role_t *m_role;
-            abac_oset_t *m_oset;
+            abac_aspect_t *m_role;
     };
 
-    class Credential {
-        public:
-            Credential() : m_cred(NULL) { } // do not use: here for swig
-            Credential(abac_credential_t *cred) :
-                m_head(), m_tail(), m_cred(abac_credential_dup(cred)) { 
-		    if ( abac_credential_holds_roles(cred)) {
-			m_head = Role(abac_credential_head(cred));
-			m_tail = Role(abac_credential_tail(cred));
-		    }
-		    else {
-			m_head = Role(abac_credential_head_oset(cred));
-			m_tail = Role(abac_credential_tail_oset(cred));
-		    }
-	    }
-            Credential(const Credential &cred) :
-                m_head(cred.m_head),
-                m_tail(cred.m_tail),
-                m_cred(abac_credential_dup(cred.m_cred))
-                    { }
-            ~Credential() { abac_credential_free(m_cred); }
-
-            const Role &head() { return m_head; }
-            const Role &tail() { return m_tail; }
-            abac_chunk_t attribute_cert() { return abac_credential_attribute_cert(m_cred); }
-            abac_chunk_t issuer_cert() { return abac_credential_issuer_cert(m_cred); }
-        
+    class Oset {
+        public:
+            Oset() : m_oset(NULL) { } // do not use: here for swig
+            Oset(abac_aspect_t *oset): m_oset(abac_aspect_dup(oset)) 
+              { }
+            Oset(char *oset_name) : m_oset(abac_aspect_role_principal_create(oset_name)) 
+              { }
+            Oset(char *principal_name, char *oset_name) : 
+               m_oset(abac_aspect_oset_create(principal_name, oset_name)) 
+              { }
+            Oset(const Oset &oset) { 
+                m_oset =abac_aspect_dup(oset.m_oset);
+              }
+            ~Oset() { 
+                if(m_oset) abac_aspect_free(m_oset);
+              }
+            bool is_object() const { 
+                return abac_aspect_is_object(m_oset); 
+              }
+            bool is_principal() const { 
+                return abac_aspect_is_principal(m_oset); 
+              }
+            bool is_linking() const { 
+                return abac_aspect_is_linking(m_oset); 
+              }
+            char *string() const { 
+                return abac_aspect_string(m_oset);
+              }
+            char *typed_string() {
+                char* string=abac_aspect_typed_string(m_oset);
+                return string;
+              }
+            char *linked_role() const { 
+                return abac_aspect_linked_role_name(m_oset);
+              }
+            char *oset_name() const { 
+                return abac_aspect_aspect_name(m_oset);
+              }
+            char *principal() const { 
+                return abac_aspect_principal_name(m_oset);
+              }
+            char *object() const { 
+                return abac_aspect_object_name(m_oset);
+              }
+/* Add a data term to this name. */
+            int add_data_term(DataTerm& d) {
+                abac_aspect_add_param(m_oset, d.term()); 
+                return 1;
+              }
+/* Return the DataTerms bound to this name.  If the name is returned
+   in a proof, these will all have values. */
+            std::vector<DataTerm> get_data_terms() {
+                abac_term_t **terms, **end;
+                int i, success_int;
+                terms = abac_param_list_vectorize(abac_aspect_aspect_params(m_oset));
+                for (i = 0; terms[i] != NULL; ++i)
+                    ;
+                end = &terms[i];
+                std::vector<DataTerm> dataterms = std::vector<DataTerm>(terms, end);
+                abac_terms_free(terms);
+                return dataterms;
+              }
+            int add_linking_data_term(DataTerm& d) {
+                abac_aspect_add_linked_param(m_oset, d.term());
+                return 1;
+              }
+            std::vector<DataTerm> get_linked_data_terms() {
+                abac_term_t **terms, **end;
+                int i, success_int;
+                terms = abac_param_list_vectorize(abac_aspect_linked_role_params(m_oset));
+                for (i = 0; terms[i] != NULL; ++i)
+                    ;
+                end = &terms[i];
+                std::vector<DataTerm> dataterms = std::vector<DataTerm>(terms, end);
+                abac_terms_free(terms);
+                return dataterms;
+              }
+            abac_aspect_t *oset() {return m_oset;}
         private:
-            abac_credential_t *m_cred;
-            Role m_head, m_tail;
+            abac_aspect_t *m_oset;
     };
 
+
+    class ID {
+        public:
+            ID() : m_id(NULL) { } // do not use: here for swig
+            ID(abac_id_t *id): m_id(abac_id_dup(id)) 
+              { }
+            ID(const ID &id) { m_id =abac_id_dup(id.m_id); }
+            ~ID() { if(m_id) abac_id_free(m_id); }
+
+/* load an ID cert from a file
+Will throw an exception if the cert cannot be loaded */
+            ID(char *filename) {
+                m_id=abac_id_from_file(filename); 
+                if(m_id==NULL)
+                  abac_errx(1, "Id creation from filename failed");
+              }
+/* generates a new ID with the supplied CN and validity period
+   - CN must be alphanumeric and begin with a letter
+   - validity must be at least one second
+   Will throw an exception if either of the above is violated */
+            ID(char *cn, int validity) {
+                int rt=abac_id_generate(&m_id, cn, validity);
+                if(rt != ABAC_ID_SUCCESS)  
+                  abac_errx(1, "Id creation failed");
+              }
+/* loads the private key associated with the cert
+   will throw an exception if the key cannot be loaded */
+            void load_privkey(char *filename) {
+                int rt=abac_id_load_privkey(m_id, filename);
+                if(rt != 1) 
+                  abac_errx(1, "Failed to load private key");
+              }
+            abac_id_t *id() { return m_id; }
+
+/* returns the SHA1 keyid of the cert */
+            char *keyid() { return abac_id_keyid(m_id); }
+/* returns the CN (the parameter passed to the constructor or the
+   CN of the cert). */
+            char *name() { return abac_id_cn(m_id); }
+/* returns true if the ID has an associated private key */
+            bool has_privkey() {
+                return abac_id_has_privkey(m_id);
+              }
+/* writes a PEM-encoded cert to the file handle */
+            void write_cert(FILE *out) {
+                abac_id_write_cert(m_id, out); 
+              }
+/* writes a PEM-encoded cert to a file named out */
+            void write_cert(char *filename) {
+                FILE *out = fopen(filename, "w");
+                write_cert(out);
+                fclose(out);
+              }
+/* writes a PEM-encoded private key to the file handle
+   throws an exception if no private key is loaded */
+            void write_privkey(FILE *out) {
+                if(!has_privkey())
+                    abac_errx(1, "No privkey to write");
+                abac_id_write_privkey(m_id, out);
+              }
+/* writes a PEM-encoded private key a file named out
+   throws an exception if no private key is loaded */
+            void write_privkey(char *filename) {
+                FILE *out = fopen(filename, "w");
+                write_privkey(out);
+                fclose(out);
+              }
+/* returns a DER-encoded binary representation of the X.509 ID cert
+   associated with this ID.
+   can be passed to libabac's Context::load_id_chunk() */
+            abac_chunk_t cert_chunk() {
+                return abac_id_cert_chunk(m_id);
+              }
+        public:
+            abac_id_t *m_id;
+    };
+
+
+/* N.B., The way you use this class is by instantiating the object, adding
+   subjects to it, and then baking it. Only once it's baked can you access the
+   X.509 cert. Once it's been baked you can no longer add subjects to it. */
+    class Attribute {
+        public:
+            Attribute() : m_attr(NULL) { } // do not use: here for swig
+            Attribute(abac_attribute_t *attr): m_attr(abac_attribute_dup(attr)) 
+              { }
+            Attribute(abac_credential_t *cred) {
+                m_attr=abac_attribute_dup(abac_credential_attribute(cred));
+              }
+            Attribute(const Attribute &id) { 
+                m_attr =abac_attribute_dup(id.m_attr);
+              }
+            ~Attribute() { 
+                if(m_attr) abac_attribute_free(m_attr);
+              }
+/* Create an object to be signed by the given issuer with the given role
+   and validity period
+   An exception will be thrown if:
+     - the issuer has no private key
+     - the Head is invalid
+     - the validity period is invalid (must be >= 1 second) */
+            Attribute(Role& head, int validity) {
+                int rt=abac_attribute_create(&m_attr, head.role(), NULL, validity);
+                if(rt!=ABAC_ATTRIBUTE_SUCCESS)
+                    abac_errx(1, "attribute(role), unable to make an attribute");
+              }
+            Attribute(Oset& head, int validity) {
+                int rt=abac_attribute_create(&m_attr, head.oset(), NULL, validity);
+                if(rt!=ABAC_ATTRIBUTE_SUCCESS)
+                    abac_errx(1, "attribute(oset), unable to make an attribute");
+              }
+            bool add_tail(Role& tail) {
+                if(abac_attribute_add_tail(m_attr, tail.role()))
+                    return 1;
+                    else return 0;
+              }
+            bool add_tail(Oset& tail) {
+                if(abac_attribute_add_tail(m_attr, tail.oset()))
+                    return 1;
+                    else return 0;
+              }
+            char *head_string() {
+                abac_aspect_t *head=abac_attribute_head(m_attr);
+                char *string=abac_aspect_string(head);
+                return string;
+              }
+            char *tail_string() {
+                abac_aspect_t *tail=abac_attribute_tail(m_attr);
+                char *string=abac_aspect_string(tail);
+                return string;
+              }
+            char *head_typed_string() {
+                abac_aspect_t *head=abac_attribute_head(m_attr);
+                char *string=abac_aspect_typed_string(head);
+                return string;
+              }
+            char *tail_typed_string() {
+                abac_aspect_t *tail=abac_attribute_tail(m_attr);
+                char *string=abac_aspect_typed_string(tail);
+                return string;
+              }
+            char *string() {
+                char *head=head_string();
+                char *tail=tail_string();
+                if(head==NULL || tail==NULL)
+                    abac_errx(1, "attribute string, head and tail can not be NULL");
+                char *tmp=NULL;
+                asprintf(&tmp,"%s<-%s",head,tail);
+                return tmp;
+              }
+            char *typed_string() {
+                char *head=head_typed_string();
+                char *tail=tail_typed_string();
+                if(head==NULL || tail==NULL)
+                    abac_errx(1, "attribute string, head and tail can not be NULL");
+                char *tmp=NULL;
+                asprintf(&tmp,"%s<-%s",head,tail);
+                return tmp;
+              }
+            const Role &role_head() {
+                abac_aspect_t *head=abac_attribute_head(m_attr);
+                static Role role=Role(head);
+                return role;
+              }
+            const Oset &oset_head() {
+                abac_aspect_t *head=abac_attribute_tail(m_attr);
+                static Oset oset=Oset(head);
+                return oset;
+              }
+            std::vector<Role> role_tails() {
+                abac_aspect_t **tails, **end;
+                int i, success_int;
+                char * string=abac_aspect_string(abac_attribute_tail(m_attr));
+                printf("XXX %s XXX\n",string);
+                tails = abac_attribute_tail_vectorized(m_attr);
+                for (i = 0; tails[i] != NULL; ++i)
+                    ;
+                end = &tails[i];
+                std::vector<Role> roles = std::vector<Role>(tails, end);
+                abac_aspects_free(tails);
+                return roles;
+              }
+            std::vector<Oset> oset_tails() {
+                abac_aspect_t **tails, **end;
+                int i, success_int;
+                tails = abac_attribute_tail_vectorized(m_attr);
+                for (i = 0; tails[i] != NULL; ++i)
+                    ;
+                end = &tails[i];
+                std::vector<Oset> osets = std::vector<Oset>(tails, end);
+                abac_aspects_free(tails);
+                return osets;
+              }
+            abac_attribute_t *attribute() { return m_attr; }
+
+/* Generate the cert. Call this after you've added subjects to your cert.
+   This returns false if there are no subjects
+   This will throw an exception if the cert's already been baked. */
+            bool bake() {
+                int rt=abac_attribute_bake(m_attr);
+                if(rt!=1)
+                    abac_errx(1, "bake, can not bake the cert");
+              }
+/* Returns true iff the cert has been baked. */
+            bool baked() {
+                return abac_attribute_baked(m_attr);
+              }
+/* Write the DER-encoded X.509 attribute cert to the open file handle
+   Throws an exception if the cert isn't baked */
+            void write_cert(FILE *out) {
+                int rt= abac_attribute_write(m_attr,out);
+                if(!rt)
+                    abac_errx(1, "write, cert is not baked");
+              }
+/* Write the DER-encoded X.509 attribute cert to a file named out
+   Throws an exception if the cert isn't baked */
+            void write_cert(char *filename) {
+                FILE *out = fopen(filename, "w");
+                write_cert(out);
+                fclose(out);
+              }
+/* returns a DER-encoded binary representation of the X.509 attribute
+   cert associated with this cert
+   Throws an exception if the cert isn't baked
+   the chunk can be passed to libabac's Context::load_attribute_chunk() */
+            abac_chunk_t cert_chunk() {
+                return abac_attribute_cert_chunk(m_attr);
+              }
+      private:
+            abac_attribute_t *m_attr;
+     };
+
+
     class Context {
         public:
-            Context() { m_ctx = abac_context_new(); }
-            Context(const Context &context) { m_ctx = abac_context_dup(context.m_ctx); }
-            ~Context() { abac_context_free(m_ctx); }
-
-            /* see abac.h for possible return values */
-            int load_id_file(char *filename) { return abac_context_load_id_file(m_ctx, filename); }
-            int load_id_chunk(abac_chunk_t cert) { return abac_context_load_id_chunk(m_ctx, cert); }
-            int load_attribute_file(char *filename) { return abac_context_load_attribute_file(m_ctx, filename); }
-            int load_attribute_chunk(abac_chunk_t cert) { return abac_context_load_attribute_chunk(m_ctx, cert); }
-
-            /* load an entire directory full of certs */
-            void load_directory(char *path) { abac_context_load_directory(m_ctx, path); }
-
-            /* abac query, returns a vector of credentials on success, NULL on fail */
-            std::vector<Credential> query(char *role, char *principal, bool &success) {
-                abac_credential_t **creds, **end;
-                int i, success_int;
-
-                creds = abac_context_query(m_ctx, role, principal, &success_int);
-                success = success_int;
-
-                for (i = 0; creds[i] != NULL; ++i)
-                    ;
-
-                end = &creds[i];
-                std::vector<Credential> credentials = std::vector<Credential>(creds, end);
-
-                abac_context_credentials_free(creds);
-
-                return credentials;
-            }
-
-            std::vector<Credential> credentials() {
+            Context() { m_ctx = abac_context_new(); m_abac_version=strdup("1.0"); }
+            Context(const Context &context) { 
+                m_ctx = abac_context_dup(context.m_ctx);
+                m_abac_version=strdup(context.m_abac_version);
+              }
+            ~Context() { 
+                abac_context_free(m_ctx);
+                if(m_abac_version) free(m_abac_version);
+              }
+
+/* load an identity certificate, returns:
+      ABAC_CERT_SUCCESS   successfully loaded
+      ABAC_CERT_INVALID   invalid certificate (or file not found)
+      ABAC_CERT_BAD_SIG   invalid signature */
+            int load_id(ABAC::ID& id) {
+                return abac_context_load_id_id(m_ctx, id.id());
+              }
+            int load_id_file(char *filename) {
+                return abac_context_load_id_file(m_ctx, filename);
+              }
+            int load_id_chunk(abac_chunk_t cert) { 
+                return abac_context_load_id_chunk(m_ctx, cert);
+              }
+/* load an attribute certificate, returns the same values as above
+   * additionally can return ABAC_CERT_MISSING_ISSUER if the issuer
+   certificate has not been loaded */
+            int load_attribute(ABAC::Attribute& a) {
+                return abac_context_load_attribute_attribute(m_ctx, a.attribute());
+              }
+            int load_attribute_file(char *filename) { 
+                return abac_context_load_attribute_file(m_ctx, filename);
+              }
+            int load_attribute_chunk(abac_chunk_t cert) {
+                return abac_context_load_attribute_chunk(m_ctx, cert);
+              }
+/* load a directory full of certificates:
+   first: ${path}/*_ID.{der,pem} as identity certificates
+   then: ${path}/*_attr.der as attribute certificates */
+            void load_directory(char *path) {
+                abac_context_load_directory(m_ctx, path);
+              }
+/* run the query:
+       role <-?- principal
+   returns true/false in success
+   returns a proof upon success, partial proof on failure */
+            std::vector<Attribute> query(char *role, char *principal, bool &success) {
+                 abac_credential_t **creds, **end;
+                 int i, success_int;
+
+                 creds = abac_context_query(m_ctx, role, principal, &success_int);
+                 success = success_int;
+
+                 for (i = 0; creds[i] != NULL; ++i)
+                    ;
+
+                 end = &creds[i];
+                 std::vector<Attribute> attributes = std::vector<Attribute>(creds, end);
+                 if(debug) printf("rules, got (%d)\n", i);
+
+                 abac_context_credentials_free(creds);
+
+                 return attributes;
+              }
+
+/* returns a vector of all the credentials loaded in the context */
+            std::vector<Attribute> context_credentials(bool &success) {
                 abac_credential_t **creds, **end;
                 int i;
+                success = 1;
 
                 creds = abac_context_credentials(m_ctx);
@@ -144,13 +593,22 @@
 
                 end = &creds[i];
-                std::vector<Credential> credentials = std::vector<Credential>(creds, end);
+                std::vector<Attribute> attributes = std::vector<Attribute>(creds, end);
+                if(debug) printf("credentials, got (%d)\n", i);
 
                 abac_context_credentials_free(creds);
-                return credentials;
-            }
+                return attributes;
+              }
+            
+            char *version() const { return m_abac_version; }
 
         private:
             abac_context_t *m_ctx;
+            char *m_abac_version;
     };
+
+    Constraint::Constraint(Role *role)
+    { m_constraint=abac_condition_from_aspect(role->role()); }
+    Constraint::Constraint(Oset *oset)
+    { m_constraint=abac_condition_from_aspect(oset->oset()); }
 }
 
