MySQL 8.0.37
Source Code Documentation
access_rights.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2021, 2024, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef MYSQL_HARNESS_ACCESS_RIGHTS_INCLUDED
27#define MYSQL_HARNESS_ACCESS_RIGHTS_INCLUDED
28
29#include "harness_export.h"
30
31#ifdef _WIN32
32#include <aclapi.h>
33#else
34#include <sys/stat.h> // stat
35#include <sys/types.h>
36#include <unistd.h>
37#endif
38
39#include <optional>
40#include <system_error>
41#include <utility> // exchange
42#include <vector>
43
45
46namespace mysql_harness {
47
48#ifndef _WIN32
49
50namespace posix::access_rights {
51
53
54/**
55 * denies permissions.
56 */
57template <int Mask>
59 public:
60 static constexpr const mode_t kMask = Mask;
61 static constexpr const mode_t kFullAccessMask = (S_IRWXU | S_IRWXG | S_IRWXO);
62
63 // Mask MUST not have flags output of FullAccessMask
64 static_assert(!(kMask & ~kFullAccessMask));
65
67 const security_descriptor_type &perms) {
68 if ((perms & kMask) != 0) {
70 make_error_code(std::errc::permission_denied));
71 }
72
73 return {};
74 }
75};
76
77/**
78 * allows permissions.
79 */
80template <int Mask>
82 public:
83 static constexpr const mode_t kMask = Mask;
84 static constexpr const mode_t kFullAccessMask = (S_IRWXU | S_IRWXG | S_IRWXO);
85
87 const security_descriptor_type &perms) {
88 if ((perms & kFullAccessMask) != kMask) {
90 make_error_code(std::errc::permission_denied));
91 }
92
93 return {};
94 }
95};
96
97} // namespace posix::access_rights
98#endif
99
100#ifdef _WIN32
101namespace win32::access_rights {
102
103class LocalDeleter {
104 public:
105 void operator()(void *ptr) { LocalFree(ptr); }
106};
107
108template <class T>
109using LocalAllocated = std::unique_ptr<T, LocalDeleter>;
110
111/**
112 * a smart-pointer for types whose size is discovered at runtime.
113 *
114 * used to wrap APIs like the SECURITY_DESCRIPTOR
115 * on windows which has variable size and explicit no allocation
116 * and no free function.
117 *
118 * It is up to the caller to:
119 *
120 * - ask for the size of the data
121 * - allocate and free
122 *
123 * Uses LocalFree() to free its owned memory which makes it suitable
124 * win32 APIs which explicitly "must be freed with LocalFree()".
125 */
126template <class T>
127class Allocated {
128 public:
129 using allocated_type = LocalAllocated<T>;
130 using pointer = typename allocated_type::pointer;
131 using element_type = typename allocated_type::element_type;
132
133 /**
134 * allocate memory.
135 *
136 * @param size size to allocate.
137 */
138 explicit Allocated(size_t size)
139 : allocated_{reinterpret_cast<pointer>(LocalAlloc(LPTR, size))} {}
140
141 /**
142 * take ownership of p.
143 *
144 * p MUST be allocated by LocalAlloc()
145 */
146 Allocated(pointer p) : allocated_{p} {}
147
148 pointer get() const noexcept { return allocated_.get(); }
149
150 pointer operator->() const { return allocated_.get(); }
151
152 void reset(pointer ptr) { allocated_.reset(ptr); }
153
154 private:
155 allocated_type allocated_;
156};
157
158/**
159 * a Allocated which remembers its size().
160 */
161template <class T>
162class SizedAllocated : public Allocated<T> {
163 public:
164 /**
165 * allocate memory.
166 *
167 * @param size size to allocate.
168 */
169 SizedAllocated(size_t size) : Allocated<T>{size}, size_{size} {}
170
171 [[nodiscard]] size_t size() const noexcept { return size_; }
172
173 private:
174 size_t size_;
175};
176
177using security_descriptor_type = Allocated<SECURITY_DESCRIPTOR>;
178
179/**
180 * a SID structure of a "well-known-sid".
181 */
182stdx::expected<Allocated<SID>, std::error_code> HARNESS_EXPORT
183create_well_known_sid(WELL_KNOWN_SID_TYPE well_known_sid);
184
185/**
186 * get current users SID.
187 */
188stdx::expected<Allocated<SID>, std::error_code> HARNESS_EXPORT
189current_user_sid();
190
191/**
192 * Security Identifier.
193 */
194class HARNESS_EXPORT Sid {
195 public:
196 /**
197 * wrap a native SID pointer.
198 */
199 Sid(SID *sid) : sid_{std::move(sid)} {}
200
201 BYTE revision() const { return sid_->Revision; }
202 BYTE sub_authority_count() const { return sid_->SubAuthorityCount; }
203 SID_IDENTIFIER_AUTHORITY identifier_authority() const {
204 return sid_->IdentifierAuthority;
205 }
206
207 std::string to_string() const;
208
209 SID *native() { return sid_; }
210
211 friend bool operator==(const Sid &, const Sid &);
212
213 private:
214 SID *sid_;
215};
216
217inline bool operator==(const Sid &a, const Sid &b) {
218 return EqualSid(a.sid_, b.sid_);
219}
220
221/**
222 * Access Control Entry.
223 *
224 * header of all ACE structures.
225 */
226class HARNESS_EXPORT Ace {
227 public:
228 Ace(ACE_HEADER *ace) : ace_{std::move(ace)} {}
229
230 BYTE type() const { return ace_->AceType; }
231 BYTE flags() const { return ace_->AceFlags; }
232 WORD size() const { return ace_->AceSize; }
233
234 void *data() const { return ace_; }
235
236 std::string to_string() const;
237
238 private:
239 ACE_HEADER *ace_;
240};
241
242/**
243 * Access Control List.
244 */
245class HARNESS_EXPORT Acl {
246 public:
247 explicit Acl(ACL *acl) : acl_{std::move(acl)} {}
248
249 class HARNESS_EXPORT iterator {
250 public:
251 using value_type = Ace;
252 using reference = value_type &;
253
254 iterator(ACL *acl, size_t ndx) : acl_{acl}, ndx_{ndx} {}
255
256 reference operator*();
257 iterator &operator++();
258 bool operator!=(const iterator &other) const;
259
260 private:
261 ACL *acl_;
262 size_t ndx_;
263
264 value_type ace_{nullptr};
265 };
266
267 iterator begin() const { return {acl_, 0}; }
268 iterator end() const { return {acl_, size()}; }
269
270 size_t size() const;
271
272 std::string to_string() const;
273
274 private:
275 ACL *acl_;
276};
277
278/**
279 * Allowed Access ACE (Access Control Entry).
280 */
281class HARNESS_EXPORT AccessAllowedAce {
282 public:
283 explicit AccessAllowedAce(ACCESS_ALLOWED_ACE *ace) : ace_{ace} {}
284
285 ACCESS_MASK mask() const { return ace_->Mask; }
286 Sid sid() const { return reinterpret_cast<SID *>(&ace_->SidStart); }
287
288 std::string to_string() const;
289
290 private:
291 ACCESS_ALLOWED_ACE *ace_;
292};
293
294/**
295 * a optional DACL.
296 *
297 * a optional DACL allows to differentiate between an empty DACL and a no DACL:
298 *
299 * - if no DACL is set, everything is allowed.
300 * - if a DACL is set, but empty, nothing is allowed.
301 */
302using OptionalDacl = std::optional<ACL *>;
303
304/**
305 * Security Descriptor.
306 *
307 * contains a DACL.
308 *
309 * may be in absolute or self-relative form.
310 */
311class HARNESS_EXPORT SecurityDescriptor {
312 public:
313 /**
314 * wrap a native SECURITY_DESCRITOR pointer.
315 *
316 * does NOT take ownership of the SECURITY_DESCRIPTOR.
317 */
318 explicit SecurityDescriptor(SECURITY_DESCRIPTOR *desc) : desc_{desc} {}
319
320 /**
321 * initialize an security descriptor with a revision.
322 *
323 * the descriptor will:
324 *
325 * - have no SACL
326 * - no DACL
327 * - no owner
328 * - no primary group
329 * - all control flags set to false.
330 */
332 DWORD revision = SECURITY_DESCRIPTOR_REVISION);
333
334 /**
335 * set optional ACL
336 */
337 stdx::expected<void, std::error_code> dacl(const OptionalDacl &dacl,
338 bool dacl_defaulted);
339
340 /**
341 * get a optional ACL.
342 */
344
345 /**
346 * check if a security descriptor is self-relative.
347 */
348 bool is_self_relative() const {
349 return control().value_or(0) & SE_SELF_RELATIVE;
350 }
351
352 /**
353 * get the control bits of a security descritor.
354 */
356
357 /**
358 * transform a security descriptor into self-relative form.
359 */
361 make_self_relative();
362
363 /**
364 * get string representation.
365 */
366 std::string to_string() const;
367
368 private:
369 SECURITY_DESCRIPTOR *desc_;
370};
371
372class HARNESS_EXPORT AclBuilder {
373 public:
374 struct WellKnownSid {
375 WELL_KNOWN_SID_TYPE sid;
376 };
377
378 /**
379 * identify a current-user-lookup.
380 */
381 struct CurrentUser {};
382
383 /**
384 * grant additional rights to a trustee identified by a SID.
385 *
386 * when applied will combine the specified rights with the existing allowed
387 * or denied rights of the trustee.
388 *
389 * @param sid SID of the trustee
390 * @param rights rights to grant.
391 */
392 static EXPLICIT_ACCESSW ace_grant_access(SID *sid, DWORD rights);
393
394 /**
395 * set rights of a trustee identified by a SID.
396 *
397 * when applied will set the specified rights of the trustee.
398 *
399 * @param sid SID of the trustee
400 * @param rights rights to grant.
401 */
402 static EXPLICIT_ACCESSW ace_set_access(SID *sid, DWORD rights);
403
404 /**
405 * revoke access of a trustee identified by a SID.
406 *
407 * when applied will revoke the all rights of the trustee.
408 *
409 * @param sid SID of the trustee
410 */
411 static EXPLICIT_ACCESSW ace_revoke_access(SID *sid);
412
413 /**
414 * create a AclBuilder from a empty security descriptor.
415 */
416 AclBuilder();
417
418 /**
419 * create a AclBuilder from an existing security descritor.
420 */
421 explicit AclBuilder(security_descriptor_type old_desc);
422
423 /**
424 * grant additional access rights to the current user.
425 */
426 AclBuilder &grant(CurrentUser, DWORD rights);
427
428 /**
429 * grant additional access rights to a well-known-sid.
430 */
431 AclBuilder &grant(const WellKnownSid &owner, DWORD rights);
432
433 AclBuilder &grant(Allocated<SID> sid, DWORD rights);
434
435 AclBuilder &set(CurrentUser, DWORD rights);
436
437 AclBuilder &set(const WellKnownSid &owner, DWORD rights);
438
439 AclBuilder &set(Allocated<SID> sid, DWORD rights);
440
441 AclBuilder &revoke(CurrentUser);
442
443 AclBuilder &revoke(const WellKnownSid &owner);
444
445 AclBuilder &revoke(Allocated<SID> sid);
446
448
449 private:
450 std::vector<Allocated<SID>> owned_sids_;
451
452 std::error_code ec_{};
453 std::vector<EXPLICIT_ACCESSW> perms_;
454 mysql_harness::win32::access_rights::OptionalDacl dacl_;
455 // Allocated<SECURITY_DESCRIPTOR>
456 security_descriptor_type old_desc_;
457};
458
459class HARNESS_EXPORT AllowUserReadWritableVerifier {
460 public:
462 const security_descriptor_type &perms);
463};
464
465class HARNESS_EXPORT DenyOtherReadWritableVerifier {
466 public:
468 const security_descriptor_type &perms);
469};
470
471} // namespace win32::access_rights
472#endif
473
474#ifdef _WIN32
476#else
478#endif
479
480/**
481 * fail access_rights_verify() if others can read or write or execute.
482 */
484#ifdef _WIN32
486#else
488#endif
489
490/**
491 * fail access_rights_verify() if someone else then the owner of the file can
492 * read or write.
493 */
495#ifdef _WIN32
497#else
499#endif
500
501/**
502 * get a access rights of file.
503 *
504 * @param file_name of a file.
505 */
507access_rights_get(const std::string &file_name) noexcept;
508
509/**
510 * check if a security descriptor satisfies a verifier.
511 */
512template <class Func>
514 const security_descriptor_type &rights, Func &&func) {
515 return func(rights);
516}
517
518/**
519 * set access rights of a file.
520 */
522 const std::string &file_name, const security_descriptor_type &sec_desc);
523
524} // namespace mysql_harness
525#endif
Sid class.
Definition: common.h:219
allows permissions.
Definition: access_rights.h:81
stdx::expected< void, std::error_code > operator()(const security_descriptor_type &perms)
Definition: access_rights.h:86
static constexpr const mode_t kFullAccessMask
Definition: access_rights.h:84
static constexpr const mode_t kMask
Definition: access_rights.h:83
denies permissions.
Definition: access_rights.h:58
static constexpr const mode_t kMask
Definition: access_rights.h:60
stdx::expected< void, std::error_code > operator()(const security_descriptor_type &perms)
Definition: access_rights.h:66
static constexpr const mode_t kFullAccessMask
Definition: access_rights.h:61
Definition: expected.h:944
const char * p
Definition: ctype-mb.cc:1237
static int flags[50]
Definition: hp_test1.cc:40
static mi_bit_type mask[]
Definition: mi_packrec.cc:141
bool operator!=(const my_thread_handle &a, const my_thread_handle &b)
Definition: my_thread.h:158
bool operator==(const my_thread_handle &a, const my_thread_handle &b)
Definition: my_thread.h:151
uint16_t value_type
Definition: vt100.h:184
std::string HARNESS_EXPORT reset()
get 'reset attributes' ESC sequence.
Definition: vt100.cc:37
bool initialize(THD *thd)
Initialize the dictionary while starting the server for the first time.
Definition: bootstrapper.cc:886
std::string file_name(Log_file_id file_id)
Provides name of the log file with the given file id, e.g.
Definition: log0pre_8_0_30.cc:94
mode_t security_descriptor_type
Definition: access_rights.h:52
Definition: common.h:42
std::string HARNESS_EXPORT to_string(const ShutdownPending::Reason &reason)
Definition: process_state_component.cc:60
std::error_code make_error_code(DynamicLoaderErrc ec)
make error_code from a DynamicLoaderErrc.
Definition: dynamic_loader.cc:79
HARNESS_EXPORT stdx::expected< void, std::error_code > access_rights_set(const std::string &file_name, const security_descriptor_type &sec_desc)
set access rights of a file.
Definition: access_rights.cc:759
posix::access_rights::DenyPermissionVerifier<(S_IRWXO)> DenyOtherReadWritableVerifier
fail access_rights_verify() if others can read or write or execute.
Definition: access_rights.h:487
posix::access_rights::security_descriptor_type security_descriptor_type
Definition: access_rights.h:477
posix::access_rights::AllowPermissionVerifier<(S_IRUSR|S_IWUSR)> AllowUserReadWritableVerifier
fail access_rights_verify() if someone else then the owner of the file can read or write.
Definition: access_rights.h:498
stdx::expected< void, std::error_code > access_rights_verify(const security_descriptor_type &rights, Func &&func)
check if a security descriptor satisfies a verifier.
Definition: access_rights.h:513
HARNESS_EXPORT stdx::expected< security_descriptor_type, std::error_code > access_rights_get(const std::string &file_name) noexcept
get a access rights of file.
Definition: access_rights.cc:743
void get(PSI_field *, PSI_longlong *) noexcept
Definition: pfs_plugin_column_bigint_v1_all_empty.cc:32
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:192
Definition: gcs_xcom_synode.h:64
constexpr auto make_unexpected(E &&e) -> unexpected< std::decay_t< E > >
Definition: expected.h:125
std::set< Key, Compare, ut::allocator< Key > > set
Specialization of set which uses ut_allocator.
Definition: ut0new.h:2882
required string type
Definition: replication_group_member_actions.proto:34
Ssl_acceptor_context_property_type & operator++(Ssl_acceptor_context_property_type &property_type)
Increment operator for Ssl_acceptor_context_type Used by iterator.
Definition: ssl_acceptor_context_data.cc:114