Skip to content

Commit 078b689

Browse files
committed
Handle case of host == NULL
The fix addresses two defects. The getaddrinfo interface contract allowed for host == NULL, but Ziti_resolve assumed host != NULL. zitify nc -l 9999 would trigger a fault. Additionally, hints was accessed without checking to ensure it was NULL. Lastly, Ziti_resolve would leak res and addr if the function wasn't successful. Signed-off-by: Tom Carroll <[email protected]>
1 parent d3a58bd commit 078b689

File tree

1 file changed

+66
-26
lines changed

1 file changed

+66
-26
lines changed

library/zitilib.c

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,34 @@ ZITI_FUNC
12251225
int Ziti_resolve(const char *host, const char *port, const struct addrinfo *hints, struct addrinfo **addrlist) {
12261226
in_port_t portnum = port ? (in_port_t) strtol(port, NULL, 10) : 0;
12271227
ZITI_LOG(DEBUG, "host[%s] port[%s]", host, port);
1228-
struct addrinfo *res = calloc(1, sizeof(struct addrinfo));
1228+
1229+
/**
1230+
* Linux and FreeBSD freeaddrinfo(ai) frees ai->canonname and ai, but not ai->ai_addr.
1231+
* ai is allocated large enough to carry the sockaddr
1232+
*/
1233+
union sockaddr_union {
1234+
struct sockaddr sa;
1235+
struct sockaddr_in in4;
1236+
struct sockaddr_in6 in6;
1237+
};
1238+
1239+
struct result_storage {
1240+
struct addrinfo addrinfo;
1241+
union sockaddr_union sockaddr;
1242+
} *store = calloc(1, sizeof *store);
1243+
1244+
if (!store)
1245+
goto error;
1246+
1247+
struct addrinfo *res = &store->addrinfo;
1248+
union sockaddr_union *addr = &store->sockaddr;
1249+
1250+
res->ai_family = AF_UNSPEC;
1251+
res->ai_socktype = 0;
1252+
res->ai_protocol = 0;
1253+
1254+
addr->sa.sa_family = AF_UNSPEC;
1255+
12291256
if (hints) {
12301257
res->ai_socktype = hints->ai_socktype;
12311258
switch (hints->ai_socktype) {
@@ -1239,27 +1266,36 @@ int Ziti_resolve(const char *host, const char *port, const struct addrinfo *hint
12391266
res->ai_protocol = 0;
12401267
break;
12411268
default: // no other protocols are supported
1242-
return -1;
1269+
goto error;
1270+
}
1271+
1272+
switch (hints->ai_family) {
1273+
case AF_INET:
1274+
case AF_INET6:
1275+
case AF_UNSPEC:
1276+
res->ai_family = hints->ai_family;
1277+
break;
1278+
default: // unsupported address family
1279+
goto error;
12431280
}
12441281
}
12451282

1246-
struct sockaddr_in *addr4 = calloc(1, sizeof(struct sockaddr_in6));
1247-
int rc = 0;
1248-
if ((rc = uv_ip4_addr(host, portnum, addr4)) == 0) {
1249-
ZITI_LOG(DEBUG, "host[%s] port[%s] rc = %d", host, port, rc);
1283+
if ((res->ai_family == AF_UNSPEC || res->ai_family == AF_INET)
1284+
&& uv_ip4_addr(host ? host : "127.0.0.1", portnum, &addr->in4) == 0) {
1285+
ZITI_LOG(DEBUG, "host[%s] port[%s]", host, port);
12501286

12511287
res->ai_family = AF_INET;
1252-
res->ai_addr = (struct sockaddr *) addr4;
1253-
res->ai_addrlen = sizeof(struct sockaddr_in);
1254-
1288+
res->ai_addr = &addr->sa;
1289+
res->ai_addrlen = sizeof addr->in4;
12551290
*addrlist = res;
12561291
return 0;
1257-
} else if (uv_ip6_addr(host, portnum, (struct sockaddr_in6 *) addr4) == 0) {
1258-
ZITI_LOG(INFO, "host[%s] port[%s] rc = %d", host, port, rc);
1292+
} else if ((res->ai_family == AF_UNSPEC || res->ai_family == AF_INET6)
1293+
&& uv_ip6_addr(host ? host : "::1", portnum, &addr->in6) == 0) {
1294+
ZITI_LOG(INFO, "host[%s] port[%s]", host, port);
12591295

12601296
res->ai_family = AF_INET6;
1261-
res->ai_addr = (struct sockaddr *) addr4;
1262-
res->ai_addrlen = sizeof(struct sockaddr_in6);
1297+
res->ai_addr = &addr->sa;
1298+
res->ai_addrlen = sizeof addr->in6;
12631299
*addrlist = res;
12641300
return 0;
12651301
}
@@ -1273,14 +1309,14 @@ int Ziti_resolve(const char *host, const char *port, const struct addrinfo *hint
12731309
tlsuv_parse_url(&url, ctrl);
12741310

12751311
if (strncmp(host, url.hostname, url.hostname_len) == 0) {
1276-
return -1;
1312+
goto error;
12771313
}
12781314

12791315
if (wrap->ztx) {
12801316
MODEL_MAP_FOR(chit, wrap->ztx->channels) {
12811317
ziti_channel_t *ch = model_map_it_value(chit);
12821318
if (strcmp(ch->host, host) == 0) {
1283-
return -1;
1319+
goto error;
12841320
}
12851321
}
12861322
}
@@ -1300,21 +1336,25 @@ int Ziti_resolve(const char *host, const char *port, const struct addrinfo *hint
13001336
int err = await_future(f);
13011337
set_error(err);
13021338

1303-
if (err == 0) {
1304-
addr4->sin_family = AF_INET;
1305-
addr4->sin_port = htons(portnum);
1306-
addr4->sin_addr.s_addr = (in_addr_t)(uintptr_t)f->result;
1339+
if (err != 0)
1340+
goto error;
13071341

1308-
res->ai_family = AF_INET;
1309-
res->ai_addr = (struct sockaddr *) addr4;
1310-
res->ai_socktype = hints->ai_socktype;
1342+
addr->in4.sin_family = AF_INET;
1343+
addr->in4.sin_port = htons(portnum);
1344+
addr->in4.sin_addr.s_addr = (in_addr_t)(uintptr_t)f->result;
1345+
1346+
res->ai_family = AF_INET;
1347+
res->ai_addr = &addr->sa;
1348+
res->ai_addrlen = sizeof addr->in4;
1349+
*addrlist = res;
13111350

1312-
res->ai_addrlen = sizeof(*addr4);
1313-
*addrlist = res;
1314-
}
13151351
destroy_future(f);
13161352

1317-
return err == 0 ? 0 : -1;
1353+
return 0;
1354+
1355+
error:
1356+
free(store);
1357+
return -1;
13181358
}
13191359

13201360
int Ziti_check_socket(ziti_socket_t fd) {

0 commit comments

Comments
 (0)