![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Programming Guru
![]() Join Date: Apr 2005
Posts: 1,799
Rep Power: 5
![]() |
FTP Server in Python
For Linux class I had to code a server FTP host in Python 2.3.4 for Knoppix. I've got quite a few commands working nicely, but something goes wrong after sending the LIST of files from the folder (right now it's a sample list for testing). The client doesn't respond to the sent item, even though it goes through. Anything more I send to it doesn't reply to, and I can't recieve anything from either ports. I'm stuck in a dead lock.
I assume it has something to do with the format of the file list. It may also have to do with what port I'm sending the file list from, although I know I send it to the connected passive port. If you aren't familiar in detail with how the Passive FTP system works, please don't guess your way in to a simple response. It's going to be something about an incorrect address or port dealing with how the FTP server interacts with the client (from which there is very little documentation ).import socket
import os
class ftp_server:
def __init__(self):
self.host = '10.174.28.135'
self.passive_port = 7214
self.log("""
-------------------------------
-- FTPy FTP Server in Python --
-------------------------------
Parses raw socket connections to
simulate the FTP environment.
Passive FTP for Knoppix Linux:
command : client >1023 -> server 21
data : client >1023 -> server >1023
Programmed by Aaron Voelker.
Initiating server...""")
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind(('', 21))
self.sock.listen(1)
a = self.passive_port/256
b = self.passive_port%256
self.tuple_port = (a, b)
self.host_join = ','.join(self.host.split('.'))
self.passive = False
self.log("Server initiated.")
def log(self, msg):
print msg
def get(self):
return self.conn.recv(1024).replace('\r', '').replace('\n', '')
def getcwd(self):
return os.getcwd().split(chr(92))[-1]
def put(self, ftr):
x = {
150:" Data connection accepted from %s:%s; transfer starting.\r\n226 Listing completed."%(self.host, self.passive_port),
200:" Type okay.",
220:" %s FTPy Server (Aaron Voelker) ready."%self.host,
226:" Listing completed.",
227:" Entering Passive Mode (%s,%s,%s)"%(self.host_join, self.tuple_port[0], self.tuple_port[1]),
230:" User logged in, proceed.",
250:' "/%s" is new cwd.'%self.getcwd(),
257:' "/%s" is cwd.'%self.getcwd(),
331:" User name okay, need password.",
502:" Command not implemented.",
551:" Requested action aborted. Page type unknown."
}[ftr]
s = '%s%s\r\n'%(ftr, x)
self.conn.send(s)
return s
def main(self):
self.log("Awaiting a connection...\n")
self.conn, addr = self.sock.accept ()
self.log("Connection created by %s.\nEstablishing session."%addr[0])
self.put(220)
self.log("\nStarting Instruction Loop.")
while 1:
# if self.passive:
# try:
# data = self.conn2.recv(1024)
# print data
# except socket.error:
# pass
try:
data = self.get().upper()
except socket.error:
self.log("\n-- Connection Reset, shutting down FTP.\n ")
self.conn.close()
self.sock.shutdown(socket.SHUT_RDWR)
raise socket.error
self.log(" >>> %s"%data)
if data[:4] == 'USER': s = 331
elif data[:4] == 'PASS': s = 230
elif data[:3] == 'PWD': s = 257
elif data[:4] == 'TYPE':
s = 200
# self.type = data.split(' ')[-1]
elif data[:4] == 'PASV':
# create passive port
self.sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock2.bind(('', self.passive_port ))
self.sock2.listen(1)
# self.sock2.settimeout(1)
s = self.put(227)
self.log(" <<< %s"%s)
self.log(" [Connecting to passive port %s]"%self.passive_port)
self.conn2, addr = self.sock2.accept()
self.passive = True
self.log(" [Connected]\n")
s = 0 # don't routine
elif data[:3] == 'CWD':
try:
os.chdir('..%s'%data.split(' ')[-1])
s = 250
except OSError:
s = 551
elif data[:4] == 'LIST':
s = self.put(150)
self.log(" <<< %s"%s)
s = self.passive_do(1)
self.log(" >>> %s"%s)
# s = self.put(226)
# self.log(" >>> %s"%s)
# print "<<< "+ self.conn2.recv(1024)
s = 0 # don't routine
else: s = 502
if s:
s = self.put(s)
self.log(" <<< %s"%s)
def passive_do(self, id):
if id == 1:
res = """drwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 bladerunner\r\ndrwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 cc1\r\ndrwxr-xr-x 5 ftpuser ftpusers 512 Jul 4 2002 ccgold\r\ndrwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 dune2\r\ndrwxr-xr-x 6 ftpuser ftpusers 512 Jul 26 2001 dune2000\r\ndrwxr-xr-x 6 ftpuser ftpusers 512 Oct 8 2002 earthandbeyond\r\ndrwxr-xr-x 8 ftpuser ftpusers 512 Jul 4 2002 emperor\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 firestorm\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jan 29 2003 generals\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 kyrandia1\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 kyrandia2\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 kyrandia3\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 lands1\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 lands2\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 lands3\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 lionking\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 macintosh\r\ndrwxr-xr-x 7 ftpuser ftpusers 512 Jul 26 2001 monopoly\r\ndrwxr-xr-x 7 ftpuser ftpusers 512 Jul 26 2001 nox\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jun 27 2002 pirates\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 recoil\r\ndrwxr-xr-x 6 ftpuser ftpusers 512 Jul 26 2001 redalert\r\ndrwxr-xr-x 9 ftpuser ftpusers 512 Apr 3 2002 redalert2\r\ndrwxr-xr-x 7 ftpuser ftpusers 512 Jan 29 2003 renegade\r\ndrwxr-xr-x 2 ftpuser ftpusers 512 Oct 10 2002 support\r\n-rw-r--r-- 1 ftpuser ftpusers 0 Nov 16 2004 test\r\ndrwxr-xr-x 6 ftpuser ftpusers 512 Jul 26 2001 tiberiansun\r\n-rw-r--r-- 1 ftpuser ftpusers 2368 Sep 22 2004 version.txt\r\ndrwxr-xr-x 2 ftpuser ftpusers 512 Mar 4 2003 wchat\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Aug 23 2001 youngmerlin\r\nTotal of 11 Files, 10966 Blocks.\r\n"""
self.conn2.send(res)
# self.conn2.send('\r\n') # send blank
return res
while 1:
try:
ftp_server().main()
except socket.error:
print "Rebooting server...\n" |
|
|
|
|
|
#2 |
|
Programming Guru
![]() Join Date: Apr 2005
Posts: 1,799
Rep Power: 5
![]() |
Here's an example log of the updated source
-------------------------------
-- FTPy FTP Server in Python --
-------------------------------
Parses raw socket connections to
simulate the FTP environment.
Passive FTP for Knoppix Linux:
command : client >1023 -> server 21
data : client >1023 -> server >1023
Programmed by Aaron Voelker.
Initiating server...
Server initiated.
Awaiting a connection...
Connection created by 127.0.0.1.
Establishing session.
Starting Instruction Loop.
>>> USER ANONYMOUS
<<< 331 User name okay, need password.
>>> PASS IEUSER@
<<< 230 User logged in, proceed.
>>> OPTS UTF8 ON
<<< 502 Command not implemented.
>>> PWD
<<< 257 "/python" is cwd.
>>> CWD /PYTHON/
<<< 250 "/PYTHON" is new cwd.
>>> TYPE A
<<< 200 Type okay.
>>> PASV
<<< 227 Entering Passive Mode (127,0,0,1,9,227)
[Connecting to passive port 2531]
[Connected]
>>> LIST
<<< 150 Data connection accepted from 192.168.0.136:2531; transfer starting.
<<< drwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 bladerunner
drwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 cc1
drwxr-xr-x 5 ftpuser ftpusers 512 Jul 4 2002 ccgold
drwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 dune2
drwxr-xr-x 6 ftpuser ftpusers 512 Jul 26 2001 dune2000
drwxr-xr-x 6 ftpuser ftpusers 512 Oct 8 2002 earthandbeyond
drwxr-xr-x 8 ftpuser ftpusers 512 Jul 4 2002 emperor
drwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 firestorm
drwxr-xr-x 4 ftpuser ftpusers 512 Jan 29 2003 generals
drwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 kyrandia1
drwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 kyrandia2
drwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 kyrandia3
drwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 lands1
drwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 lands2
drwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 lands3
drwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 lionking
drwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 macintosh
drwxr-xr-x 7 ftpuser ftpusers 512 Jul 26 2001 monopoly
drwxr-xr-x 7 ftpuser ftpusers 512 Jul 26 2001 nox
drwxr-xr-x 3 ftpuser ftpusers 512 Jun 27 2002 pirates
drwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 recoil
drwxr-xr-x 6 ftpuser ftpusers 512 Jul 26 2001 redalert
drwxr-xr-x 9 ftpuser ftpusers 512 Apr 3 2002 redalert2
drwxr-xr-x 7 ftpuser ftpusers 512 Jan 29 2003 renegade
drwxr-xr-x 2 ftpuser ftpusers 512 Oct 10 2002 support
-rw-r--r-- 1 ftpuser ftpusers 0 Nov 16 2004 test
drwxr-xr-x 6 ftpuser ftpusers 512 Jul 26 2001 tiberiansun
-rw-r--r-- 1 ftpuser ftpusers 2368 Sep 22 2004 version.txt
drwxr-xr-x 2 ftpuser ftpusers 512 Mar 4 2003 wchat
drwxr-xr-x 3 ftpuser ftpusers 512 Aug 23 2001 youngmerlin
<<< 226 Listing completed.And here's the updated source: import socket
import os
class ftp_server:
def __init__(self):
self.host = '192.168.0.136'
self.passive_port = 2531
self.log("""
-------------------------------
-- FTPy FTP Server in Python --
-------------------------------
Parses raw socket connections to
simulate the FTP environment.
Passive FTP for Knoppix Linux:
command : client >1023 -> server 21
data : client >1023 -> server >1023
Programmed by Aaron Voelker.
Initiating server...""")
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.bind(('', 21))
self.sock.listen(1)
a = self.passive_port/256
b = self.passive_port%256
self.tuple_port = (a, b)
self.host_join = ','.join(self.host.split('.'))
self.passive = False
self.log("Server initiated.")
def log(self, msg):
f = open("logs.txt", "a")
f.write(msg+'\n')
f.close()
def get(self):
return self.conn.recv(1024).replace('\r', '').replace('\n', '')
def getcwd(self):
return os.getcwd().split(chr(92))[-1]
def put(self, ftr):
x = {
150:" Data connection accepted from %s:%s; transfer starting."%(self.host, self.passive_port),
200:" Type okay.",
220:" %s FTPy Server (Aaron Voelker) ready."%self.host,
226:" Listing completed.",
227:" Entering Passive Mode (%s,%s,%s)"%(self.addr_join, self.tuple_port[0], self.tuple_port[1]),
230:" User logged in, proceed.",
250:' "/%s" is new cwd.'%self.getcwd(),
257:' "/%s" is cwd.'%self.getcwd(),
331:" User name okay, need password.",
502:" Command not implemented.",
551:" Requested action aborted. Page type unknown."
}[ftr]
s = '%s%s\r\n'%(ftr, x)
self.conn.send(s)
return s
def main(self):
self.log("Awaiting a connection...\n")
self.conn, self.addr = self.sock.accept ()
self.addr_join = ','.join(self.addr[0].split('.'))
self.log("Connection created by %s.\nEstablishing session."%self.addr[0])
self.put(220)
self.log("\nStarting Instruction Loop.")
while 1:
# if self.passive:
# try:
# data = self.conn2.recv(1024)
# print data
# except socket.error:
# pass
try:
data = self.get().upper()
except socket.error:
self.log("\n-- Connection Reset, shutting down FTP.\n ")
self.conn.close()
self.sock.shutdown(socket.SHUT_RDWR)
if self.passive:
self.conn2.close()
self.sock2.shutdown(socket.SHUT_RDWR)
raise socket.error
self.log(" >>> %s"%data)
if data[:4] == 'USER': s = 331
elif data[:4] == 'PASS': s = 230
elif data[:3] == 'PWD': s = 257
elif data[:4] == 'TYPE':
s = 200
# self.type = data.split(' ')[-1]
elif data[:4] == 'PASV':
# create passive port
self.sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock2.bind((self.addr[0], self.passive_port))
self.sock2.listen(1)
# self.sock2.settimeout(1)
s = self.put(227)
self.log(" <<< %s"%s)
self.log(" [Connecting to passive port %s]"%self.passive_port)
self.conn2, addr = self.sock2.accept()
self.passive = True
self.log(" [Connected]\n")
s = 0 # don't routine
elif data[:3] == 'CWD':
try:
os.chdir('..%s'%data.split(' ')[-1])
s = 250
except OSError:
s = 551
elif data[:4] == 'LIST':
s = self.put(150)
self.log(" <<< %s"%s)
s = self.passive_do(1)
self.log(" <<< %s"%s)
s = self.put(226)
self.log(" <<< %s"%s)
# print "<<< "+ self.conn2.recv(1024)
s = 0 # don't routine
else: s = 502
if s:
s = self.put(s)
self.log(" <<< %s"%s)
def passive_do(self, id):
if id == 1:
res = """drwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 bladerunner\r\ndrwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 cc1\r\ndrwxr-xr-x 5 ftpuser ftpusers 512 Jul 4 2002 ccgold\r\ndrwxr-xr-x 5 ftpuser ftpusers 512 Jul 26 2001 dune2\r\ndrwxr-xr-x 6 ftpuser ftpusers 512 Jul 26 2001 dune2000\r\ndrwxr-xr-x 6 ftpuser ftpusers 512 Oct 8 2002 earthandbeyond\r\ndrwxr-xr-x 8 ftpuser ftpusers 512 Jul 4 2002 emperor\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 firestorm\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jan 29 2003 generals\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 kyrandia1\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 kyrandia2\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 kyrandia3\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 lands1\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 lands2\r\ndrwxr-xr-x 4 ftpuser ftpusers 512 Jul 26 2001 lands3\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 lionking\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 macintosh\r\ndrwxr-xr-x 7 ftpuser ftpusers 512 Jul 26 2001 monopoly\r\ndrwxr-xr-x 7 ftpuser ftpusers 512 Jul 26 2001 nox\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jun 27 2002 pirates\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Jul 26 2001 recoil\r\ndrwxr-xr-x 6 ftpuser ftpusers 512 Jul 26 2001 redalert\r\ndrwxr-xr-x 9 ftpuser ftpusers 512 Apr 3 2002 redalert2\r\ndrwxr-xr-x 7 ftpuser ftpusers 512 Jan 29 2003 renegade\r\ndrwxr-xr-x 2 ftpuser ftpusers 512 Oct 10 2002 support\r\n-rw-r--r-- 1 ftpuser ftpusers 0 Nov 16 2004 test\r\ndrwxr-xr-x 6 ftpuser ftpusers 512 Jul 26 2001 tiberiansun\r\n-rw-r--r-- 1 ftpuser ftpusers 2368 Sep 22 2004 version.txt\r\ndrwxr-xr-x 2 ftpuser ftpusers 512 Mar 4 2003 wchat\r\ndrwxr-xr-x 3 ftpuser ftpusers 512 Aug 23 2001 youngmerlin\r\n"""
self.conn2.send(res)
# self.conn2.send('\r\n') # send blank
return res
while 1:
try:
ftp_server().main()
except socket.error:
print "Rebooting server...\n"But I still can't quite get it to work. It must be something about the wrong ports. Yes, the file list is sent through the passive port after attaining a connection. |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|