diff --git a/src/encrypt.c b/src/encrypt.c index 419788c2..a33a93d4 100644 --- a/src/encrypt.c +++ b/src/encrypt.c @@ -153,6 +153,7 @@ char* ss_encrypt(char *plaintext, ssize_t *len, struct enc_ctx *ctx) { if (ctx != NULL) { int c_len = *len + BLOCK_SIZE; int iv_len = 0; + int err = 0; char *ciphertext = malloc(max(iv_len + c_len, BUF_SIZE)); if (!ctx->init) { @@ -170,9 +171,15 @@ char* ss_encrypt(char *plaintext, ssize_t *len, struct enc_ctx *ctx) { #endif } - EVP_EncryptUpdate(&ctx->evp, (uint8_t*)(ciphertext+iv_len), + err = EVP_EncryptUpdate(&ctx->evp, (uint8_t*)(ciphertext+iv_len), &c_len, (const uint8_t *)plaintext, *len); + if (!err) { + free(ciphertext); + free(plaintext); + return NULL; + } + #ifdef DEBUG dump("PLAIN", plaintext); dump("CIPHER", ciphertext); @@ -195,6 +202,7 @@ char* ss_decrypt(char *ciphertext, ssize_t *len, struct enc_ctx *ctx) { if (ctx != NULL) { int p_len = *len + BLOCK_SIZE; int iv_len = 0; + int err = 0; char *plaintext = malloc(max(p_len, BUF_SIZE)); if (!ctx->init) { @@ -208,9 +216,15 @@ char* ss_decrypt(char *ciphertext, ssize_t *len, struct enc_ctx *ctx) { #endif } - EVP_DecryptUpdate(&ctx->evp, (uint8_t*)plaintext, &p_len, + err = EVP_DecryptUpdate(&ctx->evp, (uint8_t*)plaintext, &p_len, (const uint8_t*)(ciphertext + iv_len), *len - iv_len); + if (!err) { + free(ciphertext); + free(plaintext); + return NULL; + } + #ifdef DEBUG dump("PLAIN", plaintext); dump("CIPHER", ciphertext); @@ -234,20 +248,24 @@ void enc_ctx_init(int method, struct enc_ctx *ctx, int enc) { if (cipher == NULL) { LOGE("Cipher %s not found in OpenSSL library", supported_ciphers[method]); FATAL("Cannot initialize cipher"); - return; } memset(ctx, 0, sizeof(struct enc_ctx)); EVP_CIPHER_CTX *evp = &ctx->evp; EVP_CIPHER_CTX_init(evp); - EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc); + if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc)) { + LOGE("Cannot initialize cipher %s", supported_ciphers[method]); + exit(EXIT_FAILURE); + } if (!EVP_CIPHER_CTX_set_key_length(evp, enc_key_len)) { EVP_CIPHER_CTX_cleanup(evp); LOGE("Invalid key length: %d", enc_key_len); exit(EXIT_FAILURE); } - EVP_CIPHER_CTX_set_padding(evp, 1); + if (method > RC4) { + EVP_CIPHER_CTX_set_padding(evp, 1); + } } void enc_key_init(int method, const char *pass) { diff --git a/src/local.c b/src/local.c index faa9ae05..305939e4 100644 --- a/src/local.c +++ b/src/local.c @@ -139,6 +139,12 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { // local socks5 server if (server->stage == 5) { remote->buf = ss_encrypt(remote->buf, &r, server->e_ctx); + if (remote->buf == NULL) { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } int s = send(remote->fd, remote->buf, r, 0); if(s == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -243,6 +249,12 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { addr_to_send = ss_encrypt(addr_to_send, &addr_len, server->e_ctx); + if (addr_to_send == NULL) { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } int s = send(remote->fd, addr_to_send, addr_len, 0); free(addr_to_send); @@ -374,6 +386,12 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { } server->buf = ss_decrypt(server->buf, &r, server->d_ctx); + if (server->buf == NULL) { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } int s = send(server->fd, server->buf, r, 0); if (s == -1) { @@ -487,7 +505,9 @@ void free_remote(struct remote *remote) { if (remote->server != NULL) { remote->server->remote = NULL; } - free(remote->buf); + if (remote->buf) { + free(remote->buf); + } free(remote->recv_ctx); free(remote->send_ctx); free(remote); @@ -545,7 +565,9 @@ void free_server(struct server *server) { EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); free(server->d_ctx); } - free(server->buf); + if (server->buf) { + free(server->buf); + } free(server->recv_ctx); free(server->send_ctx); free(server); @@ -714,6 +736,7 @@ int main (int argc, char **argv) { // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); + signal(SIGABRT, SIG_IGN); // Setup keys LOGD("initialize cihpers... %s", method); diff --git a/src/redir.c b/src/redir.c index d6f80fcb..bd3de626 100644 --- a/src/redir.c +++ b/src/redir.c @@ -132,6 +132,12 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { } remote->buf = ss_encrypt(remote->buf, &r, server->e_ctx); + if (remote->buf == NULL) { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } int s = send(remote->fd, remote->buf, r, 0); if(s == -1) { @@ -252,6 +258,12 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { } server->buf = ss_decrypt(server->buf, &r, server->d_ctx); + if (server->buf == NULL) { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } int s = send(server->fd, server->buf, r, 0); if (s == -1) { @@ -304,6 +316,12 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) { memcpy(addr_to_send + addr_len, &server->destaddr.sin_port, 2); addr_len += 2; addr_to_send = ss_encrypt(addr_to_send, &addr_len, server->e_ctx); + if (addr_to_send == NULL) { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } int s = send(remote->fd, addr_to_send, addr_len, 0); free(addr_to_send); @@ -390,7 +408,9 @@ void free_remote(struct remote *remote) { if (remote->server != NULL) { remote->server->remote = NULL; } - free(remote->buf); + if (remote->buf != NULL) { + free(remote->buf); + } free(remote->recv_ctx); free(remote->send_ctx); free(remote); @@ -447,7 +467,9 @@ void free_server(struct server *server) { EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); free(server->d_ctx); } - free(server->buf); + if (server->buf != NULL) { + free(server->buf); + } free(server->recv_ctx); free(server->send_ctx); free(server); @@ -615,6 +637,7 @@ int main (int argc, char **argv) { // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); + signal(SIGABRT, SIG_IGN); // Setup keys LOGD("calculating ciphers..."); diff --git a/src/server.c b/src/server.c index ef747ca3..2c33d0af 100644 --- a/src/server.c +++ b/src/server.c @@ -191,6 +191,13 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { *buf = ss_decrypt(*buf, &r, server->d_ctx); + if (*buf == NULL) { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + // handshake and transmit data if (server->stage == 5) { int s = send(remote->fd, remote->buf, r, 0); @@ -262,7 +269,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) { } if (offset == 0) { - LOGE("incorrect header with length %zu", r); + LOGE("invalid header with length %zu", r); close_and_free_server(EV_A_ server); return; } @@ -495,6 +502,14 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) { } server->buf = ss_encrypt(server->buf, &r, server->e_ctx); + + if (server->buf == NULL) { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + int s = send(server->fd, server->buf, r, 0); if (s == -1) { @@ -630,7 +645,9 @@ void free_remote(struct remote *remote) { if (remote->server != NULL) { remote->server->remote = NULL; } - free(remote->buf); + if (remote->buf != NULL) { + free(remote->buf); + } free(remote->recv_ctx); free(remote->send_ctx); free(remote); @@ -697,7 +714,9 @@ void free_server(struct server *server) { EVP_CIPHER_CTX_cleanup(&server->d_ctx->evp); free(server->d_ctx); } - free(server->buf); + if (server->buf != NULL) { + free(server->buf); + } free(server->recv_ctx); free(server->send_ctx); free(server); @@ -831,6 +850,7 @@ int main (int argc, char **argv) { // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); + signal(SIGABRT, SIG_IGN); // setup asyncns asyncns_t *asyncns;