curl_add_if("RTSP" NOT CURL_DISABLE_RTSP)
curl_add_if("RTMP" USE_LIBRTMP)
curl_add_if("MQTT" NOT CURL_DISABLE_MQTT)
+curl_add_if("MQTTS" NOT CURL_DISABLE_MQTT AND _ssl_enabled)
curl_add_if("WS" NOT CURL_DISABLE_WEBSOCKETS)
curl_add_if("WSS" NOT CURL_DISABLE_WEBSOCKETS AND _ssl_enabled)
if(_items)
fi
if test "$CURL_DISABLE_MQTT" != "1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTT"
+ if test "$SSL_ENABLED" = "1"; then
+ SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTTS"
+ fi
fi
if test "$CURL_DISABLE_POP3" != "1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3"
### libcurl
A client-side URL transfer library, supporting DICT, FILE, FTP, FTPS, GOPHER,
-GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP,
+GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTMP,
RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.
libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading,
**curl** is a tool for transferring data from or to a server using URLs. It
supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS,
-IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP,
-SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.
+IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTMP, RTMPS, RTSP, SCP,
+SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.
curl is powered by libcurl for all transfer-related features. See
*libcurl(3)* for details.
Doing a "POST" publishes the post data to the topic and exits.
+## TLS protection
+
+Use `mqtts://` to do MQTT over TLS: MQTTS.
+
### Subscribing
Command usage:
CURLPROTO_IMAPS
CURLPROTO_LDAP
CURLPROTO_LDAPS
+CURLPROTO_MQTT
+CURLPROTO_MQTTS
CURLPROTO_POP3
CURLPROTO_POP3S
CURLPROTO_RTMP
These are the available protocols:
DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
-MQTT, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP,
-SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
+MQTT, MQTTS, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP,
+SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
You can set "ALL" as a short-cut to enable all protocols. Note that by setting
all, you may enable protocols that were not supported the day you write this
CURLPROTO_IMAPS
CURLPROTO_LDAP
CURLPROTO_LDAPS
+CURLPROTO_MQTT
+CURLPROTO_MQTTS
CURLPROTO_POP3
CURLPROTO_POP3S
CURLPROTO_RTMP
These are the available protocols:
DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS,
-MQTT, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP, SCP, SFTP,
-SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
+MQTT, MQTTS, POP3, POP3S, RTMP, RTMPE, RTMPS, RTMPT, RTMPTE, RTMPTS, RTSP,
+SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS, WSS
You can set "ALL" as a short-cut to enable all protocols. Note that by setting
all, you may enable protocols that were not supported the day you write this
CURLPROTO_LDAP 7.19.4
CURLPROTO_LDAPS 7.19.4
CURLPROTO_MQTT 7.71.0
+CURLPROTO_MQTTS 8.19.0
CURLPROTO_POP3 7.20.0
CURLPROTO_POP3S 7.20.0
CURLPROTO_RTMP 7.21.0
- `%IMAPPORT` - Port number of the IMAP server
- `%LOGDIR` - Log directory relative to %PWD
- `%MQTTPORT` - Port number of the MQTT server
+- `%MQTTSPORT` - Port number of the MQTTS server
- `%NOLISTENPORT` - Port number where no service is listening
- `%POP36PORT` - IPv6 port number of the POP3 server
- `%POP3PORT` - Port number of the POP3 server
#define CURLPROTO_SMBS (1L << 27)
#define CURLPROTO_MQTT (1L << 28)
#define CURLPROTO_GOPHERS (1L << 29)
+#define CURLPROTO_MQTTS (1L << 30)
#define CURLPROTO_ALL (~0L) /* enable everything */
/* long may be 32 or 64 bits, but we should never depend on anything else
#include "url.h"
#include "escape.h"
#include "rand.h"
+#include "cfilters.h"
+#include "connect.h"
/* first byte is command.
second byte is for flags. */
return result;
}
+#ifdef USE_SSL
+
+static CURLcode mqtts_connecting(struct Curl_easy *data, bool *done)
+{
+ struct connectdata *conn = data->conn;
+ CURLcode result;
+
+ result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done);
+ if(result)
+ connclose(conn, "Failed TLS connection");
+ return result;
+}
+
+/*
+ * MQTTS protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_mqtts = {
+ "mqtts", /* scheme */
+ mqtt_setup_conn, /* setup_connection */
+ mqtt_do, /* do_it */
+ mqtt_done, /* done */
+ ZERO_NULL, /* do_more */
+ ZERO_NULL, /* connect_it */
+ mqtts_connecting, /* connecting */
+ mqtt_doing, /* doing */
+ ZERO_NULL, /* proto_pollset */
+ mqtt_pollset, /* doing_pollset */
+ ZERO_NULL, /* domore_pollset */
+ ZERO_NULL, /* perform_pollset */
+ ZERO_NULL, /* disconnect */
+ ZERO_NULL, /* write_resp */
+ ZERO_NULL, /* write_resp_hd */
+ ZERO_NULL, /* connection_check */
+ ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
+ PORT_MQTTS, /* defport */
+ CURLPROTO_MQTTS, /* protocol */
+ CURLPROTO_MQTT, /* family */
+ PROTOPT_SSL /* flags */
+};
+
+#endif
+
/*
* MQTT protocol handler.
*/
***************************************************************************/
#ifndef CURL_DISABLE_MQTT
extern const struct Curl_handler Curl_handler_mqtt;
+#ifdef USE_SSL
+extern const struct Curl_handler Curl_handler_mqtts;
+#endif
#endif
#endif /* HEADER_CURL_MQTT_H */
#else
NULL,
#endif
- NULL, NULL,
+#if defined(USE_SSL) && !defined(CURL_DISABLE_MQTT)
+ &Curl_handler_mqtts,
+#else
+ NULL,
+#endif
+ NULL,
#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)
&Curl_handler_gophers,
#else
#define PORT_RTMPS PORT_HTTPS
#define PORT_GOPHER 70
#define PORT_MQTT 1883
+#define PORT_MQTTS 8883
struct curl_trc_featt;
#ifndef CURL_DISABLE_MQTT
"mqtt",
#endif
+#if defined(USE_SSL) && !defined(CURL_DISABLE_MQTT)
+ "mqtts",
+#endif
#ifndef CURL_DISABLE_POP3
"pop3",
#endif
" ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \\\n"
" (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))" },
{ "mqtt", "#ifndef CURL_DISABLE_MQTT" },
+ { "mqtts", "#if defined(USE_SSL) && !defined(CURL_DISABLE_MQTT)" },
{ "pop3", "#ifndef CURL_DISABLE_POP3" },
{ "pop3s", "#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)" },
{ "rtmp", "#ifdef USE_LIBRTMP" },
\
test1630 test1631 test1632 test1633 test1634 test1635 test1636 \
\
+test1640 \
+\
test1650 test1651 test1652 test1653 test1654 test1655 test1656 test1657 \
test1658 \
test1660 test1661 test1662 test1663 test1664 test1665 \
--- /dev/null
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+MQTT
+MQTT SUBSCRIBE
+MQTTS
+</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>
+mqtts
+</features>
+<server>
+mqtts
+</server>
+<name>
+MQTTS SUBSCRIBE
+</name>
+<command option="binary-trace">
+mqtts://%HOSTIP:%MQTTSPORT/topic --insecure
+</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 20020000
+client SUBSCRIBE a 00010005746f70696300
+server SUBACK 3 9003000100
+server PUBLISH d 300d0005746f70696368656c6c6f0a
+server DISCONNECT 0 e000
+</protocol>
+</verify>
+</testcase>
$proto = uc($proto) if($proto);
die "unsupported protocol: '$proto'" unless($proto &&
- ($proto =~ /^(((DNS|FTP|HTTP|HTTP\/2|HTTP\/3|IMAP|POP3|GOPHER|SMTP|HTTPS-MTLS)S?)|(TFTP|SFTP|SOCKS|SSH|RTSP|HTTPTLS|DICT|SMB|SMBS|TELNET|MQTT))$/));
+ ($proto =~ /^(((DNS|FTP|HTTP|HTTP\/2|HTTP\/3|IMAP|POP3|GOPHER|SMTP|HTTPS-MTLS)S?)|(TFTP|SFTP|SOCKS|SSH|RTSP|HTTPTLS|DICT|SMB|SMBS|TELNET|MQTT|MQTTS))$/));
$ipver = (not $ipver) ? 'ipv4' : lc($ipver);
die "unsupported IP version: '$ipver'" unless($ipver &&
}
}
for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', 'httptls',
- 'dict', 'smb', 'smbs', 'telnet', 'mqtt', 'https-mtls',
- 'dns')) {
+ 'dict', 'smb', 'smbs', 'telnet', 'mqtt', 'mqtts',
+ 'https-mtls', 'dns')) {
for my $ipvnum ((4, 6)) {
for my $idnum ((1, 2)) {
my $serv = servername_id($proto, $ipvnum, $idnum);
'pop3s' => \&verifyftp,
'imaps' => \&verifyftp,
'mqtt' => \&verifypid,
+ 'mqtts' => \&verifypid,
'smtps' => \&verifyftp,
'tftp' => \&verifyftp,
'ssh' => \&verifyssh,
if($proto eq "gophers") {
$flags .= "--connect " . protoport("gopher");
}
+ elsif($proto eq "mqtts") {
+ $flags .= "--connect " . protoport("mqtt");
+ }
elsif(!$proxy) {
$flags .= "--connect " . protoport("http");
}
$run{'mqtt'}="$pid $pid2";
}
}
+ elsif($what eq "mqtts" ) {
+ if(!$stunnel) {
+ # we cannot run mqtts tests without stunnel
+ return ("no stunnel", 4);
+ }
+ if($run{'mqtt'} &&
+ !responsive_mqtt_server("mqtt", "", $verbose)) {
+ if(stopserver('mqtt')) {
+ return ("failed stopping unresponsive MQTT server", 3);
+ }
+ }
+ if(!$run{'mqtt'}) {
+ ($serr, $pid, $pid2, $PORT{"mqtt"}) = runmqttserver("", $verbose);
+ if($pid <= 0) {
+ return ("failed starting mqtt server", $serr);
+ }
+ logmsg sprintf("* pid mqtt => %d %d\n", $pid, $pid2) if($verbose);
+ $run{'mqtt'}="$pid $pid2";
+ }
+ if(!$run{$what}) {
+ ($serr, $pid, $pid2, $PORT{$what}) =
+ runhttpsserver($verbose, $what, "", $certfile);
+ if($pid <= 0) {
+ return ("failed starting MQTTS server (stunnel)", $serr);
+ }
+ logmsg sprintf("* pid $what => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{$what}="$pid $pid2";
+ }
+ }
elsif($what eq "http-unix") {
if($run{'http-unix'} &&
!responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) {
'HTTP2', 'HTTP2TLS',
'HTTP3',
'IMAP', 'IMAP6', 'IMAPS',
- 'MQTT',
+ 'MQTT', 'MQTTS',
'NOLISTEN',
'POP3', 'POP36', 'POP3S',
'RTSP', 'RTSP6',