1 /* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
2 
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6 
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation.  The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License, version 2.0, for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #ifndef ACL_TABLE_USER_INCLUDED
24 #define ACL_TABLE_USER_INCLUDED
25 
26 #include "my_config.h"
27 
28 #ifdef HAVE_SYS_TIME_H
29 #include <sys/time.h>
30 #endif
31 
32 #include <sys/types.h>
33 #include <functional>
34 #include <memory>
35 #include <string>
36 #include <utility>
37 
38 #include "my_alloc.h"
39 #include "sql/auth/acl_table_base.h"
40 #include "sql/auth/partial_revokes.h"
41 #include "sql/auth/user_table.h"
42 
43 class ACL_USER;
44 class RowIterator;
45 class THD;
46 class User_table_schema;
47 struct LEX_USER;
48 struct TABLE;
49 
50 namespace acl_table {
51 enum class User_attribute_type {
52   ADDITIONAL_PASSWORD = 0,
53   RESTRICTIONS,
54   PASSWORD_LOCKING,
55   METADATA,
56   COMMENT
57 };
58 
59 struct Password_lock {
60   /**
61      read from the user config. The number of days to keep the accont locked
62   */
63   int password_lock_time_days;
64   /**
65     read from the user config. The number of failed login attemps before the
66     account is locked
67   */
68   uint failed_login_attempts;
69 
70   Password_lock();
71 
72   Password_lock &operator=(const Password_lock &other);
73 
74   Password_lock &operator=(Password_lock &&other);
75 
76   Password_lock(const Password_lock &other);
77 
78   Password_lock(Password_lock &&other);
79 };
80 
81 // Forward and alias declarations
82 using acl_table_user_writer_status =
83     std::pair<Table_op_error_code, struct timeval>;
84 
85 /**
86   mysql.user table writer. It updates or drop a one single row from the table.
87 */
88 
89 class Acl_table_user_writer_status {
90  public:
91   Acl_table_user_writer_status(MEM_ROOT *mem_root);
Acl_table_user_writer_status(bool skip,ulong rights,Table_op_error_code err,struct timeval pwd_timestamp,std::string cred,MEM_ROOT * mem_root,Password_lock & password_lock)92   Acl_table_user_writer_status(bool skip, ulong rights, Table_op_error_code err,
93                                struct timeval pwd_timestamp, std::string cred,
94                                MEM_ROOT *mem_root, Password_lock &password_lock)
95       : skip_cache_update(skip),
96         updated_rights(rights),
97         error(err),
98         password_change_timestamp(pwd_timestamp),
99         second_cred(cred),
100         restrictions(mem_root),
101         password_lock(password_lock) {}
102 
103   bool skip_cache_update;
104   ulong updated_rights;
105   Table_op_error_code error;
106   struct timeval password_change_timestamp;
107   std::string second_cred;
108   Restrictions restrictions;
109   Password_lock password_lock;
110 };
111 
112 class Acl_table_user_writer : public Acl_table {
113  public:
114   Acl_table_user_writer(THD *thd, TABLE *table, LEX_USER *combo, ulong rights,
115                         bool revoke_grant, bool can_create_user,
116                         Pod_user_what_to_update what_to_update,
117                         Restrictions *restrictions);
118   virtual ~Acl_table_user_writer();
119   virtual Acl_table_op_status finish_operation(Table_op_error_code &error);
120   Acl_table_user_writer_status driver();
121 
122   bool setup_table(int &error, bool &builtin_password);
123 
124   /* Set of functions to set user table data */
125   bool update_authentication_info(Acl_table_user_writer_status &return_value);
126   bool update_privileges(Acl_table_user_writer_status &return_value);
127   bool update_ssl_properties();
128   bool update_user_resources();
129   bool update_password_expiry();
130   bool update_account_locking();
131   bool update_password_history();
132   bool update_password_reuse();
133   bool update_password_require_current();
134   bool update_user_attributes(std::string &current_password,
135                               Acl_table_user_writer_status &return_value);
136 
137   void replace_user_application_user_metadata(
138       std::function<bool(TABLE *table)> const &update);
139   ulong get_user_privileges();
140   std::string get_current_credentials();
141 
142  private:
143   bool update_user_application_user_metadata();
144   bool m_has_user_application_user_metadata;
145   LEX_USER *m_combo;
146   ulong m_rights;
147   bool m_revoke_grant;
148   bool m_can_create_user;
149   Pod_user_what_to_update m_what_to_update;
150   User_table_schema *m_table_schema;
151   Restrictions *m_restrictions;
152   std::function<bool(TABLE *table)> m_user_application_user_metadata;
153 };
154 
155 /**
156   mysql.user table reader. It reads all raws from table and create in-memory
157   cache.
158 */
159 
160 class Acl_table_user_reader : public Acl_table {
161  public:
162   Acl_table_user_reader(THD *thd, TABLE *table);
163   ~Acl_table_user_reader();
164   bool driver();
165   bool setup_table(bool &is_old_db_layout);
166   bool read_row(bool &is_old_db_layout, bool &super_users_with_empty_plugin);
167   virtual Acl_table_op_status finish_operation(Table_op_error_code &error);
168 
169   /* Set of function to read user table data */
170   void reset_acl_user(ACL_USER &user);
171   void read_account_name(ACL_USER &user);
172   bool read_authentication_string(ACL_USER &user);
173   void read_privileges(ACL_USER &user);
174   void read_ssl_fields(ACL_USER &user);
175   void read_user_resources(ACL_USER &user);
176   bool read_plugin_info(ACL_USER &user, bool &super_users_with_empty_plugin,
177                         bool &is_old_db_layout);
178   bool read_password_expiry(ACL_USER &user, bool &password_expired);
179   void read_password_locked(ACL_USER &user);
180   void read_password_last_changed(ACL_USER &user);
181   void read_password_lifetime(ACL_USER &user);
182   void read_password_history_fields(ACL_USER &user);
183   void read_password_reuse_time_fields(ACL_USER &user);
184   void read_password_require_current(ACL_USER &user);
185   bool read_user_attributes(ACL_USER &user);
186   void add_row_to_acl_users(ACL_USER &user);
187 
188  private:
189   User_table_schema *m_table_schema;
190   unique_ptr_destroy_only<RowIterator> m_iterator;
191   MEM_ROOT m_mem_root;
192   Restrictions *m_restrictions;
193   Json_object *m_user_application_user_metadata_json;
194 };
195 
196 }  // namespace acl_table
197 #endif /* ACL_TABLE_USER_INCLUDED */
198