diff --git a/libkmipclient/https.c b/libkmipclient/https.c index 2cea1276..c01e13f1 100644 --- a/libkmipclient/https.c +++ b/libkmipclient/https.c @@ -735,7 +735,8 @@ int kmip_connection_https_perform(struct kmip_connection *conn, switch (conn->config.encoding) { case KMIP_ENCODING_TTLV: rc = kmip_decode_ttlv(write_cb.ttlv.resp_mem_bio, NULL, - response, debug); + response, KMIP_DECODE_MAX_NESTING_LEVEL, + debug); if (rc != 0) { kmip_debug(debug, "kmip_decode_ttlv failed"); goto out; @@ -750,7 +751,7 @@ int kmip_connection_https_perform(struct kmip_connection *conn, } rc = kmip_decode_json(write_cb.json.resp_obj, NULL, response, - debug); + KMIP_DECODE_MAX_NESTING_LEVEL, debug); if (rc != 0) { kmip_debug(debug, "kmip_decode_json failed"); goto out; @@ -768,7 +769,8 @@ int kmip_connection_https_perform(struct kmip_connection *conn, rc = kmip_decode_xml(xmlDocGetRootElement( write_cb.xml.ctx->myDoc), - NULL, response, debug); + NULL, response, + KMIP_DECODE_MAX_NESTING_LEVEL, debug); if (rc != 0) { kmip_debug(debug, "kmip_decode_xml failed"); goto out; diff --git a/libkmipclient/json.c b/libkmipclient/json.c index 78337192..53beb236 100644 --- a/libkmipclient/json.c +++ b/libkmipclient/json.c @@ -27,12 +27,16 @@ * @param parent the parent node or NULL if no parent exists. * @param node On return: the decoded node. The newly allocated * node has a reference count of 1. + * @param max_nesting_level the maximum nesting levels of structures within the + * KMIP node. If the nesting level is reached, E2BIG + * is returned. * @param debug if true, debug messages are printed * * @returns 0 in case of success, or a negative errno value */ int kmip_decode_json(const json_object *obj, struct kmip_node *parent, - struct kmip_node **node, bool debug) + struct kmip_node **node, size_t max_nesting_level, + bool debug) { json_object *tag_obj, *type_obj, *value_obj, *name_obj; enum kmip_tag tag, v1_attr_tag = 0; @@ -42,6 +46,9 @@ int kmip_decode_json(const json_object *obj, struct kmip_node *parent, int rc, num, i; int64_t int64; + if (max_nesting_level == 0) + return -E2BIG; + if (obj == NULL || node == NULL) return -EINVAL; @@ -138,7 +145,7 @@ int kmip_decode_json(const json_object *obj, struct kmip_node *parent, for (i = 0; i < num; i++) { rc = kmip_decode_json( json_object_array_get_idx(value_obj, i), - n, &e, debug); + n, &e, max_nesting_level - 1, debug); if (rc != 0) { kmip_debug(debug, "Failed to parse " "array element %d", i); diff --git a/libkmipclient/kmip.h b/libkmipclient/kmip.h index 3344cb01..158123e0 100644 --- a/libkmipclient/kmip.h +++ b/libkmipclient/kmip.h @@ -94,19 +94,23 @@ int kmip_connection_https_perform(struct kmip_connection *connection, bool debug); void kmip_connection_https_term(struct kmip_connection *connection); -/* KIMP decoding and encoding internal functions */ +/* KIMP decoding and encoding internal functions and definitions */ +#define KMIP_DECODE_MAX_NESTING_LEVEL 32 + int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node, - bool debug); + size_t max_nesting_level, bool debug); int kmip_encode_ttlv(struct kmip_node *node, BIO *bio, size_t *size, bool debug); int kmip_decode_json(const json_object *obj, struct kmip_node *parent, - struct kmip_node **node, bool debug); + struct kmip_node **node, size_t max_nesting_level, + bool debug); int kmip_encode_json(const struct kmip_node *node, json_object **obj, bool debug); int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent, - struct kmip_node **node, bool debug); + struct kmip_node **node, size_t max_nesting_level, + bool debug); int kmip_encode_xml(const struct kmip_node *node, xmlNode **xml, bool debug); #endif diff --git a/libkmipclient/tls.c b/libkmipclient/tls.c index 682ad1c4..d42d1fec 100644 --- a/libkmipclient/tls.c +++ b/libkmipclient/tls.c @@ -493,7 +493,8 @@ int kmip_connection_tls_perform(struct kmip_connection *conn, kmip_debug(debug, "%lu bytes sent", size); /* receive the response */ - rc = kmip_decode_ttlv(conn->plain_tls.bio, NULL, response, debug); + rc = kmip_decode_ttlv(conn->plain_tls.bio, NULL, response, + KMIP_DECODE_MAX_NESTING_LEVEL, debug); if (rc != 0 || *response == NULL) { kmip_debug(debug, "kmip_decode_ttlv failed"); goto out; diff --git a/libkmipclient/ttlv.c b/libkmipclient/ttlv.c index 9c6702b1..fe9815de 100644 --- a/libkmipclient/ttlv.c +++ b/libkmipclient/ttlv.c @@ -28,12 +28,15 @@ * as many bytes as needed. * @param node On return: the decoded node. The newly allocated * node has a reference count of 1. + * @param max_nesting_level the maximum nesting levels of structures within the + * KMIP node. If the nesting level is reached, E2BIG + * is returned. * @param debug if true, debug messages are printed * * @returns 0 in case of success, or a negative errno value */ int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node, - bool debug) + size_t max_nesting_level, bool debug) { unsigned char padding[KMIP_TTLV_BLOCK_LENGTH]; unsigned char ttlv[KMIP_TTLV_HEADER_LENGTH]; @@ -44,6 +47,9 @@ int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node, uint64_t int64; int rc; + if (max_nesting_level == 0) + return -E2BIG; + if (bio == NULL || node == NULL) return -EINVAL; @@ -167,7 +173,8 @@ int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node, switch (n->type) { case KMIP_TYPE_STRUCTURE: while (value_len > 0) { - rc = kmip_decode_ttlv(bio, &value_len, &e, debug); + rc = kmip_decode_ttlv(bio, &value_len, &e, + max_nesting_level - 1, debug); if (rc != 0) { kmip_debug(debug, "kmip_decode_ttlv failed: " "rc: %d", rc); diff --git a/libkmipclient/xml.c b/libkmipclient/xml.c index 6f2bacf6..22766085 100644 --- a/libkmipclient/xml.c +++ b/libkmipclient/xml.c @@ -28,12 +28,16 @@ * @param parent the parent node or NULL if no parent exists. * @param node On return: the decoded node.The newly allocated * node has a reference count of 1. + * @param max_nesting_level the maximum nesting levels of structures within the + * KMIP node. If the nesting level is reached, E2BIG + * is returned. * @param debug if true, debug messages are printed * * @returns 0 in case of success, or a negative errno value */ int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent, - struct kmip_node **node, bool debug) + struct kmip_node **node, size_t max_nesting_level, + bool debug) { char *tag_attr = NULL, *name_attr = NULL, *type_attr = NULL; enum kmip_tag tag, v1_attr_tag = 0; @@ -44,6 +48,9 @@ int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent, int64_t int64; int rc = 0, i; + if (max_nesting_level == 0) + return -E2BIG; + if (xml == NULL || node == NULL) return -EINVAL; @@ -122,7 +129,8 @@ int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent, if (child->type != XML_ELEMENT_NODE) continue; - rc = kmip_decode_xml(child, n, &e, debug); + rc = kmip_decode_xml(child, n, &e, + max_nesting_level - 1, debug); if (rc != 0) { kmip_debug(debug, "Failed to parse child " "element %d", i);