Some fixes :3

This commit is contained in:
trollhase 2013-08-23 07:45:53 +02:00
parent c968cf1e64
commit aa0a319234

View file

@ -23,13 +23,24 @@ def mask(rights):
return m return m
def _r( (u,g,o) ):
return ( (u&7) << 6 ) + ( (g&7) << 3 ) + (o&7)
class FSNode: class FSNode:
def __init__(self,name,owner="nobody",group="nobody",rights=384,size=0, iun=1): def __init__(self,name,owner="nobody",group="nobody",rights=(6,4,4),size=0, iun=1):
self.name = name self.name = name
self.owner = owner self.owner = owner
self.group = group self.group = group
self.rights = rights
if type(rights) == tuple and len(rights) == 3:
self.rights = _r( rights )
elif type(rights) == int:
self.rights = rights
else:
self.rights = _r( (6,4,4) )
self.size = size self.size = size
self.parent = None self.parent = None
self.iun = iun self.iun = iun
@ -95,7 +106,7 @@ class FSNode:
return p return p
class Directory(FSNode): class Directory(FSNode):
def __init__(self,name,owner="nobody",group="nobody",rights=384,size=4096,files=[]): def __init__(self,name,owner="nobody",group="nobody",rights=(6,4,4),size=4096,files=[]):
FSNode.__init__(self, name=name, owner=owner, group=group,rights=rights, size=size, iun=randint(2,10)) FSNode.__init__(self, name=name, owner=owner, group=group,rights=rights, size=size, iun=randint(2,10))
self.files = files self.files = files
@ -258,8 +269,12 @@ class WelcomeMessage(FTPMessage):
FTPMessage.__init__(self,"220","FTP Server ready") FTPMessage.__init__(self,"220","FTP Server ready")
class EnteringPassiveModeMessage(FTPMessage): class EnteringPassiveModeMessage(FTPMessage):
def __init__(self,addrtuple): def __init__(self,(ip,port)):
FTPMessage.__init__(self,"227","Entering Passive Mode %s." % addrtuple) addr = ip.split(".")
addr.append( str( (port >> 8) & 0xFF ) )
addr.append( str( port & 0xFF ) )
FTPMessage.__init__(self,"227","Entering Passive Mode (%s)." % (",".join(addr) ) )
class BeginDirectoryListingMessage(FTPMessage): class BeginDirectoryListingMessage(FTPMessage):
def __init__(self): def __init__(self):
@ -309,6 +324,22 @@ class EndFileRetrieve(FTPMessage):
def __init__(self): def __init__(self):
FTPMessage.__init__(self,"226","Transfer complete") FTPMessage.__init__(self,"226","Transfer complete")
class UnableToBuildConnectionMessage(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"425","Unable to build data connection")
class CommandNotAllowedInAscii(FTPMessage):
def __init__(self,cmd):
FTPMessage.__init__(self,"550","%s not allowed in ASCII mode")
class AbortSuccessfulMessage(FTPMessage):
def __init__(self):
FTPMessage.__init__(self,"226","Abort successful")
class SystemTypeMessage(FTPMessage):
def __init__(self, sys="UNIX",typ="L8"):
FTPMessage.__init__(self,"215","%s Type: %s" % ( sys.upper(), typ ))
# Data Connection Handler # Data Connection Handler
class NListHandler: class NListHandler:
def __init__(self, directory, handler): def __init__(self, directory, handler):
@ -358,6 +389,7 @@ class State:
class MainState(State): class MainState(State):
def process(self, handler, message): def process(self, handler, message):
if message.cmd == "QUIT": if message.cmd == "QUIT":
handler.debug( "Quitting" )
handler.send( QuitMessage() ) handler.send( QuitMessage() )
handler.running = False handler.running = False
else: else:
@ -366,6 +398,7 @@ class MainState(State):
class NonAuthorizedState(MainState): class NonAuthorizedState(MainState):
def process(self, handler, message): def process(self, handler, message):
if message.cmd == "USER": if message.cmd == "USER":
handler.debug("Setting user to %s" % message.parameter)
handler.user = message.parameter handler.user = message.parameter
handler.state = AuthorizingState() handler.state = AuthorizingState()
handler.send( PasswordRequiredMessage(handler.user) ) handler.send( PasswordRequiredMessage(handler.user) )
@ -374,69 +407,81 @@ class NonAuthorizedState(MainState):
class AuthorizingState(MainState): class AuthorizingState(MainState):
def process(self, handler, message): def process(self, handler, message):
if message.cmd == "PASS": if message.cmd == "USER":
handler.debug("Changing user to %s" % message.parameter)
handler.user = message.parameter
handler.send( PasswordRequiredMessage(handler.user) )
elif message.cmd == "PASS":
password = message.parameter password = message.parameter
if handler.authorizer.authorize(handler.user, password, handler): if handler.authorizer.authorize(handler.user, password, handler):
handler.debug("User login %s successful" % handler.user) handler.debug("User login %s successful using password %s" % (handler.user,password))
handler.state = AuthorizedState() handler.state = AuthorizedState()
handler.send( AuthorizationSuccessfulMessage() ) handler.send( AuthorizationSuccessfulMessage() )
else: else:
handler.debug("User login %s failed" % handler.user) handler.debug("User login %s failed using password %s" % (handler.user, password) )
handler.state = NonAuthorizedState() handler.state = NonAuthorizedState()
handler.send( AuthorizationFailedMessage() ) handler.send( AuthorizationFailedMessage() )
else: else:
MainState.process(self, handler, message) MainState.process(self, handler, message)
class AuthorizedState(MainState): class AuthorizedState(MainState):
def addrtuple(self, ip, port):
b = ip.split(".")
b.append( str( (port >> 8) & 0xFF ) )
b.append( str( port & 0xFF ) )
return "(" + ",".join(b)+ ")"
def process(self, handler, message): def process(self, handler, message):
if message.cmd == "PASV": if message.cmd == "PASV":
port = handler.createPassiveDataConnection() addr = handler.createPassiveDataConnection()
handler.debug("Created passive data connection") handler.debug("Created passive data connection")
handler.send( EnteringPassiveModeMessage( self.addrtuple("127.0.0.1",port) ) ) handler.send( EnteringPassiveModeMessage( addr ) )
elif message.cmd in ["DELE","RMD","RNFR","RNTO","STOR"]: elif message.cmd == "DELE":
handler.debug( "Attempt to delete file %s" % message.parameter )
handler.send( OperationNotPermittedMessage() )
elif message.cmd == "RMD":
handler.debug( "Attempt to delete directory %s" % message.parameter )
handler.send( OperationNotPermittedMessage() )
elif message.cmd == "RNFR":
handler.debug( "Attempt to rename %s" % message.parameter )
handler.send( OperationNotPermittedMessage() )
elif message.cmd == "RNTO":
handler.debug( "Attempt to rename to %s" % message.parameter )
handler.send( OperationNotPermittedMessage() )
elif message.cmd == "STOR":
handler.debug( "Attempt to store a file %s" % message.parameter )
handler.send( OperationNotPermittedMessage() ) handler.send( OperationNotPermittedMessage() )
elif message.cmd == "RETR": elif message.cmd == "RETR":
node = handler.get_node(message.parameter) node = handler.get_node(message.parameter)
if node.is_file(): if node.is_file():
handler.runDataConnection( RetrieveHandler(node, handler) ) if handler.runDataConnection( RetrieveHandler(node, handler) ):
handler.debug( "Retrieving file %s" % message.parameter )
else:
handler.send( UnableToBuildConnectionMessage() )
else: else:
handler.send( OperationNotPermittedMessage() ) handler.send( OperationNotPermittedMessage() )
elif message.cmd == "PORT": elif message.cmd == "PORT":
hp = message.parameter.split(",") hp = message.parameter.split(",")
if len(hp) != 6: if len(hp) != 6:
handler.debug( "Invalid port information" )
handler.send( InvalidParametersMessage() ) handler.send( InvalidParametersMessage() )
return return
if int(hp[0]) == 10 or int(hp[0]) == 127 or int(hp[0]) == 192: #Prevent local scanning if int(hp[0]) == 10 or int(hp[0]) == 127 or int(hp[0]) == 192: #Prevent local scanning
handler.debug( "Attempt to port to local network." )
handler.send( InvalidPortCommandMessage() ) handler.send( InvalidPortCommandMessage() )
return return
addr = ( ".".join(hp[:4]), int(hp[4])<<8+int(hp[5]) ) addr = ( ".".join(hp[:4]), int(hp[4])<<8+int(hp[5]) )
handler.createActiveDataConnection(addr) handler.debug( "Creating active data connection to %s:%d" % addr )
handler.debug("Created active data connection to %s:%d" % addr) handler.createActiveDataConnection(addr)
handler.send( CommandSuccessfulMessage("PORT") ) handler.send( CommandSuccessfulMessage("PORT") )
elif message.cmd == "LIST": elif message.cmd == "LIST":
handler.debug("Listing current directory")
if handler.runDataConnection(ListHandler(handler.currentDirectory, handler)): if handler.runDataConnection(ListHandler(handler.currentDirectory, handler)):
handler.debug("successful") handler.debug("Listing current directory")
else: else:
handler.debug("failed") handler.send( UnableToBuildConnectionMessage() )
elif message.cmd == "NLST": elif message.cmd == "NLST":
handler.debug("Listing current directory (simple)")
if handler.runDataConnection(NListHandler(handler.currentDirectory)): if handler.runDataConnection(NListHandler(handler.currentDirectory)):
handler.debug("successful") handler.debug("Listing current directory (simple)")
else: else:
handler.debug("failed") handler.send( UnableToBuildConnectionMessage() )
elif message.cmd == "CWD": elif message.cmd == "CWD":
node = handler.get_node(message.parameter) node = handler.get_node(message.parameter)
if node is None or not node.is_dir(): if node is None or not node.is_dir():
@ -449,20 +494,33 @@ class AuthorizedState(MainState):
elif message.cmd == "CDUP": elif message.cmd == "CDUP":
node = handler.currentDirectory.get_parent_directory() node = handler.currentDirectory.get_parent_directory()
if node is None or not node.is_dir(): if node is None or not node.is_dir():
handler.debug("Error trying to switch to parent directory") handler.debug("Error trying to switch to non-existent parent directory")
else: else:
handler.debug("Changed working directory to "+node.get_absolute_path()) handler.debug("Changed working directory to "+node.get_absolute_path())
handler.currentDirectory = node handler.currentDirectory = node
handler.send( ChangeDirectorySuccessfulMessage() ) handler.send( ChangeDirectorySuccessfulMessage() )
elif message.cmd == "PWD": elif message.cmd == "PWD":
handler.debug( "Printing working directory" )
handler.send( WorkingDirectoryMessage(handler.currentDirectory.get_absolute_path()) ) handler.send( WorkingDirectoryMessage(handler.currentDirectory.get_absolute_path()) )
elif message.cmd == "TYPE": elif message.cmd == "TYPE":
if message.parameter == "A": if message.parameter == "A":
handler.debug("Setting type to ASCII")
handler.send( TypeSetMessage(message.parameter) ) handler.send( TypeSetMessage(message.parameter) )
else: else:
handler.debug("Unrecognized type %s" % message.parameter)
handler.send( InvalidCommandMessage("TYPE") ) handler.send( InvalidCommandMessage("TYPE") )
elif message.cmd == "NOOP": elif message.cmd == "NOOP":
handler.debug("No operation")
handler.send( CommandSuccessfulMessage("NOOP") ) handler.send( CommandSuccessfulMessage("NOOP") )
elif message.cmd == "SIZE":
handler.debug("Requested size of %s" % message.parameter)
handler.send( CommandNotAllowedInAscii("SIZE") )
elif message.cmd == "ABOR":
handler.debug("Aborting data connection")
handler.send( AbortSuccessfulMessage() )
elif message.cmd == "SYST":
handler.debug("Requested system type")
handler.send( SystemTypeMessage() )
else: else:
MainState.process(self, handler, message) MainState.process(self, handler, message)
@ -488,14 +546,13 @@ class FTPHandler(SocketServer.BaseRequestHandler):
print ("[%s] " % self.client_address[0]) + text print ("[%s] " % self.client_address[0]) + text
def send(self, message): def send(self, message):
line = str(message) self.request.send( str(message) )
self.debug("< "+line)
self.request.send( line )
def createPassiveDataConnection(self): def createPassiveDataConnection(self):
port = randint(60000,63000) port = randint(60000,63000)
self.connection = PassiveDataConnection(port) self.connection = PassiveDataConnection(port)
return port myaddr = self.request.getsockname()
return (myaddr[0],port)
def createActiveDataConnection(self,addr): def createActiveDataConnection(self,addr):
self.connection = ActiveDataConnection(addr) self.connection = ActiveDataConnection(addr)
@ -553,7 +610,6 @@ class FTPHandler(SocketServer.BaseRequestHandler):
linereader.push(data) linereader.push(data)
for line in linereader.get_lines(): for line in linereader.get_lines():
self.debug("> "+line)
message = FTPMessage.parse(line) message = FTPMessage.parse(line)
self.state.process(self,message) self.state.process(self,message)