Dateien nach "src" hochladen
This commit is contained in:
110
src/terminal_backend.py
Normal file
110
src/terminal_backend.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import os
|
||||||
|
import pty
|
||||||
|
import select
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
from flask import session, request, render_template
|
||||||
|
from flask_socketio import emit
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
clients = {}
|
||||||
|
running_threads = {}
|
||||||
|
|
||||||
|
|
||||||
|
def init_terminal_routes(app, socketio, db, Vault, LocalUser, fernet):
|
||||||
|
|
||||||
|
@app.route('/terminal/<vault_id>')
|
||||||
|
def terminal(vault_id):
|
||||||
|
if 'user' not in session:
|
||||||
|
return "Nicht eingeloggt", 403
|
||||||
|
|
||||||
|
current_user = db.session.query(LocalUser).filter_by(username=session['user']).first()
|
||||||
|
vault = db.session.query(Vault).filter_by(id=vault_id).first()
|
||||||
|
|
||||||
|
if not current_user or not vault:
|
||||||
|
return "Nicht gefunden", 404
|
||||||
|
|
||||||
|
if current_user.role == 'user' and vault not in current_user.vaults:
|
||||||
|
return "Kein Zugriff", 403
|
||||||
|
|
||||||
|
return render_template('terminal.html', vault_id=vault_id)
|
||||||
|
|
||||||
|
@socketio.on('connect', namespace='/terminal')
|
||||||
|
def handle_connect(auth):
|
||||||
|
vault_id = auth.get('vault_id') if auth else None
|
||||||
|
if not vault_id:
|
||||||
|
emit('output', 'Kein Vault angegeben.')
|
||||||
|
return
|
||||||
|
|
||||||
|
current_user = db.session.query(LocalUser).filter_by(username=session['user']).first()
|
||||||
|
vault = db.session.query(Vault).filter_by(id=vault_id).first()
|
||||||
|
|
||||||
|
if not vault or (current_user.role == 'user' and vault not in current_user.vaults):
|
||||||
|
emit('output', 'Zugriff verweigert.')
|
||||||
|
return
|
||||||
|
|
||||||
|
sid = request.sid
|
||||||
|
|
||||||
|
def spawn_shell():
|
||||||
|
try:
|
||||||
|
hostname = vault.host_ip or vault.hostname
|
||||||
|
if vault.auth_type == 'password':
|
||||||
|
decrypted_pw = fernet.decrypt(vault.password_hash.encode()).decode()
|
||||||
|
ssh_cmd = f"sshpass -p {shlex.quote(decrypted_pw)} ssh -o StrictHostKeyChecking=no -p {vault.port} {vault.user}@{hostname}"
|
||||||
|
else:
|
||||||
|
key_path = f"/tmp/sshkey_{vault.id}.pem"
|
||||||
|
with open(key_path, "w") as f:
|
||||||
|
f.write(vault.ssh_key)
|
||||||
|
os.chmod(key_path, 0o600)
|
||||||
|
ssh_cmd = f"ssh -i {key_path} -o StrictHostKeyChecking=no -p {vault.port} {vault.user}@{hostname}"
|
||||||
|
|
||||||
|
def read(fd):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = os.read(fd, 1024)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
socketio.emit('output', data.decode(errors='ignore'), namespace='/terminal', to=sid)
|
||||||
|
except OSError:
|
||||||
|
break
|
||||||
|
|
||||||
|
pid, fd = pty.fork()
|
||||||
|
if pid == 0:
|
||||||
|
os.execvp("bash", ["bash", "-c", ssh_cmd])
|
||||||
|
|
||||||
|
clients[sid] = fd
|
||||||
|
thread = Thread(target=read, args=(fd,))
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
running_threads[sid] = thread
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
emit('output', f'Fehler beim Starten der Shell: {e}')
|
||||||
|
|
||||||
|
thread = Thread(target=spawn_shell)
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
@socketio.on('input', namespace='/terminal')
|
||||||
|
def handle_input(data):
|
||||||
|
sid = request.sid
|
||||||
|
fd = clients.get(sid)
|
||||||
|
if fd:
|
||||||
|
try:
|
||||||
|
os.write(fd, data.encode())
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ INPUT-Fehler: {e}")
|
||||||
|
|
||||||
|
@socketio.on('disconnect', namespace='/terminal')
|
||||||
|
def handle_disconnect():
|
||||||
|
sid = request.sid
|
||||||
|
fd = clients.pop(sid, None)
|
||||||
|
if fd:
|
||||||
|
try:
|
||||||
|
os.close(fd)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
thread = running_threads.pop(sid, None)
|
||||||
|
if thread and thread.is_alive():
|
||||||
|
print(f"Thread für SID {sid} wird beendet (disconnect).")
|
Reference in New Issue
Block a user