diff --git a/src/server.c b/src/server.c index b948fedf..f1a2291a 100644 --- a/src/server.c +++ b/src/server.c @@ -569,7 +569,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) struct sockaddr_in *addr = (struct sockaddr_in *)&storage; size_t in_addr_len = sizeof(struct in_addr); addr->sin_family = AF_INET; - if (r > in_addr_len) { + if (r > in_addr_len + 3) { addr->sin_addr = *(struct in_addr *)(server->buf + offset); dns_ntop(AF_INET, (const void *)(server->buf + offset), host, INET_ADDRSTRLEN); @@ -589,7 +589,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) } else if ((atyp & ADDRTYPE_MASK) == 3) { // Domain name uint8_t name_len = *(uint8_t *)(server->buf + offset); - if (name_len < r) { + if (name_len + 4 < r) { memcpy(host, server->buf + offset + 1, name_len); offset += name_len + 1; } else { @@ -627,7 +627,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage; size_t in6_addr_len = sizeof(struct in6_addr); addr->sin6_family = AF_INET6; - if (r > in6_addr_len) { + if (r > in6_addr_len + 3) { addr->sin6_addr = *(struct in6_addr *)(server->buf + offset); dns_ntop(AF_INET6, (const void *)(server->buf + offset), host, INET6_ADDRSTRLEN); diff --git a/src/udprelay.c b/src/udprelay.c index 2d5f9437..cb78132d 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -229,7 +229,7 @@ static int parse_udprealy_header(const char * buf, const int buf_len, if ((atyp & ADDRTYPE_MASK) == 1) { // IP V4 size_t in_addr_len = sizeof(struct in_addr); - if (buf_len > in_addr_len) { + if (buf_len > in_addr_len + 3) { if (storage != NULL) { struct sockaddr_in *addr = (struct sockaddr_in *)storage; addr->sin_family = AF_INET; @@ -245,32 +245,34 @@ static int parse_udprealy_header(const char * buf, const int buf_len, } else if ((atyp & ADDRTYPE_MASK) == 3) { // Domain name uint8_t name_len = *(uint8_t *)(buf + offset); - if (name_len < buf_len && name_len < 255 && name_len > 0) { + if (name_len + 4 < buf_len) { + if (storage != NULL) { + char tmp[256] = {0}; + struct cork_ip ip; + memcpy(tmp, buf + offset + 1, name_len); + if (cork_ip_init(&ip, tmp) != -1) { + if (ip.version == 4) { + struct sockaddr_in *addr = (struct sockaddr_in *)storage; + dns_pton(AF_INET, tmp, &(addr->sin_addr)); + addr->sin_port = *(uint16_t *)(buf + offset + 1 + name_len); + addr->sin_family = AF_INET; + } else if (ip.version == 6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage; + dns_pton(AF_INET, tmp, &(addr->sin6_addr)); + addr->sin6_port = *(uint16_t *)(buf + offset + 1 + name_len); + addr->sin6_family = AF_INET6; + } + } + } if (host != NULL) { memcpy(host, buf + offset + 1, name_len); } - offset += name_len + 1; - } - if (storage != NULL) { - struct cork_ip ip; - if (cork_ip_init(&ip, host) != -1) { - if (ip.version == 4) { - struct sockaddr_in *addr = (struct sockaddr_in *)storage; - dns_pton(AF_INET, host, &(addr->sin_addr)); - addr->sin_port = *(uint16_t *)(buf + offset); - addr->sin_family = AF_INET; - } else if (ip.version == 6) { - struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage; - dns_pton(AF_INET, host, &(addr->sin6_addr)); - addr->sin6_port = *(uint16_t *)(buf + offset); - addr->sin6_family = AF_INET6; - } - } + offset += 1 + name_len; } } else if ((atyp & ADDRTYPE_MASK) == 4) { // IP V6 size_t in6_addr_len = sizeof(struct in6_addr); - if (buf_len > in6_addr_len) { + if (buf_len > in6_addr_len + 3) { if (storage != NULL) { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage; addr->sin6_family = AF_INET6;