start and stop apache server on dave
[strongswan.git] / src / libimcv / plugins / imv_scanner.c
1 /*
2 * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15 #include "imv_scanner_state.h"
16
17 #include <imv/imv_agent.h>
18 #include <pa_tnc/pa_tnc_msg.h>
19 #include <ietf/ietf_attr.h>
20 #include <ietf/ietf_attr_pa_tnc_error.h>
21 #include <ietf/ietf_attr_port_filter.h>
22
23 #include <tncif_names.h>
24 #include <tncif_pa_subtypes.h>
25
26 #include <pen/pen.h>
27 #include <debug.h>
28
29 /* IMV definitions */
30
31 static const char imv_name[] = "Scanner";
32
33 #define IMV_VENDOR_ID PEN_ITA
34 #define IMV_SUBTYPE PA_SUBTYPE_ITA_SCANNER
35
36 static imv_agent_t *imv_scanner;
37
38 /**
39 * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
40 */
41 TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
42 TNC_Version min_version,
43 TNC_Version max_version,
44 TNC_Version *actual_version)
45 {
46 if (imv_scanner)
47 {
48 DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name);
49 return TNC_RESULT_ALREADY_INITIALIZED;
50 }
51 imv_scanner = imv_agent_create(imv_name, IMV_VENDOR_ID, IMV_SUBTYPE,
52 imv_id, actual_version);
53 if (!imv_scanner)
54 {
55 return TNC_RESULT_FATAL;
56 }
57 if (min_version > TNC_IFIMV_VERSION_1 || max_version < TNC_IFIMV_VERSION_1)
58 {
59 DBG1(DBG_IMV, "no common IF-IMV version");
60 return TNC_RESULT_NO_COMMON_VERSION;
61 }
62 return TNC_RESULT_SUCCESS;
63 }
64
65 /**
66 * see section 3.7.2 of TCG TNC IF-IMV Specification 1.2
67 */
68 TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
69 TNC_ConnectionID connection_id,
70 TNC_ConnectionState new_state)
71 {
72 imv_state_t *state;
73
74 if (!imv_scanner)
75 {
76 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
77 return TNC_RESULT_NOT_INITIALIZED;
78 }
79 switch (new_state)
80 {
81 case TNC_CONNECTION_STATE_CREATE:
82 state = imv_scanner_state_create(connection_id);
83 return imv_scanner->create_state(imv_scanner, state);
84 case TNC_CONNECTION_STATE_DELETE:
85 return imv_scanner->delete_state(imv_scanner, connection_id);
86 default:
87 return imv_scanner->change_state(imv_scanner, connection_id,
88 new_state, NULL);
89 }
90 }
91
92 static TNC_Result send_message(TNC_ConnectionID connection_id)
93 {
94 pa_tnc_msg_t *msg;
95 pa_tnc_attr_t *attr;
96 TNC_Result result;
97
98 msg = pa_tnc_msg_create();
99 msg->build(msg);
100 result = imv_scanner->send_message(imv_scanner, connection_id,
101 msg->get_encoding(msg));
102 msg->destroy(msg);
103
104 return result;
105 }
106
107 /**
108 * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
109 */
110 TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
111 TNC_ConnectionID connection_id,
112 TNC_BufferReference msg,
113 TNC_UInt32 msg_len,
114 TNC_MessageType msg_type)
115 {
116 pa_tnc_msg_t *pa_tnc_msg;
117 pa_tnc_attr_t *attr;
118 imv_state_t *state;
119 enumerator_t *enumerator;
120 TNC_Result result;
121 bool fatal_error = FALSE;
122
123 if (!imv_scanner)
124 {
125 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
126 return TNC_RESULT_NOT_INITIALIZED;
127 }
128
129 /* get current IMV state */
130 if (!imv_scanner->get_state(imv_scanner, connection_id, &state))
131 {
132 return TNC_RESULT_FATAL;
133 }
134
135 /* parse received PA-TNC message and automatically handle any errors */
136 result = imv_scanner->receive_message(imv_scanner, connection_id,
137 chunk_create(msg, msg_len), msg_type,
138 &pa_tnc_msg);
139
140 /* no parsed PA-TNC attributes available if an error occurred */
141 if (!pa_tnc_msg)
142 {
143 return result;
144 }
145
146 /* analyze PA-TNC attributes */
147 enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
148 while (enumerator->enumerate(enumerator, &attr))
149 {
150 if (attr->get_vendor_id(attr) != PEN_IETF)
151 {
152 continue;
153 }
154
155 if (attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
156 {
157 ietf_attr_pa_tnc_error_t *error_attr;
158 pa_tnc_error_code_t error_code;
159 chunk_t msg_info, attr_info;
160
161 error_attr = (ietf_attr_pa_tnc_error_t*)attr;
162 error_code = error_attr->get_error_code(error_attr);
163 msg_info = error_attr->get_msg_info(error_attr);
164
165 DBG1(DBG_IMV, "received PA-TNC error '%N' concerning message %#B",
166 pa_tnc_error_code_names, error_code, &msg_info);
167 switch (error_code)
168 {
169 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
170 attr_info = error_attr->get_attr_info(error_attr);
171 DBG1(DBG_IMV, " unsupported attribute %#B", &attr_info);
172 break;
173 default:
174 break;
175 }
176 fatal_error = TRUE;
177 }
178 else if (attr->get_type(attr) == IETF_ATTR_PORT_FILTER)
179 {
180 ietf_attr_port_filter_t *attr_port_filter;
181 enumerator_t *enumerator;
182 bool blocked;
183 u_int8_t protocol;
184 u_int16_t port;
185
186 attr_port_filter = (ietf_attr_port_filter_t*)attr;
187 enumerator = attr_port_filter->create_port_enumerator(attr_port_filter);
188 while (enumerator->enumerate(enumerator, &blocked, &protocol, &port))
189 {
190 DBG2(DBG_IMV, "%s: %s %5u", blocked ? "blocked" : "allowed",
191 (protocol == IPPROTO_TCP) ? "tcp" : "udp", port);
192 }
193 enumerator->destroy(enumerator);
194 }
195 }
196 enumerator->destroy(enumerator);
197 pa_tnc_msg->destroy(pa_tnc_msg);
198
199 if (fatal_error)
200 {
201 state->set_recommendation(state,
202 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
203 TNC_IMV_EVALUATION_RESULT_ERROR);
204 return imv_scanner->provide_recommendation(imv_scanner, connection_id);
205 }
206
207 return imv_scanner->provide_recommendation(imv_scanner, connection_id);
208 }
209
210 /**
211 * see section 3.7.4 of TCG TNC IF-IMV Specification 1.2
212 */
213 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
214 TNC_ConnectionID connection_id)
215 {
216 if (!imv_scanner)
217 {
218 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
219 return TNC_RESULT_NOT_INITIALIZED;
220 }
221 return imv_scanner->provide_recommendation(imv_scanner, connection_id);
222 }
223
224 /**
225 * see section 3.7.5 of TCG TNC IF-IMV Specification 1.2
226 */
227 TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
228 TNC_ConnectionID connection_id)
229 {
230 if (!imv_scanner)
231 {
232 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
233 return TNC_RESULT_NOT_INITIALIZED;
234 }
235 return TNC_RESULT_SUCCESS;
236 }
237
238 /**
239 * see section 3.7.6 of TCG TNC IF-IMV Specification 1.2
240 */
241 TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
242 {
243 if (!imv_scanner)
244 {
245 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
246 return TNC_RESULT_NOT_INITIALIZED;
247 }
248 imv_scanner->destroy(imv_scanner);
249 imv_scanner = NULL;
250
251 return TNC_RESULT_SUCCESS;
252 }
253
254 /**
255 * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.2
256 */
257 TNC_Result TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
258 TNC_TNCS_BindFunctionPointer bind_function)
259 {
260 if (!imv_scanner)
261 {
262 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
263 return TNC_RESULT_NOT_INITIALIZED;
264 }
265 return imv_scanner->bind_functions(imv_scanner, bind_function);
266 }