Browse Source

fixed a bug in domain name validation

pull/2430/head
PantherJohn 6 years ago
parent
commit
cb0bf4c549
12 changed files with 25 additions and 82 deletions
  1. 2
      src/CMakeLists.txt
  2. 6
      src/Makefile.am
  3. 2
      src/local.c
  4. 45
      src/netutils.c
  5. 3
      src/netutils.h
  6. 2
      src/redir.c
  7. 2
      src/server.c
  8. 29
      src/shadowsocks.h
  9. 6
      src/tcprelay.c
  10. 4
      src/tcprelay.h
  11. 2
      src/tunnel.c
  12. 4
      src/udprelay.c

2
src/CMakeLists.txt

@ -34,7 +34,7 @@ set(SS_SHARED_SOURCES
json.c
cache.c
netutils.c
relay.c
tcprelay.c
)
set(LIBSHADOWSOCKS_LIBEV_SOURCE

6
src/Makefile.am

@ -42,7 +42,7 @@ common_src = utils.c \
jconf.c \
json.c \
udprelay.c \
relay.c \
tcprelay.c \
cache.c \
netutils.c
@ -101,7 +101,7 @@ ss_redir_SOURCES = utils.c \
netutils.c \
cache.c \
udprelay.c \
relay.c \
tcprelay.c \
redir.c \
$(crypto_src) \
$(plugin_src) \
@ -122,5 +122,5 @@ include_HEADERS = shadowsocks.h
noinst_HEADERS = acl.h crypto.h stream.h aead.h json.h netutils.h tls.h uthash.h \
cache.h http.h plugin.h resolv.h utils.h base64.h ppbloom.h \
common.h jconf.h manager.h protocol.h rule.h socks5.h udprelay.h relay.h winsock.h
common.h jconf.h manager.h protocol.h rule.h socks5.h udprelay.h tcprelay.h winsock.h
EXTRA_DIST = ss-nat

2
src/local.c

@ -57,7 +57,7 @@
#include "tls.h"
#include "plugin.h"
#include "winsock.h"
#include "relay.h"
#include "tcprelay.h"
#include "acl.h"
#ifndef LIB_ONLY

45
src/netutils.c

@ -601,48 +601,13 @@ sockaddr_cmp_addr(struct sockaddr_storage *addr1,
}
}
int
validate_hostname(const char *hostname, const int hostname_len)
{
if (hostname == NULL)
return 0;
if (hostname_len < 1 || hostname_len > 255)
return 0;
if (hostname[0] == '.')
return 0;
const char *label = hostname;
while (label < hostname + hostname_len) {
size_t label_len = hostname_len - (label - hostname);
char *next_dot = strchr(label, '.');
if (next_dot != NULL)
label_len = next_dot - label;
if (label + label_len > hostname + hostname_len)
return 0;
if (label_len > 63 || label_len < 1)
return 0;
if (label[0] == '-' || label[label_len - 1] == '-')
return 0;
if (strspn(label, valid_label_bytes) < label_len)
return 0;
label += label_len + 1;
}
return 1;
}
char *
hostname_readable(char *dname, uint16_t port)
hostname_readable(const char *dname,
const int dname_len, uint16_t port)
{
char *ret = ss_calloc(strlen(dname) + MAX_PORT_STR_LEN, sizeof(*ret));
sprintf(ret, "%s:%d", dname, ntohs(port));
size_t len = dname_len + MAX_PORT_STR_LEN;
char *ret = ss_calloc(len , sizeof(*ret));
snprintf(ret, len, "%.*s:%d", dname_len, dname, ntohs(port));
return ret;
}

3
src/netutils.h

