diff --git a/libraries/SocketWrapper/SocketWrapper.h b/libraries/SocketWrapper/SocketWrapper.h index c9af9ff7..5f6337e8 100644 --- a/libraries/SocketWrapper/SocketWrapper.h +++ b/libraries/SocketWrapper/SocketWrapper.h @@ -30,8 +30,8 @@ class ZephyrSocketWrapper { bool connect(const char *host, uint16_t port) { // Resolve address - struct addrinfo hints; - struct addrinfo *res; + struct addrinfo hints = {0}; + struct addrinfo *res = nullptr; bool rv = true; hints.ai_family = AF_INET; @@ -102,24 +102,27 @@ class ZephyrSocketWrapper { } #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) - bool connectSSL(const char *host, uint16_t port, char *ca_certificate_pem = nullptr) { + bool connectSSL(const char *host, uint16_t port, const char *ca_certificate_pem = nullptr) { // Resolve address - struct addrinfo hints; - struct addrinfo *res; + struct addrinfo hints = {0}; + struct addrinfo *res = nullptr; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; int resolve_attempts = 100; int ret; - bool rv = true; + bool rv = false; sec_tag_t sec_tag_opt[] = { CA_CERTIFICATE_TAG, }; - uint32_t timeo_optval = 100; + struct timeval timeout_opt = { + .tv_sec = 0, + .tv_usec = 100000, + }; while (resolve_attempts--) { ret = getaddrinfo(host, String(port).c_str(), &hints, &res); @@ -132,33 +135,33 @@ class ZephyrSocketWrapper { } if (ret != 0) { - rv = false; goto exit; } if (ca_certificate_pem != nullptr) { ret = tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, ca_certificate_pem, strlen(ca_certificate_pem) + 1); + if (ret != 0) { + goto exit; + } } sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2); if (sock_fd < 0) { - rv = false; goto exit; } - setsockopt(sock_fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt)); - - setsockopt(sock_fd, SOL_TLS, TLS_HOSTNAME, host, strlen(host)); - - setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof(timeo_optval)); + if (setsockopt(sock_fd, SOL_TLS, TLS_HOSTNAME, host, strlen(host)) || + setsockopt(sock_fd, SOL_TLS, TLS_SEC_TAG_LIST, sec_tag_opt, sizeof(sec_tag_opt)) || + setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout_opt, sizeof(timeout_opt))) { + goto exit; + } if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) { - ::close(sock_fd); - sock_fd = -1; - rv = false; goto exit; } + + rv = true; is_ssl = true; exit: @@ -167,6 +170,10 @@ class ZephyrSocketWrapper { res = nullptr; } + if (!rv && sock_fd >= 0) { + ::close(sock_fd); + sock_fd = -1; + } return rv; } #endif diff --git a/libraries/SocketWrapper/ZephyrClient.h b/libraries/SocketWrapper/ZephyrClient.h index 37ee7401..d338d766 100644 --- a/libraries/SocketWrapper/ZephyrClient.h +++ b/libraries/SocketWrapper/ZephyrClient.h @@ -32,8 +32,8 @@ class ZephyrClient : public arduino::Client, ZephyrSocketWrapper { return ret; } #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) - int connectSSL(const char *host, uint16_t port, char *cert) { - auto ret = ZephyrSocketWrapper::connectSSL((char *)host, port, cert); + int connectSSL(const char *host, uint16_t port, const char *cert) { + auto ret = ZephyrSocketWrapper::connectSSL(host, port, cert); if (ret) { _connected = true; } diff --git a/libraries/SocketWrapper/ZephyrSSLClient.h b/libraries/SocketWrapper/ZephyrSSLClient.h index 2c7bd461..a29bd13d 100644 --- a/libraries/SocketWrapper/ZephyrSSLClient.h +++ b/libraries/SocketWrapper/ZephyrSSLClient.h @@ -14,7 +14,7 @@ class ZephyrSSLClient : public ZephyrClient { return connectSSL(host, port, nullptr); } - int connect(const char *host, uint16_t port, char *cert) { + int connect(const char *host, uint16_t port, const char *cert) { return connectSSL(host, port, cert); } }; diff --git a/libraries/WiFi/examples/WiFiWebClientTLS/WiFiWebClientTLS.ino b/libraries/WiFi/examples/WiFiWebClientTLS/WiFiWebClientTLS.ino new file mode 100644 index 00000000..5907d158 --- /dev/null +++ b/libraries/WiFi/examples/WiFiWebClientTLS/WiFiWebClientTLS.ino @@ -0,0 +1,116 @@ +/* + Web client with single CA certificate test + + This sketch demonstrates how to load your own TLS CA certificates + and use them to establish a secure connection to a remote server, + such as www.howsmyssl.com. +*/ + +#include +#include +#include "arduino_secrets.h" + +char ssid[] = SECRET_SSID; +char pass[] = SECRET_PASS; + +char server[] = "www.howsmyssl.com"; +int port = 443; + +ZephyrSSLClient client; +int status = WL_IDLE_STATUS; + +// ISRG Root X1 (Let's Encrypt root CA certificate) +const char isrg_root_x1[] = +"-----BEGIN CERTIFICATE-----\n" +"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\n" +"-----END CERTIFICATE-----\n"; + +void setup() { + Serial.begin(115200); + while (!Serial) { + ; + } + + // Check for WiFi module + if (WiFi.status() == WL_NO_SHIELD) { + Serial.println("Communication with WiFi module failed!"); + return; + } + + // Connect to WiFi + while (status != WL_CONNECTED) { + Serial.print("Attempting to connect to SSID: "); + Serial.println(ssid); + status = WiFi.begin(ssid, pass); + delay(3000); + } + + Serial.println("Connected to wifi"); + Serial.print("IP Address: "); + Serial.println(WiFi.localIP()); + Serial.print("RSSI: "); + Serial.println(WiFi.RSSI()); + + Serial.println("\nStarting connection to server..."); + + if (client.connect(server, port, isrg_root_x1)) { + Serial.println("Connected to server!"); + + // Make HTTP request + client.println("GET /a/check HTTP/1.1"); + client.print("Host: "); + client.println(server); + client.println("Connection: close"); + client.println(); + } else { + Serial.println("Connection failed!"); + } +} + +void loop() { + // if there are incoming bytes available + // from the server, read them and print them: + while (client.available()) { + char c = client.read(); + Serial.write(c); + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + Serial.println(); + Serial.println("disconnecting from server."); + client.stop(); + + // do nothing forevermore: + while (true) + ; + } +} diff --git a/libraries/WiFi/examples/WiFiWebClientTLS/arduino_secrets.h b/libraries/WiFi/examples/WiFiWebClientTLS/arduino_secrets.h new file mode 100644 index 00000000..0c9fdd55 --- /dev/null +++ b/libraries/WiFi/examples/WiFiWebClientTLS/arduino_secrets.h @@ -0,0 +1,2 @@ +#define SECRET_SSID "" +#define SECRET_PASS ""