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
No related branches found
No related tags found
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