Browse Source

add onetime authentication

pull/390/head
Max Lv 9 years ago
parent
commit
42ee808681
9 changed files with 80 additions and 6 deletions
  1. 5
      README.md
  2. 3
      shadowsocks-libev.8
  3. 10
      src/encrypt.c
  4. 6
      src/encrypt.h
  5. 16
      src/local.c
  6. 12
      src/redir.c
  7. 17
      src/server.c
  8. 14
      src/tunnel.c
  9. 3
      src/utils.c

5
README.md

@ -258,6 +258,11 @@ Usage
[-u] enable udprelay mode,
TPROXY is required in redir mode
[-U] enable UDP relay and disable TCP relay,
not available in local mode
[-A] enable onetime authentication
[-L <addr>:<port>] specify destination server address and port
for local port forwarding,
only available in tunnel mode

3
shadowsocks-libev.8

@ -96,6 +96,9 @@ Setup the name servers for libudns. The default server is fetched from
.B \-u
Enable UDP relay.
.TP
.B \-A
Enable onetime authentication.
.TP
.B \-v
Enable verbose mode.
.TP

10
src/encrypt.c

@ -75,6 +75,7 @@
static uint8_t *enc_table;
static uint8_t *dec_table;
static uint8_t auth_key[ONETIMEAUTH_KEYBYTES];
static uint8_t enc_key[MAX_KEY_LENGTH];
static int enc_key_len;
static int enc_iv_len;
@ -1026,6 +1027,14 @@ static int cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, int *olen,
#endif
}
int ss_onetimeauth(char *auth, char *msg, int msg_len) {
return crypto_onetimeauth((uint8_t *)auth, (uint8_t *)msg, msg_len, auth_key);
}
int ss_onetimeauth_verify(char *auth, char *msg, int msg_len) {
return crypto_onetimeauth_verify((uint8_t *)auth, (uint8_t *)msg, msg_len, auth_key);
}
char * ss_encrypt_all(int buf_size, char *plaintext, ssize_t *len, int method)
{
if (method > TABLE) {
@ -1446,6 +1455,7 @@ int enc_init(const char *pass, const char *method)
} else {
enc_key_init(m, pass);
}
crypto_generichash(auth_key, ONETIMEAUTH_KEYBYTES, (uint8_t *)pass, strlen(pass), NULL, 0);
return m;
}

6
src/encrypt.h

@ -140,6 +140,9 @@ typedef struct {
#define SALSA20 15
#define CHACHA20 16
#define ONETIMEAUTH_BYTES 16U
#define ONETIMEAUTH_KEYBYTES 32U
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define max(a, b) (((a) > (b)) ? (a) : (b))
@ -161,4 +164,7 @@ int enc_get_iv_len(void);
void cipher_context_release(cipher_ctx_t *evp);
unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md);
int ss_onetimeauth(char *auth, char *msg, int msg_len);
int ss_onetimeauth_verify(char *auth, char *msg, int msg_len);
#endif // _ENCRYPT_H

16
src/local.c

