From 8d46ced3c947c74ced3fd01d66648be79968d929 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Thu, 24 Sep 2015 11:00:13 +0800 Subject: [PATCH] fix auth in udprelay --- src/common.h | 2 +- src/encrypt.c | 3 ++- src/local.c | 4 ++-- src/redir.c | 2 +- src/server.c | 2 +- src/tunnel.c | 2 +- src/udprelay.c | 30 +++++++++++++++++++----------- src/udprelay.h | 1 + 8 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/common.h b/src/common.h index bbe0c6b7..cf7ac7aa 100644 --- a/src/common.h +++ b/src/common.h @@ -60,7 +60,7 @@ int init_udprelay(const char *server_host, const char *server_port, const ss_addr_t tunnel_addr, #endif #endif - int method, int timeout, const char *iface); + int method, int auth, int timeout, const char *iface); void free_udprelay(void); diff --git a/src/encrypt.c b/src/encrypt.c index c99c8100..a796c980 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -1244,8 +1244,9 @@ char * ss_decrypt_all(int buf_size, char *ciphertext, ssize_t *len, int method, c_len - iv_len); } - if (auth) { + if (auth || (plaintext[0] & ONETIMEAUTH_FLAG)) { char hash[ONETIMEAUTH_BYTES]; + memcpy(hash, plaintext + p_len - ONETIMEAUTH_BYTES, ONETIMEAUTH_BYTES); ret = !ss_onetimeauth_verify(hash, plaintext, p_len - ONETIMEAUTH_BYTES, iv); if (ret) p_len -= ONETIMEAUTH_BYTES; } diff --git a/src/local.c b/src/local.c index 9eff43e8..5c443a47 100644 --- a/src/local.c +++ b/src/local.c @@ -1153,7 +1153,7 @@ int main(int argc, char **argv) if (mode != TCP_ONLY) { LOGI("udprelay enabled"); init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0], - get_sockaddr_len(listen_ctx.remote_addr[0]), m, listen_ctx.timeout, iface); + get_sockaddr_len(listen_ctx.remote_addr[0]), m, auth, listen_ctx.timeout, iface); } LOGI("listening at %s:%s", local_addr, local_port); @@ -1289,7 +1289,7 @@ int start_ss_local_server(profile_t profile) LOGI("udprelay enabled"); struct sockaddr *addr = (struct sockaddr *)storage; init_udprelay(local_addr, local_port_str, addr, - get_sockaddr_len(addr), m, timeout, NULL); + get_sockaddr_len(addr), m, auth, timeout, NULL); } LOGI("listening at %s:%s", local_addr, local_port_str); diff --git a/src/redir.c b/src/redir.c index 37246f49..791c2fc6 100644 --- a/src/redir.c +++ b/src/redir.c @@ -794,7 +794,7 @@ int main(int argc, char **argv) if (mode != TCP_ONLY) { LOGI("UDP relay enabled"); init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0], - get_sockaddr_len(listen_ctx.remote_addr[0]), m, listen_ctx.timeout, NULL); + get_sockaddr_len(listen_ctx.remote_addr[0]), m, auth, listen_ctx.timeout, NULL); } if (mode == UDP_ONLY) { diff --git a/src/server.c b/src/server.c index 395156c3..c0909c85 100644 --- a/src/server.c +++ b/src/server.c @@ -1473,7 +1473,7 @@ int main(int argc, char **argv) // Setup UDP if (mode != TCP_ONLY) { - init_udprelay(server_host[index], server_port, m, atoi(timeout), + init_udprelay(server_host[index], server_port, m, auth, atoi(timeout), iface); } diff --git a/src/tunnel.c b/src/tunnel.c index f0ebbebf..e5000066 100644 --- a/src/tunnel.c +++ b/src/tunnel.c @@ -873,7 +873,7 @@ int main(int argc, char **argv) LOGI("UDP relay enabled"); init_udprelay(local_addr, local_port, listen_ctx.remote_addr[0], get_sockaddr_len(listen_ctx.remote_addr[0]), - tunnel_addr, m, listen_ctx.timeout, iface); + tunnel_addr, m, auth, listen_ctx.timeout, iface); } if (mode == UDP_ONLY) { diff --git a/src/udprelay.c b/src/udprelay.c index 812732a4..53a56f75 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -216,14 +216,17 @@ static int construct_udprealy_header(const struct sockaddr_storage *in_addr, #endif static int parse_udprealy_header(const char * buf, const int buf_len, - char *host, char *port, + int *auth, char *host, char *port, struct sockaddr_storage *storage) { const uint8_t atyp = *(uint8_t *)buf; int offset = 1; + + if (auth != NULL) *auth |= (atyp & ONETIMEAUTH_FLAG); + // get remote addr and port - if (atyp == 1) { + if ((atyp & ADDRTYPE_MASK) == 1) { // IP V4 size_t in_addr_len = sizeof(struct in_addr); if (buf_len > in_addr_len) { @@ -239,7 +242,7 @@ static int parse_udprealy_header(const char * buf, const int buf_len, } offset += in_addr_len; } - } else if (atyp == 3) { + } 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) { @@ -264,7 +267,7 @@ static int parse_udprealy_header(const char * buf, const int buf_len, } } } - } else if (atyp == 4) { + } else if ((atyp & ADDRTYPE_MASK) == 4) { // IP V6 size_t in6_addr_len = sizeof(struct in6_addr); if (buf_len > in6_addr_len) { @@ -657,14 +660,14 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents) #ifdef UDPRELAY_REDIR struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); - int len = parse_udprealy_header(buf, buf_len, NULL, NULL, &dst_addr); + int len = parse_udprealy_header(buf, buf_len, NULL, NULL, NULL, &dst_addr); if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) { LOGI("[udp] ss-redir does not support domain name"); goto CLEAN_UP; } #else - int len = parse_udprealy_header(buf, buf_len, NULL, NULL, NULL); + int len = parse_udprealy_header(buf, buf_len, NULL, NULL, NULL, NULL); #endif if (len == 0) { @@ -830,7 +833,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) tx += buf_len; - buf = ss_decrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, 1); + buf = ss_decrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, server_ctx->auth); if (buf == NULL) { ERROR("[udp] server_ss_decrypt_all"); goto CLEAN_UP; @@ -972,8 +975,8 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); - int addr_header_len = parse_udprealy_header(buf + offset, - buf_len - offset, host, port, + int addr_header_len = parse_udprealy_header(buf + offset, buf_len - offset, + &server_ctx->auth, host, port, &dst_addr); if (addr_header_len == 0) { // error in parse header @@ -1089,7 +1092,11 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) memmove(buf, buf + offset, buf_len); } - buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, 1); + if (server_ctx->auth) { + buf[0] |= ONETIMEAUTH_FLAG; + } + + buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method, server_ctx->auth); int s = sendto(remote_ctx->fd, buf, buf_len, 0, remote_addr, remote_addr_len); @@ -1213,7 +1220,7 @@ int init_udprelay(const char *server_host, const char *server_port, const ss_addr_t tunnel_addr, #endif #endif - int method, int timeout, const char *iface) + int method, int auth, int timeout, const char *iface) { // Inilitialize ev loop struct ev_loop *loop = EV_DEFAULT; @@ -1236,6 +1243,7 @@ int init_udprelay(const char *server_host, const char *server_port, #ifdef UDPRELAY_REMOTE server_ctx->loop = loop; #endif + server_ctx->auth = auth; server_ctx->timeout = max(timeout, MIN_UDP_TIMEOUT); server_ctx->method = method; server_ctx->iface = iface; diff --git a/src/udprelay.h b/src/udprelay.h index e48da211..5d5e1b1a 100644 --- a/src/udprelay.h +++ b/src/udprelay.h @@ -45,6 +45,7 @@ struct server_ctx { ev_io io; int fd; int method; + int auth; int timeout; const char *iface; struct cache *conn_cache;