MySQL 8.3.0
Source Code Documentation
access_rights.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2021, 2023, 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 value_type = Ace;
251 using reference = value_type &;
252
253 iterator(ACL *acl, size_t ndx) : acl_{acl}, ndx_{ndx} {}
254
255 reference operator*();
256 iterator &operator++();
257 bool operator!=(const iterator &other) const;
258
259 private:
260 ACL *acl_;
261 size_t ndx_;
262
263 value_type ace_{nullptr};
264 };
265
266 iterator begin() const { return {acl_, 0}; }
267 iterator end() const { return {acl_, size()}; }
268
269 size_t size() const;
270
271 std::string to_string() const;
272
273 private:
274 ACL *acl_;
275};
276
277/**
278 * Allowed Access ACE (Access Control Entry).
279 */
280class HARNESS_EXPORT AccessAllowedAce {
281 public:
282 explicit AccessAllowedAce(ACCESS_ALLOWED_ACE *ace) : ace_{ace} {}
283
284 ACCESS_MASK mask() const { return ace_->Mask; }
285 Sid sid() const { return reinterpret_cast<SID *>(&ace_->SidStart); }
286
287 std::string to_string() const;
288
289 private:
290 ACCESS_ALLOWED_ACE *ace_;
291};
292
293/**
294 * a optional DACL.
295 *
296 * a optional DACL allows to differentiate between an empty DACL and a no DACL:
297 *
298 * - if no DACL is set, everything is allowed.
299 * - if a DACL is set, but empty, nothing is allowed.
300 */
301using OptionalDacl = std::optional<ACL *>;
302
303/**
304 * Security Descriptor.
305 *
306 * contains a DACL.
307 *
308 * may be in absolute or self-relative form.
309 */
310class HARNESS_EXPORT SecurityDescriptor {
311 public:
312 /**
313 * wrap a native SECURITY_DESCRITOR pointer.
314 *
315 * does NOT take ownership of the SECURITY_DESCRIPTOR.
316 */
317 explicit SecurityDescriptor(SECURITY_DESCRIPTOR *desc) : desc_{desc} {}
318
319 /**
320 * initialize an security descriptor with a revision.
321 *
322 * the descriptor will:
323 *
324 * - have no SACL
325 * - no DACL
326 * - no owner
327 * - no primary group
328 * - all control flags set to false.
329 */
331 DWORD revision = SECURITY_DESCRIPTOR_REVISION);
332
333 /**
334 * set optional ACL
335 */
336 stdx::expected<void, std::error_code> dacl(const OptionalDacl &dacl,
337 bool dacl_defaulted);
338
339 /**
340 * get a optional ACL.
341 */
343
344 /**
345 * check if a security descriptor is self-relative.
346 */
347 bool is_self_relative() const {
348 return control().value_or(0) & SE_SELF_RELATIVE;
349 }
350
351 /**
352 * get the control bits of a security descritor.
353 */
355
356 /**
357 * transform a security descriptor into self-relative form.
358 */
360 make_self_relative();
361
362 /**
363 * get string representation.
364 */
365 std::string to_string() const;
366
367 private:
368 SECURITY_DESCRIPTOR *desc_;
369};
370
371class HARNESS_EXPORT AclBuilder {
372 public:
373 struct WellKnownSid {
374 WELL_KNOWN_SID_TYPE sid;
375 };
376
377 /**
378 * identify a current-user-lookup.
379 */
380 struct CurrentUser {};
381
382 /**
383 * grant additional rights to a trustee identified by a SID.
384 *
385 * when applied will combine the specified rights with the existing allowed
386 * or denied rights of the trustee.
387 *
388 * @param sid SID of the trustee
389 * @param rights rights to grant.
390 */
391 static EXPLICIT_ACCESSW ace_grant_access(SID *sid, DWORD rights);
392
393 /**
394 * set rights of a trustee identified by a SID.
395 *
396 * when applied will set the specified rights of the trustee.
397 *
398 * @param sid SID of the trustee
399 * @param rights rights to grant.
400 */
401 static EXPLICIT_ACCESSW ace_set_access(SID *sid, DWORD rights);
402
403 /**
404 * revoke access of a trustee identified by a SID.
405 *
406 * when applied will revoke the all rights of the trustee.
407 *
408 * @param sid SID of the trustee
409 */
410 static EXPLICIT_ACCESSW ace_revoke_access(SID *sid);
411
412 /**
413 * create a AclBuilder from a empty security descriptor.
414 */
415 AclBuilder();
416
417 /**
418 * create a AclBuilder from an existing security descritor.
419 */
420 explicit AclBuilder(security_descriptor_type old_desc);
421
422 /**
423 * grant additional access rights to the current user.
424 */
425 AclBuilder &grant(CurrentUser, DWORD rights);
426
427 /**
428 * grant additional access rights to a well-known-sid.
429 */
430 AclBuilder &grant(const WellKnownSid &owner, DWORD rights);
431
432 AclBuilder &grant(Allocated<SID> sid, DWORD rights);
433
434 AclBuilder &set(CurrentUser, DWORD rights);
435
436 AclBuilder &set(const WellKnownSid &owner, DWORD rights);
437
438 AclBuilder &set(Allocated<SID> sid, DWORD rights);
439
440 AclBuilder &revoke(CurrentUser);
441
442 AclBuilder &revoke(const WellKnownSid &owner);
443
444 AclBuilder &revoke(Allocated<SID> sid);
445
447
448 private:
449 std::vector<Allocated<SID>> owned_sids_;
450
451 std::error_code ec_{};
452 std::vector<EXPLICIT_ACCESSW> perms_;
453 mysql_harness::win32::access_rights::OptionalDacl dacl_;
454 // Allocated<SECURITY_DESCRIPTOR>
455 security_descriptor_type old_desc_;
456};
457
458class HARNESS_EXPORT AllowUserReadWritableVerifier {
459 public:
461 const security_descriptor_type &perms);
462};
463
464class HARNESS_EXPORT DenyOtherReadWritableVerifier {
465 public:
467 const security_descriptor_type &perms);
468};
469
470} // namespace win32::access_rights
471#endif
472
473#ifdef _WIN32
475#else
477#endif
478
479/**
480 * fail access_rights_verify() if others can read or write or execute.
481 */
483#ifdef _WIN32
485#else
487#endif
488
489/**
490 * fail access_rights_verify() if someone else then the owner of the file can
491 * read or write.
492 */
494#ifdef _WIN32
496#else
498#endif
499
500/**
501 * get a access rights of file.
502 *
503 * @param file_name of a file.
504 */
506access_rights_get(const std::string &file_name) noexcept;
507
508/**
509 * check if a security descriptor satisfies a verifier.
510 */
511template <class Func>
513 const security_descriptor_type &rights, Func &&func) {
514 return func(rights);
515}
516
517/**
518 * set access rights of a file.
519 */
521 const std::string &file_name, const security_descriptor_type &sec_desc);
522
523} // namespace mysql_harness
524#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:1234
static int flags[50]
Definition: hp_test1.cc:39
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
void * begin(THD *thd, const TABLE *table, size_t data_size, size_t memory, size_t num_threads) noexcept
Definition: bulk_data_service.cc:1533
uint16_t value_type
Definition: vt100.h:183
std::string HARNESS_EXPORT reset()
get 'reset attributes' ESC sequence.
Definition: vt100.cc:36
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
MYSQL_STRINGS_EXPORT void initialize(const char *charset_dir=nullptr, MY_CHARSET_LOADER *loader=nullptr)
Initialize character set/collation library.
Definition: collations.cc:97
mode_t security_descriptor_type
Definition: access_rights.h:51
Definition: common.h:41
std::string HARNESS_EXPORT to_string(const ShutdownPending::Reason &reason)
Definition: process_state_component.cc:59
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:758
posix::access_rights::DenyPermissionVerifier<(S_IRWXO)> DenyOtherReadWritableVerifier
fail access_rights_verify() if others can read or write or execute.
Definition: access_rights.h:486
posix::access_rights::security_descriptor_type security_descriptor_type
Definition: access_rights.h:476
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:497
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:512
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:742
void get(PSI_field *, PSI_longlong *) noexcept
Definition: pfs_plugin_column_bigint_v1_all_empty.cc:31
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:191
Definition: varlen_sort.h:174
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:2881
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:272