diff --git a/README.md b/README.md index 00672bd7..11e223e0 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,28 @@ It is a port of [shadowsocks](https://github.com/clowwindy/shadowsocks) created by [@clowwindy](https://github.com/clowwindy) maintained by [@madeye](https://github.com/madeye). -Current version: 1.2 [![Build Status](https://travis-ci.org/madeye/shadowsocks-libev.png?branch=master)](https://travis-ci.org/madeye/shadowsocks-libev) +Current version: 1.3 [![Build Status](https://travis-ci.org/madeye/shadowsocks-libev.png?branch=master)](https://travis-ci.org/madeye/shadowsocks-libev) + +Changelog +--------- + +shadowsocks 1.3 -- Thu, 16 May 2013 10:51:15 +0800 + + * Able to bind connections to specific interface + * Support more ciphers: aes-128-cfb, aes-192-cfb, aes-256-cfb, bf-cfb, cast5-cfb, des-cfb + +shadowsocks 1.2 -- Tue, 07 May 2013 14:10:33 +0800 + + * Close timeouted TCP connections + * Fix a high load issue + +shadowsocks 1.1 -- Wed, 10 Apr 2013 12:11:36 +0800 + + * Fix a IPV6 resolve issue + +shadowsocks 1.0 -- Sat, 06 Apr 2013 16:59:15 +0800 + + * Initial release Features -------- @@ -52,7 +73,8 @@ usage: options: - encrypt_method: table, rc4 + encrypt_method: table, rc4, aes-128-cfb, aes-192-cfb, aes-256-cfb, + bf-cfb, cast5-cfb, des-cfb pid_file: valid path to the pid file timeout: socket timeout in senconds config_file: json format config file diff --git a/ar-lib b/ar-lib index fe2301e7..0f62c6fc 100755 --- a/ar-lib +++ b/ar-lib @@ -4,7 +4,7 @@ me=ar-lib scriptversion=2012-03-01.08; # UTC -# Copyright (C) 2010-2013 Free Software Foundation, Inc. +# Copyright (C) 2010, 2012 Free Software Foundation, Inc. # Written by Peter Rosin . # # This program is free software; you can redistribute it and/or modify diff --git a/configure b/configure index 61731791..954893a0 100755 --- a/configure +++ b/configure @@ -10850,6 +10850,65 @@ fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing MD5" >&5 +$as_echo_n "checking for library containing MD5... " >&6; } +if test "${ac_cv_search_MD5+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char MD5 (); +int +main () +{ +return MD5 (); + ; + return 0; +} +_ACEOF +for ac_lib in '' crypto; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_MD5=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_MD5+set}" = set; then : + break +fi +done +if test "${ac_cv_search_MD5+set}" = set; then : + +else + ac_cv_search_MD5=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_MD5" >&5 +$as_echo "$ac_cv_search_MD5" >&6; } +ac_res=$ac_cv_search_MD5 +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +else + as_fn_error $? "libcrypto not found." "$LINENO" 5 +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for what kind of host" >&5 $as_echo_n "checking for what kind of host... " >&6; } case $host in diff --git a/configure.ac b/configure.ac index 7403f4f1..f78d779e 100755 --- a/configure.ac +++ b/configure.ac @@ -16,8 +16,12 @@ AC_PROG_LIBTOOL AC_PROG_LN_S AC_PROG_MAKE_SET +dnl Checks for libev m4_include([libev/libev.m4]) +dnl Checks for openssl +AC_SEARCH_LIBS([MD5], [crypto], [ ], AC_MSG_ERROR([libcrypto not found.])) + dnl Checks for host. AC_MSG_CHECKING(for what kind of host) case $host in diff --git a/debian/changelog b/debian/changelog index 595a5f18..d97e1c6b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ shadowsocks (1.3-1) unstable; urgency=low * Able to bind connections to specific interface + * Support more ciphers: aes-128-cfb, aes-192-cfb, aes-256-cfb, bf-cfb, cast5-cfb, des-cfb -- Max Lv Thu, 16 May 2013 10:51:15 +0800 diff --git a/shadowsocks.8 b/shadowsocks.8 index d7257371..149dd312 100644 --- a/shadowsocks.8 +++ b/shadowsocks.8 @@ -66,8 +66,9 @@ Set the shadowsocks password. The server and the client should use the same password. .TP .B \-m \fIencrypt_method\fP -Set the shadowsocks encryption method. Currently, shadowsocks accepts two -encryption methods: table or rc4. And the default method is \fItable\fP. +Set the shadowsocks encryption method. Currently, shadowsocks accepts several +encryption methods: table, rc4, aes-128-cfb, aes-192-cfb, aes-256-cfb, bf-cfb, +cast5-cfb and des-cfb. The default method is \fItable\fP. .TP .B \-f \fIpid_file\fP Start shadowsocks as a daemon with a specific pid file. diff --git a/src/Makefile.am b/src/Makefile.am index ad7cc6f4..7d9ae16a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,9 @@ bin_PROGRAMS = ss-local ss-server ss_local_SOURCES = utils.c jconf.c json.c \ - rc4.c md5.c encrypt.c \ + encrypt.c \ local.c ss_server_SOURCES = utils.c jconf.c json.c \ - rc4.c md5.c encrypt.c \ + encrypt.c \ server.c ss_local_LDADD = $(top_builddir)/libev/libev.la ss_server_LDADD = $(top_builddir)/libev/libev.la @@ -12,7 +12,7 @@ ss_server_LDADD += $(top_builddir)/libasyncns/libasyncns.la if BUILD_REDIRECTOR bin_PROGRAMS += ss-redir ss_redir_SOURCES = utils.c jconf.c json.c \ - rc4.c md5.c encrypt.c \ + encrypt.c \ redir.c ss_redir_LDADD = $(top_builddir)/libev/libev.la endif diff --git a/src/Makefile.in b/src/Makefile.in index 7ae961e1..ebe6b48e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -54,20 +54,18 @@ CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_ss_local_OBJECTS = utils.$(OBJEXT) jconf.$(OBJEXT) json.$(OBJEXT) \ - rc4.$(OBJEXT) md5.$(OBJEXT) encrypt.$(OBJEXT) local.$(OBJEXT) + encrypt.$(OBJEXT) local.$(OBJEXT) ss_local_OBJECTS = $(am_ss_local_OBJECTS) ss_local_DEPENDENCIES = $(top_builddir)/libev/libev.la -am__ss_redir_SOURCES_DIST = utils.c jconf.c json.c rc4.c md5.c \ - encrypt.c redir.c +am__ss_redir_SOURCES_DIST = utils.c jconf.c json.c encrypt.c redir.c @BUILD_REDIRECTOR_TRUE@am_ss_redir_OBJECTS = utils.$(OBJEXT) \ @BUILD_REDIRECTOR_TRUE@ jconf.$(OBJEXT) json.$(OBJEXT) \ -@BUILD_REDIRECTOR_TRUE@ rc4.$(OBJEXT) md5.$(OBJEXT) \ @BUILD_REDIRECTOR_TRUE@ encrypt.$(OBJEXT) redir.$(OBJEXT) ss_redir_OBJECTS = $(am_ss_redir_OBJECTS) @BUILD_REDIRECTOR_TRUE@ss_redir_DEPENDENCIES = \ @BUILD_REDIRECTOR_TRUE@ $(top_builddir)/libev/libev.la am_ss_server_OBJECTS = utils.$(OBJEXT) jconf.$(OBJEXT) json.$(OBJEXT) \ - rc4.$(OBJEXT) md5.$(OBJEXT) encrypt.$(OBJEXT) server.$(OBJEXT) + encrypt.$(OBJEXT) server.$(OBJEXT) ss_server_OBJECTS = $(am_ss_server_OBJECTS) ss_server_DEPENDENCIES = $(top_builddir)/libev/libev.la \ $(top_builddir)/libasyncns/libasyncns.la @@ -206,18 +204,18 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ss_local_SOURCES = utils.c jconf.c json.c \ - rc4.c md5.c encrypt.c \ + encrypt.c \ local.c ss_server_SOURCES = utils.c jconf.c json.c \ - rc4.c md5.c encrypt.c \ + encrypt.c \ server.c ss_local_LDADD = $(top_builddir)/libev/libev.la ss_server_LDADD = $(top_builddir)/libev/libev.la \ $(top_builddir)/libasyncns/libasyncns.la @BUILD_REDIRECTOR_TRUE@ss_redir_SOURCES = utils.c jconf.c json.c \ -@BUILD_REDIRECTOR_TRUE@ rc4.c md5.c encrypt.c \ +@BUILD_REDIRECTOR_TRUE@ encrypt.c \ @BUILD_REDIRECTOR_TRUE@ redir.c @BUILD_REDIRECTOR_TRUE@ss_redir_LDADD = $(top_builddir)/libev/libev.la @@ -321,8 +319,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jconf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rc4.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/redir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ diff --git a/src/encrypt.c b/src/encrypt.c index ce3f5cca..16ee2e49 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -3,28 +3,48 @@ #endif #include +#include #include "encrypt.h" +#include "utils.h" #define OFFSET_ROL(p, o) ((uint64_t)(*(p + o)) << (8 * o)) -static void md5(const uint8_t *text, uint8_t *digest) { - md5_state_t state; - md5_init(&state); - md5_append(&state, text, strlen((char*)text)); - md5_finish(&state, digest); +static uint8_t *enc_table; +static uint8_t *dec_table; +static char *enc_pass; + +#ifdef DEBUG +static dump(char *tag, char *text) { + int i, len; + len = strlen(text); + printf("%s: ", tag); + for (i = 0; i < len; i++) { + printf("0x%02x ", (uint8_t)text[i]); + } + printf("\n"); } +#endif + +static const char* supported_ciphers[8] = { + "table", + "rc4", + "aes-128-cfb", + "aes-192-cfb", + "aes-256-cfb", + "bf-cfb", + "cast5-cfb", + "des-cfb" +}; -static int random_compare(const void *_x, const void *_y) { - uint32_t i = enc_conf.ctx.table.salt; - uint64_t a = enc_conf.ctx.table.key; +static int random_compare(const void *_x, const void *_y, uint32_t i, uint64_t a) { uint8_t x = *((uint8_t *) _x); uint8_t y = *((uint8_t*) _y); return (a % (x + i) - a % (y + i)); } -static void merge(uint8_t *left, int llength, uint8_t *right, int rlength) -{ +static void merge(uint8_t *left, int llength, uint8_t *right, + int rlength, uint32_t salt, uint64_t key) { uint8_t *ltmp = (uint8_t *) malloc(llength * sizeof(uint8_t)); uint8_t *rtmp = (uint8_t *) malloc(rlength * sizeof(uint8_t)); @@ -37,7 +57,7 @@ static void merge(uint8_t *left, int llength, uint8_t *right, int rlength) memcpy(rtmp, right, rlength * sizeof(uint8_t)); while (llength > 0 && rlength > 0) { - if (random_compare(ll, rr) <= 0) { + if (random_compare(ll, rr, salt, key) <= 0) { *result = *ll; ++ll; --llength; @@ -68,8 +88,8 @@ static void merge(uint8_t *left, int llength, uint8_t *right, int rlength) free(rtmp); } -static void merge_sort(uint8_t array[], int length) -{ +static void merge_sort(uint8_t array[], int length, + uint32_t salt, uint64_t key) { uint8_t middle; uint8_t *left, *right; int llength; @@ -84,87 +104,164 @@ static void merge_sort(uint8_t array[], int length) left = array; right = array + llength; - merge_sort(left, llength); - merge_sort(right, middle); - merge(left, llength, right, middle); -} - -void encrypt_ctx(char *buf, int len, struct rc4_state *ctx) { - if (ctx != NULL) { - rc4_crypt(ctx, (uint8_t*) buf, (uint8_t*) buf, len); - } else { - char *end = buf + len; - while (buf < end) { - *buf = (char)enc_conf.ctx.table.encrypt_table[(uint8_t)*buf]; - buf++; - } - } -} - -void decrypt_ctx(char *buf, int len, struct rc4_state *ctx) { - if (ctx != NULL) { - rc4_crypt(ctx, (uint8_t*) buf, (uint8_t*) buf, len); - } else { - char *end = buf + len; - while (buf < end) { - *buf = (char)enc_conf.ctx.table.decrypt_table[(uint8_t)*buf]; - buf++; - } - } -} - -void enc_ctx_init(struct rc4_state *ctx, int enc) { - uint8_t *key = enc_conf.ctx.rc4.key; - int key_len = enc_conf.ctx.rc4.key_len; - rc4_init(ctx, key, key_len); -} - -static void enc_rc4_init(const char *pass) { - enc_conf.ctx.rc4.key_len = 16; - enc_conf.ctx.rc4.key = malloc(16); - md5((const uint8_t*)pass, enc_conf.ctx.rc4.key); + merge_sort(left, llength, salt, key); + merge_sort(right, middle, salt, key); + merge(left, llength, right, middle, salt, key); } -static void enc_table_init(const char *pass) { - uint8_t *enc_table = malloc(256); - uint8_t *dec_table = malloc(256); - uint8_t digest[16]; - uint32_t *salt = &enc_conf.ctx.table.salt; - uint64_t *key = &enc_conf.ctx.table.key; +void enc_table_init(const char *pass) { uint32_t i; + uint32_t salt; + uint64_t key = 0; + uint8_t *digest; - md5((const uint8_t*)pass, digest); + enc_table = malloc(256); + dec_table = malloc(256); + + digest = MD5((const uint8_t *)pass, strlen(pass), NULL); - *key = 0; for (i = 0; i < 8; i++) { - *key += OFFSET_ROL(digest, i); + key += OFFSET_ROL(digest, i); } for(i = 0; i < 256; ++i) { enc_table[i] = i; } for(i = 1; i < 1024; ++i) { - *salt = i; - merge_sort(enc_table, 256); + salt = i; + merge_sort(enc_table, 256, salt, key); } for(i = 0; i < 256; ++i) { // gen decrypt table from encrypt table dec_table[enc_table[i]] = i; } +} + +char* encrypt(char *plaintext, ssize_t *len, struct enc_ctx *ctx) { + if (ctx != NULL) { + int c_len = *len + BLOCK_SIZE; + int iv_len = ctx->iv_len; + char *ciphertext = malloc(max(iv_len + c_len, BUF_SIZE)); + + if (!ctx->init) { + uint8_t iv[EVP_MAX_IV_LENGTH]; + int i; + for (i = 0; i < iv_len; i++) { + iv[i] = rand() % 256; + } + EVP_CipherInit_ex(&ctx->evp, NULL, NULL, ctx->key, iv, 1); + memcpy(ciphertext, iv, iv_len); + ctx->iv_len = 0; + ctx->init = 1; +#ifdef DEBUG + dump("IV", ctx->iv); +#endif + } + + EVP_EncryptUpdate(&ctx->evp, (uint8_t*)(ciphertext+iv_len), + &c_len, (const uint8_t *)plaintext, *len); + +#ifdef DEBUG + dump("PLAIN", plaintext); + dump("CIPHER", ciphertext); +#endif + + *len = iv_len + c_len; + free(plaintext); + return ciphertext; + } else { + char *begin = plaintext; + while (plaintext < begin + *len) { + *plaintext = (char)enc_table[(uint8_t)*plaintext]; + plaintext++; + } + return begin; + } +} + +char* decrypt(char *ciphertext, ssize_t *len, struct enc_ctx *ctx) { + if (ctx != NULL) { + int p_len = *len + BLOCK_SIZE; + int iv_len = ctx->iv_len; + char *plaintext = malloc(max(p_len, BUF_SIZE)); + + if (!ctx->init) { + uint8_t iv[EVP_MAX_IV_LENGTH]; + memcpy(iv, ciphertext, iv_len); + EVP_CipherInit_ex(&ctx->evp, NULL, NULL, ctx->key, iv, 0); + ctx->iv_len = 0; + ctx->init = 1; +#ifdef DEBUG + dump("IV", ctx->iv); +#endif + } + + EVP_DecryptUpdate(&ctx->evp, (uint8_t*)plaintext, &p_len, + (const uint8_t*)(ciphertext + iv_len), *len - iv_len); + +#ifdef DEBUG + dump("PLAIN", plaintext); + dump("CIPHER", ciphertext); +#endif - enc_conf.ctx.table.encrypt_table = enc_table; - enc_conf.ctx.table.decrypt_table = dec_table; + *len = p_len; + free(ciphertext); + return plaintext; + } else { + char *begin = ciphertext; + while (ciphertext < begin + *len) { + *ciphertext = (char)dec_table[(uint8_t)*ciphertext]; + ciphertext++; + } + return begin; + } } -void enc_conf_init(const char *pass, const char *method) { - enc_conf.method = TABLE; - if (method != NULL && strcmp(method, "rc4") == 0) { - enc_conf.method = RC4; +void enc_ctx_init(int method, struct enc_ctx *ctx, int enc) { + uint8_t *key = ctx->key; + uint8_t iv[EVP_MAX_IV_LENGTH]; + int key_len; + + memset(ctx, 0, sizeof(struct enc_ctx)); + + EVP_CIPHER_CTX *evp = &ctx->evp; + OpenSSL_add_all_algorithms(); + const EVP_CIPHER *cipher = EVP_get_cipherbyname(supported_ciphers[method]); + ctx->iv_len = EVP_CIPHER_iv_length(cipher); + + key_len = EVP_BytesToKey(cipher, EVP_md5(), NULL, (uint8_t *)enc_pass, + strlen(enc_pass), 1, key, iv); + + EVP_CIPHER_CTX_init(evp); + EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc); + if (!EVP_CIPHER_CTX_set_key_length(evp, key_len)) { + EVP_CIPHER_CTX_cleanup(evp); + LOGE("Invalid key length: %d", key_len); + exit(EXIT_FAILURE); } - if (enc_conf.method == TABLE) { - enc_table_init(pass); - } else if (enc_conf.method == RC4) { - enc_rc4_init(pass); + EVP_CIPHER_CTX_set_padding(evp, 1); +} + +int enc_init(const char *pass, const char *method) { + enc_pass = strdup(pass); + if (method == NULL || strcmp(method, "table") == 0) { + enc_table_init(enc_pass); + return TABLE; + } else if (strcmp(method, "aes-128-cfb") == 0) { + return AES_128_CFB; + } else if (strcmp(method, "aes-192-cfb") == 0) { + return AES_192_CFB; + } else if (strcmp(method, "aes-256-cfb") == 0) { + return AES_256_CFB; + } else if (strcmp(method, "bf-cfb") == 0) { + return BF_CFB; + } else if (strcmp(method, "cast5-cfb") == 0) { + return CAST5_CFB; + } else if (strcmp(method, "des-cfb") == 0) { + return DES_CFB; + } else if (strcmp(method, "rc4") == 0) { + return RC4; } + return TABLE; } diff --git a/src/encrypt.h b/src/encrypt.h index 6e9b0f14..ed7fce2e 100644 --- a/src/encrypt.h +++ b/src/encrypt.h @@ -8,40 +8,40 @@ #include #include +#include + #ifdef HAVE_STDINT_H #include #elif HAVE_INTTYPES_H #include #endif -#include "md5.h" -#include "rc4.h" - -#define BUF_SIZE 4096 - -#define TABLE 0 -#define RC4 1 - -struct { - int method; - union { - struct { - uint8_t *encrypt_table; - uint8_t *decrypt_table; - uint32_t salt; - uint64_t key; - } table; - - struct { - uint8_t *key; - int key_len; - } rc4; - } ctx; -} enc_conf; - -void encrypt_ctx(char *buf, int len, struct rc4_state *ctx); -void decrypt_ctx(char *buf, int len, struct rc4_state *ctx); -void enc_ctx_init(struct rc4_state *ctx, int enc); -void enc_conf_init(const char *pass, const char *method); +#define BUF_SIZE 512 +#define BLOCK_SIZE 32 + +#define NONE -1 +#define TABLE 0 +#define RC4 1 +#define AES_128_CFB 2 +#define AES_192_CFB 3 +#define AES_256_CFB 4 +#define BF_CFB 5 +#define CAST5_CFB 6 +#define DES_CFB 7 + +#define min(a,b) (((a)<(b))?(a):(b)) +#define max(a,b) (((a)>(b))?(a):(b)) + +struct enc_ctx { + uint8_t init; + uint8_t iv_len; + uint8_t key[EVP_MAX_KEY_LENGTH]; + EVP_CIPHER_CTX evp; +}; + +char* encrypt(char *plaintext, ssize_t *len, struct enc_ctx *ctx); +char* decrypt(char *ciphertext, ssize_t *len, struct enc_ctx *ctx); +void enc_ctx_init(int method, struct enc_ctx *ctx, int enc); +int enc_init(const char *pass, const char *method); #endif // _ENCRYPT_H diff --git a/src/local.c b/src/local.c index 684290c8..767f3e50 100644 --- a/src/local.c +++ b/src/local.c @@ -36,8 +36,6 @@ #define EWOULDBLOCK EAGAIN #endif -#define min(a,b) (((a)<(b))?(a):(b)) - int setnonblocking(int fd) { int flags; if (-1 ==(flags = fcntl(fd, F_GETFL, 0))) @@ -140,7 +138,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { // local socks5 server if (server->stage == 5) { - encrypt_ctx(remote->buf, r, server->e_ctx); + remote->buf = encrypt(remote->buf, &r, server->e_ctx); int s = send(remote->fd, remote->buf, r, 0); if(s == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -188,8 +186,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { return; } - char addr_to_send[256]; - uint8_t addr_len = 0; + char *addr_to_send = malloc(BUF_SIZE); + ssize_t addr_len = 0; addr_to_send[addr_len++] = request->atyp; // get remote addr and port @@ -223,8 +221,10 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { return; } - encrypt_ctx(addr_to_send, addr_len, server->e_ctx); + addr_to_send = encrypt(addr_to_send, &addr_len, server->e_ctx); int s = send(remote->fd, addr_to_send, addr_len, 0); + free(addr_to_send); + if (s < addr_len) { LOGE("failed to send remote addr."); close_and_free_remote(EV_A_ remote); @@ -352,7 +352,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { } } - decrypt_ctx(server->buf, r, server->d_ctx); + server->buf = decrypt(server->buf, &r, server->d_ctx); int s = send(server->fd, server->buf, r, 0); if (s == -1) { @@ -445,6 +445,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { struct remote* new_remote(int fd, int timeout) { struct remote *remote; remote = malloc(sizeof(struct remote)); + remote->buf = malloc(BUF_SIZE); remote->recv_ctx = malloc(sizeof(struct remote_ctx)); remote->send_ctx = malloc(sizeof(struct remote_ctx)); remote->fd = fd; @@ -465,6 +466,7 @@ void free_remote(struct remote *remote) { if (remote->server != NULL) { remote->server->remote = NULL; } + free(remote->buf); free(remote->recv_ctx); free(remote->send_ctx); free(remote); @@ -481,9 +483,10 @@ void close_and_free_remote(EV_P_ struct remote *remote) { } } -struct server* new_server(int fd) { +struct server* new_server(int fd, int method) { struct server *server; server = malloc(sizeof(struct server)); + server->buf = malloc(BUF_SIZE); server->recv_ctx = malloc(sizeof(struct server_ctx)); server->send_ctx = malloc(sizeof(struct server_ctx)); server->fd = fd; @@ -494,11 +497,11 @@ struct server* new_server(int fd) { server->send_ctx->server = server; server->send_ctx->connected = 0; server->stage = 0; - if (enc_conf.method == RC4) { - server->e_ctx = malloc(sizeof(struct rc4_state)); - server->d_ctx = malloc(sizeof(struct rc4_state)); - enc_ctx_init(server->e_ctx, 1); - enc_ctx_init(server->d_ctx, 0); + if (method) { + server->e_ctx = malloc(sizeof(struct enc_ctx)); + server->d_ctx = malloc(sizeof(struct enc_ctx)); + enc_ctx_init(method, server->e_ctx, 1); + enc_ctx_init(method, server->d_ctx, 0); } else { server->e_ctx = NULL; server->d_ctx = NULL; @@ -513,10 +516,15 @@ void free_server(struct server *server) { if (server->remote != NULL) { server->remote->server = NULL; } - if (enc_conf.method == RC4) { + if (server->e_ctx != NULL) { + EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp); free(server->e_ctx); + } + if (server->d_ctx != NULL) { + EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); free(server->d_ctx); } + free(server->buf); free(server->recv_ctx); free(server->send_ctx); free(server); @@ -577,7 +585,7 @@ static void accept_cb (EV_P_ ev_io *w, int revents) { if (listener->iface) setinterface(sockfd, listener->iface); #endif - struct server *server = new_server(serverfd); + struct server *server = new_server(serverfd, listener->method); struct remote *remote = new_remote(sockfd, listener->timeout); server->remote = remote; remote->server = server; @@ -676,7 +684,7 @@ int main (int argc, char **argv) { // Setup keys LOGD("calculating ciphers..."); - enc_conf_init(password, method); + int m = enc_init(password, method); // Setup socket int listenfd; @@ -702,6 +710,7 @@ int main (int argc, char **argv) { listen_ctx.timeout = atoi(timeout); listen_ctx.fd = listenfd; listen_ctx.iface = iface; + listen_ctx.method = m; struct ev_loop *loop = ev_default_loop(0); if (!loop) { diff --git a/src/local.h b/src/local.h index daf7b482..bd9aa952 100644 --- a/src/local.h +++ b/src/local.h @@ -8,9 +8,10 @@ struct listen_ctx { ev_io io; char **remote_host; - int remote_num; char *remote_port; char *iface; + int remote_num; + int method; int timeout; int fd; struct sockaddr sock; @@ -24,12 +25,12 @@ struct server_ctx { struct server { int fd; - char buf[BUF_SIZE]; // server send from, remote recv into - char stage; int buf_len; int buf_idx; - struct rc4_state *e_ctx; - struct rc4_state *d_ctx; + char *buf; // server send from, remote recv into + char stage; + struct enc_ctx *e_ctx; + struct enc_ctx *d_ctx; struct server_ctx *recv_ctx; struct server_ctx *send_ctx; struct remote *remote; @@ -44,9 +45,9 @@ struct remote_ctx { struct remote { int fd; - char buf[BUF_SIZE]; // remote send from, server recv into int buf_len; int buf_idx; + char *buf; // remote send from, server recv into struct remote_ctx *recv_ctx; struct remote_ctx *send_ctx; struct server *server; @@ -61,7 +62,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents); struct remote* new_remote(int fd, int timeout); void free_remote(struct remote *remote); void close_and_free_remote(EV_P_ struct remote *remote); -struct server* new_server(int fd); +struct server* new_server(int fd, int method); void free_server(struct server *server); void close_and_free_server(EV_P_ struct server *server); diff --git a/src/rc4.c b/src/rc4.c deleted file mode 100644 index 1759d1fe..00000000 --- a/src/rc4.c +++ /dev/null @@ -1,103 +0,0 @@ - -/* - * rc4.c - * - * Copyright (c) 1996-2000 Whistle Communications, Inc. - * All rights reserved. - * - * Subject to the following obligations and disclaimer of warranty, use and - * redistribution of this software, in source or object code forms, with or - * without modifications are expressly permitted by Whistle Communications; - * provided, however, that: - * 1. Any and all reproductions of the source or object code must include the - * copyright notice above and the following disclaimer of warranties; and - * 2. No rights are granted, in any manner or form, to use Whistle - * Communications, Inc. trademarks, including the mark "WHISTLE - * COMMUNICATIONS" on advertising, endorsements, or otherwise except as - * such appears in the above copyright notice or in the software. - * - * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO - * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, - * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. - * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY - * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS - * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. - * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES - * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING - * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/crypto/rc4/rc4.c,v 1.2.2.1 2000/04/18 04:48:31 archie Exp $ - */ -#include -#include "rc4.h" - -static inline void -swap_bytes(u_char *a, u_char *b) -{ - u_char temp; - - temp = *a; - *a = *b; - *b = temp; -} - -/* - * Initialize an RC4 state buffer using the supplied key, - * which can have arbitrary length. - */ -void -rc4_init(struct rc4_state *const state, const u_char *key, int keylen) -{ - u_char j; - int i; - - /* Initialize state with identity permutation */ - for (i = 0; i < 256; i++) - state->perm[i] = (u_char)i; - state->index1 = 0; - state->index2 = 0; - - /* Randomize the permutation using key data */ - for (j = i = 0; i < 256; i++) { - j += state->perm[i] + key[i % keylen]; - swap_bytes(&state->perm[i], &state->perm[j]); - } -} - -/* - * Encrypt some data using the supplied RC4 state buffer. - * The input and output buffers may be the same buffer. - * Since RC4 is a stream cypher, this function is used - * for both encryption and decryption. - */ -void -rc4_crypt(struct rc4_state *const state, - const u_char *inbuf, u_char *outbuf, int buflen) -{ - int i; - u_char j; - - for (i = 0; i < buflen; i++) { - - /* Update modification indicies */ - state->index1++; - state->index2 += state->perm[state->index1]; - - /* Modify permutation */ - swap_bytes(&state->perm[state->index1], - &state->perm[state->index2]); - - /* Encrypt/decrypt next byte */ - j = state->perm[state->index1] + state->perm[state->index2]; - outbuf[i] = inbuf[i] ^ state->perm[j]; - } -} - diff --git a/src/rc4.h b/src/rc4.h deleted file mode 100644 index 40c6b46e..00000000 --- a/src/rc4.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * rc4.h - * - * Copyright (c) 1996-2000 Whistle Communications, Inc. - * All rights reserved. - * - * Subject to the following obligations and disclaimer of warranty, use and - * redistribution of this software, in source or object code forms, with or - * without modifications are expressly permitted by Whistle Communications; - * provided, however, that: - * 1. Any and all reproductions of the source or object code must include the - * copyright notice above and the following disclaimer of warranties; and - * 2. No rights are granted, in any manner or form, to use Whistle - * Communications, Inc. trademarks, including the mark "WHISTLE - * COMMUNICATIONS" on advertising, endorsements, or otherwise except as - * such appears in the above copyright notice or in the software. - * - * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO - * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, - * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. - * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY - * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS - * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. - * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES - * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING - * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/crypto/rc4/rc4.h,v 1.2.2.1 2000/04/18 04:48:32 archie Exp $ - */ - -#ifndef RC4_H_ -#define RC4_H_ - -typedef uint8_t u_char; - -struct rc4_state { - u_char perm[256]; - u_char index1; - u_char index2; -}; - -void rc4_init(struct rc4_state *state, const u_char *key, int keylen); -void rc4_crypt(struct rc4_state *state, - const u_char *inbuf, u_char *outbuf, int buflen); - -#endif - diff --git a/src/redir.c b/src/redir.c index fba7d3a6..9677f2ea 100644 --- a/src/redir.c +++ b/src/redir.c @@ -31,8 +31,6 @@ #define EWOULDBLOCK EAGAIN #endif -#define min(a,b) (((a)<(b))?(a):(b)) - int getdestaddr(int fd, struct sockaddr_in *destaddr) { socklen_t socklen = sizeof(*destaddr); int error; @@ -72,10 +70,11 @@ int create_and_bind(const char *port) { continue; int opt = 1; - int err = setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - if (err) { - ERROR("setsocket"); - } + setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + setsockopt(listen_sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); +#ifdef SO_NOSIGPIPE + setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); +#endif s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen); if (s == 0) { @@ -132,7 +131,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { } } - encrypt_ctx(remote->buf, r, server->e_ctx); + remote->buf = encrypt(remote->buf, &r, server->e_ctx); int s = send(remote->fd, remote->buf, r, 0); if(s == -1) { @@ -252,7 +251,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { } } - decrypt_ctx(server->buf, r, server->d_ctx); + server->buf = decrypt(server->buf, &r, server->d_ctx); int s = send(server->fd, server->buf, r, 0); if (s == -1) { @@ -294,8 +293,8 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { ev_timer_stop(EV_A_ &remote_send_ctx->watcher); // send destaddr - char addr_to_send[256]; - uint8_t addr_len = 0; + char *addr_to_send = malloc(BUF_SIZE); + ssize_t addr_len = 0; addr_to_send[addr_len++] = 1; // handle IP V4 only @@ -304,9 +303,11 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { addr_len += in_addr_len; memcpy(addr_to_send + addr_len, &server->destaddr.sin_port, 2); addr_len += 2; - encrypt_ctx(addr_to_send, addr_len, server->e_ctx); + addr_to_send = encrypt(addr_to_send, &addr_len, server->e_ctx); int s = send(remote->fd, addr_to_send, addr_len, 0); + free(addr_to_send); + if (s < addr_len) { LOGE("failed to send remote addr."); close_and_free_remote(EV_A_ remote); @@ -368,6 +369,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { struct remote* new_remote(int fd, int timeout) { struct remote *remote; remote = malloc(sizeof(struct remote)); + remote->buf = malloc(BUF_SIZE); remote->recv_ctx = malloc(sizeof(struct remote_ctx)); remote->send_ctx = malloc(sizeof(struct remote_ctx)); remote->fd = fd; @@ -388,6 +390,7 @@ void free_remote(struct remote *remote) { if (remote->server != NULL) { remote->server->remote = NULL; } + free(remote->buf); free(remote->recv_ctx); free(remote->send_ctx); free(remote); @@ -404,9 +407,10 @@ void close_and_free_remote(EV_P_ struct remote *remote) { } } -struct server* new_server(int fd) { +struct server* new_server(int fd, int method) { struct server *server; server = malloc(sizeof(struct server)); + server->buf = malloc(BUF_SIZE); server->recv_ctx = malloc(sizeof(struct server_ctx)); server->send_ctx = malloc(sizeof(struct server_ctx)); server->fd = fd; @@ -416,11 +420,11 @@ struct server* new_server(int fd) { server->recv_ctx->connected = 0; server->send_ctx->server = server; server->send_ctx->connected = 0; - if (enc_conf.method == RC4) { - server->e_ctx = malloc(sizeof(struct rc4_state)); - server->d_ctx = malloc(sizeof(struct rc4_state)); - enc_ctx_init(server->e_ctx, 1); - enc_ctx_init(server->d_ctx, 0); + if (method) { + server->e_ctx = malloc(sizeof(struct enc_ctx)); + server->d_ctx = malloc(sizeof(struct enc_ctx)); + enc_ctx_init(method, server->e_ctx, 1); + enc_ctx_init(method, server->d_ctx, 0); } else { server->e_ctx = NULL; server->d_ctx = NULL; @@ -435,10 +439,15 @@ void free_server(struct server *server) { if (server->remote != NULL) { server->remote->server = NULL; } - if (enc_conf.method == RC4) { + if (server->e_ctx != NULL) { + EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp); free(server->e_ctx); + } + if (server->d_ctx != NULL) { + EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); free(server->d_ctx); } + free(server->buf); free(server->recv_ctx); free(server->send_ctx); free(server); @@ -472,6 +481,11 @@ static void accept_cb (EV_P_ ev_io *w, int revents) { } setnonblocking(clientfd); + int opt = 1; + setsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); +#ifdef SO_NOSIGPIPE + setsockopt(clientfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); +#endif struct addrinfo hints, *res; int sockfd; @@ -493,18 +507,15 @@ static void accept_cb (EV_P_ ev_io *w, int revents) { return; } - struct timeval timeout; - timeout.tv_sec = listener->timeout; - timeout.tv_usec = 0; - err = setsockopt(sockfd, SOL_SOCKET, - SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); - if (err) ERROR("setsockopt"); - err = setsockopt(sockfd, SOL_SOCKET, - SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); - if (err) ERROR("setsockopt"); + setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); +#ifdef SO_NOSIGPIPE + setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); +#endif + + // Setup setnonblocking(sockfd); - struct server *server = new_server(clientfd); + struct server *server = new_server(clientfd, listener->method); struct remote *remote = new_remote(sockfd, listener->timeout); server->remote = remote; remote->server = server; @@ -601,7 +612,7 @@ int main (int argc, char **argv) { // Setup keys LOGD("calculating ciphers..."); - enc_conf_init(password, method); + int m = enc_init(password, method); // Setup socket int listenfd; @@ -626,6 +637,7 @@ int main (int argc, char **argv) { listen_ctx.remote_port = remote_port; listen_ctx.timeout = atoi(timeout); listen_ctx.fd = listenfd; + listen_ctx.method = m; struct ev_loop *loop = ev_default_loop(0); if (!loop) { diff --git a/src/redir.h b/src/redir.h index df953d73..3a283206 100644 --- a/src/redir.h +++ b/src/redir.h @@ -8,10 +8,11 @@ struct listen_ctx { ev_io io; char **remote_host; - int remote_num; char *remote_port; + int remote_num; int timeout; int fd; + int method; struct sockaddr sock; }; @@ -23,12 +24,12 @@ struct server_ctx { struct server { int fd; - char buf[BUF_SIZE]; // server send from, remote recv into int buf_len; int buf_idx; + char *buf; // server send from, remote recv into struct sockaddr_in destaddr; - struct rc4_state *e_ctx; - struct rc4_state *d_ctx; + struct enc_ctx *e_ctx; + struct enc_ctx *d_ctx; struct server_ctx *recv_ctx; struct server_ctx *send_ctx; struct remote *remote; @@ -43,9 +44,9 @@ struct remote_ctx { struct remote { int fd; - char buf[BUF_SIZE]; // remote send from, server recv into int buf_len; int buf_idx; + char *buf; // remote send from, server recv into struct remote_ctx *recv_ctx; struct remote_ctx *send_ctx; struct server *server; @@ -60,7 +61,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents); struct remote* new_remote(int fd, int timeout); void free_remote(struct remote *remote); void close_and_free_remote(EV_P_ struct remote *remote); -struct server* new_server(int fd); +struct server* new_server(int fd, int method); void free_server(struct server *server); void close_and_free_server(EV_P_ struct server *server); diff --git a/src/server.c b/src/server.c index 597611fe..059a704b 100644 --- a/src/server.c +++ b/src/server.c @@ -35,8 +35,6 @@ #define EWOULDBLOCK EAGAIN #endif -#define min(a,b) (((a)<(b))?(a):(b)) - static int verbose = 0; static int remote_conn = 0; static int server_conn = 0; @@ -142,16 +140,16 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { struct server *server = server_recv_ctx->server; struct remote *remote = NULL; - char *buf = server->buf; + char **buf = &server->buf; ev_timer_again(EV_A_ &server->recv_ctx->watcher); if (server->stage != 0) { remote = server->remote; - buf = remote->buf; + buf = &remote->buf; } - ssize_t r = recv(server->fd, buf, BUF_SIZE, 0); + ssize_t r = recv(server->fd, *buf, BUF_SIZE, 0); if (r == 0) { // connection closed @@ -174,7 +172,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { } } - decrypt_ctx(buf, r, server->d_ctx); + *buf = decrypt(*buf, &r, server->d_ctx); // handshake and transmit data if (server->stage == 5) { @@ -482,7 +480,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { } } - encrypt_ctx(server->buf, r, server->e_ctx); + server->buf = encrypt(server->buf, &r, server->e_ctx); int s = send(server->fd, server->buf, r, 0); if (s == -1) { @@ -596,6 +594,7 @@ struct remote* new_remote(int fd) { remote_conn++; struct remote *remote; remote = malloc(sizeof(struct remote)); + remote->buf = malloc(BUF_SIZE); remote->recv_ctx = malloc(sizeof(struct remote_ctx)); remote->send_ctx = malloc(sizeof(struct remote_ctx)); remote->fd = fd; @@ -617,6 +616,7 @@ void free_remote(struct remote *remote) { if (remote->server != NULL) { remote->server->remote = NULL; } + free(remote->buf); free(remote->recv_ctx); free(remote->send_ctx); free(remote); @@ -639,6 +639,7 @@ struct server* new_server(int fd, struct listen_ctx *listener) { server_conn++; struct server *server; server = malloc(sizeof(struct server)); + server->buf = malloc(BUF_SIZE); server->recv_ctx = malloc(sizeof(struct server_ctx)); server->send_ctx = malloc(sizeof(struct server_ctx)); server->fd = fd; @@ -653,11 +654,11 @@ struct server* new_server(int fd, struct listen_ctx *listener) { server->stage = 0; server->query = NULL; server->listen_ctx = listener; - if (enc_conf.method == RC4) { - server->e_ctx = malloc(sizeof(struct rc4_state)); - server->d_ctx = malloc(sizeof(struct rc4_state)); - enc_ctx_init(server->e_ctx, 1); - enc_ctx_init(server->d_ctx, 0); + if (listener->method) { + server->e_ctx = malloc(sizeof(struct enc_ctx)); + server->d_ctx = malloc(sizeof(struct enc_ctx)); + enc_ctx_init(listener->method, server->e_ctx, 1); + enc_ctx_init(listener->method, server->d_ctx, 0); } else { server->e_ctx = NULL; server->d_ctx = NULL; @@ -674,10 +675,15 @@ void free_server(struct server *server) { if (server->remote != NULL) { server->remote->server = NULL; } - if (enc_conf.method == RC4) { + if (server->e_ctx != NULL) { + EVP_CIPHER_CTX_cleanup(&server->e_ctx->evp); free(server->e_ctx); + } + if (server->d_ctx != NULL) { + EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); free(server->d_ctx); } + free(server->buf); free(server->recv_ctx); free(server->send_ctx); free(server); @@ -813,7 +819,7 @@ int main (int argc, char **argv) { // Setup keys LOGD("calculating ciphers..."); - enc_conf_init(password, method); + int m = enc_init(password, method); // Inilitialize ev loop struct ev_loop *loop = EV_DEFAULT; @@ -840,6 +846,7 @@ int main (int argc, char **argv) { listen_ctx.timeout = atoi(timeout); listen_ctx.asyncns = asyncns; listen_ctx.fd = listenfd; + listen_ctx.method = m; listen_ctx.iface = iface; ev_io_init (&listen_ctx.io, accept_cb, listenfd, EV_READ); diff --git a/src/server.h b/src/server.h index 737411b3..0094c7f0 100644 --- a/src/server.h +++ b/src/server.h @@ -12,6 +12,7 @@ struct listen_ctx { ev_io io; int fd; int timeout; + int method; char *iface; asyncns_t *asyncns; struct sockaddr sock; @@ -26,12 +27,12 @@ struct server_ctx { struct server { int fd; - char buf[BUF_SIZE]; // server send from, remote recv into - char stage; int buf_len; int buf_idx; - struct rc4_state *e_ctx; - struct rc4_state *d_ctx; + char *buf; // server send from, remote recv into + char stage; + struct enc_ctx *e_ctx; + struct enc_ctx *d_ctx; struct server_ctx *recv_ctx; struct server_ctx *send_ctx; struct listen_ctx *listen_ctx; @@ -47,9 +48,9 @@ struct remote_ctx { struct remote { int fd; - char buf[BUF_SIZE]; // remote send from, server recv into int buf_len; int buf_idx; + char *buf; // remote send from, server recv into struct remote_ctx *recv_ctx; struct remote_ctx *send_ctx; struct server *server; diff --git a/src/utils.c b/src/utils.c index 1f621b91..fce357d2 100644 --- a/src/utils.c +++ b/src/utils.c @@ -70,7 +70,8 @@ void usage() { printf(" [-m encrypt_method] [-f pid_file] [-t timeout] [-c config_file]\n"); printf("\n"); printf(" options:\n\n"); - printf(" encrypt_method: table, rc4\n"); + printf(" encrypt_method: table, rc4, aes-128-cfb, aes-192-cfb, aes-256-cfb,\n"); + printf(" bf-cfb, cast5-cfb, des-cfb\n"); printf(" pid_file: valid path to the pid file\n"); printf(" timeout: socket timeout in senconds\n"); printf(" config_file: json format config file\n");