1
// Copyright 2018 Google LLC
2
// Copyright Envoy Project Authors
3
// SPDX-License-Identifier: Apache-2.0
4

            
5
#include "source/common/jwt/struct_utils.h"
6

            
7
#include "absl/strings/str_split.h"
8

            
9
namespace Envoy {
10
namespace JwtVerify {
11

            
12
80767
StructUtils::StructUtils(const Protobuf::Struct& struct_pb) : struct_pb_(struct_pb) {}
13

            
14
200753
StructUtils::FindResult StructUtils::GetString(const std::string& name, std::string* str_value) {
15
200753
  const Protobuf::Value* found;
16
200753
  FindResult result = GetValue(name, found);
17
200753
  if (result != OK) {
18
52439
    return result;
19
52439
  }
20
148314
  if (found->kind_case() != Protobuf::Value::kStringValue) {
21
14
    return WRONG_TYPE;
22
14
  }
23
148300
  *str_value = found->string_value();
24
148300
  return OK;
25
148314
}
26

            
27
115760
StructUtils::FindResult StructUtils::GetDouble(const std::string& name, double* double_value) {
28
115760
  const Protobuf::Value* found;
29
115760
  FindResult result = GetValue(name, found);
30
115760
  if (result != OK) {
31
85890
    return result;
32
85890
  }
33
29870
  if (found->kind_case() != Protobuf::Value::kNumberValue) {
34
3
    return WRONG_TYPE;
35
3
  }
36
29867
  *double_value = found->number_value();
37
29867
  return OK;
38
29870
}
39

            
40
115760
StructUtils::FindResult StructUtils::GetUInt64(const std::string& name, uint64_t* int_value) {
41
115760
  double double_value;
42
115760
  FindResult result = GetDouble(name, &double_value);
43
115760
  if (result != OK) {
44
85893
    return result;
45
85893
  }
46
29867
  if (double_value < 0 ||
47
29867
      double_value >= static_cast<double>(std::numeric_limits<uint64_t>::max())) {
48
6
    return OUT_OF_RANGE;
49
6
  }
50
29861
  *int_value = static_cast<uint64_t>(double_value);
51
29861
  return OK;
52
29867
}
53

            
54
1
StructUtils::FindResult StructUtils::GetBoolean(const std::string& name, bool* bool_value) {
55
1
  const Protobuf::Value* found;
56
1
  FindResult result = GetValue(name, found);
57
1
  if (result != OK) {
58
    return result;
59
  }
60
1
  if (found->kind_case() != Protobuf::Value::kBoolValue) {
61
    return WRONG_TYPE;
62
  }
63
1
  *bool_value = found->bool_value();
64
1
  return OK;
65
1
}
66

            
67
StructUtils::FindResult StructUtils::GetStringList(const std::string& name,
68
38579
                                                   std::vector<std::string>* list) {
69
38579
  const Protobuf::Value* found;
70
38579
  FindResult result = GetValue(name, found);
71
38579
  if (result != OK) {
72
27863
    return result;
73
27863
  }
74
10716
  if (found->kind_case() == Protobuf::Value::kStringValue) {
75
10708
    list->push_back(found->string_value());
76
10708
    return OK;
77
10708
  }
78
8
  if (found->kind_case() == Protobuf::Value::kListValue) {
79
11
    for (const auto& v : found->list_value().values()) {
80
11
      if (v.kind_case() != Protobuf::Value::kStringValue) {
81
1
        return WRONG_TYPE;
82
1
      }
83
10
      list->push_back(v.string_value());
84
10
    }
85
6
    return OK;
86
7
  }
87
1
  return WRONG_TYPE;
88
8
}
89

            
90
StructUtils::FindResult StructUtils::GetValue(const std::string& nested_names,
91
355564
                                              const Protobuf::Value*& found) {
92
355564
  const std::vector<absl::string_view> name_vector = absl::StrSplit(nested_names, '.');
93

            
94
355564
  const Protobuf::Struct* current_struct = &struct_pb_;
95
355592
  for (size_t i = 0; i < name_vector.size(); ++i) {
96
355592
    const auto& fields = current_struct->fields();
97
355592
    const auto it = fields.find(std::string(name_vector[i]));
98
355592
    if (it == fields.end()) {
99
166587
      return MISSING;
100
166587
    }
101
189005
    if (i == name_vector.size() - 1) {
102
188977
      found = &it->second;
103
188977
      return OK;
104
188977
    }
105
28
    if (it->second.kind_case() != Protobuf::Value::kStructValue) {
106
      return WRONG_TYPE;
107
    }
108
28
    current_struct = &it->second.struct_value();
109
28
  }
110
  return MISSING;
111
355564
}
112

            
113
} // namespace JwtVerify
114
} // namespace Envoy