Browse Source

Fix #494

pull/498/head
Max Lv 9 years ago
parent
commit
c18ae5f671
1 changed files with 55 additions and 29 deletions
  1. 84
      src/server.c

84
src/server.c

@ -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) {

Loading…
Cancel
Save