source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/applications/admin/models/access.py

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 6.0 KB
Line 
1import base64
2import os
3import time
4from gluon.admin import apath
5from gluon.fileutils import read_file
6from gluon.utils import web2py_uuid
7from pydal.contrib import portalocker
8# ###########################################################
9# ## make sure administrator is on localhost or https
10# ###########################################################
11
12
13http_host = request.env.http_host.split(':')[0]
14
15if request.env.web2py_runtime_gae:
16    session_db = DAL('gae')
17    session.connect(request, response, db=session_db)
18    hosts = (http_host, )
19    is_gae = True
20else:
21    is_gae = False
22
23if request.is_https:
24    session.secure()
25elif not request.is_local and not DEMO_MODE:
26    raise HTTP(200, T('Admin is disabled because insecure channel'))
27
28try:
29    _config = {}
30    port = int(request.env.server_port or 0)
31    restricted(
32        read_file(apath('../parameters_%i.py' % port, request)), _config)
33
34    if not 'password' in _config or not _config['password']:
35        raise HTTP(200, T('admin disabled because no admin password'))
36except IOError:
37    import gluon.fileutils
38    if is_gae:
39        if gluon.fileutils.check_credentials(request):
40            session.authorized = True
41            session.last_time = time.time()
42        else:
43            raise HTTP(200,
44                       T('admin disabled because not supported on google app engine'))
45    else:
46        raise HTTP(
47            200, T('admin disabled because unable to access password file'))
48
49
50def verify_password(password):
51    session.pam_user = None
52    if DEMO_MODE:
53        ret = True
54    elif not _config.get('password'):
55        ret = False
56    elif _config['password'].startswith('pam_user:'):
57        session.pam_user = _config['password'][9:].strip()
58        import gluon.contrib.pam
59        ret = gluon.contrib.pam.authenticate(session.pam_user, password)
60    else:
61        ret = _config['password'] == CRYPT()(password)[0]
62    if ret:
63        session.hmac_key = web2py_uuid()
64    return ret
65
66
67# ###########################################################
68# ## handle brute-force login attacks
69# ###########################################################
70
71deny_file = os.path.join(request.folder, 'private', 'hosts.deny')
72allowed_number_of_attempts = 5
73expiration_failed_logins = 3600
74
75
76def read_hosts_deny():
77    import datetime
78    hosts = {}
79    if os.path.exists(deny_file):
80        hosts = {}
81        f = open(deny_file, 'r')
82        portalocker.lock(f, portalocker.LOCK_SH)
83        for line in f.readlines():
84            if not line.strip() or line.startswith('#'):
85                continue
86            fields = line.strip().split()
87            if len(fields) > 2:
88                hosts[fields[0].strip()] = (  # ip
89                    int(fields[1].strip()),  # n attemps
90                    int(fields[2].strip())   # last attempts
91                    )
92        portalocker.unlock(f)
93        f.close()
94    return hosts
95
96
97def write_hosts_deny(denied_hosts):
98    f = open(deny_file, 'w')
99    portalocker.lock(f, portalocker.LOCK_EX)
100    for key, val in denied_hosts.items():
101        if time.time() - val[1] < expiration_failed_logins:
102            line = '%s %s %s\n' % (key, val[0], val[1])
103            f.write(line)
104    portalocker.unlock(f)
105    f.close()
106
107def login_record(success=True):
108    denied_hosts = read_hosts_deny()
109    val = (0, 0)
110    if success and request.client in denied_hosts:
111        del denied_hosts[request.client]
112    elif not success:
113        val = denied_hosts.get(request.client, (0, 0))
114        if time.time() - val[1] < expiration_failed_logins \
115            and val[0] >= allowed_number_of_attempts:
116            return val[0]  # locked out
117        time.sleep(2 ** val[0])
118        val = (val[0] + 1, int(time.time()))
119        denied_hosts[request.client] = val
120    write_hosts_deny(denied_hosts)
121    return val[0]
122
123def failed_login_count():
124    denied_hosts = read_hosts_deny()
125    val = denied_hosts.get(request.client, (0, 0))
126    return val[0]
127
128
129# ###########################################################
130# ## session expiration
131# ###########################################################
132
133t0 = time.time()
134if session.authorized:
135
136    if session.last_time and session.last_time < t0 - EXPIRATION:
137        session.flash = T('session expired')
138        session.authorized = False
139    else:
140        session.last_time = t0
141
142
143if request.vars.is_mobile in ('true', 'false', 'auto'):
144    session.is_mobile = request.vars.is_mobile or 'auto'
145if request.controller == 'default' and request.function == 'index':
146    if not request.vars.is_mobile:
147        session.is_mobile = 'auto'
148if not session.is_mobile:
149    session.is_mobile = 'auto'
150if session.is_mobile == 'true':
151    is_mobile = True
152elif session.is_mobile == 'false':
153    is_mobile = False
154else:
155    is_mobile = request.user_agent().get('is_mobile',False)
156
157if DEMO_MODE:
158    session.authorized = True
159    session.forget()
160
161if request.controller == "webservices":
162    basic = request.env.http_authorization
163    if not basic or not basic[:6].lower() == 'basic ':
164        raise HTTP(401, "Wrong credentials")
165    (username, password) = base64.b64decode(basic[6:]).split(':')
166    if not verify_password(password) or MULTI_USER_MODE:
167        time.sleep(10)
168        raise HTTP(403, "Not authorized")
169elif not session.authorized and not \
170    (request.controller + '/' + request.function in
171     ('default/index', 'default/user', 'plugin_jqmobile/index', 'plugin_jqmobile/about')):
172
173    if request.env.query_string:
174        query_string = '?' + request.env.query_string
175    else:
176        query_string = ''
177
178    if request.env.web2py_original_uri:
179        url = request.env.web2py_original_uri
180    else:
181        url = request.env.path_info + query_string
182    redirect(URL(request.application, 'default', 'index', vars=dict(send=url)))
183elif session.authorized and \
184     request.controller == 'default' and \
185     request.function == 'index':
186    redirect(URL(request.application, 'default', 'site'))
187
188if request.controller == 'appadmin' and DEMO_MODE:
189    session.flash = 'Appadmin disabled in demo mode'
190    redirect(URL('default', 'sites'))
Note: See TracBrowser for help on using the repository browser.