Bad username or password if use_identity_as_username is set but not require_certificate
Hello, I stumble accross the following which might be a bug.
Connection returns Bad user name or password when the configuration file contains:
require_certificate false
use_identity_as_username true
Here are the steps to reproduce the problem:
-
Generate self-signed certificates for the server and client
-
Run mosquitto with:
docker container run --rm -it -v $(pwd)/certs:/certs:ro -v $(pwd)/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro -p 8883:8883 eclipse-mosquitto:1.6.12
The configuration file mosquitto.conf contains:
port 8883
cafile /certs/ca/ca.pem
certfile /certs/server/server.crt
keyfile /certs/server/server.key
allow_anonymous true
require_certificate false
use_identity_as_username true
- Try to connect with valid certificates. For example with the following code
client.py:
"""
MQTT subscriber for debugging/testing
"""
import logging
import ssl
import paho.mqtt.client as mqtt
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
consolehandler = logging.StreamHandler()
consolehandler.setFormatter(logging.Formatter("%(levelname)s - %(message)s"))
logger.addHandler(consolehandler)
client = mqtt.Client("test", protocol=mqtt.MQTTv5)
client.tls_set(
ca_certs="./certs/ca/ca.pem",
certfile="./certs/client/client.crt",
keyfile="./certs/client/client.key",
cert_reqs=ssl.CERT_REQUIRED,
tls_version=ssl.PROTOCOL_TLS,
ciphers=None,
)
client.enable_logger(logger)
def on_connect(client, userdata, flags, rc, properties=None):
logger.info("Connected with result: %s", rc)
if rc != 0:
logger.error("Failed to connect (%s %s %s)", userdata, flags, properties)
client.on_connect = on_connect
client.connect("localhost", 8883, 60)
client.loop_forever()
Run with: python3 client.py
You can see as result:
Connected with result: Bad user name or password
Setting use_identity_as_username false solves it, but it took me a long time to understand !
Notice that setting use_subject_as_username true provokes the same issue.
I am not sure what the correct behavior should be:
- ignore
use_identity_as_usernameifrequire_certificateisfalse? - use the client certificate CN as username if provided, else default behavior ?
I agree with your analysis of the behaviour. At the moment you're quite right that use_*_as_username implies that require_certificate is true. I'll have a think about what to do. One solution could be:
- Use the certificate credentials if a client has a certificate
- Otherwise use whatever credentials are provided by the client as part of the CONNECT
I'm a little nervous about that because of the possibility for a client without a certificate to potentially spoof a client with a certificate. I need to have more of a think about it.
Thank you for pointing this out. I was getting admin authentication errors when using the Dynamic Security Plugin, and this was the issue.