OSDN Git Service

598bec35c99338833952903d1251f55f22a00a8b
[openpts/openpts.git] / src / ptsc.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) 2011 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/ptsc.c
26  * \brief PTS collector command
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @author Olivier Valentin <olivier.valentin@us.ibm.com>
29  * @author Alexandre Ratchov <alexandre.ratchov@bull.net>
30  * @date 2010-04-04
31  * cleanup 2011-07-06 SM
32  *
33  */
34
35 #ifdef AIX
36 #include <sys/lockf.h>
37 #endif
38
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/un.h>
42 #include <sys/socketvar.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <pwd.h>
49 #include <grp.h>
50 #include <sys/stat.h>  // chmod
51
52 #include <openpts.h>
53 // #include <log.h>
54
55
56 int prop_num = 0;
57 OPENPTS_PROPERTY *start = NULL;
58 OPENPTS_PROPERTY *end = NULL;
59
60 /**
61  * collector daemon
62  *
63  * TODO support single connection.
64  * TODO for multiple conenction, multiple ctxs are required. 
65  * TODO disable remote connection
66  */ 
67 int collector2(OPENPTS_CONFIG *conf) {
68     int rc;
69     int terminate = 0;
70     OPENPTS_CONTEXT *ctx = NULL;
71     PTS_IF_M_Attribute *read_tlv = NULL;
72
73     /* Init RMs */
74     rc = getRmSetDir(conf);
75     if (rc != PTS_SUCCESS) {
76         ERROR("collector() - getRmSetDir() was failed\n");
77         return PTS_INTERNAL_ERROR;
78     }
79
80     rc = getNewRmSetDir(conf);
81     if (rc != PTS_SUCCESS) {
82         /* don't care */
83         DEBUG("collector() - getNewRmSetDir() was failed - never mind\n");
84     }
85
86
87     INFO("start collector (System UUID=%s, RM UUID = %s)\n",
88         conf->uuid->str, conf->rm_uuid->str);
89
90     /* Collector <-> Verifier - handshake loop */
91
92     ctx = newPtsContext(conf);
93
94     addPropertiesFromConfig(conf, ctx);
95
96     /* protocol loop */
97     while (!terminate) {
98         /* V->C request */
99
100         /* read() will block forever unless STDIN was explicitly set to
101            be non-blocking or we receive an interrupt. even then wrapRead() will
102            ignore EAGAIN and EINTR and keep attempting to call read(). the only way
103            this could fail is if the other end of the connection closed, in which case
104            we should exit. if timeouts are required then poll() or select() can be
105            used on blocking file descriptors to listen for input. */
106         read_tlv = readPtsTlv(STDIN_FILENO);  // ifm.c, malloc tlv
107         if (read_tlv == NULL) {
108             DEBUG("close IF-M PTS connection\n");
109             break;
110         }
111
112         /* check bad TLV */
113         if (read_tlv->type == 0) {
114             ERROR("Bad TLV type received - quit");
115             break;
116         }
117
118         if (read_tlv->length > 0 && read_tlv->value == NULL) {
119             ERROR("Malformed TLV message (ghost body) - quit");
120             break;
121         }
122
123         INFO("IF-M read type = 0x%X, len %d\n",
124                 read_tlv->type,
125                 read_tlv->length);
126
127         /* C->V responces */
128         switch (read_tlv->type) {
129             case OPENPTS_CAPABILITIES:
130                 // TODO define CAPABILITIES structure
131                 DEBUG("IF-M OPENPTS_CAPABILITIES\n");
132                 /* check the UUID */
133                 if (read_tlv->length != sizeof(OPENPTS_IF_M_Capability)) {  // TODO use defined name
134                     ERROR("Bad PTS_CAPABILITIES, len = %d != %d\n",
135                         read_tlv->length, sizeof(OPENPTS_IF_M_Capability));
136                     terminate = 1;
137                 } else {
138                     // TODO copy
139                     OPENPTS_IF_M_Capability *cap;
140                     cap = (OPENPTS_IF_M_Capability *) read_tlv->value;
141                     /* get version */
142                     // TODO
143                     /* get verifier's UUID */
144                     ctx->uuid = xmalloc_assert(sizeof(PTS_UUID));
145                     memcpy(ctx->uuid, &cap->platform_uuid, 16);
146                     ctx->str_uuid = getStringOfUuid(ctx->uuid);
147
148                     /* syslog */
149                     INFO("verifier (UUID=%s)\n", ctx->str_uuid);
150
151                     /* send PTS_CAPABILITIES msg. to verifier (=UUID) */
152                     rc = writePtsTlv(ctx, STDOUT_FILENO, OPENPTS_CAPABILITIES);
153                     if (rc < 0) {
154                         ERROR("Send CAPABILITY answer failed - quit");
155                         terminate = 1;
156                     }
157                 }
158                 break;
159
160             case DH_NONCE_PARAMETERS_REQUEST:
161                 DEBUG("IF-M DH_NONCE_PARAMETERS_REQUEST\n");
162                 /* check */
163                 if (read_tlv->length != 4) {
164                     ERROR("Bad DH_NONCE_PARAMETERS_REQUEST, len = %d != 4\n", read_tlv->length);
165                     terminate = 1;
166                 } else {
167                     /* req -> res */
168                     ctx->nonce->req->reserved      = read_tlv->value[0];
169                     ctx->nonce->req->min_nonce_len = read_tlv->value[1];
170                     // NBO to Host
171                     ctx->nonce->req->dh_group_set  = (read_tlv->value[2]<<8) | read_tlv->value[3];
172
173                     rc = getDhResponce(ctx->nonce);
174
175                     /* send responce */
176                     rc = writePtsTlv(
177                             ctx, STDOUT_FILENO, DH_NONCE_PARAMETORS_RESPONSE);
178                     if (rc < 0) {
179                         ERROR("Send NONCE answer failed - quit");
180                         terminate = 1;
181                     }
182                 }
183                 break;
184             case DH_NONCE_FINISH:
185                 DEBUG("IF-M DH_NONCE_FINISH\n");
186                 /* check */
187                 if (read_tlv->length != 152) {  // TODO  how to calc this size?
188                     ERROR("Bad DH_NONCE_FINISH, len = %d != 152\n", read_tlv->length);
189                     terminate = 1;
190                 } else {
191                     /* finish  */
192                     ctx->nonce->fin->reserved            = read_tlv->value[0];
193                     ctx->nonce->fin->nonce_length        = read_tlv->value[1];
194                     // NBO to Host
195                     ctx->nonce->fin->selected_hash_alg   = (read_tlv->value[2]<<8) | read_tlv->value[3];
196
197                     /* public */
198                     ctx->nonce->fin->dh_initiator_public = xmalloc_assert(ctx->nonce->pubkey_length);
199                     memcpy(
200                         ctx->nonce->fin->dh_initiator_public,
201                         &read_tlv->value[4],
202                         ctx->nonce->pubkey_length);
203
204                     /* nonce */
205                     ctx->nonce->fin->dh_initiator_nonce = xmalloc_assert(ctx->nonce->fin->nonce_length);
206                     memcpy(
207                         ctx->nonce->fin->dh_initiator_nonce,
208                         &read_tlv->value[4 + ctx->nonce->pubkey_length],
209                         ctx->nonce->fin->nonce_length);
210
211                     rc = calcDhFin(ctx->nonce);
212
213                     /* no responce */
214                 }
215                 break;
216             case REQUEST_RIMM_SET:  // 5
217                 DEBUG("IF-M REQUEST_RIMM_SET\n");
218                 /* check */
219                 if (read_tlv->length != 0) {
220                     ERROR("Bad REQUEST__RIMM_SET, len = %d != 0\n", read_tlv->length);
221                     terminate = 1;
222                 } else {
223                     rc = writePtsTlv(
224                             ctx, STDOUT_FILENO, RIMM_SET);
225                     if (rc < 0) {
226                         ERROR("Send RIMM_SET answer failed - quit");
227                         terminate = 1;
228                     }
229                 }
230                 break;
231             case REQUEST_NEW_RIMM_SET:
232                 DEBUG("IF-M REQUEST_NEW_RIMM_SET\n");
233                 /* check */
234                 if (read_tlv->length != 0) {
235                     ERROR("Bad REQUEST_NEW_RIMM_SET, len = %d != 0\n", read_tlv->length);
236                     terminate = 1;
237                 } else {
238                     rc = writePtsTlv(
239                             ctx, STDOUT_FILENO, NEW_RIMM_SET);
240                     if (rc < 0) {
241                         ERROR("Send NEW_RIMM_SET answer failed - quit");
242                         terminate = 1;
243                     }
244                 }
245                 break;
246             case REQUEST_INTEGRITY_REPORT:
247                 DEBUG("IF-M REQUEST_INTEGRITY_REPORT\n");
248                 /* check */
249                 if (read_tlv->length != 0) {
250                     ERROR("Bad REQUEST_INTEGRITY_REPORT, len = %d != 0\n", read_tlv->length);
251                     terminate = 1;
252                 } else {
253                     rc = writePtsTlv(ctx, STDOUT_FILENO, INTEGRITY_REPORT);
254                     if (rc < 0) {
255                         ERROR("Send INTEGRITY_REPORT answer failed - quit");
256                         terminate = 1;
257                     }
258                 }
259                 break;
260             case VERIFICATION_RESULT:
261                 /* no responce */
262                 INFO("IF-M VERIFICATION_RESULT => terminate\n");
263                 DEBUG_IFM("finish\n");
264                 terminate = 1;  // TODO add TERMINATE MSG
265                 break;
266 #ifdef CONFIG_AIDE
267             case REQUEST_AIDE_DATABASE:
268                 INFO("IF-M REQUEST_AIDE_DATABASE\n");
269                 /* check */
270                 if (read_tlv->length != 0) {
271                     ERROR("Bad REQUEST_AIDE_DATABASE, len = %d != 0\n", read_tlv->length);
272                     terminate = 1;
273                 } else {
274                     rc = writePtsTlv(ctx, STDOUT_FILENO, AIDE_DATABASE);
275                     if (rc < 0) {
276                         ERROR("Send REQUEST_AIDE_DATABASE answer failed - quit");
277                         terminate = 1;
278                     }
279                 }
280                 break;
281 #endif
282             case REQUEST_TPM_PUBKEY:
283                 /* check */
284                 if (read_tlv->length != 0) {
285                     ERROR("Bad REQUEST_TPM_PUBKEY, len = %d != 0\n", read_tlv->length);
286                     terminate = 1;
287                 } else {
288                     rc = writePtsTlv(ctx, STDOUT_FILENO, TPM_PUBKEY);  // ifm.c
289                     if (rc < 0) {
290                         ERROR("Send TPM_PUBKEY answer failed - quit");
291                         terminate = 1;
292                     }
293                 }
294                 break;
295             case NONCE:
296                 /* check */
297                 if (read_tlv->length != 20) {
298                     ERROR("Bad NONCE, len = %d != 20\n", read_tlv->length);
299                     terminate = 1;
300                 } else {
301                     /* set nonce */
302                     ctx->nonce->nonce_length = 20;
303                     if (ctx->nonce->nonce != NULL) {
304                         xfree(ctx->nonce->nonce);
305                     }
306                     ctx->nonce->nonce = xmalloc_assert(20);
307                     memcpy(ctx->nonce->nonce, read_tlv->value, 20);
308                     DEBUG_IFM("nonce[%d] : \n", ctx->nonce->nonce_length);
309                 }
310                 break;
311             case OPENPTS_ERROR:
312                 ERROR("verifier returns error, termnate\n");
313                 terminate = 1;
314                 break;
315             default:
316                 ERROR("PTS IF-M type 0x%08x is not supported\n", read_tlv->type);
317                 INFO("send OPENPTS_ERROR msg to verifier, then terminate the conenction");
318                 ctx->ifm_errno = PTS_UNRECOGNIZED_COMMAND;
319                 if (ctx->ifm_strerror != NULL) {
320                     xfree(ctx->ifm_strerror);
321                 }
322                 ctx->ifm_strerror = smalloc_assert("Unknown message type");
323                 rc = writePtsTlv(ctx, STDOUT_FILENO, OPENPTS_ERROR);  // ifm.c
324                 terminate = 1;
325                 break;
326         }  // switch case
327
328         /* free TLV */
329         if (read_tlv != NULL) {
330             freePtsTlv(read_tlv);
331         }
332     }
333
334     freePtsContext(ctx);
335
336     return 0;
337 }
338
339
340 /**
341  * Usage
342  */
343 void usage(void) {
344     fprintf(stderr, NLS(MS_OPENPTS,  OPENPTS_COLLECTOR_USAGE_1, "OpenPTS Collector\n\n"
345                     "Usage: ptsc [options] [command]\n\n"
346                     "Commands: (foreground)\n"
347                     "  -i                    Initialize PTS collector\n"
348                     "  -t                    Self test (attestation)\n"
349                     "  -s                    Startup (selftest + timestamp)\n"
350                     "  -u                    Update the RM\n"
351                     "  -e                    Clear PTS collector\n"));
352 #ifdef CONFIG_AUTO_RM_UPDATE
353     fprintf(stderr, NLS(MS_OPENPTS, OPENPTS_COLLECTOR_USAGE_2,
354                     "  -U                    Update the RM (auto)\n"));
355 #endif
356     fprintf(stderr, NLS(MS_OPENPTS, OPENPTS_COLLECTOR_USAGE_3,
357                     "  -D                    Display the configuration\n"
358                     "  -m                    IF-M mode\n"
359                     "\n"
360                     "Miscellaneous:\n"
361                     "  -h                    Show this help message\n"
362                     "  -v                    Verbose mode. Multiple -v options increase the verbosity.\n"
363                     "\n"
364                     "Options:\n"
365                     "  -c configfile         Set configuration file. defalt is %s\n"
366                     "  -P name=value         Set properties.\n"
367                     "  -R                    Remove RMs\n"
368                     "  -z                    Set the SRK secret to all zeros (20 bytes of zeros)\n"), PTSC_CONFIG_FILE);
369 }
370
371 enum COMMAND {
372     COMMAND_IFM,
373     COMMAND_INIT,
374     COMMAND_STATUS,
375     COMMAND_SELFTEST,
376     COMMAND_UPDATE,
377     COMMAND_STARTUP,
378     COMMAND_CLEAR,
379 #ifdef CONFIG_AUTO_RM_UPDATE
380     COMMAND_AUTO_UPDATE,
381 #endif
382 };
383
384 /**
385  * name=value
386  */
387 OPENPTS_PROPERTY *getPropertyFromArg(char *arg) {
388     char *name;
389     char *value;
390     char * eq;
391     OPENPTS_PROPERTY *prop;
392
393     if ((eq = strstr(arg, "=")) != NULL) {
394         /* remove CR */
395         *eq = 0;
396         name = arg;
397         value = eq + 1;
398
399         prop = newProperty(name, value);
400         return prop;
401     } else {
402         ERROR("bad property %s\n", arg);
403         return NULL;
404     }
405 }
406
407 #ifdef AIX
408 #define LOCK_DIR    "/var/ptsc/"
409 #else  // LINUX
410 #define LOCK_DIR    "/var/lib/openpts/"
411 #endif
412 #define LOCK_FILE    LOCK_DIR "ptsc.lock"
413
414 void ptsc_lock(void) {
415     int fd, oldmask, oldgrp = 0;
416     struct group *grpent = NULL;
417     struct group grp;
418     char *buf = NULL;
419     size_t buf_len;
420     int rc;
421
422     if (geteuid() == 0) {
423         // grpent = getgrnam(PTSC_GROUP_NAME);
424         // if (grpent) {
425         //     oldgrp = getegid();
426         //     setegid(grpent->gr_gid);
427         // }
428         buf_len = sysconf(_SC_GETGR_R_SIZE_MAX);
429         if (buf_len < 0) {
430             buf_len = 4096;
431         }
432         buf = xmalloc(buf_len);
433         if (buf == NULL) {
434             ERROR("no memory");
435             exit(1);
436         }
437
438         rc = getgrnam_r(PTSC_GROUP_NAME, &grp, buf, buf_len, &grpent);
439         if (rc != 0) {
440             // TODO
441             exit(1);
442         }
443         if (grpent == NULL) {
444             // TODO
445             exit(1);
446         }
447         oldgrp = getegid();
448         setegid(grp.gr_gid);
449     }
450
451     oldmask = umask(0);
452     if (mkdir(LOCK_DIR, 0775) < 0 && errno != EEXIST) {
453         perror(LOCK_DIR);
454         exit(1);
455     }
456     if (grpent) {
457         chmod(LOCK_DIR, 02775);
458         setegid(oldgrp);
459     }
460     fd = open(LOCK_FILE, O_RDWR | O_CREAT | O_TRUNC, 0660);
461     if (fd < 0) {
462         perror(LOCK_FILE);
463         exit(1);
464     }
465     umask(oldmask);
466     if (lockf(fd, F_LOCK, 0) < 0) {
467         perror(LOCK_FILE);
468         exit(1);
469     }
470
471     if (buf != NULL) xfree(buf);
472 }
473
474 static int preparePriv() {
475     int rc = PTS_SUCCESS;
476     struct group *ptsc_grp = NULL;
477     struct group grp;
478     char *buf = NULL;
479     size_t buf_len;
480
481 #if 0
482     /* check UID */
483     if ((ptscd_pwd = getpwnam_r(PTSCD_USER_NAME)) == NULL) {
484         ERROR("Looking up for user %s", PTSCD_USER_NAME);
485         return PTS_FATAL;
486     }
487 #endif
488
489     /* check GID */
490     // ptsc_grp = getgrnam(PTSC_GROUP_NAME);  // TODO use getgrnam_r
491     // if (ptsc_grp == NULL) {
492     //     ERROR("Looking up for group (name=%s) fail", PTSC_GROUP_NAME);
493     //     return PTS_FATAL;
494     // }
495     buf_len = sysconf(_SC_GETGR_R_SIZE_MAX);
496     if (buf_len < 0) {
497         buf_len = 4096;
498     }
499     buf = xmalloc(buf_len);
500     if (buf == NULL) {
501         ERROR("no memory");
502         return PTS_FATAL;
503     }
504
505     rc = getgrnam_r(PTSC_GROUP_NAME, &grp, buf, buf_len, &ptsc_grp);
506     if (rc != 0) {
507         ERROR("getgrnam_r");
508         rc = PTS_FATAL;
509         goto free;
510     }
511     if (ptsc_grp == NULL) {
512         ERROR("ptsc_grp == NULL");
513         rc = PTS_FATAL;
514         goto free;
515     }
516
517     /* set GID */
518     // rc = setgid(ptsc_grp->gr_gid);
519     rc = setgid(grp.gr_gid);
520     if (rc < 0) {
521         // TODO do not need for IF-M access (read only)
522         ERROR("Switching group (gid=%d) fail. %s\n", grp.gr_gid, strerror(errno));
523         // TODO 20110927 FAIL
524         rc = PTS_FATAL;
525         goto free;
526     }
527
528 #if 0
529     if (setuid(ptscd_pwd->pw_uid) == -1) {
530         ERROR("Switching to user %s", PTSCD_USER_NAME);
531         return PTS_FATAL;
532     }
533 #endif
534
535     /*  */
536   free:
537     if (buf != NULL) xfree(buf);
538
539     return rc;
540 }
541
542 /**
543  * dir group => PTSC_GROUP_NAME
544  *
545  * flag 0:read, 1:read/write
546  */
547 static int chmodDir(char *dirpath, int flag) {
548     int rc = PTS_SUCCESS;
549     struct group *ptsc_grp;
550     struct group grp;
551     char *buf = NULL;
552     size_t buf_len;
553
554
555     /* check GID */
556     // ptsc_grp = getgrnam(PTSC_GROUP_NAME);  // TODO use getgrnam_r
557     // if (ptsc_grp == NULL) {
558     //     ERROR("Looking up for group %s", PTSC_GROUP_NAME);
559     //     return PTS_FATAL;
560     // }
561     buf_len = sysconf(_SC_GETGR_R_SIZE_MAX);
562     if (buf_len < 0) {
563         buf_len = 4096;
564     }
565     buf = xmalloc(buf_len);
566     if (buf == NULL) {
567         ERROR("no memory");
568         return PTS_FATAL;
569     }
570
571     rc = getgrnam_r(PTSC_GROUP_NAME, &grp, buf, buf_len, &ptsc_grp);
572     if (rc != 0) {
573         ERROR("getgrnam_r");
574         rc = PTS_FATAL;
575         goto free;
576     }
577     if (ptsc_grp == NULL) {
578         ERROR("ptsc_grp == NULL");
579         rc = PTS_FATAL;
580         goto free;
581     }
582
583     /* chgep */
584     rc = chown(
585             dirpath,
586             -1,
587             ptsc_grp->gr_gid);
588     if (rc <0) {
589         rc = PTS_FATAL;
590         goto free;
591     }
592
593     if (flag == 0) {
594         rc = chmod(
595                 dirpath,
596                 S_IRUSR | S_IWUSR | S_IXUSR |
597                 S_IRGRP | S_IXGRP);
598         if (rc <0) {
599             rc = PTS_FATAL;
600             goto free;
601         }
602     } else {  // write
603         rc = chmod(
604                 dirpath,
605                 S_IRUSR | S_IWUSR | S_IXUSR |
606                 S_IRGRP | S_IWGRP | S_IXGRP);
607         if (rc <0) {
608             rc = PTS_FATAL;
609             goto free;
610         }
611     }
612
613   free:
614     if (buf != NULL) xfree(buf);
615     return rc;
616 }
617
618
619 /**
620  * Main
621  */
622 int main(int argc, char *argv[]) {
623     int rc;
624     OPENPTS_CONFIG *conf = NULL;
625     char *config_filename = NULL;
626     int command = COMMAND_STATUS;
627     int c;
628     int force = 0;
629 #ifdef CONFIG_AUTO_RM_UPDATE
630     int remove = 0;
631 #endif
632     // extern int logLocation;
633     // void setLogLocation(int ll);
634
635     /* properties by cmdline  */
636     OPENPTS_PROPERTY *prop;
637
638 #if 0
639     initCatalog();
640
641     // TODO chgrp
642     rc = preparePriv();
643     if (rc != PTS_SUCCESS) {
644         ERROR("preparePriv fail\n");
645     }
646
647     conf = newPtsConfig();
648     if (conf == NULL) {
649         ERROR("internal error\n");  // TODO(munetoh)
650         return -1;
651     }
652 #endif
653
654     /* command option */
655     while ((c = getopt(argc, argv, "ic:uUefDtsmvP:Rzh")) != EOF) {
656         switch (c) {
657         case 'i':
658             command = COMMAND_INIT;
659             break;
660         case 'u':
661             command = COMMAND_UPDATE;
662             break;
663         case 'U':
664 #ifdef CONFIG_AUTO_RM_UPDATE
665             command = COMMAND_AUTO_UPDATE;
666 #endif
667             break;
668         case 'D':
669             command = COMMAND_STATUS;
670             break;
671         case 't':
672             command = COMMAND_SELFTEST;
673             break;
674         case 's':
675             command = COMMAND_STARTUP;
676             break;
677         case 'e':
678             command = COMMAND_CLEAR;
679             break;
680         case 'f':
681             force = 1;
682             break;
683         case 'm':
684             command = COMMAND_IFM;
685             /* not everything should go to syslog - on some systems
686                this could go to a log file - let default behaviour
687                in log.c decide this */
688             // setLogLocation(OPENPTS_LOG_SYSLOG, NULL);
689             // OK setLogLocation(OPENPTS_LOG_CONSOLE, NULL);  // OK
690             // setLogLocation(OPENPTS_LOG_FILE, "/var/log/ptsc.log");  // OK call this before any out
691             break;
692         case 'c':
693             config_filename = optarg;
694             break;
695         case 'v':
696             incVerbosity();
697             break;
698         case 'R':
699 #ifdef CONFIG_AUTO_RM_UPDATE
700             remove = 1;
701 #endif
702             break;
703         case 'z':
704             conf->srk_password_mode = 1;
705             break;
706         case 'P':
707             prop = getPropertyFromArg(optarg);
708             if (prop != NULL) {
709                 if (start == NULL) {
710                     start = prop;
711                     end = prop;
712                     prop->next = NULL;
713                 } else {
714                     end->next = prop;
715                     end = prop;
716                     prop->next = NULL;
717                 }
718                 prop_num++;
719             } else {
720                 usage();
721                 return -1;
722             }
723             break;
724         case 'h':
725             /* help */
726         default:
727             usage();
728             return -1;
729             break;
730         }
731     }
732     argc -= optind;
733     argv += optind;
734
735     if (command == COMMAND_IFM) {
736         setLogLocation(OPENPTS_LOG_SYSLOG, NULL);
737     } else {
738         setLogLocation(OPENPTS_LOG_CONSOLE, NULL);
739     }
740
741     initCatalog();
742
743     // TODO chgrp
744     rc = preparePriv();
745     if (rc != PTS_SUCCESS) {
746         ERROR("preparePriv fail\n");
747     }
748
749     conf = newPtsConfig();
750     if (conf == NULL) {
751         ERROR("internal error\n");  // TODO(munetoh)
752         return -1;
753     }
754
755
756     /* DEBUG level, 1,2,3 */
757 #ifdef OPENPTS_DEBUG
758     setDebugFlags(DEBUG_FLAG | DEBUG_FSM_FLAG | DEBUG_IFM_FLAG);
759 #else
760     /* set the DEBUG level, 1,2,3 */
761     if (getVerbosity() > 2) {
762         setDebugFlags(DEBUG_FLAG | DEBUG_IFM_FLAG | DEBUG_FSM_FLAG | DEBUG_CAL_FLAG );
763     } else if (getVerbosity() > 1) {
764         setDebugFlags(DEBUG_FLAG | DEBUG_IFM_FLAG);
765     } else if (getVerbosity() > 0) {
766         setDebugFlags(DEBUG_FLAG);
767     }
768 #endif
769
770     DEBUG("VERBOSITY (%d), DEBUG mode (0x%x)\n", getVerbosity(), getDebugFlags());
771
772     ptsc_lock();
773
774     /* load config */
775     if (config_filename == NULL) {
776         // this goto stdout and bad with "-m"
777         // VERBOSE(1, NLS(MS_OPENPTS, OPENPTS_COLLECTOR_CONFIG_FILE, "Config file: %s\n"), PTSC_CONFIG_FILE);
778         rc = readPtsConfig(conf, PTSC_CONFIG_FILE);
779         if (rc != PTS_SUCCESS) {
780             goto free;
781         }
782     } else {
783         // VERBOSE(1, NLS(MS_OPENPTS, OPENPTS_COLLECTOR_CONFIG_FILE, "Config file: %s\n"), config_filename);
784         rc = readPtsConfig(conf, config_filename);
785         if (rc != PTS_SUCCESS) {
786             goto free;
787         }
788     }
789
790     /* check dir */
791     // TODO root only
792
793     /* only do this when needed */
794     if (command != COMMAND_STATUS) {
795         /* check IR dir */
796         if (checkDir(conf->ir_dir) != PTS_SUCCESS) {
797             rc = makeDir(conf->ir_dir);
798             if (rc != PTS_SUCCESS) {
799                 ERROR("Can not create the dir to store IR, %s\n", conf->ir_dir);
800                 goto free;
801             }
802             rc = chmodDir(conf->ir_dir, 1);
803             if (rc != PTS_SUCCESS) {
804                 ERROR("Can not create the dir to store IR, %s\n", conf->ir_dir);
805                 goto free;
806             }
807         }
808     }
809
810     /* initialize the PTS collector */
811     if (command == COMMAND_INIT) {
812         VERBOSE(1, NLS(MS_OPENPTS, OPENPTS_COLLECTOR_INIT_RM, "Initializing Reference Manifest\n"));
813         rc = init(conf, prop_num, start, end);
814         /* Exit */
815         goto free;
816     }
817
818     /* Clear the PTS collector */
819     if (command == COMMAND_CLEAR) {
820         VERBOSE(1, NLS(MS_OPENPTS, OPENPTS_COLLECTOR_CLEAR, "Clear PTS collector\n"));
821         rc = clear(conf, force);
822         /* Exit */
823         goto free;
824     }
825
826
827     /* RM UUID */
828     if (conf->rm_uuid == NULL) {
829         ERROR("rm_uuid is missing");
830         /* Exit */
831         goto free;
832     } else {
833         rc = readOpenptsUuidFile(conf->rm_uuid);
834         if (rc != PTS_SUCCESS) {
835             OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_FAILED_READ_RM_UUID,
836                    "Failed to read the Reference Manifest UUID file '%s':\n"
837                    "Please ensure on the target that:\n"
838                    "  * ptsc has been initialized (ptsc -i)\n"
839                    "  * you (uid==%d) are allowed to attest (i.e. a member of group '%s')"),
840                    conf->rm_uuid->filename, getuid(), PTSC_GROUP_NAME);
841             goto free;
842         } else {
843             DEBUG("conf->str_rm_uuid         : %s\n", conf->rm_uuid->str);
844         }
845     }
846
847     /* NEWRM UUID */
848     if (conf->newrm_uuid == NULL) {
849         ERROR("newrm_uuid is missing.");
850         /* Exit */
851         goto free;
852     } else {
853         rc = readOpenptsUuidFile(conf->newrm_uuid);
854         if (rc != PTS_SUCCESS) {
855             DEBUG("conf->str_newrm_uuid      : missing (file:%s)\n", conf->newrm_uuid->filename);
856             // goto free;
857         } else {
858             DEBUG("conf->str_newrm_uuid      : %s (for next boot)\n", conf->newrm_uuid->str);
859         }
860     }
861
862     /* load RSA PUB key */
863     // TODO single key => multiple keys?
864 #ifdef CONFIG_NO_TSS
865     TODO("CONFIG_NO_TSS, no TPM_PUBKEY\n");
866     conf->pubkey_length = 0;
867     conf->pubkey = NULL;
868 #else
869     /* only do this when needed */
870     if (command != COMMAND_STATUS) {
871         /* get PUBKEY */
872         rc = getTssPubKey(
873                 conf->uuid->uuid,
874                 conf->aik_storage_type,  // TSS_PS_TYPE_SYSTEM,
875                 conf->srk_password_mode,
876                 conf->tpm_resetdalock,
877                 conf->aik_storage_filename,  // NULL,
878                 conf->aik_auth_type,
879                 &conf->pubkey_length,
880                 &conf->pubkey);
881         if (rc != TSS_SUCCESS) {
882             ERROR("getTssPubKey() fail rc=0x%x srk password mode=%d, key =%s\n",
883                 rc, conf->srk_password_mode, conf->uuid->str);
884             OUTPUT(NLS(MS_OPENPTS, OPENPTS_TPM_TSS_COMMS_FAILURE,
885                 "TSS communications failure. Is tcsd running?\n"));
886             goto free;
887         }
888     }
889 #endif
890
891     /* run */
892     switch (command) {
893 #ifdef CONFIG_AUTO_RM_UPDATE
894         case COMMAND_AUTO_UPDATE:
895             /* update by command, but HUP is better */
896             VERBOSE(1, "Updating Reference Manifest\n");
897             //addDebugFlags(DEBUG_CAL_FLAG);
898             /* update RMs */
899             rc = update(conf, prop_num, start, end, remove);
900             if (rc != PTS_SUCCESS) {
901                 ERROR("update was fail\n");
902             }
903             break;
904 #endif
905         case COMMAND_STATUS:
906             rc = printCollectorStatus(conf);
907             break;
908         case COMMAND_SELFTEST:
909             rc = selftest(conf, prop_num, start, end);
910             if (rc == OPENPTS_SELFTEST_SUCCESS) {
911                 OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_SUCCESS, "selftest - OK\n"));
912             } else if (rc == OPENPTS_SELFTEST_RENEWED) {
913                 OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_RENEWED, "selftest - Renewed\n"));
914             } else if (rc == OPENPTS_SELFTEST_FALLBACK) {
915                 OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_FALLBACK, "selftest - fallback\n"));
916             } else if (rc == OPENPTS_SELFTEST_FAILED) {
917                 OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_FAIL, "selftest - fail\n"));
918             } else {
919                 ERROR("TBD\n");
920             }
921             break;
922         case COMMAND_STARTUP:
923             rc = selftest(conf, prop_num, start, end);
924             if (rc == OPENPTS_SELFTEST_SUCCESS) {
925                 OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_SUCCESS, "selftest - OK\n"));
926                 /* timestamp */
927                 extendEvCollectorStart(conf);  // collector.c
928             } else if (rc == OPENPTS_SELFTEST_RENEWED) {
929                 OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_RENEWED, "selftest - Renewed\n"));
930                 /* timestamp */
931                 extendEvCollectorStart(conf);
932             } else if (rc == OPENPTS_SELFTEST_FALLBACK) {
933                 OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_FALLBACK, "selftest - fallback\n"));
934                 /* timestamp */
935                 extendEvCollectorStart(conf);
936             } else if (rc == OPENPTS_SELFTEST_FAILED) {
937                 OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_FAIL, "selftest - fail\n"));
938                 if (conf->autoupdate == 1) {
939                     ERROR("selftest failed, trying to generate a new manifest\n");
940                     /* del RM_UUID */
941                     conf->rm_uuid->status = OPENPTS_UUID_FILENAME_ONLY;
942                     if (conf->rm_uuid->uuid != NULL) freeUuid(conf->rm_uuid->uuid);
943                     if (conf->rm_uuid->str != NULL) xfree(conf->rm_uuid->str);
944                     if (conf->rm_uuid->time != NULL) xfree(conf->rm_uuid->time);
945                     conf->rm_uuid->uuid = NULL;
946                     conf->rm_uuid->str = NULL;
947                     conf->rm_uuid->time = NULL;
948
949                     /* gen new RM_UUID and RM */
950                     rc = newrm(conf, prop_num, start, end);
951                     if (rc != PTS_SUCCESS) {
952                         OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_UPDATE_RM_FAIL,
953                             "Failed to generated a reference manifest\n"));
954                         goto free;
955                     }
956                     rc = selftest(conf, prop_num, start, end);
957                     if (rc == OPENPTS_SELFTEST_SUCCESS) {
958                         OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_SUCCESS, "selftest - OK\n"));
959                         OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_UPDATE_RM_SUCCESS,
960                             "Successfully generated the reference manifest\n"));
961                     } else if (rc == OPENPTS_SELFTEST_RENEWED) {
962                         OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_RENEWED, "selftest - Renewed\n"));
963                     } else {
964                         ERROR("TBD\n");
965                     }
966                 } else {
967                     OUTPUT(NLS(MS_OPENPTS, OPENPTS_COLLECTOR_UPDATE_RM_WONT,
968                         "selftest failed, keeping existing manifests as requested by configuration\n"));
969                 }
970             } else {
971                 ERROR("TBD\n");
972             }
973             break;
974         case COMMAND_UPDATE:
975             /* del RM_UUID */
976             conf->rm_uuid->status = OPENPTS_UUID_FILENAME_ONLY;
977             if (conf->rm_uuid->uuid != NULL) freeUuid(conf->rm_uuid->uuid);
978             if (conf->rm_uuid->str != NULL) xfree(conf->rm_uuid->str);
979             if (conf->rm_uuid->time != NULL) xfree(conf->rm_uuid->time);
980             conf->rm_uuid->uuid = NULL;
981             conf->rm_uuid->str = NULL;
982             conf->rm_uuid->time = NULL;
983
984             /* gen new RM_UUID and RM */
985             rc = newrm(conf, prop_num, start, end);
986             if (rc != PTS_SUCCESS) {
987                 ERROR("newrm() fail\n");
988                 goto free;
989             }
990
991             /* self test */
992             rc = selftest(conf, prop_num, start, end);
993             if (rc == OPENPTS_SELFTEST_SUCCESS) {
994                 VERBOSE(1, NLS(MS_OPENPTS, OPENPTS_COLLECTOR_UPDATE_RM_SUCCESS,
995                     "Successfully generated the reference manifest\n"));
996             } else if (rc == OPENPTS_SELFTEST_RENEWED) {
997                 TODO("TBD\n");
998             } else {
999                 TODO("TBD\n");
1000             }
1001             break;
1002         case COMMAND_IFM:
1003             /* run colelctor IF-M */
1004             rc = collector2(conf);
1005             break;
1006         default:
1007             ERROR("bad command\n");
1008             break;
1009     }
1010
1011  free:
1012     freePtsConfig(conf);
1013
1014     return rc;
1015 }