[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server/FTP - TestFilesystemAccess.py:1.1.2.1 UsernamePassword.py:1.1.2.1 FTPServer.py:1.1.2.11 FTPServerChannel.py:1.1.2.21 PublisherFTPServer.py:1.1.2.6 RecvChannel.py:1.1.2.7 XmitChannel.py:1.1.2.6
Shane Hathaway
shane@cvs.zope.org
Wed, 10 Apr 2002 17:59:52 -0400
Update of /cvs-repository/Zope3/lib/python/Zope/Server/FTP
In directory cvs.zope.org:/tmp/cvs-serv18340/FTP
Modified Files:
Tag: Zope3-Server-Branch
FTPServer.py FTPServerChannel.py PublisherFTPServer.py
RecvChannel.py XmitChannel.py
Added Files:
Tag: Zope3-Server-Branch
TestFilesystemAccess.py UsernamePassword.py
Log Message:
- Removed AlternateSocketMapMixin. It was there to support multiple socket
maps, but if we really need multiple socket maps, it would be better to
change asyncore. Had to update a lot of __init__ methods.
- Added IUsernamePassword and IFilesystemAccess, which provide a way to
implement all kinds of authentication schemes without FTP knowing about
any of the details. Modified FTPServerChannel to work based on an
IFilesystemAccess object.
- Added detection of the ZOPE_SERVER_DEBUG env var.
- Added comments here and there.
- Fixed CRs :-)
=== Added File Zope3/lib/python/Zope/Server/FTP/TestFilesystemAccess.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Implementation of IFilesystemAccess intended only for testing.
$Id: TestFilesystemAccess.py,v 1.1.2.1 2002/04/10 21:59:21 shane Exp $
"""
from Zope.Server.VFS.IFilesystemAccess import IFilesystemAccess
from Zope.Server.VFS.IUsernamePassword import IUsernamePassword
from Zope.Exceptions import Unauthorized
class TestFilesystemAccess:
__implements__ = IFilesystemAccess
passwords = {'foo': 'bar'}
def __init__(self, fs):
self.fs = fs
def authenticate(self, credentials):
if not IUsernamePassword.isImplementedBy(credentials):
raise Unauthorized
name = credentials.getUserName()
if not self.passwords.has_key(name):
raise Unauthorized
if credentials.getPassword() != self.passwords[name]:
raise Unauthorized
def open(self, credentials):
self.authenticate(credentials)
return self.fs
=== Added File Zope3/lib/python/Zope/Server/FTP/UsernamePassword.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id: UsernamePassword.py,v 1.1.2.1 2002/04/10 21:59:21 shane Exp $
"""
from Zope.Server.VFS.IUsernamePassword import IUsernamePassword
class UsernamePassword:
__implements__ = IUsernamePassword
def __init__(self, username, password):
self.username = username
self.password = password
def getUserName(self):
return self.username
def getPassword(self):
return self.password
=== Zope3/lib/python/Zope/Server/FTP/FTPServer.py 1.1.2.10 => 1.1.2.11 ===
from FTPServerChannel import FTPServerChannel
from Zope.Server.ServerBase import ServerBase
+from Zope.Server.VFS.IFilesystemAccess import IFilesystemAccess
-from Zope.Server.VFS.UnixFileSystem import \
- SchizophrenicUnixFileSystem
-from Zope.Server.Authentication.DictionaryAuthentication import \
- DictionaryAuthentication
-
-
-class FileSystemOpener:
-
- filesystem_class = SchizophrenicUnixFileSystem
-
- def __init__(self, root_dir):
- self.root_dir = root_dir
-
- def __call__(self, username):
- persona = pwd.getpwnam(username)[2:4]
- return self.filesystem_class(self.root_dir, persona)
class FTPServer(ServerBase):
@@ -45,24 +30,23 @@
SERVER_IDENT = 'Zope.Server.FTPServer'
- def __init__(self, ip, port, dir='/', auth_source=None,
- task_dispatcher=None, adj=None, start=1, hit_log=None,
- verbose=0, socket_map=None):
-
- self.openFilesystem = FileSystemOpener(dir)
- self.auth_source = auth_source
-
- super(FTPServer, self).__init__(ip, port, task_dispatcher,
- adj, start, hit_log,
- verbose, socket_map)
+ def __init__(self, ip, port, fs_access, *args, **kw):
+
+ assert IFilesystemAccess.isImplementedBy(fs_access)
+ self.fs_access = fs_access
+
+ super(FTPServer, self).__init__(ip, port, *args, **kw)
if __name__ == '__main__':
from Zope.Server.TaskThreads import ThreadedTaskDispatcher
+ from Zope.Server.VFS.OSFileSystem import OSFileSystem
+ from TestFilesystemAccess import TestFilesystemAccess
td = ThreadedTaskDispatcher()
td.setThreadCount(4)
- auth_source = DictionaryAuthentication({'root': 'bar'})
- FTPServer('', 8021, '/', auth_source, task_dispatcher=td)
+ fs = OSFileSystem('/')
+ fs_access = TestFilesystemAccess(fs)
+ FTPServer('', 8021, fs_access, task_dispatcher=td)
try:
while 1:
asyncore.poll(5)
=== Zope3/lib/python/Zope/Server/FTP/FTPServerChannel.py 1.1.2.20 => 1.1.2.21 ===
from RecvChannel import RecvChannel
from XmitChannel import XmitChannel, ApplicationXmitStream
+from UsernamePassword import UsernamePassword
+from Zope.Exceptions import Unauthorized
class FTPServerChannel(LineServerChannel):
@@ -70,9 +72,8 @@
type_mode_map = {'a':'t', 'i':'b', 'e':'b', 'l':'b'}
- def __init__(self, server, conn, addr, adj=None, socket_map=None):
- super(FTPServerChannel, self).__init__(server, conn, addr,
- adj, socket_map)
+ def __init__(self, server, conn, addr, adj=None):
+ super(FTPServerChannel, self).__init__(server, conn, addr, adj)
self.client_addr = (addr[0], 21)
@@ -85,14 +86,14 @@
self._rnfr = None
self.username = ''
- self.password = ''
+ self.credentials = None
self.reply('SERVER_READY', self.server.server_name)
def _getFilesystem(self):
- """Open the filesystem using the username and password."""
- return self.server.openFilesystem(self.username, self.password)
+ """Open the filesystem using the current credentials."""
+ return self.server.fs_access.open(self.credentials)
############################################################
@@ -222,13 +223,18 @@
def cmd_pass(self, args):
'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
- self.password = args
- self.authenticated, message = self.authenticate()
- if self.authenticated:
- self.reply('LOGIN_SUCCESS')
- else:
+ self.authenticated = 0
+ password = args
+ credentials = UsernamePassword(self.username, password)
+ try:
+ self.server.fs_access.authenticate(credentials)
+ except Unauthorized:
self.reply('LOGIN_MISMATCH')
self.close_when_done()
+ else:
+ self.credentials = credentials
+ self.authenticated = 1
+ self.reply('LOGIN_SUCCESS')
def cmd_pasv(self, args):
@@ -439,6 +445,7 @@
def cmd_user(self, args):
'See Zope.Server.FTP.IFTPCommandHandler.IFTPCommandHandler'
+ self.authenticated = 0
if len(args) > 1:
self.username = args
self.reply('PASS_REQUIRED')
@@ -454,17 +461,13 @@
path = args
else:
path = os.path.join(self.cwd, args)
- path = os.path.normpath(path)
+ # Note: don't use os.path.normpath() here! Otherwise Zope won't
+ # work on case-insensitive platforms.
return path
- def authenticate(self):
- auth = self.server.auth_source
- return auth.authenticate(self.username, self.password)
-
-
def newPassiveAcceptor(self):
- # ensure that only one of these exists at a time.
+ # ensure that only one of these exists at a time.
if self.passive_acceptor is not None:
self.passive_acceptor.close()
self.passive_acceptor = None
=== Zope3/lib/python/Zope/Server/FTP/PublisherFTPServer.py 1.1.2.5 => 1.1.2.6 ===
def __init__(self, request_factory, name, ip, port,
task_dispatcher=None, adj=None, start=1, hit_log=None,
- verbose=0, socket_map=None):
+ verbose=0):
self.request_factory = request_factory
self.openFilesystem = PublisherFileSystemOpener('/', request_factory)
super(PublisherFTPServer, self).__init__(ip, port, task_dispatcher,
adj, start, hit_log,
- verbose, socket_map)
+ verbose)
=== Zope3/lib/python/Zope/Server/FTP/RecvChannel.py 1.1.2.6 => 1.1.2.7 ===
_fileno = None # provide a default for asyncore.dispatcher._fileno
- def __init__ (self, control_channel, finish_args,
- adj=None, socket_map=None):
+ def __init__ (self, control_channel, finish_args):
self.control_channel = control_channel
self.finish_args = finish_args
self.inbuf = OverflowableBuffer(control_channel.adj.inbuf_overflow)
- ChannelBaseClass.__init__(self, None, None, adj, socket_map)
+ ChannelBaseClass.__init__(self, None, None, control_channel.adj)
# Note that this channel starts out in async mode.
def writable (self):
=== Zope3/lib/python/Zope/Server/FTP/XmitChannel.py 1.1.2.5 => 1.1.2.6 ===
_fileno = None # provide a default for asyncore.dispatcher._fileno
- def __init__ (self, control_channel, ok_reply_args,
- adj=None, socket_map=None):
+ def __init__ (self, control_channel, ok_reply_args):
self.control_channel = control_channel
self.ok_reply_args = ok_reply_args
self.set_sync()
- ChannelBaseClass.__init__(self, None, None, adj, socket_map)
+ ChannelBaseClass.__init__(self, None, None, control_channel.adj)
def _open(self):
"""Signal the client to open the connection."""