Exemple #1
0
def executeRemoteCommand(command):
    result = True
    
    if command == REMOTE_LOCK:
        if hardwareconfig.checkLock() == False:
            AFroutines.lockScreen()
            result = sendemail.sendEmail("Command successful","Screen locked")
            eventQueue.put(("Log",'Screen locked due to remote command'))
        else:
            eventQueue.put(("Log",'Lock screen failed - command received while locked'))
            result = sendemail.sendEmail("Command failed","Screen already locked")
            
    elif command == REMOTE_STARTMONITOR:
        #cant check ispy camera status, just have to assume it was not monitoring
        iSpyPath = fileconfig.config.get('TRIGGERS','ispy_path')
        roomCamID = fileconfig.config.get('TRIGGERS','room_cam_id')
        if os.path.exists(iSpyPath):
            eventQueue.put(("Log","Starting room camera due to remote command"))
        else:
            eventQueue.put(("Log","iSpy executable not found - cannot fulfill remote command"))
            return
        
        subprocess.call([iSpyPath,'commands bringonline,2,%s'%roomCamID])
        result = sendemail.sendEmail("Command successful","Movement monitoring initiated. Have a nice day.")
        
    elif command == REMOTE_STOPMONITOR:
        #cant check ispy camera status, just have to assume it was already monitoring
        iSpyPath = fileconfig.config.get('TRIGGERS','ispy_path')
        roomCamID = fileconfig.config.get('TRIGGERS','room_cam_id')
        if os.path.exists(iSpyPath):
            eventQueue.put(("Log","Stopping room camera due to remote command"))
        else:
            eventQueue.put(("Log","iSpy executable not found - cannot fulfill remote command"))
            return
            
        subprocess.call([iSpyPath,'commands takeoffline,2,%s'%roomCamID])
        result = sendemail.sendEmail("Command successful","Movement monitoring disabled. Welcome home!")
        
    elif command == REMOTE_SHUTDOWN:
        result = sendemail.sendEmail("Command successful","Shutting down...")
        eventQueue.put(("Log","Initiating standard shutdown due to remote command"))
        AFroutines.standardShutdown()
        
    elif command == REMOTE_KILLSWITCH:
        eventQueue.put(("Log","Initiating emergency shutdown due to remote command"))
        AFroutines.emergency()
        
    if result != True: eventQueue.put(('Log','Mail send failed: %s'%result))
