implemented recommendation storage
[strongswan.git] / src / libcharon / plugins / tnccs_20 / tnccs_20.c
1 /*
2 * Copyright (C) 2010 Sansar Choinyanbuu
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_20.h"
17
18 #include <debug.h>
19 #include <daemon.h>
20 #include <tnc/tncif.h>
21 #include <tnc/tncifimv_names.h>
22 #include <tnc/tnccs/tnccs.h>
23
24 typedef struct recommendation_entry_t recommendation_entry_t;
25 typedef struct private_tnccs_20_t private_tnccs_20_t;
26
27 /**
28 * Recommendation entry
29 */
30 struct recommendation_entry_t {
31
32 /**
33 * IMV ID
34 */
35 TNC_IMVID id;
36
37 /**
38 * Action Recommendation provided by IMV instance
39 */
40 TNC_IMV_Action_Recommendation rec;
41
42 /**
43 * Evaluation Result provided by IMV instance
44 */
45 TNC_IMV_Evaluation_Result eval;
46 };
47
48 /**
49 * Private data of a tnccs_20_t object.
50 */
51 struct private_tnccs_20_t {
52
53 /**
54 * Public tls_t interface.
55 */
56 tls_t public;
57
58 /**
59 * TNCC if TRUE, TNCS if FALSE
60 */
61 bool is_server;
62
63 /**
64 * Connection ID assigned to this TNCCS connection
65 */
66 TNC_ConnectionID connection_id;
67
68 /**
69 * Batch being constructed
70 */
71 chunk_t batch;
72
73 /**
74 * Action Recommendations and Evaluations Results provided by IMVs
75 */
76 linked_list_t *recommendations;
77 };
78
79 METHOD(tnccs_t, send_message, void,
80 private_tnccs_20_t* this, TNC_BufferReference message,
81 TNC_UInt32 message_len,
82 TNC_MessageType message_type)
83 {
84 chunk_t msg = { message, message_len },
85 batch = this->batch;
86
87 DBG1(DBG_TNC, "TNCCS 2.0 send message");
88 this->batch = chunk_cat("mc", batch, msg);
89 }
90
91 METHOD(tnccs_t, provide_recommendation, void,
92 private_tnccs_20_t* this, TNC_IMVID id,
93 TNC_IMV_Action_Recommendation rec,
94 TNC_IMV_Evaluation_Result eval)
95 {
96 enumerator_t *enumerator;
97 recommendation_entry_t *entry;
98 bool found = FALSE;
99
100 DBG2(DBG_TNC, "IMV %u provides recommendation '%N' and evaluation '%N'",
101 id, action_recommendation_names, rec, evaluation_result_names, eval);
102
103 enumerator = this->recommendations->create_enumerator(this->recommendations);
104 while (enumerator->enumerate(enumerator, &entry))
105 {
106 if (entry->id == id)
107 {
108 found = TRUE;
109 break;
110 }
111 }
112 enumerator->destroy(enumerator);
113
114 if (!found)
115 {
116 entry = malloc_thing(recommendation_entry_t);
117 entry->id = id;
118 this->recommendations->insert_last(this->recommendations, entry);
119 }
120
121 /* Assign provided action recommendation and evaluation result */
122 entry->rec = rec;
123 entry->eval = eval;
124 }
125
126 METHOD(tls_t, process, status_t,
127 private_tnccs_20_t *this, void *buf, size_t buflen)
128 {
129 char *pos;
130 size_t len;
131
132 if (this->is_server && !this->connection_id)
133 {
134 this->connection_id = charon->tnccs->create_connection(charon->tnccs,
135 (tnccs_t*)this,
136 _send_message, _provide_recommendation);
137 charon->imvs->notify_connection_change(charon->imvs,
138 this->connection_id, TNC_CONNECTION_STATE_CREATE);
139 }
140 DBG1(DBG_TNC, "received TNCCS Batch (%u bytes) for Connection ID %u",
141 buflen, this->connection_id);
142 DBG3(DBG_TNC, "%.*s", buflen, buf);
143 pos = strchr(buf, '|');
144 if (pos)
145 {
146 pos++;
147 len = buflen - ((char*)buf - pos);
148 }
149 else
150 {
151 pos = buf;
152 len = buflen;
153 }
154 if (this->is_server)
155 {
156 charon->imvs->receive_message(charon->imvs, this->connection_id,
157 pos, len, 0x0080ab31);
158 charon->imvs->batch_ending(charon->imvs, this->connection_id);
159 }
160 else
161 {
162 charon->imcs->receive_message(charon->imcs, this->connection_id,
163 pos, len, 0x0080ab31);
164 charon->imcs->batch_ending(charon->imcs, this->connection_id);
165 }
166 return NEED_MORE;
167 }
168
169 METHOD(tls_t, build, status_t,
170 private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen)
171 {
172 char *msg = this->is_server ? "tncs->tncc 2.0|" : "tncc->tncs 2.0|";
173 size_t len;
174
175 this->batch = chunk_cat("cm", chunk_create(msg, strlen(msg)), this->batch);
176
177 if (!this->is_server && !this->connection_id)
178 {
179 this->connection_id = charon->tnccs->create_connection(charon->tnccs,
180 (tnccs_t*)this, _send_message, NULL);
181 charon->imcs->notify_connection_change(charon->imcs,
182 this->connection_id, TNC_CONNECTION_STATE_CREATE);
183 charon->imcs->notify_connection_change(charon->imcs,
184 this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
185 charon->imcs->begin_handshake(charon->imcs, this->connection_id);
186 }
187
188 len = this->batch.len;
189 *msglen = len;
190 *buflen = len;
191 memcpy(buf, this->batch.ptr, len);
192
193 DBG1(DBG_TNC, "sending TNCCS Batch (%d bytes) for Connection ID %u",
194 len, this->connection_id);
195 DBG3(DBG_TNC, "%.*s", len, buf);
196 chunk_free(&this->batch);
197
198 return ALREADY_DONE;
199 }
200
201 METHOD(tls_t, is_server, bool,
202 private_tnccs_20_t *this)
203 {
204 return this->is_server;
205 }
206
207 METHOD(tls_t, get_purpose, tls_purpose_t,
208 private_tnccs_20_t *this)
209 {
210 return TLS_PURPOSE_EAP_TNC;
211 }
212
213 METHOD(tls_t, is_complete, bool,
214 private_tnccs_20_t *this)
215 {
216 return FALSE;
217 }
218
219 METHOD(tls_t, get_eap_msk, chunk_t,
220 private_tnccs_20_t *this)
221 {
222 return chunk_empty;
223 }
224
225 METHOD(tls_t, destroy, void,
226 private_tnccs_20_t *this)
227 {
228 charon->tnccs->remove_connection(charon->tnccs, this->connection_id);
229 this->recommendations->destroy_function(this->recommendations, free);
230 free(this->batch.ptr);
231 free(this);
232 }
233
234 /**
235 * See header
236 */
237 tls_t *tnccs_20_create(bool is_server)
238 {
239 private_tnccs_20_t *this;
240
241 INIT(this,
242 .public = {
243 .process = _process,
244 .build = _build,
245 .is_server = _is_server,
246 .get_purpose = _get_purpose,
247 .is_complete = _is_complete,
248 .get_eap_msk = _get_eap_msk,
249 .destroy = _destroy,
250 },
251 .is_server = is_server,
252 .recommendations = linked_list_create(),
253 );
254
255 return &this->public;
256 }