From d5a9000d466511c36cc3b4e6d49e322d6dbfdc52 Mon Sep 17 00:00:00 2001 From: Deomid Ryabkov <rojer@cesanta.com> Date: Wed, 30 Aug 2017 13:38:51 +0100 Subject: [PATCH] Harden MQTT parser some more PUBLISHED_FROM=5e7fcc7bf145aa8e1045e8d627b1c0731bb4341b --- mongoose.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/mongoose.c b/mongoose.c index 2c81f5df1..974a9d7ce 100644 --- a/mongoose.c +++ b/mongoose.c @@ -9956,19 +9956,31 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { switch (cmd) { case MG_MQTT_CMD_CONNECT: { p = scanto(p, &mm->protocol_name); + if (p > end - 4) return -2; mm->protocol_version = *(uint8_t *) p++; mm->connect_flags = *(uint8_t *) p++; mm->keep_alive_timer = getu16(p); p += 2; - if (p < end) p = scanto(p, &mm->client_id); - if (p < end && (mm->connect_flags & MG_MQTT_HAS_WILL)) + if (p >= end) return -2; + p = scanto(p, &mm->client_id); + if (p > end) return -2; + if (mm->connect_flags & MG_MQTT_HAS_WILL) { + if (p >= end) return -2; p = scanto(p, &mm->will_topic); - if (p < end && (mm->connect_flags & MG_MQTT_HAS_WILL)) + } + if (mm->connect_flags & MG_MQTT_HAS_WILL) { + if (p >= end) return -2; p = scanto(p, &mm->will_message); - if (p < end && (mm->connect_flags & MG_MQTT_HAS_USER_NAME)) + } + if (mm->connect_flags & MG_MQTT_HAS_USER_NAME) { + if (p >= end) return -2; p = scanto(p, &mm->user_name); - if (p < end && (mm->connect_flags & MG_MQTT_HAS_PASSWORD)) + } + if (mm->connect_flags & MG_MQTT_HAS_PASSWORD) { + if (p >= end) return -2; p = scanto(p, &mm->password); + } + if (p != end) return -2; LOG(LL_DEBUG, ("%d %2x %d proto [%.*s] client_id [%.*s] will_topic [%.*s] " @@ -9982,6 +9994,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { break; } case MG_MQTT_CMD_CONNACK: + if (end - p < 2) return -2; mm->connack_ret_code = p[1]; break; case MG_MQTT_CMD_PUBACK: @@ -9993,7 +10006,9 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { break; case MG_MQTT_CMD_PUBLISH: { p = scanto(p, &mm->topic); + if (p > end) return -2; if (mm->qos > 0) { + if (end - p < 2) return -2; mm->message_id = getu16(p); p += 2; } @@ -10002,6 +10017,7 @@ MG_INTERNAL int parse_mqtt(struct mbuf *io, struct mg_mqtt_message *mm) { break; } case MG_MQTT_CMD_SUBSCRIBE: + if (end - p < 2) return -2; mm->message_id = getu16(p); p += 2; /* @@ -10036,7 +10052,12 @@ static void mqtt_handler(struct mg_connection *nc, int ev, /* There can be multiple messages in the buffer, process them all. */ while (1) { int len = parse_mqtt(io, &mm); - if (len == -1) break; /* not fully buffered */ + if (len < 0) { + if (len == -1) break; /* not fully buffered */ + /* Protocol error. */ + nc->flags |= MG_F_CLOSE_IMMEDIATELY; + break; + } nc->handler(nc, MG_MQTT_EVENT_BASE + mm.cmd, &mm MG_UD_ARG(user_data)); mbuf_remove(io, len); } -- GitLab