C中的MOSQUITO和SSL/TLS

C中的MOSQUITO和SSL/TLS,c,openssl,mqtt,mosquitto,libmosquitto,C,Openssl,Mqtt,Mosquitto,Libmosquitto,我正在尝试使用libmosquitto(在C中)连接到SSL/TLS中的MQTT代理。我确信它在服务器端工作,因为我在命令行中使用mosquitto_sub(或mosquitto_pub)成功连接到borker,并且使用我在代码中使用的相同证书 当我尝试使用我的C程序进行连接时,总是会出现以下错误:“错误:无法创建TLS上下文。” 我正在Linux上使用libmosquitto1.4.8。以下是我正在使用的代码: #include <mosquitto.h> static stru

我正在尝试使用libmosquitto(在C中)连接到SSL/TLS中的MQTT代理。我确信它在服务器端工作,因为我在命令行中使用mosquitto_sub(或mosquitto_pub)成功连接到borker,并且使用我在代码中使用的相同证书

当我尝试使用我的C程序进行连接时,总是会出现以下错误:“错误:无法创建TLS上下文。”

我正在Linux上使用libmosquitto1.4.8。以下是我正在使用的代码:

#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.
}
#包括
静态结构SomeStruct*data=NULL;
//变量mosq包含在结构中
//该结构已在其他地方创建
无效foo(无效)
{
//我通常检查返回值,但已删除
//这是为了使代码更容易阅读
Mosquito_lib_init();
数据->mosq=mosquitto_new(“foobar”,true,data);
//连接回调
MOSQUITO_用户名_pw_集(数据->mosq,“用户”,“通过”);
mosquito_tls_set(数据->mosq,“/path/to/ca/file.crt,
空,空,空,空);
MOSQUITO\u tls\u不安全\u集(数据->mosq,1)
MOSQUITO\u tls\u选项集(数据->mosq,
1,//也尝试了0
NULL,//还尝试了“tlsv1.2”
无效);
//到目前为止,所有返回值都是正确的
mosquitto_connect(data->mosq,“mqtt.example.com”,8883,30);//失败
//日志:错误:无法创建TLS上下文。
//发生TLS错误。
}
有人知道可能是什么问题吗

干杯

安托万


编辑:我忘记添加我没有使用mosquitto的主循环,因为我使用的另一个库已经有一个主循环,并且我需要的线程数量非常有限。因此,每当文件描述符更改时,我都调用
mosquitto\u循环()

只有在SSL\u CTX\u new()的情况下才会发生此问题失败。如果mosquitto_sub在同一台机器上正常工作,这似乎不太可能。请尝试“tlsv1”、“tlsv1.1”作为tls_opts_集合的其他选项。您也可以尝试修补mosquitto客户端库,以获取有关openssl不满意原因的更多信息:

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;
                }

再现问题的示例代码:

#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;
}

最后的OpenSSL错误与您的相同,因此您需要检查是否已取消初始化OpenSSL是的,但这可能是您的代码完全独立于libmosquito所做的事情。

我们需要真实的数据,如服务器名称,而不是虚假的数据,如
mqtt.example.com
。我不知道服务器名称与我遇到的问题有什么关系-我试图尽可能简化代码,但对mos的所有调用quitto lib在这里我尝试了不同版本的tls,但始终存在相同的问题。mosquitto和tls是否没有已知问题?我将尝试您发送的修补程序,谢谢。使用您提供的修补程序,我得到以下输出:
OpenSSL错误:错误:140A90F1:lib(20):func(169):原因(241)
这表明
mosquitto_lib_init()
没有被调用,或者openssl库已经被去初始化-可能是通过调用
mosquitto_lib_cleanup()
来实现的。根据上面发布的(不完整的)代码OP判断,他正在调用
mosquitto_lib_init()
…我不调用mosquitto_lib_cleanup(),但我确实在做任何其他事情之前调用了mosquito_lib_init()。虽然我忘了告诉您我没有使用主循环,但请参阅我在第一篇文章中的编辑
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