OSDN Git Service

import v0.2.5
[openpts/openpts.git] / src / verifier.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/verifier.c
26  * \brief TCG IF-M Verifier
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-04-06
29  * cleanup 2011-07-20 SM
30  *
31  */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <netdb.h>
37 #include <errno.h>
38
39 #define __USE_GNU
40 #include <search.h>  // hash table
41
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/stat.h>
45 #include <sys/wait.h>
46 #include <netinet/in.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49
50 #include <openpts.h>
51
52 /**
53  * verifier
54  *
55  * @param ctx
56  * @param host
57  * @param port
58  * @param conf_dir - base dir of collector configuration
59  * @param mode   0:normal  1:sync (update policy, ignorelist)
60  *     0  OPENPTS_VERIFY_MODE
61  *     1  OPENPTS_UPDATE_MODE -- note) do not update the RM, use updateRm()
62  *
63  * Returm
64  *   PTS_SUCCESS
65  *   PTS_OS_ERROR
66  *   PTS_INTERNAL_ERROR
67  *   PTS_RULE_NOT_FOUND  RM not found
68  *
69  * Function Test
70  *
71  *   file         test
72  *   ----------------------------------
73  *   check_ifm.c  test_ifm
74  */
75
76
77 /**
78  *   Capability->Lookup->Setup
79  */
80
81 int verifierHandleCapability(
82     OPENPTS_CONTEXT *ctx,
83     char *conf_dir,
84     char *host,
85     OPENPTS_IF_M_Capability *cap) {
86     OPENPTS_UUID *verifier_uuid = NULL;
87     int rc = 0;
88     int i;
89     char * collector_dir = NULL;
90     char * rm_dir = NULL;
91     OPENPTS_CONFIG *target_conf = NULL;
92     OPENPTS_CONFIG *conf = NULL;
93
94     /**/
95     conf = ctx->conf;
96     verifier_uuid = ctx->conf->uuid;
97
98     /* collector UUID */
99     if (ctx->collector_uuid != NULL) freeOpenptsUuid(ctx->collector_uuid);
100     ctx->collector_uuid = newOpenptsUuid2(&cap->platform_uuid);
101     if (ctx->collector_uuid == NULL) {
102         ERROR("Bad collector uuid\n");
103         goto close;
104     }
105
106     /* Manifest UUID */
107     if (ctx->rm_uuid != NULL) freeOpenptsUuid(ctx->rm_uuid);
108     ctx->rm_uuid = newOpenptsUuid2(&cap->manifest_uuid);
109     if (ctx->rm_uuid == NULL) {
110         ERROR("Bad RM uuid\n");
111         goto close;
112     }
113
114     /* check the Collector we already know  */
115     collector_dir = getFullpathName(conf_dir, ctx->collector_uuid->str);
116
117     /* check the Local Collector Config */
118     rc = checkDir(collector_dir);
119     if (rc != PTS_SUCCESS) {
120         /* DIR is missing, unknwon collector */
121         ERROR("verifier() - Unknown collector, UUID= %s dir= %s, rc=%d\n",
122             ctx->collector_uuid->str, collector_dir, rc);
123         addReason(ctx, "Missing collector configuration");
124         addReason(ctx, "Collector hostname = %s", host);
125         addReason(ctx, "Collector UUID = %s", ctx->collector_uuid->str);
126         rc = PTS_NOT_INITIALIZED;
127         goto close;
128     }
129
130
131     /* target_conf */
132     if (ctx->target_conf == NULL) {
133         /* no collector info, create new one for this */
134         ctx->target_conf = newPtsConfig();
135         /* short cut */
136         target_conf = ctx->target_conf;
137
138         // UUID is dir name
139         target_conf->uuid = newOpenptsUuid2(ctx->collector_uuid->uuid);
140         target_conf->config_file = getFullpathName(collector_dir, "target.conf");
141
142         rc = readTargetConf(target_conf, target_conf->config_file);
143         if (rc != PTS_SUCCESS) {
144             ERROR("verifier() - readTargetConf failed, %s\n", target_conf->config_file);
145             addReason(ctx, "Missing collector configuration file");
146             addReason(ctx, "Collector hostname = %s", host);
147             addReason(ctx, "Collector UUID = %s", ctx->collector_uuid->str);
148             rc = PTS_NOT_INITIALIZED;
149             goto close;
150         }
151
152     } else {
153         /* collector info exist, check with */
154         target_conf = ctx->target_conf;
155         if (memcmp(target_conf->uuid->uuid, ctx->collector_uuid->uuid, 16) != 0) {
156             /* Miss, hostname or IP address was changed?  */
157             ERROR("verifier() - Unexpected collector UUID= %s, must be %s\n",
158                 ctx->collector_uuid->str, target_conf->uuid->uuid);
159             addReason(ctx, "Collector configuration was changed");
160             addReason(ctx, "Collector hostname = %s", host);
161             addReason(ctx, "Expected Collector UUID = %s", target_conf->uuid->uuid);
162             addReason(ctx, "Given Collector UUID = %s", ctx->collector_uuid->str);
163             rc = PTS_NOT_INITIALIZED;
164             goto close;
165         } else {
166             /* Hit keep current collector info */
167             DEBUG("verifier() - use existing target conf\n");
168             DEBUG("Good Collector UUID\n");
169         }
170     }
171
172
173     /* Fill versions */
174     memcpy(&target_conf->pts_flag,    &cap->flag, 4);
175     memcpy(&target_conf->tpm_version, &cap->tpm_version, 4);
176     memcpy(&target_conf->tss_version, &cap->tss_version, 4);
177     memcpy(&target_conf->pts_version, &cap->pts_version, 4);
178
179
180     DEBUG("Verifier  UUID         : %s\n", verifier_uuid->str);
181     DEBUG("Collector UUID         : %s\n", ctx->collector_uuid->str);
182     DEBUG("Collector RM UUID      : %s\n", ctx->rm_uuid->str);
183
184     /* Check RM by UUID */
185     DEBUG("RM  UUID               : %s\n", target_conf->rm_uuid->str);
186
187     /* check RM UUID */
188     // if (target_conf->uuid->status == OPENPTS_UUID_CHANGED) {
189     if (memcmp(target_conf->rm_uuid->uuid, ctx->rm_uuid->uuid, 16) != 0) {
190         /* RM changed */
191         DEBUG("RM was changed\n");
192         // RM UUID was changed
193         // 1) NEW RM UUID => Good Reboot
194         // 2) past RM UUID => fallback?
195         // 3) Unknown UUID => PTS_RULE_NOT_FOUND
196
197         /* compare stored NEWRM UUID and given RM UUID */
198         if ((target_conf->newrm_uuid != NULL) &&
199             (target_conf->newrm_uuid->uuid != NULL) &&
200             (memcmp(target_conf->newrm_uuid->uuid, ctx->rm_uuid->uuid, 16) == 0)) {
201             /* HIT - Good Reboot */
202             /* NEWRM -> RM -> OLDRM */
203             DEBUG("RM changed %s -> %s (good reboot)\n",
204                 target_conf->rm_uuid->str, target_conf->newrm_uuid->str);
205
206             printf("Collector's manifest has been changed to new manifest (expected reboot)\n");
207             printf("  current manifest UUID : %s\n", target_conf->newrm_uuid->str);
208             printf("  old manifest UUID     : %s\n", target_conf->rm_uuid->str);
209
210             /* Free Old RM */
211             if (target_conf->oldrm_uuid != NULL) {
212                 if (target_conf->oldrm_uuid->uuid != NULL) free(target_conf->oldrm_uuid->uuid);
213                 if (target_conf->oldrm_uuid->str != NULL)  free(target_conf->oldrm_uuid->str);
214                 if (target_conf->oldrm_uuid->time != NULL) free(target_conf->oldrm_uuid->time);
215             } else {
216                 target_conf->oldrm_uuid = newOpenptsUuid();
217                 // TODO create this before?
218                 target_conf->oldrm_uuid->filename =  getFullpathName(target_conf->config_dir, "oldrm_uuid");
219             }
220
221             /* Copy RM UUID pointers to  Old RM's UUID ptrs */
222             target_conf->oldrm_uuid->uuid   = target_conf->rm_uuid->uuid;
223             target_conf->oldrm_uuid->str    = target_conf->rm_uuid->str;
224             target_conf->oldrm_uuid->time   = target_conf->rm_uuid->time;
225             target_conf->oldrm_uuid->status = OPENPTS_UUID_FILLED;
226
227             /* Save Old RM */
228             rc = writeOpenptsUuidFile(target_conf->oldrm_uuid, 1);
229             if (rc != PTS_SUCCESS) {
230                 ERROR("writeOpenptsUuidFile fail\n");
231             }
232
233             /* Copy NEWRM to RM */
234             target_conf->rm_uuid->uuid   = target_conf->newrm_uuid->uuid;
235             target_conf->rm_uuid->str    = target_conf->newrm_uuid->str;
236             target_conf->rm_uuid->time   = target_conf->newrm_uuid->time;
237             target_conf->rm_uuid->status = OPENPTS_UUID_FILLED;
238
239             /* Save RM */
240             rc = writeOpenptsUuidFile(target_conf->rm_uuid, 1);
241             if (rc != PTS_SUCCESS) {
242                 ERROR("writeOpenptsUuidFile fail\n");
243             }
244
245             /* Delete New RM */
246             target_conf->newrm_uuid->uuid   = NULL;
247             target_conf->newrm_uuid->str    = NULL;
248             target_conf->newrm_uuid->time   =  NULL;
249             target_conf->newrm_uuid->status = OPENPTS_UUID_FILENAME_ONLY;
250             rc = remove(target_conf->newrm_uuid->filename);
251
252             goto rm;
253         } else if ((target_conf->oldrm_uuid != NULL) &&
254             (target_conf->oldrm_uuid->uuid != NULL) &&
255             (memcmp(target_conf->oldrm_uuid->uuid, ctx->rm_uuid->uuid, 16) == 0)) {
256             /* HIT - fallback ? */
257             TODO("Fallback - TBD\n");
258             rc = PTS_RULE_NOT_FOUND;  // TODO
259             goto close;
260         } else {
261             /* Unknown RM */
262             /* MISS no RM for the client(collector)  */
263             PTS_DateTime *t0;
264             PTS_DateTime *t1;
265
266             ERROR("RM changed %s -> %s (not new rm)\n",
267                 target_conf->rm_uuid->str, ctx->rm_uuid->str);
268
269             // TODO DEBUG("RM changed %s -> %s\n", target_conf->rm_uuid->str, rm_uuid->str);
270
271             // TODO update RM
272             addReason(ctx, "Collector uses another Reference Manifest(RM)");
273             addReason(ctx, "Collector hostname = %s", host);
274             addReason(ctx, "Collector UUID = %s", ctx->collector_uuid->str);
275
276             t0 = getDateTimeOfUuid(target_conf->rm_uuid->uuid);
277             t1 = getDateTimeOfUuid(ctx->rm_uuid->uuid);
278
279             addReason(ctx, "Previous RM UUID = %s, timestamp = %04d-%02d-%02d-%02d:%02d:%02d",
280                 target_conf->rm_uuid->str,
281                 t0->year + 1900,
282                 t0->mon + 1,
283                 t0->mday,
284                 t0->hour,
285                 t0->min,
286                 t0->sec);
287
288             addReason(ctx, "Current  RM UUID = %s, timestamp = %04d-%02d-%02d-%02d:%02d:%02d",
289                 ctx->rm_uuid->str,
290                 t1->year + 1900,
291                 t1->mon + 1,
292                 t1->mday,
293                 t1->hour,
294                 t1->min,
295                 t1->sec);
296
297             rc = PTS_RULE_NOT_FOUND;  // TODO
298             goto close;
299         }
300     } else {
301         /* HIT */
302         DEBUG("RM UUID is HIT\n");
303     }
304
305
306   rm:
307     /* check RM */
308     rm_dir = getFullpathName(collector_dir, target_conf->rm_uuid->str);
309     rc = checkDir(rm_dir);
310     if (rc != PTS_SUCCESS) {
311         /* unknwon RM */
312         ERROR("verifier() - Unknown RM, (RM dir = %s)\n", rm_dir);
313         addReason(ctx, "Missing Reference Manifest(RM)");
314         addReason(ctx, "Collector hostname = %s", host);
315         addReason(ctx, "Collector UUID = %s", target_conf->uuid->str);
316         addReason(ctx, "Collector RM UUID = %s", target_conf->rm_uuid->str);
317         addReason(ctx, "Missing RM dir = %s", rm_dir);
318         rc = PTS_RULE_NOT_FOUND;
319         goto close;
320     }
321
322
323     /* Load RMs */
324     rc = getRmSetDir(target_conf);  // ctx->conf);
325
326     DEBUG("logging dir            : %s\n", collector_dir);
327     for (i = 0; i < conf->rm_num; i++) {
328         DEBUG("RM[%d]                  : %s\n", i, target_conf->rm_filename[i]);
329     }
330 #ifdef CONFIG_AIDE
331     DEBUG("AIDE DB                : %s\n", target_conf->aide_database_filename);
332 #ifdef CONFIG_SQLITE
333     DEBUG("AIDE SQLITE DB         : %s\n", target_conf->aide_sqlite_filename);
334 #endif
335     DEBUG("AIDE ignore list       : %s\n", target_conf->aide_ignorelist_filename);
336 #endif
337     DEBUG("IR                     : %s\n", target_conf->ir_filename);
338     DEBUG("Prop                   : %s\n", target_conf->prop_filename);
339     DEBUG("Policy                 : %s\n", target_conf->policy_filename);
340
341     /* check RM */
342     for (i = 0; i< target_conf->rm_num; i++) {
343         struct stat st;
344         if (lstat(target_conf->rm_filename[i], &st) == -1) {
345             ERROR("verifier - RM (%s) is missing. Get RM from target. enroll(init) first\n",
346                 target_conf->rm_filename[i]);
347             rc = PTS_INTERNAL_ERROR;
348             goto close;
349         }
350     }
351
352     return PTS_SUCCESS;
353
354   close:
355
356     return rc;
357 }
358
359
360 /**
361  *  
362  */
363 int verifierHandleRimmSet(
364         OPENPTS_CONTEXT *ctx,
365         BYTE *value) {
366     int rc = PTS_SUCCESS;
367     OPENPTS_CONFIG *target_conf;
368     int i;
369     struct stat st;
370     char buf[BUF_SIZE];
371
372
373     int num;
374     int len;
375
376     /* check */
377     if (ctx == NULL) {
378         ERROR("verifierHandleRimmSet() - ctx is NULL\n");
379         rc = PTS_FATAL;
380         goto error;
381     }
382
383     if (ctx->target_conf == NULL) {
384         ERROR("verifierHandleRimmSet() - target_conf is NULL\n");
385         rc = PTS_FATAL;
386         goto error;
387     }
388     target_conf = ctx->target_conf;
389
390     if (value == NULL) {
391         ERROR("verifierHandleRimmSet() - value is NULL\n");
392         rc = PTS_FATAL;
393         goto error;
394     }
395
396
397     /* num */
398     num = getUint32(value);
399     DEBUG_IFM("RM num                 : %d\n", num);
400
401     target_conf->rm_num = num;
402     value += 4;
403
404
405     /* Check RM DIR */
406     if (lstat(target_conf->rm_basedir, &st) == -1) {
407         /* Missing rm_basedir => create */
408         rc = mkdir(target_conf->rm_basedir, S_IRUSR | S_IWUSR | S_IXUSR);
409         if (rc != 0) {
410             ERROR("create conf directory, %s was failed\n", target_conf->rm_basedir);
411             rc = PTS_INTERNAL_ERROR;
412             goto error;
413         }
414     } else if ((st.st_mode & S_IFMT) != S_IFDIR) {
415         ERROR("RM directory, %s is not a directory %x %x\n", buf, (st.st_mode & S_IFMT), S_IFDIR);
416         rc = PTS_INTERNAL_ERROR;
417         goto close;
418     }
419
420     /* Get RMs  */
421     ctx->conf->rm_num = num;
422     for (i = 0; i < num; i++) {
423         snprintf(buf, BUF_SIZE, "%s/rm%d.xml",
424             target_conf->rm_basedir,
425             i);
426
427         if (target_conf->rm_filename[i] != NULL) {
428             DEBUG("enroll() - free conf->rm_filename[%d] %s\n", i, target_conf->rm_filename[i]);
429             free(target_conf->rm_filename[i]);
430         }
431
432         target_conf->rm_filename[i] = smalloc(buf);
433
434
435         len = getUint32(value);
436         DEBUG("RM[%d] size             : %d\n", i, len);
437         DEBUG("RM[%d] filename         : %s\n", i, target_conf->rm_filename[i]);
438
439         value += 4;
440
441         rc = saveToFile(target_conf->rm_filename[i], len, value);
442         if (rc < 0) {
443             ERROR("enroll - save RM[%d], %s failed\n", i, target_conf->rm_filename[i]);
444             rc = PTS_INTERNAL_ERROR;
445             goto close;
446         }
447
448         value += len;
449     }
450
451     /* Save RM UUID file */
452     target_conf->rm_uuid->filename = getFullpathName(target_conf->config_dir, "./rm_uuid");
453     target_conf->rm_uuid->status = OPENPTS_UUID_FILLED;
454
455     rc = writeOpenptsUuidFile(target_conf->rm_uuid, 1);  // TODO do not overwite?
456     if (rc != PTS_SUCCESS) {
457         ERROR("writeOpenptsUuidFile fail\n");
458     }
459
460   close:
461   error:
462     return rc;
463 }
464
465
466 /**
467  * Write policy.conf from current prop
468  *
469  * return num of polocy
470  *
471  * ignore ima.0.*=*
472  *
473  * TODO move to prop.c
474  */
475 int  writePolicyConf(OPENPTS_CONTEXT *ctx, char *filename) {
476     FILE *fp;
477     OPENPTS_PROPERTY *prop;
478     int i = 0;
479
480     DEBUG("writePolicyConf       : %s\n", filename);
481
482     if ((fp = fopen(filename, "w")) == NULL) {
483         ERROR("writePolicyConf() - File %s open was failed\n", filename);
484         return -1;
485     }
486
487     /* top */
488     prop = ctx->prop_start;
489
490     fprintf(fp, "# OpenPTS validation policy, name=value\n");
491     while (prop != NULL) {
492         if (!strncmp(prop->name, "ima.aggregate", 13)) {
493             /* IMA aggregate validation policy */
494             fprintf(fp, "%s=%s\n", prop->name, prop->value);
495             i++;
496         } else if (!strncmp(prop->name, "ima.", 4)) {
497             /* IMA measurement - SKIP */
498         } else {
499             fprintf(fp, "%s=%s\n", prop->name, prop->value);
500             i++;
501         }
502         prop = prop->next;
503     }
504     fprintf(fp, "# %d reference props\n", i);
505     fclose(fp);
506
507     return i;
508 }
509
510
511 #ifdef CONFIG_AIDE
512 #define HASH_TABLE_SIZE ((size_t) 2048)
513
514 /**
515  * Write writeAideIgnoreList from current prop
516  * IMA measurment with OPENPTS_RESULT_UNKNOWN flag -> 
517  *
518  * Returm
519  *   n  count of list
520  *   -1 ERROR
521  *
522  * ima.0.integrty=unknown
523  * ima.0.name=/init
524  * 
525  * TODO move to prop.c?
526  * TODO use hash table, name:count?
527  */
528 int  writeAideIgnoreList(OPENPTS_CONTEXT *ctx, char *filename) {
529     FILE *fp;
530     OPENPTS_SNAPSHOT * ss;
531     OPENPTS_PCR_EVENT_WRAPPER *ew;
532     TSS_PCR_EVENT *event;
533     char *name;
534     int cnt = 0;
535     /* hash */
536     struct hsearch_data hd;
537     ENTRY e, *ep;
538     void* ecnt = 0;
539     int rc;
540
541     DEBUG("writeAideIgnoreList     : %s\n", filename);
542
543     if ((fp = fopen(filename, "w")) == NULL) {
544         ERROR("File %s open was failed\n", filename);
545         return -1;
546     }
547
548     /* top */
549     ss = getSnapshotFromTable(ctx->ss_table, 10, 1);  // Linux-IMA, TODO define by CONF?
550     if (ss == NULL) {
551         ERROR("Snapshot at PCR[10] level 1 is missing\n");
552     } else {
553         ew = ss->start;
554
555
556         /* look over the  event chain  */
557         fprintf(fp, "# OpenPTS AIDE ignore name list\n");
558
559         /* ew -> hash */
560         memset(&hd, 0, sizeof(hd));
561
562         rc = hcreate_r(HASH_TABLE_SIZE, &hd);
563         if (rc == 0) {
564             if (errno == ENOMEM) {
565                 ERROR("ENOMEM\n");
566                 cnt = -1;
567                 goto error;
568             }
569             ERROR("ERROR rc=%d\n", rc);
570             // return -1;
571             cnt = -1;
572             goto error;
573         }
574
575         while (ew != NULL) {
576             if (ew->status == OPENPTS_RESULT_UNKNOWN) {
577                 event = ew->event;
578                 name = (char *)event->rgbEvent;
579                 name += SHA1_DIGEST_SIZE;
580                 /* add '\n' */
581                 name = snmalloc(name, (event->ulEventLength - SHA1_DIGEST_SIZE));
582
583                 ecnt = 0;
584
585                 e.key = name;
586                 e.data = NULL;
587
588                 rc = hsearch_r(e, FIND, &ep, &hd);
589                 if (rc == 0) {
590                     /* miss */
591                     e.data = (void*) ecnt;
592                     rc = hsearch_r(e, ENTER, &ep, &hd);
593                     // TODO check error
594                     fprintf(fp, "# %d \n", cnt);
595                     fprintf(fp, "%s\n", name);
596                     cnt++;
597                 } else {
598                     /* hit, ++ */
599                     ecnt = ep->data;
600                     ecnt++;
601                     ep->data = ecnt;
602                 }
603             }
604             ew = ew->next_pcr;
605         }
606         hdestroy_r(&hd);
607     }  // SS
608
609     /* close  */
610     fprintf(fp, "# %d props\n", cnt);
611
612   error:
613     fclose(fp);
614
615     return cnt;
616 }
617 #endif  // CONFIG_AIDE
618
619
620 /**
621  *  
622  */
623 int verifierHandleIR(
624         OPENPTS_CONTEXT *ctx,
625         int length,
626         BYTE *value,
627         int mode,
628         int *result) {
629     int rc = PTS_SUCCESS;
630     OPENPTS_CONFIG *target_conf;
631     int i;
632
633     /* check */
634     if (ctx == NULL) {
635         ERROR("verifierHandleRimmSet() - ctx is NULL\n");
636         rc = PTS_FATAL;
637         goto error;
638     }
639
640     if (ctx->target_conf == NULL) {
641         ERROR("verifierHandleRimmSet() - target_conf is NULL\n");
642         rc = PTS_FATAL;
643         goto error;
644     }
645     target_conf = ctx->target_conf;
646
647     if (value == NULL) {
648         ERROR("verifierHandleRimmSet() - value is NULL\n");
649         rc = PTS_FATAL;
650         goto error;
651     }
652
653
654     /* save IR to file */
655     if (length > 0) {
656         rc = saveToFile(target_conf->ir_filename, length, value);
657         if (rc < 0) {
658             ERROR("verifier - save IR failed\n");
659             rc = PTS_INTERNAL_ERROR;
660             goto close;
661         }
662     } else {
663         ERROR("verifier - collector can not send IR\n");
664         rc = PTS_INTERNAL_ERROR;
665         goto close;
666     }
667
668     /* load Reference Manifest (BIN-BHV) */
669     DEBUG("Load RM  -------------------------------- \n");
670
671     for (i = 0; i <  target_conf->rm_num; i++) {
672         rc = readRmFile(ctx, target_conf->rm_filename[i], i);
673         if (rc < 0) {
674             ERROR("readRmFile fail\n");
675             rc = PTS_INTERNAL_ERROR;
676             goto close;
677         }
678     }
679
680     if (mode == 0) {
681         /* Load Policy to validate properties */
682         DEBUG("Load Policy  -------------------------------- \n");
683         rc = loadPolicyFile(ctx, target_conf->policy_filename);
684         if (rc < 0) {
685             ERROR("loadPolicyFile fail\n");
686             rc = PTS_INTERNAL_ERROR;
687             goto close;
688         }
689     } else {
690         /* remove */
691         // ctx->conf->aide_ignorelist_filename = NULL;
692     }
693
694     /* Validate IR by FSM */
695     *result = validateIr(ctx, target_conf->ir_filename);  /* ir.c */
696
697
698     if (mode == OPENPTS_VERIFY_MODE) {
699         /* save properties */
700         DEBUG("save property          : %s\n", target_conf->prop_filename);
701
702         rc = saveProperties(ctx, target_conf->prop_filename);
703         if (rc != PTS_SUCCESS) {
704             ERROR("saveProperties was failed %s\n", target_conf->prop_filename);
705             goto close;
706         }
707     } else if (mode == OPENPTS_UPDATE_MODE) {
708         /* gen policy and ignore list */
709         DEBUG("update policy and ignore list %s\n", target_conf->policy_filename);
710         rc = writePolicyConf(ctx, target_conf->policy_filename);
711         DEBUG("policy num            : %d policies\n", rc);
712 #ifdef CONFIG_AIDE
713         if (ctx->ima_unknown > 0) {
714             rc = writeAideIgnoreList(ctx, target_conf->aide_ignorelist_filename);
715             DEBUG("%d ignore list of AIDE\n", rc);
716         }
717 #endif
718     } else {
719         ERROR("unknown mode %d\n", mode);
720         goto close;
721     }
722     rc = PTS_SUCCESS;
723
724    close:
725    error:
726
727     return rc;
728 }
729
730 /**
731  * enroll
732  *
733  * get target UUID
734  * get target RMs
735  * else?
736  *
737  * Function Test
738  *
739  *   file         test
740  *   ----------------------------------
741  *   
742  */
743 int enroll(
744     OPENPTS_CONTEXT *ctx,
745     char *host,
746     char *ssh_username,
747     char *ssh_port,
748     char *conf_dir,
749     int force) {
750     int sock;
751     int rc = PTS_SUCCESS;
752     int len;
753     PTS_IF_M_Attribute *read_tlv = NULL;
754     pid_t ssh_pid = -1;
755     int ssh_status;
756     OPENPTS_UUID *verifier_uuid = NULL;
757     OPENPTS_CONFIG *target_conf;
758     OPENPTS_IF_M_Capability *cap;
759
760     /* check */
761     // TODO
762
763     DEBUG("enroll() - start, force = %d  (1:overwite) --------------------------------------\n", force);
764
765     if (ctx->conf == NULL) {
766         ERROR("ctx->conf\n");
767         return PTS_INTERNAL_ERROR;
768     }
769
770     /* new target_conf */
771     if (ctx->target_conf != NULL) {
772         ERROR("enroll() - target_conf of %s already exist?\n", host);
773         goto out;
774     }
775
776     ctx->target_conf = newPtsConfig();
777     target_conf = ctx->target_conf;
778     target_conf->hostname = smalloc(host);
779
780     /* verifier (my) UUID */
781     verifier_uuid = ctx->conf->uuid;
782
783     /* connect to the target collector */
784     ssh_pid = ssh_connect(host,
785                           ssh_username,
786                           ssh_port,
787                           NULL,
788                           &sock);
789
790     if (ssh_pid == -1) {
791         ERROR("connection to %s failed.\n", host);
792         rc = PTS_OS_ERROR;
793         goto out;
794     }
795
796     /* V->C capability (hello) */
797     len = writePtsTlv(ctx, sock, OPENPTS_CAPABILITIES);
798     if (len < 0) {
799         ERROR("send OPENPTS_CAPABILITIES was failed\n");
800         rc = PTS_INTERNAL_ERROR;
801         goto close;
802     }
803
804     /* C->V capability (hello) */
805     read_tlv = readPtsTlv(sock);
806     if (read_tlv == NULL) {
807         ERROR("Can not get the message from collector\n");
808         rc = PTS_INTERNAL_ERROR;
809         goto close;
810     }
811     if (read_tlv->type != OPENPTS_CAPABILITIES) {
812         ERROR("\n");
813         rc = PTS_INTERNAL_ERROR;
814         goto close;
815     }
816     if (read_tlv->length != sizeof(OPENPTS_IF_M_Capability)) {  // TODO set name
817         ERROR("UUID length = %d != 36\n", read_tlv->length);
818         rc = PTS_INTERNAL_ERROR;
819         goto close;
820     }
821     cap =  (OPENPTS_IF_M_Capability *)read_tlv->value;
822
823     /* Fill versions */
824     memcpy(&target_conf->pts_flag,    &cap->flag, 4);
825     memcpy(&target_conf->tpm_version, &cap->tpm_version, 4);
826     memcpy(&target_conf->tss_version, &cap->tss_version, 4);
827     memcpy(&target_conf->pts_version, &cap->pts_version, 4);
828
829     /* collector UUID */
830     target_conf->uuid = newOpenptsUuid2(&cap->platform_uuid);
831     if (target_conf->uuid == NULL) {
832         ERROR("Bad collector uuid\n");
833         goto close;
834     }
835
836     /* Manifest UUID */
837     target_conf->rm_uuid = newOpenptsUuid2(&cap->manifest_uuid);
838     if (target_conf->rm_uuid == NULL) {
839         ERROR("Bad collector uuid\n");
840         goto close;
841     }
842
843     /* verifier */
844     DEBUG("Verifier  UUID         : %s\n", verifier_uuid->str);
845     DEBUG("Collector UUID         : %s\n", target_conf->uuid->str);
846     DEBUG("RM UUID                : %s\n", target_conf->rm_uuid->str);
847
848     target_conf->config_dir =
849         getFullpathName(conf_dir, target_conf->uuid->str);
850     target_conf->config_file =
851         getFullpathName(target_conf->config_dir, "target.conf");
852     target_conf->uuid->filename =
853         getFullpathName(target_conf->config_dir, "uuid");
854     target_conf->rm_basedir =
855         getFullpathName(target_conf->config_dir, target_conf->rm_uuid->str);
856
857 #ifdef CONFIG_AIDE
858     target_conf->aide_database_filename =
859         getFullpathName(target_conf->config_dir, "aide.db.gz");
860     target_conf->aide_ignorelist_filename =
861         getFullpathName(target_conf->config_dir, "aide.ignore");
862 #ifdef CONFIG_SQLITE
863     target_conf->aide_sqlite_filename =
864         getFullpathName(target_conf->config_dir, "aide.sqlite.db");
865 #endif
866 #endif
867
868
869     /* create */
870     rc = makeDir(target_conf->config_dir);
871     // TODO check rc
872
873     DEBUG("conf dir               : %s\n", target_conf->config_dir);
874     DEBUG("rm dir                 : %s\n", target_conf->rm_basedir);
875     DEBUG("AIDE DB                : %s\n", target_conf->aide_database_filename);
876 #ifdef CONFIG_SQLITE
877     DEBUG("AIDE SQLite DB         : %s\n", target_conf->aide_sqlite_filename);
878 #endif
879
880     if (force == 1) {
881         /* delete existing info */
882         // DEBUG("enroll - force=1 NA. Sorry\n");
883     } else {
884         /* check existing info */
885         struct stat st;
886         if (lstat(target_conf->config_file , &st) == -1) {
887             // Missing,
888             DEBUG("%s is missing. Get RM from target\n", target_conf->config_file);
889         } else {
890             // EXIST -> Update
891             fprintf(stderr, "%s exist. if you want to override, use -f option\n", target_conf->config_file);
892             rc = PTS_INTERNAL_ERROR;
893             goto close;
894         }
895     }
896
897
898     /* free */
899     // TODO free
900     // read_tlv->value -= 16; // TODO
901     freePtsTlv(read_tlv);
902
903     /* get the Reference Manifest from target(collector) */
904
905
906     /* V->C template RIMM req  */
907     len = writePtsTlv(ctx, sock, REQUEST_RIMM_SET);
908     if (len < 0) {
909         ERROR("template RIMM req was failed\n");
910         rc = PTS_INTERNAL_ERROR;
911         goto close;
912     }
913
914     /* C->V template RIMM (RIMM embedded to CTX) */
915     read_tlv = readPtsTlv(sock);
916     if (read_tlv->type == OPENPTS_ERROR) {
917         ERROR("Request RIMM_SET was failed. collector returns error message");
918         rc = PTS_INTERNAL_ERROR;
919         goto close;
920     } else if (read_tlv->type != RIMM_SET) {
921         ERROR("Bad return message, %X != %X", read_tlv->type, RIMM_SET);
922         rc = PTS_INTERNAL_ERROR;
923         goto close;
924     }
925
926     rc = verifierHandleRimmSet(ctx, (BYTE*) read_tlv->value);
927     if (rc != PTS_SUCCESS) {
928         ERROR("Bad RIMM_SET?");
929         rc = PTS_INTERNAL_ERROR;
930         goto close;
931     }
932
933     /* free */
934     freePtsTlv(read_tlv);
935     read_tlv = NULL;
936
937 #ifdef CONFIG_AIDE
938     // TODO(munetoh) capability defile validation mode of collector
939     /* V->C AIDE_DATABASE req  */
940     len = writePtsTlv(ctx, sock, REQUEST_AIDE_DATABASE);
941
942     if (len < 0) {
943         ERROR("template RIMM req was failed\n");
944         rc = PTS_INTERNAL_ERROR;
945         goto close;
946     }
947
948     /* C->V AIDE DATABASE */
949     read_tlv = readPtsTlv(sock);
950     if (read_tlv->type != AIDE_DATABASE) {
951         if (read_tlv->type == OPENPTS_ERROR) {
952             // TODO check msg?
953             /* AIDE DB is missing */
954             target_conf->ima_validation_mode = OPENPTS_VALIDATION_MODE_NONE;
955             DEBUG("enroll - AIDE DB is missing. do not validate IMA's IMLs\n");
956         } else {
957             ERROR("");
958             rc = PTS_INTERNAL_ERROR;
959             goto close;
960         }
961     } else {
962         // Got AIDE DB?
963         if (read_tlv->length > 0) {
964             /* AIDE_DATABASE -> CTX */
965             DEBUG("AIDE_DATABASE size     : %d\n", read_tlv->length);
966
967             rc = saveToFile(target_conf->aide_database_filename, read_tlv->length, read_tlv->value);
968             if (rc < 0) {
969                 ERROR("enroll - save AIDE DB failed\n");
970                 rc = PTS_INTERNAL_ERROR;
971                 goto close;
972             }
973
974 #ifdef CONFIG_SQLITE
975             DEBUG("conv to sqlite %s\n", target_conf->aide_sqlite_filename);
976             rc = convertAideDbfileToSQLiteDbFile(
977                     ctx->conf->aide_database_filename,
978                     ctx->conf->aide_sqlite_filename);
979             if (rc != PTS_SUCCESS) {
980                 ERROR("enroll - convert AIDE DB to SQLiteDB was failed\n");
981                 rc = PTS_INTERNAL_ERROR;
982                 goto close;
983             }
984 #endif
985             target_conf->ima_validation_mode = OPENPTS_VALIDATION_MODE_AIDE;
986         } else {
987             /* no AIDE DB */
988             target_conf->ima_validation_mode = OPENPTS_VALIDATION_MODE_NONE;
989             DEBUG("enroll - AIDE DB is missing. do not validate IMA's IMLs\n");
990         }
991     }
992
993     /* free */
994     freePtsTlv(read_tlv);
995     read_tlv = NULL;
996
997 #endif  // CONFIG_AIDE
998
999
1000
1001     /* V->C TPM PUBKEY req */
1002     len = writePtsTlv(ctx, sock, REQUEST_TPM_PUBKEY);  // ifm.c
1003
1004     if (len < 0) {
1005         ERROR("enroll() - REQUEST_TPM_PUBKEY was failed, len=%d\n", rc);
1006         rc = PTS_INTERNAL_ERROR;
1007         goto close;
1008     }
1009
1010     /* C->V TPM PUBKEY */
1011     read_tlv = readPtsTlv(sock);
1012     if (read_tlv->type == OPENPTS_ERROR) {
1013         // TODO Ignore now
1014         TODO("Target did not have TPM_PUBKEY");
1015         addReason(ctx, "Target did not have TPM_PUBKEY\n");
1016         rc = PTS_INTERNAL_ERROR;
1017         goto close;
1018     } else if (read_tlv->type != TPM_PUBKEY) {
1019         ERROR("read_tlv->type != TPM_PUBKEY, but %d", read_tlv->type);
1020         rc = PTS_INTERNAL_ERROR;
1021         goto close;
1022     }
1023
1024     if (read_tlv->length > 0) {
1025         /* TPM_PUBKEY -> CTX */
1026         DEBUG("TPM_PUBKEY size        : %d\n", read_tlv->length);
1027
1028         // TODO used by two
1029         if (target_conf->pubkey != NULL) {
1030             DEBUG("enroll() - reset the PUBKEY\n");
1031             free(target_conf->pubkey);
1032         }
1033
1034         target_conf->pubkey_length = read_tlv->length;
1035         target_conf->pubkey = malloc(target_conf->pubkey_length);
1036         // TODO check NULL
1037         memcpy(
1038             target_conf->pubkey,
1039             read_tlv->value,
1040             target_conf->pubkey_length);
1041         /* save to the target.conf */
1042     } else {
1043         DEBUG("enroll - TPM_PUBKEY is missing.\n");
1044     }
1045
1046     /* save target conf */
1047     writeTargetConf(target_conf, target_conf->uuid->uuid, target_conf->config_file);  // ctx.c
1048
1049     /* OK */
1050     rc = PTS_SUCCESS;
1051
1052   close:
1053     close(sock);
1054     waitpid(ssh_pid, &ssh_status, 0);
1055
1056   out:
1057     /* free */
1058
1059     if (read_tlv != NULL) freePtsTlv(read_tlv);
1060
1061     freePtsConfig(ctx->target_conf);
1062     ctx->target_conf = NULL;
1063
1064     DEBUG("enroll() - done, force = %d  (1:overwite) --------------------------------------\n", force);
1065
1066     return rc;
1067 }
1068
1069
1070 /**
1071  *  Standalone IF-M verifier 
1072  */
1073 int verifier(
1074     OPENPTS_CONTEXT *ctx,
1075     char *host,
1076     char *ssh_username,
1077     char *ssh_port,
1078     char *conf_dir,
1079     int mode) {
1080     int rc = PTS_SUCCESS;
1081     int len;
1082     int result = OPENPTS_RESULT_VALID;
1083     /* sock */
1084     int sock;
1085     pid_t ssh_pid;
1086     int ssh_status;
1087     /* TLV/PTS */
1088     PTS_IF_M_Attribute *read_tlv = NULL;
1089     OPENPTS_CONFIG *conf;
1090     char * collector_dir = NULL;
1091     char * rm_dir = NULL;
1092     OPENPTS_IF_M_Capability *cap;
1093
1094     DEBUG("verifier() - start\n");
1095     DEBUG("  conf_dir             : %s\n", conf_dir);
1096     DEBUG("  mode                 : %d  (0:just verify, 1:update the policy)\n", mode);
1097     /* check */
1098     if (ctx == NULL) {
1099         ERROR("ctx is null\n");
1100         return PTS_INTERNAL_ERROR;
1101     }
1102     conf = ctx->conf;
1103     if (conf == NULL) {
1104         ERROR("conf is null\n");
1105         return PTS_INTERNAL_ERROR;
1106     }
1107
1108     /* connect to the target collector */
1109     ssh_pid = ssh_connect(host,
1110                           ssh_username,
1111                           ssh_port,
1112                           NULL,
1113                           &sock);
1114
1115     if (ssh_pid == -1) {
1116         ERROR("connection failed (server = %s)\n", host);
1117         addReason(ctx, "connection failed (server = %s)\n", host);
1118         rc = PTS_OS_ERROR;
1119         goto out;
1120     }
1121
1122     /* IF-M start */
1123
1124     /* V->C capability (hello) */
1125     len = writePtsTlv(ctx, sock, OPENPTS_CAPABILITIES);
1126     if (len < 0) {
1127         ERROR("Send OPENPTS_CAPABILITIES was failed\n");
1128         goto close;
1129     }
1130
1131     /* C->V capability (hello) */
1132     read_tlv = readPtsTlv(sock);
1133     if (read_tlv == NULL) {
1134         ERROR("can't connect to target, %s\n", host);
1135         rc = PTS_INTERNAL_ERROR;
1136         goto close;
1137     } else if (read_tlv->type != OPENPTS_CAPABILITIES) {
1138         goto close;
1139     } else if (read_tlv->length != sizeof(OPENPTS_IF_M_Capability)) {
1140         // TODO PTS_CAPABILITIES_SIZE
1141         ERROR("UUID length = %d != 36\n", read_tlv->length);
1142         rc = PTS_INTERNAL_ERROR;
1143         goto close;
1144     }
1145     cap = (OPENPTS_IF_M_Capability *)read_tlv->value;
1146
1147     rc = verifierHandleCapability(ctx, conf_dir, host, cap);
1148     if (rc != PTS_SUCCESS) goto close;
1149
1150     /* V->C  D-H nonce param req ---------------------------------- */
1151     /*   setup req  */
1152     ctx->nonce->req->reserved = 0;
1153     ctx->nonce->req->min_nonce_len = 16;
1154     ctx->nonce->req->dh_group_set = DH_GROUP_2;
1155
1156     /*   send req   */
1157     len = writePtsTlv(ctx, sock, DH_NONCE_PARAMETERS_REQUEST);
1158     if (len < 0) {
1159         ERROR("Send DH_NONCE_PARAMETERS_REQUEST was failed\n");
1160         goto close;
1161     }
1162
1163     /* C->V  D-H nonce param res ---------------------------------- */
1164     freePtsTlv(read_tlv);
1165
1166     read_tlv = readPtsTlv(sock);
1167     if (read_tlv == NULL) {
1168         ERROR("[IF-M] DH_NONCE_PARAMETERS_REQUEST was failed, check the collector");
1169         rc = PTS_INTERNAL_ERROR;
1170         goto close;
1171     } else if (read_tlv->type != DH_NONCE_PARAMETORS_RESPONSE) {
1172         goto close;
1173     }
1174     // DEBUG("new read_tlv %p\n",read_tlv);
1175
1176     /* res -> fin */
1177     ctx->nonce->res->reserved[0]         = read_tlv->value[0];
1178     ctx->nonce->res->reserved[1]         = read_tlv->value[1];
1179     ctx->nonce->res->reserved[2]         = read_tlv->value[2];
1180     ctx->nonce->res->nonce_length        = read_tlv->value[3];
1181     ctx->nonce->res->selected_dh_group   = (read_tlv->value[4]<<8) | read_tlv->value[5];
1182     ctx->nonce->res->hash_alg_set        = (read_tlv->value[6]<<8) | read_tlv->value[7];
1183
1184     /* set pubkey length */
1185     setDhPubkeylength(ctx->nonce);
1186
1187     /* nonce */
1188     ctx->nonce->res->dh_respondor_nonce = malloc(ctx->nonce->res->nonce_length);
1189     memcpy(
1190         ctx->nonce->res->dh_respondor_nonce,
1191         &read_tlv->value[8],
1192         ctx->nonce->res->nonce_length);
1193
1194     /* pubkey */
1195     ctx->nonce->res->dh_respondor_public = malloc(ctx->nonce->pubkey_length);
1196     memcpy(
1197         ctx->nonce->res->dh_respondor_public,
1198         &read_tlv->value[8 + ctx->nonce->res->nonce_length],
1199         ctx->nonce->pubkey_length);
1200     ctx->nonce->pubkey = ctx->nonce->res->dh_respondor_public;  // link
1201
1202     rc = calcDh(ctx->nonce);
1203     if (rc != 0) {
1204         ERROR("calcDh failed\n");
1205         goto close;
1206     }
1207
1208     /* V->C D-H nonce finish  --------------------------------------------- */
1209     len = writePtsTlv(ctx, sock, DH_NONCE_FINISH);
1210     if (len < 0) {
1211         ERROR("Send DH_NONCE_FINISH was failed\n");
1212         goto close;
1213     }
1214
1215
1216     /* V->C IR req -------------------------------------------------------- */
1217     len = writePtsTlv(ctx, sock, REQUEST_INTEGRITY_REPORT);
1218     if (len < 0) {
1219         ERROR("Send REQUEST_INTEGRITY_REPORT was failed\n");
1220         goto close;
1221     }
1222
1223     /* C->V IR ------------------------------------------------------------ */
1224     freePtsTlv(read_tlv);
1225     read_tlv = readPtsTlv(sock);
1226     if (read_tlv == NULL) {
1227         ERROR("REQUEST_INTEGRITY_REPORT was failed, check the collector");
1228         rc = PTS_INTERNAL_ERROR;
1229         goto close;
1230     } else if (read_tlv->type != INTEGRITY_REPORT) {
1231         rc = PTS_INTERNAL_ERROR;
1232         goto close;
1233     }
1234
1235     rc = verifierHandleIR(ctx, read_tlv->length, read_tlv->value, mode, &result);
1236
1237     /* V->C VR */
1238     len = writePtsTlv(ctx, sock, VERIFICATION_RESULT);
1239     if (len < 0) {
1240         rc = PTS_INTERNAL_ERROR;
1241         goto close;
1242     }
1243
1244     /* return validateIr() result  */
1245     // TODO
1246     // OPENPTS_RESULT_INVALID
1247     if (result == OPENPTS_RESULT_VALID) {
1248         DEBUG("verifier() result      : VALID");
1249         rc = PTS_SUCCESS;        // 0 -> 0
1250     } else if (result == OPENPTS_RESULT_UNVERIFIED) {
1251         DEBUG("verifier() result      : UNVERIFIED");
1252         rc = PTS_VERIFY_FAILED;  // 101 -> 34
1253     } else if (result == OPENPTS_RESULT_INVALID) {
1254         DEBUG("verifier() result      : INVALID");
1255         rc = PTS_VERIFY_FAILED;  // 102 -> 34
1256     } else if (result == OPENPTS_RESULT_UNKNOWN) {
1257         DEBUG("verifier() result      : UNKNOWN");
1258         rc = PTS_VERIFY_FAILED;  // 104 -> 34
1259     } else if (result == OPENPTS_RESULT_IGNORE) {
1260         DEBUG("verifier() result      : IGNORE");
1261         rc = PTS_VERIFY_FAILED;  // 103 -> 34
1262     } else {
1263         DEBUG("verifier() result      : ERROR");
1264         rc = PTS_INTERNAL_ERROR;
1265     }
1266
1267   close:
1268     /* close socket */
1269     close(sock);
1270     waitpid(ssh_pid, &ssh_status, 0);
1271
1272   out:
1273     /* free */
1274     if (read_tlv != NULL) freePtsTlv(read_tlv);
1275     if (collector_dir != NULL) free(collector_dir);
1276     if (rm_dir != NULL) free(rm_dir);
1277     if ((rc == PTS_VERIFY_FAILED) && (mode == 1)) {
1278         DEBUG("verifier() - update the policy");
1279         rc = PTS_SUCCESS;
1280     }
1281
1282     DEBUG("verifier() - done (rc = %d)\n", rc);
1283
1284     return rc;
1285 }
1286
1287