diff --git a/mysql-test/suite/plugins/r/server_audit_pwd_mask.result b/mysql-test/suite/plugins/r/server_audit_pwd_mask.result new file mode 100644 index 00000000000..7cf3b05bcf1 --- /dev/null +++ b/mysql-test/suite/plugins/r/server_audit_pwd_mask.result @@ -0,0 +1,22 @@ +install plugin ed25519 soname 'auth_ed25519'; +install plugin server_audit soname 'server_audit'; +set global server_audit_file_path='server_audit.log'; +set global server_audit_output_type=file; +set global server_audit_logging=on; +# unsafe to log passwords (pwd-123) +CREATE USER u1 IDENTIFIED BY 'pwd_123'; +create user u2 IDENTIFIED VIA ed25519 USING PASSWORD('pwd_123'); +SET PASSWORD FOR u1 = PASSWORD('pwd_123'); +ALTER USER u1 IDENTIFIED BY 'pwd_123'; +alter user u2 identified VIA ed25519 USING password('pwd_123'); +GRANT ALL ON test TO u1 IDENTIFIED BY "pwd_123"; +GRANT ALL ON test TO u1 identified VIA ed25519 as password('pwd_123') or ed25519 using password('pwd_123'); +# pattern should not be found +NOT FOUND /pwd_123/ in server_audit.log +# pattern should not be found +# cleaunup +DROP USER u1; +DROP USER u2; +set global server_audit_logging=off; +UNINSTALL PLUGIN ed25519; +UNINSTALL PLUGIN server_audit; diff --git a/mysql-test/suite/plugins/t/server_audit_pwd_mask.test b/mysql-test/suite/plugins/t/server_audit_pwd_mask.test new file mode 100644 index 00000000000..af6425b2035 --- /dev/null +++ b/mysql-test/suite/plugins/t/server_audit_pwd_mask.test @@ -0,0 +1,46 @@ + +--source include/have_plugin_auth.inc +--source include/not_embedded.inc + +if (!$SERVER_AUDIT_SO) { + skip No SERVER_AUDIT plugin; +} +if (!$AUTH_ED25519_SO) { + skip No auth_ed25519 plugin; +} +--disable_ps2_protocol + +let $MYSQLD_DATADIR= `SELECT @@datadir`; +let SEARCH_FILE= $MYSQLD_DATADIR/server_audit.log; + +install plugin ed25519 soname 'auth_ed25519'; +install plugin server_audit soname 'server_audit'; + + +set global server_audit_file_path='server_audit.log'; +set global server_audit_output_type=file; +set global server_audit_logging=on; + +--echo # unsafe to log passwords (pwd-123) + +CREATE USER u1 IDENTIFIED BY 'pwd_123'; +create user u2 IDENTIFIED VIA ed25519 USING PASSWORD('pwd_123'); +SET PASSWORD FOR u1 = PASSWORD('pwd_123'); +ALTER USER u1 IDENTIFIED BY 'pwd_123'; +alter user u2 identified VIA ed25519 USING password('pwd_123'); +GRANT ALL ON test TO u1 IDENTIFIED BY "pwd_123"; +GRANT ALL ON test TO u1 identified VIA ed25519 as password('pwd_123') or ed25519 using password('pwd_123'); +--let SEARCH_PATTERN=pwd_123 +--echo # pattern should not be found +--source include/search_pattern_in_file.inc +--echo # pattern should not be found + +--echo # cleaunup +DROP USER u1; +DROP USER u2; +set global server_audit_logging=off; +--remove_file $SEARCH_FILE +--disable_warnings +UNINSTALL PLUGIN ed25519; +UNINSTALL PLUGIN server_audit; +--enable_warnings diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index e45282c6e20..2de27215ed9 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -1512,12 +1512,33 @@ static size_t escape_string(const char *str, unsigned int len, return result - res_start; } +/* + Replace "password" with "*****" in + + "password" + + if is 0 + + "password" + + or + + "password" + + if is 0 + + "password" + + NOTE: there can be " or ' around the password, the words are case + insensitive. +*/ static size_t escape_string_hide_passwords(const char *str, unsigned int len, char *result, size_t result_len, const char *word1, size_t word1_len, const char *word2, size_t word2_len, - int next_text_string) + const char *word0, size_t word0_len, + char chr0) { const char *res_start= result; const char *res_end= result + result_len - 2; @@ -1525,18 +1546,32 @@ static size_t escape_string_hide_passwords(const char *str, unsigned int len, while (len) { - if (len > word1_len + 1 && strncasecmp(str, word1, word1_len) == 0) + int word1_found= (word1 && len > word1_len + 1 && + strncasecmp(str, word1, word1_len) == 0); + int word0_found= (word0 && len > word0_len + 1 && + strncasecmp(str, word0, word0_len) == 0); + if (word1_found || word0_found) { - const char *next_s= str + word1_len; + const char *next_s; size_t c; - if (next_text_string) + if (word0_found) { + next_s= str + word0_len; + if (chr0) + { + SKIP_SPACES(next_s); + if (len < (size_t)(next_s - str) + 1 + 1 || + next_s[0] != chr0) + goto no_password; + next_s++; + } while (*next_s && *next_s != '\'' && *next_s != '"') ++next_s; } else { + next_s= str + word1_len; if (word2) { SKIP_SPACES(next_s); @@ -1851,23 +1886,27 @@ do_log_query: case SQLCOM_ALTER_USER: csize+= escape_string_hide_passwords(query, query_len, uh_buffer, uh_buffer_size, - "IDENTIFIED", 10, "BY", 2, 0); + "IDENTIFIED", 10, "BY", 2, + "PASSWORD", 8, '('); break; case SQLCOM_CHANGE_MASTER: csize+= escape_string_hide_passwords(query, query_len, uh_buffer, uh_buffer_size, - "MASTER_PASSWORD", 15, "=", 1, 0); + "MASTER_PASSWORD", 15, "=", 1, + 0, 0, 0); break; case SQLCOM_CREATE_SERVER: case SQLCOM_ALTER_SERVER: csize+= escape_string_hide_passwords(query, query_len, uh_buffer, uh_buffer_size, - "PASSWORD", 8, NULL, 0, 0); + "PASSWORD", 8, NULL, 0, + 0, 0, 0); break; case SQLCOM_SET_OPTION: csize+= escape_string_hide_passwords(query, query_len, uh_buffer, uh_buffer_size, - "=", 1, NULL, 0, 1); + NULL, 0, NULL, 0, + "=", 1, 0); break; default: csize+= escape_string(query, query_len,