Some fixes :3
This commit is contained in:
parent
c968cf1e64
commit
aa0a319234
1 changed files with 89 additions and 33 deletions
122
fakeftp.py
122
fakeftp.py
|
@ -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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue