implemented parsing of TNCCS 1.1 messages
[strongswan.git] / src / libcharon / plugins / tnccs_11 / messages / tnccs_msg.c
1 /*
2 * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
3 * Copyright (C) 2010 Andreas Steffen, 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 "tnccs_msg.h"
17 #include "imc_imv_msg.h"
18 #include "tnccs_error_msg.h"
19 #include "tnccs_preferred_language_msg.h"
20 #include "tnccs_reason_strings_msg.h"
21 #include "tnccs_recommendation_msg.h"
22 #include "tnccs_tncs_contact_info_msg.h"
23
24 #include <library.h>
25 #include <debug.h>
26
27 ENUM(tnccs_msg_type_names, IMC_IMV_MSG, TNCCS_MSG_ROOF,
28 "IMC-IMV",
29 "TNCCS-Recommendation",
30 "TNCCS-Error",
31 "TNCCS-PreferredLanguage",
32 "TNCCS-ReasonStrings",
33 "TNCCS-TNCSContactInfo"
34 );
35
36 /**
37 * See header
38 */
39 tnccs_msg_t* tnccs_msg_create_from_node(xmlNodePtr node, linked_list_t *errors)
40 {
41 char *error_msg, buf[BUF_LEN];
42 tnccs_error_type_t error_type = TNCCS_ERROR_MALFORMED_BATCH;
43 tnccs_msg_t *msg;
44 tnccs_msg_type_t type = IMC_IMV_MSG;
45
46 if (streq((char*)node->name, "IMC-IMV-Message"))
47 {
48 DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
49 return imc_imv_msg_create_from_node(node, errors);
50 }
51 else if (streq((char*)node->name, "TNCC-TNCS-Message"))
52 {
53 bool found = FALSE;
54 xmlNsPtr ns = node->ns;
55 xmlNodePtr cur = node->xmlChildrenNode;
56 xmlNodePtr xml_msg_node = NULL;
57
58 while (cur)
59 {
60 if (streq((char*)cur->name, "Type") && cur->ns == ns)
61 {
62 xmlChar *content = xmlNodeGetContent(cur);
63
64 type = strtol((char*)content, NULL, 16);
65 xmlFree(content);
66 found = TRUE;
67 }
68 else if (streq((char*)cur->name, "XML") && cur->ns == ns)
69 {
70 xml_msg_node = cur->xmlChildrenNode;
71 }
72 cur = cur->next;
73 }
74 if (!found)
75 {
76 error_msg = "Type is missing in TNCC-TNCS-Message";
77 goto fatal;
78 }
79 if (!xml_msg_node)
80 {
81 error_msg = "XML node is missing in TNCC-TNCS-Message";
82 goto fatal;
83 }
84 cur = xml_msg_node;
85
86 /* skip empty and blank nodes */
87 while (cur && xmlIsBlankNode(cur))
88 {
89 cur = cur->next;
90 }
91 if (!cur)
92 {
93 error_msg = "XML node is empty";
94 goto fatal;
95 }
96
97 /* check if TNCCS message type and node name agree */
98 if (type >= TNCCS_MSG_RECOMMENDATION && type <= TNCCS_MSG_ROOF)
99 {
100 DBG2(DBG_TNC, "processing %N message", tnccs_msg_type_names, type);
101 if (cur->ns != ns)
102 {
103 error_msg = "node is not in the TNCCS message namespace";
104 goto fatal;
105 }
106 if (type != enum_from_name(tnccs_msg_type_names, (char*)cur->name))
107 {
108 error_msg = buf;
109 snprintf(buf, BUF_LEN, "expected '%N' node but was '%s'",
110 tnccs_msg_type_names, type, (char*)cur->name);
111 goto fatal;
112 }
113 }
114
115 switch (type)
116 {
117 case TNCCS_MSG_RECOMMENDATION:
118 return tnccs_recommendation_msg_create_from_node(cur, errors);
119 case TNCCS_MSG_ERROR:
120 return tnccs_error_msg_create_from_node(cur);
121 case TNCCS_MSG_PREFERRED_LANGUAGE:
122 return tnccs_preferred_language_msg_create_from_node(cur, errors);
123 case TNCCS_MSG_REASON_STRINGS:
124 return tnccs_reason_strings_msg_create_from_node(cur, errors);
125 case TNCCS_MSG_TNCS_CONTACT_INFO:
126 return tnccs_tncs_contact_info_msg_create_from_node(cur, errors);
127 default:
128 DBG1(DBG_TNC, "ignoring TNCC-TNCS-Message with type %d", type);
129 return NULL;
130 }
131 }
132 DBG1(DBG_TNC, "ignoring unknown message node '%s'", (char*)node->name);
133 return NULL;
134
135 fatal:
136 msg = tnccs_error_msg_create(error_type, error_msg);
137 errors->insert_last(errors, msg);
138 return NULL;
139 }
140