Skip to content
Snippets Groups Projects
Commit 93adfa9a authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

Add new "Synchronet Broker" MQTT TLS type

With this, you don't need a username, password, PSK, or PSK ID,
certs, CAs, etc, and things just work by magic (when using the
Synchronet broker)
parent 7907e9a5
Branches
Tags
No related merge requests found
Pipeline #8119 passed
...@@ -102,6 +102,7 @@ static JSBool js_connect(JSContext* cx, uintN argc, jsval *arglist) ...@@ -102,6 +102,7 @@ static JSBool js_connect(JSContext* cx, uintN argc, jsval *arglist)
if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_mqtt_class)) == NULL) if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_mqtt_class)) == NULL)
return JS_FALSE; return JS_FALSE;
scfg_t* scfg = JS_GetRuntimePrivate(JS_GetRuntime(cx));
rc = JS_SUSPENDREQUEST(cx); rc = JS_SUSPENDREQUEST(cx);
...@@ -126,6 +127,13 @@ static JSBool js_connect(JSContext* cx, uintN argc, jsval *arglist) ...@@ -126,6 +127,13 @@ static JSBool js_connect(JSContext* cx, uintN argc, jsval *arglist)
JSVALUE_TO_STRBUF(cx, argv[argn], password, sizeof password, NULL); JSVALUE_TO_STRBUF(cx, argv[argn], password, sizeof password, NULL);
++argn; ++argn;
} }
if (p->cfg.tls.mode == MQTT_TLS_SBBS) {
username[0] = 0;
strlcpy(password, scfg->sys_pass, sizeof(password));
mosquitto_int_option(p->handle, MOSQ_OPT_PROTOCOL_VERSION, 5);
}
else
mosquitto_int_option(p->handle, MOSQ_OPT_PROTOCOL_VERSION, p->cfg.protocol_version); mosquitto_int_option(p->handle, MOSQ_OPT_PROTOCOL_VERSION, p->cfg.protocol_version);
mosquitto_username_pw_set(p->handle, *username ? username : NULL, *password ? password : NULL); mosquitto_username_pw_set(p->handle, *username ? username : NULL, *password ? password : NULL);
p->retval = MOSQ_ERR_SUCCESS; p->retval = MOSQ_ERR_SUCCESS;
...@@ -151,6 +159,30 @@ static JSBool js_connect(JSContext* cx, uintN argc, jsval *arglist) ...@@ -151,6 +159,30 @@ static JSBool js_connect(JSContext* cx, uintN argc, jsval *arglist)
NULL // ciphers (default) NULL // ciphers (default)
); );
} }
else if (p->cfg.tls.mode == MQTT_TLS_SBBS) {
user_t user = {
.number = 1
};
if ((getuserdat(scfg, &user) == USER_SUCCESS)
&& user.number == 1
&& user_is_sysop(&user)) {
char hexpass[LEN_PASS * 2 + 1];
for (size_t i = 0; user.pass[i]; i++) {
const char hd[] = "0123456789ABCDEF";
hexpass[i*2] = hd[(((uint8_t *)user.pass)[i] & 0xf0) >> 4];
hexpass[i*2+1] = hd[user.pass[i] & 0x0f];
}
strlwr(user.alias);
p->retval = mosquitto_tls_psk_set(p->handle,
hexpass,
user.alias,
NULL // ciphers (default)
);
}
else
p->retval = MQTT_FAILURE;
}
if (p->retval == MOSQ_ERR_SUCCESS) if (p->retval == MOSQ_ERR_SUCCESS)
p->retval = mosquitto_connect_bind(p->handle, p->retval = mosquitto_connect_bind(p->handle,
broker_addr, broker_addr,
......
...@@ -380,10 +380,17 @@ int mqtt_connect(struct mqtt* mqtt, const char* bind_address) ...@@ -380,10 +380,17 @@ int mqtt_connect(struct mqtt* mqtt, const char* bind_address)
char topic[128]; char topic[128];
char* username = mqtt->cfg->mqtt.username; char* username = mqtt->cfg->mqtt.username;
char* password = mqtt->cfg->mqtt.password; char* password = mqtt->cfg->mqtt.password;
if (*username == '\0') if (*username == '\0')
username = NULL; username = NULL;
if (*password == '\0') if (*password == '\0')
password = NULL; password = NULL;
if (mqtt->cfg->mqtt.tls.mode == MQTT_TLS_SBBS) {
username = NULL;
password = mqtt->cfg->sys_pass;
mosquitto_int_option(mqtt->handle, MOSQ_OPT_PROTOCOL_VERSION, 5);
}
else
mosquitto_int_option(mqtt->handle, MOSQ_OPT_PROTOCOL_VERSION, mqtt->cfg->mqtt.protocol_version); mosquitto_int_option(mqtt->handle, MOSQ_OPT_PROTOCOL_VERSION, mqtt->cfg->mqtt.protocol_version);
mosquitto_username_pw_set(mqtt->handle, username, password); mosquitto_username_pw_set(mqtt->handle, username, password);
char value[128]; char value[128];
...@@ -416,6 +423,32 @@ int mqtt_connect(struct mqtt* mqtt, const char* bind_address) ...@@ -416,6 +423,32 @@ int mqtt_connect(struct mqtt* mqtt, const char* bind_address)
if (result != MOSQ_ERR_SUCCESS) if (result != MOSQ_ERR_SUCCESS)
return result; return result;
} }
else if (mqtt->cfg->mqtt.tls.mode == MQTT_TLS_SBBS) {
user_t user = {
.number = 1
};
int result = MQTT_FAILURE;
if ((getuserdat(mqtt->cfg, &user) == USER_SUCCESS)
&& user.number == 1
&& user_is_sysop(&user)) {
strlwr(user.pass);
char hexpass[LEN_PASS * 2 + 1];
for (size_t i = 0; user.pass[i]; i++) {
const char hd[] = "0123456789ABCDEF";
hexpass[i*2] = hd[(((uint8_t *)user.pass)[i] & 0xf0) >> 4];
hexpass[i*2+1] = hd[user.pass[i] & 0x0f];
}
strlwr(user.alias);
result = mosquitto_tls_psk_set(mqtt->handle,
hexpass,
user.alias,
NULL // ciphers (default)
);
}
if (result != MOSQ_ERR_SUCCESS)
return result;
}
return mosquitto_connect_bind(mqtt->handle, return mosquitto_connect_bind(mqtt->handle,
mqtt->cfg->mqtt.broker_addr, mqtt->cfg->mqtt.broker_addr,
mqtt->cfg->mqtt.broker_port, mqtt->cfg->mqtt.broker_port,
......
...@@ -159,22 +159,24 @@ void mqtt_cfg() ...@@ -159,22 +159,24 @@ void mqtt_cfg()
static char* mqttVersion[] static char* mqttVersion[]
= { "3.1.0", "3.1.1", "5.0", NULL }; = { "3.1.0", "3.1.1", "5.0", NULL };
static char* mqttTlsMode[] static char* mqttTlsMode[]
= { "Off", "Certificate", "Pre-Shared-Key", NULL }; = { "Off", "Certificate", "Pre-Shared-Key", "Synchronet Broker", NULL };
while (1) { while (1) {
int i = 0; int i = 0;
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Enabled", cfg.mqtt.enabled ? "Yes" : "No"); snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Enabled", cfg.mqtt.enabled ? "Yes" : "No");
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Broker Address", cfg.mqtt.broker_addr); snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Broker Address", cfg.mqtt.broker_addr);
snprintf(opt[i++], MAX_OPLN, "%-20s%u", "Broker Port", cfg.mqtt.broker_port); snprintf(opt[i++], MAX_OPLN, "%-20s%u", "Broker Port", cfg.mqtt.broker_port);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Username", cfg.mqtt.username);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Password", cfg.mqtt.password);
snprintf(opt[i++], MAX_OPLN, "%-20s%u seconds", "Keep-alive", cfg.mqtt.keepalive); snprintf(opt[i++], MAX_OPLN, "%-20s%u seconds", "Keep-alive", cfg.mqtt.keepalive);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Protocol Version", mqttVersion[cfg.mqtt.protocol_version - 3]);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Publish Verbosity", cfg.mqtt.verbose ? "High" : "Low"); snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Publish Verbosity", cfg.mqtt.verbose ? "High" : "Low");
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Publish QOS", mqttQOS[cfg.mqtt.publish_qos]); snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Publish QOS", mqttQOS[cfg.mqtt.publish_qos]);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Subscribe QOS", mqttQOS[cfg.mqtt.subscribe_qos]); snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Subscribe QOS", mqttQOS[cfg.mqtt.subscribe_qos]);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Log Level", logLevelStringList[cfg.mqtt.log_level]); snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Log Level", logLevelStringList[cfg.mqtt.log_level]);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "TLS (encryption)", mqttTlsMode[cfg.mqtt.tls.mode]); snprintf(opt[i++], MAX_OPLN, "%-20s%s", "TLS (encryption)", mqttTlsMode[cfg.mqtt.tls.mode]);
if (cfg.mqtt.tls.mode != MQTT_TLS_SBBS) {
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Username", cfg.mqtt.username);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Password", cfg.mqtt.password);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Protocol Version", mqttVersion[cfg.mqtt.protocol_version - 3]);
}
if (cfg.mqtt.tls.mode == MQTT_TLS_CERT) { if (cfg.mqtt.tls.mode == MQTT_TLS_CERT) {
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "CA Cert", cfg.mqtt.tls.cafile); snprintf(opt[i++], MAX_OPLN, "%-20s%s", "CA Cert", cfg.mqtt.tls.cafile);
snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Client Cert", cfg.mqtt.tls.certfile); snprintf(opt[i++], MAX_OPLN, "%-20s%s", "Client Cert", cfg.mqtt.tls.certfile);
...@@ -238,48 +240,25 @@ void mqtt_cfg() ...@@ -238,48 +240,25 @@ void mqtt_cfg()
cfg.mqtt.broker_port = atoi(str); cfg.mqtt.broker_port = atoi(str);
break; break;
case 3: case 3:
uifc.helpbuf =
"~ User name ~\n"
"\n"
"Enter the user name to use for authenticating with the MQTT Broker.\n"
;
uifc.input(WIN_MID | WIN_SAV, 0, 0, "User name for authentication"
, cfg.mqtt.username, sizeof(cfg.mqtt.username) - 1, K_EDIT);
break;
case 4:
uifc.helpbuf =
"~ Password ~\n"
"\n"
"Enter the user password to use for authenticating with the MQTT Broker.\n"
;
uifc.input(WIN_MID | WIN_SAV, 0, 0, "Password for authentication"
, cfg.mqtt.password, sizeof(cfg.mqtt.password) - 1, K_EDIT);
break;
case 5:
SAFEPRINTF(str, "%u", cfg.mqtt.keepalive); SAFEPRINTF(str, "%u", cfg.mqtt.keepalive);
if (uifc.input(WIN_MID | WIN_SAV, 0, 0, "Seconds to keep inactive connection alive" if (uifc.input(WIN_MID | WIN_SAV, 0, 0, "Seconds to keep inactive connection alive"
, str, 5, K_EDIT | K_NUMBER) > 0 && atoi(str) >= 5) , str, 5, K_EDIT | K_NUMBER) > 0 && atoi(str) >= 5)
cfg.mqtt.keepalive = atoi(str); cfg.mqtt.keepalive = atoi(str);
break; break;
case 6: case 4:
i = cfg.mqtt.protocol_version - 3;
if ((i = uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &i, 0, "Protocol Version", mqttVersion)) >= 0)
cfg.mqtt.protocol_version = 3 + i;
break;
case 7:
cfg.mqtt.verbose = !cfg.mqtt.verbose; cfg.mqtt.verbose = !cfg.mqtt.verbose;
break; break;
case 8: case 5:
i = cfg.mqtt.publish_qos; i = cfg.mqtt.publish_qos;
if ((i = uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &i, 0, "Quality of Service for Publishing", mqttQOS)) >= 0) if ((i = uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &i, 0, "Quality of Service for Publishing", mqttQOS)) >= 0)
cfg.mqtt.publish_qos = i; cfg.mqtt.publish_qos = i;
break; break;
case 9: case 6:
i = cfg.mqtt.subscribe_qos; i = cfg.mqtt.subscribe_qos;
if ((i = uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &i, 0, "Quality of Service for Subscriptions", mqttQOS)) >= 0) if ((i = uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &i, 0, "Quality of Service for Subscriptions", mqttQOS)) >= 0)
cfg.mqtt.subscribe_qos = i; cfg.mqtt.subscribe_qos = i;
break; break;
case 10: case 7:
uifc.helpbuf = uifc.helpbuf =
"~ MQTT Log Level ~\n" "~ MQTT Log Level ~\n"
"\n" "\n"
...@@ -292,14 +271,15 @@ void mqtt_cfg() ...@@ -292,14 +271,15 @@ void mqtt_cfg()
if (i >= 0 && i <= LOG_DEBUG) if (i >= 0 && i <= LOG_DEBUG)
cfg.mqtt.log_level = i; cfg.mqtt.log_level = i;
break; break;
case 11: case 8:
uifc.helpbuf = uifc.helpbuf =
"~ Encryption via TLS ~\n" "~ Encryption via TLS ~\n"
"\n" "\n"
"MQTT traffic may be encrypted via TLS using either:\n" "MQTT traffic may be encrypted via TLS using one of:\n"
"\n" "\n"
" - `Certificate-based` authentication (mutual-auth optionally supported)\n" " - `Certificate-based` authentication (mutual-auth optionally supported)\n"
" - `Pre-Shared-Key` authentication\n" " - `Pre-Shared-Key` authentication\n"
" - `Synchronet Broker` use internal Synchronet authentication\n"
"\n" "\n"
"When TLS is used, the default MQTT port is `8883`.\n" "When TLS is used, the default MQTT port is `8883`.\n"
; ;
...@@ -308,6 +288,29 @@ void mqtt_cfg() ...@@ -308,6 +288,29 @@ void mqtt_cfg()
if (i >= 0) if (i >= 0)
cfg.mqtt.tls.mode = i; cfg.mqtt.tls.mode = i;
break; break;
case 9:
uifc.helpbuf =
"~ User name ~\n"
"\n"
"Enter the user name to use for authenticating with the MQTT Broker.\n"
;
uifc.input(WIN_MID | WIN_SAV, 0, 0, "User name for authentication"
, cfg.mqtt.username, sizeof(cfg.mqtt.username) - 1, K_EDIT);
break;
case 10:
uifc.helpbuf =
"~ Password ~\n"
"\n"
"Enter the user password to use for authenticating with the MQTT Broker.\n"
;
uifc.input(WIN_MID | WIN_SAV, 0, 0, "Password for authentication"
, cfg.mqtt.password, sizeof(cfg.mqtt.password) - 1, K_EDIT);
break;
case 11:
i = cfg.mqtt.protocol_version - 3;
if ((i = uifc.list(WIN_MID | WIN_SAV, 0, 0, 0, &i, 0, "Protocol Version", mqttVersion)) >= 0)
cfg.mqtt.protocol_version = 3 + i;
break;
case 12: case 12:
if (cfg.mqtt.tls.mode == MQTT_TLS_CERT) { if (cfg.mqtt.tls.mode == MQTT_TLS_CERT) {
uifc.helpbuf = uifc.helpbuf =
......
...@@ -387,7 +387,8 @@ struct mqtt_cfg { ...@@ -387,7 +387,8 @@ struct mqtt_cfg {
enum { enum {
MQTT_TLS_DISABLED, MQTT_TLS_DISABLED,
MQTT_TLS_CERT, MQTT_TLS_CERT,
MQTT_TLS_PSK MQTT_TLS_PSK,
MQTT_TLS_SBBS
} mode; } mode;
char cafile[256]; char cafile[256];
char certfile[256]; char certfile[256];
......
...@@ -228,7 +228,7 @@ bool read_main_cfg(scfg_t* cfg, char* error, size_t maxerrlen) ...@@ -228,7 +228,7 @@ bool read_main_cfg(scfg_t* cfg, char* error, size_t maxerrlen)
cfg->mqtt.subscribe_qos = iniGetIntInRange(section, NULL, "subscribe_qos", 0, 2, 2); cfg->mqtt.subscribe_qos = iniGetIntInRange(section, NULL, "subscribe_qos", 0, 2, 2);
cfg->mqtt.protocol_version = iniGetIntInRange(section, NULL, "protocol_version", 3, 4, 5); cfg->mqtt.protocol_version = iniGetIntInRange(section, NULL, "protocol_version", 3, 4, 5);
cfg->mqtt.log_level = iniGetLogLevel(section, NULL, "LogLevel", LOG_INFO); cfg->mqtt.log_level = iniGetLogLevel(section, NULL, "LogLevel", LOG_INFO);
cfg->mqtt.tls.mode = iniGetIntInRange(section, NULL, "tls_mode", MQTT_TLS_DISABLED, MQTT_TLS_DISABLED, MQTT_TLS_PSK); cfg->mqtt.tls.mode = iniGetIntInRange(section, NULL, "tls_mode", MQTT_TLS_DISABLED, MQTT_TLS_DISABLED, MQTT_TLS_SBBS);
SAFECOPY(cfg->mqtt.tls.cafile, iniGetString(section, NULL, "tls_cafile", "", value)); SAFECOPY(cfg->mqtt.tls.cafile, iniGetString(section, NULL, "tls_cafile", "", value));
SAFECOPY(cfg->mqtt.tls.certfile, iniGetString(section, NULL, "tls_certfile", "", value)); SAFECOPY(cfg->mqtt.tls.certfile, iniGetString(section, NULL, "tls_certfile", "", value));
SAFECOPY(cfg->mqtt.tls.keyfile, iniGetString(section, NULL, "tls_keyfile", "", value)); SAFECOPY(cfg->mqtt.tls.keyfile, iniGetString(section, NULL, "tls_keyfile", "", value));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment