Комаров и SSL/TLS в C
Я пытаюсь подключиться к брокеру MQTT в SSL/TLS с помощью libmosquitto (в C). Я уверен, что он работает на стороне сервера, так как я успешно подключился к программе-участнику с помощью mosquitto_sub (или mosquitto_pub) в командной строке и с тем же сертификатом, который я использую в своем коде.
Когда я пытаюсь подключиться с помощью моей программы на C, я всегда получаю следующую ошибку: "Ошибка: невозможно создать контекст TLS".
Я использую libmosquitto 1.4.8 в Linux. Вот код, который я использую:
#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.
}
Кто-нибудь знает в чем может быть проблема?
Ура,
Antoine
РЕДАКТИРОВАТЬ: я забыл добавить, что я не использую основной цикл комара, потому что другая библиотека, которую я использую, уже имеет одну, и мне нужно иметь очень ограниченное количество потоков. Поэтому я звоню mosquitto_loop()
каждый раз, когда дескриптор файла изменяется.
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.