Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
snf-ganeti
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
itminedu
snf-ganeti
Commits
be500c29
Commit
be500c29
authored
16 years ago
by
Michael Hanselmann
Browse files
Options
Downloads
Patches
Plain Diff
ganeti.http: Add support for basic HTTP authentication
As per RFC2617. Reviewed-by: amishchenko
parent
f8bd7df3
Loading
Loading
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
Makefile.am
+1
-0
1 addition, 0 deletions
Makefile.am
lib/http/auth.py
+199
-0
199 additions, 0 deletions
lib/http/auth.py
with
200 additions
and
0 deletions
Makefile.am
+
1
−
0
View file @
be500c29
...
...
@@ -102,6 +102,7 @@ rapi_PYTHON = \
http_PYTHON
=
\
lib/http/__init__.py
\
lib/http/auth.py
\
lib/http/client.py
\
lib/http/server.py
...
...
This diff is collapsed.
Click to expand it.
lib/http/auth.py
0 → 100644
+
199
−
0
View file @
be500c29
#
#
# Copyright (C) 2007, 2008 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
"""
HTTP authentication module.
"""
import
logging
import
time
import
re
import
base64
import
binascii
from
ganeti
import
constants
from
ganeti
import
utils
from
ganeti
import
http
from
cStringIO
import
StringIO
# Digest types from RFC2617
HTTP_BASIC_AUTH
=
"
Basic
"
HTTP_DIGEST_AUTH
=
"
Digest
"
# Not exactly as described in RFC2616, section 2.2, but good enough
_NOQUOTE
=
re
.
compile
(
r
"
^[-_a-z0-9]$
"
,
re
.
I
)
def
_FormatAuthHeader
(
scheme
,
params
):
"""
Formats WWW-Authentication header value as per RFC2617, section 1.2
@type scheme: str
@param scheme: Authentication scheme
@type params: dict
@param params: Additional parameters
@rtype: str
@return: Formatted header value
"""
buf
=
StringIO
()
buf
.
write
(
scheme
)
for
name
,
value
in
params
.
iteritems
():
buf
.
write
(
"
"
)
buf
.
write
(
name
)
buf
.
write
(
"
=
"
)
if
_NOQUOTE
.
match
(
value
):
buf
.
write
(
value
)
else
:
buf
.
write
(
"
\"
"
)
# TODO: Better quoting
buf
.
write
(
value
.
replace
(
"
\"
"
,
"
\\\"
"
))
buf
.
write
(
"
\"
"
)
return
buf
.
getvalue
()
class
HttpServerRequestAuthentication
(
object
):
# Default authentication realm
AUTH_REALM
=
None
def
GetAuthRealm
(
self
,
req
):
"""
Returns the authentication realm for a request.
MAY be overriden by a subclass, which then can return different realms for
different paths. Returning
"
None
"
means no authentication is needed for a
request.
@type req: L{http.server._HttpServerRequest}
@param req: HTTP request context
@rtype: str or None
@return: Authentication realm
"""
return
self
.
AUTH_REALM
def
PreHandleRequest
(
self
,
req
):
"""
Called before a request is handled.
@type req: L{http.server._HttpServerRequest}
@param req: HTTP request context
"""
realm
=
self
.
GetAuthRealm
(
req
)
# Authentication required?
if
realm
is
None
:
return
# Check "Authorization" header
if
self
.
_CheckAuthorization
(
req
):
# User successfully authenticated
return
# Send 401 Unauthorized response
params
=
{
"
realm
"
:
realm
,
}
# TODO: Support for Digest authentication (RFC2617, section 3).
# TODO: Support for more than one WWW-Authenticate header with the same
# response (RFC2617, section 4.6).
headers
=
{
http
.
HTTP_WWW_AUTHENTICATE
:
_FormatAuthHeader
(
HTTP_BASIC_AUTH
,
params
),
}
raise
http
.
HttpUnauthorized
(
headers
=
headers
)
def
_CheckAuthorization
(
self
,
req
):
"""
Checks
"
Authorization
"
header sent by client.
@type req: L{http.server._HttpServerRequest}
@param req: HTTP request context
@type credentials: str
@param credentials: Credentials sent
@rtype: bool
@return: Whether user is allowed to execute request
"""
credentials
=
req
.
request_headers
.
get
(
http
.
HTTP_AUTHORIZATION
,
None
)
if
not
credentials
:
return
False
# Extract scheme
parts
=
credentials
.
strip
().
split
(
None
,
2
)
if
len
(
parts
)
<
1
:
# Missing scheme
return
False
# RFC2617, section 1.2: "[...] It uses an extensible, case-insensitive
# token to identify the authentication scheme [...]"
scheme
=
parts
[
0
].
lower
()
if
scheme
==
HTTP_BASIC_AUTH
.
lower
():
# Do basic authentication
if
len
(
parts
)
<
2
:
raise
http
.
HttpBadRequest
(
message
=
(
"
Basic authentication requires
"
"
credentials
"
))
return
self
.
_CheckBasicAuthorization
(
req
,
parts
[
1
])
elif
scheme
==
HTTP_DIGEST_AUTH
.
lower
():
# TODO: Implement digest authentication
# RFC2617, section 3.3: "Note that the HTTP server does not actually need
# to know the user's cleartext password. As long as H(A1) is available to
# the server, the validity of an Authorization header may be verified."
pass
# Unsupported authentication scheme
return
False
def
_CheckBasicAuthorization
(
self
,
req
,
input
):
"""
Checks credentials sent for basic authentication.
@type req: L{http.server._HttpServerRequest}
@param req: HTTP request context
@type input: str
@param input: Username and password encoded as Base64
@rtype: bool
@return: Whether user is allowed to execute request
"""
try
:
creds
=
base64
.
b64decode
(
input
.
encode
(
'
ascii
'
)).
decode
(
'
ascii
'
)
except
(
TypeError
,
binascii
.
Error
,
UnicodeError
):
logging
.
exception
(
"
Error when decoding Basic authentication credentials
"
)
return
False
if
"
:
"
not
in
creds
:
return
False
(
user
,
password
)
=
creds
.
split
(
"
:
"
,
1
)
return
self
.
Authenticate
(
req
,
user
,
password
)
def
AuthenticateBasic
(
self
,
req
,
user
,
password
):
"""
Checks the password for a user.
This function MUST be overriden by a subclass.
"""
raise
NotImplementedError
()
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment