shadowsocksr-libev: add support for read listening mode from config
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
parent
0c4a35392b
commit
d6c9ef9ae1
@ -1,16 +1,14 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Copyright (C) 2021 ImmortalWrt
|
||||
# <https://immortalwrt.org>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
# Copyright (C) 2017-2020 Yousong Zhou <yszhou4tech@gmail.com>
|
||||
# Copyright (C) 2018 Lean <coolsnowwolf@gmail.com>
|
||||
# Copyright (C) 2021 ImmortalWrt.org
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=shadowsocksr-libev
|
||||
PKG_VERSION:=2.5.6
|
||||
PKG_RELEASE:=7
|
||||
PKG_RELEASE:=8
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/shadowsocksrr/shadowsocksr-libev
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,40 @@
|
||||
diff --git a/src/jconf.c b/src/jconf.c
|
||||
index 710f70d..1613e20 100644
|
||||
--- a/src/jconf.c
|
||||
+++ b/src/jconf.c
|
||||
@@ -259,6 +259,19 @@ read_jconf(const char *file)
|
||||
conf.server_legacy.obfs = to_string(value);
|
||||
} else if (strcmp(name, "obfs_param") == 0) { // SSR
|
||||
conf.server_legacy.obfs_param = to_string(value);
|
||||
+ } else if (strcmp(name, "mode") == 0) {
|
||||
+ char *mode_str = to_string(value);
|
||||
+
|
||||
+ if (strcmp(mode_str, "tcp_only") == 0)
|
||||
+ conf.mode = TCP_ONLY;
|
||||
+ else if (strcmp(mode_str, "tcp_and_udp") == 0)
|
||||
+ conf.mode = TCP_AND_UDP;
|
||||
+ else if (strcmp(mode_str, "udp_only") == 0)
|
||||
+ conf.mode = UDP_ONLY;
|
||||
+ else
|
||||
+ LOGI("ignore unknown mode: %s, use tcp_only as fallback",
|
||||
+ mode_str);
|
||||
+ ss_free(mode_str);
|
||||
} else {
|
||||
match = 0;
|
||||
}
|
||||
diff --git a/src/redir.c b/src/redir.c
|
||||
index feafd5e..64521a1 100644
|
||||
--- a/src/redir.c
|
||||
+++ b/src/redir.c
|
||||
@@ -1252,7 +1252,10 @@ main(int argc, char **argv)
|
||||
if (user == NULL) {
|
||||
user = conf->user;
|
||||
}
|
||||
- if (mtu == 0) {
|
||||
+ if (mode == TCP_ONLY) {
|
||||
+ mode = conf->mode;
|
||||
+ }
|
||||
+ if (mtu == 0) {
|
||||
mtu = conf->mtu;
|
||||
}
|
||||
if (mptcp == 0) {
|
||||
55
package/lean/shadowsocksr-libev/src/server/Makefile.am
Normal file
55
package/lean/shadowsocksr-libev/src/server/Makefile.am
Normal file
@ -0,0 +1,55 @@
|
||||
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)
|
||||
if !USE_SYSTEM_SHARED_LIB
|
||||
AM_CFLAGS += -I$(top_srcdir)/libev
|
||||
AM_CFLAGS += -I$(top_srcdir)/libudns
|
||||
AM_CFLAGS += -I$(top_srcdir)/libsodium/src/libsodium/include
|
||||
endif
|
||||
AM_CFLAGS += -I$(top_srcdir)/libipset/include
|
||||
AM_CFLAGS += -I$(top_srcdir)/libcork/include
|
||||
AM_CFLAGS += $(LIBPCRE_CFLAGS)
|
||||
|
||||
SS_COMMON_LIBS = $(top_builddir)/libipset/libipset.la \
|
||||
$(top_builddir)/libcork/libcork.la \
|
||||
$(INET_NTOP_LIB) $(LIBPCRE_LIBS)
|
||||
if USE_SYSTEM_SHARED_LIB
|
||||
SS_COMMON_LIBS += -lev -lsodium -lm
|
||||
else
|
||||
SS_COMMON_LIBS += $(top_builddir)/libev/libev.la \
|
||||
$(top_builddir)/libsodium/src/libsodium/libsodium.la
|
||||
endif
|
||||
|
||||
bin_PROGRAMS = ss-server ss-check
|
||||
|
||||
sni_src = http.c \
|
||||
tls.c \
|
||||
rule.c
|
||||
|
||||
ss_check_SOURCES = check.c
|
||||
|
||||
ss_server_SOURCES = utils.c \
|
||||
netutils.c \
|
||||
jconf.c \
|
||||
json.c \
|
||||
encrypt.c \
|
||||
udprelay.c \
|
||||
cache.c \
|
||||
acl.c \
|
||||
resolv.c \
|
||||
server.c \
|
||||
$(sni_src)
|
||||
|
||||
|
||||
ss_check_LDADD = $(SS_COMMON_LIBS)
|
||||
ss_server_LDADD = $(SS_COMMON_LIBS)
|
||||
|
||||
if USE_SYSTEM_SHARED_LIB
|
||||
ss_server_LDADD += -ludns
|
||||
else
|
||||
ss_server_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
endif
|
||||
|
||||
ss_check_CFLAGS = $(AM_CFLAGS)
|
||||
ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE
|
||||
919
package/lean/shadowsocksr-libev/src/server/Makefile.in
Normal file
919
package/lean/shadowsocksr-libev/src/server/Makefile.in
Normal file
@ -0,0 +1,919 @@
|
||||
# Makefile.in generated by automake 1.15 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_1 = -I$(top_srcdir)/libev \
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@ -I$(top_srcdir)/libudns \
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@ -I$(top_srcdir)/libsodium/src/libsodium/include
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@am__append_2 = -lev -lsodium -lm
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_3 = $(top_builddir)/libev/libev.la \
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@ $(top_builddir)/libsodium/src/libsodium/libsodium.la
|
||||
|
||||
bin_PROGRAMS = ss-server$(EXEEXT) ss-check$(EXEEXT)
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@am__append_4 = -ludns
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_5 = $(top_builddir)/libudns/libudns.la
|
||||
subdir = server
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \
|
||||
$(top_srcdir)/m4/ax_tls.m4 $(top_srcdir)/m4/inet_ntop.m4 \
|
||||
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
||||
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
|
||||
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/mbedtls.m4 \
|
||||
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/pcre.m4 \
|
||||
$(top_srcdir)/m4/polarssl.m4 \
|
||||
$(top_srcdir)/m4/stack-protector.m4 $(top_srcdir)/m4/zlib.m4 \
|
||||
$(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_ss_check_OBJECTS = ss_check-check.$(OBJEXT)
|
||||
ss_check_OBJECTS = $(am_ss_check_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
am__DEPENDENCIES_2 = $(top_builddir)/libipset/libipset.la \
|
||||
$(top_builddir)/libcork/libcork.la $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1) $(am__append_3)
|
||||
ss_check_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
am__v_lt_1 =
|
||||
ss_check_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_check_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
am__objects_1 = ss_server-http.$(OBJEXT) ss_server-tls.$(OBJEXT) \
|
||||
ss_server-rule.$(OBJEXT)
|
||||
am_ss_server_OBJECTS = ss_server-utils.$(OBJEXT) \
|
||||
ss_server-netutils.$(OBJEXT) ss_server-jconf.$(OBJEXT) \
|
||||
ss_server-json.$(OBJEXT) ss_server-encrypt.$(OBJEXT) \
|
||||
ss_server-udprelay.$(OBJEXT) ss_server-cache.$(OBJEXT) \
|
||||
ss_server-acl.$(OBJEXT) ss_server-resolv.$(OBJEXT) \
|
||||
ss_server-server.$(OBJEXT) $(am__objects_1)
|
||||
ss_server_OBJECTS = $(am_ss_server_OBJECTS)
|
||||
ss_server_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
$(am__append_5)
|
||||
ss_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_server_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/auto/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CC_1 =
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
SOURCES = $(ss_check_SOURCES) $(ss_server_SOURCES)
|
||||
DIST_SOURCES = $(ss_check_SOURCES) $(ss_server_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/auto/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
ASCIIDOC = @ASCIIDOC@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
GZIP = @GZIP@
|
||||
INET_NTOP_LIB = @INET_NTOP_LIB@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBPCRE = @LIBPCRE@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MV = @MV@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PCRE_CONFIG = @PCRE_CONFIG@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
XMLTO = @XMLTO@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
ax_pthread_config = @ax_pthread_config@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pcre_pcreh = @pcre_pcreh@
|
||||
pcreh = @pcreh@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
subdirs = @subdirs@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VERSION_INFO = 2:0:0
|
||||
AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations \
|
||||
-fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE \
|
||||
$(PTHREAD_CFLAGS) $(am__append_1) \
|
||||
-I$(top_srcdir)/libipset/include \
|
||||
-I$(top_srcdir)/libcork/include $(LIBPCRE_CFLAGS)
|
||||
SS_COMMON_LIBS = $(top_builddir)/libipset/libipset.la \
|
||||
$(top_builddir)/libcork/libcork.la $(INET_NTOP_LIB) \
|
||||
$(LIBPCRE_LIBS) $(am__append_2) $(am__append_3)
|
||||
sni_src = http.c \
|
||||
tls.c \
|
||||
rule.c
|
||||
|
||||
ss_check_SOURCES = check.c
|
||||
ss_server_SOURCES = utils.c \
|
||||
netutils.c \
|
||||
jconf.c \
|
||||
json.c \
|
||||
encrypt.c \
|
||||
udprelay.c \
|
||||
cache.c \
|
||||
acl.c \
|
||||
resolv.c \
|
||||
server.c \
|
||||
$(sni_src)
|
||||
|
||||
ss_check_LDADD = $(SS_COMMON_LIBS)
|
||||
ss_server_LDADD = $(SS_COMMON_LIBS) $(am__append_4) $(am__append_5)
|
||||
ss_check_CFLAGS = $(AM_CFLAGS)
|
||||
ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign server/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign server/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p \
|
||||
|| test -f $$p1 \
|
||||
; then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' \
|
||||
-e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' \
|
||||
`; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(bindir)" && rm -f $$files
|
||||
|
||||
clean-binPROGRAMS:
|
||||
@list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list || exit $$?; \
|
||||
test -n "$(EXEEXT)" || exit 0; \
|
||||
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list
|
||||
|
||||
ss-check$(EXEEXT): $(ss_check_OBJECTS) $(ss_check_DEPENDENCIES) $(EXTRA_ss_check_DEPENDENCIES)
|
||||
@rm -f ss-check$(EXEEXT)
|
||||
$(AM_V_CCLD)$(ss_check_LINK) $(ss_check_OBJECTS) $(ss_check_LDADD) $(LIBS)
|
||||
|
||||
ss-server$(EXEEXT): $(ss_server_OBJECTS) $(ss_server_DEPENDENCIES) $(EXTRA_ss_server_DEPENDENCIES)
|
||||
@rm -f ss-server$(EXEEXT)
|
||||
$(AM_V_CCLD)$(ss_server_LINK) $(ss_server_OBJECTS) $(ss_server_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_check-check.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-acl.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-cache.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-encrypt.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-http.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-jconf.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-json.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-netutils.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-resolv.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-rule.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-server.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-tls.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-udprelay.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-utils.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
|
||||
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
ss_check-check.o: check.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -MT ss_check-check.o -MD -MP -MF $(DEPDIR)/ss_check-check.Tpo -c -o ss_check-check.o `test -f 'check.c' || echo '$(srcdir)/'`check.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_check-check.Tpo $(DEPDIR)/ss_check-check.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check.c' object='ss_check-check.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -c -o ss_check-check.o `test -f 'check.c' || echo '$(srcdir)/'`check.c
|
||||
|
||||
ss_check-check.obj: check.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -MT ss_check-check.obj -MD -MP -MF $(DEPDIR)/ss_check-check.Tpo -c -o ss_check-check.obj `if test -f 'check.c'; then $(CYGPATH_W) 'check.c'; else $(CYGPATH_W) '$(srcdir)/check.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_check-check.Tpo $(DEPDIR)/ss_check-check.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check.c' object='ss_check-check.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -c -o ss_check-check.obj `if test -f 'check.c'; then $(CYGPATH_W) 'check.c'; else $(CYGPATH_W) '$(srcdir)/check.c'; fi`
|
||||
|
||||
ss_server-utils.o: utils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-utils.o -MD -MP -MF $(DEPDIR)/ss_server-utils.Tpo -c -o ss_server-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-utils.Tpo $(DEPDIR)/ss_server-utils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='ss_server-utils.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
|
||||
|
||||
ss_server-utils.obj: utils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-utils.obj -MD -MP -MF $(DEPDIR)/ss_server-utils.Tpo -c -o ss_server-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-utils.Tpo $(DEPDIR)/ss_server-utils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='ss_server-utils.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
|
||||
|
||||
ss_server-netutils.o: netutils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-netutils.o -MD -MP -MF $(DEPDIR)/ss_server-netutils.Tpo -c -o ss_server-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-netutils.Tpo $(DEPDIR)/ss_server-netutils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_server-netutils.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c
|
||||
|
||||
ss_server-netutils.obj: netutils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-netutils.obj -MD -MP -MF $(DEPDIR)/ss_server-netutils.Tpo -c -o ss_server-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-netutils.Tpo $(DEPDIR)/ss_server-netutils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_server-netutils.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi`
|
||||
|
||||
ss_server-jconf.o: jconf.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-jconf.o -MD -MP -MF $(DEPDIR)/ss_server-jconf.Tpo -c -o ss_server-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-jconf.Tpo $(DEPDIR)/ss_server-jconf.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jconf.c' object='ss_server-jconf.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c
|
||||
|
||||
ss_server-jconf.obj: jconf.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-jconf.obj -MD -MP -MF $(DEPDIR)/ss_server-jconf.Tpo -c -o ss_server-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-jconf.Tpo $(DEPDIR)/ss_server-jconf.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jconf.c' object='ss_server-jconf.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi`
|
||||
|
||||
ss_server-json.o: json.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-json.o -MD -MP -MF $(DEPDIR)/ss_server-json.Tpo -c -o ss_server-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-json.Tpo $(DEPDIR)/ss_server-json.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='json.c' object='ss_server-json.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c
|
||||
|
||||
ss_server-json.obj: json.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-json.obj -MD -MP -MF $(DEPDIR)/ss_server-json.Tpo -c -o ss_server-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-json.Tpo $(DEPDIR)/ss_server-json.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='json.c' object='ss_server-json.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi`
|
||||
|
||||
ss_server-encrypt.o: encrypt.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-encrypt.o -MD -MP -MF $(DEPDIR)/ss_server-encrypt.Tpo -c -o ss_server-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-encrypt.Tpo $(DEPDIR)/ss_server-encrypt.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encrypt.c' object='ss_server-encrypt.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c
|
||||
|
||||
ss_server-encrypt.obj: encrypt.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-encrypt.obj -MD -MP -MF $(DEPDIR)/ss_server-encrypt.Tpo -c -o ss_server-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-encrypt.Tpo $(DEPDIR)/ss_server-encrypt.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encrypt.c' object='ss_server-encrypt.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi`
|
||||
|
||||
ss_server-udprelay.o: udprelay.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-udprelay.o -MD -MP -MF $(DEPDIR)/ss_server-udprelay.Tpo -c -o ss_server-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-udprelay.Tpo $(DEPDIR)/ss_server-udprelay.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udprelay.c' object='ss_server-udprelay.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c
|
||||
|
||||
ss_server-udprelay.obj: udprelay.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-udprelay.obj -MD -MP -MF $(DEPDIR)/ss_server-udprelay.Tpo -c -o ss_server-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-udprelay.Tpo $(DEPDIR)/ss_server-udprelay.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udprelay.c' object='ss_server-udprelay.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi`
|
||||
|
||||
ss_server-cache.o: cache.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-cache.o -MD -MP -MF $(DEPDIR)/ss_server-cache.Tpo -c -o ss_server-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-cache.Tpo $(DEPDIR)/ss_server-cache.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='ss_server-cache.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
|
||||
|
||||
ss_server-cache.obj: cache.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-cache.obj -MD -MP -MF $(DEPDIR)/ss_server-cache.Tpo -c -o ss_server-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-cache.Tpo $(DEPDIR)/ss_server-cache.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='ss_server-cache.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
|
||||
|
||||
ss_server-acl.o: acl.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-acl.o -MD -MP -MF $(DEPDIR)/ss_server-acl.Tpo -c -o ss_server-acl.o `test -f 'acl.c' || echo '$(srcdir)/'`acl.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-acl.Tpo $(DEPDIR)/ss_server-acl.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acl.c' object='ss_server-acl.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-acl.o `test -f 'acl.c' || echo '$(srcdir)/'`acl.c
|
||||
|
||||
ss_server-acl.obj: acl.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-acl.obj -MD -MP -MF $(DEPDIR)/ss_server-acl.Tpo -c -o ss_server-acl.obj `if test -f 'acl.c'; then $(CYGPATH_W) 'acl.c'; else $(CYGPATH_W) '$(srcdir)/acl.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-acl.Tpo $(DEPDIR)/ss_server-acl.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acl.c' object='ss_server-acl.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-acl.obj `if test -f 'acl.c'; then $(CYGPATH_W) 'acl.c'; else $(CYGPATH_W) '$(srcdir)/acl.c'; fi`
|
||||
|
||||
ss_server-resolv.o: resolv.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-resolv.o -MD -MP -MF $(DEPDIR)/ss_server-resolv.Tpo -c -o ss_server-resolv.o `test -f 'resolv.c' || echo '$(srcdir)/'`resolv.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-resolv.Tpo $(DEPDIR)/ss_server-resolv.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolv.c' object='ss_server-resolv.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-resolv.o `test -f 'resolv.c' || echo '$(srcdir)/'`resolv.c
|
||||
|
||||
ss_server-resolv.obj: resolv.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-resolv.obj -MD -MP -MF $(DEPDIR)/ss_server-resolv.Tpo -c -o ss_server-resolv.obj `if test -f 'resolv.c'; then $(CYGPATH_W) 'resolv.c'; else $(CYGPATH_W) '$(srcdir)/resolv.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-resolv.Tpo $(DEPDIR)/ss_server-resolv.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolv.c' object='ss_server-resolv.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-resolv.obj `if test -f 'resolv.c'; then $(CYGPATH_W) 'resolv.c'; else $(CYGPATH_W) '$(srcdir)/resolv.c'; fi`
|
||||
|
||||
ss_server-server.o: server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-server.o -MD -MP -MF $(DEPDIR)/ss_server-server.Tpo -c -o ss_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-server.Tpo $(DEPDIR)/ss_server-server.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='ss_server-server.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c
|
||||
|
||||
ss_server-server.obj: server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-server.obj -MD -MP -MF $(DEPDIR)/ss_server-server.Tpo -c -o ss_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-server.Tpo $(DEPDIR)/ss_server-server.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='ss_server-server.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi`
|
||||
|
||||
ss_server-http.o: http.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-http.o -MD -MP -MF $(DEPDIR)/ss_server-http.Tpo -c -o ss_server-http.o `test -f 'http.c' || echo '$(srcdir)/'`http.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-http.Tpo $(DEPDIR)/ss_server-http.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='ss_server-http.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-http.o `test -f 'http.c' || echo '$(srcdir)/'`http.c
|
||||
|
||||
ss_server-http.obj: http.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-http.obj -MD -MP -MF $(DEPDIR)/ss_server-http.Tpo -c -o ss_server-http.obj `if test -f 'http.c'; then $(CYGPATH_W) 'http.c'; else $(CYGPATH_W) '$(srcdir)/http.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-http.Tpo $(DEPDIR)/ss_server-http.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='ss_server-http.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-http.obj `if test -f 'http.c'; then $(CYGPATH_W) 'http.c'; else $(CYGPATH_W) '$(srcdir)/http.c'; fi`
|
||||
|
||||
ss_server-tls.o: tls.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-tls.o -MD -MP -MF $(DEPDIR)/ss_server-tls.Tpo -c -o ss_server-tls.o `test -f 'tls.c' || echo '$(srcdir)/'`tls.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-tls.Tpo $(DEPDIR)/ss_server-tls.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tls.c' object='ss_server-tls.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-tls.o `test -f 'tls.c' || echo '$(srcdir)/'`tls.c
|
||||
|
||||
ss_server-tls.obj: tls.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-tls.obj -MD -MP -MF $(DEPDIR)/ss_server-tls.Tpo -c -o ss_server-tls.obj `if test -f 'tls.c'; then $(CYGPATH_W) 'tls.c'; else $(CYGPATH_W) '$(srcdir)/tls.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-tls.Tpo $(DEPDIR)/ss_server-tls.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tls.c' object='ss_server-tls.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-tls.obj `if test -f 'tls.c'; then $(CYGPATH_W) 'tls.c'; else $(CYGPATH_W) '$(srcdir)/tls.c'; fi`
|
||||
|
||||
ss_server-rule.o: rule.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-rule.o -MD -MP -MF $(DEPDIR)/ss_server-rule.Tpo -c -o ss_server-rule.o `test -f 'rule.c' || echo '$(srcdir)/'`rule.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-rule.Tpo $(DEPDIR)/ss_server-rule.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rule.c' object='ss_server-rule.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-rule.o `test -f 'rule.c' || echo '$(srcdir)/'`rule.c
|
||||
|
||||
ss_server-rule.obj: rule.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-rule.obj -MD -MP -MF $(DEPDIR)/ss_server-rule.Tpo -c -o ss_server-rule.obj `if test -f 'rule.c'; then $(CYGPATH_W) 'rule.c'; else $(CYGPATH_W) '$(srcdir)/rule.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-rule.Tpo $(DEPDIR)/ss_server-rule.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rule.c' object='ss_server-rule.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-rule.obj `if test -f 'rule.c'; then $(CYGPATH_W) 'rule.c'; else $(CYGPATH_W) '$(srcdir)/rule.c'; fi`
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
|
||||
clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \
|
||||
ctags ctags-am distclean distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-binPROGRAMS \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags tags-am uninstall uninstall-am uninstall-binPROGRAMS
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
3
package/lean/shadowsocksr-libev/src/server/README.md
Normal file
3
package/lean/shadowsocksr-libev/src/server/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# server
|
||||
|
||||
`ss-server` and `ss-check` from https://github.com/ywb94/shadowsocks-libev
|
||||
597
package/lean/shadowsocksr-libev/src/server/acl.c
Normal file
597
package/lean/shadowsocksr-libev/src/server/acl.c
Normal file
@ -0,0 +1,597 @@
|
||||
/*
|
||||
* acl.c - Manage the ACL (Access Control List)
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ipset/ipset.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "rule.h"
|
||||
#include "utils.h"
|
||||
#include "cache.h"
|
||||
#include "acl.h"
|
||||
|
||||
static struct ip_set white_list_ipv4;
|
||||
static struct ip_set white_list_ipv6;
|
||||
|
||||
static struct ip_set black_list_ipv4;
|
||||
static struct ip_set black_list_ipv6;
|
||||
|
||||
static struct cork_dllist black_list_rules;
|
||||
static struct cork_dllist white_list_rules;
|
||||
|
||||
static int acl_mode = BLACK_LIST;
|
||||
|
||||
static struct cache *block_list;
|
||||
|
||||
static struct ip_set outbound_block_list_ipv4;
|
||||
static struct ip_set outbound_block_list_ipv6;
|
||||
static struct cork_dllist outbound_block_list_rules;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NO_FIREWALL_MODE 0
|
||||
#define IPTABLES_MODE 1
|
||||
#define FIREWALLD_MODE 2
|
||||
|
||||
static FILE *shell_stdin;
|
||||
static int mode = NO_FIREWALL_MODE;
|
||||
|
||||
static char chain_name[64];
|
||||
static char *iptables_init_chain =
|
||||
"iptables -N %s; iptables -F %s; iptables -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
|
||||
static char *iptables_remove_chain =
|
||||
"iptables -D OUTPUT -p tcp --tcp-flags RST RST -j %s; iptables -F %s; iptables -X %s";
|
||||
static char *iptables_add_rule = "iptables -A %s -d %s -j DROP";
|
||||
static char *iptables_remove_rule = "iptables -D %s -d %s -j DROP";
|
||||
|
||||
static char *ip6tables_init_chain =
|
||||
"ip6tables -N %s; ip6tables -F %s; ip6tables -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
|
||||
static char *ip6tables_remove_chain =
|
||||
"ip6tables -D OUTPUT -p tcp --tcp-flags RST RST -j %s; ip6tables -F %s; ip6tables -X %s";
|
||||
static char *ip6tables_add_rule = "ip6tables -A %s -d %s -j DROP";
|
||||
static char *ip6tables_remove_rule = "ip6tables -D %s -d %s -j DROP";
|
||||
|
||||
static char *firewalld_init_chain =
|
||||
"firewall-cmd --direct --add-chain ipv4 filter %s; \
|
||||
firewall-cmd --direct --passthrough ipv4 -F %s; \
|
||||
firewall-cmd --direct --passthrough ipv4 -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
|
||||
static char *firewalld_remove_chain =
|
||||
"firewall-cmd --direct --passthrough ipv4 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \
|
||||
firewall-cmd --direct --passthrough ipv4 -F %s; \
|
||||
firewall-cmd --direct --remove-chain ipv4 filter %s";
|
||||
static char *firewalld_add_rule = "firewall-cmd --direct --passthrough ipv4 -A %s -d %s -j DROP";
|
||||
static char *firewalld_remove_rule = "firewall-cmd --direct --passthrough ipv4 -D %s -d %s -j DROP";
|
||||
|
||||
static char *firewalld6_init_chain =
|
||||
"firewall-cmd --direct --add-chain ipv6 filter %s; \
|
||||
firewall-cmd --direct --passthrough ipv6 -F %s; \
|
||||
firewall-cmd --direct --passthrough ipv6 -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
|
||||
static char *firewalld6_remove_chain =
|
||||
"firewall-cmd --direct --passthrough ipv6 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \
|
||||
firewall-cmd --direct --passthrough ipv6 -F %s; \
|
||||
firewall-cmd --direct --remove-chain ipv6 filter %s";
|
||||
static char *firewalld6_add_rule = "firewall-cmd --direct --passthrough ipv6 -A %s -d %s -j DROP";
|
||||
static char *firewalld6_remove_rule = "firewall-cmd --direct --passthrough ipv6 -D %s -d %s -j DROP";
|
||||
|
||||
static int
|
||||
run_cmd(const char *cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
char cmdstring[256];
|
||||
|
||||
sprintf(cmdstring, "%s\n", cmd);
|
||||
size_t len = strlen(cmdstring);
|
||||
|
||||
if (shell_stdin != NULL) {
|
||||
ret = fwrite(cmdstring, 1, len, shell_stdin);
|
||||
fflush(shell_stdin);
|
||||
}
|
||||
|
||||
return ret == len;
|
||||
}
|
||||
|
||||
static int
|
||||
init_firewall()
|
||||
{
|
||||
int ret = 0;
|
||||
char cli[256];
|
||||
FILE *fp;
|
||||
|
||||
if (getuid() != 0)
|
||||
return -1;
|
||||
|
||||
sprintf(cli, "firewall-cmd --version 2>&1");
|
||||
fp = popen(cli, "r");
|
||||
|
||||
if (fp == NULL)
|
||||
return -1;
|
||||
|
||||
if (pclose(fp) == 0) {
|
||||
mode = FIREWALLD_MODE;
|
||||
} else {
|
||||
/* Check whether we have permission to operate iptables.
|
||||
* Note that checking `iptables --version` is insufficient:
|
||||
* eg, running within a child user namespace.
|
||||
*/
|
||||
sprintf(cli, "iptables -L 2>&1");
|
||||
fp = popen(cli, "r");
|
||||
if (fp == NULL)
|
||||
return -1;
|
||||
if (pclose(fp) == 0)
|
||||
mode = IPTABLES_MODE;
|
||||
}
|
||||
|
||||
sprintf(chain_name, "SHADOWSOCKS_LIBEV_%d", getpid());
|
||||
|
||||
if (mode == FIREWALLD_MODE) {
|
||||
sprintf(cli, firewalld6_init_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
sprintf(cli, firewalld_init_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
} else if (mode == IPTABLES_MODE) {
|
||||
sprintf(cli, ip6tables_init_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
sprintf(cli, iptables_init_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
}
|
||||
|
||||
shell_stdin = popen("/bin/sh", "w");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
reset_firewall()
|
||||
{
|
||||
int ret = 0;
|
||||
char cli[256];
|
||||
|
||||
if (getuid() != 0)
|
||||
return -1;
|
||||
|
||||
if (mode == IPTABLES_MODE) {
|
||||
sprintf(cli, ip6tables_remove_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
sprintf(cli, iptables_remove_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
} else if (mode == FIREWALLD_MODE) {
|
||||
sprintf(cli, firewalld6_remove_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
sprintf(cli, firewalld_remove_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
}
|
||||
|
||||
if (shell_stdin != NULL) {
|
||||
run_cmd("exit 0");
|
||||
pclose(shell_stdin);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
set_firewall_rule(char *addr, int add)
|
||||
{
|
||||
char cli[256];
|
||||
struct cork_ip ip;
|
||||
|
||||
if (getuid() != 0)
|
||||
return -1;
|
||||
|
||||
if (cork_ip_init(&ip, addr))
|
||||
return -1;
|
||||
|
||||
if (add) {
|
||||
if (mode == IPTABLES_MODE)
|
||||
sprintf(cli, ip.version == 4 ? iptables_add_rule : ip6tables_add_rule,
|
||||
chain_name, addr);
|
||||
else if (mode == FIREWALLD_MODE)
|
||||
sprintf(cli, ip.version == 4 ? firewalld_add_rule : firewalld6_add_rule,
|
||||
chain_name, addr);
|
||||
return run_cmd(cli);
|
||||
} else {
|
||||
if (mode == IPTABLES_MODE)
|
||||
sprintf(cli, ip.version == 4 ? iptables_remove_rule : ip6tables_remove_rule,
|
||||
chain_name, addr);
|
||||
else if (mode == FIREWALLD_MODE)
|
||||
sprintf(cli, ip.version == 4 ? firewalld_remove_rule : firewalld6_remove_rule,
|
||||
chain_name, addr);
|
||||
return run_cmd(cli);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_firewall_rule(void *key, void *element)
|
||||
{
|
||||
if (key == NULL)
|
||||
return;
|
||||
char *addr = (char *)key;
|
||||
set_firewall_rule(addr, 0);
|
||||
ss_free(element);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
init_block_list(int firewall)
|
||||
{
|
||||
// Initialize cache
|
||||
#ifdef __linux__
|
||||
if (firewall)
|
||||
init_firewall();
|
||||
else
|
||||
mode = NO_FIREWALL_MODE;
|
||||
cache_create(&block_list, 256, free_firewall_rule);
|
||||
#else
|
||||
cache_create(&block_list, 256, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
free_block_list()
|
||||
{
|
||||
#ifdef __linux__
|
||||
if (mode != NO_FIREWALL_MODE)
|
||||
reset_firewall();
|
||||
#endif
|
||||
cache_clear(block_list, 0); // Remove all items
|
||||
}
|
||||
|
||||
int
|
||||
remove_from_block_list(char *addr)
|
||||
{
|
||||
size_t addr_len = strlen(addr);
|
||||
return cache_remove(block_list, addr, addr_len);
|
||||
}
|
||||
|
||||
void
|
||||
clear_block_list()
|
||||
{
|
||||
cache_clear(block_list, 3600); // Clear items older than 1 hour
|
||||
}
|
||||
|
||||
int
|
||||
check_block_list(char *addr)
|
||||
{
|
||||
size_t addr_len = strlen(addr);
|
||||
|
||||
if (cache_key_exist(block_list, addr, addr_len)) {
|
||||
int *count = NULL;
|
||||
cache_lookup(block_list, addr, addr_len, &count);
|
||||
|
||||
if (count != NULL && *count > MAX_TRIES)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
update_block_list(char *addr, int err_level)
|
||||
{
|
||||
size_t addr_len = strlen(addr);
|
||||
|
||||
if (cache_key_exist(block_list, addr, addr_len)) {
|
||||
int *count = NULL;
|
||||
cache_lookup(block_list, addr, addr_len, &count);
|
||||
if (count != NULL) {
|
||||
if (*count > MAX_TRIES)
|
||||
return 1;
|
||||
(*count) += err_level;
|
||||
}
|
||||
} else if (err_level > 0) {
|
||||
int *count = (int *)ss_malloc(sizeof(int));
|
||||
*count = 1;
|
||||
cache_insert(block_list, addr, addr_len, count);
|
||||
#ifdef __linux__
|
||||
if (mode != NO_FIREWALL_MODE)
|
||||
set_firewall_rule(addr, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_addr_cidr(const char *str, char *host, int *cidr)
|
||||
{
|
||||
int ret = -1, n = 0;
|
||||
char *pch;
|
||||
|
||||
pch = strchr(str, '/');
|
||||
while (pch != NULL) {
|
||||
n++;
|
||||
ret = pch - str;
|
||||
pch = strchr(pch + 1, '/');
|
||||
}
|
||||
if (ret == -1) {
|
||||
strcpy(host, str);
|
||||
*cidr = -1;
|
||||
} else {
|
||||
memcpy(host, str, ret);
|
||||
host[ret] = '\0';
|
||||
*cidr = atoi(str + ret + 1);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
trimwhitespace(char *str)
|
||||
{
|
||||
char *end;
|
||||
|
||||
// Trim leading space
|
||||
while (isspace(*str))
|
||||
str++;
|
||||
|
||||
if (*str == 0) // All spaces?
|
||||
return str;
|
||||
|
||||
// Trim trailing space
|
||||
end = str + strlen(str) - 1;
|
||||
while (end > str && isspace(*end))
|
||||
end--;
|
||||
|
||||
// Write new null terminator
|
||||
*(end + 1) = 0;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
init_acl(const char *path)
|
||||
{
|
||||
// initialize ipset
|
||||
ipset_init_library();
|
||||
|
||||
ipset_init(&white_list_ipv4);
|
||||
ipset_init(&white_list_ipv6);
|
||||
ipset_init(&black_list_ipv4);
|
||||
ipset_init(&black_list_ipv6);
|
||||
ipset_init(&outbound_block_list_ipv4);
|
||||
ipset_init(&outbound_block_list_ipv6);
|
||||
|
||||
cork_dllist_init(&black_list_rules);
|
||||
cork_dllist_init(&white_list_rules);
|
||||
cork_dllist_init(&outbound_block_list_rules);
|
||||
|
||||
struct ip_set *list_ipv4 = &black_list_ipv4;
|
||||
struct ip_set *list_ipv6 = &black_list_ipv6;
|
||||
struct cork_dllist *rules = &black_list_rules;
|
||||
|
||||
FILE *f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
LOGE("Invalid acl path.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char buf[257];
|
||||
while (!feof(f))
|
||||
if (fgets(buf, 256, f)) {
|
||||
// Trim the newline
|
||||
int len = strlen(buf);
|
||||
if (len > 0 && buf[len - 1] == '\n') {
|
||||
buf[len - 1] = '\0';
|
||||
}
|
||||
|
||||
char *line = trimwhitespace(buf);
|
||||
|
||||
// Skip comments
|
||||
if (line[0] == '#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen(line) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(line, "[outbound_block_list]") == 0) {
|
||||
list_ipv4 = &outbound_block_list_ipv4;
|
||||
list_ipv6 = &outbound_block_list_ipv6;
|
||||
rules = &outbound_block_list_rules;
|
||||
continue;
|
||||
} else if (strcmp(line, "[black_list]") == 0
|
||||
|| strcmp(line, "[bypass_list]") == 0) {
|
||||
list_ipv4 = &black_list_ipv4;
|
||||
list_ipv6 = &black_list_ipv6;
|
||||
rules = &black_list_rules;
|
||||
continue;
|
||||
} else if (strcmp(line, "[white_list]") == 0
|
||||
|| strcmp(line, "[proxy_list]") == 0) {
|
||||
list_ipv4 = &white_list_ipv4;
|
||||
list_ipv6 = &white_list_ipv6;
|
||||
rules = &white_list_rules;
|
||||
continue;
|
||||
} else if (strcmp(line, "[reject_all]") == 0
|
||||
|| strcmp(line, "[bypass_all]") == 0) {
|
||||
acl_mode = WHITE_LIST;
|
||||
continue;
|
||||
} else if (strcmp(line, "[accept_all]") == 0
|
||||
|| strcmp(line, "[proxy_all]") == 0) {
|
||||
acl_mode = BLACK_LIST;
|
||||
continue;
|
||||
}
|
||||
|
||||
char host[257];
|
||||
int cidr;
|
||||
parse_addr_cidr(line, host, &cidr);
|
||||
|
||||
struct cork_ip addr;
|
||||
int err = cork_ip_init(&addr, host);
|
||||
if (!err) {
|
||||
if (addr.version == 4) {
|
||||
if (cidr >= 0) {
|
||||
ipset_ipv4_add_network(list_ipv4, &(addr.ip.v4), cidr);
|
||||
} else {
|
||||
ipset_ipv4_add(list_ipv4, &(addr.ip.v4));
|
||||
}
|
||||
} else if (addr.version == 6) {
|
||||
if (cidr >= 0) {
|
||||
ipset_ipv6_add_network(list_ipv6, &(addr.ip.v6), cidr);
|
||||
} else {
|
||||
ipset_ipv6_add(list_ipv6, &(addr.ip.v6));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rule_t *rule = new_rule();
|
||||
accept_rule_arg(rule, line);
|
||||
init_rule(rule);
|
||||
add_rule(rules, rule);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
free_rules(struct cork_dllist *rules)
|
||||
{
|
||||
struct cork_dllist_item *iter;
|
||||
while ((iter = cork_dllist_head(rules)) != NULL) {
|
||||
rule_t *rule = cork_container_of(iter, rule_t, entries);
|
||||
remove_rule(rule);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free_acl(void)
|
||||
{
|
||||
ipset_done(&black_list_ipv4);
|
||||
ipset_done(&black_list_ipv6);
|
||||
ipset_done(&white_list_ipv4);
|
||||
ipset_done(&white_list_ipv6);
|
||||
|
||||
free_rules(&black_list_rules);
|
||||
free_rules(&white_list_rules);
|
||||
}
|
||||
|
||||
int
|
||||
get_acl_mode(void)
|
||||
{
|
||||
return acl_mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0, if not match.
|
||||
* Return 1, if match black list.
|
||||
* Return -1, if match white list.
|
||||
*/
|
||||
int
|
||||
acl_match_host(const char *host)
|
||||
{
|
||||
struct cork_ip addr;
|
||||
int ret = 0;
|
||||
int err = cork_ip_init(&addr, host);
|
||||
|
||||
if (err) {
|
||||
int host_len = strlen(host);
|
||||
if (lookup_rule(&black_list_rules, host, host_len) != NULL)
|
||||
ret = 1;
|
||||
else if (lookup_rule(&white_list_rules, host, host_len) != NULL)
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (addr.version == 4) {
|
||||
if (ipset_contains_ipv4(&black_list_ipv4, &(addr.ip.v4)))
|
||||
ret = 1;
|
||||
else if (ipset_contains_ipv4(&white_list_ipv4, &(addr.ip.v4)))
|
||||
ret = -1;
|
||||
} else if (addr.version == 6) {
|
||||
if (ipset_contains_ipv6(&black_list_ipv6, &(addr.ip.v6)))
|
||||
ret = 1;
|
||||
else if (ipset_contains_ipv6(&white_list_ipv6, &(addr.ip.v6)))
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
acl_add_ip(const char *ip)
|
||||
{
|
||||
struct cork_ip addr;
|
||||
int err = cork_ip_init(&addr, ip);
|
||||
if (err) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr.version == 4) {
|
||||
ipset_ipv4_add(&black_list_ipv4, &(addr.ip.v4));
|
||||
} else if (addr.version == 6) {
|
||||
ipset_ipv6_add(&black_list_ipv6, &(addr.ip.v6));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
acl_remove_ip(const char *ip)
|
||||
{
|
||||
struct cork_ip addr;
|
||||
int err = cork_ip_init(&addr, ip);
|
||||
if (err) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr.version == 4) {
|
||||
ipset_ipv4_remove(&black_list_ipv4, &(addr.ip.v4));
|
||||
} else if (addr.version == 6) {
|
||||
ipset_ipv6_remove(&black_list_ipv6, &(addr.ip.v6));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0, if not match.
|
||||
* Return 1, if match black list.
|
||||
*/
|
||||
int
|
||||
outbound_block_match_host(const char *host)
|
||||
{
|
||||
struct cork_ip addr;
|
||||
int ret = 0;
|
||||
int err = cork_ip_init(&addr, host);
|
||||
|
||||
if (err) {
|
||||
int host_len = strlen(host);
|
||||
if (lookup_rule(&outbound_block_list_rules, host, host_len) != NULL)
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (addr.version == 4) {
|
||||
if (ipset_contains_ipv4(&outbound_block_list_ipv4, &(addr.ip.v4)))
|
||||
ret = 1;
|
||||
} else if (addr.version == 6) {
|
||||
if (ipset_contains_ipv6(&outbound_block_list_ipv6, &(addr.ip.v6)))
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
53
package/lean/shadowsocksr-libev/src/server/acl.h
Normal file
53
package/lean/shadowsocksr-libev/src/server/acl.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* acl.h - Define the ACL interface
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ACL_H
|
||||
#define _ACL_H
|
||||
|
||||
#define BLACK_LIST 0
|
||||
#define WHITE_LIST 1
|
||||
|
||||
#define MAX_TRIES 64
|
||||
#define MALICIOUS 8
|
||||
#define SUSPICIOUS 4
|
||||
#define BAD 2
|
||||
#define MALFORMED 1
|
||||
|
||||
int init_acl(const char *path);
|
||||
void free_acl(void);
|
||||
void clear_block_list(void);
|
||||
|
||||
int acl_match_host(const char *ip);
|
||||
int acl_add_ip(const char *ip);
|
||||
int acl_remove_ip(const char *ip);
|
||||
|
||||
int get_acl_mode(void);
|
||||
|
||||
void init_block_list(int firewall);
|
||||
void free_block_list();
|
||||
int check_block_list(char *addr);
|
||||
int update_block_list(char *addr, int err_level);
|
||||
int remove_from_block_list(char *addr);
|
||||
|
||||
int outbound_block_match_host(const char *host);
|
||||
|
||||
#endif // _ACL_H
|
||||
993
package/lean/shadowsocksr-libev/src/server/auth.c
Normal file
993
package/lean/shadowsocksr-libev/src/server/auth.c
Normal file
@ -0,0 +1,993 @@
|
||||
|
||||
#include "auth.h"
|
||||
|
||||
static int auth_simple_pack_unit_size = 2000;
|
||||
typedef int (*hmac_with_key_func)(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len);
|
||||
typedef int (*hash_func)(char *auth, char *msg, int msg_len);
|
||||
|
||||
typedef struct auth_simple_global_data {
|
||||
uint8_t local_client_id[8];
|
||||
uint32_t connection_id;
|
||||
}auth_simple_global_data;
|
||||
|
||||
typedef struct auth_simple_local_data {
|
||||
int has_sent_header;
|
||||
char * recv_buffer;
|
||||
int recv_buffer_size;
|
||||
uint32_t recv_id;
|
||||
uint32_t pack_id;
|
||||
char * salt;
|
||||
uint8_t * user_key;
|
||||
char uid[4];
|
||||
int user_key_len;
|
||||
hmac_with_key_func hmac;
|
||||
hash_func hash;
|
||||
int hash_len;
|
||||
}auth_simple_local_data;
|
||||
|
||||
void auth_simple_local_data_init(auth_simple_local_data* local) {
|
||||
local->has_sent_header = 0;
|
||||
local->recv_buffer = (char*)malloc(16384);
|
||||
local->recv_buffer_size = 0;
|
||||
local->recv_id = 1;
|
||||
local->pack_id = 1;
|
||||
local->salt = "";
|
||||
local->user_key = 0;
|
||||
local->user_key_len = 0;
|
||||
local->hmac = 0;
|
||||
local->hash = 0;
|
||||
local->hash_len = 0;
|
||||
local->salt = "";
|
||||
}
|
||||
|
||||
void * auth_simple_init_data() {
|
||||
auth_simple_global_data *global = (auth_simple_global_data*)malloc(sizeof(auth_simple_global_data));
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
return global;
|
||||
}
|
||||
|
||||
obfs * auth_simple_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(auth_simple_local_data));
|
||||
auth_simple_local_data_init((auth_simple_local_data*)self->l_data);
|
||||
return self;
|
||||
}
|
||||
|
||||
obfs * auth_aes128_md5_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(auth_simple_local_data));
|
||||
auth_simple_local_data_init((auth_simple_local_data*)self->l_data);
|
||||
((auth_simple_local_data*)self->l_data)->hmac = ss_md5_hmac_with_key;
|
||||
((auth_simple_local_data*)self->l_data)->hash = ss_md5_hash_func;
|
||||
((auth_simple_local_data*)self->l_data)->hash_len = 16;
|
||||
((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_md5";
|
||||
return self;
|
||||
}
|
||||
|
||||
obfs * auth_aes128_sha1_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(auth_simple_local_data));
|
||||
auth_simple_local_data_init((auth_simple_local_data*)self->l_data);
|
||||
((auth_simple_local_data*)self->l_data)->hmac = ss_sha1_hmac_with_key;
|
||||
((auth_simple_local_data*)self->l_data)->hash = ss_sha1_hash_func;
|
||||
((auth_simple_local_data*)self->l_data)->hash_len = 20;
|
||||
((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_sha1";
|
||||
return self;
|
||||
}
|
||||
|
||||
void auth_simple_dispose(obfs *self) {
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
if (local->recv_buffer != NULL) {
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = NULL;
|
||||
}
|
||||
if (local->user_key != NULL) {
|
||||
free(local->user_key);
|
||||
local->user_key = NULL;
|
||||
}
|
||||
free(local);
|
||||
self->l_data = NULL;
|
||||
dispose_obfs(self);
|
||||
}
|
||||
|
||||
int auth_simple_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
|
||||
int out_size = rand_len + datalength + 6;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
outdata[2] = rand_len;
|
||||
memmove(outdata + rand_len + 2, data, datalength);
|
||||
fillcrc32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
void memintcopy_lt(void *mem, uint32_t val) {
|
||||
((uint8_t *)mem)[0] = val;
|
||||
((uint8_t *)mem)[1] = val >> 8;
|
||||
((uint8_t *)mem)[2] = val >> 16;
|
||||
((uint8_t *)mem)[3] = val >> 24;
|
||||
}
|
||||
|
||||
int auth_simple_pack_auth_data(auth_simple_global_data *global, char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
|
||||
int out_size = rand_len + datalength + 6 + 12;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
outdata[2] = rand_len;
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
memintcopy_lt(outdata + rand_len + 2, t);
|
||||
memmove(outdata + rand_len + 2 + 4, global->local_client_id, 4);
|
||||
memintcopy_lt(outdata + rand_len + 2 + 8, global->connection_id);
|
||||
memmove(outdata + rand_len + 2 + 12, data, datalength);
|
||||
fillcrc32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 64);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = get_head_size(plaindata, datalength, 30);
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_simple_pack_auth_data((auth_simple_global_data *)self->server.g_data, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_simple_pack_data(data, auth_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_simple_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
int crc = crc32((unsigned char*)recv_buffer, length);
|
||||
if (crc != -1) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
int data_size = length - recv_buffer[2] - 6;
|
||||
memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int auth_sha1_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
|
||||
int out_size = rand_len + datalength + 6;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
outdata[2] = rand_len;
|
||||
memmove(outdata + rand_len + 2, data, datalength);
|
||||
filladler32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0x7F) + 1;
|
||||
int data_offset = rand_len + 4 + 2;
|
||||
int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN;
|
||||
fillcrc32to((unsigned char *)server->key, server->key_len, (unsigned char *)outdata);
|
||||
outdata[4] = out_size >> 8;
|
||||
outdata[5] = out_size;
|
||||
outdata[6] = rand_len;
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
memintcopy_lt(outdata + data_offset, t);
|
||||
memmove(outdata + data_offset + 4, global->local_client_id, 4);
|
||||
memintcopy_lt(outdata + data_offset + 8, global->connection_id);
|
||||
memmove(outdata + data_offset + 12, data, datalength);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv);
|
||||
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 256);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = get_head_size(plaindata, datalength, 30);
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_sha1_pack_data(data, auth_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_sha1_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
if (checkadler32((unsigned char*)recv_buffer, length) == 0) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
int pos = recv_buffer[2] + 2;
|
||||
int data_size = length - pos - 4;
|
||||
memmove(buffer, recv_buffer + pos, data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_v2_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
|
||||
int out_size = rand_len + datalength + 6;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[2] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[2] = 0xFF;
|
||||
outdata[3] = rand_len >> 8;
|
||||
outdata[4] = rand_len;
|
||||
}
|
||||
memmove(outdata + rand_len + 2, data, datalength);
|
||||
filladler32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_v2_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
|
||||
int data_offset = rand_len + 4 + 2;
|
||||
int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN;
|
||||
const char* salt = "auth_sha1_v2";
|
||||
int salt_len = strlen(salt);
|
||||
unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len);
|
||||
memcpy(crc_salt, salt, salt_len);
|
||||
memcpy(crc_salt + salt_len, server->key, server->key_len);
|
||||
fillcrc32to(crc_salt, salt_len + server->key_len, (unsigned char *)outdata);
|
||||
free(crc_salt);
|
||||
outdata[4] = out_size >> 8;
|
||||
outdata[5] = out_size;
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[6] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[6] = 0xFF;
|
||||
outdata[7] = rand_len >> 8;
|
||||
outdata[8] = rand_len;
|
||||
}
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
memmove(outdata + data_offset, global->local_client_id, 8);
|
||||
memintcopy_lt(outdata + data_offset + 8, global->connection_id);
|
||||
memmove(outdata + data_offset + 12, data, datalength);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv);
|
||||
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_v2_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 4096);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = get_head_size(plaindata, datalength, 30);
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_sha1_v2_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_sha1_v2_pack_data(data, auth_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_sha1_v2_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_v2_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
char error = 0;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
if (checkadler32((unsigned char*)recv_buffer, length) == 0) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
int pos = recv_buffer[2];
|
||||
if (pos < 255)
|
||||
{
|
||||
pos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = ((recv_buffer[3] << 8) | recv_buffer[4]) + 2;
|
||||
}
|
||||
int data_size = length - pos - 4;
|
||||
memmove(buffer, recv_buffer + pos, data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len;
|
||||
if (error == 0) {
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_v4_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
|
||||
int out_size = rand_len + datalength + 8;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
uint32_t crc_val = crc32((unsigned char*)outdata, 2);
|
||||
outdata[2] = crc_val;
|
||||
outdata[3] = crc_val >> 8;
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[4] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[4] = 0xFF;
|
||||
outdata[5] = rand_len >> 8;
|
||||
outdata[6] = rand_len;
|
||||
}
|
||||
memmove(outdata + rand_len + 4, data, datalength);
|
||||
filladler32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_v4_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
|
||||
int data_offset = rand_len + 4 + 2;
|
||||
int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN;
|
||||
const char* salt = "auth_sha1_v4";
|
||||
int salt_len = strlen(salt);
|
||||
unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len + 2);
|
||||
crc_salt[0] = outdata[0] = out_size >> 8;
|
||||
crc_salt[1] = outdata[1] = out_size;
|
||||
|
||||
memcpy(crc_salt + 2, salt, salt_len);
|
||||
memcpy(crc_salt + salt_len + 2, server->key, server->key_len);
|
||||
fillcrc32to(crc_salt, salt_len + server->key_len + 2, (unsigned char *)outdata + 2);
|
||||
free(crc_salt);
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[6] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[6] = 0xFF;
|
||||
outdata[7] = rand_len >> 8;
|
||||
outdata[8] = rand_len;
|
||||
}
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
memintcopy_lt(outdata + data_offset, t);
|
||||
memmove(outdata + data_offset + 4, global->local_client_id, 4);
|
||||
memintcopy_lt(outdata + data_offset + 8, global->connection_id);
|
||||
memmove(outdata + data_offset + 12, data, datalength);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv);
|
||||
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_v4_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 4096);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = get_head_size(plaindata, datalength, 30);
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_sha1_v4_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_sha1_v4_pack_data(data, auth_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_sha1_v4_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_v4_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
char error = 0;
|
||||
while (local->recv_buffer_size > 4) {
|
||||
uint32_t crc_val = crc32((unsigned char*)recv_buffer, 2);
|
||||
if ((((uint32_t)recv_buffer[3] << 8) | recv_buffer[2]) != (crc_val & 0xffff)) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
if (checkadler32((unsigned char*)recv_buffer, length) == 0) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
int pos = recv_buffer[4];
|
||||
if (pos < 255)
|
||||
{
|
||||
pos += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = (((int)recv_buffer[5] << 8) | recv_buffer[6]) + 4;
|
||||
}
|
||||
int data_size = length - pos - 4;
|
||||
memmove(buffer, recv_buffer + pos, data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len;
|
||||
if (error == 0) {
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int auth_aes128_sha1_pack_data(char *data, int datalength, char *outdata, auth_simple_local_data *local, server_info *server) {
|
||||
unsigned int rand_len = (datalength > 1200 ? 0 : local->pack_id > 4 ? (xorshift128plus() & 0x20) : datalength > 900 ? (xorshift128plus() & 0x80) : (xorshift128plus() & 0x200)) + 1;
|
||||
int out_size = rand_len + datalength + 8;
|
||||
memcpy(outdata + rand_len + 4, data, datalength);
|
||||
outdata[0] = out_size;
|
||||
outdata[1] = out_size >> 8;
|
||||
uint8_t key_len = local->user_key_len + 4;
|
||||
uint8_t *key = (uint8_t*)malloc(key_len);
|
||||
memcpy(key, local->user_key, local->user_key_len);
|
||||
memintcopy_lt(key + key_len - 4, local->pack_id);
|
||||
|
||||
{
|
||||
uint8_t rnd_data[rand_len];
|
||||
rand_bytes(rnd_data, rand_len);
|
||||
memcpy(outdata + 4, rnd_data, rand_len);
|
||||
}
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, outdata, 2, key, key_len);
|
||||
memcpy(outdata + 2, hash, 2);
|
||||
}
|
||||
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[4] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[4] = 0xFF;
|
||||
outdata[5] = rand_len;
|
||||
outdata[6] = rand_len >> 8;
|
||||
}
|
||||
++local->pack_id;
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, outdata, out_size - 4, key, key_len);
|
||||
memcpy(outdata + out_size - 4, hash, 4);
|
||||
}
|
||||
free(key);
|
||||
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, auth_simple_local_data *local, char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 400 ? (xorshift128plus() & 0x200) : (xorshift128plus() & 0x400));
|
||||
int data_offset = rand_len + 16 + 4 + 4 + 7;
|
||||
int out_size = data_offset + datalength + 4;
|
||||
|
||||
char encrypt[24];
|
||||
char encrypt_data[16];
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(server->iv_len + server->key_len);
|
||||
uint8_t key_len = server->iv_len + server->key_len;
|
||||
memcpy(key, server->iv, server->iv_len);
|
||||
memcpy(key + server->iv_len, server->key, server->key_len);
|
||||
|
||||
{
|
||||
uint8_t rnd_data[rand_len];
|
||||
rand_bytes(rnd_data, rand_len);
|
||||
memcpy(outdata + data_offset - rand_len, rnd_data, rand_len);
|
||||
}
|
||||
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
memintcopy_lt(encrypt, t);
|
||||
memcpy(encrypt + 4, global->local_client_id, 4);
|
||||
memintcopy_lt(encrypt + 8, global->connection_id);
|
||||
encrypt[12] = out_size;
|
||||
encrypt[13] = out_size >> 8;
|
||||
encrypt[14] = rand_len;
|
||||
encrypt[15] = rand_len >> 8;
|
||||
|
||||
{
|
||||
|
||||
if (local->user_key == NULL) {
|
||||
if(server->param != NULL && server->param[0] != 0) {
|
||||
char *param = server->param;
|
||||
char *delim = strchr(param, ':');
|
||||
if(delim != NULL) {
|
||||
char uid_str[16] = {};
|
||||
strncpy(uid_str, param, delim - param);
|
||||
char key_str[128];
|
||||
strcpy(key_str, delim + 1);
|
||||
long uid_long = strtol(uid_str, NULL, 10);
|
||||
memintcopy_lt(local->uid, uid_long);
|
||||
|
||||
char hash[21] = {0};
|
||||
local->hash(hash, key_str, strlen(key_str));
|
||||
|
||||
local->user_key_len = local->hash_len;
|
||||
local->user_key = (uint8_t*)malloc(local->user_key_len);
|
||||
memcpy(local->user_key, hash, local->hash_len);
|
||||
}
|
||||
}
|
||||
if (local->user_key == NULL) {
|
||||
rand_bytes((uint8_t *)local->uid, 4);
|
||||
|
||||
local->user_key_len = server->key_len;
|
||||
local->user_key = (uint8_t*)malloc(local->user_key_len);
|
||||
memcpy(local->user_key, server->key, local->user_key_len);
|
||||
}
|
||||
}
|
||||
|
||||
char encrypt_key_base64[256] = {0};
|
||||
unsigned char encrypt_key[local->user_key_len];
|
||||
memcpy(encrypt_key, local->user_key, local->user_key_len);
|
||||
base64_encode(encrypt_key, local->user_key_len, encrypt_key_base64);
|
||||
|
||||
int base64_len;
|
||||
base64_len = (local->user_key_len + 2) / 3 * 4;
|
||||
memcpy(encrypt_key_base64 + base64_len, local->salt, strlen(local->salt));
|
||||
|
||||
char enc_key[16];
|
||||
int enc_key_len = base64_len + strlen(local->salt);
|
||||
bytes_to_key_with_size(encrypt_key_base64, enc_key_len, (uint8_t*)enc_key, 16);
|
||||
ss_aes_128_cbc(encrypt, encrypt_data, enc_key);
|
||||
memcpy(encrypt + 4, encrypt_data, 16);
|
||||
memcpy(encrypt, local->uid, 4);
|
||||
}
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, encrypt, 20, key, key_len);
|
||||
memcpy(encrypt + 20, hash, 4);
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t rnd[1];
|
||||
rand_bytes(rnd, 1);
|
||||
memcpy(outdata, rnd, 1);
|
||||
char hash[20];
|
||||
local->hmac(hash, (char *)rnd, 1, key, key_len);
|
||||
memcpy(outdata + 1, hash, 6);
|
||||
}
|
||||
|
||||
memcpy(outdata + 7, encrypt, 24);
|
||||
memcpy(outdata + data_offset, data, datalength);
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, outdata, out_size - 4, local->user_key, local->user_key_len);
|
||||
memmove(outdata + out_size - 4, hash, 4);
|
||||
}
|
||||
free(key);
|
||||
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 4096);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = 1200;
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_aes128_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, local, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_aes128_sha1_pack_data(data, auth_simple_pack_unit_size, buffer, local, &self->server);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_aes128_sha1_pack_data(data, len, buffer, local, &self->server);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
//server_info *server = (server_info*)&self->server;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
int key_len = local->user_key_len + 4;
|
||||
uint8_t *key = (uint8_t*)malloc(key_len);
|
||||
memcpy(key, local->user_key, local->user_key_len);
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
char error = 0;
|
||||
while (local->recv_buffer_size > 4) {
|
||||
memintcopy_lt(key + key_len - 4, local->recv_id);
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, (char*)recv_buffer, 2, key, key_len);
|
||||
|
||||
if (memcmp(hash, recv_buffer + 2, 2)) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int length = ((int)recv_buffer[1] << 8) + recv_buffer[0];
|
||||
if (length >= 8192 || length < 8) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, (char *)recv_buffer, length - 4, key, key_len);
|
||||
if (memcmp(hash, recv_buffer + length - 4, 4))
|
||||
{
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++local->recv_id;
|
||||
int pos = recv_buffer[4];
|
||||
if (pos < 255)
|
||||
{
|
||||
pos += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = (((int)recv_buffer[6] << 8) | recv_buffer[5]) + 4;
|
||||
}
|
||||
int data_size = length - pos - 4;
|
||||
memmove(buffer, recv_buffer + pos, data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len;
|
||||
if (error == 0) {
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
free(out_buffer);
|
||||
free(key);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength + 8);
|
||||
|
||||
if (local->user_key == NULL) {
|
||||
if(self->server.param != NULL && self->server.param[0] != 0) {
|
||||
char *param = self->server.param;
|
||||
char *delim = strchr(param, ':');
|
||||
if(delim != NULL) {
|
||||
char uid_str[16] = {};
|
||||
strncpy(uid_str, param, delim - param);
|
||||
char key_str[128];
|
||||
strcpy(key_str, delim + 1);
|
||||
long uid_long = strtol(uid_str, NULL, 10);
|
||||
memintcopy_lt(local->uid, uid_long);
|
||||
|
||||
char hash[21] = {0};
|
||||
local->hash(hash, key_str, strlen(key_str));
|
||||
|
||||
local->user_key_len = local->hash_len;
|
||||
local->user_key = (uint8_t*)malloc(local->user_key_len);
|
||||
memcpy(local->user_key, hash, local->hash_len);
|
||||
}
|
||||
}
|
||||
if (local->user_key == NULL) {
|
||||
rand_bytes((uint8_t *)local->uid, 4);
|
||||
|
||||
local->user_key_len = self->server.key_len;
|
||||
local->user_key = (uint8_t*)malloc(local->user_key_len);
|
||||
memcpy(local->user_key, self->server.key, local->user_key_len);
|
||||
}
|
||||
}
|
||||
|
||||
int outlength = datalength + 8;
|
||||
memmove(out_buffer, plaindata, datalength);
|
||||
memmove(out_buffer + datalength, local->uid, 4);
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, out_buffer, outlength - 4, local->user_key, local->user_key_len);
|
||||
memmove(out_buffer + outlength - 4, hash, 4);
|
||||
}
|
||||
|
||||
if (*capacity < outlength) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = outlength * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, outlength);
|
||||
|
||||
free(out_buffer);
|
||||
return outlength;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_client_udp_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
if (datalength <= 4)
|
||||
return 0;
|
||||
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
|
||||
char hash[20];
|
||||
local->hmac(hash, plaindata, datalength - 4, self->server.key, self->server.key_len);
|
||||
|
||||
if (memcmp(hash, plaindata + datalength - 4, 4))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return datalength - 4;
|
||||
}
|
||||
30
package/lean/shadowsocksr-libev/src/server/auth.h
Normal file
30
package/lean/shadowsocksr-libev/src/server/auth.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* auth.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_H
|
||||
#define _AUTH_H
|
||||
|
||||
void * auth_simple_init_data();
|
||||
obfs * auth_simple_new_obfs();
|
||||
void auth_simple_dispose(obfs *self);
|
||||
|
||||
int auth_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
|
||||
int auth_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
int auth_sha1_v2_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_sha1_v2_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
int auth_sha1_v4_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_sha1_v4_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
int auth_aes128_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_aes128_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
#endif // _AUTH_H
|
||||
119
package/lean/shadowsocksr-libev/src/server/base64.c
Normal file
119
package/lean/shadowsocksr-libev/src/server/base64.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include "base64.h"
|
||||
|
||||
/* BASE 64 encode table */
|
||||
static const char base64en[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
#define BASE64_PAD '='
|
||||
|
||||
#define BASE64DE_FIRST '+'
|
||||
#define BASE64DE_LAST 'z'
|
||||
|
||||
/* ASCII order for BASE 64 decode, -1 in unused character */
|
||||
static const signed char base64de[] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
/* '+', ',', '-', '.', '/', */
|
||||
-1, -1, -1, 62, -1, -1, -1, 63,
|
||||
/* '0', '1', '2', '3', '4', '5', '6', '7', */
|
||||
52, 53, 54, 55, 56, 57, 58, 59,
|
||||
/* '8', '9', ':', ';', '<', '=', '>', '?', */
|
||||
60, 61, -1, -1, -1, -1, -1, -1,
|
||||
/* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */
|
||||
-1, 0, 1, 2, 3, 4, 5, 6,
|
||||
/* 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
/* 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */
|
||||
15, 16, 17, 18, 19, 20, 21, 22,
|
||||
/* 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */
|
||||
23, 24, 25, -1, -1, -1, -1, -1,
|
||||
/* '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */
|
||||
-1, 26, 27, 28, 29, 30, 31, 32,
|
||||
/* 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */
|
||||
33, 34, 35, 36, 37, 38, 39, 40,
|
||||
/* 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */
|
||||
41, 42, 43, 44, 45, 46, 47, 48,
|
||||
/* 'x', 'y', 'z', */
|
||||
49, 50, 51,
|
||||
};
|
||||
|
||||
int
|
||||
base64_encode(const unsigned char *in, unsigned int inlen, char *out)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = j = 0; i < inlen; i++) {
|
||||
int s = i % 3; /* from 6/gcd(6, 8) */
|
||||
|
||||
switch (s) {
|
||||
case 0:
|
||||
out[j++] = base64en[(in[i] >> 2) & 0x3F];
|
||||
continue;
|
||||
case 1:
|
||||
out[j++] = base64en[((in[i-1] & 0x3) << 4) + ((in[i] >> 4) & 0xF)];
|
||||
continue;
|
||||
case 2:
|
||||
out[j++] = base64en[((in[i-1] & 0xF) << 2) + ((in[i] >> 6) & 0x3)];
|
||||
out[j++] = base64en[in[i] & 0x3F];
|
||||
}
|
||||
}
|
||||
|
||||
/* move back */
|
||||
i -= 1;
|
||||
|
||||
/* check the last and add padding */
|
||||
if ((i % 3) == 0) {
|
||||
out[j++] = base64en[(in[i] & 0x3) << 4];
|
||||
out[j++] = BASE64_PAD;
|
||||
out[j++] = BASE64_PAD;
|
||||
} else if ((i % 3) == 1) {
|
||||
out[j++] = base64en[(in[i] & 0xF) << 2];
|
||||
out[j++] = BASE64_PAD;
|
||||
}
|
||||
|
||||
return BASE64_OK;
|
||||
}
|
||||
|
||||
int
|
||||
base64_decode(const char *in, unsigned int inlen, unsigned char *out)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = j = 0; i < inlen; i++) {
|
||||
int c;
|
||||
int s = i % 4; /* from 8/gcd(6, 8) */
|
||||
|
||||
if (in[i] == '=')
|
||||
return BASE64_OK;
|
||||
|
||||
if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST ||
|
||||
(c = base64de[(int)in[i]]) == -1)
|
||||
return BASE64_INVALID;
|
||||
|
||||
switch (s) {
|
||||
case 0:
|
||||
out[j] = ((unsigned int)c << 2) & 0xFF;
|
||||
continue;
|
||||
case 1:
|
||||
out[j++] += ((unsigned int)c >> 4) & 0x3;
|
||||
|
||||
/* if not last char with padding */
|
||||
if (i < (inlen - 3) || in[inlen - 2] != '=')
|
||||
out[j] = ((unsigned int)c & 0xF) << 4;
|
||||
continue;
|
||||
case 2:
|
||||
out[j++] += ((unsigned int)c >> 2) & 0xF;
|
||||
|
||||
/* if not last char with padding */
|
||||
if (i < (inlen - 2) || in[inlen - 1] != '=')
|
||||
out[j] = ((unsigned int)c & 0x3) << 6;
|
||||
continue;
|
||||
case 3:
|
||||
out[j++] += (unsigned char)c;
|
||||
}
|
||||
}
|
||||
|
||||
return BASE64_OK;
|
||||
}
|
||||
16
package/lean/shadowsocksr-libev/src/server/base64.h
Normal file
16
package/lean/shadowsocksr-libev/src/server/base64.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __BASE64_H__
|
||||
#define __BASE64_H__
|
||||
|
||||
enum {BASE64_OK = 0, BASE64_INVALID};
|
||||
|
||||
#define BASE64_ENCODE_OUT_SIZE(s) (((s) + 2) / 3 * 4)
|
||||
#define BASE64_DECODE_OUT_SIZE(s) (((s)) / 4 * 3)
|
||||
|
||||
int
|
||||
base64_encode(const unsigned char *in, unsigned int inlen, char *out);
|
||||
|
||||
int
|
||||
base64_decode(const char *in, unsigned int inlen, unsigned char *out);
|
||||
|
||||
|
||||
#endif /* __BASE64_H__ */
|
||||
308
package/lean/shadowsocksr-libev/src/server/cache.c
Normal file
308
package/lean/shadowsocksr-libev/src/server/cache.c
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* cache.c - Manage the connection cache for UDPRELAY
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Original Author: Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org
|
||||
* License: This is licensed under the same terms as uthash itself
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cache.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include "win32.h"
|
||||
#endif
|
||||
|
||||
/** Creates a new cache object
|
||||
*
|
||||
* @param dst
|
||||
* Where the newly allocated cache object will be stored in
|
||||
*
|
||||
* @param capacity
|
||||
* The maximum number of elements this cache object can hold
|
||||
*
|
||||
* @return EINVAL if dst is NULL, ENOMEM if malloc fails, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_create(struct cache **dst, const size_t capacity,
|
||||
void (*free_cb)(void *key, void *element))
|
||||
{
|
||||
struct cache *new = NULL;
|
||||
|
||||
if (!dst) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((new = malloc(sizeof(*new))) == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
new->max_entries = capacity;
|
||||
new->entries = NULL;
|
||||
new->free_cb = free_cb;
|
||||
*dst = new;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Frees an allocated cache object
|
||||
*
|
||||
* @param cache
|
||||
* The cache object to free
|
||||
*
|
||||
* @param keep_data
|
||||
* Whether to free contained data or just delete references to it
|
||||
*
|
||||
* @return EINVAL if cache is NULL, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_delete(struct cache *cache, int keep_data)
|
||||
{
|
||||
struct cache_entry *entry, *tmp;
|
||||
|
||||
if (!cache) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (keep_data) {
|
||||
HASH_CLEAR(hh, cache->entries);
|
||||
} else {
|
||||
HASH_ITER(hh, cache->entries, entry, tmp){
|
||||
HASH_DEL(cache->entries, entry);
|
||||
if (entry->data != NULL) {
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(entry->key, entry->data);
|
||||
} else {
|
||||
ss_free(entry->data);
|
||||
}
|
||||
}
|
||||
ss_free(entry->key);
|
||||
ss_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
ss_free(cache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Clear old cache object
|
||||
*
|
||||
* @param cache
|
||||
* The cache object to clear
|
||||
*
|
||||
* @param age
|
||||
* Clear only objects older than the age (sec)
|
||||
*
|
||||
* @return EINVAL if cache is NULL, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_clear(struct cache *cache, ev_tstamp age)
|
||||
{
|
||||
struct cache_entry *entry, *tmp;
|
||||
|
||||
if (!cache) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ev_tstamp now = ev_time();
|
||||
|
||||
HASH_ITER(hh, cache->entries, entry, tmp){
|
||||
if (now - entry->ts > age) {
|
||||
HASH_DEL(cache->entries, entry);
|
||||
if (entry->data != NULL) {
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(entry->key, entry->data);
|
||||
} else {
|
||||
ss_free(entry->data);
|
||||
}
|
||||
}
|
||||
ss_free(entry->key);
|
||||
ss_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Removes a cache entry
|
||||
*
|
||||
* @param cache
|
||||
* The cache object
|
||||
*
|
||||
* @param key
|
||||
* The key of the entry to remove
|
||||
*
|
||||
* @param key_len
|
||||
* The length of key
|
||||
*
|
||||
* @return EINVAL if cache is NULL, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_remove(struct cache *cache, char *key, size_t key_len)
|
||||
{
|
||||
struct cache_entry *tmp;
|
||||
|
||||
if (!cache || !key) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
HASH_FIND(hh, cache->entries, key, key_len, tmp);
|
||||
|
||||
if (tmp) {
|
||||
HASH_DEL(cache->entries, tmp);
|
||||
if (tmp->data != NULL) {
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(tmp->key, tmp->data);
|
||||
} else {
|
||||
ss_free(tmp->data);
|
||||
}
|
||||
}
|
||||
ss_free(tmp->key);
|
||||
ss_free(tmp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Checks if a given key is in the cache
|
||||
*
|
||||
* @param cache
|
||||
* The cache object
|
||||
*
|
||||
* @param key
|
||||
* The key to look-up
|
||||
*
|
||||
* @param key_len
|
||||
* The length of key
|
||||
*
|
||||
* @param result
|
||||
* Where to store the result if key is found.
|
||||
*
|
||||
* A warning: Even though result is just a pointer,
|
||||
* you have to call this function with a **ptr,
|
||||
* otherwise this will blow up in your face.
|
||||
*
|
||||
* @return EINVAL if cache is NULL, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_lookup(struct cache *cache, char *key, size_t key_len, void *result)
|
||||
{
|
||||
struct cache_entry *tmp = NULL;
|
||||
char **dirty_hack = result;
|
||||
|
||||
if (!cache || !key || !result) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
HASH_FIND(hh, cache->entries, key, key_len, tmp);
|
||||
if (tmp) {
|
||||
HASH_DELETE(hh, cache->entries, tmp);
|
||||
tmp->ts = ev_time();
|
||||
HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp);
|
||||
*dirty_hack = tmp->data;
|
||||
} else {
|
||||
*dirty_hack = result = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cache_key_exist(struct cache *cache, char *key, size_t key_len)
|
||||
{
|
||||
struct cache_entry *tmp = NULL;
|
||||
|
||||
if (!cache || !key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_FIND(hh, cache->entries, key, key_len, tmp);
|
||||
if (tmp) {
|
||||
HASH_DELETE(hh, cache->entries, tmp);
|
||||
tmp->ts = ev_time();
|
||||
HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Inserts a given <key, value> pair into the cache
|
||||
*
|
||||
* @param cache
|
||||
* The cache object
|
||||
*
|
||||
* @param key
|
||||
* The key that identifies <value>
|
||||
*
|
||||
* @param key_len
|
||||
* The length of key
|
||||
*
|
||||
* @param data
|
||||
* Data associated with <key>
|
||||
*
|
||||
* @return EINVAL if cache is NULL, ENOMEM if malloc fails, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_insert(struct cache *cache, char *key, size_t key_len, void *data)
|
||||
{
|
||||
struct cache_entry *entry = NULL;
|
||||
struct cache_entry *tmp_entry = NULL;
|
||||
|
||||
if (!cache) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((entry = malloc(sizeof(*entry))) == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
entry->key = ss_malloc(key_len + 1);
|
||||
memcpy(entry->key, key, key_len);
|
||||
entry->key[key_len] = 0;
|
||||
|
||||
entry->data = data;
|
||||
entry->ts = ev_time();
|
||||
HASH_ADD_KEYPTR(hh, cache->entries, entry->key, key_len, entry);
|
||||
|
||||
if (HASH_COUNT(cache->entries) >= cache->max_entries) {
|
||||
HASH_ITER(hh, cache->entries, entry, tmp_entry){
|
||||
HASH_DELETE(hh, cache->entries, entry);
|
||||
if (entry->data != NULL) {
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(entry->key, entry->data);
|
||||
} else {
|
||||
ss_free(entry->data);
|
||||
}
|
||||
}
|
||||
ss_free(entry->key);
|
||||
ss_free(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
62
package/lean/shadowsocksr-libev/src/server/cache.h
Normal file
62
package/lean/shadowsocksr-libev/src/server/cache.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* cache.h - Define the cache manager interface
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Original Author: Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org
|
||||
* License: This is licensed under the same terms as uthash itself
|
||||
*/
|
||||
|
||||
#ifndef _CACHE_
|
||||
#define _CACHE_
|
||||
|
||||
#include "uthash.h"
|
||||
#include "ev.h"
|
||||
|
||||
/**
|
||||
* A cache entry
|
||||
*/
|
||||
struct cache_entry {
|
||||
char *key; /**<The key */
|
||||
void *data; /**<Payload */
|
||||
ev_tstamp ts; /**<Timestamp */
|
||||
UT_hash_handle hh; /**<Hash Handle for uthash */
|
||||
};
|
||||
|
||||
/**
|
||||
* A cache object
|
||||
*/
|
||||
struct cache {
|
||||
size_t max_entries; /**<Amount of entries this cache object can hold */
|
||||
struct cache_entry *entries; /**<Head pointer for uthash */
|
||||
void (*free_cb) (void *key, void *element); /**<Callback function to free cache entries */
|
||||
};
|
||||
|
||||
int cache_create(struct cache **dst, const size_t capacity,
|
||||
void (*free_cb)(void *key, void *element));
|
||||
int cache_delete(struct cache *cache, int keep_data);
|
||||
int cache_clear(struct cache *cache, ev_tstamp age);
|
||||
int cache_lookup(struct cache *cache, char *key, size_t key_len, void *result);
|
||||
int cache_insert(struct cache *cache, char *key, size_t key_len, void *data);
|
||||
int cache_remove(struct cache *cache, char *key, size_t key_len);
|
||||
int cache_key_exist(struct cache *cache, char *key, size_t key_len);
|
||||
|
||||
#endif
|
||||
236
package/lean/shadowsocksr-libev/src/server/check.c
Normal file
236
package/lean/shadowsocksr-libev/src/server/check.c
Normal file
@ -0,0 +1,236 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include<arpa/inet.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
//#define __DEBUG__
|
||||
#ifdef __DEBUG__
|
||||
#define DEBUG(format,...) printf("File: "__FILE__", Line: %05d: "format"/n", __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG(format,...)
|
||||
#endif
|
||||
|
||||
static sigjmp_buf jmpbuf;
|
||||
static void alarm_func()
|
||||
{
|
||||
siglongjmp(jmpbuf, 1);
|
||||
}
|
||||
|
||||
static struct hostent *timeGethostbyname(const char *domain, int timeout)
|
||||
{
|
||||
struct hostent *ipHostent = NULL;
|
||||
signal(SIGALRM, alarm_func);
|
||||
if(sigsetjmp(jmpbuf, 1) != 0)
|
||||
{
|
||||
alarm(0);//timout
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
return NULL;
|
||||
}
|
||||
alarm(timeout);//setting alarm
|
||||
ipHostent = gethostbyname(domain);
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
return ipHostent;
|
||||
}
|
||||
|
||||
|
||||
#define MY_HTTP_DEFAULT_PORT 80
|
||||
#define BUFFER_SIZE 1024
|
||||
#define HTTP_POST "POST /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n"\
|
||||
"Content-Type:application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s"
|
||||
#define HTTP_GET "GET /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n\r\n"
|
||||
|
||||
static int http_parse_url(const char *url,char *host,char *file,int *port)
|
||||
{
|
||||
char *ptr1,*ptr2;
|
||||
int len = 0;
|
||||
if(!url || !host || !file || !port){
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr1 = (char *)url;
|
||||
|
||||
if(!strncmp(ptr1,"http://",strlen("http://"))){
|
||||
ptr1 += strlen("http://");
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr2 = strchr(ptr1,'/');
|
||||
if(ptr2){
|
||||
len = strlen(ptr1) - strlen(ptr2);
|
||||
memcpy(host,ptr1,len);
|
||||
host[len] = '\0';
|
||||
if(*(ptr2 + 1)){
|
||||
memcpy(file,ptr2 + 1,strlen(ptr2) - 1 );
|
||||
file[strlen(ptr2) - 1] = '\0';
|
||||
}
|
||||
}else{
|
||||
memcpy(host,ptr1,strlen(ptr1));
|
||||
host[strlen(ptr1)] = '\0';
|
||||
}
|
||||
//get host and ip
|
||||
ptr1 = strchr(host,':');
|
||||
if(ptr1){
|
||||
*ptr1++ = '\0';
|
||||
*port = atoi(ptr1);
|
||||
}else{
|
||||
*port = MY_HTTP_DEFAULT_PORT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int http_tcpclient_recv(int socket,char *lpbuff){
|
||||
int recvnum = 0;
|
||||
|
||||
recvnum = recv(socket, lpbuff,BUFFER_SIZE*4,0);
|
||||
|
||||
return recvnum;
|
||||
}
|
||||
|
||||
static int http_tcpclient_send(int socket,char *buff,int size){
|
||||
int sent=0,tmpres=0;
|
||||
|
||||
while(sent < size){
|
||||
tmpres = send(socket,buff+sent,size-sent,0);
|
||||
if(tmpres == -1){
|
||||
return 1;
|
||||
}
|
||||
sent += tmpres;
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int http_get(const char *url,int socket_fd)
|
||||
{
|
||||
char lpbuf[BUFFER_SIZE*4] = {'\0'};
|
||||
|
||||
char host_addr[BUFFER_SIZE] = {'\0'};
|
||||
char file[BUFFER_SIZE] = {'\0'};
|
||||
int port = 0;
|
||||
|
||||
|
||||
if(!url){
|
||||
DEBUG(" failed!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(http_parse_url(url,host_addr,file,&port)){
|
||||
DEBUG("http_parse_url failed!\n");
|
||||
return 1;
|
||||
}
|
||||
DEBUG("url: %s\thost_addr : %s\tfile:%s\t,%d\n",url,host_addr,file,port);
|
||||
|
||||
|
||||
if(socket_fd < 0){
|
||||
DEBUG("http_tcpclient_create failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sprintf(lpbuf,HTTP_GET,file,host_addr,port);
|
||||
|
||||
if(http_tcpclient_send(socket_fd,lpbuf,strlen(lpbuf)) < 0){
|
||||
DEBUG("http_tcpclient_send failed..\n");
|
||||
return 1;
|
||||
}
|
||||
DEBUG("request:\n%s\n",lpbuf);
|
||||
|
||||
if(http_tcpclient_recv(socket_fd,lpbuf) <= 0){
|
||||
DEBUG("http_tcpclient_recv failed\n");
|
||||
close(socket_fd);
|
||||
return 1;
|
||||
}
|
||||
DEBUG("rec:\n%s\n",lpbuf);
|
||||
close(socket_fd);
|
||||
|
||||
//return http_parse_result(lpbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd,http_flag=0,http_ret=1;
|
||||
struct sockaddr_in addr;
|
||||
struct hostent *host;
|
||||
struct timeval timeo = {3, 0};
|
||||
socklen_t len = sizeof(timeo);
|
||||
|
||||
char http_url[100]="http://";
|
||||
|
||||
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (argc >= 4)
|
||||
timeo.tv_sec = atoi(argv[3]);
|
||||
if (argc>=5)
|
||||
http_flag=1;
|
||||
|
||||
if((host=timeGethostbyname(argv[1],timeo.tv_sec)) == NULL) {
|
||||
DEBUG("gethostbyname err\n");
|
||||
return 1;
|
||||
}
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len) == -1)
|
||||
{
|
||||
|
||||
DEBUG("setsockopt send err\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, len) == -1)
|
||||
{
|
||||
|
||||
DEBUG("setsockopt recv err\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr = *((struct in_addr *)host->h_addr);
|
||||
//addr.sin_addr.s_addr = inet_addr(argv[1]);
|
||||
addr.sin_port = htons(atoi(argv[2]));
|
||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
if (errno == EINPROGRESS)
|
||||
{
|
||||
DEBUG("timeout err\n");
|
||||
return 1;
|
||||
}
|
||||
DEBUG("connect err\n");
|
||||
return 1;
|
||||
}
|
||||
if(http_flag==0)
|
||||
{
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
strcat(http_url,argv[1]);
|
||||
http_ret=http_get(http_url,fd);
|
||||
if(http_ret==1)
|
||||
{
|
||||
DEBUG("recv err");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG("recv ok");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
58
package/lean/shadowsocksr-libev/src/server/common.h
Normal file
58
package/lean/shadowsocksr-libev/src/server/common.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* common.h - Provide global definitions
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#define DEFAULT_CONF_PATH "/etc/shadowsocks-libev/config.json"
|
||||
|
||||
#ifndef SOL_TCP
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
#endif
|
||||
|
||||
#if defined(MODULE_TUNNEL) || defined(MODULE_REDIR)
|
||||
#define MODULE_LOCAL
|
||||
#endif
|
||||
|
||||
int init_udprelay(const char *server_host, const char *server_port,
|
||||
#ifdef MODULE_LOCAL
|
||||
const struct sockaddr *remote_addr, const int remote_addr_len,
|
||||
#ifdef MODULE_TUNNEL
|
||||
const ss_addr_t tunnel_addr,
|
||||
#endif
|
||||
#endif
|
||||
int mtu, int method, int auth, int timeout, const char *iface, const char *protocol, const char *protocol_param);
|
||||
|
||||
void free_udprelay(void);
|
||||
|
||||
#ifdef ANDROID
|
||||
int protect_socket(int fd);
|
||||
int send_traffic_stat(uint64_t tx, uint64_t rx);
|
||||
#endif
|
||||
|
||||
#define STAGE_ERROR -1 /* Error detected */
|
||||
#define STAGE_INIT 0 /* Initial stage */
|
||||
#define STAGE_HANDSHAKE 1 /* Handshake with client */
|
||||
#define STAGE_PARSE 2 /* Parse the header */
|
||||
#define STAGE_RESOLVE 4 /* Resolve the hostname */
|
||||
#define STAGE_STREAM 5 /* Stream between client and server */
|
||||
|
||||
#endif // _COMMON_H
|
||||
97
package/lean/shadowsocksr-libev/src/server/crc32.c
Normal file
97
package/lean/shadowsocksr-libev/src/server/crc32.c
Normal file
@ -0,0 +1,97 @@
|
||||
static uint32_t crc32_table[256] = {0};
|
||||
|
||||
void init_crc32_table(void) {
|
||||
uint32_t c, i, j;
|
||||
if (crc32_table[0] == 0) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
c = i;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (c & 1)
|
||||
c = 0xedb88320L ^ (c >> 1);
|
||||
else
|
||||
c = c >> 1;
|
||||
}
|
||||
crc32_table[i] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t crc32(unsigned char *buffer, unsigned int size) {
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
unsigned int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
crc = crc32_table[(crc ^ buffer[i]) & 0xFF] ^ (crc >> 8);
|
||||
}
|
||||
return crc ^ 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void fillcrc32to(unsigned char *buffer, unsigned int size, unsigned char *outbuffer) {
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
unsigned int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
crc = crc32_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
|
||||
}
|
||||
crc ^= 0xFFFFFFFF;
|
||||
outbuffer[0] = crc;
|
||||
outbuffer[1] = crc >> 8;
|
||||
outbuffer[2] = crc >> 16;
|
||||
outbuffer[3] = crc >> 24;
|
||||
}
|
||||
|
||||
void fillcrc32(unsigned char *buffer, unsigned int size) {
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
unsigned int i;
|
||||
size -= 4;
|
||||
for (i = 0; i < size; i++) {
|
||||
crc = crc32_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
|
||||
}
|
||||
buffer += size;
|
||||
buffer[0] = crc;
|
||||
buffer[1] = crc >> 8;
|
||||
buffer[2] = crc >> 16;
|
||||
buffer[3] = crc >> 24;
|
||||
}
|
||||
|
||||
void adler32_short(unsigned char *buffer, unsigned int size, uint32_t *a, uint32_t *b) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
*a += buffer[i];
|
||||
*b += *a;
|
||||
}
|
||||
*a %= 65521;
|
||||
*b %= 65521;
|
||||
}
|
||||
|
||||
#define NMAX 5552
|
||||
uint32_t adler32(unsigned char *buffer, unsigned int size) {
|
||||
uint32_t a = 1;
|
||||
uint32_t b = 0;
|
||||
while ( size >= NMAX ) {
|
||||
adler32_short(buffer, NMAX, &a, &b);
|
||||
buffer += NMAX;
|
||||
size -= NMAX;
|
||||
}
|
||||
adler32_short(buffer, size, &a, &b);
|
||||
return (b << 16) + a;
|
||||
}
|
||||
#undef NMAX
|
||||
|
||||
void filladler32(unsigned char *buffer, unsigned int size) {
|
||||
size -= 4;
|
||||
uint32_t checksum = adler32(buffer, size);
|
||||
buffer += size;
|
||||
buffer[0] = checksum;
|
||||
buffer[1] = checksum >> 8;
|
||||
buffer[2] = checksum >> 16;
|
||||
buffer[3] = checksum >> 24;
|
||||
}
|
||||
|
||||
int checkadler32(unsigned char *buffer, unsigned int size) {
|
||||
size -= 4;
|
||||
uint32_t checksum = adler32(buffer, size);
|
||||
buffer += size;
|
||||
return checksum == (((uint32_t)buffer[3] << 24)
|
||||
| ((uint32_t)buffer[2] << 16)
|
||||
| ((uint32_t)buffer[1] << 8)
|
||||
| (uint32_t)buffer[0]);
|
||||
}
|
||||
|
||||
1645
package/lean/shadowsocksr-libev/src/server/encrypt.c
Normal file
1645
package/lean/shadowsocksr-libev/src/server/encrypt.c
Normal file
File diff suppressed because it is too large
Load Diff
222
package/lean/shadowsocksr-libev/src/server/encrypt.h
Normal file
222
package/lean/shadowsocksr-libev/src/server/encrypt.h
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* encrypt.h - Define the enryptor's interface
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ENCRYPT_H
|
||||
#define _ENCRYPT_H
|
||||
|
||||
#ifndef __MINGW32__
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
typedef EVP_CIPHER cipher_kt_t;
|
||||
typedef EVP_CIPHER_CTX cipher_evp_t;
|
||||
typedef EVP_MD digest_type_t;
|
||||
#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH
|
||||
#define MAX_IV_LENGTH EVP_MAX_IV_LENGTH
|
||||
#define MAX_MD_SIZE EVP_MAX_MD_SIZE
|
||||
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
|
||||
#include <polarssl/cipher.h>
|
||||
#include <polarssl/md.h>
|
||||
typedef cipher_info_t cipher_kt_t;
|
||||
typedef cipher_context_t cipher_evp_t;
|
||||
typedef md_info_t digest_type_t;
|
||||
#define MAX_KEY_LENGTH 64
|
||||
#define MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH
|
||||
#define MAX_MD_SIZE POLARSSL_MD_MAX_SIZE
|
||||
|
||||
#elif defined(USE_CRYPTO_MBEDTLS)
|
||||
|
||||
#include <mbedtls/cipher.h>
|
||||
#include <mbedtls/md.h>
|
||||
typedef mbedtls_cipher_info_t cipher_kt_t;
|
||||
typedef mbedtls_cipher_context_t cipher_evp_t;
|
||||
typedef mbedtls_md_info_t digest_type_t;
|
||||
#define MAX_KEY_LENGTH 64
|
||||
#define MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH
|
||||
#define MAX_MD_SIZE MBEDTLS_MD_MAX_SIZE
|
||||
|
||||
/* we must have MBEDTLS_CIPHER_MODE_CFB defined */
|
||||
#if !defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||
#error Cipher Feedback mode a.k.a CFB not supported by your mbed TLS.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
|
||||
#include <CommonCrypto/CommonCrypto.h>
|
||||
|
||||
#define kCCAlgorithmInvalid UINT32_MAX
|
||||
#define kCCContextValid 0
|
||||
#define kCCContextInvalid -1
|
||||
|
||||
typedef struct {
|
||||
CCCryptorRef cryptor;
|
||||
int valid;
|
||||
CCOperation encrypt;
|
||||
CCAlgorithm cipher;
|
||||
CCMode mode;
|
||||
CCPadding padding;
|
||||
uint8_t iv[MAX_IV_LENGTH];
|
||||
uint8_t key[MAX_KEY_LENGTH];
|
||||
size_t iv_len;
|
||||
size_t key_len;
|
||||
} cipher_cc_t;
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
cipher_evp_t *evp;
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t cc;
|
||||
#endif
|
||||
uint8_t iv[MAX_IV_LENGTH];
|
||||
} cipher_ctx_t;
|
||||
|
||||
typedef struct {
|
||||
cipher_kt_t *info;
|
||||
size_t iv_len;
|
||||
size_t key_len;
|
||||
} cipher_t;
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#define SODIUM_BLOCK_SIZE 64
|
||||
|
||||
enum crpher_index {
|
||||
NONE = -1,
|
||||
TABLE = 0,
|
||||
RC4,
|
||||
RC4_MD5_6,
|
||||
RC4_MD5,
|
||||
AES_128_CFB,
|
||||
AES_192_CFB,
|
||||
AES_256_CFB,
|
||||
AES_128_CTR,
|
||||
AES_192_CTR,
|
||||
AES_256_CTR,
|
||||
BF_CFB,
|
||||
CAMELLIA_128_CFB,
|
||||
CAMELLIA_192_CFB,
|
||||
CAMELLIA_256_CFB,
|
||||
CAST5_CFB,
|
||||
DES_CFB,
|
||||
IDEA_CFB,
|
||||
RC2_CFB,
|
||||
SEED_CFB,
|
||||
SALSA20,
|
||||
CHACHA20,
|
||||
CHACHA20IETF,
|
||||
CIPHER_NUM,
|
||||
};
|
||||
|
||||
#define ONETIMEAUTH_FLAG 0x10
|
||||
#define ADDRTYPE_MASK 0xEF
|
||||
|
||||
#define ONETIMEAUTH_BYTES 10U
|
||||
#define MD5_BYTES 16U
|
||||
#define SHA1_BYTES 20U
|
||||
#define CLEN_BYTES 2U
|
||||
#define AUTH_BYTES (ONETIMEAUTH_BYTES + CLEN_BYTES)
|
||||
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
typedef struct buffer {
|
||||
size_t idx;
|
||||
size_t len;
|
||||
size_t capacity;
|
||||
char *array;
|
||||
} buffer_t;
|
||||
|
||||
typedef struct chunk {
|
||||
uint32_t idx;
|
||||
uint32_t len;
|
||||
uint32_t counter;
|
||||
buffer_t *buf;
|
||||
} chunk_t;
|
||||
|
||||
typedef struct enc_ctx {
|
||||
uint8_t init;
|
||||
uint64_t counter;
|
||||
cipher_ctx_t evp;
|
||||
} enc_ctx_t;
|
||||
|
||||
void bytes_to_key_with_size(const char *pass, size_t len, uint8_t *md, size_t md_size);
|
||||
|
||||
int ss_encrypt_all(buffer_t *plaintext, int method, int auth, size_t capacity);
|
||||
int ss_decrypt_all(buffer_t *ciphertext, int method, int auth, size_t capacity);
|
||||
int ss_encrypt(buffer_t *plaintext, enc_ctx_t *ctx, size_t capacity);
|
||||
int ss_decrypt(buffer_t *ciphertext, enc_ctx_t *ctx, size_t capacity);
|
||||
|
||||
void enc_ctx_init(int method, enc_ctx_t *ctx, int enc);
|
||||
int enc_init(const char *pass, const char *method);
|
||||
int enc_get_iv_len(void);
|
||||
uint8_t* enc_get_key(void);
|
||||
int enc_get_key_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_md5_hmac(char *auth, char *msg, int msg_len, uint8_t *iv);
|
||||
int ss_md5_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len);
|
||||
int ss_md5_hash_func(char *auth, char *msg, int msg_len);
|
||||
int ss_sha1_hmac(char *auth, char *msg, int msg_len, uint8_t *iv);
|
||||
int ss_sha1_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len);
|
||||
int ss_sha1_hash_func(char *auth, char *msg, int msg_len);
|
||||
int ss_aes_128_cbc(char *encrypt, char *out_data, char *key);
|
||||
int ss_onetimeauth(buffer_t *buf, uint8_t *iv, size_t capacity);
|
||||
int ss_onetimeauth_verify(buffer_t *buf, uint8_t *iv);
|
||||
|
||||
int ss_check_hash(buffer_t *buf, chunk_t *chunk, enc_ctx_t *ctx, size_t capacity);
|
||||
int ss_gen_hash(buffer_t *buf, uint32_t *counter, enc_ctx_t *ctx, size_t capacity);
|
||||
|
||||
int balloc(buffer_t *ptr, size_t capacity);
|
||||
int brealloc(buffer_t *ptr, size_t len, size_t capacity);
|
||||
void bfree(buffer_t *ptr);
|
||||
|
||||
#endif // _ENCRYPT_H
|
||||
152
package/lean/shadowsocksr-libev/src/server/http.c
Normal file
152
package/lean/shadowsocksr-libev/src/server/http.c
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* malloc() */
|
||||
#include <string.h> /* strncpy() */
|
||||
#include <strings.h> /* strncasecmp() */
|
||||
#include <ctype.h> /* isblank() */
|
||||
|
||||
#include "http.h"
|
||||
#include "protocol.h"
|
||||
|
||||
#define SERVER_NAME_LEN 256
|
||||
|
||||
static int parse_http_header(const char *, size_t, char **);
|
||||
static int get_header(const char *, const char *, int, char **);
|
||||
static int next_header(const char **, int *);
|
||||
|
||||
static const protocol_t http_protocol_st = {
|
||||
.default_port = 80,
|
||||
.parse_packet = &parse_http_header,
|
||||
};
|
||||
const protocol_t *const http_protocol = &http_protocol_st;
|
||||
|
||||
/*
|
||||
* Parses a HTTP request for the Host: header
|
||||
*
|
||||
* Returns:
|
||||
* >=0 - length of the hostname and updates *hostname
|
||||
* caller is responsible for freeing *hostname
|
||||
* -1 - Incomplete request
|
||||
* -2 - No Host header included in this request
|
||||
* -3 - Invalid hostname pointer
|
||||
* -4 - malloc failure
|
||||
* < -4 - Invalid HTTP request
|
||||
*
|
||||
*/
|
||||
static int
|
||||
parse_http_header(const char *data, size_t data_len, char **hostname)
|
||||
{
|
||||
int result, i;
|
||||
|
||||
if (hostname == NULL)
|
||||
return -3;
|
||||
|
||||
if (data_len == 0)
|
||||
return -1;
|
||||
|
||||
result = get_header("Host:", data, data_len, hostname);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
/*
|
||||
* if the user specifies the port in the request, it is included here.
|
||||
* Host: example.com:80
|
||||
* so we trim off port portion
|
||||
*/
|
||||
for (i = result - 1; i >= 0; i--)
|
||||
if ((*hostname)[i] == ':') {
|
||||
(*hostname)[i] = '\0';
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
get_header(const char *header, const char *data, int data_len, char **value)
|
||||
{
|
||||
int len, header_len;
|
||||
|
||||
header_len = strlen(header);
|
||||
|
||||
/* loop through headers stopping at first blank line */
|
||||
while ((len = next_header(&data, &data_len)) != 0)
|
||||
if (len > header_len && strncasecmp(header, data, header_len) == 0) {
|
||||
/* Eat leading whitespace */
|
||||
while (header_len < len && isblank(data[header_len]))
|
||||
header_len++;
|
||||
|
||||
*value = malloc(len - header_len + 1);
|
||||
if (*value == NULL)
|
||||
return -4;
|
||||
|
||||
strncpy(*value, data + header_len, len - header_len);
|
||||
(*value)[len - header_len] = '\0';
|
||||
|
||||
return len - header_len;
|
||||
}
|
||||
|
||||
/* If there is no data left after reading all the headers then we do not
|
||||
* have a complete HTTP request, there must be a blank line */
|
||||
if (data_len == 0)
|
||||
return -1;
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int
|
||||
next_header(const char **data, int *len)
|
||||
{
|
||||
int header_len;
|
||||
|
||||
/* perhaps we can optimize this to reuse the value of header_len, rather
|
||||
* than scanning twice.
|
||||
* Walk our data stream until the end of the header */
|
||||
while (*len > 2 && (*data)[0] != '\r' && (*data)[1] != '\n') {
|
||||
(*len)--;
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
/* advanced past the <CR><LF> pair */
|
||||
*data += 2;
|
||||
*len -= 2;
|
||||
|
||||
/* Find the length of the next header */
|
||||
header_len = 0;
|
||||
while (*len > header_len + 1
|
||||
&& (*data)[header_len] != '\r'
|
||||
&& (*data)[header_len + 1] != '\n')
|
||||
header_len++;
|
||||
|
||||
return header_len;
|
||||
}
|
||||
34
package/lean/shadowsocksr-libev/src/server/http.h
Normal file
34
package/lean/shadowsocksr-libev/src/server/http.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef HTTP_H
|
||||
#define HTTP_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "protocol.h"
|
||||
|
||||
const protocol_t *const http_protocol;
|
||||
|
||||
#endif
|
||||
625
package/lean/shadowsocksr-libev/src/server/http_simple.c
Normal file
625
package/lean/shadowsocksr-libev/src/server/http_simple.c
Normal file
@ -0,0 +1,625 @@
|
||||
|
||||
#include "http_simple.h"
|
||||
|
||||
static char* g_useragent[] = {
|
||||
"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0",
|
||||
"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/44.0",
|
||||
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Ubuntu/11.10 Chromium/27.0.1453.93 Chrome/27.0.1453.93 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0",
|
||||
"Mozilla/5.0 (compatible; WOW64; MSIE 10.0; Windows NT 6.2)",
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)",
|
||||
"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",
|
||||
"Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/BuildID) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
|
||||
};
|
||||
|
||||
static int g_useragent_index = -1;
|
||||
|
||||
typedef struct http_simple_local_data {
|
||||
int has_sent_header;
|
||||
int has_recv_header;
|
||||
char *encode_buffer;
|
||||
int host_matched;
|
||||
char *recv_buffer;
|
||||
int recv_buffer_size;
|
||||
}http_simple_local_data;
|
||||
|
||||
void http_simple_local_data_init(http_simple_local_data* local) {
|
||||
local->has_sent_header = 0;
|
||||
local->has_recv_header = 0;
|
||||
local->encode_buffer = NULL;
|
||||
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
|
||||
local->host_matched = 0;
|
||||
|
||||
if (g_useragent_index == -1) {
|
||||
g_useragent_index = xorshift128plus() % (sizeof(g_useragent) / sizeof(*g_useragent));
|
||||
}
|
||||
}
|
||||
|
||||
obfs * http_simple_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(http_simple_local_data));
|
||||
http_simple_local_data_init((http_simple_local_data*)self->l_data);
|
||||
return self;
|
||||
}
|
||||
|
||||
void http_simple_dispose(obfs *self) {
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
if (local->encode_buffer != NULL) {
|
||||
free(local->encode_buffer);
|
||||
local->encode_buffer = NULL;
|
||||
}
|
||||
free(local);
|
||||
dispose_obfs(self);
|
||||
}
|
||||
|
||||
char http_simple_hex(char c) {
|
||||
if (c < 10) return c + '0';
|
||||
return c - 10 + 'a';
|
||||
}
|
||||
|
||||
int get_data_from_http_header(char *data, char **outdata) {
|
||||
char *delim = "\r\n";
|
||||
char *delim_hex = "%";
|
||||
int outlength = 0;
|
||||
|
||||
char *buf = *outdata;
|
||||
char *p_line;
|
||||
p_line = strtok(data, delim);
|
||||
|
||||
//while(p_line)
|
||||
{
|
||||
char *p_hex;
|
||||
|
||||
p_hex = strtok(p_line, delim_hex);
|
||||
|
||||
while((p_hex = strtok(NULL, delim_hex)))
|
||||
{
|
||||
char hex = 0;
|
||||
|
||||
if(strlen(p_hex) <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strlen(p_hex) > 2)
|
||||
{
|
||||
char *c_hex = (char*)malloc(2);
|
||||
memcpy(c_hex, p_hex, 2);
|
||||
hex = (char)strtol(c_hex, NULL, 16);
|
||||
free(c_hex);
|
||||
}
|
||||
else
|
||||
{
|
||||
hex = (char)strtol(p_hex, NULL, 16);
|
||||
}
|
||||
|
||||
outlength += 1;
|
||||
buf = (char*)realloc(buf, outlength);
|
||||
buf[outlength - 1] = hex;
|
||||
}
|
||||
|
||||
//p_line = strtok(p_line, delim);
|
||||
}
|
||||
return outlength;
|
||||
}
|
||||
|
||||
void get_host_from_http_header(char *data, char **host) {
|
||||
char* data_begin = strstr(data, "Host: ");
|
||||
|
||||
if(data_begin == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data_begin += 6;
|
||||
char* data_end = strstr(data_begin, "\r\n");
|
||||
char* data_end_port = strstr(data_begin, ":");
|
||||
|
||||
int host_length = 0;
|
||||
|
||||
if(data_end_port != NULL)
|
||||
{
|
||||
host_length = data_end_port - data_begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
host_length = data_end - data_begin;
|
||||
}
|
||||
|
||||
if(host_length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memset(*host, 0x00, 1024);
|
||||
memcpy(*host, data_begin, host_length);
|
||||
}
|
||||
|
||||
void http_simple_encode_head(http_simple_local_data *local, char *data, int datalength) {
|
||||
if (local->encode_buffer == NULL) {
|
||||
local->encode_buffer = (char*)malloc(datalength * 3 + 1);
|
||||
}
|
||||
int pos = 0;
|
||||
for (; pos < datalength; ++pos) {
|
||||
local->encode_buffer[pos * 3] = '%';
|
||||
local->encode_buffer[pos * 3 + 1] = http_simple_hex(((unsigned char)data[pos] >> 4));
|
||||
local->encode_buffer[pos * 3 + 2] = http_simple_hex(data[pos] & 0xF);
|
||||
}
|
||||
local->encode_buffer[pos * 3] = 0;
|
||||
}
|
||||
|
||||
int http_simple_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
if (local->has_sent_header) {
|
||||
return datalength;
|
||||
}
|
||||
char hosts[1024];
|
||||
char * phost[128];
|
||||
int host_num = 0;
|
||||
int pos;
|
||||
char hostport[128];
|
||||
int head_size = self->server.head_len + (xorshift128plus() & 0x3F);
|
||||
int outlength;
|
||||
char * out_buffer = (char*)malloc(datalength + 2048);
|
||||
char * body_buffer = NULL;
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
http_simple_encode_head(local, encryptdata, head_size);
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
self->server.param = NULL;
|
||||
strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts);
|
||||
phost[host_num++] = hosts;
|
||||
for (pos = 0; hosts[pos]; ++pos) {
|
||||
if (hosts[pos] == ',') {
|
||||
phost[host_num++] = &hosts[pos + 1];
|
||||
hosts[pos] = 0;
|
||||
} else if (hosts[pos] == '#') {
|
||||
char * body_pointer = &hosts[pos + 1];
|
||||
char * p;
|
||||
int trans_char = 0;
|
||||
p = body_buffer = (char*)malloc(2048);
|
||||
for ( ; *body_pointer; ++body_pointer) {
|
||||
if (*body_pointer == '\\') {
|
||||
trans_char = 1;
|
||||
continue;
|
||||
} else if (*body_pointer == '\n') {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
continue;
|
||||
}
|
||||
if (trans_char) {
|
||||
if (*body_pointer == '\\' ) {
|
||||
*p = '\\';
|
||||
} else if (*body_pointer == 'n' ) {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
} else {
|
||||
*p = '\\';
|
||||
*p = *body_pointer;
|
||||
}
|
||||
trans_char = 0;
|
||||
} else {
|
||||
*p = *body_pointer;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
*p = 0;
|
||||
hosts[pos] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
host_num = xorshift128plus() % host_num;
|
||||
if (self->server.port == 80)
|
||||
sprintf(hostport, "%s", phost[host_num]);
|
||||
else
|
||||
sprintf(hostport, "%s:%d", phost[host_num], self->server.port);
|
||||
if (body_buffer) {
|
||||
sprintf(out_buffer,
|
||||
"GET /%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"%s\r\n\r\n",
|
||||
local->encode_buffer,
|
||||
hostport,
|
||||
body_buffer);
|
||||
} else {
|
||||
sprintf(out_buffer,
|
||||
"GET /%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"User-Agent: %s\r\n"
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
|
||||
"Accept-Language: en-US,en;q=0.8\r\n"
|
||||
"Accept-Encoding: gzip, deflate\r\n"
|
||||
"DNT: 1\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"\r\n",
|
||||
local->encode_buffer,
|
||||
hostport,
|
||||
g_useragent[g_useragent_index]
|
||||
);
|
||||
}
|
||||
//LOGI("http header: %s", out_buffer);
|
||||
outlength = strlen(out_buffer);
|
||||
memmove(out_buffer + outlength, encryptdata + head_size, datalength - head_size);
|
||||
outlength += datalength - head_size;
|
||||
local->has_sent_header = 1;
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
if (body_buffer != NULL)
|
||||
free(body_buffer);
|
||||
if (local->encode_buffer != NULL) {
|
||||
free(local->encode_buffer);
|
||||
local->encode_buffer = NULL;
|
||||
}
|
||||
return outlength;
|
||||
}
|
||||
|
||||
int http_simple_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
if (local->has_sent_header) {
|
||||
return datalength;
|
||||
}
|
||||
int outlength;
|
||||
char * out_buffer = (char*)malloc(datalength + 2048);
|
||||
|
||||
time_t now;
|
||||
struct tm *tm_now;
|
||||
char datetime[200];
|
||||
|
||||
time(&now);
|
||||
tm_now = localtime(&now);
|
||||
strftime(datetime, 200, "%a, %d %b %Y %H:%M:%S GMT", tm_now);
|
||||
|
||||
sprintf(out_buffer,
|
||||
"HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Encoding: gzip\r\nContent-Type: text/html\r\nDate: "
|
||||
"%s"
|
||||
"\r\nServer: nginx\r\nVary: Accept-Encoding\r\n\r\n",
|
||||
datetime);
|
||||
|
||||
outlength = strlen(out_buffer);
|
||||
memmove(out_buffer + outlength, encryptdata, datalength);
|
||||
outlength += datalength;
|
||||
|
||||
local->has_sent_header = 1;
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
return outlength;
|
||||
}
|
||||
|
||||
int http_simple_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
*needsendback = 0;
|
||||
if (local->has_recv_header) {
|
||||
return datalength;
|
||||
}
|
||||
char* data_begin = strstr(encryptdata, "\r\n\r\n");
|
||||
if (data_begin) {
|
||||
int outlength;
|
||||
data_begin += 4;
|
||||
local->has_recv_header = 1;
|
||||
outlength = datalength - (data_begin - encryptdata);
|
||||
memmove(encryptdata, data_begin, outlength);
|
||||
return outlength;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int http_simple_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
*needsendback = 0;
|
||||
if (local->has_recv_header) {
|
||||
return datalength;
|
||||
}
|
||||
|
||||
if(datalength != 0)
|
||||
{
|
||||
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength);
|
||||
memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
int outlength = local->recv_buffer_size;
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata, local->recv_buffer, local->recv_buffer_size);
|
||||
}
|
||||
|
||||
if(local->recv_buffer_size > 10)
|
||||
{
|
||||
if(strstr(local->recv_buffer, "GET /") == local->recv_buffer || strstr(local->recv_buffer, "POST /") == local->recv_buffer)
|
||||
{
|
||||
if(local->recv_buffer_size > 65536)
|
||||
{
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
local->has_sent_header = 1;
|
||||
local->has_recv_header = 1;
|
||||
LOGE("http_simple: over size");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
local->has_sent_header = 1;
|
||||
local->has_recv_header = 1;
|
||||
LOGE("http_simple: not match begin");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGE("http_simple: too short");
|
||||
local->has_sent_header = 1;
|
||||
local->has_recv_header = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* data_begin = strstr(encryptdata, "\r\n\r\n");
|
||||
if (data_begin) {
|
||||
int outlength;
|
||||
char *ret_buf = (char*)malloc(*capacity);
|
||||
memset(ret_buf, 0x00, *capacity);
|
||||
int ret_buf_len = 0;
|
||||
ret_buf_len = get_data_from_http_header(encryptdata, &ret_buf);
|
||||
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
{
|
||||
self->server.param = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(local->host_matched == 0)
|
||||
{
|
||||
char *host = (char*)malloc(1024);
|
||||
get_host_from_http_header(local->recv_buffer, &host);
|
||||
char hosts[1024];
|
||||
char * phost[128];
|
||||
int host_num = 0;
|
||||
int pos = 0;
|
||||
int is_match = 0;
|
||||
char * body_buffer = NULL;
|
||||
strncpy(hosts, self->server.param, sizeof hosts);
|
||||
phost[host_num++] = hosts;
|
||||
|
||||
for (pos = 0; hosts[pos]; ++pos) {
|
||||
if (hosts[pos] == ',') {
|
||||
phost[host_num++] = &hosts[pos + 1];
|
||||
hosts[pos] = 0;
|
||||
} else if (hosts[pos] == '#') {
|
||||
char * body_pointer = &hosts[pos + 1];
|
||||
char * p;
|
||||
int trans_char = 0;
|
||||
p = body_buffer = (char*)malloc(2048);
|
||||
for ( ; *body_pointer; ++body_pointer) {
|
||||
if (*body_pointer == '\\') {
|
||||
trans_char = 1;
|
||||
continue;
|
||||
} else if (*body_pointer == '\n') {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
continue;
|
||||
}
|
||||
if (trans_char) {
|
||||
if (*body_pointer == '\\' ) {
|
||||
*p = '\\';
|
||||
} else if (*body_pointer == 'n' ) {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
} else {
|
||||
*p = '\\';
|
||||
*p = *body_pointer;
|
||||
}
|
||||
trans_char = 0;
|
||||
} else {
|
||||
*p = *body_pointer;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
*p = 0;
|
||||
hosts[pos] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(pos = 0; pos < host_num; pos++)
|
||||
{
|
||||
if(strcmp(phost[pos], host) == 0)
|
||||
{
|
||||
is_match = 1;
|
||||
local->host_matched = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(is_match == 0)
|
||||
{
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
local->has_sent_header = 1;
|
||||
local->has_recv_header = 1;
|
||||
LOGE("http_simple: not match host, host: %s", host);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(host);
|
||||
}
|
||||
}
|
||||
|
||||
if(ret_buf_len <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
data_begin += 4;
|
||||
local->has_recv_header = 1;
|
||||
|
||||
ret_buf = (char*)realloc(ret_buf, ret_buf_len + datalength - (data_begin - encryptdata));
|
||||
outlength = ret_buf_len + datalength - (data_begin - encryptdata);
|
||||
|
||||
memcpy(ret_buf + ret_buf_len, data_begin, datalength - (data_begin - encryptdata));
|
||||
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
|
||||
memcpy(encryptdata, ret_buf, outlength);
|
||||
free(ret_buf);
|
||||
return outlength;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void boundary(char result[])
|
||||
{
|
||||
char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
int i,lstr;
|
||||
char ss[3] = {0};
|
||||
lstr = strlen(str);
|
||||
srand((unsigned int)time((time_t *)NULL));
|
||||
for(i = 0; i < 32; ++i)
|
||||
{
|
||||
sprintf(ss, "%c", str[(rand()%lstr)]);
|
||||
strcat(result, ss);
|
||||
}
|
||||
}
|
||||
|
||||
int http_post_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
if (local->has_sent_header) {
|
||||
return datalength;
|
||||
}
|
||||
char hosts[1024];
|
||||
char * phost[128];
|
||||
int host_num = 0;
|
||||
int pos;
|
||||
char hostport[128];
|
||||
int head_size = self->server.head_len + (xorshift128plus() & 0x3F);
|
||||
int outlength;
|
||||
char * out_buffer = (char*)malloc(datalength + 2048);
|
||||
char * body_buffer = NULL;
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
http_simple_encode_head(local, encryptdata, head_size);
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
self->server.param = NULL;
|
||||
strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts);
|
||||
phost[host_num++] = hosts;
|
||||
for (pos = 0; hosts[pos]; ++pos) {
|
||||
if (hosts[pos] == ',') {
|
||||
phost[host_num++] = &hosts[pos + 1];
|
||||
hosts[pos] = 0;
|
||||
} else if (hosts[pos] == '#') {
|
||||
char * body_pointer = &hosts[pos + 1];
|
||||
char * p;
|
||||
int trans_char = 0;
|
||||
p = body_buffer = (char*)malloc(2048);
|
||||
for ( ; *body_pointer; ++body_pointer) {
|
||||
if (*body_pointer == '\\') {
|
||||
trans_char = 1;
|
||||
continue;
|
||||
} else if (*body_pointer == '\n') {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
continue;
|
||||
}
|
||||
if (trans_char) {
|
||||
if (*body_pointer == '\\' ) {
|
||||
*p = '\\';
|
||||
} else if (*body_pointer == 'n' ) {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
} else {
|
||||
*p = '\\';
|
||||
*p = *body_pointer;
|
||||
}
|
||||
trans_char = 0;
|
||||
} else {
|
||||
*p = *body_pointer;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
*p = 0;
|
||||
hosts[pos] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
host_num = xorshift128plus() % host_num;
|
||||
if (self->server.port == 80)
|
||||
sprintf(hostport, "%s", phost[host_num]);
|
||||
else
|
||||
sprintf(hostport, "%s:%d", phost[host_num], self->server.port);
|
||||
if (body_buffer) {
|
||||
sprintf(out_buffer,
|
||||
"POST /%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"%s\r\n\r\n",
|
||||
local->encode_buffer,
|
||||
hostport,
|
||||
body_buffer);
|
||||
} else {
|
||||
char result[33] = {0};
|
||||
boundary(result);
|
||||
sprintf(out_buffer,
|
||||
"POST /%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"User-Agent: %s\r\n"
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
|
||||
"Accept-Language: en-US,en;q=0.8\r\n"
|
||||
"Accept-Encoding: gzip, deflate\r\n"
|
||||
"Content-Type: multipart/form-data; boundary=%s\r\n"
|
||||
"DNT: 1\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"\r\n",
|
||||
local->encode_buffer,
|
||||
hostport,
|
||||
g_useragent[g_useragent_index],
|
||||
result
|
||||
);
|
||||
}
|
||||
//LOGI("http header: %s", out_buffer);
|
||||
outlength = strlen(out_buffer);
|
||||
memmove(out_buffer + outlength, encryptdata + head_size, datalength - head_size);
|
||||
outlength += datalength - head_size;
|
||||
local->has_sent_header = 1;
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
if (body_buffer != NULL)
|
||||
free(body_buffer);
|
||||
if (local->encode_buffer != NULL) {
|
||||
free(local->encode_buffer);
|
||||
local->encode_buffer = NULL;
|
||||
}
|
||||
return outlength;
|
||||
}
|
||||
21
package/lean/shadowsocksr-libev/src/server/http_simple.h
Normal file
21
package/lean/shadowsocksr-libev/src/server/http_simple.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* http_simple.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _HTTP_SIMPLE_H
|
||||
#define _HTTP_SIMPLE_H
|
||||
|
||||
obfs * http_simple_new_obfs();
|
||||
void http_simple_dispose(obfs *self);
|
||||
|
||||
int http_simple_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
int http_simple_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback);
|
||||
|
||||
int http_post_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
|
||||
int http_simple_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
int http_simple_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback);
|
||||
|
||||
#endif // _HTTP_SIMPLE_H
|
||||
260
package/lean/shadowsocksr-libev/src/server/jconf.c
Normal file
260
package/lean/shadowsocksr-libev/src/server/jconf.c
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* jconf.c - Parse the JSON format config file
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "jconf.h"
|
||||
#include "json.h"
|
||||
#include "string.h"
|
||||
|
||||
#include <libcork/core.h>
|
||||
|
||||
#define check_json_value_type(value, expected_type, message) \
|
||||
do { \
|
||||
if ((value)->type != (expected_type)) \
|
||||
FATAL((message)); \
|
||||
} while(0)
|
||||
|
||||
static char *
|
||||
to_string(const json_value *value)
|
||||
{
|
||||
if (value->type == json_string) {
|
||||
return ss_strndup(value->u.string.ptr, value->u.string.length);
|
||||
} else if (value->type == json_integer) {
|
||||
return strdup(ss_itoa(value->u.integer));
|
||||
} else if (value->type == json_null) {
|
||||
return "null";
|
||||
} else {
|
||||
LOGE("%d", value->type);
|
||||
FATAL("Invalid config format.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
free_addr(ss_addr_t *addr)
|
||||
{
|
||||
ss_free(addr->host);
|
||||
ss_free(addr->port);
|
||||
}
|
||||
|
||||
void
|
||||
parse_addr(const char *str, ss_addr_t *addr)
|
||||
{
|
||||
int ipv6 = 0, ret = -1, n = 0;
|
||||
char *pch;
|
||||
|
||||
struct cork_ip ip;
|
||||
if (cork_ip_init(&ip, str) != -1) {
|
||||
addr->host = strdup(str);
|
||||
addr->port = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
pch = strchr(str, ':');
|
||||
while (pch != NULL) {
|
||||
n++;
|
||||
ret = pch - str;
|
||||
pch = strchr(pch + 1, ':');
|
||||
}
|
||||
if (n > 1) {
|
||||
ipv6 = 1;
|
||||
if (str[ret - 1] != ']') {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
if (ipv6) {
|
||||
addr->host = ss_strndup(str + 1, strlen(str) - 2);
|
||||
} else {
|
||||
addr->host = strdup(str);
|
||||
}
|
||||
addr->port = NULL;
|
||||
} else {
|
||||
if (ipv6) {
|
||||
addr->host = ss_strndup(str + 1, ret - 2);
|
||||
} else {
|
||||
addr->host = ss_strndup(str, ret);
|
||||
}
|
||||
addr->port = strdup(str + ret + 1);
|
||||
}
|
||||
}
|
||||
|
||||
jconf_t *
|
||||
read_jconf(const char *file)
|
||||
{
|
||||
static jconf_t conf;
|
||||
|
||||
memset(&conf, 0, sizeof(jconf_t));
|
||||
|
||||
char *buf;
|
||||
json_value *obj;
|
||||
|
||||
FILE *f = fopen(file, "rb");
|
||||
if (f == NULL) {
|
||||
FATAL("Invalid config path.");
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
long pos = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
if (pos >= MAX_CONF_SIZE) {
|
||||
FATAL("Too large config file.");
|
||||
}
|
||||
|
||||
buf = ss_malloc(pos + 1);
|
||||
if (buf == NULL) {
|
||||
FATAL("No enough memory.");
|
||||
}
|
||||
|
||||
int nread = fread(buf, pos, 1, f);
|
||||
if (!nread) {
|
||||
FATAL("Failed to read the config file.");
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
buf[pos] = '\0'; // end of string
|
||||
|
||||
json_settings settings = { 0UL, 0, NULL, NULL, NULL };
|
||||
char error_buf[512];
|
||||
obj = json_parse_ex(&settings, buf, pos, error_buf);
|
||||
|
||||
if (obj == NULL) {
|
||||
FATAL(error_buf);
|
||||
}
|
||||
|
||||
if (obj->type == json_object) {
|
||||
unsigned int i, j;
|
||||
for (i = 0; i < obj->u.object.length; i++) {
|
||||
char *name = obj->u.object.values[i].name;
|
||||
json_value *value = obj->u.object.values[i].value;
|
||||
if (strcmp(name, "server") == 0) {
|
||||
if (value->type == json_array) {
|
||||
for (j = 0; j < value->u.array.length; j++) {
|
||||
if (j >= MAX_REMOTE_NUM) {
|
||||
break;
|
||||
}
|
||||
json_value *v = value->u.array.values[j];
|
||||
char *addr_str = to_string(v);
|
||||
parse_addr(addr_str, conf.remote_addr + j);
|
||||
ss_free(addr_str);
|
||||
conf.remote_num = j + 1;
|
||||
}
|
||||
} else if (value->type == json_string) {
|
||||
conf.remote_addr[0].host = to_string(value);
|
||||
conf.remote_addr[0].port = NULL;
|
||||
conf.remote_num = 1;
|
||||
}
|
||||
} else if (strcmp(name, "port_password") == 0) {
|
||||
if (value->type == json_object) {
|
||||
for (j = 0; j < value->u.object.length; j++) {
|
||||
if (j >= MAX_PORT_NUM) {
|
||||
break;
|
||||
}
|
||||
json_value *v = value->u.object.values[j].value;
|
||||
if (v->type == json_string) {
|
||||
conf.port_password[j].port = ss_strndup(value->u.object.values[j].name,
|
||||
value->u.object.values[j].name_length);
|
||||
conf.port_password[j].password = to_string(v);
|
||||
conf.port_password_num = j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (strcmp(name, "server_port") == 0) {
|
||||
conf.remote_port = to_string(value);
|
||||
} else if (strcmp(name, "local_address") == 0) {
|
||||
conf.local_addr = to_string(value);
|
||||
} else if (strcmp(name, "local_port") == 0) {
|
||||
conf.local_port = to_string(value);
|
||||
} else if (strcmp(name, "password") == 0) {
|
||||
conf.password = to_string(value);
|
||||
} else if (strcmp(name, "protocol") == 0) { // SSR
|
||||
conf.protocol = to_string(value);
|
||||
} else if (strcmp(name, "protocol_param") == 0) { // SSR
|
||||
conf.protocol_param = to_string(value);
|
||||
} else if (strcmp(name, "method") == 0) {
|
||||
conf.method = to_string(value);
|
||||
} else if (strcmp(name, "obfs") == 0) { // SSR
|
||||
conf.obfs = to_string(value);
|
||||
} else if (strcmp(name, "obfs_param") == 0) { // SSR
|
||||
conf.obfs_param = to_string(value);
|
||||
} else if (strcmp(name, "timeout") == 0) {
|
||||
conf.timeout = to_string(value);
|
||||
} else if (strcmp(name, "user") == 0) {
|
||||
conf.user = to_string(value);
|
||||
} else if (strcmp(name, "fast_open") == 0) {
|
||||
check_json_value_type(value, json_boolean,
|
||||
"invalid config file: option 'fast_open' must be a boolean");
|
||||
conf.fast_open = 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;
|
||||
} else if (strcmp(name, "nofile") == 0) {
|
||||
check_json_value_type(value, json_integer,
|
||||
"invalid config file: option 'nofile' must be an integer");
|
||||
conf.nofile = value->u.integer;
|
||||
} else if (strcmp(name, "nameserver") == 0) {
|
||||
conf.nameserver = to_string(value);
|
||||
} else if (strcmp(name, "tunnel_address") == 0) {
|
||||
conf.tunnel_address = to_string(value);
|
||||
} else if (strcmp(name, "mode") == 0) {
|
||||
char *mode_str = to_string(value);
|
||||
|
||||
if (strcmp(mode_str, "tcp_only") == 0)
|
||||
conf.mode = TCP_ONLY;
|
||||
else if (strcmp(mode_str, "tcp_and_udp") == 0)
|
||||
conf.mode = TCP_AND_UDP;
|
||||
else if (strcmp(mode_str, "udp_only") == 0)
|
||||
conf.mode = UDP_ONLY;
|
||||
else
|
||||
LOGI("ignore unknown mode: %s, use tcp_only as fallback",
|
||||
mode_str);
|
||||
ss_free(mode_str);
|
||||
} else if (strcmp(name, "mtu") == 0) {
|
||||
check_json_value_type(value, json_integer,
|
||||
"invalid config file: option 'mtu' must be an integer");
|
||||
conf.mtu = value->u.integer;
|
||||
} else if (strcmp(name, "mptcp") == 0) {
|
||||
check_json_value_type(value, json_boolean,
|
||||
"invalid config file: option 'mptcp' must be a boolean");
|
||||
conf.mptcp = value->u.boolean;
|
||||
} else if (strcmp(name, "ipv6_first") == 0) {
|
||||
check_json_value_type(value, json_boolean,
|
||||
"invalid config file: option 'ipv6_first' must be a boolean");
|
||||
conf.ipv6_first = value->u.boolean;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FATAL("Invalid config file");
|
||||
}
|
||||
|
||||
ss_free(buf);
|
||||
json_value_free(obj);
|
||||
return &conf;
|
||||
}
|
||||
78
package/lean/shadowsocksr-libev/src/server/jconf.h
Normal file
78
package/lean/shadowsocksr-libev/src/server/jconf.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* jconf.h - Define the config data structure
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _JCONF_H
|
||||
#define _JCONF_H
|
||||
|
||||
#define MAX_PORT_NUM 1024
|
||||
#define MAX_REMOTE_NUM 10
|
||||
#define MAX_CONF_SIZE 128 * 1024
|
||||
#define MAX_DNS_NUM 4
|
||||
#define MAX_CONNECT_TIMEOUT 10
|
||||
#define MAX_REQUEST_TIMEOUT 60
|
||||
#define MIN_UDP_TIMEOUT 10
|
||||
|
||||
#define TCP_ONLY 0
|
||||
#define TCP_AND_UDP 1
|
||||
#define UDP_ONLY 3
|
||||
|
||||
typedef struct {
|
||||
char *host;
|
||||
char *port;
|
||||
} ss_addr_t;
|
||||
|
||||
typedef struct {
|
||||
char *port;
|
||||
char *password;
|
||||
} ss_port_password_t;
|
||||
|
||||
typedef struct {
|
||||
int remote_num;
|
||||
ss_addr_t remote_addr[MAX_REMOTE_NUM];
|
||||
int port_password_num;
|
||||
ss_port_password_t port_password[MAX_PORT_NUM];
|
||||
char *remote_port;
|
||||
char *local_addr;
|
||||
char *local_port;
|
||||
char *password;
|
||||
char *protocol; // SSR
|
||||
char *protocol_param; // SSR
|
||||
char *method;
|
||||
char *obfs; // SSR
|
||||
char *obfs_param; // SSR
|
||||
char *timeout;
|
||||
char *user;
|
||||
int auth;
|
||||
int fast_open;
|
||||
int nofile;
|
||||
char *nameserver;
|
||||
char *tunnel_address;
|
||||
int mode;
|
||||
int mtu;
|
||||
int mptcp;
|
||||
int ipv6_first;
|
||||
} jconf_t;
|
||||
|
||||
jconf_t *read_jconf(const char *file);
|
||||
void parse_addr(const char *str, ss_addr_t *addr);
|
||||
void free_addr(ss_addr_t *addr);
|
||||
|
||||
#endif // _JCONF_H
|
||||
1002
package/lean/shadowsocksr-libev/src/server/json.c
Normal file
1002
package/lean/shadowsocksr-libev/src/server/json.c
Normal file
File diff suppressed because it is too large
Load Diff
249
package/lean/shadowsocksr-libev/src/server/json.h
Normal file
249
package/lean/shadowsocksr-libev/src/server/json.h
Normal file
@ -0,0 +1,249 @@
|
||||
/* vim: set et ts=3 sw=3 sts=3 ft=c:
|
||||
*
|
||||
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
|
||||
* https://github.com/udp/json-parser
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _JSON_H
|
||||
#define _JSON_H
|
||||
|
||||
#ifndef json_char
|
||||
#define json_char char
|
||||
#endif
|
||||
|
||||
#ifndef json_int_t
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#define json_int_t int64_t
|
||||
#else
|
||||
#define json_int_t __int64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned long max_memory;
|
||||
int settings;
|
||||
|
||||
/* Custom allocator support (leave null to use malloc/free)
|
||||
*/
|
||||
|
||||
void * (*mem_alloc)(size_t, int zero, void *user_data);
|
||||
void (*mem_free)(void *, void *user_data);
|
||||
|
||||
void *user_data; /* will be passed to mem_alloc and mem_free */
|
||||
} json_settings;
|
||||
|
||||
#define json_enable_comments 0x01
|
||||
|
||||
typedef enum {
|
||||
json_none,
|
||||
json_object,
|
||||
json_array,
|
||||
json_integer,
|
||||
json_double,
|
||||
json_string,
|
||||
json_boolean,
|
||||
json_null
|
||||
} json_type;
|
||||
|
||||
extern const struct _json_value json_value_none;
|
||||
|
||||
typedef struct _json_value {
|
||||
struct _json_value *parent;
|
||||
|
||||
json_type type;
|
||||
|
||||
union {
|
||||
int boolean;
|
||||
json_int_t integer;
|
||||
double dbl;
|
||||
|
||||
struct {
|
||||
unsigned int length;
|
||||
json_char *ptr; /* null terminated */
|
||||
} string;
|
||||
|
||||
struct {
|
||||
unsigned int length;
|
||||
|
||||
struct {
|
||||
json_char *name;
|
||||
unsigned int name_length;
|
||||
|
||||
struct _json_value *value;
|
||||
} *values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin() const
|
||||
{
|
||||
return values;
|
||||
}
|
||||
decltype(values) end() const
|
||||
{
|
||||
return values + length;
|
||||
}
|
||||
#endif
|
||||
} object;
|
||||
|
||||
struct {
|
||||
unsigned int length;
|
||||
struct _json_value **values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin() const
|
||||
{
|
||||
return values;
|
||||
}
|
||||
decltype(values) end() const
|
||||
{
|
||||
return values + length;
|
||||
}
|
||||
#endif
|
||||
} array;
|
||||
} u;
|
||||
|
||||
union {
|
||||
struct _json_value *next_alloc;
|
||||
void *object_mem;
|
||||
} _reserved;
|
||||
|
||||
/* Some C++ operator sugar */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
public:
|
||||
|
||||
inline _json_value(){
|
||||
memset(this, 0, sizeof(_json_value));
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (int index) const {
|
||||
if (type != json_array || index < 0
|
||||
|| ((unsigned int)index) >= u.array.length) {
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
return *u.array.values[index];
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (const char *index) const {
|
||||
if (type != json_object) {
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < u.object.length; ++i)
|
||||
if (!strcmp(u.object.values[i].name, index)) {
|
||||
return *u.object.values[i].value;
|
||||
}
|
||||
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
inline operator const char * () const
|
||||
{
|
||||
switch (type) {
|
||||
case json_string:
|
||||
return u.string.ptr;
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
inline operator
|
||||
json_int_t() const
|
||||
{
|
||||
switch (type) {
|
||||
case json_integer:
|
||||
return u.integer;
|
||||
|
||||
case json_double:
|
||||
return (json_int_t)u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline operator
|
||||
bool() const
|
||||
{
|
||||
if (type != json_boolean) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return u.boolean != 0;
|
||||
}
|
||||
|
||||
inline operator double () const
|
||||
{
|
||||
switch (type) {
|
||||
case json_integer:
|
||||
return (double)u.integer;
|
||||
|
||||
case json_double:
|
||||
return u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
} json_value;
|
||||
|
||||
json_value *json_parse(const json_char *json,
|
||||
size_t length);
|
||||
|
||||
#define json_error_max 128
|
||||
json_value *json_parse_ex(json_settings *settings,
|
||||
const json_char *json,
|
||||
size_t length,
|
||||
char *error);
|
||||
|
||||
void json_value_free(json_value *);
|
||||
|
||||
/* Not usually necessary, unless you used a custom mem_alloc and now want to
|
||||
* use a custom mem_free.
|
||||
*/
|
||||
void json_value_free_ex(json_settings *settings,
|
||||
json_value *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
370
package/lean/shadowsocksr-libev/src/server/list.c
Normal file
370
package/lean/shadowsocksr-libev/src/server/list.c
Normal file
@ -0,0 +1,370 @@
|
||||
#include "list.h"
|
||||
|
||||
/// 文件:list_impl.c
|
||||
/// 功能:实现链表的基本操作
|
||||
/// 作者:bluewind
|
||||
/// 完成时间:2011.5.29
|
||||
/// 修改时间:2011.5.31, 2011.7.2
|
||||
/// 修改备注:在头节点处添加一个空节点,可以优化添加、删除节点代码
|
||||
/// 再次修改,链表增加节点数据data_size,限制数据大小,修改了
|
||||
/// 添加复制数据代码,修正重复添加节点后释放节点的Bug,添加了前
|
||||
/// 插、排序和遍历功能,7.3 添加tail尾指针,改进后插法性能,并改名
|
||||
/// --------------------------------------------------------------
|
||||
|
||||
void swap_data(Node n1, Node n2);
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_init
|
||||
// 功能: 链表初始化
|
||||
// 参数: 无
|
||||
// 返回值:已初始化链表指针
|
||||
// 备注: 链表本身动态分配,由list_destroy函数管理释放
|
||||
/// --------------------------------------------------------------
|
||||
List list_init(unsigned int data_size)
|
||||
{
|
||||
List list = (List) malloc(sizeof(struct clist));
|
||||
if(list != NULL) //内存分配成功
|
||||
{
|
||||
list->head = (Node) malloc(sizeof(node)); //为头节点分配内存
|
||||
if(list->head) //内存分配成功
|
||||
{
|
||||
list->head->data = NULL; //初始化头节点
|
||||
list->head->next = NULL;
|
||||
list->data_size = data_size;
|
||||
list->tail = list->head;
|
||||
list->size = 0;
|
||||
|
||||
list->add_back = list_add_back; //初始化成员函数
|
||||
list->add_front = list_add_front;
|
||||
list->delete_node = list_delete_node;
|
||||
list->delete_at = list_delete_at;
|
||||
list->modify_at = list_modify_at;
|
||||
list->have_same = list_have_same;
|
||||
list->have_same_cmp = list_have_same_cmp;
|
||||
list->foreach = list_foreach;
|
||||
list->clear = list_clear;
|
||||
list->sort = list_sort;
|
||||
list->destroy = list_destroy;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_add_back
|
||||
// 功能: 添加链表结点 (后插法)
|
||||
// 参数: l--链表指针,data--链表数据指针,可为任意类型
|
||||
// 返回值:int型,为1表示添加成功,为0表示添加失败
|
||||
// 备注: 如果链表本身为空或是分配节点内存失败,将返回0
|
||||
/// --------------------------------------------------------------
|
||||
int list_add_back(List l, void *data)
|
||||
{
|
||||
Node new_node = (Node) malloc(sizeof(node));
|
||||
|
||||
if(l != NULL && new_node != NULL) //链表本身不为空,且内存申请成功
|
||||
{
|
||||
new_node->data = malloc(l->data_size);
|
||||
memcpy(new_node->data, data, l->data_size);
|
||||
new_node->next = NULL;
|
||||
|
||||
l->tail->next = new_node; //添加节点
|
||||
l->tail = new_node; //记录尾节点位置
|
||||
l->size ++; //链表元素总数加1
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_add_front
|
||||
// 功能: 添加链表结点 (前插法)
|
||||
// 参数: l--链表指针,data--链表数据指针,可为任意类型
|
||||
// 返回值:int型,为1表示添加成功,为0表示添加失败
|
||||
// 备注: 如果链表本身为空或是分配节点内存失败,将返回0
|
||||
/// --------------------------------------------------------------
|
||||
int list_add_front(List l, void *data)
|
||||
{
|
||||
Node new_node = (Node) malloc(sizeof(node));
|
||||
|
||||
if(l != NULL && new_node != NULL)
|
||||
{
|
||||
new_node->data = malloc(l->data_size);
|
||||
memcpy(new_node->data, data, l->data_size);
|
||||
new_node->next = l->head->next;
|
||||
|
||||
l->head->next = new_node;
|
||||
if(!l->size) //记录尾指针位置
|
||||
l->tail = new_node;
|
||||
l->size ++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_delete_node
|
||||
// 功能:删除链表结点
|
||||
// 参数:l--链表指针,data--链表数据指针,可为任意类型
|
||||
// *pfunc为指向一个数据类型比较的函数指针
|
||||
// 返回值:int型,为1表示删除成功,为0表示没有找到匹配数据
|
||||
// 备注:*pfunc函数接口参数ndata为节点数据,data为比较数据,返回为真表示匹配数据
|
||||
/// --------------------------------------------------------------
|
||||
int list_delete_node(List l, void *data, int (*pfunc)(void *ndata, void *data))
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node prev = l->head; //前一个节点
|
||||
Node curr = l->head->next; //当前节点
|
||||
|
||||
while(curr != NULL)
|
||||
{
|
||||
if(pfunc(curr->data, data)) //如果找到匹配数据
|
||||
{
|
||||
if(curr == l->tail) //如果是删除尾节点
|
||||
l->tail = prev;
|
||||
|
||||
prev->next = prev->next->next; //修改前节点next指针指向下下个节点
|
||||
|
||||
free(curr->data); //释放节点数据
|
||||
free(curr); //释放节点
|
||||
|
||||
l->size--; //链表元素总数减1
|
||||
return 1; //返回真值
|
||||
}
|
||||
prev = prev->next; //没有找到匹配时移动前节点和当前节点
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; //没有找到匹配数据
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_delete_at
|
||||
// 功能: 修改链表节点元素值
|
||||
// 参数: l--链表指针,index--索引值, 范围(0 -- size-1)
|
||||
// 返回值:int型,为1表示删除成功,为0表示删除失败
|
||||
// 备注: 如果链表本身为空或是index为非法值,将返回0
|
||||
/// --------------------------------------------------------------
|
||||
int list_delete_at(List l, unsigned int index)
|
||||
{
|
||||
unsigned int cindex = 0;
|
||||
|
||||
if(l != NULL && index >= 0 && index < l->size)
|
||||
{
|
||||
Node prev = l->head; //前一个节点
|
||||
Node curr = l->head->next; //当前节点
|
||||
|
||||
while(cindex != index)
|
||||
{
|
||||
prev = prev->next;
|
||||
curr = curr->next;
|
||||
cindex ++;
|
||||
}
|
||||
|
||||
if(index == (l->size) - 1)
|
||||
l->tail = prev;
|
||||
|
||||
prev->next = prev->next->next;
|
||||
free(curr->data);
|
||||
free(curr);
|
||||
l->size --;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_modify_at
|
||||
// 功能: 修改链表节点元素值
|
||||
// 参数: l--链表指针,index--索引值, 范围(0 -- size-1)
|
||||
// data--链表数据指针
|
||||
// 返回值:int型,为1表示修改成功,为0表示修改失败
|
||||
// 备注: 如果链表本身为空或是index为非法值,将返回0
|
||||
/// --------------------------------------------------------------
|
||||
int list_modify_at(List l, unsigned int index, void *new_data)
|
||||
{
|
||||
unsigned int cindex = 0;
|
||||
|
||||
if(l != NULL && index >= 0 && index < l->size ) //非空链表,并且index值合法
|
||||
{
|
||||
Node curr = l->head->next;
|
||||
while(cindex != index)
|
||||
{
|
||||
curr = curr->next;
|
||||
cindex ++;
|
||||
}
|
||||
memcpy(curr->data, new_data, l->data_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_sort
|
||||
// 功能: 链表排序
|
||||
// 参数: l--链表指针,*pfunc为指向一个数据类型比较的函数指针
|
||||
// 返回值:无
|
||||
// 备注: 使用简单选择排序法,相比冒泡法每次交换,效率高一点
|
||||
/// --------------------------------------------------------------
|
||||
void list_sort(List l, compare pfunc)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node min, icurr, jcurr;
|
||||
|
||||
icurr = l->head->next;
|
||||
while(icurr)
|
||||
{
|
||||
min = icurr; //记录最小值
|
||||
jcurr = icurr->next; //内循环指向下一个节点
|
||||
while(jcurr)
|
||||
{
|
||||
if(pfunc(min->data, jcurr->data)) //如果找到n+1到最后一个元素最小值
|
||||
min = jcurr; //记录下最小值的位置
|
||||
|
||||
jcurr = jcurr->next;
|
||||
}
|
||||
|
||||
if(min != icurr) //当最小值位置和n+1元素位置不相同时
|
||||
{
|
||||
swap_data(min, icurr); //才进行交换,减少交换次数
|
||||
}
|
||||
|
||||
icurr = icurr->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void swap_data(Node n1, Node n2)
|
||||
{
|
||||
void *temp;
|
||||
|
||||
temp = n2->data;
|
||||
n2->data = n1->data;
|
||||
n1->data = temp;
|
||||
}
|
||||
|
||||
|
||||
int list_have_same(List l, void *data, int (*pfunc)(void *ndata, void *data))
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node curr;
|
||||
|
||||
for(curr = l->head->next; curr != NULL; curr = curr->next)
|
||||
{
|
||||
if(pfunc(curr->data, data))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_have_same_cmp(List l, void *data)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node curr;
|
||||
|
||||
for(curr = l->head->next; curr != NULL; curr = curr->next)
|
||||
{
|
||||
if(memcmp(curr->data, data, l->data_size))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_foreach
|
||||
// 功能: 遍历链表元素
|
||||
// 参数: l--链表指针,doit为指向一个处理数据的函数指针
|
||||
// 返回值:无
|
||||
// 备注: doit申明为void (*dofunc)(void *ndata)原型
|
||||
/// --------------------------------------------------------------
|
||||
void list_foreach(List l, dofunc doit)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node curr;
|
||||
|
||||
for(curr = l->head->next; curr != NULL; curr = curr->next)
|
||||
{
|
||||
doit(curr->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_clear
|
||||
// 功能: 清空链表元素
|
||||
// 参数: l--链表指针
|
||||
// 返回值:无
|
||||
// 备注: 没有使用先Destroy再Init链表的办法,直接实现
|
||||
/// --------------------------------------------------------------
|
||||
void list_clear(List l)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node temp;
|
||||
Node curr = l->head->next;
|
||||
|
||||
while(curr != NULL)
|
||||
{
|
||||
temp = curr->next;
|
||||
|
||||
free(curr->data); //释放节点和数据
|
||||
free(curr);
|
||||
|
||||
curr = temp;
|
||||
}
|
||||
|
||||
l->size = 0; //重置链表数据
|
||||
l->head->next = NULL;
|
||||
l->tail = l->head;
|
||||
}
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_destroy
|
||||
// 功能: 释放链表
|
||||
// 参数: l--链表指针
|
||||
// 返回值:空链表指针
|
||||
/// --------------------------------------------------------------
|
||||
List list_destroy(List l)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node temp;
|
||||
|
||||
while(l->head)
|
||||
{
|
||||
temp = l->head->next;
|
||||
|
||||
if(l->head->data != NULL) //如果是头节点就不释放数据空间
|
||||
free(l->head->data); //先释放节点数据(但是节点数据里也有指针?)
|
||||
free(l->head); //再释放节点
|
||||
|
||||
l->head = temp;
|
||||
}
|
||||
|
||||
free(l); //释放链表本身占用空间
|
||||
l = NULL;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
61
package/lean/shadowsocksr-libev/src/server/list.h
Normal file
61
package/lean/shadowsocksr-libev/src/server/list.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef LIST_H_H
|
||||
#define LIST_H_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct clist *List;
|
||||
|
||||
typedef int (*compare)(void *ndata, void *data);
|
||||
typedef void (*dofunc)(void *ndata);
|
||||
|
||||
typedef int (*lpf0)(List l, void *data);
|
||||
typedef int (*lpf1)(List l, void *data, compare pfunc);
|
||||
typedef List (*lpf2)(List l);
|
||||
typedef void (*lpf3)(List l);
|
||||
typedef void (*lpf4)(List l, dofunc pfunc);
|
||||
typedef int (*lpf5)(List l, unsigned int index, void *new_data);
|
||||
typedef void (*lpf6)(List l, compare pfunc);
|
||||
typedef int (*lpf7)(List l, unsigned int index);
|
||||
|
||||
typedef struct cnode
|
||||
{
|
||||
void *data;
|
||||
struct cnode *next;
|
||||
}node, *Node;
|
||||
|
||||
typedef struct clist
|
||||
{
|
||||
Node head;
|
||||
Node tail;
|
||||
unsigned int size;
|
||||
unsigned int data_size;
|
||||
lpf0 add_back;
|
||||
lpf0 add_front;
|
||||
lpf1 delete_node;
|
||||
lpf1 have_same;
|
||||
lpf0 have_same_cmp;
|
||||
lpf4 foreach;
|
||||
lpf3 clear;
|
||||
lpf2 destroy;
|
||||
lpf5 modify_at;
|
||||
lpf6 sort;
|
||||
lpf7 delete_at;
|
||||
}list;
|
||||
|
||||
//初始化链表
|
||||
List list_init(unsigned int data_size);
|
||||
int list_add_back(List l, void *data);
|
||||
int list_add_front(List l, void *data);
|
||||
int list_delete_node(List l, void *data, compare pfunc);
|
||||
int list_delete_at(List l, unsigned int index);
|
||||
int list_modify_at(List l, unsigned int index, void *new_data);
|
||||
int list_have_same(List l, void *data, compare pfunc);
|
||||
int list_have_same_cmp(List l, void *data);
|
||||
void list_foreach(List l, dofunc doit);
|
||||
void list_sort(List l, compare pfunc);
|
||||
void list_clear(List l);
|
||||
//释放链表
|
||||
List list_destroy(List l);
|
||||
#endif
|
||||
297
package/lean/shadowsocksr-libev/src/server/netutils.c
Normal file
297
package/lean/shadowsocksr-libev/src/server/netutils.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* netutils.c - Network utilities
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <libcork/core.h>
|
||||
#include <udns.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include "win32.h"
|
||||
#define sleep(n) Sleep(1000 * (n))
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#define SET_INTERFACE
|
||||
#endif
|
||||
|
||||
#include "netutils.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifndef SO_REUSEPORT
|
||||
#define SO_REUSEPORT 15
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static const char valid_label_bytes[] =
|
||||
"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
#if defined(MODULE_LOCAL)
|
||||
extern int keep_resolving;
|
||||
#endif
|
||||
|
||||
int
|
||||
set_reuseport(int socket)
|
||||
{
|
||||
int opt = 1;
|
||||
return setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
|
||||
}
|
||||
|
||||
size_t
|
||||
get_sockaddr_len(struct sockaddr *addr)
|
||||
{
|
||||
if (addr->sa_family == AF_INET) {
|
||||
return sizeof(struct sockaddr_in);
|
||||
} else if (addr->sa_family == AF_INET6) {
|
||||
return sizeof(struct sockaddr_in6);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SET_INTERFACE
|
||||
int
|
||||
setinterface(int socket_fd, const char *interface_name)
|
||||
{
|
||||
struct ifreq interface;
|
||||
memset(&interface, 0, sizeof(struct ifreq));
|
||||
strncpy(interface.ifr_name, interface_name, IFNAMSIZ);
|
||||
int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface,
|
||||
sizeof(struct ifreq));
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
bind_to_address(int socket_fd, const char *host)
|
||||
{
|
||||
if (host != NULL) {
|
||||
struct cork_ip ip;
|
||||
struct sockaddr_storage storage;
|
||||
memset(&storage, 0, sizeof(struct sockaddr_storage));
|
||||
if (cork_ip_init(&ip, host) != -1) {
|
||||
if (ip.version == 4) {
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)&storage;
|
||||
dns_pton(AF_INET, host, &addr->sin_addr);
|
||||
addr->sin_family = AF_INET;
|
||||
return bind(socket_fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
|
||||
} else if (ip.version == 6) {
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage;
|
||||
dns_pton(AF_INET6, host, &addr->sin6_addr);
|
||||
addr->sin6_family = AF_INET6;
|
||||
return bind(socket_fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in6));
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
get_sockaddr(char *host, char *port,
|
||||
struct sockaddr_storage *storage, int block,
|
||||
int ipv6first)
|
||||
{
|
||||
struct cork_ip ip;
|
||||
if (cork_ip_init(&ip, host) != -1) {
|
||||
if (ip.version == 4) {
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)storage;
|
||||
addr->sin_family = AF_INET;
|
||||
dns_pton(AF_INET, host, &(addr->sin_addr));
|
||||
if (port != NULL) {
|
||||
addr->sin_port = htons(atoi(port));
|
||||
}
|
||||
} else if (ip.version == 6) {
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage;
|
||||
addr->sin6_family = AF_INET6;
|
||||
dns_pton(AF_INET6, host, &(addr->sin6_addr));
|
||||
if (port != NULL) {
|
||||
addr->sin6_port = htons(atoi(port));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result, *rp;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
|
||||
hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */
|
||||
|
||||
int err, i;
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
err = getaddrinfo(host, port, &hints, &result);
|
||||
#if defined(MODULE_LOCAL)
|
||||
if (!keep_resolving)
|
||||
break;
|
||||
#endif
|
||||
if ((!block || !err)) {
|
||||
break;
|
||||
} else {
|
||||
sleep(pow(2, i));
|
||||
LOGE("failed to resolve server name, wait %.0f seconds", pow(2, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
LOGE("getaddrinfo: %s", gai_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int prefer_af = ipv6first ? AF_INET6 : AF_INET;
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next)
|
||||
if (rp->ai_family == prefer_af) {
|
||||
if (rp->ai_family == AF_INET)
|
||||
memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in));
|
||||
else if (rp->ai_family == AF_INET6)
|
||||
memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
}
|
||||
|
||||
if (rp == NULL) {
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
if (rp->ai_family == AF_INET)
|
||||
memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in));
|
||||
else if (rp->ai_family == AF_INET6)
|
||||
memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rp == NULL) {
|
||||
LOGE("failed to resolve remote addr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sockaddr_cmp(struct sockaddr_storage *addr1,
|
||||
struct sockaddr_storage *addr2, socklen_t len)
|
||||
{
|
||||
struct sockaddr_in *p1_in = (struct sockaddr_in *)addr1;
|
||||
struct sockaddr_in *p2_in = (struct sockaddr_in *)addr2;
|
||||
struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1;
|
||||
struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2;
|
||||
if (p1_in->sin_family < p2_in->sin_family)
|
||||
return -1;
|
||||
if (p1_in->sin_family > p2_in->sin_family)
|
||||
return 1;
|
||||
/* compare ip4 */
|
||||
if (p1_in->sin_family == AF_INET) {
|
||||
/* just order it, ntohs not required */
|
||||
if (p1_in->sin_port < p2_in->sin_port)
|
||||
return -1;
|
||||
if (p1_in->sin_port > p2_in->sin_port)
|
||||
return 1;
|
||||
return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
|
||||
} else if (p1_in6->sin6_family == AF_INET6) {
|
||||
/* just order it, ntohs not required */
|
||||
if (p1_in6->sin6_port < p2_in6->sin6_port)
|
||||
return -1;
|
||||
if (p1_in6->sin6_port > p2_in6->sin6_port)
|
||||
return 1;
|
||||
return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
|
||||
INET6_SIZE);
|
||||
} else {
|
||||
/* eek unknown type, perform this comparison for sanity. */
|
||||
return memcmp(addr1, addr2, len);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sockaddr_cmp_addr(struct sockaddr_storage *addr1,
|
||||
struct sockaddr_storage *addr2, socklen_t len)
|
||||
{
|
||||
struct sockaddr_in *p1_in = (struct sockaddr_in *)addr1;
|
||||
struct sockaddr_in *p2_in = (struct sockaddr_in *)addr2;
|
||||
struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1;
|
||||
struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2;
|
||||
if (p1_in->sin_family < p2_in->sin_family)
|
||||
return -1;
|
||||
if (p1_in->sin_family > p2_in->sin_family)
|
||||
return 1;
|
||||
/* compare ip4 */
|
||||
if (p1_in->sin_family == AF_INET) {
|
||||
return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
|
||||
} else if (p1_in6->sin6_family == AF_INET6) {
|
||||
return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
|
||||
INET6_SIZE);
|
||||
} else {
|
||||
/* eek unknown type, perform this comparison for sanity. */
|
||||
return memcmp(addr1, addr2, len);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
validate_hostname(const char *hostname, const int hostname_len)
|
||||
{
|
||||
if (hostname == NULL)
|
||||
return 0;
|
||||
|
||||
if (hostname_len < 1 || hostname_len > 255)
|
||||
return 0;
|
||||
|
||||
if (hostname[0] == '.')
|
||||
return 0;
|
||||
|
||||
const char *label = hostname;
|
||||
while (label < hostname + hostname_len) {
|
||||
size_t label_len = hostname_len - (label - hostname);
|
||||
char *next_dot = strchr(label, '.');
|
||||
if (next_dot != NULL)
|
||||
label_len = next_dot - label;
|
||||
|
||||
if (label + label_len > hostname + hostname_len)
|
||||
return 0;
|
||||
|
||||
if (label_len > 63 || label_len < 1)
|
||||
return 0;
|
||||
|
||||
if (label[0] == '-' || label[label_len - 1] == '-')
|
||||
return 0;
|
||||
|
||||
if (strspn(label, valid_label_bytes) < label_len)
|
||||
return 0;
|
||||
|
||||
label += label_len + 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
98
package/lean/shadowsocksr-libev/src/server/netutils.h
Normal file
98
package/lean/shadowsocksr-libev/src/server/netutils.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* netutils.h - Network utilities
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _NETUTILS_H
|
||||
#define _NETUTILS_H
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <netdb.h>
|
||||
#elif !defined(__MINGW32__)
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
// only enable TCP_FASTOPEN on linux
|
||||
#if defined(__linux__)
|
||||
#include <linux/tcp.h>
|
||||
/* conditional define for TCP_FASTOPEN */
|
||||
#ifndef TCP_FASTOPEN
|
||||
#define TCP_FASTOPEN 23
|
||||
#endif
|
||||
/* conditional define for MSG_FASTOPEN */
|
||||
#ifndef MSG_FASTOPEN
|
||||
#define MSG_FASTOPEN 0x20000000
|
||||
#endif
|
||||
#elif !defined(__APPLE__)
|
||||
#ifdef TCP_FASTOPEN
|
||||
#undef TCP_FASTOPEN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Backward compatibility for MPTCP_ENABLED between kernel 3 & 4 */
|
||||
#ifndef MPTCP_ENABLED
|
||||
#ifdef TCP_CC_INFO
|
||||
#define MPTCP_ENABLED 42
|
||||
#else
|
||||
#define MPTCP_ENABLED 26
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** byte size of ip4 address */
|
||||
#define INET_SIZE 4
|
||||
/** byte size of ip6 address */
|
||||
#define INET6_SIZE 16
|
||||
|
||||
size_t get_sockaddr_len(struct sockaddr *addr);
|
||||
ssize_t get_sockaddr(char *host, char *port,
|
||||
struct sockaddr_storage *storage, int block,
|
||||
int ipv6first);
|
||||
int set_reuseport(int socket);
|
||||
|
||||
#ifdef SET_INTERFACE
|
||||
int setinterface(int socket_fd, const char *interface_name);
|
||||
#endif
|
||||
|
||||
int bind_to_address(int socket_fd, const char *address);
|
||||
|
||||
/**
|
||||
* Compare two sockaddrs. Imposes an ordering on the addresses.
|
||||
* Compares address and port.
|
||||
* @param addr1: address 1.
|
||||
* @param addr2: address 2.
|
||||
* @param len: lengths of addr.
|
||||
* @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger.
|
||||
*/
|
||||
int sockaddr_cmp(struct sockaddr_storage *addr1,
|
||||
struct sockaddr_storage *addr2, socklen_t len);
|
||||
|
||||
/**
|
||||
* Compare two sockaddrs. Compares address, not the port.
|
||||
* @param addr1: address 1.
|
||||
* @param addr2: address 2.
|
||||
* @param len: lengths of addr.
|
||||
* @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger.
|
||||
*/
|
||||
int sockaddr_cmp_addr(struct sockaddr_storage *addr1,
|
||||
struct sockaddr_storage *addr2, socklen_t len);
|
||||
|
||||
int validate_hostname(const char *hostname, const int hostname_len);
|
||||
|
||||
#endif
|
||||
205
package/lean/shadowsocksr-libev/src/server/obfs.c
Normal file
205
package/lean/shadowsocksr-libev/src/server/obfs.c
Normal file
@ -0,0 +1,205 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "obfs.h"
|
||||
|
||||
int rand_bytes(uint8_t *output, int len);
|
||||
#define OBFS_HMAC_SHA1_LEN 10
|
||||
|
||||
#include "obfsutil.c"
|
||||
#include "crc32.c"
|
||||
#include "base64.c"
|
||||
#include "http_simple.c"
|
||||
#include "tls1.2_ticket.c"
|
||||
#include "verify.c"
|
||||
#include "auth.c"
|
||||
|
||||
void * init_data() {
|
||||
return malloc(1);
|
||||
}
|
||||
|
||||
obfs * new_obfs() {
|
||||
obfs * self = (obfs*)malloc(sizeof(obfs));
|
||||
self->l_data = NULL;
|
||||
return self;
|
||||
}
|
||||
|
||||
void set_server_info(obfs *self, server_info *server) {
|
||||
memmove(&self->server, server, sizeof(server_info));
|
||||
}
|
||||
|
||||
void get_server_info(obfs *self, server_info *server) {
|
||||
memmove(server, &self->server, sizeof(server_info));
|
||||
}
|
||||
|
||||
void dispose_obfs(obfs *self) {
|
||||
free(self);
|
||||
}
|
||||
|
||||
obfs_class * new_obfs_class(char *plugin_name)
|
||||
{
|
||||
if (plugin_name == NULL)
|
||||
return NULL;
|
||||
if (strcmp(plugin_name, "origin") == 0)
|
||||
return NULL;
|
||||
if (strcmp(plugin_name, "plain") == 0)
|
||||
return NULL;
|
||||
init_crc32_table();
|
||||
init_shift128plus();
|
||||
if (strcmp(plugin_name, "http_simple") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = init_data;
|
||||
plugin->new_obfs = http_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = http_simple_dispose;
|
||||
|
||||
plugin->client_encode = http_simple_client_encode;
|
||||
plugin->client_decode = http_simple_client_decode;
|
||||
|
||||
plugin->server_encode = http_simple_server_encode;
|
||||
plugin->server_decode = http_simple_server_decode;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "http_post") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = init_data;
|
||||
plugin->new_obfs = http_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = http_simple_dispose;
|
||||
|
||||
plugin->client_encode = http_post_client_encode;
|
||||
plugin->client_decode = http_simple_client_decode;
|
||||
|
||||
plugin->server_encode = http_simple_server_encode;
|
||||
plugin->server_decode = http_simple_server_decode;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "tls1.2_ticket_auth") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = tls12_ticket_auth_init_data;
|
||||
plugin->new_obfs = tls12_ticket_auth_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = tls12_ticket_auth_dispose;
|
||||
|
||||
plugin->client_encode = tls12_ticket_auth_client_encode;
|
||||
plugin->client_decode = tls12_ticket_auth_client_decode;
|
||||
|
||||
plugin->server_encode = tls12_ticket_auth_server_encode;
|
||||
plugin->server_decode = tls12_ticket_auth_server_decode;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "verify_simple") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = init_data;
|
||||
plugin->new_obfs = verify_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = verify_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = verify_simple_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = verify_simple_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
plugin->server_pre_encrypt = verify_simple_server_pre_encrypt;
|
||||
plugin->server_post_decrypt = verify_simple_server_post_decrypt;
|
||||
plugin->server_udp_pre_encrypt = NULL;
|
||||
plugin->server_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_simple") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_simple_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_simple_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_sha1") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_sha1_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_sha1_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_sha1_v2") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_sha1_v2_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_sha1_v2_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_sha1_v4") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_sha1_v4_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_sha1_v4_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_aes128_md5") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_aes128_md5_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_aes128_sha1_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_aes128_sha1_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = auth_aes128_sha1_client_udp_pre_encrypt;
|
||||
plugin->client_udp_post_decrypt = auth_aes128_sha1_client_udp_post_decrypt;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_aes128_sha1") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_aes128_sha1_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_aes128_sha1_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_aes128_sha1_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = auth_aes128_sha1_client_udp_pre_encrypt;
|
||||
plugin->client_udp_post_decrypt = auth_aes128_sha1_client_udp_post_decrypt;
|
||||
|
||||
return plugin;
|
||||
}
|
||||
LOGE("Load obfs '%s' failed", plugin_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_obfs_class(obfs_class *plugin) {
|
||||
free(plugin);
|
||||
}
|
||||
100
package/lean/shadowsocksr-libev/src/server/obfs.h
Normal file
100
package/lean/shadowsocksr-libev/src/server/obfs.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* obfs.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _OBFS_H
|
||||
#define _OBFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct server_info {
|
||||
char host[64];
|
||||
uint16_t port;
|
||||
char *param;
|
||||
void *g_data;
|
||||
uint8_t *iv;
|
||||
size_t iv_len;
|
||||
uint8_t *recv_iv;
|
||||
size_t recv_iv_len;
|
||||
uint8_t *key;
|
||||
size_t key_len;
|
||||
int head_len;
|
||||
size_t tcp_mss;
|
||||
}server_info;
|
||||
|
||||
typedef struct obfs {
|
||||
server_info server;
|
||||
void *l_data;
|
||||
}obfs;
|
||||
|
||||
typedef struct obfs_class {
|
||||
void * (*init_data)();
|
||||
obfs * (*new_obfs)();
|
||||
void (*get_server_info)(obfs *self, server_info *server);
|
||||
void (*set_server_info)(obfs *self, server_info *server);
|
||||
void (*dispose)(obfs *self);
|
||||
|
||||
int (*client_pre_encrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*client_encode)(obfs *self,
|
||||
char **pencryptdata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*client_decode)(obfs *self,
|
||||
char **pencryptdata,
|
||||
int datalength,
|
||||
size_t* capacity,
|
||||
int *needsendback);
|
||||
int (*client_post_decrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*client_udp_pre_encrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*client_udp_post_decrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_pre_encrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_post_decrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_udp_pre_encrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_udp_post_decrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_encode)(obfs *self,
|
||||
char **pencryptdata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_decode)(obfs *self,
|
||||
char **pencryptdata,
|
||||
int datalength,
|
||||
size_t* capacity,
|
||||
int *needsendback);
|
||||
}obfs_class;
|
||||
|
||||
obfs_class * new_obfs_class(char *plugin_name);
|
||||
void free_obfs_class(obfs_class *plugin);
|
||||
|
||||
void set_server_info(obfs *self, server_info *server);
|
||||
void get_server_info(obfs *self, server_info *server);
|
||||
obfs * new_obfs();
|
||||
void dispose_obfs(obfs *self);
|
||||
|
||||
#endif // _OBFS_H
|
||||
36
package/lean/shadowsocksr-libev/src/server/obfsutil.c
Normal file
36
package/lean/shadowsocksr-libev/src/server/obfsutil.c
Normal file
@ -0,0 +1,36 @@
|
||||
int get_head_size(char *plaindata, int size, int def_size) {
|
||||
if (plaindata == NULL || size < 2)
|
||||
return def_size;
|
||||
int head_type = plaindata[0] & 0x7;
|
||||
if (head_type == 1)
|
||||
return 7;
|
||||
if (head_type == 4)
|
||||
return 19;
|
||||
if (head_type == 3)
|
||||
return 4 + plaindata[1];
|
||||
return def_size;
|
||||
}
|
||||
|
||||
static int shift128plus_init_flag = 0;
|
||||
static uint64_t shift128plus_s[2] = {0x10000000, 0xFFFFFFFF};
|
||||
|
||||
void init_shift128plus(void) {
|
||||
if (shift128plus_init_flag == 0) {
|
||||
shift128plus_init_flag = 1;
|
||||
uint32_t seed = time(NULL);
|
||||
shift128plus_s[0] = seed | 0x100000000L;
|
||||
shift128plus_s[1] = ((uint64_t)seed << 32) | 0x1;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t xorshift128plus(void) {
|
||||
uint64_t x = shift128plus_s[0];
|
||||
uint64_t const y = shift128plus_s[1];
|
||||
shift128plus_s[0] = y;
|
||||
x ^= x << 23; // a
|
||||
x ^= x >> 17; // b
|
||||
x ^= y ^ (y >> 26); // c
|
||||
shift128plus_s[1] = x;
|
||||
return x + y;
|
||||
}
|
||||
|
||||
34
package/lean/shadowsocksr-libev/src/server/protocol.h
Normal file
34
package/lean/shadowsocksr-libev/src/server/protocol.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef PROTOCOL_H
|
||||
#define PROTOCOL_H
|
||||
|
||||
typedef struct protocol {
|
||||
const int default_port;
|
||||
int(*const parse_packet)(const char *, size_t, char **);
|
||||
} protocol_t;
|
||||
|
||||
#endif
|
||||
444
package/lean/shadowsocksr-libev/src/server/resolv.c
Normal file
444
package/lean/shadowsocksr-libev/src/server/resolv.c
Normal file
@ -0,0 +1,444 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <ev.h>
|
||||
#include <udns.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include "win32.h"
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "resolv.h"
|
||||
#include "utils.h"
|
||||
#include "netutils.h"
|
||||
|
||||
/*
|
||||
* Implement DNS resolution interface using libudns
|
||||
*/
|
||||
|
||||
struct ResolvQuery {
|
||||
void (*client_cb)(struct sockaddr *, void *);
|
||||
void (*client_free_cb)(void *);
|
||||
void *client_cb_data;
|
||||
struct dns_query *queries[2];
|
||||
size_t response_count;
|
||||
struct sockaddr **responses;
|
||||
uint16_t port;
|
||||
};
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static struct ev_io resolv_io_watcher;
|
||||
static struct ev_timer resolv_timeout_watcher;
|
||||
static const int MODE_IPV4_ONLY = 0;
|
||||
static const int MODE_IPV6_ONLY = 1;
|
||||
static const int MODE_IPV4_FIRST = 2;
|
||||
static const int MODE_IPV6_FIRST = 3;
|
||||
static int resolv_mode = 0;
|
||||
|
||||
static void resolv_sock_cb(struct ev_loop *, struct ev_io *, int);
|
||||
static void resolv_timeout_cb(struct ev_loop *, struct ev_timer *, int);
|
||||
static void dns_query_v4_cb(struct dns_ctx *, struct dns_rr_a4 *, void *);
|
||||
static void dns_query_v6_cb(struct dns_ctx *, struct dns_rr_a6 *, void *);
|
||||
static void dns_timer_setup_cb(struct dns_ctx *, int, void *);
|
||||
static void process_client_callback(struct ResolvQuery *);
|
||||
static inline int all_queries_are_null(struct ResolvQuery *);
|
||||
static struct sockaddr *choose_ipv4_first(struct ResolvQuery *);
|
||||
static struct sockaddr *choose_ipv6_first(struct ResolvQuery *);
|
||||
static struct sockaddr *choose_any(struct ResolvQuery *);
|
||||
|
||||
int
|
||||
resolv_init(struct ev_loop *loop, char **nameservers, int nameserver_num, int ipv6first)
|
||||
{
|
||||
if (ipv6first)
|
||||
resolv_mode = MODE_IPV6_FIRST;
|
||||
else
|
||||
resolv_mode = MODE_IPV4_FIRST;
|
||||
|
||||
struct dns_ctx *ctx = &dns_defctx;
|
||||
if (nameservers == NULL) {
|
||||
/* Nameservers not specified, use system resolver config */
|
||||
dns_init(ctx, 0);
|
||||
} else {
|
||||
dns_reset(ctx);
|
||||
|
||||
for (int i = 0; i < nameserver_num; i++) {
|
||||
char *server = nameservers[i];
|
||||
dns_add_serv(ctx, server);
|
||||
}
|
||||
}
|
||||
|
||||
int sockfd = dns_open(ctx);
|
||||
if (sockfd < 0) {
|
||||
FATAL("Failed to open DNS resolver socket");
|
||||
}
|
||||
|
||||
if (nameserver_num == 1 && nameservers != NULL) {
|
||||
if (strncmp("127.0.0.1", nameservers[0], 9) == 0
|
||||
|| strncmp("::1", nameservers[0], 3) == 0) {
|
||||
if (verbose) {
|
||||
LOGI("bind UDP resolver to %s", nameservers[0]);
|
||||
}
|
||||
if (bind_to_address(sockfd, nameservers[0]) == -1)
|
||||
ERROR("bind_to_address");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __MINGW32__
|
||||
setnonblocking(sockfd);
|
||||
#else
|
||||
int flags = fcntl(sockfd, F_GETFL, 0);
|
||||
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
ev_io_init(&resolv_io_watcher, resolv_sock_cb, sockfd, EV_READ);
|
||||
resolv_io_watcher.data = ctx;
|
||||
|
||||
ev_io_start(loop, &resolv_io_watcher);
|
||||
|
||||
ev_timer_init(&resolv_timeout_watcher, resolv_timeout_cb, 0.0, 0.0);
|
||||
resolv_timeout_watcher.data = ctx;
|
||||
|
||||
dns_set_tmcbck(ctx, dns_timer_setup_cb, loop);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void
|
||||
resolv_shutdown(struct ev_loop *loop)
|
||||
{
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;
|
||||
|
||||
ev_io_stop(loop, &resolv_io_watcher);
|
||||
|
||||
if (ev_is_active(&resolv_timeout_watcher)) {
|
||||
ev_timer_stop(loop, &resolv_timeout_watcher);
|
||||
}
|
||||
|
||||
dns_close(ctx);
|
||||
}
|
||||
|
||||
struct ResolvQuery *
|
||||
resolv_query(const char *hostname, void (*client_cb)(struct sockaddr *, void *),
|
||||
void (*client_free_cb)(void *), void *client_cb_data,
|
||||
uint16_t port)
|
||||
{
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;
|
||||
|
||||
/*
|
||||
* Wrap udns's call back in our own
|
||||
*/
|
||||
struct ResolvQuery *cb_data = ss_malloc(sizeof(struct ResolvQuery));
|
||||
if (cb_data == NULL) {
|
||||
LOGE("Failed to allocate memory for DNS query callback data.");
|
||||
return NULL;
|
||||
}
|
||||
memset(cb_data, 0, sizeof(struct ResolvQuery));
|
||||
|
||||
cb_data->client_cb = client_cb;
|
||||
cb_data->client_free_cb = client_free_cb;
|
||||
cb_data->client_cb_data = client_cb_data;
|
||||
memset(cb_data->queries, 0, sizeof(cb_data->queries));
|
||||
cb_data->response_count = 0;
|
||||
cb_data->responses = NULL;
|
||||
cb_data->port = port;
|
||||
|
||||
/* Submit A and AAAA queries */
|
||||
if (resolv_mode != MODE_IPV6_ONLY) {
|
||||
cb_data->queries[0] = dns_submit_a4(ctx,
|
||||
hostname, 0,
|
||||
dns_query_v4_cb, cb_data);
|
||||
if (cb_data->queries[0] == NULL) {
|
||||
LOGE("Failed to submit DNS query: %s",
|
||||
dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
}
|
||||
|
||||
if (resolv_mode != MODE_IPV4_ONLY) {
|
||||
cb_data->queries[1] = dns_submit_a6(ctx,
|
||||
hostname, 0,
|
||||
dns_query_v6_cb, cb_data);
|
||||
if (cb_data->queries[1] == NULL) {
|
||||
LOGE("Failed to submit DNS query: %s",
|
||||
dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
}
|
||||
|
||||
if (all_queries_are_null(cb_data)) {
|
||||
if (cb_data->client_free_cb != NULL) {
|
||||
cb_data->client_free_cb(cb_data->client_cb_data);
|
||||
}
|
||||
ss_free(cb_data);
|
||||
}
|
||||
|
||||
return cb_data;
|
||||
}
|
||||
|
||||
void
|
||||
resolv_cancel(struct ResolvQuery *query_handle)
|
||||
{
|
||||
struct ResolvQuery *cb_data = (struct ResolvQuery *)query_handle;
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;
|
||||
|
||||
for (int i = 0; i < sizeof(cb_data->queries) / sizeof(cb_data->queries[0]);
|
||||
i++)
|
||||
if (cb_data->queries[i] != NULL) {
|
||||
dns_cancel(ctx, cb_data->queries[i]);
|
||||
ss_free(cb_data->queries[i]);
|
||||
}
|
||||
|
||||
if (cb_data->client_free_cb != NULL) {
|
||||
cb_data->client_free_cb(cb_data->client_cb_data);
|
||||
}
|
||||
|
||||
ss_free(cb_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* DNS UDP socket activity callback
|
||||
*/
|
||||
static void
|
||||
resolv_sock_cb(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
{
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)w->data;
|
||||
|
||||
if (revents & EV_READ) {
|
||||
dns_ioevent(ctx, ev_now(loop));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper for client callback we provide to udns
|
||||
*/
|
||||
static void
|
||||
dns_query_v4_cb(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
|
||||
{
|
||||
struct ResolvQuery *cb_data = (struct ResolvQuery *)data;
|
||||
|
||||
if (result == NULL) {
|
||||
if (verbose) {
|
||||
LOGI("IPv4 resolv: %s", dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
} else if (result->dnsa4_nrr > 0) {
|
||||
struct sockaddr **new_responses = ss_realloc(cb_data->responses,
|
||||
(cb_data->response_count +
|
||||
result->dnsa4_nrr) *
|
||||
sizeof(struct sockaddr *));
|
||||
if (new_responses == NULL) {
|
||||
LOGE("Failed to allocate memory for additional DNS responses");
|
||||
} else {
|
||||
cb_data->responses = new_responses;
|
||||
|
||||
for (int i = 0; i < result->dnsa4_nrr; i++) {
|
||||
struct sockaddr_in *sa =
|
||||
(struct sockaddr_in *)ss_malloc(sizeof(struct sockaddr_in));
|
||||
sa->sin_family = AF_INET;
|
||||
sa->sin_port = cb_data->port;
|
||||
sa->sin_addr = result->dnsa4_addr[i];
|
||||
|
||||
cb_data->responses[cb_data->response_count] =
|
||||
(struct sockaddr *)sa;
|
||||
if (cb_data->responses[cb_data->response_count] == NULL) {
|
||||
LOGE(
|
||||
"Failed to allocate memory for DNS query result address");
|
||||
} else {
|
||||
cb_data->response_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ss_free(result);
|
||||
cb_data->queries[0] = NULL; /* mark A query as being completed */
|
||||
|
||||
/* Once all queries have completed, call client callback */
|
||||
if (all_queries_are_null(cb_data)) {
|
||||
return process_client_callback(cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dns_query_v6_cb(struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data)
|
||||
{
|
||||
struct ResolvQuery *cb_data = (struct ResolvQuery *)data;
|
||||
|
||||
if (result == NULL) {
|
||||
if (verbose) {
|
||||
LOGI("IPv6 resolv: %s", dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
} else if (result->dnsa6_nrr > 0) {
|
||||
struct sockaddr **new_responses = ss_realloc(cb_data->responses,
|
||||
(cb_data->response_count +
|
||||
result->dnsa6_nrr) *
|
||||
sizeof(struct sockaddr *));
|
||||
if (new_responses == NULL) {
|
||||
LOGE("Failed to allocate memory for additional DNS responses");
|
||||
} else {
|
||||
cb_data->responses = new_responses;
|
||||
|
||||
for (int i = 0; i < result->dnsa6_nrr; i++) {
|
||||
struct sockaddr_in6 *sa =
|
||||
(struct sockaddr_in6 *)ss_malloc(sizeof(struct sockaddr_in6));
|
||||
sa->sin6_family = AF_INET6;
|
||||
sa->sin6_port = cb_data->port;
|
||||
sa->sin6_addr = result->dnsa6_addr[i];
|
||||
|
||||
cb_data->responses[cb_data->response_count] =
|
||||
(struct sockaddr *)sa;
|
||||
if (cb_data->responses[cb_data->response_count] == NULL) {
|
||||
LOGE(
|
||||
"Failed to allocate memory for DNS query result address");
|
||||
} else {
|
||||
cb_data->response_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ss_free(result);
|
||||
cb_data->queries[1] = NULL; /* mark AAAA query as being completed */
|
||||
|
||||
/* Once all queries have completed, call client callback */
|
||||
if (all_queries_are_null(cb_data)) {
|
||||
return process_client_callback(cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called once all queries have been completed
|
||||
*/
|
||||
static void
|
||||
process_client_callback(struct ResolvQuery *cb_data)
|
||||
{
|
||||
struct sockaddr *best_address = NULL;
|
||||
|
||||
if (resolv_mode == MODE_IPV4_FIRST) {
|
||||
best_address = choose_ipv4_first(cb_data);
|
||||
} else if (resolv_mode == MODE_IPV6_FIRST) {
|
||||
best_address = choose_ipv6_first(cb_data);
|
||||
} else {
|
||||
best_address = choose_any(cb_data);
|
||||
}
|
||||
|
||||
cb_data->client_cb(best_address, cb_data->client_cb_data);
|
||||
|
||||
for (int i = 0; i < cb_data->response_count; i++)
|
||||
ss_free(cb_data->responses[i]);
|
||||
|
||||
ss_free(cb_data->responses);
|
||||
if (cb_data->client_free_cb != NULL) {
|
||||
cb_data->client_free_cb(cb_data->client_cb_data);
|
||||
}
|
||||
ss_free(cb_data);
|
||||
}
|
||||
|
||||
static struct sockaddr *
|
||||
choose_ipv4_first(struct ResolvQuery *cb_data)
|
||||
{
|
||||
for (int i = 0; i < cb_data->response_count; i++)
|
||||
if (cb_data->responses[i]->sa_family == AF_INET) {
|
||||
return cb_data->responses[i];
|
||||
}
|
||||
|
||||
return choose_any(cb_data);
|
||||
}
|
||||
|
||||
static struct sockaddr *
|
||||
choose_ipv6_first(struct ResolvQuery *cb_data)
|
||||
{
|
||||
for (int i = 0; i < cb_data->response_count; i++)
|
||||
if (cb_data->responses[i]->sa_family == AF_INET6) {
|
||||
return cb_data->responses[i];
|
||||
}
|
||||
|
||||
return choose_any(cb_data);
|
||||
}
|
||||
|
||||
static struct sockaddr *
|
||||
choose_any(struct ResolvQuery *cb_data)
|
||||
{
|
||||
if (cb_data->response_count >= 1) {
|
||||
return cb_data->responses[0];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* DNS timeout callback
|
||||
*/
|
||||
static void
|
||||
resolv_timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents)
|
||||
{
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)w->data;
|
||||
|
||||
if (revents & EV_TIMER) {
|
||||
dns_timeouts(ctx, 30, ev_now(loop));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback to setup DNS timeout callback
|
||||
*/
|
||||
static void
|
||||
dns_timer_setup_cb(struct dns_ctx *ctx, int timeout, void *data)
|
||||
{
|
||||
struct ev_loop *loop = (struct ev_loop *)data;
|
||||
|
||||
if (ev_is_active(&resolv_timeout_watcher)) {
|
||||
ev_timer_stop(loop, &resolv_timeout_watcher);
|
||||
}
|
||||
|
||||
if (ctx != NULL && timeout >= 0) {
|
||||
ev_timer_set(&resolv_timeout_watcher, timeout, 0.0);
|
||||
ev_timer_start(loop, &resolv_timeout_watcher);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
all_queries_are_null(struct ResolvQuery *cb_data)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
for (int i = 0; i < sizeof(cb_data->queries) / sizeof(cb_data->queries[0]);
|
||||
i++)
|
||||
result = result && cb_data->queries[i] == NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
50
package/lean/shadowsocksr-libev/src/server/resolv.h
Normal file
50
package/lean/shadowsocksr-libev/src/server/resolv.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef RESOLV_H
|
||||
#define RESOLV_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include "win32.h"
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
struct ResolvQuery;
|
||||
|
||||
int resolv_init(struct ev_loop *, char **, int, int);
|
||||
struct ResolvQuery *resolv_query(const char *, void (*)(struct sockaddr *,
|
||||
void *), void (*)(
|
||||
void *), void *, uint16_t);
|
||||
void resolv_cancel(struct ResolvQuery *);
|
||||
void resolv_shutdown(struct ev_loop *);
|
||||
|
||||
#endif
|
||||
137
package/lean/shadowsocksr-libev/src/server/rule.c
Normal file
137
package/lean/shadowsocksr-libev/src/server/rule.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* Copyright (c) 2011 Manuel Kasper <mk@neon1.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
extern void ss_error(const char *s);
|
||||
#endif
|
||||
|
||||
#include "rule.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void free_rule(rule_t *);
|
||||
|
||||
rule_t *
|
||||
new_rule()
|
||||
{
|
||||
rule_t *rule;
|
||||
|
||||
rule = calloc(1, sizeof(rule_t));
|
||||
if (rule == NULL) {
|
||||
ERROR("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
int
|
||||
accept_rule_arg(rule_t *rule, const char *arg)
|
||||
{
|
||||
if (rule->pattern == NULL) {
|
||||
rule->pattern = strdup(arg);
|
||||
if (rule->pattern == NULL) {
|
||||
ERROR("strdup failed");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
LOGE("Unexpected table rule argument: %s", arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
add_rule(struct cork_dllist *rules, rule_t *rule)
|
||||
{
|
||||
cork_dllist_add(rules, &rule->entries);
|
||||
}
|
||||
|
||||
int
|
||||
init_rule(rule_t *rule)
|
||||
{
|
||||
if (rule->pattern_re == NULL) {
|
||||
const char *reerr;
|
||||
int reerroffset;
|
||||
|
||||
rule->pattern_re =
|
||||
pcre_compile(rule->pattern, 0, &reerr, &reerroffset, NULL);
|
||||
if (rule->pattern_re == NULL) {
|
||||
LOGE("Regex compilation of \"%s\" failed: %s, offset %d",
|
||||
rule->pattern, reerr, reerroffset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
rule_t *
|
||||
lookup_rule(const struct cork_dllist *rules, const char *name, size_t name_len)
|
||||
{
|
||||
struct cork_dllist_item *curr, *next;
|
||||
|
||||
if (name == NULL) {
|
||||
name = "";
|
||||
name_len = 0;
|
||||
}
|
||||
|
||||
cork_dllist_foreach_void(rules, curr, next) {
|
||||
rule_t *rule = cork_container_of(curr, rule_t, entries);
|
||||
if (pcre_exec(rule->pattern_re, NULL,
|
||||
name, name_len, 0, 0, NULL, 0) >= 0)
|
||||
return rule;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
remove_rule(rule_t *rule)
|
||||
{
|
||||
cork_dllist_remove(&rule->entries);
|
||||
free_rule(rule);
|
||||
}
|
||||
|
||||
static void
|
||||
free_rule(rule_t *rule)
|
||||
{
|
||||
if (rule == NULL)
|
||||
return;
|
||||
|
||||
ss_free(rule->pattern);
|
||||
if (rule->pattern_re != NULL)
|
||||
pcre_free(rule->pattern_re);
|
||||
ss_free(rule);
|
||||
}
|
||||
58
package/lean/shadowsocksr-libev/src/server/rule.h
Normal file
58
package/lean/shadowsocksr-libev/src/server/rule.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* Copyright (c) 2011 Manuel Kasper <mk@neon1.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef RULE_H
|
||||
#define RULE_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <libcork/ds.h>
|
||||
|
||||
#ifdef HAVE_PCRE_H
|
||||
#include <pcre.h>
|
||||
#elif HAVE_PCRE_PCRE_H
|
||||
#include <pcre/pcre.h>
|
||||
#endif
|
||||
|
||||
typedef struct rule {
|
||||
char *pattern;
|
||||
|
||||
/* Runtime fields */
|
||||
pcre *pattern_re;
|
||||
|
||||
struct cork_dllist_item entries;
|
||||
} rule_t;
|
||||
|
||||
void add_rule(struct cork_dllist *, rule_t *);
|
||||
int init_rule(rule_t *);
|
||||
rule_t *lookup_rule(const struct cork_dllist *, const char *, size_t);
|
||||
void remove_rule(rule_t *);
|
||||
rule_t *new_rule();
|
||||
int accept_rule_arg(rule_t *, const char *);
|
||||
|
||||
#endif
|
||||
2209
package/lean/shadowsocksr-libev/src/server/server.c
Normal file
2209
package/lean/shadowsocksr-libev/src/server/server.c
Normal file
File diff suppressed because it is too large
Load Diff
115
package/lean/shadowsocksr-libev/src/server/server.h
Normal file
115
package/lean/shadowsocksr-libev/src/server/server.h
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* server.h - Define shadowsocks server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SERVER_H
|
||||
#define _SERVER_H
|
||||
|
||||
#include <ev.h>
|
||||
#include <time.h>
|
||||
#include <libcork/ds.h>
|
||||
|
||||
#include "encrypt.h"
|
||||
#include "jconf.h"
|
||||
#include "resolv.h"
|
||||
#include "obfs.h"
|
||||
#include "protocol.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef struct listen_ctx {
|
||||
ev_io io;
|
||||
int fd;
|
||||
int timeout;
|
||||
int method;
|
||||
char *iface;
|
||||
struct ev_loop *loop;
|
||||
|
||||
// SSR
|
||||
char *protocol_name;
|
||||
char *protocol_param;
|
||||
char *obfs_name;
|
||||
char *obfs_param;
|
||||
void **list_protocol_global;
|
||||
void **list_obfs_global;
|
||||
} listen_ctx_t;
|
||||
|
||||
typedef struct server_ctx {
|
||||
ev_io io;
|
||||
ev_timer watcher;
|
||||
int connected;
|
||||
struct server *server;
|
||||
} server_ctx_t;
|
||||
|
||||
typedef struct server {
|
||||
int fd;
|
||||
int stage;
|
||||
buffer_t *buf;
|
||||
ssize_t buf_capacity;
|
||||
buffer_t *header_buf;
|
||||
|
||||
int auth;
|
||||
struct chunk *chunk;
|
||||
|
||||
struct enc_ctx *e_ctx;
|
||||
struct enc_ctx *d_ctx;
|
||||
struct server_ctx *recv_ctx;
|
||||
struct server_ctx *send_ctx;
|
||||
struct listen_ctx *listen_ctx;
|
||||
struct remote *remote;
|
||||
|
||||
struct ResolvQuery *query;
|
||||
|
||||
struct cork_dllist_item entries;
|
||||
|
||||
// SSR
|
||||
obfs *protocol;
|
||||
obfs *obfs;
|
||||
obfs_class *protocol_plugin;
|
||||
obfs_class *obfs_plugin;
|
||||
int obfs_compatible_state;
|
||||
int protocol_compatible_state;
|
||||
} server_t;
|
||||
|
||||
typedef struct query {
|
||||
server_t *server;
|
||||
char hostname[257];
|
||||
} query_t;
|
||||
|
||||
typedef struct remote_ctx {
|
||||
ev_io io;
|
||||
int connected;
|
||||
struct remote *remote;
|
||||
} remote_ctx_t;
|
||||
|
||||
typedef struct remote {
|
||||
int fd;
|
||||
buffer_t *buf;
|
||||
ssize_t buf_capacity;
|
||||
struct remote_ctx *recv_ctx;
|
||||
struct remote_ctx *send_ctx;
|
||||
struct server *server;
|
||||
|
||||
// SSR
|
||||
int remote_index;
|
||||
} remote_t;
|
||||
|
||||
#endif // _SERVER_H
|
||||
263
package/lean/shadowsocksr-libev/src/server/tls.c
Normal file
263
package/lean/shadowsocksr-libev/src/server/tls.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This is a minimal TLS implementation intended only to parse the server name
|
||||
* extension. This was created based primarily on Wireshark dissection of a
|
||||
* TLS handshake and RFC4366.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* malloc() */
|
||||
#include <string.h> /* strncpy() */
|
||||
|
||||
#ifndef __MINGW32__
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <win32.h>
|
||||
#endif
|
||||
|
||||
#include "tls.h"
|
||||
#include "protocol.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define SERVER_NAME_LEN 256
|
||||
#define TLS_HEADER_LEN 5
|
||||
#define TLS_HANDSHAKE_CONTENT_TYPE 0x16
|
||||
#define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 0x01
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static int parse_tls_header(const char *, size_t, char **);
|
||||
static int parse_extensions(const char *, size_t, char **);
|
||||
static int parse_server_name_extension(const char *, size_t, char **);
|
||||
|
||||
static const protocol_t tls_protocol_st = {
|
||||
.default_port = 443,
|
||||
.parse_packet = &parse_tls_header,
|
||||
};
|
||||
const protocol_t *const tls_protocol = &tls_protocol_st;
|
||||
|
||||
/* Parse a TLS packet for the Server Name Indication extension in the client
|
||||
* hello handshake, returning the first servername found (pointer to static
|
||||
* array)
|
||||
*
|
||||
* Returns:
|
||||
* >=0 - length of the hostname and updates *hostname
|
||||
* caller is responsible for freeing *hostname
|
||||
* -1 - Incomplete request
|
||||
* -2 - No Host header included in this request
|
||||
* -3 - Invalid hostname pointer
|
||||
* -4 - malloc failure
|
||||
* < -4 - Invalid TLS client hello
|
||||
*/
|
||||
static int
|
||||
parse_tls_header(const char *data, size_t data_len, char **hostname)
|
||||
{
|
||||
char tls_content_type;
|
||||
char tls_version_major;
|
||||
char tls_version_minor;
|
||||
size_t pos = TLS_HEADER_LEN;
|
||||
size_t len;
|
||||
|
||||
if (hostname == NULL)
|
||||
return -3;
|
||||
|
||||
/* Check that our TCP payload is at least large enough for a TLS header */
|
||||
if (data_len < TLS_HEADER_LEN)
|
||||
return -1;
|
||||
|
||||
/* SSL 2.0 compatible Client Hello
|
||||
*
|
||||
* High bit of first byte (length) and content type is Client Hello
|
||||
*
|
||||
* See RFC5246 Appendix E.2
|
||||
*/
|
||||
if (data[0] & 0x80 && data[2] == 1) {
|
||||
if (verbose)
|
||||
LOGI("Received SSL 2.0 Client Hello which can not support SNI.");
|
||||
return -2;
|
||||
}
|
||||
|
||||
tls_content_type = data[0];
|
||||
if (tls_content_type != TLS_HANDSHAKE_CONTENT_TYPE) {
|
||||
if (verbose)
|
||||
LOGI("Request did not begin with TLS handshake.");
|
||||
return -5;
|
||||
}
|
||||
|
||||
tls_version_major = data[1];
|
||||
tls_version_minor = data[2];
|
||||
if (tls_version_major < 3) {
|
||||
if (verbose)
|
||||
LOGI("Received SSL %d.%d handshake which can not support SNI.",
|
||||
tls_version_major, tls_version_minor);
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* TLS record length */
|
||||
len = ((unsigned char)data[3] << 8) +
|
||||
(unsigned char)data[4] + TLS_HEADER_LEN;
|
||||
data_len = MIN(data_len, len);
|
||||
|
||||
/* Check we received entire TLS record length */
|
||||
if (data_len < len)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Handshake
|
||||
*/
|
||||
if (pos + 1 > data_len) {
|
||||
return -5;
|
||||
}
|
||||
if (data[pos] != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) {
|
||||
if (verbose)
|
||||
LOGI("Not a client hello");
|
||||
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* Skip past fixed length records:
|
||||
* 1 Handshake Type
|
||||
* 3 Length
|
||||
* 2 Version (again)
|
||||
* 32 Random
|
||||
* to Session ID Length
|
||||
*/
|
||||
pos += 38;
|
||||
|
||||
/* Session ID */
|
||||
if (pos + 1 > data_len)
|
||||
return -5;
|
||||
len = (unsigned char)data[pos];
|
||||
pos += 1 + len;
|
||||
|
||||
/* Cipher Suites */
|
||||
if (pos + 2 > data_len)
|
||||
return -5;
|
||||
len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1];
|
||||
pos += 2 + len;
|
||||
|
||||
/* Compression Methods */
|
||||
if (pos + 1 > data_len)
|
||||
return -5;
|
||||
len = (unsigned char)data[pos];
|
||||
pos += 1 + len;
|
||||
|
||||
if (pos == data_len && tls_version_major == 3 && tls_version_minor == 0) {
|
||||
if (verbose)
|
||||
LOGI("Received SSL 3.0 handshake without extensions");
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Extensions */
|
||||
if (pos + 2 > data_len)
|
||||
return -5;
|
||||
len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
if (pos + len > data_len)
|
||||
return -5;
|
||||
return parse_extensions(data + pos, len, hostname);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_extensions(const char *data, size_t data_len, char **hostname)
|
||||
{
|
||||
size_t pos = 0;
|
||||
size_t len;
|
||||
|
||||
/* Parse each 4 bytes for the extension header */
|
||||
while (pos + 4 <= data_len) {
|
||||
/* Extension Length */
|
||||
len = ((unsigned char)data[pos + 2] << 8) +
|
||||
(unsigned char)data[pos + 3];
|
||||
|
||||
/* Check if it's a server name extension */
|
||||
if (data[pos] == 0x00 && data[pos + 1] == 0x00) {
|
||||
/* There can be only one extension of each type, so we break
|
||||
* our state and move p to beinnging of the extension here */
|
||||
if (pos + 4 + len > data_len)
|
||||
return -5;
|
||||
return parse_server_name_extension(data + pos + 4, len, hostname);
|
||||
}
|
||||
pos += 4 + len; /* Advance to the next extension header */
|
||||
}
|
||||
/* Check we ended where we expected to */
|
||||
if (pos != data_len)
|
||||
return -5;
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_server_name_extension(const char *data, size_t data_len,
|
||||
char **hostname)
|
||||
{
|
||||
size_t pos = 2; /* skip server name list length */
|
||||
size_t len;
|
||||
|
||||
while (pos + 3 < data_len) {
|
||||
len = ((unsigned char)data[pos + 1] << 8) +
|
||||
(unsigned char)data[pos + 2];
|
||||
|
||||
if (pos + 3 + len > data_len)
|
||||
return -5;
|
||||
|
||||
switch (data[pos]) { /* name type */
|
||||
case 0x00: /* host_name */
|
||||
*hostname = malloc(len + 1);
|
||||
if (*hostname == NULL) {
|
||||
ERROR("malloc() failure");
|
||||
return -4;
|
||||
}
|
||||
|
||||
strncpy(*hostname, data + pos + 3, len);
|
||||
|
||||
(*hostname)[len] = '\0';
|
||||
|
||||
return len;
|
||||
default:
|
||||
if (verbose)
|
||||
LOGI("Unknown server name extension name type: %d",
|
||||
data[pos]);
|
||||
}
|
||||
pos += 3 + len;
|
||||
}
|
||||
/* Check we ended where we expected to */
|
||||
if (pos != data_len)
|
||||
return -5;
|
||||
|
||||
return -2;
|
||||
}
|
||||
33
package/lean/shadowsocksr-libev/src/server/tls.h
Normal file
33
package/lean/shadowsocksr-libev/src/server/tls.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TLS_H
|
||||
#define TLS_H
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
const protocol_t *const tls_protocol;
|
||||
|
||||
#endif
|
||||
609
package/lean/shadowsocksr-libev/src/server/tls1.2_ticket.c
Normal file
609
package/lean/shadowsocksr-libev/src/server/tls1.2_ticket.c
Normal file
@ -0,0 +1,609 @@
|
||||
|
||||
#include "tls1.2_ticket.h"
|
||||
#include "list.c"
|
||||
|
||||
typedef struct tls12_ticket_auth_global_data {
|
||||
uint8_t local_client_id[32];
|
||||
List client_data;
|
||||
time_t startup_time;
|
||||
}tls12_ticket_auth_global_data;
|
||||
|
||||
typedef struct tls12_ticket_auth_local_data {
|
||||
int handshake_status;
|
||||
char *send_buffer;
|
||||
int send_buffer_size;
|
||||
char *recv_buffer;
|
||||
int recv_buffer_size;
|
||||
}tls12_ticket_auth_local_data;
|
||||
|
||||
void tls12_ticket_auth_local_data_init(tls12_ticket_auth_local_data* local) {
|
||||
local->handshake_status = 0;
|
||||
local->send_buffer = malloc(0);
|
||||
local->send_buffer_size = 0;
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
}
|
||||
|
||||
void * tls12_ticket_auth_init_data() {
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)malloc(sizeof(tls12_ticket_auth_global_data));
|
||||
rand_bytes(global->local_client_id, 32);
|
||||
global->client_data = list_init(22);
|
||||
global->startup_time = time(NULL);
|
||||
return global;
|
||||
}
|
||||
|
||||
obfs * tls12_ticket_auth_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(tls12_ticket_auth_local_data));
|
||||
tls12_ticket_auth_local_data_init((tls12_ticket_auth_local_data*)self->l_data);
|
||||
return self;
|
||||
}
|
||||
|
||||
void tls12_ticket_auth_dispose(obfs *self) {
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
if (local->send_buffer != NULL) {
|
||||
free(local->send_buffer);
|
||||
local->send_buffer = NULL;
|
||||
}
|
||||
if (local->recv_buffer != NULL) {
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = NULL;
|
||||
}
|
||||
free(local);
|
||||
dispose_obfs(self);
|
||||
}
|
||||
|
||||
int tls12_ticket_pack_auth_data(tls12_ticket_auth_global_data *global, server_info *server, char *outdata) {
|
||||
int out_size = 32;
|
||||
time_t t = time(NULL);
|
||||
outdata[0] = t >> 24;
|
||||
outdata[1] = t >> 16;
|
||||
outdata[2] = t >> 8;
|
||||
outdata[3] = t;
|
||||
rand_bytes((uint8_t*)outdata + 4, 18);
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(server->key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, server->key, server->key_len);
|
||||
memcpy(key + server->key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, key, server->key_len + 32);
|
||||
free(key);
|
||||
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
void tls12_ticket_auth_pack_data(char *encryptdata, int datalength, int start, int len, char *out_buffer, int outlength) {
|
||||
out_buffer[outlength] = 0x17;
|
||||
out_buffer[outlength + 1] = 0x3;
|
||||
out_buffer[outlength + 2] = 0x3;
|
||||
out_buffer[outlength + 3] = len >> 8;
|
||||
out_buffer[outlength + 4] = len;
|
||||
memcpy(out_buffer + outlength + 5, encryptdata + start, len);
|
||||
}
|
||||
|
||||
int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
||||
char * out_buffer = NULL;
|
||||
|
||||
if (local->handshake_status == 8) {
|
||||
if (datalength < 1024) {
|
||||
if (*capacity < datalength + 5) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata + 5, encryptdata, datalength);
|
||||
encryptdata[0] = 0x17;
|
||||
encryptdata[1] = 0x3;
|
||||
encryptdata[2] = 0x3;
|
||||
encryptdata[3] = datalength >> 8;
|
||||
encryptdata[4] = datalength;
|
||||
return datalength + 5;
|
||||
} else {
|
||||
out_buffer = (char*)malloc(datalength + 2048);
|
||||
int start = 0;
|
||||
int outlength = 0;
|
||||
int len;
|
||||
while (datalength - start > 2048) {
|
||||
len = xorshift128plus() % 4096 + 100;
|
||||
if (len > datalength - start)
|
||||
len = datalength - start;
|
||||
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
||||
outlength += len + 5;
|
||||
start += len;
|
||||
}
|
||||
if (datalength - start > 0) {
|
||||
len = datalength - start;
|
||||
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
||||
outlength += len + 5;
|
||||
}
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
return outlength;
|
||||
}
|
||||
}
|
||||
local->send_buffer = (char*)realloc(local->send_buffer, local->send_buffer_size + datalength + 5);
|
||||
memcpy(local->send_buffer + local->send_buffer_size + 5, encryptdata, datalength);
|
||||
local->send_buffer[local->send_buffer_size] = 0x17;
|
||||
local->send_buffer[local->send_buffer_size + 1] = 0x3;
|
||||
local->send_buffer[local->send_buffer_size + 2] = 0x3;
|
||||
local->send_buffer[local->send_buffer_size + 3] = datalength >> 8;
|
||||
local->send_buffer[local->send_buffer_size + 4] = datalength;
|
||||
local->send_buffer_size += datalength + 5;
|
||||
|
||||
if (local->handshake_status == 0) {
|
||||
#define CSTR_DECL(name, len, str) const char* name = str; const int len = sizeof(str) - 1;
|
||||
CSTR_DECL(tls_data0, tls_data0_len, "\x00\x1c\xc0\x2b\xc0\x2f\xcc\xa9\xcc\xa8\xcc\x14\xcc\x13\xc0\x0a\xc0\x14\xc0\x09\xc0\x13\x00\x9c\x00\x35\x00\x2f\x00\x0a\x01\x00"
|
||||
);
|
||||
CSTR_DECL(tls_data1, tls_data1_len, "\xff\x01\x00\x01\x00"
|
||||
);
|
||||
CSTR_DECL(tls_data2, tls_data2_len, "\x00\x17\x00\x00\x00\x23\x00\xd0");
|
||||
CSTR_DECL(tls_data3, tls_data3_len, "\x00\x0d\x00\x16\x00\x14\x06\x01\x06\x03\x05\x01\x05\x03\x04\x01\x04\x03\x03\x01\x03\x03\x02\x01\x02\x03\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x12\x00\x00\x75\x50\x00\x00\x00\x0b\x00\x02\x01\x00\x00\x0a\x00\x06\x00\x04\x00\x17\x00\x18"
|
||||
//"00150066000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" // padding
|
||||
);
|
||||
uint8_t tls_data[2048];
|
||||
int tls_data_len = 0;
|
||||
memcpy(tls_data, tls_data1, tls_data1_len);
|
||||
tls_data_len += tls_data1_len;
|
||||
|
||||
char hosts[1024];
|
||||
char * phost[128];
|
||||
int host_num = 0;
|
||||
int pos;
|
||||
|
||||
char sni[256] = {0};
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
self->server.param = NULL;
|
||||
strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts);
|
||||
phost[host_num++] = hosts;
|
||||
for (pos = 0; hosts[pos]; ++pos) {
|
||||
if (hosts[pos] == ',') {
|
||||
phost[host_num++] = &hosts[pos + 1];
|
||||
}
|
||||
}
|
||||
host_num = xorshift128plus() % host_num;
|
||||
|
||||
sprintf(sni, "%s", phost[host_num]);
|
||||
int sni_len = strlen(sni);
|
||||
if (sni_len > 0 && sni[sni_len - 1] >= '0' && sni[sni_len - 1] <= '9')
|
||||
sni_len = 0;
|
||||
tls_data[tls_data_len] = '\0';
|
||||
tls_data[tls_data_len + 1] = '\0';
|
||||
tls_data[tls_data_len + 2] = (sni_len + 5) >> 8;
|
||||
tls_data[tls_data_len + 3] = (sni_len + 5);
|
||||
tls_data[tls_data_len + 4] = (sni_len + 3) >> 8;
|
||||
tls_data[tls_data_len + 5] = (sni_len + 3);
|
||||
tls_data[tls_data_len + 6] = '\0';
|
||||
tls_data[tls_data_len + 7] = sni_len >> 8;
|
||||
tls_data[tls_data_len + 8] = sni_len;
|
||||
memcpy(tls_data + tls_data_len + 9, sni, sni_len);
|
||||
tls_data_len += 9 + sni_len;
|
||||
memcpy(tls_data + tls_data_len, tls_data2, tls_data2_len);
|
||||
tls_data_len += tls_data2_len;
|
||||
rand_bytes(tls_data + tls_data_len, 208);
|
||||
tls_data_len += 208;
|
||||
memcpy(tls_data + tls_data_len, tls_data3, tls_data3_len);
|
||||
tls_data_len += tls_data3_len;
|
||||
|
||||
datalength = 11 + 32 + 1 + 32 + tls_data0_len + 2 + tls_data_len;
|
||||
out_buffer = (char*)malloc(datalength);
|
||||
char *pdata = out_buffer + datalength - tls_data_len;
|
||||
int len = tls_data_len;
|
||||
memcpy(pdata, tls_data, tls_data_len);
|
||||
pdata[-1] = tls_data_len;
|
||||
pdata[-2] = tls_data_len >> 8;
|
||||
pdata -= 2; len += 2;
|
||||
memcpy(pdata - tls_data0_len, tls_data0, tls_data0_len);
|
||||
pdata -= tls_data0_len; len += tls_data0_len;
|
||||
memcpy(pdata - 32, global->local_client_id, 32);
|
||||
pdata -= 32; len += 32;
|
||||
pdata[-1] = 0x20;
|
||||
pdata -= 1; len += 1;
|
||||
tls12_ticket_pack_auth_data(global, &self->server, pdata - 32);
|
||||
pdata -= 32; len += 32;
|
||||
pdata[-1] = 0x3;
|
||||
pdata[-2] = 0x3; // tls version
|
||||
pdata -= 2; len += 2;
|
||||
pdata[-1] = len;
|
||||
pdata[-2] = len >> 8;
|
||||
pdata[-3] = 0;
|
||||
pdata[-4] = 1;
|
||||
pdata -= 4; len += 4;
|
||||
|
||||
pdata[-1] = len;
|
||||
pdata[-2] = len >> 8;
|
||||
pdata -= 2; len += 2;
|
||||
pdata[-1] = 0x1;
|
||||
pdata[-2] = 0x3; // tls version
|
||||
pdata -= 2; len += 2;
|
||||
pdata[-1] = 0x16; // tls handshake
|
||||
pdata -= 1; len += 1;
|
||||
|
||||
local->handshake_status = 1;
|
||||
} else if (datalength == 0) {
|
||||
datalength = local->send_buffer_size + 43;
|
||||
out_buffer = (char*)malloc(datalength);
|
||||
char *pdata = out_buffer;
|
||||
memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6);
|
||||
pdata += 6;
|
||||
memcpy(pdata, "\x16\x03\x03\x00\x20", 5);
|
||||
pdata += 5;
|
||||
rand_bytes((uint8_t*)pdata, 22);
|
||||
pdata += 22;
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, out_buffer, pdata - out_buffer, key, self->server.key_len + 32);
|
||||
free(key);
|
||||
memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN);
|
||||
|
||||
pdata += OBFS_HMAC_SHA1_LEN;
|
||||
memcpy(pdata, local->send_buffer, local->send_buffer_size);
|
||||
free(local->send_buffer);
|
||||
local->send_buffer = NULL;
|
||||
|
||||
local->handshake_status = 8;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (*capacity < datalength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = datalength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata, out_buffer, datalength);
|
||||
free(out_buffer);
|
||||
return datalength;
|
||||
}
|
||||
|
||||
int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
||||
char * out_buffer = NULL;
|
||||
|
||||
if (local->handshake_status == 8) {
|
||||
if (datalength < 1024) {
|
||||
if (*capacity < datalength + 5) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata + 5, encryptdata, datalength);
|
||||
encryptdata[0] = 0x17;
|
||||
encryptdata[1] = 0x3;
|
||||
encryptdata[2] = 0x3;
|
||||
encryptdata[3] = datalength >> 8;
|
||||
encryptdata[4] = datalength;
|
||||
return datalength + 5;
|
||||
} else {
|
||||
out_buffer = (char*)malloc(datalength + 2048);
|
||||
int start = 0;
|
||||
int outlength = 0;
|
||||
int len;
|
||||
while (datalength - start > 2048) {
|
||||
len = xorshift128plus() % 4096 + 100;
|
||||
if (len > datalength - start)
|
||||
len = datalength - start;
|
||||
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
||||
outlength += len + 5;
|
||||
start += len;
|
||||
}
|
||||
if (datalength - start > 0) {
|
||||
len = datalength - start;
|
||||
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
||||
outlength += len + 5;
|
||||
}
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
return outlength;
|
||||
}
|
||||
}
|
||||
|
||||
local->handshake_status = 3;
|
||||
|
||||
out_buffer = (char*)malloc(43 + 86);
|
||||
int data_len = 0;
|
||||
char *p_data = out_buffer + 86;
|
||||
|
||||
memcpy(p_data - 10, "\xc0\x2f\x00\x00\x05\xff\x01\x00\x01\x00", 10);
|
||||
p_data -= 10;data_len += 10;
|
||||
|
||||
memcpy(p_data - 32, global->local_client_id, 32);
|
||||
p_data -= 32;data_len += 32;
|
||||
|
||||
p_data[-1] = 0x20;
|
||||
p_data -= 1;data_len += 1;
|
||||
|
||||
tls12_ticket_pack_auth_data(global, &self->server, p_data - 32);
|
||||
p_data -= 32;data_len += 32;
|
||||
|
||||
p_data[-1] = 0x3;
|
||||
p_data[-2] = 0x3; // tls version
|
||||
p_data -= 2;data_len += 2;
|
||||
|
||||
p_data[-1] = data_len;
|
||||
p_data[-2] = data_len >> 8;
|
||||
p_data[-3] = 0x00;
|
||||
p_data[-4] = 0x02;
|
||||
p_data -= 4; data_len += 4;
|
||||
|
||||
p_data[-1] = data_len;
|
||||
p_data[-2] = data_len >> 8;
|
||||
p_data[-3] = 0x03;
|
||||
p_data[-4] = 0x03;
|
||||
p_data[-5] = 0x16;
|
||||
p_data -= 5; data_len += 5;
|
||||
|
||||
memcpy(out_buffer, p_data, data_len);
|
||||
char *pdata = out_buffer + 86;
|
||||
|
||||
memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6);
|
||||
pdata += 6;
|
||||
memcpy(pdata, "\x16\x03\x03\x00\x20", 5);
|
||||
pdata += 5;
|
||||
rand_bytes((uint8_t*)pdata, 22);
|
||||
pdata += 22;
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, out_buffer, 43 + 86, key, self->server.key_len + 32);
|
||||
free(key);
|
||||
memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN);
|
||||
|
||||
memmove(encryptdata, out_buffer, 43 + 86);
|
||||
free(out_buffer);
|
||||
return 43 + 86;
|
||||
}
|
||||
|
||||
int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
||||
|
||||
*needsendback = 0;
|
||||
|
||||
if (local->handshake_status == 8) {
|
||||
local->recv_buffer_size += datalength;
|
||||
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size);
|
||||
memcpy(local->recv_buffer + local->recv_buffer_size - datalength, encryptdata, datalength);
|
||||
datalength = 0;
|
||||
while (local->recv_buffer_size > 5) {
|
||||
if (local->recv_buffer[0] != 0x17)
|
||||
return -1;
|
||||
int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4];
|
||||
if (size + 5 > local->recv_buffer_size)
|
||||
break;
|
||||
if (*capacity < datalength + size) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + size) * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata + datalength, local->recv_buffer + 5, size);
|
||||
datalength += size;
|
||||
local->recv_buffer_size -= 5 + size;
|
||||
memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size);
|
||||
}
|
||||
return datalength;
|
||||
}
|
||||
if (datalength < 11 + 32 + 1 + 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, encryptdata + 11, 22, key, self->server.key_len + 32);
|
||||
free(key);
|
||||
|
||||
if (memcmp(encryptdata + 33, hash, OBFS_HMAC_SHA1_LEN)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*needsendback = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
||||
|
||||
*needsendback = 0;
|
||||
|
||||
if (local->handshake_status == 8) {
|
||||
if(datalength != 0)
|
||||
{
|
||||
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength);
|
||||
memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
}
|
||||
datalength = 0;
|
||||
|
||||
while (local->recv_buffer_size > 5) {
|
||||
if (local->recv_buffer[0] != 0x17 || local->recv_buffer[1] != 0x03 || local->recv_buffer[2] != 0x03)
|
||||
{
|
||||
LOGE("server_decode data error, wrong tls version 3");
|
||||
return -1;
|
||||
}
|
||||
int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4];
|
||||
if (size + 5 > local->recv_buffer_size)
|
||||
break;
|
||||
if (*capacity < local->recv_buffer_size + size) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (local->recv_buffer_size + size) * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata + datalength, local->recv_buffer + 5, size);
|
||||
datalength += size;
|
||||
local->recv_buffer_size -= 5 + size;
|
||||
memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size);
|
||||
}
|
||||
return datalength;
|
||||
}
|
||||
|
||||
if (local->handshake_status == 3) {
|
||||
|
||||
char *verify = encryptdata;
|
||||
|
||||
if(datalength < 43)
|
||||
{
|
||||
LOGE("server_decode data error, too short:%d", (int)datalength);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(encryptdata[0] != 0x14 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x01 || encryptdata[5] != 0x01)
|
||||
{
|
||||
LOGE("server_decode data error, wrong tls version");
|
||||
return -1;
|
||||
}
|
||||
|
||||
encryptdata += 6;
|
||||
|
||||
if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x20)
|
||||
{
|
||||
LOGE("server_decode data error, wrong tls version 2");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, verify, 33, key, self->server.key_len + 32);
|
||||
free(key);
|
||||
|
||||
if (memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN) != 0) {
|
||||
LOGE("server_decode data error, hash Mismatch %d",(int)memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN));
|
||||
return -1;
|
||||
}
|
||||
|
||||
local->recv_buffer_size = datalength - 43;
|
||||
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size);
|
||||
memmove(local->recv_buffer, encryptdata + 37, datalength - 43);
|
||||
|
||||
local->handshake_status = 8;
|
||||
return tls12_ticket_auth_server_decode(self, pencryptdata, 0, capacity, needsendback);
|
||||
}
|
||||
|
||||
local->handshake_status = 2;
|
||||
if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x01)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
encryptdata += 3;
|
||||
|
||||
{
|
||||
int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1];
|
||||
if(size != datalength - 5)
|
||||
{
|
||||
LOGE("tls_auth wrong tls head size");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
encryptdata += 2;
|
||||
|
||||
if(encryptdata[0] != 0x01 || encryptdata[1] != 0x00)
|
||||
{
|
||||
LOGE("tls_auth not client hello message");
|
||||
return -1;
|
||||
}
|
||||
|
||||
encryptdata += 2;
|
||||
|
||||
{
|
||||
int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1];
|
||||
if(size != datalength - 9)
|
||||
{
|
||||
LOGE("tls_auth wrong message size");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
encryptdata += 2;
|
||||
|
||||
if(encryptdata[0] != 0x03 || encryptdata[1] != 0x03)
|
||||
{
|
||||
LOGE("tls_auth wrong tls version");
|
||||
return -1;
|
||||
}
|
||||
|
||||
encryptdata += 2;
|
||||
|
||||
char *verifyid = encryptdata;
|
||||
|
||||
encryptdata += 32;
|
||||
|
||||
int sessionid_len = encryptdata[0];
|
||||
if(sessionid_len < 32)
|
||||
{
|
||||
LOGE("tls_auth wrong sessionid_len");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *sessionid = encryptdata + 1;
|
||||
memcpy(global->local_client_id , sessionid, sessionid_len);
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + sessionid_len);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, sessionid_len);
|
||||
ss_sha1_hmac_with_key(hash, verifyid, 22, key, self->server.key_len + sessionid_len);
|
||||
free(key);
|
||||
|
||||
encryptdata += (sessionid_len + 1);
|
||||
|
||||
long utc_time = ((int)(unsigned char)verifyid[0] << 24) + ((int)(unsigned char)verifyid[1] << 16) + ((int)(unsigned char)verifyid[2] << 8) + (unsigned char)verifyid[3];
|
||||
time_t t = time(NULL);
|
||||
|
||||
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
{
|
||||
self->server.param = NULL;
|
||||
}
|
||||
|
||||
int max_time_dif = 0;
|
||||
int time_dif = utc_time - t;
|
||||
if(self->server.param)
|
||||
{
|
||||
max_time_dif = atoi(self->server.param);
|
||||
}
|
||||
|
||||
if(max_time_dif > 0 && (time_dif < -max_time_dif || time_dif > max_time_dif || utc_time - global->startup_time < -max_time_dif / 2))
|
||||
{
|
||||
LOGE("tls_auth wrong time");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(verifyid + 22, hash, OBFS_HMAC_SHA1_LEN)) {
|
||||
LOGE("tls_auth wrong sha1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int search_result = global->client_data->have_same_cmp(global->client_data, verifyid);
|
||||
if(search_result != 0)
|
||||
{
|
||||
LOGE("replay attack detect!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
global->client_data->add_back(global->client_data, verifyid);
|
||||
|
||||
encryptdata += 48;
|
||||
|
||||
*needsendback = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
20
package/lean/shadowsocksr-libev/src/server/tls1.2_ticket.h
Normal file
20
package/lean/shadowsocksr-libev/src/server/tls1.2_ticket.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* http_simple.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TLS1_2_TICKET_H
|
||||
#define _TLS1_2_TICKET_H
|
||||
|
||||
void * tls12_ticket_auth_init_data();
|
||||
obfs * tls12_ticket_auth_new_obfs();
|
||||
void tls12_ticket_auth_dispose(obfs *self);
|
||||
|
||||
int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback);
|
||||
|
||||
int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback);
|
||||
|
||||
#endif // _TLS1_2_TICKET_H
|
||||
1452
package/lean/shadowsocksr-libev/src/server/udprelay.c
Normal file
1452
package/lean/shadowsocksr-libev/src/server/udprelay.c
Normal file
File diff suppressed because it is too large
Load Diff
95
package/lean/shadowsocksr-libev/src/server/udprelay.h
Normal file
95
package/lean/shadowsocksr-libev/src/server/udprelay.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* udprelay.h - Define UDP relay's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _UDPRELAY_H
|
||||
#define _UDPRELAY_H
|
||||
|
||||
#include <ev.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "encrypt.h"
|
||||
#include "jconf.h"
|
||||
#include "obfs.h"
|
||||
|
||||
#ifdef MODULE_REMOTE
|
||||
#include "resolv.h"
|
||||
#endif
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define MAX_UDP_PACKET_SIZE (65507)
|
||||
|
||||
#define DEFAULT_PACKET_SIZE 1397 // 1492 - 1 - 28 - 2 - 64 = 1397, the default MTU for UDP relay
|
||||
|
||||
typedef struct server_ctx {
|
||||
ev_io io;
|
||||
int fd;
|
||||
int method;
|
||||
int auth;
|
||||
int timeout;
|
||||
const char *iface;
|
||||
struct cache *conn_cache;
|
||||
#ifdef MODULE_LOCAL
|
||||
const struct sockaddr *remote_addr;
|
||||
int remote_addr_len;
|
||||
#ifdef MODULE_TUNNEL
|
||||
ss_addr_t tunnel_addr;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MODULE_REMOTE
|
||||
struct ev_loop *loop;
|
||||
#endif
|
||||
// SSR
|
||||
obfs *protocol;
|
||||
obfs_class *protocol_plugin;
|
||||
void *protocol_global;
|
||||
} server_ctx_t;
|
||||
|
||||
#ifdef MODULE_REMOTE
|
||||
typedef struct query_ctx {
|
||||
struct ResolvQuery *query;
|
||||
struct sockaddr_storage src_addr;
|
||||
buffer_t *buf;
|
||||
int addr_header_len;
|
||||
char addr_header[384];
|
||||
struct server_ctx *server_ctx;
|
||||
struct remote_ctx *remote_ctx;
|
||||
} query_ctx_t;
|
||||
#endif
|
||||
|
||||
typedef struct remote_ctx {
|
||||
ev_io io;
|
||||
ev_timer watcher;
|
||||
int af;
|
||||
int fd;
|
||||
int addr_header_len;
|
||||
char addr_header[384];
|
||||
struct sockaddr_storage src_addr;
|
||||
#ifdef MODULE_REMOTE
|
||||
struct sockaddr_storage dst_addr;
|
||||
#endif
|
||||
struct server_ctx *server_ctx;
|
||||
} remote_ctx_t;
|
||||
|
||||
#endif // _UDPRELAY_H
|
||||
1074
package/lean/shadowsocksr-libev/src/server/uthash.h
Normal file
1074
package/lean/shadowsocksr-libev/src/server/uthash.h
Normal file
File diff suppressed because it is too large
Load Diff
448
package/lean/shadowsocksr-libev/src/server/utils.c
Normal file
448
package/lean/shadowsocksr-libev/src/server/utils.c
Normal file
@ -0,0 +1,448 @@
|
||||
/*
|
||||
* utils.c - Misc utilities
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#ifndef __MINGW32__
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#define INT_DIGITS 19 /* enough for 64 bit integer */
|
||||
|
||||
#ifdef LIB_ONLY
|
||||
FILE *logfile;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SYSLOG
|
||||
int use_syslog = 0;
|
||||
#endif
|
||||
|
||||
#ifndef __MINGW32__
|
||||
void
|
||||
ERROR(const char *s)
|
||||
{
|
||||
char *msg = strerror(errno);
|
||||
LOGE("%s: %s", s, msg);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int use_tty = 1;
|
||||
|
||||
char *
|
||||
ss_itoa(int i)
|
||||
{
|
||||
/* Room for INT_DIGITS digits, - and '\0' */
|
||||
static char buf[INT_DIGITS + 2];
|
||||
char *p = buf + INT_DIGITS + 1; /* points to terminating '\0' */
|
||||
if (i >= 0) {
|
||||
do {
|
||||
*--p = '0' + (i % 10);
|
||||
i /= 10;
|
||||
} while (i != 0);
|
||||
return p;
|
||||
} else { /* i < 0 */
|
||||
do {
|
||||
*--p = '0' - (i % 10);
|
||||
i /= 10;
|
||||
} while (i != 0);
|
||||
*--p = '-';
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int
|
||||
ss_isnumeric(const char *s) {
|
||||
if (!s || !*s)
|
||||
return 0;
|
||||
while (isdigit(*s))
|
||||
++s;
|
||||
return *s == '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* setuid() and setgid() for a specified user.
|
||||
*/
|
||||
int
|
||||
run_as(const char *user)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
if (user[0]) {
|
||||
/* Convert user to a long integer if it is a non-negative number.
|
||||
* -1 means it is a user name. */
|
||||
long uid = -1;
|
||||
if (ss_isnumeric(user)) {
|
||||
errno = 0;
|
||||
char *endptr;
|
||||
uid = strtol(user, &endptr, 10);
|
||||
if (errno || endptr == user)
|
||||
uid = -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETPWNAM_R
|
||||
struct passwd pwdbuf, *pwd;
|
||||
memset(&pwdbuf, 0, sizeof(struct passwd));
|
||||
size_t buflen;
|
||||
int err;
|
||||
|
||||
for (buflen = 128;; buflen *= 2) {
|
||||
char buf[buflen]; /* variable length array */
|
||||
|
||||
/* Note that we use getpwnam_r() instead of getpwnam(),
|
||||
* which returns its result in a statically allocated buffer and
|
||||
* cannot be considered thread safe. */
|
||||
err = uid >= 0 ? getpwuid_r((uid_t)uid, &pwdbuf, buf, buflen, &pwd)
|
||||
: getpwnam_r(user, &pwdbuf, buf, buflen, &pwd);
|
||||
|
||||
if (err == 0 && pwd) {
|
||||
/* setgid first, because we may not be allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0) {
|
||||
LOGE(
|
||||
"Could not change group id to that of run_as user '%s': %s",
|
||||
pwd->pw_name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
|
||||
LOGE("Could not change supplementary groups for user '%s'.", pwd->pw_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setuid(pwd->pw_uid) != 0) {
|
||||
LOGE(
|
||||
"Could not change user id to that of run_as user '%s': %s",
|
||||
pwd->pw_name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
} else if (err != ERANGE) {
|
||||
if (err) {
|
||||
LOGE("run_as user '%s' could not be found: %s", user,
|
||||
strerror(err));
|
||||
} else {
|
||||
LOGE("run_as user '%s' could not be found.", user);
|
||||
}
|
||||
return 0;
|
||||
} else if (buflen >= 16 * 1024) {
|
||||
/* If getpwnam_r() seems defective, call it quits rather than
|
||||
* keep on allocating ever larger buffers until we crash. */
|
||||
LOGE(
|
||||
"getpwnam_r() requires more than %u bytes of buffer space.",
|
||||
(unsigned)buflen);
|
||||
return 0;
|
||||
}
|
||||
/* Else try again with larger buffer. */
|
||||
}
|
||||
#else
|
||||
/* No getpwnam_r() :-( We'll use getpwnam() and hope for the best. */
|
||||
struct passwd *pwd;
|
||||
|
||||
if (!(pwd = uid >=0 ? getpwuid((uid_t)uid) : getpwnam(user))) {
|
||||
LOGE("run_as user %s could not be found.", user);
|
||||
return 0;
|
||||
}
|
||||
/* setgid first, because we may not allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0) {
|
||||
LOGE("Could not change group id to that of run_as user '%s': %s",
|
||||
pwd->pw_name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
|
||||
LOGE("Could not change supplementary groups for user '%s'.", pwd->pw_name);
|
||||
return 0;
|
||||
}
|
||||
if (setuid(pwd->pw_uid) != 0) {
|
||||
LOGE("Could not change user id to that of run_as user '%s': %s",
|
||||
pwd->pw_name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // __MINGW32__
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *
|
||||
ss_strndup(const char *s, size_t n)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
char *ret;
|
||||
|
||||
if (len <= n) {
|
||||
return strdup(s);
|
||||
}
|
||||
|
||||
ret = ss_malloc(n + 1);
|
||||
strncpy(ret, s, n);
|
||||
ret[n] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
FATAL(const char *msg)
|
||||
{
|
||||
LOGE("%s", msg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void *
|
||||
ss_malloc(size_t size)
|
||||
{
|
||||
void *tmp = malloc(size);
|
||||
if (tmp == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void *
|
||||
ss_realloc(void *ptr, size_t new_size)
|
||||
{
|
||||
void *new = realloc(ptr, new_size);
|
||||
if (new == NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
printf("\n");
|
||||
printf("shadowsocks-libev %s with %s\n\n", VERSION, USING_CRYPTO);
|
||||
printf(
|
||||
" maintained by Max Lv <max.c.lv@gmail.com> and Linus Yang <laokongzi@gmail.com>\n\n");
|
||||
printf(" usage:\n\n");
|
||||
#ifdef MODULE_LOCAL
|
||||
printf(" ss-local\n");
|
||||
#elif MODULE_REMOTE
|
||||
printf(" ss-server\n");
|
||||
#elif MODULE_TUNNEL
|
||||
printf(" ss-tunnel\n");
|
||||
#elif MODULE_REDIR
|
||||
printf(" ss-redir\n");
|
||||
#elif MODULE_MANAGER
|
||||
printf(" ss-manager\n");
|
||||
#endif
|
||||
printf("\n");
|
||||
printf(
|
||||
" -s <server_host> Host name or IP address of your remote server.\n");
|
||||
printf(
|
||||
" -p <server_port> Port number of your remote server.\n");
|
||||
printf(
|
||||
" -l <local_port> Port number of your local server.\n");
|
||||
printf(
|
||||
" -k <password> Password of your remote server.\n");
|
||||
printf(
|
||||
" -m <encrypt_method> Encrypt method: table, rc4, rc4-md5,\n");
|
||||
printf(
|
||||
" aes-128-cfb, aes-192-cfb, aes-256-cfb,\n");
|
||||
printf(
|
||||
" aes-128-ctr, aes-192-ctr, aes-256-ctr,\n");
|
||||
printf(
|
||||
" bf-cfb, camellia-128-cfb, camellia-192-cfb,\n");
|
||||
printf(
|
||||
" camellia-256-cfb, cast5-cfb, des-cfb,\n");
|
||||
printf(
|
||||
" idea-cfb, rc2-cfb, seed-cfb, salsa20,\n");
|
||||
printf(
|
||||
" chacha20 and chacha20-ietf.\n");
|
||||
printf(
|
||||
" The default cipher is rc4-md5.\n");
|
||||
printf("\n");
|
||||
printf(
|
||||
" [-a <user>] Run as another user.\n");
|
||||
printf(
|
||||
" [-f <pid_file>] The file path to store pid.\n");
|
||||
printf(
|
||||
" [-t <timeout>] Socket timeout in seconds.\n");
|
||||
printf(
|
||||
" [-c <config_file>] The path to config file.\n");
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
printf(
|
||||
" [-n <number>] Max number of open files.\n");
|
||||
#endif
|
||||
#ifndef MODULE_REDIR
|
||||
printf(
|
||||
" [-i <interface>] Network interface to bind.\n");
|
||||
#endif
|
||||
printf(
|
||||
" [-b <local_address>] Local address to bind.\n");
|
||||
printf("\n");
|
||||
printf(
|
||||
" [-u] Enable UDP relay.\n");
|
||||
#ifdef MODULE_REDIR
|
||||
printf(
|
||||
" TPROXY is required in redir mode.\n");
|
||||
#endif
|
||||
printf(
|
||||
" [-U] Enable UDP relay and disable TCP relay.\n");
|
||||
printf(
|
||||
" [-A] Enable onetime authentication.\n");
|
||||
#ifdef MODULE_REMOTE
|
||||
printf(
|
||||
" [-6] Resovle hostname to IPv6 address first.\n");
|
||||
#endif
|
||||
printf("\n");
|
||||
#ifdef MODULE_TUNNEL
|
||||
printf(
|
||||
" [-L <addr>:<port>] Destination server address and port\n");
|
||||
printf(
|
||||
" for local port forwarding.\n");
|
||||
#endif
|
||||
#ifdef MODULE_REMOTE
|
||||
printf(
|
||||
" [-d <addr>] Name servers for internal DNS resolver.\n");
|
||||
#endif
|
||||
#if defined(MODULE_REMOTE) || defined(MODULE_LOCAL)
|
||||
printf(
|
||||
" [--fast-open] Enable TCP fast open.\n");
|
||||
printf(
|
||||
" with Linux kernel > 3.7.0.\n");
|
||||
printf(
|
||||
" [--acl <acl_file>] Path to ACL (Access Control List).\n");
|
||||
#endif
|
||||
#if defined(MODULE_REMOTE) || defined(MODULE_MANAGER)
|
||||
printf(
|
||||
" [--manager-address <addr>] UNIX domain socket address.\n");
|
||||
#endif
|
||||
#ifdef MODULE_MANAGER
|
||||
printf(
|
||||
" [--executable <path>] Path to the executable of ss-server.\n");
|
||||
#endif
|
||||
printf(
|
||||
" [--mtu <MTU>] MTU of your network interface.\n");
|
||||
#ifdef __linux__
|
||||
printf(
|
||||
" [--mptcp] Enable Multipath TCP on MPTCP Kernel.\n");
|
||||
#ifdef MODULE_REMOTE
|
||||
printf(
|
||||
" [--firewall] Setup firewall rules for auto blocking.\n");
|
||||
#endif
|
||||
#endif
|
||||
printf("\n");
|
||||
printf(
|
||||
" [-v] Verbose mode.\n");
|
||||
printf(
|
||||
" [-h, --help] Print this message.\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
daemonize(const char *path)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
/* Our process ID and Session ID */
|
||||
pid_t pid, sid;
|
||||
|
||||
/* Fork off the parent process */
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* If we got a good PID, then
|
||||
* we can exit the parent process. */
|
||||
if (pid > 0) {
|
||||
FILE *file = fopen(path, "w");
|
||||
if (file == NULL) {
|
||||
FATAL("Invalid pid file\n");
|
||||
}
|
||||
|
||||
fprintf(file, "%d", (int)pid);
|
||||
fclose(file);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Change the file mode mask */
|
||||
umask(0);
|
||||
|
||||
/* Open any logs here */
|
||||
|
||||
/* Create a new SID for the child process */
|
||||
sid = setsid();
|
||||
if (sid < 0) {
|
||||
/* Log the failure */
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Change the current working directory */
|
||||
if ((chdir("/")) < 0) {
|
||||
/* Log the failure */
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Close out the standard file descriptors */
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
int
|
||||
set_nofile(int nofile)
|
||||
{
|
||||
struct rlimit limit = { nofile, nofile }; /* set both soft and hard limit */
|
||||
|
||||
if (nofile <= 0) {
|
||||
FATAL("nofile must be greater than 0\n");
|
||||
}
|
||||
|
||||
if (setrlimit(RLIMIT_NOFILE, &limit) < 0) {
|
||||
if (errno == EPERM) {
|
||||
LOGE(
|
||||
"insufficient permission to change NOFILE, not starting as root?");
|
||||
return -1;
|
||||
} else if (errno == EINVAL) {
|
||||
LOGE("invalid nofile, decrease nofile and try again");
|
||||
return -1;
|
||||
} else {
|
||||
LOGE("setrlimit failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
232
package/lean/shadowsocksr-libev/src/server/utils.h
Normal file
232
package/lean/shadowsocksr-libev/src/server/utils.h
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* utils.h - Misc utilities
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
#define USING_CRYPTO OPENSSL_VERSION_TEXT
|
||||
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
#include <polarssl/version.h>
|
||||
#define USING_CRYPTO POLARSSL_VERSION_STRING_FULL
|
||||
|
||||
#elif defined(USE_CRYPTO_MBEDTLS)
|
||||
#include <mbedtls/version.h>
|
||||
#define USING_CRYPTO MBEDTLS_VERSION_STRING_FULL
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _UTILS_H
|
||||
#define _UTILS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#define PORTSTRLEN 16
|
||||
#define SS_ADDRSTRLEN (INET6_ADDRSTRLEN + PORTSTRLEN + 1)
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define USE_TTY()
|
||||
#define USE_SYSLOG(ident)
|
||||
#define LOGI(...) \
|
||||
((void)__android_log_print(ANDROID_LOG_DEBUG, "shadowsocks", \
|
||||
__VA_ARGS__))
|
||||
#define LOGE(...) \
|
||||
((void)__android_log_print(ANDROID_LOG_ERROR, "shadowsocks", \
|
||||
__VA_ARGS__))
|
||||
|
||||
#else
|
||||
|
||||
#define STR(x) # x
|
||||
#define TOSTR(x) STR(x)
|
||||
|
||||
#ifdef LIB_ONLY
|
||||
|
||||
extern FILE *logfile;
|
||||
|
||||
#define TIME_FORMAT "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
#define USE_TTY()
|
||||
|
||||
#define USE_SYSLOG(ident)
|
||||
|
||||
#define USE_LOGFILE(ident) \
|
||||
do { \
|
||||
if (ident != NULL) { logfile = fopen(ident, "w+"); } } \
|
||||
while (0)
|
||||
|
||||
#define CLOSE_LOGFILE \
|
||||
do { \
|
||||
if (logfile != NULL) { fclose(logfile); } } \
|
||||
while (0)
|
||||
|
||||
#define LOGI(format, ...) \
|
||||
do { \
|
||||
if (logfile != NULL) { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
fprintf(logfile, " %s INFO: " format "\n", timestr, ## __VA_ARGS__); \
|
||||
fflush(logfile); } \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define LOGE(format, ...) \
|
||||
do { \
|
||||
if (logfile != NULL) { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
fprintf(logfile, " %s ERROR: " format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
fflush(logfile); } \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#define TIME_FORMAT "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
#define USE_TTY()
|
||||
|
||||
#define USE_SYSLOG(ident)
|
||||
|
||||
#define LOGI(format, ...) \
|
||||
do { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
fprintf(stderr, " %s INFO: " format "\n", timestr, ## __VA_ARGS__); \
|
||||
fflush(stderr); } \
|
||||
while (0)
|
||||
|
||||
#define LOGE(format, ...) \
|
||||
do { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
fprintf(stderr, " %s ERROR: " format "\n", timestr, ## __VA_ARGS__); \
|
||||
fflush(stderr); } \
|
||||
while (0)
|
||||
|
||||
#else
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
extern int use_tty;
|
||||
#define USE_TTY() \
|
||||
do { \
|
||||
use_tty = isatty(STDERR_FILENO); \
|
||||
} while (0) \
|
||||
|
||||
#define HAS_SYSLOG
|
||||
extern int use_syslog;
|
||||
|
||||
#define TIME_FORMAT "%F %T"
|
||||
|
||||
#define USE_SYSLOG(ident) \
|
||||
do { \
|
||||
use_syslog = 1; \
|
||||
openlog((ident), LOG_CONS | LOG_PID, 0); } \
|
||||
while (0)
|
||||
|
||||
#define LOGI(format, ...) \
|
||||
do { \
|
||||
if (use_syslog) { \
|
||||
syslog(LOG_INFO, format, ## __VA_ARGS__); \
|
||||
} else { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
if (use_tty) { \
|
||||
fprintf(stderr, "\e[01;32m %s INFO: \e[0m" format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
} else { \
|
||||
fprintf(stderr, " %s INFO: " format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define LOGE(format, ...) \
|
||||
do { \
|
||||
if (use_syslog) { \
|
||||
syslog(LOG_ERR, format, ## __VA_ARGS__); \
|
||||
} else { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
if (use_tty) { \
|
||||
fprintf(stderr, "\e[01;35m %s ERROR: \e[0m" format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
} else { \
|
||||
fprintf(stderr, " %s ERROR: " format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
} \
|
||||
} } \
|
||||
while (0)
|
||||
|
||||
#endif
|
||||
/* _WIN32 */
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
|
||||
#ifdef ERROR
|
||||
#undef ERROR
|
||||
#endif
|
||||
#define ERROR(s) ss_error(s)
|
||||
|
||||
#else
|
||||
|
||||
void ERROR(const char *s);
|
||||
|
||||
#endif
|
||||
|
||||
char *ss_itoa(int i);
|
||||
int ss_isnumeric(const char *s);
|
||||
int run_as(const char *user);
|
||||
void FATAL(const char *msg);
|
||||
void usage(void);
|
||||
void daemonize(const char *path);
|
||||
char *ss_strndup(const char *s, size_t n);
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
int set_nofile(int nofile);
|
||||
#endif
|
||||
|
||||
void *ss_malloc(size_t size);
|
||||
void *ss_realloc(void *ptr, size_t new_size);
|
||||
|
||||
#define ss_free(ptr) \
|
||||
do { \
|
||||
free(ptr); \
|
||||
ptr = NULL; \
|
||||
} while (0)
|
||||
|
||||
#endif // _UTILS_H
|
||||
188
package/lean/shadowsocksr-libev/src/server/verify.c
Normal file
188
package/lean/shadowsocksr-libev/src/server/verify.c
Normal file
@ -0,0 +1,188 @@
|
||||
|
||||
#include "verify.h"
|
||||
|
||||
static int verify_simple_pack_unit_size = 2000;
|
||||
|
||||
typedef struct verify_simple_local_data {
|
||||
char * recv_buffer;
|
||||
int recv_buffer_size;
|
||||
}verify_simple_local_data;
|
||||
|
||||
void verify_simple_local_data_init(verify_simple_local_data* local) {
|
||||
local->recv_buffer = (char*)malloc(16384);
|
||||
local->recv_buffer_size = 0;
|
||||
}
|
||||
|
||||
obfs * verify_simple_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(verify_simple_local_data));
|
||||
verify_simple_local_data_init((verify_simple_local_data*)self->l_data);
|
||||
return self;
|
||||
}
|
||||
|
||||
void verify_simple_dispose(obfs *self) {
|
||||
verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
if (local->recv_buffer != NULL) {
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = NULL;
|
||||
}
|
||||
free(local);
|
||||
self->l_data = NULL;
|
||||
dispose_obfs(self);
|
||||
}
|
||||
|
||||
int verify_simple_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
|
||||
int out_size = rand_len + datalength + 6;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
outdata[2] = rand_len;
|
||||
memmove(outdata + rand_len + 2, data, datalength);
|
||||
fillcrc32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int verify_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
//verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 32);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
while ( len > verify_simple_pack_unit_size ) {
|
||||
pack_len = verify_simple_pack_data(data, verify_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += verify_simple_pack_unit_size;
|
||||
len -= verify_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = verify_simple_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int verify_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
int crc = crc32((unsigned char*)recv_buffer, length);
|
||||
if (crc != -1) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
int data_size = length - recv_buffer[2] - 6;
|
||||
memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int verify_simple_server_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
//verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 32);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
while ( len > verify_simple_pack_unit_size ) {
|
||||
pack_len = verify_simple_pack_data(data, verify_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += verify_simple_pack_unit_size;
|
||||
len -= verify_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = verify_simple_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int verify_simple_server_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
{
|
||||
LOGE("verify_simple: wrong buf length %d", local->recv_buffer_size + datalength);
|
||||
return -1;
|
||||
}
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
LOGE("verify_simple: wrong length %d", length);
|
||||
return -1;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
int crc = crc32((unsigned char*)recv_buffer, length);
|
||||
if (crc != -1) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
LOGE("verify_simple: wrong crc");
|
||||
return -1;
|
||||
}
|
||||
int data_size = length - recv_buffer[2] - 6;
|
||||
memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
19
package/lean/shadowsocksr-libev/src/server/verify.h
Normal file
19
package/lean/shadowsocksr-libev/src/server/verify.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* verify.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _VERIFY_H
|
||||
#define _VERIFY_H
|
||||
|
||||
obfs * verify_simple_new_obfs();
|
||||
void verify_simple_dispose(obfs *self);
|
||||
|
||||
int verify_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int verify_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
int verify_simple_server_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int verify_simple_server_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
#endif // _VERIFY_H
|
||||
Loading…
Reference in New Issue
Block a user