2

I am trying to connect to an MQTT broker in SSL/TLS using libmosquitto (in C). I am sure it is working on the server side as I successfully connected to the borker using mosquitto_sub (or mosquitto_pub) in the command line and with the same certificate I am using in my code.

When I try to connect using my C program, I always get the following error : "Error: Unable to create TLS context."

I am using libmosquitto 1.4.8 on Linux. Here is the code I am using :

#include <mosquitto.h>

static struct SomeStruct *data = NULL;
// The variable mosq is included in the struct
// The struct has been created somewhere else

void foo(void)
{
    // I usually check the return values but removed
    // it to make the code easier to read
    mosquitto_lib_init();
    data->mosq = mosquitto_new("foobar", true, data);

    // Connect the callbacks

    mosquitto_username_pw_set(data->mosq, "user", "pass");
    mosquitto_tls_set(data->mosq, "/path/to/ca/file.crt,
                        NULL, NULL, NULL, NULL);
    mosquitto_tls_insecure_set(data->mosq, 1)
    mosquitto_tls_opts_set(data->mosq,
                            1,    // also tried 0
                            NULL, // also tried "tlsv1.2"
                            NULL);

    // All the return values are correct up to here

    mosquitto_connect(data->mosq, "mqtt.example.com", 8883, 30); // Fails
    // Logs : Error: Unable to create TLS context.
    // A TLS error occurred.
}

Does anyone know what could be the issue ?

Cheers,

Antoine

EDIT : I forgot to add that I am not using mosquitto's main loop beacause another library I use already has one and I need to have a very limited number of threads. I therefore call mosquitto_loop() everytime the file descriptor changes.

Antoine
  • 63
  • 2
  • 6
  • We need real data, like a server name, rather than fake data, like `mqtt.example.com`. – jww May 02 '16 at 16:56
  • 1
    I don't see how the server name could be related to the problem I'm having - I tried to simplify as much as possible the code, but all the calls to the mosquitto lib are here – Antoine May 03 '16 at 08:35

1 Answers1

1

This problem can only occur if SSL_CTX_new() fails. This seems pretty unlikely if mosquitto_sub works just fine on the same machine. Try "tlsv1", "tlsv1.1" as other options to tls_opts_set. You can also try patching the mosquitto client library to get more information about why openssl is unhappy:

diff --git a/lib/net_mosq.c b/lib/net_mosq.c
index 08f24d9..d4c57fd 100644
--- a/lib/net_mosq.c
+++ b/lib/net_mosq.c
@@ -409,6 +409,8 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t
 #ifdef WITH_TLS
        int ret;
        BIO *bio;
+       int e;
+       char ebuf[256];
 #endif

        if(!mosq || !host || !port) return MOSQ_ERR_INVAL;
@@ -441,6 +443,11 @@ int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t
 #endif
                if(!mosq->ssl_ctx){
                        _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context.");
+                       e = ERR_get_error();
+                       while(e){
+                               _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "OpenSSL Error: %s", ERR_error_string(e, ebuf));
+                               e = ERR_get_error();
+                       }
                        COMPAT_CLOSE(sock);
                        return MOSQ_ERR_TLS;
                }

Example code that reproduces the problem:

#include <stdio.h>

#include <mosquitto.h>

void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str)
{
    printf("LOG: %s\n", str);
}


int main(int argc, char *argv[])
{
    struct mosquitto *mosq = NULL;
    int rc;

    printf("Calling connect before lib init, this should fail.\n");
    mosq = mosquitto_new(NULL, true, NULL);
    mosquitto_log_callback_set(mosq, my_log_callback);
    mosquitto_tls_set(mosq, "mosquitto.org.crt", NULL, NULL, NULL, NULL);
    rc = mosquitto_connect(mosq, "test.mosquitto.org", 8883, 60);
    printf("connect returned %d\n", rc);
    mosquitto_destroy(mosq);


    mosquitto_lib_init();


    printf("Calling connect after lib init, this should be fine.\n");
    mosq = mosquitto_new(NULL, true, NULL);
    mosquitto_log_callback_set(mosq, my_log_callback);
    mosquitto_tls_set(mosq, "mosquitto.org.crt", NULL, NULL, NULL, NULL);
    rc = mosquitto_connect(mosq, "test.mosquitto.org", 8883, 60);
    printf("connect returned %d\n", rc);
    mosquitto_destroy(mosq);


    mosquitto_lib_cleanup();


    printf("Calling connect after lib cleanup, this should fail.\n");
    mosq = mosquitto_new(NULL, true, NULL);
    mosquitto_log_callback_set(mosq, my_log_callback);
    mosquitto_tls_set(mosq, "mosquitto.org.crt", NULL, NULL, NULL, NULL);
    rc = mosquitto_connect(mosq, "test.mosquitto.org", 8883, 60);
    printf("connect returned %d\n", rc);
    mosquitto_destroy(mosq);

    return 0;
}

This produces the output:

Calling connect before lib init, this should fail.
LOG: Error: Unable to create TLS context.
LOG: OpenSSL Error: error:140A90A1:lib(20):func(169):reason(161)
connect returned 8
Calling connect after lib init, this should be fine.
LOG: Client mosq/7v?>w@YfTKk\U=;sO] sending CONNECT
connect returned 0
Calling connect after lib cleanup, this should fail.
LOG: Error: Unable to create TLS context.
LOG: OpenSSL Error: error:140A90F1:lib(20):func(169):reason(241)
connect returned 8

The final OpenSSL error is the same as yours, so you need to check whether you've deinitialised openssl. This is something mosquitto_lib_cleanup() does, but it could be something your code is doing completely independently of libmosquitto.

ralight
  • 11,033
  • 3
  • 49
  • 59
  • I tried with different versions of tls, there is always the same problem. Are there no known problem with mosquitto and TLS ? I will try the patch you've send, thanks. – Antoine May 03 '16 at 08:39
  • With the patch you provided I get the following output : `OpenSSL Error: error:140A90F1:lib(20):func(169):reason(241)` – Antoine May 03 '16 at 11:09
  • That suggests that `mosquitto_lib_init()` hasn't been called, or that the openssl library has been deinitialised - possibly by calling `mosquitto_lib_cleanup()`. – ralight May 03 '16 at 16:33
  • Judging by the (incomplete) code OP posted above, he is calling `mosquitto_lib_init()` ... – jpmens May 03 '16 at 16:48
  • I do not call mosquitto_lib_cleanup(), but I do call mosquitto_lib_init() before doing anything else. Although I forgot to tell that I was not using the main loop, please see my edit in my first post – Antoine May 04 '16 at 08:20
  • You are right, somewhere else in the code SSL was used and cleaned, which was producing the error. Thank you very much, my problem is now solved ! :) – Antoine May 11 '16 at 17:42
  • I'm glad you got to the bottom of it finally. – ralight May 11 '16 at 18:49