Browse Source

Add `--key` option to set key directly (#1207)

pull/1210/head
Max Lv 8 years ago
committed by GitHub
parent
commit
ef0402eb10
25 changed files with 364 additions and 104 deletions
  1. 6
      doc/shadowsocks-libev.asciidoc
  2. 5
      doc/ss-local.asciidoc
  3. 8
      doc/ss-redir.asciidoc
  4. 5
      doc/ss-server.asciidoc
  5. 5
      doc/ss-tunnel.asciidoc
  6. 4
      m4/sodium.m4
  7. 5
      src/Makefile.am
  8. 16
      src/aead.c
  9. 3
      src/aead.h
  10. 106
      src/base64.c
  11. 54
      src/base64.h
  12. 2
      src/common.h
  13. 139
      src/crypto.c
  14. 22
      src/crypto.h
  15. 2
      src/jconf.c
  16. 1
      src/jconf.h
  17. 16
      src/local.c
  18. 2
      src/manager.c
  19. 1
      src/manager.h
  20. 16
      src/redir.c
  21. 15
      src/server.c
  22. 13
      src/stream.c
  23. 2
      src/stream.h
  24. 16
      src/tunnel.c
  25. 4
      src/utils.c

6
doc/shadowsocks-libev.asciidoc

@ -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.
+

5
doc/ss-local.asciidoc

@ -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.
+

8
doc/ss-redir.asciidoc

@ -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.

5
doc/ss-server.asciidoc

@ -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.
+

5
doc/ss-tunnel.asciidoc

@ -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.
+

4
m4/sodium.m4

@ -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])])
])

5
src/Makefile.am

@ -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

16
src/aead.c

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

3
src/aead.h

@ -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
src/base64.c

@ -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;
}

54
src/base64.h

@ -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 */

2
src/common.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
};

139
src/crypto.c

@ -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;
}

22
src/crypto.h

@ -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);
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);
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 *, 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[];

2
src/jconf.c

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

1
src/jconf.h

@ -53,6 +53,7 @@ typedef struct {
char *local_addr;
char *local_port;
char *password;
char *key;
char *method;
char *timeout;
char *user;

16
src/local.c

@ -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");

2
src/manager.c

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

1
src/manager.h

@ -40,6 +40,7 @@ struct manager_ctx {
int mode;
int auth;
char *password;
char *key;
char *timeout;
char *method;
char *iface;

16
src/redir.c

@ -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");

15
src/server.c

@ -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");

13
src/stream.c

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

2
src/stream.h

@ -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

16
src/tunnel.c

@ -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");

4
src/utils.c

@ -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");

Loading…
Cancel
Save