def test_app_auth_with_valid_pubkey_by_multipart_form(self): url = self.get_url('/') client = self.get_http_client() response = yield client.fetch(url) self.assertEqual(response.code, 200) privatekey = read_file(make_tests_data_path('user_rsa_key')) files = [('privatekey', 'user_rsa_key', privatekey)] content_type, body = encode_multipart_formdata(self.body_dict.items(), files) headers = { 'Content-Type': content_type, 'content-length': str(len(body)) } response = yield client.fetch(url, method='POST', headers=headers, body=body) data = json.loads(to_str(response.body)) self.assertIsNone(data['status']) self.assertIsNotNone(data['id']) self.assertIsNotNone(data['encoding']) url = url.replace('http', 'ws') ws_url = url + 'ws?id=' + data['id'] ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertEqual(to_str(msg, data['encoding']), banner) ws.close()
def test_app_for_sending_message_with_large_size(self): url = self.get_url('/') client = self.get_http_client() body = urlencode(dict(self.body, username='******')) response = yield client.fetch(url, method='POST', body=body, headers=self.headers) data = json.loads(to_str(response.body)) self.assertIsNone(data['status']) self.assertIsNotNone(data['id']) self.assertIsNotNone(data['encoding']) url = url.replace('http', 'ws') ws_url = url + 'ws?id=' + data['id'] ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertEqual(to_str(msg, data['encoding']), banner) send = 'h' * (64 * 1024) + '\r\n\r\n' yield ws.write_message(json.dumps({'data': send})) lst = [] while True: msg = yield ws.read_message() lst.append(msg) if msg.endswith(b'\r\n\r\n'): break recv = b''.join(lst).decode(data['encoding']) self.assertEqual(send, recv) ws.close()
def test_app_with_too_many_connections(self): url = self.get_url('/') client = self.get_http_client() body = urlencode(dict(self.body, username='******')) response = yield client.fetch(url, method='POST', body=body, headers=self.headers) data = json.loads(to_str(response.body)) worker_id = data['id'] self.assertIsNotNone(worker_id) self.assertIsNotNone(data['encoding']) self.assertIsNone(data['status']) response = yield client.fetch(url, method='POST', body=body, headers=self.headers) data = json.loads(to_str(response.body)) self.assertIsNone(data['id']) self.assertIsNone(data['encoding']) self.assertEqual(data['status'], 'Too many connections.') ws_url = url.replace('http', 'ws') + 'ws?id=' + worker_id ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertIsNotNone(msg) response = yield client.fetch(url, method='POST', body=body, headers=self.headers) data = json.loads(to_str(response.body)) self.assertIsNone(data['id']) self.assertIsNone(data['encoding']) self.assertEqual(data['status'], 'Too many connections.') ws.close()
def test_app_with_too_many_connections(self): clients['127.0.0.1'] = {'fake_worker_id': None} url = self.get_url('/') response = yield self.async_post(url, self.body) data = json.loads(to_str(response.body)) self.assertEqual('Too many live connections.', data['status']) clients['127.0.0.1'].clear() response = yield self.async_post(url, self.body) self.assert_status_none(json.loads(to_str(response.body)))
def test_app_with_too_many_connections(self): clients['127.0.0.1'] = {'fake_worker_id': None} url = self.get_url('/') response = yield self.async_post(url, urlencode(self.body), self.headers) # noqa data = json.loads(to_str(response.body)) self.assertEqual('Too many connections.', data['status']) # noqa clients['127.0.0.1'].clear() response = yield self.async_post(url, urlencode(self.body), self.headers) # noqa self.assert_status_equal(json.loads(to_str(response.body)), None)
def test_app_with_correct_credentials_user_robey(self): url = self.get_url('/') response = yield self.async_post(url, self.body) data = json.loads(to_str(response.body)) self.assert_status_equal(data, None) url = url.replace('http', 'ws') ws_url = url + 'ws?id=' + data['id'] ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertEqual(to_str(msg, data['encoding']), banner) ws.close()
def test_app_auth_with_valid_pubkey_by_urlencoded_form(self): url = self.get_url('/') privatekey = read_file(make_tests_data_path('user_rsa_key')) self.body_dict.update(privatekey=privatekey) response = yield self.async_post(url, self.body_dict) data = json.loads(to_str(response.body)) self.assert_status_none(data) url = url.replace('http', 'ws') ws_url = url + 'ws?id=' + data['id'] ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertEqual(to_str(msg, data['encoding']), banner) ws.close()
def test_app_with_correct_credentials_but_with_no_port(self): default_port = handler.DEFAULT_PORT handler.DEFAULT_PORT = self.sshserver_port # with no port value body = self.body.replace(str(self.sshserver_port), '') response = self.sync_post(body) self.assert_status_equal(json.loads(to_str(response.body)), None) # with no port argument body = body.replace('port=&', '') response = self.sync_post(body) self.assert_status_equal(json.loads(to_str(response.body)), None) handler.DEFAULT_PORT = default_port
def test_app_auth_with_pubkey_cannot_be_decoded(self): url = self.get_url('/') client = self.get_http_client() response = yield client.fetch(url) self.assertEqual(response.code, 200) privatekey = 'h' * 1024 files = [('privatekey', 'user_rsa_key', privatekey)] content_type, body = encode_multipart_formdata(self.body_dict.items(), files) body = body.encode('utf-8') # added some gbk bytes to the privatekey, make it cannot be decoded body = body[:-100] + b'\xb4\xed\xce\xf3' + body[-100:] headers = { 'Content-Type': content_type, 'content-length': str(len(body)) } response = yield client.fetch(url, method='POST', headers=headers, body=body) data = json.loads(to_str(response.body)) self.assertIsNone(data['id']) self.assertIsNone(data['encoding']) self.assertTrue(data['status'].startswith('Invalid private key'))
def test_app_with_correct_header_origin(self): headers = dict(self.headers, Origin=self.origin) response = yield self.async_post('/', urlencode(self.body), headers) self.assert_status_equal(json.loads(to_str(response.body)), None) self.assertEqual( response.headers.get('Access-Control-Allow-Origin'), self.origin )
def test_app_with_wrong_header_origin(self): headers = dict(Origin='localhost') response = yield self.async_post('/', self.body, headers=headers) self.assert_status_equal( 'Cross origin operation is not allowed.', json.loads(to_str(response.body)), ) # noqa
def test_app_with_correct_credentials_user_bar(self): url = self.get_url('/') client = self.get_http_client() response = yield client.fetch(url) self.assertEqual(response.code, 200) body = self.body.replace('robey', 'bar') response = yield client.fetch(url, method='POST', body=body) data = json.loads(to_str(response.body)) self.assertIsNone(data['status']) self.assertIsNotNone(data['id']) self.assertIsNotNone(data['encoding']) url = url.replace('http', 'ws') ws_url = url + 'ws?id=' + data['id'] ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertEqual(to_str(msg, data['encoding']), banner) # messages below will be ignored silently yield ws.write_message('hello') yield ws.write_message('"hello"') yield ws.write_message('[hello]') yield ws.write_message(json.dumps({'resize': []})) yield ws.write_message(json.dumps({'resize': {}})) yield ws.write_message(json.dumps({'resize': 'ab'})) yield ws.write_message(json.dumps({'resize': ['a', 'b']})) yield ws.write_message(json.dumps({'resize': {'a': 1, 'b': 2}})) yield ws.write_message(json.dumps({'resize': [100]})) yield ws.write_message(json.dumps({'resize': [100] * 10})) yield ws.write_message(json.dumps({'resize': [-1, -1]})) yield ws.write_message(json.dumps({'data': [1]})) yield ws.write_message(json.dumps({'data': (1, )})) yield ws.write_message(json.dumps({'data': {'a': 2}})) yield ws.write_message(json.dumps({'data': 1})) yield ws.write_message(json.dumps({'data': 2.1})) yield ws.write_message(json.dumps({'key-non-existed': 'hello'})) # end - those just for testing webssh websocket stablity yield ws.write_message(json.dumps({'resize': [79, 23]})) msg = yield ws.read_message() self.assertEqual(b'resized', msg) yield ws.write_message(json.dumps({'data': 'bye'})) msg = yield ws.read_message() self.assertEqual(b'bye', msg) ws.close()
def test_app_with_wrong_credentials(self): response = self.fetch('/') self.assertEqual(response.code, 200) response = self.fetch('/', method='POST', body=self.body + 's') data = json.loads(to_str(response.body)) self.assertIsNone(data['encoding']) self.assertIsNone(data['id']) self.assertIn('Authentication failed.', data['status'])
def test_app_with_user_pass2fa_with_correct_passwords(self): self.body_dict.update(username='******', password='******', totp='passcode') response = yield self.async_post('/', self.body_dict) self.assertEqual(response.code, 200) data = json.loads(to_str(response.body)) self.assert_status_none(data)
def parse_encoding(self, data): try: encoding = to_str(data.strip(), 'ascii') except UnicodeDecodeError: return if is_valid_encoding(encoding): return encoding
def test_app_with_correct_credentials(self): response = self.fetch('/') self.assertEqual(response.code, 200) response = self.fetch('/', method='POST', body=self.body) data = json.loads(to_str(response.body)) self.assertIsNone(data['status']) self.assertIsNotNone(data['id']) self.assertIsNotNone(data['encoding'])
def get_default_encoding(self, ssh): try: _, stdout, _ = ssh.exec_command('locale charmap') except paramiko.SSHException: result = None else: result = to_str(stdout.read().strip()) return result if result else 'utf-8'
def test_app_with_correct_credentials_user_robey(self): url = self.get_url('/') client = self.get_http_client() response = yield client.fetch(url) self.assertEqual(response.code, 200) response = yield client.fetch(url, method='POST', body=self.body) data = json.loads(to_str(response.body)) self.assertIsNone(data['status']) self.assertIsNotNone(data['id']) self.assertIsNotNone(data['encoding']) url = url.replace('http', 'ws') ws_url = url + 'ws?id=' + data['id'] ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertEqual(to_str(msg, data['encoding']), banner) ws.close()
def test_app_with_user_pass2fa_with_wrong_pkey_correct_passwords(self): url = self.get_url('/') privatekey = read_file(make_tests_data_path('user_rsa_key')) self.body_dict.update(username='******', password='******', privatekey=privatekey, totp='passcode') response = yield self.async_post(url, self.body_dict) data = json.loads(to_str(response.body)) self.assert_status_none(data)
def test_app_with_user_keyonly_for_bad_authentication_type(self): url = self.get_url('/') self.body_dict.update(username='******', password='******') body = urlencode(self.body_dict) response = yield self.async_post(url, body) self.assertEqual(response.code, 200) data = json.loads(to_str(response.body)) self.assertIsNone(data['id']) self.assertIsNone(data['encoding']) self.assertIn('Bad authentication type', data['status'])
def test_app_with_user_pkey2fa_with_empty_passcode(self): url = self.get_url('/') privatekey = read_file(make_tests_data_path('user_rsa_key')) self.body_dict.update(username='******', password='******', privatekey=privatekey, totp='') response = yield self.async_post(url, self.body_dict) data = json.loads(to_str(response.body)) self.assert_status_in('Need a verification code', data)
def test_app_with_bad_host_key(self): url = self.get_url('/') client = self.get_http_client() body = urlencode(dict(self.body, username='******')) response = yield client.fetch(url, method='POST', body=body, headers=self.headers) data = json.loads(to_str(response.body)) self.assertIsNone(data['id']) self.assertIsNone(data['encoding']) self.assertEqual('Bad host key.', data['status'])
def get_default_encoding(self, ssh): try: _, stdout, _ = ssh.exec_command('locale') except paramiko.SSHException: result = None else: data = stdout.read() result = parse_encoding(to_str(data)) return result if result else 'utf-8'
def test_app_with_correct_event_origin(self): url = self.get_url('/') client = self.get_http_client() body = urlencode(dict(self.body, username='******', _origin=self.origin)) response = yield client.fetch(url, method='POST', body=body, headers=self.headers) data = json.loads(to_str(response.body)) self.assertIsNotNone(data['id']) self.assertIsNotNone(data['encoding']) self.assertIsNone(data['status']) self.assertIsNone(response.headers.get('Access-Control-Allow-Origin'))
def test_app_with_hostname_not_in_hostkeys(self): url = self.get_url('/') client = self.get_http_client() body = urlencode(dict(self.body, username='******')) response = yield client.fetch(url, method='POST', body=body, headers=self.headers) data = json.loads(to_str(response.body)) self.assertIsNone(data['id']) self.assertIsNone(data['encoding']) message = 'Connection to {}:{} is not allowed.'.format(self.body['hostname'], self.sshserver_port) # noqa self.assertEqual(message, data['status'])
def test_app_with_wrong_event_origin(self): url = self.get_url('/') client = self.get_http_client() body = urlencode(dict(self.body, username='******', _origin='localhost')) response = yield client.fetch(url, method='POST', body=body, headers=self.headers) data = json.loads(to_str(response.body)) self.assertIsNone(data['id']) self.assertIsNone(data['encoding']) self.assertEqual( 'Cross origin operation is not allowed.', data['status'] )
def test_app_auth_with_valid_pubkey_by_urlencoded_form(self): url = self.get_url('/') client = self.get_http_client() response = yield client.fetch(url) self.assertEqual(response.code, 200) privatekey = read_file(make_tests_data_path('user_rsa_key')) self.body_dict.update(privatekey=privatekey) body = urlencode(self.body_dict) response = yield client.fetch(url, method='POST', body=body) data = json.loads(to_str(response.body)) self.assertIsNone(data['status']) self.assertIsNotNone(data['id']) self.assertIsNotNone(data['encoding']) url = url.replace('http', 'ws') ws_url = url + 'ws?id=' + data['id'] ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertEqual(to_str(msg, data['encoding']), banner) ws.close()
def test_app_with_correct_credentials_but_with_no_port(self): default_port = handler.DEFAULT_PORT handler.DEFAULT_PORT = self.sshserver_port # with no port value body = self.body.replace(str(self.sshserver_port), '') response = self.sync_post(body) data = json.loads(to_str(response.body)) self.assertIsNone(data['status']) self.assertIsNotNone(data['id']) self.assertIsNotNone(data['encoding']) # with no port argument body = body.replace('port=&', '') response = self.sync_post(body) data = json.loads(to_str(response.body)) self.assertIsNone(data['status']) self.assertIsNotNone(data['id']) self.assertIsNotNone(data['encoding']) handler.DEFAULT_PORT = default_port
def test_app_with_correct_credentials_but_without_id_argument(self): url = self.get_url('/') response = yield self.async_post(url, self.body) data = json.loads(to_str(response.body)) self.assert_status_equal(data, None) url = url.replace('http', 'ws') ws_url = url + 'ws' ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertIsNone(msg) self.assertIn('Missing argument id', ws.close_reason)
def test_app_with_correct_credentials_but_wrong_id(self): url = self.get_url('/') response = yield self.async_post(url, self.body) data = json.loads(to_str(response.body)) self.assert_status_equal(data, None) url = url.replace('http', 'ws') ws_url = url + 'ws?id=1' + data['id'] ws = yield tornado.websocket.websocket_connect(ws_url) msg = yield ws.read_message() self.assertIsNone(msg) self.assertIn('Websocket authentication failed', ws.close_reason)