Package modules :: Package machinery :: Module physical
[hide private]
[frames] | no frames]

Source Code for Module modules.machinery.physical

  1  # Copyright (C) 2012-2014 The MITRE Corporation. 
  2  # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org 
  3  # See the file 'docs/LICENSE' for copying permission. 
  4   
  5  import socket 
  6  import logging 
  7  import xmlrpclib 
  8  import subprocess 
  9   
 10  from lib.cuckoo.core.guest import GuestManager 
 11  from lib.cuckoo.common.abstracts import Machinery 
 12  from lib.cuckoo.common.exceptions import CuckooCriticalError 
 13  from lib.cuckoo.common.exceptions import CuckooMachineError 
 14   
 15  log = logging.getLogger(__name__) 
 16   
 17   
18 -class Physical(Machinery):
19 """Manage physical sandboxes.""" 20 21 # Physical machine states. 22 RUNNING = "running" 23 STOPPED = "stopped" 24 ERROR = "error" 25
26 - def _initialize_check(self):
27 """Ensures that credentials have been entered into the config file. 28 @raise CuckooCriticalError: if no credentials were provided or if 29 one or more physical machines are offline. 30 """ 31 if not self.options.physical.user or not self.options.physical.password: 32 raise CuckooCriticalError("Physical machine credentials are missing, please add it to the config file") 33 34 for machine in self.machines(): 35 if self._status(machine.label) != self.RUNNING: 36 raise CuckooCriticalError("Physical machine is currently offline")
37
38 - def _get_machine(self, label):
39 """Retrieve all machine info given a machine's name. 40 @param label: machine name. 41 @return: machine dictionary (id, ip, platform, ...). 42 @raises CuckooMachineError: if no machine is available with the given label. 43 """ 44 for m in self.machines(): 45 if label == m.label: 46 return m 47 48 raise CuckooMachineError("No machine with label: %s." % label)
49
50 - def start(self, label):
51 """Start a physical machine. 52 @param label: physical machine name. 53 @raise CuckooMachineError: if unable to start. 54 """ 55 # Check to ensure a given machine is running 56 log.debug("Checking if machine %r is running.", label) 57 status = self._status(label) 58 if status == self.RUNNING: 59 log.debug("Machine already running: %s.", label) 60 61 elif status == self.STOPPED: 62 self._wait_status(label, self.RUNNING) 63 64 else: 65 raise CuckooMachineError("Error occurred while starting: " 66 "%s (STATUS=%s)" % (label, status))
67
68 - def stop(self, label):
69 """Stops a physical machine. 70 @param label: physical machine name. 71 @raise CuckooMachineError: if unable to stop. 72 """ 73 # Since we are 'stopping' a physical machine, it must 74 # actually be rebooted to kick off the re-imaging process 75 n = self.options.physical.user 76 p = self.options.physical.password 77 creds = "%s%%%s" % (n, p) 78 status = self._status(label) 79 80 if status == self.RUNNING: 81 log.debug("Rebooting machine: %s.", label) 82 machine = self._get_machine(label) 83 84 args = [ 85 "net", "rpc", "shutdown", "-I", machine.ip, 86 "-U", creds, "-r", "-f", "--timeout=5" 87 ] 88 shutdown = subprocess.Popen(args, stdout=subprocess.PIPE) 89 output, _ = shutdown.communicate() 90 91 if "Shutdown of remote machine succeeded" not in output: 92 raise CuckooMachineError("Unable to initiate RPC request") 93 else: 94 log.debug("Reboot success: %s." % label)
95
96 - def _list(self):
97 """Lists physical machines installed. 98 @return: physical machine names list. 99 """ 100 active_machines = [] 101 for machine in self.machines(): 102 if self._status(machine.label) == self.RUNNING: 103 active_machines.append(machine.label) 104 105 return active_machines
106
107 - def _status(self, label):
108 """Gets current status of a physical machine. 109 @param label: physical machine name. 110 @return: status string. 111 """ 112 # For physical machines, the agent can either be contacted or not. 113 # However, there is some information to be garnered from potential 114 # exceptions. 115 log.debug("Getting status for machine: %s.", label) 116 machine = self._get_machine(label) 117 guest = GuestManager(machine.id, machine.ip, machine.platform) 118 119 if not guest: 120 raise CuckooMachineError("Unable to get status for machine: %s." 121 % label) 122 123 else: 124 try: 125 status = guest.server.get_status() 126 except xmlrpclib.Fault as e: 127 # Contacted Agent, but it threw an error. 128 log.debug("Agent error: %s (%s) (Error: %s).", 129 machine.id, machine.ip, e) 130 return self.ERROR 131 except socket.error as e: 132 # Could not contact agent. 133 log.debug("Agent unresponsive: %s (%s) (Error: %s).", 134 machine.id, machine.ip, e) 135 return self.STOPPED 136 except Exception as e: 137 # TODO Handle this better. 138 log.debug("Received unknown exception: %s.", e) 139 return self.ERROR 140 141 # If the agent responded successfully, then the physical machine 142 # is running 143 if status: 144 return self.RUNNING 145 146 return self.ERROR
147