libprelude/master: Prevent unsafe modification of Libprelude provided Analyzer object
[email protected] Wed, 20 Jan 2010 16:16:09 +0100 (CET)
| Newsgroups | gmane.comp.security.ids.prelude.cvs |
|---|---|
| Message-ID | <[email protected]> |
commit 6d43c53505a3071d4b66e4d2a4aa13a56bb80934 Author: Yoann Vandoorselaere <[email protected]> Date: Wed Jan 20 15:51:54 2010 +0100 Prevent unsafe modification of Libprelude provided Analyzer object Modifying the idmef_node_t or idmef_address_t object within an idmef_analyzer_t retrieved through prelude_client_get_analyzer() could result in undefined behavior when the analyzer was later accessed through the administrative console. ======================================== src/include/prelude-option.h | 15 +++-- src/prelude-client.c | 136 +++++++++++++++++++++++++++++++++++------- src/prelude-option.c | 13 ++++ 3 files changed, 137 insertions(+), 27 deletions(-) ======================================== diff --git a/src/include/prelude-option.h b/src/include/prelude-option.h index 7d15835..2506a94 100644 --- a/src/include/prelude-option.h +++ b/src/include/prelude-option.h @@ -40,18 +40,18 @@ typedef enum { PRELUDE_OPTION_TYPE_DESTROY = 0x20 } prelude_option_type_t; - + typedef enum { PRELUDE_OPTION_INPUT_TYPE_STRING = 1, PRELUDE_OPTION_INPUT_TYPE_INTEGER = 2, PRELUDE_OPTION_INPUT_TYPE_BOOLEAN = 3 } prelude_option_input_type_t; - + typedef struct prelude_option prelude_option_t; typedef struct prelude_option_context prelude_option_context_t; -typedef int (*prelude_option_destroy_callback_t)(prelude_option_t *opt, prelude_string_t *out, void *context); +typedef int (*prelude_option_destroy_callback_t)(prelude_option_t *opt, prelude_string_t *out, void *context); typedef int (*prelude_option_commit_callback_t)(prelude_option_t *opt, prelude_string_t *out, void *context); typedef int (*prelude_option_get_callback_t)(prelude_option_t *opt, prelude_string_t *out, void *context); typedef int (*prelude_option_set_callback_t)(prelude_option_t *opt, const char *optarg, prelude_string_t *err, void *context); @@ -170,7 +170,7 @@ prelude_option_t *prelude_option_get_parent(prelude_option_t *opt); void prelude_option_set_destroy_callback(prelude_option_t *opt, prelude_option_destroy_callback_t destroy); - + prelude_option_destroy_callback_t prelude_option_get_destroy_callback(prelude_option_t *opt); @@ -195,14 +195,17 @@ int prelude_option_new_context(prelude_option_t *opt, prelude_option_context_t * void prelude_option_context_destroy(prelude_option_context_t *oc); +void *prelude_option_context_get_data(prelude_option_context_t *oc); + +void prelude_option_context_set_data(prelude_option_context_t *oc, void *data); prelude_option_t *prelude_option_search(prelude_option_t *parent, const char *name, prelude_option_type_t type, prelude_bool_t walk_children); prelude_option_context_t *prelude_option_search_context(prelude_option_t *opt, const char *name); - + #ifdef __cplusplus } #endif - + #endif /* _LIBPRELUDE_PRELUDE_GETOPT_H */ diff --git a/src/prelude-client.c b/src/prelude-client.c index 5fc7f66..17ffead 100644 --- a/src/prelude-client.c +++ b/src/prelude-client.c @@ -90,6 +90,13 @@ +typedef struct { + prelude_client_t *client; + idmef_address_t *addr; + idmef_address_t *idmef_addr; +} node_address_data_t; + + struct prelude_client { int refcount; @@ -498,12 +505,13 @@ static int fill_client_infos(prelude_client_t *client, const char *program) static int set_node_address_category(prelude_option_t *opt, const char *optarg, prelude_string_t *err, void *context) { idmef_address_category_t category; + node_address_data_t *data = context; category = idmef_address_category_to_numeric(optarg); if ( category < 0 ) return category; - idmef_address_set_category(context, category); + idmef_address_set_category(data->addr, category); return 0; } @@ -512,7 +520,8 @@ static int set_node_address_category(prelude_option_t *opt, const char *optarg, static int get_node_address_category(prelude_option_t *opt, prelude_string_t *out, void *context) { - idmef_address_category_t category = idmef_address_get_category(context); + node_address_data_t *data = context; + idmef_address_category_t category = idmef_address_get_category(data->addr); return prelude_string_cat(out, idmef_address_category_to_string(category)); } @@ -520,10 +529,12 @@ static int get_node_address_category(prelude_option_t *opt, prelude_string_t *ou static int set_node_address_vlan_num(prelude_option_t *opt, const char *optarg, prelude_string_t *err, void *context) { + node_address_data_t *data = context; + if ( ! optarg ) - idmef_address_unset_vlan_num(context); + idmef_address_unset_vlan_num(data->addr); else - idmef_address_set_vlan_num(context, atoi(optarg)); + idmef_address_set_vlan_num(data->addr, atoi(optarg)); return 0; } @@ -533,8 +544,9 @@ static int set_node_address_vlan_num(prelude_option_t *opt, const char *optarg, static int get_node_address_vlan_num(prelude_option_t *opt, prelude_string_t *out, void *context) { int32_t *num; + node_address_data_t *data = context; - num = idmef_address_get_vlan_num(context); + num = idmef_address_get_vlan_num(data->addr); if ( num ) return prelude_string_sprintf(out, "%" PRELUDE_PRId32, *num); @@ -547,6 +559,7 @@ static int set_node_address_vlan_name(prelude_option_t *opt, const char *optarg, { int ret; prelude_string_t *str = NULL; + node_address_data_t *data = context; if ( optarg ) { ret = prelude_string_new_dup(&str, optarg); @@ -554,7 +567,7 @@ static int set_node_address_vlan_name(prelude_option_t *opt, const char *optarg, return ret; } - idmef_address_set_vlan_name(context, str); + idmef_address_set_vlan_name(data->addr, str); return 0; } @@ -564,8 +577,9 @@ static int set_node_address_vlan_name(prelude_option_t *opt, const char *optarg, static int get_node_address_vlan_name(prelude_option_t *opt, prelude_string_t *out, void *context) { prelude_string_t *str; + node_address_data_t *data = context; - str = idmef_address_get_vlan_name(context); + str = idmef_address_get_vlan_name(data->addr); if ( ! str ) return 0; @@ -578,6 +592,7 @@ static int set_node_address_address(prelude_option_t *opt, const char *optarg, p { int ret; prelude_string_t *str = NULL; + node_address_data_t *data = context; if ( optarg ) { ret = prelude_string_new_dup(&str, optarg); @@ -585,7 +600,7 @@ static int set_node_address_address(prelude_option_t *opt, const char *optarg, p return ret; } - idmef_address_set_address(context, str); + idmef_address_set_address(data->addr, str); return 0; } @@ -594,8 +609,9 @@ static int set_node_address_address(prelude_option_t *opt, const char *optarg, p static int get_node_address_address(prelude_option_t *opt, prelude_string_t *out, void *context) { prelude_string_t *str; + node_address_data_t *data = context; - str = idmef_address_get_address(context); + str = idmef_address_get_address(data->addr); if ( ! str ) return 0; @@ -608,6 +624,7 @@ static int set_node_address_netmask(prelude_option_t *opt, const char *optarg, p { int ret; prelude_string_t *str = NULL; + node_address_data_t *data = context; if ( optarg ) { ret = prelude_string_new_dup(&str, optarg); @@ -615,7 +632,7 @@ static int set_node_address_netmask(prelude_option_t *opt, const char *optarg, p return ret; } - idmef_address_set_netmask(context, str); + idmef_address_set_netmask(data->addr, str); return 0; } @@ -624,8 +641,9 @@ static int set_node_address_netmask(prelude_option_t *opt, const char *optarg, p static int get_node_address_netmask(prelude_option_t *opt, prelude_string_t *out, void *context) { prelude_string_t *str; + node_address_data_t *data = context; - str = idmef_address_get_netmask(context); + str = idmef_address_get_netmask(data->addr); if ( ! str ) return 0; @@ -634,35 +652,110 @@ static int get_node_address_netmask(prelude_option_t *opt, prelude_string_t *out + static int set_node_address(prelude_option_t *opt, const char *optarg, prelude_string_t *err, void *context) { int ret; - idmef_node_t *node; - idmef_address_t *addr; + node_address_data_t *data; prelude_option_context_t *octx; prelude_client_t *ptr = context; - if ( prelude_option_search_context(opt, optarg) ) + octx = prelude_option_search_context(opt, optarg); + if ( octx ) return 0; - ret = idmef_analyzer_new_node(ptr->analyzer, &node); + data = malloc(sizeof(*data)); + if ( ! data ) + return prelude_error_from_errno(errno); + + data->client = ptr; + data->idmef_addr = NULL; + + ret = idmef_address_new(&data->addr); + if ( ret < 0 ) { + free(data); + return ret; + } + + ret = prelude_option_new_context(opt, &octx, optarg, data); + if ( ret < 0 ) { + idmef_address_destroy(data->addr); + free(data); + } + + return ret; +} + + +static int commit_node_address(prelude_option_t *opt, prelude_string_t *out, void *context) +{ + int ret; + idmef_node_t *node; + idmef_analyzer_t *analyzer; + idmef_address_t *addr = NULL, *naddr; + node_address_data_t *data = context; + + ret = idmef_analyzer_new_node(data->client->analyzer, &node); if ( ret < 0 ) return ret; - ret = idmef_node_new_address(node, &addr, -1); + if ( node && data->idmef_addr ) { + while ( (addr = idmef_node_get_next_address(node, addr)) ) { + if ( addr == data->idmef_addr ) { + idmef_address_destroy(addr); + break; + } + } + } + + ret = idmef_address_clone(data->addr, &naddr); if ( ret < 0 ) - return -1; + return ret; - return prelude_option_new_context(opt, &octx, optarg, addr); -} + data->idmef_addr = naddr; + idmef_node_set_address(node, naddr, -1); + + if ( data->client->_analyzer_copy ) { + ret = idmef_analyzer_clone(data->client->analyzer, &analyzer); + if ( ret < 0 ) + return ret; + idmef_analyzer_destroy(data->client->_analyzer_copy); + data->client->_analyzer_copy = analyzer; + } + + return 0; +} static int destroy_node_address(prelude_option_t *opt, prelude_string_t *out, void *context) { - idmef_address_t *addr = context; + int ret; + idmef_node_t *node; + idmef_analyzer_t *analyzer; + idmef_address_t *addr = NULL; + node_address_data_t *data = context; + + node = idmef_analyzer_get_node(data->client->analyzer); + if ( node ) { + while ( (addr = idmef_node_get_next_address(node, addr)) ) { + if ( addr == data->idmef_addr ) { + idmef_address_destroy(addr); + break; + } + } + } + + if ( data->client->_analyzer_copy ) { + ret = idmef_analyzer_clone(data->client->analyzer, &analyzer); + if ( ret == 0 ) { + idmef_analyzer_destroy(data->client->_analyzer_copy); + data->client->_analyzer_copy = analyzer; + } + } - idmef_address_destroy(addr); + idmef_address_destroy(data->addr); + free(data); return 0; } @@ -1097,6 +1190,7 @@ int _prelude_client_register_options(void) if ( ret < 0 ) return ret; + prelude_option_set_commit_callback(opt, commit_node_address); prelude_option_set_destroy_callback(opt, destroy_node_address); ret = prelude_option_add(opt, NULL, PRELUDE_OPTION_TYPE_CFG|PRELUDE_OPTION_TYPE_WIDE, 0, "address", diff --git a/src/prelude-option.c b/src/prelude-option.c index 72364ad..61b7b1e 100644 --- a/src/prelude-option.c +++ b/src/prelude-option.c @@ -1610,6 +1610,19 @@ int prelude_option_new_context(prelude_option_t *opt, prelude_option_context_t * } +void prelude_option_context_set_data(prelude_option_context_t *oc, void *data) +{ + oc->data = data; +} + + + +void *prelude_option_context_get_data(prelude_option_context_t *oc) +{ + return oc->data; +} + + void prelude_option_context_destroy(prelude_option_context_t *oc) { _______________________________________________ Prelude-cvslog site list [email protected] http://lists.prelude-ids.org/mailman/listinfo/prelude-cvslog