|
|
@ -102,9 +102,10 @@ static void free_remote(remote_t *remote); |
|
|
|
static void close_and_free_remote(EV_P_ remote_t *remote); |
|
|
|
static void free_server(server_t *server); |
|
|
|
static void close_and_free_server(EV_P_ server_t *server); |
|
|
|
|
|
|
|
static void server_resolve_cb(struct sockaddr *addr, void *data); |
|
|
|
|
|
|
|
static size_t parse_header_len(const char atyp, const char *data, size_t offset); |
|
|
|
|
|
|
|
int verbose = 0; |
|
|
|
|
|
|
|
static int white_list = 0; |
|
|
@ -215,6 +216,24 @@ static void free_connections(struct ev_loop *loop) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static size_t parse_header_len(const char atyp, const char *data, size_t offset) |
|
|
|
{ |
|
|
|
size_t len = 0; |
|
|
|
if ((atyp & ADDRTYPE_MASK) == 1) { |
|
|
|
// IP V4 |
|
|
|
len += sizeof(struct in_addr); |
|
|
|
} else if ((atyp & ADDRTYPE_MASK) == 3) { |
|
|
|
// Domain name |
|
|
|
uint8_t name_len = *(uint8_t *)(data + offset); |
|
|
|
len += name_len + 1; |
|
|
|
} else if ((atyp & ADDRTYPE_MASK) == 4) { |
|
|
|
// IP V6 |
|
|
|
len += sizeof(struct in6_addr); |
|
|
|
} |
|
|
|
len += 2; |
|
|
|
return len; |
|
|
|
} |
|
|
|
|
|
|
|
static char *get_peer_name(int fd) |
|
|
|
{ |
|
|
|
static char peer_name[INET6_ADDRSTRLEN] = { 0 }; |
|
|
@ -603,6 +622,39 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) |
|
|
|
memset(&info, 0, sizeof(struct addrinfo)); |
|
|
|
memset(&storage, 0, sizeof(struct sockaddr_storage)); |
|
|
|
|
|
|
|
if (auth || (atyp & ONETIMEAUTH_FLAG)) { |
|
|
|
size_t header_len = parse_header_len(atyp, server->buf->array, offset); |
|
|
|
size_t len = server->buf->len; |
|
|
|
|
|
|
|
if (len < offset + header_len + ONETIMEAUTH_BYTES) { |
|
|
|
report_addr(server->fd); |
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
server->buf->len = offset + header_len + ONETIMEAUTH_BYTES; |
|
|
|
if (ss_onetimeauth_verify(server->buf, server->d_ctx->evp.iv)) { |
|
|
|
char *peer_name = get_peer_name(server->fd); |
|
|
|
if (peer_name) { |
|
|
|
LOGE("authentication error from %s", peer_name); |
|
|
|
if (acl) { |
|
|
|
if (acl_get_mode() == BLACK_LIST) { |
|
|
|
acl_add_ip(peer_name); |
|
|
|
LOGE("add %s to the black list", peer_name); |
|
|
|
} else { |
|
|
|
acl_remove_ip(peer_name); |
|
|
|
LOGE("remove %s from the white list", peer_name); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
server->buf->len = len; |
|
|
|
server->auth = 1; |
|
|
|
} |
|
|
|
|
|
|
|
// get remote addr and port |
|
|
|
if ((atyp & ADDRTYPE_MASK) == 1) { |
|
|
|
// IP V4 |
|
|
@ -697,34 +749,8 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) |
|
|
|
|
|
|
|
offset += 2; |
|
|
|
|
|
|
|
if (auth || (atyp & ONETIMEAUTH_FLAG)) { |
|
|
|
if (server->buf->len < offset + ONETIMEAUTH_BYTES) { |
|
|
|
report_addr(server->fd); |
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
return; |
|
|
|
} |
|
|
|
size_t len = server->buf->len; |
|
|
|
server->buf->len = offset + ONETIMEAUTH_BYTES; |
|
|
|
if (ss_onetimeauth_verify(server->buf, server->d_ctx->evp.iv)) { |
|
|
|
char *peer_name = get_peer_name(server->fd); |
|
|
|
if (peer_name) { |
|
|
|
LOGE("authentication error from %s", peer_name); |
|
|
|
if (acl) { |
|
|
|
if (acl_get_mode() == BLACK_LIST) { |
|
|
|
acl_add_ip(peer_name); |
|
|
|
LOGE("add %s to the black list", peer_name); |
|
|
|
} else { |
|
|
|
acl_remove_ip(peer_name); |
|
|
|
LOGE("remove %s from the white list", peer_name); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
return; |
|
|
|
} |
|
|
|
server->buf->len = len; |
|
|
|
offset += ONETIMEAUTH_BYTES; |
|
|
|
server->auth = 1; |
|
|
|
if (server->auth) { |
|
|
|
offset += ONETIMEAUTH_BYTES; |
|
|
|
} |
|
|
|
|
|
|
|
if (server->buf->len < offset) { |
|
|
|