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 2012-01-05 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
56 BYTE* getPtsTlvMessage(OPENPTS_CONTEXT *ctx, int type, int *len);
59 static TNC_IMVID imv_id = -1;
60 static int initialized = 0;
62 static OPENPTS_CONFIG *conf = NULL;
63 static OPENPTS_CONTEXT *ctx = NULL;
64 static int result = OPENPTS_RESULT_UNKNOWN;
66 static TNC_Result sendMessage(
67 /*in*/ TNC_IMVID imvID,
68 /*in*/ TNC_ConnectionID connectionID,
69 /*in*/ TNC_BufferReference message,
70 /*in*/ TNC_UInt32 messageLength,
71 /*in*/ TNC_MessageType messageType);
73 static TNC_Result provideRecommendation(
74 /*in*/ TNC_IMVID imvID,
75 /*in*/ TNC_ConnectionID connectionID,
76 /*in*/ TNC_IMV_Action_Recommendation recommendation,
77 /*in*/ TNC_IMV_Evaluation_Result evaluation);
79 static TNC_Result setAttribute(
80 /*in*/ TNC_IMVID imvID,
81 /*in*/ TNC_ConnectionID connectionID,
82 /*in*/ TNC_AttributeID attributeID,
83 /*in*/ TNC_UInt32 bufferLength,
84 /*out*/ TNC_BufferReference buffer);
87 static TNC_TNCS_ReportMessageTypesPointer reportMessageTypesPtr;
88 static TNC_TNCS_RequestHandshakeRetryPointer requestHandshakeRetryPtr;
89 static TNC_TNCS_ProvideRecommendationPointer provideRecommendationPtr;
90 static TNC_TNCS_GetAttributePointer getAttributePtr;
91 static TNC_TNCS_SetAttributePointer setAttributePtr;
92 static TNC_TNCS_SendMessagePointer sendMessagePtr;
95 static TNC_MessageType messageTypes[] = {
96 ((TNC_VENDORID_PA_TNC << 8) | TNC_VENDORID_PA_TNC), // TNC generic (Error)
97 // ((TNC_VENDORID_TCG_PEN << 8) | TNC_SUBTYPE_TCG_PTS), // PTS generic
98 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS) // OpenPTS
102 /* IMV Functions -------------------------------------------------------------*/
107 * TNC_IMV_Initialize (MANDATORY)
109 * The TNC Server calls this function to initialize the IMV and agree on the API version number to
110 * be used. It also supplies the IMV ID, an IMV identifier that the IMV must use when calling TNC
111 * Server callback functions. All IMVs MUST implement this function.
113 * The TNC Server MUST NOT call any other IF-IMV API functions for an IMV until it has
114 * successfully completed a call to TNC_IMV_Initialize(). Once a call to this function has
115 * completed successfully, this function MUST NOT be called again for a particular IMV-TNCS pair
116 * until a call to TNC_IMV_Terminate has completed successfully.
118 * The TNC Server MUST set minVersion to the minimum IF-IMV API version number that it
119 * supports and MUST set maxVersion to the maximum API version number that it supports. The
120 * TNC Server also MUST set pOutActualVersion so that the IMV can use it as an output
121 * parameter to provide the actual API version number to be used. With the C binding, this would
122 * involve setting pOutActualVersion to point to a suitable storage location.
124 * The IMV MUST check these to determine whether there is an API version number that it supports
125 * in this range. If not, the IMV MUST return TNC_RESULT_NO_COMMON_VERSION. Otherwise, the
126 * IMV SHOULD select a mutually supported version number, store that version number at
127 * pOutActualVersion, and initialize the IMV. If the initialization completes successfully, the IMV
128 * SHOULD return TNC_RESULT_SUCCESS. Otherwise, it SHOULD return another result code.
130 * If an IMV determines that pOutActualVersion is not set properly to allow the IMV to use it as
131 * an output parameter, the IMV SHOULD return TNC_RESULT_INVALID_PARAMETER. With the C
132 * binding, this might involve checking for a NULL pointer. IMVs are not required to make this check
133 * and there is no guarantee that IMVs will be able to perform it adequately (since it is often
134 * impossible or very hard to detect invalid pointers).
136 * @praram imvID - IMV ID assigned by TNCS
137 * @praram minVersion - Minimum API version supported by TNCS
138 * @praram maxVersion - Maximum API version supported by TNCS
139 * @praram pOutActualVersion - Mutually supported API version number
141 TNC_IMV_API TNC_Result TNC_IMV_Initialize(
142 /*in*/ TNC_IMVID imvID,
143 /*in*/ TNC_Version minVersion,
144 /*in*/ TNC_Version maxVersion,
145 /*in*/ TNC_Version *pOutActualVersion) {
147 DEBUG("TNC_IMV_Initialize() - imvID=%d, minVersion=%d, maxVersion=%d\n",
148 (int)imvID, (int)minVersion, (int)maxVersion);
152 LOG(LOG_ERR, "Not initialized");
153 return TNC_RESULT_ALREADY_INITIALIZED;
156 /* Only support version 1 */
157 if ((minVersion < TNC_IFIMV_VERSION_1 ) ||
158 (maxVersion > TNC_IFIMV_VERSION_1)) {
159 LOG(LOG_ERR, "TNC_RESULT_NO_COMMON_VERSION\n");
160 return TNC_RESULT_NO_COMMON_VERSION;
163 if (!pOutActualVersion) {
164 LOG(LOG_ERR, "TNC_RESULT_INVALID_PARAMETER\n");
165 return TNC_RESULT_INVALID_PARAMETER;
168 *pOutActualVersion = TNC_IFIMV_VERSION_1;
172 conf = newPtsConfig();
174 LOG(LOG_ERR, "Can not allocate OPENPTS_CONFIG\n");
175 rc = TNC_RESULT_FATAL;
179 ctx = newPtsContext(conf);
181 LOG(LOG_ERR, "Can not allocate OPENPTS_CONTEXT\n");
182 rc = TNC_RESULT_FATAL;
186 /* configure PTS Verifier (System wide) */
187 rc = readPtsConfig(conf, PTSV_CONFIG_FILE);
188 if (rc != PTS_SUCCESS) {
189 LOG(LOG_ERR, "read config file, '%s' was failed - abort\n",
191 rc = TNC_RESULT_FATAL;
194 DEBUG_IFM("config file : %s\n", PTSV_CONFIG_FILE);
196 /* check the IMV settings */
198 if (conf->uuid->status == OPENPTS_UUID_FILENAME_ONLY) {
199 /* 1st use?, create new UUID */
200 rc = genOpenptsUuid(conf->uuid);
201 if (rc != PTS_SUCCESS) {
202 LOG(LOG_ERR, "generation of UUID was failed\n");
203 rc = TNC_RESULT_FATAL;
206 /* save to the file */
207 rc = writeOpenptsUuidFile(conf->uuid, 1);
208 if (rc != PTS_SUCCESS) {
209 LOG(LOG_ERR, "Creation of UUID file, %s was failed\n",
210 conf->uuid->filename);
211 rc = TNC_RESULT_FATAL;
214 DEBUG_IFM("conf->uuid->filename : %s (new UUID)\n", conf->uuid->filename);
215 DEBUG_IFM("conf->uuid->str : %s (new UUID)\n", conf->uuid->str);
217 DEBUG_IFM("conf->uuid->filename : %s\n", conf->uuid->filename);
218 DEBUG_IFM("conf->uuid->str : %s\n", conf->uuid->str);
222 DEBUG_IFM("conf->enrollment : 0x%x (none:%x, cred:%x, auto:%x)\n",
224 IMV_ENROLLMENT_NONE, IMV_ENROLLMENT_CREDENTIAL, IMV_ENROLLMENT_AUTO);
226 DEBUG_IFM("conf->config_dir : %s\n",
233 DEBUG_IFM("V imvID=%d - TNC_IMV_Initialize\n", (int) imvID);
235 return TNC_RESULT_SUCCESS;
238 if (ctx != NULL) freePtsContext(ctx);
240 if (conf != NULL) freePtsConfig(conf);
248 * TNC_IMV_NotifyConnectionChange (OPTIONAL)
250 TNC_IMV_API TNC_Result TNC_IMV_NotifyConnectionChange(
251 /*in*/ TNC_IMVID imvID,
252 /*in*/ TNC_ConnectionID connectionID,
253 /*in*/ TNC_ConnectionState newState) {
254 DEBUG("TNC_IMV_NotifyConnectionChange\n");
257 LOG(LOG_ERR, "Not initialized");
258 return TNC_RESULT_NOT_INITIALIZED;
262 LOG(LOG_ERR, "imvID != imv_id");
263 return TNC_RESULT_INVALID_PARAMETER;
265 DEBUG_IFM("V imvID=%d, connectionID=%d - TNC_IMV_NotifyConnectionChange\n",
266 (int)imvID, (int)connectionID);
268 return TNC_RESULT_SUCCESS;
273 * TNC_IMV_ReceiveMessage (OPTIONAL)
275 * The TNC Server calls this function to deliver a message to the IMV. The message is contained in
276 * the buffer referenced by message and contains the number of octets (bytes) indicated by
277 * messageLength. The type of the message is indicated by messageType. The message MUST be
278 * from an IMC (or a TNCC or other party acting as an IMC).
280 * The IMV SHOULD send any IMC-IMV messages it wants to send as soon as possible after this
281 * function is called and then return from this function to indicate that it is finished sending
282 * messages in response to this message.
284 * As with all IMV functions, the IMV SHOULD NOT wait a long time before returning from
285 * TNC_IMV_ReceiveMessage. To do otherwise would risk delaying the handshake indefinitely. A
286 * long delay might frustrate users or exceed network timeouts (PDP, PEP or otherwise).
288 * The IMV should implement this function if it wants to receive messages. Most IMVs will do so,
289 * since they will base their IMV Action Recommendations on measurements received from the
290 * IMC. However, some IMVs may base their IMV Action Recommendations on other data such as
291 * reports from intrusion detection systems or scanners. Those IMVs need not implement this
294 * The IMV MUST NOT ever modify the buffer contents and MUST NOT access the buffer after
295 * TNC_IMV_ReceiveMessage has returned. If the IMV wants to retain the message, it should
296 * copy it before returning from TNC_IMV_ReceiveMessage.
298 * In the imvID parameter, the TNCS MUST pass the IMV ID value provided to
299 * TNC_IMV_Initialize. In the connectionID parameter, the TNCS MUST pass a valid
300 * network connection ID. In the message parameter, the TNCS MUST pass a reference to a buffer
301 * containing the message being delivered to the IMV. In the messageLength parameter, the
302 * TNCS MUST pass the number of octets in the message. If the value of the messageLength
303 * parameter is zero (0), the message parameter may be NULL with platform bindings that have
304 * such a value. In the messageType parameter, the TNCS MUST pass the type of the message.
306 * This value MUST match one of the TNC_MessageType values previously supplied by the IMV to
307 * the TNCS in the IMV’s most recent call to TNC_TNCS_ReportMessageTypes. IMVs MAY check
308 * these parameters to make sure they are valid and return an error if not, but IMVs are not required
309 * to make these checks.
311 * @praram imvID - IMV ID assigned by TNCS
312 * @praram connectionID - Network connection ID on which message was received
313 * @praram message - Reference to buffer containing message
314 * @praram messageLength - Number of octets in message
315 * @praram messageType - Message type of message
321 TNC_IMV_API TNC_Result TNC_IMV_ReceiveMessage(
322 /*in*/ TNC_IMVID imvID,
323 /*in*/ TNC_ConnectionID connectionID,
324 /*in*/ TNC_BufferReference messageBuffer,
325 /*in*/ TNC_UInt32 messageLength,
326 /*in*/ TNC_MessageType messageType) {
327 PTS_IF_M_Attribute *read_tlv;
334 OPENPTS_IF_M_Capability *cap;
337 OPENPTS_CONFIG *target_conf;
342 int verifierHandleCapability(
343 OPENPTS_CONTEXT *ctx,
346 OPENPTS_IF_M_Capability *cap);
348 int verifierHandleRimmSet(
349 OPENPTS_CONTEXT *ctx,
352 int verifierHandleIR(
353 OPENPTS_CONTEXT *ctx,
359 DEBUG("TNC_IMV_ReceiveMessage msg[%d] type=0x%x\n",
360 messageLength, (int)messageType);
363 LOG(LOG_ERR, "Not initialized");
364 return TNC_RESULT_NOT_INITIALIZED;
367 DEBUG_IFM("[C->V] imvID=%d, connectionID=%d, type=0x%x, msg[%d]\n",
368 (int)imvID, (int)connectionID, (int)messageType, (int)messageLength);
373 if (messageType == ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS)) {
375 read_tlv = (PTS_IF_M_Attribute*)messageBuffer; // NBO
377 if (read_tlv == NULL) {
378 LOG(LOG_ERR, "null input");
379 return TNC_RESULT_FATAL;
383 vid = read_tlv->vid[0] << 16;
384 vid += read_tlv->vid[1] << 8;
385 vid += read_tlv->vid[2];
386 if (vid != TNC_VENDORID_OPENPTS) {
387 LOG(LOG_ERR, "read_tlv->vid = 0x%X (!= 0x%X)",
388 vid, TNC_VENDORID_OPENPTS);
389 return TNC_RESULT_FATAL;
392 /* type and length */
393 type = ntohl(read_tlv->type);
394 length = ntohl(read_tlv->length);
395 value = &messageBuffer[12];
398 if (messageLength != (TNC_UInt32) (12 + length)) {
399 LOG(LOG_ERR, "Bad message %d != %d\n",
400 messageLength, 12 + length);
401 return TNC_RESULT_FATAL;
404 DEBUG_IFM("[C->V] vid=%X, type=%08X, length=%d\n", vid, type, length);
408 case OPENPTS_CAPABILITIES:
409 /* Check Collector */
410 DEBUG_IFM("[C->V] OPENPTS_CAPABILITIES[%d]\n", 12 + length);
411 if (ctx->tnc_state != TNC_STATE_START) {
412 /* Bad message order */
413 LOG(LOG_ERR, "Bad message order state=%d != %d, type=%08x",
414 ctx->tnc_state, TNC_STATE_START, type);
415 return TNC_RESULT_FATAL;
419 cap = (OPENPTS_IF_M_Capability *) value;
421 rc = verifierHandleCapability(ctx, conf->config_dir, NULL, cap);
423 if (rc == PTS_NOT_INITIALIZED) {
424 if (conf->enrollment == IMV_ENROLLMENT_AUTO) {
425 /* enroll with this collector */
426 DEBUG_IFM("Auto Mode, Trust 1st connection -> start enrollment!!!"
427 " #######################################\n");
429 if (ctx->target_conf == NULL) {
430 ctx->target_conf = newPtsConfig();
432 target_conf = ctx->target_conf;
434 /* intialize the target_conf */
435 target_conf->uuid = ctx->collector_uuid;
436 ctx->collector_uuid = NULL;
437 target_conf->rm_uuid = ctx->rm_uuid;
440 target_conf->config_dir =
441 getFullpathName(conf->config_dir, target_conf->uuid->str);
442 target_conf->config_file =
443 getFullpathName(target_conf->config_dir, "target.conf");
444 target_conf->uuid->filename =
445 getFullpathName(target_conf->config_dir, "uuid");
446 target_conf->rm_basedir =
447 getFullpathName(target_conf->config_dir, target_conf->rm_uuid->str);
449 target_conf->ir_filename =
450 getFullpathName(target_conf->config_dir, "./ir.xml");
451 target_conf->prop_filename =
452 getFullpathName(target_conf->config_dir, "./vr.properties");
453 target_conf->policy_filename =
454 getFullpathName(target_conf->config_dir, "./policy.conf");
457 target_conf->aide_database_filename =
458 getFullpathName(target_conf->config_dir, "aide.db.gz");
459 target_conf->aide_ignorelist_filename =
460 getFullpathName(target_conf->config_dir, "aide.ignore");
462 target_conf->aide_sqlite_filename =
463 getFullpathName(target_conf->config_dir, "aide.sqlite.db");
468 rc = makeDir(target_conf->config_dir);
471 DEBUG("conf dir : %s\n", target_conf->config_dir);
472 DEBUG("rm dir : %s\n", target_conf->rm_basedir);
473 DEBUG("AIDE DB : %s\n", target_conf->aide_database_filename);
475 DEBUG("AIDE SQLite DB : %s\n", target_conf->aide_sqlite_filename);
480 /* verify and create policy */
481 /* then allow the 1st connection */
483 } else if (conf->enrollment == IMV_ENROLLMENT_CREDENTIAL) {
484 LOG(LOG_TODO, "TBD\n");
487 LOG(LOG_ERR, "Collector is not initialized yet\n");
490 } else if (rc != PTS_SUCCESS) {
494 ctx->tnc_state = TNC_STATE_CAP;
498 /* send IMV's capability to IMC */
499 msg = getPtsTlvMessage(ctx, OPENPTS_CAPABILITIES, &len);
503 (TNC_BufferReference)msg,
505 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
507 DEBUG_IFM("[C<-V] OPENPTS_CAPABILITIES[%d]\n", len);
510 if (enrollment == 1) {
511 /* start enrollment */
512 ctx->tnc_state = TNC_STATE_KEY_REQ;
513 msg = getPtsTlvMessage(ctx, REQUEST_TPM_PUBKEY, &len);
517 (TNC_BufferReference)msg,
519 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
521 DEBUG_IFM("[C<-V] REQUEST_TPM_PUBKEY[%d]\n", len);
523 /*start verify, send NONCE and IR REQ*/
524 /* Next : Send NONCE */
525 ctx->nonce->nonce_length = 20;
526 ctx->nonce->nonce = xmalloc_assert(20);
527 rc = getRandom(ctx->nonce->nonce, 20);
528 if (rc != PTS_SUCCESS) {
529 LOG(LOG_ERR, "getRandom() fail\n");
532 ctx->tnc_state = TNC_STATE_NONCE;
533 msg = getPtsTlvMessage(ctx, NONCE, &len);
537 (TNC_BufferReference)msg,
539 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
541 DEBUG_IFM("[C<-V] NONCE[%d]\n", len);
544 ctx->tnc_state = TNC_STATE_IR;
545 msg = getPtsTlvMessage(ctx, REQUEST_INTEGRITY_REPORT, &len);
549 (TNC_BufferReference)msg,
551 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
553 DEBUG_IFM("[C<-V] REQUEST_INTEGRITY_REPORT[%d]\n", len);
558 DEBUG_IFM("[C->V] TPM_PUBKEY[%d]\n", 12 + length);
559 // TODO check the state
561 if (ctx->target_conf == NULL) {
562 LOG(LOG_ERR, "Bad sequence\n");
564 /* PUBKEY -> target_conf */
565 ctx->target_conf->pubkey_length = length;
566 ctx->target_conf->pubkey = xmalloc(ctx->target_conf->pubkey_length);
567 if (ctx->target_conf->pubkey == NULL) {
568 return TNC_RESULT_FATAL;
572 ctx->target_conf->pubkey,
573 value, // NG read_tlv->value
574 ctx->target_conf->pubkey_length);
575 ctx->tnc_state = TNC_STATE_KEY;
578 /* Next: send RM REQ - continue enrollment */
579 ctx->tnc_state = TNC_STATE_RM_REQ;
580 msg = getPtsTlvMessage(ctx, REQUEST_RIMM_SET, &len);
584 (TNC_BufferReference)msg,
586 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
588 DEBUG_IFM("[C<-V] REQUEST_RIMM_SET[%d]\n", len);
593 DEBUG_IFM("[C->V] RIMM_SET[%d]\n", 12 + length);
595 /* save to the file, UUID/UUID/rmN.xml*/
596 rc = verifierHandleRimmSet(ctx, value);
597 if (rc != PTS_SUCCESS) {
598 LOG(LOG_ERR, "verifierHandleRimmSet() fail\n");
599 return TNC_RESULT_FATAL;
602 /* save target conf */
605 ctx->target_conf->uuid->uuid,
606 ctx->target_conf->config_file); // ctx.c
608 /* Next : Send NONCE */
609 ctx->nonce->nonce_length = 20;
610 ctx->nonce->nonce = xmalloc_assert(20);
611 rc = getRandom(ctx->nonce->nonce, 20);
612 if (rc != PTS_SUCCESS) {
613 LOG(LOG_ERR, "getRandom() fail\n");
616 ctx->tnc_state = TNC_STATE_NONCE_ENROLL;
617 msg = getPtsTlvMessage(ctx, NONCE, &len);
621 (TNC_BufferReference)msg,
623 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
625 DEBUG_IFM("[C<-V] NONCE[%d]\n", len);
628 ctx->tnc_state = TNC_STATE_IR_ENROLL;
629 msg = getPtsTlvMessage(ctx, REQUEST_INTEGRITY_REPORT, &len);
633 (TNC_BufferReference)msg,
635 ((TNC_VENDORID_OPENPTS << 8) | TNC_SUBTYPE_OPENPTS));
637 DEBUG_IFM("[C<-V] REQUEST_INTEGRITY_REPORT[%d]\n", len);
641 case INTEGRITY_REPORT:
642 if (ctx->tnc_state == TNC_STATE_IR_ENROLL) {
643 /* Enrollment, create default policy */
644 DEBUG_IFM("[C->V] INTEGRITY_REPORT[%d] (Enrollment)\n", 12 + length);
645 mode = OPENPTS_UPDATE_MODE;
646 } else if (ctx->tnc_state == TNC_STATE_IR) {
648 DEBUG_IFM("[C->V] INTEGRITY_REPORT[%d]\n", 12 + length);
649 mode = OPENPTS_VERIFY_MODE;
652 LOG(LOG_ERR, "bad state");
657 rc = verifierHandleIR(ctx, length, value, mode, &result);
658 if (rc != PTS_SUCCESS) {
659 LOG(LOG_ERR, "verifierHandleIR() fail rc = %d\n", rc);
660 // 25 PTS_INVALID_SNAPSHOT?
661 // return TNC_RESULT_FATAL;
663 // DEBUG("result = %d => recomandation\n", result);
667 LOG(LOG_ERR, "The corrector returns ERROR message");
669 result = OPENPTS_RESULT_UNKNOWN;
671 return TNC_RESULT_FATAL;
673 LOG(LOG_ERR, "Unknown type %08X", type);
674 result = OPENPTS_RESULT_UNKNOWN;
678 } else if (messageType == ((TNC_VENDORID_TCG_PEN << 8) | TNC_SUBTYPE_TCG_PTS)) {
680 LOG(LOG_ERR, "TBD\n");
681 return TNC_RESULT_FATAL;
683 LOG(LOG_ERR, "bad msg from collector");
684 return TNC_RESULT_FATAL;
687 return TNC_RESULT_SUCCESS;
694 * TNC_IMV_SolicitRecommendation (MANDATORY)
696 * The TNC Server calls this function at the end of an Integrity Check Handshake (after all IMC-IMV
697 * messages have been delivered) to solicit recommendations from IMVs that have not yet provided
698 * a recommendation. The TNCS SHOULD NOT call this method for an IMV and a particular
699 * connection if that IMV has already called TNC_TNCS_ProvideRecommendation with that
700 * connection since the TNCS last called TNC_IMV_NotifyConnectionChange for that IMV and
701 * connection. If an IMV is not able to provide a recommendation at this time, it SHOULD call
702 * TNC_TNCS_ProvideRecommendation with the recommendation parameter set to
703 * TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION. If an IMV returns from this
704 * function without calling TNC_TNCS_ProvideRecommendation, the TNCS MAY consider the
705 * IMV’s Action Recommendation to be
706 * TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION. The TNCS MAY take other
707 * actions, such as logging this IMV behavior, which is erroneous.
709 * All IMVs MUST implement this function.
711 * Note that a TNCC or TNCS MAY cut off IMC-IMV communications at any time for any reason,
712 * including limited support for long conversations in underlying protocols, user or administrator
713 * intervention, or policy. If this happens, the TNCS will return TNC_RESULT_ILLEGAL_OPERATION
714 * from TNC_TNCS_SendMessage and call TNC_IMV_SolicitRecommendation to elicit IMV
715 * Action Recommendations based on the data they have gathered so far.
716 * In the imvID parameter, the TNCS MUST pass the IMV ID value provided to
718 * TNC_IMV_Initialize. In the connectionID parameter, the TNCS MUST pass a valid
719 * network connection ID. IMVs MAY check these values to make sure they are valid and return an
720 * error if not, but IMVs are not required to make these checks.
722 * @param imvID - IMV ID assigned by TNCS
723 * @param connectionID - Network connection ID for which a recommendation is requested
726 TNC_IMV_API TNC_Result TNC_IMV_SolicitRecommendation(
727 /*in*/ TNC_IMVID imvID,
728 /*in*/ TNC_ConnectionID connectionID) {
729 TNC_BufferReference lang = (TNC_BufferReference) "en"; // BYTE*
730 TNC_BufferReference str;
731 TNC_IMV_Action_Recommendation recommendation;
732 TNC_IMV_Evaluation_Result evaluation;
735 DEBUG("TNC_IMV_SolicitRecommendation\n");
738 LOG(LOG_ERR, "Not initialized");
739 return TNC_RESULT_NOT_INITIALIZED;
742 if (imvID != imv_id) {
743 LOG(LOG_ERR, "Bad ID");
744 return TNC_RESULT_INVALID_PARAMETER;
748 if (result == OPENPTS_RESULT_VALID) {
749 DEBUG("verifier() result : VALID");
750 str = (TNC_BufferReference)"valid";
751 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
752 evaluation = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
753 } else if (result == OPENPTS_RESULT_UNVERIFIED) {
754 DEBUG("verifier() result : UNVERIFIED");
755 str = (TNC_BufferReference)"unverified";
756 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
757 evaluation = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
758 } else if (result == OPENPTS_RESULT_INVALID) {
759 LOG(LOG_TODO, "verifier() result : INVALID");
760 str = (TNC_BufferReference)"invalid";
761 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
762 evaluation = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR;
763 } else if (result == OPENPTS_RESULT_UNKNOWN) {
764 DEBUG("verifier() result : UNKNOWN");
765 str = (TNC_BufferReference)"unknown";
766 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
767 evaluation = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
768 } else if (result == OPENPTS_RESULT_IGNORE) {
769 DEBUG("verifier() result : IGNORE");
770 str = (TNC_BufferReference)"ignore";
771 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
772 evaluation = TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
774 DEBUG("verifier() result : ERROR");
775 str = (TNC_BufferReference)"error";
776 recommendation = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
777 evaluation = TNC_IMV_EVALUATION_RESULT_ERROR;
781 // Just for testing, provide a recommendation:
782 // IMVs may tell the TNCS about languages and resons
783 len = strlen((char*)lang) + 1;
787 TNC_ATTRIBUTEID_REASON_LANGUAGE,
791 len = strlen((char*)str) + 1;
795 TNC_ATTRIBUTEID_REASON_STRING,
799 DEBUG_IFM("[C<-V] imvID=%d, connectionID=%d - TNC_IMV_SolicitRecommendation\n",
800 (int)imvID, (int)connectionID);
802 return provideRecommendation(
813 * TNC_IMV_BatchEnding (OPTIONAL)
815 * The TNC Server calls this function to notify IMVs that all IMC messages received in a batch have
816 * been delivered and this is the IMV’s last chance to send a message in the batch of IMV
817 * messages currently being collected.. An IMV MAY implement this function if it wants to perform
818 * some actions after all the IMC messages received during a batch have been delivered (using
819 * TNC_IMV_ReceiveMessage). For instance, if an IMV has not received any messages from an
820 * IMC it may conclude that its IMC is not installed on the endpoint and may decide to call
821 * TNC_TNCS_ProvideRecommendation with the recommendation parameter set to
822 * TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS.
824 * An IMV MAY call TNC_TNCS_SendMessage from this function. As with all IMV functions, the IMV
825 * SHOULD NOT wait a long time before returning from TNC_IMV_BatchEnding. To do otherwise
826 * would risk delaying the handshake indefinitely. A long delay might frustrate users or exceed
827 * network timeouts (PDP, PEP or otherwise).
829 * In the imvID parameter, the TNCS MUST pass the IMV ID value provided to
830 * TNC_IMV_Initialize. In the connectionID parameter, the TNCS MUST pass a valid
831 * network connection ID. IMVs MAY check these values to make sure they are valid and return an
832 * error if not, but IMVs are not required to make these checks.
835 TNC_IMV_API TNC_Result TNC_IMV_BatchEnding(
836 /*in*/ TNC_IMVID imvID,
837 /*in*/ TNC_ConnectionID connectionID) {
838 DEBUG("TNC_IMV_BatchEnding\n");
841 LOG(LOG_ERR, "Not initialized");
842 return TNC_RESULT_NOT_INITIALIZED;
845 if (imvID != imv_id) {
846 LOG(LOG_ERR, "imvID != imv_id");
847 return TNC_RESULT_INVALID_PARAMETER;
850 DEBUG_IFM("V imvID=%d, connectionID=%d - TNC_IMV_BatchEnding\n",
851 (int)imvID, (int)connectionID);
853 return TNC_RESULT_SUCCESS;
858 * TNC_IMV_Terminate (OPTIONAL)
860 TNC_IMV_API TNC_Result TNC_IMV_Terminate(
861 /*in*/ TNC_IMVID imvID) {
862 DEBUG("TNC_IMV_Terminate\n");
865 LOG(LOG_ERR, "Not initialized");
866 return TNC_RESULT_NOT_INITIALIZED;
869 if (imvID != imv_id) {
870 LOG(LOG_ERR, "Bad id");
871 return TNC_RESULT_INVALID_PARAMETER;
880 DEBUG_IFM("V imvID=%d - TNC_IMV_Terminate\n",
883 return TNC_RESULT_SUCCESS;
887 /* TNC Server Functions */
890 * Call TNC_TNCS_ReportMessageTypes (MANDATORY) in the TNCS
892 static TNC_Result reportMessageTypes(
893 /*in*/ TNC_IMVID imvID,
894 /*in*/ TNC_MessageTypeList supportedTypes,
895 /*in*/ TNC_UInt32 typeCount) {
896 DEBUG("reportMessageTypes %d\n", (int)imvID);
898 if (!reportMessageTypesPtr) {
899 LOG(LOG_ERR, "null input");
900 return TNC_RESULT_FATAL;
903 DEBUG_IFM("[C<-V] imvID=%d - reportMessageTypes\n",
906 // Call the function in the TMCC
907 return (*reportMessageTypesPtr)(imvID, supportedTypes, typeCount);
912 * Call TNC_TNCS_SendMessage (MANDATORY) in the TNCS
914 static TNC_Result sendMessage(
915 /*in*/ TNC_IMVID imvID,
916 /*in*/ TNC_ConnectionID connectionID,
917 /*in*/ TNC_BufferReference message,
918 /*in*/ TNC_UInt32 messageLength,
919 /*in*/ TNC_MessageType messageType) {
920 DEBUG("sendMessage\n");
922 if (!sendMessagePtr) {
923 LOG(LOG_ERR, "null input");
924 return TNC_RESULT_FATAL;
927 DEBUG_IFM("[C<-V] imvID=%d, connectionID=%d, type=0x%x, msg[%d]\n",
928 (int)imvID, (int)connectionID, (int)messageType, (int)messageLength);
930 // Call the function in the TMCC
931 return (*sendMessagePtr)(
941 // imv.c:343: error: ‘requestHandshakeRetry’ defined but not used
944 * Call TNC_TNCS_RequestHandshakeRetry (MANDATORY) in the TNCS
946 static TNC_Result requestHandshakeRetry(
947 /*in*/ TNC_IMVID imvID,
948 /*in*/ TNC_ConnectionID connectionID,
949 /*in*/ TNC_RetryReason reason) {
950 DEBUG("requestHandshakeRetry\n");
952 if (!requestHandshakeRetryPtr)
953 return TNC_RESULT_FATAL;
955 // Call the function in the TMCC
956 return (*requestHandshakeRetryPtr)(imvID, connectionID, reason);
962 * Call TNC_TNCS_ProvideRecommendation (MANDATORY) in the TNCS
964 static TNC_Result provideRecommendation(
965 /*in*/ TNC_IMVID imvID,
966 /*in*/ TNC_ConnectionID connectionID,
967 /*in*/ TNC_IMV_Action_Recommendation recommendation,
968 /*in*/ TNC_IMV_Evaluation_Result evaluation) {
969 DEBUG("provideRecommendation\n");
971 if (!provideRecommendationPtr) {
972 LOG(LOG_ERR, "null input");
973 return TNC_RESULT_FATAL;
976 DEBUG_IFM("[C<-V] imvID=%d, connectionID=%d - provideRecommendation\n",
977 (int)imvID, (int)connectionID);
979 return (*provideRecommendationPtr)(
988 // imv.c:381: error: ‘getAttribute’ defined but not used
990 * Call TNC_TNCS_GetAttribute (OPTIONAL) in the TNCS
992 static TNC_Result getAttribute(
993 /*in*/ TNC_IMVID imvID,
994 /*in*/ TNC_ConnectionID connectionID,
995 /*in*/ TNC_AttributeID attributeID,
996 /*in*/ TNC_UInt32 bufferLength,
997 /*out*/ TNC_BufferReference buffer,
998 /*out*/ TNC_UInt32 *pOutValueLength) {
999 DEBUG("getAttribute\n");
1001 if (!getAttributePtr)
1002 return TNC_RESULT_FATAL;
1004 return (*getAttributePtr)(
1015 * Call TNC_TNCS_SetAttribute (OPTIONAL) in the TNCS
1017 static TNC_Result setAttribute(
1018 /*in*/ TNC_IMVID imvID,
1019 /*in*/ TNC_ConnectionID connectionID,
1020 /*in*/ TNC_AttributeID attributeID,
1021 /*in*/ TNC_UInt32 bufferLength,
1022 /*out*/ TNC_BufferReference buffer) {
1023 DEBUG("setAttribute\n");
1025 if (!setAttributePtr) {
1026 LOG(LOG_ERR, "null input");
1027 return TNC_RESULT_FATAL;
1030 DEBUG_IFM("[C<-V] imvID=%d, connectionID=%d - setAttribute\n",
1031 (int)imvID, (int)connectionID);
1033 return (*setAttributePtr)(
1042 /* Platform-Specific IMV Functions */
1045 * TNC_IMV_ProvideBindFunction
1047 TNC_IMV_API TNC_Result TNC_IMV_ProvideBindFunction(
1048 /*in*/ TNC_IMVID imvID,
1049 /*in*/ TNC_TNCS_BindFunctionPointer bindFunction) {
1050 DEBUG("TNC_IMV_ProvideBindFunction\n");
1053 LOG(LOG_ERR, "Not initialized");
1054 return TNC_RESULT_NOT_INITIALIZED;
1057 if (imvID != imv_id) {
1058 LOG(LOG_ERR, "Bad id");
1059 return TNC_RESULT_INVALID_PARAMETER;
1063 // Look for required functions in the parent TMCC
1064 if ((*bindFunction)(imvID, "TNC_TNCS_ReportMessageTypes",
1065 (void**)&reportMessageTypesPtr) !=
1066 TNC_RESULT_SUCCESS) {
1067 LOG(LOG_ERR, "TBD");
1068 return TNC_RESULT_FATAL;
1070 if ((*bindFunction)(imvID, "TNC_TNCS_RequestHandshakeRetry",
1071 (void**)&requestHandshakeRetryPtr) !=
1072 TNC_RESULT_SUCCESS) {
1073 LOG(LOG_ERR, "TBD");
1074 return TNC_RESULT_FATAL;
1076 if ((*bindFunction)(imvID, "TNC_TNCS_ProvideRecommendation",
1077 (void**)&provideRecommendationPtr) !=
1078 TNC_RESULT_SUCCESS) {
1079 LOG(LOG_ERR, "TBD");
1080 return TNC_RESULT_FATAL;
1082 if ((*bindFunction)(imvID, "TNC_TNCS_SendMessage",
1083 (void**)&sendMessagePtr) !=
1084 TNC_RESULT_SUCCESS) {
1085 LOG(LOG_ERR, "TBD");
1086 return TNC_RESULT_FATAL;
1088 if ((*bindFunction)(imvID, "TNC_TNCS_GetAttribute",
1089 (void**)&getAttributePtr) !=
1090 TNC_RESULT_SUCCESS) {
1091 // TODO(munetoh) optional
1092 LOG(LOG_ERR, "TBD");
1093 return TNC_RESULT_FATAL;
1095 if ((*bindFunction)(imvID, "TNC_TNCS_SetAttribute",
1096 (void**)&setAttributePtr) !=
1097 TNC_RESULT_SUCCESS) {
1098 // TODO(munetoh) optional
1099 LOG(LOG_ERR, "TBD");
1100 return TNC_RESULT_FATAL;
1104 if (reportMessageTypes(
1105 imvID, messageTypes,
1106 sizeof(messageTypes) / sizeof(TNC_MessageType)) ==
1107 TNC_RESULT_SUCCESS) {
1108 return TNC_RESULT_SUCCESS;
1110 LOG(LOG_ERR, "TBD");
1111 return TNC_RESULT_FATAL;