diff --git a/functions/ftp_server.py b/functions/ftp_server.py new file mode 100755 index 00000000..86bbeb18 --- /dev/null +++ b/functions/ftp_server.py @@ -0,0 +1,90 @@ +import os +import socket +import threading +import sys +import random + +def handle_client(client_socket, root_folder, username, password): + authenticated = False + try: + client_socket.send("220 Welcome to the FTP server\r\n".encode()) + + while True: + request = client_socket.recv(1024).decode().strip() + if not request: + break + + if request.startswith("USER"): + if request.split()[1] == username: + client_socket.send("331 User name okay, need password.\r\n".encode()) + else: + client_socket.send("530 Invalid username.\r\n".encode()) + break + elif request.startswith("PASS"): + if request.split()[1] == password and not authenticated: + client_socket.send("230 User logged in, proceed.\r\n".encode()) + authenticated = True + else: + client_socket.send("530 Authentication failed.\r\n".encode()) + break + elif authenticated: + if request.startswith("PWD"): + client_socket.send(f"257 \"{root_folder}\" is the current directory.\r\n".encode()) + elif request.startswith("LIST"): + # This is a placeholder for proper LIST command handling with data connection + client_socket.send("150 Here comes the directory listing.\r\n".encode()) + client_socket.send("This would be the file list\r\n".encode()) + client_socket.send("226 Directory send OK.\r\n".encode()) + elif request.startswith("TYPE"): + type_code = request.split()[1] + if type_code.upper() == 'I': + client_socket.send("200 Switching to Binary mode.\r\n".encode()) + elif type_code.upper() == 'A': + client_socket.send("200 Switching to ASCII mode.\r\n".encode()) + else: + client_socket.send("504 Command not implemented for that parameter.\r\n".encode()) + elif request.startswith("PASV"): + # Dummy response for PASV command + client_socket.send("227 Entering Passive Mode (127,0,0,1,204,173).\r\n".encode()) + elif request.startswith("PORT"): + # Dummy response for PORT command + client_socket.send("200 PORT command successful.\r\n".encode()) + else: + client_socket.send("500 Syntax error, command unrecognized.\r\n".encode()) + else: + client_socket.send("530 Please login with USER and PASS.\r\n".encode()) + + except Exception as e: + print(f"Error: {e}") + + finally: + client_socket.close() + +def start_ftp_server(root_folder, port, username, password): + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind(('localhost', port)) + server_socket.listen(5) + print("FTP server started on port", port) + + try: + while True: + client_socket, client_address = server_socket.accept() + print(f"Accepted connection from {client_address}") + client_handler = threading.Thread(target=handle_client, args=(client_socket, root_folder, username, password)) + client_handler.start() + + except KeyboardInterrupt: + print("Shutting down the server.") + server_socket.close() + +if __name__ == "__main__": + if len(sys.argv) != 5: + print("Usage: python3 ftp_server.py root_path port username password") + sys.exit(1) + + root_folder = os.path.expanduser(sys.argv[1]) + port_number = int(sys.argv[2]) + username = sys.argv[3] + password = sys.argv[4] + + start_ftp_server(root_folder, port_number, username, password) diff --git a/functions/sftp_server.sh b/functions/sftp_server.sh deleted file mode 100644 index 6e3b9a35..00000000 --- a/functions/sftp_server.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -port=22 -ip=$(hostname -I | awk '{print $1}') - -# Set the log file path -log_file="$rdhome/.logs/sftp_server.log" - -# TODO: add nc or find an alternative command -# Check if the port is in use -if nc -z localhost $port; then - zenity --error --no-wrap \ - --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" \ - --title "RetroDECK - SFTP Server" \ - --text="Port $port is already in use. Please stop any services on that port and try again." - exit 1 -fi - -# Create a temporary directory for SFTP chroot -mkdir -p /tmp/sftp_home/retrodeck/etc -echo "retrodeck:$(openssl passwd -1 retrodeck)" >> /tmp/sftp_home/retrodeck/etc/passwd - -# Set rdhome as the home directory for retrodeck user -mkdir -p /var/config/retrodeck/ssh -echo "Match User retrodeck\n ChrootDirectory $rdhome" >> /var/config/retrodeck/ssh/sshd_config - -# Redirect SSHD logs to the specified log file -echo "Match User retrodeck\n ChrootDirectory $rdhome\n ForceCommand internal-sftp -l INFO -f $log_file" >> /var/config/retrodeck/ssh/sshd_config - -# Start SSHD with SFTP support and specific user and password -nohup sshd -p $port -o PasswordAuthentication=yes -o PubkeyAuthentication=no -o AuthorizedKeysFile=/dev/null -o UsePAM=no -o AllowTcpForwarding=no -o PermitRootLogin=no -o ChrootDirectory=/tmp/sftp_home/retrodeck & - -# Get the PID of the SSH/SFTP server process -ssh_pid=$! - -# Function to stop the SSH/SFTP server -stop_ssh_server() { - kill -9 $ssh_pid - rm -rf /tmp/sftp_home - exit 0 -} - -# Create a Zenity window with only the "Stop" button -zenity --icon-name=net.retrodeck.retrodeck --info --no-wrap \ - --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" \ - --title "RetroDECK - SFTP Server" \ - --text="SFTP server started.\n\nAddress: $ip\nport: $port\nID:\tretrodeck\nPassword:\tretrodeck\npointing to:\n$rdhome\n\nPress Stop to terminate the server." --ok-label="Stop" || stop_ssh_server - -# If the user clicks "Stop", call the function to stop the SSH/SFTP server -stop_ssh_server diff --git a/functions/start_ftp_server.sh b/functions/start_ftp_server.sh new file mode 100755 index 00000000..ad504805 --- /dev/null +++ b/functions/start_ftp_server.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Function to stop the FTP server +stop_server() { + if [ -n "$SERVER_PID" ]; then + kill $SERVER_PID + pkill -f ftp_server.py + fi +} + +# Start the FTP server +ftp_id="RetroDECK" +ftp_pass="RetroDECK" +ftp_port=6346 +rdhome="/home/jay/retrodeck" #DEBUG +python3 /home/jay/gits/RetroDECK/functions/ftp_server.py "$rdhome" "$ftp_port" "$ftp_id" "$ftp_pass" & +SERVER_PID=$(pgrep -f "python3 /home/jay/gits/RetroDECK/functions/ftp_server.py") + +# Main menu with only "Stop" button +zenity --info --text="FTP server started, log in with:\n\nID: $ftp_id\nPassword: $ftp_pass\nPort: $ftp_port.\n\nPress 'Stop' when done" --ok-label="Stop" +stop_server \ No newline at end of file