From b655fb2b8f43a46ef5c24487be0923caae871466 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Mon, 20 Feb 2017 10:29:32 +0800 Subject: [PATCH] Replace nonce cache with a ping-pong bloom filter (#1282) * Add Ping-Pong bloom filter * Refine bloom filter insertion * Reduce the error rate to 0.00001 * Avoid alignment issue in murmurhash2 * Fix a memory leak * Fix build on non-GPU targets * Detect get_current_dir_name in configure * Update README.md * Remove redudant bfree() * Reduce the memory usage for local client * Fix #1275 * Refine #1275 * Use IP when bypassing SNI domains * Also apply replay detector on UDP traffic * Update deb build script Now build script is able to auto detect system and choose libraries necessary to build. Also update the README accordingly. * Update build script to enable jessie/stretch etc Also include a few cleanup that simplified pkg installation from backports repository. --- .gitmodules | 4 ++ Makefile.am | 5 ++- configure.ac | 3 +- libbloom | 1 + src/Makefile.am | 5 ++- src/aead.c | 38 ++++++++++--------- src/crypto.c | 12 +++--- src/crypto.h | 2 +- src/jconf.c | 4 +- src/jconf.h | 1 - src/local.c | 9 +++-- src/manager.c | 19 ++-------- src/manager.h | 1 - src/ppbloom.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ppbloom.h | 31 ++++++++++++++++ src/redir.c | 5 ++- src/server.c | 5 ++- src/stream.c | 44 +++++++++++----------- src/tunnel.c | 7 +++- 19 files changed, 217 insertions(+), 77 deletions(-) create mode 160000 libbloom create mode 100644 src/ppbloom.c create mode 100644 src/ppbloom.h diff --git a/.gitmodules b/.gitmodules index 77612e09..bf4d6cac 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,3 +6,7 @@ path = libipset url = https://github.com/shadowsocks/ipset.git ignore = dirty +[submodule "libbloom"] + path = libbloom + url = https://github.com/shadowsocks/libbloom.git + ignore = dirty diff --git a/Makefile.am b/Makefile.am index 06af285c..c836452c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ if USE_SYSTEM_SHARED_LIB -SUBDIRS = src +SUBDIRS = src libbloom else -SUBDIRS = libcork libipset src +SUBDIRS = libcork libipset libbloom src endif if ENABLE_DOCUMENTATION @@ -14,6 +14,7 @@ pkgconfiglibdir = $(libdir)/pkgconfig pkgconfiglib_DATA = shadowsocks-libev.pc EXTRA_DIST = acl Changes completions debian docker rpm README.md +EXTRA_DIST += libbloom EXTRA_DIST += libcork/include libipset/include EXTRA_DIST += libipset/src/libipset/map/inspection-template.c.in EXTRA_DIST += libipset/src/libipset/set/inspection-template.c.in diff --git a/configure.ac b/configure.ac index bd03c597..f8fa1de9 100755 --- a/configure.ac +++ b/configure.ac @@ -230,7 +230,8 @@ AC_CHECK_LIB([ev], [ev_loop_destroy], [LIBS="-lev $LIBS"], [AC_MSG_ERROR([Couldn AC_CONFIG_FILES([shadowsocks-libev.pc Makefile - src/Makefile]) + src/Makefile + libbloom/Makefile]) AM_COND_IF([USE_SYSTEM_SHARED_LIB], [AC_DEFINE([USE_SYSTEM_SHARED_LIB], [1], [Define if use system shared lib.])], diff --git a/libbloom b/libbloom new file mode 160000 index 00000000..f6e53fe6 --- /dev/null +++ b/libbloom @@ -0,0 +1 @@ +Subproject commit f6e53fe6486c40b751b58e6e8e516aeb6247e493 diff --git a/src/Makefile.am b/src/Makefile.am index 955fb570..4d383186 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,7 @@ VERSION_INFO = 2:0:0 AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations -fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE AM_CFLAGS += $(PTHREAD_CFLAGS) +AM_CFLAGS += -I$(top_srcdir)/libbloom if !USE_SYSTEM_SHARED_LIB AM_CFLAGS += -I$(top_srcdir)/libipset/include AM_CFLAGS += -I$(top_srcdir)/libcork/include @@ -9,6 +10,7 @@ endif AM_CFLAGS += $(LIBPCRE_CFLAGS) SS_COMMON_LIBS = $(INET_NTOP_LIB) $(LIBPCRE_LIBS) +SS_COMMON_LIBS += $(top_builddir)/libbloom/libbloom.la if !USE_SYSTEM_SHARED_LIB SS_COMMON_LIBS += $(top_builddir)/libipset/libipset.la \ $(top_builddir)/libcork/libcork.la @@ -26,6 +28,7 @@ sni_src = http.c \ crypto_src = crypto.c \ aead.c \ stream.c \ + ppbloom.c \ base64.c plugin_src = plugin.c @@ -112,6 +115,6 @@ libshadowsocks_libev_la_LIBADD = $(ss_local_LDADD) include_HEADERS = shadowsocks.h noinst_HEADERS = acl.h crypto.h stream.h aead.h json.h netutils.h redir.h server.h tls.h uthash.h \ - cache.h http.h local.h plugin.h resolv.h tunnel.h utils.h base64.h \ + cache.h http.h local.h plugin.h resolv.h tunnel.h utils.h base64.h ppbloom.h \ common.h jconf.h manager.h protocol.h rule.h socks5.h udprelay.h EXTRA_DIST = ss-nat diff --git a/src/aead.c b/src/aead.c index a397dd36..d32665e2 100644 --- a/src/aead.c +++ b/src/aead.c @@ -33,7 +33,7 @@ #include #include -#include "cache.h" +#include "ppbloom.h" #include "aead.h" #include "utils.h" @@ -405,13 +405,11 @@ aead_encrypt_all(buffer_t *plaintext, cipher_t *cipher, size_t capacity) (uint8_t *)plaintext->data, plaintext->len, NULL, 0, cipher_ctx.nonce, cipher_ctx.skey); - if (err) { - bfree(plaintext); - aead_ctx_release(&cipher_ctx); + aead_ctx_release(&cipher_ctx); + + if (err) return CRYPTO_ERROR; - } - aead_ctx_release(&cipher_ctx); assert(ciphertext->len == clen); brealloc(plaintext, salt_len + ciphertext->len, capacity); @@ -444,6 +442,11 @@ aead_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity) uint8_t *salt = cipher_ctx.salt; memcpy(salt, ciphertext->data, salt_len); + if (ppbloom_check((void *)salt, salt_len) == 1) { + LOGE("crypto: AEAD: repeat salt detected"); + return CRYPTO_ERROR; + } + aead_cipher_ctx_set_key(&cipher_ctx, 0); size_t plen = plaintext->len; @@ -453,13 +456,12 @@ aead_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity) ciphertext->len - salt_len, NULL, 0, cipher_ctx.nonce, cipher_ctx.skey); - if (err) { - bfree(ciphertext); - aead_ctx_release(&cipher_ctx); + aead_ctx_release(&cipher_ctx); + + if (err) return CRYPTO_ERROR; - } - aead_ctx_release(&cipher_ctx); + ppbloom_add((void *)salt, salt_len); brealloc(ciphertext, plaintext->len, capacity); memcpy(ciphertext->data, plaintext->data, plaintext->len); @@ -488,6 +490,7 @@ aead_chunk_encrypt(cipher_ctx_t *ctx, uint8_t *p, uint8_t *c, NULL, 0, n, ctx->skey); if (err) return CRYPTO_ERROR; + assert(clen == CHUNK_SIZE_LEN + tlen); sodium_increment(n, nlen); @@ -497,6 +500,7 @@ aead_chunk_encrypt(cipher_ctx_t *ctx, uint8_t *p, uint8_t *c, NULL, 0, n, ctx->skey); if (err) return CRYPTO_ERROR; + assert(clen == plen + tlen); sodium_increment(n, nlen); @@ -634,12 +638,9 @@ aead_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity) aead_cipher_ctx_set_key(cipher_ctx, 0); - if (cache_key_exist(nonce_cache, (char *)cipher_ctx->salt, salt_len)) { + if (ppbloom_check((void *)cipher_ctx->salt, salt_len) == 1) { LOGE("crypto: AEAD: repeat salt detected"); - bfree(ciphertext); return CRYPTO_ERROR; - } else { - cache_insert(nonce_cache, (char *)cipher_ctx->salt, salt_len, NULL); } memmove(cipher_ctx->chunk->data, cipher_ctx->chunk->data + salt_len, @@ -647,6 +648,10 @@ aead_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity) cipher_ctx->chunk->len -= salt_len; cipher_ctx->init = 1; + + } else if (cipher_ctx->init == 1) { + ppbloom_add((void *)cipher_ctx->salt, salt_len); + cipher_ctx->init = 2; } size_t plen = 0; @@ -685,9 +690,6 @@ aead_key_init(int method, const char *pass, const char *key) return NULL; } - // Initialize cache - cache_create(&nonce_cache, 1024, NULL); - cipher_t *cipher = (cipher_t *)ss_malloc(sizeof(cipher_t)); memset(cipher, 0, sizeof(cipher_t)); diff --git a/src/crypto.c b/src/crypto.c index 8ad31943..99a14f9c 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -29,13 +29,11 @@ #include #include "base64.h" -#include "cache.h" #include "crypto.h" #include "stream.h" #include "aead.h" #include "utils.h" - -struct cache *nonce_cache; +#include "ppbloom.h" int balloc(buffer_t *ptr, size_t capacity) @@ -111,8 +109,12 @@ crypto_init(const char *password, const char *key, const char *method) FATAL("Failed to initialize sodium"); } - // Initialize NONCE cache - cache_create(&nonce_cache, 1024, NULL); + // Initialize NONCE bloom filter +#ifdef MODULE_REMOTE + ppbloom_init(1000000, 0.00001); +#else + ppbloom_init(100000, 0.0000001); +#endif if (method != NULL) { for (i = 0; i < STREAM_CIPHER_NUM; i++) diff --git a/src/crypto.h b/src/crypto.h index 2bfad654..2376fcc1 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -84,7 +84,7 @@ typedef struct { } cipher_t; typedef struct { - uint8_t init; + uint32_t init; uint64_t counter; cipher_evp_t *evp; cipher_t *cipher; diff --git a/src/jconf.c b/src/jconf.c index c1b0ca47..f9690826 100644 --- a/src/jconf.c +++ b/src/jconf.c @@ -223,9 +223,7 @@ read_jconf(const char *file) "invalid config file: option 'reuse_port' must be a boolean"); conf.reuse_port = value->u.boolean; } else if (strcmp(name, "auth") == 0) { - check_json_value_type(value, json_boolean, - "invalid config file: option 'auth' must be a boolean"); - conf.auth = value->u.boolean; + FATAL("One time auth has been deprecated. Try AEAD ciphers instead."); } else if (strcmp(name, "nofile") == 0) { check_json_value_type(value, json_integer, "invalid config file: option 'nofile' must be an integer"); diff --git a/src/jconf.h b/src/jconf.h index 89cb1744..891f6168 100644 --- a/src/jconf.h +++ b/src/jconf.h @@ -59,7 +59,6 @@ typedef struct { char *user; char *plugin; char *plugin_opts; - int auth; int fast_open; int reuse_port; int nofile; diff --git a/src/local.c b/src/local.c index 346b6ae3..5e68a891 100644 --- a/src/local.c +++ b/src/local.c @@ -676,7 +676,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents) struct sockaddr_storage storage; memset(&storage, 0, sizeof(struct sockaddr_storage)); #ifndef ANDROID - if (sni_detected || atyp == 3) + if (atyp == 3) err = get_sockaddr(host, port, &storage, 0, ipv6first); else #endif @@ -1211,10 +1211,10 @@ main(int argc, char **argv) USE_TTY(); #ifdef ANDROID - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUvV6", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUvV6A", long_options, NULL)) != -1) { #else - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUv6", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:n:huUv6A", long_options, NULL)) != -1) { #endif switch (c) { @@ -1309,6 +1309,9 @@ main(int argc, char **argv) vpn = 1; break; #endif + case 'A': + FATAL("One time auth has been deprecated. Try AEAD ciphers instead."); + break; case '?': // The option character is not recognized. LOGE("Unrecognized option: %s", optarg); diff --git a/src/manager.c b/src/manager.c index f4b61534..eb46b736 100644 --- a/src/manager.c +++ b/src/manager.c @@ -151,10 +151,6 @@ construct_command_line(struct manager_ctx *manager, struct server *server) int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " -u"); } - if (manager->auth) { - int len = strlen(cmd); - snprintf(cmd + len, BUF_SIZE - len, " -A"); - } if (manager->fast_open) { int len = strlen(cmd); snprintf(cmd + len, BUF_SIZE - len, " --fast-open"); @@ -884,7 +880,6 @@ main(int argc, char **argv) char *plugin = NULL; char *plugin_opts = NULL; - int auth = 0; int fast_open = 0; int reuse_port = 0; int mode = TCP_ONLY; @@ -999,14 +994,14 @@ main(int argc, char **argv) case 'h': usage(); exit(EXIT_SUCCESS); - case 'A': - auth = 1; - break; #ifdef HAVE_SETRLIMIT case 'n': nofile = atoi(optarg); break; #endif + case 'A': + FATAL("One time auth has been deprecated. Try AEAD ciphers instead."); + break; case '?': // The option character is not recognized. LOGE("Unrecognized option: %s", optarg); @@ -1047,9 +1042,6 @@ main(int argc, char **argv) if (conf->nameserver != NULL) { nameservers[nameserver_num++] = conf->nameserver; } - if (auth == 0) { - auth = conf->auth; - } if (mode == TCP_ONLY) { mode = conf->mode; } @@ -1107,10 +1099,6 @@ main(int argc, char **argv) #endif } - if (auth) { - LOGI("onetime authentication enabled"); - } - // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); @@ -1130,7 +1118,6 @@ main(int argc, char **argv) manager.fast_open = fast_open; manager.verbose = verbose; manager.mode = mode; - manager.auth = auth; manager.password = password; manager.timeout = timeout; manager.method = method; diff --git a/src/manager.h b/src/manager.h index 6ecf6735..978bf37e 100644 --- a/src/manager.h +++ b/src/manager.h @@ -38,7 +38,6 @@ struct manager_ctx { int reuse_port; int verbose; int mode; - int auth; char *password; char *key; char *timeout; diff --git a/src/ppbloom.c b/src/ppbloom.c new file mode 100644 index 00000000..0ef5b95d --- /dev/null +++ b/src/ppbloom.c @@ -0,0 +1,98 @@ +/* + * ppbloom.c - Ping-Pong Bloom Filter for nonce reuse detection + * + * Copyright (C) 2013 - 2017, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#include +#include + +#include "bloom.h" +#include "ppbloom.h" +#include "utils.h" + +#define PING 0 +#define PONG 1 + +static struct bloom ppbloom[2]; +static int bloom_count[2]; +static int current; +static int entries; +static double error; + +int +ppbloom_init(int n, double e) +{ + int err; + entries = n / 2; + error = e; + + err = bloom_init(ppbloom + PING, entries, error); + if (err) return err; + + err = bloom_init(ppbloom + PONG, entries, error); + if (err) return err; + + bloom_count[PING] = 0; + bloom_count[PONG] = 0; + + current = PING; + + return 0; +} + +int +ppbloom_check(const void *buffer, int len) +{ + int ret; + + ret = bloom_check(ppbloom + PING, buffer, len); + if (ret) return ret; + + ret = bloom_check(ppbloom + PONG, buffer, len); + if (ret) return ret; + + return 0; +} + +int +ppbloom_add(const void *buffer, int len) +{ + int err; + err = bloom_add(ppbloom + current, buffer, len); + if (err == -1) return err; + + bloom_count[current]++; + + if (bloom_count[current] >= entries) { + bloom_count[current] = 0; + current = current == PING ? PONG : PING; + bloom_free(ppbloom + current); + bloom_init(ppbloom + current, entries, error); + } + + return 0; +} + +void +ppbloom_free() +{ + bloom_free(ppbloom + PING); + bloom_free(ppbloom + PONG); +} diff --git a/src/ppbloom.h b/src/ppbloom.h new file mode 100644 index 00000000..855a78d5 --- /dev/null +++ b/src/ppbloom.h @@ -0,0 +1,31 @@ +/* + * ppbloom.h - Define the Ping-Pong Bloom Filter interface + * + * Copyright (C) 2013 - 2017, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifndef _PPBLOOM_ +#define _PPBLOOM_ + +int ppbloom_init(int entries, double error); +int ppbloom_check(const void * buffer, int len); +int ppbloom_add(const void * buffer, int len); +void ppbloom_free(void); + +#endif diff --git a/src/redir.c b/src/redir.c index 410b1f94..84c5969a 100644 --- a/src/redir.c +++ b/src/redir.c @@ -818,7 +818,7 @@ main(int argc, char **argv) USE_TTY(); - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUv6", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUv6A", long_options, NULL)) != -1) { switch (c) { case GETOPT_VAL_MTU: @@ -897,6 +897,9 @@ main(int argc, char **argv) case '6': ipv6first = 1; break; + case 'A': + FATAL("One time auth has been deprecated. Try AEAD ciphers instead."); + break; case '?': // The option character is not recognized. LOGE("Unrecognized option: %s", optarg); diff --git a/src/server.c b/src/server.c index 8a5cef0c..e492b167 100644 --- a/src/server.c +++ b/src/server.c @@ -1384,7 +1384,7 @@ main(int argc, char **argv) USE_TTY(); - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:b:c:i:d:a:n:huUv6", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:b:c:i:d:a:n:huUv6A", long_options, NULL)) != -1) { switch (c) { case GETOPT_VAL_FAST_OPEN: @@ -1477,6 +1477,9 @@ main(int argc, char **argv) case '6': ipv6first = 1; break; + case 'A': + FATAL("One time auth has been deprecated. Try AEAD ciphers instead."); + break; case '?': // The option character is not recognized. LOGE("Unrecognized option: %s", optarg); diff --git a/src/stream.c b/src/stream.c index e9aa35d5..5ea30dd4 100644 --- a/src/stream.c +++ b/src/stream.c @@ -31,7 +31,7 @@ #include -#include "cache.h" +#include "ppbloom.h" #include "stream.h" #include "utils.h" @@ -321,11 +321,10 @@ stream_encrypt_all(buffer_t *plaintext, cipher_t *cipher, size_t capacity) plaintext->len); } - if (err) { - bfree(plaintext); - stream_ctx_release(&cipher_ctx); + stream_ctx_release(&cipher_ctx); + + if (err) return CRYPTO_ERROR; - } #ifdef SS_DEBUG dump("PLAIN", plaintext->data, plaintext->len); @@ -333,8 +332,6 @@ stream_encrypt_all(buffer_t *plaintext, cipher_t *cipher, size_t capacity) dump("NONCE", ciphertext->data, nonce_len); #endif - stream_ctx_release(&cipher_ctx); - brealloc(plaintext, nonce_len + ciphertext->len, capacity); memcpy(plaintext->data, ciphertext->data, nonce_len + ciphertext->len); plaintext->len = nonce_len + ciphertext->len; @@ -430,6 +427,12 @@ stream_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity) uint8_t *nonce = cipher_ctx.nonce; memcpy(nonce, ciphertext->data, nonce_len); + + if (ppbloom_check((void *)nonce, nonce_len) == 1) { + LOGE("crypto: stream: repeat IV detected"); + return CRYPTO_ERROR; + } + cipher_ctx_set_nonce(&cipher_ctx, nonce, nonce_len, 0); if (cipher->method >= SALSA20) { @@ -443,11 +446,10 @@ stream_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity) ciphertext->len - nonce_len); } - if (err) { - bfree(ciphertext); - stream_ctx_release(&cipher_ctx); + stream_ctx_release(&cipher_ctx); + + if (err) return CRYPTO_ERROR; - } #ifdef SS_DEBUG dump("PLAIN", plaintext->data, plaintext->len); @@ -455,7 +457,7 @@ stream_decrypt_all(buffer_t *ciphertext, cipher_t *cipher, size_t capacity) dump("NONCE", ciphertext->data, nonce_len); #endif - stream_ctx_release(&cipher_ctx); + ppbloom_add((void *)nonce, nonce_len); brealloc(ciphertext, plaintext->len, capacity); memcpy(ciphertext->data, plaintext->data, plaintext->len); @@ -468,7 +470,7 @@ int stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity) { if (cipher_ctx == NULL) - return -1; + return CRYPTO_ERROR; cipher_t *cipher = cipher_ctx->cipher; @@ -511,14 +513,16 @@ stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity) cipher_ctx->init = 1; if (cipher->method >= RC4_MD5) { - if (cache_key_exist(nonce_cache, (char *)nonce, nonce_len)) { + if (ppbloom_check((void *)nonce, nonce_len) == 1) { LOGE("crypto: stream: repeat IV detected"); - bfree(ciphertext); - return -1; - } else { - cache_insert(nonce_cache, (char *)nonce, nonce_len, NULL); + return CRYPTO_ERROR; } } + } else if (cipher_ctx->init == 1) { + if (cipher->method >= RC4_MD5) { + ppbloom_add((void *)cipher_ctx->nonce, cipher->nonce_len); + cipher_ctx->init = 2; + } } if (ciphertext->len <= 0) @@ -550,10 +554,8 @@ stream_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity) ciphertext->len); } - if (err) { - bfree(ciphertext); + if (err) return CRYPTO_ERROR; - } #ifdef SS_DEBUG dump("PLAIN", plaintext->data, plaintext->len); diff --git a/src/tunnel.c b/src/tunnel.c index 79d1216a..098478a5 100644 --- a/src/tunnel.c +++ b/src/tunnel.c @@ -766,10 +766,10 @@ main(int argc, char **argv) USE_TTY(); #ifdef ANDROID - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUvV6", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUvV6A", long_options, NULL)) != -1) { #else - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUv6", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:n:huUv6A", long_options, NULL)) != -1) { #endif switch (c) { @@ -860,6 +860,9 @@ main(int argc, char **argv) vpn = 1; break; #endif + case 'A': + FATAL("One time auth has been deprecated. Try AEAD ciphers instead."); + break; case '?': // The option character is not recognized. LOGE("Unrecognized option: %s", optarg);