diff --git a/ChangeLog.txt b/ChangeLog.txt
index 8c6a2b03..8b9737c5 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -14,6 +14,9 @@ Broker:
up. Once the backlog has cleared the client will respond. If it is not
able to catch up, sending additional duplicates would not help either.
- Produce an error if two bridges share the same local_clientid.
+- Add use_subject_as_username option for certificate based client
+ authentication to use the entire certificate subject as a username, rather
+ than just the CN. Closes #469467.
Client library:
- Outgoing messages with QoS>1 are no longer retried after a timeout period.
diff --git a/THANKS.txt b/THANKS.txt
index bc48605e..a29f0006 100644
--- a/THANKS.txt
+++ b/THANKS.txt
@@ -21,6 +21,7 @@ Dirk O. Kaar
Dominik Obermaier
Dominik Zajac
Ed Morris
+Fabian Ruff
Frank Hansen
Gary Koh
Joan Zapata
diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml
index be6866e2..22e42f70 100644
--- a/man/mosquitto.conf.5.xml
+++ b/man/mosquitto.conf.5.xml
@@ -52,7 +52,7 @@
usernames and passwords. Be sure to use network encryption if you
are using this option otherwise the username and password will be
vulnerable to interception.
- When using certificate based encryption there are two options
+ When using certificate based encryption there are three options
that affect authentication. The first is require_certificate, which
may be set to true or false. If false, the SSL/TLS component of the
client will verify the server but there is no requirement for the
@@ -60,14 +60,17 @@
limited to the MQTT built in username/password. If
require_certificate is true, the client must provide a valid
certificate in order to connect successfully. In this case, the
- second option, use_identity_as_username, becomes relevant. If set
- to true, the Common Name (CN) from the client certificate is used
- instead of the MQTT username for access control purposes. The
- password is not replaced because it is assumed that only
- authenticated clients have valid certificates. If
+ second and third options, use_identity_as_username and
+ use_subject_as_username, become relevant. If set to true,
+ use_identity_as_user causes the Common Name (CN) from the client
+ certificate to be used instead of the MQTT username for access
+ control purposes. The password is not replaced because it is
+ assumed that only authenticated clients have valid certificates. If
use_identity_as_username is false, the client must authenticate as
- normal (if required by password_file) through the MQTT
- options.
+ normal (if required by password_file) through the MQTT options. The
+ same principle applies for the use_subject_as_username option, but
+ the entire certificate subject is used as the username instead of
+ just the CN.When using pre-shared-key based encryption through the psk_hint
and psk_file options, the client must provide a valid identity and
key in order to connect to the broker before any MQTT communication
@@ -823,6 +826,28 @@
is true, the
option will not be
used for this listener.
+ This takes priority over
+ if both
+ are set to true.
+ See also
+
+
+
+
+ [ true | false ]
+
+ If is
+ true, you may set
+ to
+ true to use the complete subject value
+ from the client certificate as a username. If this
+ is true, the
+ option will not be
+ used for this listener.
+ The subject will be generated in a form similar
+ to .
+ See also
+
diff --git a/mosquitto.conf b/mosquitto.conf
index 3488b4a3..4aba355b 100644
--- a/mosquitto.conf
+++ b/mosquitto.conf
@@ -208,8 +208,16 @@
# If require_certificate is true, you may set use_identity_as_username to true
# to use the CN value from the client certificate as a username. If this is
# true, the password_file option will not be used for this listener.
+# This takes priority over use_subject_as_username.
+# See also use_subject_as_username.
#use_identity_as_username false
+# If require_certificate is true, you may set use_subject_as_username to true
+# to use the complete subject value from the client certificate as a username.
+# If this is true, the password_file option will not be used for this listener.
+# See also use_identity_as_username
+#use_subject_as_username false
+
# If you have require_certificate set to true, you can create a certificate
# revocation list file to revoke access to particular client certificates. If
# you have done this, use crlfile to point to the PEM encoded revocation file.
diff --git a/src/read_handle_server.c b/src/read_handle_server.c
index e5e6fd8b..47942de9 100644
--- a/src/read_handle_server.c
+++ b/src/read_handle_server.c
@@ -344,16 +344,23 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
goto handle_connect_error;
}
name_entry = X509_NAME_get_entry(name, i);
- context->username = _mosquitto_strdup((char *)ASN1_STRING_data(name_entry->value));
+ if(name_entry){
+ context->username = mosquitto__strdup((char *)ASN1_STRING_data(name_entry->value));
+ }
} else { // use_subject_as_username
- BIO *subjectBio = BIO_new(BIO_s_mem());
- X509_NAME_print_ex(subjectBio, X509_get_subject_name(client_cert) , 0, XN_FLAG_RFC2253);
- char *dataStart = NULL;
- long nameLength = BIO_get_mem_data(subjectBio, &dataStart);
- char *subject = mosquitto__malloc(sizeof(char)*nameLength);
- memset(subject, 0x00, sizeof(char)*(nameLength + 1));
- memcpy(subject, dataStart, nameLength);
- BIO_free(subjectBio);
+ BIO *subject_bio = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(subject_bio, X509_get_subject_name(client_cert), 0, XN_FLAG_RFC2253);
+ char *data_start = NULL;
+ long name_length = BIO_get_mem_data(subject_bio, &data_start);
+ char *subject = mosquitto__malloc(sizeof(char)*name_length+1);
+ if(!subject){
+ BIO_free(subject_bio);
+ rc = MOSQ_ERR_NOMEM;
+ goto handle_connect_error;
+ }
+ memcpy(subject, data_start, name_length);
+ subject[name_length] = '\0';
+ BIO_free(subject_bio);
context->username = subject;
}
if(!context->username){