【问题标题】:mosquitto and SSL/TLS in C [closed]C中的蚊子和SSL / TLS [关闭]
【发布时间】:2016-05-02 15:54:08
【问题描述】:

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

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

我在 Linux 上使用 libmosquitto 1.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.
}

有谁知道可能是什么问题?

干杯,

安东尼

编辑:我忘了补充一点,我没有使用 mosquitto 的主循环,因为我使用的另一个库已经有一个,而且我需要的线程数量非常有限。因此,每次文件描述符更改时,我都会调用mosquitto_loop()

【问题讨论】:

  • 我们需要真实数据,例如服务器名称,而不是虚假数据,例如 mqtt.example.com
  • 我看不出服务器名称与我遇到的问题有什么关系——我试图尽可能简化代码,但所有对 mosquitto lib 的调用都在这里

标签: c openssl mqtt mosquitto libmosquitto


【解决方案1】:

只有在 SSL_CTX_new() 失败时才会出现此问题。如果 mosquitto_sub 在同一台机器上运行良好,这似乎不太可能。尝试将“tlsv1”、“tlsv1.1”作为 tls_opts_set 的其他选项。您还可以尝试修补 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;
}

这会产生输出:

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

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

【讨论】:

  • 我尝试了不同版本的tls,总是有同样的问题。 mosquitto 和 TLS 没有已知问题吗?我会试试你发送的补丁,谢谢。
  • 使用您提供的补丁,我得到以下输出:OpenSSL Error: error:140A90F1:lib(20):func(169):reason(241)
  • 这表明 mosquitto_lib_init() 尚未被调用,或者 openssl 库已被取消初始化 - 可能通过调用 mosquitto_lib_cleanup()
  • 从上面发布的(不完整的)代码 OP 来看,他正在调用mosquitto_lib_init() ...
  • 我不调用 mosquitto_lib_cleanup(),但在做其他事情之前我会调用 mosquitto_lib_init()。虽然我忘了说我没有使用主循环,但请在我的第一篇文章中查看我的编辑
猜你喜欢
  • 2018-11-17
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
  • 2017-05-07
  • 2011-09-12
  • 2012-12-03
  • 1970-01-01
  • 2020-07-17
相关资源
最近更新 更多