Browse Source

handle errors in openssl #10

pull/11/head
Max Lv 12 years ago
parent
commit
87c130c9e2
4 changed files with 96 additions and 12 deletions
  1. 28
      src/encrypt.c
  2. 27
      src/local.c
  3. 27
      src/redir.c
  4. 26
      src/server.c

28
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) {

27
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);

27
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...");

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

Loading…
Cancel
Save