Merge remote-tracking branch 'remotes/origin/dev'

pull/32/merge
Apex Liu 2017-06-07 17:34:35 +08:00
commit a91abb3f02
17 changed files with 522 additions and 205 deletions

View File

@ -1,8 +1,7 @@
#!/bin/bash
PATH_ROOT=$(cd "$(dirname "$0")"; pwd)
PYEXEC=${PATH_ROOT}/external/linux/release/bin/python3.4
PYSTATIC=${PATH_ROOT}/external/linux/release/lib/libpython3.4m.a
function on_error()
{
@ -14,14 +13,34 @@ function on_error()
exit 1
}
if [ ! -f "${PYSTATIC}" ]; then
echo "python static not found, now build it..."
"${PATH_ROOT}/build/build-py-static.sh"
function build_linux
{
PYEXEC=${PATH_ROOT}/external/linux/release/bin/python3.4
PYSTATIC=${PATH_ROOT}/external/linux/release/lib/libpython3.4m.a
if [ ! -f "${PYSTATIC}" ]; then
on_error "can not build python static."
echo "python static not found, now build it..."
"${PATH_ROOT}/build/build-py-static.sh"
if [ ! -f "${PYSTATIC}" ]; then
on_error "can not build python static."
fi
fi
${PYEXEC} -B "${PATH_ROOT}/build/build.py" $@
}
function build_macos
{
python3 -B "${PATH_ROOT}/build/build.py" $@
}
SYSTEM=`uname -s`
if [ $SYSTEM = "Linux" ] ; then
build_linux
elif [ $SYSTEM = "Darwin" ] ; then
build_macos
else
echo "Unsupported platform."
fi
${PYEXEC} -B "${PATH_ROOT}/build/build.py" $@

View File

@ -514,11 +514,276 @@ class BuilderLinux(BuilderBase):
utils.remove(_path)
class BuilderMacOS(BuilderBase):
def __init__(self):
super().__init__()
def _init_path(self):
self.PATH_TMP = os.path.join(PATH_EXTERNAL, 'macos', 'tmp')
self.PATH_RELEASE = os.path.join(PATH_EXTERNAL, 'macos', 'release')
self.OPENSSL_PATH_SRC = os.path.join(self.PATH_TMP, 'openssl-{}'.format(env.ver_openssl))
self.LIBUV_PATH_SRC = os.path.join(self.PATH_TMP, 'libuv-{}'.format(env.ver_libuv))
self.MBEDTLS_PATH_SRC = os.path.join(self.PATH_TMP, 'mbedtls-mbedtls-{}'.format(env.ver_mbedtls))
self.LIBSSH_PATH_SRC = os.path.join(self.PATH_TMP, 'libssh-{}'.format(env.ver_libssh))
self.SQLITE_PATH_SRC = os.path.join(self.PATH_TMP, 'sqlite-autoconf-{}'.format(env.ver_sqlite))
self.JSONCPP_PATH_SRC = os.path.join(PATH_EXTERNAL, 'jsoncpp')
self.MONGOOSE_PATH_SRC = os.path.join(PATH_EXTERNAL, 'mongoose')
if not os.path.exists(self.PATH_TMP):
utils.makedirs(self.PATH_TMP)
def _build_jsoncpp(self, file_name):
cc.n('prepare jsoncpp source code...', end='')
if not os.path.exists(self.JSONCPP_PATH_SRC):
cc.v('')
os.system('unzip "{}/{}" -d "{}"'.format(PATH_DOWNLOAD, file_name, PATH_EXTERNAL))
os.rename(os.path.join(PATH_EXTERNAL, 'jsoncpp-{}'.format(env.ver_jsoncpp)), self.JSONCPP_PATH_SRC)
else:
cc.w('already exists, skip.')
def _build_mongoose(self, file_name):
cc.n('prepare mongoose source code...', end='')
if not os.path.exists(self.MONGOOSE_PATH_SRC):
cc.v('')
os.system('unzip "{}/{}" -d "{}"'.format(PATH_DOWNLOAD, file_name, PATH_EXTERNAL))
os.rename(os.path.join(PATH_EXTERNAL, 'mongoose-{}'.format(env.ver_mongoose)), self.MONGOOSE_PATH_SRC)
else:
cc.w('already exists, skip.')
def _build_openssl(self, file_name):
pass # we do not need build openssl anymore, because first time run build.sh we built Python, it include openssl.
# if not os.path.exists(self.OPENSSL_PATH_SRC):
# os.system('tar -zxvf "{}/{}" -C "{}"'.format(PATH_DOWNLOAD, file_name, self.PATH_TMP))
#
# cc.n('build openssl static...')
# if os.path.exists(os.path.join(self.PATH_RELEASE, 'lib', 'libssl.a')):
# cc.w('already exists, skip.')
# return
#
# old_p = os.getcwd()
# os.chdir(self.OPENSSL_PATH_SRC)
# #os.system('./config --prefix={} --openssldir={}/openssl no-zlib no-shared'.format(self.PATH_RELEASE, self.PATH_RELEASE))
# os.system('./config --prefix={} --openssldir={}/openssl -fPIC no-zlib no-shared'.format(self.PATH_RELEASE, self.PATH_RELEASE))
# os.system('make')
# os.system('make install')
# os.chdir(old_p)
def _build_libuv(self, file_name):
cc.w('build libuv...skip')
return
if not os.path.exists(self.LIBUV_PATH_SRC):
# os.system('tar -zxvf "{}/{}" -C "{}"'.format(PATH_DOWNLOAD, file_name, PATH_TMP))
os.system('unzip "{}/{}" -d "{}"'.format(PATH_DOWNLOAD, file_name, self.PATH_TMP))
cc.n('build libuv...', end='')
if os.path.exists(os.path.join(self.PATH_RELEASE, 'lib', 'libuv.a')):
cc.w('already exists, skip.')
return
cc.v('')
# we need following...
# apt-get install autoconf aptitude libtool gcc-c++
old_p = os.getcwd()
os.chdir(self.LIBUV_PATH_SRC)
os.system('sh autogen.sh')
os.system('./configure --prefix={} --with-pic'.format(self.PATH_RELEASE))
os.system('make')
os.system('make install')
os.chdir(old_p)
def _build_mbedtls(self, file_name):
if not os.path.exists(self.MBEDTLS_PATH_SRC):
# os.system('tar -zxvf "{}/{}" -C "{}"'.format(PATH_DOWNLOAD, file_name, PATH_TMP))
os.system('unzip "{}/{}" -d "{}"'.format(PATH_DOWNLOAD, file_name, self.PATH_TMP))
cc.n('build mbedtls...', end='')
if os.path.exists(os.path.join(self.PATH_RELEASE, 'lib', 'libmbedtls.a')):
cc.w('already exists, skip.')
return
cc.v('')
# fix the Makefile
mkfile = os.path.join(self.MBEDTLS_PATH_SRC, 'Makefile')
f = open(mkfile)
fl = f.readlines()
f.close()
fixed = False
for i in range(len(fl)):
x = fl[i].split('=')
if x[0] == 'DESTDIR':
fl[i] = 'DESTDIR={}\n'.format(self.PATH_RELEASE)
fixed = True
break
if not fixed:
cc.e('can not fix Makefile of mbedtls.')
return
f = open(mkfile, 'w')
f.writelines(fl)
f.close()
# # fix config.h
# mkfile = os.path.join(self.MBEDTLS_PATH_SRC, 'include', 'mbedtls', 'config.h')
# f = open(mkfile)
# fl = f.readlines()
# f.close()
#
# for i in range(len(fl)):
# if fl[i].find('#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED') >= 0:
# fl[i] = '//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED\n'
# elif fl[i].find('#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED') >= 0:
# fl[i] = '//#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED\n'
# elif fl[i].find('#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED') >= 0:
# fl[i] = '//#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED\n'
# elif fl[i].find('#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED') >= 0:
# fl[i] = '//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED\n'
# elif fl[i].find('#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED') >= 0:
# fl[i] = '//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED\n'
# elif fl[i].find('#define MBEDTLS_SELF_TEST') >= 0:
# fl[i] = '//#define MBEDTLS_SELF_TEST\n'
# elif fl[i].find('#define MBEDTLS_SSL_RENEGOTIATION') >= 0:
# fl[i] = '//#define MBEDTLS_SSL_RENEGOTIATION\n'
# elif fl[i].find('#define MBEDTLS_ECDH_C') >= 0:
# fl[i] = '//#define MBEDTLS_ECDH_C\n'
# elif fl[i].find('#define MBEDTLS_ECDSA_C') >= 0:
# fl[i] = '//#define MBEDTLS_ECDSA_C\n'
# elif fl[i].find('#define MBEDTLS_ECP_C') >= 0:
# fl[i] = '//#define MBEDTLS_ECP_C\n'
# elif fl[i].find('#define MBEDTLS_NET_C') >= 0:
# fl[i] = '//#define MBEDTLS_NET_C\n'
#
# elif fl[i].find('#define MBEDTLS_RSA_NO_CRT') >= 0:
# fl[i] = '#define MBEDTLS_RSA_NO_CRT\n'
# elif fl[i].find('#define MBEDTLS_SSL_PROTO_SSL3') >= 0:
# fl[i] = '#define MBEDTLS_SSL_PROTO_SSL3\n'
#
# f = open(mkfile, 'w')
# f.writelines(fl)
# f.close()
# fix source file
utils.ensure_file_exists(os.path.join(PATH_EXTERNAL, 'fix-external', 'mbedtls', 'include', 'mbedtls', 'config.h'))
utils.copy_file(os.path.join(PATH_EXTERNAL, 'fix-external', 'mbedtls', 'include', 'mbedtls'), os.path.join(self.MBEDTLS_PATH_SRC, 'include', 'mbedtls'), 'config.h')
utils.ensure_file_exists(os.path.join(PATH_EXTERNAL, 'fix-external', 'mbedtls', 'library', 'rsa.c'))
utils.copy_file(os.path.join(PATH_EXTERNAL, 'fix-external', 'mbedtls', 'library'), os.path.join(self.MBEDTLS_PATH_SRC, 'library'), 'rsa.c')
old_p = os.getcwd()
os.chdir(self.MBEDTLS_PATH_SRC)
os.system('make CFLAGS="-fPIC" lib')
os.system('make install')
os.chdir(old_p)
def _build_libssh(self, file_name):
if not os.path.exists(self.LIBSSH_PATH_SRC):
# os.system('tar -zxvf "{}/{}" -C "{}"'.format(PATH_DOWNLOAD, file_name, PATH_TMP))
os.system('unzip "{}/{}" -d "{}"'.format(PATH_DOWNLOAD, file_name, self.PATH_TMP))
# os.rename(os.path.join(self.PATH_TMP, 'master'), os.path.join(self.PATH_TMP, 'libssh-{}'.format(LIBSSH_VER)))
cc.n('build libssh...', end='')
if os.path.exists(os.path.join(self.PATH_RELEASE, 'lib', 'libssh.a')) and os.path.exists(os.path.join(self.PATH_RELEASE, 'lib', 'libssh_threads.a')):
cc.w('already exists, skip.')
return
cc.v('')
build_path = os.path.join(self.LIBSSH_PATH_SRC, 'build')
# utils.makedirs(build_path)
# here is a bug in cmake v2.8.11 (default on ubuntu14), in FindOpenSSL.cmake,
# it parse opensslv.h, use regex like this:
# REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
# but in openssl-1.0.2h, the version define line is:
# # define OPENSSL_VERSION_NUMBER 0x1000208fL
# notice there is a space char between # and define, so find openssl always fail.
# old_p = os.getcwd()
# os.chdir(build_path)
# cmd = 'cmake' \
# ' -DCMAKE_INSTALL_PREFIX={}' \
# ' -D_OPENSSL_VERSION={}' \
# ' -DOPENSSL_INCLUDE_DIR={}/include' \
# ' -DOPENSSL_LIBRARIES={}/lib' \
# ' -DCMAKE_BUILD_TYPE=Release' \
# ' -DWITH_GSSAPI=OFF' \
# ' -DWITH_ZLIB=OFF' \
# ' -DWITH_STATIC_LIB=ON' \
# ' -DWITH_PCAP=OFF' \
# ' -DWITH_EXAMPLES=OFF' \
# ' -DWITH_NACL=OFF' \
# ' ..'.format(self.PATH_RELEASE, OPENSSL_VER, self.PATH_RELEASE, self.PATH_RELEASE)
# cc.n(cmd)
# os.system(cmd)
# # os.system('make ssh_static ssh_threads_static')
# os.system('make ssh_static')
# # os.system('make install')
# os.chdir(old_p)
cmake_define = ' -DCMAKE_INSTALL_PREFIX={}' \
' -D_OPENSSL_VERSION={}' \
' -DOPENSSL_INCLUDE_DIR={}/include' \
' -DOPENSSL_LIBRARIES={}/lib' \
' -DWITH_GSSAPI=OFF' \
' -DWITH_ZLIB=OFF' \
' -DWITH_STATIC_LIB=ON' \
' -DWITH_PCAP=OFF' \
' -DWITH_TESTING=OFF' \
' -DWITH_CLIENT_TESTING=OFF' \
' -DWITH_EXAMPLES=OFF' \
' -DWITH_BENCHMARKS=OFF' \
' -DWITH_NACL=OFF' \
' ..'.format(self.PATH_RELEASE, env.ver_openssl_number, self.PATH_RELEASE, self.PATH_RELEASE)
try:
utils.cmake(build_path, 'Release', False, cmake_define)
except:
pass
# because make install will fail because we can not disable ssh_shared target,
# so we copy necessary files ourselves.
utils.ensure_file_exists(os.path.join(self.LIBSSH_PATH_SRC, 'build', 'src', 'libssh.a'))
utils.ensure_file_exists(os.path.join(self.LIBSSH_PATH_SRC, 'build', 'src', 'threads', 'libssh_threads.a'))
utils.copy_file(os.path.join(self.LIBSSH_PATH_SRC, 'build', 'src'), os.path.join(self.PATH_RELEASE, 'lib'), 'libssh.a')
utils.copy_file(os.path.join(self.LIBSSH_PATH_SRC, 'build', 'src', 'threads'), os.path.join(self.PATH_RELEASE, 'lib'), 'libssh_threads.a')
utils.copy_ex(os.path.join(self.LIBSSH_PATH_SRC, 'include'), os.path.join(self.PATH_RELEASE, 'include'), 'libssh')
def _build_sqlite(self, file_name):
if not os.path.exists(self.SQLITE_PATH_SRC):
os.system('tar -zxvf "{}/{}" -C "{}"'.format(PATH_DOWNLOAD, file_name, self.PATH_TMP))
cc.n('build sqlite static...', end='')
if os.path.exists(os.path.join(self.PATH_RELEASE, 'lib', 'libsqlite3.a')):
cc.w('already exists, skip.')
return
cc.v('')
old_p = os.getcwd()
os.chdir(self.SQLITE_PATH_SRC)
os.system('./configure --prefix={}'.format(self.PATH_RELEASE))
os.system('make')
os.system('make install')
os.chdir(old_p)
def fix_output(self):
# remove .so files, otherwise will link to .so but not .a in default.
# rm = ['libsqlite3.la', 'libsqlite3.so.0', 'libsqlite3.so', 'libsqlite3.so.0.8.6', 'libuv.la', 'libuv.so.1', 'libuv.so', 'libuv.so.1.0.0']
rm = ['libuv.la', 'libuv.so.1', 'libuv.so', 'libuv.so.1.0.0']
for i in rm:
_path = os.path.join(self.PATH_RELEASE, 'lib', i)
if os.path.exists(_path):
utils.remove(_path)
def gen_builder(dist):
if dist == 'windows':
builder = BuilderWin()
elif dist == 'linux':
builder = BuilderLinux()
elif dist == 'macos':
builder = BuilderMacOS()
else:
raise RuntimeError('unsupported platform.')

View File

@ -1,3 +1,3 @@
# -*- coding: utf8 -*-
VER_TELEPORT_SERVER = "2.2.9.3"
VER_TELEPORT_SERVER = "2.2.10.1"
VER_TELEPORT_ASSIST = "2.2.6.1"

View File

@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />
<module classpath="CMake" type="CPP_MODULE" version="4" />

Binary file not shown.

View File

@ -1,6 +1,6 @@
#ifndef __TS_SERVER_VER_H__
#define __TS_SERVER_VER_H__
#define TP_SERVER_VER L"2.2.9.3"
#define TP_SERVER_VER L"2.2.10.1"
#endif // __TS_SERVER_VER_H__

View File

@ -249,7 +249,8 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user,
// 因为是从sftp会话得来的登录数据因此限制本会话只能用于sftp不允许再使用shell了。
_this->_enter_sftp_mode();
} else {
}
else {
_this->m_server_ip = sess_info->host_ip;
_this->m_server_port = sess_info->host_port;
_this->m_auth_mode = sess_info->auth_mode;
@ -284,20 +285,20 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user,
int port = (int)_this->m_server_port;
ssh_options_set(_this->m_srv_session, SSH_OPTIONS_PORT, &port);
#ifdef EX_DEBUG
// int flag = SSH_LOG_FUNCTIONS;
// ssh_options_set(_this->m_srv_session, SSH_OPTIONS_LOG_VERBOSITY, &flag);
// int flag = SSH_LOG_FUNCTIONS;
// ssh_options_set(_this->m_srv_session, SSH_OPTIONS_LOG_VERBOSITY, &flag);
#endif
if (_this->m_auth_mode != TS_AUTH_MODE_NONE)
ssh_options_set(_this->m_srv_session, SSH_OPTIONS_USER, _this->m_user_name.c_str());
#ifdef EX_DEBUG
// int _timeout_us = 500000000; // 5 sec.
// ssh_options_set(_this->m_srv_session, SSH_OPTIONS_TIMEOUT_USEC, &_timeout_us);
#else
int _timeout_us = 10000000; // 10 sec.
ssh_options_set(_this->m_srv_session, SSH_OPTIONS_TIMEOUT_USEC, &_timeout_us);
#endif
//#ifdef EX_DEBUG
// // int _timeout_us = 500000000; // 5 sec.
// // ssh_options_set(_this->m_srv_session, SSH_OPTIONS_TIMEOUT_USEC, &_timeout_us);
//#else
// int _timeout_us = 10000000; // 10 sec.
// ssh_options_set(_this->m_srv_session, SSH_OPTIONS_TIMEOUT_USEC, &_timeout_us);
//#endif
int rc = 0;
rc = ssh_connect(_this->m_srv_session);
@ -308,119 +309,127 @@ int SshSession::_on_auth_password_request(ssh_session session, const char *user,
return SSH_AUTH_ERROR;
}
// 检查服务端支持的认证协议
ssh_userauth_none(_this->m_srv_session, NULL);
int auth_methods = ssh_userauth_list(_this->m_srv_session, NULL);
// // 检查服务端支持的认证协议
// rc = ssh_userauth_none(_this->m_srv_session, NULL);
// if (rc == SSH_AUTH_ERROR) {
// EXLOGE("[ssh] invalid password for password mode to login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port);
// _this->m_have_error = true;
// _this->m_retcode = SESS_STAT_ERR_AUTH_DENIED;
// return SSH_AUTH_ERROR;
// }
// // int auth_methods = ssh_userauth_list(_this->m_srv_session, NULL);
// const char* banner = ssh_get_issue_banner(_this->m_srv_session);
// if (NULL != banner) {
// EXLOGE("[ssh] issue banner: %s\n", banner);
// }
if (_this->m_auth_mode == TS_AUTH_MODE_PASSWORD) {
if (auth_methods & SSH_AUTH_METHOD_PASSWORD) {
rc = ssh_userauth_password(_this->m_srv_session, NULL, _this->m_user_auth.c_str());
if (rc != SSH_AUTH_SUCCESS) {
EXLOGE("[ssh] invalid password for password mode to login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port);
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_AUTH_DENIED;
return SSH_AUTH_DENIED;
// 优先尝试交互式登录SSHv2推荐
rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL);
while(rc == SSH_AUTH_INFO) {
int nprompts = ssh_userauth_kbdint_getnprompts(_this->m_srv_session);
if(0 == nprompts) {
rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL);
continue;
}
}
else if (auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
bool is_login = false;
for (;;) {
rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL);
if (rc != SSH_AUTH_INFO)
break;
if(ssh_userauth_kbdint_getnprompts(_this->m_srv_session) != 1)
break;
for (int iprompt = 0; iprompt < nprompts; ++iprompt) {
char echo = 0;
const char* prompt = ssh_userauth_kbdint_getprompt(_this->m_srv_session, iprompt, &echo);
EXLOGV("[ssh] interactive login prompt: %s\n", prompt);
rc = ssh_userauth_kbdint_setanswer(_this->m_srv_session, 0, _this->m_user_auth.c_str());
if (rc < 0)
break;
// 有时候服务端会再发一个空的提示来完成交互
rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL);
if (rc == SSH_AUTH_INFO) {
if (ssh_userauth_kbdint_getnprompts(_this->m_srv_session) != 0)
break;
rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL);
if (rc < 0)
break;
rc = ssh_userauth_kbdint_setanswer(_this->m_srv_session, iprompt, _this->m_user_auth.c_str());
if (rc < 0) {
EXLOGE("[ssh] invalid password for interactive mode to login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port);
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_AUTH_DENIED;
return SSH_AUTH_ERROR;
}
if(rc == SSH_AUTH_SUCCESS)
is_login = true;
break;
}
if (!is_login) {
EXLOGE("[ssh] invalid password for keyboard-interactive mode to login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port);
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_AUTH_DENIED;
return SSH_AUTH_DENIED;
}
rc = ssh_userauth_kbdint(_this->m_srv_session, NULL, NULL);
}
if (rc == SSH_AUTH_SUCCESS) {
EXLOGW("[ssh] logon with keyboard interactive mode.\n");
_this->m_is_logon = true;
return SSH_AUTH_SUCCESS;
}
else {
EXLOGE("[ssh] real SSH server [%s:%d] does not support password or keyboard-interactive login.\n", _this->m_server_ip.c_str(), _this->m_server_port);
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_AUTH_DENIED;
return SSH_AUTH_DENIED;
EXLOGD("[ssh] failed to login with keyboard interactive mode, got %d, try password mode.\n", rc);
}
// 不支持交互式登录,则尝试密码方式
rc = ssh_userauth_password(_this->m_srv_session, NULL, _this->m_user_auth.c_str());
if (rc == SSH_AUTH_SUCCESS) {
EXLOGW("[ssh] logon with password mode.\n");
_this->m_is_logon = true;
return SSH_AUTH_SUCCESS;
}
else {
EXLOGD("[ssh] failed to login with password mode, got %d.\n", rc);
}
EXLOGE("[ssh] can not use password mode or interactive mode ot login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port);
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_AUTH_DENIED;
return SSH_AUTH_ERROR;
}
else if (_this->m_auth_mode == TS_AUTH_MODE_PRIVATE_KEY) {
if (auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
ssh_key key = NULL;
if (SSH_OK != ssh_pki_import_privkey_base64(_this->m_user_auth.c_str(), NULL, NULL, NULL, &key)) {
EXLOGE("[ssh] can not import private-key for auth.\n");
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_BAD_SSH_KEY;
return SSH_AUTH_DENIED;
}
ssh_key key = NULL;
if (SSH_OK != ssh_pki_import_privkey_base64(_this->m_user_auth.c_str(), NULL, NULL, NULL, &key)) {
EXLOGE("[ssh] can not import private-key for auth.\n");
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_BAD_SSH_KEY;
return SSH_AUTH_ERROR;
}
rc = ssh_userauth_publickey(_this->m_srv_session, NULL, key);
if (rc != SSH_OK) {
ssh_key_free(key);
EXLOGE("[ssh] invalid private-key for login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port);
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_AUTH_DENIED;
return SSH_AUTH_DENIED;
}
rc = ssh_userauth_publickey(_this->m_srv_session, NULL, key);
ssh_key_free(key);
ssh_key_free(key);
if (rc == SSH_AUTH_SUCCESS) {
EXLOGW("[ssh] logon with public-key mode.\n");
_this->m_is_logon = true;
return SSH_AUTH_SUCCESS;
}
else {
EXLOGE("[ssh] real SSH server [%s:%d] does not support public key login.\n", _this->m_server_ip.c_str(), _this->m_server_port);
EXLOGE("[ssh] failed to use private-key to login to real SSH server %s:%d.\n", _this->m_server_ip.c_str(), _this->m_server_port);
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_AUTH_DENIED;
return SSH_AUTH_DENIED;
return SSH_AUTH_ERROR;
}
}
else if (_this->m_auth_mode == TS_AUTH_MODE_NONE)
{
// do nothing.
return SSH_AUTH_DENIED;
else if (_this->m_auth_mode == TS_AUTH_MODE_NONE) {
return SSH_AUTH_ERROR;
}
else {
EXLOGE("[ssh] invalid auth mode.\n");
_this->m_have_error = true;
_this->m_retcode = SESS_STAT_ERR_AUTH_DENIED;
return SSH_AUTH_DENIED;
return SSH_AUTH_ERROR;
}
_this->m_is_logon = true;
return SSH_AUTH_SUCCESS;
}
ssh_channel SshSession::_on_new_channel_request(ssh_session session, void *userdata) {
// 客户端尝试打开一个通道(然后才能通过这个通道发控制命令或者收发数据)
EXLOGV("[ssh] allocated session channel\n");
EXLOGV("[ssh] client open channel\n");
SshSession *_this = (SshSession *)userdata;
ssh_channel cli_channel = ssh_channel_new(session);
if(cli_channel == NULL) {
EXLOGE("[ssh] can not create channel for client.\n");
return NULL;
}
ssh_set_channel_callbacks(cli_channel, &_this->m_cli_channel_cb);
// 我们也要向真正的服务器申请打开一个通道,来进行转发
ssh_channel srv_channel = ssh_channel_new(_this->m_srv_session);
if(srv_channel == NULL) {
EXLOGE("[ssh] can not create channel for server.\n");
return NULL;
}
if (ssh_channel_open_session(srv_channel)) {
EXLOGE("[ssh] error opening channel to real server: %s\n", ssh_get_error(session));
ssh_channel_free(cli_channel);
@ -443,6 +452,7 @@ ssh_channel SshSession::_on_new_channel_request(ssh_session session, void *userd
_this->m_channel_srv_cli.insert(std::make_pair(srv_channel, cli_info));
}
EXLOGD("[ssh] channel for client and server created.\n");
return cli_channel;
}
@ -757,7 +767,7 @@ void SshSession::_process_sftp_command(const ex_u8* data, int len) {
m_rec.record_command("SFTP INITIALIZE\r\n");
return;
}
// 需要的数据至少14字节
// uint32 + byte + uint32 + (uint32 + char + ...)
// pkg_len + cmd + req_id + string( length + content...)
@ -766,22 +776,22 @@ void SshSession::_process_sftp_command(const ex_u8* data, int len) {
ex_u8* str1_ptr = (ex_u8*)data + 9;
int str1_len = (int)((str1_ptr[0] << 24) | (str1_ptr[1] << 16) | (str1_ptr[2] << 8) | str1_ptr[3]);
// if (str1_len + 9 != pkg_len)
// return;
// if (str1_len + 9 != pkg_len)
// return;
ex_u8* str2_ptr = NULL;// (ex_u8*)data + 13;
int str2_len = 0;// (int)((data[9] << 24) | (data[10] << 16) | (data[11] << 8) | data[12]);
const char* act = NULL;
switch (sftp_cmd) {
case 0x03:
// 0x03 = 3 = SSH_FXP_OPEN
act = "open file";
break;
// case 0x0b:
// // 0x0b = 11 = SSH_FXP_OPENDIR
// act = "open dir";
// break;
// case 0x0b:
// // 0x0b = 11 = SSH_FXP_OPENDIR
// act = "open dir";
// break;
case 0x0d:
// 0x0d = 13 = SSH_FXP_REMOVE
act = "remove file";
@ -856,17 +866,8 @@ int SshSession::_on_client_shell_request(ssh_session session, ssh_channel channe
SshSession *_this = (SshSession *)userdata;
if (_this->m_is_sftp) {
EXLOGE("[ssh] try to request shell on a sftp-session.\n");
// char buf[2048] = { 0 };
// snprintf(buf, sizeof(buf),
// "\r\n\r\n"\
// "!! ERROR !!\r\n"\
// "Session-ID '%s' has been used for SFTP.\r\n"\
// "\r\n", _this->m_sid.c_str()
// );
// ssh_channel_write(channel, buf, strlen(buf));
//
return 1;
EXLOGE("[ssh] request shell on a sftp-session is denied.\n");
return SSH_ERROR;
}
EXLOGD("[ssh] client request shell\n");
@ -874,17 +875,20 @@ int SshSession::_on_client_shell_request(ssh_session session, ssh_channel channe
TS_SSH_CHANNEL_INFO *srv_info = _this->_get_srv_channel(channel);
if (NULL == srv_info || NULL == srv_info->channel) {
EXLOGE("[ssh] when client request shell, not found server channel.\n");
return 1;
return SSH_ERROR;
}
srv_info->type = TS_SSH_CHANNEL_TYPE_SHELL;
TS_SSH_CHANNEL_INFO *cli_info = _this->_get_cli_channel(srv_info->channel);
if (NULL == cli_info || NULL == cli_info->channel) {
EXLOGE("[ssh] when client request shell, not found client channel.\n");
return 1;
return SSH_ERROR;
}
cli_info->type = TS_SSH_CHANNEL_TYPE_SHELL;
// FIXME: if client is putty, it will block here. the following function will never return.
// at this time, can not write data to this channel. read from this channel with timeout, got 0 byte.
// I have no idea how to fix it... :(
return ssh_channel_request_shell(srv_info->channel);
}
@ -1109,12 +1113,8 @@ int SshSession::_on_server_channel_data(ssh_session session, ssh_channel channel
" - authroized by %s\r\n"\
"=============================================\r\n"\
"\r\n",
// \
// "\033]0;tpssh://%s\007\r\n",
_this->m_server_ip.c_str(),
_this->m_server_port, auth_mode
// ,
// _this->m_server_ip.c_str()
);
int buf_len = strlen(buf);
@ -1123,11 +1123,7 @@ int SshSession::_on_server_channel_data(ssh_session session, ssh_channel channel
memcpy(&_data[0], buf, buf_len);
memcpy(&_data[buf_len], data, len);
// 注意,这里虽然可以改变窗口(或者标签页)的标题,但是因为这是服务端发回的第一个包,后面服务端可能还会发类似的包(仅一次)来改变标题
// 导致窗口标题又被改变,因此理论上应该解析服务端发回的包,如果包含上述格式的,需要替换一次。
//_write(info->channel, buf, strlen(buf));
ret = ssh_channel_write(info->channel, &_data[0], _data.size());
//EXLOGD("--- first send to client : %d %d %d\n", _data.size(), ret, len);
_this->m_recving_from_srv = false;
return len;
@ -1135,7 +1131,7 @@ int SshSession::_on_server_channel_data(ssh_session session, ssh_channel channel
}
#endif
if(is_stderr)
if (is_stderr)
ret = ssh_channel_write_stderr(info->channel, data, len);
else
ret = ssh_channel_write(info->channel, data, len);
@ -1143,8 +1139,6 @@ int SshSession::_on_server_channel_data(ssh_session session, ssh_channel channel
EXLOGE("[ssh] send data(%dB) to client failed (2). [%d][%s][%s]\n", len, ret, ssh_get_error(_this->m_cli_session), ssh_get_error(_this->m_cli_session));
}
//EXLOGD("--- send to client: %d %d\n", ret, len);
_this->m_recving_from_srv = false;
return ret;
}

Binary file not shown.

View File

@ -1,6 +1,6 @@
#ifndef __TS_SERVER_VER_H__
#define __TS_SERVER_VER_H__
#define TP_SERVER_VER L"2.2.9.3"
#define TP_SERVER_VER L"2.2.10.1"
#endif // __TS_SERVER_VER_H__

View File

@ -119,12 +119,9 @@ class WebServerCore:
# 启动session超时管理
web_session().start()
# 启动数据库定时事务例如MySQL防丢失连接
get_db().start_keep_alive()
tornado.ioloop.IOLoop.instance().start()
get_db().stop_keep_alive()
web_session().stop()
return 0

View File

@ -25,7 +25,7 @@ def create_and_init(db, step_begin, step_end):
`account_status` int(11) DEFAULT 0,
`account_lock` int(11) DEFAULT 0,
`account_desc` varchar(255),
`oath_secret` varchar(64),
`oath_secret` varchar(64)
);""".format(db.table_prefix, db.auto_increment))
_db_exec(db, step_begin, step_end, '创建表 auth', """CREATE TABLE `{}auth`(

View File

@ -46,10 +46,6 @@ class TPDatabase:
self._table_prefix = ''
self._conn_pool = None
self._stop_flag = False
self._thread_keep_alive_handle = None
self._thread_keep_alive_cond = threading.Condition()
@property
def table_prefix(self):
return self._table_prefix
@ -95,30 +91,6 @@ class TPDatabase:
return True
def start_keep_alive(self):
self._thread_keep_alive_handle = threading.Thread(target=self._thread_keep_alive)
self._thread_keep_alive_handle.start()
def stop_keep_alive(self):
self._stop_flag = True
self._thread_keep_alive_cond.acquire()
self._thread_keep_alive_cond.notify()
self._thread_keep_alive_cond.release()
if self._thread_keep_alive_handle is not None:
self._thread_keep_alive_handle.join()
log.v('database-keep-alive-thread stopped.\n')
def _thread_keep_alive(self):
while True:
self._thread_keep_alive_cond.acquire()
# 每一小时醒来执行一次查询,避免连接丢失
self._thread_keep_alive_cond.wait(3600)
self._thread_keep_alive_cond.release()
if self._stop_flag:
break
self.query('SELECT `value` FROM `{}config` WHERE `name`="db_ver";'.format(self._table_prefix))
def _init_sqlite(self, db_file):
self.db_type = self.DB_TYPE_SQLITE
self.auto_increment = 'AUTOINCREMENT'
@ -179,13 +151,15 @@ class TPDatabase:
def is_field_exists(self, table_name, field_name):
if self.db_type == self.DB_TYPE_SQLITE:
ret = self.query('PRAGMA table_info(`{}`);'.format(table_name))
print(ret)
if ret is None:
return None
if len(ret) == 0:
return False
else:
return True
for f in ret:
if f[1] == field_name:
return True
return False
elif self.db_type == self.DB_TYPE_MYSQL:
ret = self.query('DESC `{}` `{}`;'.format(table_name, field_name))
print(ret)
@ -460,51 +434,118 @@ class TPMysqlPool(TPDatabasePool):
autocommit=False,
connect_timeout=3.0,
charset='utf8')
except pymysql.err.OperationalError as e:
errno, _ = e.args
if 2003 == errno:
log.e('[mysql] connect [{}:{}] failed: {}\n'.format(self._host, self._port, e.__str__()))
return None
except Exception as e:
log.e('[mysql] connect [{}:{}] failed: {}\n'.format(self._host, self._port, e.__str__()))
return None
def _do_query(self, conn, sql):
cursor = conn.cursor()
try:
cursor.execute(sql)
db_ret = cursor.fetchall()
conn.commit()
return db_ret
except Exception as e:
log.v('[mysql] SQL={}\n'.format(sql))
log.e('[mysql] _do_query() failed: {}\n'.format(e.__str__()))
return None
finally:
cursor.close()
for retry in range(2):
cursor = conn.cursor()
try:
cursor.execute(sql)
db_ret = cursor.fetchall()
conn.commit()
return db_ret
except pymysql.err.OperationalError as e:
errno, _ = e.args
if retry == 1 or errno not in [2006, 2013]:
log.v('[mysql] SQL={}\n'.format(sql))
log.e('[mysql] _do_query() failed: {}\n'.format(e.__str__()))
return None
log.w('[mysql] lost connection, reconnect.\n')
with self._locker:
thread_id = threading.get_ident()
if thread_id not in self._connections:
log.e('[mysql] database pool internal error.\n')
return None
_conn = self._do_connect()
if _conn is not None:
self._connections[thread_id] = _conn
conn = _conn
else:
return None
except Exception as e:
log.v('[mysql] SQL={}\n'.format(sql))
log.e('[mysql] _do_query() failed: {}\n'.format(e.__str__()))
return None
finally:
cursor.close()
def _do_exec(self, conn, sql):
cursor = conn.cursor()
try:
cursor.execute(sql)
conn.commit()
return True
except Exception as e:
log.e('[mysql] _do_exec() failed: {}\n'.format(e.__str__()))
log.e('[mysql] SQL={}'.format(sql))
return None
finally:
cursor.close()
for retry in range(2):
cursor = conn.cursor()
try:
cursor.execute(sql)
conn.commit()
return True
except pymysql.err.OperationalError as e:
errno, _ = e.args
if retry == 1 or errno not in [2006, 2013]:
log.v('[mysql] SQL={}\n'.format(sql))
log.e('[mysql] _do_exec() failed: {}\n'.format(e.__str__()))
return None
log.w('[mysql] lost connection, reconnect.\n')
with self._locker:
thread_id = threading.get_ident()
if thread_id not in self._connections:
log.e('[mysql] database pool internal error.\n')
return None
_conn = self._do_connect()
if _conn is not None:
self._connections[thread_id] = _conn
conn = _conn
else:
return None
except Exception as e:
log.e('[mysql] _do_exec() failed: {}\n'.format(e.__str__()))
log.e('[mysql] SQL={}'.format(sql))
return None
finally:
cursor.close()
def _do_transaction(self, conn, sql_list):
cursor = conn.cursor()
try:
conn.begin()
for sql in sql_list:
cursor.execute(sql)
conn.commit()
return True
except Exception as e:
conn.rollback()
log.e('[mysql] _do_transaction() failed: {}\n'.format(e.__str__()))
return False
finally:
cursor.close()
for retry in range(2):
cursor = conn.cursor()
try:
conn.begin()
for sql in sql_list:
cursor.execute(sql)
conn.commit()
return True
except pymysql.err.OperationalError as e:
errno, _ = e.args
if retry == 1 or errno not in [2006, 2013]:
log.v('[mysql] SQL={}\n'.format(sql))
log.e('[mysql] _do_transaction() failed: {}\n'.format(e.__str__()))
return False
log.w('[mysql] lost connection, reconnect.\n')
with self._locker:
thread_id = threading.get_ident()
if thread_id not in self._connections:
log.e('[mysql] database pool internal error.\n')
return False
_conn = self._do_connect()
if _conn is not None:
self._connections[thread_id] = _conn
conn = _conn
else:
return False
except Exception as e:
conn.rollback()
log.e('[mysql] _do_transaction() failed: {}\n'.format(e.__str__()))
return False
finally:
cursor.close()
def _last_insert_id(self, conn):
cursor = conn.cursor()

View File

@ -193,7 +193,6 @@ class OathVerifyHandler(TPBaseUserAuthJsonHandler):
class OathSecretQrCodeHandler(TPBaseUserAuthJsonHandler):
def get(self):
secret = self.get_session('tmp_oath_secret', None)
print('tmp-oath-secret:', secret)
user_info = self.get_current_user()
img_data = gen_oath_qrcode(user_info['name'], secret)

View File

@ -6,7 +6,7 @@ from eom_app.app.configs import app_cfg
from eom_app.module import host
from eom_app.module import user
from eom_common.eomcore.logger import *
from .base import TPBaseUserAuthJsonHandler, TPBaseAdminAuthHandler, TPBaseAdminAuthJsonHandler
from .base import TPBaseUserAuthHandler, TPBaseUserAuthJsonHandler, TPBaseAdminAuthHandler, TPBaseAdminAuthJsonHandler
cfg = app_cfg()
@ -16,7 +16,7 @@ class IndexHandler(TPBaseAdminAuthHandler):
self.render('user/index.mako')
class PersonalHandler(TPBaseAdminAuthHandler):
class PersonalHandler(TPBaseUserAuthHandler):
def get(self):
user_info = self.get_current_user()
self.render('user/personal.mako', user=user_info)

View File

@ -61,7 +61,9 @@ def verify_oath(user_id, oath_code):
if len(db_ret) != 1:
return False
oath_secret = db_ret[0][0]
oath_secret = str(db_ret[0][0]).strip()
if 0 == len(oath_secret):
return False
return verify_oath_code(oath_secret, oath_code)

View File

@ -1,4 +1,4 @@
# -*- coding: utf8 -*-
TS_VER = "2.2.9.3"
TS_VER = "2.2.10.1"
TP_ASSIST_LAST_VER = "2.2.6.1"
TP_ASSIST_REQUIRE = "2.0.0.1"

View File

@ -14,6 +14,6 @@ Build 构建号。构建号用于表明此版本发布之前进行了多少
TELEPORT_SERVER 2.2.9.3
TELEPORT_SERVER 2.2.10.1
TELEPORT_ASSIST 2.2.6.1
TELEPORT_ASSIST_REQUIRE 2.0.0.1