Commit deaad00a authored by Pieter Hintjens's avatar Pieter Hintjens

Problem: zmq_connect() does not validate TCP addresses

Since https://github.com/zeromq/libzmq/commit/350a1a, TCP addresses
get resolved asynchronously, so zmq_connect no longer returned an
error on incorrect addresses.

This is troublesome since we rely on some error checking to catch
blatant errors.

Solution add some upfront syntax checking that catches at least the
obvious kinds of errors (invalid characters, wrong or missing port
number).
parent 40784337
......@@ -596,7 +596,39 @@ int zmq::socket_base_t::connect (const char *addr_)
// Resolve address (if needed by the protocol)
if (protocol == "tcp") {
// Defer resolution until a socket is opened
// Do some basic sanity checks on tcp:// address syntax
// - hostname starts with digit or letter, with embedded '-' or '.'
// - IPv6 address may contain hex chars and colons.
// - IPv4 address may contain decimal digits and dots.
// - Address must end in ":port" where port is *, or numeric
// - Address may contain two parts separated by ':'
// Following code is quick and dirty check to catch obvious errors,
// without trying to be fully accurate.
const char *check = address.c_str ();
if (isalnum (*check) || isxdigit (*check)) {
check++;
while (isalnum (*check)
|| isxdigit (*check)
|| *check == '.' || *check == '-' || *check == ':'|| *check == ';')
check++;
}
// Assume the worst, now look for success
rc = -1;
// Did we reach the end of the address safely?
if (*check == 0) {
// Do we have a valid port string? (cannot be '*' in connect
check = strrchr (address.c_str (), ':');
if (check) {
check++;
if (*check && (isdigit (*check)))
rc = 0; // Valid
}
}
if (rc == -1) {
delete paddr;
return -1;
}
// Defer resolution until a socket is opened
paddr->resolved.tcp_addr = NULL;
}
#if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS
......
......@@ -466,7 +466,8 @@ int zmq::tcp_address_t::to_string (std::string &addr_)
return -1;
}
// not using service resolv because of https://github.com/zeromq/libzmq/commit/1824574f9b5a8ce786853320e3ea09fe1f822bc4
// Not using service resolv because of
// https://github.com/zeromq/libzmq/commit/1824574f9b5a8ce786853320e3ea09fe1f822bc4
char hbuf [NI_MAXHOST];
int rc = getnameinfo (addr (), addrlen (), hbuf, sizeof hbuf, NULL, 0, NI_NUMERICHOST);
if (rc != 0) {
......
......@@ -31,14 +31,18 @@ int main (void)
int rc = zmq_connect (sock, "tcp://localhost:1234");
assert (rc == 0);
// Because of lazy resolution of TCP names, this will succeed
rc = zmq_connect (sock, "tcp://localhost:invalid");
assert (rc == 0);
assert (rc == -1);
// Because of lazy resolution of TCP names, this will succeed
rc = zmq_connect (sock, "tcp://in val id:1234");
assert (rc == 0);
assert (rc == -1);
rc = zmq_connect (sock, "tcp://");
assert (rc == -1);
rc = zmq_connect (sock, "tcp://192.168.0.200:*");
assert (rc == -1);
rc = zmq_connect (sock, "invalid://localhost:1234");
assert (rc == -1);
assert (errno == EPROTONOSUPPORT);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment