1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00

Update address lookup in C TLS client to use modern methods.

The implementation using gethostbyname() was only intended to be used during prototyping but was forgotten when the code was finalized.

Replace it with gettaddrinfo() which is more modern and supports IPv6.

Suggested by Bruno Friedmann.
This commit is contained in:
David Steele 2019-01-26 12:01:18 +02:00
parent 4d1060ea6b
commit 053972bfe0
4 changed files with 60 additions and 15 deletions

View File

@ -30,6 +30,14 @@
<p>Add <id>_DARWIN_C_SOURCE</id> flag to Makefile for <proper>MacOS</proper> builds.</p> <p>Add <id>_DARWIN_C_SOURCE</id> flag to Makefile for <proper>MacOS</proper> builds.</p>
</release-item> </release-item>
<release-item>
<release-item-contributor-list>
<release-item-ideator id="bruno.friedmann"/>
</release-item-contributor-list>
<p>Update address lookup in C TLS client to use modern methods.</p>
</release-item>
</release-improvement-list> </release-improvement-list>
<release-development-list> <release-development-list>
@ -6128,6 +6136,11 @@
<contributor-id type="github">baburdick</contributor-id> <contributor-id type="github">baburdick</contributor-id>
</contributor> </contributor>
<contributor id="bruno.friedmann">
<contributor-name-display>Bruno Friedmann</contributor-name-display>
<contributor-id type="github">tigerfoot</contributor-id>
</contributor>
<contributor id="camilo.aguilar"> <contributor id="camilo.aguilar">
<contributor-name-display>Camilo Aguilar</contributor-name-display> <contributor-name-display>Camilo Aguilar</contributor-name-display>
<contributor-id type="github">c4milo</contributor-id> <contributor-id type="github">c4milo</contributor-id>

View File

@ -287,24 +287,43 @@ tlsClientOpen(TlsClient *this)
TRY_BEGIN() TRY_BEGIN()
{ {
// Resolve the ip address. We'll just blindly take the first address that comes up. // Set hits that narrow the type of address we are looking for -- we'll take ipv4 or ipv6
struct hostent *host_entry = NULL; struct addrinfo hints;
if ((host_entry = gethostbyname(strPtr(this->host))) == NULL) memset(&hints, 0, sizeof hints);
THROW_FMT(HostConnectError, "unable to resolve host '%s'", strPtr(this->host)); hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Connect to the server // Convert the port to a zero-terminated string for use with getaddrinfo()
this->socket = socket(AF_INET, SOCK_STREAM, 0); char port[32];
THROW_ON_SYS_ERROR(this->socket == -1, HostConnectError, "unable to create socket"); cvtUIntToZ(this->port, port, sizeof(port));
struct sockaddr_in socketAddr; // Get an address for the host. We are only going to try the first address returned.
memset(&socketAddr, 0, sizeof(socketAddr)); struct addrinfo *hostAddress;
socketAddr.sin_family = AF_INET; int result;
socketAddr.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr*)host_entry->h_addr_list[0])));
socketAddr.sin_port = htons((uint16_t)this->port);
if (connect(this->socket, (struct sockaddr *)&socketAddr, sizeof(socketAddr)) == -1) if ((result = getaddrinfo(strPtr(this->host), port, &hints, &hostAddress)) != 0)
THROW_SYS_ERROR_FMT(HostConnectError, "unable to connect to '%s:%u'", strPtr(this->host), this->port); {
THROW_FMT(
HostConnectError, "unable to get address for '%s': [%d] %s", strPtr(this->host), result,
gai_strerror(result));
}
// Connect to the host
TRY_BEGIN()
{
this->socket = socket(hostAddress->ai_family, hostAddress->ai_socktype, hostAddress->ai_protocol);
THROW_ON_SYS_ERROR(this->socket == -1, HostConnectError, "unable to create socket");
if (connect(this->socket, hostAddress->ai_addr, hostAddress->ai_addrlen) == -1)
THROW_SYS_ERROR_FMT(HostConnectError, "unable to connect to '%s:%u'", strPtr(this->host), this->port);
}
FINALLY()
{
freeaddrinfo(hostAddress);
}
TRY_END();
// Enable TCP keepalives // Enable TCP keepalives
int socketValue = 1; int socketValue = 1;

View File

@ -121,7 +121,8 @@ testRun(void)
// Connection errors // Connection errors
// ------------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------------
TEST_ASSIGN(client, tlsClientNew(strNew("99.99.99.99.99"), 9443, 0, true, NULL, NULL), "new client"); TEST_ASSIGN(client, tlsClientNew(strNew("99.99.99.99.99"), 9443, 0, true, NULL, NULL), "new client");
TEST_ERROR(tlsClientOpen(client), HostConnectError, "unable to resolve host '99.99.99.99.99'"); TEST_ERROR(
tlsClientOpen(client), HostConnectError, "unable to get address for '99.99.99.99.99': [-2] Name or service not known");
TEST_ASSIGN(client, tlsClientNew(strNew("localhost"), 9443, 100, true, NULL, NULL), "new client"); TEST_ASSIGN(client, tlsClientNew(strNew("localhost"), 9443, 100, true, NULL, NULL), "new client");
TEST_ERROR(tlsClientOpen(client), HostConnectError, "unable to connect to 'localhost:9443': [111] Connection refused"); TEST_ERROR(tlsClientOpen(client), HostConnectError, "unable to connect to 'localhost:9443': [111] Connection refused");

View File

@ -5,6 +5,18 @@
obj:*/libcrypto.so* obj:*/libcrypto.so*
} }
# This is an issue on CentOS 7 after calling getaddrinfo() even if freeaddrinfo() is called as well
{
ignore_free_error_after_getaddrinfo
Memcheck:Free
fun:free
fun:__libc_freeres
fun:_vgnU_freeres
fun:__run_exit_handlers
fun:exit
...
}
# This only seems to be an issue on Ubuntu 12.04 -- probably due to the old version of Valgrind # This only seems to be an issue on Ubuntu 12.04 -- probably due to the old version of Valgrind
{ {
ignore_libcrypto_uninit_cond_jump ignore_libcrypto_uninit_cond_jump