mirror of
https://github.com/dkmstr/openuds.git
synced 2025-03-13 08:58:35 +03:00
Updated os_detector to use Sec-Ch-Ua-Platform and Sec-Ch-Ua for os detection if available instead of user agent (left user agent as fallback anyway). Better for chrome bases browsers.
This commit is contained in:
parent
c5171c014b
commit
974f652df0
@ -53,7 +53,7 @@ MOBILE_OS_LIST: typing.Final[tuple[types.os.KnownOS, ...]] = tuple(set(ALL_OS_LI
|
||||
DEFAULT_OS: typing.Final[types.os.KnownOS] = types.os.KnownOS.WINDOWS
|
||||
|
||||
|
||||
knownBrowsers = tuple(types.os.KnownBrowser)
|
||||
knownBrowsers: typing.Final[tuple[types.os.KnownBrowser, ...]] = tuple(types.os.KnownBrowser)
|
||||
|
||||
browsersREs: dict[types.os.KnownBrowser, tuple] = {
|
||||
types.os.KnownBrowser.FIREFOX: (re.compile(r'Firefox/([0-9.]+)'),),
|
||||
|
@ -41,7 +41,7 @@ class DetectedOsInfo(typing.NamedTuple):
|
||||
|
||||
|
||||
class KnownOS(enum.Enum):
|
||||
LINUX = ('Linux', 'armv7l')
|
||||
LINUX = ('Linux',) # previusly got 'armv7l'
|
||||
CHROME_OS = ('CrOS',)
|
||||
WINDOWS_PHONE = ('Windows Phone',)
|
||||
WINDOWS = ('Windows',)
|
||||
@ -58,15 +58,16 @@ class KnownOS(enum.Enum):
|
||||
def __str__(self):
|
||||
return self.os_name()
|
||||
|
||||
# Order is important here, as we will use the first match
|
||||
class KnownBrowser(enum.StrEnum):
|
||||
# Known browsers
|
||||
FIREFOX = 'Firefox'
|
||||
SEAMONKEY = 'Seamonkey'
|
||||
CHROME = 'Chrome'
|
||||
CHROMIUM = 'Chromium'
|
||||
EDGE = 'Microsoft Edge'
|
||||
SAFARI = 'Safari'
|
||||
OPERA = 'Opera'
|
||||
CHROME = 'Chrome'
|
||||
CHROMIUM = 'Chromium'
|
||||
IEXPLORER = 'Explorer'
|
||||
EDGE = 'Edge'
|
||||
OTHER = 'Other'
|
||||
|
||||
|
@ -41,50 +41,76 @@ from uds.core import types, consts
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
def getOsFromUA(
|
||||
ua: typing.Optional[str],
|
||||
def detect_os(
|
||||
headers: collections.abc.Mapping[str, typing.Any],
|
||||
) -> types.os.DetectedOsInfo:
|
||||
"""
|
||||
Basic OS Client detector (very basic indeed :-))
|
||||
"""
|
||||
ua = ua or types.os.KnownOS.UNKNOWN.value[0]
|
||||
ua = (headers.get('User-Agent') or types.os.KnownOS.UNKNOWN.value[0])
|
||||
|
||||
res = types.os.DetectedOsInfo(os=types.os.KnownOS.UNKNOWN, browser=types.os.KnownBrowser.OTHER, version='0.0')
|
||||
found: bool = False
|
||||
for os in consts.os.KNOWN_OS_LIST:
|
||||
if found:
|
||||
break
|
||||
for osName in os.value:
|
||||
if osName in ua:
|
||||
res = res._replace(os=os)
|
||||
found = True
|
||||
res = types.os.DetectedOsInfo(
|
||||
os=types.os.KnownOS.UNKNOWN, browser=types.os.KnownBrowser.OTHER, version='0.0'
|
||||
)
|
||||
|
||||
# First, try to detect from Sec-Ch-Ua-Platform
|
||||
# Remember all Sec... headers are only available on secure connections
|
||||
secChUaPlatform = headers.get('Sec-Ch-Ua-Platform')
|
||||
found = types.os.KnownOS.UNKNOWN
|
||||
|
||||
if secChUaPlatform is not None:
|
||||
# Strip initial and final " chars if present
|
||||
secChUaPlatform = secChUaPlatform.strip('"')
|
||||
for os in consts.os.KNOWN_OS_LIST:
|
||||
if secChUaPlatform in os.value:
|
||||
found = os
|
||||
break
|
||||
else: # Try to detect from User-Agent
|
||||
ual = ua.lower()
|
||||
for os in consts.os.KNOWN_OS_LIST:
|
||||
if os.os_name().lower() in ual:
|
||||
found = os
|
||||
break
|
||||
|
||||
match = None
|
||||
# If we found a known OS, store it
|
||||
if found != types.os.KnownOS.UNKNOWN:
|
||||
res = res._replace(os=found)
|
||||
|
||||
ruleKey, ruleValue = None, None
|
||||
for ruleKey, ruleValue in consts.os.browserRules.items():
|
||||
must, mustNot = ruleValue
|
||||
# Try to detect browser from Sec-Ch-Ua first
|
||||
secChUa = headers.get('Sec-Ch-Ua')
|
||||
if secChUa is not None:
|
||||
for browser in consts.os.knownBrowsers:
|
||||
if browser in secChUa:
|
||||
res = res._replace(browser=browser)
|
||||
break
|
||||
else:
|
||||
# Try to detect browser from User-Agent
|
||||
match = None
|
||||
|
||||
for mustRe in consts.os.browsersREs[must]:
|
||||
match = mustRe.search(ua)
|
||||
if match is None:
|
||||
continue
|
||||
# Check against no maching rules
|
||||
for mustNotREs in mustNot:
|
||||
for cre in consts.os.browsersREs[mustNotREs]:
|
||||
if cre.search(ua) is not None:
|
||||
match = None
|
||||
break
|
||||
ruleKey, ruleValue = None, None
|
||||
for ruleKey, ruleValue in consts.os.browserRules.items():
|
||||
must, mustNot = ruleValue
|
||||
|
||||
for mustRe in consts.os.browsersREs[must]:
|
||||
match = mustRe.search(ua)
|
||||
if match is None:
|
||||
continue
|
||||
# Check against no maching rules
|
||||
for mustNotREs in mustNot:
|
||||
for cre in consts.os.browsersREs[mustNotREs]:
|
||||
if cre.search(ua) is not None:
|
||||
match = None
|
||||
break
|
||||
if match is None:
|
||||
break
|
||||
if match is not None:
|
||||
break
|
||||
if match is not None:
|
||||
break
|
||||
if match is not None:
|
||||
break
|
||||
|
||||
if match is not None:
|
||||
res = res._replace(browser=ruleKey, version=match.groups(1)[0])
|
||||
if match is not None:
|
||||
res = res._replace(browser=ruleKey, version=match.groups(1)[0])
|
||||
|
||||
logger.debug('Detected: %s %s', res.os, res.browser)
|
||||
|
||||
return res
|
||||
|
@ -136,7 +136,7 @@ def _process_request(request: 'ExtendedHttpRequest') -> typing.Optional['HttpRes
|
||||
request.authorized = request.session.get(AUTHORIZED_KEY, False)
|
||||
|
||||
# Ensures request contains os
|
||||
request.os = OsDetector.getOsFromUA(request.META.get('HTTP_USER_AGENT', 'Unknown'))
|
||||
request.os = OsDetector.detect_os(request.headers)
|
||||
|
||||
# Ensures that requests contains the valid user
|
||||
_get_user(request)
|
||||
|
@ -40,7 +40,7 @@ from django.views.decorators.cache import never_cache
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
from uds.web.util import errors
|
||||
from uds.core import auths, types
|
||||
from uds.core import auths, types, exceptions
|
||||
from uds.core.auths.auth import (
|
||||
webLogin,
|
||||
webLogout,
|
||||
@ -107,14 +107,12 @@ def authCallback_stage2(request: 'ExtendedHttpRequestWithUser', ticketId: str) -
|
||||
|
||||
result = authenticateViaCallback(authenticator, params, request)
|
||||
|
||||
# os = OsDetector.getOsFromUA(request.META['HTTP_USER_AGENT'])
|
||||
|
||||
if result.url:
|
||||
raise auths.exceptions.Redirect(result.url)
|
||||
raise exceptions.auth.Redirect(result.url)
|
||||
|
||||
if result.user is None:
|
||||
authLogLogin(request, authenticator, f'{params}', 'Invalid at auth callback')
|
||||
raise auths.exceptions.InvalidUserException()
|
||||
raise exceptions.auth.InvalidUserException()
|
||||
|
||||
response = HttpResponseRedirect(reverse('page.index'))
|
||||
|
||||
@ -131,9 +129,9 @@ def authCallback_stage2(request: 'ExtendedHttpRequestWithUser', ticketId: str) -
|
||||
response = HttpResponseRedirect(reverse('page.mfa'))
|
||||
|
||||
return response
|
||||
except auths.exceptions.Redirect as e:
|
||||
except exceptions.auth.Redirect as e:
|
||||
return HttpResponseRedirect(request.build_absolute_uri(str(e)) if e.args and e.args[0] else '/')
|
||||
except auths.exceptions.Logout as e:
|
||||
except exceptions.auth.Logout as e:
|
||||
return webLogout(
|
||||
request,
|
||||
request.build_absolute_uri(str(e)) if e.args and e.args[0] else None,
|
||||
@ -214,7 +212,7 @@ def ticketAuth(
|
||||
password = CryptoManager().decrypt(data['password'])
|
||||
except Exception:
|
||||
logger.error('Ticket stored is not valid')
|
||||
raise auths.exceptions.InvalidUserException() from None
|
||||
raise exceptions.auth.InvalidUserException() from None
|
||||
|
||||
auth = Authenticator.objects.get(uuid=auth)
|
||||
# If user does not exists in DB, create it right now
|
||||
@ -232,7 +230,7 @@ def ticketAuth(
|
||||
|
||||
usr = auth.getOrCreateUser(username, realname)
|
||||
if usr is None or State.isActive(usr.state) is False: # If user is inactive, raise an exception
|
||||
raise auths.exceptions.InvalidUserException()
|
||||
raise exceptions.auth.InvalidUserException()
|
||||
|
||||
# Add groups to user (replace existing groups)
|
||||
usr.groups.set(grps) # type: ignore
|
||||
|
Loading…
x
Reference in New Issue
Block a user