def executeRemoteCommand(command):
    result = True

    if command == REMOTE_LOCK:
        if hardwareconfig.checkLock() == False:
            AFroutines.lockScreen()
            result = sendemail.sendEmail("Command successful", "Screen locked")
            eventQueue.put(("Log", 'Screen locked due to remote command'))
        else:
            eventQueue.put(
                ("Log", 'Lock screen failed - command received while locked'))
            result = sendemail.sendEmail("Command failed",
                                         "Screen already locked")

    elif command == REMOTE_STARTMONITOR:
        #cant check ispy camera status, just have to assume it was not monitoring
        iSpyPath = fileconfig.config.get('TRIGGERS', 'ispy_path')
        roomCamID = fileconfig.config.get('TRIGGERS', 'room_cam_id')
        if os.path.exists(iSpyPath):
            eventQueue.put(
                ("Log", "Starting room camera due to remote command"))
        else:
            eventQueue.put(
                ("Log",
                 "iSpy executable not found - cannot fulfill remote command"))
            return

        subprocess.call([iSpyPath, 'commands bringonline,2,%s' % roomCamID])
        result = sendemail.sendEmail(
            "Command successful",
            "Movement monitoring initiated. Have a nice day.")

    elif command == REMOTE_STOPMONITOR:
        #cant check ispy camera status, just have to assume it was already monitoring
        iSpyPath = fileconfig.config.get('TRIGGERS', 'ispy_path')
        roomCamID = fileconfig.config.get('TRIGGERS', 'room_cam_id')
        if os.path.exists(iSpyPath):
            eventQueue.put(
                ("Log", "Stopping room camera due to remote command"))
        else:
            eventQueue.put(
                ("Log",
                 "iSpy executable not found - cannot fulfill remote command"))
            return

        subprocess.call([iSpyPath, 'commands takeoffline,2,%s' % roomCamID])
        result = sendemail.sendEmail(
            "Command successful",
            "Movement monitoring disabled. Welcome home!")

    elif command == REMOTE_SHUTDOWN:
        result = sendemail.sendEmail("Command successful", "Shutting down...")
        eventQueue.put(
            ("Log", "Initiating standard shutdown due to remote command"))
        AFroutines.standardShutdown()

    elif command == REMOTE_KILLSWITCH:
        eventQueue.put(
            ("Log", "Initiating emergency shutdown due to remote command"))
        AFroutines.emergency()

    if result != True: eventQueue.put(('Log', 'Mail send failed: %s' % result))
    def run(self):

        if fileconfig.config.get('TRIGGERS', 'debuglog') == 'True':
            global VERBOSELOGS
            VERBOSELOGS = True

        debugLog('Lockwatcher Started')

        global startupTime
        startupTime = time.time()

        #send log/status updates to connections in here - for config programs
        listeners = []

        confMonThread = configMonitor()
        confMonThread.start()

        LOCKED = fileconfig.config.get('TRIGGERS', 'lockedtriggers').split(',')
        ALWAYS = fileconfig.config.get('TRIGGERS', 'alwaystriggers').split(',')
        ACTIVE = LOCKED + ALWAYS

        global eventQueue
        eventQueue = Queue.Queue()

        threadStatuses = {}
        threadDict = {}

        for trigger in ACTIVE:
            if trigger != '': startMonitor(threadDict, trigger)

        if fileconfig.config.get('EMAIL', 'ENABLE_REMOTE') == 'True':
            startMonitor(threadDict, 'email')

        #new month, new log
        logPath = fileconfig.config.get('TRIGGERS', 'logfile')
        if os.path.exists(logPath):
            creationTime = time.ctime(os.path.getctime(logPath))
            creationMonth = datetime.datetime.strptime(creationTime,
                                                       "%a %b %d %H:%M:%S %Y")
            monthNow = time.strftime('%m %Y')
            if creationMonth != monthNow:
                try:
                    open(logPath, 'w').close()
                except:
                    pass

        eventQueue.put(('Log', 'Lockwatcher monitoring started'))

        badCommands = 0
        shutdownActivated = False
        while True:
            event = eventQueue.get(block=True, timeout=None)
            debugLog('Event in queue: ' + str(event))
            eventType = event[0]

            #--------------trigger activated under shutdown conditions
            if eventType == 'Kill':
                eventReason = event[1]
                #don't trigger multiple shutdowns but keep logging while we can
                if shutdownActivated == False:
                    shutdownActivated = True

                    if fileconfig.config.get('EMAIL','email_alert') == 'True' and \
                        'Kill switch' not in eventReason:
                        try:
                            #has a 4 second timeout for blocking operations
                            result = sendemail.sendEmail(
                                'Emergency shutdown triggered', eventReason)
                            if result != True:
                                eventQueue.put(
                                    ('Log', 'Mail send failed: %s' % result))
                        except:
                            pass  #email failed, oh well.
                    AFroutines.emergency()

            #--------------thread status changed, inform any listeners
            elif eventType == 'Status':
                #if self.statuses != None: self.statuses[event[1]].set(event[2])
                threadStatuses[event[1]] = event[2]
                msg = 'Status::%s::%s' % (event[1], event[2])
                broadcast(listeners, msg)

            #-----------config programs can request all the current statuses
            elif eventType == 'getStatuses':
                msg = 'AllStatuses::'
                for name, value in threadStatuses.items():
                    msg = msg + '%s::%s|' % (name, value)
                msg = msg[:-1]

                broadcast(listeners, msg)

            #--------------add to log file + listener log window if they exist
            elif eventType == 'Log':
                addLogEntry(str(event[1]), listeners)

            elif eventType == 'stop':
                broadcast(listeners, 'Shutdown')
                for threadname in threadDict.keys():
                    if isRunning(threadname, threadDict):
                        threadDict[threadname].terminate()
                confMonThread.terminate()
                time.sleep(1)  #give threads time to shutdown
                return

            elif eventType == 'startMonitor':
                monitor = event[1]
                if monitor in trigMonitorMap.keys():
                    thread = trigMonitorMap[monitor]
                else:
                    continue
                if not isRunning(thread, threadDict):
                    startMonitor(threadDict, trigEventMap[monitor])

            elif eventType == 'stopMonitor':
                monitor = event[1]

                if monitor == 'devices':
                    threadnames = [
                        'deviceMonitor', 'volumeMonitor',
                        'logicalDiskRemoveMonitor', 'logicalDiskCreateMonitor'
                    ]
                else:
                    threadnames = [trigMonitorMap[monitor]]

                for threadname in threadnames:
                    if isRunning(threadname, threadDict):
                        threadDict[threadname].terminate()
                        threadDict[threadname] = None

            elif eventType == 'Mail':
                #malformed emails would be a good way of crashing lockwatcher
                #be careful to valididate mail here
                validMail = True
                try:
                    command, code = event[1].split(' ')
                    eventQueue.put(
                        ('Log', 'Received mail "%s %s"' % (command, code)))
                except:
                    validMail = False

                #forgive bad command codes - crappy attack and causes
                #loop if we look at our returned emails with same sender/recv addresss
                if validMail == True:
                    try:
                        command = int(command)
                        if command not in commandList:
                            continue
                    except:
                        continue

                if validMail == True and sendemail.validHMAC(code,
                                                             command) == True:
                    executeRemoteCommand(command)
                    badCommands = 0  #good command resets limit
                else:
                    badCommands += 1
                    result = sendemail.sendEmail(
                        "Command failed",
                        "Bad command or authentication code received: %s" %
                        str(event[1]))
                    if result != True:
                        eventQueue.put(
                            ('Log', 'Mail send failed: %s' % result))
                    eventQueue.put((
                        'Log',
                        'Mail not authenticated or bad command: "%s". Ensure clocks are synchronised.'
                        % str(event[1])))
                    badCommandLimit = int(
                        fileconfig.config.get('EMAIL', 'BAD_COMMAND_LIMIT'))
                    if badCommandLimit > 0 and badCommands >= badCommandLimit:
                        addLogEntry(str(event[1]), listeners)

                        if shutdownActivated == False:
                            shutdownActivated = True
                            AFroutines.emergency()

                    continue

            elif eventType == 'reloadConfig':
                fileconfig.reloadConfig()
                if isRunning('keyboardMonitor', threadDict):
                    threadDict['keyboardMonitor'].reloadConfig()
                #eventQueue.put(('Log','Config reload forced'))  #debugmode

            elif eventType == 'newListener':
                port = int(event[1])
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                eventQueue.put(
                    ('Log',
                     'Lockwatcher connected to new configuration client'))
                try:
                    s.connect(('127.0.0.1', port))
                except:
                    eventQueue.put(
                        ('Log', 'Error: Failed to connect to client port: ' +
                         str(port)))
                    continue

                s.send(b'True@@')
                listeners.append(s)

            else:
                eventQueue.put(
                    ('Log', 'Error: Unknown event in queue: ' + str(event)))
