1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-24 09:08:49 -05:00

mqtt: detect illegal and too large file size

Add test 3017 and 3018 to verify.
Closes #7166
This commit is contained in:
Harry Sintonen 2021-06-01 18:22:31 +03:00 committed by Daniel Stenberg
parent 4f209d8833
commit 8ccf75532b
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
5 changed files with 164 additions and 4 deletions

View File

@ -477,6 +477,12 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done)
/* -- switched state -- */ /* -- switched state -- */
remlen = mq->remaining_length; remlen = mq->remaining_length;
infof(data, "Remaining length: %zd bytes\n", remlen); 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); Curl_pgrsSetDownloadSize(data, remlen);
data->req.bytecount = 0; data->req.bytecount = 0;
data->req.size = remlen; 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); Curl_debug(data, CURLINFO_HEADER_IN, (char *)&byte, 1);
pkt[mq->npacket++] = byte; pkt[mq->npacket++] = byte;
} while((byte & 0x80) && (mq->npacket < 4)); } 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) if(result)
break; break;
mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL); mq->remaining_length = mqtt_decode_len(&pkt[0], mq->npacket, NULL);

View File

@ -232,4 +232,6 @@ test2100 \
\ \
test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 \ test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 \
test3008 test3009 test3010 test3011 test3012 test3013 test3014 test3015 \ test3008 test3009 test3010 test3011 test3012 test3013 test3014 test3015 \
test3016 test3016 \
\
test3017 test3018

67
tests/data/test3017 Normal file
View File

@ -0,0 +1,67 @@
<testcase>
<info>
<keywords>
MQTT
MQTT SUBSCRIBE
</keywords>
</info>
#
# Server-side
<reply>
<data nocheck="yes">
hello
</data>
<datacheck hex="yes">
00 04 33 30 31 37 68 65 6c 6c 6f 5b 4c 46 5d 0a
</datacheck>
<servercmd>
excessive-remaining TRUE
</servercmd>
</reply>
#
# Client-side
<client>
<features>
mqtt
</features>
<server>
mqtt
</server>
<name>
MQTT SUBSCRIBE with pathological PUBLISH length
</name>
<command option="binary-trace">
mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -m 3
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
# These are hexadecimal protocol dumps from the client
#
# Strip out the random part of the client id from the CONNECT message
# before comparison
<strippart>
s/^(.* 00044d5154540402003c000c6375726c).*/$1/
</strippart>
# on windows the disconnect is never seen - no idea why
<strip>
^server DISCONNECT 0 e000
</strip>
<protocol>
client CONNECT 18 00044d5154540402003c000c6375726c
server CONNACK 2 20020000
client SUBSCRIBE 9 000100043330313700
server SUBACK 3 9003000100
server PUBLISH c 30ffffff8000043330313768656c6c6f0a
</protocol>
# 8 is CURLE_WEIRD_SERVER_REPLY
<errorcode>
8
</errorcode>
</verify>
</testcase>

65
tests/data/test3018 Normal file
View File

@ -0,0 +1,65 @@
<testcase>
<info>
<keywords>
MQTT
MQTT SUBSCRIBE
--max-filesize
</keywords>
</info>
#
# Server-side
<reply>
<data nocheck="yes">
hello
</data>
<datacheck hex="yes">
00 04 33 30 31 38 68 65 6c 6c 6f 5b 4c 46 5d 0a
</datacheck>
</reply>
#
# Client-side
<client>
<features>
mqtt
</features>
<server>
mqtt
</server>
<name>
MQTT SUBSCRIBE with PUBLISH larger than --max-filesize
</name>
<command option="binary-trace">
mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER --max-filesize 11
</command>
</client>
#
# Verify data after the test has been "shot"
<verify>
# These are hexadecimal protocol dumps from the client
#
# Strip out the random part of the client id from the CONNECT message
# before comparison
<strippart>
s/^(.* 00044d5154540402003c000c6375726c).*/$1/
</strippart>
# on windows the disconnect is never seen - no idea why
<strip>
^server DISCONNECT 0 e000
</strip>
<protocol>
client CONNECT 18 00044d5154540402003c000c6375726c
server CONNACK 2 20020000
client SUBSCRIBE 9 000100043330313800
server SUBACK 3 9003000100
server PUBLISH c 300c00043330313868656c6c6f0a
</protocol>
# 63 is CURLE_FILESIZE_EXCEEDED
<errorcode>
63
</errorcode>
</verify>
</testcase>

View File

@ -106,6 +106,7 @@ struct configurable {
this */ this */
bool publish_before_suback; bool publish_before_suback;
bool short_publish; bool short_publish;
bool excessive_remaining;
unsigned char error_connack; unsigned char error_connack;
int testnum; int testnum;
}; };
@ -130,6 +131,7 @@ static void resetdefaults(void)
config.version = CONFIG_VERSION; config.version = CONFIG_VERSION;
config.publish_before_suback = FALSE; config.publish_before_suback = FALSE;
config.short_publish = FALSE; config.short_publish = FALSE;
config.excessive_remaining = FALSE;
config.error_connack = 0; config.error_connack = 0;
config.testnum = 0; config.testnum = 0;
} }
@ -171,6 +173,10 @@ static void getconfig(void)
config.testnum = atoi(value); config.testnum = atoi(value);
logmsg("testnum = %d", config.testnum); logmsg("testnum = %d", config.testnum);
} }
else if(!strcmp(key, "excessive-remaining")) {
logmsg("excessive-remaining set");
config.excessive_remaining = TRUE;
}
} }
} }
fclose(fp); fclose(fp);
@ -337,7 +343,8 @@ static int disconnect(FILE *dump, curl_socket_t fd)
*/ */
/* return number of bytes used */ /* 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; int bytes = 0;
unsigned char encode; unsigned char encode;
@ -393,10 +400,19 @@ static int publish(FILE *dump,
ssize_t packetlen; ssize_t packetlen;
ssize_t sendamount; ssize_t sendamount;
ssize_t rc; ssize_t rc;
char rembuffer[4]; unsigned char rembuffer[4];
int encodedlen; 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) */ /* one packet type byte (possibly two more for packetid) */
packetlen = remaininglength + encodedlen + 1; packetlen = remaininglength + encodedlen + 1;