From 26e9007fd7cb20da25beca6fd16a7fe51b56288a Mon Sep 17 00:00:00 2001 From: Adam Shapiro Date: Tue, 6 Apr 2021 17:12:03 -0400 Subject: [PATCH 1/5] Include the error code in the perror printout. --- c/src/point_one/polaris/portability.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/c/src/point_one/polaris/portability.h b/c/src/point_one/polaris/portability.h index b3a73a4..69e7bee 100644 --- a/c/src/point_one/polaris/portability.h +++ b/c/src/point_one/polaris/portability.h @@ -52,17 +52,26 @@ static inline int P1_GetElapsedMS(const P1_TimeValue_t* start, #else // POSIX +# include # include # include # ifndef P1_printf # define P1_printf printf # endif + # ifndef P1_fprintf # define P1_fprintf fprintf # endif + +// The standard POSIX perror() does not include the numeric error code in the +// printout, which is often very useful, so we do not use it. +// +// Note that we ignore the ret argument here, which is meant for use with +// FreeRTOS, and instead get the actual error value from errno on POSIX systems. # ifndef P1_perror -# define P1_perror(format, ...) perror(format) +# define P1_perror(format, ret) \ + P1_fprintf(stderr, format ". [error=%s (%d)]\n", strerror(errno), errno) # endif typedef struct timeval P1_TimeValue_t; From 962f830244197fb538c29b809fdeac9dcd92d0e7 Mon Sep 17 00:00:00 2001 From: Adam Shapiro Date: Tue, 6 Apr 2021 18:04:45 -0400 Subject: [PATCH 2/5] Use SSL_get_error() to print the SSL error code instead of -1. OpenSSL functions return their error codes via SSL_get_error() instead of errno, so we can't use the normal perror()/strerror(). They also do not have a function --- c/src/point_one/polaris/polaris.c | 72 ++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/c/src/point_one/polaris/polaris.c b/c/src/point_one/polaris/polaris.c index 8569b97..388070b 100644 --- a/c/src/point_one/polaris/polaris.c +++ b/c/src/point_one/polaris/polaris.c @@ -12,6 +12,7 @@ #include // For memmove() #ifdef POLARIS_USE_TLS +#include #include #endif @@ -26,6 +27,66 @@ #define P1_PrintError(x, ...) \ P1_perror("polaris.c:" STR(__LINE__) "] " x, ##__VA_ARGS__) +#if defined(POLARIS_USE_TLS) +static void __P1_PrintWriteError(int line, PolarisContext_t* context, + const char* message, int ret) { + SSL_load_error_strings(); + int ssl_error = SSL_get_error(context->ssl, ret); + if (ssl_error == SSL_ERROR_SYSCALL) { + P1_fprintf(stderr, + "polaris.c:%d] %s. [error=%s (syscall: errno=%d; %s)]\n", + line, message, strerror(errno), errno, + ERR_error_string(ssl_error, NULL)); + } else { + // Note: OpenSSL has a function sort of like strerror(), SSL_error_string(), + // but in practice its output is less than helpful most of the time. We'll + // still print it, but we'll also print out our own error name string: + const char* error_name; + switch (ssl_error) { + case SSL_ERROR_NONE: + error_name = "SSL_ERROR_NONE"; + break; + case SSL_ERROR_SSL: + error_name = "SSL_ERROR_SSL"; + break; + case SSL_ERROR_WANT_READ: + error_name = "SSL_ERROR_WANT_READ"; + break; + case SSL_ERROR_WANT_WRITE: + error_name = "SSL_ERROR_WANT_WRITE"; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + error_name = "SSL_ERROR_WANT_X509_LOOKUP"; + break; + // case SSL_ERROR_SYSCALL: + // error_name = "SSL_ERROR_SYSCALL"; + // break; + case SSL_ERROR_ZERO_RETURN: + error_name = "SSL_ERROR_ZERO_RETURN"; + break; + case SSL_ERROR_WANT_CONNECT: + error_name = "SSL_ERROR_WANT_CONNECT"; + break; + case SSL_ERROR_WANT_ACCEPT: + error_name = "SSL_ERROR_WANT_ACCEPT"; + break; + default: + error_name = ""; + break; + } + + P1_fprintf(stderr, "polaris.c:%d] %s. [error=%s (%d; %s)]\n", line, message, + error_name, ssl_error, ERR_error_string(ssl_error, NULL)); + } +} + +#define P1_PrintWriteError(context, x, ret) \ + __P1_PrintWriteError(__LINE__, context, x, ret) +#else +#define P1_PrintWriteError(context, x, ret) P1_PrintError(x, ret) +#endif + + #if defined(POLARIS_TRACE) && !defined(POLARIS_DEBUG) # define POLARIS_DEBUG 1 #endif @@ -96,7 +157,6 @@ int Polaris_Init(PolarisContext_t* context) { SSL_library_init(); OpenSSL_add_all_algorithms(); - SSL_load_error_strings(); #endif return POLARIS_SUCCESS; @@ -259,7 +319,7 @@ int Polaris_ConnectTo(PolarisContext_t* context, const char* endpoint_url, ret = send(context->socket, context->recv_buffer, message_size, 0); #endif if (ret != message_size) { - P1_PrintError("Error sending authentication token", ret); + P1_PrintWriteError(context, "Error sending authentication token", ret); CloseSocket(context, 1); return POLARIS_SEND_ERROR; } @@ -329,7 +389,7 @@ int Polaris_SendECEFPosition(PolarisContext_t* context, double x_m, double y_m, #endif if (ret != message_size) { - P1_PrintError("Error sending ECEF position", ret); + P1_PrintWriteError(context, "Error sending ECEF position", ret); return POLARIS_SEND_ERROR; } else { return POLARIS_SUCCESS; @@ -372,7 +432,7 @@ int Polaris_SendLLAPosition(PolarisContext_t* context, double latitude_deg, #endif if (ret != message_size) { - P1_PrintError("Error sending LLA position", ret); + P1_PrintWriteError(context, "Error sending LLA position", ret); return POLARIS_SEND_ERROR; } else { return POLARIS_SUCCESS; @@ -403,7 +463,7 @@ int Polaris_RequestBeacon(PolarisContext_t* context, const char* beacon_id) { #endif if (ret != message_size) { - P1_PrintError("Error sending beacon request", ret); + P1_PrintWriteError(context, "Error sending beacon request", ret); return POLARIS_SEND_ERROR; } else { return POLARIS_SUCCESS; @@ -727,7 +787,7 @@ static int SendPOSTRequest(PolarisContext_t* context, const char* endpoint_url, #endif if (ret != message_size) { - P1_PrintError("Error sending POST request", ret); + P1_PrintWriteError(context, "Error sending POST request", ret); CloseSocket(context, 1); return POLARIS_SEND_ERROR; } From 5e998ac8064189ab559586331212e5c4a791754b Mon Sep 17 00:00:00 2001 From: Adam Shapiro Date: Tue, 6 Apr 2021 21:00:13 -0400 Subject: [PATCH 3/5] Use the TLS port for connections in the C++ library. --- examples/ntrip/ntrip_example.cc | 2 +- src/point_one/polaris/polaris_interface.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ntrip/ntrip_example.cc b/examples/ntrip/ntrip_example.cc index 7dfefb4..e565fd4 100644 --- a/examples/ntrip/ntrip_example.cc +++ b/examples/ntrip/ntrip_example.cc @@ -30,7 +30,7 @@ DEFINE_string( polaris_host, POLARIS_ENDPOINT_URL, "The Polaris corrections endpoint URL to be used."); -DEFINE_int32(polaris_port, POLARIS_ENDPOINT_PORT, +DEFINE_int32(polaris_port, POLARIS_ENDPOINT_TLS_PORT, "The TCP port of the Polaris corrections endpoint."); DEFINE_string(polaris_api_key, "", diff --git a/src/point_one/polaris/polaris_interface.h b/src/point_one/polaris/polaris_interface.h index 3d833c4..de83bf1 100644 --- a/src/point_one/polaris/polaris_interface.h +++ b/src/point_one/polaris/polaris_interface.h @@ -15,7 +15,7 @@ namespace point_one { namespace polaris { extern const std::string DEFAULT_ENDPOINT_URL; -static constexpr int DEFAULT_ENDPOINT_PORT = POLARIS_ENDPOINT_PORT; +static constexpr int DEFAULT_ENDPOINT_PORT = POLARIS_ENDPOINT_TLS_PORT; /** * @brief C++ wrapper class for the Polaris Client C library. From d5edf2b76c8cb2fca99a0b3bfac48b4b82f6a3c6 Mon Sep 17 00:00:00 2001 From: Adam Shapiro Date: Tue, 6 Apr 2021 21:09:20 -0400 Subject: [PATCH 4/5] Catch TLS connections with no encyrption (i.e., wrong endpoint). If TLS is enabled, we assume that we are connecting to a secure endpoint. If not, subsequent SSL_write() calls will fail with SSL_ERROR_SSL. --- c/src/point_one/polaris/polaris.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/c/src/point_one/polaris/polaris.c b/c/src/point_one/polaris/polaris.c index 388070b..b2f3655 100644 --- a/c/src/point_one/polaris/polaris.c +++ b/c/src/point_one/polaris/polaris.c @@ -669,7 +669,18 @@ static int OpenSocket(PolarisContext_t* context, const char* endpoint_url, // Perform SSL handhshake. if (SSL_connect(context->ssl) == -1) { - P1_Print("SSL handshake failed to %s:%d.\n", endpoint_url, endpoint_port); + P1_Print("SSL handshake failed to tcp://%s:%d.\n", endpoint_url, + endpoint_port); + CloseSocket(context, 1); + return POLARIS_ERROR; + } + + const SSL_CIPHER* c = SSL_get_current_cipher(context->ssl); + if (c == NULL) { + P1_Print( + "Server failed to negotiate encryption cipher. Verify that endpoint " + "tcp://%s:%d supports TLS 1.2 or better.\n", + endpoint_url, endpoint_port); CloseSocket(context, 1); return POLARIS_ERROR; } From 90ab759b96da32d152c9f8727abf9bdcbd4c48ce Mon Sep 17 00:00:00 2001 From: Adam Shapiro Date: Tue, 6 Apr 2021 21:10:24 -0400 Subject: [PATCH 5/5] Use the default URL/port defined by the Polaris interface in the NTRIP example. --- examples/ntrip/ntrip_example.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ntrip/ntrip_example.cc b/examples/ntrip/ntrip_example.cc index e565fd4..b99580e 100644 --- a/examples/ntrip/ntrip_example.cc +++ b/examples/ntrip/ntrip_example.cc @@ -27,10 +27,10 @@ using namespace point_one::polaris; // Options for connecting to Polaris Server: DEFINE_string( - polaris_host, POLARIS_ENDPOINT_URL, + polaris_host, DEFAULT_ENDPOINT_URL, "The Polaris corrections endpoint URL to be used."); -DEFINE_int32(polaris_port, POLARIS_ENDPOINT_TLS_PORT, +DEFINE_int32(polaris_port, DEFAULT_ENDPOINT_PORT, "The TCP port of the Polaris corrections endpoint."); DEFINE_string(polaris_api_key, "",