Exemple #4
0
    def run(self):
        
        if fileconfig.config.get('TRIGGERS','debuglog') == 'True':
            global VERBOSELOGS
            VERBOSELOGS = True
            
        debugLog('Lockwatcher Started')
        
        global startupTime 
        startupTime = time.time()
        
        #send log/status updates to connections in here - for config programs
        listeners = []
        
        confMonThread = configMonitor()
        confMonThread.start()
        
        LOCKED = fileconfig.config.get('TRIGGERS','lockedtriggers').split(',')
        ALWAYS = fileconfig.config.get('TRIGGERS','alwaystriggers').split(',')
        ACTIVE = LOCKED+ALWAYS
        
        global eventQueue
        eventQueue = Queue.Queue()

        threadStatuses = {}
        threadDict = {}
        
        for trigger in ACTIVE:
            if trigger != '': startMonitor(threadDict,trigger)

        if fileconfig.config.get('EMAIL','ENABLE_REMOTE') == 'True':
            startMonitor(threadDict,'email')
        
        
        #new month, new log
        logPath = fileconfig.config.get('TRIGGERS','logfile')
        if os.path.exists(logPath):
            creationTime = time.ctime(os.path.getctime(logPath))
            creationMonth = datetime.datetime.strptime(creationTime, "%a %b %d %H:%M:%S %Y")
            monthNow = time.strftime('%m %Y')
            if creationMonth != monthNow:
                try:
                    open(logPath, 'w').close()
                except: pass
                    
        eventQueue.put(('Log','Lockwatcher monitoring started'))
        
        badCommands = 0
        shutdownActivated = False
        while True:
            event = eventQueue.get(block=True, timeout=None)
            debugLog('Event in queue: '+str(event))
            eventType = event[0]
            
            #--------------trigger activated under shutdown conditions
            if eventType == 'Kill':
                eventReason = event[1]
                #don't trigger multiple shutdowns but keep logging while we can
                if shutdownActivated == False: 
                    shutdownActivated = True
                    
                    if fileconfig.config.get('EMAIL','email_alert') == 'True' and \
                        'Kill switch' not in eventReason:
                        try:
                            #has a 4 second timeout for blocking operations
                            result = sendemail.sendEmail('Emergency shutdown triggered',eventReason)
                            if result != True:
                                eventQueue.put(('Log','Mail send failed: %s'%result))
                        except:
                            pass #email failed, oh well. 
                    AFroutines.emergency()
            
            #--------------thread status changed, inform any listeners        
            elif eventType == 'Status':
                #if self.statuses != None: self.statuses[event[1]].set(event[2])
                threadStatuses[event[1]] = event[2]
                msg = 'Status::%s::%s'%(event[1],event[2])
                broadcast(listeners,msg)
                
            #-----------config programs can request all the current statuses
            elif eventType == 'getStatuses':
                msg = 'AllStatuses::'
                for name,value in threadStatuses.items():
                    msg = msg+ '%s::%s|'%(name,value)
                msg = msg[:-1]
                
                broadcast(listeners,msg)
            
            #--------------add to log file + listener log window if they exist
            elif eventType == 'Log':
                addLogEntry(str(event[1]),listeners)
                
            elif eventType == 'stop':
                broadcast(listeners,'Shutdown')
                for threadname in threadDict.keys():
                    if isRunning(threadname,threadDict): threadDict[threadname].terminate()
                confMonThread.terminate()
                time.sleep(1) #give threads time to shutdown
                return
            
            elif eventType == 'startMonitor':
                monitor=event[1]
                if monitor in trigMonitorMap.keys():
                    thread = trigMonitorMap[monitor]
                else: continue
                if not isRunning(thread,threadDict): startMonitor(threadDict,trigEventMap[monitor])
            
            elif eventType == 'stopMonitor':
                monitor = event[1]
                
                if monitor == 'devices':
                    threadnames = ['deviceMonitor','volumeMonitor',
                                   'logicalDiskRemoveMonitor','logicalDiskCreateMonitor']
                else:
                    threadnames = [trigMonitorMap[monitor]]
                    
                for threadname in threadnames:
                    if isRunning(threadname,threadDict):
                        threadDict[threadname].terminate()
                        threadDict[threadname] = None
            
            elif eventType == 'Mail':
                #malformed emails would be a good way of crashing lockwatcher
                #be careful to valididate mail here
                validMail = True
                try:
                    command, code = event[1].split(' ')
                    eventQueue.put(('Log','Received mail "%s %s"'%(command,code)))
                except:
                    validMail = False
                    
                #forgive bad command codes - crappy attack and causes
                #loop if we look at our returned emails with same sender/recv addresss
                if validMail == True:
                    try: 
                        command = int(command)
                        if command not in commandList:
                            continue
                    except:
                        continue
                    
                if validMail == True and sendemail.validHMAC(code,command) == True:
                    executeRemoteCommand(command) 
                    badCommands = 0 #good command resets limit
                else:
                    badCommands += 1
                    result = sendemail.sendEmail("Command failed","Bad command or authentication code received: %s"%str(event[1]))
                    if result != True:
                        eventQueue.put(('Log','Mail send failed: %s'%result))
                    eventQueue.put(('Log','Mail not authenticated or bad command: "%s". Ensure clocks are synchronised.'%str(event[1])))
                    badCommandLimit = int(fileconfig.config.get('EMAIL','BAD_COMMAND_LIMIT'))
                    if badCommandLimit > 0 and badCommands >= badCommandLimit:
                        addLogEntry(str(event[1]),listeners)
                        
                        if shutdownActivated == False:
                            shutdownActivated = True
                            AFroutines.emergency()
                            
                    continue
                
            elif eventType == 'reloadConfig':
                fileconfig.reloadConfig()
                if isRunning('keyboardMonitor',threadDict): threadDict['keyboardMonitor'].reloadConfig()
                #eventQueue.put(('Log','Config reload forced'))  #debugmode
                
            elif eventType == 'newListener':
                port = int(event[1])
                s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
                eventQueue.put(('Log','Lockwatcher connected to new configuration client'))
                try:
                    s.connect( ('127.0.0.1', port) )
                except: 
                    eventQueue.put(('Log','Error: Failed to connect to client port: '+str(port)))
                    continue
                
                s.send(b'True@@')
                listeners.append(s)
                
            else:
                eventQueue.put(('Log','Error: Unknown event in queue: '+str(event)))