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