Keep a copy of the tnccs instance for PT-TLS handover
[strongswan.git] / src / libtnccs / plugins / tnccs_dynamic / tnccs_dynamic.c
1 /*
2 * Copyright (C) 2011-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 "tnccs_dynamic.h"
17
18 #include <tnc/tnc.h>
19
20 #include <utils/debug.h>
21
22 typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t;
23
24 /**
25 * Private data of a tnccs_dynamic_t object.
26 */
27 struct private_tnccs_dynamic_t {
28
29 /**
30 * Public tnccs_t interface.
31 */
32 tnccs_t public;
33
34 /**
35 * Server identity
36 */
37 identification_t *server;
38
39 /**
40 * Client identity
41 */
42 identification_t *peer;
43
44 /**
45 * Detected TNC IF-TNCCS stack
46 */
47 tls_t *tls;
48
49 /**
50 * Underlying TNC IF-T transport protocol
51 */
52 tnc_ift_type_t transport;
53
54 /**
55 * Type of TNC client authentication
56 */
57 u_int32_t auth_type;
58
59 /**
60 * Callback function to communicate recommendation (TNC Server only)
61 */
62 tnccs_cb_t callback;
63
64 /**
65 * reference count
66 */
67 refcount_t ref;
68
69 };
70
71 /**
72 * Determine the version of the IF-TNCCS protocol used by analyzing the first
73 * byte of the TNCCS batch received from a TNC Client according to the rules
74 * defined by section 3.5 "Interoperability with older IF-TNCCS versions" of
75 * the TCG TNC IF-TNCCS TLV Bindings Version 2.0 standard.
76 */
77 tnccs_type_t determine_tnccs_protocol(char version)
78 {
79 switch (version)
80 {
81 case '\t':
82 case '\n':
83 case '\r':
84 case ' ':
85 case '<':
86 return TNCCS_1_1;
87 case 0x00:
88 return TNCCS_SOH;
89 case 0x02:
90 return TNCCS_2_0;
91 default:
92 return TNCCS_UNKNOWN;
93 }
94 }
95
96 METHOD(tls_t, process, status_t,
97 private_tnccs_dynamic_t *this, void *buf, size_t buflen)
98 {
99 tnccs_type_t type;
100 tnccs_t *tnccs;
101
102 if (!this->tls)
103 {
104 if (buflen == 0)
105 {
106 return FAILED;
107 }
108 type = determine_tnccs_protocol(*(char*)buf);
109 DBG1(DBG_TNC, "%N protocol detected dynamically",
110 tnccs_type_names, type);
111 tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, TRUE,
112 this->server, this->peer, this->transport,
113 this->callback);
114 if (!tnccs)
115 {
116 DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type);
117 return FAILED;
118 }
119 tnccs->set_auth_type(tnccs, this->auth_type);
120 this->tls = &tnccs->tls;
121 }
122 return this->tls->process(this->tls, buf, buflen);
123 }
124
125 METHOD(tls_t, build, status_t,
126 private_tnccs_dynamic_t *this, void *buf, size_t *buflen, size_t *msglen)
127 {
128 return this->tls->build(this->tls, buf, buflen, msglen);
129 }
130
131 METHOD(tls_t, is_server, bool,
132 private_tnccs_dynamic_t *this)
133 {
134 return TRUE;
135 }
136
137 METHOD(tls_t, get_server_id, identification_t*,
138 private_tnccs_dynamic_t *this)
139 {
140 return this->server;
141 }
142
143 METHOD(tls_t, set_peer_id, void,
144 private_tnccs_dynamic_t *this, identification_t *id)
145 {
146 DESTROY_IF(this->peer);
147 this->peer = id->clone(id);
148 if (this->tls)
149 {
150 this->tls->set_peer_id(this->tls, id);
151 }
152 }
153
154 METHOD(tls_t, get_peer_id, identification_t*,
155 private_tnccs_dynamic_t *this)
156 {
157 return this->peer;
158 }
159
160 METHOD(tls_t, get_purpose, tls_purpose_t,
161 private_tnccs_dynamic_t *this)
162 {
163 return TLS_PURPOSE_EAP_TNC;
164 }
165
166 METHOD(tls_t, is_complete, bool,
167 private_tnccs_dynamic_t *this)
168 {
169 return this->tls ? this->tls->is_complete(this->tls) : FALSE;
170 }
171
172 METHOD(tls_t, get_eap_msk, chunk_t,
173 private_tnccs_dynamic_t *this)
174 {
175 return chunk_empty;
176 }
177
178 METHOD(tls_t, destroy, void,
179 private_tnccs_dynamic_t *this)
180 {
181 if (ref_put(&this->ref))
182 {
183 DESTROY_IF(this->tls);
184 this->server->destroy(this->server);
185 this->peer->destroy(this->peer);
186 free(this);
187 }
188 }
189
190 METHOD(tnccs_t, get_transport, tnc_ift_type_t,
191 private_tnccs_dynamic_t *this)
192 {
193 return this->transport;
194 }
195
196 METHOD(tnccs_t, set_transport, void,
197 private_tnccs_dynamic_t *this, tnc_ift_type_t transport)
198 {
199 this->transport = transport;
200 }
201
202 METHOD(tnccs_t, get_auth_type, u_int32_t,
203 private_tnccs_dynamic_t *this)
204 {
205 return this->auth_type;
206 }
207
208 METHOD(tnccs_t, set_auth_type, void,
209 private_tnccs_dynamic_t *this, u_int32_t auth_type)
210 {
211 this->auth_type = auth_type;
212 }
213
214 METHOD(tnccs_t, get_pdp_server, chunk_t,
215 private_tnccs_dynamic_t *this, u_int16_t *port)
216 {
217 tnccs_t *tnccs = (tnccs_t*)this->tls;
218
219 return tnccs->get_pdp_server(tnccs, port);
220 }
221
222 METHOD(tnccs_t, get_ref, tnccs_t*,
223 private_tnccs_dynamic_t *this)
224 {
225 ref_get(&this->ref);
226 return &this->public;
227 }
228
229 /**
230 * See header
231 */
232 tnccs_t* tnccs_dynamic_create(bool is_server,
233 identification_t *server, identification_t *peer,
234 tnc_ift_type_t transport, tnccs_cb_t cb)
235 {
236 private_tnccs_dynamic_t *this;
237
238 INIT(this,
239 .public = {
240 .tls = {
241 .process = _process,
242 .build = _build,
243 .is_server = _is_server,
244 .get_server_id = _get_server_id,
245 .set_peer_id = _set_peer_id,
246 .get_peer_id = _get_peer_id,
247 .get_purpose = _get_purpose,
248 .is_complete = _is_complete,
249 .get_eap_msk = _get_eap_msk,
250 .destroy = _destroy,
251 },
252 .get_transport = _get_transport,
253 .set_transport = _set_transport,
254 .get_auth_type = _get_auth_type,
255 .set_auth_type = _set_auth_type,
256 .get_pdp_server = _get_pdp_server,
257 .get_ref = _get_ref,
258 },
259 .server = server->clone(server),
260 .peer = peer->clone(peer),
261 .transport = transport,
262 .callback = cb,
263 .ref = 1,
264 );
265
266 return &this->public;
267 }