Home | History | Annotate | Download | only in lib
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "mojo/public/cpp/bindings/lib/message_header_validator.h"
      6 
      7 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
      8 #include "mojo/public/cpp/bindings/lib/bounds_checker.h"
      9 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
     10 
     11 namespace mojo {
     12 namespace internal {
     13 namespace {
     14 
     15 bool IsValidMessageHeader(const MessageHeader* header) {
     16   // NOTE: Our goal is to preserve support for future extension of the message
     17   // header. If we encounter fields we do not understand, we must ignore them.
     18 
     19   // Extra validation of the struct header:
     20   if (header->num_fields == 2) {
     21     if (header->num_bytes != sizeof(MessageHeader)) {
     22       ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
     23       return false;
     24     }
     25   } else if (header->num_fields == 3) {
     26     if (header->num_bytes != sizeof(MessageHeaderWithRequestID)) {
     27       ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
     28       return false;
     29     }
     30   } else if (header->num_fields > 3) {
     31     if (header->num_bytes < sizeof(MessageHeaderWithRequestID)) {
     32       ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
     33       return false;
     34     }
     35   }
     36 
     37   // Validate flags (allow unknown bits):
     38 
     39   // These flags require a RequestID.
     40   if (header->num_fields < 3 &&
     41         ((header->flags & kMessageExpectsResponse) ||
     42          (header->flags & kMessageIsResponse))) {
     43     ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID);
     44     return false;
     45   }
     46 
     47   // These flags are mutually exclusive.
     48   if ((header->flags & kMessageExpectsResponse) &&
     49       (header->flags & kMessageIsResponse)) {
     50     ReportValidationError(
     51         VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION);
     52     return false;
     53   }
     54 
     55   return true;
     56 }
     57 
     58 }  // namespace
     59 
     60 MessageHeaderValidator::MessageHeaderValidator(MessageReceiver* sink)
     61     : MessageFilter(sink) {
     62 }
     63 
     64 bool MessageHeaderValidator::Accept(Message* message) {
     65   // Pass 0 as number of handles because we don't expect any in the header, even
     66   // if |message| contains handles.
     67   BoundsChecker bounds_checker(message->data(), message->data_num_bytes(), 0);
     68 
     69   if (!ValidateStructHeader(message->data(), sizeof(MessageHeader), 2,
     70                             &bounds_checker)) {
     71     return false;
     72   }
     73 
     74   if (!IsValidMessageHeader(message->header()))
     75     return false;
     76 
     77   return sink_->Accept(message);
     78 }
     79 
     80 }  // namespace internal
     81 }  // namespace mojo
     82