From 7657aac584ed2dd83ac25a28ee60b64848d6919b Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 12 Jun 2015 22:52:15 +0100 Subject: [PATCH] [469467] Fixes and documentation to use_subject_as_username patch. This is for certificate based client authentication. Thanks to Fabian Ruff. Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=469467 --- ChangeLog.txt | 3 +++ THANKS.txt | 1 + man/mosquitto.conf.5.xml | 41 ++++++++++++++++++++++++++++++++-------- mosquitto.conf | 8 ++++++++ src/read_handle_server.c | 25 +++++++++++++++--------- 5 files changed, 61 insertions(+), 17 deletions(-) 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){