diff --git a/src/memgraph.cpp b/src/memgraph.cpp index adf10ec34..c659bbc3c 100644 --- a/src/memgraph.cpp +++ b/src/memgraph.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -116,14 +117,24 @@ using ServerT = communication::Server; using communication::ServerContext; #ifdef MG_ENTERPRISE + +DEFINE_string( + auth_user_or_role_name_regex, "[a-zA-Z0-9_.+-@]+", + "Set to the regular expression that each user or role name must fulfill."); + class AuthQueryHandler final : public query::AuthQueryHandler { auth::Auth *auth_; + std::regex name_regex_; public: - explicit AuthQueryHandler(auth::Auth *auth) : auth_(auth) {} + AuthQueryHandler(auth::Auth *auth, const std::regex &name_regex) + : auth_(auth), name_regex_(name_regex) {} bool CreateUser(const std::string &username, const std::optional &password) override { + if (!std::regex_match(username, name_regex_)) { + throw query::QueryRuntimeException("Invalid user name."); + } try { std::lock_guard lock(auth_->WithLock()); return !!auth_->AddUser(username, password); @@ -133,6 +144,9 @@ class AuthQueryHandler final : public query::AuthQueryHandler { } bool DropUser(const std::string &username) override { + if (!std::regex_match(username, name_regex_)) { + throw query::QueryRuntimeException("Invalid user name."); + } try { std::lock_guard lock(auth_->WithLock()); auto user = auth_->GetUser(username); @@ -145,6 +159,9 @@ class AuthQueryHandler final : public query::AuthQueryHandler { void SetPassword(const std::string &username, const std::optional &password) override { + if (!std::regex_match(username, name_regex_)) { + throw query::QueryRuntimeException("Invalid user name."); + } try { std::lock_guard lock(auth_->WithLock()); auto user = auth_->GetUser(username); @@ -160,6 +177,9 @@ class AuthQueryHandler final : public query::AuthQueryHandler { } bool CreateRole(const std::string &rolename) override { + if (!std::regex_match(rolename, name_regex_)) { + throw query::QueryRuntimeException("Invalid role name."); + } try { std::lock_guard lock(auth_->WithLock()); return !!auth_->AddRole(rolename); @@ -169,6 +189,9 @@ class AuthQueryHandler final : public query::AuthQueryHandler { } bool DropRole(const std::string &rolename) override { + if (!std::regex_match(rolename, name_regex_)) { + throw query::QueryRuntimeException("Invalid role name."); + } try { std::lock_guard lock(auth_->WithLock()); auto role = auth_->GetRole(rolename); @@ -211,6 +234,9 @@ class AuthQueryHandler final : public query::AuthQueryHandler { std::optional GetRolenameForUser( const std::string &username) override { + if (!std::regex_match(username, name_regex_)) { + throw query::QueryRuntimeException("Invalid user name."); + } try { std::lock_guard lock(auth_->WithLock()); auto user = auth_->GetUser(username); @@ -227,6 +253,9 @@ class AuthQueryHandler final : public query::AuthQueryHandler { std::vector GetUsernamesForRole( const std::string &rolename) override { + if (!std::regex_match(rolename, name_regex_)) { + throw query::QueryRuntimeException("Invalid role name."); + } try { std::lock_guard lock(auth_->WithLock()); auto role = auth_->GetRole(rolename); @@ -248,6 +277,12 @@ class AuthQueryHandler final : public query::AuthQueryHandler { void SetRole(const std::string &username, const std::string &rolename) override { + if (!std::regex_match(username, name_regex_)) { + throw query::QueryRuntimeException("Invalid user name."); + } + if (!std::regex_match(rolename, name_regex_)) { + throw query::QueryRuntimeException("Invalid role name."); + } try { std::lock_guard lock(auth_->WithLock()); auto user = auth_->GetUser(username); @@ -273,6 +308,9 @@ class AuthQueryHandler final : public query::AuthQueryHandler { } void ClearRole(const std::string &username) override { + if (!std::regex_match(username, name_regex_)) { + throw query::QueryRuntimeException("Invalid user name."); + } try { std::lock_guard lock(auth_->WithLock()); auto user = auth_->GetUser(username); @@ -289,6 +327,9 @@ class AuthQueryHandler final : public query::AuthQueryHandler { std::vector> GetPrivileges( const std::string &user_or_role) override { + if (!std::regex_match(user_or_role, name_regex_)) { + throw query::QueryRuntimeException("Invalid user or role name."); + } try { std::lock_guard lock(auth_->WithLock()); std::vector> grants; @@ -392,6 +433,9 @@ class AuthQueryHandler final : public query::AuthQueryHandler { const std::string &user_or_role, const std::vector &privileges, const TEditFun &edit_fun) { + if (!std::regex_match(user_or_role, name_regex_)) { + throw query::QueryRuntimeException("Invalid user or role name."); + } try { std::lock_guard lock(auth_->WithLock()); std::vector permissions; @@ -583,7 +627,8 @@ void SingleNodeMain() { } // Register modules END #ifdef MG_ENTERPRISE - AuthQueryHandler auth_handler(&auth); + AuthQueryHandler auth_handler(&auth, + std::regex(FLAGS_auth_user_or_role_name_regex)); #else AuthQueryHandler auth_handler; #endif diff --git a/src/query/frontend/ast/cypher_main_visitor.cpp b/src/query/frontend/ast/cypher_main_visitor.cpp index e0aa62eff..ae7591027 100644 --- a/src/query/frontend/ast/cypher_main_visitor.cpp +++ b/src/query/frontend/ast/cypher_main_visitor.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -455,12 +454,7 @@ antlrcpp::Any CypherMainVisitor::visitCallProcedure( */ antlrcpp::Any CypherMainVisitor::visitUserOrRoleName( MemgraphCypher::UserOrRoleNameContext *ctx) { - std::string value = ctx->symbolicName()->accept(this).as(); - const std::regex NAME_REGEX("[a-zA-Z0-9_.+-]+"); - if (!std::regex_match(value, NAME_REGEX)) { - throw SyntaxException("Invalid user or role name."); - } - return value; + return ctx->symbolicName()->accept(this).as(); } /** diff --git a/tests/unit/cypher_main_visitor.cpp b/tests/unit/cypher_main_visitor.cpp index b1a2f2814..cb473a076 100644 --- a/tests/unit/cypher_main_visitor.cpp +++ b/tests/unit/cypher_main_visitor.cpp @@ -2142,16 +2142,16 @@ void check_auth_query(Base *ast_generator, std::string input, TEST_P(CypherMainVisitorTest, UserOrRoleName) { auto &ast_generator = *GetParam(); - ASSERT_THROW(ast_generator.ParseQuery("CREATE ROLE `us|er`"), - SyntaxException); - ASSERT_THROW(ast_generator.ParseQuery("CREATE ROLE `us er`"), - SyntaxException); check_auth_query(&ast_generator, "CREATE ROLE `user`", AuthQuery::Action::CREATE_ROLE, "", "user", "", {}, {}); check_auth_query(&ast_generator, "CREATE ROLE us___er", AuthQuery::Action::CREATE_ROLE, "", "us___er", "", {}, {}); check_auth_query(&ast_generator, "CREATE ROLE `us+er`", AuthQuery::Action::CREATE_ROLE, "", "us+er", "", {}, {}); + check_auth_query(&ast_generator, "CREATE ROLE `us|er`", + AuthQuery::Action::CREATE_ROLE, "", "us|er", "", {}, {}); + check_auth_query(&ast_generator, "CREATE ROLE `us er`", + AuthQuery::Action::CREATE_ROLE, "", "us er", "", {}, {}); } TEST_P(CypherMainVisitorTest, CreateRole) {