0003-auth-inject-dnsbl-function-in-condition-evaluation-c.patch
src/authentic2/utils/evaluate.py | ||
---|---|---|
93 | 93 |
def check_dnsbl(dnsbl, remote_addr): |
94 | 94 |
domain = '.'.join(reversed(remote_addr.split('.'))) + '.' + dnsbl |
95 | 95 |
exception = None |
96 |
log = logger.debug |
|
96 | 97 |
try: |
97 | 98 |
answers = dns.resolver.resolve(domain, 'A', lifetime=1) |
98 | 99 |
result = any(answer.address for answer in answers) |
... | ... | |
104 | 105 |
result = False |
105 | 106 |
except dns.exception.DNSException as e: |
106 | 107 |
exception = e |
107 |
logger.warning(f'utils: could not check dnsbl {dnsbl} for domain "%s": %s', domain, e)
|
|
108 |
log = logger.warning
|
|
108 | 109 |
result = False |
109 |
logger.debug('utils: dnsbl lookup of "%s", result=%s exception=%s', domain, result, exception)
|
|
110 |
log('utils: dnsbl lookup of "%s", result=%s exception=%s', domain, result, exception) |
|
110 | 111 |
return result |
111 | 112 | |
112 | 113 | |
... | ... | |
299 | 300 |
if on_raise is not None: |
300 | 301 |
return on_raise |
301 | 302 |
raise e |
303 | ||
304 | ||
305 |
def make_condition_context(*, request=None, **kwargs): |
|
306 |
'''Helper to make a condition context''' |
|
307 |
ctx = { |
|
308 |
'dnsbl': dnsbl, |
|
309 |
} |
|
310 |
if request: |
|
311 |
ctx['headers'] = HTTPHeaders(request) |
|
312 |
ctx['remote_addr'] = request.META.get('REMOTE_ADDR') |
|
313 |
ctx.update(kwargs) |
|
314 |
return ctx |
src/authentic2/views.py | ||
---|---|---|
62 | 62 |
from .forms import registration as registration_forms |
63 | 63 |
from .utils import misc as utils_misc |
64 | 64 |
from .utils import switch_user as utils_switch_user |
65 |
from .utils.evaluate import HTTPHeaders
|
|
65 |
from .utils.evaluate import make_condition_context
|
|
66 | 66 |
from .utils.service import get_service_from_request, get_service_from_token, set_service_ref |
67 | 67 |
from .utils.view_decorators import enable_view_restriction |
68 | 68 | |
... | ... | |
344 | 344 |
else: # New frontends API |
345 | 345 |
auth_blocks = [] |
346 | 346 |
parameters = {'request': request, 'context': context} |
347 |
remote_addr = request.META.get('REMOTE_ADDR') |
|
348 | 347 |
login_hint = set(request.session.get('login-hint', [])) |
349 |
show_ctx = dict(remote_addr=remote_addr, login_hint=login_hint, headers=HTTPHeaders(request))
|
|
348 |
show_ctx = make_condition_context(request=request, login_hint=login_hint)
|
|
350 | 349 |
if service: |
351 | 350 |
show_ctx['service_ou_slug'] = service.ou and service.ou.slug |
352 | 351 |
show_ctx['service_slug'] = service.slug |
tests/test_auth_saml.py | ||
---|---|---|
16 | 16 | |
17 | 17 |
import os |
18 | 18 |
import re |
19 |
from unittest import mock |
|
19 | 20 | |
20 | 21 |
import lasso |
21 | 22 |
import pytest |
... | ... | |
239 | 240 |
assert 'login-saml-1' not in response |
240 | 241 | |
241 | 242 | |
243 |
def test_login_condition_dnsbl(db, app, settings, caplog): |
|
244 |
settings.A2_AUTH_SAML_ENABLE = True |
|
245 |
settings.MELLON_IDENTITY_PROVIDERS = [ |
|
246 |
{"METADATA": os.path.join(os.path.dirname(__file__), 'metadata.xml')}, |
|
247 |
{"METADATA": os.path.join(os.path.dirname(__file__), 'metadata.xml')}, |
|
248 |
] |
|
249 |
settings.AUTH_FRONTENDS_KWARGS = { |
|
250 |
'saml': { |
|
251 |
'show_condition': { |
|
252 |
'0': 'remote_addr in dnsbl(\'dnswl.example.com\')', |
|
253 |
'1': 'remote_addr not in dnsbl(\'dnswl.example.com\')', |
|
254 |
} |
|
255 |
} |
|
256 |
} |
|
257 |
with mock.patch('authentic2.utils.evaluate.check_dnsbl', return_value=True): |
|
258 |
response = app.get('/login/') |
|
259 |
assert 'login-saml-0' in response |
|
260 |
assert 'login-saml-1' not in response |
|
261 | ||
262 | ||
242 | 263 |
def test_login_autorun(db, app, settings): |
243 | 264 |
response = app.get('/login/') |
244 | 265 | |
245 |
- |