OSDN Git Service

fixed issue reported by SAT, base64 functions are updated
[openpts/openpts.git] / src / aide.c
1 /*
2  * This file is part of the OpenPTS project.
3  *
4  * The Initial Developer of the Original Code is International
5  * Business Machines Corporation. Portions created by IBM
6  * Corporation are Copyright (C) 2010 International Business
7  * Machines Corporation. All Rights Reserved.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the Common Public License as published by
11  * IBM Corporation; either version 1 of the License, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * Common Public License for more details.
18  *
19  * You should have received a copy of the Common Public License
20  * along with this program; if not, a copy can be viewed at
21  * http://www.opensource.org/licenses/cpl1.0.php.
22  */
23
24 /**
25  * \file src/aide.c
26  * \brief AIDE I/F APIs
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-06-13
29  * cleanup 2011-07-06 SM
30  *
31  * 1) Integrity check with AIDE
32  *
33  *  $ ./configure --with-aide
34  *  $ make
35  *
36  * 2) Integrity check with AIDE and SQLite (fast?)
37  *
38  *  # yum install sqlite-devel
39  *
40  *  $ ./configure --with-aide --with-sqlite
41  *  $ make
42  *
43  *
44  * 3) Performance
45  *
46  *   simple list   30sec
47  *   hash table    36sec
48  *   SQLite        XXsec
49  *   PostgreSQL    XXsec (TBD)
50  *
51  * hash table
52  *   http://www.gnu.org/s/libc/manual/html_node/Hash-Search-Function.html
53  *
54  * binary digest did not work well, thus try base64 string in stead binary blob.
55  * 
56  *   digest - md ptr
57  *   name - in ptr
58  */
59
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63
64 #define __USE_GNU
65 #include <search.h>  // hash table
66 #include <errno.h>
67
68 #ifdef CONFIG_SQLITE
69 #include <sqlite3.h>
70 #endif
71
72 #include <zlib.h>
73
74 #include <openpts.h>
75
76 /**
77  * new AIDE_METADATA
78  *
79  * TODO(munetoh) new -> add?
80  */
81 AIDE_METADATA * newAideMetadata() {
82     AIDE_METADATA *metadata;
83     metadata = (AIDE_METADATA *) malloc(sizeof(AIDE_METADATA));
84     if (metadata == NULL) {
85         ERROR("no memory\n");
86         return NULL;
87     }
88     memset(metadata, 0, sizeof(AIDE_METADATA));
89
90     return metadata;
91 }
92
93
94
95 /**
96  * free AIDE_METADATA
97  *
98  * TODO(munetoh) sep. all and single
99  */
100 void freeAideMetadata(AIDE_METADATA *md) {
101     if (md == NULL) return;
102
103     if (md->next != NULL) {
104         freeAideMetadata(md->next);
105     }
106
107     /* free */
108     if (md->name != NULL) free(md->name);
109     if (md->lname != NULL) free(md->lname);
110     if (md->sha1 != NULL) free(md->sha1);
111     if (md->sha256 != NULL) free(md->sha256);
112     if (md->ima_name != NULL) free(md->ima_name);
113     if (md->hash_key != NULL) free(md->hash_key);
114
115     free(md);
116     md = NULL;
117
118     return;
119 }
120
121 /**
122  * add
123  */
124 int addAideMetadata(AIDE_CONTEXT *ctx, AIDE_METADATA *md) {
125     int rc = 0;
126
127     /* update ctx*/
128     if (ctx->start == NULL) {
129         /* first metadata */
130         ctx->start = md;
131         ctx->end = md;
132     } else {
133         ctx->end->next = md;
134         md->prev = ctx->end;
135         ctx->end = md;
136     }
137     ctx->metadata_num++;
138
139     return rc;
140 }
141
142 // #define AIDE_CHBY_LIST 1
143 #define AIDE_CHBY_LIST 0
144
145 #define AIDE_HASH_TABLE_SIZE 16000
146
147 // check hash size
148 // user time
149 // 10 0.315
150 // 20 0.642
151 #define AIDE_HASH_CHECK_SIZE SHA1_DIGEST_SIZE
152 // #define AIDE_HASH_CHECK_SIZE 20
153
154 /**
155  * new AIDE_CONTEXT
156  */
157 AIDE_CONTEXT * newAideContext() {
158     int rc;
159     AIDE_CONTEXT *ctx;
160
161     // DEBUG("newAideContext()\n");
162
163     ctx = malloc(sizeof(AIDE_CONTEXT));
164     if (ctx == NULL) {
165         ERROR("no memory\n");
166         return NULL;
167     }
168     memset(ctx, 0, sizeof(AIDE_CONTEXT));
169
170     /* hash tables */
171     // TODO set the size in openpts.h
172     ctx->aide_md_table = malloc(sizeof(struct hsearch_data));
173     // TODO ck null
174     memset(ctx->aide_md_table, 0, sizeof(struct hsearch_data));
175     rc = hcreate_r(AIDE_HASH_TABLE_SIZE, ctx->aide_md_table);  // hash table for metadata
176     if (rc == 0) {
177         ERROR("hcreate faild, errno=%x\n", errno);
178         goto error;
179     }
180     ctx->aide_md_table_size = 0;
181
182     ctx->aide_in_table = malloc(sizeof(struct hsearch_data));
183     // TODO ck null
184     memset(ctx->aide_in_table, 0, sizeof(struct hsearch_data));
185     //  4096 full
186     rc = hcreate_r(AIDE_HASH_TABLE_SIZE, ctx->aide_in_table);  // hash table for ignore name
187     if (rc == 0) {
188         ERROR("hcreate faild\n");
189         goto error;
190     }
191     ctx->aide_in_table_size = 0;
192
193     DEBUG("newAideContext %p\n", ctx);
194     return ctx;
195
196   error:
197     if (ctx != NULL) free(ctx);
198     return NULL;
199 }
200
201 /**
202  *
203  */
204 void freeAideIgnoreList(AIDE_LIST *list) {
205     if (list == NULL) {
206         return;
207     }
208
209     if (list->next != NULL) {
210         freeAideIgnoreList(list->next);
211     }
212
213
214     /* Free */
215     if (list->name != NULL) {
216         free(list->name);
217     }
218
219     free(list);
220
221     return;
222 }
223
224 /**
225  * free AIDE_CONTEXT
226  */
227 void freeAideContext(AIDE_CONTEXT *ctx) {
228     /* check */
229     if (ctx == NULL) {
230         ERROR("ctx is NULL\n");
231         return;
232     }
233     DEBUG("freeAideContext %p \n", ctx);
234
235     // DEBUG("aide_md_table_size = %d\n", ctx->aide_md_table_size);
236     // DEBUG("aide_in_table_size = %d\n", ctx->aide_in_table_size);
237
238     /* hash tables */
239     hdestroy_r(ctx->aide_md_table);
240     hdestroy_r(ctx->aide_in_table);
241
242     free(ctx->aide_md_table);
243     free(ctx->aide_in_table);
244
245 #ifdef CONFIG_SQLITE
246     if (ctx->sqlite_db != NULL) {
247         /* close DB */
248         sqlite3_close(ctx->sqlite_db);
249     }
250 #endif
251
252     /* free metadata chain */
253     if (ctx->start != NULL) {
254         freeAideMetadata(ctx->start);
255     }
256
257     /* free ignore list */
258     if (ctx->ignore_name_start != NULL) {
259         // DEBUG("free tx->ignore_name_start\n");
260         freeAideIgnoreList(ctx->ignore_name_start);
261     }
262
263     free(ctx);
264     return;
265 }
266
267
268 /**
269  * load AIDE db file (giped)
270
271  name    lname attr       sha1                         sha256
272  /bin/vi 0     1073750017 C9ID19uSxnrv/Bt0uYbloaVO1SQ= VTYuAxsuG4pmWHP9ZCTO1KUsYk2uwTvwiCJ/OxzsVd0=
273  /bin 0 1 0 0
274  /bin/dnsdomainname hostname 3 0 0
275  
276  */
277
278 #define AIDE_SPEC_BUF_SIZE 1024
279 #define AIDE_MAX_ITEM_NUM  20
280 #define AIDE_MAX_ITEM_SIZE 10
281
282 // TODO(munetoh) add more...
283 #define AIDE_ITEM_NAME    0  // char
284 #define AIDE_ITEM_LNAME   1  // int
285 #define AIDE_ITEM_ATTR    2  // int
286 #define AIDE_ITEM_SHA1    3  // base64
287 #define AIDE_ITEM_SHA256  4  // base64
288 #define AIDE_ITEM_SHA512  5  // base64
289 #define AIDE_ITEM_PERM    6  //
290 #define AIDE_ITEM_UID     7  //
291 #define AIDE_ITEM_GID     8  //
292 #define AIDE_ITEM_ACL     9  //
293 #define AIDE_ITEM_XATTRS 10  //
294
295 int getAideItemIndex(char *buf) {
296     if (!strncmp(buf, "name", 4)) {
297         return AIDE_ITEM_NAME;
298     } else if (!strncmp(buf, "lname", 5)) {
299         return AIDE_ITEM_LNAME;
300     } else if (!strncmp(buf, "attr", 4)) {
301         return AIDE_ITEM_ATTR;
302     } else if (!strncmp(buf, "sha1", 4)) {
303         return AIDE_ITEM_SHA1;
304     } else if (!strncmp(buf, "sha256", 6)) {
305         return AIDE_ITEM_SHA256;
306     } else if (!strncmp(buf, "sha512", 6)) {
307         return AIDE_ITEM_SHA512;
308     } else if (!strncmp(buf, "perm", 4)) {
309         return AIDE_ITEM_PERM;
310     } else if (!strncmp(buf, "acl", 4)) {
311         return AIDE_ITEM_ACL;
312     } else if (!strncmp(buf, "uid", 4)) {
313         return AIDE_ITEM_UID;
314     } else if (!strncmp(buf, "gid", 4)) {
315         return AIDE_ITEM_GID;
316     } else if (!strncmp(buf, "xattrs", 6)) {
317         return AIDE_ITEM_XATTRS;
318     } else {
319         ERROR("Unknown AIDE item [%s]\n", buf);
320         return -1;
321     }
322 }
323
324
325 /**
326  * load AIDE database from file
327  *
328  *   filename base64(digest)
329  *
330  * caller
331  *  ir.c
332  */
333 int loadAideDatabaseFile(AIDE_CONTEXT *ctx, char *filename) {
334     gzFile fp;
335     char buf[AIDE_SPEC_BUF_SIZE];
336     int  items[AIDE_MAX_ITEM_NUM];
337     int  item_num = 0;
338     char *ptr;
339     char *end;
340     char *sep;
341     AIDE_METADATA *md;
342     int body = 0;
343     int i;
344     int is_null;
345     int len;
346     ENTRY e;  // htable
347     ENTRY *ep;
348     int rc;
349     char *sha1_b64_ptr;
350
351
352     DEBUG("loadAideDatabaseFile - start, filename=[%s]\n", filename);
353
354     fp = gzopen(filename, "r");
355     if (fp == NULL) {
356         ERROR("%s missing\n", filename);
357         return -1;
358     }
359
360     while (gzgets(fp, buf, sizeof(buf)) != NULL) {
361         if (!strncmp(buf, "#", 1)) {
362         } else if (!strncmp(buf, "@@begin_db", 10)) {
363             body = 1;
364         } else if (!strncmp(buf, "@@end_db", 8)) {
365             body = 0;
366         } else if (!strncmp(buf, "@@db_spec", 9)) {
367             /* check item def */
368             ptr = &buf[10];
369             end = buf + strlen(buf);
370             item_num = 0;
371
372             /* loop */
373             while (ptr < end) {
374                 /* skip space */
375                 while ((ptr < end) && (*ptr == 0x20)) {
376                     printf("skip %d ", *ptr);
377                     ptr++;
378                 }
379
380                 /* find sep */
381                 sep = strstr(ptr, " ");
382                 if (sep == NULL) {
383                     ERROR("bad data, %s\n", buf);
384                     return -1;
385                 } else {
386                     // terminate at " "
387                     *sep = 0;
388                 }
389                 /* get item code */
390                 items[item_num] = getAideItemIndex(ptr);
391
392                 if (items[item_num] < 0) {
393                     ERROR("Bad spec\n");
394                     return -1;
395                 }
396                 item_num++;
397
398                 if (sep + 3 > end) break;  // TODO(munetoh)
399                 ptr = sep + 1;
400             }
401             body = 2;
402
403             if (item_num > AIDE_MAX_ITEM_NUM) {
404                 ERROR("loadAideDatabaseFile - %d items > %d \n", item_num, AIDE_MAX_ITEM_NUM);
405                 return -1;
406             }
407             DEBUG("loadAideDatabaseFile - has %d items\n", item_num);
408         } else if (body == 2) { /* DB items */
409             /* new MD */
410             md = newAideMetadata();
411
412             /* check item  */
413             ptr = buf;
414             end = buf + strlen(buf);
415             sep = buf;
416
417             // *end = 0;  // TODO(munetoh) remove \n
418
419             sha1_b64_ptr = NULL;
420
421             /* loop */
422             for (i = 0; i < item_num; i++) {
423                 /* space -> \0 */
424                 if (i != item_num - 1) {
425                     // printf("SEP %d %d\n",i, item_num);
426                     sep = strstr(ptr, " ");
427                     if (sep == NULL) {
428                         ERROR("bad data, %s\n", buf);
429                         freeAideMetadata(md);
430                         return -1;
431                     } else {
432                         *sep = 0;  // set \0
433                     }
434                 }
435
436                 /* check the null string*/
437                 if (!strncmp(ptr, "0", strlen(ptr))) {
438                     is_null = 1;
439                 } else if (!strncmp(ptr, "0\n", strlen(ptr))) {
440                     is_null = 1;
441                 } else {
442                     is_null = 0;
443                 }
444
445                 switch (items[i]) {
446                     case AIDE_ITEM_NAME:   // char
447                         if (!is_null) {
448                             md->name = smalloc(ptr);
449                         }
450                         break;
451                     case AIDE_ITEM_LNAME:  // char
452                         if (!is_null) {
453                             md->lname = smalloc(ptr);
454                         }
455                         break;
456                     case AIDE_ITEM_ATTR:   // int
457                         md->attr = atoi(ptr);
458                         break;
459                     case AIDE_ITEM_SHA1:   // base64
460                         if (!is_null) {
461                             sha1_b64_ptr = ptr;
462                             md->sha1 = decodeBase64(
463                                 (char *)ptr,
464                                 SHA1_BASE64_DIGEST_SIZE,
465                                 &len);
466                             if (md->sha1 == NULL) {
467                                 ERROR("decodeBase64 fail");
468                                 goto close;
469                             }
470                             if (len != SHA1_DIGEST_SIZE) {
471                                 ERROR("bad SHA1 size %d  %s\n", len, ptr);
472                                 // printf("base64 [%s] => [", ptr);
473                                 printHex("digest", md->sha1, len, "\n");
474                                 // printf("]\n");
475                             }
476                         }
477                         break;
478                     case AIDE_ITEM_SHA256:  // base64
479                         if (!is_null) {
480                             md->sha256 = decodeBase64(
481                                 (char *)ptr,
482                                 SHA256_BASE64_DIGEST_SIZE,
483                                 &len);
484                             if (md->sha256 == NULL) {
485                                 ERROR("decodeBase64 fail");
486                                 goto close;
487                             }
488                             if (len != SHA256_DIGEST_SIZE) {
489                                 ERROR("bad SHA256 size %d\n", len);
490                                 printf("base64 [%s] => [", ptr);
491                                 printHex("", (BYTE *)ptr, 2, " ");
492                                 printf("][\n");
493                                 printHex("", md->sha256, len, " ");
494                                 printf("]\n");
495                             }
496                         }
497                         break;
498                     case AIDE_ITEM_SHA512:  // base64
499                         if (!is_null) {
500                             md->sha512 = decodeBase64(
501                                 (char *)ptr,
502                                 SHA512_BASE64_DIGEST_SIZE,
503                                 &len);
504                             if (md->sha512 == NULL) {
505                                 ERROR("decodeBase64 fail");
506                                 goto close;
507                             }
508                             if (len != SHA512_DIGEST_SIZE) {
509                                 ERROR("bad SHA512 size %d\n", len);
510                                 printf("base64 [%s] => [", ptr);
511                                 printHex("", (BYTE *)ptr, 2, "");
512                                 printf("][\n");
513                                 printHex("", md->sha512, len, "");
514                                 printf("]\n");
515                             }
516                         }
517                         break;
518                     case AIDE_ITEM_XATTRS:
519                         // DEBUG("AIDE_ITEM_XATTRS\n");
520                         break;
521                     default:
522                         // DEBUG("Unknown item[%d] %d\n", i, items[i]);
523                         break;
524                 }  // switch
525                 ptr = sep + 1;
526             }  // for
527
528             /* update ctx */
529             md->status = OPENPTS_AIDE_MD_STATUS_NEW;
530             addAideMetadata(ctx, md);
531
532             /* save to the hash table */
533             if (sha1_b64_ptr != NULL) {
534                 // TODO SHA1 only, add hash agility later
535                 /* alloc hash key */
536                 sha1_b64_ptr[SHA1_BASE64_DIGEST_SIZE] = 0;  // jXgiZyt0yUbP4QhAq9WFsLF/FL4=  28
537                 md->hash_key = malloc(strlen(sha1_b64_ptr) +1);
538                 // TODO check NULL
539                 memcpy(md->hash_key, sha1_b64_ptr, strlen(sha1_b64_ptr) + 1);
540
541                 e.key = (char *)md->hash_key;
542                 e.data = (void *)md;
543                 rc = hsearch_r(e, ENTER, &ep, ctx->aide_md_table);
544
545                 if (rc == 0) {
546                     if (errno == ENOMEM) {
547                         ERROR("  hsearch_r failed, table is full, errno=%x\n", errno);
548                     } else {
549                         ERROR("  hsearch_r failed, errno=%x\n", errno);
550                     }
551                 }
552                 // CAUTION too many messages, use for debugging the unit test
553                 // DEBUG("Hash Table <-  %4d [%s] %s\n", ctx->aide_md_table_size, md->hash_key, md->name);
554                 ctx->aide_md_table_size++;
555             }
556
557
558 #if 0
559             if (ctx->start == NULL) {
560                 ctx->start = md;
561                 ctx->end = md;
562             } else {
563                 ctx->end->next = md;
564                 md->prev = ctx->end;
565                 ctx->end = md;
566             }
567             ctx->metadata_num++;
568 #endif
569         } else {
570             // ignore printf("??? [%s]\n", buf);
571         }  // if
572     }  // while
573  close:
574     gzclose(fp);
575     DEBUG("loadAideDatabaseFile - has %d entries\n", ctx->metadata_num);
576     DEBUG("loadAideDatabaseFile - done\n");
577
578     return ctx->metadata_num;
579 }
580
581
582 /**
583  * read AIDE ignore name
584  *
585  * Return
586  *    PTS_SUCCESS
587  *    PTS_OS_ERROR
588  * caller
589  *  ir.c
590  */
591 int readAideIgnoreNameFile(AIDE_CONTEXT *ctx, char *filename) {
592     int rc = PTS_SUCCESS;
593     FILE *fp;
594     char line[BUF_SIZE];
595     int len;
596     int cnt = 0;
597     AIDE_LIST *list;
598     ENTRY e;  // htable
599     ENTRY *ep;
600
601     DEBUG("readAideIgnoreNameFile - start, filename=[%s]\n", filename);
602
603     /* Open file for read */
604     fp = fopen(filename, "r");
605     if (fp == NULL) {
606         DEBUG("%s missing\n", filename);
607         return -1;
608     }
609
610
611     /* parse */
612     while (fgets(line, BUF_SIZE, fp) != NULL) {  // read line
613         /* ignore comment, null line */
614         if (line[0] == '#') {
615             // comment
616         } else {
617             /* name=value line*/
618             /* remove CR */
619             len = strlen(line);
620             if (line[len-1] == 0x0a) line[len-1] = 0;
621
622             DEBUG("%4d [%s]\n", cnt, line);
623
624             /* new  */
625             list = malloc(sizeof(AIDE_LIST));
626             if (list == NULL) {
627                 ERROR("no mem\n");
628                 rc = PTS_OS_ERROR;
629                 goto error;  // return -1;
630             }
631             memset(list, 0, sizeof(AIDE_LIST));
632             list->name = smalloc(line);
633
634             /* add to chain */
635             if (ctx->ignore_name_start == NULL) {
636                 /* first entry */
637                 ctx->ignore_name_start = list;
638                 ctx->ignore_name_end = list;
639                 list->next = NULL;
640             } else {
641                 /* next entry */
642                 ctx->ignore_name_end->next = list;
643                 ctx->ignore_name_end = list;
644                 list->next = NULL;
645             }
646
647             /* hash table */
648             e.key = list->name;
649             e.data = (void *)list;
650             rc = hsearch_r(e, ENTER, &ep, ctx->aide_in_table);
651             if (rc == 0) {
652                 if (errno == ENOMEM) {
653                     ERROR("  hsearch_r failed, ignore name table is full, errno=%x\n", errno);
654                 } else {
655                     ERROR("  hsearch_r failed, errno=%x\n", errno);
656                 }
657             }
658             ctx->aide_in_table_size++;
659
660             cnt++;
661         }  // #
662     }  // while
663
664   error:
665     fclose(fp);
666
667     DEBUG("readAideIgnoreNameFile - done, num = %d\n", cnt);
668
669     return rc;
670 }
671
672
673 /**
674  * print all AIDE data, for TEST and DEBUG
675  */
676 int printAideData(AIDE_CONTEXT *ctx) {
677     AIDE_METADATA *md;
678     int i;
679
680     DEBUG("printAideData - start\n");
681     DEBUG("printAideData - num = %d\n", ctx->metadata_num);
682
683     md = ctx->start;
684
685     for (i = 0; i < ctx->metadata_num; i++) {
686         printf("%4d ", i);
687         if ( md->name  != NULL) printf("%30s ", md->name);
688         if ( md->lname != NULL) printf("%20s ", md->lname);
689         if ( md->attr  != 0)    printf("%08X ", md->attr);
690         if (md->sha1   != NULL)
691             printHex("", md->sha1, 20, " ");
692         else
693             printf("                                        -");
694
695         if (md->sha256 != NULL)
696             printHex("", md->sha256, 32, " ");
697         else
698             printf("                                                                -");
699
700         printf(" <<\n");
701         md = md->next;
702     }
703
704     DEBUG("printAideData - end\n");
705
706     return 0;
707 }
708
709 #if 1
710 int hexcmp(BYTE *d1, BYTE *d2, int len) {
711     int i;
712
713     for (i = 0; i < len; i++) {
714         if (d1[i] != d2[i]) {
715             return -1;
716         }
717     }
718     // HIT
719     return 0;
720 }
721 #endif
722
723 // TODO(munetoh) how this work?
724 void copyAideMetadata(AIDE_METADATA *dst, AIDE_METADATA *src) {
725     if (dst->name == NULL) {
726         dst->name = malloc(strlen(src->name) + 1);
727         memcpy(dst->name, src->name, strlen(src->name) + 1);
728     }
729 }
730
731 /**
732  * check AIDE MD vs given MD (SHA1)
733  *
734  * TODO(munetoh) obsolute use checkEventByAide()
735  */
736 int checkFileByAide(AIDE_CONTEXT *ctx, AIDE_METADATA *metadata) {
737     AIDE_METADATA *md;
738     int i;
739
740     if (ctx == NULL) {
741         return -1;
742     }
743
744     if (metadata == NULL) {
745         return -1;
746     }
747
748     md = ctx->start;
749
750     for (i = 0; i < ctx->metadata_num; i++) {
751         if (md == NULL) {
752             return -1;
753         }
754         if ((metadata->sha1 != NULL) && (md->sha1 != NULL)) {
755             if (!hexcmp(metadata->sha1, md->sha1, SHA1_DIGEST_SIZE)) {
756                 /* hit */
757                 DEBUG_FSM("checkFileByAide - HIT name=[%s]\n", md->name);
758                 md->status = OPENPTS_AIDE_MD_STATUS_HIT;
759                 copyAideMetadata(metadata, md);
760                 return 0;
761             }
762         }
763         md = md->next;
764     }
765     DEBUG_FSM("checkFileByAide - MISS\n");
766     return -2;
767 }
768
769
770 /**
771  *
772  * return 
773  *    -1: MISS
774  *     0: HIT
775  *
776  */
777 int checkIgnoreList(AIDE_CONTEXT *ctx, char *name) {
778     AIDE_LIST *list;
779     int len;
780
781     /* check */
782     if (name == NULL) {
783         ERROR("checkIgnoreList() - name is null\n");
784         return -2;
785     }
786
787     list = ctx->ignore_name_start;
788     while (list != NULL) {
789         // TODO(munetoh)  not check the all string
790         if (list->name != NULL) {
791             len = strlen(list->name);
792             if (!strncmp(name, list->name, len)) {
793                 /* Hit */
794                 DEBUG("HIT %s\n", name);
795                 return 0;
796             }
797         } else {
798             ERROR("checkIgnoreList() - list->name is null\n");
799             return -2;
800         }
801
802         list = list->next;
803     }
804
805     return -1;
806 }
807
808
809 /**
810  * check Eventlog with AIDE DB
811  *
812  * IMA
813  * event->rgbEvent[0] - [20] <= SHA1 digest of the File
814  *
815  * Return
816  *   -1: ERROR
817  *    0: HIT
818  *    1: IGNORE
819  *    2: MISS
820  *
821  * skip this check 33sec -> 2sec
822  * 
823  */
824 int checkEventByAide(AIDE_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
825     TSS_PCR_EVENT *event;
826     char *name;
827     int rc = 0;
828     char *buf;
829     int buf_len;
830 #ifdef CONFIG_SQLITE
831 #else
832     AIDE_METADATA *md;
833 #if AIDE_CHBY_LIST
834     int i;
835 #else
836     ENTRY e;
837     ENTRY *ep;
838 #endif  //  AIDE_CHBY_LIST
839 #endif  //  CONFIG_SQLITE
840
841     // DEBUG("checkEventByAide - start\n");
842
843     if (ctx == NULL) {
844         ERROR("checkEventByAide - AIDE_CONTEXT is NULL\n");
845         return -1;
846     }
847
848     if (eventWrapper == NULL) {
849         ERROR("OcheckEventByAide - PENPTS_PCR_EVENT_WRAPPER is NULL\n");
850         return -1;
851     }
852
853     event = eventWrapper->event;
854
855     // 20100627 ignore pseudo event
856     if (event->eventType == OPENPTS_PSEUDO_EVENT_TYPE) {
857         ERROR("validateImaMeasurement - event->eventType == OPENPTS_PSEUDO_EVENT_TYPE\n");
858         return 1;
859     }
860
861     if (event->rgbEvent == NULL) {
862         DEBUG("no event\n");
863         return -1;
864     }
865
866     if (event->ulPcrValueLength != SHA1_DIGEST_SIZE) {
867         DEBUG("bad digest size\n");
868         return -1;
869     }
870
871     /* OK, let's find the HIT */
872 #ifdef CONFIG_SQLITE
873     /* base64 */
874     buf = encodeBase64(
875             event->rgbEvent,
876             20
877             &buf_len);
878     if (buf == NULL) {
879         ERROR("encodeBase64 fail");
880         return -1;
881     }
882     rc = verifyBySQLite(ctx, (char*)buf);
883     free(buf);
884
885     if (rc == OPENPTS_RESULT_VALID) {
886         /* hit */
887         // md = (AIDE_METADATA *) ep->data;
888         // DEBUG_FSM("checkFileByAide - HIT name=[%s]\n", md->name);
889         // md->status = OPENPTS_AIDE_MD_STATUS_HIT;
890         // md->event_wrapper = eventWrapper;  // n:1
891         // eventWrapper->aide_metadata = md;  // 1:n
892         // this output many lines:-P
893         // DEBUG("HIT  [%s] \n",b64);
894         return 0;
895     }
896 #else  // CONFIG_SQLITE
897 #if AIDE_CHBY_LIST
898     md = ctx->start;
899
900     for (i = 0; i < ctx->metadata_num; i++) {
901         if (md == NULL) {
902             DEBUG("AIDE MeataData is NULL\n");
903             return -1;
904         }
905
906         if (md->sha1 != NULL) {
907             if (memcmp(event->rgbEvent, md->sha1, SHA1_DIGEST_SIZE) == 0) {
908                 /* hit */
909                 DEBUG_FSM("checkFileByAide - HIT name=[%s]\n", md->name);
910                 md->status = OPENPTS_AIDE_MD_STATUS_HIT;
911                 md->event_wrapper = eventWrapper;  // n:1
912                 eventWrapper->aide_metadata = md;  // 1:n
913                 // copyAideMetadata(metadata, md);
914                 return 0;
915             }
916         }
917         md = md->next;
918     }
919     DEBUG_FSM("checkFileByAide - MISS\n");
920 #else  // hashtable
921
922     buf = encodeBase64(
923             event->rgbEvent,
924             20,
925             &buf_len);
926     if (buf == NULL) {
927         ERROR("encodeBase64 fail");
928         return -1;
929     }
930     e.key = (char *) buf;  // size?
931     e.data = NULL;  // just initialized for static analysys
932
933     // before (list)
934     //   real  0m36.896s
935     //   user  0m33.913s
936     //
937     // after (hash) BINARY
938     //   real  0m33.002s
939     //   user  0m30.093s
940     //
941     // after (hash) BASE64 :-(
942     //   real  0m39.148s
943     //   user  0m36.529s
944     //
945     // skip
946     //   real  0m2.506s
947     //   user  0m0.109s
948
949     rc = hsearch_r(e, FIND, &ep, ctx->aide_md_table);
950     if (rc != 0) {
951         /* hit */
952         // DEBUG("MD HIT\n");
953         md = (AIDE_METADATA *) ep->data;
954         DEBUG_FSM("checkFileByAide - HIT name=[%s]\n", md->name);
955         md->status = OPENPTS_AIDE_MD_STATUS_HIT;
956         md->event_wrapper = eventWrapper;  // n:1
957         eventWrapper->aide_metadata = md;  // 1:n
958         // DEBUG("HIT  [%s] %s\n",b64, md->name);
959         return 0;
960     } else {
961         // DEBUG("MISS [%s] MISS\n",b64);
962     }
963
964 #endif
965 #endif  // CONFIG_SQLITE
966
967     /* check ignore list */
968
969     // TODO(munetoh)
970     name = (char *)event->rgbEvent;
971     name += SHA1_DIGEST_SIZE;
972     /* add '\n' */
973     name = snmalloc(name, (event->ulEventLength - SHA1_DIGEST_SIZE));
974
975 #if 1
976     rc = checkIgnoreList(ctx, name);
977     if (rc == 0) {
978         // HIT
979         free(name);
980         return 1;  // IGNORE
981     }
982
983     free(name);
984     return 2;
985 #else
986     free(name);
987     return 1;  // force
988 #endif
989 }
990
991
992 /**
993  * Get AIDE metadata by name
994  * 
995  * "name" must be unique but
996  * if multiple entries has sama name this returns first one. :-P 
997  */
998 AIDE_METADATA *getMetadataFromAideByName(AIDE_CONTEXT *ctx, char *name) {
999     AIDE_METADATA *md;
1000     int i;
1001
1002     if (ctx == NULL) {
1003         return NULL;
1004     }
1005
1006     if (name == NULL) {
1007         return NULL;
1008     }
1009
1010     md = ctx->start;
1011
1012     for (i = 0; i < ctx->metadata_num; i++) {
1013         if (md == NULL) {
1014             return NULL;
1015         }
1016         if (md->name != NULL) {
1017             if (!strcmp(md->name, name)) {
1018                 /* hit */
1019                 DEBUG("checkFileByAide HIT %s\n", name);
1020                 return md;
1021             }
1022         }
1023         md = md->next;
1024     }
1025     return NULL;
1026 }
1027
1028 /**
1029  * Convert the following char to %XX
1030  *
1031  *  Caller have to free out buffer; 
1032  *
1033  *  Return 
1034  *    New length
1035  *    -1 ERROR
1036  *
1037  *   "%20"
1038  * % "%25"
1039  * : "%3A"
1040  * @ "%40"
1041  * [ "%5B"
1042  * ] "%5D"
1043  * { "%7B"
1044  * } "%7D"
1045  * ~ "%7E"
1046 */
1047 int escapeFilename(char **out, char *in) {
1048     char *buf;
1049     int len;
1050     int i, j;
1051
1052     len = strlen(in);
1053
1054     /*  rough malloc new buffer */
1055     buf = malloc(len*3);
1056     if (buf == NULL) {
1057         ERROR("no memory\n");
1058         return -1;
1059     }
1060
1061     /* convert */
1062     j = 0;
1063     for (i = 0; i < len; i++) {
1064         if (in[i] == 0x20) {
1065             buf[j]     = '%';
1066             buf[j + 1] = '2';
1067             buf[j + 2] = '0';
1068             j +=3;
1069         } else if (in[i] == 0x25) {
1070             buf[j]     = '%';
1071             buf[j + 1] = '2';
1072             buf[j + 2] = '5';
1073             j +=3;
1074         } else if (in[i] == 0x3A) {
1075             buf[j]     = '%';
1076             buf[j + 1] = '3';
1077             buf[j + 2] = 'A';
1078             j +=3;
1079         } else if (in[i] == 0x40) {
1080             buf[j]     = '%';
1081             buf[j + 1] = '4';
1082             buf[j + 2] = '0';
1083             j +=3;
1084         } else if (in[i] == 0x5B) {
1085             buf[j]     = '%';
1086             buf[j + 1] = '5';
1087             buf[j + 2] = 'B';
1088             j +=3;
1089         } else if (in[i] == 0x5D) {
1090             buf[j]     = '%';
1091             buf[j + 1] = '5';
1092             buf[j + 2] = 'D';
1093             j +=3;
1094         } else if (in[i] == 0x7B) {
1095             buf[j]     = '%';
1096             buf[j + 1] = '7';
1097             buf[j + 2] = 'B';
1098             j +=3;
1099         } else if (in[i] == 0x7D) {
1100             buf[j]     = '%';
1101             buf[j + 1] = '7';
1102             buf[j + 2] = 'D';
1103             j +=3;
1104         } else if (in[i] == 0x7E) {
1105             buf[j]     = '%';
1106             buf[j + 1] = '7';
1107             buf[j + 2] = 'E';
1108             j +=3;
1109         } else {
1110             buf[j] = in[i];
1111             j++;
1112         }
1113     }
1114     buf[j] = 0;
1115
1116     *out = buf;
1117     return j;
1118 }
1119
1120
1121 /**
1122  * Convert IML TSS/file(ptscd.conf) to AIDE DB
1123  *
1124  * ctx       get the IML before call this func
1125  * filename  output AIDE DB filename
1126  *
1127  * TODO(munetoh) IMA_31 only 
1128  */
1129 int convertImlToAideDbFile(OPENPTS_CONTEXT *ctx, char *filename) {
1130     gzFile fp;
1131     int i = 0;
1132     OPENPTS_SNAPSHOT *ss;
1133     OPENPTS_PCR_EVENT_WRAPPER *eventWrapper;
1134     TSS_PCR_EVENT *event;
1135     char *buf;
1136     int buf_len;
1137     char *aide_filename = NULL;
1138     int len;
1139
1140     DEBUG("convertImlToAideDbFile %s\n", filename);
1141
1142     /* file open for write */
1143     fp = gzopen(filename, "wb");
1144     if (fp == NULL) {
1145         ERROR("%s fail to open\n", filename);
1146         return -1;
1147     }
1148
1149     /* Header */
1150     gzprintf(fp, "@@begin_db\n");
1151     gzprintf(fp, "# This file was generated by OpenPTS\n");
1152     gzprintf(fp, "@@db_spec name sha1 \n");
1153
1154     /* IMLs */
1155     ss = getSnapshotFromTable(ctx->ss_table, 10, 1);  // TODO def or conf
1156     if (ss == NULL) {
1157         ERROR("events is missing\n");
1158         goto close;
1159     }
1160     eventWrapper = ss->start;
1161     if (eventWrapper == NULL) {
1162         ERROR("events is missing\n");
1163         goto close;
1164     }
1165
1166     event = eventWrapper->event;
1167
1168     // DEBUG("PCR[%d]\n", ss->pcrIndex);
1169     // DEBUG("event_num %d\n", ss->event_num);
1170
1171     // for (i = 0; i < ctx->eventNum; i++) {
1172     for (i = 0; i < ctx->ss_table->event_num; i++) {  // TODO ss->event_num?
1173         // DEBUG("SM DEBUG event %p\n",event);
1174
1175         if (event == NULL) {
1176             ERROR("event is NULL\n");
1177             goto close;
1178         }
1179
1180         if (event->rgbEvent == NULL) {
1181             ERROR("event->rgbEvent is NULL\n");
1182             goto close;
1183         }
1184
1185         // TODO 2010-10-05 SM
1186         // AIDE convert the following chars in filename
1187         // SPACE 0x20  ->  "%20"
1188         // @     0x40  ->  "%40"
1189         // [ "%5B"
1190         // ] "%5D"
1191         // % "%25"
1192         // : "%3A"
1193         // { "%7B"
1194         // } "%7D"
1195         // ~ "%7E"
1196
1197         // gzprintf(fp, "%s ",&eventWrapper->event->rgbEvent[20]);
1198
1199         /* filename (allocated) */
1200         len = escapeFilename(&aide_filename, (char *) &eventWrapper->event->rgbEvent[20]);
1201         if (len < 0) {
1202             ERROR("convertImlToAideDbFile - no mem?\n");
1203             gzprintf(fp, "bad_filename ");
1204         } else {
1205             gzprintf(fp, "%s ", aide_filename);
1206             free(aide_filename);
1207             aide_filename = NULL;
1208         }
1209
1210         /* digest */
1211         buf = encodeBase64(
1212             (unsigned char *)event->rgbEvent,
1213             SHA1_DIGEST_SIZE,
1214             &buf_len);
1215         if (buf == NULL) {
1216             ERROR("encodeBase64 fail");
1217             goto close;
1218         }
1219         gzprintf(fp, "%s \n", buf);
1220         free(buf);
1221
1222         // printf("%d %s\n", i, buf);
1223
1224         eventWrapper = eventWrapper->next_pcr;
1225         if (eventWrapper == NULL) break;
1226         event = eventWrapper->event;
1227     }
1228
1229     /* Footer */
1230     gzprintf(fp, "@@end_db\n");
1231
1232     /* file close */
1233     gzseek(fp, 1L, SEEK_CUR);  // add one \n
1234   close:
1235     gzclose(fp);
1236     if (aide_filename != NULL) free(aide_filename);
1237
1238     DEBUG("convertImlToAideDbFile - done\n");
1239
1240     return i+1;  // event num
1241 }
1242
1243 /**
1244  * reduce the size of AIDE DB
1245  *
1246  *                     reduced
1247  *  AIDE-DB  IMA-IML   AIDE-DB
1248  *  --------------------------
1249  *     O        O         O
1250  *     O        -         -
1251  *     -        O         -
1252  *     -        -         -
1253  *  --------------------------
1254  *
1255  *
1256  * return AIDE entry count
1257  *
1258  */
1259 int writeReducedAidbDatabase(AIDE_CONTEXT *ctx, char *filename) {
1260     gzFile fp;
1261     AIDE_METADATA *md;
1262     int i;
1263     int cnt = 0;
1264     char *buf;
1265     int buf_len;
1266
1267     DEBUG("writeReducedAidbDatabase %s\n", filename);
1268
1269     if (ctx == NULL) {
1270         return -1;
1271     }
1272
1273     /* file open for write */
1274     fp = gzopen(filename, "wb");
1275     if (fp == NULL) {
1276         ERROR("%s fail to open\n", filename);
1277         return -1;
1278     }
1279
1280     /* Header */
1281     gzprintf(fp, "@@begin_db\n");
1282     gzprintf(fp, "# This file was generated by OpenPTS\n");
1283     gzprintf(fp, "@@db_spec name sha1 \n");
1284
1285     /* scan */
1286     md = ctx->start;
1287
1288     for (i = 0; i < ctx->metadata_num; i++) {
1289         if (md == NULL) {
1290             return -1;
1291         }
1292
1293         if (md->status == OPENPTS_AIDE_MD_STATUS_HIT) {
1294             // printf("+");
1295             buf = encodeBase64(
1296                 (unsigned char *)md->sha1,
1297                 SHA1_DIGEST_SIZE,
1298                 &buf_len);
1299             if (buf == NULL) {
1300                 ERROR("encodeBase64 fail");
1301                 return -1;
1302             }
1303             gzprintf(fp, "%s ", md->name);
1304             gzprintf(fp, "%s \n", buf);
1305             free(buf);
1306             cnt++;
1307         }
1308
1309         md = md->next;
1310     }
1311
1312     /* Footer */
1313     gzprintf(fp, "@@end_db\n");
1314
1315     /* file close */
1316     gzseek(fp, 1L, SEEK_CUR);  // add one \n
1317     gzclose(fp);
1318
1319     DEBUG("convertImlToAideDbFile - done\n");
1320
1321
1322     return cnt;
1323 }
1324
1325 #ifdef CONFIG_SQLITE
1326 /**
1327  * Convert AIDE BD file to SQLite DB file 
1328  *
1329  * Return 
1330  *  0 PTS_SUCCESS success
1331  *    PTS_INTERNAL_ERROR  ERROR
1332  */
1333 int convertAideDbfileToSQLiteDbFile(char * aide_filename, char * sqlite_filename) {
1334     int rc = PTS_SUCCESS;
1335     AIDE_CONTEXT *ctx;
1336     sqlite3 *db;
1337     int i;
1338     int j;
1339     AIDE_METADATA *md;
1340     char *err;
1341     char *sql;
1342
1343     /* check */
1344     if (aide_filename == NULL) {
1345         ERROR("AIDE file is null\n");
1346         return PTS_INTERNAL_ERROR;
1347     }
1348     if (sqlite_filename == NULL) {
1349         ERROR("sqlite file is null\n");
1350         return PTS_INTERNAL_ERROR;
1351     }
1352
1353
1354     /* new AIDE context */
1355     ctx = newAideContext();
1356
1357     /* read AIDE DB file -> ctx */
1358     rc = loadAideDatabaseFile(ctx, aide_filename);
1359     if (rc < 0) {
1360         ERROR("read AIDE DB %s fail, rc = %d", aide_filename, rc);
1361         return -1;
1362     }
1363
1364
1365     /* SQLite */
1366
1367     /* rm existing DB file */
1368     remove(sqlite_filename);
1369
1370     /* open */
1371     sqlite3_open(sqlite_filename, &db);
1372     if (db == NULL) {
1373         ERROR("open AIDE DB fail\n");
1374         rc = PTS_INTERNAL_ERROR;
1375         goto free;
1376     }
1377
1378     sqlite3_exec(db,
1379         "CREATE TABLE sample (id INTEGER PRIMARY KEY, digest TEXT NOT NULL, "
1380         "name TEXT NOT NULL, state INTEGER NOT NULL)",
1381         NULL, NULL, &err);
1382     // DEBUG("CREATE err=%s\n", err);
1383
1384     /* */
1385     sqlite3_exec(db, "BEGIN", NULL, NULL, &err);
1386     // DEBUG("BEGIN err=%s\n", err);
1387
1388     /* add */
1389     md = ctx->start;
1390     j = 0;
1391     for (i = 0; i < ctx->metadata_num; i++) {
1392         if (md->hash_key != NULL) {
1393             sql = sqlite3_mprintf(
1394                 "INSERT INTO sample (id, digest, name, state)  VALUES (%d, '%s','%s', %d)",
1395                     j, md->hash_key, md->name, 0);
1396             sqlite3_exec(db, sql, NULL, NULL, &err);
1397             // DEBUG("INSERT err=%s\n", err);
1398             j++;
1399         }
1400         md = md->next;
1401     }
1402
1403     /* */
1404     sqlite3_exec(db, "COMMIT", NULL, NULL, &err);
1405     // DEBUG("COMMIT err=%s\n", err);
1406
1407     /* INDEX */
1408     sqlite3_exec(db, "CREATE INDEX digestindex ON sample(digest)", NULL, NULL, &err);
1409     // DEBUG("CREATE INDEX err=%s\n", err);
1410
1411     /* close */
1412     sqlite3_close(db);
1413
1414     /* Good */
1415     rc = PTS_SUCCESS;
1416
1417   free:
1418     freeAideContext(ctx);
1419
1420     return rc;
1421 }
1422
1423 /**
1424  * load (open) SQLite DB file 
1425  */
1426 int loadSQLiteDatabaseFile(AIDE_CONTEXT *ctx, char *filename) {
1427     /* check */
1428     if (ctx == NULL) {
1429         ERROR("ctx == NULL\n");
1430         return PTS_INTERNAL_ERROR;
1431     }
1432     if (filename == NULL) {
1433         ERROR("filename == NULL\n");
1434         return PTS_INTERNAL_ERROR;
1435     }
1436
1437     /* open */
1438     sqlite3_open(filename, &ctx->sqlite_db);
1439     if (ctx->sqlite_db == NULL) {
1440         ERROR("open AIDE SQLite DB %s fail\n", filename);
1441         return PTS_INTERNAL_ERROR;
1442     }
1443
1444     return PTS_SUCCESS;
1445 }
1446
1447 /**
1448  * Veify 
1449  */
1450 int verifyBySQLite(AIDE_CONTEXT *ctx, char * key) {
1451     char *err;
1452     char *sql;
1453     char **result;
1454     int row, col;
1455
1456     /* check */
1457     if (ctx == NULL) {
1458         ERROR("ctx == NULL\n");
1459         return PTS_INTERNAL_ERROR;
1460     }
1461     if (ctx->sqlite_db == NULL) {
1462         ERROR("ctx->sqlite_db == NULL\n");
1463         return PTS_INTERNAL_ERROR;
1464     }
1465
1466     sql = sqlite3_mprintf("SELECT * from sample where digest = '%s'", key);
1467     sqlite3_get_table(ctx->sqlite_db, sql, &result, &row, &col, &err);
1468     // DEBUG("%2d %d %s\n",row,col, md->hash_key);
1469
1470     if (row >= 1) {
1471         return OPENPTS_RESULT_VALID;
1472     }
1473
1474     // ERROR("row = %d\n",row);
1475
1476     /* free */
1477     sqlite3_free(sql);
1478     sqlite3_free(err);
1479     sqlite3_free_table(result);
1480
1481
1482
1483     return OPENPTS_RESULT_UNKNOWN;
1484 }
1485 #endif  // CONFIG_SQLITE