e50758f3e09707f13db7ccb258ce22de996436de
[strongswan.git] / src / libimcv / plugins / imc_hcd / imc_hcd.c
1 /*
2 * Copyright (C) 2015 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "imc_hcd_state.h"
17
18 #include <imc/imc_agent.h>
19 #include <imc/imc_msg.h>
20 #include <imc/imc_os_info.h>
21 #include <generic/generic_attr_bool.h>
22 #include <generic/generic_attr_chunk.h>
23 #include <generic/generic_attr_string.h>
24 #include <ietf/ietf_attr.h>
25 #include <ietf/ietf_attr_attr_request.h>
26 #include <pwg/pwg_attr.h>
27 #include <pwg/pwg_attr_vendor_smi_code.h>
28
29 #include <tncif_pa_subtypes.h>
30
31 #include <pen/pen.h>
32 #include <utils/debug.h>
33
34 /* IMC definitions */
35
36 static const char imc_name[] = "HCD";
37
38 static pen_type_t msg_types[] = {
39 { PEN_PWG, PA_SUBTYPE_PWG_HCD_SYSTEM },
40 { PEN_PWG, PA_SUBTYPE_PWG_HCD_CONSOLE },
41 { PEN_PWG, PA_SUBTYPE_PWG_HCD_MARKER },
42 { PEN_PWG, PA_SUBTYPE_PWG_HCD_FINISHER },
43 { PEN_PWG, PA_SUBTYPE_PWG_HCD_INTERFACE },
44 { PEN_PWG, PA_SUBTYPE_PWG_HCD_SCANNER }
45 };
46
47 static imc_agent_t *imc_hcd;
48 static imc_os_info_t *os;
49
50 typedef struct quadruple_t quadruple_t;
51
52 struct quadruple_t {
53 char *section;
54 pwg_attr_t name_attr;
55 pwg_attr_t patches_attr;
56 pwg_attr_t string_version_attr;
57 pwg_attr_t version_attr;
58 };
59
60 static quadruple_t quadruples[] = {
61 { "firmware",
62 PWG_HCD_FIRMWARE_NAME, PWG_HCD_FIRMWARE_PATCHES,
63 PWG_HCD_FIRMWARE_STRING_VERSION, PWG_HCD_FIRMWARE_VERSION },
64 { "resident_application",
65 PWG_HCD_RESIDENT_APP_NAME, PWG_HCD_RESIDENT_APP_PATCHES,
66 PWG_HCD_RESIDENT_APP_STRING_VERSION, PWG_HCD_RESIDENT_APP_VERSION },
67 { "user_application",
68 PWG_HCD_USER_APP_NAME, PWG_HCD_USER_APP_PATCHES,
69 PWG_HCD_USER_APP_STRING_VERSION, PWG_HCD_USER_APP_VERSION }
70 };
71
72 /**
73 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
74 */
75 TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id,
76 TNC_Version min_version,
77 TNC_Version max_version,
78 TNC_Version *actual_version)
79 {
80 if (imc_hcd)
81 {
82 DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
83 return TNC_RESULT_ALREADY_INITIALIZED;
84 }
85 imc_hcd = imc_agent_create(imc_name, msg_types, countof(msg_types),
86 imc_id, actual_version);
87 if (!imc_hcd)
88 {
89 return TNC_RESULT_FATAL;
90 }
91
92 os = imc_os_info_create();
93 if (!os)
94 {
95 imc_hcd->destroy(imc_hcd);
96 imc_hcd = NULL;
97
98 return TNC_RESULT_FATAL;
99 }
100
101 if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
102 {
103 DBG1(DBG_IMC, "no common IF-IMC version");
104 return TNC_RESULT_NO_COMMON_VERSION;
105 }
106 return TNC_RESULT_SUCCESS;
107 }
108
109 /**
110 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
111 */
112 TNC_Result TNC_IMC_API TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
113 TNC_ConnectionID connection_id, TNC_ConnectionState new_state)
114 {
115 imc_state_t *state;
116
117 if (!imc_hcd)
118 {
119 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
120 return TNC_RESULT_NOT_INITIALIZED;
121 }
122 switch (new_state)
123 {
124 case TNC_CONNECTION_STATE_CREATE:
125 state = imc_hcd_state_create(connection_id);
126 return imc_hcd->create_state(imc_hcd, state);
127 case TNC_CONNECTION_STATE_HANDSHAKE:
128 if (imc_hcd->change_state(imc_hcd, connection_id, new_state,
129 &state) != TNC_RESULT_SUCCESS)
130 {
131 return TNC_RESULT_FATAL;
132 }
133 state->set_result(state, imc_id,
134 TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
135 return TNC_RESULT_SUCCESS;
136 case TNC_CONNECTION_STATE_DELETE:
137 return imc_hcd->delete_state(imc_hcd, connection_id);
138 default:
139 return imc_hcd->change_state(imc_hcd, connection_id,
140 new_state, NULL);
141 }
142 }
143
144 /**
145 * Add AttributesNaturalLanguage attribute to send queue
146 */
147 static void add_attrs_natural_lang(imc_msg_t *msg, char *section)
148 {
149 pa_tnc_attr_t *attr;
150 char *string;
151
152 string = lib->settings->get_str(lib->settings,
153 "%s.plugins.imc-hcd.subtypes.%s.attributes_natural_language",
154 "en", lib->ns, section);
155 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_ATTRS_NATURAL_LANG,
156 string);
157 attr = generic_attr_string_create(chunk_from_str(string),
158 pen_type_create(PEN_PWG, PWG_HCD_ATTRS_NATURAL_LANG));
159 msg->add_attribute(msg, attr);
160 }
161
162 /**
163 * Add DefaultPasswordEnabled attribute to send queue
164 */
165 static void add_default_pwd_enabled(imc_msg_t *msg)
166 {
167 pa_tnc_attr_t *attr;
168 bool status;
169
170 status = lib->settings->get_bool(lib->settings,
171 "%s.plugins.imc-hcd.subtypes.system.default_password_enabled",
172 FALSE, lib->ns);
173 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_DEFAULT_PWD_ENABLED,
174 status ? "yes" : "no");
175 attr = generic_attr_bool_create(status,
176 pen_type_create(PEN_PWG, PWG_HCD_DEFAULT_PWD_ENABLED));
177 msg->add_attribute(msg, attr);
178 }
179
180 /**
181 * Add ForwardingEnabled attribute to send queue
182 */
183 static void add_forwarding_enabled(imc_msg_t *msg)
184 {
185 pa_tnc_attr_t *attr;
186 bool status;
187
188 status = lib->settings->get_bool(lib->settings,
189 "%s.plugins.imc-hcd.subtypes.system.forwarding_enabled",
190 FALSE, lib->ns);
191 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_FORWARDING_ENABLED,
192 status ? "yes" : "no");
193 attr = generic_attr_bool_create(status,
194 pen_type_create(PEN_PWG, PWG_HCD_FORWARDING_ENABLED));
195 msg->add_attribute(msg, attr);
196 }
197
198 /**
199 * Add MachineTypeModel attribute to send queue
200 */
201 static void add_machine_type_model(imc_msg_t *msg)
202 {
203 pa_tnc_attr_t *attr;
204 char *string;
205
206 string = lib->settings->get_str(lib->settings,
207 "%s.plugins.imc-hcd.subtypes.system.machine_type_model",
208 "", lib->ns);
209 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_MACHINE_TYPE_MODEL,
210 string);
211 attr = generic_attr_string_create(chunk_from_str(string),
212 pen_type_create(PEN_PWG, PWG_HCD_MACHINE_TYPE_MODEL));
213 msg->add_attribute(msg, attr);
214 }
215
216 /**
217 * Add PSTNFaxEnabled attribute to send queue
218 */
219 static void add_pstn_fax_enabled(imc_msg_t *msg)
220 {
221 pa_tnc_attr_t *attr;
222 bool status;
223
224 status = lib->settings->get_bool(lib->settings,
225 "%s.plugins.imc-hcd.subtypes.system.pstn_fax_enabled",
226 FALSE, lib->ns);
227 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_PSTN_FAX_ENABLED,
228 status ? "yes" : "no");
229 attr = generic_attr_bool_create(status,
230 pen_type_create(PEN_PWG, PWG_HCD_PSTN_FAX_ENABLED));
231 msg->add_attribute(msg, attr);
232 }
233
234 /**
235 * Add TimeSource attribute to send queue
236 */
237 static void add_time_source(imc_msg_t *msg)
238 {
239 pa_tnc_attr_t *attr;
240 char *string;
241
242 string = lib->settings->get_str(lib->settings,
243 "%s.plugins.imc-hcd.subtypes.system.time_source",
244 "", lib->ns);
245 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_TIME_SOURCE,
246 string);
247 attr = generic_attr_string_create(chunk_from_str(string),
248 pen_type_create(PEN_PWG, PWG_HCD_TIME_SOURCE));
249 msg->add_attribute(msg, attr);
250 }
251
252 /**
253 * Add UserApplicationEnabled attribute to send queue
254 */
255 static void add_user_app_enabled(imc_msg_t *msg)
256 {
257 pa_tnc_attr_t *attr;
258 bool status;
259
260 status = lib->settings->get_bool(lib->settings,
261 "%s.plugins.imc-hcd.subtypes.system.user_application_enabled",
262 FALSE, lib->ns);
263 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_USER_APP_ENABLED,
264 status ? "yes" : "no");
265 attr = generic_attr_bool_create(status,
266 pen_type_create(PEN_PWG, PWG_HCD_USER_APP_ENABLED));
267 msg->add_attribute(msg, attr);
268 }
269
270 /**
271 * Add UserApplicationPersistenceEnabled attribute to send queue
272 */
273 static void add_user_app_persist_enabled(imc_msg_t *msg)
274 {
275 pa_tnc_attr_t *attr;
276 bool status;
277
278 status = lib->settings->get_bool(lib->settings,
279 "%s.plugins.imc-hcd.subtypes.system.user_application_persistence.enabled",
280 FALSE, lib->ns);
281 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_USER_APP_PERSIST_ENABLED,
282 status ? "yes" : "no");
283 attr = generic_attr_bool_create(status,
284 pen_type_create(PEN_PWG, PWG_HCD_USER_APP_PERSIST_ENABLED));
285 msg->add_attribute(msg, attr);
286 }
287
288 /**
289 * Add VendorName attribute to send queue
290 */
291 static void add_vendor_name(imc_msg_t *msg)
292 {
293 pa_tnc_attr_t *attr;
294 char *string;
295
296 string = lib->settings->get_str(lib->settings,
297 "%s.plugins.imc-hcd.subtypes.system.vendor_name",
298 "", lib->ns);
299 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_VENDOR_NAME,
300 string);
301 attr = generic_attr_string_create(chunk_from_str(string),
302 pen_type_create(PEN_PWG, PWG_HCD_VENDOR_NAME));
303 msg->add_attribute(msg, attr);
304 }
305
306 /**
307 * Add VendorSMICode attribute to send queue
308 */
309 static void add_vendor_smi_code(imc_msg_t *msg)
310 {
311 pa_tnc_attr_t *attr;
312 int smi_code;
313
314 smi_code = lib->settings->get_int(lib->settings,
315 "%s.plugins.imc-hcd.subtypes.system.vendor_smi_code",
316 0, lib->ns);
317 DBG2(DBG_IMC, " %N: 0x%06x (%d)", pwg_attr_names, PWG_HCD_VENDOR_SMI_CODE,
318 smi_code, smi_code);
319 attr = pwg_attr_vendor_smi_code_create(smi_code);
320 msg->add_attribute(msg, attr);
321 }
322
323 /**
324 * Add CertificationState attribute to send queue
325 */
326 static void add_certification_state(imc_msg_t *msg)
327 {
328 pa_tnc_attr_t *attr;
329 char *hex_string;
330 chunk_t blob;
331
332 hex_string = lib->settings->get_str(lib->settings,
333 "%s.plugins.imc-hcd.subtypes.system.certification_state",
334 NULL, lib->ns);
335 if (hex_string)
336 {
337 blob = chunk_from_hex(chunk_from_str(hex_string), NULL);
338
339 DBG2(DBG_IMC, " %N: %B", pwg_attr_names, PWG_HCD_CERTIFICATION_STATE,
340 &blob);
341 attr = generic_attr_chunk_create(blob,
342 pen_type_create(PEN_PWG, PWG_HCD_CERTIFICATION_STATE));
343 msg->add_attribute(msg, attr);
344 chunk_free(&blob);
345 }
346 }
347
348 /**
349 * Add CertificationState attribute to send queue
350 */
351 static void add_configuration_state(imc_msg_t *msg)
352 {
353 pa_tnc_attr_t *attr;
354 char *hex_string;
355 chunk_t blob;
356
357 hex_string = lib->settings->get_str(lib->settings,
358 "%s.plugins.imc-hcd.subtypes.system.configuration_state",
359 NULL, lib->ns);
360 if (hex_string)
361 {
362 blob = chunk_from_hex(chunk_from_str(hex_string), NULL);
363
364 DBG2(DBG_IMC, " %N: %B", pwg_attr_names, PWG_HCD_CONFIGURATION_STATE,
365 &blob);
366 attr = generic_attr_chunk_create(blob,
367 pen_type_create(PEN_PWG, PWG_HCD_CONFIGURATION_STATE));
368 msg->add_attribute(msg, attr);
369 chunk_free(&blob);
370 }
371 }
372
373 /**
374 * Add Correlated Attributes to send queue
375 */
376 static void add_quadruple(imc_msg_t *msg, char *section, quadruple_t *quad)
377 {
378 pa_tnc_attr_t *attr;
379 const size_t version_len = 16;
380 char version[version_len];
381 char hex_version_default[] = "00000000000000000000000000000000";
382 char *app, *name, *patches, *pos, *string_version, *hex_version;
383 chunk_t num_version;
384 enumerator_t *enumerator;
385
386 enumerator = lib->settings->create_section_enumerator(lib->settings,
387 "%s.plugins.imc-hcd.subtypes.%s.%s",
388 lib->ns, section, quad->section);
389 while (enumerator->enumerate(enumerator, &app))
390 {
391 name = lib->settings->get_str(lib->settings,
392 "%s.plugins.imc-hcd.subtypes.%s.%s.%s.name",
393 "", lib->ns, section, quad->section, app);
394 patches = lib->settings->get_str(lib->settings,
395 "%s.plugins.imc-hcd.subtypes.%s.%s.%s.patches",
396 "", lib->ns, section, quad->section, app);
397 string_version = lib->settings->get_str(lib->settings,
398 "%s.plugins.imc-hcd.subtypes.%s.%s.%s.string_version",
399 "", lib->ns, section, quad->section, app);
400 hex_version = lib->settings->get_str(lib->settings,
401 "%s.plugins.imc-hcd.subtypes.%s.%s.%s.version",
402 hex_version_default, lib->ns, section, quad->section, app);
403
404 /* replace \n escape character by CRLF */
405 pos = patches;
406 while (TRUE)
407 {
408 pos = strchr(pos, '\\');
409 if (pos == NULL)
410 {
411 break;
412 }
413 if (pos[1] == 'n')
414 {
415 pos[0] = '\r';
416 pos[1] = '\n';
417 pos++;
418 }
419 pos++;
420 }
421
422 /* convert hex string into binary chunk */
423 if (strlen(hex_version) > 2 * version_len)
424 {
425 hex_version = hex_version_default;
426 }
427 num_version = chunk_from_hex(chunk_from_str(hex_version), version);
428
429 DBG2(DBG_IMC, "--- %s ---", app);
430
431 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, quad->name_attr, name);
432 attr = generic_attr_string_create(chunk_from_str(name),
433 pen_type_create(PEN_PWG, quad->name_attr));
434 msg->add_attribute(msg, attr);
435
436 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, quad->patches_attr, patches);
437 attr = generic_attr_string_create(chunk_from_str(patches),
438 pen_type_create(PEN_PWG, quad->patches_attr));
439 msg->add_attribute(msg, attr);
440
441 DBG2(DBG_IMC, " %N: %s", pwg_attr_names, quad->string_version_attr,
442 string_version);
443 attr = generic_attr_string_create(chunk_from_str(string_version),
444 pen_type_create(PEN_PWG, quad->string_version_attr));
445 msg->add_attribute(msg, attr);
446
447 DBG2(DBG_IMC, " %N: %#B", pwg_attr_names, quad->version_attr, &num_version);
448 attr = generic_attr_chunk_create(num_version,
449 pen_type_create(PEN_PWG, quad->version_attr));
450 msg->add_attribute(msg, attr);
451 }
452 enumerator->destroy(enumerator);
453 }
454
455 /**
456 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
457 */
458 TNC_Result TNC_IMC_API TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
459 TNC_ConnectionID connection_id)
460 {
461 imc_state_t *state;
462 imc_msg_t *out_msg;
463 TNC_Result result = TNC_RESULT_SUCCESS;
464 pa_subtype_pwg_t subtype;
465 pen_type_t msg_type;
466 enumerator_t *enumerator;
467 char *section;
468 int i;
469
470 if (!imc_hcd)
471 {
472 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
473 return TNC_RESULT_NOT_INITIALIZED;
474 }
475 if (!imc_hcd->get_state(imc_hcd, connection_id, &state))
476 {
477 return TNC_RESULT_FATAL;
478 }
479
480 /* Enumerate over all HCD subtype sections */
481 enumerator = lib->settings->create_section_enumerator(lib->settings,
482 "%s.plugins.imc-hcd.subtypes", lib->ns);
483 while (enumerator->enumerate(enumerator, &section) &&
484 result == TNC_RESULT_SUCCESS)
485 {
486 if (streq(section, "system"))
487 {
488 subtype = PA_SUBTYPE_PWG_HCD_SYSTEM;
489 }
490 else if (streq(section, "console"))
491 {
492 subtype = PA_SUBTYPE_PWG_HCD_CONSOLE;
493 }
494 else if (streq(section, "marker"))
495 {
496 subtype = PA_SUBTYPE_PWG_HCD_MARKER;
497 }
498 else if (streq(section, "finisher"))
499 {
500 subtype = PA_SUBTYPE_PWG_HCD_FINISHER;
501 }
502 else if (streq(section, "interface"))
503 {
504 subtype = PA_SUBTYPE_PWG_HCD_INTERFACE;
505 }
506 else if (streq(section, "scanner"))
507 {
508 subtype = PA_SUBTYPE_PWG_HCD_SCANNER;
509 }
510 else
511 {
512 DBG1(DBG_IMC, "HCD subtype '%s' not supported", section);
513 continue;
514 }
515 DBG2(DBG_IMC, "retrieving attributes for PA subtype %N/%N",
516 pen_names, PEN_PWG, pa_subtype_pwg_names, subtype);
517 msg_type = pen_type_create(PEN_PWG, subtype);
518 out_msg = imc_msg_create(imc_hcd, state, connection_id, imc_id,
519 TNC_IMVID_ANY, msg_type);
520
521 /* mandatory attributes that are always sent without request */
522 add_attrs_natural_lang(out_msg, section);
523 if (subtype == PA_SUBTYPE_PWG_HCD_SYSTEM)
524 {
525 add_default_pwd_enabled(out_msg);
526 add_forwarding_enabled(out_msg);
527 add_machine_type_model(out_msg);
528 add_pstn_fax_enabled(out_msg);
529 add_time_source(out_msg);
530 add_vendor_name(out_msg);
531 add_vendor_smi_code(out_msg);
532 add_user_app_enabled(out_msg);
533 add_user_app_persist_enabled(out_msg);
534 }
535 if (lib->settings->get_bool(lib->settings,
536 "%s.plugins.imc-hcd.push_info", FALSE, lib->ns))
537 {
538 /* correlated attributes */
539 for (i = 0; i < countof(quadruples); i++)
540 {
541 add_quadruple(out_msg, section, &quadruples[i]);
542 }
543 }
544
545 /* send PA-TNC message with the excl flag not set */
546 result = out_msg->send(out_msg, FALSE);
547 out_msg->destroy(out_msg);
548 }
549 enumerator->destroy(enumerator);
550
551 return result;
552 }
553
554 static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
555 {
556 imc_msg_t *out_msg;
557 enumerator_t *enumerator;
558 pa_tnc_attr_t *attr;
559 pen_type_t type;
560 TNC_Result result;
561 bool fatal_error = FALSE, pushed_info;
562
563 /* generate an outgoing PA-TNC message - we might need it */
564 out_msg = imc_msg_create_as_reply(in_msg);
565
566 /* parse received PA-TNC message and handle local and remote errors */
567 result = in_msg->receive(in_msg, out_msg, &fatal_error);
568 if (result != TNC_RESULT_SUCCESS)
569 {
570 out_msg->destroy(out_msg);
571 return result;
572 }
573 pushed_info = lib->settings->get_bool(lib->settings,
574 "%s.plugins.imc-hcd.push_info", FALSE, lib->ns);
575
576 /* analyze PA-TNC attributes */
577 enumerator = in_msg->create_attribute_enumerator(in_msg);
578 while (enumerator->enumerate(enumerator, &attr))
579 {
580 type = attr->get_type(attr);
581
582 if (type.vendor_id == PEN_IETF)
583 {
584 if (type.type == IETF_ATTR_ATTRIBUTE_REQUEST)
585 {
586 ietf_attr_attr_request_t *attr_cast;
587 pen_type_t *entry;
588 enumerator_t *e;
589
590 attr_cast = (ietf_attr_attr_request_t*)attr;
591
592 e = attr_cast->create_enumerator(attr_cast);
593 while (e->enumerate(e, &entry))
594 {
595 if (entry->vendor_id == PEN_PWG)
596 {
597 switch (entry->type)
598 {
599 case PWG_HCD_ATTRS_NATURAL_LANG:
600 add_attrs_natural_lang(out_msg, "system");
601 break;
602 case PWG_HCD_DEFAULT_PWD_ENABLED:
603 add_default_pwd_enabled(out_msg);
604 break;
605 case PWG_HCD_FORWARDING_ENABLED:
606 add_forwarding_enabled(out_msg);
607 break;
608 case PWG_HCD_MACHINE_TYPE_MODEL:
609 add_machine_type_model(out_msg);
610 break;
611 case PWG_HCD_PSTN_FAX_ENABLED:
612 add_pstn_fax_enabled(out_msg);
613 break;
614 case PWG_HCD_TIME_SOURCE:
615 add_time_source(out_msg);
616 break;
617 case PWG_HCD_USER_APP_ENABLED:
618 add_user_app_enabled(out_msg);
619 break;
620 case PWG_HCD_USER_APP_PERSIST_ENABLED:
621 add_user_app_persist_enabled(out_msg);
622 break;
623 case PWG_HCD_VENDOR_NAME:
624 add_vendor_name(out_msg);
625 break;
626 case PWG_HCD_VENDOR_SMI_CODE:
627 add_vendor_smi_code(out_msg);
628 break;
629 case PWG_HCD_CERTIFICATION_STATE:
630 add_certification_state(out_msg);
631 break;
632 case PWG_HCD_CONFIGURATION_STATE:
633 add_configuration_state(out_msg);
634 break;
635 default:
636 if (pushed_info)
637 {
638 continue;
639 }
640 }
641
642 /* if not pushed, deliver on request */
643 switch (entry->type)
644 {
645 case PWG_HCD_FIRMWARE_NAME:
646 add_quadruple(out_msg, "system", &quadruples[0]);
647 break;
648 case PWG_HCD_RESIDENT_APP_NAME:
649 add_quadruple(out_msg, "system", &quadruples[1]);
650 break;
651 case PWG_HCD_USER_APP_NAME:
652 add_quadruple(out_msg, "system", &quadruples[2]);
653 break;
654 default:
655 break;
656 }
657 }
658 }
659 e->destroy(e);
660 }
661 }
662 }
663 enumerator->destroy(enumerator);
664
665 if (fatal_error)
666 {
667 result = TNC_RESULT_FATAL;
668 }
669 else
670 {
671 /* send PA-TNC message with the EXCL flag set */
672 result = out_msg->send(out_msg, TRUE);
673 }
674 out_msg->destroy(out_msg);
675
676 return result;
677 }
678
679 /**
680 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
681 */
682 TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
683 TNC_ConnectionID connection_id,
684 TNC_BufferReference msg,
685 TNC_UInt32 msg_len,
686 TNC_MessageType msg_type)
687 {
688 imc_state_t *state;
689 imc_msg_t *in_msg;
690 TNC_Result result;
691
692 if (!imc_hcd)
693 {
694 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
695 return TNC_RESULT_NOT_INITIALIZED;
696 }
697 if (!imc_hcd->get_state(imc_hcd, connection_id, &state))
698 {
699 return TNC_RESULT_FATAL;
700 }
701 in_msg = imc_msg_create_from_data(imc_hcd, state, connection_id, msg_type,
702 chunk_create(msg, msg_len));
703 result = receive_message(state, in_msg);
704 in_msg->destroy(in_msg);
705
706 return result;
707 }
708
709 /**
710 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
711 */
712 TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
713 TNC_ConnectionID connection_id,
714 TNC_UInt32 msg_flags,
715 TNC_BufferReference msg,
716 TNC_UInt32 msg_len,
717 TNC_VendorID msg_vid,
718 TNC_MessageSubtype msg_subtype,
719 TNC_UInt32 src_imv_id,
720 TNC_UInt32 dst_imc_id)
721 {
722 imc_state_t *state;
723 imc_msg_t *in_msg;
724 TNC_Result result;
725
726 if (!imc_hcd)
727 {
728 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
729 return TNC_RESULT_NOT_INITIALIZED;
730 }
731 if (!imc_hcd->get_state(imc_hcd, connection_id, &state))
732 {
733 return TNC_RESULT_FATAL;
734 }
735 in_msg = imc_msg_create_from_long_data(imc_hcd, state, connection_id,
736 src_imv_id, dst_imc_id,msg_vid, msg_subtype,
737 chunk_create(msg, msg_len));
738 result =receive_message(state, in_msg);
739 in_msg->destroy(in_msg);
740
741 return result;
742 }
743
744 /**
745 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
746 */
747 TNC_Result TNC_IMC_API TNC_IMC_BatchEnding(TNC_IMCID imc_id,
748 TNC_ConnectionID connection_id)
749 {
750 if (!imc_hcd)
751 {
752 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
753 return TNC_RESULT_NOT_INITIALIZED;
754 }
755 return TNC_RESULT_SUCCESS;
756 }
757
758 /**
759 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
760 */
761 TNC_Result TNC_IMC_API TNC_IMC_Terminate(TNC_IMCID imc_id)
762 {
763 if (!imc_hcd)
764 {
765 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
766 return TNC_RESULT_NOT_INITIALIZED;
767 }
768 imc_hcd->destroy(imc_hcd);
769 imc_hcd = NULL;
770
771 os->destroy(os);
772 os = NULL;
773
774 return TNC_RESULT_SUCCESS;
775 }
776
777 /**
778 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
779 */
780 TNC_Result TNC_IMC_API TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
781 TNC_TNCC_BindFunctionPointer bind_function)
782 {
783 if (!imc_hcd)
784 {
785 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
786 return TNC_RESULT_NOT_INITIALIZED;
787 }
788 return imc_hcd->bind_functions(imc_hcd, bind_function);
789 }