@ -263,8 +263,7 @@ int sockaddr_cmp(struct sockaddr_storage *addr1,
int sockaddr_cmp_addr(struct sockaddr_storage *addr1,
struct sockaddr_storage *addr2, socklen_t len);
int validate_hostname(const char *hostname, const int hostname_len);
char *hostname_readable(char *dname, uint16_t port);
char *hostname_readable(const char *dname, const int dname_len, uint16_t port);
int is_addr_loopback(const struct sockaddr *addr);

2
src/redir.c

@ -49,7 +49,7 @@
#include "utils.h"
#include "common.h"
#include "acl.h"
#include "relay.h"
#include "tcprelay.h"
int verbose = 0;
int ipv6first = 0;

2
src/server.c

@ -55,7 +55,7 @@
#include "acl.h"
#include "plugin.h"
#include "winsock.h"
#include "relay.h"
#include "tcprelay.h"
#ifndef SSMAXCONN
#define SSMAXCONN 1024

29
src/shadowsocks.h

@ -123,6 +123,8 @@ void free_ssocks_addr(ssocks_addr_t *destaddr)
* parse_ssocks_header
* create_ssocks_header
*
* CAVEATS: The domain name is not null-terminated
*
* / Pre-encryption //////////////////////
* - Shadowsocks Request
* +------+----------+----------+----------+
@ -182,32 +184,9 @@ parse_ssocks_header(buffer_t *buf, ssocks_addr_t *destaddr, int offset)
memcpy(dname, buf->data + offset + 1, dname_len);
offset += dname_len + 1;
destaddr->dname = dname;
destaddr->dname_len = dname_len;
destaddr->port = *(uint16_t *)(buf->data + offset);
struct cork_ip ip;
if (cork_ip_init(&ip, dname) != -1) {
switch (ip.version) {
case 4: {
struct sockaddr_in *addr
= ss_calloc(1, sizeof(*addr));
addr->sin_family = AF_INET;
memcpy(&addr->sin_addr, &ip.ip.v4, sizeof(ip.ip.v4));
addr->sin_port = destaddr->port;
destaddr->addr = (struct sockaddr_storage *)addr;
} break;
case 6: {
struct sockaddr_in6 *addr
= ss_calloc(1, sizeof(*addr));
addr->sin6_family = AF_INET;
memcpy(&addr->sin6_addr, &ip.ip.v6, sizeof(ip.ip.v6));
addr->sin6_port = destaddr->port;
destaddr->addr = (struct sockaddr_storage *)addr;
} break;
}
} else {
destaddr->dname = dname;
destaddr->dname_len = dname_len;
}
} break;
case SSOCKS_ATYP_IPV6: {
size_t in6_addr_len = sizeof(struct in_addr);

src/relay.c → src/tcprelay.c

@ -57,7 +57,7 @@
#include "acl.h"
#include "plugin.h"
#include "relay.h"
#include "tcprelay.h"
extern int acl;
extern int verbose;
@ -183,7 +183,7 @@ create_remote(EV_P_ remote_t *remote, buffer_t *buf,
if (destaddr->dname_len == -1) {
return -1;
} else if (destaddr->dname_len <= 0 ||
!validate_hostname(destaddr->dname, destaddr->dname_len))
destaddr->dname_len >= MAX_HOSTNAME_LEN)
{
destaddr->dname = NULL;
}
@ -197,7 +197,7 @@ create_remote(EV_P_ remote_t *remote, buffer_t *buf,
if (verbose) {
LOGI("%s %s", direct ? "bypassing" : "connecting to",
destaddr->dname ? hostname_readable(destaddr->dname, destaddr->port)
destaddr->dname ? hostname_readable(destaddr->dname, destaddr->dname_len, destaddr->port)
: sockaddr_readable("%a:%p", destaddr->addr));
}

src/relay.h → src/tcprelay.h

@ -20,8 +20,8 @@
* <http://www.gnu.org/licenses/>.
*/
#ifndef _RELAY_H
#define _RELAY_H
#ifndef _TCP_RELAY_H
#define _TCP_RELAY_H
#include <time.h>

2
src/tunnel.c

@ -54,7 +54,7 @@
#include "utils.h"
#include "plugin.h"
#include "winsock.h"
#include "relay.h"
#include "tcprelay.h"
int verbose = 0;
int acl = 0;

4
src/udprelay.c

@ -691,7 +691,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
}
if (destaddr->dname_len <= 0 ||
!validate_hostname(destaddr->dname, destaddr->dname_len))
destaddr->dname_len >= MAX_HOSTNAME_LEN)
{
destaddr->dname = NULL;
}
@ -705,7 +705,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents)
if (verbose) {
LOGI("%s %s", remote->direct ? "bypassing" : "connecting to",
destaddr->dname ? hostname_readable(destaddr->dname, destaddr->port)
destaddr->dname ? hostname_readable(destaddr->dname, destaddr->dname_len, destaddr->port)
: sockaddr_readable("%a:%p", destaddr->addr));
}

Loading…
Cancel
Save