1
2 /**
3 * Copyright (C) 2018-present MongoDB, Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the Server Side Public License, version 1,
7 * as published by MongoDB, Inc.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * Server Side Public License for more details.
13 *
14 * You should have received a copy of the Server Side Public License
15 * along with this program. If not, see
16 * <http://www.mongodb.com/licensing/server-side-public-license>.
17 *
18 * As a special exception, the copyright holders give permission to link the
19 * code of portions of this program with the OpenSSL library under certain
20 * conditions as described in each individual source file and distribute
21 * linked combinations including the program with the OpenSSL library. You
22 * must comply with the Server Side Public License in all respects for
23 * all of the code used other than as permitted herein. If you modify file(s)
24 * with this exception, you may extend this exception to your version of the
25 * file(s), but you are not obligated to do so. If you do not wish to do so,
26 * delete this exception statement from your version. If you delete this
27 * exception statement from all source files in the program, then also delete
28 * it in the license file.
29 */
30
31 #include "mongo/platform/basic.h"
32
33 #include "mongo/db/auth/address_restriction.h"
34 #include "mongo/db/auth/address_restriction_gen.h"
35 #include "mongo/db/server_options.h"
36 #include "mongo/stdx/memory.h"
37
38 constexpr mongo::StringData mongo::address_restriction_detail::ClientSource::label;
39 constexpr mongo::StringData mongo::address_restriction_detail::ClientSource::field;
40
41 constexpr mongo::StringData mongo::address_restriction_detail::ServerAddress::label;
42 constexpr mongo::StringData mongo::address_restriction_detail::ServerAddress::field;
43
parseAddressRestrictionSet(const BSONObj & obj)44 mongo::StatusWith<mongo::RestrictionSet<>> mongo::parseAddressRestrictionSet(
45 const BSONObj& obj) try {
46 IDLParserErrorContext ctx("address restriction");
47 const auto ar = Address_restriction::parse(ctx, obj);
48 std::vector<std::unique_ptr<NamedRestriction>> vec;
49
50 const boost::optional<std::vector<StringData>>& client = ar.getClientSource();
51 if (client) {
52 vec.push_back(stdx::make_unique<ClientSourceRestriction>(client.get()));
53 }
54
55 const boost::optional<std::vector<StringData>>& server = ar.getServerAddress();
56 if (server) {
57 vec.push_back(stdx::make_unique<ServerAddressRestriction>(server.get()));
58 }
59
60 if (vec.empty()) {
61 return Status(ErrorCodes::CollectionIsEmpty,
62 "At least one of 'clientSource' or 'serverAddress' must be set");
63 }
64 return RestrictionSet<>(std::move(vec));
65 } catch (const DBException& e) {
66 return Status(ErrorCodes::BadValue, e.what());
67 }
68
parseAuthenticationRestriction(const BSONArray & arr)69 mongo::StatusWith<mongo::SharedRestrictionDocument> mongo::parseAuthenticationRestriction(
70 const BSONArray& arr) {
71 static_assert(
72 std::is_same<std::shared_ptr<RestrictionDocument<>>, SharedRestrictionDocument>::value,
73 "SharedRestrictionDocument expected to be a shared_ptr to a RestrictionDocument<>");
74 using document_type = SharedRestrictionDocument::element_type;
75 static_assert(std::is_same<document_type::pointer_type,
76 std::unique_ptr<document_type::element_type>>::value,
77 "SharedRestrictionDocument expected to contain a sequence of unique_ptrs");
78
79 document_type::sequence_type doc;
80 for (const auto& elem : arr) {
81 if (elem.type() != Object) {
82 return Status(ErrorCodes::UnsupportedFormat,
83 "restriction array sub-documents must be address restriction objects");
84 }
85
86 auto restriction = parseAddressRestrictionSet(elem.Obj());
87 if (!restriction.isOK()) {
88 return restriction.getStatus();
89 }
90
91 doc.emplace_back(
92 stdx::make_unique<document_type::element_type>(std::move(restriction.getValue())));
93 }
94
95 return std::make_shared<document_type>(std::move(doc));
96 }
97
getRawAuthenticationRestrictions(const BSONArray & arr)98 mongo::StatusWith<mongo::BSONArray> mongo::getRawAuthenticationRestrictions(
99 const BSONArray& arr) noexcept try {
100 BSONArrayBuilder builder;
101
102 for (auto const& elem : arr) {
103 if (elem.type() != Object) {
104 return Status(ErrorCodes::UnsupportedFormat,
105 "'authenticationRestrictions' array sub-documents must be address "
106 "restriction objects");
107 }
108 IDLParserErrorContext ctx("address restriction");
109 auto const ar = Address_restriction::parse(ctx, elem.Obj());
110 if (auto const&& client = ar.getClientSource()) {
111 // Validate
112 ClientSourceRestriction(client.get());
113 }
114 if (auto const&& server = ar.getServerAddress()) {
115 // Validate
116 ServerAddressRestriction(server.get());
117 }
118 if (!ar.getClientSource() && !ar.getServerAddress()) {
119 return Status(ErrorCodes::CollectionIsEmpty,
120 "At least one of 'clientSource' and/or 'serverAddress' must be set");
121 }
122 builder.append(ar.toBSON());
123 }
124 return builder.arr();
125 } catch (const DBException& e) {
126 return Status(ErrorCodes::BadValue, e.what());
127 } catch (const std::exception& e) {
128 return Status(ErrorCodes::InternalError, e.what());
129 }
130