source: TI05-delivery/trunk/lib/python/pybbftp/server.py @ 1333

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/trunk/lib/python/pybbftp/server.py@1333
Revision 1333, 6.6 KB checked in by spascoe, 15 years ago (diff)

Moved python logging code into pybbftp.server

Line 
1"""
2Start a bbftp server process and define python callbacks for authentication and authorisation.
3
4Interface to the BBftp server.
5
6@copyright Copyright (C) 2006 CCLRC & NERC
7@license This software may be distributed under the terms of the Q Public Licence, version 1.0 or later.
8
9@author Stephen Pascoe
10"""
11
12#!NOTE: Importing bbftpd and bbftpc together is dangerous and will cause stange errors.
13#       However if the module is being scanned by epydoc allow the import (This is a hack!)
14import sys
15if sys.modules.has_key('pybbftp.bbftpc') and not sys.modules.has_key('epydoc'):
16    raise ImportError, "pybbftp.bbftpc extension already loaded.  You cannot use both client and server extensions together"
17
18import bbftpd
19
20class TROPT:
21    """Static class containing constants used by bbftp in the transferoption parameter.
22
23    TROPT.X always corresponds to TROPT_X as defined in bbftpd/structures.h.
24    Options that aren't likely to be used for the delivery service are not
25    included (e.g. TROPT_RFIO).
26
27    @cvar TMP always use temporary name.
28    @cvar ACC keep access and modification time.
29    @cvar MODE keep mode.
30    @cvar DIR create all dirs in path.
31    """
32    TMP = bbftpd.TROPT_TMP
33    ACC = bbftpd.TROPT_ACC
34    MODE = bbftpd.TROPT_MODE
35    DIR = bbftpd.TROPT_DIR
36
37class MSG:
38    """Static class containing message codes used by bbftp.
39
40    MSG.X corresponds to MSG_X or MSG_X_V2 as defined in bbftpd/structures.h.
41    Message codes not returned by the auth/authz interface are not included.
42
43    @cvar CHDIR a chdir request.
44    @cvar LIST a ls/dir request.
45    @cvar MKDIR a mkdir request.
46    @cvar RM a rm request.
47    @cvar STAT a stat request.
48    @cvar DF a statfs request.
49    """
50    CHDIR = bbftpd.MSG_CHDIR_V2
51    LIST = bbftpd.MSG_LIST_V2
52    MKDIR = bbftpd.MSG_MKDIR_V2
53    RM = bbftpd.MSG_RM
54    STAT = bbftpd.MSG_STAT
55    DF = bbftpd.MSG_DF
56   
57
58# Import all LOG_* levels from syslog.
59import syslog
60for x in dir(syslog):
61    if x[:4] == 'LOG_':
62        globals()[x] = getattr(syslog, x)
63
64#--------------------------------------------------------------------------------------------------------------
65
66def start(authHandler, args):
67    """Start the bbftp server.
68
69    The server performs a fork() during initialisation, the child process remains in
70    the server's main loop and the parent returns from this function.  The server process
71    calls authHandler.authorise() on each connection to do authentication/authorisation.
72
73    @note because the server process forks, authHandler will not see any changes to the python
74        interpreter following the call to start().
75
76    @param authHandler an instance of AuthHandler.
77    @param args a list of command line arguments.
78    @return the PID of the server process.
79    """
80   
81    return bbftpd.run(authHandler, args)
82
83
84class AuthenticationFailure(Exception):
85    """Signals authentication failed.
86    """
87    pass
88
89class AuthorisationFailure(Exception):
90    """Signals authorisation failed.
91    """
92    pass
93
94
95
96class AuthHandler(object):
97    """Abstract base class for implementing authentication.
98
99    Subclasses should implement the authorise() method to authenticate clients connecting to
100    the server.  An AuthHandler object is passed to start() when initialising the server.
101    """
102   
103    def send(self, buffer):
104        """Send a message to the client during authentication
105
106        This method must only be used from within self.authenticate() which has been called
107        from the bbftp server process started by start().
108
109        @param buffer a string containing the message to send.
110        """
111   
112        return bbftpd.send(buffer)
113
114    def recv(self):
115        """Receive a message from the client during authentication
116
117        This method must only be used from within self.authenticate() which has been called
118        from the bbftp server process started by start().
119
120        @return a string containing the message received.
121        """
122
123        return bbftpd.recv()
124
125    def authenticate(self):
126        """Authenticate a connection.
127
128        This function should be overridden in subclasses to implement authentication using
129        the method calls self.send() and send.recv().  It is called by the bbftp server process
130        created using the start() function.
131
132        @note because the server process forks on each connection, calls to authorise() will
133            see the state of the python interpreter as it was when start() was called.
134
135        @return an AuthzHandler instance if authentication succeeds.  Any false value is considered
136            an authorisation failure.
137        @raise AuthorisationFailure the preferred way of signaling authorisation failure to
138            the bbftp server process.
139        """
140
141        raise NotImplementedError
142
143    def log(self, priority, msg):
144        """Send a message to the bbftpd logger.
145
146        @param priority one of server.LOG_*
147        @param msg the message to log
148        """
149        bbftpd.log(priority, msg)
150
151
152class AuthzHandler(object):
153    """Abstract base class for implementing authorisation.
154
155    @ivar username: the client's username.  This attribute must be set before an instance of AuthzHandler
156        is returned to the bbftp server process by AuthHandler.authenticate().
157       
158    """
159
160    def authzControl(self, msgcode, transferoption, path):
161        """Authorise a control command.
162
163        @param msgcode the command type.
164        @param transferoption extra options specified in the command.
165        @param path the file or directory to which the command applies.
166        @return bool for success or failure.
167        """
168
169        raise NotImplementedError
170
171    def authzRetr(self, path):
172        """Authorise a retrieve request.
173
174        @param path the file being retrieved.
175        @return bool for success or failure.
176        """
177
178        raise NotImplementedError
179
180    def authzStore(self, path):
181        """Authorise a store request.
182
183        @param path the destination file.
184        @return bool for success or failure.
185        """
186
187        raise NotImplementedError
188
189    def log(self, priority, msg):
190        """Send a message to the bbftpd logger.
191
192        @param priority one of server.LOG_*
193        @param msg the message to log
194        """
195        bbftpd.log(priority, msg)
196
197
198#--------------------------------------------------------------------------------------------------------------
199
200
201class LiberalAuthzHandler(AuthzHandler):
202    """Allow everything.
203    """
204
205    def __init__(self, username):
206        self.username = username
207
208    def authzControl(self, m, t, p):
209        return True;
210
211    def authzRetr(self, p):
212        return True;
213
214    def authzStore(self, p):
215        return True;
216   
Note: See TracBrowser for help on using the repository browser.