From a7a314ed32549164b48f6829a427573903780ff5 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Thu, 7 Mar 2013 11:14:06 +0800 Subject: [PATCH] refine the code structure --- encrypt.c | 91 ++++++++++++------------------ encrypt.h | 36 ++++++------ local.c | 161 +++++++++++++++++++++++++++--------------------------- local.h | 8 ++- 4 files changed, 140 insertions(+), 156 deletions(-) diff --git a/encrypt.c b/encrypt.c index da589c3d..6337a4f8 100644 --- a/encrypt.c +++ b/encrypt.c @@ -8,7 +8,7 @@ #define OFFSET_ROL(p, o) ((u_int64_t)(*(p + o)) << (8 * o)) -static void md5(const unsigned char *text, unsigned char *digest) { +static void md5(const uint8_t *text, uint8_t *digest) { md5_state_t state; md5_init(&state); md5_append(&state, text, strlen((char*)text)); @@ -16,8 +16,8 @@ static void md5(const unsigned char *text, unsigned char *digest) { } static int random_compare(const void *_x, const void *_y) { - uint32_t i = _i; - uint64_t a = _a; + uint32_t i = enc_conf.ctx.table.salt; + uint64_t a = enc_conf.ctx.table.key; uint8_t x = *((uint8_t *) _x); uint8_t y = *((uint8_t*) _y); return (a % (x + i) - a % (y + i)); @@ -25,53 +25,32 @@ static int random_compare(const void *_x, const void *_y) { static void merge(uint8_t *left, int llength, uint8_t *right, int rlength) { - /* Temporary memory locations for the 2 segments of the array to merge. */ uint8_t *ltmp = (uint8_t *) malloc(llength * sizeof(uint8_t)); uint8_t *rtmp = (uint8_t *) malloc(rlength * sizeof(uint8_t)); - /* - * Pointers to the elements being sorted in the temporary memory locations. - */ uint8_t *ll = ltmp; uint8_t *rr = rtmp; uint8_t *result = left; - /* - * Copy the segment of the array to be merged into the temporary memory - * locations. - */ memcpy(ltmp, left, llength * sizeof(uint8_t)); memcpy(rtmp, right, rlength * sizeof(uint8_t)); while (llength > 0 && rlength > 0) { if (random_compare(ll, rr) <= 0) { - /* - * Merge the first element from the left back into the main array - * if it is smaller or equal to the one on the right. - */ *result = *ll; ++ll; --llength; } else { - /* - * Merge the first element from the right back into the main array - * if it is smaller than the one on the left. - */ *result = *rr; ++rr; --rlength; } ++result; } - /* - * All the elements from either the left or the right temporary array - * segment have been merged back into the main array. Append the remaining - * elements from the other temporary array back into the main array. - */ + if (llength > 0) while (llength > 0) { - /* Appending the rest of the left temporary array. */ *result = *ll; ++result; ++ll; @@ -79,43 +58,29 @@ static void merge(uint8_t *left, int llength, uint8_t *right, int rlength) } else while (rlength > 0) { - /* Appending the rest of the right temporary array. */ *result = *rr; ++result; ++rr; --rlength; } - /* Release the memory used for the temporary arrays. */ free(ltmp); free(rtmp); } static void merge_sort(uint8_t array[], int length) { - /* This is the middle index and also the length of the right array. */ uint8_t middle; - - /* - * Pointers to the beginning of the left and right segment of the array - * to be merged. - */ uint8_t *left, *right; - - /* Length of the left segment of the array to be merged. */ int llength; if (length <= 1) return; - /* Let integer division truncate the value. */ middle = length / 2; llength = length - middle; - /* - * Set the pointers to the appropriate segments of the array to be merged. - */ left = array; right = array + llength; @@ -126,11 +91,11 @@ static void merge_sort(uint8_t array[], int length) void encrypt_ctx(char *buf, int len, struct rc4_state *ctx) { if (ctx != NULL) { - rc4_crypt(ctx, (unsigned char*) buf, (unsigned char*) buf, len); + rc4_crypt(ctx, (uint8_t*) buf, (uint8_t*) buf, len); } else { char *end = buf + len; while (buf < end) { - *buf = (char)enc_ctx.table.encrypt_table[(uint8_t)*buf]; + *buf = (char)enc_conf.ctx.table.encrypt_table[(uint8_t)*buf]; buf++; } } @@ -138,45 +103,48 @@ void encrypt_ctx(char *buf, int len, struct rc4_state *ctx) { void decrypt_ctx(char *buf, int len, struct rc4_state *ctx) { if (ctx != NULL) { - rc4_crypt(ctx, (unsigned char*) buf, (unsigned char*) buf, len); + rc4_crypt(ctx, (uint8_t*) buf, (uint8_t*) buf, len); } else { char *end = buf + len; while (buf < end) { - *buf = (char)enc_ctx.table.decrypt_table[(uint8_t)*buf]; + *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_ctx.rc4.key; - int key_len = enc_ctx.rc4.key_len; + uint8_t *key = enc_conf.ctx.rc4.key; + int key_len = enc_conf.ctx.rc4.key_len; rc4_init(ctx, key, key_len); } -void enc_key_init(const char *pass) { - enc_ctx.rc4.key_len = 16; - enc_ctx.rc4.key = malloc(16); - md5((const unsigned char*)pass, enc_ctx.rc4.key); +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); } -void get_table(const char *pass) { +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; uint32_t i; - md5((const unsigned char*)pass, digest); + md5((const uint8_t*)pass, digest); + *key = 0; for (i = 0; i < 8; i++) { - _a += 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) { - _i = i; + *salt = i; merge_sort(enc_table, 256); } for(i = 0; i < 256; ++i) { @@ -184,6 +152,19 @@ void get_table(const char *pass) { dec_table[enc_table[i]] = i; } - enc_ctx.table.encrypt_table = enc_table; - enc_ctx.table.decrypt_table = dec_table; + enc_conf.ctx.table.encrypt_table = enc_table; + enc_conf.ctx.table.decrypt_table = dec_table; +} + +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; + } + if (enc_conf.method == TABLE) { + enc_table_init(pass); + } else if (enc_conf.method == RC4) { + enc_rc4_init(pass); + } } + diff --git a/encrypt.h b/encrypt.h index b08edfb3..87310b3c 100755 --- a/encrypt.h +++ b/encrypt.h @@ -14,27 +14,27 @@ #define TABLE 0 #define RC4 1 -union { - struct { - unsigned char *encrypt_table; - unsigned char *decrypt_table; - } table; - - struct { - unsigned char *key; - int key_len; - } rc4; -} enc_ctx; - -void get_table(const char* key); +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_key_init(const char *pass); - -unsigned int _i; -unsigned long long _a; -int _method; +void enc_conf_init(const char *pass, const char *method); #define LOGD(...) ((void)fprintf(stdout, __VA_ARGS__)) #define LOGE(...) ((void)fprintf(stderr, __VA_ARGS__)) diff --git a/local.c b/local.c index 3eeaf2ac..31d25a4c 100755 --- a/local.c +++ b/local.c @@ -33,15 +33,8 @@ #define EWOULDBLOCK EAGAIN #endif -#define MAX_SERVER_NUM 10 - #define min(a,b) (((a)<(b))?(a):(b)) -static char *_servers[MAX_SERVER_NUM]; -static int _server_num; -static char *_remote_port; -static int _timeout; - int setnonblocking(int fd) { int flags; if (-1 ==(flags = fcntl(fd, F_GETFL, 0))) @@ -232,9 +225,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { inet_aton("0.0.0.0", &sin_addr); memcpy(server->buf, &response, 4); - memcpy(server->buf + 4, &sin_addr, sizeof(struct in_addr)); - *((unsigned short *)(server->buf + 4 + sizeof(struct in_addr))) - = (unsigned short) htons(atoi(_remote_port)); + memset(server->buf + 4, 0, sizeof(struct in_addr) + sizeof(unsigned short)); int reply_size = 4 + sizeof(struct in_addr) + sizeof(unsigned short); int r = send(server->fd, server->buf, reply_size, 0); @@ -445,7 +436,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { } } -struct remote* new_remote(int fd) { +struct remote* new_remote(int fd, int timeout) { struct remote *remote; remote = malloc(sizeof(struct remote)); remote->recv_ctx = malloc(sizeof(struct remote_ctx)); @@ -453,7 +444,7 @@ struct remote* new_remote(int fd) { remote->fd = fd; 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); - ev_timer_init(&remote->send_ctx->watcher, remote_timeout_cb, _timeout, 0); + ev_timer_init(&remote->send_ctx->watcher, remote_timeout_cb, timeout, 0); remote->recv_ctx->remote = remote; remote->recv_ctx->connected = 0; remote->send_ctx->remote = remote; @@ -494,7 +485,7 @@ struct server* new_server(int fd) { server->send_ctx->server = server; server->send_ctx->connected = 0; server->stage = 0; - if (_method == RC4) { + 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); @@ -511,7 +502,7 @@ void free_server(struct server *server) { if (server->remote != NULL) { server->remote->server = NULL; } - if (_method == RC4) { + if (enc_conf.method == RC4) { free(server->e_ctx); free(server->d_ctx); } @@ -545,8 +536,8 @@ static void accept_cb (EV_P_ ev_io *w, int revents) memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - int index = clock() % _server_num; - int err = getaddrinfo(_servers[index], _remote_port, &hints, &res); + int index = clock() % listener->remote_num; + int err = getaddrinfo(listener->remote_host[index], listener->remote_port, &hints, &res); if (err) { perror("getaddrinfo"); close_and_free_server(EV_A_ server); @@ -563,7 +554,7 @@ static void accept_cb (EV_P_ ev_io *w, int revents) } struct timeval timeout; - timeout.tv_sec = _timeout; + timeout.tv_sec = listener->timeout; timeout.tv_usec = 0; err = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); @@ -573,7 +564,7 @@ static void accept_cb (EV_P_ ev_io *w, int revents) if (err) perror("setsockopt"); setnonblocking(sockfd); - struct remote *remote = new_remote(sockfd); + struct remote *remote = new_remote(sockfd, listener->timeout); server->remote = remote; remote->server = server; connect(sockfd, res->ai_addr, res->ai_addrlen); @@ -589,30 +580,77 @@ static void print_usage() { printf("usage: ss -s server_host -p server_port -l local_port\n"); printf(" -k password [-m encrypt_method] [-f pid_file]\n"); printf("\n"); - printf("info:\n"); + printf("options:\n"); printf(" encrypt_method: table, rc4\n"); printf(" pid_file: valid path to the pid file\n"); } +static void demonize(const char* path) { + + /* Our process ID and Session ID */ + pid_t pid, sid; + + /* Fork off the parent process */ + pid = fork(); + if (pid < 0) { + exit(EXIT_FAILURE); + } + + /* If we got a good PID, then + we can exit the parent process. */ + if (pid > 0) { + FILE *file = fopen(path, "w"); + fprintf(file, "%d", pid); + fclose(file); + exit(EXIT_SUCCESS); + } + + /* Change the file mode mask */ + umask(0); + + /* Open any logs here */ + + /* Create a new SID for the child process */ + sid = setsid(); + if (sid < 0) { + /* Log the failure */ + exit(EXIT_FAILURE); + } + + /* Change the current working directory */ + if ((chdir("/")) < 0) { + /* Log the failure */ + exit(EXIT_FAILURE); + } + + /* Close out the standard file descriptors */ + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + +} + int main (int argc, char **argv) { - char *remote_port = NULL; char *port = NULL; - char *key = NULL; + char *password = NULL; char *timeout = "10"; char *method = NULL; int c; int f_flags = 0; char *f_path = NULL; + int remote_num = 0; + char *remote_host[MAX_REMOTE_NUM]; + char *remote_port = NULL; + opterr = 0; - _server_num = 0; while ((c = getopt (argc, argv, "f:s:p:l:k:t:m:")) != -1) { switch (c) { case 's': - _servers[_server_num++] = strdup(optarg); + remote_host[remote_num++] = optarg; break; case 'p': remote_port = optarg; @@ -621,7 +659,7 @@ int main (int argc, char **argv) port = optarg; break; case 'k': - key = optarg; + password = optarg; break; case 'f': f_flags = 1; @@ -636,8 +674,8 @@ int main (int argc, char **argv) } } - if (_server_num == 0 || remote_port == NULL || - port == NULL || key == NULL) { + if (remote_num == 0 || remote_port == NULL || + port == NULL || password == NULL) { print_usage(); exit(EXIT_FAILURE); } @@ -649,68 +687,17 @@ int main (int argc, char **argv) exit(EXIT_FAILURE); } - /* Our process ID and Session ID */ - pid_t pid, sid; + demonize(f_path); - /* Fork off the parent process */ - pid = fork(); - if (pid < 0) { - exit(EXIT_FAILURE); - } - /* If we got a good PID, then - we can exit the parent process. */ - if (pid > 0) { - FILE *file = fopen(f_path, "w"); - fprintf(file, "%d", pid); - fclose(file); - exit(EXIT_SUCCESS); - } - - /* Change the file mode mask */ - umask(0); - - /* Open any logs here */ - - /* Create a new SID for the child process */ - sid = setsid(); - if (sid < 0) { - /* Log the failure */ - exit(EXIT_FAILURE); - } - - - /* Change the current working directory */ - if ((chdir("/")) < 0) { - /* Log the failure */ - exit(EXIT_FAILURE); - } - - /* Close out the standard file descriptors */ - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); } signal(SIGPIPE, SIG_IGN); - // init global variables - _remote_port = strdup(remote_port); - _timeout = atoi(timeout); - _method = TABLE; - if (method != NULL) { - if (strcmp(method, "rc4") == 0) { - _method = RC4; - } - } - + // Setup keys LOGD("calculating ciphers\n"); + enc_conf_init(password, method); - if (_method == RC4) { - enc_key_init(key); - } else { - get_table(key); - } - + // Setup socket int listenfd; listenfd = create_and_bind(port); if (listenfd < 0) { @@ -721,11 +708,21 @@ int main (int argc, char **argv) LOGE("listen() error.\n"); return 1; } + setnonblocking(listenfd); LOGD("server listening at port %s\n", port); - setnonblocking(listenfd); + // Setup proxy context struct listen_ctx listen_ctx; + listen_ctx.remote_num = remote_num; + listen_ctx.remote_host = malloc(sizeof(char *) * remote_num); + while (remote_num > 0) { + int index = --remote_num; + listen_ctx.remote_host[index] = strdup(remote_host[index]); + } + listen_ctx.remote_port = strdup(remote_port); + listen_ctx.timeout = atoi(timeout); listen_ctx.fd = listenfd; + struct ev_loop *loop = ev_default_loop(0); if (!loop) { return 1; diff --git a/local.h b/local.h index 2d153f72..305b6e77 100644 --- a/local.h +++ b/local.h @@ -4,8 +4,14 @@ #include #include "encrypt.h" +#define MAX_REMOTE_NUM 10 + struct listen_ctx { ev_io io; + char **remote_host; + int remote_num; + char *remote_port; + int timeout; int fd; struct sockaddr sock; }; @@ -50,7 +56,7 @@ 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); -struct remote* new_remote(int fd); +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);