~ubuntu-branches/ubuntu/oneiric/moin/oneiric-security

« back to all changes in this revision

Viewing changes to MoinMoin/auth/http.py

  • Committer: Bazaar Package Importer
  • Author(s): Jamie Strandboge
  • Date: 2010-03-30 12:55:34 UTC
  • mfrom: (0.1.17 sid)
  • Revision ID: james.westby@ubuntu.com-20100330125534-4c2ufc1rok24447l
Tags: 1.9.2-2ubuntu1
* Merge from Debian testing (LP: #521834). Based on work by Stefan Ebner.
  Remaining changes:
 - Remove python-xml from Suggests field, the package isn't anymore in
   sys.path.
 - Demote fckeditor from Recommends to Suggests; the code was previously
   embedded in moin, but it was also disabled, so there's no reason for us
   to pull this in by default currently. Note: This isn't necessary anymore
   but needs a MIR for fckeditor, so postpone dropping this change until
   lucid+1
* debian/rules:
  - Replace hardcoded python2.5 with python* and hardcore python2.6 for ln
* debian/control.in: drop versioned depends on cdbs

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
"""
3
3
    MoinMoin - http authentication
4
4
 
5
 
    You need either your webserver configured for doing HTTP auth (like Apache
6
 
    reading some .htpasswd file) or Twisted (will accept HTTP auth against
7
 
    password stored in moin user profile, but currently will NOT ask for auth)
8
 
    or Standalone (in which case it will ask for auth and accept auth against
9
 
    stored user profile.)
10
 
 
11
 
    @copyright: 2006 MoinMoin:ThomasWaldmann
12
 
                2007 MoinMoin:JohannesBerg
 
5
    HTTPAuth
 
6
    ========
 
7
 
 
8
    HTTPAuth is just a dummy redirecting to MoinMoin.auth.GivenAuth for backwards
 
9
    compatibility.
 
10
 
 
11
    Please fix your setup, this dummy will be removed soon:
 
12
 
 
13
    Old (1.8.x):
 
14
    ------------
 
15
    from MoinMoin.auth.http import HTTPAuth
 
16
    auth = [HTTPAuth(autocreate=True)]
 
17
    # any presence (or absence) of 'http' auth name, e.g.:
 
18
    auth_methods_trusted = ['http', 'xmlrpc_applytoken']
 
19
 
 
20
    New (1.9.x):
 
21
    ------------
 
22
    from MoinMoin.auth import GivenAuth
 
23
    auth = [GivenAuth(autocreate=True)]
 
24
    # presence (or absence) of 'given' auth name, e.g.:
 
25
    auth_methods_trusted = ['given', 'xmlrpc_applytoken']
 
26
 
 
27
    HTTPAuthMoin
 
28
    ============
 
29
 
 
30
    HTTPAuthMoin is HTTP auth done by moin (not by your web server).
 
31
 
 
32
    Moin will request HTTP Basic Auth and use the HTTP Basic Auth header it
 
33
    receives to authenticate username/password against the moin user profiles.
 
34
 
 
35
    from MoinMoin.auth.http import HTTPAuthMoin
 
36
    auth = [HTTPAuthMoin()]
 
37
    # check if you want 'http' auth name in there:
 
38
    auth_methods_trusted = ['http', 'xmlrpc_applytoken']
 
39
 
 
40
    @copyright: 2009 MoinMoin:ThomasWaldmann
13
41
    @license: GNU GPL, see COPYING for details.
14
42
"""
15
43
 
 
44
from MoinMoin import log
 
45
logging = log.getLogger(__name__)
 
46
 
16
47
from MoinMoin import config, user
17
 
from MoinMoin.request import request_twisted, request_cli, request_standalone
18
 
from MoinMoin.auth import BaseAuth
19
 
from base64 import decodestring
20
 
 
21
 
class HTTPAuth(BaseAuth):
22
 
    """ authenticate via http basic/digest/ntlm auth """
 
48
from MoinMoin.auth import BaseAuth, GivenAuth
 
49
 
 
50
 
 
51
class HTTPAuth(GivenAuth):
 
52
    name = 'http'  # GivenAuth uses 'given'
 
53
 
 
54
    def __init__(self, *args, **kwargs):
 
55
        logging.warning("DEPRECATED use of MoinMoin.auth.http.HTTPAuth, please read instructions there or docs/CHANGES!")
 
56
        GivenAuth.__init__(self, *args, **kwargs)
 
57
 
 
58
 
 
59
class HTTPAuthMoin(BaseAuth):
 
60
    """ authenticate via http (basic) auth """
23
61
    name = 'http'
24
62
 
25
 
    def __init__(self, autocreate=False):
 
63
    def __init__(self, autocreate=False, realm='MoinMoin', coding='iso-8859-1'):
26
64
        self.autocreate = autocreate
 
65
        self.realm = realm
 
66
        self.coding = coding
27
67
        BaseAuth.__init__(self)
28
68
 
29
69
    def request(self, request, user_obj, **kw):
36
76
        if user_obj:
37
77
            return user_obj, True
38
78
 
39
 
        # for standalone, request authorization and verify it,
40
 
        # deny access if it isn't verified
41
 
        if isinstance(request, request_standalone.Request):
42
 
            request.setHttpHeader('WWW-Authenticate: Basic realm="MoinMoin"')
43
 
            auth = request.headers.get('Authorization')
44
 
            if auth:
45
 
                auth = auth.split()[-1]
46
 
                info = decodestring(auth).split(':', 1)
47
 
                if len(info) == 2:
48
 
                    u = user.User(request, auth_username=info[0], password=info[1],
49
 
                                  auth_method=self.name, auth_attribs=[])
50
 
            if not u:
51
 
                request.makeForbidden(401, _('You need to log in.'))
52
 
        # for Twisted, just check
53
 
        elif isinstance(request, request_twisted.Request):
54
 
            username = request.twistd.getUser().decode(config.charset)
55
 
            password = request.twistd.getPassword().decode(config.charset)
56
 
            # when using Twisted http auth, we use username and password from
57
 
            # the moin user profile, so both can be changed by user.
58
 
            u = user.User(request, auth_username=username, password=password,
59
 
                          auth_method=self.name, auth_attribs=())
60
 
        elif not isinstance(request, request_cli.Request):
61
 
            env = request.env
62
 
            auth_type = env.get('AUTH_TYPE', '').lower()
63
 
            if auth_type in ['basic', 'digest', 'ntlm', 'negotiate', ]:
64
 
                username = env.get('REMOTE_USER', '').decode(config.charset)
65
 
                if auth_type in ('ntlm', 'negotiate', ):
66
 
                    # converting to standard case so the user can even enter wrong case
67
 
                    # (added since windows does not distinguish between e.g.
68
 
                    #  "Mike" and "mike")
69
 
                    username = username.split('\\')[-1] # split off domain e.g.
70
 
                                                        # from DOMAIN\user
71
 
                    # this "normalizes" the login name from {meier, Meier, MEIER} to Meier
72
 
                    # put a comment sign in front of next line if you don't want that:
73
 
                    username = username.title()
74
 
                # when using http auth, we have external user name and password,
75
 
                # we don't use the moin user profile for those attributes.
76
 
                u = user.User(request, auth_username=username,
77
 
                              auth_method=self.name, auth_attribs=('name', 'password'))
78
 
 
 
79
        auth = request.authorization
 
80
        if auth and auth.username and auth.password is not None:
 
81
            logging.debug("http basic auth, received username: %r password: %r" % (
 
82
                          auth.username, auth.password))
 
83
            u = user.User(request,
 
84
                          name=auth.username.decode(self.coding),
 
85
                          password=auth.password.decode(self.coding),
 
86
                          auth_method=self.name, auth_attribs=[])
 
87
            logging.debug("user: %r" % u)
 
88
 
 
89
        if not u or not u.valid:
 
90
            from werkzeug import Response, abort
 
91
            response = Response(_('Please log in first.'), 401,
 
92
                                {'WWW-Authenticate': 'Basic realm="%s"' % self.realm})
 
93
            abort(response)
 
94
 
 
95
        logging.debug("u: %r" % u)
79
96
        if u and self.autocreate:
 
97
            logging.debug("autocreating user")
80
98
            u.create_or_update()
81
99
        if u and u.valid:
 
100
            logging.debug("returning valid user %r" % u)
82
101
            return u, True # True to get other methods called, too
83
102
        else:
 
103
            logging.debug("returning %r" % user_obj)
84
104
            return user_obj, True
 
105