def InstallerNotifyServer(): """An emergency function Invoked when the client installation failed.""" # We make a temporary emergency config file to contain the new client id. Note # that the notification callback does not really mean anything to us, since # the client is not installed and we dont have basic interrogate information. config_lib.CONFIG.SetWriteBack("temp.yaml") try: log_data = open(config_lib.CONFIG["Installer.logfile"], "rb").read() except (IOError, OSError): log_data = "" # Start the client and send the server a message, then terminate. The # private key may be empty if we did not install properly yet. In this case, # the client will automatically generate a random client ID and private key # (and the message will be unauthenticated since we never enrolled.). comms.CommsInit().RunOnce() client = comms.GRRHTTPClient( ca_cert=config_lib.CONFIG["CA.certificate"], private_key=config_lib.CONFIG.Get("Client.private_key")) client.client_worker.SendReply( session_id=rdfvalue.FlowSessionID(flow_name="InstallationFailed"), message_type=rdf_flows.GrrMessage.Type.STATUS, request_id=0, response_id=0, rdf_value=rdf_flows.GrrStatus( status=rdf_flows.GrrStatus.ReturnedStatus.GENERIC_ERROR, error_message="Installation failed.", backtrace=log_data[-10000:])) client.RunOnce()
def _ForemanOp(self): """Sends Foreman checks periodically.""" period = config.CONFIG["Client.foreman_check_frequency"] self._threads["Worker"].SendReply( rdf_protodict.DataBlob(), session_id=rdfvalue.FlowSessionID(flow_name="Foreman"), require_fastpoll=False) time.sleep(period)
def SendNannyMessage(self): msg = self.nanny_controller.GetNannyMessage() if msg: self.SendReply( rdfvalue.DataBlob(string=msg), session_id=rdfvalue.FlowSessionID(flow_name="NannyMessage"), priority=rdfvalue.GrrMessage.Priority.LOW_PRIORITY, require_fastpoll=False) self.nanny_controller.ClearNannyMessage()
def _ForemanCheckerThread(self): """Sends Foreman checks periodically.""" period = config.CONFIG["Client.foreman_check_frequency"] while True: self._client_worker.SendReply( rdf_protodict.DataBlob(), session_id=rdfvalue.FlowSessionID(flow_name="Foreman"), priority=rdf_flows.GrrMessage.Priority.LOW_PRIORITY) time.sleep(period)
def SendClientAlert(self, msg): self.SendReply( rdfvalue.DataBlob(string=msg), session_id=rdfvalue.FlowSessionID(flow_name="ClientAlert"), priority=rdfvalue.GrrMessage.Priority.LOW_PRIORITY, require_fastpoll=False)
def Run(self): """A Generator which makes a single request to the GRR server. Callers should generate this when they wish to make a connection to the server. It is up to the caller to sleep between calls in order to enforce the required network and CPU utilization policies. Raises: RuntimeError: Too many connection errors have been encountered. Yields: A Status() object indicating how the last POST went. """ while True: self.consecutive_connection_errors = 0 while self.active_server_url is None: if self.EstablishConnection(): # Everything went as expected - we don't need to return to # the main loop (which would mean sleeping for a poll_time). break else: # If we can't reconnect to the server for a long time, we restart # to reset our state. In some very rare cases, the urrlib can get # confused and we need to reset it before we can start talking to # the server again. self.consecutive_connection_errors += 1 limit = config_lib.CONFIG["Client.connection_error_limit"] if self.consecutive_connection_errors > limit: raise RuntimeError( "Too many connection errors, exiting.") # Constantly retrying will not work, we back off a bit. time.sleep(60) yield Status() # Check if there is a message from the nanny to be sent. self.client_worker.SendNannyMessage() now = time.time() # Check with the foreman if we need to if (now > self.last_foreman_check + config_lib.CONFIG["Client.foreman_check_frequency"]): # We must not queue messages from the comms thread with blocking=True # or we might deadlock. If the output queue is full, we can't accept # more work from the foreman anyways so it's ok to drop the message. try: self.client_worker.SendReply( rdfvalue.DataBlob(), session_id=rdfvalue.FlowSessionID(flow_name="Foreman"), priority=rdfvalue.GrrMessage.Priority.LOW_PRIORITY, require_fastpoll=False, blocking=False) self.last_foreman_check = now except Queue.Full: pass status = self.RunOnce() # We suicide if our memory is exceeded, and there is no more work to do # right now. Our death should not result in loss of messages since we are # not holding any requests in our input queues. if (self.client_worker.MemoryExceeded() and not self.client_worker.IsActive() and self.client_worker.InQueueSize() == 0 and self.client_worker.OutQueueSize() == 0): logging.warning("Memory exceeded - exiting.") self.client_worker.SendClientAlert( "Memory limit exceeded, exiting.") # Make sure this will return True so we don't get more work. # pylint: disable=g-bad-name self.client_worker.MemoryExceeded = lambda: True # pylint: enable=g-bad-name # Now send back the client message. self.RunOnce() # And done for now. sys.exit(-1) self.Wait(status) yield status
def SendForemanRequest(self): self.client_worker.SendReply( rdfvalue.DataBlob(), session_id=rdfvalue.FlowSessionID(flow_name="Foreman"), priority=rdfvalue.GrrMessage.Priority.LOW_PRIORITY, require_fastpoll=False)