1 /*
2
3 silcchannel.c
4
5 Author: Pekka Riikonen <priikone@silcnet.org>
6
7 Copyright (C) 1997 - 2005 Pekka Riikonen
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 */
19 /* Channel Payload and Channel Key Payload implementations. */
20 /* $Id: silcchannel.c,v 1.44 2005/12/28 14:19:06 priikone Exp $ */
21
22 #include "silc.h"
23 #include "silcchannel.h"
24
25 /******************************************************************************
26
27 Channel Payload
28
29 ******************************************************************************/
30
31 /* Channel Message Payload structure. Contents of this structure is parsed
32 from SILC packets. */
33 struct SilcChannelPayloadStruct {
34 unsigned char *channel_name;
35 unsigned char *channel_id;
36 SilcUInt32 mode;
37 SilcUInt16 name_len;
38 SilcUInt16 id_len;
39 };
40
41 /* Parses channel payload returning new channel payload structure. */
42
43 SilcChannelPayload silc_channel_payload_parse(const unsigned char *payload,
44 SilcUInt32 payload_len)
45 {
46 SilcBufferStruct buffer;
47 SilcChannelPayload newp;
48 int ret;
49
50 SILC_LOG_DEBUG(("Parsing channel payload"));
51
52 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
53 newp = silc_calloc(1, sizeof(*newp));
54 if (!newp)
55 return NULL;
56
57 /* Parse the Channel Payload. Ignore the padding. */
58 ret = silc_buffer_unformat(&buffer,
59 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_name,
60 &newp->name_len),
61 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_id,
62 &newp->id_len),
63 SILC_STR_UI_INT(&newp->mode),
64 SILC_STR_END);
65 if (ret == -1)
66 goto err;
67
68 if ((newp->name_len < 1 || newp->name_len > silc_buffer_len(&buffer) - 8) ||
69 (newp->id_len < 1 || newp->id_len > silc_buffer_len(&buffer) - 8) ||
70 (newp->id_len + newp->name_len > silc_buffer_len(&buffer) - 8)) {
71 SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
72 goto err;
73 }
74
75 return newp;
76
77 err:
78 silc_channel_payload_free(newp);
79 return NULL;
80 }
81
82 /* Parses list of channel payloads returning list of payloads. */
83
84 SilcDList silc_channel_payload_parse_list(const unsigned char *payload,
85 SilcUInt32 payload_len)
86 {
87 SilcBufferStruct buffer;
88 SilcDList list;
89 SilcChannelPayload newp;
90 SilcUInt32 len;
91 int ret;
92
93 SILC_LOG_DEBUG(("Parsing channel payload list"));
94
95 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
96 list = silc_dlist_init();
97
98 while (silc_buffer_len(&buffer)) {
99 newp = silc_calloc(1, sizeof(*newp));
100 if (!newp)
101 goto err;
102 ret = silc_buffer_unformat(&buffer,
103 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_name,
104 &newp->name_len),
105 SILC_STR_UI16_NSTRING_ALLOC(&newp->channel_id,
106 &newp->id_len),
107 SILC_STR_UI_INT(&newp->mode),
108 SILC_STR_END);
109 if (ret == -1)
110 goto err;
111
112 if ((newp->name_len < 1 || newp->name_len > silc_buffer_len(&buffer) - 8) ||
113 (newp->id_len < 1 || newp->id_len > silc_buffer_len(&buffer) - 8) ||
114 (newp->id_len + newp->name_len > silc_buffer_len(&buffer) - 8)) {
115 SILC_LOG_ERROR(("Incorrect channel payload in packet, packet dropped"));
116 goto err;
117 }
118
119 len = 2 + newp->name_len + 2 + newp->id_len + 4;
120 if (silc_buffer_len(&buffer) < len)
121 break;
122 silc_buffer_pull(&buffer, len);
123
124 silc_dlist_add(list, newp);
125 }
126
127 return list;
128
129 err:
130 silc_channel_payload_list_free(list);
131 return NULL;
132 }
133
134 /* Encode new channel payload and returns it as buffer. */
135
136 SilcBuffer silc_channel_payload_encode(const unsigned char *channel_name,
137 SilcUInt16 channel_name_len,
138 const unsigned char *channel_id,
139 SilcUInt32 channel_id_len,
140 SilcUInt32 mode)
141 {
142 SilcBuffer buffer;
143
144 SILC_LOG_DEBUG(("Encoding message payload"));
145
146 buffer = silc_buffer_alloc_size(2 + channel_name_len + 2 +
147 channel_id_len + 4);
148 if (!buffer)
149 return NULL;
150
151 /* Encode the Channel Payload */
152 silc_buffer_format(buffer,
153 SILC_STR_UI_SHORT(channel_name_len),
154 SILC_STR_UI_XNSTRING(channel_name, channel_name_len),
155 SILC_STR_UI_SHORT(channel_id_len),
156 SILC_STR_UI_XNSTRING(channel_id, channel_id_len),
157 SILC_STR_UI_INT(mode),
158 SILC_STR_END);
159
160 return buffer;
161 }
162
163 /* Frees Channel Payload */
164
165 void silc_channel_payload_free(SilcChannelPayload payload)
166 {
167 silc_free(payload->channel_name);
168 silc_free(payload->channel_id);
169 silc_free(payload);
170 }
171
172 /* Free's list of Channel Payloads */
173
174 void silc_channel_payload_list_free(SilcDList list)
175 {
176 SilcChannelPayload entry;
177
178 silc_dlist_start(list);
179 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
180 silc_free(entry->channel_name);
181 silc_free(entry->channel_id);
182 silc_dlist_del(list, entry);
183 silc_free(entry);
184 }
185
186 silc_dlist_uninit(list);
187 }
188
189 /* Return the channel name */
190
191 unsigned char *silc_channel_get_name(SilcChannelPayload payload,
192 SilcUInt32 *channel_name_len)
193 {
194 if (channel_name_len)
195 *channel_name_len = payload->name_len;
196
197 return payload->channel_name;
198 }
199
200 /* Return the channel ID */
201
202 unsigned char *silc_channel_get_id(SilcChannelPayload payload,
203 SilcUInt32 *channel_id_len)
204 {
205 if (channel_id_len)
206 *channel_id_len = payload->id_len;
207
208 return payload->channel_id;
209 }
210
211 /* Return the channel ID as parsed ID. */
212
213 SilcBool silc_channel_get_id_parse(SilcChannelPayload payload,
214 SilcChannelID *ret_channel_id)
215 {
216 return silc_id_str2id(payload->channel_id, payload->id_len,
217 SILC_ID_CHANNEL, ret_channel_id,
218 sizeof(SilcChannelID));
219 }
220
221 /* Return the mode. The mode is arbitrary. It can be the mode of the
222 channel or perhaps the mode of the client on the channel. The protocol
223 dictates what the usage of the mode is in different circumstances. */
224
225 SilcUInt32 silc_channel_get_mode(SilcChannelPayload payload)
226 {
227 return payload->mode;
228 }
229
230
231 /******************************************************************************
232
233 Channel Key Payload
234
235 ******************************************************************************/
236
237 /* Channel Key Payload structrue. Channel keys are parsed from SILC
238 packets into this structure. */
239 struct SilcChannelKeyPayloadStruct {
240 unsigned char *id;
241 unsigned char *cipher;
242 unsigned char *key;
243 SilcUInt16 id_len;
244 SilcUInt16 cipher_len;
245 SilcUInt16 key_len;
246 };
247
248 /* Parses channel key payload returning new channel key payload structure */
249
250 SilcChannelKeyPayload
251 silc_channel_key_payload_parse(const unsigned char *payload,
252 SilcUInt32 payload_len)
253 {
254 SilcBufferStruct buffer;
255 SilcChannelKeyPayload newp;
256 int ret;
257
258 SILC_LOG_DEBUG(("Parsing channel key payload"));
259
260 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
261 newp = silc_calloc(1, sizeof(*newp));
262 if (!newp)
263 return NULL;
264
265 /* Parse the Channel Key Payload */
266 ret =
267 silc_buffer_unformat(&buffer,
268 SILC_STR_UI16_NSTRING_ALLOC(&newp->id, &newp->id_len),
269 SILC_STR_UI16_NSTRING_ALLOC(&newp->cipher,
270 &newp->cipher_len),
271 SILC_STR_UI16_NSTRING_ALLOC(&newp->key,
272 &newp->key_len),
273 SILC_STR_END);
274 if (ret == -1)
275 goto err;
276
277 if (newp->id_len < 1 || newp->key_len < 1 || newp->cipher_len < 1 ||
278 newp->id_len + newp->cipher_len + newp->key_len > silc_buffer_len(&buffer) - 6) {
279 SILC_LOG_ERROR(("Incorrect channel key payload in packet"));
280 goto err;
281 }
282
283 return newp;
284
285 err:
286 if (newp->id)
287 silc_free(newp->id);
288 if (newp->cipher)
289 silc_free(newp->cipher);
290 if (newp->key)
291 silc_free(newp->key);
292 silc_free(newp);
293 return NULL;
294 }
295
296 /* Encodes channel key payload into a buffer and returns it. This is used
297 to add channel key payload into a packet. */
298
299 SilcBuffer silc_channel_key_payload_encode(SilcUInt16 id_len,
300 const unsigned char *id,
301 SilcUInt16 cipher_len,
302 const unsigned char *cipher,
303 SilcUInt16 key_len,
304 const unsigned char *key)
305 {
306 SilcBuffer buffer;
307 SilcUInt32 len;
308
309 SILC_LOG_DEBUG(("Encoding channel key payload"));
310
311 /* Allocate channel payload buffer. Length is 2 + id + 2 + key +
312 2 + cipher */
313 len = 2 + id_len + 2 + key_len + 2 + cipher_len;
314 buffer = silc_buffer_alloc_size(len);
315 if (!buffer)
316 return NULL;
317
318 /* Encode the Channel Payload */
319 silc_buffer_format(buffer,
320 SILC_STR_UI_SHORT(id_len),
321 SILC_STR_UI_XNSTRING(id, id_len),
322 SILC_STR_UI_SHORT(cipher_len),
323 SILC_STR_UI_XNSTRING(cipher, cipher_len),
324 SILC_STR_UI_SHORT(key_len),
325 SILC_STR_UI_XNSTRING(key, key_len),
326 SILC_STR_END);
327
328 return buffer;
329 }
330
331 /* Frees Channel Key Payload */
332
333 void silc_channel_key_payload_free(SilcChannelKeyPayload payload)
334 {
335 if (payload) {
336 silc_free(payload->id);
337 silc_free(payload->cipher);
338 if (payload->key) {
339 memset(payload->key, 0, payload->key_len);
340 silc_free(payload->key);
341 }
342 silc_free(payload);
343 }
344 }
345
346 /* Return ID */
347
348 unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload,
349 SilcUInt32 *id_len)
350 {
351 if (id_len)
352 *id_len = payload->id_len;
353
354 return payload->id;
355 }
356
357 /* Return cipher name */
358
359 unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload,
360 SilcUInt32 *cipher_len)
361 {
362 if (cipher_len)
363 *cipher_len = payload->cipher_len;
364
365 return payload->cipher;
366 }
367
368 /* Return key */
369
370 unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload,
371 SilcUInt32 *key_len)
372 {
373 if (key_len)
374 *key_len = payload->key_len;
375
376 return payload->key;
377 }
378
This page was automatically generated by the LXR engine.
Free-text search provided by Glimpse