diff --git a/assets/shadowsocks b/assets/shadowsocks index 557abd4b..9e9eb45f 100755 Binary files a/assets/shadowsocks and b/assets/shadowsocks differ diff --git a/jni/shadowsocks/encrypt.c b/jni/shadowsocks/encrypt.c index 788c4a0f..c104a95a 100755 --- a/jni/shadowsocks/encrypt.c +++ b/jni/shadowsocks/encrypt.c @@ -111,11 +111,11 @@ static void mergesort(uint8_t array[], int length) merge(left, llength, right, middle); } -void encrypt(char *buf, int len) { - if (_method == RC4_ENC) { +void encrypt(char *buf, int len, EVP_CIPHER_CTX *ctx) { + if (ctx != NULL) { int outlen; unsigned char mybuf[BUF_SIZE]; - EVP_CipherUpdate(&ctx, mybuf, &outlen, (unsigned char*)buf, len); + EVP_CipherUpdate(ctx, mybuf, &outlen, (unsigned char*)buf, len); memcpy(buf, mybuf, len); } else { char *end = buf + len; @@ -126,11 +126,11 @@ void encrypt(char *buf, int len) { } } -void decrypt(char *buf, int len) { - if (_method == RC4_ENC) { +void decrypt(char *buf, int len, EVP_CIPHER_CTX *ctx) { + if (ctx != NULL) { int outlen; unsigned char mybuf[BUF_SIZE]; - EVP_CipherUpdate(&ctx, mybuf, &outlen, (unsigned char*) buf, len); + EVP_CipherUpdate(ctx, mybuf, &outlen, (unsigned char*) buf, len); memcpy(buf, mybuf, len); } else { char *end = buf + len; @@ -141,51 +141,36 @@ void decrypt(char *buf, int len) { } } -int send_encrypt(int sock, char *buf, int len, int flags) { - char mybuf[BUF_SIZE]; - memcpy(mybuf, buf, len); - encrypt(mybuf, len); - return send(sock, mybuf, len, flags); +void enc_ctx_init(EVP_CIPHER_CTX *ctx, const char *pass, int enc) { + unsigned char key[EVP_MAX_KEY_LENGTH]; + unsigned char iv[EVP_MAX_IV_LENGTH]; + int key_len = EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, (unsigned char*) pass, + strlen(pass), 1, key, iv); + EVP_CIPHER_CTX_init(ctx); + EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, enc); + if (!EVP_CIPHER_CTX_set_key_length(ctx, key_len)) { + LOGE("Invalid key length: %d", key_len); + EVP_CIPHER_CTX_cleanup(ctx); + exit(EXIT_FAILURE); + } + EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc); } -int recv_decrypt(int sock, char *buf, int len, int flags) { - char mybuf[BUF_SIZE]; - int result = recv(sock, mybuf, len, flags); - memcpy(buf, mybuf, len); - decrypt(buf, len); - return result; -} +void get_table(const char *pass) { + uint8_t *table = encrypt_table; + uint8_t *tmp_hash = MD5((unsigned char *) pass, strlen(pass), NULL); + _a = htole64(*(uint64_t *) tmp_hash); + uint32_t i; -void get_table(const char* pass) { - if (_method == RC4_ENC) { - unsigned char key[EVP_MAX_KEY_LENGTH]; - unsigned char iv[EVP_MAX_IV_LENGTH]; - int key_len = EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, (unsigned char*) pass, - strlen(pass), 1, key, iv); - EVP_CIPHER_CTX_init(&ctx); - EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1); - if (!EVP_CIPHER_CTX_set_key_length(&ctx, key_len)) { - LOGE("Invalid key length: %d", key_len); - EVP_CIPHER_CTX_cleanup(&ctx); - exit(EXIT_FAILURE); - } - EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, 1); - } else { - uint8_t *table = encrypt_table; - uint8_t *tmp_hash = MD5((unsigned char *) pass, strlen(pass), NULL); - _a = htole64(*(uint64_t *) tmp_hash); - uint32_t i; - - for(i = 0; i < 256; ++i) { - table[i] = i; - } - for(i = 1; i < 1024; ++i) { - _i = i; - mergesort(table, 256); - } - for(i = 0; i < 256; ++i) { - // gen decrypt table from encrypt table - decrypt_table[encrypt_table[i]] = i; - } + for(i = 0; i < 256; ++i) { + table[i] = i; + } + for(i = 1; i < 1024; ++i) { + _i = i; + mergesort(table, 256); + } + for(i = 0; i < 256; ++i) { + // gen decrypt table from encrypt table + decrypt_table[encrypt_table[i]] = i; } } diff --git a/jni/shadowsocks/encrypt.h b/jni/shadowsocks/encrypt.h index 84fa8880..a17cb6a1 100755 --- a/jni/shadowsocks/encrypt.h +++ b/jni/shadowsocks/encrypt.h @@ -10,18 +10,16 @@ #define BUF_SIZE 4096 -#define TABLE_ENC 0 -#define RC4_ENC 1 +#define TABLE 0 +#define RC4 1 unsigned char encrypt_table[256]; unsigned char decrypt_table[256]; -EVP_CIPHER_CTX ctx; void get_table(const char* key); -void encrypt(char *buf, int len); -void decrypt(char *buf, int len); -int send_encrypt(int sock, char *buf, int len, int flags); -int recv_decrypt(int sock, char *buf, int len, int flags); +void encrypt(char *buf, int len, EVP_CIPHER_CTX *ctx); +void decrypt(char *buf, int len, EVP_CIPHER_CTX *ctx); +void enc_ctx_init(EVP_CIPHER_CTX *ctx, const char *pass, int enc); unsigned int _i; unsigned long long _a; diff --git a/jni/shadowsocks/local.c b/jni/shadowsocks/local.c index d523273b..4e46fb08 100644 --- a/jni/shadowsocks/local.c +++ b/jni/shadowsocks/local.c @@ -28,6 +28,7 @@ static char *_server; static char *_remote_port; static int _timeout; +static char *_key; int setnonblocking(int fd) { int flags; @@ -123,7 +124,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { // local socks5 server if (server->stage == 5) { - encrypt(remote->buf, r); + encrypt(remote->buf, r, server->e_ctx); int w = send(remote->fd, remote->buf, r, 0); if(w == -1) { if (errno == EAGAIN) { @@ -186,7 +187,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { size_t in_addr_len = sizeof(struct in_addr); memcpy(addr_to_send + addr_len, server->buf + 4, in_addr_len + 2); addr_len += in_addr_len + 2; - addr_to_send[addr_len] = 0; } else if (request->atyp == 3) { // Domain name @@ -198,7 +198,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { // get port addr_to_send[addr_len++] = *(unsigned char *)(server->buf + 4 + 1 + name_len); addr_to_send[addr_len++] = *(unsigned char *)(server->buf + 4 + 1 + name_len + 1); - addr_to_send[addr_len] = 0; } else { LOGE("unsupported addrtype: %d\n", request->atyp); close_and_free_remote(EV_A_ remote); @@ -206,7 +205,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { return; } - send_encrypt(remote->fd, addr_to_send, addr_len, 0); + encrypt(addr_to_send, addr_len, server->e_ctx); + send(remote->fd, addr_to_send, addr_len, 0); // Fake reply struct socks5_response response; @@ -233,7 +233,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { } server->stage = 5; - } } } @@ -333,7 +332,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { return; } } - decrypt(server->buf, r); + decrypt(server->buf, r, server->d_ctx); int w = send(server->fd, server->buf, r, MSG_NOSIGNAL); if(w == -1) { if (errno == EAGAIN) { @@ -482,6 +481,15 @@ struct server* new_server(int fd) { server->send_ctx->server = server; server->send_ctx->connected = 0; server->stage = 0; + if (_method == RC4) { + server->e_ctx = malloc(sizeof(EVP_CIPHER_CTX)); + server->d_ctx = malloc(sizeof(EVP_CIPHER_CTX)); + enc_ctx_init(server->e_ctx, _key, 1); + enc_ctx_init(server->d_ctx, _key, 0); + } else { + server->e_ctx = NULL; + server->d_ctx = NULL; + } return server; } void free_server(struct server *server) { @@ -489,6 +497,12 @@ void free_server(struct server *server) { if (server->remote != NULL) { server->remote->server = NULL; } + if (_method == RC4) { + EVP_CIPHER_CTX_cleanup(server->e_ctx); + EVP_CIPHER_CTX_cleanup(server->d_ctx); + free(server->e_ctx); + free(server->d_ctx); + } free(server->recv_ctx); free(server->send_ctx); free(server); @@ -603,12 +617,6 @@ int main (int argc, char **argv) exit(EXIT_FAILURE); } - if (method != NULL) { - if (strcmp(method, "rc4") == 0) { - _method = RC4_ENC; - } - } - if (f_flags) { /* Our process ID and Session ID */ @@ -658,12 +666,22 @@ int main (int argc, char **argv) fclose(file); } + // init global variables _server = strdup(server); _remote_port = strdup(remote_port); _timeout = atoi(timeout); + _key = key; + _method = TABLE; + if (method != NULL) { + if (strcmp(method, "rc4") == 0) { + _method = RC4; + } + } LOGD("calculating ciphers %d", _method); - get_table(key); + if (_method != RC4) { + get_table(key); + } int listenfd; listenfd = create_and_bind(port); diff --git a/jni/shadowsocks/local.h b/jni/shadowsocks/local.h index 60a94e6e..b2aed3bc 100644 --- a/jni/shadowsocks/local.h +++ b/jni/shadowsocks/local.h @@ -21,6 +21,8 @@ struct server { char buf[BUF_SIZE]; // server send from, remote recv into char stage; int buf_len; + EVP_CIPHER_CTX *e_ctx; + EVP_CIPHER_CTX *d_ctx; struct server_ctx *recv_ctx; struct server_ctx *send_ctx; struct remote *remote; diff --git a/libs/armeabi/shadowsocks b/libs/armeabi/shadowsocks index 557abd4b..9e9eb45f 100755 Binary files a/libs/armeabi/shadowsocks and b/libs/armeabi/shadowsocks differ diff --git a/src/com/github/shadowsocks/Shadowsocks.java b/src/com/github/shadowsocks/Shadowsocks.java index adfd3921..829f9046 100755 --- a/src/com/github/shadowsocks/Shadowsocks.java +++ b/src/com/github/shadowsocks/Shadowsocks.java @@ -405,31 +405,35 @@ public class Shadowsocks extends PreferenceActivity implements } } - - if (key.equals("remotePort")) - if (settings.getString("remotePort", "").equals("")) + if (key.equals("remotePort")) { + if (settings.getString("remotePort", "").equals("")) { remotePortText.setSummary(getString(R.string.remote_port_summary)); - else + } else { remotePortText.setSummary(settings.getString("remotePort", "")); - else if (key.equals("port")) - if (settings.getString("port", "").equals("")) + } + } else if (key.equals("port")) { + if (settings.getString("port", "").equals("")) { portText.setSummary(getString(R.string.port_summary)); - else + } else { portText.setSummary(settings.getString("port", "")); - else if (key.equals("sitekey")) - if (settings.getString("sitekey", "").equals("")) + } + } else if (key.equals("sitekey")) { + if (settings.getString("sitekey", "").equals("")) { sitekeyText.setSummary(getString(R.string.sitekey_summary)); - else + } else { sitekeyText.setSummary(settings.getString("sitekey", "")); - else if (key.equals("encMethod")) - if (!settings.getString("encMethod", "").equals("")) + } + } else if (key.equals("encMethod")) { + if (!settings.getString("encMethod", "").equals("")) { encMethodText.setSummary(settings.getString("encMethod", "")); - else if (key.equals("proxy")) + } + } else if (key.equals("proxy")) { if (settings.getString("proxy", "").equals("")) { proxyText.setSummary(getString(R.string.proxy_summary)); } else { proxyText.setSummary(settings.getString("proxy", "")); } + } } @Override