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 #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kControl
32 
33 #include "mongo/platform/basic.h"
34 
35 #include "mongo/util/version.h"
36 
37 #include "mongo/config.h"
38 
39 #ifdef MONGO_CONFIG_SSL
40 #include <openssl/crypto.h>
41 #endif
42 
43 #include <pcrecpp.h>
44 
45 #include <sstream>
46 
47 #include "mongo/db/jsobj.h"
48 #include "mongo/util/assert_util.h"
49 #include "mongo/util/log.h"
50 
51 namespace mongo {
52 namespace {
53 
54 const class : public VersionInfoInterface {
55 public:
majorVersion() const56     int majorVersion() const noexcept final {
57         return 0;
58     }
59 
minorVersion() const60     int minorVersion() const noexcept final {
61         return 0;
62     }
63 
patchVersion() const64     int patchVersion() const noexcept final {
65         return 0;
66     }
67 
extraVersion() const68     int extraVersion() const noexcept final {
69         return 0;
70     }
71 
version() const72     StringData version() const noexcept final {
73         return "unknown";
74     }
75 
gitVersion() const76     StringData gitVersion() const noexcept final {
77         return "none";
78     }
79 
modules() const80     std::vector<StringData> modules() const final {
81         return {"unknown"};
82     }
83 
allocator() const84     StringData allocator() const noexcept final {
85         return "unknown";
86     }
87 
jsEngine() const88     StringData jsEngine() const noexcept final {
89         return "unknown";
90     }
91 
targetMinOS() const92     StringData targetMinOS() const noexcept final {
93         return "unknown";
94     }
95 
buildInfo() const96     std::vector<BuildInfoTuple> buildInfo() const final {
97         return {};
98     }
99 
100 } kFallbackVersionInfo{};
101 
102 const VersionInfoInterface* globalVersionInfo = nullptr;
103 
104 }  // namespace
105 
enable(const VersionInfoInterface * handler)106 void VersionInfoInterface::enable(const VersionInfoInterface* handler) {
107     globalVersionInfo = handler;
108 }
109 
instance(NotEnabledAction action)110 const VersionInfoInterface& VersionInfoInterface::instance(NotEnabledAction action) noexcept {
111     if (globalVersionInfo)
112         return *globalVersionInfo;
113     if (action == NotEnabledAction::kFallback)
114         return kFallbackVersionInfo;
115     severe() << "Terminating because valid version info has not been configured";
116     fassertFailed(40278);
117 }
118 
isSameMajorVersion(const char * otherVersion) const119 bool VersionInfoInterface::isSameMajorVersion(const char* otherVersion) const noexcept {
120     int major = -1, minor = -1;
121     pcrecpp::RE ver_regex("^(\\d+)\\.(\\d+)\\.");
122     ver_regex.PartialMatch(otherVersion, &major, &minor);
123 
124     if (major == -1 || minor == -1)
125         return false;
126 
127     return (major == majorVersion() && minor == minorVersion());
128 }
129 
makeVersionString(StringData binaryName) const130 std::string VersionInfoInterface::makeVersionString(StringData binaryName) const {
131     std::stringstream ss;
132     ss << binaryName << " v" << version();
133     return ss.str();
134 }
135 
appendBuildInfo(BSONObjBuilder * result) const136 void VersionInfoInterface::appendBuildInfo(BSONObjBuilder* result) const {
137     *result << "version" << version() << "gitVersion" << gitVersion()
138 #if defined(_WIN32)
139             << "targetMinOS" << targetMinOS()
140 #endif
141             << "modules" << modules() << "allocator" << allocator() << "javascriptEngine"
142             << jsEngine() << "sysInfo"
143             << "deprecated";
144 
145     BSONArrayBuilder versionArray(result->subarrayStart("versionArray"));
146     versionArray << majorVersion() << minorVersion() << patchVersion() << extraVersion();
147     versionArray.done();
148 
149     BSONObjBuilder opensslInfo(result->subobjStart("openssl"));
150 #ifdef MONGO_CONFIG_SSL
151     opensslInfo << "running" << openSSLVersion() << "compiled" << OPENSSL_VERSION_TEXT;
152 #else
153     opensslInfo << "running"
154                 << "disabled"
155                 << "compiled"
156                 << "disabled";
157 #endif
158     opensslInfo.done();
159 
160     BSONObjBuilder buildvarsInfo(result->subobjStart("buildEnvironment"));
161     for (auto&& envDataEntry : buildInfo()) {
162         if (std::get<2>(envDataEntry)) {
163             buildvarsInfo << std::get<0>(envDataEntry) << std::get<1>(envDataEntry);
164         }
165     }
166     buildvarsInfo.done();
167 
168     *result << "bits" << (int)sizeof(void*) * 8;
169     result->appendBool("debug", kDebugBuild);
170     result->appendNumber("maxBsonObjectSize", BSONObjMaxUserSize);
171 }
172 
openSSLVersion(StringData prefix,StringData suffix) const173 std::string VersionInfoInterface::openSSLVersion(StringData prefix, StringData suffix) const {
174 #ifndef MONGO_CONFIG_SSL
175     return "";
176 #else
177     return prefix.toString() + SSLeay_version(SSLEAY_VERSION) + suffix;
178 #endif
179 }
180 
logTargetMinOS() const181 void VersionInfoInterface::logTargetMinOS() const {
182     log() << "targetMinOS: " << targetMinOS();
183 }
184 
logBuildInfo() const185 void VersionInfoInterface::logBuildInfo() const {
186     log() << "git version: " << gitVersion();
187 
188 #ifdef MONGO_CONFIG_SSL
189     log() << openSSLVersion("OpenSSL version: ");
190 #endif
191 
192     log() << "allocator: " << allocator();
193 
194     std::stringstream ss;
195     ss << "modules: ";
196     auto modules_list = modules();
197     if (modules_list.size() == 0) {
198         ss << "none";
199     } else {
200         for (const auto& m : modules_list) {
201             ss << m << " ";
202         }
203     }
204     log() << ss.str();
205 
206     log() << "build environment:";
207     for (auto&& envDataEntry : buildInfo()) {
208         if (std::get<3>(envDataEntry)) {
209             auto val = std::get<1>(envDataEntry);
210             if (val.size() == 0)
211                 continue;
212             log() << "    " << std::get<0>(envDataEntry) << ": " << std::get<1>(envDataEntry);
213         }
214     }
215 }
216 
mongoShellVersion(const VersionInfoInterface & provider)217 std::string mongoShellVersion(const VersionInfoInterface& provider) {
218     std::stringstream ss;
219     ss << "MongoDB shell version v" << provider.version();
220     return ss.str();
221 }
222 
mongosVersion(const VersionInfoInterface & provider)223 std::string mongosVersion(const VersionInfoInterface& provider) {
224     std::stringstream ss;
225     ss << "mongos version v" << provider.version();
226     return ss.str();
227 }
228 
mongodVersion(const VersionInfoInterface & provider)229 std::string mongodVersion(const VersionInfoInterface& provider) {
230     std::stringstream ss;
231     ss << "db version v" << provider.version();
232     return ss.str();
233 }
234 
235 }  // namespace mongo
236