diff --git a/lib/mqtt.c b/lib/mqtt.c index d88fa737d..d49a5f1cc 100644 --- a/lib/mqtt.c +++ b/lib/mqtt.c @@ -477,6 +477,12 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) /* -- switched state -- */ remlen = mq->remaining_length; infof(data, "Remaining length: %zd bytes\n", remlen); + if(data->set.max_filesize && + (curl_off_t)remlen > data->set.max_filesize) { + failf(data, "Maximum file size exceeded"); + result = CURLE_FILESIZE_EXCEEDED; + goto end; + } Curl_pgrsSetDownloadSize(data, remlen); data->req.bytecount = 0; data->req.size = remlen; @@ -582,6 +588,10 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done) Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1); pkt[mq->npacket++] = byte; } while((byte & 0x80) && (mq->npacket < 4)); + if(nread && (byte & 0x80)) + /* MQTT supports up to 127 * 128^0 + 127 * 128^1 + 127 * 128^2 + + 127 * 128^3 bytes. server tried to send more */ + result = CURLE_WEIRD_SERVER_REPLY; if(result) break; mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL); diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 77feeccee..2b25a92b3 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -232,4 +232,6 @@ test2100 \ \ test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 \ test3008 test3009 test3010 test3011 test3012 test3013 test3014 test3015 \ -test3016 +test3016 \ +\ +test3017 test3018 diff --git a/tests/data/test3017 b/tests/data/test3017 new file mode 100644 index 000000000..4d907b39f --- /dev/null +++ b/tests/data/test3017 @@ -0,0 +1,67 @@ + + + +MQTT +MQTT SUBSCRIBE + + + +# +# Server-side + + +hello + + +00 04 33 30 31 37 68 65 6c 6c 6f 5b 4c 46 5d 0a + + +excessive-remaining TRUE + + + +# +# Client-side + + +mqtt + + +mqtt + + +MQTT SUBSCRIBE with pathological PUBLISH length + + +mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -m 3 + + + +# +# Verify data after the test has been "shot" + +# These are hexadecimal protocol dumps from the client +# +# Strip out the random part of the client id from the CONNECT message +# before comparison + +s/^(.* 00044d5154540402003c000c6375726c).*/$1/ + +# on windows the disconnect is never seen - no idea why + +^server DISCONNECT 0 e000 + + +client CONNECT 18 00044d5154540402003c000c6375726c +server CONNACK 2 20020000 +client SUBSCRIBE 9 000100043330313700 +server SUBACK 3 9003000100 +server PUBLISH c 30ffffff8000043330313768656c6c6f0a + + +# 8 is CURLE_WEIRD_SERVER_REPLY + +8 + + + diff --git a/tests/data/test3018 b/tests/data/test3018 new file mode 100644 index 000000000..71e06b593 --- /dev/null +++ b/tests/data/test3018 @@ -0,0 +1,65 @@ + + + +MQTT +MQTT SUBSCRIBE +--max-filesize + + + +# +# Server-side + + +hello + + +00 04 33 30 31 38 68 65 6c 6c 6f 5b 4c 46 5d 0a + + + +# +# Client-side + + +mqtt + + +mqtt + + +MQTT SUBSCRIBE with PUBLISH larger than --max-filesize + + +mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER --max-filesize 11 + + + +# +# Verify data after the test has been "shot" + +# These are hexadecimal protocol dumps from the client +# +# Strip out the random part of the client id from the CONNECT message +# before comparison + +s/^(.* 00044d5154540402003c000c6375726c).*/$1/ + +# on windows the disconnect is never seen - no idea why + +^server DISCONNECT 0 e000 + + +client CONNECT 18 00044d5154540402003c000c6375726c +server CONNACK 2 20020000 +client SUBSCRIBE 9 000100043330313800 +server SUBACK 3 9003000100 +server PUBLISH c 300c00043330313868656c6c6f0a + + +# 63 is CURLE_FILESIZE_EXCEEDED + +63 + + + diff --git a/tests/server/mqttd.c b/tests/server/mqttd.c index 8134336da..18339262e 100644 --- a/tests/server/mqttd.c +++ b/tests/server/mqttd.c @@ -106,6 +106,7 @@ struct configurable { this */ bool publish_before_suback; bool short_publish; + bool excessive_remaining; unsigned char error_connack; int testnum; }; @@ -130,6 +131,7 @@ static void resetdefaults(void) config.version = CONFIG_VERSION; config.publish_before_suback = FALSE; config.short_publish = FALSE; + config.excessive_remaining = FALSE; config.error_connack = 0; config.testnum = 0; } @@ -171,6 +173,10 @@ static void getconfig(void) config.testnum = atoi(value); logmsg("testnum = %d", config.testnum); } + else if(!strcmp(key, "excessive-remaining")) { + logmsg("excessive-remaining set"); + config.excessive_remaining = TRUE; + } } } fclose(fp); @@ -337,7 +343,8 @@ static int disconnect(FILE *dump, curl_socket_t fd) */ /* return number of bytes used */ -static int encode_length(size_t packetlen, char *remlength) /* 4 bytes */ +static int encode_length(size_t packetlen, + unsigned char *remlength) /* 4 bytes */ { int bytes = 0; unsigned char encode; @@ -393,10 +400,19 @@ static int publish(FILE *dump, ssize_t packetlen; ssize_t sendamount; ssize_t rc; - char rembuffer[4]; + unsigned char rembuffer[4]; int encodedlen; - encodedlen = encode_length(remaininglength, rembuffer); + if(config.excessive_remaining) { + /* manually set illegal remaining length */ + rembuffer[0] = 0xff; + rembuffer[1] = 0xff; + rembuffer[2] = 0xff; + rembuffer[3] = 0x80; /* maximum allowed here by spec is 0x7f */ + encodedlen = 4; + } + else + encodedlen = encode_length(remaininglength, rembuffer); /* one packet type byte (possibly two more for packetid) */ packetlen = remaininglength + encodedlen + 1;