4
Authenticating HTTP Server
6
This module builds on BaseHTTPServer and implements
11
from utils import VERSION, AUTHOR
22
import BufferingHTTPServer
26
from string import atoi,split
28
AUTH_ERROR_MSG="""<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
30
<TITLE>401 Authorization Required</TITLE>
32
<H1>Authorization Required</H1>
33
This server could not verify that you
34
are authorized to access the document
35
requested. Either you supplied the wrong
36
credentials (e.g., bad password), or your
37
browser doesn't understand how to supply
38
the credentials required.<P>
41
class AuthRequestHandler:
43
Simple handler that use buffering and can check for auth headers
45
In order to use it create a subclass of BufferedAuthRequestHandler
46
or BasicAuthRequestHandler depending on if you want to send
47
responses as block or as stream.
49
In your subclass you have to define the method get_userinfo(user,pw)
50
which should return 1 or None depending on whether the password was
51
ok or not. None means that the user is not authorized.
54
# False means no authentiation
57
AUTH_ERROR_MSG="""<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
59
<TITLE>401 Authorization Required</TITLE>
61
<H1>Authorization Required</H1>
62
This server could not verify that you
63
are authorized to access the document
64
requested. Either you supplied the wrong
65
credentials (e.g., bad password), or your
66
browser doesn't understand how to supply
67
the credentials required.<P>
70
server_version = "AuthHTTP/" + __version__
72
def _log(self, message):
77
Special handle method with buffering and authentication
80
self.infp=open("/tmp/in.%s" %self.__class__, "a+")
82
self.infp.write("------------------------------------------------------------------------------\n")
83
self.raw_requestline = self.rfile.readline()
84
self.infp.write(self.raw_requestline)
85
self.request_version = version = "HTTP/0.9" # Default
86
requestline = self.raw_requestline
88
# needed by send_error
89
self.command = requestline
91
if requestline[-2:] == '\r\n':
92
requestline = requestline[:-2]
93
elif requestline[-1:] == '\n':
94
requestline = requestline[:-1]
96
self.requestline = requestline
97
words = string.split(requestline)
99
[command, path, version] = words
100
if version[:5] != 'HTTP/':
101
self.send_error(400, "Bad request version (%s)" % `version`)
103
elif len(words) == 2:
104
[command, path] = words
107
"Bad HTTP/0.9 request type (%s)" % `command`)
110
self.send_error(400, "Bad request syntax (%s)" % `requestline`)
113
self.command, self.path, self.request_version = command, path, version
114
self.headers = self.MessageClass(self.rfile, 0)
115
self.infp.write(str(self.headers))
117
# test authentification
120
a=self.headers["Authorization"]
122
up2=base64.decodestring(up)
123
user,pw=string.split(up2,":")
124
if not self.get_userinfo(user,pw):
125
self.send_autherror(401,"Authorization Required"); return
127
self.send_autherror(401,"Authorization Required")
130
# check for methods starting with do_
131
mname = 'do_' + command
132
if not hasattr(self, mname):
133
self.send_error(501, "Unsupported method (%s)" % `command`)
136
method = getattr(self, mname)
143
def write_infp(self,s):
144
self.infp.write(str(s))
147
def send_response(self,code, message=None):
148
"""Override send_response to use the correct http version
151
self.log_request(code)
153
if self.responses.has_key(code):
154
message = self.responses[code][0]
158
if self.request_version != 'HTTP/0.9':
159
self._append("%s %s %s\r\n" %
160
(self.request_version, str(code), message))
162
self.send_header('Server', self.version_string())
163
self.send_header('Date', self.date_time_string())
164
self.send_header('Connection', 'close')
167
"""Common code for GET and HEAD commands.
169
This sends the response code and MIME headers.
171
Return value is either a file object (which has to be copied
172
to the outputfile by the caller unless the command was HEAD,
173
and must be closed by the caller under all circumstances), or
174
None, in which case the caller has nothing further to do.
177
path = self.translate_path(self.path)
178
if os.path.isdir(path):
179
self.send_error(403, "Directory listing not supported")
184
self.send_error(404, "File not found")
187
self.send_response(200)
188
self.send_header("Content-type", self.guess_type(path))
192
def send_autherror(self,code,message=None):
194
short, long = self.responses[code]
196
short, long = '???', '???'
201
emsg=self.AUTH_ERROR_MSG
202
self.log_error("code %d, message %s", code, message)
203
self.send_response(code, message)
204
self.send_header("WWW-Authenticate","Basic realm=\"PyWebDAV\"")
205
self.send_header("Content-Type", 'text/html')
208
lines=split(emsg,"\n")
210
self._append("%s\r\n" %l)
212
def get_userinfo(self,user):
213
""" return the password of the user
214
Override this class to return the right password
220
class BufferedAuthRequestHandler(BufferingHTTPServer.BufferedHTTPRequestHandler,AuthRequestHandler):
224
AuthRequestHandler.handle(self)
227
class BasicAuthRequestHandler(BufferingHTTPServer.BufferedHTTPRequestHandler,AuthRequestHandler):
230
""" write the string to wfile """