Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
webssh
Overview
Overview
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
郑天保
webssh
Commits
2e347029
Commit
2e347029
authored
Aug 22, 2018
by
Sheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Changed validation error messages
parent
d43a0115
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
49 additions
and
38 deletions
+49
-38
test_app.py
tests/test_app.py
+10
-10
test_handler.py
tests/test_handler.py
+12
-9
handler.py
webssh/handler.py
+27
-19
No files found.
tests/test_app.py
View file @
2e347029
...
@@ -64,31 +64,31 @@ class TestApp(AsyncHTTPTestCase):
...
@@ -64,31 +64,31 @@ class TestApp(AsyncHTTPTestCase):
self
.
assertEqual
(
response
.
code
,
200
)
self
.
assertEqual
(
response
.
code
,
200
)
body
=
'hostname=&port=&username=&password'
body
=
'hostname=&port=&username=&password'
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
self
.
assertIn
(
b
'
"status": "The hostname field is required"'
,
response
.
body
)
# noqa
self
.
assertIn
(
b
'
The hostname field is required'
,
response
.
body
)
body
=
'hostname=127.0.0.1&port=&username=&password'
body
=
'hostname=127.0.0.1&port=&username=&password'
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
self
.
assertIn
(
b
'
"status": "The port field is required"
'
,
response
.
body
)
self
.
assertIn
(
b
'
The port field is required
'
,
response
.
body
)
body
=
'hostname=127.0.0&port=22&username=&password'
body
=
'hostname=127.0.0&port=22&username=&password'
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
self
.
assertIn
(
b
'
"status": "
Invalid hostname'
,
response
.
body
)
self
.
assertIn
(
b
'Invalid hostname'
,
response
.
body
)
body
=
'hostname=http://www.googe.com&port=22&username=&password'
body
=
'hostname=http://www.googe.com&port=22&username=&password'
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
self
.
assertIn
(
b
'
"status": "
Invalid hostname'
,
response
.
body
)
self
.
assertIn
(
b
'Invalid hostname'
,
response
.
body
)
body
=
'hostname=127.0.0.1&port=port&username=&password'
body
=
'hostname=127.0.0.1&port=port&username=&password'
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
self
.
assertIn
(
b
'
"status": "
Invalid port'
,
response
.
body
)
self
.
assertIn
(
b
'Invalid port'
,
response
.
body
)
body
=
'hostname=127.0.0.1&port=70000&username=&password'
body
=
'hostname=127.0.0.1&port=70000&username=&password'
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
self
.
assertIn
(
b
'
"status": "
Invalid port'
,
response
.
body
)
self
.
assertIn
(
b
'Invalid port'
,
response
.
body
)
body
=
'hostname=127.0.0.1&port=7000&username=&password'
body
=
'hostname=127.0.0.1&port=7000&username=&password'
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
response
=
self
.
fetch
(
'/'
,
method
=
'POST'
,
body
=
body
)
self
.
assertIn
(
b
'
"status": "The username field is required"
'
,
response
.
body
)
# noqa
self
.
assertIn
(
b
'
The username field is required
'
,
response
.
body
)
# noqa
def
test_app_with_wrong_credentials
(
self
):
def
test_app_with_wrong_credentials
(
self
):
response
=
self
.
fetch
(
'/'
)
response
=
self
.
fetch
(
'/'
)
...
@@ -173,7 +173,7 @@ class TestApp(AsyncHTTPTestCase):
...
@@ -173,7 +173,7 @@ class TestApp(AsyncHTTPTestCase):
data
=
json
.
loads
(
to_str
(
response
.
body
))
data
=
json
.
loads
(
to_str
(
response
.
body
))
self
.
assertIsNone
(
data
[
'id'
])
self
.
assertIsNone
(
data
[
'id'
])
self
.
assertIsNone
(
data
[
'encoding'
])
self
.
assertIsNone
(
data
[
'encoding'
])
self
.
assert
Equal
(
data
[
'status'
],
'Not a valid private key or wrong password for decrypting the key.'
)
# noqa
self
.
assert
True
(
data
[
'status'
]
.
startswith
(
'Invalid private key'
))
@tornado.testing.gen_test
@tornado.testing.gen_test
def
test_app_auth_with_pubkey_exceeds_key_max_size
(
self
):
def
test_app_auth_with_pubkey_exceeds_key_max_size
(
self
):
...
@@ -194,7 +194,7 @@ class TestApp(AsyncHTTPTestCase):
...
@@ -194,7 +194,7 @@ class TestApp(AsyncHTTPTestCase):
data
=
json
.
loads
(
to_str
(
response
.
body
))
data
=
json
.
loads
(
to_str
(
response
.
body
))
self
.
assertIsNone
(
data
[
'id'
])
self
.
assertIsNone
(
data
[
'id'
])
self
.
assertIsNone
(
data
[
'encoding'
])
self
.
assertIsNone
(
data
[
'encoding'
])
self
.
assert
Equal
(
data
[
'status'
],
'Not a valid private key.'
)
self
.
assert
True
(
data
[
'status'
]
.
startswith
(
'Invalid private key'
)
)
@tornado.testing.gen_test
@tornado.testing.gen_test
def
test_app_auth_with_pubkey_cannot_be_decoded
(
self
):
def
test_app_auth_with_pubkey_cannot_be_decoded
(
self
):
...
@@ -218,7 +218,7 @@ class TestApp(AsyncHTTPTestCase):
...
@@ -218,7 +218,7 @@ class TestApp(AsyncHTTPTestCase):
data
=
json
.
loads
(
to_str
(
response
.
body
))
data
=
json
.
loads
(
to_str
(
response
.
body
))
self
.
assertIsNone
(
data
[
'id'
])
self
.
assertIsNone
(
data
[
'id'
])
self
.
assertIsNone
(
data
[
'encoding'
])
self
.
assertIsNone
(
data
[
'encoding'
])
self
.
assert
Equal
(
data
[
'status'
],
'Not a valid private key.'
)
self
.
assert
True
(
data
[
'status'
]
.
startswith
(
'Invalid private key'
)
)
@tornado.testing.gen_test
@tornado.testing.gen_test
def
test_app_post_form_with_large_body_size
(
self
):
def
test_app_post_form_with_large_body_size
(
self
):
...
...
tests/test_handler.py
View file @
2e347029
...
@@ -79,21 +79,24 @@ class TestIndexHandler(unittest.TestCase):
...
@@ -79,21 +79,24 @@ class TestIndexHandler(unittest.TestCase):
fname
=
'test_ed25519.key'
fname
=
'test_ed25519.key'
cls
=
paramiko
.
Ed25519Key
cls
=
paramiko
.
Ed25519Key
key
=
read_file
(
os
.
path
.
join
(
base_dir
,
'tests'
,
fname
))
key
=
read_file
(
os
.
path
.
join
(
base_dir
,
'tests'
,
fname
))
pkey
=
IndexHandler
.
get_pkey_obj
(
key
,
None
)
pkey
=
IndexHandler
.
get_pkey_obj
(
key
,
None
,
fname
)
self
.
assertIsInstance
(
pkey
,
cls
)
self
.
assertIsInstance
(
pkey
,
cls
)
pkey
=
IndexHandler
.
get_pkey_obj
(
key
,
'iginored'
)
pkey
=
IndexHandler
.
get_pkey_obj
(
key
,
'iginored'
,
fname
)
self
.
assertIsInstance
(
pkey
,
cls
)
self
.
assertIsInstance
(
pkey
,
cls
)
with
self
.
assertRaises
(
ValueError
):
with
self
.
assertRaises
(
ValueError
)
as
exc
:
pkey
=
IndexHandler
.
get_pkey_obj
(
'x'
+
key
,
None
)
pkey
=
IndexHandler
.
get_pkey_obj
(
'x'
+
key
,
None
,
fname
)
self
.
assertIn
(
'Invalid private key'
,
str
(
exc
))
def
test_get_pkey_obj_with_encrypted_key
(
self
):
def
test_get_pkey_obj_with_encrypted_key
(
self
):
fname
=
'test_ed25519_password.key'
fname
=
'test_ed25519_password.key'
password
=
'abc123'
password
=
'abc123'
cls
=
paramiko
.
Ed25519Key
cls
=
paramiko
.
Ed25519Key
key
=
read_file
(
os
.
path
.
join
(
base_dir
,
'tests'
,
fname
))
key
=
read_file
(
os
.
path
.
join
(
base_dir
,
'tests'
,
fname
))
pkey
=
IndexHandler
.
get_pkey_obj
(
key
,
password
)
pkey
=
IndexHandler
.
get_pkey_obj
(
key
,
password
,
fname
)
self
.
assertIsInstance
(
pkey
,
cls
)
self
.
assertIsInstance
(
pkey
,
cls
)
with
self
.
assertRaises
(
ValueError
):
with
self
.
assertRaises
(
ValueError
)
as
exc
:
pkey
=
IndexHandler
.
get_pkey_obj
(
key
,
'wrongpass'
)
pkey
=
IndexHandler
.
get_pkey_obj
(
key
,
'wrongpass'
,
fname
)
with
self
.
assertRaises
(
ValueError
):
self
.
assertIn
(
'Wrong password'
,
str
(
exc
))
pkey
=
IndexHandler
.
get_pkey_obj
(
'x'
+
key
,
password
)
with
self
.
assertRaises
(
ValueError
)
as
exc
:
pkey
=
IndexHandler
.
get_pkey_obj
(
'x'
+
key
,
password
,
fname
)
self
.
assertIn
(
'Invalid private key'
,
str
(
exc
))
webssh/handler.py
View file @
2e347029
...
@@ -68,18 +68,19 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
...
@@ -68,18 +68,19 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
self
.
host_keys_settings
=
host_keys_settings
self
.
host_keys_settings
=
host_keys_settings
def
get_privatekey
(
self
):
def
get_privatekey
(
self
):
try
:
lst
=
self
.
request
.
files
.
get
(
'privatekey'
)
data
=
self
.
request
.
files
.
get
(
'privatekey'
)[
0
][
'body'
]
if
not
lst
:
# no privatekey provided
except
TypeError
:
# no privatekey provided
return
return
self
.
filename
=
lst
[
0
][
'filename'
]
data
=
lst
[
0
][
'body'
]
if
len
(
data
)
<
KEY_MAX_SIZE
:
if
len
(
data
)
<
KEY_MAX_SIZE
:
try
:
try
:
return
to_str
(
data
)
return
to_str
(
data
)
except
UnicodeDecodeError
:
except
(
UnicodeDecodeError
,
ValueError
,
SyntaxError
)
:
pass
pass
raise
ValueError
(
'
Not a valid private key.'
)
raise
ValueError
(
'
Invalid private key: {}'
.
format
(
self
.
filename
)
)
@classmethod
@classmethod
def
get_specific_pkey
(
cls
,
pkeycls
,
privatekey
,
password
):
def
get_specific_pkey
(
cls
,
pkeycls
,
privatekey
,
password
):
...
@@ -95,24 +96,30 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
...
@@ -95,24 +96,30 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
return
pkey
return
pkey
@classmethod
@classmethod
def
get_pkey_obj
(
cls
,
privatekey
,
password
):
def
get_pkey_obj
(
cls
,
privatekey
,
password
,
filename
):
password
=
to_bytes
(
password
)
bpass
=
to_bytes
(
password
)
pkey
=
cls
.
get_specific_pkey
(
paramiko
.
RSAKey
,
privatekey
,
password
)
\
pkey
=
cls
.
get_specific_pkey
(
paramiko
.
RSAKey
,
privatekey
,
bpass
)
\
or
cls
.
get_specific_pkey
(
paramiko
.
DSSKey
,
privatekey
,
password
)
\
or
cls
.
get_specific_pkey
(
paramiko
.
DSSKey
,
privatekey
,
bpass
)
\
or
cls
.
get_specific_pkey
(
paramiko
.
ECDSAKey
,
privatekey
,
password
)
\
or
cls
.
get_specific_pkey
(
paramiko
.
ECDSAKey
,
privatekey
,
bpass
)
\
or
cls
.
get_specific_pkey
(
paramiko
.
Ed25519Key
,
privatekey
,
or
cls
.
get_specific_pkey
(
paramiko
.
Ed25519Key
,
privatekey
,
bpass
)
password
)
if
not
pkey
:
if
not
pkey
:
raise
ValueError
(
'Not a valid private key or wrong password '
if
not
password
:
'for decrypting the key.'
)
error
=
'Invalid private key: {}'
.
format
(
filename
)
else
:
error
=
(
'Wrong password {!r} for decrypting the private key.'
)
.
format
(
password
)
raise
ValueError
(
error
)
return
pkey
return
pkey
def
get_hostname
(
self
):
def
get_hostname
(
self
):
value
=
self
.
get_value
(
'hostname'
)
value
=
self
.
get_value
(
'hostname'
)
if
not
(
is_valid_hostname
(
value
)
|
is_valid_ipv4_address
(
value
)
|
if
not
(
is_valid_hostname
(
value
)
|
is_valid_ipv4_address
(
value
)
|
is_valid_ipv6_address
(
value
)):
is_valid_ipv6_address
(
value
)):
raise
ValueError
(
'Invalid hostname
{}
'
.
format
(
value
))
raise
ValueError
(
'Invalid hostname
: {}.
'
.
format
(
value
))
return
value
return
value
def
get_port
(
self
):
def
get_port
(
self
):
...
@@ -125,12 +132,12 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
...
@@ -125,12 +132,12 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
if
is_valid_port
(
port
):
if
is_valid_port
(
port
):
return
port
return
port
raise
ValueError
(
'Invalid port
{}
'
.
format
(
value
))
raise
ValueError
(
'Invalid port
: {}.
'
.
format
(
value
))
def
get_value
(
self
,
name
):
def
get_value
(
self
,
name
):
value
=
self
.
get_argument
(
name
)
value
=
self
.
get_argument
(
name
)
if
not
value
:
if
not
value
:
raise
ValueError
(
'The {} field is required'
.
format
(
name
))
raise
ValueError
(
'The {} field is required
.
'
.
format
(
name
))
return
value
return
value
def
get_args
(
self
):
def
get_args
(
self
):
...
@@ -139,7 +146,8 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
...
@@ -139,7 +146,8 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
username
=
self
.
get_value
(
'username'
)
username
=
self
.
get_value
(
'username'
)
password
=
self
.
get_argument
(
'password'
)
password
=
self
.
get_argument
(
'password'
)
privatekey
=
self
.
get_privatekey
()
privatekey
=
self
.
get_privatekey
()
pkey
=
self
.
get_pkey_obj
(
privatekey
,
password
)
if
privatekey
else
None
pkey
=
self
.
get_pkey_obj
(
privatekey
,
password
,
self
.
filename
)
\
if
privatekey
else
None
args
=
(
hostname
,
port
,
username
,
password
,
pkey
)
args
=
(
hostname
,
port
,
username
,
password
,
pkey
)
logging
.
debug
(
args
)
logging
.
debug
(
args
)
return
args
return
args
...
...
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