The SILC Project

source navigation ]
identifier search ]
freetext search ]
file search ]

silc/lib/silccore/silcchannel.c

  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