1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +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>
</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-development-list>
@ -6128,6 +6136,11 @@
<contributor-id type="github">baburdick</contributor-id>
</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-name-display>Camilo Aguilar</contributor-name-display>
<contributor-id type="github">c4milo</contributor-id>

View File

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

View File

@ -121,7 +121,8 @@ testRun(void)
// Connection errors
// -------------------------------------------------------------------------------------------------------------------------
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_ERROR(tlsClientOpen(client), HostConnectError, "unable to connect to 'localhost:9443': [111] Connection refused");

View File

@ -5,6 +5,18 @@
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
{
ignore_libcrypto_uninit_cond_jump