1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2014 The Chromium Authors. All rights reserved.
2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be
3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file.
4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/message_header_validator.h"
6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/validation_context.h"
8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/validation_errors.h"
9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/bindings/lib/validation_util.h"
10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo {
12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace {
13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool IsValidMessageHeader(const internal::MessageHeader* header,
15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                          internal::ValidationContext* validation_context) {
16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // NOTE: Our goal is to preserve support for future extension of the message
17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // header. If we encounter fields we do not understand, we must ignore them.
18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Extra validation of the struct header:
20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (header->version == 0) {
21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (header->num_bytes != sizeof(internal::MessageHeader)) {
22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      internal::ReportValidationError(
23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          validation_context,
24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return false;
26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  } else if (header->version == 1) {
28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (header->num_bytes != sizeof(internal::MessageHeaderWithRequestID)) {
29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      internal::ReportValidationError(
30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          validation_context,
31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return false;
33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  } else if (header->version > 1) {
35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (header->num_bytes < sizeof(internal::MessageHeaderWithRequestID)) {
36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      internal::ReportValidationError(
37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          validation_context,
38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER);
39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return false;
40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Validate flags (allow unknown bits):
44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // These flags require a RequestID.
46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (header->version < 1 && ((header->flags & Message::kFlagExpectsResponse) ||
47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                              (header->flags & Message::kFlagIsResponse))) {
48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    internal::ReportValidationError(
49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        validation_context,
50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        internal::VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID);
51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return false;
52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // These flags are mutually exclusive.
55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if ((header->flags & Message::kFlagExpectsResponse) &&
56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      (header->flags & Message::kFlagIsResponse)) {
57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    internal::ReportValidationError(
58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        validation_context,
59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS);
60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return false;
61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return true;
64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace
67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMessageHeaderValidator::MessageHeaderValidator(MessageReceiver* sink)
69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    : MessageHeaderValidator("MessageHeaderValidator", sink) {}
70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMessageHeaderValidator::MessageHeaderValidator(const std::string& description,
72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                               MessageReceiver* sink)
73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    : MessageFilter(sink), description_(description) {
74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid MessageHeaderValidator::SetDescription(const std::string& description) {
77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  description_ = description;
78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool MessageHeaderValidator::Accept(Message* message) {
81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Pass 0 as number of handles because we don't expect any in the header, even
82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // if |message| contains handles.
83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  internal::ValidationContext validation_context(
84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      message->data(), message->data_num_bytes(), 0, message, description_);
85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (!internal::ValidateStructHeaderAndClaimMemory(message->data(),
87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                                    &validation_context))
88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return false;
89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (!IsValidMessageHeader(message->header(), &validation_context))
91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return false;
92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return sink_->Accept(message);
94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace mojo
97