Commit b16ac605 authored by Max Lv's avatar Max Lv

rc4 works now, fix #3

parent b11f386b
No preview for this file type
...@@ -111,11 +111,11 @@ static void mergesort(uint8_t array[], int length) ...@@ -111,11 +111,11 @@ static void mergesort(uint8_t array[], int length)
merge(left, llength, right, middle); merge(left, llength, right, middle);
} }
void encrypt(char *buf, int len) { void encrypt(char *buf, int len, EVP_CIPHER_CTX *ctx) {
if (_method == RC4_ENC) { if (ctx != NULL) {
int outlen; int outlen;
unsigned char mybuf[BUF_SIZE]; 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); memcpy(buf, mybuf, len);
} else { } else {
char *end = buf + len; char *end = buf + len;
...@@ -126,11 +126,11 @@ void encrypt(char *buf, int len) { ...@@ -126,11 +126,11 @@ void encrypt(char *buf, int len) {
} }
} }
void decrypt(char *buf, int len) { void decrypt(char *buf, int len, EVP_CIPHER_CTX *ctx) {
if (_method == RC4_ENC) { if (ctx != NULL) {
int outlen; int outlen;
unsigned char mybuf[BUF_SIZE]; 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); memcpy(buf, mybuf, len);
} else { } else {
char *end = buf + len; char *end = buf + len;
...@@ -141,51 +141,36 @@ void decrypt(char *buf, int len) { ...@@ -141,51 +141,36 @@ void decrypt(char *buf, int len) {
} }
} }
int send_encrypt(int sock, char *buf, int len, int flags) { void enc_ctx_init(EVP_CIPHER_CTX *ctx, const char *pass, int enc) {
char mybuf[BUF_SIZE]; unsigned char key[EVP_MAX_KEY_LENGTH];
memcpy(mybuf, buf, len); unsigned char iv[EVP_MAX_IV_LENGTH];
encrypt(mybuf, len); int key_len = EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, (unsigned char*) pass,
return send(sock, mybuf, len, flags); strlen(pass), 1, key, iv);
} EVP_CIPHER_CTX_init(ctx);
EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, enc);
int recv_decrypt(int sock, char *buf, int len, int flags) { if (!EVP_CIPHER_CTX_set_key_length(ctx, key_len)) {
char mybuf[BUF_SIZE]; LOGE("Invalid key length: %d", key_len);
int result = recv(sock, mybuf, len, flags); EVP_CIPHER_CTX_cleanup(ctx);
memcpy(buf, mybuf, len); exit(EXIT_FAILURE);
decrypt(buf, len); }
return result; EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc);
} }
void get_table(const char* pass) { void get_table(const char *pass) {
if (_method == RC4_ENC) { uint8_t *table = encrypt_table;
unsigned char key[EVP_MAX_KEY_LENGTH]; uint8_t *tmp_hash = MD5((unsigned char *) pass, strlen(pass), NULL);
unsigned char iv[EVP_MAX_IV_LENGTH]; _a = htole64(*(uint64_t *) tmp_hash);
int key_len = EVP_BytesToKey(EVP_rc4(), EVP_md5(), NULL, (unsigned char*) pass, uint32_t i;
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) { for(i = 0; i < 256; ++i) {
table[i] = i; table[i] = i;
} }
for(i = 1; i < 1024; ++i) { for(i = 1; i < 1024; ++i) {
_i = i; _i = i;
mergesort(table, 256); mergesort(table, 256);
} }
for(i = 0; i < 256; ++i) { for(i = 0; i < 256; ++i) {
// gen decrypt table from encrypt table // gen decrypt table from encrypt table
decrypt_table[encrypt_table[i]] = i; decrypt_table[encrypt_table[i]] = i;
}
} }
} }
...@@ -10,18 +10,16 @@ ...@@ -10,18 +10,16 @@
#define BUF_SIZE 4096 #define BUF_SIZE 4096
#define TABLE_ENC 0 #define TABLE 0
#define RC4_ENC 1 #define RC4 1
unsigned char encrypt_table[256]; unsigned char encrypt_table[256];
unsigned char decrypt_table[256]; unsigned char decrypt_table[256];
EVP_CIPHER_CTX ctx;
void get_table(const char* key); void get_table(const char* key);
void encrypt(char *buf, int len); void encrypt(char *buf, int len, EVP_CIPHER_CTX *ctx);
void decrypt(char *buf, int len); void decrypt(char *buf, int len, EVP_CIPHER_CTX *ctx);
int send_encrypt(int sock, char *buf, int len, int flags); void enc_ctx_init(EVP_CIPHER_CTX *ctx, const char *pass, int enc);
int recv_decrypt(int sock, char *buf, int len, int flags);
unsigned int _i; unsigned int _i;
unsigned long long _a; unsigned long long _a;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
static char *_server; static char *_server;
static char *_remote_port; static char *_remote_port;
static int _timeout; static int _timeout;
static char *_key;
int setnonblocking(int fd) { int setnonblocking(int fd) {
int flags; int flags;
...@@ -123,7 +124,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { ...@@ -123,7 +124,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
// local socks5 server // local socks5 server
if (server->stage == 5) { if (server->stage == 5) {
encrypt(remote->buf, r); encrypt(remote->buf, r, server->e_ctx);
int w = send(remote->fd, remote->buf, r, 0); int w = send(remote->fd, remote->buf, r, 0);
if(w == -1) { if(w == -1) {
if (errno == EAGAIN) { if (errno == EAGAIN) {
...@@ -186,7 +187,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { ...@@ -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); size_t in_addr_len = sizeof(struct in_addr);
memcpy(addr_to_send + addr_len, server->buf + 4, in_addr_len + 2); memcpy(addr_to_send + addr_len, server->buf + 4, in_addr_len + 2);
addr_len += in_addr_len + 2; addr_len += in_addr_len + 2;
addr_to_send[addr_len] = 0;
} else if (request->atyp == 3) { } else if (request->atyp == 3) {
// Domain name // Domain name
...@@ -198,7 +198,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { ...@@ -198,7 +198,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
// get port // 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);
addr_to_send[addr_len++] = *(unsigned char *)(server->buf + 4 + 1 + name_len + 1); addr_to_send[addr_len++] = *(unsigned char *)(server->buf + 4 + 1 + name_len + 1);
addr_to_send[addr_len] = 0;
} else { } else {
LOGE("unsupported addrtype: %d\n", request->atyp); LOGE("unsupported addrtype: %d\n", request->atyp);
close_and_free_remote(EV_A_ remote); close_and_free_remote(EV_A_ remote);
...@@ -206,7 +205,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { ...@@ -206,7 +205,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
return; 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 // Fake reply
struct socks5_response response; struct socks5_response response;
...@@ -233,7 +233,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { ...@@ -233,7 +233,6 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
} }
server->stage = 5; server->stage = 5;
} }
} }
} }
...@@ -333,7 +332,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { ...@@ -333,7 +332,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
return; return;
} }
} }
decrypt(server->buf, r); decrypt(server->buf, r, server->d_ctx);
int w = send(server->fd, server->buf, r, MSG_NOSIGNAL); int w = send(server->fd, server->buf, r, MSG_NOSIGNAL);
if(w == -1) { if(w == -1) {
if (errno == EAGAIN) { if (errno == EAGAIN) {
...@@ -482,6 +481,15 @@ struct server* new_server(int fd) { ...@@ -482,6 +481,15 @@ struct server* new_server(int fd) {
server->send_ctx->server = server; server->send_ctx->server = server;
server->send_ctx->connected = 0; server->send_ctx->connected = 0;
server->stage = 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; return server;
} }
void free_server(struct server *server) { void free_server(struct server *server) {
...@@ -489,6 +497,12 @@ void free_server(struct server *server) { ...@@ -489,6 +497,12 @@ void free_server(struct server *server) {
if (server->remote != NULL) { if (server->remote != NULL) {
server->remote->server = 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->recv_ctx);
free(server->send_ctx); free(server->send_ctx);
free(server); free(server);
...@@ -603,12 +617,6 @@ int main (int argc, char **argv) ...@@ -603,12 +617,6 @@ int main (int argc, char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (method != NULL) {
if (strcmp(method, "rc4") == 0) {
_method = RC4_ENC;
}
}
if (f_flags) { if (f_flags) {
/* Our process ID and Session ID */ /* Our process ID and Session ID */
...@@ -658,12 +666,22 @@ int main (int argc, char **argv) ...@@ -658,12 +666,22 @@ int main (int argc, char **argv)
fclose(file); fclose(file);
} }
// init global variables
_server = strdup(server); _server = strdup(server);
_remote_port = strdup(remote_port); _remote_port = strdup(remote_port);
_timeout = atoi(timeout); _timeout = atoi(timeout);
_key = key;
_method = TABLE;
if (method != NULL) {
if (strcmp(method, "rc4") == 0) {
_method = RC4;
}
}
LOGD("calculating ciphers %d", _method); LOGD("calculating ciphers %d", _method);
get_table(key); if (_method != RC4) {
get_table(key);
}
int listenfd; int listenfd;
listenfd = create_and_bind(port); listenfd = create_and_bind(port);
......
...@@ -21,6 +21,8 @@ struct server { ...@@ -21,6 +21,8 @@ struct server {
char buf[BUF_SIZE]; // server send from, remote recv into char buf[BUF_SIZE]; // server send from, remote recv into
char stage; char stage;
int buf_len; int buf_len;
EVP_CIPHER_CTX *e_ctx;
EVP_CIPHER_CTX *d_ctx;
struct server_ctx *recv_ctx; struct server_ctx *recv_ctx;
struct server_ctx *send_ctx; struct server_ctx *send_ctx;
struct remote *remote; struct remote *remote;
......
No preview for this file type
...@@ -405,31 +405,35 @@ public class Shadowsocks extends PreferenceActivity implements ...@@ -405,31 +405,35 @@ public class Shadowsocks extends PreferenceActivity implements
} }
} }
if (key.equals("remotePort")) {
if (key.equals("remotePort")) if (settings.getString("remotePort", "").equals("")) {
if (settings.getString("remotePort", "").equals(""))
remotePortText.setSummary(getString(R.string.remote_port_summary)); remotePortText.setSummary(getString(R.string.remote_port_summary));
else } else {
remotePortText.setSummary(settings.getString("remotePort", "")); 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)); portText.setSummary(getString(R.string.port_summary));
else } else {
portText.setSummary(settings.getString("port", "")); 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)); sitekeyText.setSummary(getString(R.string.sitekey_summary));
else } else {
sitekeyText.setSummary(settings.getString("sitekey", "")); 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", "")); encMethodText.setSummary(settings.getString("encMethod", ""));
else if (key.equals("proxy")) }
} else if (key.equals("proxy")) {
if (settings.getString("proxy", "").equals("")) { if (settings.getString("proxy", "").equals("")) {
proxyText.setSummary(getString(R.string.proxy_summary)); proxyText.setSummary(getString(R.string.proxy_summary));
} else { } else {
proxyText.setSummary(settings.getString("proxy", "")); proxyText.setSummary(settings.getString("proxy", ""));
} }
}
} }
@Override @Override
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment