Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
C
coco
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
coco
Commits
da2bd7cd
Unverified
Commit
da2bd7cd
authored
6 years ago
by
老广
Committed by
GitHub
6 years ago
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #71 from jumpserver/dev
Dev
parents
a518b9a7
c31b22d4
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
371 additions
and
29 deletions
+371
-29
app.py
coco/app.py
+1
-1
connection.py
coco/connection.py
+140
-2
httpd.py
coco/httpd.py
+18
-13
interactive.py
coco/interactive.py
+1
-1
models.py
coco/models.py
+171
-0
proxy.py
coco/proxy.py
+35
-8
session.py
coco/session.py
+3
-2
requirements.txt
requirements/requirements.txt
+2
-2
No files found.
coco/app.py
View file @
da2bd7cd
...
...
@@ -25,7 +25,7 @@ from .utils import get_logger, register_app, register_service
eventlet
.
monkey_patch
()
hub_prevent_multiple_readers
(
False
)
__version__
=
'1.3.
2
'
__version__
=
'1.3.
3
'
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
dirname
(
__file__
))
logger
=
get_logger
(
__file__
)
...
...
This diff is collapsed.
Click to expand it.
coco/connection.py
View file @
da2bd7cd
...
...
@@ -2,16 +2,22 @@
#
import
os
import
re
import
socket
import
selectors
import
telnetlib
import
paramiko
from
paramiko.ssh_exception
import
SSHException
from
.ctx
import
app_service
from
.utils
import
get_logger
,
get_private_key_fingerprint
from
.utils
import
get_logger
,
get_private_key_fingerprint
,
net_input
logger
=
get_logger
(
__file__
)
TIMEOUT
=
10
BUF_SIZE
=
1024
MANUAL_LOGIN
=
'manual'
AUTO_LOGIN
=
'auto'
class
SSHConnection
:
...
...
@@ -104,7 +110,8 @@ class SSHConnection:
ssh
.
connect
(
gateway
.
ip
,
port
=
gateway
.
port
,
username
=
gateway
.
username
,
password
=
gateway
.
password
,
pkey
=
gateway
.
private_key_obj
)
pkey
=
gateway
.
private_key_obj
,
timeout
=
TIMEOUT
)
except
(
paramiko
.
AuthenticationException
,
paramiko
.
BadAuthenticationType
,
SSHException
):
...
...
@@ -148,3 +155,134 @@ class SSHConnection:
logger
.
error
(
e
)
continue
return
sock
class
TelnetConnection
:
def
__init__
(
self
,
asset
,
system_user
,
client
):
self
.
client
=
client
self
.
asset
=
asset
self
.
system_user
=
system_user
self
.
sock
=
None
self
.
sel
=
selectors
.
DefaultSelector
()
self
.
incorrect_pattern
=
re
.
compile
(
r'incorrect|failed|失败|错误'
,
re
.
I
)
self
.
username_pattern
=
re
.
compile
(
r'login:\s*$|username:\s*$|用户名:\s*$|账\s*号:\s*$'
,
re
.
I
)
self
.
password_pattern
=
re
.
compile
(
r'password:\s*$|passwd:\s*$|密\s*码:\s*$'
,
re
.
I
)
self
.
success_pattern
=
re
.
compile
(
r'Last\s*login|success|成功'
,
re
.
I
)
def
get_socket
(
self
):
logger
.
info
(
'Get telnet server socket. {}'
.
format
(
self
.
client
.
user
))
self
.
sock
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
self
.
sock
.
settimeout
(
10
)
self
.
sock
.
connect
((
self
.
asset
.
ip
,
self
.
asset
.
port
))
# Send SGA and ECHO options to Telnet Server
self
.
sock
.
send
(
telnetlib
.
IAC
+
telnetlib
.
DO
+
telnetlib
.
SGA
)
self
.
sock
.
send
(
telnetlib
.
IAC
+
telnetlib
.
DO
+
telnetlib
.
ECHO
)
self
.
sel
.
register
(
self
.
sock
,
selectors
.
EVENT_READ
)
while
True
:
events
=
self
.
sel
.
select
()
for
sock
in
[
key
.
fileobj
for
key
,
_
in
events
]:
data
=
sock
.
recv
(
BUF_SIZE
)
if
sock
==
self
.
sock
:
logger
.
info
(
b
'[Telnet server send]: '
+
data
)
if
not
data
:
self
.
sock
.
close
()
msg
=
'The server <{}> closes the connection.'
.
format
(
self
.
asset
.
hostname
)
logger
.
info
(
msg
)
return
None
,
msg
if
data
.
startswith
(
telnetlib
.
IAC
):
self
.
option_negotiate
(
data
)
else
:
result
=
self
.
login_auth
(
data
)
if
result
:
msg
=
'Successful asset connection.<{}>/<{}>/<{}>.'
.
format
(
self
.
client
.
user
,
self
.
system_user
.
username
,
self
.
asset
.
hostname
)
logger
.
info
(
msg
)
self
.
client
.
send
(
b
'
\r\n
'
+
data
)
return
self
.
sock
,
None
elif
result
is
False
:
self
.
sock
.
close
()
msg
=
'Authentication failed.
\r\n
'
logger
.
info
(
msg
)
return
None
,
msg
elif
result
is
None
:
continue
def
option_negotiate
(
self
,
data
):
"""
Telnet server option negotiate before connection
:param data: option negotiate data
:return:
"""
logger
.
info
(
b
'[Server options negotiate]: '
+
data
)
data_list
=
data
.
split
(
telnetlib
.
IAC
)
new_data_list
=
[]
for
x
in
data_list
:
if
x
==
telnetlib
.
DO
+
telnetlib
.
ECHO
:
new_data_list
.
append
(
telnetlib
.
WONT
+
telnetlib
.
ECHO
)
elif
x
==
telnetlib
.
WILL
+
telnetlib
.
ECHO
:
new_data_list
.
append
(
telnetlib
.
DO
+
telnetlib
.
ECHO
)
elif
x
==
telnetlib
.
WILL
+
telnetlib
.
SGA
:
new_data_list
.
append
(
telnetlib
.
DO
+
telnetlib
.
SGA
)
elif
x
==
telnetlib
.
DO
+
telnetlib
.
TTYPE
:
new_data_list
.
append
(
telnetlib
.
WILL
+
telnetlib
.
TTYPE
)
elif
x
==
telnetlib
.
SB
+
telnetlib
.
TTYPE
+
b
'
\x01
'
:
new_data_list
.
append
(
telnetlib
.
SB
+
telnetlib
.
TTYPE
+
b
'
\x00
'
+
b
'XTERM-256COLOR'
)
elif
telnetlib
.
DO
in
x
:
new_data_list
.
append
(
x
.
replace
(
telnetlib
.
DO
,
telnetlib
.
WONT
))
elif
telnetlib
.
WILL
in
x
:
new_data_list
.
append
(
x
.
replace
(
telnetlib
.
WILL
,
telnetlib
.
DONT
))
elif
telnetlib
.
WONT
in
x
:
new_data_list
.
append
(
x
.
replace
(
telnetlib
.
WONT
,
telnetlib
.
DONT
))
elif
telnetlib
.
DONT
in
x
:
new_data_list
.
append
(
x
.
replace
(
telnetlib
.
DONT
,
telnetlib
.
WONT
))
else
:
new_data_list
.
append
(
x
)
new_data
=
telnetlib
.
IAC
.
join
(
new_data_list
)
logger
.
info
(
b
'[Client options negotiate]: '
+
new_data
)
self
.
sock
.
send
(
new_data
)
def
login_auth
(
self
,
raw_data
):
logger
.
info
(
'[Telnet login auth]: ({})'
.
format
(
self
.
client
.
user
))
try
:
data
=
raw_data
.
decode
(
'utf-8'
)
except
UnicodeDecodeError
:
try
:
data
=
raw_data
.
decode
(
'gbk'
)
except
UnicodeDecodeError
:
logger
.
info
(
b
'[Decode error]: '
+
b
'>>'
+
raw_data
+
b
'<<'
)
return
None
if
self
.
incorrect_pattern
.
search
(
data
):
logger
.
info
(
b
'[Login incorrect prompt]: '
+
b
'>>'
+
raw_data
+
b
'<<'
)
return
False
elif
self
.
username_pattern
.
search
(
data
):
logger
.
info
(
b
'[Username prompt]: '
+
b
'>>'
+
raw_data
+
b
'<<'
)
self
.
sock
.
send
(
self
.
system_user
.
username
.
encode
(
'utf-8'
)
+
b
'
\r\n
'
)
return
None
elif
self
.
password_pattern
.
search
(
data
):
logger
.
info
(
b
'[Password prompt]: '
+
b
'>>'
+
raw_data
+
b
'<<'
)
self
.
sock
.
send
(
self
.
system_user
.
password
.
encode
(
'utf-8'
)
+
b
'
\r\n
'
)
return
None
elif
self
.
success_pattern
.
search
(
data
):
logger
.
info
(
b
'[Login Success prompt]: '
+
b
'>>'
+
raw_data
+
b
'<<'
)
return
True
else
:
logger
.
info
(
b
'[No match]: '
+
b
'>>'
+
raw_data
+
b
'<<'
)
return
None
This diff is collapsed.
Click to expand it.
coco/httpd.py
View file @
da2bd7cd
...
...
@@ -21,8 +21,6 @@ class BaseNamespace(Namespace):
def
on_connect
(
self
):
self
.
current_user
=
self
.
get_current_user
()
if
self
.
current_user
is
None
:
return
redirect
(
self
.
socketio
.
config
[
'LOGIN_URL'
])
logger
.
debug
(
"{} connect websocket"
.
format
(
self
.
current_user
))
def
get_current_user
(
self
):
...
...
@@ -34,6 +32,10 @@ class BaseNamespace(Namespace):
user
=
app_service
.
check_user_cookie
(
session_id
,
csrf_token
)
if
token
:
user
=
app_service
.
check_user_with_token
(
token
)
msg
=
"Get current user: session_id<{}> token<{}> => {}"
.
format
(
session_id
,
token
,
user
)
logger
.
debug
(
msg
)
return
user
...
...
@@ -123,7 +125,7 @@ class ProxyNamespace(BaseNamespace):
child
,
parent
=
socket
.
socketpair
()
client
=
Client
(
parent
,
room
[
"request"
])
forwarder
=
ProxyServer
(
client
)
forwarder
=
ProxyServer
(
client
,
login_from
=
'WT'
)
room
[
"client"
]
=
client
room
[
"forwarder"
]
=
forwarder
room
[
"proxy"
]
=
WSProxy
(
self
,
child
,
room
[
"id"
])
...
...
@@ -149,27 +151,30 @@ class ProxyNamespace(BaseNamespace):
token
=
message
.
get
(
'token'
,
None
)
secret
=
message
.
get
(
'secret'
,
None
)
win_size
=
message
.
get
(
'size'
,
(
80
,
24
))
room
=
self
.
new_room
()
self
.
emit
(
'room'
,
{
'room'
:
room
[
"id"
],
'secret'
:
secret
})
join_room
(
room
[
'id'
])
if
not
token
or
not
secret
:
logger
.
debug
(
"Token or secret is None: {}"
.
format
(
token
,
secret
)
)
self
.
emit
(
'data'
,
{
'data'
:
"
\n
Operation not permitted!"
,
'room'
:
room
[
"id"
]}
)
msg
=
"Token or secret is None: {} {}"
.
format
(
token
,
secret
)
logger
.
error
(
msg
)
self
.
emit
(
'data'
,
{
'data'
:
msg
,
'room'
:
room
[
'id'
]},
room
=
room
[
'id'
]
)
self
.
emit
(
'disconnect'
)
return
None
return
info
=
app_service
.
get_token_asset
(
token
)
logger
.
debug
(
info
)
if
not
info
:
logger
.
debug
(
"Token info is None"
)
self
.
emit
(
'data'
,
{
'data'
:
"
\n
Operation not permitted!"
,
'room'
:
room
[
"id"
]}
)
msg
=
"Token info is none, maybe token expired"
logger
.
error
(
msg
)
self
.
emit
(
'data'
,
{
'data'
:
msg
,
'room'
:
room
[
'id'
]},
room
=
room
[
'id'
]
)
self
.
emit
(
'disconnect'
)
return
None
user_id
=
info
.
get
(
'user'
,
None
)
self
.
current_user
=
app_service
.
get_user_profile
(
user_id
)
room
[
"request"
]
.
user
=
self
.
current_user
#
room["request"].user = self.current_user
self
.
on_host
({
'secret'
:
secret
,
'uuid'
:
info
[
'asset'
],
...
...
@@ -180,7 +185,7 @@ class ProxyNamespace(BaseNamespace):
def
on_resize
(
self
,
message
):
cols
,
rows
=
message
.
get
(
'cols'
,
None
),
message
.
get
(
'rows'
,
None
)
logger
.
debug
(
"On resize event trigger: {}*{}"
.
format
(
cols
,
rows
))
rooms
=
self
.
connections
.
get
(
request
.
sid
)
rooms
=
self
.
connections
.
get
(
request
.
sid
,
{}
)
if
self
.
win_size
!=
(
cols
,
rows
):
logger
.
debug
(
"Start change win size: {}*{}"
.
format
(
cols
,
rows
))
for
room
in
rooms
.
values
():
...
...
@@ -203,7 +208,7 @@ class ProxyNamespace(BaseNamespace):
def
on_logout
(
self
,
room_id
):
room
=
self
.
connections
.
get
(
request
.
sid
,
{})
.
get
(
room_id
)
if
room
:
room
[
"proxy"
]
.
close
()
room
.
get
(
"proxy"
)
and
room
[
"proxy"
]
.
close
()
self
.
close_room
(
room_id
)
del
self
.
connections
[
request
.
sid
][
room_id
]
del
room
...
...
This diff is collapsed.
Click to expand it.
coco/interactive.py
View file @
da2bd7cd
...
...
@@ -260,7 +260,7 @@ class InteractiveServer:
if
system_user
is
None
:
self
.
client
.
send
(
_
(
"没有系统用户"
))
return
forwarder
=
ProxyServer
(
self
.
client
)
forwarder
=
ProxyServer
(
self
.
client
,
login_from
=
'ST'
)
forwarder
.
proxy
(
asset
,
system_user
)
def
interact
(
self
):
...
...
This diff is collapsed.
Click to expand it.
coco/models.py
View file @
da2bd7cd
...
...
@@ -86,8 +86,178 @@ class Client:
# print("GC: Client object has been gc")
class
BaseServer
:
"""
Base Server
Achieve command record
sub-class: Server, Telnet Server
"""
def
__init__
(
self
):
self
.
send_bytes
=
0
self
.
recv_bytes
=
0
self
.
stop_evt
=
threading
.
Event
()
self
.
input_data
=
SizedList
(
maxsize
=
1024
)
self
.
output_data
=
SizedList
(
maxsize
=
1024
)
self
.
_in_input_state
=
True
self
.
_input_initial
=
False
self
.
_in_vim_state
=
False
self
.
_input
=
""
self
.
_output
=
""
self
.
_session_ref
=
None
def
set_session
(
self
,
session
):
self
.
_session_ref
=
weakref
.
ref
(
session
)
@property
def
session
(
self
):
if
self
.
_session_ref
:
return
self
.
_session_ref
()
else
:
return
None
def
parse
(
self
,
b
):
if
isinstance
(
b
,
str
):
b
=
b
.
encode
(
"utf-8"
)
if
not
self
.
_input_initial
:
self
.
_input_initial
=
True
if
self
.
_have_enter_char
(
b
):
self
.
_in_input_state
=
False
self
.
_input
=
self
.
_parse_input
()
else
:
if
not
self
.
_in_input_state
:
self
.
_output
=
self
.
_parse_output
()
logger
.
debug
(
"
\n
{}
\n
Input: {}
\n
Output: {}
\n
{}"
.
format
(
"#"
*
30
+
" Command "
+
"#"
*
30
,
self
.
_input
,
self
.
_output
,
"#"
*
30
+
" End "
+
"#"
*
30
,
))
if
self
.
_input
:
self
.
session
.
put_command
(
self
.
_input
,
self
.
_output
)
self
.
input_data
.
clean
()
self
.
output_data
.
clean
()
self
.
_in_input_state
=
True
@staticmethod
def
_have_enter_char
(
s
):
for
c
in
char
.
ENTER_CHAR
:
if
c
in
s
:
return
True
return
False
def
_parse_output
(
self
):
if
not
self
.
output_data
:
return
''
parser
=
utils
.
TtyIOParser
()
return
parser
.
parse_output
(
self
.
output_data
)
def
_parse_input
(
self
):
if
not
self
.
input_data
or
self
.
input_data
[
0
]
==
char
.
RZ_PROTOCOL_CHAR
:
return
parser
=
utils
.
TtyIOParser
()
return
parser
.
parse_input
(
self
.
input_data
)
class
TelnetServer
(
BaseServer
):
"""
Telnet server
"""
def
__init__
(
self
,
sock
,
asset
,
system_user
):
super
(
TelnetServer
,
self
)
.
__init__
()
self
.
sock
=
sock
self
.
asset
=
asset
self
.
system_user
=
system_user
def
fileno
(
self
):
return
self
.
sock
.
fileno
()
def
send
(
self
,
b
):
self
.
parse
(
b
)
return
self
.
sock
.
send
(
b
)
def
recv
(
self
,
size
):
data
=
self
.
sock
.
recv
(
size
)
self
.
session
.
put_replay
(
data
)
if
self
.
_input_initial
:
if
self
.
_in_input_state
:
self
.
input_data
.
append
(
data
)
else
:
self
.
output_data
.
append
(
data
)
return
data
def
close
(
self
):
logger
.
info
(
"Closed server {}"
.
format
(
self
))
self
.
parse
(
b
''
)
self
.
stop_evt
.
set
()
self
.
sock
.
close
()
def
__getattr__
(
self
,
item
):
return
getattr
(
self
.
sock
,
item
)
def
__str__
(
self
):
return
"<To: {}>"
.
format
(
str
(
self
.
asset
))
class
Server
(
BaseServer
):
"""
SSH Server
Server object like client, a wrapper object, a connection to the asset,
Because we don't want to using python dynamic feature, such asset
have the chan and system_user attr.
"""
# Todo: Server name is not very suitable
def
__init__
(
self
,
chan
,
sock
,
asset
,
system_user
):
super
(
Server
,
self
)
.
__init__
()
self
.
chan
=
chan
self
.
sock
=
sock
self
.
asset
=
asset
self
.
system_user
=
system_user
def
fileno
(
self
):
return
self
.
chan
.
fileno
()
def
send
(
self
,
b
):
self
.
parse
(
b
)
return
self
.
chan
.
send
(
b
)
def
recv
(
self
,
size
):
data
=
self
.
chan
.
recv
(
size
)
self
.
session
.
put_replay
(
data
)
if
self
.
_input_initial
:
if
self
.
_in_input_state
:
self
.
input_data
.
append
(
data
)
else
:
self
.
output_data
.
append
(
data
)
return
data
def
close
(
self
):
logger
.
info
(
"Closed server {}"
.
format
(
self
))
self
.
parse
(
b
''
)
self
.
stop_evt
.
set
()
self
.
chan
.
close
()
self
.
chan
.
transport
.
close
()
if
self
.
sock
:
self
.
sock
.
transport
.
close
()
def
__getattr__
(
self
,
item
):
return
getattr
(
self
.
chan
,
item
)
def
__str__
(
self
):
return
"<To: {}>"
.
format
(
str
(
self
.
asset
))
# def __del__(self):
# print("GC: Server object has been gc")
'''
class Server:
"""
SSH Server
Server object like client, a wrapper object, a connection to the asset,
Because we don't want to using python dynamic feature, such asset
have the chan and system_user attr.
...
...
@@ -199,6 +369,7 @@ class Server:
# def __del__(self):
# print("GC: Server object has been gc")
'''
class
WSProxy
:
...
...
This diff is collapsed.
Click to expand it.
coco/proxy.py
View file @
da2bd7cd
...
...
@@ -8,8 +8,8 @@ import time
from
paramiko.ssh_exception
import
SSHException
from
.session
import
Session
from
.models
import
Server
from
.connection
import
SSHConnection
from
.models
import
Server
,
TelnetServer
from
.connection
import
SSHConnection
,
TelnetConnection
from
.ctx
import
current_app
,
app_service
from
.utils
import
wrap_with_line_feed
as
wr
,
wrap_with_warning
as
warning
,
\
get_logger
,
net_input
...
...
@@ -18,12 +18,15 @@ from .utils import wrap_with_line_feed as wr, wrap_with_warning as warning, \
logger
=
get_logger
(
__file__
)
TIMEOUT
=
10
BUF_SIZE
=
4096
MANUAL_LOGIN
=
'manual'
AUTO_LOGIN
=
'auto'
class
ProxyServer
:
def
__init__
(
self
,
client
):
def
__init__
(
self
,
client
,
login_from
):
self
.
client
=
client
self
.
server
=
None
self
.
login_from
=
login_from
self
.
connecting
=
True
self
.
stop_event
=
threading
.
Event
()
...
...
@@ -34,13 +37,24 @@ class ProxyServer:
"""
password
,
private_key
=
\
app_service
.
get_system_user_auth_info
(
system_user
)
if
not
password
and
not
private_key
:
if
system_user
.
login_mode
==
MANUAL_LOGIN
or
(
not
password
and
not
private_key
)
:
prompt
=
"{}'s password: "
.
format
(
system_user
.
username
)
password
=
net_input
(
self
.
client
,
prompt
=
prompt
,
sensitive
=
True
)
system_user
.
password
=
password
system_user
.
private_key
=
private_key
def
proxy
(
self
,
asset
,
system_user
):
if
asset
.
protocol
!=
system_user
.
protocol
:
msg
=
'System user <{}> and asset <{}> protocol are inconsistent.'
.
format
(
system_user
.
name
,
asset
.
hostname
)
self
.
client
.
send
(
warning
(
wr
(
msg
,
before
=
1
,
after
=
0
)))
return
if
system_user
.
login_mode
==
MANUAL_LOGIN
and
not
system_user
.
username
:
system_user_name
=
net_input
(
self
.
client
,
prompt
=
'username: '
,
before
=
1
)
system_user
.
username
=
system_user_name
self
.
get_system_user_auth
(
system_user
)
self
.
send_connecting_message
(
asset
,
system_user
)
self
.
server
=
self
.
get_server_conn
(
asset
,
system_user
)
...
...
@@ -49,7 +63,7 @@ class ProxyServer:
command_recorder
=
current_app
.
new_command_recorder
()
replay_recorder
=
current_app
.
new_replay_recorder
()
session
=
Session
(
self
.
client
,
self
.
server
,
self
.
client
,
self
.
server
,
self
.
login_from
,
command_recorder
=
command_recorder
,
replay_recorder
=
replay_recorder
,
)
...
...
@@ -74,15 +88,26 @@ class ProxyServer:
if
not
self
.
validate_permission
(
asset
,
system_user
):
self
.
client
.
send
(
warning
(
'No permission'
))
return
None
if
True
:
if
system_user
.
protocol
==
asset
.
protocol
==
'telnet'
:
server
=
self
.
get_telnet_server_conn
(
asset
,
system_user
)
elif
system_user
.
protocol
==
asset
.
protocol
==
'ssh'
:
server
=
self
.
get_ssh_server_conn
(
asset
,
system_user
)
else
:
server
=
self
.
get_ssh_server_conn
(
asset
,
system_user
)
server
=
None
return
server
# Todo: Support telnet
def
get_telnet_server_conn
(
self
,
asset
,
system_user
):
pass
telnet
=
TelnetConnection
(
asset
,
system_user
,
self
.
client
)
sock
,
msg
=
telnet
.
get_socket
()
if
not
sock
:
self
.
client
.
send
(
warning
(
wr
(
msg
,
before
=
1
,
after
=
0
)))
server
=
None
else
:
server
=
TelnetServer
(
sock
,
asset
,
system_user
)
# self.client.send(b'\r\n')
self
.
connecting
=
False
return
server
def
get_ssh_server_conn
(
self
,
asset
,
system_user
):
request
=
self
.
client
.
request
...
...
@@ -116,6 +141,8 @@ class ProxyServer:
break
def
watch_win_size_change_async
(
self
):
if
not
isinstance
(
self
.
server
,
Server
):
return
thread
=
threading
.
Thread
(
target
=
self
.
watch_win_size_change
)
thread
.
daemon
=
True
thread
.
start
()
...
...
This diff is collapsed.
Click to expand it.
coco/session.py
View file @
da2bd7cd
...
...
@@ -14,10 +14,11 @@ logger = get_logger(__file__)
class
Session
:
def
__init__
(
self
,
client
,
server
,
command_recorder
=
None
,
replay_recorder
=
None
):
def
__init__
(
self
,
client
,
server
,
login_from
,
command_recorder
=
None
,
replay_recorder
=
None
):
self
.
id
=
str
(
uuid
.
uuid4
())
self
.
client
=
client
# Master of the session, it's a client sock
self
.
server
=
server
# Server channel
self
.
login_from
=
login_from
# Login from
self
.
_watchers
=
[]
# Only watch session
self
.
_sharers
=
[]
# Join to the session, read and write
self
.
replaying
=
True
...
...
@@ -174,7 +175,7 @@ class Session:
"user"
:
self
.
client
.
user
.
username
,
"asset"
:
self
.
server
.
asset
.
hostname
,
"system_user"
:
self
.
server
.
system_user
.
username
,
"login_from"
:
"ST"
,
"login_from"
:
self
.
login_from
,
"remote_addr"
:
self
.
client
.
addr
[
0
],
"is_finished"
:
True
if
self
.
stop_evt
.
is_set
()
else
False
,
"date_last_active"
:
self
.
date_last_active
.
strftime
(
"
%
Y-
%
m-
%
d
%
H:
%
M:
%
S"
)
+
" +0000"
,
...
...
This diff is collapsed.
Click to expand it.
requirements/requirements.txt
View file @
da2bd7cd
...
...
@@ -18,8 +18,8 @@ idna==2.6
itsdangerous==0.24
Jinja2==2.10
jmespath==0.9.3
jms-storage==0.0.1
7
jumpserver-python-sdk==0.0.4
2
jms-storage==0.0.1
8
jumpserver-python-sdk==0.0.4
4
MarkupSafe==1.0
oss2==2.4.0
paramiko==2.4.0
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment