Browse Source

refine the code structure

pull/4/merge
Max Lv 11 years ago
parent
commit
a7a314ed32
4 changed files with 140 additions and 156 deletions
  1. 91
      encrypt.c
  2. 36
      encrypt.h
  3. 161
      local.c
  4. 8
      local.h

91
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);
}
}

36
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__))

161
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;

8
local.h

@ -4,8 +4,14 @@
#include <ev.h>
#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);

Loading…
Cancel
Save