forked from UTSAVS26/PyVerse
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
47 lines (43 loc) · 1.7 KB
/
Copy pathserver.py
File metadata and controls
47 lines (43 loc) · 1.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import asyncio
import websockets
from client.utils import encrypt, decrypt, derive_key
from auth import check_token
import subprocess
import argparse
import json
clients = {}
async def handle_connection(websocket, path, token, key):
encrypted_auth = await websocket.recv()
try:
decrypted_data = decrypt(encrypted_auth, key)
auth_data = json.loads(decrypted_data.decode('utf-8'))
except Exception as e:
await websocket.send(encrypt(b"AUTH_FAILED", key))
return
if not check_token(auth_data.get("token"), token):
await websocket.send(encrypt("AUTH_FAILED", key))
return
await websocket.send(encrypt("AUTH_SUCCESS", key))
while True:
try:
enc_cmd = await websocket.recv()
cmd = decrypt(enc_cmd, key)
output = subprocess.getoutput(cmd)
await websocket.send(encrypt(output, key))
except websockets.ConnectionClosed:
break
async def main(host, port, token, password):
# TODO: in production, generate a random salt and persist it securely
salt = b'secure-shell-salt'
key = derive_key(password, salt)
async with websockets.serve(lambda ws, path: handle_connection(ws, path, token, key), host, port):
print(f"[*] Server running on {host}:{port}")
await asyncio.Future() # Run forever
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--host", default="0.0.0.0")
parser.add_argument("--port", type=int, required=True)
parser.add_argument("--token", required=True)
parser.add_argument("--password", required=True)
args = parser.parse_args()
asyncio.run(main(args.host, args.port, args.token, args.password))