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