|
@ -439,248 +439,246 @@ server_recv_cb(EV_P_ ev_io *w, int revents) |
|
|
close_and_free_remote(EV_A_ remote); |
|
|
close_and_free_remote(EV_A_ remote); |
|
|
close_and_free_server(EV_A_ server); |
|
|
close_and_free_server(EV_A_ server); |
|
|
return; |
|
|
return; |
|
|
} else { |
|
|
|
|
|
char host[257], ip[INET6_ADDRSTRLEN], port[16]; |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
buffer_t ss_addr_to_send; |
|
|
|
|
|
buffer_t *abuf = &ss_addr_to_send; |
|
|
|
|
|
balloc(abuf, BUF_SIZE); |
|
|
|
|
|
|
|
|
// Fake reply |
|
|
|
|
|
if (server->stage == 1) { |
|
|
|
|
|
struct socks5_response response; |
|
|
|
|
|
response.ver = SVERSION; |
|
|
|
|
|
response.rep = 0; |
|
|
|
|
|
response.rsv = 0; |
|
|
|
|
|
response.atyp = 1; |
|
|
|
|
|
|
|
|
abuf->array[abuf->len++] = request->atyp; |
|
|
|
|
|
int atyp = request->atyp; |
|
|
|
|
|
|
|
|
buffer_t resp_to_send; |
|
|
|
|
|
buffer_t *resp_buf = &resp_to_send; |
|
|
|
|
|
balloc(resp_buf, BUF_SIZE); |
|
|
|
|
|
|
|
|
// get remote addr and port |
|
|
|
|
|
if (atyp == 1) { |
|
|
|
|
|
// IP V4 |
|
|
|
|
|
size_t in_addr_len = sizeof(struct in_addr); |
|
|
|
|
|
memcpy(abuf->array + abuf->len, buf->array + 4, in_addr_len + 2); |
|
|
|
|
|
abuf->len += in_addr_len + 2; |
|
|
|
|
|
|
|
|
memcpy(resp_buf->array, &response, sizeof(struct socks5_response)); |
|
|
|
|
|
memcpy(resp_buf->array + sizeof(struct socks5_response), |
|
|
|
|
|
&sock_addr.sin_addr, sizeof(sock_addr.sin_addr)); |
|
|
|
|
|
memcpy(resp_buf->array + sizeof(struct socks5_response) + |
|
|
|
|
|
sizeof(sock_addr.sin_addr), |
|
|
|
|
|
&sock_addr.sin_port, sizeof(sock_addr.sin_port)); |
|
|
|
|
|
|
|
|
if (acl || verbose) { |
|
|
|
|
|
uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in_addr_len)); |
|
|
|
|
|
dns_ntop(AF_INET, (const void *)(buf->array + 4), |
|
|
|
|
|
ip, INET_ADDRSTRLEN); |
|
|
|
|
|
sprintf(port, "%d", p); |
|
|
|
|
|
} |
|
|
|
|
|
} else if (atyp == 3) { |
|
|
|
|
|
// Domain name |
|
|
|
|
|
uint8_t name_len = *(uint8_t *)(buf->array + 4); |
|
|
|
|
|
abuf->array[abuf->len++] = name_len; |
|
|
|
|
|
memcpy(abuf->array + abuf->len, buf->array + 4 + 1, name_len + 2); |
|
|
|
|
|
abuf->len += name_len + 2; |
|
|
|
|
|
|
|
|
int reply_size = sizeof(struct socks5_response) + |
|
|
|
|
|
sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port); |
|
|
|
|
|
|
|
|
if (acl || verbose) { |
|
|
|
|
|
uint16_t p = |
|
|
|
|
|
ntohs(*(uint16_t *)(buf->array + 4 + 1 + name_len)); |
|
|
|
|
|
memcpy(host, buf->array + 4 + 1, name_len); |
|
|
|
|
|
host[name_len] = '\0'; |
|
|
|
|
|
sprintf(port, "%d", p); |
|
|
|
|
|
} |
|
|
|
|
|
} else if (atyp == 4) { |
|
|
|
|
|
// IP V6 |
|
|
|
|
|
size_t in6_addr_len = sizeof(struct in6_addr); |
|
|
|
|
|
memcpy(abuf->array + abuf->len, buf->array + 4, in6_addr_len + 2); |
|
|
|
|
|
abuf->len += in6_addr_len + 2; |
|
|
|
|
|
|
|
|
int s = send(server->fd, resp_buf->array, reply_size, 0); |
|
|
|
|
|
|
|
|
if (acl || verbose) { |
|
|
|
|
|
uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in6_addr_len)); |
|
|
|
|
|
dns_ntop(AF_INET6, (const void *)(buf->array + 4), |
|
|
|
|
|
ip, INET6_ADDRSTRLEN); |
|
|
|
|
|
sprintf(port, "%d", p); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
bfree(abuf); |
|
|
|
|
|
LOGE("unsupported addrtype: %d", request->atyp); |
|
|
|
|
|
|
|
|
bfree(resp_buf); |
|
|
|
|
|
|
|
|
|
|
|
if (s < reply_size) { |
|
|
|
|
|
LOGE("failed to send fake reply"); |
|
|
close_and_free_remote(EV_A_ remote); |
|
|
close_and_free_remote(EV_A_ remote); |
|
|
close_and_free_server(EV_A_ server); |
|
|
close_and_free_server(EV_A_ server); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
if (udp_assc) { |
|
|
|
|
|
close_and_free_remote(EV_A_ remote); |
|
|
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (server->stage == 1) { |
|
|
|
|
|
// Fake reply |
|
|
|
|
|
struct socks5_response response; |
|
|
|
|
|
response.ver = SVERSION; |
|
|
|
|
|
response.rep = 0; |
|
|
|
|
|
response.rsv = 0; |
|
|
|
|
|
response.atyp = 1; |
|
|
|
|
|
|
|
|
|
|
|
buffer_t resp_to_send; |
|
|
|
|
|
buffer_t *resp_buf = &resp_to_send; |
|
|
|
|
|
balloc(resp_buf, BUF_SIZE); |
|
|
|
|
|
|
|
|
|
|
|
memcpy(resp_buf->array, &response, sizeof(struct socks5_response)); |
|
|
|
|
|
memcpy(resp_buf->array + sizeof(struct socks5_response), |
|
|
|
|
|
&sock_addr.sin_addr, sizeof(sock_addr.sin_addr)); |
|
|
|
|
|
memcpy(resp_buf->array + sizeof(struct socks5_response) + |
|
|
|
|
|
sizeof(sock_addr.sin_addr), |
|
|
|
|
|
&sock_addr.sin_port, sizeof(sock_addr.sin_port)); |
|
|
|
|
|
|
|
|
char host[257], ip[INET6_ADDRSTRLEN], port[16]; |
|
|
|
|
|
|
|
|
int reply_size = sizeof(struct socks5_response) + |
|
|
|
|
|
sizeof(sock_addr.sin_addr) + sizeof(sock_addr.sin_port); |
|
|
|
|
|
|
|
|
buffer_t ss_addr_to_send; |
|
|
|
|
|
buffer_t *abuf = &ss_addr_to_send; |
|
|
|
|
|
balloc(abuf, BUF_SIZE); |
|
|
|
|
|
|
|
|
int s = send(server->fd, resp_buf->array, reply_size, 0); |
|
|
|
|
|
|
|
|
abuf->array[abuf->len++] = request->atyp; |
|
|
|
|
|
int atyp = request->atyp; |
|
|
|
|
|
|
|
|
bfree(resp_buf); |
|
|
|
|
|
|
|
|
// get remote addr and port |
|
|
|
|
|
if (atyp == 1) { |
|
|
|
|
|
// IP V4 |
|
|
|
|
|
size_t in_addr_len = sizeof(struct in_addr); |
|
|
|
|
|
memcpy(abuf->array + abuf->len, buf->array + 4, in_addr_len + 2); |
|
|
|
|
|
abuf->len += in_addr_len + 2; |
|
|
|
|
|
|
|
|
if (s < reply_size) { |
|
|
|
|
|
LOGE("failed to send fake reply"); |
|
|
|
|
|
bfree(abuf); |
|
|
|
|
|
close_and_free_remote(EV_A_ remote); |
|
|
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if (udp_assc) { |
|
|
|
|
|
bfree(abuf); |
|
|
|
|
|
close_and_free_remote(EV_A_ remote); |
|
|
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (acl || verbose) { |
|
|
|
|
|
uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in_addr_len)); |
|
|
|
|
|
dns_ntop(AF_INET, (const void *)(buf->array + 4), |
|
|
|
|
|
ip, INET_ADDRSTRLEN); |
|
|
|
|
|
sprintf(port, "%d", p); |
|
|
|
|
|
} |
|
|
|
|
|
} else if (atyp == 3) { |
|
|
|
|
|
// Domain name |
|
|
|
|
|
uint8_t name_len = *(uint8_t *)(buf->array + 4); |
|
|
|
|
|
abuf->array[abuf->len++] = name_len; |
|
|
|
|
|
memcpy(abuf->array + abuf->len, buf->array + 4 + 1, name_len + 2); |
|
|
|
|
|
abuf->len += name_len + 2; |
|
|
|
|
|
|
|
|
|
|
|
if (acl || verbose) { |
|
|
|
|
|
uint16_t p = |
|
|
|
|
|
ntohs(*(uint16_t *)(buf->array + 4 + 1 + name_len)); |
|
|
|
|
|
memcpy(host, buf->array + 4 + 1, name_len); |
|
|
|
|
|
host[name_len] = '\0'; |
|
|
|
|
|
sprintf(port, "%d", p); |
|
|
} |
|
|
} |
|
|
|
|
|
} else if (atyp == 4) { |
|
|
|
|
|
// IP V6 |
|
|
|
|
|
size_t in6_addr_len = sizeof(struct in6_addr); |
|
|
|
|
|
memcpy(abuf->array + abuf->len, buf->array + 4, in6_addr_len + 2); |
|
|
|
|
|
abuf->len += in6_addr_len + 2; |
|
|
|
|
|
|
|
|
|
|
|
if (acl || verbose) { |
|
|
|
|
|
uint16_t p = ntohs(*(uint16_t *)(buf->array + 4 + in6_addr_len)); |
|
|
|
|
|
dns_ntop(AF_INET6, (const void *)(buf->array + 4), |
|
|
|
|
|
ip, INET6_ADDRSTRLEN); |
|
|
|
|
|
sprintf(port, "%d", p); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
bfree(abuf); |
|
|
|
|
|
LOGE("unsupported addrtype: %d", request->atyp); |
|
|
|
|
|
close_and_free_remote(EV_A_ remote); |
|
|
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
size_t abuf_len = abuf->len; |
|
|
|
|
|
int sni_detected = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (atyp == 1 || atyp == 4) { |
|
|
|
|
|
char *hostname; |
|
|
|
|
|
uint16_t p = ntohs(*(uint16_t *)(abuf->array + abuf->len - 2)); |
|
|
|
|
|
int ret = 0; |
|
|
|
|
|
if (p == http_protocol->default_port) |
|
|
|
|
|
ret = http_protocol->parse_packet(buf->array + 3 + abuf->len, |
|
|
|
|
|
buf->len - 3 - abuf->len, &hostname); |
|
|
|
|
|
else if (p == tls_protocol->default_port) |
|
|
|
|
|
ret = tls_protocol->parse_packet(buf->array + 3 + abuf->len, |
|
|
|
|
|
buf->len - 3 - abuf->len, &hostname); |
|
|
|
|
|
if (ret == -1) { |
|
|
|
|
|
server->stage = 2; |
|
|
|
|
|
bfree(abuf); |
|
|
|
|
|
return; |
|
|
|
|
|
} else if (ret > 0) { |
|
|
|
|
|
sni_detected = 1; |
|
|
|
|
|
|
|
|
|
|
|
// Reconstruct address buffer |
|
|
|
|
|
abuf->len = 0; |
|
|
|
|
|
abuf->array[abuf->len++] = 3; |
|
|
|
|
|
abuf->array[abuf->len++] = ret; |
|
|
|
|
|
memcpy(abuf->array + abuf->len, hostname, ret); |
|
|
|
|
|
abuf->len += ret; |
|
|
|
|
|
p = htons(p); |
|
|
|
|
|
memcpy(abuf->array + abuf->len, &p, 2); |
|
|
|
|
|
abuf->len += 2; |
|
|
|
|
|
|
|
|
|
|
|
if (acl || verbose) { |
|
|
|
|
|
memcpy(host, hostname, ret); |
|
|
|
|
|
host[ret] = '\0'; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
size_t abuf_len = abuf->len; |
|
|
|
|
|
int sni_detected = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (atyp == 1 || atyp == 4) { |
|
|
|
|
|
char *hostname; |
|
|
|
|
|
uint16_t p = ntohs(*(uint16_t *)(abuf->array + abuf->len - 2)); |
|
|
|
|
|
int ret = 0; |
|
|
|
|
|
if (p == http_protocol->default_port) |
|
|
|
|
|
ret = http_protocol->parse_packet(buf->array + 3 + abuf->len, |
|
|
|
|
|
buf->len - 3 - abuf->len, &hostname); |
|
|
|
|
|
else if (p == tls_protocol->default_port) |
|
|
|
|
|
ret = tls_protocol->parse_packet(buf->array + 3 + abuf->len, |
|
|
|
|
|
buf->len - 3 - abuf->len, &hostname); |
|
|
|
|
|
if (ret == -1) { |
|
|
|
|
|
server->stage = 2; |
|
|
|
|
|
bfree(abuf); |
|
|
|
|
|
return; |
|
|
|
|
|
} else if (ret > 0) { |
|
|
|
|
|
sni_detected = 1; |
|
|
|
|
|
|
|
|
|
|
|
// Reconstruct address buffer |
|
|
|
|
|
abuf->len = 0; |
|
|
|
|
|
abuf->array[abuf->len++] = 3; |
|
|
|
|
|
abuf->array[abuf->len++] = ret; |
|
|
|
|
|
memcpy(abuf->array + abuf->len, hostname, ret); |
|
|
|
|
|
abuf->len += ret; |
|
|
|
|
|
p = htons(p); |
|
|
|
|
|
memcpy(abuf->array + abuf->len, &p, 2); |
|
|
|
|
|
abuf->len += 2; |
|
|
|
|
|
|
|
|
ss_free(hostname); |
|
|
|
|
|
|
|
|
if (acl || verbose) { |
|
|
|
|
|
memcpy(host, hostname, ret); |
|
|
|
|
|
host[ret] = '\0'; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
server->stage = 5; |
|
|
|
|
|
|
|
|
|
|
|
buf->len -= (3 + abuf_len); |
|
|
|
|
|
if (buf->len > 0) { |
|
|
|
|
|
memmove(buf->array, buf->array + 3 + abuf_len, buf->len); |
|
|
|
|
|
|
|
|
ss_free(hostname); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (verbose) { |
|
|
|
|
|
if (sni_detected || atyp == 3) |
|
|
|
|
|
LOGI("connect to %s:%s", host, port); |
|
|
|
|
|
else if (atyp == 1) |
|
|
|
|
|
LOGI("connect to %s:%s", ip, port); |
|
|
|
|
|
else if (atyp == 4) |
|
|
|
|
|
LOGI("connect to [%s]:%s", ip, port); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
server->stage = 5; |
|
|
|
|
|
|
|
|
if (acl) { |
|
|
|
|
|
int host_match = acl_match_host(host); |
|
|
|
|
|
int ip_match = acl_match_host(ip); |
|
|
|
|
|
|
|
|
buf->len -= (3 + abuf_len); |
|
|
|
|
|
if (buf->len > 0) { |
|
|
|
|
|
memmove(buf->array, buf->array + 3 + abuf_len, buf->len); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int bypass = get_acl_mode() == WHITE_LIST; |
|
|
|
|
|
|
|
|
if (verbose) { |
|
|
|
|
|
if (sni_detected || atyp == 3) |
|
|
|
|
|
LOGI("connect to %s:%s", host, port); |
|
|
|
|
|
else if (atyp == 1) |
|
|
|
|
|
LOGI("connect to %s:%s", ip, port); |
|
|
|
|
|
else if (atyp == 4) |
|
|
|
|
|
LOGI("connect to [%s]:%s", ip, port); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (get_acl_mode() == BLACK_LIST) { |
|
|
|
|
|
if (ip_match > 0) |
|
|
|
|
|
bypass = 1; // bypass IPs in black list |
|
|
|
|
|
|
|
|
if (acl) { |
|
|
|
|
|
int host_match = acl_match_host(host); |
|
|
|
|
|
int ip_match = acl_match_host(ip); |
|
|
|
|
|
|
|
|
if (host_match > 0) |
|
|
|
|
|
bypass = 1; // bypass hostnames in black list |
|
|
|
|
|
else if (host_match < 0) |
|
|
|
|
|
bypass = 0; // proxy hostnames in white list |
|
|
|
|
|
} else if (get_acl_mode() == WHITE_LIST) { |
|
|
|
|
|
if (ip_match < 0) |
|
|
|
|
|
bypass = 0; // proxy IPs in white list |
|
|
|
|
|
|
|
|
int bypass = get_acl_mode() == WHITE_LIST; |
|
|
|
|
|
|
|
|
if (host_match < 0) |
|
|
|
|
|
bypass = 0; // proxy hostnames in white list |
|
|
|
|
|
else if (host_match > 0) |
|
|
|
|
|
bypass = 1; // bypass hostnames in black list |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (get_acl_mode() == BLACK_LIST) { |
|
|
|
|
|
if (ip_match > 0) |
|
|
|
|
|
bypass = 1; // bypass IPs in black list |
|
|
|
|
|
|
|
|
if (bypass) { |
|
|
|
|
|
if (verbose) { |
|
|
|
|
|
if (sni_detected || atyp == 3) |
|
|
|
|
|
LOGI("bypass %s:%s", host, port); |
|
|
|
|
|
else if (atyp == 1) |
|
|
|
|
|
LOGI("bypass %s:%s", ip, port); |
|
|
|
|
|
else if (atyp == 4) |
|
|
|
|
|
LOGI("bypass [%s]:%s", ip, port); |
|
|
|
|
|
} |
|
|
|
|
|
struct sockaddr_storage storage; |
|
|
|
|
|
int err; |
|
|
|
|
|
memset(&storage, 0, sizeof(struct sockaddr_storage)); |
|
|
|
|
|
if (atyp == 1 || atyp == 4) { |
|
|
|
|
|
err = get_sockaddr(ip, port, &storage, 0); |
|
|
|
|
|
} else { |
|
|
|
|
|
err = get_sockaddr(host, port, &storage, 1); |
|
|
|
|
|
} |
|
|
|
|
|
if (err != -1) { |
|
|
|
|
|
remote = create_remote(server->listener, (struct sockaddr *)&storage); |
|
|
|
|
|
remote->direct = 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (host_match > 0) |
|
|
|
|
|
bypass = 1; // bypass hostnames in black list |
|
|
|
|
|
else if (host_match < 0) |
|
|
|
|
|
bypass = 0; // proxy hostnames in white list |
|
|
|
|
|
} else if (get_acl_mode() == WHITE_LIST) { |
|
|
|
|
|
if (ip_match < 0) |
|
|
|
|
|
bypass = 0; // proxy IPs in white list |
|
|
|
|
|
|
|
|
// Not match ACL |
|
|
|
|
|
if (remote == NULL) { |
|
|
|
|
|
remote = create_remote(server->listener, NULL); |
|
|
|
|
|
|
|
|
if (host_match < 0) |
|
|
|
|
|
bypass = 0; // proxy hostnames in white list |
|
|
|
|
|
else if (host_match > 0) |
|
|
|
|
|
bypass = 1; // bypass hostnames in black list |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (remote == NULL) { |
|
|
|
|
|
bfree(abuf); |
|
|
|
|
|
LOGE("invalid remote addr"); |
|
|
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
if (bypass) { |
|
|
|
|
|
if (verbose) { |
|
|
|
|
|
if (sni_detected || atyp == 3) |
|
|
|
|
|
LOGI("bypass %s:%s", host, port); |
|
|
|
|
|
else if (atyp == 1) |
|
|
|
|
|
LOGI("bypass %s:%s", ip, port); |
|
|
|
|
|
else if (atyp == 4) |
|
|
|
|
|
LOGI("bypass [%s]:%s", ip, port); |
|
|
|
|
|
} |
|
|
|
|
|
struct sockaddr_storage storage; |
|
|
|
|
|
int err; |
|
|
|
|
|
memset(&storage, 0, sizeof(struct sockaddr_storage)); |
|
|
|
|
|
if (atyp == 1 || atyp == 4) { |
|
|
|
|
|
err = get_sockaddr(ip, port, &storage, 0); |
|
|
|
|
|
} else { |
|
|
|
|
|
err = get_sockaddr(host, port, &storage, 1); |
|
|
|
|
|
} |
|
|
|
|
|
if (err != -1) { |
|
|
|
|
|
remote = create_remote(server->listener, (struct sockaddr *)&storage); |
|
|
|
|
|
remote->direct = 1; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (!remote->direct) { |
|
|
|
|
|
if (auth) { |
|
|
|
|
|
abuf->array[0] |= ONETIMEAUTH_FLAG; |
|
|
|
|
|
ss_onetimeauth(abuf, server->e_ctx->evp.iv, BUF_SIZE); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Not match ACL |
|
|
|
|
|
if (remote == NULL) { |
|
|
|
|
|
remote = create_remote(server->listener, NULL); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (buf->len > 0 && auth) { |
|
|
|
|
|
ss_gen_hash(buf, &remote->counter, server->e_ctx, BUF_SIZE); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (remote == NULL) { |
|
|
|
|
|
bfree(abuf); |
|
|
|
|
|
LOGE("invalid remote addr"); |
|
|
|
|
|
close_and_free_server(EV_A_ server); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
brealloc(remote->buf, buf->len + abuf->len, BUF_SIZE); |
|
|
|
|
|
memcpy(remote->buf->array, abuf->array, abuf->len); |
|
|
|
|
|
remote->buf->len = buf->len + abuf->len; |
|
|
|
|
|
|
|
|
if (!remote->direct) { |
|
|
|
|
|
if (auth) { |
|
|
|
|
|
abuf->array[0] |= ONETIMEAUTH_FLAG; |
|
|
|
|
|
ss_onetimeauth(abuf, server->e_ctx->evp.iv, BUF_SIZE); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (buf->len > 0) { |
|
|
|
|
|
memcpy(remote->buf->array + abuf->len, buf->array, buf->len); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
if (buf->len > 0) { |
|
|
|
|
|
memcpy(remote->buf->array, buf->array, buf->len); |
|
|
|
|
|
remote->buf->len = buf->len; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (buf->len > 0 && auth) { |
|
|
|
|
|
ss_gen_hash(buf, &remote->counter, server->e_ctx, BUF_SIZE); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
server->remote = remote; |
|
|
|
|
|
remote->server = server; |
|
|
|
|
|
|
|
|
brealloc(remote->buf, buf->len + abuf->len, BUF_SIZE); |
|
|
|
|
|
memcpy(remote->buf->array, abuf->array, abuf->len); |
|
|
|
|
|
remote->buf->len = buf->len + abuf->len; |
|
|
|
|
|
|
|
|
bfree(abuf); |
|
|
|
|
|
|
|
|
if (buf->len > 0) { |
|
|
|
|
|
memcpy(remote->buf->array + abuf->len, buf->array, buf->len); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
if (buf->len > 0) { |
|
|
|
|
|
memcpy(remote->buf->array, buf->array, buf->len); |
|
|
|
|
|
remote->buf->len = buf->len; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
server->remote = remote; |
|
|
|
|
|
remote->server = server; |
|
|
|
|
|
|
|
|
|
|
|
bfree(abuf); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|