LiamBindle / MQTT-C

A portable MQTT C client for embedded systems and PCs alike.
https://liambindle.ca/MQTT-C
MIT License
766 stars 269 forks source link

`mqtt_connect` with Unvalidated SSL-connection returns `MQTT_ERROR_SOCKET_ERROR` #192

Open J-Kappes opened 1 month ago

J-Kappes commented 1 month ago

I used the following variation on the posix_sockets.h template.

`posix_sockets.h` ```c #if !defined(__POSIX_SOCKET_TEMPLATE_H__) #define __POSIX_SOCKET_TEMPLATE_H__ #include #include #include #if !defined(WIN32) #include #include #include #else #include #endif #if defined(__VMS) #include #endif #include #include #include #include /* A template for opening a non-blocking POSIX socket with SSL encryption. */ int open_nb_socket(const char* addr, const char* port, BIO** bio, SSL_CTX** ssl_ctx); int open_nb_socket(const char* addr, const char* port, BIO** bio, SSL_CTX** ssl_ctx) { struct addrinfo hints = {0}; hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */ hints.ai_socktype = SOCK_STREAM; /* Must be TCP */ int sockfd = -1; int rv; struct addrinfo *p, *servinfo; /* get address information */ rv = getaddrinfo(addr, port, &hints, &servinfo); if(rv != 0) { fprintf(stderr, "Failed to open socket (getaddrinfo): %s\n", gai_strerror(rv)); return -1; } /* open the first possible socket */ for(p = servinfo; p != NULL; p = p->ai_next) { sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sockfd == -1) continue; /* connect to server */ rv = connect(sockfd, p->ai_addr, p->ai_addrlen); if(rv == -1) { close(sockfd); sockfd = -1; continue; } break; } /* free servinfo */ freeaddrinfo(servinfo); if (sockfd == -1) { fprintf(stderr, "Failed to open socket\n"); return -1; } /* make non-blocking */ #if !defined(WIN32) if (sockfd != -1) fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); #else if (sockfd != INVALID_SOCKET) { int iMode = 1; ioctlsocket(sockfd, FIONBIO, &iMode); } #endif #if defined(__VMS) /* OpenVMS only partially implements fcntl. It works on file descriptors but silently fails on socket descriptors. So we need to fall back on to the older ioctl system to set non-blocking IO */ int on = 1; if (sockfd != -1) ioctl(sockfd, FIONBIO, &on); #endif /* Initialize OpenSSL */ SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); *ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if (!*ssl_ctx) { fprintf(stderr, "Failed to create SSL context\n"); close(sockfd); return -1; } /* Create BIO and set SSL */ *bio = BIO_new_ssl(*ssl_ctx, 1); SSL* ssl; BIO_get_ssl(*bio, &ssl); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* Set file descriptor for BIO */ BIO* bio_socket = BIO_new(BIO_s_socket()); BIO_set_fd(bio_socket, sockfd, BIO_NOCLOSE); *bio = BIO_push(*bio, bio_socket); /* Return the socket file descriptor */ return sockfd; } #endif ```