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