source: libabac/abac.hh @ 440ba20

mei_rt2mei_rt2_fix_1
Last change on this file since 440ba20 was 440ba20, checked in by Mei <mei@…>, 12 years ago

1) wrap up refactoring to move all the code gen to abac structure
2) all original testsuite passed
3) add couple more ui calls in abac.hh ie. manage constraint's

creation, hook to dump yap db.

  • Property mode set to 100644
File size: 25.1 KB
Line 
1#ifndef __ABAC_HH__
2#define __ABAC_HH__
3
4#include <string>
5#include <vector>
6
7namespace ABAC {
8    extern "C" {
9        #include "abac.h"
10    }
11
12    static int debug=0;
13
14    class Role;
15    class Oset;
16
17    class Constraint {
18        public:
19            Constraint() : m_constraint(NULL) { } // do not use: here for swig
20            Constraint(abac_condition_t *constraint): 
21              m_constraint(abac_condition_dup(constraint))
22              { }
23            Constraint(const Constraint &constraint) { 
24                m_constraint =abac_condition_dup(constraint.m_constraint);
25              }
26            ~Constraint() { 
27                if(m_constraint) abac_condition_free(m_constraint);
28              }
29            /* range constraint */
30            Constraint(char *vartype) {
31                m_constraint=abac_condition_create(vartype);
32              }
33            /* min, max, target */
34            int add_constraint_item(char *vtype,char *itype, char *val) {
35                return abac_condition_add_range_item(m_constraint,vtype,itype,val);
36              }
37            void add_constraint_item_help() {
38                printf(" USAGE: add_constraint_item(\"integer\",\"max\",\"2000\"); \n");
39                printf("        add_constraint_item(\"time\",\"target\",\"20201101T182930\"); \n");
40              }
41            /* role constraint */
42            Constraint(Role *role);
43            /* oset constraint */
44            Constraint(Oset *oset);
45            char *string() const { 
46                return abac_condition_string(m_constraint);
47              }
48            char *typed_string() const { 
49                return abac_condition_typed_string(m_constraint);
50              }
51            abac_condition_t *constraint()
52              { return m_constraint; }
53        private:
54            abac_condition_t *m_constraint;
55    };
56
57    /* XXX need to track the principal [keyid:alice] so can generate
58       the id_type_clause within attribute clause */
59    class DataTerm {
60        public:
61            DataTerm() : m_term(NULL) { } // do not use: here for swig
62            DataTerm(abac_term_t *term) { 
63                m_term=abac_term_dup(term);
64                abac_condition_t *constraint=abac_term_constraint(m_term);
65                if(constraint) m_cond=new Constraint(constraint);
66                  else m_cond=NULL;
67              }
68            DataTerm(const DataTerm &term) { 
69                m_term =abac_term_dup(term.m_term);
70                abac_condition_t *constraint=abac_term_constraint(m_term);
71                if(constraint) m_cond=new Constraint(constraint);
72                  else m_cond=NULL;
73              }
74            ~DataTerm() { 
75                if(m_term) abac_term_free(m_term);
76                if(m_cond) free(m_cond);
77              }
78            /* this is for named principal data term */
79            DataTerm(char *sha) {
80                if(debug) printf("adding a Dataterm named principal(%s)\n",sha);
81                int isnamed=1;
82                int type=e_TERM_PRINCIPAL;
83                m_term=abac_term_named_create(type,sha);
84            }
85            /* can be an a variable data term or a specific value */
86            DataTerm(char* typenm, char *name, Constraint *cond=NULL) {
87                int type=abac_verify_term_type(typenm);
88                if(debug) printf("adding a Dataterm (%s)\n",name);
89                if(type==ABAC_TERM_FAIL)
90                  abac_errx(1, "DataTerm, fail to create the term");
91                if(cond) {
92                  m_cond=cond;
93                  m_term=abac_term_create(type,name,cond->constraint());
94                  } else {
95                      m_cond=NULL;
96                      m_term=abac_term_create(type,name,NULL);
97                }
98              }
99            char *string() const { 
100                return abac_term_string(m_term);
101              }
102            char *typed_string() const { 
103                return abac_term_typed_string(m_term);
104              }
105            bool is_time() const {
106                return abac_term_is_time_type(m_term);
107              }
108            bool is_string() const {
109                return abac_term_is_string_type(m_term);
110              }
111            bool is_urn() const {
112                return abac_term_is_urn_type(m_term);
113              }
114            bool is_integer() const {
115                return abac_term_is_integer_type(m_term);
116              }
117/* Add a constraint to this term. */
118            int add_constraint(Constraint& cond) {
119                m_cond=new Constraint(cond);
120                abac_term_add_constraint(m_term, m_cond->constraint());
121              }
122            int type() {
123                abac_term_type(m_term);
124              }
125            char *name() {
126                return abac_term_name(m_term);
127              }
128            char *value() {
129/* ??? value XXX */
130              }
131            Constraint *constraint() {
132                return m_cond;
133              }
134            abac_term_t *term() {
135                return m_term;
136              }
137
138        private:
139            abac_term_t *m_term;
140            Constraint *m_cond;
141    };
142
143
144    class Role {
145        public:
146            Role() : m_role(NULL) { } // do not use: here for swig
147            Role(abac_aspect_t *role): m_role(abac_aspect_dup(role))
148              { }
149            Role(char *principal_name) : 
150               m_role(abac_aspect_role_principal_create(principal_name)) 
151              { }
152            Role(char *principal_name, char *role_name) : 
153               m_role(abac_aspect_role_create(principal_name, role_name)) 
154              { }
155            Role(const Role &role) { 
156                m_role = abac_aspect_dup(role.m_role);
157              }
158            ~Role() { 
159                if (m_role) abac_aspect_free(m_role);
160              }
161            bool is_principal() const { 
162                return abac_aspect_is_principal(m_role); 
163              }
164            bool is_linking() const { 
165                return abac_aspect_is_linking(m_role); 
166              }
167            char *string() const { 
168                return abac_aspect_string(m_role);
169              }
170            char *typed_string() {
171                char* string=abac_aspect_typed_string(m_role);
172                return string;
173              }
174            char *linked_role() const { 
175                return abac_aspect_linked_role_name(m_role);
176              }
177            char *role_name() const { 
178                return abac_aspect_aspect_name(m_role);
179              }
180            char *principal() const { 
181                return abac_aspect_principal_name(m_role);
182              }
183/* Add a data term to this name. */
184            int add_data_term(DataTerm& d) {
185                abac_aspect_add_param(m_role, d.term());
186                return 1;
187              }
188/* Return the DataTerms bound to this name.  If the name is returned
189   in a proof, these will all have values. */
190            std::vector<DataTerm> get_data_terms(bool &success) {
191                abac_term_t **terms, **end;
192                int i;
193                terms = abac_param_list_vectorize(abac_aspect_aspect_params(m_role));
194                for (i = 0; terms[i] != NULL; ++i)
195                    ;
196                end = &terms[i];
197                std::vector<DataTerm> dataterms = std::vector<DataTerm>(terms, end);
198                abac_terms_free(terms);
199                success=1;
200                return dataterms;
201              }
202            int add_linking_data_term(DataTerm& d) {
203                abac_aspect_add_linked_param(m_role, d.term());
204                return 1;
205              }
206            std::vector<DataTerm> get_linked_data_terms(bool &success) {
207                abac_term_t **terms, **end;
208                int i;
209                terms = abac_param_list_vectorize(abac_aspect_linked_role_params(m_role));
210                for (i = 0; terms[i] != NULL; ++i)
211                    ;
212                end = &terms[i];
213                std::vector<DataTerm> dataterms = std::vector<DataTerm>(terms, end);
214                abac_terms_free(terms);
215                success=1;
216                return dataterms;
217              }
218            abac_aspect_t *role() {return m_role;}
219        private:
220            abac_aspect_t *m_role;
221    };
222
223    class Oset {
224        public:
225            Oset() : m_oset(NULL) { } // do not use: here for swig
226            Oset(abac_aspect_t *oset): m_oset(abac_aspect_dup(oset)) 
227              { }
228            Oset(char *oset_name) : m_oset(abac_aspect_role_principal_create(oset_name)) 
229              { }
230            Oset(char *principal_name, char *oset_name) : 
231               m_oset(abac_aspect_oset_create(principal_name, oset_name)) 
232              { }
233            Oset(const Oset &oset) { 
234                m_oset =abac_aspect_dup(oset.m_oset);
235              }
236            ~Oset() { 
237                if(m_oset) abac_aspect_free(m_oset);
238              }
239            bool is_object() const { 
240                return abac_aspect_is_object(m_oset); 
241              }
242            bool is_principal() const { 
243                return abac_aspect_is_principal(m_oset); 
244              }
245            bool is_linking() const { 
246                return abac_aspect_is_linking(m_oset); 
247              }
248            char *string() const { 
249                return abac_aspect_string(m_oset);
250              }
251            char *typed_string() {
252                char* string=abac_aspect_typed_string(m_oset);
253                return string;
254              }
255            char *linked_role() const { 
256                return abac_aspect_linked_role_name(m_oset);
257              }
258            char *oset_name() const { 
259                return abac_aspect_aspect_name(m_oset);
260              }
261            char *principal() const { 
262                return abac_aspect_principal_name(m_oset);
263              }
264            char *object() const { 
265                return abac_aspect_object_name(m_oset);
266              }
267/* Add a data term to this name. */
268            int add_data_term(DataTerm& d) {
269                abac_aspect_add_param(m_oset, d.term()); 
270                return 1;
271              }
272/* Return the DataTerms bound to this name.  If the name is returned
273   in a proof, these will all have values. */
274            std::vector<DataTerm> get_data_terms(bool &success) {
275                abac_term_t **terms, **end;
276                int i;
277                terms = abac_param_list_vectorize(abac_aspect_aspect_params(m_oset));
278                for (i = 0; terms[i] != NULL; ++i)
279                    ;
280                end = &terms[i];
281                std::vector<DataTerm> dataterms = std::vector<DataTerm>(terms, end);
282                abac_terms_free(terms);
283                success=1;
284                return dataterms;
285              }
286            int add_linking_data_term(DataTerm& d) {
287                abac_aspect_add_linked_param(m_oset, d.term());
288                return 1;
289              }
290            std::vector<DataTerm> get_linked_data_terms(bool &success) {
291                abac_term_t **terms, **end;
292                int i;
293                terms = abac_param_list_vectorize(abac_aspect_linked_role_params(m_oset));
294                for (i = 0; terms[i] != NULL; ++i)
295                    ;
296                end = &terms[i];
297                std::vector<DataTerm> dataterms = std::vector<DataTerm>(terms, end);
298                abac_terms_free(terms);
299                success=1;
300                return dataterms;
301              }
302            abac_aspect_t *oset() {return m_oset;}
303        private:
304            abac_aspect_t *m_oset;
305    };
306
307
308    class ID {
309        public:
310            ID() : m_id(NULL) { } // do not use: here for swig
311            ID(abac_id_t *id): m_id(abac_id_dup(id)) 
312              { }
313            ID(const ID &id) { m_id =abac_id_dup(id.m_id); }
314            ~ID() { if(m_id) abac_id_free(m_id); }
315
316/* load an ID cert from a file
317Will throw an exception if the cert cannot be loaded */
318            ID(char *filename) {
319                m_id=abac_id_from_file(filename); 
320                if(m_id==NULL)
321                  abac_errx(1, "Id creation from filename failed");
322              }
323/* generates a new ID with the supplied CN and validity period
324   - CN must be alphanumeric and begin with a letter
325   - validity must be at least one second
326   Will throw an exception if either of the above is violated */
327            ID(char *cn, int validity) {
328                int rt=abac_id_generate(&m_id, cn, validity);
329                if(rt != ABAC_ID_SUCCESS) 
330                  abac_errx(1, "Id creation failed");
331              }
332/* loads the private key associated with the cert
333   will throw an exception if the key cannot be loaded */
334            void load_privkey(char *filename) {
335                int rt=abac_id_load_privkey(m_id, filename);
336                if(rt != 1) 
337                  abac_errx(1, "Failed to load private key");
338              }
339            abac_id_t *id() { return m_id; }
340
341/* returns the SHA1 keyid of the cert */
342            char *keyid() { return abac_id_keyid(m_id); }
343/* returns the CN (the parameter passed to the constructor or the
344   CN of the cert). */
345            char *name() { return abac_id_cn(m_id); }
346/* returns true if the ID has an associated private key */
347            bool has_privkey() {
348                return abac_id_has_privkey(m_id);
349              }
350/* writes a PEM-encoded cert to the file handle */
351            void write_cert(FILE *out) {
352                abac_id_write_cert(m_id, out); 
353              }
354/* writes a PEM-encoded cert to a file named out */
355            void write_cert(char *filename) {
356                FILE *out = fopen(filename, "w");
357                write_cert(out);
358                fclose(out);
359              }
360/* writes a PEM-encoded private key to the file handle
361   throws an exception if no private key is loaded */
362            void write_privkey(FILE *out) {
363                if(!has_privkey())
364                    abac_errx(1, "No privkey to write");
365                abac_id_write_privkey(m_id, out);
366              }
367/* writes a PEM-encoded private key a file named out
368   throws an exception if no private key is loaded */
369            void write_privkey(char *filename) {
370                FILE *out = fopen(filename, "w");
371                write_privkey(out);
372                fclose(out);
373              }
374/* returns a DER-encoded binary representation of the X.509 ID cert
375   associated with this ID.
376   can be passed to libabac's Context::load_id_chunk() */
377            abac_chunk_t cert_chunk() {
378                return abac_id_cert_chunk(m_id);
379              }
380        public:
381            abac_id_t *m_id;
382    };
383
384
385/* N.B., The way you use this class is by instantiating the object, adding
386   subjects to it, and then baking it. Only once it's baked can you access the
387   X.509 cert. Once it's been baked you can no longer add subjects to it. */
388    class Attribute {
389        public:
390            Attribute() : m_attr(NULL) { } // do not use: here for swig
391            Attribute(abac_attribute_t *attr): m_attr(abac_attribute_dup(attr)) 
392              { }
393            Attribute(abac_credential_t *cred) {
394                m_attr=abac_attribute_dup(abac_credential_attribute(cred));
395              }
396            Attribute(const Attribute &id) { 
397                m_attr =abac_attribute_dup(id.m_attr);
398              }
399            ~Attribute() { 
400                if(m_attr) abac_attribute_free(m_attr);
401              }
402/* Create an object to be signed by the given issuer with the given role
403   and validity period
404   An exception will be thrown if:
405     - the issuer has no private key
406     - the Head is invalid
407     - the validity period is invalid (must be >= 1 second) */
408            Attribute(Role& head, int validity) {
409                int rt=abac_attribute_create(&m_attr, head.role(), NULL, validity);
410                if(rt!=ABAC_ATTRIBUTE_SUCCESS)
411                    abac_errx(1, "attribute(role), unable to make an attribute");
412              }
413            Attribute(Oset& head, int validity) {
414                int rt=abac_attribute_create(&m_attr, head.oset(), NULL, validity);
415                if(rt!=ABAC_ATTRIBUTE_SUCCESS)
416                    abac_errx(1, "attribute(oset), unable to make an attribute");
417              }
418            bool add_tail(Role& tail) {
419                if(abac_attribute_add_tail(m_attr, tail.role()))
420                    return 1;
421                    else return 0;
422              }
423            bool add_tail(Oset& tail) {
424                if(abac_attribute_add_tail(m_attr, tail.oset()))
425                    return 1;
426                    else return 0;
427              }
428            char *head_string() {
429                abac_aspect_t *head=abac_attribute_head(m_attr);
430                char *string=abac_aspect_string(head);
431                return string;
432              }
433            char *tail_string() {
434                abac_aspect_t *tail=abac_attribute_tail(m_attr);
435                char *string=abac_aspect_string(tail);
436                return string;
437              }
438            char *head_typed_string() {
439                abac_aspect_t *head=abac_attribute_head(m_attr);
440                char *string=abac_aspect_typed_string(head);
441                return string;
442              }
443            char *tail_typed_string() {
444                abac_aspect_t *tail=abac_attribute_tail(m_attr);
445                char *string=abac_aspect_typed_string(tail);
446                return string;
447              }
448            char *string() {
449                char *head=head_string();
450                char *tail=tail_string();
451                if(head==NULL || tail==NULL)
452                    abac_errx(1, "attribute string, head and tail can not be NULL");
453                char *tmp=NULL;
454                asprintf(&tmp,"%s<-%s",head,tail);
455                return tmp;
456              }
457            char *typed_string() {
458                char *head=head_typed_string();
459                char *tail=tail_typed_string();
460                if(head==NULL || tail==NULL)
461                    abac_errx(1, "attribute string, head and tail can not be NULL");
462                char *tmp=NULL;
463                asprintf(&tmp,"%s<-%s",head,tail);
464                return tmp;
465              }
466            const Role &role_head() {
467                abac_aspect_t *head=abac_attribute_head(m_attr);
468                static Role role=Role(head);
469                return role;
470              }
471            const Oset &oset_head() {
472                abac_aspect_t *head=abac_attribute_tail(m_attr);
473                static Oset oset=Oset(head);
474                return oset;
475              }
476            std::vector<Role> role_tails(bool &success) {
477                abac_aspect_t **tails, **end;
478                int i;
479                tails = abac_attribute_tail_vectorized(m_attr);
480                for (i = 0; tails[i] != NULL; ++i)
481                    ;
482                end = &tails[i];
483                std::vector<Role> roles = std::vector<Role>(tails, end);
484                abac_aspects_free(tails);
485                success=1;
486                return roles;
487              }
488            std::vector<Oset> oset_tails(bool &success) {
489                abac_aspect_t **tails, **end;
490                int i;
491                tails = abac_attribute_tail_vectorized(m_attr);
492                for (i = 0; tails[i] != NULL; ++i)
493                    ;
494                end = &tails[i];
495                std::vector<Oset> osets = std::vector<Oset>(tails, end);
496                success=1;
497                abac_aspects_free(tails);
498                return osets;
499              }
500            abac_attribute_t *attribute() { return m_attr; }
501
502/* Generate the cert. Call this after you've added subjects to your cert.
503   This returns false if there are no subjects
504   This will throw an exception if the cert's already been baked. */
505            bool bake() {
506                /* can not bake in ABAC_CN mode */
507                if(USE("ABAC_CN"))
508                    abac_errx(1, "bake, can not bake the cert with env(ABAC_CN) set");
509                int rt=abac_attribute_bake(m_attr);
510                if(rt!=1)
511                    abac_errx(1, "bake, can not bake the cert");
512              }
513/* Returns true iff the cert has been baked. */
514            bool baked() {
515                return abac_attribute_baked(m_attr);
516              }
517/* Write the DER-encoded X.509 attribute cert to the open file handle
518   Throws an exception if the cert isn't baked */
519            void write_cert(FILE *out) {
520                int rt= abac_attribute_write(m_attr,out);
521                if(!rt)
522                    abac_errx(1, "write, cert is not baked");
523              }
524/* Write the DER-encoded X.509 attribute cert to a file named out
525   Throws an exception if the cert isn't baked */
526            void write_cert(char *filename) {
527                FILE *out = fopen(filename, "w");
528                printf("writing to %s\n", filename);
529                write_cert(out);
530                printf("done writing to %s\n", filename);
531                fclose(out);
532              }
533/* returns a DER-encoded binary representation of the X.509 attribute
534   cert associated with this cert
535   Throws an exception if the cert isn't baked
536   the chunk can be passed to libabac's Context::load_attribute_chunk() */
537            abac_chunk_t cert_chunk() {
538                return abac_attribute_cert_chunk(m_attr);
539              }
540/* generate yap clauses and injected into db */
541            int consume() {
542              /* attribute needs to be baked */ 
543                if(!baked()) {
544                    return ABAC_ATTRIBUTE_FAIL;
545                }
546              }
547      private:
548            abac_attribute_t *m_attr;
549     };
550
551
552    class Context {
553        public:
554            Context() { m_ctx = abac_context_new(); m_abac_version=strdup("1.0"); }
555            Context(const Context &context) { 
556                m_ctx = abac_context_dup(context.m_ctx);
557                m_abac_version=strdup(context.m_abac_version);
558              }
559            ~Context() { 
560                abac_context_free(m_ctx);
561                if(m_abac_version) free(m_abac_version);
562              }
563
564/* load an identity certificate, returns:
565      ABAC_CERT_SUCCESS   successfully loaded
566      ABAC_CERT_INVALID   invalid certificate (or file not found)
567      ABAC_CERT_BAD_SIG   invalid signature */
568            void dump_yap() {
569                show_yap_db("dump_yap");
570              }
571            int load_id(ABAC::ID& id) {
572                return abac_context_load_id_id(m_ctx, id.id());
573              }
574            int load_id_file(char *filename, char *keyfilename) {
575                return abac_context_load_id_file(m_ctx, filename, keyfilename);
576              }
577            int load_id_chunk(abac_chunk_t cert) { 
578                return abac_context_load_id_chunk(m_ctx, cert);
579              }
580/* load an attribute certificate, returns the same values as above
581   * additionally can return ABAC_CERT_MISSING_ISSUER if the issuer
582   certificate has not been loaded */
583            int load_attribute(ABAC::Attribute& a) {
584                return abac_context_load_attribute_attribute(m_ctx, a.attribute());
585              }
586            int load_attribute_file(char *filename) { 
587                return abac_context_load_attribute_file(m_ctx, filename);
588              }
589            int load_attribute_chunk(abac_chunk_t cert) {
590                return abac_context_load_attribute_chunk(m_ctx, cert);
591              }
592/* load a directory full of certificates:
593   first: ${path}/*_ID.{der,pem} as identity certificates
594   then: ${path}/*_attr.der as attribute certificates */
595            void load_directory(char *path) {
596                abac_context_load_directory(m_ctx, path);
597              }
598/* run the query:
599       role <-?- principal
600   returns true/false in success
601   returns a proof upon success, partial proof on failure */
602            std::vector<Attribute> query(char *role, char *principal, bool &success) {
603                 abac_credential_t **creds, **end;
604                 int i, success_int;
605
606                 creds = abac_context_query(m_ctx, role, principal, &success_int);
607                 success = success_int;
608
609                 for (i = 0; creds[i] != NULL; ++i)
610                    ;
611
612                 end = &creds[i];
613                 std::vector<Attribute> attributes = std::vector<Attribute>(creds, end);
614                 if(debug) printf("rules, got (%d)\n", i);
615
616                 abac_context_credentials_free(creds);
617
618                 return attributes;
619              }
620
621/* returns a vector of all the credentials loaded in the context */
622            std::vector<Attribute> context_credentials(bool &success) {
623                abac_credential_t **creds, **end;
624                int i;
625                success = 1;
626
627                creds = abac_context_credentials(m_ctx);
628                for (i = 0; creds[i] != NULL; ++i)
629                    ;
630
631                end = &creds[i];
632                std::vector<Attribute> attributes = std::vector<Attribute>(creds, end);
633                if(debug) printf("credentials, got (%d)\n", i);
634
635                abac_context_credentials_free(creds);
636                if(debug) show_yap_db("calling from context_credentials");
637                return attributes;
638              }
639           
640            char *version() const { return m_abac_version; }
641
642        private:
643            abac_context_t *m_ctx;
644            char *m_abac_version;
645    };
646
647    Constraint::Constraint(Role *role)
648    { m_constraint=abac_condition_create_from_aspect(role->role()); }
649    Constraint::Constraint(Oset *oset)
650    { m_constraint=abac_condition_create_from_aspect(oset->oset()); }
651}
652
653#endif /* __ABAC_HH__ */
Note: See TracBrowser for help on using the repository browser.