X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilccore%2Fsilcargument.c;h=eac8bdf60e72d5dfef128924ba389df5fbee842f;hb=52e57c880aba9c5e89f59d962eb9af75670b76e0;hp=4fe9b7c41ed0c3cc4724b3815d64e7b1e1076f74;hpb=0f0340b9fbce9704cc7171f8f0104ce9103d2de6;p=silc.git diff --git a/lib/silccore/silcargument.c b/lib/silccore/silcargument.c index 4fe9b7c4..eac8bdf6 100644 --- a/lib/silccore/silcargument.c +++ b/lib/silccore/silcargument.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2005 Pekka Riikonen + Copyright (C) 2001 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,14 +19,10 @@ /* Implementation of Argument Payload routines */ /* $Id$ */ -#include "silcincludes.h" +#include "silc.h" #include "silcargument.h" -/****************************************************************************** - - Argument Payload - -******************************************************************************/ +/*************************** Argument Payload *******************************/ struct SilcArgumentPayloadStruct { SilcUInt32 argc; @@ -71,8 +67,10 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload, SILC_STR_UI_SHORT(&p_len), SILC_STR_UI_CHAR(&arg_type), SILC_STR_END); - if (ret == -1 || p_len > silc_buffer_len(&buffer) - 3) + if (ret == -1 || p_len > silc_buffer_len(&buffer) - 3) { + SILC_LOG_DEBUG(("Malformed argument payload")); goto err; + } newp->argv_lens[i] = p_len; newp->argv_types[i] = arg_type; @@ -83,8 +81,10 @@ SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload, SILC_STR_UI_XNSTRING_ALLOC(&newp->argv[i], p_len), SILC_STR_END); - if (ret == -1) + if (ret == -1) { + SILC_LOG_DEBUG(("Malformed argument payload")); goto err; + } silc_buffer_pull(&buffer, p_len); pull_len += 3 + p_len; @@ -162,7 +162,8 @@ SilcBuffer silc_argument_payload_encode_one(SilcBuffer args, len = 3 + (SilcUInt16)arg_len; buffer = silc_buffer_realloc(buffer, - (buffer ? silc_buffer_truelen(buffer) + len : len)); + (buffer ? silc_buffer_truelen(buffer) + + len : len)); if (!buffer) return NULL; silc_buffer_pull(buffer, silc_buffer_len(buffer)); @@ -296,3 +297,205 @@ unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload, return payload->argv[i]; } + +/* Return argument already decoded */ + +static SilcBool silc_argument_decode(unsigned char *data, + SilcUInt32 data_len, + SilcArgumentDecodeType dec_type, + void *ret_arg, + void **ret_arg_alloc) +{ + switch (dec_type) { + + case SILC_ARGUMENT_ID: + if (ret_arg) + if (!silc_id_payload_parse_id(data, data_len, (SilcID *)ret_arg)) + return FALSE; + + if (ret_arg_alloc) { + SilcID id; + if (!silc_id_payload_parse_id(data, data_len, &id)) + return FALSE; + *ret_arg_alloc = silc_memdup(&id, sizeof(id)); + } + break; + + case SILC_ARGUMENT_PUBLIC_KEY: + { + SilcPublicKey public_key; + + if (!ret_arg_alloc) + return FALSE; + + if (!silc_public_key_payload_decode(data, data_len, &public_key)) + return FALSE; + + *ret_arg_alloc = public_key; + } + break; + + case SILC_ARGUMENT_ATTRIBUTES: + if (!ret_arg_alloc) + return FALSE; + + *ret_arg_alloc = silc_attribute_payload_parse(data, data_len); + break; + + case SILC_ARGUMENT_UINT32: + if (data_len != 4) + return FALSE; + + if (ret_arg) { + SilcUInt32 *i = ret_arg; + SILC_GET32_MSB(*i, data); + } + + if (ret_arg_alloc) { + SilcUInt32 i; + SILC_GET32_MSB(i, data); + *ret_arg_alloc = silc_memdup(&i, sizeof(i)); + } + break; + + case SILC_ARGUMENT_BOOL: + if (data_len != sizeof(SilcBool)) + return FALSE; + + if (ret_arg) { + SilcBool *b = ret_arg; + *b = (data[0] == 0x01 ? TRUE : FALSE); + } + + if (ret_arg_alloc) { + SilcBool b; + b = (data[0] == 0x01 ? TRUE : FALSE); + *ret_arg_alloc = silc_memdup(&b, sizeof(b)); + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +/* Return argument already decoded */ + +SilcBool silc_argument_get_decoded(SilcArgumentPayload payload, + SilcUInt32 type, + SilcArgumentDecodeType dec_type, + void *ret_arg, + void **ret_arg_alloc) +{ + unsigned char *tmp; + SilcUInt32 tmp_len; + + tmp = silc_argument_get_arg_type(payload, type, &tmp_len); + if (!tmp) + return FALSE; + + return silc_argument_decode(tmp, tmp_len, dec_type, ret_arg, ret_arg_alloc); +} + +/************************* Argument List Payload ****************************/ + +/* Parses argument payload list */ + +SilcArgumentPayload +silc_argument_list_parse(const unsigned char *payload, + SilcUInt32 payload_len) +{ + SilcArgumentPayload arg; + SilcUInt16 argc; + + if (payload_len < 5) + return NULL; + + SILC_GET16_MSB(argc, payload); + + arg = silc_argument_payload_parse(payload + 2, payload_len - 2, argc); + + return arg; +} + +/* Parses argument payload list of specific argument types */ + +SilcDList +silc_argument_list_parse_decoded(const unsigned char *payload, + SilcUInt32 payload_len, + SilcArgumentDecodeType dec_type) +{ + SilcArgumentPayload arg; + SilcArgumentDecodedList dec; + unsigned char *data; + SilcUInt32 data_len, type; + SilcDList list; + + arg = silc_argument_list_parse(payload, payload_len); + if (!arg) + return NULL; + + list = silc_dlist_init(); + if (!list) { + silc_argument_payload_free(arg); + return NULL; + } + + data = silc_argument_get_first_arg(arg, &type, &data_len); + while (data) { + dec = silc_calloc(1, sizeof(*dec)); + if (!dec) + continue; + dec->arg_type = type; + if (silc_argument_decode(data, data_len, dec_type, NULL, &dec->argument)) + silc_dlist_add(list, dec); + else + silc_free(dec); + data = silc_argument_get_next_arg(arg, &type, &data_len); + } + + silc_argument_payload_free(arg); + + silc_dlist_start(list); + + return list; +} + +/* Free decoded argument payload list */ + +void silc_argument_list_free(SilcDList list, SilcArgumentDecodeType dec_type) +{ + SilcArgumentDecodedList dec; + + if (!list) + return; + + silc_dlist_start(list); + while ((dec = silc_dlist_get(list))) { + switch (dec_type) { + + case SILC_ARGUMENT_ID: + case SILC_ARGUMENT_UINT32: + case SILC_ARGUMENT_BOOL: + silc_free(dec->argument); + break; + + case SILC_ARGUMENT_PUBLIC_KEY: + silc_pkcs_public_key_free(dec->argument); + break; + + case SILC_ARGUMENT_ATTRIBUTES: + silc_attribute_payload_free(dec->argument); + break; + + default: + break; + } + + silc_free(dec); + } + + silc_dlist_uninit(list); +}