Implemented SWID prototype IMC/IMV pair
[strongswan.git] / src / libpts / plugins / imc_swid / imc_swid.c
1 /*
2 * Copyright (C) 2013 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_swid_state.h"
17
18 #include "libpts.h"
19 #include "swid/swid_tag_id.h"
20 #include "tcg/swid/tcg_swid_attr_req.h"
21 #include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
22
23 #include <imc/imc_agent.h>
24 #include <imc/imc_msg.h>
25
26 #include <tncif_pa_subtypes.h>
27
28 #include <pen/pen.h>
29 #include <utils/debug.h>
30
31 /* IMC definitions */
32
33 static const char imc_name[] = "SWID";
34
35 static pen_type_t msg_types[] = {
36 { PEN_TCG, PA_SUBTYPE_TCG_SWID }
37 };
38
39 static imc_agent_t *imc_swid;
40
41 /**
42 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
43 */
44 TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
45 TNC_Version min_version,
46 TNC_Version max_version,
47 TNC_Version *actual_version)
48 {
49 if (imc_swid)
50 {
51 DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
52 return TNC_RESULT_ALREADY_INITIALIZED;
53 }
54 imc_swid = imc_agent_create(imc_name, msg_types, countof(msg_types),
55 imc_id, actual_version);
56 if (!imc_swid)
57 {
58 return TNC_RESULT_FATAL;
59 }
60
61 libpts_init();
62
63 if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
64 {
65 DBG1(DBG_IMC, "no common IF-IMC version");
66 return TNC_RESULT_NO_COMMON_VERSION;
67 }
68 return TNC_RESULT_SUCCESS;
69 }
70
71 /**
72 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
73 */
74 TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
75 TNC_ConnectionID connection_id,
76 TNC_ConnectionState new_state)
77 {
78 imc_state_t *state;
79
80 if (!imc_swid)
81 {
82 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
83 return TNC_RESULT_NOT_INITIALIZED;
84 }
85 switch (new_state)
86 {
87 case TNC_CONNECTION_STATE_CREATE:
88 state = imc_swid_state_create(connection_id);
89 return imc_swid->create_state(imc_swid, state);
90 case TNC_CONNECTION_STATE_HANDSHAKE:
91 if (imc_swid->change_state(imc_swid, connection_id, new_state,
92 &state) != TNC_RESULT_SUCCESS)
93 {
94 return TNC_RESULT_FATAL;
95 }
96 state->set_result(state, imc_id,
97 TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
98 return TNC_RESULT_SUCCESS;
99 case TNC_CONNECTION_STATE_DELETE:
100 return imc_swid->delete_state(imc_swid, connection_id);
101 default:
102 return imc_swid->change_state(imc_swid, connection_id,
103 new_state, NULL);
104 }
105 }
106
107 /**
108 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
109 */
110 TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
111 TNC_ConnectionID connection_id)
112 {
113 imc_state_t *state;
114
115 if (!imc_swid)
116 {
117 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
118 return TNC_RESULT_NOT_INITIALIZED;
119 }
120 if (!imc_swid->get_state(imc_swid, connection_id, &state))
121 {
122 return TNC_RESULT_FATAL;
123 }
124
125 return TNC_RESULT_SUCCESS;
126 }
127
128 static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
129 {
130 imc_msg_t *out_msg;
131 imc_swid_state_t *swid_state;
132 enumerator_t *enumerator;
133 pa_tnc_attr_t *attr;
134 pen_type_t type;
135 TNC_Result result;
136 bool fatal_error = FALSE;
137
138 /* parse received PA-TNC message and handle local and remote errors */
139 result = in_msg->receive(in_msg, &fatal_error);
140 if (result != TNC_RESULT_SUCCESS)
141 {
142 return result;
143 }
144 out_msg = imc_msg_create_as_reply(in_msg);
145 swid_state = (imc_swid_state_t*)state;
146
147 /* analyze PA-TNC attributes */
148 enumerator = in_msg->create_attribute_enumerator(in_msg);
149 while (enumerator->enumerate(enumerator, &attr))
150 {
151 tcg_swid_attr_req_t *attr_req;
152 tcg_swid_attr_tag_id_inv_t *attr_tag_id_inv;
153 swid_tag_id_t *tag_id;
154 u_int8_t flags;
155 u_int32_t request_id, eid_epoch;
156
157 type = attr->get_type(attr);
158
159 if (type.vendor_id != PEN_TCG || type.type != TCG_SWID_REQUEST)
160 {
161 continue;
162 }
163
164 attr_req = (tcg_swid_attr_req_t*)attr;
165 flags = attr_req->get_flags(attr_req);
166 request_id = attr_req->get_request_id(attr_req);
167 if (flags & TCG_SWID_ATTR_REQ_FLAG_R)
168 {
169 eid_epoch = swid_state->get_eid_epoch(swid_state);
170 attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
171 attr_tag_id_inv = (tcg_swid_attr_tag_id_inv_t*)attr;
172 tag_id = swid_tag_id_create(
173 chunk_from_str("regid.2004-03.org.strongswan"),
174 chunk_from_str("strongSwan-5-1-0"),
175 chunk_empty);
176 attr_tag_id_inv->add_tag_id(attr_tag_id_inv, tag_id);
177 out_msg->add_attribute(out_msg, attr);
178 }
179 }
180 enumerator->destroy(enumerator);
181
182 if (fatal_error)
183 {
184 result = TNC_RESULT_FATAL;
185 }
186 else
187 {
188 result = out_msg->send(out_msg, TRUE);
189 }
190 out_msg->destroy(out_msg);
191
192 return result;
193 }
194
195 /**
196 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
197
198 */
199 TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
200 TNC_ConnectionID connection_id,
201 TNC_BufferReference msg,
202 TNC_UInt32 msg_len,
203 TNC_MessageType msg_type)
204 {
205 imc_state_t *state;
206 imc_msg_t *in_msg;
207 TNC_Result result;
208
209 if (!imc_swid)
210 {
211 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
212 return TNC_RESULT_NOT_INITIALIZED;
213 }
214 if (!imc_swid->get_state(imc_swid, connection_id, &state))
215 {
216 return TNC_RESULT_FATAL;
217 }
218 in_msg = imc_msg_create_from_data(imc_swid, state, connection_id, msg_type,
219 chunk_create(msg, msg_len));
220 result = receive_message(state, in_msg);
221 in_msg->destroy(in_msg);
222
223 return result;
224 }
225
226 /**
227 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
228 */
229 TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
230 TNC_ConnectionID connection_id,
231 TNC_UInt32 msg_flags,
232 TNC_BufferReference msg,
233 TNC_UInt32 msg_len,
234 TNC_VendorID msg_vid,
235 TNC_MessageSubtype msg_subtype,
236 TNC_UInt32 src_imv_id,
237 TNC_UInt32 dst_imc_id)
238 {
239 imc_state_t *state;
240 imc_msg_t *in_msg;
241 TNC_Result result;
242
243 if (!imc_swid)
244 {
245 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
246 return TNC_RESULT_NOT_INITIALIZED;
247 }
248 if (!imc_swid->get_state(imc_swid, connection_id, &state))
249 {
250 return TNC_RESULT_FATAL;
251 }
252 in_msg = imc_msg_create_from_long_data(imc_swid, state, connection_id,
253 src_imv_id, dst_imc_id,msg_vid, msg_subtype,
254 chunk_create(msg, msg_len));
255 result =receive_message(state, in_msg);
256 in_msg->destroy(in_msg);
257
258 return result;
259 }
260
261 /**
262 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
263 */
264 TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
265 TNC_ConnectionID connection_id)
266 {
267 if (!imc_swid)
268 {
269 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
270 return TNC_RESULT_NOT_INITIALIZED;
271 }
272 return TNC_RESULT_SUCCESS;
273 }
274
275 /**
276 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
277 */
278 TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
279 {
280 if (!imc_swid)
281 {
282 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
283 return TNC_RESULT_NOT_INITIALIZED;
284 }
285
286 libpts_deinit();
287
288 imc_swid->destroy(imc_swid);
289 imc_swid = NULL;
290
291 return TNC_RESULT_SUCCESS;
292 }
293
294 /**
295 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
296 */
297 TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
298 TNC_TNCC_BindFunctionPointer bind_function)
299 {
300 if (!imc_swid)
301 {
302 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
303 return TNC_RESULT_NOT_INITIALIZED;
304 }
305 return imc_swid->bind_functions(imc_swid, bind_function);
306 }