mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-20 21:43:41 +00:00
Add --key option to set key directly (#1207)
This commit is contained in:
@@ -45,8 +45,14 @@ Set the local port number.
|
||||
Not available in server nor manager mode.
|
||||
|
||||
-k <password>::
|
||||
--password <password>::
|
||||
Set the password. The server and the client should use the same password.
|
||||
|
||||
--key <key_in_base64>::
|
||||
Set the key directly. The key should be encoded with URL-safe Base64.
|
||||
+
|
||||
Not available in manager mode.
|
||||
|
||||
-m <encrypt_method>::
|
||||
Set the cipher.
|
||||
+
|
||||
|
||||
@@ -15,6 +15,7 @@ SYNOPSIS
|
||||
[-a <user_name>] [-b <local_address] [-n <nofile>]
|
||||
[--fast-open] [--reuse-port] [--acl <acl_config>] [--mtu <MTU>]
|
||||
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
|
||||
[--password <password>] [--key <key_in_base64]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -40,8 +41,12 @@ Set the server's port number.
|
||||
Set the local port number.
|
||||
|
||||
-k <password>::
|
||||
--password <password>::
|
||||
Set the password. The server and the client should use the same password.
|
||||
|
||||
--key <key_in_base64>::
|
||||
Set the key directly. The key should be encoded with URL-safe Base64.
|
||||
|
||||
-m <encrypt_method>::
|
||||
Set the cipher.
|
||||
+
|
||||
|
||||
@@ -14,6 +14,7 @@ SYNOPSIS
|
||||
[-t <timeout>] [-c <config_file>] [-b <local_address>]
|
||||
[-a <user_name>] [-n <nofile>] [--mtu <MTU>]
|
||||
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
|
||||
[--password <password>] [--key <key_in_base64]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -40,8 +41,11 @@ Set the server's port number.
|
||||
Set the local port number.
|
||||
|
||||
-k <password>::
|
||||
Set the password. The server and the client should use the same
|
||||
password.
|
||||
--password <password>::
|
||||
Set the password. The server and the client should use the same password.
|
||||
|
||||
--key <key_in_base64>::
|
||||
Set the key directly. The key should be encoded with URL-safe Base64.
|
||||
|
||||
-m <encrypt_method>::
|
||||
Set the cipher.
|
||||
|
||||
@@ -17,6 +17,7 @@ SYNOPSIS
|
||||
[--acl <acl_config>] [--mtu <MTU>]
|
||||
[--manager-address <path_to_unix_domain>]
|
||||
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
|
||||
[--password <password>] [--key <key_in_base64]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -38,8 +39,12 @@ Set the server's hostname or IP.
|
||||
Set the server's port number.
|
||||
|
||||
-k <password>::
|
||||
--password <password>::
|
||||
Set the password. The server and the client should use the same password.
|
||||
|
||||
--key <key_in_base64>::
|
||||
Set the key directly. The key should be encoded with URL-safe Base64.
|
||||
|
||||
-m <encrypt_method>::
|
||||
Set the cipher.
|
||||
+
|
||||
|
||||
@@ -15,6 +15,7 @@ SYNOPSIS
|
||||
[-b <local_addr>] [-a <user_name>] [-n <nofile>]
|
||||
[-L addr:port] [--mtu <MTU>] [--mptcp] [--reuse-port]
|
||||
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
|
||||
[--key <key_in_base64>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -40,8 +41,12 @@ Set the server's port number.
|
||||
Set the local port number.
|
||||
|
||||
-k <password>::
|
||||
--password <password>::
|
||||
Set the password. The server and the client should use the same password.
|
||||
|
||||
--key <key_in_base64>::
|
||||
Set the key directly. The key should be encoded with URL-safe Base64.
|
||||
|
||||
-m <encrypt_method>::
|
||||
Set the cipher.
|
||||
+
|
||||
|
||||
+2
-2
@@ -30,11 +30,11 @@ AC_DEFUN([ss_SODIUM],
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
|
||||
#include <sodium.h>
|
||||
], [
|
||||
#if SODIUM_LIBRARY_VERSION_MAJOR < 9
|
||||
#if SODIUM_LIBRARY_VERSION_MAJOR < 8
|
||||
# error
|
||||
#endif
|
||||
])],
|
||||
[AC_MSG_RESULT([checking for version of libsodium... yes])],
|
||||
[AC_MSG_ERROR([Wrong libsodium: version >= 1.0.9 required])])
|
||||
[AC_MSG_ERROR([Wrong libsodium: version >= 1.0.8 required])])
|
||||
|
||||
])
|
||||
|
||||
+3
-2
@@ -25,7 +25,8 @@ sni_src = http.c \
|
||||
|
||||
crypto_src = crypto.c \
|
||||
aead.c \
|
||||
stream.c
|
||||
stream.c \
|
||||
base64.c
|
||||
|
||||
plugin_src = plugin.c
|
||||
|
||||
@@ -111,6 +112,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 \
|
||||
cache.h http.h local.h plugin.h resolv.h tunnel.h utils.h base64.h \
|
||||
common.h jconf.h manager.h protocol.h rule.h socks5.h udprelay.h
|
||||
EXTRA_DIST = ss-nat
|
||||
|
||||
+10
-6
@@ -138,7 +138,6 @@ dump(char *tag, char *text, int len)
|
||||
printf("0x%02x ", (uint8_t)text[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char *supported_aead_ciphers[AEAD_CIPHER_NUM] = {
|
||||
@@ -691,7 +690,7 @@ aead_decrypt(buffer_t *ciphertext, cipher_ctx_t *cipher_ctx, size_t capacity)
|
||||
}
|
||||
|
||||
cipher_t *
|
||||
aead_key_init(int method, const char *pass)
|
||||
aead_key_init(int method, const char *pass, const char *key)
|
||||
{
|
||||
if (method < AES128GCM || method >= AEAD_CIPHER_NUM) {
|
||||
LOGE("aead_key_init(): Illegal method");
|
||||
@@ -724,8 +723,12 @@ aead_key_init(int method, const char *pass)
|
||||
FATAL("Cannot initialize cipher");
|
||||
}
|
||||
|
||||
cipher->key_len = crypto_derive_key(cipher, pass, cipher->key,
|
||||
supported_aead_ciphers_key_size[method], 2);
|
||||
if (key != NULL)
|
||||
cipher->key_len = crypto_parse_key(key, cipher->key,
|
||||
supported_aead_ciphers_key_size[method]);
|
||||
else
|
||||
cipher->key_len = crypto_derive_key(key, cipher->key,
|
||||
supported_aead_ciphers_key_size[method]);
|
||||
|
||||
if (cipher->key_len == 0) {
|
||||
FATAL("Cannot generate key and nonce");
|
||||
@@ -739,7 +742,7 @@ aead_key_init(int method, const char *pass)
|
||||
}
|
||||
|
||||
cipher_t *
|
||||
aead_init(const char *pass, const char *method)
|
||||
aead_init(const char *pass, const char *key, const char *method)
|
||||
{
|
||||
int m = AES128GCM;
|
||||
if (method != NULL) {
|
||||
@@ -753,5 +756,6 @@ aead_init(const char *pass, const char *method)
|
||||
m = AES256GCM;
|
||||
}
|
||||
}
|
||||
return aead_key_init(m, pass);
|
||||
return aead_key_init(m, pass, key);
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -41,6 +41,7 @@ int aead_decrypt(buffer_t *, cipher_ctx_t *, size_t);
|
||||
|
||||
void aead_ctx_init(cipher_t *, cipher_ctx_t *, int);
|
||||
void aead_ctx_release(cipher_ctx_t *);
|
||||
cipher_t *aead_init(const char *pass, const char *method);
|
||||
|
||||
cipher_t *aead_init(const char *pass, const char *key, const char *method);
|
||||
|
||||
#endif // _AEAD_H
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Base64 encode/decode
|
||||
* @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
/* ---------------- private code */
|
||||
static const uint8_t map2[] =
|
||||
{
|
||||
0xff, 0xff, 0x3e, 0xff, 0xff, 0x34, 0x35, 0x36,
|
||||
0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
|
||||
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
|
||||
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
|
||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
|
||||
0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x1a, 0x1b,
|
||||
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
|
||||
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
|
||||
};
|
||||
|
||||
int base64_decode(uint8_t *out, const char *in, int out_size)
|
||||
{
|
||||
int i, v;
|
||||
uint8_t *dst = out;
|
||||
|
||||
v = 0;
|
||||
for (i = 0; in[i] && in[i] != '='; i++) {
|
||||
unsigned int index = in[i] - 43;
|
||||
if (index >= sizeof(map2) || map2[index] == 0xff)
|
||||
return -1;
|
||||
v = (v << 6) + map2[index];
|
||||
if (i & 3) {
|
||||
if (dst - out < out_size) {
|
||||
*dst++ = v >> (6 - 2 * (i & 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dst - out;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* b64_encode: Stolen from VLC's http.c.
|
||||
* Simplified by Michael.
|
||||
* Fixed edge cases and made it work from data (vs. strings) by Ryan.
|
||||
*****************************************************************************/
|
||||
|
||||
char *base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
|
||||
{
|
||||
static const char b64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
char *ret, *dst;
|
||||
unsigned i_bits = 0;
|
||||
int i_shift = 0;
|
||||
int bytes_remaining = in_size;
|
||||
|
||||
if (in_size >= UINT_MAX / 4 ||
|
||||
out_size < BASE64_SIZE(in_size))
|
||||
return NULL;
|
||||
ret = dst = out;
|
||||
while (bytes_remaining) {
|
||||
i_bits = (i_bits << 8) + *in++;
|
||||
bytes_remaining--;
|
||||
i_shift += 8;
|
||||
|
||||
do {
|
||||
*dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
|
||||
i_shift -= 6;
|
||||
} while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
|
||||
}
|
||||
while ((dst - ret) & 3)
|
||||
*dst++ = '=';
|
||||
*dst = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Decode a base64-encoded string.
|
||||
*
|
||||
* @param out buffer for decoded data
|
||||
* @param in null-terminated input string
|
||||
* @param out_size size in bytes of the out buffer, must be at
|
||||
* least 3/4 of the length of in
|
||||
* @return number of bytes written, or a negative value in case of
|
||||
* invalid input
|
||||
*/
|
||||
int base64_decode(uint8_t *out, const char *in, int out_size);
|
||||
|
||||
/**
|
||||
* Encode data to base64 and null-terminate.
|
||||
*
|
||||
* @param out buffer for encoded data
|
||||
* @param out_size size in bytes of the output buffer, must be at
|
||||
* least BASE64_SIZE(in_size)
|
||||
* @param in_size size in bytes of the 'in' buffer
|
||||
* @return 'out' or NULL in case of error
|
||||
*/
|
||||
char *base64_encode(char *out, int out_size, const uint8_t *in, int in_size);
|
||||
|
||||
/**
|
||||
* Calculate the output size needed to base64-encode x bytes.
|
||||
*/
|
||||
#define BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)
|
||||
|
||||
#endif /* BASE64_H */
|
||||
@@ -67,6 +67,8 @@ enum {
|
||||
GETOPT_VAL_MPTCP,
|
||||
GETOPT_VAL_PLUGIN,
|
||||
GETOPT_VAL_PLUGIN_OPTS,
|
||||
GETOPT_VAL_PASSWORD,
|
||||
GETOPT_VAL_KEY,
|
||||
GETOPT_VAL_MANAGER_ADDRESS,
|
||||
GETOPT_VAL_EXECUTABLE
|
||||
};
|
||||
|
||||
+76
-63
@@ -28,6 +28,7 @@
|
||||
#include <sodium.h>
|
||||
#include <mbedtls/md5.h>
|
||||
|
||||
#include "base64.h"
|
||||
#include "cache.h"
|
||||
#include "crypto.h"
|
||||
#include "stream.h"
|
||||
@@ -100,66 +101,8 @@ crypto_md5(const unsigned char *d, size_t n, unsigned char *md)
|
||||
return md;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_derive_key(const cipher_t *cipher, const char *pass,
|
||||
uint8_t *key, size_t nkey, int version)
|
||||
{
|
||||
if (version == 2) {
|
||||
const unsigned char salt[crypto_pwhash_SALTBYTES] = {
|
||||
's', 'h', 'a', 'd', 'o', 'w', 's', 'o',
|
||||
'c', 'k', 's', ' ', 'h', 'a', 's', 'h'
|
||||
};
|
||||
int err = crypto_pwhash (key, nkey, (char*)pass, strlen(pass), salt,
|
||||
crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE,
|
||||
crypto_pwhash_ALG_DEFAULT);
|
||||
if (err)
|
||||
FATAL("Out of memory when doing password hashing");
|
||||
else
|
||||
return nkey;
|
||||
}
|
||||
|
||||
size_t datal;
|
||||
datal = strlen((const char *)pass);
|
||||
|
||||
const digest_type_t *md = mbedtls_md_info_from_string("MD5");
|
||||
if (md == NULL) {
|
||||
FATAL("MD5 Digest not found in crypto library");
|
||||
}
|
||||
|
||||
mbedtls_md_context_t c;
|
||||
unsigned char md_buf[MAX_MD_SIZE];
|
||||
int addmd;
|
||||
unsigned int i, j, mds;
|
||||
|
||||
mds = mbedtls_md_get_size(md);
|
||||
memset(&c, 0, sizeof(mbedtls_md_context_t));
|
||||
|
||||
if (pass == NULL)
|
||||
return nkey;
|
||||
if (mbedtls_md_setup(&c, md, 1))
|
||||
return 0;
|
||||
|
||||
for (j = 0, addmd = 0; j < nkey; addmd++) {
|
||||
mbedtls_md_starts(&c);
|
||||
if (addmd) {
|
||||
mbedtls_md_update(&c, md_buf, mds);
|
||||
}
|
||||
mbedtls_md_update(&c, (uint8_t *)pass, datal);
|
||||
mbedtls_md_finish(&c, &(md_buf[0]));
|
||||
|
||||
for (i = 0; i < mds; i++, j++) {
|
||||
if (j >= nkey)
|
||||
break;
|
||||
key[j] = md_buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_md_free(&c);
|
||||
return nkey;
|
||||
}
|
||||
|
||||
crypto_t *
|
||||
crypto_init(const char *password, const char *method)
|
||||
crypto_init(const char *password, const char *key, const char *method)
|
||||
{
|
||||
int i, m = -1;
|
||||
|
||||
@@ -178,7 +121,7 @@ crypto_init(const char *password, const char *method)
|
||||
break;
|
||||
}
|
||||
if (m != -1) {
|
||||
cipher_t *cipher = stream_init(password, method);
|
||||
cipher_t *cipher = stream_init(password, key, method);
|
||||
if (cipher == NULL)
|
||||
return NULL;
|
||||
crypto_t *crypto = (crypto_t *)malloc(sizeof(crypto_t));
|
||||
@@ -189,7 +132,7 @@ crypto_init(const char *password, const char *method)
|
||||
.encrypt = &stream_encrypt,
|
||||
.decrypt = &stream_decrypt,
|
||||
.ctx_init = &stream_ctx_init,
|
||||
.ctx_release = &stream_ctx_release
|
||||
.ctx_release = &stream_ctx_release,
|
||||
};
|
||||
memcpy(crypto, &tmp, sizeof(crypto_t));
|
||||
return crypto;
|
||||
@@ -201,7 +144,7 @@ crypto_init(const char *password, const char *method)
|
||||
break;
|
||||
}
|
||||
if (m != -1) {
|
||||
cipher_t *cipher = aead_init(password, method);
|
||||
cipher_t *cipher = aead_init(password, key, method);
|
||||
if (cipher == NULL)
|
||||
return NULL;
|
||||
crypto_t *crypto = (crypto_t *)ss_malloc(sizeof(crypto_t));
|
||||
@@ -212,7 +155,7 @@ crypto_init(const char *password, const char *method)
|
||||
.encrypt = &aead_encrypt,
|
||||
.decrypt = &aead_decrypt,
|
||||
.ctx_init = &aead_ctx_init,
|
||||
.ctx_release = &aead_ctx_release
|
||||
.ctx_release = &aead_ctx_release,
|
||||
};
|
||||
memcpy(crypto, &tmp, sizeof(crypto_t));
|
||||
return crypto;
|
||||
@@ -222,3 +165,73 @@ crypto_init(const char *password, const char *method)
|
||||
LOGE("invalid cipher name: %s", method);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_derive_key(const char *pass, uint8_t *key, size_t key_len)
|
||||
{
|
||||
size_t datal;
|
||||
datal = strlen((const char *)pass);
|
||||
|
||||
const digest_type_t *md = mbedtls_md_info_from_string("MD5");
|
||||
if (md == NULL) {
|
||||
FATAL("MD5 Digest not found in crypto library");
|
||||
}
|
||||
|
||||
mbedtls_md_context_t c;
|
||||
unsigned char md_buf[MAX_MD_SIZE];
|
||||
int addmd;
|
||||
unsigned int i, j, mds;
|
||||
|
||||
mds = mbedtls_md_get_size(md);
|
||||
memset(&c, 0, sizeof(mbedtls_md_context_t));
|
||||
|
||||
if (pass == NULL)
|
||||
return key_len;
|
||||
if (mbedtls_md_setup(&c, md, 1))
|
||||
return 0;
|
||||
|
||||
for (j = 0, addmd = 0; j < key_len; addmd++) {
|
||||
mbedtls_md_starts(&c);
|
||||
if (addmd) {
|
||||
mbedtls_md_update(&c, md_buf, mds);
|
||||
}
|
||||
mbedtls_md_update(&c, (uint8_t *)pass, datal);
|
||||
mbedtls_md_finish(&c, &(md_buf[0]));
|
||||
|
||||
for (i = 0; i < mds; i++, j++) {
|
||||
if (j >= key_len)
|
||||
break;
|
||||
key[j] = md_buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_md_free(&c);
|
||||
return key_len;
|
||||
}
|
||||
|
||||
int
|
||||
crypto_parse_key(const char *base64, uint8_t *key, size_t key_len)
|
||||
{
|
||||
size_t base64_len = strlen(base64);
|
||||
int out_len = BASE64_SIZE(base64_len);
|
||||
uint8_t out[out_len];
|
||||
|
||||
out_len = base64_decode(out, base64, out_len);
|
||||
if (out_len > 0 && out_len >= key_len) {
|
||||
memcpy(key, out, key_len);
|
||||
#ifdef DEBUG
|
||||
dump("KEY", (char*)key, key_len);
|
||||
#endif
|
||||
return key_len;
|
||||
}
|
||||
|
||||
out_len = BASE64_SIZE(key_len);
|
||||
char out_key[out_len];
|
||||
rand_bytes(key, key_len);
|
||||
base64_encode(out_key, out_len, key, key_len);
|
||||
LOGE("Invalid key for your chosen cipher!");
|
||||
LOGE("It requires a %zu-byte key encoded with URL-safe Base64", key_len);
|
||||
LOGE("Generating a new random key: %s", out_key);
|
||||
FATAL("Please use the key above or input a valid key");
|
||||
return key_len;
|
||||
}
|
||||
|
||||
+10
-10
@@ -100,17 +100,17 @@ typedef struct crypto {
|
||||
void(*const ctx_release)(cipher_ctx_t *);
|
||||
} crypto_t;
|
||||
|
||||
int balloc(buffer_t *ptr, size_t capacity);
|
||||
int brealloc(buffer_t *ptr, size_t len, size_t capacity);
|
||||
int bprepend(buffer_t *dst, buffer_t *src, size_t capacity);
|
||||
void bfree(buffer_t *ptr);
|
||||
int rand_bytes(void *output, int len);
|
||||
int balloc(buffer_t *, size_t);
|
||||
int brealloc(buffer_t *, size_t, size_t);
|
||||
int bprepend(buffer_t *, buffer_t *, size_t);
|
||||
void bfree(buffer_t *);
|
||||
int rand_bytes(void *, int);
|
||||
|
||||
crypto_t *crypto_init(const char *password, const char *method);
|
||||
unsigned char *crypto_md5(const unsigned char *d, size_t n,
|
||||
unsigned char *md);
|
||||
int crypto_derive_key(const cipher_t *cipher, const char *pass,
|
||||
uint8_t *key, size_t nkey, int version);
|
||||
crypto_t *crypto_init(const char *, const char *, const char *);
|
||||
unsigned char *crypto_md5(const unsigned char *, size_t, unsigned char *);
|
||||
|
||||
int crypto_derive_key(const char *, uint8_t *, size_t);
|
||||
int crypto_parse_key(const char *, uint8_t *, size_t);
|
||||
|
||||
extern struct cache *nonce_cache;
|
||||
extern const char *supported_stream_ciphers[];
|
||||
|
||||
@@ -198,6 +198,8 @@ read_jconf(const char *file)
|
||||
conf.local_port = to_string(value);
|
||||
} else if (strcmp(name, "password") == 0) {
|
||||
conf.password = to_string(value);
|
||||
} else if (strcmp(name, "key") == 0) {
|
||||
conf.key = to_string(value);
|
||||
} else if (strcmp(name, "method") == 0) {
|
||||
conf.method = to_string(value);
|
||||
} else if (strcmp(name, "timeout") == 0) {
|
||||
|
||||
@@ -53,6 +53,7 @@ typedef struct {
|
||||
char *local_addr;
|
||||
char *local_port;
|
||||
char *password;
|
||||
char *key;
|
||||
char *method;
|
||||
char *timeout;
|
||||
char *user;
|
||||
|
||||
+13
-3
@@ -1173,6 +1173,7 @@ main(int argc, char **argv)
|
||||
char *local_port = NULL;
|
||||
char *local_addr = NULL;
|
||||
char *password = NULL;
|
||||
char *key = NULL;
|
||||
char *timeout = NULL;
|
||||
char *method = NULL;
|
||||
char *pid_path = NULL;
|
||||
@@ -1199,6 +1200,8 @@ main(int argc, char **argv)
|
||||
{ "mptcp", no_argument, NULL, GETOPT_VAL_MPTCP },
|
||||
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
|
||||
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
|
||||
{ "password", required_argument, NULL, GETOPT_VAL_PASSWORD },
|
||||
{ "key", required_argument, NULL, GETOPT_VAL_KEY },
|
||||
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
@@ -1236,6 +1239,9 @@ main(int argc, char **argv)
|
||||
case GETOPT_VAL_PLUGIN_OPTS:
|
||||
plugin_opts = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_KEY:
|
||||
key = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_REUSE_PORT:
|
||||
reuse_port = 1;
|
||||
break;
|
||||
@@ -1251,6 +1257,7 @@ main(int argc, char **argv)
|
||||
case 'l':
|
||||
local_port = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_PASSWORD:
|
||||
case 'k':
|
||||
password = optarg;
|
||||
break;
|
||||
@@ -1339,6 +1346,9 @@ main(int argc, char **argv)
|
||||
if (password == NULL) {
|
||||
password = conf->password;
|
||||
}
|
||||
if (key == NULL) {
|
||||
key = conf->key;
|
||||
}
|
||||
if (method == NULL) {
|
||||
method = conf->method;
|
||||
}
|
||||
@@ -1380,7 +1390,7 @@ main(int argc, char **argv)
|
||||
#ifndef HAVE_LAUNCHD
|
||||
local_port == NULL ||
|
||||
#endif
|
||||
password == NULL) {
|
||||
(password == NULL && key == NULL)) {
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -1464,7 +1474,7 @@ main(int argc, char **argv)
|
||||
|
||||
// Setup keys
|
||||
LOGI("initializing ciphers... %s", method);
|
||||
crypto = crypto_init(password, method);
|
||||
crypto = crypto_init(password, key, method);
|
||||
if (crypto == NULL)
|
||||
FATAL("failed to initialize ciphers");
|
||||
|
||||
@@ -1645,7 +1655,7 @@ start_ss_local_server(profile_t profile)
|
||||
|
||||
// Setup keys
|
||||
LOGI("initializing ciphers... %s", method);
|
||||
crypto = crypto_init(password, method);
|
||||
crypto = crypto_init(password, NULL, method);
|
||||
if (crypto == NULL)
|
||||
FATAL("failed to init ciphers");
|
||||
|
||||
|
||||
@@ -910,6 +910,7 @@ main(int argc, char **argv)
|
||||
{ "mtu", required_argument, NULL, GETOPT_VAL_MTU },
|
||||
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
|
||||
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
|
||||
{ "password", required_argument, NULL, GETOPT_VAL_PASSWORD },
|
||||
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
@@ -950,6 +951,7 @@ main(int argc, char **argv)
|
||||
server_host[server_num++] = optarg;
|
||||
}
|
||||
break;
|
||||
case GETOPT_VAL_PASSWORD:
|
||||
case 'k':
|
||||
password = optarg;
|
||||
break;
|
||||
|
||||
@@ -40,6 +40,7 @@ struct manager_ctx {
|
||||
int mode;
|
||||
int auth;
|
||||
char *password;
|
||||
char *key;
|
||||
char *timeout;
|
||||
char *method;
|
||||
char *iface;
|
||||
|
||||
+13
-3
@@ -786,6 +786,7 @@ main(int argc, char **argv)
|
||||
char *local_port = NULL;
|
||||
char *local_addr = NULL;
|
||||
char *password = NULL;
|
||||
char *key = NULL;
|
||||
char *timeout = NULL;
|
||||
char *method = NULL;
|
||||
char *pid_path = NULL;
|
||||
@@ -807,6 +808,8 @@ main(int argc, char **argv)
|
||||
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
|
||||
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
|
||||
{ "reuse-port", no_argument, NULL, GETOPT_VAL_REUSE_PORT },
|
||||
{ "password", required_argument, NULL, GETOPT_VAL_PASSWORD },
|
||||
{ "key", required_argument, NULL, GETOPT_VAL_KEY },
|
||||
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
@@ -832,6 +835,9 @@ main(int argc, char **argv)
|
||||
case GETOPT_VAL_PLUGIN_OPTS:
|
||||
plugin_opts = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_KEY:
|
||||
key = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_REUSE_PORT:
|
||||
reuse_port = 1;
|
||||
break;
|
||||
@@ -847,6 +853,7 @@ main(int argc, char **argv)
|
||||
case 'l':
|
||||
local_port = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_PASSWORD:
|
||||
case 'k':
|
||||
password = optarg;
|
||||
break;
|
||||
@@ -928,6 +935,9 @@ main(int argc, char **argv)
|
||||
if (password == NULL) {
|
||||
password = conf->password;
|
||||
}
|
||||
if (key == NULL) {
|
||||
key = conf->key;
|
||||
}
|
||||
if (method == NULL) {
|
||||
method = conf->method;
|
||||
}
|
||||
@@ -962,8 +972,8 @@ main(int argc, char **argv)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (remote_num == 0 || remote_port == NULL ||
|
||||
local_port == NULL || password == NULL) {
|
||||
if (remote_num == 0 || remote_port == NULL || local_port == NULL
|
||||
|| (password == NULL && key == NULL)) {
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -1044,7 +1054,7 @@ main(int argc, char **argv)
|
||||
|
||||
// Setup keys
|
||||
LOGI("initializing ciphers... %s", method);
|
||||
crypto = crypto_init(password, method);
|
||||
crypto = crypto_init(password, key, method);
|
||||
if (crypto == NULL)
|
||||
FATAL("failed to initialize ciphers");
|
||||
|
||||
|
||||
+13
-2
@@ -1338,6 +1338,7 @@ main(int argc, char **argv)
|
||||
int mtu = 0;
|
||||
char *user = NULL;
|
||||
char *password = NULL;
|
||||
char *key = NULL;
|
||||
char *timeout = NULL;
|
||||
char *method = NULL;
|
||||
char *pid_path = NULL;
|
||||
@@ -1364,6 +1365,8 @@ main(int argc, char **argv)
|
||||
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
|
||||
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
|
||||
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
|
||||
{ "password", required_argument, NULL, GETOPT_VAL_PASSWORD },
|
||||
{ "key", required_argument, NULL, GETOPT_VAL_KEY },
|
||||
#ifdef __linux__
|
||||
{ "mptcp", no_argument, NULL, GETOPT_VAL_MPTCP },
|
||||
#endif
|
||||
@@ -1401,6 +1404,9 @@ main(int argc, char **argv)
|
||||
mptcp = 1;
|
||||
LOGI("enable multipath TCP");
|
||||
break;
|
||||
case GETOPT_VAL_KEY:
|
||||
key = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_REUSE_PORT:
|
||||
reuse_port = 1;
|
||||
break;
|
||||
@@ -1415,6 +1421,7 @@ main(int argc, char **argv)
|
||||
case 'p':
|
||||
server_port = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_PASSWORD:
|
||||
case 'k':
|
||||
password = optarg;
|
||||
break;
|
||||
@@ -1495,6 +1502,9 @@ main(int argc, char **argv)
|
||||
if (password == NULL) {
|
||||
password = conf->password;
|
||||
}
|
||||
if (key == NULL) {
|
||||
key = conf->key;
|
||||
}
|
||||
if (method == NULL) {
|
||||
method = conf->method;
|
||||
}
|
||||
@@ -1542,7 +1552,8 @@ main(int argc, char **argv)
|
||||
server_host[server_num++] = NULL;
|
||||
}
|
||||
|
||||
if (server_num == 0 || server_port == NULL || password == NULL) {
|
||||
if (server_num == 0 || server_port == NULL
|
||||
|| (password == NULL && key == NULL)) {
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -1621,7 +1632,7 @@ main(int argc, char **argv)
|
||||
|
||||
// setup keys
|
||||
LOGI("initializing ciphers... %s", method);
|
||||
crypto = crypto_init(password, method);
|
||||
crypto = crypto_init(password, key, method);
|
||||
if (crypto == NULL)
|
||||
FATAL("failed to initialize ciphers");
|
||||
|
||||
|
||||
+8
-5
@@ -598,7 +598,7 @@ stream_ctx_release(cipher_ctx_t *cipher_ctx)
|
||||
}
|
||||
|
||||
cipher_t *
|
||||
stream_key_init(int method, const char *pass)
|
||||
stream_key_init(int method, const char *pass, const char *key)
|
||||
{
|
||||
if (method <= TABLE || method >= STREAM_CIPHER_NUM) {
|
||||
LOGE("cipher->key_init(): Illegal method");
|
||||
@@ -623,8 +623,10 @@ stream_key_init(int method, const char *pass)
|
||||
FATAL("Cannot initialize cipher");
|
||||
}
|
||||
|
||||
cipher->key_len = crypto_derive_key(cipher, pass,
|
||||
cipher->key, cipher_key_size(cipher), 1);
|
||||
if (key != NULL)
|
||||
cipher->key_len = crypto_parse_key(key, cipher->key, cipher_key_size(cipher));
|
||||
else
|
||||
cipher->key_len = crypto_derive_key(pass, cipher->key, cipher_key_size(cipher));
|
||||
|
||||
if (cipher->key_len == 0) {
|
||||
FATAL("Cannot generate key and NONCE");
|
||||
@@ -640,7 +642,7 @@ stream_key_init(int method, const char *pass)
|
||||
}
|
||||
|
||||
cipher_t *
|
||||
stream_init(const char *pass, const char *method)
|
||||
stream_init(const char *pass, const char *key, const char *method)
|
||||
{
|
||||
int m = TABLE;
|
||||
if (method != NULL) {
|
||||
@@ -657,5 +659,6 @@ stream_init(const char *pass, const char *method)
|
||||
LOGE("Table is deprecated");
|
||||
return NULL;
|
||||
}
|
||||
return stream_key_init(m, pass);
|
||||
return stream_key_init(m, pass, key);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -47,6 +47,6 @@ int stream_decrypt(buffer_t *, cipher_ctx_t *, size_t);
|
||||
void stream_ctx_init(cipher_t *, cipher_ctx_t *, int);
|
||||
void stream_ctx_release(cipher_ctx_t *);
|
||||
|
||||
cipher_t *stream_init(const char *pass, const char *method);
|
||||
cipher_t *stream_init(const char *pass, const char *key, const char *method);
|
||||
|
||||
#endif // _STREAM_H
|
||||
|
||||
+13
-3
@@ -729,6 +729,7 @@ main(int argc, char **argv)
|
||||
char *local_port = NULL;
|
||||
char *local_addr = NULL;
|
||||
char *password = NULL;
|
||||
char *key = NULL;
|
||||
char *timeout = NULL;
|
||||
char *method = NULL;
|
||||
char *pid_path = NULL;
|
||||
@@ -754,6 +755,8 @@ main(int argc, char **argv)
|
||||
{ "plugin", required_argument, NULL, GETOPT_VAL_PLUGIN },
|
||||
{ "plugin-opts", required_argument, NULL, GETOPT_VAL_PLUGIN_OPTS },
|
||||
{ "reuse-port", no_argument, NULL, GETOPT_VAL_REUSE_PORT },
|
||||
{ "password", required_argument, NULL, GETOPT_VAL_PASSWORD },
|
||||
{ "key", required_argument, NULL, GETOPT_VAL_KEY },
|
||||
{ "help", no_argument, NULL, GETOPT_VAL_HELP },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
@@ -784,6 +787,9 @@ main(int argc, char **argv)
|
||||
case GETOPT_VAL_PLUGIN_OPTS:
|
||||
plugin_opts = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_KEY:
|
||||
key = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_REUSE_PORT:
|
||||
reuse_port = 1;
|
||||
break;
|
||||
@@ -799,6 +805,7 @@ main(int argc, char **argv)
|
||||
case 'l':
|
||||
local_port = optarg;
|
||||
break;
|
||||
case GETOPT_VAL_PASSWORD:
|
||||
case 'k':
|
||||
password = optarg;
|
||||
break;
|
||||
@@ -891,6 +898,9 @@ main(int argc, char **argv)
|
||||
if (password == NULL) {
|
||||
password = conf->password;
|
||||
}
|
||||
if (key == NULL) {
|
||||
key = conf->key;
|
||||
}
|
||||
if (method == NULL) {
|
||||
method = conf->method;
|
||||
}
|
||||
@@ -928,8 +938,8 @@ main(int argc, char **argv)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (remote_num == 0 || remote_port == NULL || tunnel_addr_str == NULL ||
|
||||
local_port == NULL || password == NULL) {
|
||||
if (remote_num == 0 || remote_port == NULL || tunnel_addr_str == NULL
|
||||
|| local_port == NULL || (password == NULL && key == NULL)) {
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -1017,7 +1027,7 @@ main(int argc, char **argv)
|
||||
|
||||
// Setup keys
|
||||
LOGI("initializing ciphers... %s", method);
|
||||
crypto = crypto_init(password, method);
|
||||
crypto = crypto_init(password, key, method);
|
||||
if (crypto == NULL)
|
||||
FATAL("failed to initialize ciphers");
|
||||
|
||||
|
||||
@@ -353,6 +353,10 @@ usage()
|
||||
#ifdef __linux__
|
||||
printf(
|
||||
" [--mptcp] Enable Multipath TCP on MPTCP Kernel.\n");
|
||||
#endif
|
||||
#ifndef MODULE_MANAGER
|
||||
printf(
|
||||
" [--key <key_in_base64>] Key of your remote server.\n");
|
||||
#endif
|
||||
printf(
|
||||
" [--plugin <name>] Enable SIP003 plugin. (Experimental)\n");
|
||||
|
||||
Reference in New Issue
Block a user