예제 #1
0
  def testReordering(self):
    """Check that out of order client messages are reordered."""
    flow_obj = self.FlowSetup("FlowOrderTest")

    # Simultate processing messages arriving in random order
    message_ids = [2, 1, 4, 3, 5]
    self.SendMessages(message_ids, flow_obj.session_id)

    # Send the status message
    message = self.SendOKStatus(6, flow_obj.session_id)

    runner = flow_runner.FlowRunner(flow_obj)
    notification = rdfvalue.Notification(timestamp=rdfvalue.RDFDatetime().Now())
    runner.ProcessCompletedRequests(notification, [message])

    # Check that the messages were processed in order
    self.assertEqual(flow_obj.messages, [1, 2, 3, 4, 5])
예제 #2
0
  def testAuthentication1(self):
    """Test that flows refuse to processes unauthenticated messages."""
    flow_obj = self.FlowSetup("FlowOrderTest")

    # Simultate processing messages arriving in random order
    message_ids = [2, 1, 4, 3, 5]
    self.SendMessages(message_ids, flow_obj.session_id,
                      authenticated=False)

    # Send the status message
    message = self.SendOKStatus(6, flow_obj.session_id)

    runner = flow_runner.FlowRunner(flow_obj)
    notification = rdfvalue.Notification(timestamp=rdfvalue.RDFDatetime().Now())
    runner.ProcessCompletedRequests(notification, [message])

    # Now messages should actually be processed
    self.assertEqual(flow_obj.messages, [])
예제 #3
0
  def testAuthentication2(self):
    """Test that flows refuse to processes unauthenticated messages.

    Here we try to simulate an attacker injecting unauthenticated
    messages midstream.

    The current implementation actually fails to process the entire
    flow since the injected messages displace the real ones if they
    arrive earlier. This can be an effective DoS against legitimate
    clients but would require attackers to guess session ids.
    """
    flow_obj = self.FlowSetup("FlowOrderTest")

    # Simultate processing messages arriving in random order
    message_ids = [1, 2]
    self.SendMessages(message_ids, flow_obj.session_id,
                      authenticated=True)

    # Now suppose some of the messages are spoofed
    message_ids = [3, 4, 5]
    self.SendMessages(message_ids, flow_obj.session_id,
                      authenticated=False)

    # And now our real messages arrive
    message_ids = [5, 6]
    self.SendMessages(message_ids, flow_obj.session_id,
                      authenticated=True)

    # Send the status message
    message = self.SendOKStatus(7, flow_obj.session_id)

    runner = flow_runner.FlowRunner(flow_obj)
    notification = rdfvalue.Notification(timestamp=rdfvalue.RDFDatetime().Now())
    runner.ProcessCompletedRequests(notification, [message])

    # Some messages should actually be processed
    self.assertEqual(flow_obj.messages, [1, 2, 5, 6])
예제 #4
0
    def Notify(self, message_type, subject, msg):
        """Send a notification to the originating user.

    Args:
       message_type: The type of the message. This allows the UI to format
         a link to the original object e.g. "ViewObject" or "HostInformation"
       subject: The urn of the AFF4 object of interest in this link.
       msg: A free form textual message.
    """
        user = self.context.creator
        # Don't send notifications to system users.
        if self.args.notify_to_user and user not in aff4.GRRUser.SYSTEM_USERS:

            # Prefix the message with the hostname of the client we are running
            # against.
            if self.args.client_id:
                client_fd = aff4.FACTORY.Open(self.args.client_id,
                                              mode="rw",
                                              token=self.token)
                hostname = client_fd.Get(client_fd.Schema.HOSTNAME) or ""
                client_msg = "%s: %s" % (hostname, msg)
            else:
                client_msg = msg

            # Add notification to the User object.
            fd = aff4.FACTORY.Create(aff4.ROOT_URN.Add("users").Add(user),
                                     "GRRUser",
                                     mode="rw",
                                     token=self.token)

            # Queue notifications to the user.
            fd.Notify(message_type, subject, client_msg, self.session_id)
            fd.Close()

            # Add notifications to the flow.
            notification = rdfvalue.Notification(
                type=message_type,
                subject=utils.SmartUnicode(subject),
                message=utils.SmartUnicode(msg),
                source=self.session_id,
                timestamp=rdfvalue.RDFDatetime().Now())

            data_store.DB.Set(self.session_id,
                              aff4.AFF4Object.GRRFlow.SchemaCls.NOTIFICATION,
                              notification,
                              replace=False,
                              sync=False,
                              token=self.token)

            # Disable further notifications.
            self.context.user_notified = True

        # Allow the flow to either specify an event name or an event handler URN.
        notification_event = (self.args.notification_event
                              or self.args.notification_urn)
        if notification_event:
            if self.context.state == rdfvalue.Flow.State.ERROR:
                status = rdfvalue.FlowNotification.Status.ERROR

            else:
                status = rdfvalue.FlowNotification.Status.OK

            event = rdfvalue.FlowNotification(
                session_id=self.context.session_id,
                flow_name=self.args.flow_name,
                client_id=self.args.client_id,
                status=status)

            self.flow_obj.Publish(notification_event, message=event)