source: libabac/abac_verifier.c @ a17f536

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

1) modified code all around to add support for encrypted private key for

ID credential

2) add new abac_key_t structure (abac_key.c)
3) add new keycheck option to creddy
4) add 2 new test suites

  • Property mode set to 100644
File size: 32.8 KB
Line 
1/**
2**  abac_verifier.c
3**/
4
5// include the GNU extension of asprintf
6#define _GNU_SOURCE
7
8#include <stdio.h>
9#include <regex.h>
10#include <sys/mman.h>
11#include <fcntl.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <unistd.h>
15
16
17#include <assert.h>
18#include <stdio.h>
19
20#include <library.h>
21
22#include "abac_internal.h"
23#include "abac_verifier.h"
24
25#include "abac_util.h"
26#include "abac_rt.h"
27
28static int debug=0;
29
30/* from abac_attribute.c */
31extern char *get_cred_encoding(abac_attribute_t *ptr);
32
33extern abac_aspect_t *abac_yy_get_rule_head_aspect();
34extern abac_aspect_t *abac_yy_get_rule_tail_aspect();
35extern abac_list_t *abac_yy_get_rule_clauses();
36extern char* abac_decode_string(char *);
37extern void abac_yy_free_rule_clauses();
38extern char *generate_pl_type_clause(char *, int);
39extern abac_list_t *generate_pl_clauses(abac_aspect_t *, abac_aspect_t *);
40extern void generate_pl_set_abac_yyfptr_encoded(char *string);
41
42extern void abac_print_aspect_string_with_condition(abac_aspect_t *role, FILE*);
43
44extern int abac_id_load_privkey_chunk(abac_id_t *ptr, chunk_t keychunk);
45
46struct _abac_id_credential_t {
47    char *hashkeyid; 
48    abac_id_t *id;
49    char *pl_clause;
50
51    UT_hash_handle hh;
52};
53/* hash table base on sha with a p */
54abac_id_credential_t *id_creds = NULL;
55/* linked list of all the ids's hashkeyid */
56abac_list_t *id_hashkeyid_list = NULL;
57
58/* can store either role or oset */
59struct _abac_credential_t {
60    char *hashkeyid;
61    abac_attribute_t *attr;
62    abac_list_t *pl_clauses;
63
64    UT_hash_handle hh;
65};
66/* hash table base on encoded attr rule */
67abac_credential_t *attr_creds = NULL;
68/* linked list of all the attr's hashkeyid */
69abac_list_t *attr_hashkeyid_list = NULL;
70
71/*****************************************************************************/
72void abac_print_cred_info(abac_credential_t *cred, FILE *fp)
73{
74    if(fp == NULL)
75        fp=stdout;
76
77    abac_attribute_t *ptr=cred->attr;
78    abac_aspect_t *head=abac_attribute_head(ptr);
79    abac_aspect_t *tail=abac_attribute_tail(ptr);
80
81    if(debug) {
82        fprintf(fp,"---> printing out credential info cred(%d)..\n", (int) cred);
83        if(head) {
84            abac_print_aspect_string_with_condition(head,fp);
85        }
86        if(tail) {
87            abac_print_aspect_string_with_condition(tail,fp);
88        }
89
90        abac_list_t *clauses=cred->pl_clauses;
91        if (clauses != NULL) {
92            char *cur=NULL;
93            abac_list_foreach(clauses, cur,
94                fprintf(fp,"\n  a clause(%d):\n",(int)cur);
95                if(cur)
96                    fprintf(fp,"strlen(%d)loc(%d)(%s)\n", strlen(cur),(int)cur, cur);
97            );
98        }
99        } else {
100            fprintf(fp," ");
101            abac_print_aspect_string_with_condition(head,fp);
102            fprintf(fp," <- ");
103            abac_print_aspect_string_with_condition(tail,fp);
104            fprintf(fp,"\n");
105   }
106}
107
108void abac_print_prin_info(abac_id_credential_t *prin, FILE *fp)
109{
110    if(fp == NULL)
111        return;
112
113    abac_id_t *ptr=abac_id_credential_id(prin);
114
115    if(debug) fprintf(fp,"---> printing out principal info ..\n");
116    if(abac_id_has_privkey(ptr))
117        fprintf(fp," (%s,%s,y)\n",abac_id_name(ptr),abac_id_idtype_string(ptr));
118        else
119            fprintf(fp," (%s,%s,n)\n",abac_id_name(ptr),abac_id_idtype_string(ptr));
120}
121
122//
123int abac_verify_idtype_type(char *type) {
124    int i;
125
126    if (type == NULL)
127        return 0;
128
129    for (i = 1; i <= _idtypename_cnt ; i++)
130        if(strcmp(type,_idtypename[i])==0)
131            return i;
132    return 0;
133}
134
135char *abac_idtype_string(int i)
136{
137    if(i > _idtypename_cnt) {
138        printf("bad idtypename idx %d\n", i);
139        panic("abac_idtype_string: went out of range on idtypename");
140    }
141    return (char*) _idtypename[i];
142}
143
144// convert a chunk to a lowercase binary string
145// malloc's the string
146static char *_chunk_to_string(chunk_t chunk) {
147    int i;
148
149    char *ret = abac_xmalloc(chunk.len * 2 + 1);
150
151    for (i = 0; i < chunk.len; ++i)
152        sprintf(ret + 2 * i, "%02x", chunk.ptr[i]);
153
154    return ret;
155}
156
157// verify that cert was issued by issuer
158// cert and issuer can be the same, in which case the self-sig is validated
159static int _verify_signature(certificate_t *issuer_cert, certificate_t *cert) {
160    if (cert->issued_by(cert, issuer_cert))
161        if (cert->get_validity(cert, NULL, NULL, NULL))
162            return 1;
163    return 0;
164}
165
166/**
167 * Init the verifier subsystem.
168 */
169void abac_verifier_init(void) {
170    // silence all debugging
171
172    if (!library_init(NULL))
173        exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
174
175    if (!lib->plugins->load(lib->plugins, NULL,
176            lib->settings->get_str(lib->settings, "pki.load", PLUGINS)))
177        exit(SS_RC_INITIALIZATION_FAILED);
178
179    attr_hashkeyid_list = abac_list_new();
180    id_hashkeyid_list = abac_list_new();
181}
182
183/**
184 * Uninitialize the system, free up any allocated memory.
185 */
186void abac_verifier_deinit(void) {
187    if(debug)printf("abac_verifier_deinit... being called..\n");
188
189    abac_id_credential_t *ptr;
190    while ((ptr = id_creds) != NULL) {
191        if(debug) printf("abac_verifier_deinit: deleting id (%s)\n",abac_id_name(ptr->id));
192        HASH_DEL(id_creds, ptr);
193
194        free(ptr->hashkeyid); 
195        free(ptr->pl_clause);
196        abac_id_free(ptr->id); 
197        free(ptr);
198    }
199
200    abac_credential_t *ptr2;
201    while ((ptr2 = attr_creds) != NULL) {
202        HASH_DEL(attr_creds, ptr2);
203        if(debug) {
204           printf("abac_verifier_deinit: deleting attr hashkey(%s)\n",ptr2->hashkeyid); 
205        }
206        free(ptr2->hashkeyid);
207        abac_attribute_free(ptr2->attr);
208        char *cur=NULL;
209        abac_list_foreach(ptr2->pl_clauses, cur,
210              free(cur);
211        );
212        free(ptr2->pl_clauses);
213        free(ptr2);
214    }
215
216    if(attr_hashkeyid_list) { 
217        char *cur;
218        if(attr_hashkeyid_list) {
219            abac_list_foreach(attr_hashkeyid_list, cur,
220                if(cur) free(cur);
221            );
222        }
223        abac_list_free(attr_hashkeyid_list);
224    }
225
226    if(id_hashkeyid_list) { 
227        if(debug) printf("looking to free id_hashkeyid_lst..\n");
228        char *cur;
229        if(id_hashkeyid_list) {
230            abac_list_foreach(id_hashkeyid_list, cur,
231                if(cur) {
232                   if(debug) printf("hum.. id hashkey being freed.. %s\n", cur); 
233                   free(cur);
234                }
235            );
236        }
237        abac_list_free(id_hashkeyid_list);
238    }
239
240    library_deinit();
241}
242
243abac_id_credential_t *abac_verifier_add_id_credential(abac_id_t *a_id)
244{ 
245    abac_id_credential_t *id_cred;
246    char *cn=abac_id_cn(a_id);
247    char *keyid=abac_id_keyid(a_id);
248
249    if(debug) {
250         printf("abac_verifier_add_id_credential, cn(%s),keyid(%s)\n",
251                cn, keyid);
252    }
253
254    // add the abac_id to the map of id credentials
255    id_cred = abac_xmalloc(sizeof(abac_id_credential_t));
256    id_cred->hashkeyid = abac_xstrdup(keyid);
257    id_cred->id=abac_id_dup(a_id);
258
259    /* special handling here */
260    if(USE("ABAC_CN")) {
261        id_cred->pl_clause = generate_pl_type_clause(cn, abac_id_idtype(a_id));
262        } else {
263           id_cred->pl_clause=generate_pl_type_clause(prologIt(keyid), abac_id_idtype(a_id));
264    }
265    HASH_ADD_KEYPTR(hh, id_creds, id_cred->hashkeyid, strlen(id_cred->hashkeyid), id_cred);
266    if(debug)
267        printf("-->adding into id_creds, (%s)..cnt(%d)(%d)\n",
268                                   id_cred->hashkeyid, HASH_COUNT(id_creds),(int)id_cred);
269
270    assert(id_hashkeyid_list);
271    abac_list_add(id_hashkeyid_list, abac_xstrdup(id_cred->hashkeyid));
272    return id_cred;
273}
274
275/**
276 * Load an ID
277 */
278static int _load_id(abac_id_t **a_id,certificate_t *cert, abac_id_credential_t **id_cred_ret) {
279    abac_id_credential_t *id_cred = NULL;
280    char *keyid = NULL;
281    chunk_t id;
282    int ret;
283    x509_t *x509 = (x509_t *)cert;
284
285    assert(cert != NULL);
286
287    // get the key ID, add p to keyid SHA here */
288    id = x509->get_subjectKeyIdentifier(x509);
289    keyid = _chunk_to_string(id);
290
291    /* Mike said this is the way it is */
292    char *str;
293    int rv = asprintf(&str, "%Y", cert->get_issuer(cert));
294
295    /* add p to cn name here */
296    char *cn=(char *)abac_xmalloc(strlen(str)+2);
297    cn[0]='p';
298    int n=sscanf(str,"CN=%s", &(cn[1]));
299    if ( n!=1 ) { 
300        ret = ABAC_CERT_BAD_CN;
301        goto error;
302    }
303
304    if(debug) {
305        printf ("DEBUG:keyid %s \n", keyid);
306        printf( "DEBUG:issuer '%s' \n", str);
307        printf ("DEBUG:cn %s \n", cn);
308    }
309    free(str);
310
311    // if we already have this cert 'error' with success
312    HASH_FIND_STR(id_creds, keyid, id_cred);
313    if (id_cred != NULL) {
314        if(debug) printf("existing cert \n");
315        ret = ABAC_CERT_EXISTS;
316        goto error;
317    }
318
319    // validate sig
320    ret = _verify_signature(cert, cert);
321    if (!ret) {
322        ret = ABAC_CERT_BAD_SIG;
323        goto error;
324    }
325
326    // success, add a new abac_id
327    if(*a_id==NULL) {
328        *a_id=abac_id_keyid_new(keyid,cn,cert);
329    }
330
331    abac_id_credential_t *n_id_cred=abac_verifier_add_id_credential(*a_id);
332    *id_cred_ret=n_id_cred;
333
334    return ABAC_CERT_SUCCESS;
335
336error:
337    if (keyid != NULL) free(keyid);
338    if (cn != NULL) free(cn);
339
340    return ret;
341}
342
343/* collect all the creds stored so far */
344abac_stack_t *abac_verifier_dump_creds()
345{
346    abac_stack_t *cred_list = abac_stack_new();
347
348    int cnt=0;
349    if(attr_hashkeyid_list) {
350        char *keyid;
351        abac_credential_t *cred;
352        abac_list_foreach(attr_hashkeyid_list, keyid,
353            cred=abac_credential_lookup(keyid);
354            abac_stack_push(cred_list, cred);
355            cnt++;
356        );
357    }
358    if(debug) printf("abac_verifier_dump_cred: %d\n",cnt);
359    return cred_list;
360}
361
362/* collect all the id stored so far */
363abac_stack_t *abac_verifier_dump_principals()
364{
365    abac_stack_t *id_list = abac_stack_new();
366
367    int cnt=0;
368    if(id_hashkeyid_list) {
369        char *keyid;
370        abac_id_credential_t *id;
371        abac_list_foreach(id_hashkeyid_list, keyid,
372            id=abac_id_credential_lookup(keyid);
373            abac_stack_push(id_list, id);
374            cnt++;
375        );
376    }
377    if(debug) printf("abac_verifier_dump_principals: %d\n",cnt);
378    return id_list;
379}
380
381
382static void check_id_cred(abac_id_credential_t *id_cred)
383{
384    if(id_cred) {
385        printf("checking on this id_cred location %d\n", (int)id_cred);
386        printf("  --> sha is (%s)\n", abac_id_keyid(id_cred->id));
387        printf("  --> cn is (%s)\n", abac_id_cn(id_cred->id));
388    }
389}
390
391/**
392 * Load an attribute cert as string.
393 * have minimum syntax & validity check
394 */
395static int _load_attribute_string(char* attr_string) {
396    printf("NOT implemented yet!!!");
397    return ABAC_CERT_INVALID;
398}
399
400/**
401 * Load an ID cert from a file.
402 */
403int abac_verifier_load_id_file_key_file(char *filename, char *keyfilename,
404abac_id_credential_t **id_cred_ret)
405{
406    abac_id_t *id=NULL;
407    if (lib == NULL)
408        errx(1, "looks like you didn't call libabac_init() (lib is NULL)");
409
410    if(debug) printf("loading id file... %s\n", filename);
411
412    // load the cert, with public key
413    certificate_t *cert = lib->creds->create(
414        lib->creds, CRED_CERTIFICATE, CERT_X509,
415        BUILD_FROM_FILE, filename,
416        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
417        BUILD_END
418    );
419
420    if (cert == NULL)
421        return ABAC_CERT_INVALID;
422
423    int rc=_load_id(&id,cert,id_cred_ret);
424    if(rc==ABAC_CERT_EXISTS) {
425        if(debug) printf("abac_verifier_load_id_files: id already exists\n");
426        return ABAC_CERT_SUCCESS;
427    } 
428
429    /* try to load the private key if it is there */
430    if((rc==ABAC_CERT_SUCCESS) && keyfilename!=NULL && file_exist(keyfilename)) {
431        if(debug) printf("loading... %s\n", keyfilename);
432        int keyrc=abac_id_load_privkey_file(id, keyfilename);
433        if(debug) {
434           if(keyrc == 1) printf("..load_id_file: load(%s) with a private key\n",filename);
435               else printf("..load_id_file: load(%s) without a private key\n",filename);
436        }
437    }
438    return ABAC_CERT_SUCCESS;
439}
440
441int abac_verifier_load_enc_id_file_key_file(char *filename, char *keyfilename,
442char *pfile, abac_id_credential_t **id_cred_ret)
443{
444    abac_id_t *id=NULL;
445    if (lib == NULL)
446        errx(1, "looks like you didn't call libabac_init() (lib is NULL)");
447
448    if(debug) printf("loading id file... %s\n", filename);
449
450    // load the cert, with public key
451    certificate_t *cert = lib->creds->create(
452        lib->creds, CRED_CERTIFICATE, CERT_X509,
453        BUILD_FROM_FILE, filename,
454        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
455        BUILD_END
456    );
457
458    if (cert == NULL)
459        return ABAC_CERT_INVALID;
460
461    int rc=_load_id(&id,cert,id_cred_ret);
462    if(rc==ABAC_CERT_EXISTS) {
463        if(debug) printf("abac_verifier_load_id_files: id already exists\n");
464        return ABAC_CERT_SUCCESS;
465    } 
466
467    /* try to load the private key if it is there */
468    if((rc==ABAC_CERT_SUCCESS) && keyfilename!=NULL && file_exist(keyfilename)) {
469        if(debug) printf("loading... %s\n", keyfilename);
470        int keyrc=abac_id_load_enc_privkey_file(id, keyfilename, pfile);
471        if(debug) {
472           if(keyrc == 1) printf("..load_id_file: load(%s) with a private key\n",filename);
473               else printf("..load_id_file: load(%s) without a private key\n",filename);
474        }
475    }
476    return ABAC_CERT_SUCCESS;
477}
478
479/**
480 * Load an ID cert from a abac_id_t
481 */
482int abac_verifier_load_id_id(abac_id_t *id, abac_id_credential_t **id_cred_ret) {
483    certificate_t *cert = abac_id_cert(id);
484    return _load_id(&id,cert,id_cred_ret);
485}
486
487/**
488 * Load an ID cert from a chunk.
489 */
490int abac_verifier_load_id_pem_chunk(chunk_t chunk, abac_id_credential_t **id_cred_ret) {
491    abac_id_t *id=NULL;
492    // load the cert
493    certificate_t *cert = lib->creds->create(
494        lib->creds, CRED_CERTIFICATE, CERT_X509,
495        BUILD_BLOB_PEM, chunk,
496        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
497        BUILD_END
498    );
499    if (cert == NULL)
500        return ABAC_CERT_INVALID;
501    return _load_id(&id, cert,id_cred_ret);
502}
503/**
504 * Load an ID cert from a chunk, Note, this only loads the id cert part
505 * and so it is not suitable for creating an attribute credential with.
506 * Only a complete id cert + privkey could create attribute credential.
507 */
508int abac_verifier_load_id_chunk(chunk_t chunk, abac_id_credential_t **id_cred_ret) {
509    abac_id_t *id=NULL;
510    // load the cert
511    certificate_t *cert = lib->creds->create(
512        lib->creds, CRED_CERTIFICATE, CERT_X509,
513        BUILD_BLOB_ASN1_DER, chunk,
514        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
515        BUILD_END
516    );
517    if (cert == NULL)
518        return ABAC_CERT_INVALID;
519    return _load_id(&id, cert,id_cred_ret);
520}
521
522/**
523 * Load an ID cert from a cert chunk and a privkey chunk,
524 * this complete id cert + privkey could create attribute credential.
525 */
526int abac_verifier_load_id_privkey_chunk(chunk_t chunk, chunk_t privkey_chunk,
527abac_id_credential_t **id_cred_ret) {
528
529    abac_id_t *id=NULL;
530    // load the cert
531    certificate_t *cert = lib->creds->create(
532        lib->creds, CRED_CERTIFICATE, CERT_X509,
533        BUILD_BLOB_ASN1_DER, chunk,
534        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
535        BUILD_END
536    );
537    if (cert == NULL)
538        return ABAC_CERT_INVALID;
539
540    int rc=_load_id(&id, cert,id_cred_ret);
541    if(rc == ABAC_CERT_SUCCESS) {
542        rc=abac_id_load_privkey_chunk(id, privkey_chunk);
543    }
544
545    return rc;
546}
547
548int abac_verifier_load_id_enc_privkey_chunk(chunk_t chunk, chunk_t privkey_chunk,
549char* pfile, abac_id_credential_t **id_cred_ret) {
550
551    abac_id_t *id=NULL;
552    // load the cert
553    certificate_t *cert = lib->creds->create(
554        lib->creds, CRED_CERTIFICATE, CERT_X509,
555        BUILD_BLOB_ASN1_DER, chunk,
556        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
557        BUILD_END
558    );
559    if (cert == NULL)
560        return ABAC_CERT_INVALID;
561
562    int rc=_load_id(&id, cert,id_cred_ret);
563    if(rc == ABAC_CERT_SUCCESS) {
564        rc=abac_id_load_enc_privkey_chunk(id, privkey_chunk, pfile);
565    }
566
567    return rc;
568}
569
570
571
572abac_id_t *abac_verifier_load_issuer(char *filename, char *keyfilename)
573{
574    abac_id_credential_t *id_cred=NULL;
575    int ret=abac_verifier_load_id_file_key_file(filename,keyfilename,&id_cred);
576    if(ret !=ABAC_CERT_SUCCESS)
577        return NULL;
578    abac_id_t *issuer=abac_id_credential_id(id_cred);
579    return issuer;
580}
581
582
583static int matchex(const char *subject, const char *pattern, int *so, int *eo)
584{
585int rc; // Returned code
586regmatch_t pmatch;
587
588regex_t re; // Compiled regexp pattern
589
590if (regcomp(&re, pattern, 0) != 0) return 0;
591
592rc = regexec(&re, subject, 1 , &pmatch, 0);
593regfree(&re); 
594
595if (rc == REG_NOMATCH ) return 0; 
596
597*so=pmatch.rm_so;
598*eo=pmatch.rm_eo;
599
600return 1;
601}
602
603
604
605static chunk_t _extract_chunk(char *data, char* startline, char* endline)
606{
607    int found=0;
608    int startos=0;
609    int endos=0;
610    regex_t re;
611    regmatch_t pm;
612    int rc;
613
614    int st;
615    int et;
616
617    rc=matchex(data, startline, &st, &et);
618    if(rc==0) return chunk_empty;
619    startos=st;
620
621    rc=matchex(data, endline, &st, &et);
622    if(rc==0) return chunk_empty;
623    endos=et;
624   
625    int len=endos - startos; 
626
627    if(debug) printf("making a chunk of size (%d) from %d and %d\n",len, startos,endos);
628    char *ptr=strndup(data+startos,len);
629
630    chunk_t ret = { ptr, len };
631    return ret;
632}
633
634   
635int abac_verifier_load_idkey_file(char *filename, abac_id_credential_t **id_cred_ret)
636{
637    struct stat sb;
638    int fd;
639    int rc;
640
641    fd = open(filename, O_RDONLY);
642    if (fd == -1) { return 1; }
643    if(stat(filename, &sb) == -1) {
644        close(fd);
645        return 1;
646    }
647    char* data = (char *)mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
648    if(data == MAP_FAILED) {
649        close(fd);
650        return 1;
651    }
652    close(fd);
653
654    chunk_t key_pem_chunk=_extract_chunk(data,
655               "-----BEGIN RSA PRIVATE KEY-----","-----END RSA PRIVATE KEY-----");
656    chunk_t cert_pem_chunk=_extract_chunk(data,
657                   "-----BEGIN CERTIFICATE-----","-----END CERTIFICATE-----");
658
659    /* key=0, cert=0 */
660    if(key_pem_chunk.len==0 && cert_pem_chunk.len==0) {
661        if(debug) printf("abac_verifier_load_idkey_file: no key or id in idkey_file\n");
662        goto error;
663    }
664
665    /* key=0, cert=1 */
666    if(key_pem_chunk.len==0) {
667        if(debug) printf("abac_verifier_load_idkey_file: no key in idkey_file\n");
668        munmap(data, sb.st_size);
669        chunk_free(&key_pem_chunk);
670        return abac_verifier_load_id_file_key_file(filename,NULL,id_cred_ret);
671    }
672
673    /* key=1, cert=1 */
674    if(cert_pem_chunk.len!=0) {
675        if(debug) {
676            printf("loading cert pem chunk %d\n", cert_pem_chunk.len);
677            printf("(%s)\n",cert_pem_chunk.ptr);
678        }
679        rc=abac_verifier_load_id_pem_chunk(cert_pem_chunk, id_cred_ret);
680        if(rc != 0) {
681            if(debug) printf("abac_verifier_load_idkey_file: fail to load the id\n");
682            goto error;
683        }
684    /* key=1, cert=0 */
685        } else {
686            if(debug) printf("abac_verifier_load_idkey_file: there is no id info in there\n");
687            goto error;
688    }
689   
690    /* handle the key_pem_chunk */
691    if(debug)  {
692        printf("loading key pem chunk %d\n", key_pem_chunk.len);
693        printf("(%s)\n",key_pem_chunk.ptr);
694    }
695    abac_id_t *id=abac_id_credential_id(*id_cred_ret);
696    rc=abac_id_load_privkey_chunk(id, key_pem_chunk);
697    if(rc==0) {
698        printf("abac_verifier_load_idkey_file:failed to load priv key!!!\n");
699        goto error;
700    }
701
702    munmap(data, sb.st_size);
703    return 0;
704
705error:
706    munmap(data, sb.st_size);
707    return 1;
708}
709
710
711int abac_verifier_load_enc_idkey_file(char *filename, char *pfile, 
712abac_id_credential_t **id_cred_ret)
713{
714    struct stat sb;
715    int fd;
716    int rc;
717
718    fd = open(filename, O_RDONLY);
719    if (fd == -1) { return 1; }
720    if(stat(filename, &sb) == -1) {
721        close(fd);
722        return 1;
723    }
724    char* data = (char *)mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
725    if(data == MAP_FAILED) {
726        close(fd);
727        return 1;
728    }
729    close(fd);
730
731    chunk_t key_pem_chunk=_extract_chunk(data,
732               "-----BEGIN RSA PRIVATE KEY-----","-----END RSA PRIVATE KEY-----");
733    chunk_t cert_pem_chunk=_extract_chunk(data,
734                   "-----BEGIN CERTIFICATE-----","-----END CERTIFICATE-----");
735
736    /* key=0, cert=0 */
737    if(key_pem_chunk.len==0 && cert_pem_chunk.len==0) {
738        if(debug) printf("abac_verifier_load_idkey_file: no key or id in idkey_file\n");
739        goto error;
740    }
741
742    /* key=0, cert=1 */
743    if(key_pem_chunk.len==0) {
744        if(debug) printf("abac_verifier_load_idkey_file: no key in idkey_file\n");
745        munmap(data, sb.st_size);
746        chunk_free(&key_pem_chunk);
747        return abac_verifier_load_id_file_key_file(filename,NULL,id_cred_ret);
748    }
749
750    /* key=1, cert=1 */
751    if(cert_pem_chunk.len!=0) {
752        if(debug) {
753            printf("loading cert pem chunk %d\n", cert_pem_chunk.len);
754            printf("(%s)\n",cert_pem_chunk.ptr);
755        }
756        rc=abac_verifier_load_id_pem_chunk(cert_pem_chunk, id_cred_ret);
757        if(rc != 0) {
758            if(debug) printf("abac_verifier_load_idkey_file: fail to load the id\n");
759            goto error;
760        }
761    /* key=1, cert=0 */
762        } else {
763            if(debug) printf("abac_verifier_load_idkey_file: there is no id info in there\n");
764            goto error;
765    }
766   
767    /* handle the key_pem_chunk */
768    if(debug)  {
769        printf("loading key pem chunk %d\n", key_pem_chunk.len);
770        printf("(%s)\n",key_pem_chunk.ptr);
771        printf("(%d)\n",strlen(key_pem_chunk.ptr));
772    }
773    abac_id_t *id=abac_id_credential_id(*id_cred_ret);
774    rc=abac_id_load_enc_privkey_chunk(id, key_pem_chunk, pfile);
775    if(rc==0) {
776        printf("abac_verifier_load_idkey_file:failed to load priv key!!!\n");
777        goto error;
778    }
779
780    munmap(data, sb.st_size);
781    return 0;
782
783error:
784    munmap(data, sb.st_size);
785    return 1;
786}
787
788void abac_print_clauses(abac_list_t *clauses, FILE *fp)
789{
790    if (clauses != NULL) {
791        char *cur;
792        printf("total-- %d clauses\n", abac_list_size(clauses));
793        abac_list_foreach(clauses, cur,
794            if(cur) {
795                if(fp)
796                    fprintf (fp,"a clause, %d(%s)\n", (int)cur,cur);
797                    else printf ("a clause, %d(%s)\n", (int)cur,cur);
798            }
799        );
800    }
801}
802
803abac_id_credential_t *abac_id_credential_dup(abac_id_credential_t *ptr) {
804    assert(ptr != NULL);
805    if(debug)
806       printf("calling abac_id_credential_dup, increment id ref count\n");
807    abac_id_dup(ptr->id);
808    return ptr;
809}
810
811abac_id_t *abac_id_credential_id(abac_id_credential_t *ptr)
812{
813    assert(ptr);
814    return ptr->id;
815}
816
817
818abac_id_credential_t *abac_id_credential_lookup(char *pname)
819{
820    abac_id_credential_t *id_cred=NULL;
821    HASH_FIND_STR(id_creds, pname, id_cred);
822    if(id_cred != NULL)
823        return abac_id_credential_dup(id_cred);
824    else return NULL;
825}
826
827void abac_id_credential_free(abac_id_credential_t *ptr)
828{
829    if (ptr == NULL)
830        return;
831
832    if(debug)
833        printf("abac_id_credential_free:freeing (%s)\n", abac_id_name(ptr->id));
834
835    // this is very hacky...
836    int last=abac_id_lastone(ptr->id);
837    if(!last) {
838        if(debug) printf("abac_id_credential_free:not last one\n");
839        abac_id_free(ptr->id);
840        } else {
841            if(debug) printf("abac_id_credential_free: deleting id (%s)\n",abac_id_name(ptr->id));
842            free(ptr->hashkeyid);
843            if(ptr->pl_clause)
844                free(ptr->pl_clause);
845            abac_id_free(ptr->id);
846            HASH_DEL(id_creds, ptr);
847            free(ptr);
848    }
849}
850
851/****************************************************************************/
852
853static int _verify_valid_credential_string(certificate_t *cert,
854abac_credential_t **cred_ret, char *encoded_attr_string)
855{
856    abac_aspect_t *head_aspect = NULL;
857    abac_aspect_t *tail_aspect = NULL;
858    abac_list_t *clauses=NULL;
859    abac_id_credential_t *id_cred;
860    abac_id_t *issuer_id;
861    int ret, i;
862
863    // get the attr
864    head_aspect = abac_yy_get_rule_head_aspect();
865    tail_aspect = abac_yy_get_rule_tail_aspect();
866    clauses = abac_yy_get_rule_clauses();
867
868    // get the issuer based on keyid
869    char *principalname = abac_aspect_principal_principalname(head_aspect);
870    if(debug) printf("LOOKING for %s\n", principalname);
871
872    HASH_FIND_STR(id_creds, principalname, id_cred);
873    if(id_cred == NULL) {
874        ret = ABAC_CERT_MISSING_ISSUER;
875        if(debug)
876             printf("can not find %s in id_creds\n", principalname);
877        goto error;
878    }
879    issuer_id=id_cred->id;
880    if (issuer_id == NULL) {
881        ret = ABAC_CERT_MISSING_ISSUER;
882        if(debug)
883             printf("can not find %s in id_creds\n", principalname);
884        goto error;
885    }
886
887
888    // make sure the issuer's signed it
889    ret = _verify_signature(abac_id_cert(issuer_id), cert);
890    if (!ret) {
891        abac_yy_set_error_code(ABAC_RT_CERT_BAD_SIG);
892        ret=ABAC_CERT_BAD_SIG;
893        goto error;
894    }
895
896    // at this point we know we have a good attribute cert baked it in
897    abac_attribute_t *attr=abac_attribute_new(issuer_id, cert, cert->get_ref(cert));
898    abac_attribute_set_head(attr, head_aspect);
899    abac_attribute_add_tail(attr, tail_aspect);
900
901    abac_credential_t *cred = abac_xmalloc(sizeof(abac_credential_t));
902    cred->hashkeyid=abac_xstrdup(encoded_attr_string);
903    cred->attr=attr;
904    cred->pl_clauses = clauses;
905    *cred_ret = cred;
906
907    // success, add the key to the map of certificates
908    HASH_ADD_KEYPTR(hh, attr_creds, cred->hashkeyid, strlen(cred->hashkeyid), cred);
909
910    assert(attr_hashkeyid_list);
911    abac_list_add(attr_hashkeyid_list, abac_xstrdup(cred->hashkeyid));
912
913    if(debug)
914        printf("-->adding into attr_creds 2, (%s)..cnt(%d)\n",
915                                   cred->hashkeyid, HASH_COUNT(attr_creds));
916
917    return ABAC_CERT_SUCCESS;
918
919error:
920    if (head_aspect) abac_aspect_free(head_aspect);
921    if (tail_aspect) abac_aspect_free(tail_aspect);
922    abac_yy_free_rule_clauses();
923
924    return ret;
925}
926
927/**
928 * Load an attribute cert.
929 * Returns true only if the certificate is valid and is issued by the proper
930 * authority.
931 * attribute string is parsed via yyparse call
932 */
933static int _load_attribute_cert(certificate_t *cert, abac_credential_t **cred_ret) {
934    ietf_attributes_t *attr_cert = NULL;
935    abac_id_credential_t *issuer;
936    int ret, i;
937
938    // get the attr
939    ac_t *ac = (ac_t *)cert;
940    attr_cert = ac->get_groups(ac);
941    if (attr_cert == NULL) {
942        ret = ABAC_CERT_INVALID;
943        goto error;
944    }
945
946    char *encoded_attr_string=attr_cert->get_string(attr_cert);
947    char *attr_string = abac_decode_string(encoded_attr_string);
948    if(debug)
949         printf("string to be yyparse..(%d)(%s)\n",strlen(attr_string),attr_string);
950
951    if (attr_string == NULL) {
952        ret = ABAC_CERT_INVALID;
953        goto error;
954    }
955
956    /* call into yacc parser */
957    abac_reset_yyfptr(attr_string);
958    abac_yy_init();
959    int rc=yyparse();
960    if (rc) {
961        ret = ABAC_CERT_INVALID;
962        goto error;
963    }
964
965    ret=_verify_valid_credential_string(cert,cred_ret,encoded_attr_string);
966
967    if(ret != ABAC_CERT_SUCCESS) {
968        panic("_load_attribute_cert: fail to process (%s)",encoded_attr_string);
969    }
970
971    // free up some crap
972    attr_cert->destroy(attr_cert);
973
974    return ret;
975
976error:
977    if (cert) cert->destroy(cert);
978    if (attr_cert) attr_cert->destroy(attr_cert);
979    return ret;
980}
981
982/**
983 * Load an attribute cert from a abac_attribute_t.
984 * attr should be all checked out before arriving here
985 */
986int abac_verifier_load_attribute_cert_attribute(abac_attribute_t *ptr, abac_credential_t **cred_ret) {
987    // get the attr
988    abac_aspect_t *head=abac_attribute_head(ptr);
989    abac_aspect_t *tail=abac_attribute_tail(ptr);
990
991    // preprocess for constraint part
992    preprocess_pl_head(head);
993    preprocess_pl_tail(tail);
994
995/* setup the encoded attribute string */
996    char *encoded_attr_string=get_cred_encoding(ptr);
997    generate_pl_set_abac_yyfptr_encoded(encoded_attr_string);
998/* collect up type clauses, constraint clauses and
999   generate rule clauses */
1000    abac_list_t *clauses=generate_pl_clauses(head,tail);
1001
1002    abac_print_clauses(clauses,NULL);
1003
1004    abac_credential_t *cred = abac_xmalloc(sizeof(abac_credential_t));
1005    cred->hashkeyid=abac_xstrdup(encoded_attr_string);
1006    cred->attr=abac_attribute_dup(ptr);
1007    cred->pl_clauses = clauses;
1008    *cred_ret = cred;
1009
1010    // success, add the key to the map of certificates
1011    HASH_ADD_KEYPTR(hh, attr_creds, cred->hashkeyid, strlen(cred->hashkeyid), cred);
1012
1013    assert(attr_hashkeyid_list);
1014    abac_list_add(attr_hashkeyid_list, abac_xstrdup(cred->hashkeyid));
1015
1016    if(debug)
1017        printf("-->adding into attr_creds, (%s)..cnt(%d)\n",
1018                                   cred->hashkeyid, HASH_COUNT(attr_creds));
1019    return ABAC_CERT_SUCCESS;
1020}
1021
1022/**
1023 * Load an attribute cert from a file.
1024 */
1025int abac_verifier_load_attribute_cert_file(char *filename, abac_credential_t **cred) {
1026    // load the cert
1027    if(debug) printf("..loading attr file %s\n", filename);
1028    certificate_t *cert = lib->creds->create(
1029        lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
1030        BUILD_FROM_FILE, filename,
1031        BUILD_END
1032    );
1033    if (cert == NULL)
1034        return ABAC_CERT_INVALID;
1035    return _load_attribute_cert(cert, cred);
1036}
1037
1038/**
1039 * Load an attribute cert from a chunk.
1040 */
1041int abac_verifier_load_attribute_cert_chunk(chunk_t chunk, abac_credential_t **cred) {
1042    // load the cert
1043    certificate_t *cert = lib->creds->create(
1044        lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
1045        BUILD_BLOB_ASN1_DER, chunk,
1046        BUILD_END
1047    );
1048    if (cert == NULL)
1049        return ABAC_CERT_INVALID;
1050
1051    return _load_attribute_cert(cert, cred);
1052}
1053
1054/**
1055 * Return the encoding of the attribute cert.
1056 */
1057abac_chunk_t abac_credential_attribute_cert(abac_credential_t *cred) {
1058    abac_attribute_t *ptr=cred->attr;
1059    certificate_t *cert=abac_attribute_cert(ptr);
1060    chunk_t encoding = chunk_empty;
1061    int rc=cert->get_encoding(cert,CERT_ASN1_DER,&encoding);
1062    abac_chunk_t ret = { encoding.ptr, encoding.len };
1063    return ret;
1064}
1065
1066/**
1067 * Return the encoding of the issuer cert.
1068 */
1069abac_chunk_t abac_credential_issuer_cert(abac_credential_t *cred) {
1070    certificate_t *issuer_cert=abac_attribute_issuer_cert(cred->attr);
1071    assert(issuer_cert);
1072    chunk_t encoding = chunk_empty;
1073// XXX MEI, not sure ??
1074    int rc=issuer_cert->get_encoding(issuer_cert,CERT_ASN1_DER,&encoding);
1075    abac_chunk_t ret = { encoding.ptr, encoding.len };
1076    return ret;
1077}
1078
1079/**
1080 * Return the clause of the cert
1081 */
1082abac_list_t *abac_credential_clauses(abac_credential_t *cred) {
1083    return cred->pl_clauses;
1084}
1085
1086abac_attribute_t *abac_credential_attribute(abac_credential_t *cred) {
1087    assert(cred);
1088    return cred->attr;
1089}
1090
1091/**
1092 * Increase the ref count of a credential.
1093 */
1094abac_credential_t *abac_credential_dup(abac_credential_t *cred) {
1095    assert(cred != NULL);
1096
1097    abac_attribute_dup(cred->attr);
1098    return cred;
1099}
1100
1101/**
1102 *  lookup for a credential.
1103 */
1104abac_credential_t *abac_credential_lookup(char* cred_string)
1105{
1106    if(debug)
1107        printf("abac_credential_lookup: looking for (%s)\n", cred_string);
1108    abac_credential_t *attr_cred;
1109
1110    HASH_FIND_STR(attr_creds, cred_string, attr_cred);
1111    if (attr_cred == NULL) {
1112        if(debug) printf("DEBUG:NOT FOUND..\n");
1113        return NULL;
1114    }
1115    abac_credential_t *rt=abac_credential_dup(attr_cred);
1116    if(debug) printf("DEBUG:FOUND.. (%d) returning, (%d)\n", (int)attr_cred, (int) rt);
1117    return rt;
1118}
1119
1120/**
1121 * Decrease the reference count of a credential, freeing it when it reaches 0.
1122 */
1123void abac_credential_free(abac_credential_t *cred)
1124{
1125    if(debug)
1126        printf("abac_credential_free:freeing cred(%d)clause(%d)\n", (int)cred, (int)cred->pl_clauses);
1127
1128    if (cred == NULL)
1129        return;
1130
1131    // this is very hacky...
1132    int last=abac_attribute_lastone(cred->attr);
1133    if(!last) {
1134        abac_attribute_free(cred->attr);
1135        } else {
1136            free(cred->hashkeyid);
1137            char *cur=NULL;
1138            abac_list_foreach(cred->pl_clauses, cur,
1139                free(cur);
1140            );
1141            abac_attribute_free(cred->attr);
1142            HASH_DEL(attr_creds, cred);
1143            free(cred);
1144    }
1145}
1146
1147char *abac_id_clause(abac_id_credential_t *id_cred)
1148{
1149    if(id_cred)
1150        return id_cred->pl_clause;
1151    return NULL;
1152}
1153
1154/* retrieve the cn that is associated with this sha_string */
1155char *abac_cn_with_sha(char *sha_string)
1156{
1157    // get the issuer based on keyid
1158    abac_id_credential_t *id_cred;
1159    HASH_FIND_STR(id_creds, sha_string, id_cred);
1160    if (id_cred == NULL) {
1161        return NULL;
1162    }
1163    if(debug)
1164        check_id_cred(id_cred);
1165    return abac_id_cn(id_cred->id);
1166}
1167
1168char *abac_idtype_with_sha(char* sha_string)
1169{ 
1170    // get the issuer based on keyid
1171    abac_id_credential_t *id_cred;
1172    HASH_FIND_STR(id_creds, sha_string, id_cred);
1173    if (id_cred == NULL) {
1174        return NULL;
1175    }
1176    int idtype=abac_id_idtype(id_cred->id);
1177   
1178    return abac_idtype_string(idtype);
1179}
1180
1181abac_aspect_t *abac_credential_head(abac_credential_t *cred) {
1182    return abac_attribute_head(cred->attr); 
1183}
1184
1185abac_aspect_t *abac_credential_tail(abac_credential_t *cred) {
1186    return abac_attribute_tail(cred->attr); 
1187}
1188
1189
Note: See TracBrowser for help on using the repository browser.