OSDN Git Service

fixed issues reported by static analysis tool
[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 = malloc(SHA1_DIGEST_SIZE + 8);
463                             len = decodeBase64(
464                                 md->sha1,
465                                 (unsigned char *)ptr,
466                                 SHA1_BASE64_DIGEST_SIZE);
467                             if (len != SHA1_DIGEST_SIZE) {
468                                 ERROR("bad SHA1 size %d  %s\n", len, ptr);
469                                 // printf("base64 [%s] => [", ptr);
470                                 printHex("digest", md->sha1, len, "\n");
471                                 // printf("]\n");
472                             }
473                         }
474                         break;
475                     case AIDE_ITEM_SHA256:  // base64
476                         if (!is_null) {
477                             md->sha256 = malloc(SHA256_DIGEST_SIZE);
478                             len = decodeBase64(
479                                 md->sha256,
480                                 (unsigned char *)ptr,
481                                 SHA256_BASE64_DIGEST_SIZE);
482                             if (len != SHA256_DIGEST_SIZE) {
483                                 ERROR("bad SHA256 size %d\n", len);
484                                 printf("base64 [%s] => [", ptr);
485                                 printHex("", (BYTE *)ptr, 2, " ");
486                                 printf("][\n");
487                                 printHex("", md->sha256, len, " ");
488                                 printf("]\n");
489                             }
490                         }
491                         break;
492                     case AIDE_ITEM_SHA512:  // base64
493                         if (!is_null) {
494                             md->sha512 = malloc(SHA512_DIGEST_SIZE);
495                             len = decodeBase64(
496                                 md->sha512,
497                                 (unsigned char *)ptr,
498                                 SHA512_BASE64_DIGEST_SIZE);
499                             if (len != SHA512_DIGEST_SIZE) {
500                                 ERROR("bad SHA512 size %d\n", len);
501                                 printf("base64 [%s] => [", ptr);
502                                 printHex("", (BYTE *)ptr, 2, "");
503                                 printf("][\n");
504                                 printHex("", md->sha512, len, "");
505                                 printf("]\n");
506                             }
507                         }
508                         break;
509                     case AIDE_ITEM_XATTRS:
510                         // DEBUG("AIDE_ITEM_XATTRS\n");
511                         break;
512                     default:
513                         // DEBUG("Unknown item[%d] %d\n", i, items[i]);
514                         break;
515                 }  // switch
516                 ptr = sep + 1;
517             }  // for
518
519             /* update ctx */
520             md->status = OPENPTS_AIDE_MD_STATUS_NEW;
521             addAideMetadata(ctx, md);
522
523             /* save to the hash table */
524             if (sha1_b64_ptr != NULL) {
525                 // TODO SHA1 only, add hash agility later
526                 /* alloc hash key */
527                 sha1_b64_ptr[SHA1_BASE64_DIGEST_SIZE] = 0;  // jXgiZyt0yUbP4QhAq9WFsLF/FL4=  28
528                 md->hash_key = malloc(strlen(sha1_b64_ptr) +1);
529                 // TODO check NULL
530                 memcpy(md->hash_key, sha1_b64_ptr, strlen(sha1_b64_ptr) + 1);
531
532                 e.key = (char *)md->hash_key;
533                 e.data = (void *)md;
534                 rc = hsearch_r(e, ENTER, &ep, ctx->aide_md_table);
535
536                 if (rc == 0) {
537                     if (errno == ENOMEM) {
538                         ERROR("  hsearch_r failed, table is full, errno=%x\n", errno);
539                     } else {
540                         ERROR("  hsearch_r failed, errno=%x\n", errno);
541                     }
542                 }
543                 // CAUTION too many messages, use for debugging the unit test
544                 // DEBUG("Hash Table <-  %4d [%s] %s\n", ctx->aide_md_table_size, md->hash_key, md->name);
545                 ctx->aide_md_table_size++;
546             }
547
548
549 #if 0
550             if (ctx->start == NULL) {
551                 ctx->start = md;
552                 ctx->end = md;
553             } else {
554                 ctx->end->next = md;
555                 md->prev = ctx->end;
556                 ctx->end = md;
557             }
558             ctx->metadata_num++;
559 #endif
560         } else {
561             // ignore printf("??? [%s]\n", buf);
562         }  // if
563     }  // while
564
565     gzclose(fp);
566     DEBUG("loadAideDatabaseFile - has %d entries\n", ctx->metadata_num);
567     DEBUG("loadAideDatabaseFile - done\n");
568
569     return ctx->metadata_num;
570 }
571
572
573 /**
574  * read AIDE ignore name
575  *
576  * Return
577  *    PTS_SUCCESS
578  *    PTS_OS_ERROR
579  * caller
580  *  ir.c
581  */
582 int readAideIgnoreNameFile(AIDE_CONTEXT *ctx, char *filename) {
583     int rc = PTS_SUCCESS;
584     FILE *fp;
585     char line[BUF_SIZE];
586     int len;
587     int cnt = 0;
588     AIDE_LIST *list;
589     ENTRY e;  // htable
590     ENTRY *ep;
591
592     DEBUG("readAideIgnoreNameFile - start, filename=[%s]\n", filename);
593
594     /* Open file for read */
595     fp = fopen(filename, "r");
596     if (fp == NULL) {
597         DEBUG("%s missing\n", filename);
598         return -1;
599     }
600
601
602     /* parse */
603     while (fgets(line, BUF_SIZE, fp) != NULL) {  // read line
604         /* ignore comment, null line */
605         if (line[0] == '#') {
606             // comment
607         } else {
608             /* name=value line*/
609             /* remove CR */
610             len = strlen(line);
611             if (line[len-1] == 0x0a) line[len-1] = 0;
612
613             DEBUG("%4d [%s]\n", cnt, line);
614
615             /* new  */
616             list = malloc(sizeof(AIDE_LIST));
617             if (list == NULL) {
618                 ERROR("no mem\n");
619                 rc = PTS_OS_ERROR;
620                 goto error;  // return -1;
621             }
622             memset(list, 0, sizeof(AIDE_LIST));
623             list->name = smalloc(line);
624
625             /* add to chain */
626             if (ctx->ignore_name_start == NULL) {
627                 /* first entry */
628                 ctx->ignore_name_start = list;
629                 ctx->ignore_name_end = list;
630                 list->next = NULL;
631             } else {
632                 /* next entry */
633                 ctx->ignore_name_end->next = list;
634                 ctx->ignore_name_end = list;
635                 list->next = NULL;
636             }
637
638             /* hash table */
639             e.key = list->name;
640             e.data = (void *)list;
641             rc = hsearch_r(e, ENTER, &ep, ctx->aide_in_table);
642             if (rc == 0) {
643                 if (errno == ENOMEM) {
644                     ERROR("  hsearch_r failed, ignore name table is full, errno=%x\n", errno);
645                 } else {
646                     ERROR("  hsearch_r failed, errno=%x\n", errno);
647                 }
648             }
649             ctx->aide_in_table_size++;
650
651             cnt++;
652         }  // #
653     }  // while
654
655   error:
656     fclose(fp);
657
658     DEBUG("readAideIgnoreNameFile - done, num = %d\n", cnt);
659
660     return rc;
661 }
662
663
664 /**
665  * print all AIDE data, for TEST and DEBUG
666  */
667 int printAideData(AIDE_CONTEXT *ctx) {
668     AIDE_METADATA *md;
669     int i;
670
671     DEBUG("printAideData - start\n");
672     DEBUG("printAideData - num = %d\n", ctx->metadata_num);
673
674     md = ctx->start;
675
676     for (i = 0; i < ctx->metadata_num; i++) {
677         printf("%4d ", i);
678         if ( md->name  != NULL) printf("%30s ", md->name);
679         if ( md->lname != NULL) printf("%20s ", md->lname);
680         if ( md->attr  != 0)    printf("%08X ", md->attr);
681         if (md->sha1   != NULL)
682             printHex("", md->sha1, 20, " ");
683         else
684             printf("                                        -");
685
686         if (md->sha256 != NULL)
687             printHex("", md->sha256, 32, " ");
688         else
689             printf("                                                                -");
690
691         printf(" <<\n");
692         md = md->next;
693     }
694
695     DEBUG("printAideData - end\n");
696
697     return 0;
698 }
699
700 #if 1
701 int hexcmp(BYTE *d1, BYTE *d2, int len) {
702     int i;
703
704     for (i = 0; i < len; i++) {
705         if (d1[i] != d2[i]) {
706             return -1;
707         }
708     }
709     // HIT
710     return 0;
711 }
712 #endif
713
714 // TODO(munetoh) how this work?
715 void copyAideMetadata(AIDE_METADATA *dst, AIDE_METADATA *src) {
716     if (dst->name == NULL) {
717         dst->name = malloc(strlen(src->name) + 1);
718         memcpy(dst->name, src->name, strlen(src->name) + 1);
719     }
720 }
721
722 /**
723  * check AIDE MD vs given MD (SHA1)
724  *
725  * TODO(munetoh) obsolute use checkEventByAide()
726  */
727 int checkFileByAide(AIDE_CONTEXT *ctx, AIDE_METADATA *metadata) {
728     AIDE_METADATA *md;
729     int i;
730
731     if (ctx == NULL) {
732         return -1;
733     }
734
735     if (metadata == NULL) {
736         return -1;
737     }
738
739     md = ctx->start;
740
741     for (i = 0; i < ctx->metadata_num; i++) {
742         if (md == NULL) {
743             return -1;
744         }
745         if ((metadata->sha1 != NULL) && (md->sha1 != NULL)) {
746             if (!hexcmp(metadata->sha1, md->sha1, SHA1_DIGEST_SIZE)) {
747                 /* hit */
748                 DEBUG_FSM("checkFileByAide - HIT name=[%s]\n", md->name);
749                 md->status = OPENPTS_AIDE_MD_STATUS_HIT;
750                 copyAideMetadata(metadata, md);
751                 return 0;
752             }
753         }
754         md = md->next;
755     }
756     DEBUG_FSM("checkFileByAide - MISS\n");
757     return -2;
758 }
759
760
761 /**
762  *
763  * return 
764  *    -1: MISS
765  *     0: HIT
766  *
767  */
768 int checkIgnoreList(AIDE_CONTEXT *ctx, char *name) {
769     AIDE_LIST *list;
770     int len;
771
772     /* check */
773     if (name == NULL) {
774         ERROR("checkIgnoreList() - name is null\n");
775         return -2;
776     }
777
778     list = ctx->ignore_name_start;
779     while (list != NULL) {
780         // TODO(munetoh)  not check the all string
781         if (list->name != NULL) {
782             len = strlen(list->name);
783             if (!strncmp(name, list->name, len)) {
784                 /* Hit */
785                 DEBUG("HIT %s\n", name);
786                 return 0;
787             }
788         } else {
789             ERROR("checkIgnoreList() - list->name is null\n");
790             return -2;
791         }
792
793         list = list->next;
794     }
795
796     return -1;
797 }
798
799
800 /**
801  * check Eventlog with AIDE DB
802  *
803  * IMA
804  * event->rgbEvent[0] - [20] <= SHA1 digest of the File
805  *
806  * Return
807  *   -1: ERROR
808  *    0: HIT
809  *    1: IGNORE
810  *    2: MISS
811  *
812  * skip this check 33sec -> 2sec
813  * 
814  */
815 int checkEventByAide(AIDE_CONTEXT *ctx, OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
816     TSS_PCR_EVENT *event;
817     char *name;
818     int rc = 0;
819 #ifdef CONFIG_SQLITE
820     BYTE b64[SHA1_BASE64_DIGEST_SIZE+1];
821 #else
822     AIDE_METADATA *md;
823 #if AIDE_CHBY_LIST
824     int i;
825 #else
826     ENTRY e;
827     ENTRY *ep;
828     BYTE b64[SHA1_BASE64_DIGEST_SIZE+1];
829 #endif
830 #endif  //  CONFIG_SQLITE
831
832     // DEBUG("checkEventByAide - start\n");
833
834     if (ctx == NULL) {
835         ERROR("checkEventByAide - AIDE_CONTEXT is NULL\n");
836         return -1;
837     }
838
839     if (eventWrapper == NULL) {
840         ERROR("OcheckEventByAide - PENPTS_PCR_EVENT_WRAPPER is NULL\n");
841         return -1;
842     }
843
844     event = eventWrapper->event;
845
846     // 20100627 ignore pseudo event
847     if (event->eventType == OPENPTS_PSEUDO_EVENT_TYPE) {
848         ERROR("validateImaMeasurement - event->eventType == OPENPTS_PSEUDO_EVENT_TYPE\n");
849         return 1;
850     }
851
852     if (event->rgbEvent == NULL) {
853         DEBUG("no event\n");
854         return -1;
855     }
856
857     if (event->ulPcrValueLength != SHA1_DIGEST_SIZE) {
858         DEBUG("bad digest size\n");
859         return -1;
860     }
861
862     /* OK, let's find the HIT */
863 #ifdef CONFIG_SQLITE
864     /* base64 */
865     encodeBase64(b64, event->rgbEvent, 20);
866     b64[SHA1_BASE64_DIGEST_SIZE] = 0;
867
868     rc = verifyBySQLite(ctx, (char*)b64);
869
870     if (rc == OPENPTS_RESULT_VALID) {
871         /* hit */
872         // md = (AIDE_METADATA *) ep->data;
873         // DEBUG_FSM("checkFileByAide - HIT name=[%s]\n", md->name);
874         // md->status = OPENPTS_AIDE_MD_STATUS_HIT;
875         // md->event_wrapper = eventWrapper;  // n:1
876         // eventWrapper->aide_metadata = md;  // 1:n
877         // this output many lines:-P
878         // DEBUG("HIT  [%s] \n",b64);
879         return 0;
880     }
881 #else  // CONFIG_SQLITE
882 #if AIDE_CHBY_LIST
883     md = ctx->start;
884
885     for (i = 0; i < ctx->metadata_num; i++) {
886         if (md == NULL) {
887             DEBUG("AIDE MeataData is NULL\n");
888             return -1;
889         }
890
891         if (md->sha1 != NULL) {
892             if (memcmp(event->rgbEvent, md->sha1, SHA1_DIGEST_SIZE) == 0) {
893                 /* hit */
894                 DEBUG_FSM("checkFileByAide - HIT name=[%s]\n", md->name);
895                 md->status = OPENPTS_AIDE_MD_STATUS_HIT;
896                 md->event_wrapper = eventWrapper;  // n:1
897                 eventWrapper->aide_metadata = md;  // 1:n
898                 // copyAideMetadata(metadata, md);
899                 return 0;
900             }
901         }
902         md = md->next;
903     }
904     DEBUG_FSM("checkFileByAide - MISS\n");
905 #else  // hashtable
906
907     encodeBase64(b64, event->rgbEvent, 20);
908     b64[SHA1_BASE64_DIGEST_SIZE] = 0;
909
910     e.key = (char *) b64;  // size?
911     e.data = NULL;  // just initialized for static analysys
912
913     // before (list)
914     //   real  0m36.896s
915     //   user  0m33.913s
916     //
917     // after (hash) BINARY
918     //   real  0m33.002s
919     //   user  0m30.093s
920     //
921     // after (hash) BASE64 :-(
922     //   real  0m39.148s
923     //   user  0m36.529s
924     //
925     // skip
926     //   real  0m2.506s
927     //   user  0m0.109s
928
929     rc = hsearch_r(e, FIND, &ep, ctx->aide_md_table);
930     if (rc != 0) {
931         /* hit */
932         // DEBUG("MD HIT\n");
933         md = (AIDE_METADATA *) ep->data;
934         DEBUG_FSM("checkFileByAide - HIT name=[%s]\n", md->name);
935         md->status = OPENPTS_AIDE_MD_STATUS_HIT;
936         md->event_wrapper = eventWrapper;  // n:1
937         eventWrapper->aide_metadata = md;  // 1:n
938         // DEBUG("HIT  [%s] %s\n",b64, md->name);
939         return 0;
940     } else {
941         // DEBUG("MISS [%s] MISS\n",b64);
942     }
943
944 #endif
945 #endif  // CONFIG_SQLITE
946
947     /* check ignore list */
948
949     // TODO(munetoh)
950     name = (char *)event->rgbEvent;
951     name += SHA1_DIGEST_SIZE;
952     /* add '\n' */
953     name = snmalloc(name, (event->ulEventLength - SHA1_DIGEST_SIZE));
954
955 #if 1
956     rc = checkIgnoreList(ctx, name);
957     if (rc == 0) {
958         // HIT
959         free(name);
960         return 1;  // IGNORE
961     }
962
963     free(name);
964     return 2;
965 #else
966     free(name);
967     return 1;  // force
968 #endif
969 }
970
971
972 /**
973  * Get AIDE metadata by name
974  * 
975  * "name" must be unique but
976  * if multiple entries has sama name this returns first one. :-P 
977  */
978 AIDE_METADATA *getMetadataFromAideByName(AIDE_CONTEXT *ctx, char *name) {
979     AIDE_METADATA *md;
980     int i;
981
982     if (ctx == NULL) {
983         return NULL;
984     }
985
986     if (name == NULL) {
987         return NULL;
988     }
989
990     md = ctx->start;
991
992     for (i = 0; i < ctx->metadata_num; i++) {
993         if (md == NULL) {
994             return NULL;
995         }
996         if (md->name != NULL) {
997             if (!strcmp(md->name, name)) {
998                 /* hit */
999                 DEBUG("checkFileByAide HIT %s\n", name);
1000                 return md;
1001             }
1002         }
1003         md = md->next;
1004     }
1005     return NULL;
1006 }
1007
1008 /**
1009  * Convert the following char to %XX
1010  *
1011  *  Caller have to free out buffer; 
1012  *
1013  *  Return 
1014  *    New length
1015  *    -1 ERROR
1016  *
1017  *   "%20"
1018  * % "%25"
1019  * : "%3A"
1020  * @ "%40"
1021  * [ "%5B"
1022  * ] "%5D"
1023  * { "%7B"
1024  * } "%7D"
1025  * ~ "%7E"
1026 */
1027 int escapeFilename(char **out, char *in) {
1028     char *buf;
1029     int len;
1030     int i, j;
1031
1032     len = strlen(in);
1033
1034     /*  rough malloc new buffer */
1035     buf = malloc(len*3);
1036     if (buf == NULL) {
1037         ERROR("no memory\n");
1038         return -1;
1039     }
1040
1041     /* convert */
1042     j = 0;
1043     for (i = 0; i < len; i++) {
1044         if (in[i] == 0x20) {
1045             buf[j]     = '%';
1046             buf[j + 1] = '2';
1047             buf[j + 2] = '0';
1048             j +=3;
1049         } else if (in[i] == 0x25) {
1050             buf[j]     = '%';
1051             buf[j + 1] = '2';
1052             buf[j + 2] = '5';
1053             j +=3;
1054         } else if (in[i] == 0x3A) {
1055             buf[j]     = '%';
1056             buf[j + 1] = '3';
1057             buf[j + 2] = 'A';
1058             j +=3;
1059         } else if (in[i] == 0x40) {
1060             buf[j]     = '%';
1061             buf[j + 1] = '4';
1062             buf[j + 2] = '0';
1063             j +=3;
1064         } else if (in[i] == 0x5B) {
1065             buf[j]     = '%';
1066             buf[j + 1] = '5';
1067             buf[j + 2] = 'B';
1068             j +=3;
1069         } else if (in[i] == 0x5D) {
1070             buf[j]     = '%';
1071             buf[j + 1] = '5';
1072             buf[j + 2] = 'D';
1073             j +=3;
1074         } else if (in[i] == 0x7B) {
1075             buf[j]     = '%';
1076             buf[j + 1] = '7';
1077             buf[j + 2] = 'B';
1078             j +=3;
1079         } else if (in[i] == 0x7D) {
1080             buf[j]     = '%';
1081             buf[j + 1] = '7';
1082             buf[j + 2] = 'D';
1083             j +=3;
1084         } else if (in[i] == 0x7E) {
1085             buf[j]     = '%';
1086             buf[j + 1] = '7';
1087             buf[j + 2] = 'E';
1088             j +=3;
1089         } else {
1090             buf[j] = in[i];
1091             j++;
1092         }
1093     }
1094     buf[j] = 0;
1095
1096     *out = buf;
1097     return j;
1098 }
1099
1100
1101 /**
1102  * Convert IML TSS/file(ptscd.conf) to AIDE DB
1103  *
1104  * ctx       get the IML before call this func
1105  * filename  output AIDE DB filename
1106  *
1107  * TODO(munetoh) IMA_31 only 
1108  */
1109 int convertImlToAideDbFile(OPENPTS_CONTEXT *ctx, char *filename) {
1110     gzFile fp;
1111     int i = 0;
1112     OPENPTS_SNAPSHOT *ss;
1113     OPENPTS_PCR_EVENT_WRAPPER *eventWrapper;
1114     TSS_PCR_EVENT *event;
1115     unsigned char buf[128];  // TODO(munetoh)
1116     char *aide_filename = NULL;
1117     int len;
1118
1119     DEBUG("convertImlToAideDbFile %s\n", filename);
1120
1121     /* file open for write */
1122     fp = gzopen(filename, "wb");
1123     if (fp == NULL) {
1124         ERROR("%s fail to open\n", filename);
1125         return -1;
1126     }
1127
1128     /* Header */
1129     gzprintf(fp, "@@begin_db\n");
1130     gzprintf(fp, "# This file was generated by OpenPTS\n");
1131     gzprintf(fp, "@@db_spec name sha1 \n");
1132
1133     /* IMLs */
1134     ss = getSnapshotFromTable(ctx->ss_table, 10, 1);  // TODO def or conf
1135     if (ss == NULL) {
1136         ERROR("events is missing\n");
1137         goto close;
1138     }
1139     eventWrapper = ss->start;
1140     if (eventWrapper == NULL) {
1141         ERROR("events is missing\n");
1142         goto close;
1143     }
1144
1145     event = eventWrapper->event;
1146
1147     // DEBUG("PCR[%d]\n", ss->pcrIndex);
1148     // DEBUG("event_num %d\n", ss->event_num);
1149
1150     // for (i = 0; i < ctx->eventNum; i++) {
1151     for (i = 0; i < ctx->ss_table->event_num; i++) {  // TODO ss->event_num?
1152         memset(buf, 0, sizeof(buf));
1153         // DEBUG("SM DEBUG event %p\n",event);
1154
1155         if (event == NULL) {
1156             ERROR("event is NULL\n");
1157             goto close;
1158         }
1159
1160         if (event->rgbEvent == NULL) {
1161             ERROR("event->rgbEvent is NULL\n");
1162             goto close;
1163         }
1164
1165         // TODO 2010-10-05 SM
1166         // AIDE convert the following chars in filename
1167         // SPACE 0x20  ->  "%20"
1168         // @     0x40  ->  "%40"
1169         // [ "%5B"
1170         // ] "%5D"
1171         // % "%25"
1172         // : "%3A"
1173         // { "%7B"
1174         // } "%7D"
1175         // ~ "%7E"
1176
1177         // gzprintf(fp, "%s ",&eventWrapper->event->rgbEvent[20]);
1178
1179         /* filename (allocated) */
1180         len = escapeFilename(&aide_filename, (char *) &eventWrapper->event->rgbEvent[20]);
1181         if (len < 0) {
1182             ERROR("convertImlToAideDbFile - no mem?\n");
1183             gzprintf(fp, "bad_filename ");
1184         } else {
1185             gzprintf(fp, "%s ", aide_filename);
1186             free(aide_filename);
1187             aide_filename = NULL;
1188         }
1189
1190         /* digest */
1191         encodeBase64(buf, (unsigned char *)event->rgbEvent, SHA1_DIGEST_SIZE);
1192         gzprintf(fp, "%s \n", buf);
1193
1194         // printf("%d %s\n", i, buf);
1195
1196         eventWrapper = eventWrapper->next_pcr;
1197         if (eventWrapper == NULL) break;
1198         event = eventWrapper->event;
1199     }
1200
1201     /* Footer */
1202     gzprintf(fp, "@@end_db\n");
1203
1204     /* file close */
1205     gzseek(fp, 1L, SEEK_CUR);  // add one \n
1206   close:
1207     gzclose(fp);
1208     if (aide_filename != NULL) free(aide_filename);
1209
1210     DEBUG("convertImlToAideDbFile - done\n");
1211
1212     return i+1;  // event num
1213 }
1214
1215 /**
1216  * reduce the size of AIDE DB
1217  *
1218  *                     reduced
1219  *  AIDE-DB  IMA-IML   AIDE-DB
1220  *  --------------------------
1221  *     O        O         O
1222  *     O        -         -
1223  *     -        O         -
1224  *     -        -         -
1225  *  --------------------------
1226  *
1227  *
1228  * return AIDE entry count
1229  *
1230  */
1231 int writeReducedAidbDatabase(AIDE_CONTEXT *ctx, char *filename) {
1232     gzFile fp;
1233     AIDE_METADATA *md;
1234     int i;
1235     int cnt = 0;
1236     unsigned char buf[128];  // TODO(munetoh)
1237
1238     DEBUG("writeReducedAidbDatabase %s\n", filename);
1239
1240     if (ctx == NULL) {
1241         return -1;
1242     }
1243
1244     /* file open for write */
1245     fp = gzopen(filename, "wb");
1246     if (fp == NULL) {
1247         ERROR("%s fail to open\n", filename);
1248         return -1;
1249     }
1250
1251     /* Header */
1252     gzprintf(fp, "@@begin_db\n");
1253     gzprintf(fp, "# This file was generated by OpenPTS\n");
1254     gzprintf(fp, "@@db_spec name sha1 \n");
1255
1256     /* scan */
1257     md = ctx->start;
1258
1259     for (i = 0; i < ctx->metadata_num; i++) {
1260         if (md == NULL) {
1261             return -1;
1262         }
1263
1264         if (md->status == OPENPTS_AIDE_MD_STATUS_HIT) {
1265             // printf("+");
1266             memset(buf, 0, sizeof(buf));
1267             encodeBase64(buf, (unsigned char *)md->sha1, SHA1_DIGEST_SIZE);
1268             gzprintf(fp, "%s ", md->name);
1269             gzprintf(fp, "%s \n", buf);
1270             cnt++;
1271         }
1272
1273         md = md->next;
1274     }
1275
1276     /* Footer */
1277     gzprintf(fp, "@@end_db\n");
1278
1279     /* file close */
1280     gzseek(fp, 1L, SEEK_CUR);  // add one \n
1281     gzclose(fp);
1282
1283     DEBUG("convertImlToAideDbFile - done\n");
1284
1285
1286     return cnt;
1287 }
1288
1289 #ifdef CONFIG_SQLITE
1290 /**
1291  * Convert AIDE BD file to SQLite DB file 
1292  *
1293  * Return 
1294  *  0 PTS_SUCCESS success
1295  *    PTS_INTERNAL_ERROR  ERROR
1296  */
1297 int convertAideDbfileToSQLiteDbFile(char * aide_filename, char * sqlite_filename) {
1298     int rc = PTS_SUCCESS;
1299     AIDE_CONTEXT *ctx;
1300     sqlite3 *db;
1301     int i;
1302     int j;
1303     AIDE_METADATA *md;
1304     char *err;
1305     char *sql;
1306
1307     /* check */
1308     if (aide_filename == NULL) {
1309         ERROR("AIDE file is null\n");
1310         return PTS_INTERNAL_ERROR;
1311     }
1312     if (sqlite_filename == NULL) {
1313         ERROR("sqlite file is null\n");
1314         return PTS_INTERNAL_ERROR;
1315     }
1316
1317
1318     /* new AIDE context */
1319     ctx = newAideContext();
1320
1321     /* read AIDE DB file -> ctx */
1322     rc = loadAideDatabaseFile(ctx, aide_filename);
1323     if (rc < 0) {
1324         ERROR("read AIDE DB %s fail, rc = %d", aide_filename, rc);
1325         return -1;
1326     }
1327
1328
1329     /* SQLite */
1330
1331     /* rm existing DB file */
1332     remove(sqlite_filename);
1333
1334     /* open */
1335     sqlite3_open(sqlite_filename, &db);
1336     if (db == NULL) {
1337         ERROR("open AIDE DB fail\n");
1338         rc = PTS_INTERNAL_ERROR;
1339         goto free;
1340     }
1341
1342     sqlite3_exec(db,
1343         "CREATE TABLE sample (id INTEGER PRIMARY KEY, digest TEXT NOT NULL, "
1344         "name TEXT NOT NULL, state INTEGER NOT NULL)",
1345         NULL, NULL, &err);
1346     // DEBUG("CREATE err=%s\n", err);
1347
1348     /* */
1349     sqlite3_exec(db, "BEGIN", NULL, NULL, &err);
1350     // DEBUG("BEGIN err=%s\n", err);
1351
1352     /* add */
1353     md = ctx->start;
1354     j = 0;
1355     for (i = 0; i < ctx->metadata_num; i++) {
1356         if (md->hash_key != NULL) {
1357             sql = sqlite3_mprintf(
1358                 "INSERT INTO sample (id, digest, name, state)  VALUES (%d, '%s','%s', %d)",
1359                     j, md->hash_key, md->name, 0);
1360             sqlite3_exec(db, sql, NULL, NULL, &err);
1361             // DEBUG("INSERT err=%s\n", err);
1362             j++;
1363         }
1364         md = md->next;
1365     }
1366
1367     /* */
1368     sqlite3_exec(db, "COMMIT", NULL, NULL, &err);
1369     // DEBUG("COMMIT err=%s\n", err);
1370
1371     /* INDEX */
1372     sqlite3_exec(db, "CREATE INDEX digestindex ON sample(digest)", NULL, NULL, &err);
1373     // DEBUG("CREATE INDEX err=%s\n", err);
1374
1375     /* close */
1376     sqlite3_close(db);
1377
1378     /* Good */
1379     rc = PTS_SUCCESS;
1380
1381   free:
1382     freeAideContext(ctx);
1383
1384     return rc;
1385 }
1386
1387 /**
1388  * load (open) SQLite DB file 
1389  */
1390 int loadSQLiteDatabaseFile(AIDE_CONTEXT *ctx, char *filename) {
1391     /* check */
1392     if (ctx == NULL) {
1393         ERROR("ctx == NULL\n");
1394         return PTS_INTERNAL_ERROR;
1395     }
1396     if (filename == NULL) {
1397         ERROR("filename == NULL\n");
1398         return PTS_INTERNAL_ERROR;
1399     }
1400
1401     /* open */
1402     sqlite3_open(filename, &ctx->sqlite_db);
1403     if (ctx->sqlite_db == NULL) {
1404         ERROR("open AIDE SQLite DB %s fail\n", filename);
1405         return PTS_INTERNAL_ERROR;
1406     }
1407
1408     return PTS_SUCCESS;
1409 }
1410
1411 /**
1412  * Veify 
1413  */
1414 int verifyBySQLite(AIDE_CONTEXT *ctx, char * key) {
1415     char *err;
1416     char *sql;
1417     char **result;
1418     int row, col;
1419
1420     /* check */
1421     if (ctx == NULL) {
1422         ERROR("ctx == NULL\n");
1423         return PTS_INTERNAL_ERROR;
1424     }
1425     if (ctx->sqlite_db == NULL) {
1426         ERROR("ctx->sqlite_db == NULL\n");
1427         return PTS_INTERNAL_ERROR;
1428     }
1429
1430     sql = sqlite3_mprintf("SELECT * from sample where digest = '%s'", key);
1431     sqlite3_get_table(ctx->sqlite_db, sql, &result, &row, &col, &err);
1432     // DEBUG("%2d %d %s\n",row,col, md->hash_key);
1433
1434     if (row >= 1) {
1435         return OPENPTS_RESULT_VALID;
1436     }
1437
1438     // ERROR("row = %d\n",row);
1439
1440     /* free */
1441     sqlite3_free(sql);
1442     sqlite3_free(err);
1443     sqlite3_free_table(result);
1444
1445
1446
1447     return OPENPTS_RESULT_UNKNOWN;
1448 }
1449 #endif  // CONFIG_SQLITE