Merge lp:~sergei.glushchenko/percona-server/5.5-ps-bug1320879 into lp:percona-server/5.5
- 5.5-ps-bug1320879
- Merge into 5.5
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Laurynas Biveinis | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 681 | ||||
Proposed branch: | lp:~sergei.glushchenko/percona-server/5.5-ps-bug1320879 | ||||
Merge into: | lp:percona-server/5.5 | ||||
Diff against target: |
1258 lines (+664/-298) 6 files modified
mysql-test/include/audit_log_events.inc (+3/-1) mysql-test/r/audit_log.result (+303/-145) mysql-test/t/audit_log.test (+75/-21) plugin/audit_log/audit_log.c (+239/-99) plugin/audit_log/file_logger.c (+38/-29) plugin/audit_log/logger.h (+6/-3) |
||||
To merge this branch: | bzr merge lp:~sergei.glushchenko/percona-server/5.5-ps-bug1320879 | ||||
Related bugs: |
|
||||
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurynas Biveinis (community) | Approve | ||
Review via email: mp+220912@code.launchpad.net |
This proposal supersedes a proposal from 2014-05-23.
Commit message
Description of the change
Bug 1320879: multiple issues when checking audit.log with xmllint
- fixed XML attribute names
- wrapped log by XML tag <audit>
- added XML declaration at the beginning of the file
- expanded test case to verify log with XML parser
- escape not only query text but also other string values
This makes xmllint to stop complaining and also makes
mysqlauditgrep from MySQL tools to work with audit log generated
by PS audit log plugin.
Blueprint
https:/
- variable audit_log_format to accept additional options JSON and CSV
- expanded test case to produce JSON and CSV logs and validate them
http://
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal | # |
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Yes, it was wrong branch.
Laurynas Biveinis (laurynas-biveinis) : | # |
Preview Diff
1 | === modified file 'mysql-test/include/audit_log_events.inc' | |||
2 | --- mysql-test/include/audit_log_events.inc 2014-05-14 14:32:33 +0000 | |||
3 | +++ mysql-test/include/audit_log_events.inc 2014-05-26 07:58:11 +0000 | |||
4 | @@ -2,7 +2,9 @@ | |||
5 | 2 | 2 | ||
6 | 3 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); | 3 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); |
7 | 4 | --error ER_TABLE_EXISTS_ERROR | 4 | --error ER_TABLE_EXISTS_ERROR |
9 | 5 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); | 5 | CREATE TABLE t1 |
10 | 6 | (c1 INT, | ||
11 | 7 | c2 CHAR(20)); | ||
12 | 6 | INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c'); | 8 | INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c'); |
13 | 7 | SELECT * FROM t1; | 9 | SELECT * FROM t1; |
14 | 8 | --error ER_NO_SUCH_TABLE | 10 | --error ER_NO_SUCH_TABLE |
15 | 9 | 11 | ||
16 | === modified file 'mysql-test/r/audit_log.result' | |||
17 | --- mysql-test/r/audit_log.result 2014-05-14 14:32:33 +0000 | |||
18 | +++ mysql-test/r/audit_log.result 2014-05-26 07:58:11 +0000 | |||
19 | @@ -1,146 +1,304 @@ | |||
20 | 1 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); | 1 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); |
166 | 2 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); | 2 | CREATE TABLE t1 |
167 | 3 | ERROR 42S01: Table 't1' already exists | 3 | (c1 INT, |
168 | 4 | INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c'); | 4 | c2 CHAR(20)); |
169 | 5 | SELECT * FROM t1; | 5 | ERROR 42S01: Table 't1' already exists |
170 | 6 | c1 c2 | 6 | INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c'); |
171 | 7 | 1 a | 7 | SELECT * FROM t1; |
172 | 8 | 2 b | 8 | c1 c2 |
173 | 9 | 3 c | 9 | 1 a |
174 | 10 | SELECT * FROM t2; | 10 | 2 b |
175 | 11 | ERROR 42S02: Table 'test.t2' doesn't exist | 11 | 3 c |
176 | 12 | DROP TABLE t1; | 12 | SELECT * FROM t2; |
177 | 13 | PREPARE stmt1 FROM 'SELECT 1'; | 13 | ERROR 42S02: Table 'test.t2' doesn't exist |
178 | 14 | EXECUTE stmt1; | 14 | DROP TABLE t1; |
179 | 15 | 1 | 15 | PREPARE stmt1 FROM 'SELECT 1'; |
180 | 16 | 1 | 16 | EXECUTE stmt1; |
181 | 17 | SHOW STATUS LIKE 'audit_log%'; | 17 | 1 |
182 | 18 | Variable_name Value | 18 | 1 |
183 | 19 | DEALLOCATE PREPARE stmt1; | 19 | SHOW STATUS LIKE 'audit_log%'; |
184 | 20 | show variables like 'audit_log%'; | 20 | Variable_name Value |
185 | 21 | Variable_name Value | 21 | DEALLOCATE PREPARE stmt1; |
186 | 22 | audit_log_buffer_size 4096 | 22 | show variables like 'audit_log%'; |
187 | 23 | audit_log_file test_audit.log | 23 | Variable_name Value |
188 | 24 | audit_log_flush OFF | 24 | audit_log_buffer_size 4096 |
189 | 25 | audit_log_format OLD | 25 | audit_log_file test_audit.log |
190 | 26 | audit_log_policy ALL | 26 | audit_log_flush OFF |
191 | 27 | audit_log_rotate_on_size 0 | 27 | audit_log_format OLD |
192 | 28 | audit_log_rotations 0 | 28 | audit_log_policy ALL |
193 | 29 | audit_log_strategy ASYNCHRONOUS | 29 | audit_log_rotate_on_size 0 |
194 | 30 | connect(localhost,no_such_user,,mysql,MASTER_PORT,MASTER_SOCKET); | 30 | audit_log_rotations 0 |
195 | 31 | ERROR 28000: Access denied for user 'no_such_user'@'localhost' (using password: NO) | 31 | audit_log_strategy ASYNCHRONOUS |
196 | 32 | create table t1 (id int); | 32 | connect(localhost,no_such_user,,mysql,MASTER_PORT,MASTER_SOCKET); |
197 | 33 | create table t2 (id int); | 33 | ERROR 28000: Access denied for user 'no_such_user'@'localhost' (using password: NO) |
198 | 34 | insert into t1 values (1), (2); | 34 | create table t1 (id int); |
199 | 35 | insert into t2 values (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2); | 35 | create table t2 (id int); |
200 | 36 | select * from t1; | 36 | insert into t1 values (1), (2); |
201 | 37 | id | 37 | insert into t2 values (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2); |
202 | 38 | 1 | 38 | select * from t1; |
203 | 39 | 2 | 39 | id |
204 | 40 | alter table t1 rename renamed_t1; | 40 | 1 |
205 | 41 | select * from t_doesnt_exist; | 41 | 2 |
206 | 42 | ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist | 42 | alter table t1 rename renamed_t1; |
207 | 43 | syntax_error_query; | 43 | select * from t_doesnt_exist; |
208 | 44 | ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'syntax_error_query' at line 1 | 44 | ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist |
209 | 45 | drop table renamed_t1, t2; | 45 | syntax_error_query; |
210 | 46 | show variables like 'audit_log%'; | 46 | ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'syntax_error_query' at line 1 |
211 | 47 | Variable_name Value | 47 | drop table renamed_t1, t2; |
212 | 48 | audit_log_buffer_size 4096 | 48 | show variables like 'audit_log%'; |
213 | 49 | audit_log_file test_audit.log | 49 | Variable_name Value |
214 | 50 | audit_log_flush OFF | 50 | audit_log_buffer_size 4096 |
215 | 51 | audit_log_format OLD | 51 | audit_log_file test_audit.log |
216 | 52 | audit_log_policy ALL | 52 | audit_log_flush OFF |
217 | 53 | audit_log_rotate_on_size 0 | 53 | audit_log_format OLD |
218 | 54 | audit_log_rotations 0 | 54 | audit_log_policy ALL |
219 | 55 | audit_log_strategy ASYNCHRONOUS | 55 | audit_log_rotate_on_size 0 |
220 | 56 | create database sa_db; | 56 | audit_log_rotations 0 |
221 | 57 | create table t1 (id2 int); | 57 | audit_log_strategy ASYNCHRONOUS |
222 | 58 | insert into t1 values (1), (2); | 58 | create database sa_db; |
223 | 59 | select * from t1; | 59 | create table t1 (id2 int); |
224 | 60 | id2 | 60 | insert into t1 values (1), (2); |
225 | 61 | 1 | 61 | select * from t1; |
226 | 62 | 2 | 62 | id2 |
227 | 63 | drop table t1; | 63 | 1 |
228 | 64 | use sa_db; | 64 | 2 |
229 | 65 | create table sa_t1(id int); | 65 | drop table t1; |
230 | 66 | insert into sa_t1 values (1), (2); | 66 | use sa_db; |
231 | 67 | drop table sa_t1; | 67 | create table sa_t1(id int); |
232 | 68 | drop database sa_db; | 68 | insert into sa_t1 values (1), (2); |
233 | 69 | create user 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; | 69 | drop table sa_t1; |
234 | 70 | drop user 'jeffrey'@'localhost'; | 70 | drop database sa_db; |
235 | 71 | select '&;&&&""""<><<>>>>'; | 71 | create user 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; |
236 | 72 | &;&&&""""<><<>>>> | 72 | drop user 'jeffrey'@'localhost'; |
237 | 73 | &;&&&""""<><<>>>> | 73 | select '&;&&&""""<><<>>>>'; |
238 | 74 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); | 74 | &;&&&""""<><<>>>> |
239 | 75 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); | 75 | &;&&&""""<><<>>>> |
240 | 76 | ERROR 42S01: Table 't1' already exists | 76 | set global audit_log_flush= ON; |
241 | 77 | INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c'); | 77 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); |
242 | 78 | SELECT * FROM t1; | 78 | CREATE TABLE t1 |
243 | 79 | c1 c2 | 79 | (c1 INT, |
244 | 80 | 1 a | 80 | c2 CHAR(20)); |
245 | 81 | 2 b | 81 | ERROR 42S01: Table 't1' already exists |
246 | 82 | 3 c | 82 | INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c'); |
247 | 83 | SELECT * FROM t2; | 83 | SELECT * FROM t1; |
248 | 84 | ERROR 42S02: Table 'test.t2' doesn't exist | 84 | c1 c2 |
249 | 85 | DROP TABLE t1; | 85 | 1 a |
250 | 86 | PREPARE stmt1 FROM 'SELECT 1'; | 86 | 2 b |
251 | 87 | EXECUTE stmt1; | 87 | 3 c |
252 | 88 | 1 | 88 | SELECT * FROM t2; |
253 | 89 | 1 | 89 | ERROR 42S02: Table 'test.t2' doesn't exist |
254 | 90 | SHOW STATUS LIKE 'audit_log%'; | 90 | DROP TABLE t1; |
255 | 91 | Variable_name Value | 91 | PREPARE stmt1 FROM 'SELECT 1'; |
256 | 92 | DEALLOCATE PREPARE stmt1; | 92 | EXECUTE stmt1; |
257 | 93 | show variables like 'audit_log%'; | 93 | 1 |
258 | 94 | Variable_name Value | 94 | 1 |
259 | 95 | audit_log_buffer_size 4096 | 95 | SHOW STATUS LIKE 'audit_log%'; |
260 | 96 | audit_log_file test_audit.log | 96 | Variable_name Value |
261 | 97 | audit_log_flush OFF | 97 | DEALLOCATE PREPARE stmt1; |
262 | 98 | audit_log_format NEW | 98 | show variables like 'audit_log%'; |
263 | 99 | audit_log_policy LOGINS | 99 | Variable_name Value |
264 | 100 | audit_log_rotate_on_size 0 | 100 | audit_log_buffer_size 4096 |
265 | 101 | audit_log_rotations 0 | 101 | audit_log_file test_audit.log |
266 | 102 | audit_log_strategy SYNCHRONOUS | 102 | audit_log_flush OFF |
267 | 103 | connect(localhost,no_such_user,,mysql,MASTER_PORT,MASTER_SOCKET); | 103 | audit_log_format NEW |
268 | 104 | ERROR 28000: Access denied for user 'no_such_user'@'localhost' (using password: NO) | 104 | audit_log_policy LOGINS |
269 | 105 | create table t1 (id int); | 105 | audit_log_rotate_on_size 0 |
270 | 106 | create table t2 (id int); | 106 | audit_log_rotations 0 |
271 | 107 | insert into t1 values (1), (2); | 107 | audit_log_strategy SEMISYNCHRONOUS |
272 | 108 | insert into t2 values (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2); | 108 | connect(localhost,no_such_user,,mysql,MASTER_PORT,MASTER_SOCKET); |
273 | 109 | select * from t1; | 109 | ERROR 28000: Access denied for user 'no_such_user'@'localhost' (using password: NO) |
274 | 110 | id | 110 | create table t1 (id int); |
275 | 111 | 1 | 111 | create table t2 (id int); |
276 | 112 | 2 | 112 | insert into t1 values (1), (2); |
277 | 113 | alter table t1 rename renamed_t1; | 113 | insert into t2 values (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2); |
278 | 114 | select * from t_doesnt_exist; | 114 | select * from t1; |
279 | 115 | ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist | 115 | id |
280 | 116 | syntax_error_query; | 116 | 1 |
281 | 117 | ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'syntax_error_query' at line 1 | 117 | 2 |
282 | 118 | drop table renamed_t1, t2; | 118 | alter table t1 rename renamed_t1; |
283 | 119 | show variables like 'audit_log%'; | 119 | select * from t_doesnt_exist; |
284 | 120 | Variable_name Value | 120 | ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist |
285 | 121 | audit_log_buffer_size 4096 | 121 | syntax_error_query; |
286 | 122 | audit_log_file test_audit.log | 122 | ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'syntax_error_query' at line 1 |
287 | 123 | audit_log_flush OFF | 123 | drop table renamed_t1, t2; |
288 | 124 | audit_log_format NEW | 124 | show variables like 'audit_log%'; |
289 | 125 | audit_log_policy LOGINS | 125 | Variable_name Value |
290 | 126 | audit_log_rotate_on_size 0 | 126 | audit_log_buffer_size 4096 |
291 | 127 | audit_log_rotations 0 | 127 | audit_log_file test_audit.log |
292 | 128 | audit_log_strategy SYNCHRONOUS | 128 | audit_log_flush OFF |
293 | 129 | create database sa_db; | 129 | audit_log_format NEW |
294 | 130 | create table t1 (id2 int); | 130 | audit_log_policy LOGINS |
295 | 131 | insert into t1 values (1), (2); | 131 | audit_log_rotate_on_size 0 |
296 | 132 | select * from t1; | 132 | audit_log_rotations 0 |
297 | 133 | id2 | 133 | audit_log_strategy SEMISYNCHRONOUS |
298 | 134 | 1 | 134 | create database sa_db; |
299 | 135 | 2 | 135 | create table t1 (id2 int); |
300 | 136 | drop table t1; | 136 | insert into t1 values (1), (2); |
301 | 137 | use sa_db; | 137 | select * from t1; |
302 | 138 | create table sa_t1(id int); | 138 | id2 |
303 | 139 | insert into sa_t1 values (1), (2); | 139 | 1 |
304 | 140 | drop table sa_t1; | 140 | 2 |
305 | 141 | drop database sa_db; | 141 | drop table t1; |
306 | 142 | create user 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; | 142 | use sa_db; |
307 | 143 | drop user 'jeffrey'@'localhost'; | 143 | create table sa_t1(id int); |
308 | 144 | select '&;&&&""""<><<>>>>'; | 144 | insert into sa_t1 values (1), (2); |
309 | 145 | &;&&&""""<><<>>>> | 145 | drop table sa_t1; |
310 | 146 | &;&&&""""<><<>>>> | 146 | drop database sa_db; |
311 | 147 | create user 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; | ||
312 | 148 | drop user 'jeffrey'@'localhost'; | ||
313 | 149 | select '&;&&&""""<><<>>>>'; | ||
314 | 150 | &;&&&""""<><<>>>> | ||
315 | 151 | &;&&&""""<><<>>>> | ||
316 | 152 | set global audit_log_flush= ON; | ||
317 | 153 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); | ||
318 | 154 | CREATE TABLE t1 | ||
319 | 155 | (c1 INT, | ||
320 | 156 | c2 CHAR(20)); | ||
321 | 157 | ERROR 42S01: Table 't1' already exists | ||
322 | 158 | INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c'); | ||
323 | 159 | SELECT * FROM t1; | ||
324 | 160 | c1 c2 | ||
325 | 161 | 1 a | ||
326 | 162 | 2 b | ||
327 | 163 | 3 c | ||
328 | 164 | SELECT * FROM t2; | ||
329 | 165 | ERROR 42S02: Table 'test.t2' doesn't exist | ||
330 | 166 | DROP TABLE t1; | ||
331 | 167 | PREPARE stmt1 FROM 'SELECT 1'; | ||
332 | 168 | EXECUTE stmt1; | ||
333 | 169 | 1 | ||
334 | 170 | 1 | ||
335 | 171 | SHOW STATUS LIKE 'audit_log%'; | ||
336 | 172 | Variable_name Value | ||
337 | 173 | DEALLOCATE PREPARE stmt1; | ||
338 | 174 | show variables like 'audit_log%'; | ||
339 | 175 | Variable_name Value | ||
340 | 176 | audit_log_buffer_size 4096 | ||
341 | 177 | audit_log_file test_audit.log | ||
342 | 178 | audit_log_flush OFF | ||
343 | 179 | audit_log_format JSON | ||
344 | 180 | audit_log_policy ALL | ||
345 | 181 | audit_log_rotate_on_size 0 | ||
346 | 182 | audit_log_rotations 0 | ||
347 | 183 | audit_log_strategy SEMISYNCHRONOUS | ||
348 | 184 | connect(localhost,no_such_user,,mysql,MASTER_PORT,MASTER_SOCKET); | ||
349 | 185 | ERROR 28000: Access denied for user 'no_such_user'@'localhost' (using password: NO) | ||
350 | 186 | create table t1 (id int); | ||
351 | 187 | create table t2 (id int); | ||
352 | 188 | insert into t1 values (1), (2); | ||
353 | 189 | insert into t2 values (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2); | ||
354 | 190 | select * from t1; | ||
355 | 191 | id | ||
356 | 192 | 1 | ||
357 | 193 | 2 | ||
358 | 194 | alter table t1 rename renamed_t1; | ||
359 | 195 | select * from t_doesnt_exist; | ||
360 | 196 | ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist | ||
361 | 197 | syntax_error_query; | ||
362 | 198 | ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'syntax_error_query' at line 1 | ||
363 | 199 | drop table renamed_t1, t2; | ||
364 | 200 | show variables like 'audit_log%'; | ||
365 | 201 | Variable_name Value | ||
366 | 202 | audit_log_buffer_size 4096 | ||
367 | 203 | audit_log_file test_audit.log | ||
368 | 204 | audit_log_flush OFF | ||
369 | 205 | audit_log_format JSON | ||
370 | 206 | audit_log_policy ALL | ||
371 | 207 | audit_log_rotate_on_size 0 | ||
372 | 208 | audit_log_rotations 0 | ||
373 | 209 | audit_log_strategy SEMISYNCHRONOUS | ||
374 | 210 | create database sa_db; | ||
375 | 211 | create table t1 (id2 int); | ||
376 | 212 | insert into t1 values (1), (2); | ||
377 | 213 | select * from t1; | ||
378 | 214 | id2 | ||
379 | 215 | 1 | ||
380 | 216 | 2 | ||
381 | 217 | drop table t1; | ||
382 | 218 | use sa_db; | ||
383 | 219 | create table sa_t1(id int); | ||
384 | 220 | insert into sa_t1 values (1), (2); | ||
385 | 221 | drop table sa_t1; | ||
386 | 222 | drop database sa_db; | ||
387 | 223 | create user 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; | ||
388 | 224 | drop user 'jeffrey'@'localhost'; | ||
389 | 225 | select '&;&&&""""<><<>>>>'; | ||
390 | 226 | &;&&&""""<><<>>>> | ||
391 | 227 | &;&&&""""<><<>>>> | ||
392 | 228 | set global audit_log_flush= ON; | ||
393 | 229 | CREATE TABLE t1 (c1 INT, c2 CHAR(20)); | ||
394 | 230 | CREATE TABLE t1 | ||
395 | 231 | (c1 INT, | ||
396 | 232 | c2 CHAR(20)); | ||
397 | 233 | ERROR 42S01: Table 't1' already exists | ||
398 | 234 | INSERT INTO t1 VALUES (1,'a'),(2,'b'),(3,'c'); | ||
399 | 235 | SELECT * FROM t1; | ||
400 | 236 | c1 c2 | ||
401 | 237 | 1 a | ||
402 | 238 | 2 b | ||
403 | 239 | 3 c | ||
404 | 240 | SELECT * FROM t2; | ||
405 | 241 | ERROR 42S02: Table 'test.t2' doesn't exist | ||
406 | 242 | DROP TABLE t1; | ||
407 | 243 | PREPARE stmt1 FROM 'SELECT 1'; | ||
408 | 244 | EXECUTE stmt1; | ||
409 | 245 | 1 | ||
410 | 246 | 1 | ||
411 | 247 | SHOW STATUS LIKE 'audit_log%'; | ||
412 | 248 | Variable_name Value | ||
413 | 249 | DEALLOCATE PREPARE stmt1; | ||
414 | 250 | show variables like 'audit_log%'; | ||
415 | 251 | Variable_name Value | ||
416 | 252 | audit_log_buffer_size 4096 | ||
417 | 253 | audit_log_file test_audit.log | ||
418 | 254 | audit_log_flush OFF | ||
419 | 255 | audit_log_format CSV | ||
420 | 256 | audit_log_policy ALL | ||
421 | 257 | audit_log_rotate_on_size 0 | ||
422 | 258 | audit_log_rotations 0 | ||
423 | 259 | audit_log_strategy SEMISYNCHRONOUS | ||
424 | 260 | connect(localhost,no_such_user,,mysql,MASTER_PORT,MASTER_SOCKET); | ||
425 | 261 | ERROR 28000: Access denied for user 'no_such_user'@'localhost' (using password: NO) | ||
426 | 262 | create table t1 (id int); | ||
427 | 263 | create table t2 (id int); | ||
428 | 264 | insert into t1 values (1), (2); | ||
429 | 265 | insert into t2 values (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2), (1), (2); | ||
430 | 266 | select * from t1; | ||
431 | 267 | id | ||
432 | 268 | 1 | ||
433 | 269 | 2 | ||
434 | 270 | alter table t1 rename renamed_t1; | ||
435 | 271 | select * from t_doesnt_exist; | ||
436 | 272 | ERROR 42S02: Table 'test.t_doesnt_exist' doesn't exist | ||
437 | 273 | syntax_error_query; | ||
438 | 274 | ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'syntax_error_query' at line 1 | ||
439 | 275 | drop table renamed_t1, t2; | ||
440 | 276 | show variables like 'audit_log%'; | ||
441 | 277 | Variable_name Value | ||
442 | 278 | audit_log_buffer_size 4096 | ||
443 | 279 | audit_log_file test_audit.log | ||
444 | 280 | audit_log_flush OFF | ||
445 | 281 | audit_log_format CSV | ||
446 | 282 | audit_log_policy ALL | ||
447 | 283 | audit_log_rotate_on_size 0 | ||
448 | 284 | audit_log_rotations 0 | ||
449 | 285 | audit_log_strategy SEMISYNCHRONOUS | ||
450 | 286 | create database sa_db; | ||
451 | 287 | create table t1 (id2 int); | ||
452 | 288 | insert into t1 values (1), (2); | ||
453 | 289 | select * from t1; | ||
454 | 290 | id2 | ||
455 | 291 | 1 | ||
456 | 292 | 2 | ||
457 | 293 | drop table t1; | ||
458 | 294 | use sa_db; | ||
459 | 295 | create table sa_t1(id int); | ||
460 | 296 | insert into sa_t1 values (1), (2); | ||
461 | 297 | drop table sa_t1; | ||
462 | 298 | drop database sa_db; | ||
463 | 299 | create user 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; | ||
464 | 300 | drop user 'jeffrey'@'localhost'; | ||
465 | 301 | select '&;&&&""""<><<>>>>'; | ||
466 | 302 | &;&&&""""<><<>>>> | ||
467 | 303 | &;&&&""""<><<>>>> | ||
468 | 304 | set global audit_log_flush= ON; | ||
469 | 147 | 305 | ||
470 | === modified file 'mysql-test/t/audit_log.test' | |||
471 | --- mysql-test/t/audit_log.test 2014-04-21 12:07:45 +0000 | |||
472 | +++ mysql-test/t/audit_log.test 2014-05-26 07:58:11 +0000 | |||
473 | @@ -1,23 +1,77 @@ | |||
474 | 1 | --source include/not_embedded.inc | 1 | --source include/not_embedded.inc |
475 | 2 | 2 | ||
497 | 3 | # Adjustment to the OS dependent extension of shared libraries. | 3 | let $MYSQLD_DATADIR= `select @@datadir`; |
498 | 4 | let $expected_extension= so; | 4 | let MYSQLD_DATADIR= $MYSQLD_DATADIR; |
499 | 5 | if(`SELECT CONVERT(@@version_compile_os USING latin1) | 5 | |
500 | 6 | IN ("Win32","Win64","Windows")`) | 6 | --source include/audit_log_events.inc |
501 | 7 | { | 7 | |
502 | 8 | let $expected_extension= dll; | 8 | --move_file $MYSQLD_DATADIR/test_audit.log $MYSQLD_DATADIR/test_audit_old.log |
503 | 9 | } | 9 | set global audit_log_flush= ON; |
504 | 10 | 10 | perl; | |
505 | 11 | let $MYSQL_DATA_DIR= `select @@datadir`; | 11 | eval "use XML::Parser; 1" or exit 0; |
506 | 12 | 12 | $p = new XML::Parser; | |
507 | 13 | --source include/audit_log_events.inc | 13 | $p->parsefile($ENV{'MYSQLD_DATADIR'} . '/test_audit_old.log'); |
508 | 14 | 14 | EOF | |
509 | 15 | --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect | 15 | --remove_file $MYSQLD_DATADIR/test_audit.log |
510 | 16 | --shutdown_server | 16 | |
511 | 17 | --source include/wait_until_disconnected.inc | 17 | --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect |
512 | 18 | --enable_reconnect | 18 | --shutdown_server |
513 | 19 | --exec echo "restart: --audit_log_policy=LOGINS --audit-log-format=NEW --audit_log_strategy=SYNCHRONOUS" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect | 19 | --source include/wait_until_disconnected.inc |
514 | 20 | --source include/wait_until_connected_again.inc | 20 | --enable_reconnect |
515 | 21 | 21 | --exec echo "restart: --audit_log_policy=LOGINS --audit-log-format=NEW --audit_log_strategy=SEMISYNCHRONOUS" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect | |
516 | 22 | --source include/audit_log_events.inc | 22 | --source include/wait_until_connected_again.inc |
517 | 23 | 23 | ||
518 | 24 | --source include/audit_log_events.inc | ||
519 | 25 | |||
520 | 26 | --move_file $MYSQLD_DATADIR/test_audit.log $MYSQLD_DATADIR/test_audit_new.log | ||
521 | 27 | set global audit_log_flush= ON; | ||
522 | 28 | perl; | ||
523 | 29 | eval "use XML::Parser; 1" or exit 0; | ||
524 | 30 | $p = new XML::Parser; | ||
525 | 31 | $p->parsefile($ENV{'MYSQLD_DATADIR'} . '/test_audit_new.log'); | ||
526 | 32 | EOF | ||
527 | 33 | --remove_file $MYSQLD_DATADIR/test_audit.log | ||
528 | 34 | |||
529 | 35 | --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect | ||
530 | 36 | --shutdown_server | ||
531 | 37 | --source include/wait_until_disconnected.inc | ||
532 | 38 | --enable_reconnect | ||
533 | 39 | --exec echo "restart: --audit-log-format=JSON --audit_log_strategy=SEMISYNCHRONOUS" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect | ||
534 | 40 | --source include/wait_until_connected_again.inc | ||
535 | 41 | |||
536 | 42 | --source include/audit_log_events.inc | ||
537 | 43 | |||
538 | 44 | --move_file $MYSQLD_DATADIR/test_audit.log $MYSQLD_DATADIR/test_audit_json.log | ||
539 | 45 | set global audit_log_flush= ON; | ||
540 | 46 | perl; | ||
541 | 47 | eval "use JSON qw(decode_json); 1" or exit 0; | ||
542 | 48 | open my $file, $ENV{'MYSQLD_DATADIR'} . '/test_audit_json.log' or die "Could not open log: $!"; | ||
543 | 49 | while (my $line = <$file>) { | ||
544 | 50 | decode_json($line); | ||
545 | 51 | } | ||
546 | 52 | close $file; | ||
547 | 53 | EOF | ||
548 | 54 | --remove_file $MYSQLD_DATADIR/test_audit.log | ||
549 | 55 | |||
550 | 56 | --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect | ||
551 | 57 | --shutdown_server | ||
552 | 58 | --source include/wait_until_disconnected.inc | ||
553 | 59 | --enable_reconnect | ||
554 | 60 | --exec echo "restart: --audit-log-format=CSV --audit_log_strategy=SEMISYNCHRONOUS" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect | ||
555 | 61 | --source include/wait_until_connected_again.inc | ||
556 | 62 | |||
557 | 63 | --source include/audit_log_events.inc | ||
558 | 64 | |||
559 | 65 | --move_file $MYSQLD_DATADIR/test_audit.log $MYSQLD_DATADIR/test_audit_csv.log | ||
560 | 66 | set global audit_log_flush= ON; | ||
561 | 67 | perl; | ||
562 | 68 | eval "use Text::CSV; 1" or exit 0; | ||
563 | 69 | my $p = Text::CSV->new({ binary => 1, auto_diag => 1, sep_char => ',' }); | ||
564 | 70 | open my $file, $ENV{'MYSQLD_DATADIR'} . '/test_audit_csv.log' or die "Could not open log: $!"; | ||
565 | 71 | while ($p->getline($file)) {}; | ||
566 | 72 | if (not $p->eof) { | ||
567 | 73 | die "CSV parse error " . $p->error_diag(); | ||
568 | 74 | } | ||
569 | 75 | close $file; | ||
570 | 76 | EOF | ||
571 | 77 | --remove_file $MYSQLD_DATADIR/test_audit.log | ||
572 | 24 | 78 | ||
573 | === modified file 'plugin/audit_log/audit_log.c' | |||
574 | --- plugin/audit_log/audit_log.c 2014-05-14 14:32:33 +0000 | |||
575 | +++ plugin/audit_log/audit_log.c 2014-05-26 07:58:11 +0000 | |||
576 | @@ -35,7 +35,9 @@ | |||
577 | 35 | enum audit_log_policy_t { ALL, NONE, LOGINS, QUERIES }; | 35 | enum audit_log_policy_t { ALL, NONE, LOGINS, QUERIES }; |
578 | 36 | enum audit_log_strategy_t | 36 | enum audit_log_strategy_t |
579 | 37 | { ASYNCHRONOUS, PERFORMANCE, SEMISYNCHRONOUS, SYNCHRONOUS }; | 37 | { ASYNCHRONOUS, PERFORMANCE, SEMISYNCHRONOUS, SYNCHRONOUS }; |
581 | 38 | enum audit_log_format_t { OLD, NEW }; | 38 | enum audit_log_format_t { OLD, NEW, JSON, CSV }; |
582 | 39 | |||
583 | 40 | typedef void (*escape_buf_func_t)(const char *, size_t *, char *, size_t *); | ||
584 | 39 | 41 | ||
585 | 40 | static LOGGER_HANDLE *audit_file_logger= NULL; | 42 | static LOGGER_HANDLE *audit_file_logger= NULL; |
586 | 41 | static audit_log_buffer_t *audit_log_buffer= NULL; | 43 | static audit_log_buffer_t *audit_log_buffer= NULL; |
587 | @@ -113,41 +115,37 @@ | |||
588 | 113 | return buf; | 115 | return buf; |
589 | 114 | } | 116 | } |
590 | 115 | 117 | ||
591 | 118 | typedef struct | ||
592 | 119 | { | ||
593 | 120 | char character; | ||
594 | 121 | size_t length; | ||
595 | 122 | const char *replacement; | ||
596 | 123 | } escape_rule_t; | ||
597 | 124 | |||
598 | 116 | static | 125 | static |
600 | 117 | void xml_escape(const char *in, size_t *inlen, char* out, size_t *outlen) | 126 | void escape_buf(const char *in, size_t *inlen, char *out, size_t *outlen, |
601 | 127 | const escape_rule_t *escape_rules) | ||
602 | 118 | { | 128 | { |
603 | 119 | char* outstart = out; | 129 | char* outstart = out; |
604 | 120 | const char* base = in; | 130 | const char* base = in; |
605 | 121 | char* outend = out + *outlen; | 131 | char* outend = out + *outlen; |
606 | 122 | const char* inend; | 132 | const char* inend; |
608 | 123 | size_t i; | 133 | const escape_rule_t *rule; |
609 | 124 | my_bool replaced; | 134 | my_bool replaced; |
610 | 125 | 135 | ||
611 | 126 | const struct { | ||
612 | 127 | char symbol; | ||
613 | 128 | size_t length; | ||
614 | 129 | const char *replace; | ||
615 | 130 | } escape[] = { | ||
616 | 131 | { '<', 4, "<" }, | ||
617 | 132 | { '>', 4, ">" }, | ||
618 | 133 | { '&', 5, "&" }, | ||
619 | 134 | { '\r', 5, " " }, | ||
620 | 135 | { '"', 6, """ }, | ||
621 | 136 | }; | ||
622 | 137 | |||
623 | 138 | inend = in + (*inlen); | 136 | inend = in + (*inlen); |
624 | 139 | 137 | ||
625 | 140 | while ((in < inend) && (out < outend)) | 138 | while ((in < inend) && (out < outend)) |
626 | 141 | { | 139 | { |
627 | 142 | replaced= FALSE; | 140 | replaced= FALSE; |
629 | 143 | for (i= 0; i < array_elements(escape); i++) | 141 | for (rule= escape_rules; rule->character; rule++) |
630 | 144 | { | 142 | { |
632 | 145 | if (*in == escape[i].symbol) | 143 | if (*in == rule->character) |
633 | 146 | { | 144 | { |
635 | 147 | if ((outend - out) < (int) escape[i].length) | 145 | if ((outend - out) < (int) rule->length) |
636 | 148 | goto end_of_buffer; | 146 | goto end_of_buffer; |
639 | 149 | memcpy(out, escape[i].replace, escape[i].length); | 147 | memcpy(out, rule->replacement, rule->length); |
640 | 150 | out += escape[i].length; | 148 | out += rule->length; |
641 | 151 | replaced= TRUE; | 149 | replaced= TRUE; |
642 | 152 | break; | 150 | break; |
643 | 153 | } | 151 | } |
644 | @@ -161,20 +159,71 @@ | |||
645 | 161 | *inlen = in - base; | 159 | *inlen = in - base; |
646 | 162 | } | 160 | } |
647 | 163 | 161 | ||
653 | 164 | 162 | static | |
654 | 165 | static | 163 | void xml_escape(const char *in, size_t *inlen, char *out, size_t *outlen) |
655 | 166 | char *xml_escape_string(const char *in, size_t inlen, | 164 | { |
656 | 167 | char *out, size_t outlen) | 165 | const escape_rule_t rules[]= |
657 | 168 | { | 166 | { |
658 | 167 | { '<', 4, "<" }, | ||
659 | 168 | { '>', 4, ">" }, | ||
660 | 169 | { '&', 5, "&" }, | ||
661 | 170 | { '\r', 5, " " }, | ||
662 | 171 | { '\n', 5, " " }, | ||
663 | 172 | { '"', 6, """ }, | ||
664 | 173 | { 0, 0, NULL } | ||
665 | 174 | }; | ||
666 | 175 | |||
667 | 176 | escape_buf(in, inlen, out, outlen, rules); | ||
668 | 177 | } | ||
669 | 178 | |||
670 | 179 | static | ||
671 | 180 | void json_escape(const char *in, size_t *inlen, char *out, size_t *outlen) | ||
672 | 181 | { | ||
673 | 182 | const escape_rule_t rules[]= | ||
674 | 183 | { | ||
675 | 184 | { '\\', 2, "\\\\" }, | ||
676 | 185 | { '"', 2, "\\\"" }, | ||
677 | 186 | { '\r', 2, "\\r" }, | ||
678 | 187 | { '\n', 2, "\\n" }, | ||
679 | 188 | { 0, 0, NULL } | ||
680 | 189 | }; | ||
681 | 190 | |||
682 | 191 | escape_buf(in, inlen, out, outlen, rules); | ||
683 | 192 | } | ||
684 | 193 | |||
685 | 194 | static | ||
686 | 195 | void csv_escape(const char *in, size_t *inlen, char *out, size_t *outlen) | ||
687 | 196 | { | ||
688 | 197 | const escape_rule_t rules[]= | ||
689 | 198 | { | ||
690 | 199 | { '"', 2, "\"\"" }, | ||
691 | 200 | { 0, 0, NULL } | ||
692 | 201 | }; | ||
693 | 202 | |||
694 | 203 | escape_buf(in, inlen, out, outlen, rules); | ||
695 | 204 | } | ||
696 | 205 | |||
697 | 206 | static | ||
698 | 207 | char *escape_string(const char *in, size_t inlen, | ||
699 | 208 | char *out, size_t outlen, | ||
700 | 209 | char **endptr) | ||
701 | 210 | { | ||
702 | 211 | const escape_buf_func_t format_escape_func[]= | ||
703 | 212 | { xml_escape, xml_escape, json_escape, csv_escape }; | ||
704 | 213 | |||
705 | 169 | if (in != NULL) | 214 | if (in != NULL) |
706 | 170 | { | 215 | { |
707 | 171 | --outlen; | 216 | --outlen; |
709 | 172 | xml_escape(in, &inlen, out, &outlen); | 217 | format_escape_func[audit_log_format](in, &inlen, out, &outlen); |
710 | 173 | out[outlen]= 0; | 218 | out[outlen]= 0; |
711 | 219 | if (endptr) | ||
712 | 220 | *endptr= out + outlen + 1; | ||
713 | 174 | } | 221 | } |
714 | 175 | else | 222 | else |
715 | 176 | { | 223 | { |
717 | 177 | out= 0; | 224 | *out= 0; |
718 | 225 | if (endptr) | ||
719 | 226 | *endptr= out + 1; | ||
720 | 178 | } | 227 | } |
721 | 179 | return out; | 228 | return out; |
722 | 180 | } | 229 | } |
723 | @@ -273,13 +322,14 @@ | |||
724 | 273 | char arg_buf[512]; | 322 | char arg_buf[512]; |
725 | 274 | const char *format_string[] = { | 323 | const char *format_string[] = { |
726 | 275 | "<AUDIT_RECORD\n" | 324 | "<AUDIT_RECORD\n" |
733 | 276 | " \"NAME\"=\"%s\"\n" | 325 | " NAME=\"%s\"\n" |
734 | 277 | " \"RECORD\"=\"%s\"\n" | 326 | " RECORD=\"%s\"\n" |
735 | 278 | " \"TIMESTAMP\"=\"%s\"\n" | 327 | " TIMESTAMP=\"%s\"\n" |
736 | 279 | " \"MYSQL_VERSION\"=\"%s\"\n" | 328 | " MYSQL_VERSION=\"%s\"\n" |
737 | 280 | " \"STARTUP_OPTIONS\"=\"%s\"\n" | 329 | " STARTUP_OPTIONS=\"%s\"\n" |
738 | 281 | " \"OS_VERSION\"=\""MACHINE_TYPE"-"SYSTEM_TYPE"\",\n" | 330 | " OS_VERSION=\""MACHINE_TYPE"-"SYSTEM_TYPE"\"\n" |
739 | 282 | "/>\n", | 331 | "/>\n", |
740 | 332 | |||
741 | 283 | "<AUDIT_RECORD>\n" | 333 | "<AUDIT_RECORD>\n" |
742 | 284 | " <NAME>%s</NAME>\n" | 334 | " <NAME>%s</NAME>\n" |
743 | 285 | " <RECORD>%s</RECORD>\n" | 335 | " <RECORD>%s</RECORD>\n" |
744 | @@ -287,7 +337,15 @@ | |||
745 | 287 | " <MYSQL_VERSION>%s</MYSQL_VERSION>\n" | 337 | " <MYSQL_VERSION>%s</MYSQL_VERSION>\n" |
746 | 288 | " <STARTUP_OPTIONS>%s</STARTUP_OPTIONS>\n" | 338 | " <STARTUP_OPTIONS>%s</STARTUP_OPTIONS>\n" |
747 | 289 | " <OS_VERSION>"MACHINE_TYPE"-"SYSTEM_TYPE"</OS_VERSION>\n" | 339 | " <OS_VERSION>"MACHINE_TYPE"-"SYSTEM_TYPE"</OS_VERSION>\n" |
749 | 290 | "</AUDIT_RECORD>\n" }; | 340 | "</AUDIT_RECORD>\n", |
750 | 341 | |||
751 | 342 | "{\"audit_record\":{\"name\":\"%s\",\"record\":\"%s\"," | ||
752 | 343 | "\"timestamp\":\"%s\",\"mysql_version\":\"%s\"," | ||
753 | 344 | "\"startup_optionsi\":\"%s\"," | ||
754 | 345 | "\"os_version\":\""MACHINE_TYPE"-"SYSTEM_TYPE"\"}}\n", | ||
755 | 346 | |||
756 | 347 | "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"," | ||
757 | 348 | "\""MACHINE_TYPE"-"SYSTEM_TYPE"\"\n" }; | ||
758 | 291 | 349 | ||
759 | 292 | return my_snprintf(buf, buflen, | 350 | return my_snprintf(buf, buflen, |
760 | 293 | format_string[audit_log_format], | 351 | format_string[audit_log_format], |
761 | @@ -307,21 +365,23 @@ | |||
762 | 307 | { | 365 | { |
763 | 308 | char id_str[MAX_RECORD_ID_SIZE]; | 366 | char id_str[MAX_RECORD_ID_SIZE]; |
764 | 309 | char timestamp[MAX_TIMESTAMP_SIZE]; | 367 | char timestamp[MAX_TIMESTAMP_SIZE]; |
766 | 310 | char query[512]; | 368 | char query[512], tmp[128]; |
767 | 369 | char *endptr= tmp, *endtmp= tmp + sizeof(tmp); | ||
768 | 311 | const char *format_string[] = { | 370 | const char *format_string[] = { |
769 | 312 | "<AUDIT_RECORD\n" | 371 | "<AUDIT_RECORD\n" |
781 | 313 | " \"NAME\"=\"%s\"\n" | 372 | " NAME=\"%s\"\n" |
782 | 314 | " \"RECORD\"=\"%s\"\n" | 373 | " RECORD=\"%s\"\n" |
783 | 315 | " \"TIMESTAMP\"=\"%s\"\n" | 374 | " TIMESTAMP=\"%s\"\n" |
784 | 316 | " \"COMMAND_CLASS\"=\"%s\"\n" | 375 | " COMMAND_CLASS=\"%s\"\n" |
785 | 317 | " \"CONNECTION_ID\"=\"%lu\"\n" | 376 | " CONNECTION_ID=\"%lu\"\n" |
786 | 318 | " \"STATUS\"=\"%d\"\n" | 377 | " STATUS=\"%d\"\n" |
787 | 319 | " \"SQLTEXT\"=\"%s\"\n" | 378 | " SQLTEXT=\"%s\"\n" |
788 | 320 | " \"USER\"=\"%s\"\n" | 379 | " USER=\"%s\"\n" |
789 | 321 | " \"HOST\"=\"%s\"\n" | 380 | " HOST=\"%s\"\n" |
790 | 322 | " \"OS_USER\"=\"%s\"\n" | 381 | " OS_USER=\"%s\"\n" |
791 | 323 | " \"IP\"=\"%s\"\n" | 382 | " IP=\"%s\"\n" |
792 | 324 | "/>\n", | 383 | "/>\n", |
793 | 384 | |||
794 | 325 | "<AUDIT_RECORD>\n" | 385 | "<AUDIT_RECORD>\n" |
795 | 326 | " <NAME>%s</NAME>\n" | 386 | " <NAME>%s</NAME>\n" |
796 | 327 | " <RECORD>%s</RECORD>\n" | 387 | " <RECORD>%s</RECORD>\n" |
797 | @@ -334,7 +394,23 @@ | |||
798 | 334 | " <HOST>%s</HOST>\n" | 394 | " <HOST>%s</HOST>\n" |
799 | 335 | " <OS_USER>%s</OS_USER>\n" | 395 | " <OS_USER>%s</OS_USER>\n" |
800 | 336 | " <IP>%s</IP>\n" | 396 | " <IP>%s</IP>\n" |
802 | 337 | "</AUDIT_RECORD>\n" }; | 397 | "</AUDIT_RECORD>\n", |
803 | 398 | |||
804 | 399 | "{\"audit_record\":" | ||
805 | 400 | "{\"name\":\"%s\"," | ||
806 | 401 | "\"record\":\"%s\"," | ||
807 | 402 | "\"timestamp\":\"%s\"," | ||
808 | 403 | "\"command_class\":\"%s\"," | ||
809 | 404 | "\"connection_id\":\"%lu\"," | ||
810 | 405 | "\"status\":%d," | ||
811 | 406 | "\"sqltext\":\"%s\"," | ||
812 | 407 | "\"user\":\"%s\"," | ||
813 | 408 | "\"host\":\"%s\"," | ||
814 | 409 | "\"os_user\":\"%s\"," | ||
815 | 410 | "\"ip\":\"%s\"}}\n", | ||
816 | 411 | |||
817 | 412 | "\"%s\",\"%s\",\"%s\",\"%s\",\"%lu\",%d,\"%s\",\"%s\"," | ||
818 | 413 | "\"%s\",\"%s\",\"%s\"\n" }; | ||
819 | 338 | 414 | ||
820 | 339 | return my_snprintf(buf, buflen, | 415 | return my_snprintf(buf, buflen, |
821 | 340 | format_string[audit_log_format], | 416 | format_string[audit_log_format], |
822 | @@ -343,13 +419,21 @@ | |||
823 | 343 | make_timestamp(timestamp, sizeof(timestamp), t), | 419 | make_timestamp(timestamp, sizeof(timestamp), t), |
824 | 344 | event->general_sql_command.str, | 420 | event->general_sql_command.str, |
825 | 345 | event->general_thread_id, status, | 421 | event->general_thread_id, status, |
833 | 346 | xml_escape_string(event->general_query, | 422 | escape_string(event->general_query, |
834 | 347 | event->general_query_length, | 423 | event->general_query_length, |
835 | 348 | query, sizeof(query)), | 424 | query, sizeof(query), NULL), |
836 | 349 | event->general_user, | 425 | escape_string(event->general_user, |
837 | 350 | event->general_host.str, | 426 | event->general_user_length, |
838 | 351 | event->general_external_user.str, | 427 | endptr, endtmp - endptr, &endptr), |
839 | 352 | event->general_ip.str); | 428 | escape_string(event->general_host.str, |
840 | 429 | event->general_host.length, | ||
841 | 430 | endptr, endtmp - endptr, &endptr), | ||
842 | 431 | escape_string(event->general_external_user.str, | ||
843 | 432 | event->general_external_user.length, | ||
844 | 433 | endptr, endtmp - endptr, &endptr), | ||
845 | 434 | escape_string(event->general_ip.str, | ||
846 | 435 | event->general_ip.length, | ||
847 | 436 | endptr, endtmp - endptr, &endptr)); | ||
848 | 353 | } | 437 | } |
849 | 354 | 438 | ||
850 | 355 | static | 439 | static |
851 | @@ -359,21 +443,24 @@ | |||
852 | 359 | { | 443 | { |
853 | 360 | char id_str[MAX_RECORD_ID_SIZE]; | 444 | char id_str[MAX_RECORD_ID_SIZE]; |
854 | 361 | char timestamp[MAX_TIMESTAMP_SIZE]; | 445 | char timestamp[MAX_TIMESTAMP_SIZE]; |
855 | 446 | char tmp[128]; | ||
856 | 447 | char *endptr= tmp, *endtmp= tmp + sizeof(tmp); | ||
857 | 362 | const char *format_string[] = { | 448 | const char *format_string[] = { |
858 | 363 | "<AUDIT_RECORD\n" | 449 | "<AUDIT_RECORD\n" |
871 | 364 | " \"NAME\"=\"%s\"\n" | 450 | " NAME=\"%s\"\n" |
872 | 365 | " \"RECORD\"=\"%s\"\n" | 451 | " RECORD=\"%s\"\n" |
873 | 366 | " \"TIMESTAMP\"=\"%s\"\n" | 452 | " TIMESTAMP=\"%s\"\n" |
874 | 367 | " \"CONNECTION_ID\"=\"%lu\"\n" | 453 | " CONNECTION_ID=\"%lu\"\n" |
875 | 368 | " \"STATUS\"=\"%d\"\n" | 454 | " STATUS=\"%d\"\n" |
876 | 369 | " \"USER\"=\"%s\"\n" | 455 | " USER=\"%s\"\n" |
877 | 370 | " \"PRIV_USER\"=\"%s\"\n" | 456 | " PRIV_USER=\"%s\"\n" |
878 | 371 | " \"OS_LOGIN\"=\"%s\"\n" | 457 | " OS_LOGIN=\"%s\"\n" |
879 | 372 | " \"PROXY_USER\"=\"%s\"\n" | 458 | " PROXY_USER=\"%s\"\n" |
880 | 373 | " \"HOST\"=\"%s\"\n" | 459 | " HOST=\"%s\"\n" |
881 | 374 | " \"IP\"=\"%s\"\n" | 460 | " IP=\"%s\"\n" |
882 | 375 | " \"DB\"=\"%s\"\n" | 461 | " DB=\"%s\"\n" |
883 | 376 | "/>\n", | 462 | "/>\n", |
884 | 463 | |||
885 | 377 | "<AUDIT_RECORD>\n" | 464 | "<AUDIT_RECORD>\n" |
886 | 378 | " <NAME>%s</NAME>\n" | 465 | " <NAME>%s</NAME>\n" |
887 | 379 | " <RECORD>%s</RECORD>\n" | 466 | " <RECORD>%s</RECORD>\n" |
888 | @@ -387,34 +474,96 @@ | |||
889 | 387 | " <HOST>%s</HOST>\n" | 474 | " <HOST>%s</HOST>\n" |
890 | 388 | " <IP>%s</IP>\n" | 475 | " <IP>%s</IP>\n" |
891 | 389 | " <DB>%s</DB>\n" | 476 | " <DB>%s</DB>\n" |
893 | 390 | "</AUDIT_RECORD>\n" }; | 477 | "</AUDIT_RECORD>\n", |
894 | 478 | |||
895 | 479 | "{\"audit_record\":" | ||
896 | 480 | "{\"name\":\"%s\"," | ||
897 | 481 | "\"record\":\"%s\"," | ||
898 | 482 | "\"timestamp\":\"%s\"," | ||
899 | 483 | "\"connection_id\":\"%lu\"," | ||
900 | 484 | "\"status\":%d," | ||
901 | 485 | "\"user\":\"%s\"," | ||
902 | 486 | "\"priv_user\":\"%s\"," | ||
903 | 487 | "\"os_login\":\"%s\"," | ||
904 | 488 | "\"proxy_user\":\"%s\"," | ||
905 | 489 | "\"host\":\"%s\"," | ||
906 | 490 | "\"ip\":\"%s\"," | ||
907 | 491 | "\"db\":\"%s\"}}\n", | ||
908 | 492 | |||
909 | 493 | "\"%s\",\"%s\",\"%s\",\"%lu\",%d,\"%s\",\"%s\",\"%s\"," | ||
910 | 494 | "\"%s\",\"%s\",\"%s\",\"%s\"\n" }; | ||
911 | 391 | 495 | ||
912 | 392 | return my_snprintf(buf, buflen, | 496 | return my_snprintf(buf, buflen, |
913 | 393 | format_string[audit_log_format], | 497 | format_string[audit_log_format], |
928 | 394 | name, | 498 | name, |
929 | 395 | make_record_id(id_str, sizeof(id_str)), | 499 | make_record_id(id_str, sizeof(id_str)), |
930 | 396 | make_timestamp(timestamp, sizeof(timestamp), t), | 500 | make_timestamp(timestamp, sizeof(timestamp), t), |
931 | 397 | event->thread_id, | 501 | event->thread_id, |
932 | 398 | event->status, | 502 | event->status, |
933 | 399 | event->user ? event->user : "", | 503 | escape_string(event->user, |
934 | 400 | event->priv_user ? event->priv_user : "", | 504 | event->user_length, |
935 | 401 | event->external_user ? event->external_user : "", | 505 | endptr, endtmp - endptr, &endptr), |
936 | 402 | event->proxy_user ? event->proxy_user : "", | 506 | escape_string(event->priv_user, |
937 | 403 | event->host ? event->host : "", | 507 | event->priv_user_length, |
938 | 404 | event->ip ? event->ip : "", | 508 | endptr, endtmp - endptr, &endptr), |
939 | 405 | event->database ? event->database : ""); | 509 | escape_string(event->external_user, |
940 | 406 | } | 510 | event->external_user_length, |
941 | 407 | 511 | endptr, endtmp - endptr, &endptr), | |
942 | 512 | escape_string(event->proxy_user, | ||
943 | 513 | event->proxy_user_length, | ||
944 | 514 | endptr, endtmp - endptr, &endptr), | ||
945 | 515 | escape_string(event->host, | ||
946 | 516 | event->host_length, | ||
947 | 517 | endptr, endtmp - endptr, &endptr), | ||
948 | 518 | escape_string(event->user, | ||
949 | 519 | event->user_length, | ||
950 | 520 | endptr, endtmp - endptr, &endptr), | ||
951 | 521 | escape_string(event->ip, | ||
952 | 522 | event->ip_length, | ||
953 | 523 | endptr, endtmp - endptr, &endptr), | ||
954 | 524 | escape_string(event->database, | ||
955 | 525 | event->database_length, | ||
956 | 526 | endptr, endtmp - endptr, &endptr)); | ||
957 | 527 | } | ||
958 | 528 | |||
959 | 529 | static | ||
960 | 530 | size_t audit_log_header(MY_STAT *stat, char *buf, size_t buflen) | ||
961 | 531 | { | ||
962 | 532 | const char *format_string[] = { | ||
963 | 533 | "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" | ||
964 | 534 | "<AUDIT>\n", | ||
965 | 535 | "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" | ||
966 | 536 | "<AUDIT>\n", | ||
967 | 537 | "", | ||
968 | 538 | "" }; | ||
969 | 539 | |||
970 | 540 | log_file_time= stat->st_mtime; | ||
971 | 541 | |||
972 | 542 | init_record_id(stat->st_size); | ||
973 | 543 | |||
974 | 544 | return my_snprintf(buf, buflen, format_string[audit_log_format]); | ||
975 | 545 | } | ||
976 | 546 | |||
977 | 547 | |||
978 | 548 | static | ||
979 | 549 | size_t audit_log_footer(char *buf, size_t buflen) | ||
980 | 550 | { | ||
981 | 551 | const char *format_string[] = { | ||
982 | 552 | "</AUDIT>\n", | ||
983 | 553 | "</AUDIT>\n", | ||
984 | 554 | "", | ||
985 | 555 | "" }; | ||
986 | 556 | |||
987 | 557 | return my_snprintf(buf, buflen, format_string[audit_log_format]); | ||
988 | 558 | } | ||
989 | 408 | 559 | ||
990 | 409 | static | 560 | static |
991 | 410 | int init_new_log_file() | 561 | int init_new_log_file() |
992 | 411 | { | 562 | { |
993 | 412 | MY_STAT stat_arg; | ||
994 | 413 | |||
995 | 414 | audit_file_logger= logger_open(audit_log_file, audit_log_rotate_on_size, | 563 | audit_file_logger= logger_open(audit_log_file, audit_log_rotate_on_size, |
996 | 415 | audit_log_rotate_on_size ? audit_log_rotations : 0, | 564 | audit_log_rotate_on_size ? audit_log_rotations : 0, |
997 | 416 | audit_log_strategy >= SEMISYNCHRONOUS, | 565 | audit_log_strategy >= SEMISYNCHRONOUS, |
999 | 417 | &stat_arg); | 566 | audit_log_header); |
1000 | 418 | if (audit_file_logger == NULL) | 567 | if (audit_file_logger == NULL) |
1001 | 419 | { | 568 | { |
1002 | 420 | fprintf_timestamp(stderr); | 569 | fprintf_timestamp(stderr); |
1003 | @@ -423,10 +572,6 @@ | |||
1004 | 423 | return(1); | 572 | return(1); |
1005 | 424 | } | 573 | } |
1006 | 425 | 574 | ||
1007 | 426 | log_file_time= stat_arg.st_mtime; | ||
1008 | 427 | |||
1009 | 428 | init_record_id(stat_arg.st_size); | ||
1010 | 429 | |||
1011 | 430 | return(0); | 575 | return(0); |
1012 | 431 | } | 576 | } |
1013 | 432 | 577 | ||
1014 | @@ -434,9 +579,7 @@ | |||
1015 | 434 | static | 579 | static |
1016 | 435 | int reopen_log_file() | 580 | int reopen_log_file() |
1017 | 436 | { | 581 | { |
1021 | 437 | MY_STAT stat_arg; | 582 | if (logger_reopen(audit_file_logger, audit_log_header, audit_log_footer)) |
1019 | 438 | |||
1020 | 439 | if (logger_reopen(audit_file_logger, &stat_arg)) | ||
1022 | 440 | { | 583 | { |
1023 | 441 | fprintf_timestamp(stderr); | 584 | fprintf_timestamp(stderr); |
1024 | 442 | fprintf(stderr, "Cannot open file %s. ", audit_log_file); | 585 | fprintf(stderr, "Cannot open file %s. ", audit_log_file); |
1025 | @@ -444,10 +587,6 @@ | |||
1026 | 444 | return(1); | 587 | return(1); |
1027 | 445 | } | 588 | } |
1028 | 446 | 589 | ||
1029 | 447 | log_file_time= stat_arg.st_mtime; | ||
1030 | 448 | |||
1031 | 449 | init_record_id(stat_arg.st_size); | ||
1032 | 450 | |||
1033 | 451 | return(0); | 590 | return(0); |
1034 | 452 | } | 591 | } |
1035 | 453 | 592 | ||
1036 | @@ -456,7 +595,7 @@ | |||
1037 | 456 | void close_log_file() | 595 | void close_log_file() |
1038 | 457 | { | 596 | { |
1039 | 458 | if (audit_file_logger != NULL) | 597 | if (audit_file_logger != NULL) |
1041 | 459 | logger_close(audit_file_logger); | 598 | logger_close(audit_file_logger, audit_log_footer); |
1042 | 460 | } | 599 | } |
1043 | 461 | 600 | ||
1044 | 462 | 601 | ||
1045 | @@ -466,6 +605,8 @@ | |||
1046 | 466 | char buf[1024]; | 605 | char buf[1024]; |
1047 | 467 | size_t len; | 606 | size_t len; |
1048 | 468 | 607 | ||
1049 | 608 | logger_init_mutexes(); | ||
1050 | 609 | |||
1051 | 469 | if (init_new_log_file()) | 610 | if (init_new_log_file()) |
1052 | 470 | return(1); | 611 | return(1); |
1053 | 471 | 612 | ||
1054 | @@ -494,7 +635,6 @@ | |||
1055 | 494 | 635 | ||
1056 | 495 | if (audit_log_buffer != NULL) | 636 | if (audit_log_buffer != NULL) |
1057 | 496 | audit_log_buffer_shutdown(audit_log_buffer); | 637 | audit_log_buffer_shutdown(audit_log_buffer); |
1058 | 497 | |||
1059 | 498 | close_log_file(); | 638 | close_log_file(); |
1060 | 499 | 639 | ||
1061 | 500 | return(0); | 640 | return(0); |
1062 | @@ -612,7 +752,7 @@ | |||
1063 | 612 | ASYNCHRONOUS, &audit_log_strategy_typelib); | 752 | ASYNCHRONOUS, &audit_log_strategy_typelib); |
1064 | 613 | 753 | ||
1065 | 614 | static const char *audit_log_format_names[]= | 754 | static const char *audit_log_format_names[]= |
1067 | 615 | { "OLD", "NEW", 0 }; | 755 | { "OLD", "NEW", "JSON", "CSV", 0 }; |
1068 | 616 | static TYPELIB audit_log_format_typelib= | 756 | static TYPELIB audit_log_format_typelib= |
1069 | 617 | { | 757 | { |
1070 | 618 | array_elements(audit_log_format_names) - 1, "audit_log_format_typelib", | 758 | array_elements(audit_log_format_names) - 1, "audit_log_format_typelib", |
1071 | @@ -674,7 +814,7 @@ | |||
1072 | 674 | { | 814 | { |
1073 | 675 | char new_val= *(const char *)(save); | 815 | char new_val= *(const char *)(save); |
1074 | 676 | 816 | ||
1076 | 677 | if (new_val != audit_log_flush && new_val == TRUE) | 817 | if (new_val != audit_log_flush && new_val) |
1077 | 678 | { | 818 | { |
1078 | 679 | audit_log_flush= TRUE; | 819 | audit_log_flush= TRUE; |
1079 | 680 | reopen_log_file(); | 820 | reopen_log_file(); |
1080 | 681 | 821 | ||
1081 | === modified file 'plugin/audit_log/file_logger.c' | |||
1082 | --- plugin/audit_log/file_logger.c 2014-04-21 12:07:45 +0000 | |||
1083 | +++ plugin/audit_log/file_logger.c 2014-05-26 07:58:11 +0000 | |||
1084 | @@ -13,12 +13,11 @@ | |||
1085 | 13 | along with this program; if not, write to the Free Software | 13 | along with this program; if not, write to the Free Software |
1086 | 14 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | 14 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
1087 | 15 | 15 | ||
1090 | 16 | #include <string.h> | 16 | #include <my_global.h> |
1089 | 17 | |||
1091 | 18 | #include <mysql/plugin.h> | 17 | #include <mysql/plugin.h> |
1092 | 19 | #include <my_global.h> | ||
1093 | 20 | #include <my_sys.h> | 18 | #include <my_sys.h> |
1094 | 21 | #include <my_pthread.h> | 19 | #include <my_pthread.h> |
1095 | 20 | #include <string.h> | ||
1096 | 22 | 21 | ||
1097 | 23 | #include "logger.h" | 22 | #include "logger.h" |
1098 | 24 | 23 | ||
1099 | @@ -85,14 +84,17 @@ | |||
1100 | 85 | return (i == 0) ? 0 : ((i < 10) ? 1 : ((i < 100) ? 2 : 3)); | 84 | return (i == 0) ? 0 : ((i < 10) ? 1 : ((i < 100) ? 2 : 3)); |
1101 | 86 | } | 85 | } |
1102 | 87 | 86 | ||
1103 | 88 | |||
1104 | 89 | LOGGER_HANDLE *logger_open(const char *path, | 87 | LOGGER_HANDLE *logger_open(const char *path, |
1105 | 90 | unsigned long long size_limit, | 88 | unsigned long long size_limit, |
1106 | 91 | unsigned int rotations, | 89 | unsigned int rotations, |
1107 | 92 | int thread_safe, | 90 | int thread_safe, |
1109 | 93 | MY_STAT *stat) | 91 | logger_prolog_func_t header) |
1110 | 94 | { | 92 | { |
1111 | 95 | LOGGER_HANDLE new_log, *l_perm; | 93 | LOGGER_HANDLE new_log, *l_perm; |
1112 | 94 | MY_STAT stat_arg; | ||
1113 | 95 | char buf[128]; | ||
1114 | 96 | size_t len; | ||
1115 | 97 | |||
1116 | 96 | /* | 98 | /* |
1117 | 97 | I don't think we ever need more rotations, | 99 | I don't think we ever need more rotations, |
1118 | 98 | but if it's so, the rotation procedure should be adapted to it. | 100 | but if it's so, the rotation procedure should be adapted to it. |
1119 | @@ -113,22 +115,19 @@ | |||
1120 | 113 | return 0; | 115 | return 0; |
1121 | 114 | } | 116 | } |
1122 | 115 | 117 | ||
1124 | 116 | if ((new_log.file= open(new_log.path, LOG_FLAGS, 0666)) < 0) | 118 | if ((new_log.file= my_open(new_log.path, LOG_FLAGS, 0666)) < 0) |
1125 | 117 | { | 119 | { |
1126 | 118 | errno= my_errno; | 120 | errno= my_errno; |
1127 | 119 | /* Check errno for the cause */ | 121 | /* Check errno for the cause */ |
1128 | 120 | return 0; | 122 | return 0; |
1129 | 121 | } | 123 | } |
1130 | 122 | 124 | ||
1132 | 123 | if (stat != NULL) | 125 | if (my_fstat(new_log.file, &stat_arg, MYF(0))) |
1133 | 124 | { | 126 | { |
1141 | 125 | if (my_fstat(new_log.file, stat, MYF(0))) | 127 | errno= my_errno; |
1142 | 126 | { | 128 | my_close(new_log.file, MYF(0)); |
1143 | 127 | errno= my_errno; | 129 | new_log.file= -1; |
1144 | 128 | my_close(new_log.file, MYF(0)); | 130 | return 0; |
1138 | 129 | new_log.file= -1; | ||
1139 | 130 | return 0; | ||
1140 | 131 | } | ||
1145 | 132 | } | 131 | } |
1146 | 133 | 132 | ||
1147 | 134 | if (!(l_perm= (LOGGER_HANDLE *) my_malloc(sizeof(LOGGER_HANDLE), MYF(0)))) | 133 | if (!(l_perm= (LOGGER_HANDLE *) my_malloc(sizeof(LOGGER_HANDLE), MYF(0)))) |
1148 | @@ -139,22 +138,25 @@ | |||
1149 | 139 | } | 138 | } |
1150 | 140 | *l_perm= new_log; | 139 | *l_perm= new_log; |
1151 | 141 | 140 | ||
1152 | 142 | #if defined(HAVE_PSI_INTERFACE) && !defined(FLOGGER_NO_PSI) && !defined(FLOGGER_NO_THREADSAFE) | ||
1153 | 143 | if (PSI_server) | ||
1154 | 144 | PSI_server->register_mutex("file_logger", | ||
1155 | 145 | mutex_list, array_elements(mutex_list)); | ||
1156 | 146 | #endif /*HAVE_PSI_INTERFACE && !FLOGGER_NO_PSI*/ | ||
1157 | 147 | |||
1158 | 148 | flogger_mutex_init(key_LOCK_logger_service, l_perm, | 141 | flogger_mutex_init(key_LOCK_logger_service, l_perm, |
1159 | 149 | MY_MUTEX_INIT_FAST); | 142 | MY_MUTEX_INIT_FAST); |
1160 | 150 | 143 | ||
1161 | 144 | len= header(&stat_arg, buf, sizeof(buf)); | ||
1162 | 145 | my_write(l_perm->file, (uchar *)buf, len, MYF(0)); | ||
1163 | 146 | |||
1164 | 151 | return l_perm; | 147 | return l_perm; |
1165 | 152 | } | 148 | } |
1166 | 153 | 149 | ||
1168 | 154 | int logger_close(LOGGER_HANDLE *log) | 150 | int logger_close(LOGGER_HANDLE *log, logger_epilog_func_t footer) |
1169 | 155 | { | 151 | { |
1170 | 156 | int result; | 152 | int result; |
1171 | 157 | File file= log->file; | 153 | File file= log->file; |
1172 | 154 | char buf[128]; | ||
1173 | 155 | size_t len; | ||
1174 | 156 | |||
1175 | 157 | len= footer(buf, sizeof(buf)); | ||
1176 | 158 | my_write(file, (uchar *)buf, len, MYF(0)); | ||
1177 | 159 | |||
1178 | 158 | flogger_mutex_destroy(log); | 160 | flogger_mutex_destroy(log); |
1179 | 159 | my_free(log); | 161 | my_free(log); |
1180 | 160 | if ((result= my_close(file, MYF(0)))) | 162 | if ((result= my_close(file, MYF(0)))) |
1181 | @@ -163,12 +165,19 @@ | |||
1182 | 163 | } | 165 | } |
1183 | 164 | 166 | ||
1184 | 165 | 167 | ||
1186 | 166 | int logger_reopen(LOGGER_HANDLE *log, MY_STAT *stat) | 168 | int logger_reopen(LOGGER_HANDLE *log, logger_prolog_func_t header, |
1187 | 169 | logger_epilog_func_t footer) | ||
1188 | 167 | { | 170 | { |
1189 | 168 | int result= 0; | 171 | int result= 0; |
1190 | 172 | MY_STAT stat_arg; | ||
1191 | 173 | char buf[128]; | ||
1192 | 174 | size_t len; | ||
1193 | 169 | 175 | ||
1194 | 170 | flogger_mutex_lock(log); | 176 | flogger_mutex_lock(log); |
1195 | 171 | 177 | ||
1196 | 178 | len= footer(buf, sizeof(buf)); | ||
1197 | 179 | my_write(log->file, (uchar *)buf, len, MYF(0)); | ||
1198 | 180 | |||
1199 | 172 | if ((result= my_close(log->file, MYF(0)))) | 181 | if ((result= my_close(log->file, MYF(0)))) |
1200 | 173 | { | 182 | { |
1201 | 174 | errno= my_errno; | 183 | errno= my_errno; |
1202 | @@ -182,19 +191,19 @@ | |||
1203 | 182 | goto error; | 191 | goto error; |
1204 | 183 | } | 192 | } |
1205 | 184 | 193 | ||
1207 | 185 | if (stat != NULL) | 194 | if ((result= my_fstat(log->file, &stat_arg, MYF(0)))) |
1208 | 186 | { | 195 | { |
1214 | 187 | if ((result= my_fstat(log->file, stat, MYF(0)))) | 196 | errno= my_errno; |
1215 | 188 | { | 197 | goto error; |
1211 | 189 | errno= my_errno; | ||
1212 | 190 | goto error; | ||
1213 | 191 | } | ||
1216 | 192 | } | 198 | } |
1217 | 193 | 199 | ||
1218 | 200 | len= header(&stat_arg, buf, sizeof(buf)); | ||
1219 | 201 | my_write(log->file, (uchar *)buf, len, MYF(0)); | ||
1220 | 202 | |||
1221 | 194 | error: | 203 | error: |
1222 | 195 | flogger_mutex_unlock(log); | 204 | flogger_mutex_unlock(log); |
1223 | 196 | 205 | ||
1225 | 197 | return 0; | 206 | return result; |
1226 | 198 | } | 207 | } |
1227 | 199 | 208 | ||
1228 | 200 | 209 | ||
1229 | 201 | 210 | ||
1230 | === modified file 'plugin/audit_log/logger.h' | |||
1231 | --- plugin/audit_log/logger.h 2014-04-21 12:07:45 +0000 | |||
1232 | +++ plugin/audit_log/logger.h 2014-05-26 07:58:11 +0000 | |||
1233 | @@ -60,20 +60,23 @@ | |||
1234 | 60 | #endif | 60 | #endif |
1235 | 61 | 61 | ||
1236 | 62 | typedef struct logger_handle_st LOGGER_HANDLE; | 62 | typedef struct logger_handle_st LOGGER_HANDLE; |
1237 | 63 | typedef size_t (logger_prolog_func_t)(MY_STAT *, char *buf, size_t buflen); | ||
1238 | 64 | typedef size_t (logger_epilog_func_t)(char *buf, size_t buflen); | ||
1239 | 63 | 65 | ||
1240 | 64 | void logger_init_mutexes(); | 66 | void logger_init_mutexes(); |
1241 | 65 | LOGGER_HANDLE *logger_open(const char *path, | 67 | LOGGER_HANDLE *logger_open(const char *path, |
1242 | 66 | unsigned long long size_limit, | 68 | unsigned long long size_limit, |
1243 | 67 | unsigned int rotations, | 69 | unsigned int rotations, |
1244 | 68 | int thread_safe, | 70 | int thread_safe, |
1247 | 69 | MY_STAT *stat); | 71 | logger_prolog_func_t header); |
1248 | 70 | int logger_close(LOGGER_HANDLE *log); | 72 | int logger_close(LOGGER_HANDLE *log, logger_epilog_func_t footer); |
1249 | 71 | int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); | 73 | int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); |
1250 | 72 | int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); | 74 | int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); |
1251 | 73 | int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); | 75 | int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size); |
1252 | 74 | int logger_rotate(LOGGER_HANDLE *log); | 76 | int logger_rotate(LOGGER_HANDLE *log); |
1253 | 75 | int logger_sync(LOGGER_HANDLE *log); | 77 | int logger_sync(LOGGER_HANDLE *log); |
1255 | 76 | int logger_reopen(LOGGER_HANDLE *log, MY_STAT *stat); | 78 | int logger_reopen(LOGGER_HANDLE *log, logger_prolog_func_t header, |
1256 | 79 | logger_epilog_func_t footer); | ||
1257 | 77 | void logger_set_size_limit(LOGGER_HANDLE *log, unsigned long long size_limit); | 80 | void logger_set_size_limit(LOGGER_HANDLE *log, unsigned long long size_limit); |
1258 | 78 | void logger_set_rotations(LOGGER_HANDLE *log, unsigned int rotations); | 81 | void logger_set_rotations(LOGGER_HANDLE *log, unsigned int rotations); |
1259 | 79 | 82 |
Wrong target branch?