2 * This file is part of the OpenPTS project.
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.
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)
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.
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.
26 * \brief TCG TNC IF-IMV v1.2 R8
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
29 * cleanup 2011-08-22 SM
31 * http://www.trustedcomputinggroup.org/resources/tnc_ifimv_specification
32 * http://www.trustedcomputinggroup.org/files/static_page_files/646808C3-1D09-3519-AD2E60765779A42A/TNC_IFIMV_v1_2_r8.pdf
36 * 1 IMC <- IMV capability
37 * 2 IMC -> IMV capability
39 * 3 IMC <- IMV DH-nonce param req
40 * 4 IMC -> IMV DH-nonce param res
41 * 5 IMC <- IMV DH-nonce done
44 * 7 IMC <- IMV template RIMM req
46 * 9 IMC <- IMV template IR req
57 BYTE* getPtsTlvMessage(OPENPTS_CONTEXT *ctx, int type, int *len);
60 static TNC_IMVID imv_id = -1;
61 static int initialized = 0;
63 static OPENPTS_CONFIG *conf = NULL;
64 static OPENPTS_CONTEXT *ctx = NULL;
65 static int result = OPENPTS_RESULT_UNKNOWN;
68 // int verbose = DEBUG_IFM_FLAG;
69 // int verbose = DEBUG_FLAG | DEBUG_IFM_FLAG;
71 static TNC_Result sendMessage(
72 /*in*/ TNC_IMVID imvID,
73 /*in*/ TNC_ConnectionID connectionID,
74 /*in*/ TNC_BufferReference message,
75 /*in*/ TNC_UInt32 messageLength,
76 /*in*/ TNC_MessageType messageType);
78 static TNC_Result provideRecommendation(
79 /*in*/ TNC_IMVID imvID,
80 /*in*/ TNC_ConnectionID connectionID,
81 /*in*/ TNC_IMV_Action_Recommendation recommendation,
82 /*in*/ TNC_IMV_Evaluation_Result evaluation);
84 static TNC_Result setAttribute(
85 /*in*/ TNC_IMVID imvID,
86 /*in*/ TNC_ConnectionID connectionID,
87 /*in*/ TNC_AttributeID attributeID,
88 /*in*/ TNC_UInt32 bufferLength,
89 /*out*/ TNC_BufferReference buffer);
92 static TNC_TNCS_ReportMessageTypesPointer reportMessageTypesPtr;
93 static TNC_TNCS_RequestHandshakeRetryPointer requestHandshakeRetryPtr;
94 static TNC_TNCS_ProvideRecommendationPointer provideRecommendationPtr;
95 static TNC_TNCS_GetAttributePointer getAttributePtr;
96 static TNC_TNCS_SetAttributePointer setAttributePtr;
97 static TNC_TNCS_SendMessagePointer sendMessagePtr;
100 /* List of receive message types */
101 // static TNC_MessageType messageTypes[] = {
102 // TNCMESSAGENUM(TNC_VENDORID_TCG, TNC_SUBTYPE_ANY), // generic
103 // TNCMESSAGENUM(VENDORID, 0),
104 // TNCMESSAGENUM(VENDORID, 2),
105 // TNCMESSAGENUM(VENDORID, 4),
106 // TNCMESSAGENUM(VENDORID, 6),
107 // TNCMESSAGENUM(VENDORID, 8),
108 // TNCMESSAGENUM(VENDORID, 10),
110 static TNC_MessageType messageTypes[] = {
111 ((TNC_VENDORID_PA_TNC << 8) | TNC_VENDORID_PA_TNC), // TNC generic (Error)
112 // ((TNC_VENDORID_TCG_PEN << 8) | TNC_SUBTYPE_TCG_PTS), // PTS generic
113 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS) // OpenPTS
122 * TNC_IMV_Initialize (MANDATORY)
124 * The TNC Server calls this function to initialize the IMV and agree on the API version number to
125 * be used. It also supplies the IMV ID, an IMV identifier that the IMV must use when calling TNC
126 * Server callback functions. All IMVs MUST implement this function.
128 * The TNC Server MUST NOT call any other IF-IMV API functions for an IMV until it has
129 * successfully completed a call to TNC_IMV_Initialize(). Once a call to this function has
130 * completed successfully, this function MUST NOT be called again for a particular IMV-TNCS pair
131 * until a call to TNC_IMV_Terminate has completed successfully.
133 * The TNC Server MUST set minVersion to the minimum IF-IMV API version number that it
134 * supports and MUST set maxVersion to the maximum API version number that it supports. The
135 * TNC Server also MUST set pOutActualVersion so that the IMV can use it as an output
136 * parameter to provide the actual API version number to be used. With the C binding, this would
137 * involve setting pOutActualVersion to point to a suitable storage location.
139 * The IMV MUST check these to determine whether there is an API version number that it supports
140 * in this range. If not, the IMV MUST return TNC_RESULT_NO_COMMON_VERSION. Otherwise, the
141 * IMV SHOULD select a mutually supported version number, store that version number at
142 * pOutActualVersion, and initialize the IMV. If the initialization completes successfully, the IMV
143 * SHOULD return TNC_RESULT_SUCCESS. Otherwise, it SHOULD return another result code.
145 * If an IMV determines that pOutActualVersion is not set properly to allow the IMV to use it as
146 * an output parameter, the IMV SHOULD return TNC_RESULT_INVALID_PARAMETER. With the C
147 * binding, this might involve checking for a NULL pointer. IMVs are not required to make this check
148 * and there is no guarantee that IMVs will be able to perform it adequately (since it is often
149 * impossible or very hard to detect invalid pointers).
151 * @praram imvID - IMV ID assigned by TNCS
152 * @praram minVersion - Minimum API version supported by TNCS
153 * @praram maxVersion - Maximum API version supported by TNCS
154 * @praram pOutActualVersion - Mutually supported API version number
156 TNC_IMV_API TNC_Result TNC_IMV_Initialize(
157 /*in*/ TNC_IMVID imvID,
158 /*in*/ TNC_Version minVersion,
159 /*in*/ TNC_Version maxVersion,
160 /*in*/ TNC_Version *pOutActualVersion) {
162 DEBUG("TNC_IMV_Initialize() - imvID=%d, minVersion=%d, maxVersion=%d\n",
163 (int)imvID, (int)minVersion, (int)maxVersion);
167 ERROR("Not initialized");
168 return TNC_RESULT_ALREADY_INITIALIZED;
171 /* Only support version 1 */
172 if ((minVersion < TNC_IFIMV_VERSION_1 ) ||
173 (maxVersion > TNC_IFIMV_VERSION_1)) {
174 ERROR("TNC_RESULT_NO_COMMON_VERSION\n");
175 return TNC_RESULT_NO_COMMON_VERSION;
178 if (!pOutActualVersion) {
179 ERROR("TNC_RESULT_INVALID_PARAMETER\n");
180 return TNC_RESULT_INVALID_PARAMETER;
183 *pOutActualVersion = TNC_IFIMV_VERSION_1;
187 conf = newPtsConfig();
189 ERROR("Can not allocate OPENPTS_CONFIG\n");
190 rc = TNC_RESULT_FATAL;
194 ctx = newPtsContext(conf);
196 ERROR("Can not allocate OPENPTS_CONTEXT\n");
197 rc = TNC_RESULT_FATAL;
201 /* configure PTS Verifier (System wide) */
202 rc = readPtsConfig(conf, PTSV_CONFIG_FILE);
203 if (rc != PTS_SUCCESS) {
204 ERROR("read config file, '%s' was failed - abort\n",
206 rc = TNC_RESULT_FATAL;
209 DEBUG_IFM("config file : %s\n", PTSV_CONFIG_FILE);
211 /* check the IMV settings */
213 if (conf->uuid->status == OPENPTS_UUID_FILENAME_ONLY) {
214 /* 1st use?, create new UUID */
215 rc = genOpenptsUuid(conf->uuid);
216 if (rc != PTS_SUCCESS) {
217 ERROR("generation of UUID was failed\n");
218 rc = TNC_RESULT_FATAL;
221 /* save to the file */
222 rc = writeOpenptsUuidFile(conf->uuid, 1);
223 if (rc != PTS_SUCCESS) {
224 ERROR("Creation of UUID file, %s was failed\n",
225 conf->uuid->filename);
226 rc = TNC_RESULT_FATAL;
229 DEBUG_IFM("conf->uuid->filename : %s (new UUID)\n", conf->uuid->filename);
230 DEBUG_IFM("conf->uuid->str : %s (new UUID)\n", conf->uuid->str);
232 DEBUG_IFM("conf->uuid->filename : %s\n", conf->uuid->filename);
233 DEBUG_IFM("conf->uuid->str : %s\n", conf->uuid->str);
237 DEBUG_IFM("conf->enrollment : 0x%x (none:%x, cred:%x, auto:%x)\n",
239 IMV_ENROLLMENT_NONE, IMV_ENROLLMENT_CREDENTIAL, IMV_ENROLLMENT_AUTO);
241 DEBUG_IFM("conf->config_dir : %s\n",
248 DEBUG_IFM("V imvID=%d - TNC_IMV_Initialize\n", (int) imvID);
250 return TNC_RESULT_SUCCESS;
253 if (ctx != NULL) freePtsContext(ctx);
255 if (conf != NULL) freePtsConfig(conf);
263 * TNC_IMV_NotifyConnectionChange (OPTIONAL)
265 TNC_IMV_API TNC_Result TNC_IMV_NotifyConnectionChange(
266 /*in*/ TNC_IMVID imvID,
267 /*in*/ TNC_ConnectionID connectionID,
268 /*in*/ TNC_ConnectionState newState) {
269 DEBUG("TNC_IMV_NotifyConnectionChange\n");
272 ERROR("Not initialized");
273 return TNC_RESULT_NOT_INITIALIZED;
277 ERROR("imvID != imv_id");
278 return TNC_RESULT_INVALID_PARAMETER;
280 DEBUG_IFM("V imvID=%d, connectionID=%d - TNC_IMV_NotifyConnectionChange\n",
281 (int)imvID, (int)connectionID);
283 return TNC_RESULT_SUCCESS;
288 * TNC_IMV_ReceiveMessage (OPTIONAL)
290 * The TNC Server calls this function to deliver a message to the IMV. The message is contained in
291 * the buffer referenced by message and contains the number of octets (bytes) indicated by
292 * messageLength. The type of the message is indicated by messageType. The message MUST be
293 * from an IMC (or a TNCC or other party acting as an IMC).
295 * The IMV SHOULD send any IMC-IMV messages it wants to send as soon as possible after this
296 * function is called and then return from this function to indicate that it is finished sending
297 * messages in response to this message.
299 * As with all IMV functions, the IMV SHOULD NOT wait a long time before returning from
300 * TNC_IMV_ReceiveMessage. To do otherwise would risk delaying the handshake indefinitely. A
301 * long delay might frustrate users or exceed network timeouts (PDP, PEP or otherwise).
303 * The IMV should implement this function if it wants to receive messages. Most IMVs will do so,
304 * since they will base their IMV Action Recommendations on measurements received from the
305 * IMC. However, some IMVs may base their IMV Action Recommendations on other data such as
306 * reports from intrusion detection systems or scanners. Those IMVs need not implement this
309 * The IMV MUST NOT ever modify the buffer contents and MUST NOT access the buffer after
310 * TNC_IMV_ReceiveMessage has returned. If the IMV wants to retain the message, it should
311 * copy it before returning from TNC_IMV_ReceiveMessage.
313 * In the imvID parameter, the TNCS MUST pass the IMV ID value provided to
314 * TNC_IMV_Initialize. In the connectionID parameter, the TNCS MUST pass a valid
315 * network connection ID. In the message parameter, the TNCS MUST pass a reference to a buffer
316 * containing the message being delivered to the IMV. In the messageLength parameter, the
317 * TNCS MUST pass the number of octets in the message. If the value of the messageLength
318 * parameter is zero (0), the message parameter may be NULL with platform bindings that have
319 * such a value. In the messageType parameter, the TNCS MUST pass the type of the message.
321 * This value MUST match one of the TNC_MessageType values previously supplied by the IMV to
322 * the TNCS in the IMV’s most recent call to TNC_TNCS_ReportMessageTypes. IMVs MAY check
323 * these parameters to make sure they are valid and return an error if not, but IMVs are not required
324 * to make these checks.
326 * @praram imvID - IMV ID assigned by TNCS
327 * @praram connectionID - Network connection ID on which message was received
328 * @praram message - Reference to buffer containing message
329 * @praram messageLength - Number of octets in message
330 * @praram messageType - Message type of message
336 TNC_IMV_API TNC_Result TNC_IMV_ReceiveMessage(
337 /*in*/ TNC_IMVID imvID,
338 /*in*/ TNC_ConnectionID connectionID,
339 /*in*/ TNC_BufferReference messageBuffer,
340 /*in*/ TNC_UInt32 messageLength,
341 /*in*/ TNC_MessageType messageType) {
342 PTS_IF_M_Attribute *read_tlv;
349 OPENPTS_IF_M_Capability *cap;
352 OPENPTS_CONFIG *target_conf;
357 int verifierHandleCapability(
358 OPENPTS_CONTEXT *ctx,
361 OPENPTS_IF_M_Capability *cap);
363 int verifierHandleRimmSet(
364 OPENPTS_CONTEXT *ctx,
367 int verifierHandleIR(
368 OPENPTS_CONTEXT *ctx,
374 DEBUG("TNC_IMV_ReceiveMessage msg[%d] type=0x%x\n",
375 messageLength, (int)messageType);
378 ERROR("Not initialized");
379 return TNC_RESULT_NOT_INITIALIZED;
382 DEBUG_IFM("[C->V] imvID=%d, connectionID=%d, type=0x%x, msg[%d]\n",
383 (int)imvID, (int)connectionID, (int)messageType, (int)messageLength);
388 if (messageType == ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS)) {
390 read_tlv = (PTS_IF_M_Attribute*)messageBuffer; // NBO
392 if (read_tlv == NULL) {
394 return TNC_RESULT_FATAL;
398 vid = read_tlv->vid[0] << 16;
399 vid += read_tlv->vid[1] << 8;
400 vid += read_tlv->vid[2];
401 if (vid != TNC_VENDORID_OPENPTS) {
402 ERROR("read_tlv->vid = 0x%X (!= 0x%X)",
403 vid, TNC_VENDORID_OPENPTS);
404 return TNC_RESULT_FATAL;
407 /* type and length */
408 type = ntohl(read_tlv->type);
409 length = ntohl(read_tlv->length);
410 value = &messageBuffer[12];
413 if (messageLength != (TNC_UInt32) (12 + length)) {
414 ERROR("Bad message %d != %d\n",
415 messageLength, 12 + length);
416 return TNC_RESULT_FATAL;
419 DEBUG_IFM("[C->V] vid=%X, type=%08X, length=%d\n", vid, type, length);
423 case OPENPTS_CAPABILITIES:
424 /* Check Collector */
425 DEBUG_IFM("[C->V] OPENPTS_CAPABILITIES[%d]\n", 12 + length);
426 if (ctx->tnc_state != TNC_STATE_START) {
427 /* Bad message order */
428 ERROR("Bad message order state=%d != %d, type=%08x",
429 ctx->tnc_state, TNC_STATE_START, type);
430 return TNC_RESULT_FATAL;
434 cap = (OPENPTS_IF_M_Capability *) value;
436 rc = verifierHandleCapability(ctx, conf->config_dir, NULL, cap);
438 if (rc == PTS_NOT_INITIALIZED) {
439 if (conf->enrollment == IMV_ENROLLMENT_AUTO) {
440 /* enroll with this collector */
441 DEBUG_IFM("Auto Mode, Trust 1st connection -> start enrollment!!!"
442 " #######################################\n");
444 if (ctx->target_conf == NULL) {
445 ctx->target_conf = newPtsConfig();
447 target_conf = ctx->target_conf;
449 /* intialize the target_conf */
450 target_conf->uuid = ctx->collector_uuid;
451 ctx->collector_uuid = NULL;
452 target_conf->rm_uuid = ctx->rm_uuid;
455 target_conf->config_dir =
456 getFullpathName(conf->config_dir, target_conf->uuid->str);
457 target_conf->config_file =
458 getFullpathName(target_conf->config_dir, "target.conf");
459 target_conf->uuid->filename =
460 getFullpathName(target_conf->config_dir, "uuid");
461 target_conf->rm_basedir =
462 getFullpathName(target_conf->config_dir, target_conf->rm_uuid->str);
464 target_conf->ir_filename =
465 getFullpathName(target_conf->config_dir, "./ir.xml");
466 target_conf->prop_filename =
467 getFullpathName(target_conf->config_dir, "./vr.properties");
468 target_conf->policy_filename =
469 getFullpathName(target_conf->config_dir, "./policy.conf");
472 target_conf->aide_database_filename =
473 getFullpathName(target_conf->config_dir, "aide.db.gz");
474 target_conf->aide_ignorelist_filename =
475 getFullpathName(target_conf->config_dir, "aide.ignore");
477 target_conf->aide_sqlite_filename =
478 getFullpathName(target_conf->config_dir, "aide.sqlite.db");
483 rc = makeDir(target_conf->config_dir);
486 DEBUG("conf dir : %s\n", target_conf->config_dir);
487 DEBUG("rm dir : %s\n", target_conf->rm_basedir);
488 DEBUG("AIDE DB : %s\n", target_conf->aide_database_filename);
490 DEBUG("AIDE SQLite DB : %s\n", target_conf->aide_sqlite_filename);
495 /* verify and create policy */
496 /* then allow the 1st connection */
498 } else if (conf->enrollment == IMV_ENROLLMENT_CREDENTIAL) {
502 ERROR("Collector is not initialized yet\n");
505 } else if (rc != PTS_SUCCESS) {
509 ctx->tnc_state = TNC_STATE_CAP;
513 /* send IMV's capability to IMC */
514 msg = getPtsTlvMessage(ctx, OPENPTS_CAPABILITIES, &len);
518 (TNC_BufferReference)msg,
520 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
522 DEBUG_IFM("[C<-V] OPENPTS_CAPABILITIES[%d]\n", len);
525 if (enrollment == 1) {
526 /* start enrollment */
527 ctx->tnc_state = TNC_STATE_KEY_REQ;
528 msg = getPtsTlvMessage(ctx, REQUEST_TPM_PUBKEY, &len);
532 (TNC_BufferReference)msg,
534 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
536 DEBUG_IFM("[C<-V] REQUEST_TPM_PUBKEY[%d]\n", len);
538 /*start verify, send NONCE and IR REQ*/
539 /* Next : Send NONCE */
540 ctx->nonce->nonce_length = 20;
541 ctx->nonce->nonce = xmalloc_assert(20);
542 rc = getRandom(ctx->nonce->nonce, 20);
543 if (rc != PTS_SUCCESS) {
544 ERROR("getRandom() fail\n");
547 ctx->tnc_state = TNC_STATE_NONCE;
548 msg = getPtsTlvMessage(ctx, NONCE, &len);
552 (TNC_BufferReference)msg,
554 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
556 DEBUG_IFM("[C<-V] NONCE[%d]\n", len);
559 ctx->tnc_state = TNC_STATE_IR;
560 msg = getPtsTlvMessage(ctx, REQUEST_INTEGRITY_REPORT, &len);
564 (TNC_BufferReference)msg,
566 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
568 DEBUG_IFM("[C<-V] REQUEST_INTEGRITY_REPORT[%d]\n", len);
573 DEBUG_IFM("[C->V] TPM_PUBKEY[%d]\n", 12 + length);
574 // TODO check the state
576 if (ctx->target_conf == NULL) {
577 ERROR("Bad sequence\n");
579 /* PUBKEY -> target_conf */
580 ctx->target_conf->pubkey_length = length;
581 ctx->target_conf->pubkey = xmalloc(ctx->target_conf->pubkey_length);
582 if (ctx->target_conf->pubkey == NULL) {
583 return TNC_RESULT_FATAL;
587 ctx->target_conf->pubkey,
588 value, // NG read_tlv->value
589 ctx->target_conf->pubkey_length);
590 ctx->tnc_state = TNC_STATE_KEY;
593 /* Next: send RM REQ - continue enrollment */
594 ctx->tnc_state = TNC_STATE_RM_REQ;
595 msg = getPtsTlvMessage(ctx, REQUEST_RIMM_SET, &len);
599 (TNC_BufferReference)msg,
601 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
603 DEBUG_IFM("[C<-V] REQUEST_RIMM_SET[%d]\n", len);
608 DEBUG_IFM("[C->V] RIMM_SET[%d]\n", 12 + length);
610 /* save to the file, UUID/UUID/rmN.xml*/
611 rc = verifierHandleRimmSet(ctx, value);
612 if (rc != PTS_SUCCESS) {
613 ERROR("verifierHandleRimmSet() fail\n");
614 return TNC_RESULT_FATAL;
617 /* save target conf */
620 ctx->target_conf->uuid->uuid,
621 ctx->target_conf->config_file); // ctx.c
623 /* Next : Send NONCE */
624 ctx->nonce->nonce_length = 20;
625 ctx->nonce->nonce = xmalloc_assert(20);
626 rc = getRandom(ctx->nonce->nonce, 20);
627 if (rc != PTS_SUCCESS) {
628 ERROR("getRandom() fail\n");
631 ctx->tnc_state = TNC_STATE_NONCE_ENROLL;
632 msg = getPtsTlvMessage(ctx, NONCE, &len);
636 (TNC_BufferReference)msg,
638 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
640 DEBUG_IFM("[C<-V] NONCE[%d]\n", len);
643 ctx->tnc_state = TNC_STATE_IR_ENROLL;
644 msg = getPtsTlvMessage(ctx, REQUEST_INTEGRITY_REPORT, &len);
648 (TNC_BufferReference)msg,
650 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
652 DEBUG_IFM("[C<-V] REQUEST_INTEGRITY_REPORT[%d]\n", len);
656 case INTEGRITY_REPORT:
657 if (ctx->tnc_state == TNC_STATE_IR_ENROLL) {
658 /* Enrollment, create default policy */
659 DEBUG_IFM("[C->V] INTEGRITY_REPORT[%d] (Enrollment)\n", 12 + length);
660 mode = OPENPTS_UPDATE_MODE;
661 } else if (ctx->tnc_state == TNC_STATE_IR) {
663 DEBUG_IFM("[C->V] INTEGRITY_REPORT[%d]\n", 12 + length);
664 mode = OPENPTS_VERIFY_MODE;
672 rc = verifierHandleIR(ctx, length, value, mode, &result);
673 if (rc != PTS_SUCCESS) {
674 ERROR("verifierHandleIR() fail rc = %d\n", rc);
675 // 25 PTS_INVALID_SNAPSHOT?
676 // return TNC_RESULT_FATAL;
678 // DEBUG("result = %d => recomandation\n", result);
682 ERROR("The corrector returns ERROR message");
684 result = OPENPTS_RESULT_UNKNOWN;
686 return TNC_RESULT_FATAL;
688 ERROR("Unknown type %08X", type);
689 result = OPENPTS_RESULT_UNKNOWN;
693 } else if (messageType == ((TNC_VENDORID_TCG_PEN << 8) | TNC_SUBTYPE_TCG_PTS)) {
696 return TNC_RESULT_FATAL;
698 ERROR("bad msg from collector");
699 return TNC_RESULT_FATAL;
702 return TNC_RESULT_SUCCESS;
709 * TNC_IMV_SolicitRecommendation (MANDATORY)
711 * The TNC Server calls this function at the end of an Integrity Check Handshake (after all IMC-IMV
712 * messages have been delivered) to solicit recommendations from IMVs that have not yet provided
713 * a recommendation. The TNCS SHOULD NOT call this method for an IMV and a particular
714 * connection if that IMV has already called TNC_TNCS_ProvideRecommendation with that
715 * connection since the TNCS last called TNC_IMV_NotifyConnectionChange for that IMV and
716 * connection. If an IMV is not able to provide a recommendation at this time, it SHOULD call
717 * TNC_TNCS_ProvideRecommendation with the recommendation parameter set to
718 * TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION. If an IMV returns from this
719 * function without calling TNC_TNCS_ProvideRecommendation, the TNCS MAY consider the
720 * IMV’s Action Recommendation to be
721 * TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION. The TNCS MAY take other
722 * actions, such as logging this IMV behavior, which is erroneous.
724 * All IMVs MUST implement this function.
726 * Note that a TNCC or TNCS MAY cut off IMC-IMV communications at any time for any reason,
727 * including limited support for long conversations in underlying protocols, user or administrator
728 * intervention, or policy. If this happens, the TNCS will return TNC_RESULT_ILLEGAL_OPERATION
729 * from TNC_TNCS_SendMessage and call TNC_IMV_SolicitRecommendation to elicit IMV
730 * Action Recommendations based on the data they have gathered so far.
731 * In the imvID parameter, the TNCS MUST pass the IMV ID value provided to
733 * TNC_IMV_Initialize. In the connectionID parameter, the TNCS MUST pass a valid
734 * network connection ID. IMVs MAY check these values to make sure they are valid and return an
735 * error if not, but IMVs are not required to make these checks.
737 * @param imvID - IMV ID assigned by TNCS
738 * @param connectionID - Network connection ID for which a recommendation is requested
741 TNC_IMV_API TNC_Result TNC_IMV_SolicitRecommendation(
742 /*in*/ TNC_IMVID imvID,
743 /*in*/ TNC_ConnectionID connectionID) {
744 TNC_BufferReference lang = (TNC_BufferReference) "en"; // BYTE*
745 TNC_BufferReference str;
746 TNC_IMV_Action_Recommendation recommendation;
747 TNC_IMV_Evaluation_Result evaluation;
750 DEBUG("TNC_IMV_SolicitRecommendation\n");
753 ERROR("Not initialized");
754 return TNC_RESULT_NOT_INITIALIZED;
757 if (imvID != imv_id) {
759 return TNC_RESULT_INVALID_PARAMETER;
763 if (result == OPENPTS_RESULT_VALID) {
764 DEBUG("verifier() result : VALID");
765 str = (TNC_BufferReference)"valid";
766 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
767 evaluation = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
768 } else if (result == OPENPTS_RESULT_UNVERIFIED) {
769 DEBUG("verifier() result : UNVERIFIED");
770 str = (TNC_BufferReference)"unverified";
771 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
772 evaluation = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
773 } else if (result == OPENPTS_RESULT_INVALID) {
774 TODO("verifier() result : INVALID");
775 str = (TNC_BufferReference)"invalid";
776 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
777 evaluation = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
778 } else if (result == OPENPTS_RESULT_UNKNOWN) {
779 DEBUG("verifier() result : UNKNOWN");
780 str = (TNC_BufferReference)"unknown";
781 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
782 evaluation = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
783 } else if (result == OPENPTS_RESULT_IGNORE) {
784 DEBUG("verifier() result : IGNORE");
785 str = (TNC_BufferReference)"ignore";
786 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
787 evaluation = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
789 DEBUG("verifier() result : ERROR");
790 str = (TNC_BufferReference)"error";
791 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
792 evaluation = TNC_IMV_EVALUATION_RESULT_ERROR;
796 // Just for testing, provide a recommendation:
797 // IMVs may tell the TNCS about languages and resons
798 len = strlen((char*)lang) + 1;
802 TNC_ATTRIBUTEID_REASON_LANGUAGE,
806 len = strlen((char*)str) + 1;
810 TNC_ATTRIBUTEID_REASON_STRING,
814 DEBUG_IFM("[C<-V] imvID=%d, connectionID=%d - TNC_IMV_SolicitRecommendation\n",
815 (int)imvID, (int)connectionID);
817 return provideRecommendation(
828 * TNC_IMV_BatchEnding (OPTIONAL)
830 * The TNC Server calls this function to notify IMVs that all IMC messages received in a batch have
831 * been delivered and this is the IMV’s last chance to send a message in the batch of IMV
832 * messages currently being collected.. An IMV MAY implement this function if it wants to perform
833 * some actions after all the IMC messages received during a batch have been delivered (using
834 * TNC_IMV_ReceiveMessage). For instance, if an IMV has not received any messages from an
835 * IMC it may conclude that its IMC is not installed on the endpoint and may decide to call
836 * TNC_TNCS_ProvideRecommendation with the recommendation parameter set to
837 * TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS.
839 * An IMV MAY call TNC_TNCS_SendMessage from this function. As with all IMV functions, the IMV
840 * SHOULD NOT wait a long time before returning from TNC_IMV_BatchEnding. To do otherwise
841 * would risk delaying the handshake indefinitely. A long delay might frustrate users or exceed
842 * network timeouts (PDP, PEP or otherwise).
844 * In the imvID parameter, the TNCS MUST pass the IMV ID value provided to
845 * TNC_IMV_Initialize. In the connectionID parameter, the TNCS MUST pass a valid
846 * network connection ID. IMVs MAY check these values to make sure they are valid and return an
847 * error if not, but IMVs are not required to make these checks.
850 TNC_IMV_API TNC_Result TNC_IMV_BatchEnding(
851 /*in*/ TNC_IMVID imvID,
852 /*in*/ TNC_ConnectionID connectionID) {
853 DEBUG("TNC_IMV_BatchEnding\n");
856 ERROR("Not initialized");
857 return TNC_RESULT_NOT_INITIALIZED;
860 if (imvID != imv_id) {
861 ERROR("imvID != imv_id");
862 return TNC_RESULT_INVALID_PARAMETER;
865 DEBUG_IFM("V imvID=%d, connectionID=%d - TNC_IMV_BatchEnding\n",
866 (int)imvID, (int)connectionID);
868 return TNC_RESULT_SUCCESS;
873 * TNC_IMV_Terminate (OPTIONAL)
875 TNC_IMV_API TNC_Result TNC_IMV_Terminate(
876 /*in*/ TNC_IMVID imvID) {
877 DEBUG("TNC_IMV_Terminate\n");
880 ERROR("Not initialized");
881 return TNC_RESULT_NOT_INITIALIZED;
884 if (imvID != imv_id) {
886 return TNC_RESULT_INVALID_PARAMETER;
895 DEBUG_IFM("V imvID=%d - TNC_IMV_Terminate\n",
898 return TNC_RESULT_SUCCESS;
902 /* TNC Server Functions */
905 * Call TNC_TNCS_ReportMessageTypes (MANDATORY) in the TNCS
907 static TNC_Result reportMessageTypes(
908 /*in*/ TNC_IMVID imvID,
909 /*in*/ TNC_MessageTypeList supportedTypes,
910 /*in*/ TNC_UInt32 typeCount) {
911 DEBUG("reportMessageTypes %d\n", (int)imvID);
913 if (!reportMessageTypesPtr) {
915 return TNC_RESULT_FATAL;
918 DEBUG_IFM("[C<-V] imvID=%d - reportMessageTypes\n",
921 // Call the function in the TMCC
922 return (*reportMessageTypesPtr)(imvID, supportedTypes, typeCount);
927 * Call TNC_TNCS_SendMessage (MANDATORY) in the TNCS
929 static TNC_Result sendMessage(
930 /*in*/ TNC_IMVID imvID,
931 /*in*/ TNC_ConnectionID connectionID,
932 /*in*/ TNC_BufferReference message,
933 /*in*/ TNC_UInt32 messageLength,
934 /*in*/ TNC_MessageType messageType) {
935 DEBUG("sendMessage\n");
937 if (!sendMessagePtr) {
939 return TNC_RESULT_FATAL;
942 DEBUG_IFM("[C<-V] imvID=%d, connectionID=%d, type=0x%x, msg[%d]\n",
943 (int)imvID, (int)connectionID, (int)messageType, (int)messageLength);
945 // Call the function in the TMCC
946 return (*sendMessagePtr)(
956 // imv.c:343: error: ‘requestHandshakeRetry’ defined but not used
959 * Call TNC_TNCS_RequestHandshakeRetry (MANDATORY) in the TNCS
961 static TNC_Result requestHandshakeRetry(
962 /*in*/ TNC_IMVID imvID,
963 /*in*/ TNC_ConnectionID connectionID,
964 /*in*/ TNC_RetryReason reason) {
965 DEBUG("requestHandshakeRetry\n");
967 if (!requestHandshakeRetryPtr)
968 return TNC_RESULT_FATAL;
970 // Call the function in the TMCC
971 return (*requestHandshakeRetryPtr)(imvID, connectionID, reason);
977 * Call TNC_TNCS_ProvideRecommendation (MANDATORY) in the TNCS
979 static TNC_Result provideRecommendation(
980 /*in*/ TNC_IMVID imvID,
981 /*in*/ TNC_ConnectionID connectionID,
982 /*in*/ TNC_IMV_Action_Recommendation recommendation,
983 /*in*/ TNC_IMV_Evaluation_Result evaluation) {
984 DEBUG("provideRecommendation\n");
986 if (!provideRecommendationPtr) {
988 return TNC_RESULT_FATAL;
991 DEBUG_IFM("[C<-V] imvID=%d, connectionID=%d - provideRecommendation\n",
992 (int)imvID, (int)connectionID);
994 return (*provideRecommendationPtr)(
1003 // imv.c:381: error: ‘getAttribute’ defined but not used
1005 * Call TNC_TNCS_GetAttribute (OPTIONAL) in the TNCS
1007 static TNC_Result getAttribute(
1008 /*in*/ TNC_IMVID imvID,
1009 /*in*/ TNC_ConnectionID connectionID,
1010 /*in*/ TNC_AttributeID attributeID,
1011 /*in*/ TNC_UInt32 bufferLength,
1012 /*out*/ TNC_BufferReference buffer,
1013 /*out*/ TNC_UInt32 *pOutValueLength) {
1014 DEBUG("getAttribute\n");
1016 if (!getAttributePtr)
1017 return TNC_RESULT_FATAL;
1019 return (*getAttributePtr)(
1030 * Call TNC_TNCS_SetAttribute (OPTIONAL) in the TNCS
1032 static TNC_Result setAttribute(
1033 /*in*/ TNC_IMVID imvID,
1034 /*in*/ TNC_ConnectionID connectionID,
1035 /*in*/ TNC_AttributeID attributeID,
1036 /*in*/ TNC_UInt32 bufferLength,
1037 /*out*/ TNC_BufferReference buffer) {
1038 DEBUG("setAttribute\n");
1040 if (!setAttributePtr) {
1041 ERROR("null input");
1042 return TNC_RESULT_FATAL;
1045 DEBUG_IFM("[C<-V] imvID=%d, connectionID=%d - setAttribute\n",
1046 (int)imvID, (int)connectionID);
1048 return (*setAttributePtr)(
1057 /* Platform-Specific IMV Functions */
1060 * TNC_IMV_ProvideBindFunction
1062 TNC_IMV_API TNC_Result TNC_IMV_ProvideBindFunction(
1063 /*in*/ TNC_IMVID imvID,
1064 /*in*/ TNC_TNCS_BindFunctionPointer bindFunction) {
1065 DEBUG("TNC_IMV_ProvideBindFunction\n");
1068 ERROR("Not initialized");
1069 return TNC_RESULT_NOT_INITIALIZED;
1072 if (imvID != imv_id) {
1074 return TNC_RESULT_INVALID_PARAMETER;
1078 // Look for required functions in the parent TMCC
1079 if ((*bindFunction)(imvID, "TNC_TNCS_ReportMessageTypes",
1080 (void**)&reportMessageTypesPtr) !=
1081 TNC_RESULT_SUCCESS) {
1083 return TNC_RESULT_FATAL;
1085 if ((*bindFunction)(imvID, "TNC_TNCS_RequestHandshakeRetry",
1086 (void**)&requestHandshakeRetryPtr) !=
1087 TNC_RESULT_SUCCESS) {
1089 return TNC_RESULT_FATAL;
1091 if ((*bindFunction)(imvID, "TNC_TNCS_ProvideRecommendation",
1092 (void**)&provideRecommendationPtr) !=
1093 TNC_RESULT_SUCCESS) {
1095 return TNC_RESULT_FATAL;
1097 if ((*bindFunction)(imvID, "TNC_TNCS_SendMessage",
1098 (void**)&sendMessagePtr) !=
1099 TNC_RESULT_SUCCESS) {
1101 return TNC_RESULT_FATAL;
1103 if ((*bindFunction)(imvID, "TNC_TNCS_GetAttribute",
1104 (void**)&getAttributePtr) !=
1105 TNC_RESULT_SUCCESS) {
1106 // TODO(munetoh) optional
1108 return TNC_RESULT_FATAL;
1110 if ((*bindFunction)(imvID, "TNC_TNCS_SetAttribute",
1111 (void**)&setAttributePtr) !=
1112 TNC_RESULT_SUCCESS) {
1113 // TODO(munetoh) optional
1115 return TNC_RESULT_FATAL;
1119 if (reportMessageTypes(
1120 imvID, messageTypes,
1121 sizeof(messageTypes) / sizeof(TNC_MessageType)) ==
1122 TNC_RESULT_SUCCESS) {
1123 return TNC_RESULT_SUCCESS;
1126 return TNC_RESULT_FATAL;