OSDN Git Service

Re-organize console out and logging out
[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 #include <limits.h>
50
51 #include <openpts.h>
52
53
54 /**
55  * Lock (POSIX 1003.1)
56  * type:
57  *   F_RDLCK   shared     VERIFY DISPLAY
58  *   F_WRLCK   exclusive  ENROLL REMOVE UPDATE
59  * exit 1 if locked
60  */
61 void global_lock(int type) {
62     int fd;
63     struct flock fl;
64     char *home, path[PATH_MAX];
65
66
67     /* prepare the lock file before access the conf */
68     // TODO HOME/.openpts/rwlock is hardcoded here
69     home = getenv("HOME");
70     if (home == NULL) {
71         LOG(LOG_ERR, "HOME environment variable not defined\n");
72         exit(1);
73     }
74
75     snprintf(path, PATH_MAX, "%s/.openpts", home);
76     if (mkdir(path, 0700) < 0 && errno != EEXIST) {
77         LOG(LOG_ERR, "Can't create dir, %s", path);
78         exit(1);
79     }
80
81     snprintf(path, PATH_MAX, "%s/.openpts/rwlock", home);
82     fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
83     if (fd < 0) {
84         LOG(LOG_ERR, "Can't open lock file, %s", path);
85         exit(1);
86     }
87
88     fl.l_start = 0;
89     fl.l_len = 0;
90     fl.l_whence = SEEK_SET;
91     fl.l_type = type;
92     fl.l_pid = getpid();
93     //if (fcntl(fd, F_SETLKW, &fl) < 0) {
94     if (fcntl(fd, F_SETLK, &fl) < 0) {
95         // get PID of the process holding that lock
96         fcntl(fd, F_GETLK, &fl);
97         ERROR(  // TODO NLS
98             "Openpts configulation is locked by other(pid=%d)\n", fl.l_pid);
99         exit(1);
100     }
101 }
102
103
104 /**
105  * get Default Config File
106  */
107 int getDefaultConfigfile(OPENPTS_CONFIG *conf) {
108     int rc = PTS_SUCCESS;
109     /* use system default config file */
110     int createBasicConfig = 0;
111     int configDirExists = 0;
112
113     char dirpath[PATH_MAX];
114     char conf_file[PATH_MAX];
115     char uuid_file[PATH_MAX];
116     char *homeDir = getenv("HOME");
117
118     /* check */
119     if (conf == NULL) {
120         LOG(LOG_ERR, "null input");
121         return PTS_FATAL;
122     }
123
124     snprintf(dirpath, PATH_MAX, "%s/.openpts", homeDir);
125     snprintf(conf_file, PATH_MAX, "%s/.openpts/openpts.conf", homeDir);
126     snprintf(uuid_file, PATH_MAX, "%s/.openpts/uuid", homeDir);
127
128     /* check dir */
129     if (checkDir(dirpath) == PTS_SUCCESS) {
130         struct stat statBuf;
131         if (-1 == stat(conf_file, &statBuf) && ENOENT == errno) {
132             LOG(LOG_ERR, "Found openpts dir '%s', but no config file - will create one.", dirpath);
133             createBasicConfig = 1;
134         }
135         configDirExists = 1;
136     } else {
137         // create and initialize the $HOME/.openpts directory
138         rc = mkdir(dirpath, S_IRUSR | S_IWUSR | S_IXUSR);
139         if (rc != 0) {
140             LOG(LOG_ERR, "mkdir on %s failed (errno=%d)", dirpath, errno);
141             rc=PTS_FATAL;
142             goto error;
143         }
144         configDirExists = 1;
145         createBasicConfig = 1;
146     }
147
148     /* make config if missing */
149     if (createBasicConfig) {
150         /* new UUID */
151         conf->uuid = newOpenptsUuid();
152         conf->uuid->filename = smalloc_assert(uuid_file);
153         conf->uuid->status = OPENPTS_UUID_FILENAME_ONLY;
154
155         genOpenptsUuid(conf->uuid);
156         rc = writeOpenptsUuidFile(conf->uuid, 1);
157         if (rc != PTS_SUCCESS) {
158             LOG(LOG_ERR, "Can't create UUID file, %s", uuid_file);
159             rc=PTS_FATAL;
160             goto error;
161         }
162
163         /* write Conf */
164         rc = writeOpenptsConf(conf, conf_file);
165         if (rc != PTS_SUCCESS) {
166             LOG(LOG_ERR, "Can't create config file, %s", conf_file);
167             rc=PTS_FATAL;
168             goto error;
169         }
170     }
171
172     /* check conf  */
173     DEBUG("read conf file          : %s\n", conf_file);
174     rc = readOpenptsConf(conf, conf_file);
175     if (rc != PTS_SUCCESS) {
176         LOG(LOG_ERR, "readOpenptsConf() failed\n");
177     }
178
179     return rc;
180
181   error:
182     if (configDirExists == 1) {
183         /* rollback delete conf dir? */
184         // TODO
185         LOG(LOG_ERR, "Can't configure the openpts(verifier). "
186               "remove the wasted dir, e.g. rm -rf %s)", dirpath);
187     }
188
189     return rc;
190 }
191
192
193 /**
194  * verifier
195  *
196  * @param ctx
197  * @param host
198  * @param port
199  * @param conf_dir - base dir of collector configuration
200  * @param mode   0:normal  1:sync (update policy, ignorelist)
201  *     0  OPENPTS_VERIFY_MODE
202  *     1  OPENPTS_UPDATE_MODE -- note) do not update the RM, use updateRm()
203  *
204  * Returm
205  *   PTS_SUCCESS
206  *   PTS_OS_ERROR
207  *   PTS_INTERNAL_ERROR
208  *   PTS_RULE_NOT_FOUND  RM not found
209  *
210  * Function Test
211  *
212  *   file         test
213  *   ----------------------------------
214  *   check_ifm.c  test_ifm
215  */
216
217
218 /**
219  *   Capability->Lookup->Setup
220  */
221
222 int verifierHandleCapability(
223     OPENPTS_CONTEXT *ctx,
224     char *conf_dir,
225     char *host,
226     OPENPTS_IF_M_Capability *cap,
227     int *notifiedOfPendingRm,
228     int *currentRmOutOfDate) {
229     OPENPTS_UUID *verifier_uuid = NULL;
230     int rc = PTS_INTERNAL_ERROR; /* guilty until proven innocent */
231     int i;
232     OPENPTS_CONFIG *target_conf = NULL;
233     OPENPTS_CONFIG *conf = NULL;
234     // local buffer
235     char * collector_dir = NULL;
236     char * rm_dir = NULL;
237
238      *currentRmOutOfDate = 0;
239      *notifiedOfPendingRm = 0;
240
241     /* check */
242     if (ctx == NULL) {
243         LOG(LOG_ERR, "null input");
244         return PTS_FATAL;
245     }
246     conf = ctx->conf;
247     if (conf == NULL) {
248         LOG(LOG_ERR, "null input");
249         return PTS_FATAL;
250     }
251     verifier_uuid = conf->uuid;
252     if (verifier_uuid == NULL) {
253         LOG(LOG_ERR, "null input");
254         return PTS_FATAL;
255     }
256
257     /* collector UUID */
258     if (ctx->collector_uuid != NULL) {
259         freeOpenptsUuid(ctx->collector_uuid);
260     }
261     ctx->collector_uuid = newOpenptsUuid2(&cap->platform_uuid);
262     if (ctx->collector_uuid == NULL) {
263         // LOG(LOG_ERR, "Bad collector uuid\n");
264         rc = PTS_INTERNAL_ERROR;
265         goto close;
266     }
267
268     /* Manifest UUID */
269     if (ctx->rm_uuid != NULL) {
270         freeOpenptsUuid(ctx->rm_uuid);
271     }
272     ctx->rm_uuid = newOpenptsUuid2(&cap->manifest_uuid);
273     if (ctx->rm_uuid == NULL) {
274         // LOG(LOG_ERR, "Bad RM uuid\n");
275         rc = PTS_INTERNAL_ERROR;
276         goto close;
277     }
278
279     /* check the Collector we already know  */
280     collector_dir = getFullpathName(conf_dir, ctx->collector_uuid->str);
281
282     /* check the Local Collector Config */
283     rc = checkDir(collector_dir);
284     if (rc != PTS_SUCCESS) {
285         /* DIR is missing, unknwon collector */
286         LOG(LOG_ERR, "verifier() - Unknown collector, UUID= %s dir= %s, rc=%d\n",
287             ctx->collector_uuid->str, collector_dir, rc);
288         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_MISSING_CONFIG_2,
289             "Missing collector configuration"));
290         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_HOSTNAME,
291             "Collector hostname = %s"), host);
292         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_UUID,
293             "Collector UUID = %s"), ctx->collector_uuid->str);
294         rc = PTS_NOT_INITIALIZED;
295         goto close;
296     }
297
298
299     /* target_conf */
300     if (ctx->target_conf == NULL) {
301         /* no collector info, create new one for this */
302         ctx->target_conf = newPtsConfig();
303         if ( NULL == ctx->target_conf ) {
304             rc = PTS_INTERNAL_ERROR;
305             goto close;
306         }
307         /* short cut */
308         target_conf = ctx->target_conf;
309
310         // UUID is dir name
311         target_conf->uuid = newOpenptsUuid2(ctx->collector_uuid->uuid);
312         target_conf->config_file = getFullpathName(collector_dir, "target.conf");
313
314         rc = readTargetConf(target_conf, target_conf->config_file);
315         if (rc != PTS_SUCCESS) {
316             LOG(LOG_ERR, "verifier() - readTargetConf failed, %s\n", target_conf->config_file);
317             // WORK NEEDED: Please use NLS for i18n
318             addReason(ctx, -1, "Missing collector configuration file");
319             addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_HOSTNAME,
320                 "Collector hostname = %s"), host);
321             addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_UUID,
322                 "Collector UUID = %s"), ctx->collector_uuid->str);
323             rc = PTS_NOT_INITIALIZED;
324             goto close;
325         }
326
327     } else {
328         /* collector info exist, check with */
329         target_conf = ctx->target_conf;
330         if (memcmp(target_conf->uuid->uuid, ctx->collector_uuid->uuid, 16) != 0) {
331             /* Miss, hostname or IP address was changed?  */
332             LOG(LOG_ERR, "verifier() - Unexpected collector UUID= %s, must be %s\n",
333                 ctx->collector_uuid->str, target_conf->uuid->uuid);
334             // WORK NEEDED: Please use NLS for i18n
335             addReason(ctx, -1, "Collector configuration was changed");
336             addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_HOSTNAME,
337                 "Collector hostname = %s"), host);
338             addReason(ctx, -1, "Expected Collector UUID = %s", target_conf->uuid->uuid);
339             addReason(ctx, -1, "Given Collector UUID = %s", ctx->collector_uuid->str);
340             rc = PTS_NOT_INITIALIZED;
341             goto close;
342         } else {
343             /* Hit keep current collector info */
344             DEBUG("verifier() - use existing target conf\n");
345             DEBUG("Good Collector UUID\n");
346         }
347     }
348
349
350     /* Fill versions */
351     memcpy(&target_conf->pts_flag,    &cap->flag, 4);
352     memcpy(&target_conf->tpm_version, &cap->tpm_version, 4);
353     memcpy(&target_conf->tss_version, &cap->tss_version, 4);
354     memcpy(&target_conf->pts_version, &cap->pts_version, 4);
355
356     DEBUG("OPENPTS CAPS EXCHANGE - flag[0] = 0x%02x\n", target_conf->pts_flag[0]);
357     DEBUG("Verifier  UUID         : %s\n", verifier_uuid->str);
358     DEBUG("Collector UUID         : %s\n", ctx->collector_uuid->str);
359     DEBUG("Collector RM UUID      : %s\n", ctx->rm_uuid->str);
360     DEBUG("RM  UUID               : %s\n", target_conf->rm_uuid->str);
361
362 #ifdef CONFIG_AUTO_RM_UPDATE
363     /* Possible New RM Set from Collector */
364     if (isFlagSet(target_conf->pts_flag[0], OPENPTS_FLAG0_NEWRM_EXIST)) {
365         DEBUG("Discovered pending RM on target -> extracting UUID\n");
366         conf->target_newrm_exist = 1;
367         conf->target_newrm_uuid = xmalloc(sizeof(PTS_UUID));
368         if (NULL == conf->target_newrm_uuid) {
369             rc = PTS_INTERNAL_ERROR;
370             goto close;
371         }
372         memcpy(conf->target_newrm_uuid, &cap->new_manifest_uuid, 16);
373         *notifiedOfPendingRm = 1;
374     }
375 #endif
376
377     /* check RM UUID */
378     // if (target_conf->uuid->status == OPENPTS_UUID_CHANGED) {
379     if (memcmp(target_conf->rm_uuid->uuid, ctx->rm_uuid->uuid, 16) != 0) {
380         /* RM changed */
381         DEBUG("RM was changed\n");
382         // RM UUID was changed
383         // 1) NEW RM UUID => Good Reboot
384         // 2) past RM UUID => fallback?
385         // 3) Unknown UUID => PTS_RULE_NOT_FOUND
386
387         /* compare stored NEWRM UUID and given RM UUID */
388         if ((target_conf->newrm_uuid != NULL) &&
389             (target_conf->newrm_uuid->uuid != NULL) &&
390             (memcmp(target_conf->newrm_uuid->uuid, ctx->rm_uuid->uuid, 16) == 0)) {
391             /* HIT - Good Reboot */
392             /* NEWRM -> RM -> OLDRM */
393             DEBUG("RM changed %s -> %s (good reboot)\n",
394                 target_conf->rm_uuid->str, target_conf->newrm_uuid->str);
395
396                 OUTPUT(NLS(MS_OPENPTS, OPENPTS_VERIFIER_MANIFEST_CHANGED,
397                        "Collector's manifest has been changed to a new manifest (expect a reboot)\n"
398                        "  old manifest UUID : %s\n"
399                        "  new manifest UUID : %s\n"),
400                        target_conf->rm_uuid->str, target_conf->newrm_uuid->str);
401
402             /* Free Old RM */
403             if (target_conf->oldrm_uuid != NULL) {
404                 if (target_conf->oldrm_uuid->uuid != NULL) {
405                     xfree(target_conf->oldrm_uuid->uuid);
406                 }
407                 if (target_conf->oldrm_uuid->str != NULL) {
408                     xfree(target_conf->oldrm_uuid->str);
409                 }
410                 if (target_conf->oldrm_uuid->time != NULL) {
411                     xfree(target_conf->oldrm_uuid->time);
412                 }
413             } else {
414                 target_conf->oldrm_uuid = newOpenptsUuid();
415                 // TODO create this before?
416                 target_conf->oldrm_uuid->filename =  getFullpathName(target_conf->config_dir, "oldrm_uuid");
417             }
418
419             /* Copy RM UUID pointers to  Old RM's UUID ptrs */
420             target_conf->oldrm_uuid->uuid   = target_conf->rm_uuid->uuid;
421             target_conf->oldrm_uuid->str    = target_conf->rm_uuid->str;
422             target_conf->oldrm_uuid->time   = target_conf->rm_uuid->time;
423             target_conf->oldrm_uuid->status = OPENPTS_UUID_FILLED;
424
425             /* Save Old RM */
426             rc = writeOpenptsUuidFile(target_conf->oldrm_uuid, 1);
427             if (rc != PTS_SUCCESS) {
428                 LOG(LOG_ERR, "writeOpenptsUuidFile fail\n");
429             }
430
431             /* Copy NEWRM to RM */
432             target_conf->rm_uuid->uuid   = target_conf->newrm_uuid->uuid;
433             target_conf->rm_uuid->str    = target_conf->newrm_uuid->str;
434             target_conf->rm_uuid->time   = target_conf->newrm_uuid->time;
435             target_conf->rm_uuid->status = OPENPTS_UUID_FILLED;
436
437             /* Save RM */
438             rc = writeOpenptsUuidFile(target_conf->rm_uuid, 1);
439             if (rc != PTS_SUCCESS) {
440                 LOG(LOG_ERR, "writeOpenptsUuidFile fail\n");
441             }
442
443             /* Delete New RM */
444             target_conf->newrm_uuid->uuid   = NULL;
445             target_conf->newrm_uuid->str    = NULL;
446             target_conf->newrm_uuid->time   =  NULL;
447             target_conf->newrm_uuid->status = OPENPTS_UUID_FILENAME_ONLY;
448             rc = remove(target_conf->newrm_uuid->filename);
449
450             goto rm;
451         } else if ((target_conf->oldrm_uuid != NULL) &&
452             (target_conf->oldrm_uuid->uuid != NULL) &&
453             (memcmp(target_conf->oldrm_uuid->uuid, ctx->rm_uuid->uuid, 16) == 0)) {
454             /* HIT - fallback ? */
455             LOG(LOG_TODO, "Fallback - TBD\n");
456             rc = PTS_RULE_NOT_FOUND;  // TODO
457             goto close;
458         } else {
459             /* Unknown RM */
460             /* MISS no RM for the client(collector)  */
461             PTS_DateTime *t0;
462             PTS_DateTime *t1;
463
464             LOG(LOG_ERR, "RM changed %s -> %s (not new rm)\n",
465                 target_conf->rm_uuid->str, ctx->rm_uuid->str);
466
467             // TODO DEBUG("RM changed %s -> %s\n", target_conf->rm_uuid->str, rm_uuid->str);
468
469             // TODO update RM
470             addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_USING_OTHER_RM,
471                 "Collector is using another Reference Manifest (RM)"));
472             addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_HOSTNAME,
473                 "Collector hostname = %s"), host);
474             addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_UUID,
475                 "Collector UUID = %s"), ctx->collector_uuid->str);
476
477             t0 = getDateTimeOfUuid(target_conf->rm_uuid->uuid);
478             t1 = getDateTimeOfUuid(ctx->rm_uuid->uuid);
479
480             addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_PREV_RM_UUID,
481                 "Previous RM UUID = %s, timestamp = %04d-%02d-%02d-%02d:%02d:%02d"),
482                 target_conf->rm_uuid->str,
483                 t0->year + 1900,
484                 t0->mon + 1,
485                 t0->mday,
486                 t0->hour,
487                 t0->min,
488                 t0->sec);
489
490             addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_CUR_RM_UUID,
491                 "Current RM UUID = %s, timestamp = %04d-%02d-%02d-%02d:%02d:%02d"),
492                 ctx->rm_uuid->str,
493                 t1->year + 1900,
494                 t1->mon + 1,
495                 t1->mday,
496                 t1->hour,
497                 t1->min,
498                 t1->sec);
499
500             *currentRmOutOfDate = 1;
501             /* keep going so we can provide remediation based on the last
502                known RM. quitting now gives no information to the user about
503                what has changed. */
504         }
505     } else {
506         /* HIT */
507         DEBUG("RM UUID is HIT\n");
508     }
509
510
511   rm:
512     /* check RM */
513     rm_dir = getFullpathName(collector_dir, target_conf->rm_uuid->str);
514     rc = checkDir(rm_dir);
515     if (rc != PTS_SUCCESS && 0 == *currentRmOutOfDate) {
516         /* unknwon RM */
517         LOG(LOG_ERR, "verifier() - Unknown RM, (RM dir = %s)\n", rm_dir);
518         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_MISSING_RM,
519             "Missing Reference Manifest (RM)"));
520         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_HOSTNAME,
521             "Collector hostname = %s"), host);
522         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_UUID,
523             "Collector UUID = %s"), target_conf->uuid->str);
524         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_COLLECTOR_RM_UUID,
525             "Collector RM UUID = %s"), target_conf->rm_uuid->str);
526         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_MISSING_RM_DIR,
527             "Missing Reference Manifest directory = %s"), rm_dir);
528         rc = PTS_RULE_NOT_FOUND;
529         goto close;
530     }
531
532
533     /* Load RMs */
534     rc = getRmSetDir(target_conf);  // ctx->conf);
535
536     DEBUG("logging dir            : %s\n", collector_dir);
537     for (i = 0; i < conf->rm_num; i++) {
538         DEBUG("RM[%d]                  : %s\n", i, target_conf->rm_filename[i]);
539     }
540 #ifdef CONFIG_AIDE
541     DEBUG("AIDE DB                : %s\n", target_conf->aide_database_filename);
542 #ifdef CONFIG_SQLITE
543     DEBUG("AIDE SQLITE DB         : %s\n", target_conf->aide_sqlite_filename);
544 #endif
545     DEBUG("AIDE ignore list       : %s\n", target_conf->aide_ignorelist_filename);
546 #endif
547     DEBUG("IR                     : %s\n", target_conf->ir_filename);
548     DEBUG("Prop                   : %s\n", target_conf->prop_filename);
549     DEBUG("Policy                 : %s\n", target_conf->policy_filename);
550
551     /* check RM */
552     for (i = 0; i< target_conf->rm_num; i++) {
553         struct stat st;
554         if (lstat(target_conf->rm_filename[i], &st) == -1) {
555             LOG(LOG_ERR, "verifier - RM (%s) is missing. Get RM from target. enroll(init) first\n",
556                 target_conf->rm_filename[i]);
557             rc = PTS_INTERNAL_ERROR;
558             goto close;
559         }
560     }
561
562     rc = PTS_SUCCESS;
563
564   close:
565     if (rm_dir != NULL) free(rm_dir);
566     if (collector_dir != NULL) free(collector_dir);
567
568     return rc;
569 }
570
571
572 /**
573  *  
574  */
575 int verifierHandleRimmSet(
576     OPENPTS_CONTEXT *ctx,
577     BYTE *value)
578 {
579     int rc = PTS_SUCCESS;
580     OPENPTS_CONFIG *target_conf;
581     int i;
582     struct stat st;
583     char buf[BUF_SIZE];
584     int num;
585     int len;
586
587     /* check */
588     if (ctx == NULL) {
589         LOG(LOG_ERR, "null input");
590         return PTS_FATAL;
591     }
592     target_conf = ctx->target_conf;
593     if (target_conf == NULL) {
594         LOG(LOG_ERR, "null input");
595         return PTS_FATAL;
596     }
597     if (value == NULL) {
598         LOG(LOG_ERR, "null input");
599         return PTS_FATAL;
600     }
601
602     /* num */
603     num = getUint32(value);
604     DEBUG_IFM("RM num                 : %d\n", num);
605
606     target_conf->rm_num = num;
607     value += 4;
608
609
610     /* Check RM DIR */
611     if (lstat(target_conf->rm_basedir, &st) == -1) {
612         /* Missing rm_basedir => create */
613         rc = mkdir(target_conf->rm_basedir, S_IRUSR | S_IWUSR | S_IXUSR);
614         if (rc != 0) {
615             ERROR(NLS(MS_OPENPTS, OPENPTS_VERIFIER_CONF_DIR_CREATE_FAILED,
616                 "Failed to create the configuration directory '%s'\n"), buf);
617             rc = PTS_INTERNAL_ERROR;
618             goto error;
619         }
620     } else if ((st.st_mode & S_IFMT) != S_IFDIR) {
621         ERROR(NLS(MS_OPENPTS, OPENPTS_VERIFIER_RM_DIR_NOT_DIR,
622             "The reference manifest path '%s' is not a directory\n"), buf);
623         rc = PTS_INTERNAL_ERROR;
624         goto close;
625     }
626
627     /* Get RMs  */
628     ctx->conf->rm_num = num;
629     for (i = 0; i < num; i++) {
630         snprintf(buf, BUF_SIZE, "%s/rm%d.xml",
631             target_conf->rm_basedir,
632             i);
633
634         if (target_conf->rm_filename[i] != NULL) {
635             DEBUG("enroll() - free conf->rm_filename[%d] %s\n", i, target_conf->rm_filename[i]);
636             xfree(target_conf->rm_filename[i]);
637         }
638
639         target_conf->rm_filename[i] = smalloc(buf);
640
641
642         len = getUint32(value);
643         DEBUG("RM[%d] size             : %d\n", i, len);
644         DEBUG("RM[%d] filename         : %s\n", i, target_conf->rm_filename[i]);
645
646         value += 4;
647
648         rc = saveToFile(target_conf->rm_filename[i], len, value);
649         if (rc != PTS_SUCCESS) {
650             LOG(LOG_ERR, "enroll - save RM[%d], %s failed\n", i, target_conf->rm_filename[i]);
651             rc = PTS_INTERNAL_ERROR;
652             goto close;
653         }
654
655         value += len;
656     }
657
658     /* Save RM UUID file */
659     target_conf->rm_uuid->filename = getFullpathName(target_conf->config_dir, "./rm_uuid");
660     target_conf->rm_uuid->status = OPENPTS_UUID_FILLED;
661
662     rc = writeOpenptsUuidFile(target_conf->rm_uuid, 1);  // TODO do not overwite?
663     if (rc != PTS_SUCCESS) {
664         LOG(LOG_ERR, "writeOpenptsUuidFile fail\n");
665     }
666
667   close:
668   error:
669     return rc;
670 }
671
672
673 /**
674  * Write policy.conf from current prop
675  *
676  * return num of polocy
677  *
678  * ignore ima.0.*=*
679  *
680  * TODO move to prop.c
681  */
682 int  writePolicyConf(OPENPTS_CONTEXT *ctx, char *filename) {
683     FILE *fp;
684     OPENPTS_PROPERTY *prop;
685     int i = 0;
686
687     DEBUG("writePolicyConf       : %s\n", filename);
688
689     /* check */
690     if (ctx == NULL) {
691         LOG(LOG_ERR, "null input");
692         return PTS_FATAL;
693     }
694     if (filename == NULL) {
695         LOG(LOG_ERR, "null input");
696         return PTS_FATAL;
697     }
698
699     if ((fp = fopen(filename, "w")) == NULL) {
700         ERROR(NLS(MS_OPENPTS, OPENPTS_VERIFIER_OPEN_FAILED,
701             "Failed to open policy file '%s'\n"), filename);
702         return PTS_FATAL;
703     }
704
705     /* top */
706     prop = ctx->prop_start;
707
708     fprintf(fp, "# OpenPTS validation policy, name=value\n");
709     while (prop != NULL) {
710         if (!strncmp(prop->name, "ima.aggregate", 13)) {
711             /* IMA aggregate validation policy */
712             fprintf(fp, "%s=%s\n", prop->name, prop->value);
713             i++;
714         } else if (!strncmp(prop->name, "ima.", 4)) {
715             /* IMA measurement - SKIP */
716         } else if (!strncmp(prop->name, "disable.", 8)) {
717             /* Indicates a disabled tpm quote - SKIP */
718         } else {
719             fprintf(fp, "%s=%s\n", prop->name, prop->value);
720             i++;
721         }
722         prop = prop->next;
723     }
724     fprintf(fp, "# %d reference props\n", i);
725     fclose(fp);
726
727     return i;
728 }
729
730
731 #ifdef CONFIG_AIDE
732 #define HASH_TABLE_SIZE ((size_t) 2048)
733
734 /**
735  * Write writeAideIgnoreList from current prop
736  * IMA measurment with OPENPTS_RESULT_UNKNOWN flag -> 
737  *
738  * Returm
739  *   n  count of list
740  *   -1 ERROR
741  *
742  * ima.0.integrty=unknown
743  * ima.0.name=/init
744  * 
745  * TODO move to prop.c?
746  * TODO use hash table, name:count?
747  */
748 int  writeAideIgnoreList(OPENPTS_CONTEXT *ctx, char *filename) {
749     FILE *fp;
750     OPENPTS_SNAPSHOT * ss;
751     OPENPTS_PCR_EVENT_WRAPPER *ew;
752     TSS_PCR_EVENT *event;
753     char *name;
754     int cnt = 0;
755     /* hash */
756     struct hsearch_data hd;
757     ENTRY e, *ep;
758     void* ecnt = 0;
759     int rc;
760
761     DEBUG("writeAideIgnoreList     : %s\n", filename);
762
763     /* check */
764     if (ctx == NULL) {
765         LOG(LOG_ERR, "null input");
766         return PTS_FATAL;
767     }
768     if (filename == NULL) {
769         LOG(LOG_ERR, "null input");
770         return PTS_FATAL;
771     }
772
773     if ((fp = fopen(filename, "w")) == NULL) {
774         ERROR(NLS(MS_OPENPTS, OPENPTS_VERIFIER_OPEN_FAILED_2,
775             "Failed to open AIDE ignore list '%s'\n"), filename);
776         return -1;
777     }
778
779     /* top */
780     ss = getSnapshotFromTable(ctx->ss_table, 10, 1);  // Linux-IMA, TODO define by CONF?
781     if (ss == NULL) {
782         LOG(LOG_ERR, "Snapshot at PCR[10] level 1 is missing\n");
783     } else {
784         ew = ss->start;
785
786
787         /* look over the  event chain  */
788         fprintf(fp, "# OpenPTS AIDE ignore name list\n");
789
790         /* ew -> hash */
791         memset(&hd, 0, sizeof(hd));
792
793         rc = hcreate_r(HASH_TABLE_SIZE, &hd);
794         if (rc == 0) {
795             if (errno == ENOMEM) {
796                 LOG(LOG_ERR, "ENOMEM\n");
797                 cnt = -1;
798                 goto error;
799             }
800             LOG(LOG_ERR, "ERROR rc=%d\n", rc);
801             // return -1;
802             cnt = -1;
803             goto error;
804         }
805
806         while (ew != NULL) {
807             if (ew->status == OPENPTS_RESULT_UNKNOWN) {
808                 event = ew->event;
809                 name = (char *)event->rgbEvent;
810                 name += SHA1_DIGEST_SIZE;
811                 /* add '\n' */
812                 name = snmalloc(name, (event->ulEventLength - SHA1_DIGEST_SIZE));
813
814                 ecnt = 0;
815
816                 e.key = name;
817                 e.data = NULL;
818
819                 rc = hsearch_r(e, FIND, &ep, &hd);
820                 if (rc == 0) {
821                     /* miss */
822                     e.data = (void*) ecnt;
823                     rc = hsearch_r(e, ENTER, &ep, &hd);
824                     // TODO check error
825                     fprintf(fp, "# %d \n", cnt);
826                     fprintf(fp, "%s\n", name);
827                     cnt++;
828                 } else {
829                     /* hit, ++ */
830                     ecnt = ep->data;
831                     ecnt++;
832                     ep->data = ecnt;
833                 }
834             }
835             ew = ew->next_pcr;
836         }
837         hdestroy_r(&hd);
838     }  // SS
839
840     /* close  */
841     fprintf(fp, "# %d props\n", cnt);
842
843   error:
844     fclose(fp);
845
846     return cnt;
847 }
848 #endif  // CONFIG_AIDE
849
850
851 /**
852  *  target_conf->ir_filename
853  */
854 int verifierHandleIR(
855         OPENPTS_CONTEXT *ctx,
856         int length,
857         BYTE *value,
858         int mode,
859         int *result) {
860     int rc = PTS_SUCCESS;
861     OPENPTS_CONFIG *target_conf;
862     int i;
863
864     /* check */
865     if (ctx == NULL) {
866         LOG(LOG_ERR, "null input");
867         return PTS_FATAL;
868     }
869     target_conf = ctx->target_conf;
870     if (target_conf == NULL) {
871         LOG(LOG_ERR, "null input");
872         return PTS_FATAL;
873     }
874     if (value == NULL) {
875         LOG(LOG_ERR, "null input");
876         return PTS_FATAL;
877     }
878
879     /* save IR to file */
880     if (length > 0) {
881         rc = saveToFile(target_conf->ir_filename, length, value);
882         if (rc != PTS_SUCCESS) {
883             DEBUG("target_conf->ir_filename, %s\n", target_conf->ir_filename);
884             addReason(ctx, -1, "[IMV] failed to save IR, %s)", target_conf->ir_filename);
885             ERROR(NLS(MS_OPENPTS, OPENPTS_VERIFIER_SAVE_IR_FAILED,
886                 "[verifier] failed to save IR\n"));
887             rc = PTS_INTERNAL_ERROR;
888             goto close;
889         }
890     } else {
891         addReason(ctx, -1, "[IMV] failed to send IR)");
892         ERROR(NLS(MS_OPENPTS, OPENPTS_VERIFIER_SEND_IR_FAILED,
893             "[verifier] failed to send IR\n"));
894         rc = PTS_INTERNAL_ERROR;
895         goto close;
896     }
897
898     /* load Reference Manifest (BIN-BHV) */
899     DEBUG("Load RM  -------------------------------- \n");
900
901     for (i = 0; i <  target_conf->rm_num; i++) {
902         rc = readRmFile(ctx, target_conf->rm_filename[i], i);
903         if (rc < 0) {
904             LOG(LOG_ERR, "readRmFile fail\n");
905             rc = PTS_INTERNAL_ERROR;
906             goto close;
907         }
908     }
909
910     if (mode == 0) {
911         /* Load Policy to validate properties */
912         DEBUG("Load Policy  -------------------------------- \n");
913         rc = loadPolicyFile(ctx, target_conf->policy_filename);
914         if (rc < 0) {
915             LOG(LOG_ERR, "loadPolicyFile fail\n");
916             rc = PTS_INTERNAL_ERROR;
917             goto close;
918         }
919     } else {
920         /* remove */
921         // ctx->conf->aide_ignorelist_filename = NULL;
922     }
923
924     /* Validate IR by FSM */
925     // *result = validateIr(ctx, target_conf->ir_filename);  /* ir.c */
926     // TODO 2011-10-15 validateIr was changed
927     if (ctx->ir_filename != NULL) xfree(ctx->ir_filename);
928     ctx->ir_filename = smalloc(target_conf->ir_filename);
929     *result = validateIr(ctx);  /* ir.c */
930
931     if (mode == OPENPTS_VERIFY_MODE) {
932         /* save properties */
933         DEBUG("save property          : %s\n", target_conf->prop_filename);
934
935         rc = saveProperties(ctx, target_conf->prop_filename);
936         if (rc != PTS_SUCCESS) {
937             LOG(LOG_ERR, "saveProperties was failed %s\n", target_conf->prop_filename);
938             goto close;
939         }
940     } else if (mode == OPENPTS_UPDATE_MODE) {
941         /* gen policy and ignore list */
942         DEBUG("update policy and ignore list %s\n", target_conf->policy_filename);
943         rc = writePolicyConf(ctx, target_conf->policy_filename);
944         DEBUG("policy num            : %d policies\n", rc);
945 #ifdef CONFIG_AIDE
946         if (ctx->ima_unknown > 0) {
947             rc = writeAideIgnoreList(ctx, target_conf->aide_ignorelist_filename);
948             DEBUG("%d ignore list of AIDE\n", rc);
949         }
950 #endif
951     } else {
952         LOG(LOG_ERR, "unknown mode %d\n", mode);
953         rc = PTS_INTERNAL_ERROR;
954         goto close;
955     }
956     rc = PTS_SUCCESS;
957
958    close:
959
960     return rc;
961 }
962
963 /**
964  * enroll
965  *
966  * get target UUID
967  * get target RMs
968  * else?
969  *
970  * Function Test
971  *
972  *   file         test
973  *   ----------------------------------
974  *   
975  */
976 int enroll(
977     OPENPTS_CONTEXT *ctx,
978     char *host,
979     char *ssh_username,
980     char *ssh_port,
981     char *conf_dir,
982     int force) {
983     int sock;
984     int rc = PTS_SUCCESS;
985     int len;
986     PTS_IF_M_Attribute *read_tlv = NULL;
987     pid_t ssh_pid = -1;
988     int ssh_status;
989     OPENPTS_UUID *verifier_uuid = NULL;
990     OPENPTS_CONFIG *target_conf;
991     OPENPTS_IF_M_Capability *cap;
992     OPENPTS_TARGET *target;
993
994     DEBUG("enroll() - start, force = %d  (1:overwite) --------------------------------------\n", force);
995
996     /* check */
997     if (ctx == NULL) {
998         LOG(LOG_ERR, "null input");
999         return PTS_INTERNAL_ERROR;
1000     }
1001     if (ctx->conf == NULL) {
1002         LOG(LOG_ERR, "null input");
1003         return PTS_INTERNAL_ERROR;
1004     }
1005
1006     // We must ensure that target names are unique among the registered targets.
1007     // Test whether a target with the same name already exists.
1008     ctx->conf->hostname = smalloc(host);
1009     target = getTargetCollector(ctx->conf);
1010
1011     if (target != NULL) {
1012         ctx->target_conf = target->target_conf;
1013         if (!force) {
1014             OUTPUT(NLS(MS_OPENPTS, OPENPTS_VERIFIER_OVERRIDE,
1015                 "%s already exists. If you want to override please use the '-f' option\n"),
1016                 ctx->target_conf->config_file);
1017             rc = PTS_INTERNAL_ERROR;
1018             goto out;
1019         }
1020         // assert(force)
1021         // the target UUID may have been reseted, erase the known one
1022         unlinkDir(target->dir);
1023     } else if (ctx->target_conf != NULL) {
1024         LOG(LOG_ERR, "enroll() - target_conf of %s already exist?\n", host);
1025         goto out;
1026     }
1027
1028     ctx->target_conf = newPtsConfig();
1029     target_conf = ctx->target_conf;
1030     target_conf->hostname = smalloc(host);
1031
1032     /* verifier (my) UUID */
1033     verifier_uuid = ctx->conf->uuid;
1034
1035     /* connect to the target collector */
1036     ssh_pid = ssh_connect(host,
1037                           ssh_username,
1038                           ssh_port,
1039                           NULL,
1040                           &sock);
1041
1042     if (ssh_pid == -1) {
1043         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_CONNECT_FAILED,
1044             "Connection failed (server = %s)\n"), host);
1045         rc = PTS_OS_ERROR;
1046         goto out;
1047     }
1048
1049     /* V->C capability (hello) */
1050     len = writePtsTlv(ctx, sock, OPENPTS_CAPABILITIES);
1051     if (len < 0) {
1052         LOG(LOG_ERR, "Failed to send capability message, rc = %d\n", len);
1053         rc = PTS_INTERNAL_ERROR;
1054         goto close;
1055     }
1056
1057     /* C->V capability (hello) */
1058     read_tlv = readPtsTlv(sock);
1059     if (read_tlv == NULL) {
1060         LOG(LOG_ERR, "Can not get the message from collector\n");
1061         rc = PTS_INTERNAL_ERROR;
1062         goto close;
1063     }
1064
1065     if (read_tlv->type != OPENPTS_CAPABILITIES) {
1066         LOG(LOG_ERR, "Expected OPENPTS_CAPABILITIES reply, instead got type '%d'\n", read_tlv->type);
1067         rc = PTS_INTERNAL_ERROR;
1068         goto close;
1069     }
1070
1071     if (read_tlv->length != sizeof(OPENPTS_IF_M_Capability)) {  // TODO set name
1072         LOG(LOG_ERR, "UUID length = %d != 36\n", read_tlv->length);
1073         rc = PTS_INTERNAL_ERROR;
1074         goto close;
1075     }
1076
1077     cap =  (OPENPTS_IF_M_Capability *)read_tlv->value;
1078
1079     /* version */
1080     memcpy(&target_conf->pts_flag,    &cap->flag, 4);
1081     memcpy(&target_conf->tpm_version, &cap->tpm_version, 4);
1082     memcpy(&target_conf->tss_version, &cap->tss_version, 4);
1083     memcpy(&target_conf->pts_version, &cap->pts_version, 4);
1084
1085     /* collector UUID */
1086     target_conf->uuid = newOpenptsUuid2(&cap->platform_uuid);
1087     if (target_conf->uuid == NULL) {
1088         rc = PTS_INTERNAL_ERROR;
1089         goto close;
1090     }
1091
1092     /* Manifest UUID */
1093     target_conf->rm_uuid = newOpenptsUuid2(&cap->manifest_uuid);
1094     if (target_conf->rm_uuid == NULL) {
1095         rc = PTS_INTERNAL_ERROR;
1096         goto close;
1097     }
1098
1099     /* verifier */
1100     DEBUG("Verifier  UUID         : %s\n", verifier_uuid->str);
1101     DEBUG("Collector UUID         : %s\n", target_conf->uuid->str);
1102     DEBUG("RM UUID                : %s\n", target_conf->rm_uuid->str);
1103
1104     target_conf->config_dir =
1105         getFullpathName(conf_dir, target_conf->uuid->str);
1106     target_conf->config_file =
1107         getFullpathName(target_conf->config_dir, "target.conf");
1108     target_conf->uuid->filename =
1109         getFullpathName(target_conf->config_dir, "uuid");
1110     target_conf->rm_basedir =
1111         getFullpathName(target_conf->config_dir, target_conf->rm_uuid->str);
1112
1113 #ifdef CONFIG_AIDE
1114     target_conf->aide_database_filename =
1115         getFullpathName(target_conf->config_dir, "aide.db.gz");
1116     target_conf->aide_ignorelist_filename =
1117         getFullpathName(target_conf->config_dir, "aide.ignore");
1118 #ifdef CONFIG_SQLITE
1119     target_conf->aide_sqlite_filename =
1120         getFullpathName(target_conf->config_dir, "aide.sqlite.db");
1121 #endif
1122 #endif
1123
1124
1125     /* create */
1126     rc = makeDir(target_conf->config_dir);
1127     // TODO check rc
1128
1129     DEBUG("conf dir               : %s\n", target_conf->config_dir);
1130     DEBUG("rm dir                 : %s\n", target_conf->rm_basedir);
1131     DEBUG("AIDE DB                : %s\n", target_conf->aide_database_filename);
1132 #ifdef CONFIG_SQLITE
1133     DEBUG("AIDE SQLite DB         : %s\n", target_conf->aide_sqlite_filename);
1134 #endif
1135
1136     if (force == 1) {
1137         /* delete existing info */
1138         // DEBUG("enroll - force=1 NA. Sorry\n");
1139     } else {
1140         /* check existing info */
1141         struct stat st;
1142         if (lstat(target_conf->config_file , &st) == -1) {
1143             // Missing,
1144             DEBUG("%s is missing. Get RM from target\n", target_conf->config_file);
1145         } else {
1146             // EXIST -> Update
1147             OUTPUT(NLS(MS_OPENPTS, OPENPTS_VERIFIER_OVERRIDE,
1148                 "%s already exists. If you want to override please use the '-f' option\n"),
1149                 target_conf->config_file);
1150             rc = PTS_INTERNAL_ERROR;
1151             goto close;
1152         }
1153     }
1154
1155
1156     /* free */
1157     // TODO free
1158     // read_tlv->value -= 16; // TODO
1159     freePtsTlv(read_tlv);
1160     read_tlv = NULL;
1161
1162     /* get the Reference Manifest from target(collector) */
1163
1164
1165     /* V->C template RIMM req  */
1166     len = writePtsTlv(ctx, sock, REQUEST_RIMM_SET);
1167     if (len < 0) {
1168         LOG(LOG_ERR, "template RIMM req was failed\n");
1169         rc = PTS_INTERNAL_ERROR;
1170         goto close;
1171     }
1172
1173     /* C->V template RIMM (RIMM embedded to CTX) */
1174     read_tlv = readPtsTlv(sock);
1175     if (read_tlv == NULL) {
1176         LOG(LOG_ERR, "Problem receiving PTS message\n");
1177         rc = PTS_INTERNAL_ERROR;
1178         goto close;
1179     } else if (read_tlv->type == OPENPTS_ERROR) {
1180         LOG(LOG_ERR, "Request RIMM_SET was failed. collector returns error message");
1181         rc = PTS_INTERNAL_ERROR;
1182         goto close;
1183     } else if (read_tlv->type != RIMM_SET) {
1184         LOG(LOG_ERR, "Bad return message, %X != %X", read_tlv->type, RIMM_SET);
1185         rc = PTS_INTERNAL_ERROR;
1186         goto close;
1187     }
1188
1189     rc = verifierHandleRimmSet(ctx, (BYTE*) read_tlv->value);
1190     if (rc != PTS_SUCCESS) {
1191         LOG(LOG_ERR, "Bad RIMM_SET?");
1192         rc = PTS_INTERNAL_ERROR;
1193         goto close;
1194     }
1195
1196     /* free */
1197     freePtsTlv(read_tlv);
1198     read_tlv = NULL;
1199
1200
1201     /* V->C TPM PUBKEY req */
1202     len = writePtsTlv(ctx, sock, REQUEST_TPM_PUBKEY);  // ifm.c
1203
1204     if (len < 0) {
1205         LOG(LOG_ERR, "enroll() - REQUEST_TPM_PUBKEY was failed, len=%d\n", len);
1206         rc = PTS_INTERNAL_ERROR;
1207         goto close;
1208     }
1209
1210     /* C->V TPM PUBKEY */
1211     read_tlv = readPtsTlv(sock);
1212     if (read_tlv == NULL) {
1213         LOG(LOG_ERR, "Problem receiving PTS message\n");
1214         rc = PTS_INTERNAL_ERROR;
1215         goto close;
1216     } else if (read_tlv->type == OPENPTS_ERROR) {
1217         // TODO Ignore now
1218         LOG(LOG_TODO, "Target did not have TPM_PUBKEY");
1219         // WORK NEEDED - Please use NLS for i18n
1220         addReason(ctx, -1, "Target did not have TPM_PUBKEY\n");
1221         rc = PTS_INTERNAL_ERROR;
1222         goto close;
1223     } else if (read_tlv->type != TPM_PUBKEY) {
1224         LOG(LOG_ERR, "read_tlv->type != TPM_PUBKEY, but %d", read_tlv->type);
1225         rc = PTS_INTERNAL_ERROR;
1226         goto close;
1227     }
1228
1229     if (read_tlv->length > 0) {
1230         /* TPM_PUBKEY -> CTX */
1231         DEBUG("TPM_PUBKEY size        : %d\n", read_tlv->length);
1232
1233         // TODO used by two
1234         if (target_conf->pubkey != NULL) {
1235             DEBUG("enroll() - reset the PUBKEY\n");
1236             xfree(target_conf->pubkey);
1237         }
1238
1239         target_conf->pubkey_length = read_tlv->length;
1240         target_conf->pubkey = xmalloc_assert(target_conf->pubkey_length);
1241         // TODO check NULL
1242         memcpy(
1243             target_conf->pubkey,
1244             read_tlv->value,
1245             target_conf->pubkey_length);
1246         /* save to the target.conf */
1247     } else {
1248         DEBUG("enroll - TPM_PUBKEY is missing.\n");
1249     }
1250
1251
1252
1253 #ifdef CONFIG_AIDE
1254     // LOG(LOG_TODO, munetoh) capability defile validation mode of collector
1255     /* V->C AIDE_DATABASE req  */
1256     len = writePtsTlv(ctx, sock, REQUEST_AIDE_DATABASE);
1257
1258     if (len < 0) {
1259         LOG(LOG_ERR, "template RIMM req was failed\n");
1260         rc = PTS_INTERNAL_ERROR;
1261         goto close;
1262     }
1263
1264     /* C->V AIDE DATABASE */
1265     read_tlv = readPtsTlv(sock);
1266     if (read_tlv == NULL) {
1267         LOG(LOG_ERR, "Problem receiving PTS message\n");
1268         rc = PTS_INTERNAL_ERROR;
1269         goto close;
1270     } else if (read_tlv->type != AIDE_DATABASE) {
1271         if (read_tlv->type == OPENPTS_ERROR) {
1272             // TODO check msg?
1273             /* AIDE DB is missing */
1274             target_conf->ima_validation_mode = OPENPTS_VALIDATION_MODE_NONE;
1275             DEBUG("enroll - AIDE DB is missing. do not validate IMA's IMLs\n");
1276         } else {
1277             LOG(LOG_ERR, "enroll - RAIDE DB req. returns unknown message type 0x%x", read_tlv->type);
1278             rc = PTS_INTERNAL_ERROR;
1279             goto close;
1280         }
1281     } else {
1282         // Got AIDE DB?
1283         if (read_tlv->length > 0) {
1284             /* AIDE_DATABASE -> CTX */
1285             DEBUG("AIDE_DATABASE size     : %d\n", read_tlv->length);
1286
1287             rc = saveToFile(target_conf->aide_database_filename, read_tlv->length, read_tlv->value);
1288             if (rc < 0) {
1289                 LOG(LOG_ERR, "enroll - save AIDE DB failed\n");
1290                 rc = PTS_INTERNAL_ERROR;
1291                 goto close;
1292             }
1293
1294 #ifdef CONFIG_SQLITE
1295             DEBUG("conv to sqlite %s\n", target_conf->aide_sqlite_filename);
1296             rc = convertAideDbfileToSQLiteDbFile(
1297                     ctx->conf->aide_database_filename,
1298                     ctx->conf->aide_sqlite_filename);
1299             if (rc != PTS_SUCCESS) {
1300                 LOG(LOG_ERR, "enroll - convert AIDE DB to SQLiteDB was failed\n");
1301                 rc = PTS_INTERNAL_ERROR;
1302                 goto close;
1303             }
1304 #endif
1305             target_conf->ima_validation_mode = OPENPTS_VALIDATION_MODE_AIDE;
1306         } else {
1307             /* no AIDE DB */
1308             target_conf->ima_validation_mode = OPENPTS_VALIDATION_MODE_NONE;
1309             DEBUG("enroll - AIDE DB is missing. do not validate IMA's IMLs\n");
1310         }
1311     }
1312
1313     /* free */
1314     freePtsTlv(read_tlv);
1315     read_tlv = NULL;
1316
1317 #endif  // CONFIG_AIDE
1318
1319
1320
1321     /* save target conf */
1322     writeTargetConf(
1323         target_conf,
1324         target_conf->uuid->uuid,
1325         target_conf->config_file);  // conf.c
1326
1327     /* OK */
1328     rc = PTS_SUCCESS;
1329
1330   close:
1331     close(sock);
1332     waitpid(ssh_pid, &ssh_status, 0);
1333
1334   out:
1335     /* free */
1336
1337     if (read_tlv != NULL) {
1338         freePtsTlv(read_tlv);
1339     }
1340
1341     freePtsConfig(ctx->target_conf);
1342     ctx->target_conf = NULL;
1343
1344     DEBUG("enroll() - done, force = %d  (1:overwite) --------------------------------------\n", force);
1345
1346     return rc;
1347 }
1348
1349
1350 /**
1351  *  Standalone IF-M verifier 
1352  */
1353 int verifier(
1354     OPENPTS_CONTEXT *ctx,
1355     char *host,
1356     char *ssh_username,
1357     char *ssh_port,
1358     char *conf_dir,
1359     int mode) {
1360     const int MINIMUM_NONCE_LENGTH = 16;
1361     int rc = PTS_VERIFY_FAILED;  /* guilty until proven innocent */
1362     int result = OPENPTS_RESULT_INVALID;
1363     int len;
1364     /* sock */
1365     int sock;
1366     pid_t ssh_pid;
1367     int ssh_status;
1368     /* TLV/PTS */
1369     PTS_IF_M_Attribute *read_tlv = NULL;
1370     OPENPTS_CONFIG *conf;
1371     OPENPTS_IF_M_Capability *cap;
1372     int notifiedOfPendingRm = 0;
1373     int currentRmOutOfDate = 0;
1374
1375     DEBUG("verifier() - start\n");
1376     DEBUG("  conf_dir             : %s\n", conf_dir);
1377     DEBUG("  mode                 : %d  (0:just verify, 1:update the policy)\n", mode);
1378
1379     /* check */
1380     if (ctx == NULL) {
1381         LOG(LOG_ERR, "null input");
1382         return PTS_FATAL;
1383     }
1384     conf = ctx->conf;
1385     if (conf == NULL) {
1386         LOG(LOG_ERR, "null input");
1387         return PTS_FATAL;
1388     }
1389
1390     /* connect to the target collector */
1391     ssh_pid = ssh_connect(host,
1392                           ssh_username,
1393                           ssh_port,
1394                           NULL,
1395                           &sock);
1396
1397     if (ssh_pid == -1) {
1398         LOG(LOG_ERR, "connection failed (server = %s)\n", host);
1399         addReason(ctx, -1, NLS(MS_OPENPTS, OPENPTS_VERIFIER_CONNECT_FAILED,
1400             "Connection failed (server = %s)\n"), host);
1401         rc = PTS_OS_ERROR;
1402         goto out;
1403     }
1404
1405     /* IF-M start */
1406
1407     /* V->C capability (hello) */
1408     len = writePtsTlv(ctx, sock, OPENPTS_CAPABILITIES);
1409     if (len < 0) {
1410         LOG(LOG_ERR, "Failed to send capability message\n");
1411         rc = PTS_INTERNAL_ERROR;
1412         goto close;
1413     }
1414
1415     /* C->V capability (hello) */
1416     read_tlv = readPtsTlv(sock);
1417     if (read_tlv == NULL) {
1418         LOG(LOG_ERR, "can't connect to target, %s\n", host);
1419         rc = PTS_INTERNAL_ERROR;
1420         goto close;
1421     } else if (read_tlv->type != OPENPTS_CAPABILITIES) {
1422         LOG(LOG_ERR, "Expected OPENPTS_CAPABILITIES reply, instead got type '%d'\n", read_tlv->type);
1423         rc = PTS_INTERNAL_ERROR;
1424         goto close;
1425     } else if (read_tlv->length != sizeof(OPENPTS_IF_M_Capability)) {
1426         // TODO PTS_CAPABILITIES_SIZE
1427         LOG(LOG_ERR, "UUID length = %d != 36\n", read_tlv->length);
1428         rc = PTS_INTERNAL_ERROR;
1429         goto close;
1430     }
1431     cap = (OPENPTS_IF_M_Capability *)read_tlv->value;
1432
1433     rc = verifierHandleCapability(ctx, conf_dir, host, cap,
1434                                   &notifiedOfPendingRm, &currentRmOutOfDate);
1435     if (rc != PTS_SUCCESS) {
1436         LOG(LOG_ERR, "Failed to exchange capabilities\n");
1437         goto close;
1438     }
1439
1440     /* V->C  D-H nonce param req ---------------------------------- */
1441     /*   setup req  */
1442     ctx->nonce->req->reserved = 0;
1443     ctx->nonce->req->min_nonce_len = MINIMUM_NONCE_LENGTH;
1444     ctx->nonce->req->dh_group_set = DH_GROUP_2;
1445
1446     /*   send req   */
1447     len = writePtsTlv(ctx, sock, DH_NONCE_PARAMETERS_REQUEST);
1448     if (len < 0) {
1449         LOG(LOG_ERR, "Failed to send nonce parameters request\n");
1450         rc = PTS_INTERNAL_ERROR;
1451         goto close;
1452     }
1453
1454     /* C->V  D-H nonce param res ---------------------------------- */
1455     freePtsTlv(read_tlv);
1456     read_tlv = NULL;
1457
1458     read_tlv = readPtsTlv(sock);
1459     if (read_tlv == NULL) {
1460         LOG(LOG_ERR, "[IF-M] DH_NONCE_PARAMETERS_REQUEST was failed, check the collector");
1461         rc = PTS_INTERNAL_ERROR;
1462         goto close;
1463     } else if (read_tlv->type != DH_NONCE_PARAMETORS_RESPONSE) {
1464         LOG(LOG_ERR, "Expected DH_NONCE_PARAMETORS_RESPONSE reply, but instead got type '%d'\n",
1465             read_tlv->type);
1466         rc = PTS_INTERNAL_ERROR;
1467         goto close;
1468     }
1469     // DEBUG("new read_tlv %p\n",read_tlv);
1470
1471     /* res -> fin */
1472     ctx->nonce->res->reserved[0]         = read_tlv->value[0];
1473     ctx->nonce->res->reserved[1]         = read_tlv->value[1];
1474     ctx->nonce->res->reserved[2]         = read_tlv->value[2];
1475     ctx->nonce->res->nonce_length        = read_tlv->value[3];
1476     ctx->nonce->res->selected_dh_group   = (read_tlv->value[4]<<8) | read_tlv->value[5];
1477     ctx->nonce->res->hash_alg_set        = (read_tlv->value[6]<<8) | read_tlv->value[7];
1478
1479     if (ctx->nonce->res->nonce_length < MINIMUM_NONCE_LENGTH) {
1480         LOG(LOG_ERR, "Expected minimum nonce length of '%d', instead got '%d'\n",
1481             MINIMUM_NONCE_LENGTH, ctx->nonce->res->nonce_length);
1482         rc = PTS_INTERNAL_ERROR;
1483         goto close;
1484     }
1485
1486     /* set pubkey length */
1487     if ( 0 != setDhPubkeylength(ctx->nonce) ) {
1488         LOG(LOG_ERR, "setDhPubkeylength failed\n");
1489         rc = PTS_INTERNAL_ERROR;
1490         goto close;
1491     }
1492
1493     /* nonce */
1494     ctx->nonce->res->dh_respondor_nonce = xmalloc_assert(ctx->nonce->res->nonce_length);
1495     memcpy(
1496         ctx->nonce->res->dh_respondor_nonce,
1497         &read_tlv->value[8],
1498         ctx->nonce->res->nonce_length);
1499
1500     /* pubkey */
1501     ctx->nonce->res->dh_respondor_public = xmalloc_assert(ctx->nonce->pubkey_length);
1502     memcpy(
1503         ctx->nonce->res->dh_respondor_public,
1504         &read_tlv->value[8 + ctx->nonce->res->nonce_length],
1505         ctx->nonce->pubkey_length);
1506     ctx->nonce->pubkey = ctx->nonce->res->dh_respondor_public;  // link
1507
1508     rc = calcDh(ctx->nonce);
1509     if (rc != 0) {
1510         LOG(LOG_ERR, "calcDh failed\n");
1511         rc = PTS_INTERNAL_ERROR;
1512         goto close;
1513     }
1514
1515     /* V->C D-H nonce finish  --------------------------------------------- */
1516     len = writePtsTlv(ctx, sock, DH_NONCE_FINISH);
1517     if (len < 0) {
1518         LOG(LOG_ERR, "Failed to send nonce finish message\n");
1519         rc = PTS_INTERNAL_ERROR;
1520         goto close;
1521     }
1522
1523     /* V->C IR req -------------------------------------------------------- */
1524     len = writePtsTlv(ctx, sock, REQUEST_INTEGRITY_REPORT);
1525     if (len < 0) {
1526         LOG(LOG_ERR, "Failed to send request integrity report message\n");
1527         rc = PTS_INTERNAL_ERROR;
1528         goto close;
1529     }
1530
1531     /* C->V IR ------------------------------------------------------------ */
1532     freePtsTlv(read_tlv);
1533     read_tlv = NULL;
1534
1535     read_tlv = readPtsTlv(sock);
1536     if (read_tlv == NULL) {
1537         LOG(LOG_ERR, "Failed to get integrity report. Please check the collector.\n");
1538         rc = PTS_INTERNAL_ERROR;
1539         goto close;
1540     } else if (read_tlv->type != INTEGRITY_REPORT) {
1541         LOG(LOG_ERR, "read_tlv->type != INTEGRITY_REPORT, but 0x%X (0x0F:OPENPTS_ERROR)", read_tlv->type);
1542         rc = PTS_INTERNAL_ERROR;
1543         goto close;
1544     }
1545
1546     rc = verifierHandleIR(ctx, read_tlv->length, read_tlv->value, mode, &result);
1547     if (rc != PTS_SUCCESS) {
1548         LOG(LOG_ERR, "verifierHandleIR fail\n");
1549         rc = PTS_INTERNAL_ERROR;
1550         goto close;
1551     }
1552
1553 #ifdef CONFIG_AUTO_RM_UPDATE
1554     if ( notifiedOfPendingRm ) {
1555         DEBUG("Downloading new RM set\n");
1556         /* get the Reference Manifest from target(collector) -
1557            we download it here as part of the verify path because
1558            it saves us having to open a new connection to ptsc, which
1559            is wasteful */
1560
1561         /* V->C template RIMM req  */
1562         rc = writePtsTlv(ctx, sock, REQUEST_NEW_RIMM_SET);
1563         if (rc < 0) {
1564             LOG(LOG_ERR, "writePtsTlv() fail");
1565             rc = PTS_INTERNAL_ERROR;
1566             goto close;
1567         }
1568
1569         /* C->V template RIMM (RIMM embedded to CTX) */
1570         freePtsTlv(read_tlv);
1571         read_tlv = readPtsTlv(sock);
1572         if (NULL == read_tlv || NEW_RIMM_SET != read_tlv->type) {
1573             rc = PTS_INTERNAL_ERROR;
1574             goto close;
1575         }
1576
1577         DEBUG("New RIMM len %d\n", read_tlv->length);
1578
1579         /* stash a copy of the downloaded pending RM */
1580         conf->newRmSet = read_tlv->value;
1581         read_tlv->value = 0;
1582     }
1583 #endif
1584
1585     /* V->C VR */
1586     len = writePtsTlv(ctx, sock, VERIFICATION_RESULT);
1587     if (len < 0) {
1588         LOG(LOG_ERR, "writePtsTlv() fail");
1589         rc = PTS_INTERNAL_ERROR;
1590         goto close;
1591     }
1592
1593     /* return validateIr() result  */
1594     // TODO
1595     // OPENPTS_RESULT_INVALID
1596     if (currentRmOutOfDate) {
1597         DEBUG("verifier() result      : MISSING RM");
1598         rc = PTS_RULE_NOT_FOUND;
1599     } else if (result == OPENPTS_RESULT_VALID) {
1600         DEBUG("verifier() result      : VALID");
1601         rc = PTS_SUCCESS;        // 0 -> 0
1602     } else if (result == OPENPTS_RESULT_UNVERIFIED) {
1603         DEBUG("verifier() result      : UNVERIFIED");
1604         rc = PTS_VERIFY_FAILED;  // 101 -> 34
1605     } else if (result == OPENPTS_RESULT_INVALID) {
1606         DEBUG("verifier() result      : INVALID");
1607         rc = PTS_VERIFY_FAILED;  // 102 -> 34
1608     } else if (result == OPENPTS_RESULT_UNKNOWN) {
1609         DEBUG("verifier() result      : UNKNOWN");
1610         rc = PTS_VERIFY_FAILED;  // 104 -> 34
1611     } else if (result == OPENPTS_RESULT_IGNORE) {
1612         DEBUG("verifier() result      : IGNORE");
1613         rc = PTS_VERIFY_FAILED;  // 103 -> 34
1614     } else {
1615         DEBUG("verifier() result      : ERROR");
1616         rc = PTS_INTERNAL_ERROR;
1617     }
1618
1619   close:
1620     /* close socket */
1621     close(sock);
1622     waitpid(ssh_pid, &ssh_status, 0);
1623
1624   out:
1625     /* free */
1626     if (read_tlv != NULL) {
1627         freePtsTlv(read_tlv);
1628     }
1629
1630     if ((rc == PTS_VERIFY_FAILED) && (mode == 1)) {
1631         DEBUG("verifier() - update the policy");
1632         rc = PTS_SUCCESS;
1633     }
1634
1635     DEBUG("verifier() - done (rc = %d)\n", rc);
1636
1637     return rc;
1638 }