mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
libkmipclient: Limit the nesting level of KMIP STRUCTURE recursion
KMIP STRUCTURE elements can be nested, which causes a recursion of functions kmip_decode_ttlv(), kmip_decode_xml(), and kmip_decode_json(). A malformed KMIP response may thus cause stack exhaustion. Limit the KMIP STRUCTURE nesting level to 32 levels. This is more than enough for currently defined KMIP responses. The practically used nesting level is 8 or 9, dependent on the type of KMIP response. Assisted-by: IBM Bob:2.0.0 Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> Reviewed-by: Finn Callies <fcallies@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
f0bf1985c3
commit
5fdeaab3d0
@@ -735,7 +735,8 @@ int kmip_connection_https_perform(struct kmip_connection *conn,
|
|||||||
switch (conn->config.encoding) {
|
switch (conn->config.encoding) {
|
||||||
case KMIP_ENCODING_TTLV:
|
case KMIP_ENCODING_TTLV:
|
||||||
rc = kmip_decode_ttlv(write_cb.ttlv.resp_mem_bio, NULL,
|
rc = kmip_decode_ttlv(write_cb.ttlv.resp_mem_bio, NULL,
|
||||||
response, debug);
|
response, KMIP_DECODE_MAX_NESTING_LEVEL,
|
||||||
|
debug);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
kmip_debug(debug, "kmip_decode_ttlv failed");
|
kmip_debug(debug, "kmip_decode_ttlv failed");
|
||||||
goto out;
|
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,
|
rc = kmip_decode_json(write_cb.json.resp_obj, NULL, response,
|
||||||
debug);
|
KMIP_DECODE_MAX_NESTING_LEVEL, debug);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
kmip_debug(debug, "kmip_decode_json failed");
|
kmip_debug(debug, "kmip_decode_json failed");
|
||||||
goto out;
|
goto out;
|
||||||
@@ -768,7 +769,8 @@ int kmip_connection_https_perform(struct kmip_connection *conn,
|
|||||||
|
|
||||||
rc = kmip_decode_xml(xmlDocGetRootElement(
|
rc = kmip_decode_xml(xmlDocGetRootElement(
|
||||||
write_cb.xml.ctx->myDoc),
|
write_cb.xml.ctx->myDoc),
|
||||||
NULL, response, debug);
|
NULL, response,
|
||||||
|
KMIP_DECODE_MAX_NESTING_LEVEL, debug);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
kmip_debug(debug, "kmip_decode_xml failed");
|
kmip_debug(debug, "kmip_decode_xml failed");
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
@@ -27,12 +27,16 @@
|
|||||||
* @param parent the parent node or NULL if no parent exists.
|
* @param parent the parent node or NULL if no parent exists.
|
||||||
* @param node On return: the decoded node. The newly allocated
|
* @param node On return: the decoded node. The newly allocated
|
||||||
* node has a reference count of 1.
|
* 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
|
* @param debug if true, debug messages are printed
|
||||||
*
|
*
|
||||||
* @returns 0 in case of success, or a negative errno value
|
* @returns 0 in case of success, or a negative errno value
|
||||||
*/
|
*/
|
||||||
int kmip_decode_json(const json_object *obj, struct kmip_node *parent,
|
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;
|
json_object *tag_obj, *type_obj, *value_obj, *name_obj;
|
||||||
enum kmip_tag tag, v1_attr_tag = 0;
|
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;
|
int rc, num, i;
|
||||||
int64_t int64;
|
int64_t int64;
|
||||||
|
|
||||||
|
if (max_nesting_level == 0)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
if (obj == NULL || node == NULL)
|
if (obj == NULL || node == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -138,7 +145,7 @@ int kmip_decode_json(const json_object *obj, struct kmip_node *parent,
|
|||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
rc = kmip_decode_json(
|
rc = kmip_decode_json(
|
||||||
json_object_array_get_idx(value_obj, i),
|
json_object_array_get_idx(value_obj, i),
|
||||||
n, &e, debug);
|
n, &e, max_nesting_level - 1, debug);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
kmip_debug(debug, "Failed to parse "
|
kmip_debug(debug, "Failed to parse "
|
||||||
"array element %d", i);
|
"array element %d", i);
|
||||||
|
|||||||
@@ -94,19 +94,23 @@ int kmip_connection_https_perform(struct kmip_connection *connection,
|
|||||||
bool debug);
|
bool debug);
|
||||||
void kmip_connection_https_term(struct kmip_connection *connection);
|
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,
|
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,
|
int kmip_encode_ttlv(struct kmip_node *node, BIO *bio, size_t *size,
|
||||||
bool debug);
|
bool debug);
|
||||||
|
|
||||||
int kmip_decode_json(const json_object *obj, struct kmip_node *parent,
|
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,
|
int kmip_encode_json(const struct kmip_node *node, json_object **obj,
|
||||||
bool debug);
|
bool debug);
|
||||||
|
|
||||||
int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent,
|
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);
|
int kmip_encode_xml(const struct kmip_node *node, xmlNode **xml, bool debug);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -493,7 +493,8 @@ int kmip_connection_tls_perform(struct kmip_connection *conn,
|
|||||||
kmip_debug(debug, "%lu bytes sent", size);
|
kmip_debug(debug, "%lu bytes sent", size);
|
||||||
|
|
||||||
/* receive the response */
|
/* 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) {
|
if (rc != 0 || *response == NULL) {
|
||||||
kmip_debug(debug, "kmip_decode_ttlv failed");
|
kmip_debug(debug, "kmip_decode_ttlv failed");
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
@@ -28,12 +28,15 @@
|
|||||||
* as many bytes as needed.
|
* as many bytes as needed.
|
||||||
* @param node On return: the decoded node. The newly allocated
|
* @param node On return: the decoded node. The newly allocated
|
||||||
* node has a reference count of 1.
|
* 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
|
* @param debug if true, debug messages are printed
|
||||||
*
|
*
|
||||||
* @returns 0 in case of success, or a negative errno value
|
* @returns 0 in case of success, or a negative errno value
|
||||||
*/
|
*/
|
||||||
int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node,
|
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 padding[KMIP_TTLV_BLOCK_LENGTH];
|
||||||
unsigned char ttlv[KMIP_TTLV_HEADER_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;
|
uint64_t int64;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (max_nesting_level == 0)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
if (bio == NULL || node == NULL)
|
if (bio == NULL || node == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -167,7 +173,8 @@ int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node,
|
|||||||
switch (n->type) {
|
switch (n->type) {
|
||||||
case KMIP_TYPE_STRUCTURE:
|
case KMIP_TYPE_STRUCTURE:
|
||||||
while (value_len > 0) {
|
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) {
|
if (rc != 0) {
|
||||||
kmip_debug(debug, "kmip_decode_ttlv failed: "
|
kmip_debug(debug, "kmip_decode_ttlv failed: "
|
||||||
"rc: %d", rc);
|
"rc: %d", rc);
|
||||||
|
|||||||
@@ -28,12 +28,16 @@
|
|||||||
* @param parent the parent node or NULL if no parent exists.
|
* @param parent the parent node or NULL if no parent exists.
|
||||||
* @param node On return: the decoded node.The newly allocated
|
* @param node On return: the decoded node.The newly allocated
|
||||||
* node has a reference count of 1.
|
* 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
|
* @param debug if true, debug messages are printed
|
||||||
*
|
*
|
||||||
* @returns 0 in case of success, or a negative errno value
|
* @returns 0 in case of success, or a negative errno value
|
||||||
*/
|
*/
|
||||||
int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent,
|
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;
|
char *tag_attr = NULL, *name_attr = NULL, *type_attr = NULL;
|
||||||
enum kmip_tag tag, v1_attr_tag = 0;
|
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;
|
int64_t int64;
|
||||||
int rc = 0, i;
|
int rc = 0, i;
|
||||||
|
|
||||||
|
if (max_nesting_level == 0)
|
||||||
|
return -E2BIG;
|
||||||
|
|
||||||
if (xml == NULL || node == NULL)
|
if (xml == NULL || node == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@@ -122,7 +129,8 @@ int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent,
|
|||||||
if (child->type != XML_ELEMENT_NODE)
|
if (child->type != XML_ELEMENT_NODE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rc = kmip_decode_xml(child, n, &e, debug);
|
rc = kmip_decode_xml(child, n, &e,
|
||||||
|
max_nesting_level - 1, debug);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
kmip_debug(debug, "Failed to parse child "
|
kmip_debug(debug, "Failed to parse child "
|
||||||
"element %d", i);
|
"element %d", i);
|
||||||
|
|||||||
Reference in New Issue
Block a user