diff --git a/actors/src/udsactor/linux/UDSActorService.py b/actors/src/udsactor/linux/UDSActorService.py index 4f012d956..3d90fb2dc 100644 --- a/actors/src/udsactor/linux/UDSActorService.py +++ b/actors/src/udsactor/linux/UDSActorService.py @@ -87,9 +87,16 @@ class UDSActorSvc(Daemon, CommonService): set_proctitle('UDSActorDaemon') # Linux daemon will continue running unless something is requested to - if self.interactWithBroker() is False: - logger.debug('Interact with broker returned false, stopping service after a while') - return + while True: + brokerConnected = self.interactWithBroker() + if brokerConnected is False: + logger.debug('Interact with broker returned false, stopping service after a while') + return + elif brokerConnected is True: + break + + # If brokerConnected returns None, repeat the cycle + self.doWait(16000) # Wait for a looong while if self.isAlive is False: logger.debug('The service is not alive after broker interaction, stopping it') diff --git a/actors/src/udsactor/service.py b/actors/src/udsactor/service.py index dcd0f0c0a..625529ff8 100644 --- a/actors/src/udsactor/service.py +++ b/actors/src/udsactor/service.py @@ -127,7 +127,6 @@ class CommonService(object): return False # On unmanaged hosts, there is no reason right now to continue running except Exception as e: logger.debug('Exception on network info: retrying') - logger.exception() # Any other error is expectable and recoverable, so let's wait a bit and retry again # but, if too many errors, will log it (one every minute, for # example) @@ -164,11 +163,11 @@ class CommonService(object): break except Exception as e: logger.error('Error at computer renaming stage: {}'.format(e.message)) - return False + return None # Will retry complete broker connection if this point is reached elif data[0] == 'domain': if len(params) != 5: logger.error('Got invalid parameters for domain message: {}'.format(params)) - return False + return False # Stop running service self.joinDomain(params[0], params[1], params[2], params[3], params[4]) break else: diff --git a/actors/src/udsactor/windows/UDSActorService.py b/actors/src/udsactor/windows/UDSActorService.py index 06cef9091..291ffd0ab 100644 --- a/actors/src/udsactor/windows/UDSActorService.py +++ b/actors/src/udsactor/windows/UDSActorService.py @@ -236,6 +236,19 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService): # ******************************************************** # * Ask brokers what to do before proceding to main loop * # ******************************************************** + while True: + brokerConnected = self.interactWithBroker() + if brokerConnected is False: + logger.debug('Interact with broker returned false, stopping service after a while') + self.notifyStop() + win32event.WaitForSingleObject(self.hWaitStop, 5000) + return + elif brokerConnected is True: + break + + # If brokerConnected returns None, repeat the cycle + self.doWait(16000) # Wait for a looong while + if self.interactWithBroker() is False: logger.debug('Interact with broker returned false, stopping service after a while') self.notifyStop() diff --git a/server/src/uds/core/managers/UserServiceManager.py b/server/src/uds/core/managers/UserServiceManager.py index 24d1fc3cc..4d98546f0 100644 --- a/server/src/uds/core/managers/UserServiceManager.py +++ b/server/src/uds/core/managers/UserServiceManager.py @@ -51,7 +51,7 @@ import requests import json import logging -__updated__ = '2016-03-09' +__updated__ = '2016-03-14' logger = logging.getLogger(__name__) @@ -378,6 +378,34 @@ class UserServiceManager(object): except Exception as e: logger.info('preConnection failed: {}. Check connection on destination machine: {}'.format(e, url)) + def checkUuid(self, uService): + + url = uService.getCommsUrl() + + if url is None: + logger.debug('No uuid to retrieve because agent does not supports notifications') + return True # UUid is valid because it is not supported checking it + + if uService.getProperty('actor_version', '') < '2.0.0': # Just for 2.0 or newer, previous actors will not support this method + return True + + url += '/uuid' + + try: + r = requests.get(url, verify=False, timeout=2) + uuid = json.loads(r.content) + if uuid != uService.uuid: + logger.info('The requested machine has uuid {} and the expected was {}'.format(uuid, uService.uuid)) + return False + + logger.debug('Got uuid from machine: {} {} {}'.format(url, uuid, uService.uuid)) + # In fact we ignore result right now + except Exception as e: + logger.info('Get uuid failed: {}. Check connection on destination machine: {}'.format(e, url)) + return False + + return True + def sendScript(self, uService, script): ''' If allowed, send script to user service @@ -478,20 +506,26 @@ class UserServiceManager(object): # If ready, show transport for this service, if also ready ofc iads = userService.getInstance() ip = iads.getIp() - events.addEvent(userService.deployed_service, events.ET_ACCESS, username=user.name, srcip=srcIp, dstip=ip, uniqueid=userService.unique_id) - if ip is not None: - serviceNotReadyCode = 0x0003 - itrans = trans.getInstance() - if itrans.isAvailableFor(userService, ip): - userService.setConnectionSource(srcIp, 'unknown') - log.doLog(userService, log.INFO, "User service ready", log.WEB) - UserServiceManager.manager().notifyPreconnect(userService, itrans.processedUser(userService, user), itrans.protocol) - return (ip, userService, iads, trans, itrans) - else: - log.doLog(userService, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT) - logger.debug('Transport is not ready for user service {0}'.format(userService)) + + if self.checkUuid(userService) is False: # Machine is not what is expected + serviceNotReadyCode = 0x0004 + log.doLog(userService, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT) + logger.debug('Transport is not ready for user service {0}'.format(userService)) else: - logger.debug('Ip not available from user service {0}'.format(userService)) + events.addEvent(userService.deployed_service, events.ET_ACCESS, username=user.name, srcip=srcIp, dstip=ip, uniqueid=userService.unique_id) + if ip is not None: + serviceNotReadyCode = 0x0003 + itrans = trans.getInstance() + if itrans.isAvailableFor(userService, ip): + userService.setConnectionSource(srcIp, 'unknown') + log.doLog(userService, log.INFO, "User service ready", log.WEB) + self.notifyPreconnect(userService, itrans.processedUser(userService, user), itrans.protocol) + return (ip, userService, iads, trans, itrans) + else: + log.doLog(userService, log.WARN, "User service is not accessible (ip {0})".format(ip), log.TRANSPORT) + logger.debug('Transport is not ready for user service {0}'.format(userService)) + else: + logger.debug('Ip not available from user service {0}'.format(userService)) else: log.doLog(userService, log.WARN, "User {0} from {1} tried to access, but service was not ready".format(user.name, srcIp), log.WEB) diff --git a/server/src/uds/core/util/calendar/__init__.py b/server/src/uds/core/util/calendar/__init__.py index 570621e27..20486dfaf 100644 --- a/server/src/uds/core/util/calendar/__init__.py +++ b/server/src/uds/core/util/calendar/__init__.py @@ -45,7 +45,7 @@ import six import bitarray import logging -__updated__ = '2016-03-10' +__updated__ = '2016-03-14' logger = logging.getLogger(__name__) @@ -109,15 +109,17 @@ class CalendarChecker(object): return data - def _updateEvents(self, checkFrom): + def _updateEvents(self, checkFrom, startEvent=True): next_event = None for rule in self.calendar.rules.all(): - event = rule.as_rrule().after(checkFrom) - duration = rule.duration_as_minutes + if startEvent: + event = rule.as_rrule().after(checkFrom) # At start + else: + event = rule.as_rrule_end().after(checkFrom) # At end - if next_event is None or self.next_event[0] > event: - next_event = (event, datetime.timedelta(minutes=duration)) + if next_event is None or next_event > event: + next_event = event return next_event @@ -147,7 +149,7 @@ class CalendarChecker(object): return data[dtime.hour * 60 + dtime.minute] - def nextEvent(self, checkFrom=None): + def nextEvent(self, checkFrom=None, startEvent=True): ''' Returns next event for this interval Returns a list of two elements. First is datetime of event begining, second is timedelta of duration @@ -155,11 +157,12 @@ class CalendarChecker(object): if checkFrom is None: checkFrom = getSqlDatetime() - cacheKey = six.text_type(self.calendar.modified.toordinal()) + self.calendar.uuid + six.text_type(checkFrom.toordinal()) + 'event' + cacheKey = six.text_type(self.calendar.modified.toordinal()) + self.calendar.uuid + six.text_type(checkFrom.toordinal()) + 'event' + ('x' if startEvent is True else '_') + print cacheKey next_event = CalendarChecker.cache.get(cacheKey, None) - + print next_event if next_event is None: - next_event = self._updateEvents(checkFrom) + next_event = self._updateEvents(checkFrom, startEvent) CalendarChecker.cache.put(cacheKey, next_event, 3600) else: CalendarChecker.hits += 1 diff --git a/server/src/uds/models/CalendarRule.py b/server/src/uds/models/CalendarRule.py index afdba8312..57d8e437e 100644 --- a/server/src/uds/models/CalendarRule.py +++ b/server/src/uds/models/CalendarRule.py @@ -33,7 +33,7 @@ from __future__ import unicode_literals -__updated__ = '2015-09-17' +__updated__ = '2016-03-14' from django.db import models from django.utils.encoding import python_2_unicode_compatible @@ -124,6 +124,18 @@ class CalendarRule(UUIDModel): else: return rules.rrule(frq_to_rrl[self.frequency], interval=self.interval, dtstart=self.start) + def as_rrule_end(self): + if self.frequency == WEEKDAYS: + dw = [] + l = self.interval + for i in range(7): + if l & 1 == 1: + dw.append(weekdays[i]) + l >>= 1 + return rules.rrule(rules.DAILY, byweekday=dw, dtstart=self.start + datetime.timedelta(minutes=self.duration_as_minutes)) + else: + return rules.rrule(frq_to_rrl[self.frequency], interval=self.interval, dtstart=self.start + datetime.timedelta(minutes=self.duration_as_minutes)) + @property def frequency_as_minutes(self): if self.frequency != WEEKDAYS: diff --git a/server/templates/public/app/scripts/jquery.cookiebar.js b/server/templates/public/app/scripts/jquery.cookiebar.js index 76713f1d8..1b98a84c5 100644 --- a/server/templates/public/app/scripts/jquery.cookiebar.js +++ b/server/templates/public/app/scripts/jquery.cookiebar.js @@ -1,183 +1,183 @@ -/* - * Copyright (C) 2012 PrimeBox (info@primebox.co.uk) - * - * This work is licensed under the Creative Commons - * Attribution 3.0 Unported License. To view a copy - * of this license, visit - * http://creativecommons.org/licenses/by/3.0/. - * - * Documentation available at: - * http://www.primebox.co.uk/projects/cookie-bar/ - * - * When using this software you use it at your own risk. We hold - * no responsibility for any damage caused by using this plugin - * or the documentation provided. - */ -(function($){ - $.cookieBar = function(options,val){ - if(options=='cookies'){ - var doReturn = 'cookies'; - }else if(options=='set'){ - var doReturn = 'set'; - }else{ - var doReturn = false; - } - var defaults = { - message: 'We use cookies to track usage and preferences.', //Message displayed on bar - acceptButton: true, //Set to true to show accept/enable button - acceptText: 'I Understand', //Text on accept/enable button - declineButton: false, //Set to true to show decline/disable button - declineText: 'Disable Cookies', //Text on decline/disable button - policyButton: false, //Set to true to show Privacy Policy button - policyText: 'Privacy Policy', //Text on Privacy Policy button - policyURL: '/privacy-policy/', //URL of Privacy Policy - autoEnable: true, //Set to true for cookies to be accepted automatically. Banner still shows - acceptOnContinue: false, //Set to true to silently accept cookies when visitor moves to another page - expireDays: 365, //Number of days for cookieBar cookie to be stored for - forceShow: false, //Force cookieBar to show regardless of user cookie preference - effect: 'slide', //Options: slide, fade, hide - element: 'body', //Element to append/prepend cookieBar to. Remember "." for class or "#" for id. - append: false, //Set to true for cookieBar HTML to be placed at base of website. Actual position may change according to CSS - fixed: false, //Set to true to add the class "fixed" to the cookie bar. Default CSS should fix the position - bottom: false, //Force CSS when fixed, so bar appears at bottom of website - zindex: '', //Can be set in CSS, although some may prefer to set here - redirect: String(window.location.href), //Current location - domain: String(window.location.hostname), //Location of privacy policy - referrer: String(document.referrer) //Where visitor has come from - }; - var options = $.extend(defaults,options); - - //Sets expiration date for cookie - var expireDate = new Date(); - expireDate.setTime(expireDate.getTime()+(options.expireDays*24*60*60*1000)); - expireDate = expireDate.toGMTString(); - - var cookieEntry = 'cb-enabled={value}; expires='+expireDate+'; path=/'; - - //Retrieves current cookie preference - var i,cookieValue='',aCookie,aCookies=document.cookie.split('; '); - for (i=0;i=0 && String(window.location.href).indexOf(options.policyURL)==-1 && doReturn!='cookies' && doReturn!='set' && cookieValue!='accepted' && cookieValue!='declined'){ - doReturn = 'set'; - val = 'accepted'; - } - } - if(doReturn=='cookies'){ - //Returns true if cookies are enabled, false otherwise - if(cookieValue=='enabled' || cookieValue=='accepted'){ - return true; - }else{ - return false; - } - }else if(doReturn=='set' && (val=='accepted' || val=='declined')){ - //Sets value of cookie to 'accepted' or 'declined' - document.cookie = cookieEntry.replace('{value}',val); - if(val=='accepted'){ - return true; - }else{ - return false; - } - }else{ - //Sets up enable/accept button if required - var message = options.message.replace('{policy_url}',options.policyURL); - - if(options.acceptButton){ - var acceptButton = ''+options.acceptText+''; - }else{ - var acceptButton = ''; - } - //Sets up disable/decline button if required - if(options.declineButton){ - var declineButton = ''+options.declineText+''; - }else{ - var declineButton = ''; - } - //Sets up privacy policy button if required - if(options.policyButton){ - var policyButton = ''+options.policyText+''; - }else{ - var policyButton = ''; - } - //Whether to add "fixed" class to cookie bar - if(options.fixed){ - if(options.bottom){ - var fixed = ' class="fixed bottom"'; - }else{ - var fixed = ' class="fixed"'; - } - }else{ - var fixed = ''; - } - if(options.zindex!=''){ - var zindex = ' style="z-index:'+options.zindex+';"'; - }else{ - var zindex = ''; - } - - //Displays the cookie bar if arguments met - if(options.forceShow || cookieValue=='enabled' || cookieValue==''){ - if(options.append){ - $(options.element).append(''); - }else{ - $(options.element).prepend(''); - } - } - - //Sets the cookie preference to accepted if enable/accept button pressed - $('#cookie-bar .cb-enable').click(function(){ - document.cookie = cookieEntry.replace('{value}','accepted'); - if(cookieValue!='enabled' && cookieValue!='accepted'){ - window.location = options.currentLocation; - }else{ - if(options.effect=='slide'){ - $('#cookie-bar').slideUp(300,function(){$('#cookie-bar').remove();}); - }else if(options.effect=='fade'){ - $('#cookie-bar').fadeOut(300,function(){$('#cookie-bar').remove();}); - }else{ - $('#cookie-bar').hide(0,function(){$('#cookie-bar').remove();}); - } - return false; - } - }); - //Sets the cookie preference to declined if disable/decline button pressed - $('#cookie-bar .cb-disable').click(function(){ - var deleteDate = new Date(); - deleteDate.setTime(deleteDate.getTime()-(864000000)); - deleteDate = deleteDate.toGMTString(); - aCookies=document.cookie.split('; '); - for (i=0;i=0){ - document.cookie = aCookie[0]+'=0; expires='+deleteDate+'; domain='+options.domain.replace('www','')+'; path=/'; - }else{ - document.cookie = aCookie[0]+'=0; expires='+deleteDate+'; path=/'; - } - } - document.cookie = cookieEntry.replace('{value}','declined'); - if(cookieValue=='enabled' && cookieValue!='accepted'){ - window.location = options.currentLocation; - }else{ - if(options.effect=='slide'){ - $('#cookie-bar').slideUp(300,function(){$('#cookie-bar').remove();}); - }else if(options.effect=='fade'){ - $('#cookie-bar').fadeOut(300,function(){$('#cookie-bar').remove();}); - }else{ - $('#cookie-bar').hide(0,function(){$('#cookie-bar').remove();}); - } - return false; - } - }); - } - }; +/* + * Copyright (C) 2012 PrimeBox (info@primebox.co.uk) + * + * This work is licensed under the Creative Commons + * Attribution 3.0 Unported License. To view a copy + * of this license, visit + * http://creativecommons.org/licenses/by/3.0/. + * + * Documentation available at: + * http://www.primebox.co.uk/projects/cookie-bar/ + * + * When using this software you use it at your own risk. We hold + * no responsibility for any damage caused by using this plugin + * or the documentation provided. + */ +(function($){ + $.cookieBar = function(options,val){ + if(options=='cookies'){ + var doReturn = 'cookies'; + }else if(options=='set'){ + var doReturn = 'set'; + }else{ + var doReturn = false; + } + var defaults = { + message: 'We use cookies to track usage and preferences.', //Message displayed on bar + acceptButton: true, //Set to true to show accept/enable button + acceptText: 'I Understand', //Text on accept/enable button + declineButton: false, //Set to true to show decline/disable button + declineText: 'Disable Cookies', //Text on decline/disable button + policyButton: false, //Set to true to show Privacy Policy button + policyText: 'Privacy Policy', //Text on Privacy Policy button + policyURL: '/privacy-policy/', //URL of Privacy Policy + autoEnable: true, //Set to true for cookies to be accepted automatically. Banner still shows + acceptOnContinue: false, //Set to true to silently accept cookies when visitor moves to another page + expireDays: 365, //Number of days for cookieBar cookie to be stored for + forceShow: false, //Force cookieBar to show regardless of user cookie preference + effect: 'slide', //Options: slide, fade, hide + element: 'body', //Element to append/prepend cookieBar to. Remember "." for class or "#" for id. + append: false, //Set to true for cookieBar HTML to be placed at base of website. Actual position may change according to CSS + fixed: false, //Set to true to add the class "fixed" to the cookie bar. Default CSS should fix the position + bottom: false, //Force CSS when fixed, so bar appears at bottom of website + zindex: '', //Can be set in CSS, although some may prefer to set here + redirect: String(window.location.href), //Current location + domain: String(window.location.hostname), //Location of privacy policy + referrer: String(document.referrer) //Where visitor has come from + }; + var options = $.extend(defaults,options); + + //Sets expiration date for cookie + var expireDate = new Date(); + expireDate.setTime(expireDate.getTime()+(options.expireDays*24*60*60*1000)); + expireDate = expireDate.toGMTString(); + + var cookieEntry = 'cb-enabled={value}; expires='+expireDate+'; path=/'; + + //Retrieves current cookie preference + var i,cookieValue='',aCookie,aCookies=document.cookie.split('; '); + for (i=0;i=0 && String(window.location.href).indexOf(options.policyURL)==-1 && doReturn!='cookies' && doReturn!='set' && cookieValue!='accepted' && cookieValue!='declined'){ + doReturn = 'set'; + val = 'accepted'; + } + } + if(doReturn=='cookies'){ + //Returns true if cookies are enabled, false otherwise + if(cookieValue=='enabled' || cookieValue=='accepted'){ + return true; + }else{ + return false; + } + }else if(doReturn=='set' && (val=='accepted' || val=='declined')){ + //Sets value of cookie to 'accepted' or 'declined' + document.cookie = cookieEntry.replace('{value}',val); + if(val=='accepted'){ + return true; + }else{ + return false; + } + }else{ + //Sets up enable/accept button if required + var message = options.message.replace('{policy_url}',options.policyURL); + + if(options.acceptButton){ + var acceptButton = ''+options.acceptText+''; + }else{ + var acceptButton = ''; + } + //Sets up disable/decline button if required + if(options.declineButton){ + var declineButton = ''+options.declineText+''; + }else{ + var declineButton = ''; + } + //Sets up privacy policy button if required + if(options.policyButton){ + var policyButton = ''+options.policyText+''; + }else{ + var policyButton = ''; + } + //Whether to add "fixed" class to cookie bar + if(options.fixed){ + if(options.bottom){ + var fixed = ' class="fixed bottom"'; + }else{ + var fixed = ' class="fixed"'; + } + }else{ + var fixed = ''; + } + if(options.zindex!=''){ + var zindex = ' style="z-index:'+options.zindex+';"'; + }else{ + var zindex = ''; + } + + //Displays the cookie bar if arguments met + if(options.forceShow || cookieValue=='enabled' || cookieValue==''){ + if(options.append){ + $(options.element).append(''); + }else{ + $(options.element).prepend(''); + } + } + + //Sets the cookie preference to accepted if enable/accept button pressed + $('#cookie-bar .cb-enable').click(function(){ + document.cookie = cookieEntry.replace('{value}','accepted'); + if(cookieValue!='enabled' && cookieValue!='accepted'){ + window.location = options.currentLocation; + }else{ + if(options.effect=='slide'){ + $('#cookie-bar').slideUp(300,function(){$('#cookie-bar').remove();}); + }else if(options.effect=='fade'){ + $('#cookie-bar').fadeOut(300,function(){$('#cookie-bar').remove();}); + }else{ + $('#cookie-bar').hide(0,function(){$('#cookie-bar').remove();}); + } + return false; + } + }); + //Sets the cookie preference to declined if disable/decline button pressed + $('#cookie-bar .cb-disable').click(function(){ + var deleteDate = new Date(); + deleteDate.setTime(deleteDate.getTime()-(864000000)); + deleteDate = deleteDate.toGMTString(); + aCookies=document.cookie.split('; '); + for (i=0;i=0){ + document.cookie = aCookie[0]+'=0; expires='+deleteDate+'; domain='+options.domain.replace('www','')+'; path=/'; + }else{ + document.cookie = aCookie[0]+'=0; expires='+deleteDate+'; path=/'; + } + } + document.cookie = cookieEntry.replace('{value}','declined'); + if(cookieValue=='enabled' && cookieValue!='accepted'){ + window.location = options.currentLocation; + }else{ + if(options.effect=='slide'){ + $('#cookie-bar').slideUp(300,function(){$('#cookie-bar').remove();}); + }else if(options.effect=='fade'){ + $('#cookie-bar').fadeOut(300,function(){$('#cookie-bar').remove();}); + }else{ + $('#cookie-bar').hide(0,function(){$('#cookie-bar').remove();}); + } + return false; + } + }); + } + }; })(jQuery); \ No newline at end of file