mirror of
https://github.com/moparisthebest/curl
synced 2024-12-24 09:08:49 -05:00
mqtt: add support for username and password
Minor-edits-by: Daniel Stenberg Added test 2200 to 2205 Closes #7243
This commit is contained in:
parent
53c26dedf4
commit
791937b881
210
lib/mqtt.c
210
lib/mqtt.c
@ -143,32 +143,197 @@ static int mqtt_getsock(struct Curl_easy *data,
|
|||||||
return GETSOCK_READSOCK(FIRSTSOCKET);
|
return GETSOCK_READSOCK(FIRSTSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mqtt_encode_len(char *buf, size_t len)
|
||||||
|
{
|
||||||
|
unsigned char encoded;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; (len > 0) && (i<4); i++) {
|
||||||
|
encoded = len % 0x80;
|
||||||
|
len /= 0x80;
|
||||||
|
if(len)
|
||||||
|
encoded |= 0x80;
|
||||||
|
buf[i] = encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the passwd to the CONNECT packet */
|
||||||
|
static int add_passwd(const char *passwd, const size_t plen,
|
||||||
|
char *pkt, const size_t start, int remain_pos)
|
||||||
|
{
|
||||||
|
/* magic number that need to be set properly */
|
||||||
|
const size_t conn_flags_pos = remain_pos + 8;
|
||||||
|
if(plen > 0xffff)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* set password flag */
|
||||||
|
pkt[conn_flags_pos] |= 0x40;
|
||||||
|
|
||||||
|
/* length of password provided */
|
||||||
|
pkt[start] = (char)((plen >> 8) & 0xFF);
|
||||||
|
pkt[start + 1] = (char)(plen & 0xFF);
|
||||||
|
memcpy(&pkt[start + 2], passwd, plen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add user to the CONN packet */
|
||||||
|
static int add_user(const char *username, const size_t ulen,
|
||||||
|
unsigned char *pkt, const size_t start, int remain_pos)
|
||||||
|
{
|
||||||
|
/* magic number that need to be set properly */
|
||||||
|
const size_t conn_flags_pos = remain_pos + 8;
|
||||||
|
if(ulen > 0xffff)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* set username flag */
|
||||||
|
pkt[conn_flags_pos] |= 0x80;
|
||||||
|
/* length of username provided */
|
||||||
|
pkt[start] = (unsigned char)((ulen >> 8) & 0xFF);
|
||||||
|
pkt[start + 1] = (unsigned char)(ulen & 0xFF);
|
||||||
|
memcpy(&pkt[start + 2], username, ulen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add client ID to the CONN packet */
|
||||||
|
static int add_client_id(const char *client_id, const size_t client_id_len,
|
||||||
|
char *pkt, const size_t start)
|
||||||
|
{
|
||||||
|
if(client_id_len != MQTT_CLIENTID_LEN)
|
||||||
|
return 1;
|
||||||
|
pkt[start] = 0x00;
|
||||||
|
pkt[start + 1] = MQTT_CLIENTID_LEN;
|
||||||
|
memcpy(&pkt[start + 2], client_id, MQTT_CLIENTID_LEN);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set initial values of CONN packet */
|
||||||
|
static int init_connpack(char *packet, char *remain, int remain_pos)
|
||||||
|
{
|
||||||
|
/* Fixed header starts */
|
||||||
|
/* packet type */
|
||||||
|
packet[0] = MQTT_MSG_CONNECT;
|
||||||
|
/* remaining length field */
|
||||||
|
memcpy(&packet[1], remain, remain_pos);
|
||||||
|
/* Fixed header ends */
|
||||||
|
|
||||||
|
/* Variable header starts */
|
||||||
|
/* protocol length */
|
||||||
|
packet[remain_pos + 1] = 0x00;
|
||||||
|
packet[remain_pos + 2] = 0x04;
|
||||||
|
/* protocol name */
|
||||||
|
packet[remain_pos + 3] = 'M';
|
||||||
|
packet[remain_pos + 4] = 'Q';
|
||||||
|
packet[remain_pos + 5] = 'T';
|
||||||
|
packet[remain_pos + 6] = 'T';
|
||||||
|
/* protocol level */
|
||||||
|
packet[remain_pos + 7] = 0x04;
|
||||||
|
/* CONNECT flag: CleanSession */
|
||||||
|
packet[remain_pos + 8] = 0x02;
|
||||||
|
/* keep-alive 0 = disabled */
|
||||||
|
packet[remain_pos + 9] = 0x00;
|
||||||
|
packet[remain_pos + 10] = 0x3c;
|
||||||
|
/*end of variable header*/
|
||||||
|
return remain_pos + 10;
|
||||||
|
}
|
||||||
|
|
||||||
static CURLcode mqtt_connect(struct Curl_easy *data)
|
static CURLcode mqtt_connect(struct Curl_easy *data)
|
||||||
{
|
{
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
const size_t client_id_offset = 14;
|
int pos = 0;
|
||||||
const size_t packetlen = client_id_offset + MQTT_CLIENTID_LEN;
|
int rc = 0;
|
||||||
|
/*remain length*/
|
||||||
|
int remain_pos = 0;
|
||||||
|
char remain[4] = {0};
|
||||||
|
size_t packetlen = 0;
|
||||||
|
size_t payloadlen = 0;
|
||||||
|
size_t start_user = 0;
|
||||||
|
size_t start_pwd = 0;
|
||||||
char client_id[MQTT_CLIENTID_LEN + 1] = "curl";
|
char client_id[MQTT_CLIENTID_LEN + 1] = "curl";
|
||||||
const size_t clen = strlen("curl");
|
const size_t clen = strlen("curl");
|
||||||
char packet[32] = {
|
char *packet = NULL;
|
||||||
MQTT_MSG_CONNECT, /* packet type */
|
|
||||||
0x00, /* remaining length */
|
/* extracting username from request */
|
||||||
0x00, 0x04, /* protocol length */
|
const char *username = data->state.aptr.user ?
|
||||||
'M','Q','T','T', /* protocol name */
|
data->state.aptr.user : "";
|
||||||
0x04, /* protocol level */
|
const size_t ulen = strlen(username);
|
||||||
0x02, /* CONNECT flag: CleanSession */
|
/* extracting password from request */
|
||||||
0x00, 0x3c, /* keep-alive 0 = disabled */
|
const char *passwd = data->state.aptr.passwd ?
|
||||||
0x00, 0x00 /* payload1 length */
|
data->state.aptr.passwd : "";
|
||||||
};
|
const size_t plen = strlen(passwd);
|
||||||
packet[1] = (packetlen - 2) & 0x7f;
|
|
||||||
packet[client_id_offset - 1] = MQTT_CLIENTID_LEN;
|
payloadlen = ulen + plen + MQTT_CLIENTID_LEN + 2;
|
||||||
|
/* The plus 2 are for the MSB and LSB describing the length of the string to
|
||||||
|
* be added on the payload. Refer to spec 1.5.2 and 1.5.4 */
|
||||||
|
if(ulen)
|
||||||
|
payloadlen += 2;
|
||||||
|
if(plen)
|
||||||
|
payloadlen += 2;
|
||||||
|
|
||||||
|
/* getting how much occupy the remain length */
|
||||||
|
remain_pos = mqtt_encode_len(remain, payloadlen + 10);
|
||||||
|
|
||||||
|
/* 10 length of variable header and 1 the first byte of the fixed header */
|
||||||
|
packetlen = payloadlen + 10 + remain_pos + 1;
|
||||||
|
|
||||||
|
/* allocating packet */
|
||||||
|
if(packetlen > 268435455)
|
||||||
|
return CURLE_WEIRD_SERVER_REPLY;
|
||||||
|
packet = malloc(packetlen);
|
||||||
|
if(!packet)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
memset(packet, 0, packetlen);
|
||||||
|
|
||||||
|
/* set initial values for CONN pack */
|
||||||
|
pos = init_connpack(packet, remain, remain_pos);
|
||||||
|
|
||||||
result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
|
result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
|
||||||
MQTT_CLIENTID_LEN - clen + 1);
|
MQTT_CLIENTID_LEN - clen + 1);
|
||||||
memcpy(&packet[client_id_offset], client_id, MQTT_CLIENTID_LEN);
|
/* add client id */
|
||||||
|
rc = add_client_id(client_id, strlen(client_id), packet, pos + 1);
|
||||||
|
if(rc) {
|
||||||
|
failf(data, "Client ID length mismatched: [%lu]", strlen(client_id));
|
||||||
|
result = CURLE_WEIRD_SERVER_REPLY;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
infof(data, "Using client id '%s'\n", client_id);
|
infof(data, "Using client id '%s'\n", client_id);
|
||||||
|
|
||||||
|
/* position where starts the user payload */
|
||||||
|
start_user = pos + 3 + MQTT_CLIENTID_LEN;
|
||||||
|
/* position where starts the password payload */
|
||||||
|
start_pwd = start_user + ulen;
|
||||||
|
/* if user name was provided, add it to the packet */
|
||||||
|
if(ulen) {
|
||||||
|
start_pwd += 2;
|
||||||
|
|
||||||
|
rc = add_user(username, ulen,
|
||||||
|
(unsigned char *)packet, start_user, remain_pos);
|
||||||
|
if(rc) {
|
||||||
|
failf(data, "Username is too large: [%lu]", ulen);
|
||||||
|
result = CURLE_WEIRD_SERVER_REPLY;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if passwd was provided, add it to the packet */
|
||||||
|
if(plen) {
|
||||||
|
rc = add_passwd(passwd, plen, packet, start_pwd, remain_pos);
|
||||||
|
if(rc) {
|
||||||
|
failf(data, "Password is too large: [%lu]", plen);
|
||||||
|
result = CURLE_WEIRD_SERVER_REPLY;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!result)
|
if(!result)
|
||||||
result = mqtt_send(data, packet, packetlen);
|
result = mqtt_send(data, packet, packetlen);
|
||||||
|
|
||||||
|
end:
|
||||||
|
if(packet)
|
||||||
|
free(packet);
|
||||||
|
Curl_safefree(data->state.aptr.user);
|
||||||
|
Curl_safefree(data->state.aptr.passwd);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,21 +393,6 @@ static CURLcode mqtt_get_topic(struct Curl_easy *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int mqtt_encode_len(char *buf, size_t len)
|
|
||||||
{
|
|
||||||
unsigned char encoded;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0; (len > 0) && (i<4); i++) {
|
|
||||||
encoded = len % 0x80;
|
|
||||||
len /= 0x80;
|
|
||||||
if(len)
|
|
||||||
encoded |= 0x80;
|
|
||||||
buf[i] = encoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CURLcode mqtt_subscribe(struct Curl_easy *data)
|
static CURLcode mqtt_subscribe(struct Curl_easy *data)
|
||||||
{
|
{
|
||||||
|
@ -228,8 +228,11 @@ test2064 test2065 test2066 test2067 test2068 test2069 test2070 \
|
|||||||
test2071 test2072 test2073 test2074 test2075 test2076 test2077 \
|
test2071 test2072 test2073 test2074 test2075 test2076 test2077 \
|
||||||
test2078 \
|
test2078 \
|
||||||
test2080 test2081 \
|
test2080 test2081 \
|
||||||
|
\
|
||||||
test2100 \
|
test2100 \
|
||||||
\
|
\
|
||||||
|
test2200 test2201 test2202 test2203 test2204 test2205 \
|
||||||
|
\
|
||||||
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 test3017 test3018 test3019 test3020
|
test3016 test3017 test3018 test3019 test3020
|
||||||
|
62
tests/data/test2200
Normal file
62
tests/data/test2200
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
MQTT
|
||||||
|
MQTT SUBSCRIBE
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck="yes">
|
||||||
|
hello
|
||||||
|
</data>
|
||||||
|
<datacheck hex="yes">
|
||||||
|
00 04 31 31 39 30 68 65 6c 6c 6f 5b 4c 46 5d 0a
|
||||||
|
</datacheck>
|
||||||
|
|
||||||
|
# error 5 - "Connection Refused, not authorized. Wrong data supplied"
|
||||||
|
<servercmd>
|
||||||
|
error-CONNACK 5
|
||||||
|
</servercmd>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<features>
|
||||||
|
mqtt
|
||||||
|
</features>
|
||||||
|
<server>
|
||||||
|
mqtt
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
MQTT SUBSCRIBE with user and password
|
||||||
|
</name>
|
||||||
|
<command option="binary-trace">
|
||||||
|
mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -u fakeuser:fakepasswd
|
||||||
|
</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/^(.* 00044d51545404c2003c000c6375726c).*/$1/
|
||||||
|
</strippart>
|
||||||
|
<protocol>
|
||||||
|
client CONNECT 2e 00044d51545404c2003c000c6375726c
|
||||||
|
server CONNACK 2 20020005
|
||||||
|
</protocol>
|
||||||
|
|
||||||
|
# 8 is CURLE_WEIRD_SERVER_REPLY
|
||||||
|
<errorcode>
|
||||||
|
8
|
||||||
|
</errorcode>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
50
tests/data/test2201
Normal file
50
tests/data/test2201
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
MQTT
|
||||||
|
MQTT PUBLISH
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<features>
|
||||||
|
mqtt
|
||||||
|
</features>
|
||||||
|
<server>
|
||||||
|
mqtt
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
MQTT PUBLISH with user and password valid
|
||||||
|
</name>
|
||||||
|
<command option="binary-trace">
|
||||||
|
mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -d something -u testuser:testpasswd
|
||||||
|
</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/^(.* 00044d51545404c2003c000c6375726c).*/$1/
|
||||||
|
</strippart>
|
||||||
|
<protocol>
|
||||||
|
client CONNECT 2e 00044d51545404c2003c000c6375726c
|
||||||
|
server CONNACK 2 20020000
|
||||||
|
client PUBLISH f 000432323031736f6d657468696e67
|
||||||
|
client DISCONNECT 0 e000
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
59
tests/data/test2202
Normal file
59
tests/data/test2202
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
MQTT
|
||||||
|
MQTT PUBLISH
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
# error 5 - "Connection Refused, not authorized. Wrong data supplied"
|
||||||
|
<servercmd>
|
||||||
|
error-CONNACK 5
|
||||||
|
</servercmd>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<features>
|
||||||
|
mqtt
|
||||||
|
</features>
|
||||||
|
<server>
|
||||||
|
mqtt
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
MQTT PUBLISH with invalid user and password
|
||||||
|
</name>
|
||||||
|
<command option="binary-trace">
|
||||||
|
mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -d something -u fakeuser:fakepasswd
|
||||||
|
</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/^(.* 00044d51545404c2003c000c6375726c).*/$1/
|
||||||
|
</strippart>
|
||||||
|
<protocol>
|
||||||
|
client CONNECT 2e 00044d51545404c2003c000c6375726c
|
||||||
|
server CONNACK 2 20020005
|
||||||
|
</protocol>
|
||||||
|
|
||||||
|
|
||||||
|
# 8 is CURLE_WEIRD_SERVER_REPLY
|
||||||
|
<errorcode>
|
||||||
|
8
|
||||||
|
</errorcode>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
62
tests/data/test2203
Normal file
62
tests/data/test2203
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
MQTT
|
||||||
|
MQTT SUBSCRIBE
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck="yes">
|
||||||
|
hello
|
||||||
|
</data>
|
||||||
|
<datacheck hex="yes">
|
||||||
|
00 04 31 31 39 30 68 65 6c 6c 6f 5b 4c 46 5d 0a
|
||||||
|
</datacheck>
|
||||||
|
|
||||||
|
# error 5 - "Connection Refused, not authorized. No user or password supplied"
|
||||||
|
<servercmd>
|
||||||
|
error-CONNACK 5
|
||||||
|
</servercmd>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<features>
|
||||||
|
mqtt
|
||||||
|
</features>
|
||||||
|
<server>
|
||||||
|
mqtt
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
MQTT with error in CONNACK
|
||||||
|
</name>
|
||||||
|
<command option="binary-trace">
|
||||||
|
mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER
|
||||||
|
</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>
|
||||||
|
<protocol>
|
||||||
|
client CONNECT 18 00044d5154540402003c000c6375726c
|
||||||
|
server CONNACK 2 20020005
|
||||||
|
</protocol>
|
||||||
|
|
||||||
|
# 8 is CURLE_WEIRD_SERVER_REPLY
|
||||||
|
<errorcode>
|
||||||
|
8
|
||||||
|
</errorcode>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
56
tests/data/test2204
Normal file
56
tests/data/test2204
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
MQTT
|
||||||
|
MQTT SUBSCRIBE
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data nocheck="yes">
|
||||||
|
hello
|
||||||
|
</data>
|
||||||
|
<datacheck hex="yes">
|
||||||
|
00 04 31 31 39 30 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 user and password
|
||||||
|
</name>
|
||||||
|
<command option="binary-trace">
|
||||||
|
mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -u testuser:testpasswd
|
||||||
|
</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/^(.* 00044d51545404c2003c000c6375726c).*/$1/
|
||||||
|
</strippart>
|
||||||
|
<protocol>
|
||||||
|
client CONNECT 2e 00044d51545404c2003c000c6375726c
|
||||||
|
server CONNACK 2 20020000
|
||||||
|
client SUBSCRIBE 9 000100043232303400
|
||||||
|
server SUBACK 3 9003000100
|
||||||
|
server PUBLISH c 300c00043232303468656c6c6f0a
|
||||||
|
server DISCONNECT 0 e000
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
51
tests/data/test2205
Normal file
51
tests/data/test2205
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
MQTT
|
||||||
|
MQTT SUBSCRIBE
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<features>
|
||||||
|
mqtt
|
||||||
|
</features>
|
||||||
|
<server>
|
||||||
|
mqtt
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
MQTT with very long user name
|
||||||
|
</name>
|
||||||
|
<file name="log/input%TESTNUMBER">
|
||||||
|
user = %repeat[65536 x a]%:fakepasswd
|
||||||
|
</file>
|
||||||
|
<command option="binary-trace">
|
||||||
|
mqtt://%HOSTIP:%MQTTPORT/%TESTNUMBER -K log/input%TESTNUMBER
|
||||||
|
</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/^(.* 00044d51545404c2003c000c6375726c).*/$1/
|
||||||
|
</strippart>
|
||||||
|
# 8 is CURLE_WEIRD_SERVER_REPLY
|
||||||
|
<errorcode>
|
||||||
|
8
|
||||||
|
</errorcode>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
@ -584,7 +584,7 @@ sub get_disttests {
|
|||||||
if(($_ =~ /^#/) ||($_ !~ /test/)) {
|
if(($_ =~ /^#/) ||($_ !~ /test/)) {
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
$disttests .= join("", $_);
|
$disttests .= $_;
|
||||||
}
|
}
|
||||||
close(D);
|
close(D);
|
||||||
}
|
}
|
||||||
|
@ -490,11 +490,13 @@ static int fixedheader(curl_socket_t fd,
|
|||||||
|
|
||||||
static curl_socket_t mqttit(curl_socket_t fd)
|
static curl_socket_t mqttit(curl_socket_t fd)
|
||||||
{
|
{
|
||||||
unsigned char buffer[10*1024];
|
size_t buff_size = 10*1024;
|
||||||
|
unsigned char *buffer = NULL;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
unsigned short packet_id;
|
unsigned short packet_id;
|
||||||
size_t payload_len;
|
size_t payload_len;
|
||||||
|
size_t client_id_length;
|
||||||
unsigned int topic_len;
|
unsigned int topic_len;
|
||||||
size_t remaining_length = 0;
|
size_t remaining_length = 0;
|
||||||
size_t bytes = 0; /* remaining length field size in bytes */
|
size_t bytes = 0; /* remaining length field size in bytes */
|
||||||
@ -502,6 +504,7 @@ static curl_socket_t mqttit(curl_socket_t fd)
|
|||||||
long testno;
|
long testno;
|
||||||
FILE *stream = NULL;
|
FILE *stream = NULL;
|
||||||
|
|
||||||
|
|
||||||
static const char protocol[7] = {
|
static const char protocol[7] = {
|
||||||
0x00, 0x04, /* protocol length */
|
0x00, 0x04, /* protocol length */
|
||||||
'M','Q','T','T', /* protocol name */
|
'M','Q','T','T', /* protocol name */
|
||||||
@ -518,12 +521,36 @@ static curl_socket_t mqttit(curl_socket_t fd)
|
|||||||
if(testno)
|
if(testno)
|
||||||
logmsg("Found test number %ld", testno);
|
logmsg("Found test number %ld", testno);
|
||||||
|
|
||||||
|
buffer = malloc(buff_size);
|
||||||
|
if(!buffer) {
|
||||||
|
logmsg("Out of memory, unable to allocate buffer");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
unsigned char usr_flag = 0x80;
|
||||||
|
unsigned char passwd_flag = 0x40;
|
||||||
|
unsigned char conn_flags;
|
||||||
|
const size_t client_id_offset = 12;
|
||||||
|
size_t start_usr;
|
||||||
|
size_t start_passwd;
|
||||||
|
|
||||||
/* get the fixed header */
|
/* get the fixed header */
|
||||||
rc = fixedheader(fd, &byte, &remaining_length, &bytes);
|
rc = fixedheader(fd, &byte, &remaining_length, &bytes);
|
||||||
if(rc)
|
if(rc)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if(remaining_length >= buff_size) {
|
||||||
|
buff_size = remaining_length;
|
||||||
|
buffer = realloc(buffer, buff_size);
|
||||||
|
if(!buffer) {
|
||||||
|
logmsg("Failed realloc of size %lu", buff_size);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(remaining_length) {
|
if(remaining_length) {
|
||||||
|
/* reading variable header and payload into buffer */
|
||||||
rc = sread(fd, (char *)buffer, remaining_length);
|
rc = sread(fd, (char *)buffer, remaining_length);
|
||||||
if(rc > 0) {
|
if(rc > 0) {
|
||||||
logmsg("READ %d bytes", rc);
|
logmsg("READ %d bytes", rc);
|
||||||
@ -540,19 +567,40 @@ static curl_socket_t mqttit(curl_socket_t fd)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
/* ignore the connect flag byte and two keepalive bytes */
|
/* ignore the connect flag byte and two keepalive bytes */
|
||||||
|
|
||||||
payload_len = (buffer[10] << 8) | buffer[11];
|
payload_len = (buffer[10] << 8) | buffer[11];
|
||||||
|
/* first part of the payload is the client ID */
|
||||||
|
client_id_length = payload_len;
|
||||||
|
|
||||||
|
/* checking if user and password flags were set */
|
||||||
|
conn_flags = buffer[7];
|
||||||
|
|
||||||
|
start_usr = client_id_offset + payload_len;
|
||||||
|
if(usr_flag == (unsigned char)(conn_flags & usr_flag)) {
|
||||||
|
logmsg("User flag is present in CONN flag");
|
||||||
|
payload_len += (buffer[start_usr] << 8) | buffer[start_usr + 1];
|
||||||
|
payload_len += 2; /* MSB and LSB for user length */
|
||||||
|
}
|
||||||
|
|
||||||
|
start_passwd = client_id_offset + payload_len;
|
||||||
|
if(passwd_flag == (char)(conn_flags & passwd_flag)) {
|
||||||
|
logmsg("Password flag is present in CONN flags");
|
||||||
|
payload_len += (buffer[start_passwd] << 8) | buffer[start_passwd + 1];
|
||||||
|
payload_len += 2; /* MSB and LSB for password length */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check the length of the payload */
|
||||||
if((ssize_t)payload_len != (rc - 12)) {
|
if((ssize_t)payload_len != (rc - 12)) {
|
||||||
logmsg("Payload length mismatch, expected %x got %x",
|
logmsg("Payload length mismatch, expected %x got %x",
|
||||||
rc - 12, payload_len);
|
rc - 12, payload_len);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
else if((payload_len + 1) > MAX_CLIENT_ID_LENGTH) {
|
/* check the length of the client ID */
|
||||||
|
else if((client_id_length + 1) > MAX_CLIENT_ID_LENGTH) {
|
||||||
logmsg("Too large client id");
|
logmsg("Too large client id");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
memcpy(client_id, &buffer[12], payload_len);
|
memcpy(client_id, &buffer[12], client_id_length);
|
||||||
client_id[payload_len] = 0;
|
client_id[client_id_length] = 0;
|
||||||
|
|
||||||
logmsg("MQTT client connect accepted: %s", client_id);
|
logmsg("MQTT client connect accepted: %s", client_id);
|
||||||
|
|
||||||
@ -650,6 +698,8 @@ static curl_socket_t mqttit(curl_socket_t fd)
|
|||||||
} while(1);
|
} while(1);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
if(buffer)
|
||||||
|
free(buffer);
|
||||||
if(dump)
|
if(dump)
|
||||||
fclose(dump);
|
fclose(dump);
|
||||||
if(stream)
|
if(stream)
|
||||||
|
Loading…
Reference in New Issue
Block a user