diff --git a/configure b/configure index a40b5e72..7d854c42 100755 --- a/configure +++ b/configure @@ -17958,8 +17958,8 @@ $as_echo X"$file" | fi cfgfile="${ofile}T" - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" + trap "$RM -f \"$cfgfile\"; exit 1" 1 2 15 + $RM -f "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f8a8d662..c806ce3d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,58 +1,124 @@ + +set(CMAKE_C_STANDARD 99) + set(SOURCE_FILES_SNI http.c + http.h tls.c - rule.c) + tls.h + rule.c + rule.h) + +set(SOURCE_FILES_OBFS + obfs/verify.c + obfs/verify.h + obfs/tls1.2_ticket.c + obfs/tls1.2_ticket.h + obfs/obfsutil.c + obfs/obfsutil.h + obfs/obfs.c + obfs/obfs.h + obfs/http_simple.c + obfs/http_simple.h + obfs/crc32.c + obfs/crc32.h + obfs/base64.c + obfs/base64.h + obfs/auth_chain.c + obfs/auth_chain.h + obfs/auth.c + obfs/auth.h) set(SOURCE_FILES_LOCAL utils.c + utils.h jconf.c + jconf.h json.c + json.h encrypt.c + encrypt.h udprelay.c + udprelay.h cache.c + cache.h acl.c + acl.h netutils.c + netutils.h local.c + local.h + ${SOURCE_FILES_OBFS} ${SOURCE_FILES_SNI}) set(SOURCE_FILES_TUNNEL utils.c + utils.h jconf.c + jconf.h json.c + json.h encrypt.c + encrypt.h udprelay.c + udprelay.h cache.c + cache.h netutils.c - tunnel.c) + netutils.h + tunnel.c + tunnel.h) set(SOURCE_FILES_SERVER utils.c + utils.h jconf.c + jconf.h json.c + json.h encrypt.c + encrypt.h udprelay.c + udprelay.h cache.c + cache.h acl.c + acl.h resolv.c + resolv.h netutils.c + netutils.h server.c + server.h + ${SOURCE_FILES_OBFS} ${SOURCE_FILES_SNI}) set(SOURCE_FILES_MANAGER utils.c + utils.h jconf.c + jconf.h json.c + json.h manager.c) set(SOURCE_FILES_REDIR utils.c + utils.h jconf.c + jconf.h json.c + json.h encrypt.c + encrypt.h netutils.c + netutils.h cache.c + cache.h udprelay.c + udprelay.h redir.c + redir.h ${SOURCE_FILES_SNI}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/local.c b/src/local.c index e9ce536d..d7e49ad6 100644 --- a/src/local.c +++ b/src/local.c @@ -21,7 +21,9 @@ */ #ifdef HAVE_CONFIG_H + #include "config.h" + #endif #include @@ -43,8 +45,10 @@ #endif #ifdef LIB_ONLY + #include #include "shadowsocks.h" + #endif #if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__) @@ -57,7 +61,9 @@ #include #ifdef __MINGW32__ + #include "win32.h" + #endif #include "netutils.h" @@ -106,7 +112,7 @@ char *prefix; #include "jconf.h" #include "obfs/obfs.h" -static int acl = 0; +static int acl = 0; static int mode = TCP_ONLY; static int ipv6first = 0; @@ -118,24 +124,36 @@ static int nofile = 0; #endif static void server_recv_cb(EV_P_ ev_io *w, int revents); + static void server_send_cb(EV_P_ ev_io *w, int revents); + static void remote_recv_cb(EV_P_ ev_io *w, int revents); + static void remote_send_cb(EV_P_ ev_io *w, int revents); + static void accept_cb(EV_P_ ev_io *w, int revents); + static void signal_cb(EV_P_ ev_signal *w, int revents); static int create_and_bind(const char *addr, const char *port); + #ifdef HAVE_LAUNCHD static int launch_or_create(const char *addr, const char *port); #endif + static remote_t *create_remote(listen_ctx_t *listener, struct sockaddr *addr); + 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 remote_t *new_remote(int fd, int timeout); -static server_t *new_server(int fd, listen_ctx_t* profile); + +static server_t *new_server(int fd, listen_ctx_t *profile); static struct cork_dllist inactive_profiles; static listen_ctx_t *current_profile; @@ -155,42 +173,37 @@ setnonblocking(int fd) #endif void -ev_io_remote_send(EV_P_ server_t* server, remote_t* remote) -{ - ev_io_stop(EV_A_ & remote->send_ctx->io); - ev_io_start(EV_A_ & server->recv_ctx->io); +ev_io_remote_send(EV_P_ server_t *server, remote_t *remote) { + ev_io_stop(EV_A_ &remote->send_ctx->io); + ev_io_start(EV_A_ &server->recv_ctx->io); } void -ev_io_remote_recv(EV_P_ server_t* server, remote_t* remote) -{ - ev_io_stop(EV_A_ & remote->recv_ctx->io); - ev_io_start(EV_A_ & server->send_ctx->io); +ev_io_remote_recv(EV_P_ server_t *server, remote_t *remote) { + ev_io_stop(EV_A_ &remote->recv_ctx->io); + ev_io_start(EV_A_ &server->send_ctx->io); } void -ev_io_server_send(EV_P_ server_t* server, remote_t* remote) -{ - ev_io_stop(EV_A_ & server->send_ctx->io); - ev_io_start(EV_A_ & remote->recv_ctx->io); +ev_io_server_send(EV_P_ server_t *server, remote_t *remote) { + ev_io_stop(EV_A_ &server->send_ctx->io); + ev_io_start(EV_A_ &remote->recv_ctx->io); } void -ev_io_server_recv(EV_P_ server_t* server, remote_t* remote) -{ - ev_io_stop(EV_A_ & server->recv_ctx->io); - ev_io_start(EV_A_ & remote->send_ctx->io); +ev_io_server_recv(EV_P_ server_t *server, remote_t *remote) { + ev_io_stop(EV_A_ &server->recv_ctx->io); + ev_io_start(EV_A_ &remote->send_ctx->io); } int -create_and_bind(const char *addr, const char *port) -{ +create_and_bind(const char *addr, const char *port) { struct addrinfo hints; struct addrinfo *result, *rp; int s, listen_sock; memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ + hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ s = getaddrinfo(addr, port, &hints, &result); @@ -199,6 +212,11 @@ create_and_bind(const char *addr, const char *port) return -1; } + if (result == NULL) { + LOGE("Could not bind"); + return -1; + } + for (rp = result; rp != NULL; rp = rp->ai_next) { listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (listen_sock == -1) { @@ -224,11 +242,7 @@ create_and_bind(const char *addr, const char *port) } close(listen_sock); - } - - if (rp == NULL) { - LOGE("Could not bind"); - return -1; + listen_sock = -1; } freeaddrinfo(result); @@ -267,8 +281,7 @@ launch_or_create(const char *addr, const char *port) #endif static void -free_connections(struct ev_loop *loop) -{ +free_connections(struct ev_loop *loop) { struct cork_dllist_item *curr, *next; cork_dllist_foreach_void(&all_connections, curr, next) { server_t *server = cork_container_of(curr, server_t, entries_all); @@ -279,11 +292,10 @@ free_connections(struct ev_loop *loop) } static void -server_recv_cb(EV_P_ ev_io *w, int revents) -{ - server_ctx_t *server_recv_ctx = (server_ctx_t *)w; - server_t *server = server_recv_ctx->server; - remote_t *remote = server->remote; +server_recv_cb(EV_P_ ev_io *w, int revents) { + server_ctx_t *server_recv_ctx = (server_ctx_t *) w; + server_t *server = server_recv_ctx->server; + remote_t *remote = server->remote; buffer_t *buf; ssize_t r; @@ -352,7 +364,12 @@ server_recv_cb(EV_P_ ev_io *w, int revents) if (server_env->protocol_plugin) { obfs_class *protocol_plugin = server_env->protocol_plugin; if (protocol_plugin->client_pre_encrypt) { - remote->buf->len = protocol_plugin->client_pre_encrypt(server->protocol, &remote->buf->array, remote->buf->len, &remote->buf->capacity); + remote->buf->len = (size_t) protocol_plugin->client_pre_encrypt( + server->protocol, + &remote->buf->array, + (int) remote->buf->len, + &remote->buf->capacity + ); } } int err = ss_encrypt(&server_env->cipher, remote->buf, server->e_ctx, BUF_SIZE); @@ -367,7 +384,12 @@ server_recv_cb(EV_P_ ev_io *w, int revents) if (server_env->obfs_plugin) { obfs_class *obfs_plugin = server_env->obfs_plugin; if (obfs_plugin->client_encode) { - remote->buf->len = obfs_plugin->client_encode(server->obfs, &remote->buf->array, remote->buf->len, &remote->buf->capacity); + remote->buf->len = (size_t) obfs_plugin->client_encode( + server->obfs, + &remote->buf->array, + (int) remote->buf->len, + &remote->buf->capacity + ); } } // SSR end @@ -401,7 +423,11 @@ server_recv_cb(EV_P_ ev_io *w, int revents) if (!fast_open || remote->direct) { // connecting, wait until connected - int r = connect(remote->fd, (struct sockaddr *)&(remote->direct_addr.addr), remote->direct_addr.addr_len); + int r = connect( + remote->fd, + (struct sockaddr *) &(remote->direct_addr.addr), + remote->direct_addr.addr_len + ); if (r == -1 && errno != CONNECT_IN_PROGRESS) { ERROR("connect"); @@ -412,7 +438,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents) // wait on remote connected event ev_io_server_recv(EV_A_ server, remote); - ev_timer_start(EV_A_ & remote->send_ctx->watcher); + ev_timer_start(EV_A_ &remote->send_ctx->watcher); } else { #ifdef TCP_FASTOPEN #ifdef __APPLE__ @@ -480,7 +506,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents) } else { if (r > 0 && remote->buf->len == 0) { remote->buf->idx = 0; - ev_io_stop(EV_A_ & server_recv_ctx->io); + ev_io_stop(EV_A_ &server_recv_ctx->io); return; } int s = send(remote->fd, remote->buf->array, remote->buf->len, 0); @@ -496,9 +522,9 @@ server_recv_cb(EV_P_ ev_io *w, int revents) close_and_free_server(EV_A_ server); return; } - } else if (s < (int)(remote->buf->len)) { + } else if (s < (int) (remote->buf->len)) { remote->buf->len -= s; - remote->buf->idx = s; + remote->buf->idx = s; ev_io_server_recv(EV_A_ server, remote); return; } else { @@ -511,14 +537,14 @@ server_recv_cb(EV_P_ ev_io *w, int revents) return; } else if (server->stage == STAGE_INIT) { struct method_select_response response; - response.ver = SVERSION; + response.ver = SVERSION; response.method = 0; - char *send_buf = (char *)&response; + char *send_buf = (char *) &response; send(server->fd, send_buf, sizeof(response), 0); server->stage = STAGE_HANDSHAKE; int off = (buf->array[1] & 0xff) + 2; - if (buf->array[0] == 0x05 && off < (int)(buf->len)) { + if (buf->array[0] == 0x05 && off < (int) (buf->len)) { memmove(buf->array, buf->array + off, buf->len - off); buf->len -= off; continue; @@ -528,7 +554,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents) return; } else if (server->stage == STAGE_HANDSHAKE || server->stage == STAGE_PARSE) { - struct socks5_request *request = (struct socks5_request *)buf->array; + struct socks5_request *request = (struct socks5_request *) buf->array; struct sockaddr_in sock_addr; memset(&sock_addr, 0, sizeof(sock_addr)); @@ -537,7 +563,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents) if (request->cmd == 3) { udp_assc = 1; socklen_t addr_len = sizeof(sock_addr); - getsockname(server->fd, (struct sockaddr *)&sock_addr, + getsockname(server->fd, (struct sockaddr *) &sock_addr, &addr_len); if (verbose) { LOGI("udp assc request accepted"); @@ -545,11 +571,11 @@ server_recv_cb(EV_P_ ev_io *w, int revents) } else if (request->cmd != 1) { LOGE("unsupported cmd: %d", request->cmd); struct socks5_response response; - response.ver = SVERSION; - response.rep = CMD_NOT_SUPPORTED; - response.rsv = 0; + response.ver = SVERSION; + response.rep = CMD_NOT_SUPPORTED; + response.rsv = 0; response.atyp = 1; - char *send_buf = (char *)&response; + char *send_buf = (char *) &response; send(server->fd, send_buf, 4, 0); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); @@ -559,9 +585,9 @@ server_recv_cb(EV_P_ ev_io *w, int revents) // Fake reply if (server->stage == STAGE_HANDSHAKE) { struct socks5_response response; - response.ver = SVERSION; - response.rep = 0; - response.rsv = 0; + response.ver = SVERSION; + response.rep = 0; + response.rsv = 0; response.atyp = 1; buffer_t resp_to_send; @@ -611,21 +637,23 @@ server_recv_cb(EV_P_ ev_io *w, int revents) abuf->len += in_addr_len + 2; 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); + 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); + 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)); + 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); @@ -637,9 +665,12 @@ server_recv_cb(EV_P_ ev_io *w, int revents) 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); + 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 { @@ -650,13 +681,13 @@ server_recv_cb(EV_P_ ev_io *w, int revents) return; } - size_t abuf_len = abuf->len; + 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; + 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); @@ -671,12 +702,12 @@ server_recv_cb(EV_P_ ev_io *w, int revents) sni_detected = 1; // Reconstruct address buffer - abuf->len = 0; + 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); + p = htons(p); memcpy(abuf->array + abuf->len, &p, 2); abuf->len += 2; @@ -724,16 +755,16 @@ server_recv_cb(EV_P_ ev_io *w, int revents) #ifndef ANDROID if (atyp == 3) { // resolve domain so we can bypass domain with geoip err = get_sockaddr(host, port, &storage, 0, ipv6first); - if ( err != -1) { + if (err != -1) { resolved = 1; - switch(((struct sockaddr*)&storage)->sa_family) { + switch (((struct sockaddr *) &storage)->sa_family) { case AF_INET: { - struct sockaddr_in *addr_in = (struct sockaddr_in *)&storage; + struct sockaddr_in *addr_in = (struct sockaddr_in *) &storage; dns_ntop(AF_INET, &(addr_in->sin_addr), ip, INET_ADDRSTRLEN); break; } case AF_INET6: { - struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&storage; + struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *) &storage; dns_ntop(AF_INET6, &(addr_in6->sin6_addr), ip, INET6_ADDRSTRLEN); break; } @@ -781,7 +812,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents) #endif err = get_sockaddr(ip, port, &storage, 0, ipv6first); if (err != -1) { - remote = create_remote(server->listener, (struct sockaddr *)&storage); + remote = create_remote(server->listener, (struct sockaddr *) &storage); if (remote != NULL) remote->direct = 1; } } @@ -819,8 +850,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) server_def_t *server_env = server->server_env; // expelled from eden - cork_dllist_remove(&server->entries); - cork_dllist_add(&server_env->connections, &server->entries); + { cork_dllist_remove(&server->entries); }; + { cork_dllist_add(&server_env->connections, &server->entries); }; // init server cipher if (server_env->cipher.enc_method > TABLE) { @@ -843,8 +874,6 @@ server_recv_cb(EV_P_ ev_io *w, int revents) LOGI("server_info host %s", _server_info.host); } _server_info.port = server_env->port; - _server_info.param = server_env->obfs_param; - _server_info.g_data = server_env->obfs_global; _server_info.head_len = get_head_size(ss_addr_to_send.array, 320, 30); _server_info.iv = server->e_ctx->evp.iv; _server_info.iv_len = enc_get_iv_len(&server_env->cipher); @@ -854,6 +883,9 @@ server_recv_cb(EV_P_ ev_io *w, int revents) _server_info.buffer_size = BUF_SIZE; _server_info.cipher_env = &server_env->cipher; + _server_info.param = server_env->obfs_param; + _server_info.g_data = server_env->obfs_global; + if (server_env->obfs_plugin) { server->obfs = server_env->obfs_plugin->new_obfs(); server_env->obfs_plugin->set_server_info(server->obfs, &_server_info); @@ -864,8 +896,15 @@ server_recv_cb(EV_P_ ev_io *w, int revents) if (server_env->protocol_plugin) { server->protocol = server_env->protocol_plugin->new_obfs(); - _server_info.overhead = server_env->protocol_plugin->get_overhead(server->protocol) - + (server_env->obfs_plugin ? server_env->obfs_plugin->get_overhead(server->obfs) : 0); + // overhead must count on this + _server_info.overhead = (uint16_t) + ( + (server_env->protocol_plugin ? + server_env->protocol_plugin->get_overhead(server->protocol) : 0) + + + (server_env->obfs_plugin ? + server_env->obfs_plugin->get_overhead(server->obfs) : 0) + ); server_env->protocol_plugin->set_server_info(server->protocol, &_server_info); } // SSR end @@ -894,11 +933,10 @@ server_recv_cb(EV_P_ ev_io *w, int revents) static void -server_send_cb(EV_P_ ev_io *w, int revents) -{ - server_ctx_t *server_send_ctx = (server_ctx_t *)w; - server_t *server = server_send_ctx->server; - remote_t *remote = server->remote; +server_send_cb(EV_P_ ev_io *w, int revents) { + server_ctx_t *server_send_ctx = (server_ctx_t *) w; + server_t *server = server_send_ctx->server; + remote_t *remote = server->remote; if (server->buf->len == 0) { // close and free close_and_free_remote(EV_A_ remote); @@ -915,7 +953,7 @@ server_send_cb(EV_P_ ev_io *w, int revents) close_and_free_server(EV_A_ server); } return; - } else if (s < (ssize_t)(server->buf->len)) { + } else if (s < (ssize_t) (server->buf->len)) { // partly sent, move memory, wait for the next time to send server->buf->len -= s; server->buf->idx += s; @@ -946,10 +984,9 @@ stat_update_cb() #endif static void -remote_timeout_cb(EV_P_ ev_timer *watcher, int revents) -{ +remote_timeout_cb(EV_P_ ev_timer *watcher, int revents) { remote_ctx_t *remote_ctx - = cork_container_of(watcher, remote_ctx_t, watcher); + = cork_container_of(watcher, remote_ctx_t, watcher); remote_t *remote = remote_ctx->remote; server_t *server = remote->server; @@ -963,14 +1000,13 @@ remote_timeout_cb(EV_P_ ev_timer *watcher, int revents) } static void -remote_recv_cb(EV_P_ ev_io *w, int revents) -{ - remote_ctx_t *remote_recv_ctx = (remote_ctx_t *)w; - remote_t *remote = remote_recv_ctx->remote; - server_t *server = remote->server; - server_def_t *server_env = server->server_env; +remote_recv_cb(EV_P_ ev_io *w, int revents) { + remote_ctx_t *remote_recv_ctx = (remote_ctx_t *) w; + remote_t *remote = remote_recv_ctx->remote; + server_t *server = remote->server; + server_def_t *server_env = server->server_env; - ev_timer_again(EV_A_ & remote->recv_ctx->watcher); + ev_timer_again(EV_A_ &remote->recv_ctx->watcher); #ifdef ANDROID stat_update_cb(); @@ -1003,15 +1039,22 @@ remote_recv_cb(EV_P_ ev_io *w, int revents) if (log_tx_rx) rx += server->buf->len; #endif - if ( r == 0 ) + if (r == 0) return; // SSR beg if (server_env->obfs_plugin) { obfs_class *obfs_plugin = server_env->obfs_plugin; if (obfs_plugin->client_decode) { int needsendback; - server->buf->len = obfs_plugin->client_decode(server->obfs, &server->buf->array, server->buf->len, &server->buf->capacity, &needsendback); - if ((int)server->buf->len < 0) { + server->buf->len = + (size_t) obfs_plugin->client_decode( + server->obfs, + &server->buf->array, + server->buf->len, + &server->buf->capacity, + &needsendback + ); + if ((int) server->buf->len < 0) { LOGE("client_decode"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); @@ -1019,7 +1062,13 @@ remote_recv_cb(EV_P_ ev_io *w, int revents) } if (needsendback) { if (obfs_plugin->client_encode) { - remote->buf->len = obfs_plugin->client_encode(server->obfs, &remote->buf->array, 0, &remote->buf->capacity); + remote->buf->len = + (size_t) obfs_plugin->client_encode( + server->obfs, + &remote->buf->array, + 0, + &remote->buf->capacity + ); ssize_t s = send(remote->fd, remote->buf->array, remote->buf->len, 0); if (s == -1) { if (errno != EAGAIN && errno != EWOULDBLOCK) { @@ -1029,7 +1078,7 @@ remote_recv_cb(EV_P_ ev_io *w, int revents) close_and_free_server(EV_A_ server); } return; - } else if (s < (ssize_t)(remote->buf->len)) { + } else if (s < (ssize_t) (remote->buf->len)) { // partly sent, move memory, wait for the next time to send remote->buf->len -= s; remote->buf->idx += s; @@ -1045,7 +1094,7 @@ remote_recv_cb(EV_P_ ev_io *w, int revents) } } if (server->buf->len > 0) { - int err = ss_decrypt(&server_env->cipher, server->buf, server->d_ctx, BUF_SIZE); + int err = ss_decrypt(&server_env->cipher, server->buf, server->d_ctx, BUF_SIZE); if (err) { LOGE("remote invalid password or cipher"); close_and_free_remote(EV_A_ remote); @@ -1056,14 +1105,20 @@ remote_recv_cb(EV_P_ ev_io *w, int revents) if (server_env->protocol_plugin) { obfs_class *protocol_plugin = server_env->protocol_plugin; if (protocol_plugin->client_post_decrypt) { - server->buf->len = protocol_plugin->client_post_decrypt(server->protocol, &server->buf->array, server->buf->len, &server->buf->capacity); - if ((int)server->buf->len < 0) { + server->buf->len = + (size_t) protocol_plugin->client_post_decrypt( + server->protocol, + &server->buf->array, + server->buf->len, + &server->buf->capacity + ); + if ((int) server->buf->len < 0) { LOGE("client_post_decrypt"); close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); return; } - if ( server->buf->len == 0 ) + if (server->buf->len == 0) return; } } @@ -1082,33 +1137,32 @@ remote_recv_cb(EV_P_ ev_io *w, int revents) close_and_free_remote(EV_A_ remote); close_and_free_server(EV_A_ server); } - } else if (s < (int)(server->buf->len)) { + } else if (s < (int) (server->buf->len)) { server->buf->len -= s; - server->buf->idx = s; + server->buf->idx = s; ev_io_remote_recv(EV_A_ server, remote); } } static void -remote_send_cb(EV_P_ ev_io *w, int revents) -{ - remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w; - remote_t *remote = remote_send_ctx->remote; - server_t *server = remote->server; +remote_send_cb(EV_P_ ev_io *w, int revents) { + remote_ctx_t *remote_send_ctx = (remote_ctx_t *) w; + remote_t *remote = remote_send_ctx->remote; + server_t *server = remote->server; if (!remote_send_ctx->connected) { int err_no = 0; socklen_t len = sizeof err_no; #ifdef __MINGW32__ - int r = getsockopt(remote->fd, SOL_SOCKET, SO_ERROR, (char *)&err_no, &len); + int r = getsockopt(remote->fd, SOL_SOCKET, SO_ERROR, (char *) &err_no, &len); #else int r = getsockopt(remote->fd, SOL_SOCKET, SO_ERROR, &err_no, &len); #endif if (r == 0 && err_no == 0) { remote_send_ctx->connected = 1; - ev_timer_stop(EV_A_ & remote_send_ctx->watcher); - ev_timer_start(EV_A_ & remote->recv_ctx->watcher); - ev_io_start(EV_A_ & remote->recv_ctx->io); + ev_timer_stop(EV_A_ &remote_send_ctx->watcher); + ev_timer_start(EV_A_ &remote->recv_ctx->watcher); + ev_io_start(EV_A_ &remote->recv_ctx->io); // no need to send any data if (remote->buf->len == 0) { @@ -1142,7 +1196,7 @@ remote_send_cb(EV_P_ ev_io *w, int revents) close_and_free_server(EV_A_ server); } return; - } else if (s < (ssize_t)(remote->buf->len)) { + } else if (s < (ssize_t) (remote->buf->len)) { // partly sent, move memory, wait for the next time to send remote->buf->len -= s; remote->buf->idx += s; @@ -1157,24 +1211,23 @@ remote_send_cb(EV_P_ ev_io *w, int revents) } static remote_t * -new_remote(int fd, int timeout) -{ +new_remote(int fd, int timeout) { remote_t *remote; remote = ss_malloc(sizeof(remote_t)); memset(remote, 0, sizeof(remote_t)); - remote->buf = ss_malloc(sizeof(buffer_t)); - remote->recv_ctx = ss_malloc(sizeof(remote_ctx_t)); - remote->send_ctx = ss_malloc(sizeof(remote_ctx_t)); + remote->buf = ss_malloc(sizeof(buffer_t)); + remote->recv_ctx = ss_malloc(sizeof(remote_ctx_t)); + remote->send_ctx = ss_malloc(sizeof(remote_ctx_t)); balloc(remote->buf, BUF_SIZE); memset(remote->recv_ctx, 0, sizeof(remote_ctx_t)); memset(remote->send_ctx, 0, sizeof(remote_ctx_t)); remote->recv_ctx->connected = 0; remote->send_ctx->connected = 0; - remote->fd = fd; - remote->recv_ctx->remote = remote; - remote->send_ctx->remote = remote; + remote->fd = fd; + remote->recv_ctx->remote = remote; + remote->send_ctx->remote = remote; ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ); ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE); @@ -1187,8 +1240,7 @@ new_remote(int fd, int timeout) } static void -free_remote(remote_t *remote) -{ +free_remote(remote_t *remote) { if (remote->server != NULL) { remote->server->remote = NULL; } @@ -1202,64 +1254,59 @@ free_remote(remote_t *remote) } static void -close_and_free_remote(EV_P_ remote_t *remote) -{ +close_and_free_remote(EV_P_ remote_t *remote) { if (remote != NULL) { - ev_timer_stop(EV_A_ & remote->send_ctx->watcher); - ev_timer_stop(EV_A_ & remote->recv_ctx->watcher); - ev_io_stop(EV_A_ & remote->send_ctx->io); - ev_io_stop(EV_A_ & remote->recv_ctx->io); + ev_timer_stop(EV_A_ &remote->send_ctx->watcher); + ev_timer_stop(EV_A_ &remote->recv_ctx->watcher); + ev_io_stop(EV_A_ &remote->send_ctx->io); + ev_io_stop(EV_A_ &remote->recv_ctx->io); close(remote->fd); free_remote(remote); } } static server_t * -new_server(int fd, listen_ctx_t* profile) -{ +new_server(int fd, listen_ctx_t *profile) { server_t *server; server = ss_malloc(sizeof(server_t)); memset(server, 0, sizeof(server_t)); server->listener = profile; - server->recv_ctx = ss_malloc(sizeof(server_ctx_t)); - server->send_ctx = ss_malloc(sizeof(server_ctx_t)); - server->buf = ss_malloc(sizeof(buffer_t)); + server->recv_ctx = ss_malloc(sizeof(server_ctx_t)); + server->send_ctx = ss_malloc(sizeof(server_ctx_t)); + server->buf = ss_malloc(sizeof(buffer_t)); balloc(server->buf, BUF_SIZE); memset(server->recv_ctx, 0, sizeof(server_ctx_t)); memset(server->send_ctx, 0, sizeof(server_ctx_t)); - server->stage = STAGE_INIT; + server->stage = STAGE_INIT; server->recv_ctx->connected = 0; server->send_ctx->connected = 0; - server->fd = fd; - server->recv_ctx->server = server; - server->send_ctx->server = server; + server->fd = fd; + server->recv_ctx->server = server; + server->send_ctx->server = server; ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ); ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE); - cork_dllist_add(&profile->connections_eden, &server->entries); - cork_dllist_add(&all_connections, &server->entries_all); + cork_dllist_add(&profile->connections_eden, &server->entries); + cork_dllist_add(&all_connections, &server->entries_all); return server; } static void -release_profile(listen_ctx_t *profile) -{ +release_profile(listen_ctx_t *profile) { int i; ss_free(profile->iface); - for(i = 0; i < profile->server_num; i++) - { + for (i = 0; i < profile->server_num; i++) { server_def_t *server_env = &profile->servers[i]; ss_free(server_env->host); - if(server_env->addr != server_env->addr_udp) - { + if (server_env->addr != server_env->addr_udp) { ss_free(server_env->addr_udp); } ss_free(server_env->addr); @@ -1272,10 +1319,10 @@ release_profile(listen_ctx_t *profile) ss_free(server_env->obfs_param); ss_free(server_env->protocol_global); ss_free(server_env->obfs_global); - if(server_env->protocol_plugin){ + if (server_env->protocol_plugin) { free_obfs_class(server_env->protocol_plugin); } - if(server_env->obfs_plugin){ + if (server_env->obfs_plugin) { free_obfs_class(server_env->obfs_plugin); } ss_free(server_env->id); @@ -1287,25 +1334,20 @@ release_profile(listen_ctx_t *profile) } static void -check_and_free_profile(listen_ctx_t *profile) -{ +check_and_free_profile(listen_ctx_t *profile) { int i; - if(profile == current_profile) - { + if (profile == current_profile) { return; } // if this connection is created from an inactive profile, then we need to free the profile // when the last connection of that profile is colsed - if(!cork_dllist_is_empty(&profile->connections_eden)) - { + if (!cork_dllist_is_empty(&profile->connections_eden)) { return; } - for(i = 0; i < profile->server_num; i++) - { - if(!cork_dllist_is_empty(&profile->servers[i].connections)) - { + for (i = 0; i < profile->server_num; i++) { + if (!cork_dllist_is_empty(&profile->servers[i].connections)) { return; } } @@ -1316,8 +1358,7 @@ check_and_free_profile(listen_ctx_t *profile) } static void -free_server(server_t *server) -{ +free_server(server_t *server) { listen_ctx_t *profile = server->listener; server_def_t *server_env = server->server_env; @@ -1332,8 +1373,7 @@ free_server(server_t *server) ss_free(server->buf); } - if(server_env) - { + if (server_env) { if (server->e_ctx != NULL) { enc_ctx_release(&server_env->cipher, server->e_ctx); ss_free(server->e_ctx); @@ -1363,19 +1403,17 @@ free_server(server_t *server) } static void -close_and_free_server(EV_P_ server_t *server) -{ +close_and_free_server(EV_P_ server_t *server) { if (server != NULL) { - ev_io_stop(EV_A_ & server->send_ctx->io); - ev_io_stop(EV_A_ & server->recv_ctx->io); + ev_io_stop(EV_A_ &server->send_ctx->io); + ev_io_stop(EV_A_ &server->recv_ctx->io); close(server->fd); free_server(server); } } static remote_t * -create_remote(listen_ctx_t *profile, struct sockaddr *addr) -{ +create_remote(listen_ctx_t *profile, struct sockaddr *addr) { int remotefd = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP); if (remotefd == -1) { @@ -1414,25 +1452,23 @@ create_remote(listen_ctx_t *profile, struct sockaddr *addr) } static void -signal_cb(EV_P_ ev_signal *w, int revents) -{ +signal_cb(EV_P_ ev_signal *w, int revents) { if (revents & EV_SIGNAL) { switch (w->signum) { - case SIGINT: - case SIGTERM: + case SIGINT: + case SIGTERM: #ifndef __MINGW32__ - case SIGUSR1: + case SIGUSR1: #endif - ev_unloop(EV_A_ EVUNLOOP_ALL); + ev_unloop(EV_A_ EVUNLOOP_ALL); } } } void -accept_cb(EV_P_ ev_io *w, int revents) -{ - listen_ctx_t *listener = (listen_ctx_t *)w; - int serverfd = accept(listener->fd, NULL, NULL); +accept_cb(EV_P_ ev_io *w, int revents) { + listen_ctx_t *listener = (listen_ctx_t *) w; + int serverfd = accept(listener->fd, NULL, NULL); if (serverfd == -1) { ERROR("accept"); return; @@ -1446,18 +1482,16 @@ accept_cb(EV_P_ ev_io *w, int revents) server_t *server = new_server(serverfd, listener); - ev_io_start(EV_A_ & server->recv_ctx->io); + ev_io_start(EV_A_ &server->recv_ctx->io); } void -resolve_int_cb(int dummy) -{ +resolve_int_cb(int dummy) { keep_resolving = 0; } static void -init_obfs(server_def_t *serv, char *protocol, char *protocol_param, char *obfs, char *obfs_param) -{ +init_obfs(server_def_t *serv, char *protocol, char *protocol_param, char *obfs, char *obfs_param) { serv->protocol_name = protocol; serv->protocol_param = protocol_param; serv->protocol_plugin = new_obfs_class(protocol); @@ -1735,9 +1769,9 @@ main(int argc, char **argv) } if (remote_num == 0 || remote_port == NULL || - #ifndef HAVE_LAUNCHD +#ifndef HAVE_LAUNCHD local_port == NULL || - #endif +#endif password == NULL) { usage(); exit(EXIT_FAILURE); @@ -2001,28 +2035,27 @@ main(int argc, char **argv) #else int -start_ss_local_server(profile_t profile) -{ +start_ss_local_server(profile_t profile) { srand(time(NULL)); char *remote_host = profile.remote_host; - char *local_addr = profile.local_addr; - char *method = profile.method; - char *password = profile.password; - char *log = profile.log; - int remote_port = profile.remote_port; - int local_port = profile.local_port; - int timeout = profile.timeout; - int mtu = 0; - int mptcp = 0; - - ss_addr_t tunnel_addr = { .host = NULL, .port = NULL }; - - mode = profile.mode; + char *local_addr = profile.local_addr; + char *method = profile.method; + char *password = profile.password; + char *log = profile.log; + int remote_port = profile.remote_port; + int local_port = profile.local_port; + int timeout = profile.timeout; + int mtu = 0; + int mptcp = 0; + + ss_addr_t tunnel_addr = {.host = NULL, .port = NULL}; + + mode = profile.mode; fast_open = profile.fast_open; - verbose = profile.verbose; - mtu = profile.mtu; - mptcp = profile.mptcp; + verbose = profile.verbose; + mtu = profile.mtu; + mptcp = profile.mptcp; char local_port_str[16]; char remote_port_str[16]; @@ -2069,7 +2102,7 @@ start_ss_local_server(profile_t profile) struct ev_loop *loop = EV_DEFAULT; listen_ctx_t listen_ctx; - listen_ctx.server_num = 1; + listen_ctx.server_num = 1; server_def_t *serv = &listen_ctx.servers[0]; ss_server_t server_cfg; ss_server_t *serv_cfg = &server_cfg; @@ -2079,9 +2112,9 @@ start_ss_local_server(profile_t profile) server_cfg.obfs_param = 0; serv->addr = serv->addr_udp = storage; serv->addr_len = serv->addr_udp_len = get_sockaddr_len((struct sockaddr *) storage); - listen_ctx.timeout = timeout; - listen_ctx.iface = NULL; - listen_ctx.mptcp = mptcp; + listen_ctx.timeout = timeout; + listen_ctx.iface = NULL; + listen_ctx.mptcp = mptcp; if (mode != UDP_ONLY) { // Setup socket @@ -2106,8 +2139,19 @@ start_ss_local_server(profile_t profile) // Setup UDP if (mode != TCP_ONLY) { LOGI("udprelay enabled"); - init_udprelay(local_addr, local_port_str, (struct sockaddr*)listen_ctx.servers[0].addr_udp, - listen_ctx.servers[0].addr_udp_len, tunnel_addr, mtu, listen_ctx.timeout, listen_ctx.iface, &listen_ctx.servers[0].cipher, listen_ctx.servers[0].protocol_name, listen_ctx.servers[0].protocol_param); + init_udprelay( + local_addr, + local_port_str, + (struct sockaddr *) listen_ctx.servers[0].addr_udp, + listen_ctx.servers[0].addr_udp_len, + tunnel_addr, + mtu, + listen_ctx.timeout, + listen_ctx.iface, + &listen_ctx.servers[0].cipher, + listen_ctx.servers[0].protocol_name, + listen_ctx.servers[0].protocol_param + ); } if (strcmp(local_addr, ":") > 0) @@ -2120,7 +2164,13 @@ start_ss_local_server(profile_t profile) enc_init(&serv->cipher, password, method); // init obfs - init_obfs(serv, ss_strdup(serv_cfg->protocol), ss_strdup(serv_cfg->protocol_param), ss_strdup(serv_cfg->obfs), ss_strdup(serv_cfg->obfs_param)); + init_obfs( + serv, + ss_strdup(serv_cfg->protocol), + ss_strdup(serv_cfg->protocol_param), + ss_strdup(serv_cfg->obfs), + ss_strdup(serv_cfg->obfs_param) + ); // Init connections cork_dllist_init(&serv->connections); diff --git a/src/obfs/auth.c b/src/obfs/auth.c index b3c746cd..c0d322a8 100644 --- a/src/obfs/auth.c +++ b/src/obfs/auth.c @@ -671,9 +671,10 @@ int auth_aes128_sha1_pack_data(char *data, int datalength, int fulldatalength, c memintcopy_lt(key + key_len - 4, local->pack_id); { - uint8_t rnd_data[rand_len]; + uint8_t *rnd_data = (uint8_t *)malloc(rand_len); rand_bytes(rnd_data, (int)rand_len); memcpy(outdata + 4, rnd_data, rand_len); + free(rnd_data); } { @@ -719,9 +720,10 @@ int auth_aes128_sha1_pack_auth_data(auth_simple_global_data *global, server_info memcpy(key + server->iv_len, server->key, server->key_len); { - uint8_t rnd_data[rand_len]; + uint8_t *rnd_data = (uint8_t *)malloc(rand_len); rand_bytes(rnd_data, (int)rand_len); memcpy(outdata + data_offset - rand_len, rnd_data, rand_len); + free(rnd_data); } ++global->connection_id; @@ -745,7 +747,7 @@ int auth_aes128_sha1_pack_auth_data(auth_simple_global_data *global, server_info char *param = server->param; char *delim = strchr(param, ':'); if(delim != NULL) { - char uid_str[16] = {}; + char uid_str[16] = ""; strncpy(uid_str, param, delim - param); char key_str[128]; strcpy(key_str, delim + 1); @@ -770,9 +772,10 @@ int auth_aes128_sha1_pack_auth_data(auth_simple_global_data *global, server_info } char encrypt_key_base64[256] = {0}; - unsigned char encrypt_key[local->user_key_len]; + unsigned char *encrypt_key = (unsigned char *)malloc(local->user_key_len); memcpy(encrypt_key, local->user_key, local->user_key_len); base64_encode(encrypt_key, (unsigned int)local->user_key_len, encrypt_key_base64); + free(encrypt_key); int base64_len; base64_len = (local->user_key_len + 2) / 3 * 4; @@ -943,7 +946,7 @@ int auth_aes128_sha1_client_udp_pre_encrypt(obfs *self, char **pplaindata, int d char *param = self->server.param; char *delim = strchr(param, ':'); if(delim != NULL) { - char uid_str[16] = {}; + char uid_str[16] = ""; strncpy(uid_str, param, delim - param); char key_str[128]; strcpy(key_str, delim + 1); diff --git a/src/obfs/auth_chain.c b/src/obfs/auth_chain.c index b9838d56..3c30a9f5 100644 --- a/src/obfs/auth_chain.c +++ b/src/obfs/auth_chain.c @@ -1,18 +1,21 @@ #include #include +#include +#include #include "auth.h" #include "obfsutil.h" #include "crc32.h" #include "base64.h" #include "encrypt.h" +#include "obfs.h" uint32_t g_endian_test = 1; typedef struct shift128plus_ctx { uint64_t v[2]; -}shift128plus_ctx; +} shift128plus_ctx; -uint64_t shift128plus_next(shift128plus_ctx* ctx) { +uint64_t shift128plus_next(shift128plus_ctx *ctx) { uint64_t x = ctx->v[0]; uint64_t y = ctx->v[1]; ctx->v[0] = y; @@ -22,33 +25,55 @@ uint64_t shift128plus_next(shift128plus_ctx* ctx) { return x + y; } -void i64_memcpy(uint8_t* target, uint8_t* source) -{ +void i64_memcpy(uint8_t *target, uint8_t *source) { for (int i = 0; i < 8; ++i) target[i] = source[7 - i]; } -void shift128plus_init_from_bin(shift128plus_ctx* ctx, uint8_t* bin, int bin_size) { +int find_pos(int arr[], int length, int key) { + int low = 0; + int high = length - 1; + int middle = -1; + + if (key > arr[high]) + return length; + + while (low < high) { + middle = (low + high) / 2; + if (key > arr[middle]) { + low = middle + 1; + } else if (key <= arr[middle]) { + high = middle; + } + } + return low; +} + +int data_size_list_compare(const void *a, const void *b) { + return (*(int *) a - *(int *) b); +} + +void shift128plus_init_from_bin(shift128plus_ctx *ctx, uint8_t *bin, int bin_size) { uint8_t fill_bin[16] = {0}; memcpy(fill_bin, bin, bin_size); - if (*(uint8_t*)&g_endian_test == 1) { + if (*(uint8_t *) &g_endian_test == 1) { memcpy(ctx, fill_bin, 16); } else { - i64_memcpy((uint8_t*)ctx, fill_bin); - i64_memcpy((uint8_t*)ctx + 8, fill_bin + 8); + i64_memcpy((uint8_t *) ctx, fill_bin); + i64_memcpy((uint8_t *) ctx + 8, fill_bin + 8); } } -void shift128plus_init_from_bin_datalen(shift128plus_ctx* ctx, uint8_t* bin, int bin_size, int datalen) { +void shift128plus_init_from_bin_datalen(shift128plus_ctx *ctx, uint8_t *bin, int bin_size, int datalen) { uint8_t fill_bin[16] = {0}; memcpy(fill_bin, bin, bin_size); fill_bin[0] = datalen; fill_bin[1] = datalen >> 8; - if (*(uint8_t*)&g_endian_test == 1) { + if (*(uint8_t *) &g_endian_test == 1) { memcpy(ctx, fill_bin, 16); } else { - i64_memcpy((uint8_t*)ctx, fill_bin); - i64_memcpy((uint8_t*)ctx + 8, fill_bin + 8); + i64_memcpy((uint8_t *) ctx, fill_bin); + i64_memcpy((uint8_t *) ctx + 8, fill_bin + 8); } for (int i = 0; i < 4; ++i) { shift128plus_next(ctx); @@ -58,16 +83,28 @@ void shift128plus_init_from_bin_datalen(shift128plus_ctx* ctx, uint8_t* bin, int typedef struct auth_chain_global_data { uint8_t local_client_id[4]; uint32_t connection_id; -}auth_chain_global_data; +} auth_chain_global_data; + +typedef struct auth_chain_b_data { + int *data_size_list; + int data_size_list_length; + int *data_size_list2; + int data_size_list2_length; +} auth_chain_b_data; + +typedef struct auth_chain_c_data { + int *data_size_list0; + int data_size_list0_length; +} auth_chain_c_data; typedef struct auth_chain_local_data { int has_sent_header; - char * recv_buffer; + char *recv_buffer; int recv_buffer_size; uint32_t recv_id; uint32_t pack_id; - char * salt; - uint8_t * user_key; + char *salt; + uint8_t *user_key; char uid[4]; int user_key_len; int last_data_len; @@ -77,13 +114,23 @@ typedef struct auth_chain_local_data { shift128plus_ctx random_server; int cipher_init_flag; cipher_env_t cipher; - enc_ctx_t* cipher_client_ctx; - enc_ctx_t* cipher_server_ctx; -}auth_chain_local_data; + enc_ctx_t *cipher_client_ctx; + enc_ctx_t *cipher_server_ctx; + + unsigned int (*get_tcp_rand_len)( + struct auth_chain_local_data *local, + server_info *server, + int datalength, + shift128plus_ctx *random, + uint8_t *last_hash + ); + + void *auth_chain_special_data; +} auth_chain_local_data; -void auth_chain_local_data_init(auth_chain_local_data* local) { +void auth_chain_local_data_init(auth_chain_local_data *local) { local->has_sent_header = 0; - local->recv_buffer = (char*)malloc(16384); + local->recv_buffer = (char *) malloc(16384); local->recv_buffer_size = 0; local->recv_id = 1; local->pack_id = 1; @@ -93,21 +140,398 @@ void auth_chain_local_data_init(auth_chain_local_data* local) { local->cipher_init_flag = 0; local->cipher_client_ctx = 0; local->cipher_server_ctx = 0; + local->get_tcp_rand_len = NULL; +} + +unsigned int auth_chain_a_get_rand_len( + auth_chain_local_data *local, + server_info *server, + int datalength, + shift128plus_ctx *random, + uint8_t *last_hash +) { + if (datalength > 1440) + return 0; + shift128plus_init_from_bin_datalen(random, last_hash, 16, datalength); + if (datalength > 1300) + return (unsigned int) (shift128plus_next(random) % 31); + if (datalength > 900) + return (unsigned int) (shift128plus_next(random) % 127); + if (datalength > 400) + return (unsigned int) (shift128plus_next(random) % 521); + return (unsigned int) (shift128plus_next(random) % 1021); +} + +unsigned int auth_chain_b_get_rand_len( + auth_chain_local_data *local, + server_info *server, + int datalength, + shift128plus_ctx *random, + uint8_t *last_hash +) { + if (datalength > 1440) + return 0; + uint16_t overhead = server->overhead; + auth_chain_b_data *special_data = (auth_chain_b_data *) local->auth_chain_special_data; + + int other_data_size = datalength + overhead; + + // auth_chain_b_get_rand_len + shift128plus_init_from_bin_datalen(random, last_hash, 16, datalength); + int pos = find_pos(special_data->data_size_list, special_data->data_size_list_length, other_data_size); + uint64_t final_pos = pos + shift128plus_next(random) % special_data->data_size_list_length; + if (final_pos < special_data->data_size_list_length) { + return special_data->data_size_list[final_pos] - other_data_size; + } + + int pos2 = find_pos(special_data->data_size_list2, special_data->data_size_list2_length, other_data_size); + uint64_t final_pos2 = pos2 + shift128plus_next(random) % special_data->data_size_list2_length; + if (final_pos2 < special_data->data_size_list2_length) { + return special_data->data_size_list2[final_pos2] - other_data_size; + } + if (final_pos2 < pos2 + special_data->data_size_list2_length - 1) { + return 0; + } + + if (datalength > 1300) + return (unsigned int) (shift128plus_next(random) % 31); + if (datalength > 900) + return (unsigned int) (shift128plus_next(random) % 127); + if (datalength > 400) + return (unsigned int) (shift128plus_next(random) % 521); + return (unsigned int) (shift128plus_next(random) % 1021); +} + +unsigned int auth_chain_c_get_rand_len( + auth_chain_local_data *local, + server_info *server, + int datalength, + shift128plus_ctx *random, + uint8_t *last_hash +) { + uint16_t overhead = server->overhead; + auth_chain_c_data *special_data = (auth_chain_c_data *) local->auth_chain_special_data; + + int other_data_size = datalength + overhead; + + // must init random in here to make sure output sync in server and client + shift128plus_init_from_bin_datalen(random, last_hash, 16, datalength); + if (other_data_size >= special_data->data_size_list0[special_data->data_size_list0_length - 1]) { + if (datalength > 1440) + return 0; + if (datalength > 1300) + return (unsigned int) (shift128plus_next(random) % 31); + if (datalength > 900) + return (unsigned int) (shift128plus_next(random) % 127); + if (datalength > 400) + return (unsigned int) (shift128plus_next(random) % 521); + return (unsigned int) (shift128plus_next(random) % 1021); + } + + int pos = find_pos(special_data->data_size_list0, special_data->data_size_list0_length, other_data_size); + // random select a size in the leftover data_size_list0 + uint64_t final_pos = pos + shift128plus_next(random) % (special_data->data_size_list0_length - pos); + return special_data->data_size_list0[final_pos] - other_data_size; +} + +unsigned int auth_chain_d_get_rand_len( + auth_chain_local_data *local, + server_info *server, + int datalength, + shift128plus_ctx *random, + uint8_t *last_hash +) { + uint16_t overhead = server->overhead; + auth_chain_c_data *special_data = (auth_chain_c_data *) local->auth_chain_special_data; + + int other_data_size = datalength + overhead; + + // if other_data_size > the bigest item in data_size_list0, not padding any data + if (other_data_size >= special_data->data_size_list0[special_data->data_size_list0_length - 1]) { + return 0; + } + + shift128plus_init_from_bin_datalen(random, last_hash, 16, datalength); + int pos = find_pos(special_data->data_size_list0, special_data->data_size_list0_length, other_data_size); + // random select a size in the leftover data_size_list0 + uint64_t final_pos = pos + shift128plus_next(random) % (special_data->data_size_list0_length - pos); + return special_data->data_size_list0[final_pos] - other_data_size; +} + +unsigned int auth_chain_e_get_rand_len( + auth_chain_local_data *local, + server_info *server, + int datalength, + shift128plus_ctx *random, + uint8_t *last_hash +) { + shift128plus_init_from_bin_datalen(random, last_hash, 16, datalength); + uint16_t overhead = server->overhead; + auth_chain_c_data *special_data = (auth_chain_c_data *) local->auth_chain_special_data; + + int other_data_size = datalength + overhead; + + // if other_data_size > the bigest item in data_size_list0, not padding any data + if (other_data_size >= special_data->data_size_list0[special_data->data_size_list0_length - 1]) { + return 0; + } + + // use the mini size in the data_size_list0 + int pos = find_pos(special_data->data_size_list0, special_data->data_size_list0_length, other_data_size); + return special_data->data_size_list0[pos] - other_data_size; +} + +unsigned int auth_chain_f_get_rand_len( + auth_chain_local_data *local, + server_info *server, + int datalength, + shift128plus_ctx *random, + uint8_t *last_hash +) { + return auth_chain_e_get_rand_len( + local, + server, + datalength, + random, + last_hash + ); +} + +void auth_chain_b_init_data_size(obfs *self, server_info *server) { + auth_chain_b_data *special_data = (auth_chain_b_data *) + ((auth_chain_local_data *) self->l_data)->auth_chain_special_data; + + shift128plus_ctx *random = (shift128plus_ctx *) malloc(sizeof(shift128plus_ctx)); + + shift128plus_init_from_bin(random, server->key, 16); + special_data->data_size_list_length = shift128plus_next(random) % 8 + 4; + special_data->data_size_list = (int *) malloc(special_data->data_size_list_length * sizeof(int)); + for (int i = 0; i < special_data->data_size_list_length; i++) { + special_data->data_size_list[i] = shift128plus_next(random) % 2340 % 2040 % 1440; + } + // stdlib qsort + qsort(special_data->data_size_list, + special_data->data_size_list_length, + sizeof(int), + data_size_list_compare + ); + + special_data->data_size_list2_length = shift128plus_next(random) % 16 + 8; + special_data->data_size_list2 = (int *) malloc(special_data->data_size_list2_length * sizeof(int)); + for (int i = 0; i < special_data->data_size_list2_length; i++) { + special_data->data_size_list2[i] = shift128plus_next(random) % 2340 % 2040 % 1440; + } + // stdlib qsort + qsort(special_data->data_size_list2, + special_data->data_size_list2_length, + sizeof(int), + data_size_list_compare + ); + + free(random); +} + +void auth_chain_c_init_data_size(obfs *self, server_info *server) { + + auth_chain_c_data *special_data = (auth_chain_c_data *) + ((auth_chain_local_data *) self->l_data)->auth_chain_special_data; + + shift128plus_ctx *random = (shift128plus_ctx *) malloc(sizeof(shift128plus_ctx)); + + shift128plus_init_from_bin(random, server->key, 16); + special_data->data_size_list0_length = shift128plus_next(random) % (8 + 16) + (4 + 8); + special_data->data_size_list0 = (int *) malloc(special_data->data_size_list0_length * sizeof(int)); + for (int i = 0; i < special_data->data_size_list0_length; i++) { + special_data->data_size_list0[i] = shift128plus_next(random) % 2340 % 2040 % 1440; + } + // stdlib qsort + qsort(special_data->data_size_list0, + special_data->data_size_list0_length, + sizeof(int), + data_size_list_compare + ); + + free(random); +} + +#define AUTH_CHAIN_D_MAX_DATA_SIZE_LIST_LIMIT_SIZE 64 + +void auth_chain_d_check_and_patch_data_size(obfs *self, shift128plus_ctx *random) { + auth_chain_c_data *special_data = (auth_chain_c_data *) + ((auth_chain_local_data *) self->l_data)->auth_chain_special_data; + + while (special_data->data_size_list0[special_data->data_size_list0_length - 1] < 1300 + && special_data->data_size_list0_length < AUTH_CHAIN_D_MAX_DATA_SIZE_LIST_LIMIT_SIZE) { + + // data_size_list0.size + 1 + special_data->data_size_list0[special_data->data_size_list0_length] = + shift128plus_next(random) % 2340 % 2040 % 1440; + ++(special_data->data_size_list0_length); + } +} + +void auth_chain_d_init_data_size(obfs *self, server_info *server) { + + auth_chain_c_data *special_data = (auth_chain_c_data *) + ((auth_chain_local_data *) self->l_data)->auth_chain_special_data; + + shift128plus_ctx *random = (shift128plus_ctx *) malloc(sizeof(shift128plus_ctx)); + + shift128plus_init_from_bin(random, server->key, 16); + special_data->data_size_list0_length = shift128plus_next(random) % (8 + 16) + (4 + 8); + special_data->data_size_list0 = (int *) malloc(AUTH_CHAIN_D_MAX_DATA_SIZE_LIST_LIMIT_SIZE * sizeof(int)); + for (int i = 0; i < special_data->data_size_list0_length; i++) { + special_data->data_size_list0[i] = shift128plus_next(random) % 2340 % 2040 % 1440; + } + // stdlib qsort + qsort(special_data->data_size_list0, + special_data->data_size_list0_length, + sizeof(int), + data_size_list_compare + ); + + int old_len = special_data->data_size_list0_length; + auth_chain_d_check_and_patch_data_size(self, random); + if (old_len != special_data->data_size_list0_length) { + // if check_and_patch_data_size are work, re-sort again. + // stdlib qsort + qsort(special_data->data_size_list0, + special_data->data_size_list0_length, + sizeof(int), + data_size_list_compare + ); + } + + free(random); +} + +void auth_chain_f_init_data_size(obfs *self, server_info *server, const uint8_t *key_change_datetime_key_bytes) { + + auth_chain_c_data *special_data = (auth_chain_c_data *) + ((auth_chain_local_data *) self->l_data)->auth_chain_special_data; + + shift128plus_ctx *random = (shift128plus_ctx *) malloc(sizeof(shift128plus_ctx)); + + uint8_t *newKey = (uint8_t *) malloc(sizeof(uint8_t) * server->key_len); + memcpy(newKey, server->key, server->key_len); + for (int i = 0; i != 8; ++i) { + newKey[i] ^= key_change_datetime_key_bytes[i]; + } + + shift128plus_init_from_bin(random, newKey, 16); + free(newKey); + newKey = NULL; + + special_data->data_size_list0_length = shift128plus_next(random) % (8 + 16) + (4 + 8); + special_data->data_size_list0 = (int *) malloc(AUTH_CHAIN_D_MAX_DATA_SIZE_LIST_LIMIT_SIZE * sizeof(int)); + for (int i = 0; i < special_data->data_size_list0_length; i++) { + special_data->data_size_list0[i] = shift128plus_next(random) % 2340 % 2040 % 1440; + } + // stdlib qsort + qsort(special_data->data_size_list0, + special_data->data_size_list0_length, + sizeof(int), + data_size_list_compare + ); + + int old_len = special_data->data_size_list0_length; + auth_chain_d_check_and_patch_data_size(self, random); + if (old_len != special_data->data_size_list0_length) { + // if check_and_patch_data_size are work, re-sort again. + // stdlib qsort + qsort(special_data->data_size_list0, + special_data->data_size_list0_length, + sizeof(int), + data_size_list_compare + ); + } + + free(random); } -void * auth_chain_a_init_data() { - auth_chain_global_data *global = (auth_chain_global_data*)malloc(sizeof(auth_chain_global_data)); +void *auth_chain_a_init_data() { + auth_chain_global_data *global = (auth_chain_global_data *) malloc(sizeof(auth_chain_global_data)); rand_bytes(global->local_client_id, 4); - rand_bytes((uint8_t*)&global->connection_id, 4); + rand_bytes((uint8_t *) &global->connection_id, 4); global->connection_id &= 0xFFFFFF; return global; } -obfs * auth_chain_a_new_obfs() { - obfs * self = new_obfs(); +void *auth_chain_b_init_data() { + return auth_chain_a_init_data(); +} + +void *auth_chain_c_init_data() { + return auth_chain_a_init_data(); +} + +void *auth_chain_d_init_data() { + return auth_chain_c_init_data(); +} + +void *auth_chain_e_init_data() { + return auth_chain_d_init_data(); +} + +void *auth_chain_f_init_data() { + return auth_chain_e_init_data(); +} + +obfs *auth_chain_a_new_obfs() { + obfs *self = new_obfs(); + self->l_data = malloc(sizeof(auth_chain_local_data)); + auth_chain_local_data_init((auth_chain_local_data *) self->l_data); + ((auth_chain_local_data *) self->l_data)->salt = "auth_chain_a"; + ((auth_chain_local_data *) self->l_data)->get_tcp_rand_len = auth_chain_a_get_rand_len; + return self; +} + +obfs *auth_chain_b_new_obfs() { + obfs *self = new_obfs(); + self->l_data = malloc(sizeof(auth_chain_local_data)); + auth_chain_local_data_init((auth_chain_local_data *) self->l_data); + ((auth_chain_local_data *) self->l_data)->salt = "auth_chain_b"; + ((auth_chain_local_data *) self->l_data)->get_tcp_rand_len = auth_chain_b_get_rand_len; + auth_chain_b_data *special_data = (auth_chain_b_data *) malloc(sizeof(auth_chain_b_data)); + special_data->data_size_list = NULL; + special_data->data_size_list_length = 0; + special_data->data_size_list2 = NULL; + special_data->data_size_list2_length = 0; + ((auth_chain_local_data *) self->l_data)->auth_chain_special_data = special_data; + return self; +} + +obfs *auth_chain_c_new_obfs() { + obfs *self = new_obfs(); self->l_data = malloc(sizeof(auth_chain_local_data)); - auth_chain_local_data_init((auth_chain_local_data*)self->l_data); - ((auth_chain_local_data*)self->l_data)->salt = "auth_chain_a"; + auth_chain_local_data_init((auth_chain_local_data *) self->l_data); + ((auth_chain_local_data *) self->l_data)->salt = "auth_chain_c"; + ((auth_chain_local_data *) self->l_data)->get_tcp_rand_len = auth_chain_c_get_rand_len; + auth_chain_c_data *special_data = (auth_chain_c_data *) malloc(sizeof(auth_chain_c_data)); + special_data->data_size_list0 = NULL; + special_data->data_size_list0_length = 0; + ((auth_chain_local_data *) self->l_data)->auth_chain_special_data = special_data; + return self; +} + +obfs *auth_chain_d_new_obfs() { + obfs *self = auth_chain_c_new_obfs(); + ((auth_chain_local_data *) self->l_data)->salt = "auth_chain_d"; + ((auth_chain_local_data *) self->l_data)->get_tcp_rand_len = auth_chain_d_get_rand_len; + return self; +} + +obfs *auth_chain_e_new_obfs() { + obfs *self = auth_chain_d_new_obfs(); + ((auth_chain_local_data *) self->l_data)->salt = "auth_chain_e"; + ((auth_chain_local_data *) self->l_data)->get_tcp_rand_len = auth_chain_e_get_rand_len; + return self; +} + +obfs *auth_chain_f_new_obfs() { + obfs *self = auth_chain_e_new_obfs(); + ((auth_chain_local_data *) self->l_data)->salt = "auth_chain_f"; + ((auth_chain_local_data *) self->l_data)->get_tcp_rand_len = auth_chain_f_get_rand_len; return self; } @@ -115,8 +539,28 @@ int auth_chain_a_get_overhead(obfs *self) { return 4; } +int auth_chain_b_get_overhead(obfs *self) { + return auth_chain_a_get_overhead(self); +} + +int auth_chain_c_get_overhead(obfs *self) { + return auth_chain_a_get_overhead(self); +} + +int auth_chain_d_get_overhead(obfs *self) { + return auth_chain_c_get_overhead(self); +} + +int auth_chain_e_get_overhead(obfs *self) { + return auth_chain_d_get_overhead(self); +} + +int auth_chain_f_get_overhead(obfs *self) { + return auth_chain_e_get_overhead(self); +} + void auth_chain_a_dispose(obfs *self) { - auth_chain_local_data *local = (auth_chain_local_data*)self->l_data; + auth_chain_local_data *local = (auth_chain_local_data *) self->l_data; if (local->recv_buffer != NULL) { free(local->recv_buffer); local->recv_buffer = NULL; @@ -140,155 +584,251 @@ void auth_chain_a_dispose(obfs *self) { dispose_obfs(self); } -void auth_chain_set_server_info(obfs *self, server_info *server) { - server->overhead = 4; +void auth_chain_b_dispose(obfs *self) { + auth_chain_local_data *local = (auth_chain_local_data *) self->l_data; + auth_chain_b_data *special_data = (auth_chain_b_data *) local->auth_chain_special_data; + if (local->auth_chain_special_data != NULL) { + if (special_data->data_size_list != NULL) { + free(special_data->data_size_list); + special_data->data_size_list = NULL; + special_data->data_size_list_length = 0; + } + if (special_data->data_size_list2 != NULL) { + free(special_data->data_size_list2); + special_data->data_size_list2 = NULL; + special_data->data_size_list2_length = 0; + } + free(local->auth_chain_special_data); + local->auth_chain_special_data = NULL; + } + auth_chain_a_dispose(self); +} + +void auth_chain_c_dispose(obfs *self) { + auth_chain_local_data *local = (auth_chain_local_data *) self->l_data; + auth_chain_c_data *special_data = (auth_chain_c_data *) local->auth_chain_special_data; + if (local->auth_chain_special_data != NULL) { + if (special_data->data_size_list0 != NULL) { + free(special_data->data_size_list0); + special_data->data_size_list0 = NULL; + special_data->data_size_list0_length = 0; + } + free(local->auth_chain_special_data); + local->auth_chain_special_data = NULL; + } + auth_chain_a_dispose(self); +} + +void auth_chain_d_dispose(obfs *self) { + auth_chain_c_dispose(self); +} + +void auth_chain_e_dispose(obfs *self) { + auth_chain_d_dispose(self); +} + +void auth_chain_f_dispose(obfs *self) { + auth_chain_e_dispose(self); +} + +void auth_chain_a_set_server_info(obfs *self, server_info *server) { + // dont change server.overhead in there + // the server.overhead are counted from the local.c + // the input's server.overhead is the total server.overhead that sum of all the plugin's overhead memmove(&self->server, server, sizeof(server_info)); } -unsigned int auth_chain_a_get_rand_len(int datalength, shift128plus_ctx* random, uint8_t* last_hash) { - if (datalength > 1440) - return 0; - shift128plus_init_from_bin_datalen(random, last_hash, 16, datalength); - if (datalength > 1300) - return shift128plus_next(random) % 31; - if (datalength > 900) - return shift128plus_next(random) % 127; - if (datalength > 400) - return shift128plus_next(random) % 521; - return shift128plus_next(random) % 1021; +void auth_chain_b_set_server_info(obfs *self, server_info *server) { + memmove(&self->server, server, sizeof(server_info)); + // auth_chain_b_init_data_size() init in there + auth_chain_b_init_data_size(self, &self->server); +} + +void auth_chain_c_set_server_info(obfs *self, server_info *server) { + memmove(&self->server, server, sizeof(server_info)); + // auth_chain_c_init_data_size() init in there + auth_chain_c_init_data_size(self, &self->server); +} + +void auth_chain_d_set_server_info(obfs *self, server_info *server) { + memmove(&self->server, server, sizeof(server_info)); + // auth_chain_d_init_data_size() init in there + auth_chain_d_init_data_size(self, &self->server); +} + +void auth_chain_e_set_server_info(obfs *self, server_info *server) { + auth_chain_d_set_server_info(self, server); } -unsigned int udp_get_rand_len(shift128plus_ctx* random, uint8_t* last_hash) { +void auth_chain_f_set_server_info(obfs *self, server_info *server) { + memmove(&self->server, server, sizeof(server_info)); + + uint64_t key_change_interval = 60 * 60 * 24; // a day by second + if (server->param != NULL && server->param[0] != 0) { + char *delim1 = strchr(server->param, '#'); + if (delim1 != NULL && delim1[1] != '\0') { + ++delim1; + char *delim2 = strchr(delim1, '#'); + if (delim2 == NULL) { + delim2 = strchr(delim1, '\0'); + } + unsigned long l = delim2 - delim1; + if (l > 2) { + long long n = strtoll(delim1, &delim2, 0); + if (n != 0 && n != LLONG_MAX && n != LLONG_MIN && n > 0) { + key_change_interval = (uint64_t) n; + } + } + } + } + + uint8_t *key_change_datetime_key_bytes = (uint8_t *) malloc(sizeof(uint8_t) * 8); + uint64_t key_change_datetime_key = (uint64_t) (time(NULL)) / key_change_interval; + for (int i = 7; i >= 0; --i) { + key_change_datetime_key_bytes[7 - i] = (uint8_t) ((key_change_datetime_key >> (8 * i)) & 0xFF); + } + + auth_chain_f_init_data_size(self, &self->server, key_change_datetime_key_bytes); + + free(key_change_datetime_key_bytes); + key_change_datetime_key_bytes = NULL; +} + +unsigned int udp_get_rand_len(shift128plus_ctx *random, uint8_t *last_hash) { shift128plus_init_from_bin(random, last_hash, 16); return shift128plus_next(random) % 127; } -unsigned int get_rand_start_pos(int rand_len, shift128plus_ctx* random) { +unsigned int get_rand_start_pos(int rand_len, shift128plus_ctx *random) { if (rand_len > 0) return shift128plus_next(random) % 8589934609 % rand_len; return 0; } -unsigned int get_client_rand_len(auth_chain_local_data *local, int datalength) { - return auth_chain_a_get_rand_len(datalength, &local->random_client, local->last_client_hash); +unsigned int get_client_rand_len(auth_chain_local_data *local, server_info *server, int datalength) { + return local->get_tcp_rand_len(local, server, datalength, &local->random_client, local->last_client_hash); } -unsigned int get_server_rand_len(auth_chain_local_data *local, int datalength) { - return auth_chain_a_get_rand_len(datalength, &local->random_server, local->last_server_hash); +unsigned int get_server_rand_len(auth_chain_local_data *local, server_info *server, int datalength) { + return local->get_tcp_rand_len(local, server, datalength, &local->random_server, local->last_server_hash); } -int auth_chain_a_pack_data(char *data, int datalength, char *outdata, auth_chain_local_data *local, server_info *server) { - unsigned int rand_len = get_client_rand_len(local, datalength); - int out_size = (int)rand_len + datalength + 2; - outdata[0] = (char)((uint8_t)datalength ^ local->last_client_hash[14]); - outdata[1] = (char)((uint8_t)(datalength >> 8) ^ local->last_client_hash[15]); +int auth_chain_a_pack_data(char *data, int datalength, char *outdata, auth_chain_local_data *local, + server_info *server) { + unsigned int rand_len = get_client_rand_len(local, server, datalength); + int out_size = (int) rand_len + datalength + 2; + outdata[0] = (char) ((uint8_t) datalength ^ local->last_client_hash[14]); + outdata[1] = (char) ((uint8_t) (datalength >> 8) ^ local->last_client_hash[15]); { - uint8_t rnd_data[rand_len]; - rand_bytes(rnd_data, (int)rand_len); + uint8_t *rnd_data = (uint8_t *)malloc(rand_len); + rand_bytes(rnd_data, (int) rand_len); if (datalength > 0) { int start_pos = get_rand_start_pos(rand_len, &local->random_client); size_t out_len; ss_encrypt_buffer(&local->cipher, local->cipher_client_ctx, - data, datalength, &outdata[2 + start_pos], &out_len); + data, datalength, &outdata[2 + start_pos], &out_len); memcpy(outdata + 2, rnd_data, start_pos); memcpy(outdata + 2 + start_pos + datalength, rnd_data + start_pos, rand_len - start_pos); } else { memcpy(outdata + 2, rnd_data, rand_len); } + free(rnd_data); } - uint8_t key_len = (uint8_t)(local->user_key_len + 4); - uint8_t key[key_len]; + uint8_t key_len = (uint8_t) (local->user_key_len + 4); + uint8_t *key = (uint8_t *)malloc(key_len); memcpy(key, local->user_key, local->user_key_len); memintcopy_lt(key + key_len - 4, local->pack_id); ++local->pack_id; - ss_md5_hmac_with_key((char*)local->last_client_hash, outdata, out_size, key, key_len); + ss_md5_hmac_with_key((char *) local->last_client_hash, outdata, out_size, key, key_len); memcpy(outdata + out_size, local->last_client_hash, 2); - + free(key); return out_size + 2; } -int auth_chain_a_pack_auth_data(auth_chain_global_data *global, server_info *server, auth_chain_local_data *local, char *data, int datalength, char *outdata) { +int auth_chain_a_pack_auth_data(auth_chain_global_data *global, server_info *server, auth_chain_local_data *local, + char *data, int datalength, char *outdata) { const int authhead_len = 4 + 8 + 4 + 16 + 4; - const char* salt = local->salt; + const char *salt = local->salt; int out_size = authhead_len; ++global->connection_id; if (global->connection_id > 0xFF000000) { rand_bytes(global->local_client_id, 8); - rand_bytes((uint8_t*)&global->connection_id, 4); + rand_bytes((uint8_t *) &global->connection_id, 4); global->connection_id &= 0xFFFFFF; } char encrypt[20]; - uint8_t key[server->iv_len + server->key_len]; - uint8_t key_len = (uint8_t)(server->iv_len + server->key_len); + uint8_t *key = (uint8_t *)malloc(server->iv_len + server->key_len); + uint8_t key_len = (uint8_t) (server->iv_len + server->key_len); memcpy(key, server->iv, server->iv_len); memcpy(key + server->iv_len, server->key, server->key_len); time_t t = time(NULL); - memintcopy_lt(encrypt, (uint32_t)t); + memintcopy_lt(encrypt, (uint32_t) t); memcpy(encrypt + 4, global->local_client_id, 4); memintcopy_lt(encrypt + 8, global->connection_id); - encrypt[12] = (char)server->overhead; - encrypt[13] = (char)(server->overhead >> 8); + encrypt[12] = (char) server->overhead; + encrypt[13] = (char) (server->overhead >> 8); encrypt[14] = 0; encrypt[15] = 0; // first 12 bytes { - rand_bytes((uint8_t*)outdata, 4); - ss_md5_hmac_with_key((char*)local->last_client_hash, (char*)outdata, 4, key, key_len); + rand_bytes((uint8_t *) outdata, 4); + ss_md5_hmac_with_key((char *) local->last_client_hash, (char *) outdata, 4, key, key_len); memcpy(outdata + 4, local->last_client_hash, 8); } + free(key); // uid & 16 bytes auth data { uint8_t uid[4]; if (local->user_key == NULL) { - if(server->param != NULL && server->param[0] != 0) { + if (server->param != NULL && server->param[0] != 0) { char *param = server->param; char *delim = strchr(param, ':'); - if(delim != NULL) { - char uid_str[16] = {}; + if (delim != NULL) { + char uid_str[16] = ""; strncpy(uid_str, param, delim - param); char key_str[128]; strcpy(key_str, delim + 1); long uid_long = strtol(uid_str, NULL, 10); - memintcopy_lt((char*)local->uid, (uint32_t)uid_long); + memintcopy_lt((char *) local->uid, (uint32_t) uid_long); - local->user_key_len = (int)strlen(key_str); - local->user_key = (uint8_t*)malloc((size_t)local->user_key_len); + local->user_key_len = (int) strlen(key_str); + local->user_key = (uint8_t *) malloc((size_t) local->user_key_len); memcpy(local->user_key, key_str, local->user_key_len); } } if (local->user_key == NULL) { - rand_bytes((uint8_t*)local->uid, 4); + rand_bytes((uint8_t *) local->uid, 4); - local->user_key_len = (int)server->key_len; - local->user_key = (uint8_t*)malloc((size_t)local->user_key_len); + local->user_key_len = (int) server->key_len; + local->user_key = (uint8_t *) malloc((size_t) local->user_key_len); memcpy(local->user_key, server->key, local->user_key_len); } } - for (int i = 0; i < 4; ++i) - { + for (int i = 0; i < 4; ++i) { uid[i] = local->uid[i] ^ local->last_client_hash[8 + i]; } char encrypt_key_base64[256] = {0}; - unsigned char encrypt_key[local->user_key_len]; + unsigned char *encrypt_key = (unsigned char *)malloc(local->user_key_len); memcpy(encrypt_key, local->user_key, local->user_key_len); - base64_encode(encrypt_key, (unsigned int)local->user_key_len, encrypt_key_base64); + base64_encode(encrypt_key, (unsigned int) local->user_key_len, encrypt_key_base64); + free(encrypt_key); - int salt_len = strlen(salt); + int salt_len = (int)strlen(salt); int base64_len = (local->user_key_len + 2) / 3 * 4; memcpy(encrypt_key_base64 + base64_len, salt, salt_len); char enc_key[16]; int enc_key_len = base64_len + salt_len; - bytes_to_key_with_size(encrypt_key_base64, (size_t)enc_key_len, (uint8_t*)enc_key, 16); + bytes_to_key_with_size(encrypt_key_base64, (size_t) enc_key_len, (uint8_t *) enc_key, 16); char encrypt_data[16]; ss_aes_128_cbc(encrypt, encrypt_data, enc_key); memcpy(encrypt, uid, 4); @@ -296,7 +836,7 @@ int auth_chain_a_pack_auth_data(auth_chain_global_data *global, server_info *ser } // final HMAC { - ss_md5_hmac_with_key((char*)local->last_server_hash, encrypt, 20, local->user_key, local->user_key_len); + ss_md5_hmac_with_key((char *) local->last_server_hash, encrypt, 20, local->user_key, local->user_key_len); memcpy(outdata + 12, encrypt, 20); memcpy(outdata + 12 + 20, local->last_server_hash, 4); } @@ -316,27 +856,28 @@ int auth_chain_a_pack_auth_data(auth_chain_global_data *global, server_info *ser return out_size; } -int auth_chain_a_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { +int auth_chain_a_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { char *plaindata = *pplaindata; - server_info *server = (server_info*)&self->server; - auth_chain_local_data *local = (auth_chain_local_data*)self->l_data; - char * out_buffer = (char*)malloc((size_t)(datalength * 2 + 4096)); - char * buffer = out_buffer; - char * data = plaindata; + server_info *server = (server_info *) &self->server; + auth_chain_local_data *local = (auth_chain_local_data *) self->l_data; + char *out_buffer = (char *) malloc((size_t) (datalength * 2 + 4096)); + char *buffer = out_buffer; + char *data = plaindata; int len = datalength; int pack_len; if (len > 0 && local->has_sent_header == 0) { int head_size = 1200; if (head_size > datalength) head_size = datalength; - pack_len = auth_chain_a_pack_auth_data((auth_chain_global_data *)self->server.g_data, &self->server, local, data, head_size, buffer); + pack_len = auth_chain_a_pack_auth_data((auth_chain_global_data *) self->server.g_data, &self->server, local, + data, head_size, buffer); buffer += pack_len; data += head_size; len -= head_size; local->has_sent_header = 1; } int unit_size = server->tcp_mss - server->overhead; - while ( len > unit_size ) { + while (len > unit_size) { pack_len = auth_chain_a_pack_data(data, unit_size, buffer, local, &self->server); buffer += pack_len; data += unit_size; @@ -346,9 +887,10 @@ int auth_chain_a_client_pre_encrypt(obfs *self, char **pplaindata, int datalengt pack_len = auth_chain_a_pack_data(data, len, buffer, local, &self->server); buffer += pack_len; } - len = (int)(buffer - out_buffer); - if ((int)*capacity < len) { - *pplaindata = (char*)realloc(*pplaindata, *capacity = (size_t)(len * 2)); + len = (int) (buffer - out_buffer); + if ((int) *capacity < len) { + *pplaindata = (char *) realloc(*pplaindata, *capacity = (size_t) (len * 2)); + // TODO check realloc failed plaindata = *pplaindata; } local->last_data_len = datalength; @@ -357,28 +899,29 @@ int auth_chain_a_client_pre_encrypt(obfs *self, char **pplaindata, int datalengt return len; } -int auth_chain_a_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { +int auth_chain_a_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { char *plaindata = *pplaindata; - auth_chain_local_data *local = (auth_chain_local_data*)self->l_data; - server_info *server = (server_info*)&self->server; - uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; + auth_chain_local_data *local = (auth_chain_local_data *) self->l_data; + server_info *server = (server_info *) &self->server; + uint8_t *recv_buffer = (uint8_t *) local->recv_buffer; if (local->recv_buffer_size + datalength > 16384) return -1; memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); local->recv_buffer_size += datalength; int key_len = local->user_key_len + 4; - uint8_t *key = (uint8_t*)malloc((size_t)key_len); + uint8_t *key = (uint8_t *) malloc((size_t) key_len); memcpy(key, local->user_key, local->user_key_len); - char * out_buffer = (char*)malloc((size_t)local->recv_buffer_size); - char * buffer = out_buffer; + char *out_buffer = (char *) malloc((size_t) local->recv_buffer_size); + char *buffer = out_buffer; char error = 0; while (local->recv_buffer_size > 4) { memintcopy_lt(key + key_len - 4, local->recv_id); - int data_len = (int)(((unsigned)(recv_buffer[1] ^ local->last_server_hash[15]) << 8) + (recv_buffer[0] ^ local->last_server_hash[14])); - int rand_len = get_server_rand_len(local, data_len); + int data_len = (int) (((unsigned) (recv_buffer[1] ^ local->last_server_hash[15]) << 8) + + (recv_buffer[0] ^ local->last_server_hash[14])); + int rand_len = get_server_rand_len(local, server, data_len); int len = rand_len + data_len; if (len >= 4096) { local->recv_buffer_size = 0; @@ -389,7 +932,7 @@ int auth_chain_a_client_post_decrypt(obfs *self, char **pplaindata, int dataleng break; char hash[16]; - ss_md5_hmac_with_key(hash, (char*)recv_buffer, len - 2, key, key_len); + ss_md5_hmac_with_key(hash, (char *) recv_buffer, len - 2, key, key_len); if (memcmp(hash, recv_buffer + len - 2, 2)) { local->recv_buffer_size = 0; error = 1; @@ -397,20 +940,17 @@ int auth_chain_a_client_post_decrypt(obfs *self, char **pplaindata, int dataleng } int pos; - if (data_len > 0 && rand_len > 0) - { + if (data_len > 0 && rand_len > 0) { pos = 2 + get_rand_start_pos(rand_len, &local->random_server); - } - else - { + } else { pos = 2; } size_t out_len; ss_decrypt_buffer(&local->cipher, local->cipher_server_ctx, - (char*)recv_buffer + pos, data_len, buffer, &out_len); + (char *) recv_buffer + pos, data_len, buffer, &out_len); if (local->recv_id == 1) { - server->tcp_mss = (uint8_t)buffer[0] | ((uint8_t)buffer[1] << 8); + server->tcp_mss = (uint8_t) buffer[0] | ((uint8_t) buffer[1] << 8); memmove(buffer, buffer + 2, out_len -= 2); } memcpy(local->last_server_hash, hash, 16); @@ -420,9 +960,9 @@ int auth_chain_a_client_post_decrypt(obfs *self, char **pplaindata, int dataleng } int len; if (error == 0) { - len = (int)(buffer - out_buffer); - if ((int)*capacity < len) { - *pplaindata = (char*)realloc(*pplaindata, *capacity = (size_t)(len * 2)); + len = (int) (buffer - out_buffer); + if ((int) *capacity < len) { + *pplaindata = (char *) realloc(*pplaindata, *capacity = (size_t) (len * 2)); plaindata = *pplaindata; } memmove(plaindata, out_buffer, len); @@ -434,44 +974,44 @@ int auth_chain_a_client_post_decrypt(obfs *self, char **pplaindata, int dataleng return len; } -int auth_chain_a_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { +int auth_chain_a_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { char *plaindata = *pplaindata; - server_info *server = (server_info*)&self->server; - auth_chain_local_data *local = (auth_chain_local_data*)self->l_data; - char out_buffer[datalength + 1024]; + server_info *server = (server_info *) &self->server; + auth_chain_local_data *local = (auth_chain_local_data *) self->l_data; + char *out_buffer = (char *)malloc(datalength + 1024); if (local->user_key == NULL) { - if(self->server.param != NULL && self->server.param[0] != 0) { + if (self->server.param != NULL && self->server.param[0] != 0) { char *param = self->server.param; char *delim = strchr(param, ':'); - if(delim != NULL) { - char uid_str[16] = {}; + if (delim != NULL) { + char uid_str[16] = ""; strncpy(uid_str, param, delim - param); char key_str[128]; strcpy(key_str, delim + 1); long uid_long = strtol(uid_str, NULL, 10); - memintcopy_lt(local->uid, (uint32_t)uid_long); + memintcopy_lt(local->uid, (uint32_t) uid_long); - local->user_key_len = (int)strlen(key_str); - local->user_key = (uint8_t*)malloc((size_t)local->user_key_len); + local->user_key_len = (int) strlen(key_str); + local->user_key = (uint8_t *) malloc((size_t) local->user_key_len); memcpy(local->user_key, key_str, local->user_key_len); } } if (local->user_key == NULL) { - rand_bytes((uint8_t *)local->uid, 4); + rand_bytes((uint8_t *) local->uid, 4); - local->user_key_len = (int)self->server.key_len; - local->user_key = (uint8_t*)malloc((size_t)local->user_key_len); + local->user_key_len = (int) self->server.key_len; + local->user_key = (uint8_t *) malloc((size_t) local->user_key_len); memcpy(local->user_key, self->server.key, local->user_key_len); } } char auth_data[3]; uint8_t hash[16]; - ss_md5_hmac_with_key((char*)hash, auth_data, 3, server->key, server->key_len); + ss_md5_hmac_with_key((char *) hash, auth_data, 3, server->key, server->key_len); int rand_len = udp_get_rand_len(&local->random_client, hash); - uint8_t rnd_data[rand_len]; - rand_bytes(rnd_data, (int)rand_len); + uint8_t *rnd_data = (uint8_t *)malloc(rand_len); + rand_bytes(rnd_data, (int) rand_len); int outlength = datalength + rand_len + 8; char password[256] = {0}; @@ -484,7 +1024,7 @@ int auth_chain_a_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datal enc_ctx_init(&local->cipher, &ctx, 1); size_t out_len; ss_encrypt_buffer(&local->cipher, &ctx, - plaindata, datalength, out_buffer, &out_len); + plaindata, datalength, out_buffer, &out_len); enc_ctx_release(&local->cipher, &ctx); enc_release(&local->cipher); } @@ -495,33 +1035,35 @@ int auth_chain_a_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datal memmove(out_buffer + datalength, rnd_data, rand_len); memmove(out_buffer + outlength - 8, auth_data, 3); memmove(out_buffer + outlength - 5, uid, 4); + free(rnd_data); - ss_md5_hmac_with_key((char*)hash, out_buffer, outlength - 1, local->user_key, local->user_key_len); + ss_md5_hmac_with_key((char *) hash, out_buffer, outlength - 1, local->user_key, local->user_key_len); memmove(out_buffer + outlength - 1, hash, 1); - if ((int)*capacity < outlength) { - *pplaindata = (char*)realloc(*pplaindata, *capacity = (size_t)(outlength * 2)); + if ((int) *capacity < outlength) { + *pplaindata = (char *) realloc(*pplaindata, *capacity = (size_t) (outlength * 2)); plaindata = *pplaindata; } memmove(plaindata, out_buffer, outlength); + free(out_buffer); return outlength; } -int auth_chain_a_client_udp_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { +int auth_chain_a_client_udp_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { if (datalength <= 8) return 0; char *plaindata = *pplaindata; - server_info *server = (server_info*)&self->server; - auth_chain_local_data *local = (auth_chain_local_data*)self->l_data; + server_info *server = (server_info *) &self->server; + auth_chain_local_data *local = (auth_chain_local_data *) self->l_data; uint8_t hash[16]; - ss_md5_hmac_with_key((char*)hash, plaindata, datalength - 1, local->user_key, local->user_key_len); + ss_md5_hmac_with_key((char *) hash, plaindata, datalength - 1, local->user_key, local->user_key_len); - if (*hash != ((uint8_t*)plaindata)[datalength - 1]) + if (*hash != ((uint8_t *) plaindata)[datalength - 1]) return 0; - ss_md5_hmac_with_key((char*)hash, plaindata + datalength - 8, 7, server->key, server->key_len); + ss_md5_hmac_with_key((char *) hash, plaindata + datalength - 8, 7, server->key, server->key_len); int rand_len = udp_get_rand_len(&local->random_server, hash); int outlength = datalength - rand_len - 8; @@ -535,8 +1077,7 @@ int auth_chain_a_client_udp_post_decrypt(obfs *self, char **pplaindata, int data enc_ctx_t ctx; enc_ctx_init(&local->cipher, &ctx, 0); size_t out_len; - ss_decrypt_buffer(&local->cipher, &ctx, - plaindata, outlength, plaindata, &out_len); + ss_decrypt_buffer(&local->cipher, &ctx, plaindata, outlength, plaindata, &out_len); enc_ctx_release(&local->cipher, &ctx); enc_release(&local->cipher); } diff --git a/src/obfs/auth_chain.h b/src/obfs/auth_chain.h index 36c66c07..d2d7ad79 100644 --- a/src/obfs/auth_chain.h +++ b/src/obfs/auth_chain.h @@ -9,16 +9,79 @@ #include "obfs.h" -void * auth_chain_a_init_data(); -obfs * auth_chain_a_new_obfs(); + +void *auth_chain_a_init_data(); + +void *auth_chain_b_init_data(); + +void *auth_chain_c_init_data(); + +void *auth_chain_d_init_data(); + +void *auth_chain_e_init_data(); + +void *auth_chain_f_init_data(); + + +obfs *auth_chain_a_new_obfs(); + +obfs *auth_chain_b_new_obfs(); + +obfs *auth_chain_c_new_obfs(); + +obfs *auth_chain_d_new_obfs(); + +obfs *auth_chain_e_new_obfs(); + +obfs *auth_chain_f_new_obfs(); + + void auth_chain_a_dispose(obfs *self); +void auth_chain_b_dispose(obfs *self); + +void auth_chain_c_dispose(obfs *self); + +void auth_chain_d_dispose(obfs *self); + +void auth_chain_e_dispose(obfs *self); + +void auth_chain_f_dispose(obfs *self); -int auth_chain_a_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -int auth_chain_a_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -int auth_chain_a_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -int auth_chain_a_client_udp_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); +void auth_chain_a_set_server_info(obfs *self, server_info *server); + +void auth_chain_b_set_server_info(obfs *self, server_info *server); + +void auth_chain_c_set_server_info(obfs *self, server_info *server); + +void auth_chain_d_set_server_info(obfs *self, server_info *server); + +void auth_chain_e_set_server_info(obfs *self, server_info *server); + +void auth_chain_f_set_server_info(obfs *self, server_info *server); + + +int auth_chain_a_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity); + +int auth_chain_a_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity); + +int auth_chain_a_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity); + +int auth_chain_a_client_udp_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity); + int auth_chain_a_get_overhead(obfs *self); + +int auth_chain_b_get_overhead(obfs *self); + +int auth_chain_c_get_overhead(obfs *self); + +int auth_chain_d_get_overhead(obfs *self); + +int auth_chain_e_get_overhead(obfs *self); + +int auth_chain_f_get_overhead(obfs *self); + + #endif // _OBFS_AUTH_CHAIN_H diff --git a/src/obfs/crc32.c b/src/obfs/crc32.c index e60d5e29..c2f31f38 100644 --- a/src/obfs/crc32.c +++ b/src/obfs/crc32.c @@ -1,4 +1,5 @@ #include +#include #include "crc32.h" static uint32_t crc32_table[256] = {0}; diff --git a/src/obfs/obfs.c b/src/obfs/obfs.c index 70f21c1f..463359fa 100644 --- a/src/obfs/obfs.c +++ b/src/obfs/obfs.c @@ -12,14 +12,14 @@ int rand_bytes(uint8_t *output, int len); #include "auth.h" #include "auth_chain.h" -#include "encrypt.h" +#include "../utils.h" -void * init_data() { +void *init_data() { return malloc(1); } -obfs * new_obfs() { - obfs * self = (obfs*)malloc(sizeof(obfs)); +obfs *new_obfs() { + obfs *self = (obfs *) malloc(sizeof(obfs)); self->l_data = NULL; return self; } @@ -40,8 +40,7 @@ void dispose_obfs(obfs *self) { free(self); } -obfs_class * new_obfs_class(char *plugin_name) -{ +obfs_class *new_obfs_class(const char *plugin_name) { if (plugin_name == NULL) return NULL; if (strcmp(plugin_name, "origin") == 0) @@ -51,7 +50,7 @@ obfs_class * new_obfs_class(char *plugin_name) init_crc32_table(); init_shift128plus(); if (strcmp(plugin_name, "http_simple") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); plugin->init_data = init_data; plugin->new_obfs = http_simple_new_obfs; plugin->get_overhead = get_overhead; @@ -64,7 +63,7 @@ obfs_class * new_obfs_class(char *plugin_name) return plugin; } else if (strcmp(plugin_name, "http_post") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); plugin->init_data = init_data; plugin->new_obfs = http_simple_new_obfs; plugin->get_overhead = get_overhead; @@ -77,7 +76,7 @@ obfs_class * new_obfs_class(char *plugin_name) return plugin; } else if (strcmp(plugin_name, "tls1.2_ticket_auth") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); plugin->init_data = tls12_ticket_auth_init_data; plugin->new_obfs = tls12_ticket_auth_new_obfs; plugin->get_overhead = tls12_ticket_auth_get_overhead; @@ -89,36 +88,36 @@ obfs_class * new_obfs_class(char *plugin_name) plugin->client_decode = tls12_ticket_auth_client_decode; return plugin; - /*} else if (strcmp(plugin_name, "verify_simple") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); - plugin->init_data = init_data; - plugin->new_obfs = verify_simple_new_obfs; - plugin->get_server_info = get_server_info; - plugin->set_server_info = set_server_info; - plugin->dispose = verify_simple_dispose; + /*} else if (strcmp(plugin_name, "verify_simple") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + plugin->init_data = init_data; + plugin->new_obfs = verify_simple_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = verify_simple_dispose; - plugin->client_pre_encrypt = verify_simple_client_pre_encrypt; - plugin->client_post_decrypt = verify_simple_client_post_decrypt; - plugin->client_udp_pre_encrypt = NULL; - plugin->client_udp_post_decrypt = NULL; + plugin->client_pre_encrypt = verify_simple_client_pre_encrypt; + plugin->client_post_decrypt = verify_simple_client_post_decrypt; + plugin->client_udp_pre_encrypt = NULL; + plugin->client_udp_post_decrypt = NULL; - return plugin; - } else if (strcmp(plugin_name, "auth_simple") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); - plugin->init_data = auth_simple_init_data; - plugin->new_obfs = auth_simple_new_obfs; - plugin->get_server_info = get_server_info; - plugin->set_server_info = set_server_info; - plugin->dispose = auth_simple_dispose; + return plugin; + } else if (strcmp(plugin_name, "auth_simple") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + plugin->init_data = auth_simple_init_data; + plugin->new_obfs = auth_simple_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = auth_simple_dispose; - plugin->client_pre_encrypt = auth_simple_client_pre_encrypt; - plugin->client_post_decrypt = auth_simple_client_post_decrypt; - plugin->client_udp_pre_encrypt = NULL; - plugin->client_udp_post_decrypt = NULL; + plugin->client_pre_encrypt = auth_simple_client_pre_encrypt; + plugin->client_post_decrypt = auth_simple_client_post_decrypt; + plugin->client_udp_pre_encrypt = NULL; + plugin->client_udp_post_decrypt = NULL; - return plugin;*/ + return plugin;*/ } else if (strcmp(plugin_name, "auth_sha1") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); plugin->init_data = auth_simple_init_data; plugin->new_obfs = auth_simple_new_obfs; plugin->get_overhead = get_overhead; @@ -133,7 +132,7 @@ obfs_class * new_obfs_class(char *plugin_name) return plugin; } else if (strcmp(plugin_name, "auth_sha1_v2") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); plugin->init_data = auth_simple_init_data; plugin->new_obfs = auth_simple_new_obfs; plugin->get_overhead = get_overhead; @@ -148,7 +147,7 @@ obfs_class * new_obfs_class(char *plugin_name) return plugin; } else if (strcmp(plugin_name, "auth_sha1_v4") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); plugin->init_data = auth_simple_init_data; plugin->new_obfs = auth_simple_new_obfs; plugin->get_overhead = get_overhead; @@ -163,9 +162,10 @@ obfs_class * new_obfs_class(char *plugin_name) return plugin; } else if (strcmp(plugin_name, "auth_aes128_md5") == 0 || strcmp(plugin_name, "auth_aes128_sha1") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); plugin->init_data = auth_simple_init_data; - plugin->new_obfs = strcmp(plugin_name, "auth_aes128_md5") == 0 ? auth_aes128_md5_new_obfs : auth_aes128_sha1_new_obfs; + plugin->new_obfs = strcmp(plugin_name, "auth_aes128_md5") == 0 ? + auth_aes128_md5_new_obfs : auth_aes128_sha1_new_obfs; plugin->get_overhead = auth_aes128_sha1_get_overhead; plugin->get_server_info = get_server_info; plugin->set_server_info = set_server_info; @@ -178,12 +178,12 @@ obfs_class * new_obfs_class(char *plugin_name) return plugin; } else if (strcmp(plugin_name, "auth_chain_a") == 0) { - obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); plugin->init_data = auth_chain_a_init_data; plugin->new_obfs = auth_chain_a_new_obfs; plugin->get_overhead = auth_chain_a_get_overhead; plugin->get_server_info = get_server_info; - plugin->set_server_info = set_server_info; + plugin->set_server_info = auth_chain_a_set_server_info; plugin->dispose = auth_chain_a_dispose; plugin->client_pre_encrypt = auth_chain_a_client_pre_encrypt; @@ -191,6 +191,81 @@ obfs_class * new_obfs_class(char *plugin_name) plugin->client_udp_pre_encrypt = auth_chain_a_client_udp_pre_encrypt; plugin->client_udp_post_decrypt = auth_chain_a_client_udp_post_decrypt; + return plugin; + } else if (strcmp(plugin_name, "auth_chain_b") == 0) { + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); + plugin->init_data = auth_chain_b_init_data; + plugin->new_obfs = auth_chain_b_new_obfs; + plugin->get_overhead = auth_chain_b_get_overhead; + plugin->get_server_info = get_server_info; + plugin->set_server_info = auth_chain_b_set_server_info; + plugin->dispose = auth_chain_b_dispose; + + plugin->client_pre_encrypt = auth_chain_a_client_pre_encrypt; + plugin->client_post_decrypt = auth_chain_a_client_post_decrypt; + plugin->client_udp_pre_encrypt = auth_chain_a_client_udp_pre_encrypt; + plugin->client_udp_post_decrypt = auth_chain_a_client_udp_post_decrypt; + + return plugin; + } else if (strcmp(plugin_name, "auth_chain_c") == 0) { + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); + plugin->init_data = auth_chain_c_init_data; + plugin->new_obfs = auth_chain_c_new_obfs; + plugin->get_overhead = auth_chain_c_get_overhead; + plugin->get_server_info = get_server_info; + plugin->set_server_info = auth_chain_c_set_server_info; + plugin->dispose = auth_chain_c_dispose; + + plugin->client_pre_encrypt = auth_chain_a_client_pre_encrypt; + plugin->client_post_decrypt = auth_chain_a_client_post_decrypt; + plugin->client_udp_pre_encrypt = auth_chain_a_client_udp_pre_encrypt; + plugin->client_udp_post_decrypt = auth_chain_a_client_udp_post_decrypt; + + return plugin; + } else if (strcmp(plugin_name, "auth_chain_d") == 0) { + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); + plugin->init_data = auth_chain_d_init_data; + plugin->new_obfs = auth_chain_d_new_obfs; + plugin->get_overhead = auth_chain_d_get_overhead; + plugin->get_server_info = get_server_info; + plugin->set_server_info = auth_chain_d_set_server_info; + plugin->dispose = auth_chain_d_dispose; + + plugin->client_pre_encrypt = auth_chain_a_client_pre_encrypt; + plugin->client_post_decrypt = auth_chain_a_client_post_decrypt; + plugin->client_udp_pre_encrypt = auth_chain_a_client_udp_pre_encrypt; + plugin->client_udp_post_decrypt = auth_chain_a_client_udp_post_decrypt; + + return plugin; + } else if (strcmp(plugin_name, "auth_chain_e") == 0) { + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); + plugin->init_data = auth_chain_e_init_data; + plugin->new_obfs = auth_chain_e_new_obfs; + plugin->get_overhead = auth_chain_e_get_overhead; + plugin->get_server_info = get_server_info; + plugin->set_server_info = auth_chain_e_set_server_info; + plugin->dispose = auth_chain_e_dispose; + + plugin->client_pre_encrypt = auth_chain_a_client_pre_encrypt; + plugin->client_post_decrypt = auth_chain_a_client_post_decrypt; + plugin->client_udp_pre_encrypt = auth_chain_a_client_udp_pre_encrypt; + plugin->client_udp_post_decrypt = auth_chain_a_client_udp_post_decrypt; + + return plugin; + } else if (strcmp(plugin_name, "auth_chain_f") == 0) { + obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); + plugin->init_data = auth_chain_f_init_data; + plugin->new_obfs = auth_chain_f_new_obfs; + plugin->get_overhead = auth_chain_f_get_overhead; + plugin->get_server_info = get_server_info; + plugin->set_server_info = auth_chain_f_set_server_info; + plugin->dispose = auth_chain_f_dispose; + + plugin->client_pre_encrypt = auth_chain_a_client_pre_encrypt; + plugin->client_post_decrypt = auth_chain_a_client_post_decrypt; + plugin->client_udp_pre_encrypt = auth_chain_a_client_udp_pre_encrypt; + plugin->client_udp_post_decrypt = auth_chain_a_client_udp_post_decrypt; + return plugin; } LOGE("Load obfs '%s' failed", plugin_name); diff --git a/src/obfs/obfs.h b/src/obfs/obfs.h index c0335dc2..8d264ee7 100644 --- a/src/obfs/obfs.h +++ b/src/obfs/obfs.h @@ -9,6 +9,7 @@ #include #include +#include "encrypt.h" #define OBFS_HMAC_SHA1_LEN 10 @@ -70,7 +71,7 @@ typedef struct { size_t* capacity); }obfs_class; -obfs_class * new_obfs_class(char *plugin_name); +obfs_class * new_obfs_class(const char *plugin_name); void free_obfs_class(obfs_class *plugin); void set_server_info(obfs *self, server_info *server); diff --git a/src/obfs/tls1.2_ticket.c b/src/obfs/tls1.2_ticket.c index d8bd952a..652150a6 100644 --- a/src/obfs/tls1.2_ticket.c +++ b/src/obfs/tls1.2_ticket.c @@ -9,7 +9,7 @@ typedef struct tls12_ticket_auth_global_data { uint8_t local_client_id[32]; -}tls12_ticket_auth_global_data; +} tls12_ticket_auth_global_data; typedef struct tls12_ticket_auth_local_data { int handshake_status; @@ -17,9 +17,9 @@ typedef struct tls12_ticket_auth_local_data { int send_buffer_size; char *recv_buffer; int recv_buffer_size; -}tls12_ticket_auth_local_data; +} tls12_ticket_auth_local_data; -void tls12_ticket_auth_local_data_init(tls12_ticket_auth_local_data* local) { +void tls12_ticket_auth_local_data_init(tls12_ticket_auth_local_data *local) { local->handshake_status = 0; local->send_buffer = malloc(0); local->send_buffer_size = 0; @@ -27,16 +27,17 @@ void tls12_ticket_auth_local_data_init(tls12_ticket_auth_local_data* local) { local->recv_buffer_size = 0; } -void * tls12_ticket_auth_init_data() { - tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)malloc(sizeof(tls12_ticket_auth_global_data)); +void *tls12_ticket_auth_init_data() { + tls12_ticket_auth_global_data *global = + (tls12_ticket_auth_global_data *) malloc(sizeof(tls12_ticket_auth_global_data)); rand_bytes(global->local_client_id, 32); return global; } -obfs * tls12_ticket_auth_new_obfs() { - obfs * self = new_obfs(); +obfs *tls12_ticket_auth_new_obfs() { + obfs *self = new_obfs(); self->l_data = malloc(sizeof(tls12_ticket_auth_local_data)); - tls12_ticket_auth_local_data_init((tls12_ticket_auth_local_data*)self->l_data); + tls12_ticket_auth_local_data_init((tls12_ticket_auth_local_data *) self->l_data); return self; } @@ -45,7 +46,7 @@ int tls12_ticket_auth_get_overhead(obfs *self) { } void tls12_ticket_auth_dispose(obfs *self) { - tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; + tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data *) self->l_data; if (local->send_buffer != NULL) { free(local->send_buffer); local->send_buffer = NULL; @@ -61,17 +62,17 @@ void tls12_ticket_auth_dispose(obfs *self) { int tls12_ticket_pack_auth_data(tls12_ticket_auth_global_data *global, server_info *server, char *outdata) { int out_size = 32; time_t t = time(NULL); - outdata[0] = (char)(t >> 24); - outdata[1] = (char)(t >> 16); - outdata[2] = (char)(t >> 8); - outdata[3] = (char)t; - rand_bytes((uint8_t*)outdata + 4, 18); + outdata[0] = (char) (t >> 24); + outdata[1] = (char) (t >> 16); + outdata[2] = (char) (t >> 8); + outdata[3] = (char) t; + rand_bytes((uint8_t *) outdata + 4, 18); - uint8_t *key = (uint8_t*)malloc(server->key_len + 32); + uint8_t *key = (uint8_t *) malloc(server->key_len + 32); char hash[SHA1_BYTES]; memcpy(key, server->key, server->key_len); memcpy(key + server->key_len, global->local_client_id, 32); - ss_sha1_hmac_with_key(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, key, (int)(server->key_len + 32)); + ss_sha1_hmac_with_key(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, key, (int) (server->key_len + 32)); free(key); memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN); return out_size; @@ -81,32 +82,32 @@ void tls12_ticket_auth_pack_data(char *encryptdata, int start, int len, char *ou out_buffer[outlength] = 0x17; out_buffer[outlength + 1] = 0x3; out_buffer[outlength + 2] = 0x3; - out_buffer[outlength + 3] = (char)(len >> 8); - out_buffer[outlength + 4] = (char)len; + out_buffer[outlength + 3] = (char) (len >> 8); + out_buffer[outlength + 4] = (char) len; memcpy(out_buffer + outlength + 5, encryptdata + start, len); } -int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { +int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t *capacity) { char *encryptdata = *pencryptdata; - tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; - tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; - char * out_buffer = NULL; + tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data *) self->l_data; + tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data *) self->server.g_data; + char *out_buffer = NULL; if (local->handshake_status == 8) { if (datalength < 1024) { - if ((int)*capacity < datalength + 5) { - *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (size_t)((datalength + 5) * 2)); + if ((int) *capacity < datalength + 5) { + *pencryptdata = (char *) realloc(*pencryptdata, *capacity = (size_t) ((datalength + 5) * 2)); encryptdata = *pencryptdata; } memmove(encryptdata + 5, encryptdata, datalength); encryptdata[0] = 0x17; encryptdata[1] = 0x3; encryptdata[2] = 0x3; - encryptdata[3] = (char)(datalength >> 8); - encryptdata[4] = (char)datalength; + encryptdata[3] = (char) (datalength >> 8); + encryptdata[4] = (char) datalength; return datalength + 5; } else { - out_buffer = (char*)malloc((size_t)(datalength + 4096)); + out_buffer = (char *) malloc((size_t) (datalength + 4096)); int start = 0; int outlength = 0; int len; @@ -123,8 +124,8 @@ int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalen tls12_ticket_auth_pack_data(encryptdata, start, len, out_buffer, outlength); outlength += len + 5; } - if ((int)*capacity < outlength) { - *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (size_t)(outlength * 2)); + if ((int) *capacity < outlength) { + *pencryptdata = (char *) realloc(*pencryptdata, *capacity = (size_t) (outlength * 2)); encryptdata = *pencryptdata; } memcpy(encryptdata, out_buffer, outlength); @@ -135,11 +136,12 @@ int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalen if (datalength > 0) { if (datalength < 1024) { - local->send_buffer = (char*)realloc(local->send_buffer, (size_t)(local->send_buffer_size + datalength + 5)); + local->send_buffer = (char *) realloc(local->send_buffer, + (size_t) (local->send_buffer_size + datalength + 5)); tls12_ticket_auth_pack_data(encryptdata, 0, datalength, local->send_buffer, local->send_buffer_size); local->send_buffer_size += datalength + 5; } else { - out_buffer = (char*)malloc((size_t)(datalength + 4096)); + out_buffer = (char *) malloc((size_t) (datalength + 4096)); int start = 0; int outlength = 0; int len; @@ -156,11 +158,11 @@ int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalen tls12_ticket_auth_pack_data(encryptdata, start, len, out_buffer, outlength); outlength += len + 5; } - if ((int)*capacity < outlength) { - *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (size_t)(outlength * 2)); + if ((int) *capacity < outlength) { + *pencryptdata = (char *) realloc(*pencryptdata, *capacity = (size_t) (outlength * 2)); encryptdata = *pencryptdata; } - local->send_buffer = (char*)realloc(local->send_buffer, (size_t)(local->send_buffer_size + outlength)); + local->send_buffer = (char *) realloc(local->send_buffer, (size_t) (local->send_buffer_size + outlength)); memcpy(local->send_buffer + local->send_buffer_size, out_buffer, outlength); local->send_buffer_size += outlength; free(out_buffer); @@ -168,27 +170,32 @@ int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalen } if (local->handshake_status == 0) { -#define CSTR_DECL(name, len, str) const char* name = str; const int len = sizeof(str) - 1; - CSTR_DECL(tls_data0, tls_data0_len, "\x00\x1c\xc0\x2b\xc0\x2f\xcc\xa9\xcc\xa8\xcc\x14\xcc\x13\xc0\x0a\xc0\x14\xc0\x09\xc0\x13\x00\x9c\x00\x35\x00\x2f\x00\x0a\x01\x00" - ); - CSTR_DECL(tls_data1, tls_data1_len, "\xff\x01\x00\x01\x00" - ); - CSTR_DECL(tls_data2, tls_data2_len, "\x00\x17\x00\x00\x00\x23\x00\xd0"); - CSTR_DECL(tls_data3, tls_data3_len, "\x00\x0d\x00\x16\x00\x14\x06\x01\x06\x03\x05\x01\x05\x03\x04\x01\x04\x03\x03\x01\x03\x03\x02\x01\x02\x03\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x12\x00\x00\x75\x50\x00\x00\x00\x0b\x00\x02\x01\x00\x00\x0a\x00\x06\x00\x04\x00\x17\x00\x18" - //"00150066000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" // padding - ); +#define CSTR_DECL(name, len, str) const char* name = str; const int (len) = sizeof(str) - 1; + CSTR_DECL(tls_data0, tls_data0_len, + "\x00\x1c\xc0\x2b\xc0\x2f\xcc\xa9\xcc\xa8\xcc\x14\xcc\x13\xc0\x0a\xc0\x14\xc0\x09\xc0\x13\x00\x9c\x00\x35\x00\x2f\x00\x0a\x01\x00" + ); + CSTR_DECL(tls_data1, tls_data1_len, + "\xff\x01\x00\x01\x00" + ); + CSTR_DECL(tls_data2, tls_data2_len, + "\x00\x17\x00\x00\x00\x23\x00\xd0" + ); + CSTR_DECL(tls_data3, tls_data3_len, + "\x00\x0d\x00\x16\x00\x14\x06\x01\x06\x03\x05\x01\x05\x03\x04\x01\x04\x03\x03\x01\x03\x03\x02\x01\x02\x03\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x12\x00\x00\x75\x50\x00\x00\x00\x0b\x00\x02\x01\x00\x00\x0a\x00\x06\x00\x04\x00\x17\x00\x18" + //"00150066000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" // padding + ); uint8_t tls_data[2048]; int tls_data_len = 0; memcpy(tls_data, tls_data1, tls_data1_len); tls_data_len += tls_data1_len; char hosts[1024]; - char * phost[128]; + char *phost[128]; int host_num = 0; int pos; char sni[256] = {0}; - char* param = NULL; + char *param = NULL; if (self->server.param && strlen(self->server.param) > 0) param = self->server.param; else @@ -201,84 +208,94 @@ int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalen hosts[pos] = 0; } } - host_num = (int)(xorshift128plus() % (uint64_t)host_num); + host_num = (int) (xorshift128plus() % (uint64_t) host_num); snprintf(sni, sizeof sni, "%s", phost[host_num]); - int sni_len = (int)strlen(sni); + int sni_len = (int) strlen(sni); if (sni_len > 0 && sni[sni_len - 1] >= '0' && sni[sni_len - 1] <= '9') sni_len = 0; tls_data[tls_data_len] = '\0'; tls_data[tls_data_len + 1] = '\0'; - tls_data[tls_data_len + 2] = (uint8_t)((sni_len + 5) >> 8); - tls_data[tls_data_len + 3] = (uint8_t)(sni_len + 5); - tls_data[tls_data_len + 4] = (uint8_t)((sni_len + 3) >> 8); - tls_data[tls_data_len + 5] = (uint8_t)(sni_len + 3); + tls_data[tls_data_len + 2] = (uint8_t) ((sni_len + 5) >> 8); + tls_data[tls_data_len + 3] = (uint8_t) (sni_len + 5); + tls_data[tls_data_len + 4] = (uint8_t) ((sni_len + 3) >> 8); + tls_data[tls_data_len + 5] = (uint8_t) (sni_len + 3); tls_data[tls_data_len + 6] = '\0'; - tls_data[tls_data_len + 7] = (uint8_t)(sni_len >> 8); - tls_data[tls_data_len + 8] = (uint8_t)sni_len; + tls_data[tls_data_len + 7] = (uint8_t) (sni_len >> 8); + tls_data[tls_data_len + 8] = (uint8_t) sni_len; memcpy(tls_data + tls_data_len + 9, sni, sni_len); tls_data_len += 9 + sni_len; memcpy(tls_data + tls_data_len, tls_data2, tls_data2_len); tls_data_len += tls_data2_len; - unsigned ticket_len = (unsigned)(xorshift128plus() % (uint64_t)164) * 2 + 64; - tls_data[tls_data_len - 1] = (uint8_t)(ticket_len & 0xff); - tls_data[tls_data_len - 2] = (uint8_t)(ticket_len >> 8); + unsigned ticket_len = (unsigned) (xorshift128plus() % (uint64_t) 164) * 2 + 64; + tls_data[tls_data_len - 1] = (uint8_t) (ticket_len & 0xff); + tls_data[tls_data_len - 2] = (uint8_t) (ticket_len >> 8); rand_bytes(tls_data + tls_data_len, ticket_len); tls_data_len += ticket_len; memcpy(tls_data + tls_data_len, tls_data3, tls_data3_len); tls_data_len += tls_data3_len; datalength = 11 + 32 + 1 + 32 + tls_data0_len + 2 + tls_data_len; - out_buffer = (char*)malloc((size_t)datalength); + out_buffer = (char *) malloc((size_t) datalength); char *pdata = out_buffer + datalength - tls_data_len; int len = tls_data_len; memcpy(pdata, tls_data, tls_data_len); - pdata[-1] = (char)tls_data_len; - pdata[-2] = (char)(tls_data_len >> 8); - pdata -= 2; len += 2; + pdata[-1] = (char) tls_data_len; + pdata[-2] = (char) (tls_data_len >> 8); + pdata -= 2; + len += 2; memcpy(pdata - tls_data0_len, tls_data0, tls_data0_len); - pdata -= tls_data0_len; len += tls_data0_len; + pdata -= tls_data0_len; + len += tls_data0_len; memcpy(pdata - 32, global->local_client_id, 32); - pdata -= 32; len += 32; + pdata -= 32; + len += 32; pdata[-1] = 0x20; - pdata -= 1; len += 1; + pdata -= 1; + len += 1; tls12_ticket_pack_auth_data(global, &self->server, pdata - 32); - pdata -= 32; len += 32; + pdata -= 32; + len += 32; pdata[-1] = 0x3; pdata[-2] = 0x3; // tls version - pdata -= 2; len += 2; - pdata[-1] = (char)len; - pdata[-2] = (char)(len >> 8); + pdata -= 2; + len += 2; + pdata[-1] = (char) len; + pdata[-2] = (char) (len >> 8); pdata[-3] = 0; pdata[-4] = 1; - pdata -= 4; len += 4; + pdata -= 4; + len += 4; - pdata[-1] = (char)len; - pdata[-2] = (char)(len >> 8); - pdata -= 2; len += 2; + pdata[-1] = (char) len; + pdata[-2] = (char) (len >> 8); + pdata -= 2; + len += 2; pdata[-1] = 0x1; pdata[-2] = 0x3; // tls version - pdata -= 2; len += 2; + pdata -= 2; + len += 2; pdata[-1] = 0x16; // tls handshake - pdata -= 1; len += 1; + pdata -= 1; + len += 1; local->handshake_status = 1; } else if (datalength == 0) { datalength = local->send_buffer_size + 43; - out_buffer = (char*)malloc((size_t)datalength); + out_buffer = (char *) malloc((size_t) datalength); char *pdata = out_buffer; memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6); pdata += 6; memcpy(pdata, "\x16\x03\x03\x00\x20", 5); pdata += 5; - rand_bytes((uint8_t*)pdata, 22); + rand_bytes((uint8_t *) pdata, 22); pdata += 22; - uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); + uint8_t *key = (uint8_t *) malloc(self->server.key_len + 32); char hash[SHA1_BYTES]; memcpy(key, self->server.key, self->server.key_len); memcpy(key + self->server.key_len, global->local_client_id, 32); - ss_sha1_hmac_with_key(hash, out_buffer, (int)(pdata - out_buffer), key, (int)(self->server.key_len + 32)); + ss_sha1_hmac_with_key(hash, out_buffer, (int) (pdata - out_buffer), key, (int) (self->server.key_len + 32)); free(key); memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN); @@ -291,8 +308,8 @@ int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalen } else { return 0; } - if ((int)*capacity < datalength) { - *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (size_t)(datalength * 2)); + if ((int) *capacity < datalength) { + *pencryptdata = (char *) realloc(*pencryptdata, *capacity = (size_t) (datalength * 2)); encryptdata = *pencryptdata; } memmove(encryptdata, out_buffer, datalength); @@ -300,25 +317,26 @@ int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalen return datalength; } -int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) { +int +tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t *capacity, int *needsendback) { char *encryptdata = *pencryptdata; - tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; - tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; + tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data *) self->l_data; + tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data *) self->server.g_data; *needsendback = 0; if (local->handshake_status == 8) { local->recv_buffer_size += datalength; - local->recv_buffer = (char*)realloc(local->recv_buffer, (size_t)local->recv_buffer_size); + local->recv_buffer = (char *) realloc(local->recv_buffer, (size_t) local->recv_buffer_size); memcpy(local->recv_buffer + local->recv_buffer_size - datalength, encryptdata, datalength); datalength = 0; while (local->recv_buffer_size > 5) { if (local->recv_buffer[0] != 0x17) return -1; - int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4]; + int size = ((int) (unsigned char) local->recv_buffer[3] << 8) + (unsigned char) local->recv_buffer[4]; if (size + 5 > local->recv_buffer_size) break; - if ((int)*capacity < datalength + size) { - *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (size_t)((datalength + size) * 2)); + if ((int) *capacity < datalength + size) { + *pencryptdata = (char *) realloc(*pencryptdata, *capacity = (size_t) ((datalength + size) * 2)); encryptdata = *pencryptdata; } memcpy(encryptdata + datalength, local->recv_buffer + 5, size); @@ -332,11 +350,11 @@ int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalen return -1; } - uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); + uint8_t *key = (uint8_t *) malloc(self->server.key_len + 32); char hash[SHA1_BYTES]; memcpy(key, self->server.key, self->server.key_len); memcpy(key + self->server.key_len, global->local_client_id, 32); - ss_sha1_hmac_with_key(hash, encryptdata + 11, 22, key, (int)self->server.key_len + 32); + ss_sha1_hmac_with_key(hash, encryptdata + 11, 22, key, (int) self->server.key_len + 32); free(key); if (memcmp(encryptdata + 33, hash, OBFS_HMAC_SHA1_LEN)) { diff --git a/src/redir.c b/src/redir.c index 4345a362..feafd5e7 100644 --- a/src/redir.c +++ b/src/redir.c @@ -144,6 +144,11 @@ create_and_bind(const char *addr, const char *port) return -1; } + if (result == NULL) { + LOGE("Could not bind"); + return -1; + } + for (rp = result; rp != NULL; rp = rp->ai_next) { listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (listen_sock == -1) { @@ -169,11 +174,7 @@ create_and_bind(const char *addr, const char *port) } close(listen_sock); - } - - if (rp == NULL) { - LOGE("Could not bind"); - return -1; + listen_sock = -1; } freeaddrinfo(result); diff --git a/src/udprelay.c b/src/udprelay.c index ae0ff0e3..71320227 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -432,6 +432,11 @@ create_server_socket(const char *host, const char *port) } } + if (result == NULL) { + LOGE("[udp] cannot bind"); + return -1; + } + for (/*rp = result*/; rp != NULL; rp = rp->ai_next) { server_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (server_sock == -1) { @@ -483,11 +488,7 @@ create_server_socket(const char *host, const char *port) } close(server_sock); - } - - if (rp == NULL) { - LOGE("[udp] cannot bind"); - return -1; + server_sock = -1; } freeaddrinfo(result);