source: libabac/abac_verifier.c @ ca72963

mei_rt2mei_rt2_fix_1
Last change on this file since ca72963 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: 19.6 KB
Line 
1/**
2**  abac_verifier.c
3**/
4
5// include the GNU extension of asprintf
6#define _GNU_SOURCE
7
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <unistd.h>
11
12#include <assert.h>
13#include <stdio.h>
14
15#include <library.h>
16
17#include "abac_internal.h"
18#include "abac_verifier.h"
19
20#include "abac_util.h"
21#include "abac_rt.h"
22
23static int debug=0;
24
25extern abac_aspect_t *abac_yy_get_rule_head_aspect();
26extern abac_aspect_t *abac_yy_get_rule_tail_aspect();
27extern abac_list_t *abac_yy_get_rule_clauses();
28extern char* abac_decode_string(char *);
29extern void abac_yy_free_rule_clauses();
30extern char *generate_pl_type_clause(char *, int);
31
32extern void abac_print_aspect_string_with_condition(abac_aspect_t *role, FILE*);
33
34struct _abac_id_credential_t {
35    char *hashkeyid; 
36    abac_id_t *id;
37    char *pl_clause;
38
39    UT_hash_handle hh;
40};
41/* hash table base on sha with a p */
42abac_id_credential_t *id_creds = NULL;
43
44/* can store either role or oset */
45struct _abac_credential_t {
46    char *hashkeyid;
47    abac_attribute_t *attr;
48    abac_list_t *pl_clauses;
49
50    UT_hash_handle hh;
51};
52/* hash table base on encoded attr rule */
53abac_credential_t *attr_creds = NULL;
54/* linked list of all the attr's hashkeyid */
55abac_list_t *attr_hashkeyid_list = NULL;
56
57/*****************************************************************************/
58void abac_print_cred_info(abac_credential_t *cred, FILE *fp)
59{
60    if(fp == NULL)
61        fp=stdout;
62
63    abac_attribute_t *ptr=cred->attr;
64    abac_aspect_t *head=abac_attribute_head(ptr);
65    abac_aspect_t *tail=abac_attribute_tail(ptr);
66
67    if(debug) {
68        fprintf(fp,"---> printing out credential info cred(%d)..\n", (int) cred);
69        if(head) {
70            abac_print_aspect_string_with_condition(head,fp);
71        }
72        if(tail) {
73            abac_print_aspect_string_with_condition(tail,fp);
74        }
75
76        abac_list_t *clauses=cred->pl_clauses;
77        if (clauses != NULL) {
78            char *cur=NULL;
79            abac_list_foreach(clauses, cur,
80                fprintf(fp,"\n  a clause(%d):\n",(int)cur);
81                if(cur)
82                    fprintf(fp,"strlen(%d)loc(%d)(%s)\n", strlen(cur),(int)cur, cur);
83            );
84        }
85        } else {
86            fprintf(fp," ");
87            abac_print_aspect_string_with_condition(head,fp);
88            fprintf(fp," <- ");
89            abac_print_aspect_string_with_condition(tail,fp);
90            fprintf(fp,"\n");
91   }
92}
93
94//
95int abac_verify_idtype_type(char *type) {
96    int i;
97
98    if (type == NULL)
99        return 0;
100
101    for (i = 1; i <= _idtypename_cnt ; i++)
102        if(strcmp(type,_idtypename[i])==0)
103            return i;
104    return 0;
105}
106
107char *abac_idtype_string(int i)
108{
109    if(i > _idtypename_cnt) {
110        printf("bad idtypename idx %d\n", i);
111        panic("abac_idtype_string: went out of range on idtypename");
112    }
113    return (char*) _idtypename[i];
114}
115
116// convert a chunk to a lowercase binary string
117// malloc's the string
118static char *_chunk_to_string(chunk_t chunk) {
119    int i;
120
121    char *ret = abac_xmalloc(chunk.len * 2 + 1);
122
123    for (i = 0; i < chunk.len; ++i)
124        sprintf(ret + 2 * i, "%02x", chunk.ptr[i]);
125
126    return ret;
127}
128
129// verify that cert was issued by issuer
130// cert and issuer can be the same, in which case the self-sig is validated
131static int _verify_signature(certificate_t *issuer_cert, certificate_t *cert) {
132    if (cert->issued_by(cert, issuer_cert))
133        if (cert->get_validity(cert, NULL, NULL, NULL))
134            return 1;
135    return 0;
136}
137
138/**
139 * Init the verifier subsystem.
140 */
141void abac_verifier_init(void) {
142    // silence all debugging
143
144    if (!library_init(NULL))
145        exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
146
147    if (!lib->plugins->load(lib->plugins, NULL,
148            lib->settings->get_str(lib->settings, "pki.load", PLUGINS)))
149        exit(SS_RC_INITIALIZATION_FAILED);
150
151    attr_hashkeyid_list = abac_list_new();
152}
153
154/**
155 * Uninitialize the system, free up any allocated memory.
156 */
157void abac_verifier_deinit(void) {
158    abac_id_credential_t *ptr;
159    while ((ptr = id_creds) != NULL) {
160        HASH_DEL(id_creds, ptr);
161
162        free(ptr->hashkeyid);
163        free(ptr->pl_clause);
164        abac_id_free(ptr->id);
165        free(ptr);
166    }
167
168    abac_credential_t *ptr2;
169    while ((ptr2 = attr_creds) != NULL) {
170        HASH_DEL(attr_creds, ptr2);
171        if(debug) {
172           printf("attr_creds -- %s\n",ptr2->hashkeyid); 
173        }
174        free(ptr2->hashkeyid);
175        abac_attribute_free(ptr2->attr);
176        char *cur=NULL;
177        abac_list_foreach(ptr2->pl_clauses, cur,
178              free(cur);
179        );
180        free(ptr2->pl_clauses);
181        free(ptr2);
182    }
183
184    if(attr_hashkeyid_list) { 
185        char *cur;
186        if(attr_hashkeyid_list) {
187            abac_list_foreach(attr_hashkeyid_list, cur,
188                if(cur) free(cur);
189            );
190        }
191        abac_list_free(attr_hashkeyid_list);
192    }
193    library_deinit();
194}
195
196abac_id_credential_t *abac_verifier_add_id_credential(abac_id_t *a_id)
197{ 
198    abac_id_credential_t *id_cred;
199    char *cn=abac_id_cn(a_id);
200    char *keyid=abac_id_keyid(a_id);
201
202    if(debug) {
203         printf("abac_verifier_add_id_credential, cn(%s),keyid(%s)\n",
204                cn, keyid);
205    }
206
207    // add the abac_id to the map of id credentials
208    id_cred = abac_xmalloc(sizeof(abac_id_credential_t));
209    id_cred->hashkeyid = abac_xstrdup(keyid);
210    id_cred->id=abac_id_dup(a_id);
211
212    /* special handling here */
213    if(USE("ABAC_CN")) {
214        id_cred->pl_clause = generate_pl_type_clause(cn, abac_id_idtype(a_id));
215        } else {
216           id_cred->pl_clause=generate_pl_type_clause(prologIt(keyid), abac_id_idtype(a_id));
217    }
218    HASH_ADD_KEYPTR(hh, id_creds, id_cred->hashkeyid, strlen(id_cred->hashkeyid), id_cred);
219    if(debug)
220        printf("-->adding into id_creds, (%s)..cnt(%d)\n",
221                                   id_cred->hashkeyid, HASH_COUNT(id_creds));
222
223     return id_cred;
224}
225
226/**
227 * Load an ID
228 */
229static int _load_id(abac_id_t **a_id,certificate_t *cert, abac_id_credential_t **id_cred_ret) {
230    abac_id_credential_t *id_cred = NULL;
231    char *keyid = NULL;
232    chunk_t id;
233    int ret;
234    x509_t *x509 = (x509_t *)cert;
235
236    assert(cert != NULL);
237
238    // get the key ID, add p to keyid SHA here */
239    id = x509->get_subjectKeyIdentifier(x509);
240    keyid = _chunk_to_string(id);
241
242    /* Mike said this is the way it is */
243    char *str;
244    int rv = asprintf(&str, "%Y", cert->get_issuer(cert));
245
246    /* add p to cn name here */
247    char *cn=(char *)abac_xmalloc(strlen(str)+2);
248    cn[0]='p';
249    int n=sscanf(str,"CN=%s", &(cn[1]));
250    if ( n!=1 ) { 
251        ret = ABAC_CERT_BAD_CN;
252        goto error;
253    }
254
255    if(debug) {
256        printf ("DEBUG:keyid %s \n", keyid);
257        printf( "DEBUG:issuer '%s' \n", str);
258        printf ("DEBUG:cn %s \n", cn);
259    }
260    free(str);
261
262    // if we already have this cert 'error' with success
263    HASH_FIND_STR(id_creds, keyid, id_cred);
264    if (id_cred != NULL) {
265        if(debug) printf("existing cert \n");
266        ret = ABAC_CERT_EXISTS;
267        goto error;
268    }
269
270    // validate sig
271    ret = _verify_signature(cert, cert);
272    if (!ret) {
273        ret = ABAC_CERT_BAD_SIG;
274        goto error;
275    }
276
277    // success, add a new abac_id
278    if(*a_id==NULL) {
279        *a_id=abac_id_keyid_new(keyid,cn,cert);
280    }
281
282    abac_id_credential_t *n_id_cred=abac_verifier_add_id_credential(*a_id);
283    *id_cred_ret=n_id_cred;
284
285    return ABAC_CERT_SUCCESS;
286
287error:
288    if (keyid != NULL) free(keyid);
289    if (cn != NULL) free(cn);
290
291    return ret;
292}
293
294/* collect all the creds stored so far */
295abac_stack_t *abac_verifier_dump_creds()
296{
297    abac_stack_t *cred_list = abac_stack_new();
298
299    int cnt=0;
300    if(attr_hashkeyid_list) {
301        char *keyid;
302        abac_credential_t *cred;
303        abac_list_foreach(attr_hashkeyid_list, keyid,
304            cred=abac_credential_lookup(keyid);
305            abac_stack_push(cred_list, cred);
306            cnt++;
307        );
308    }
309    return cred_list;
310}
311
312
313static void check_id_cred(abac_id_credential_t *id_cred)
314{
315    if(id_cred) {
316        printf("checking on this id_cred location %d\n", (int)id_cred);
317        printf("  --> sha is (%s)\n", abac_id_keyid(id_cred->id));
318        printf("  --> cn is (%s)\n", abac_id_cn(id_cred->id));
319    }
320}
321
322/**
323 * Load an attribute cert as string.
324 * have minimum syntax & validity check
325 */
326static int _load_attribute_string(char* attr_string) {
327    printf("NOT implemented yet!!!");
328    return ABAC_CERT_INVALID;
329}
330
331int _exist(char *filename)
332{
333   struct stat stbuf;
334   if(stat(filename,&stbuf) == -1)
335       return 0;
336   return 1;
337}
338
339/**
340 * Load an ID cert from a file.
341 */
342int abac_verifier_load_id_file(char *filename, char *keyfilename, abac_id_credential_t **id_cred_ret) {
343    abac_id_t *id=NULL;
344    if (lib == NULL)
345        errx(1, "looks like you didn't call libabac_init() (lib is NULL)");
346
347    if(debug) printf("loading id file... %s\n", filename);
348
349    // load the cert, with pubic key
350    certificate_t *cert = lib->creds->create(
351        lib->creds, CRED_CERTIFICATE, CERT_X509,
352        BUILD_FROM_FILE, filename,
353        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
354        BUILD_END
355    );
356
357    if (cert == NULL)
358        return ABAC_CERT_INVALID;
359
360    int rc=_load_id(&id,cert,id_cred_ret);
361    if(rc==ABAC_CERT_EXISTS) {
362        if(debug) printf("abac_verifier_load_id_files: id already exists\n");
363        return ABAC_CERT_SUCCESS;
364    } 
365
366    /* try to load the private key if it is there */
367    if((rc==ABAC_CERT_SUCCESS) &&  _exist(keyfilename)) {
368        if(debug) printf("loading... %s\n", keyfilename);
369        int keyrc=abac_id_load_privkey(id, keyfilename);
370        if(debug) {
371           if(keyrc == 1) printf("..load_id_file: load(%s) with a private key\n",filename);
372               else printf("..load_id_file: load(%s) without a private key\n",filename);
373        }
374    }
375    return rc;
376}
377
378/**
379 * Load an ID cert from a abac_id_t
380 */
381int abac_verifier_load_id_id(abac_id_t *id, abac_id_credential_t **id_cred_ret) {
382    certificate_t *cert = abac_id_cert(id);
383    return _load_id(&id,cert,id_cred_ret);
384}
385
386/**
387 * Load an ID cert from a chunk.
388 */
389int abac_verifier_load_id_chunk(chunk_t chunk, abac_id_credential_t **id_cred_ret) {
390    abac_id_t *id=NULL;
391    // load the cert
392    certificate_t *cert = lib->creds->create(
393        lib->creds, CRED_CERTIFICATE, CERT_X509,
394        BUILD_BLOB_ASN1_DER, chunk,
395        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
396        BUILD_END
397    );
398    if (cert == NULL)
399        return ABAC_CERT_INVALID;
400    return _load_id(&id, cert,id_cred_ret);
401}
402
403
404void abac_print_clauses(abac_list_t *clauses, FILE *fp)
405{
406    if (clauses != NULL) {
407        char *cur;
408        printf("total-- %d clauses\n", abac_list_size(clauses));
409        abac_list_foreach(clauses, cur,
410            if(cur) {
411                if(fp)
412                    fprintf (fp,"a clause, %d(%s)\n", (int)cur,cur);
413                    else printf ("a clause, %d(%s)\n", (int)cur,cur);
414            }
415        );
416    }
417}
418
419abac_id_credential_t *abac_id_credential_dup(abac_id_credential_t *ptr) {
420    assert(ptr != NULL);
421    abac_id_dup(ptr->id);
422    return ptr;
423}
424
425abac_id_t *abac_id_credential_id(abac_id_credential_t *ptr)
426{
427    assert(ptr);
428    return ptr->id;
429}
430
431
432abac_id_credential_t *abac_id_credential_lookup(char *pname)
433{
434    abac_id_credential_t *id_cred=NULL;
435    HASH_FIND_STR(id_creds, pname, id_cred);
436    return id_cred;
437}
438
439void abac_id_credential_free(abac_id_credential_t *ptr)
440{
441    if (ptr == NULL)
442        return;
443
444    // this is very hacky...
445    int last=abac_id_lastone(ptr->id);
446    if(!last) {
447        abac_id_free(ptr->id);
448        } else {
449            free(ptr->hashkeyid);
450            if(ptr->pl_clause)
451                free(ptr->pl_clause);
452            abac_id_free(ptr->id);
453            HASH_DEL(id_creds, ptr);
454            free(ptr);
455    }
456}
457
458/****************************************************************************/
459
460static int _verify_valid_credential(certificate_t *cert,
461abac_credential_t **cred_ret, char *encoded_attr_string)
462{
463    abac_aspect_t *head_aspect = NULL;
464    abac_aspect_t *tail_aspect = NULL;
465    abac_list_t *clauses=NULL;
466    abac_id_credential_t *id_cred;
467    abac_id_t *issuer_id;
468    int ret, i;
469
470    // get the attr
471    head_aspect = abac_yy_get_rule_head_aspect();
472    tail_aspect = abac_yy_get_rule_tail_aspect();
473    clauses = abac_yy_get_rule_clauses();
474
475    // get the issuer based on keyid
476    char *principalname = abac_aspect_principal_principalname(head_aspect);
477    if(debug) printf("LOOKING for %s\n", principalname);
478
479    HASH_FIND_STR(id_creds, principalname, id_cred);
480    if(id_cred == NULL) {
481        ret = ABAC_CERT_MISSING_ISSUER;
482        if(debug)
483             printf("can not find %s in id_creds\n", principalname);
484        goto error;
485    }
486    issuer_id=id_cred->id;
487    if (issuer_id == NULL) {
488        ret = ABAC_CERT_MISSING_ISSUER;
489        if(debug)
490             printf("can not find %s in id_creds\n", principalname);
491        goto error;
492    }
493
494
495    // make sure the issuer's signed it
496    ret = _verify_signature(abac_id_cert(issuer_id), cert);
497    if (!ret) {
498        abac_yy_set_error_code(ABAC_RT_CERT_BAD_SIG);
499        goto error;
500    }
501
502    // at this point we know we have a good attribute cert baked it in
503    abac_attribute_t *attr=abac_attribute_new(issuer_id, cert, cert->get_ref(cert));
504    abac_attribute_set_head(attr, head_aspect);
505    abac_attribute_add_tail(attr, tail_aspect);
506
507    abac_credential_t *cred = abac_xmalloc(sizeof(abac_credential_t));
508    cred->hashkeyid=abac_xstrdup(encoded_attr_string);
509    cred->attr=attr;
510    cred->pl_clauses = clauses;
511    *cred_ret = cred;
512
513    // success, add the key to the map of certificates
514    HASH_ADD_KEYPTR(hh, attr_creds, cred->hashkeyid, strlen(cred->hashkeyid), cred);
515
516    assert(attr_hashkeyid_list);
517    abac_list_add(attr_hashkeyid_list, abac_xstrdup(cred->hashkeyid));
518    return ABAC_CERT_SUCCESS;
519
520error:
521    if (head_aspect) abac_aspect_free(head_aspect);
522    if (tail_aspect) abac_aspect_free(tail_aspect);
523    abac_yy_free_rule_clauses();
524
525    return ret;
526}
527
528/**
529 * Load an attribute cert.
530 * Returns true only if the certificate is valid and is issued by the proper
531 * authority.
532 */
533static int _load_attribute_cert(certificate_t *cert, abac_credential_t **cred_ret) {
534    ietf_attributes_t *attr_cert = NULL;
535    abac_id_credential_t *issuer;
536    int ret, i;
537
538    // get the attr
539    ac_t *ac = (ac_t *)cert;
540    attr_cert = ac->get_groups(ac);
541    if (attr_cert == NULL) {
542        ret = ABAC_CERT_INVALID;
543        goto error;
544    }
545
546    char *encoded_attr_string=attr_cert->get_string(attr_cert);
547    char *attr_string = abac_decode_string(encoded_attr_string);
548    if(debug)
549         printf("string to be yyparse..(%s)\n",attr_string);
550
551    if (attr_string == NULL) {
552        ret = ABAC_CERT_INVALID;
553        goto error;
554    }
555
556    /* call into yacc parser */
557    abac_reset_yyfptr(attr_string);
558    abac_yy_init();
559    int rc=yyparse();
560    if (rc) {
561        ret = ABAC_CERT_INVALID;
562        goto error;
563    }
564
565    ret=_verify_valid_credential(cert,cred_ret,encoded_attr_string);
566
567    // free up some crap
568    attr_cert->destroy(attr_cert);
569
570    return ABAC_CERT_SUCCESS;
571
572error:
573    if (cert) cert->destroy(cert);
574    if (attr_cert) attr_cert->destroy(attr_cert);
575    return ret;
576}
577
578/**
579 * Load an attribute cert from a abac_attribute_t.
580 */
581int abac_verifier_load_attribute_cert_attribute(abac_attribute_t *attr, abac_credential_t **cred) {
582    // load the cert
583    certificate_t *cert = abac_attribute_cert(attr);
584    if (cert == NULL)
585        return ABAC_CERT_INVALID;
586   
587    // XXX need to skip the parsing part
588    return _load_attribute_cert(cert, cred);
589}
590
591/**
592 * Load an attribute cert from a file.
593 */
594int abac_verifier_load_attribute_cert_file(char *filename, abac_credential_t **cred) {
595    // load the cert
596    if(debug) printf("..loading attr file %s\n", filename);
597    certificate_t *cert = lib->creds->create(
598        lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
599        BUILD_FROM_FILE, filename,
600        BUILD_END
601    );
602    if (cert == NULL)
603        return ABAC_CERT_INVALID;
604    return _load_attribute_cert(cert, cred);
605}
606
607/**
608 * Load an attribute cert from a chunk.
609 */
610int abac_verifier_load_attribute_cert_chunk(chunk_t chunk, abac_credential_t **cred) {
611    // load the cert
612    certificate_t *cert = lib->creds->create(
613        lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
614        BUILD_BLOB_ASN1_DER, chunk,
615        BUILD_END
616    );
617    if (cert == NULL)
618        return ABAC_CERT_INVALID;
619    return _load_attribute_cert(cert, cred);
620}
621
622/**
623 * Return the encoding of the attribute cert.
624 */
625abac_chunk_t abac_credential_attribute_cert(abac_credential_t *cred) {
626    abac_attribute_t *ptr=cred->attr;
627    certificate_t *cert=abac_attribute_cert(ptr);
628    chunk_t encoding = cert->get_encoding(cert);
629    abac_chunk_t ret = { encoding.ptr, encoding.len };
630    return ret;
631}
632
633/**
634 * Return the encoding of the issuer cert.
635 */
636abac_chunk_t abac_credential_issuer_cert(abac_credential_t *cred) {
637    certificate_t *issuer_cert=abac_attribute_issuer_cert(cred->attr);
638    assert(issuer_cert);
639    chunk_t encoding = issuer_cert->get_encoding(issuer_cert);
640    abac_chunk_t ret = { encoding.ptr, encoding.len };
641    return ret;
642}
643
644/**
645 * Return the clause of the cert
646 */
647abac_list_t *abac_credential_clauses(abac_credential_t *cred) {
648    return cred->pl_clauses;
649}
650
651abac_attribute_t *abac_credential_attribute(abac_credential_t *cred) {
652    assert(cred);
653    return cred->attr;
654}
655
656/**
657 * Increase the ref count of a credential.
658 */
659abac_credential_t *abac_credential_dup(abac_credential_t *cred) {
660    assert(cred != NULL);
661
662    abac_attribute_dup(cred->attr);
663    return cred;
664}
665
666/**
667 *  lookup for a credential.
668 */
669abac_credential_t *abac_credential_lookup(char* cred_string)
670{
671    if(debug)
672        printf("abac_credential_lookup: looking for (%s)\n", cred_string);
673    abac_credential_t *attr_cred;
674    HASH_FIND_STR(attr_creds, cred_string, attr_cred);
675    if (attr_cred == NULL) {
676        if(debug) printf("DEBUG:NOT FOUND..\n");
677        return NULL;
678    }
679    abac_credential_t *rt=abac_credential_dup(attr_cred);
680    if(debug) printf("DEBUG:FOUND.. (%d) returning, (%d)\n", (int)attr_cred, (int) rt);
681    return rt;
682}
683
684/**
685 * Decrease the reference count of a credential, freeing it when it reaches 0.
686 */
687void abac_credential_free(abac_credential_t *cred)
688{
689    if(debug)
690        printf("abac_credential_free:freeing cred(%d)clause(%d)\n", (int)cred, (int)cred->pl_clauses);
691
692    if (cred == NULL)
693        return;
694
695    // this is very hacky...
696    int last=abac_attribute_lastone(cred->attr);
697    if(!last) {
698        abac_attribute_free(cred->attr);
699        } else {
700            free(cred->hashkeyid);
701            char *cur=NULL;
702            abac_list_foreach(cred->pl_clauses, cur,
703                free(cur);
704            );
705            abac_attribute_free(cred->attr);
706            HASH_DEL(attr_creds, cred);
707            free(cred);
708    }
709}
710
711char *abac_id_clause(abac_id_credential_t *id_cred)
712{
713    if(id_cred)
714        return id_cred->pl_clause;
715    return NULL;
716}
717
718/* retrieve the cn that is associated with this sha_string */
719char *abac_cn_with_sha(char *sha_string) {
720
721    // get the issuer based on keyid
722    abac_id_credential_t *id_cred;
723    HASH_FIND_STR(id_creds, sha_string, id_cred);
724    if (id_cred == NULL) {
725        return NULL;
726    }
727    if(debug)
728        check_id_cred(id_cred);
729    return abac_id_cn(id_cred->id);
730}
731
732char *abac_idtype_with_sha(char* sha_string)
733{ 
734    // get the issuer based on keyid
735    abac_id_credential_t *id_cred;
736    HASH_FIND_STR(id_creds, sha_string, id_cred);
737    if (id_cred == NULL) {
738        return NULL;
739    }
740    int idtype=abac_id_idtype(id_cred->id);
741   
742    return abac_idtype_string(idtype);
743}
744
745abac_aspect_t *abac_credential_head(abac_credential_t *cred) {
746    return abac_attribute_head(cred->attr); 
747}
748
749abac_aspect_t *abac_credential_tail(abac_credential_t *cred) {
750    return abac_attribute_tail(cred->attr); 
751}
752
753
Note: See TracBrowser for help on using the repository browser.