Lines 304-309
class UMCP_Dispatcher(object):
|
Link Here
|
---|
|
304 |
except KeyError: |
304 |
except KeyError: |
305 |
CORE.info('Session %r not found' % (sessionid,)) |
305 |
CORE.info('Session %r not found' % (sessionid,)) |
306 |
|
306 |
|
|
|
307 |
@classmethod |
308 |
def session_timeout_timer(cls): |
309 |
now = time.time() |
310 |
for sessionid, user in list(Ressource.sessions.items()): |
311 |
session = UMCP_Dispatcher.sessions.get(sessionid) |
312 |
if (not session or not session._requestid2response_queue) and user.timed_out(now): |
313 |
CORE.info('session %r timed out' % (sessionid,)) |
314 |
Ressource.sessions.pop(user.sessionid, None) |
315 |
user.on_logout() |
316 |
return True # execute again! |
317 |
|
307 |
|
318 |
|
308 |
class UploadManager(dict): |
319 |
class UploadManager(dict): |
309 |
|
320 |
|
Lines 359-393
class QueueRequest(object):
|
Link Here
|
---|
|
359 |
|
370 |
|
360 |
class User(object): |
371 |
class User(object): |
361 |
|
372 |
|
362 |
__slots__ = ('sessionid', 'username', 'password', 'saml', '_time_remaining') |
373 |
__slots__ = ('sessionid', 'username', 'password', 'saml', '_timeout') |
363 |
|
374 |
|
364 |
def __init__(self, sessionid, username, password, saml=None): |
375 |
def __init__(self, sessionid, username, password, saml=None): |
365 |
self.sessionid = sessionid |
376 |
self.sessionid = sessionid |
366 |
self.username = username |
377 |
self.username = username |
367 |
self.password = password |
378 |
self.password = password |
368 |
self.saml = saml |
379 |
self.saml = saml |
369 |
self._time_remaining = _session_timeout |
|
|
370 |
self.reset_timeout() |
380 |
self.reset_timeout() |
371 |
|
381 |
|
372 |
def reset_timeout(self): |
382 |
def reset_timeout(self): |
373 |
self._time_remaining = self.session_validity |
383 |
self._timeout = time.time() + _session_timeout |
374 |
|
384 |
|
375 |
@property |
385 |
def timed_out(self, now): |
376 |
def session_validity(self): |
386 |
return self.session_end_time < now |
377 |
if self.saml is not None: |
|
|
378 |
return self.time_remaining |
379 |
return _session_timeout |
380 |
|
387 |
|
381 |
@property |
388 |
@property |
382 |
def time_remaining(self): |
389 |
def session_end_time(self): |
383 |
remaining = [] |
390 |
if self.is_saml_user() and self.saml.not_on_or_after: |
384 |
if self.saml is not None: |
391 |
return self.saml.not_on_or_after |
385 |
remaining.append(self.saml.time_remaining) |
392 |
return self._timeout |
386 |
remaining.append(self._time_remaining) |
|
|
387 |
try: |
388 |
return min(remaining) |
389 |
except ValueError: # no SAML, no client |
390 |
return 0 |
391 |
|
393 |
|
392 |
def is_saml_user(self): |
394 |
def is_saml_user(self): |
393 |
# self.saml indicates that it was originally a |
395 |
# self.saml indicates that it was originally a |
|
412 |
else: |
414 |
else: |
413 |
return None |
415 |
return None |
414 |
|
416 |
|
415 |
def timed_out(self): |
|
|
416 |
return self.saml.timed_out() |
417 |
|
418 |
def __repr__(self): |
417 |
def __repr__(self): |
419 |
return '<User(%s, %s, %s)>' % (self.username, self.sessionid, self.saml is not None) |
418 |
return '<User(%s, %s, %s)>' % (self.username, self.sessionid, self.saml is not None) |
420 |
|
419 |
|
Lines 429-445
class SAMLUser(object):
|
Link Here
|
---|
|
429 |
self.message = message |
428 |
self.message = message |
430 |
self.username = u''.join(response.ava['uid']) |
429 |
self.username = u''.join(response.ava['uid']) |
431 |
|
430 |
|
432 |
@property |
|
|
433 |
def time_remaining(self): |
434 |
if self.not_on_or_after == 0: |
435 |
return 0 |
436 |
return int(self.not_on_or_after - time.time()) |
437 |
|
438 |
def timed_out(self): |
439 |
if self.not_on_or_after == 0: |
440 |
return False |
441 |
return self.time_remaining < 0 |
442 |
|
443 |
|
431 |
|
444 |
traceback_pattern = re.compile(r'(Traceback.*most recent call|File.*line.*in.*\d)') |
432 |
traceback_pattern = re.compile(r'(Traceback.*most recent call|File.*line.*in.*\d)') |
445 |
|
433 |
|
Lines 668-674
class Ressource(object):
|
Link Here
|
---|
|
668 |
|
656 |
|
669 |
def check_saml_session_validity(self): |
657 |
def check_saml_session_validity(self): |
670 |
user = self.get_user() |
658 |
user = self.get_user() |
671 |
if user and user.saml is not None and user.time_remaining < 1: |
659 |
if user and user.saml is not None and user.timed_out(time.time()): |
672 |
raise UMC_HTTPError(UNAUTHORIZED) |
660 |
raise UMC_HTTPError(UNAUTHORIZED) |
673 |
|
661 |
|
674 |
def set_cookies(self, *cookies, **kwargs): |
662 |
def set_cookies(self, *cookies, **kwargs): |
Lines 695-702
class Ressource(object):
|
Link Here
|
---|
|
695 |
olduser = self.get_user() |
683 |
olduser = self.get_user() |
696 |
|
684 |
|
697 |
user = User(sessionid, username, password, saml or olduser and olduser.saml) |
685 |
user = User(sessionid, username, password, saml or olduser and olduser.saml) |
698 |
self._session_timeout_timer(user) |
|
|
699 |
|
700 |
self.sessions[sessionid] = user |
686 |
self.sessions[sessionid] = user |
701 |
self.set_cookies(('UMCSessionId', sessionid), ('UMCUsername', username)) |
687 |
self.set_cookies(('UMCSessionId', sessionid), ('UMCUsername', username)) |
702 |
return user |
688 |
return user |
Lines 715-743
class Ressource(object):
|
Link Here
|
---|
|
715 |
if not value or value not in self.sessions: |
701 |
if not value or value not in self.sessions: |
716 |
return |
702 |
return |
717 |
user = self.sessions[value] |
703 |
user = self.sessions[value] |
718 |
if user.time_remaining <= 0: |
704 |
if user.timed_out(time.time()): |
719 |
return |
705 |
return |
720 |
return user |
706 |
return user |
721 |
|
707 |
|
722 |
def _session_timeout_timer(self, user): |
|
|
723 |
"""In order to avoid problems when the system time is changed (e.g., |
724 |
via rdate), we register a timer event that counts down the session |
725 |
timeout second-wise.""" |
726 |
|
727 |
# count down the remaining time |
728 |
user._time_remaining -= 1 |
729 |
|
730 |
session = UMCP_Dispatcher.sessions.get(user.sessionid) |
731 |
if user._time_remaining <= 0 and (not session or not session._requestid2response_queue): |
732 |
self._log('info', 'session timed out') |
733 |
self.sessions.pop(user.sessionid, None) |
734 |
user.on_logout() |
735 |
return |
736 |
|
737 |
# count down the timer second-wise (in order to avoid problems when |
738 |
# changing the system time, e.g. via rdate) |
739 |
notifier.timer_add(1000, lambda: self._session_timeout_timer(user)) |
740 |
|
741 |
|
708 |
|
742 |
class CPgeneric(Ressource): |
709 |
class CPgeneric(Ressource): |
743 |
|
710 |
|
Lines 902-909
class CPGet(CPgeneric):
|
Link Here
|
---|
|
902 |
raise UMC_HTTPError(UNAUTHORIZED) |
869 |
raise UMC_HTTPError(UNAUTHORIZED) |
903 |
info['username'] = user.username |
870 |
info['username'] = user.username |
904 |
info['auth_type'] = user.saml and 'SAML' |
871 |
info['auth_type'] = user.saml and 'SAML' |
905 |
info['remaining'] = user.time_remaining |
872 |
info['remaining'] = int(user.session_end_time - time.time()) |
906 |
info['validity'] = user.session_validity |
|
|
907 |
return json.dumps({"status": 200, "result": info, "message": ""}).encode('ASCII') |
873 |
return json.dumps({"status": 200, "result": info, "message": ""}).encode('ASCII') |
908 |
|
874 |
|
909 |
@cherrypy.expose |
875 |
@cherrypy.expose |
Lines 1035-1041
class CPAuth(CPgeneric):
|
Link Here
|
---|
|
1035 |
CORE.info('CPAuth/auth/sso: got new auth request (%s:%s <=> %s)' % (get_ip_address(), remote.port, remote.name)) |
1001 |
CORE.info('CPAuth/auth/sso: got new auth request (%s:%s <=> %s)' % (get_ip_address(), remote.port, remote.name)) |
1036 |
|
1002 |
|
1037 |
user = self.get_user() |
1003 |
user = self.get_user() |
1038 |
if not user or not user.saml or user.timed_out(): |
1004 |
if not user or not user.saml or user.timed_out(time.time()): |
1039 |
# redirect user to login page in case he's not authenticated or his session timed out |
1005 |
# redirect user to login page in case he's not authenticated or his session timed out |
1040 |
raise HTTPRedirect('/univention/saml/') |
1006 |
raise HTTPRedirect('/univention/saml/') |
1041 |
|
1007 |
|
Lines 1638-1643
class UMC_HTTP_Daemon(DaemonRunner):
|
Link Here
|
---|
|
1638 |
notifier.init(notifier.GENERIC) |
1604 |
notifier.init(notifier.GENERIC) |
1639 |
notifier.dispatch.MIN_TIMER = get_int('umc/http/dispatch-interval', notifier.dispatch.MIN_TIMER) |
1605 |
notifier.dispatch.MIN_TIMER = get_int('umc/http/dispatch-interval', notifier.dispatch.MIN_TIMER) |
1640 |
notifier.dispatcher_add(UMCP_Dispatcher.check_queue) |
1606 |
notifier.dispatcher_add(UMCP_Dispatcher.check_queue) |
|
|
1607 |
notifier.timer_add(1000, UMCP_Dispatcher.session_timeout_timer) |
1641 |
notifier.loop() |
1608 |
notifier.loop() |
1642 |
except (SystemExit, KeyboardInterrupt) as exc: |
1609 |
except (SystemExit, KeyboardInterrupt) as exc: |
1643 |
# stop the web server |
1610 |
# stop the web server |