moved recommendation handling to the tnc_imv plugin
[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 <threading/mutex.h>
21 #include <tnc/tncif.h>
22 #include <tnc/tnccs/tnccs.h>
23
24 typedef struct private_tnccs_20_t private_tnccs_20_t;
25
26 /**
27 * Private data of a tnccs_20_t object.
28 */
29 struct private_tnccs_20_t {
30
31 /**
32 * Public tls_t interface.
33 */
34 tls_t public;
35
36 /**
37 * TNCC if TRUE, TNCS if FALSE
38 */
39 bool is_server;
40
41 /**
42 * Connection ID assigned to this TNCCS connection
43 */
44 TNC_ConnectionID connection_id;
45
46 /**
47 * Batch being constructed
48 */
49 chunk_t batch;
50
51 /**
52 * Mutex locking the batch in construction
53 */
54 mutex_t *mutex;
55
56 /**
57 * Set of IMV recommendations (TNC Server only)
58 */
59 recommendations_t *recs;
60 };
61
62 METHOD(tnccs_t, send_message, void,
63 private_tnccs_20_t* this, TNC_BufferReference message,
64 TNC_UInt32 message_len,
65 TNC_MessageType message_type)
66 {
67 chunk_t msg = { message, message_len };
68
69 DBG1(DBG_TNC, "TNCCS 2.0 send message");
70 this->mutex->lock(this->mutex);
71 this->batch = chunk_cat("mc", this->batch, msg);
72 this->mutex->unlock(this->mutex);
73 }
74
75 METHOD(tls_t, process, status_t,
76 private_tnccs_20_t *this, void *buf, size_t buflen)
77 {
78 char *pos;
79 size_t len;
80
81 if (this->is_server && !this->connection_id)
82 {
83 this->connection_id = charon->tnccs->create_connection(charon->tnccs,
84 (tnccs_t*)this, _send_message, &this->recs);
85 if (!this->connection_id)
86 {
87 return FAILED;
88 }
89 charon->imvs->notify_connection_change(charon->imvs,
90 this->connection_id, TNC_CONNECTION_STATE_CREATE);
91 }
92 DBG1(DBG_TNC, "received TNCCS Batch (%u bytes) for Connection ID %u",
93 buflen, this->connection_id);
94 DBG3(DBG_TNC, "%.*s", buflen, buf);
95 pos = strchr(buf, '|');
96 if (pos)
97 {
98 pos++;
99 len = buflen - (pos - (char*)buf);
100 }
101 else
102 {
103 pos = buf;
104 len = buflen;
105 }
106 DBG1(DBG_TNC, "received message '%.*s'", len, pos);
107 if (this->is_server)
108 {
109 charon->imvs->receive_message(charon->imvs, this->connection_id,
110 pos, len, 0x0080ab31);
111 charon->imvs->batch_ending(charon->imvs, this->connection_id);
112 }
113 else
114 {
115 charon->imcs->receive_message(charon->imcs, this->connection_id,
116 pos, len, 0x0080ab31);
117 charon->imcs->batch_ending(charon->imcs, this->connection_id);
118 }
119 return NEED_MORE;
120 }
121
122 METHOD(tls_t, build, status_t,
123 private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen)
124 {
125 char *msg = this->is_server ? "tncs->tncc 2.0|" : "tncc->tncs 2.0|";
126 size_t len;
127
128 this->mutex->lock(this->mutex);
129 this->batch = chunk_cat("cm", chunk_create(msg, strlen(msg)), this->batch);
130 this->mutex->unlock(this->mutex);
131
132 if (!this->is_server && !this->connection_id)
133 {
134 this->connection_id = charon->tnccs->create_connection(charon->tnccs,
135 (tnccs_t*)this, _send_message, NULL);
136 if (!this->connection_id)
137 {
138 return FAILED;
139 }
140 charon->imcs->notify_connection_change(charon->imcs,
141 this->connection_id, TNC_CONNECTION_STATE_CREATE);
142 charon->imcs->notify_connection_change(charon->imcs,
143 this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
144 charon->imcs->begin_handshake(charon->imcs, this->connection_id);
145 }
146
147 this->mutex->lock(this->mutex);
148 len = this->batch.len;
149 *msglen = len;
150 *buflen = len;
151 memcpy(buf, this->batch.ptr, len);
152 chunk_free(&this->batch);
153 this->mutex->unlock(this->mutex);
154
155 DBG1(DBG_TNC, "sending TNCCS Batch (%d bytes) for Connection ID %u",
156 len, this->connection_id);
157 DBG3(DBG_TNC, "%.*s", len, buf);
158
159 return ALREADY_DONE;
160 }
161
162 METHOD(tls_t, is_server, bool,
163 private_tnccs_20_t *this)
164 {
165 return this->is_server;
166 }
167
168 METHOD(tls_t, get_purpose, tls_purpose_t,
169 private_tnccs_20_t *this)
170 {
171 return TLS_PURPOSE_EAP_TNC;
172 }
173
174 METHOD(tls_t, is_complete, bool,
175 private_tnccs_20_t *this)
176 {
177 TNC_IMV_Action_Recommendation rec;
178 TNC_IMV_Evaluation_Result eval;
179
180 if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
181 {
182 return charon->imvs->enforce_recommendation(charon->imvs, rec);
183 }
184 else
185 {
186 return FALSE;
187 }
188 }
189
190 METHOD(tls_t, get_eap_msk, chunk_t,
191 private_tnccs_20_t *this)
192 {
193 return chunk_empty;
194 }
195
196 METHOD(tls_t, destroy, void,
197 private_tnccs_20_t *this)
198 {
199 charon->tnccs->remove_connection(charon->tnccs, this->connection_id);
200 this->mutex->destroy(this->mutex);
201 free(this->batch.ptr);
202 free(this);
203 }
204
205 /**
206 * See header
207 */
208 tls_t *tnccs_20_create(bool is_server)
209 {
210 private_tnccs_20_t *this;
211
212 INIT(this,
213 .public = {
214 .process = _process,
215 .build = _build,
216 .is_server = _is_server,
217 .get_purpose = _get_purpose,
218 .is_complete = _is_complete,
219 .get_eap_msk = _get_eap_msk,
220 .destroy = _destroy,
221 },
222 .is_server = is_server,
223 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
224 );
225
226 return &this->public;
227 }