Added SSL for Client and server. LIST still buggy.

This commit is contained in:
devoalda 2023-03-20 20:49:26 +08:00
parent 6f22116691
commit 9cb37654fc
5 changed files with 185 additions and 39 deletions

33
SSL/certificate.pem Normal file
View File

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

52
SSL/privatekey.pem Normal file
View File

@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
jsryOfVmeGQ4HMfMdrYsCMTG4QBDo84=
-----END PRIVATE KEY-----

View File

@ -1,19 +1,34 @@
import os
import socket
from socket import *
import configparser
import ssl
import sys
CLIENT_FILE = "clientfile"
BUFFER_SIZE = 1024
# TODO: Buggy after some time, Not everything is transmitted
def handle_list(conn, args):
# send command over
conn.sendall("LIST\r\n".encode())
num_of_files_received = 0
num_of_files = int(conn.recv(BUFFER_SIZE).decode('utf-8'))
print("Total files in directory: "+ str(num_of_files))
num_of_files = 0
# Receive response from server
# Decode bytes to string
response = conn.recv(BUFFER_SIZE).decode('utf-8').strip()
try:
num_of_files = int(response)
except ValueError:
print(response)
return
while num_of_files_received < num_of_files:
file_info = conn.recv(BUFFER_SIZE).decode('utf-8')
print(file_info)
# Print response
print(conn.recv(BUFFER_SIZE).decode('utf-8').strip())
num_of_files_received += 1
response = conn.recv(BUFFER_SIZE).decode('utf-8')
print(response)
def handle_quit(conn, args):
conn.sendall("QUIT\r\n".encode())
@ -24,6 +39,7 @@ def handle_quit(conn, args):
conn.close()
return True
def handle_DWLD(conn, args):
# send command over
filename = args
@ -41,6 +57,7 @@ def handle_DWLD(conn, args):
print(response)
os.chdir("../")
def handle_UPLD(conn, args):
filename = args
os.chdir(os.path.abspath(CLIENT_FILE))
@ -50,15 +67,15 @@ def handle_UPLD(conn, args):
bytes_sent = 0
file_size = os.path.getsize(filename)
conn.sendall(f"UPLD {filename} {file_size}\r".encode())
#does file exist at the server?
# does file exist at the server?
serverExist = conn.recv(BUFFER_SIZE).decode('utf-8')
#if server already has the file
# if server already has the file
if serverExist == 'T':
#do you want to overwrite?
# do you want to overwrite?
print(conn.recv(BUFFER_SIZE).decode('utf-8'))
overwrite = input()
conn.sendall(overwrite.encode('utf-8'))
#yes, overwrite
# yes, overwrite
if overwrite.upper() == 'Y':
with open(filename, "rb") as f:
while bytes_sent < file_size:
@ -68,12 +85,12 @@ def handle_UPLD(conn, args):
response = conn.recv(BUFFER_SIZE).decode().strip()
print(response)
os.chdir("../")
#no, dont overwrite
# no, dont overwrite
elif overwrite.upper() == 'N':
response = conn.recv(BUFFER_SIZE).decode().strip()
print(response)
os.chdir("../")
#server doesnt have the file
# server doesnt have the file
elif serverExist == 'F':
print(conn.recv(BUFFER_SIZE).decode('utf-8'))
with open(filename, "rb") as f:
@ -85,11 +102,13 @@ def handle_UPLD(conn, args):
print(response)
os.chdir("../")
def handle_HELP(conn, args):
conn.sendall(f"HELP\r".encode())
response = conn.recv(BUFFER_SIZE).decode('utf-8')
print(response)
def user_input():
# Get user input
user_input = input("> ").strip()
@ -103,8 +122,12 @@ def user_input():
return command, args
def ftp_cient(host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def ftp_client(host, port, cert):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
context.load_verify_locations(cert)
context.check_hostname = False
sock = context.wrap_socket(socket(AF_INET, SOCK_STREAM), server_hostname=host)
sock.connect((host, port))
response = sock.recv(BUFFER_SIZE).decode().strip()
@ -119,7 +142,7 @@ def ftp_cient(host, port):
command, args = user_input, ""
if command.upper() == "LIST":
sock.sendall("LIST\r\n".encode())
# sock.sendall("LIST\r\n".encode())
handle_list(sock, args)
elif command.upper() == "QUIT":
handle_quit(sock, args)
@ -146,4 +169,17 @@ def ftp_cient(host, port):
if __name__ == "__main__":
# FTP Client should be able to define IP and port
ftp_cient("127.0.0.1", 2001)
config = configparser.ConfigParser()
config.read('./config/config.ini')
ip = config['FTPSERVER']['ip']
port = int(config['FTPSERVER']['port'])
cert = config['SSL']['cert']
try:
ftp_client(ip, port, cert)
except KeyboardInterrupt:
print("Client interrupted")
try:
sys.exit(0)
except SystemExit:
os._exit(0)

7
config/config.ini Normal file
View File

@ -0,0 +1,7 @@
[FTPSERVER]
ip = 127.0.0.1
port = 5000
[SSL]
cert = ./SSL/certificate.pem
key = ./SSL/privatekey.pem

View File

@ -5,17 +5,19 @@ import sys
import threading
import struct
import time
import configparser
BUFFER_SIZE = 1024
SERVER_FILE = "serverfile"
# TODO: Buggy after some time, Not everything is transmitted
def handle_list(conn, args):
#conn.send(b'150 Opening ASCII mode data connection for file list.\n')
#home_directory = os.path.expanduser('~')
os.chdir(os.path.abspath(SERVER_FILE))
files = os.listdir(os.getcwd())
#send number of files over
conn.sendall(str(len(files)).encode('utf-8'))
conn.sendall(str(len(files)).encode('utf-8') +b'\r\n')
for file in files:
file_info = os.stat(file)
@ -29,7 +31,6 @@ def handle_list(conn, args):
if not files:
conn.sendall(b'226 No files in directory.\n')
os.chdir("../")
conn.sendall(b'226 Transfer complete.\n')
def handle_upload(conn, args):
filename = args[1]
@ -161,22 +162,28 @@ def handle_connection(conn):
conn.sendall(b'220 Welcome to the FTP server.\n')
while True:
data = conn.recv(BUFFER_SIZE).decode()
print(f'Server received: {data}')
if not data:
break
args = data.split()
command = args[0]
print(f'Command: {command}')
if command in commands:
if commands == handle_quit:
conn.sendall(b'Closing Connection')
conn.close()
try:
data = conn.recv(BUFFER_SIZE).decode()
print(f'Server received: {data}')
if not data:
break
commands[command](conn, args)
else:
conn.sendall(b'Invalid command.\n')
args = data.split()
command = args[0]
print(f'Command: {command}')
if command in commands:
if commands == handle_quit:
conn.sendall(b'Closing Connection')
conn.close()
break
commands[command](conn, args)
else:
conn.sendall(b'Invalid command.\n')
except ConnectionResetError:
print('Connection closed by client')
break
except OSError as e:
print(e)
break
# For FTP client testing
#handle_pwd(conn, [])
@ -192,12 +199,23 @@ def main():
# print("Usage: python3 server.py <port>")
# return
#context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
#context.load_cert_chain("certificate.pem", "privatekey.pem")
config = configparser.ConfigParser()
config.read('./config/config.ini')
port = 2001
#server = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_side=True)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# TODO: Need to allow user to define port through command line as well
port = int(config['FTPSERVER']['port'])
cert = config['SSL']['cert']
key = config['SSL']['key']
# print(cert, key)
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
# context.load_cert_chain("./SSL/certificate.pem", "./SSL/privatekey.pem")
context.load_cert_chain(cert,key)
#port = 2001
server = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_side=True)
# server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('', port))
server.listen(1)
print("Listening on port", port)