@ -94,6 +94,8 @@ static int nofile = 0;
#endif
#endif
static int auth = 0;
static void server_recv_cb(EV_P_ ev_io *w, int revents);
static void server_send_cb(EV_P_ ev_io *w, int revents);
static void remote_recv_cb(EV_P_ ev_io *w, int revents);
@ -470,6 +472,12 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
if (!remote->direct) {
memcpy(remote->buf, ss_addr_to_send, addr_len);
if (auth) {
ss_onetimeauth(remote->buf + addr_len, ss_addr_to_send, addr_len);
addr_len += ONETIMEAUTH_BYTES;
}
if (r > 0) {
memcpy(remote->buf + addr_len, buf, r);
}
@ -921,10 +929,10 @@ int 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:uvV",
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uvVA",
long_options, &option_index)) != -1) {
#else
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uv",
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uvA",
long_options, &option_index)) != -1) {
#endif
switch (c) {
@ -979,6 +987,10 @@ int main(int argc, char **argv)
case 'v':
verbose = 1;
break;
case 'A':
auth = 1;
LOGI("onetime authentication enabled");
break;
#ifdef ANDROID
case 'V':
vpn = 1;

12
src/redir.c

@ -83,6 +83,7 @@ static void close_and_free_server(EV_P_ struct server *server);
int verbose = 0;
static int mode = TCP_ONLY;
static int auth = 0;
int getdestaddr(int fd, struct sockaddr_storage *destaddr)
{
@ -376,6 +377,11 @@ static void remote_send_cb(EV_P_ ev_io *w, int revents)
return;
}
if (auth) {
ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len);
addr_len += ONETIMEAUTH_BYTES;
}
int s = send(remote->fd, ss_addr_to_send, addr_len, 0);
free(ss_addr_to_send);
@ -614,7 +620,7 @@ int main(int argc, char **argv)
opterr = 0;
while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:c:b:a:uUv")) != -1) {
while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:c:b:a:uUvA")) != -1) {
switch (c) {
case 's':
if (remote_num < MAX_REMOTE_NUM) {
@ -659,6 +665,10 @@ int main(int argc, char **argv)
case 'v':
verbose = 1;
break;
case 'A':
auth = 1;
LOGI("onetime authentication enabled");
break;
}
}

17
src/server.c

@ -109,6 +109,7 @@ int verbose = 0;
static int acl = 0;
static int mode = TCP_ONLY;
static int auth = 0;
static int fast_open = 0;
#ifdef HAVE_SETRLIMIT
@ -639,6 +640,16 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
offset += 2;
if (auth) {
if (ss_onetimeauth_verify(server->buf + offset, server->buf, offset)) {
LOGE("authentication error %d", atyp);
report_addr(server->fd);
close_and_free_server(EV_A_ server);
return;
};
offset += ONETIMEAUTH_BYTES;
}
if (verbose) {
LOGI("connect to: %s:%d", host, ntohs(port));
}
@ -1193,7 +1204,7 @@ int main(int argc, char **argv)
USE_TTY();
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:i:d:a:uUv",
while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:i:d:a:uUvA",
long_options, &option_index)) != -1) {
switch (c) {
case 0:
@ -1250,6 +1261,10 @@ int main(int argc, char **argv)
case 'v':
verbose = 1;
break;
case 'A':
auth = 1;
LOGI("onetime authentication enabled");
break;
}
}

14
src/tunnel.c

@ -91,6 +91,7 @@ int vpn = 0;
int verbose = 0;
static int mode = TCP_ONLY;
static int auth = 0;
#ifndef __MINGW32__
static int setnonblocking(int fd)
@ -418,6 +419,11 @@ static void remote_send_cb(EV_P_ ev_io *w, int revents)
return;
}
if (auth) {
ss_onetimeauth(ss_addr_to_send + addr_len, ss_addr_to_send, addr_len);
addr_len += ONETIMEAUTH_BYTES;
}
int s = send(remote->fd, ss_addr_to_send, addr_len, 0);
free(ss_addr_to_send);
@ -668,9 +674,9 @@ int main(int argc, char **argv)
USE_TTY();
#ifdef ANDROID
while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:uUvV")) != -1) {
while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:uUvVA")) != -1) {
#else
while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:uUv")) != -1) {
while ((c = getopt(argc, argv, "f:s:p:l:k:t:m:i:c:b:L:a:uUvA")) != -1) {
#endif
switch (c) {
case 's':
@ -722,6 +728,10 @@ int main(int argc, char **argv)
case 'v':
verbose = 1;
break;
case 'A':
auth = 1;
LOGI("onetime authentication enabled");
break;
#ifdef ANDROID
case 'V':
vpn = 1;

3
src/utils.c

@ -247,6 +247,9 @@ void usage()
printf(
" not available in local mode\n");
printf("\n");
printf(
" [-A] enable onetime authentication\n");
printf("\n");
printf(
" [-L <addr>:<port>] specify destination server address and port\n");
printf(

Loading…
Cancel
Save