implement mysql function VALIDATE_PASSWORD_STRENGTH()
This commit is contained in:
2
deps/oblib/src/lib/charset/ob_charset.h
vendored
2
deps/oblib/src/lib/charset/ob_charset.h
vendored
@ -277,7 +277,7 @@ public:
|
||||
return result;
|
||||
}
|
||||
template <typename foreach_char_func>
|
||||
static int foreach_char(common::ObString& str, common::ObCollationType collation_type, foreach_char_func& func)
|
||||
static int foreach_char(const common::ObString &str, common::ObCollationType collation_type, foreach_char_func &func)
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
int32_t wchar = 0;
|
||||
|
||||
1
deps/oblib/src/lib/ob_name_def.h
vendored
1
deps/oblib/src/lib/ob_name_def.h
vendored
@ -336,6 +336,7 @@
|
||||
#define N_OPERATOR_MONITOR_INFO "op_info"
|
||||
#define N_PLAN_MONITOR_INFO "plan_info"
|
||||
#define N_ANY_VAL "any_value"
|
||||
#define N_VALIDATE_PASSWORD_STRENGTH "validate_password_strength"
|
||||
// common comparison operator
|
||||
#define N_LESS_THAN "<"
|
||||
#define N_GREATER_THAN ">"
|
||||
|
||||
@ -464,6 +464,8 @@ ob_set_subtarget(ob_sql engine
|
||||
engine/expr/ob_expr_calc_urowid.cpp
|
||||
engine/expr/ob_expr_cardinality.cpp
|
||||
engine/expr/ob_expr_coll_pred.cpp
|
||||
engine/expr/ob_expr_validate_password_strength.cpp
|
||||
engine/expr/ob_expr_validate_password_strength.h
|
||||
engine/expr/ob_expr_benchmark.cpp
|
||||
engine/expr/ob_expr_benchmark.h
|
||||
engine/join/ob_basic_nested_loop_join.cpp
|
||||
|
||||
@ -187,6 +187,7 @@
|
||||
#include "ob_expr_degrees.h"
|
||||
#include "ob_expr_weight_string.h"
|
||||
#include "ob_expr_any_value.h"
|
||||
#include "ob_expr_validate_password_strength.h"
|
||||
#include "ob_expr_benchmark.h"
|
||||
|
||||
namespace oceanbase {
|
||||
@ -704,7 +705,7 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
|
||||
NULL, /* 440 */
|
||||
ObExprTimestamp::calc_timestamp1, /* 441 */
|
||||
ObExprTimestamp::calc_timestamp2, /* 442 */
|
||||
NULL, /* 443 */
|
||||
ObExprValidatePasswordStrength::eval_password_strength, /* 443 */
|
||||
NULL, /* 444 */
|
||||
NULL, /* 445 */
|
||||
NULL, /* 446 */
|
||||
|
||||
@ -271,6 +271,7 @@
|
||||
#include "sql/engine/expr/ob_expr_degrees.h"
|
||||
#include "sql/engine/expr/ob_expr_weight_string.h"
|
||||
#include "sql/engine/expr/ob_expr_any_value.h"
|
||||
#include "sql/engine/expr/ob_expr_validate_password_strength.h"
|
||||
#include "sql/engine/expr/ob_expr_benchmark.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
@ -683,6 +684,7 @@ void ObExprOperatorFactory::register_expr_operators()
|
||||
REG_OP(ObExprTimeFormat);
|
||||
REG_OP(ObExprTimestamp);
|
||||
REG_OP(ObExprDegrees);
|
||||
REG_OP(ObExprValidatePasswordStrength);
|
||||
REG_OP(ObExprWeightString);
|
||||
REG_OP(ObExprBenchmark);
|
||||
REG_OP(ObExprDay);
|
||||
|
||||
211
src/sql/engine/expr/ob_expr_validate_password_strength.cpp
Normal file
211
src/sql/engine/expr/ob_expr_validate_password_strength.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
// Copyright (c) 2021 Alibaba Inc. All Rights Reserved.
|
||||
// Author:
|
||||
// renqing <sean.yyj@antgroup.com>
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
|
||||
#include "ob_expr_validate_password_strength.h"
|
||||
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
using namespace oceanbase::sql;
|
||||
namespace oceanbase {
|
||||
namespace sql {
|
||||
|
||||
const ObValidatePasswordFunc ObExprValidatePasswordStrength::validate_funcs_[STRENGTH_MAX] = {
|
||||
NULL, // STRENGTH_WEAK is default strength, need no validation
|
||||
ObExprValidatePasswordStrength::validate_password_lessweak,
|
||||
ObExprValidatePasswordStrength::validate_password_low,
|
||||
ObExprValidatePasswordStrength::validate_password_medium,
|
||||
ObExprValidatePasswordStrength::validate_password_strong,
|
||||
};
|
||||
|
||||
ObExprValidatePasswordStrength::ObExprValidatePasswordStrength(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(
|
||||
alloc, T_FUN_SYS_VALIDATE_PASSWORD_STRENGTH, N_VALIDATE_PASSWORD_STRENGTH, 1, NOT_ROW_DIMENSION)
|
||||
{}
|
||||
|
||||
ObExprValidatePasswordStrength::~ObExprValidatePasswordStrength()
|
||||
{}
|
||||
|
||||
int ObExprValidatePasswordStrength::calc_result_type1(
|
||||
ObExprResType &type, ObExprResType &type1, ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(type_ctx);
|
||||
type.set_int();
|
||||
type.set_scale(common::ObAccuracy::DDL_DEFAULT_ACCURACY[common::ObIntType].scale_);
|
||||
type.set_precision(common::ObAccuracy::DDL_DEFAULT_ACCURACY[common::ObIntType].precision_);
|
||||
type1.set_calc_type(common::ObVarcharType);
|
||||
ObExprOperator::calc_result_flag1(type, type1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValidatePasswordStrength::calc_result1(ObObj &result, const ObObj &obj1, ObExprCtx &expr_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(expr_ctx.my_session_) || OB_ISNULL(expr_ctx.calc_buf_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("Invalid argument", KP(expr_ctx.my_session_), KP(expr_ctx.calc_buf_), K(ret));
|
||||
} else if (obj1.is_null()) {
|
||||
result.set_null();
|
||||
} else {
|
||||
ObString password;
|
||||
int strength = 0;
|
||||
if (OB_FAIL(ObCharset::charset_convert(*expr_ctx.calc_buf_,
|
||||
obj1.get_string(),
|
||||
obj1.get_collation_type(),
|
||||
ObCharset::get_system_collation(),
|
||||
password))) {
|
||||
LOG_WARN("fail to convert password to sys collation", K(obj1), K(ret));
|
||||
} else if (OB_FAIL(calc_password_strength(password, *expr_ctx.my_session_, strength))) {
|
||||
LOG_WARN("fail to calc password strength", K(password), K(ret));
|
||||
} else {
|
||||
result.set_int(strength);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValidatePasswordStrength::cg_expr(ObExprCGCtx &op_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(op_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
rt_expr.eval_func_ = eval_password_strength;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValidatePasswordStrength::eval_password_strength(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *pwd_param = NULL;
|
||||
ObCollationType c_src = ObCollationType::CS_TYPE_INVALID;
|
||||
ObString password_orig;
|
||||
ObString password;
|
||||
int strength = 0;
|
||||
|
||||
const ObBasicSessionInfo *session = ctx.exec_ctx_.get_my_session();
|
||||
if (OB_ISNULL(session)) {
|
||||
LOG_WARN("session is null", K(ret));
|
||||
} else if (OB_FAIL(expr.args_[0]->eval(ctx, pwd_param))) {
|
||||
LOG_WARN("eval arg failed", K(ret));
|
||||
} else if (pwd_param->is_null()) {
|
||||
res_datum.set_null();
|
||||
} else if (FALSE_IT(password_orig = pwd_param->get_string())) {
|
||||
} else if (FALSE_IT(c_src = expr.args_[0]->obj_meta_.get_collation_type())) {
|
||||
} else if (OB_FAIL(ObCharset::charset_convert(
|
||||
ctx.exec_ctx_.get_allocator(), password_orig, c_src, ObCharset::get_system_collation(), password))) {
|
||||
LOG_WARN("fail to convert password to sys collation", K(password_orig), K(c_src), K(ret));
|
||||
} else if (OB_FAIL(calc_password_strength(password, *session, strength))) {
|
||||
LOG_WARN("fail to calc password strength", K(password), K(ret));
|
||||
} else {
|
||||
res_datum.set_int(strength);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValidatePasswordStrength::calc_password_strength(
|
||||
const ObString &password, const ObBasicSessionInfo &session, int &strength)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool passed = true;
|
||||
strength = 0;
|
||||
for (int i = STRENGTH_LESSWEAK; OB_SUCC(ret) && passed && i < STRENGTH_MAX; ++i) {
|
||||
if (OB_FAIL(validate_funcs_[i](password, session, passed))) {
|
||||
LOG_WARN("failed to validate", K(password), K(i), K(ret));
|
||||
} else if (passed) {
|
||||
strength = i * PASSWORD_STRENGTH_MULTIPLIER;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValidatePasswordStrength::validate_password_lessweak(
|
||||
const ObString &password, const ObBasicSessionInfo &session, bool &passed)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t check_user_name = 0;
|
||||
passed = false;
|
||||
if (OB_FAIL(session.get_sys_variable(share::SYS_VAR_VALIDATE_PASSWORD_CHECK_USER_NAME, check_user_name))) {
|
||||
LOG_WARN("fail to get validate_password_length", K(ret));
|
||||
} else {
|
||||
passed = password.length() >= VALID_PASSWORD_LENGTH_MIN &&
|
||||
(!check_user_name && !ObCharset::case_insensitive_equal(password, session.get_user_name()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValidatePasswordStrength::validate_password_low(
|
||||
const ObString &password, const ObBasicSessionInfo &session, bool &passed)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
uint64_t valid_pw_len = 0;
|
||||
passed = false;
|
||||
if (OB_FAIL(session.get_sys_variable(share::SYS_VAR_VALIDATE_PASSWORD_LENGTH, valid_pw_len))) {
|
||||
LOG_WARN("fail to get validate_password_length", K(ret));
|
||||
} else {
|
||||
passed = password.length() >= valid_pw_len;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValidatePasswordStrength::validate_password_medium(
|
||||
const ObString &password, const ObBasicSessionInfo &session, bool &passed)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
uint64_t valid_mix_case_count = 0;
|
||||
uint64_t valid_number_count = 0;
|
||||
uint64_t valid_special_count = 0;
|
||||
uint64_t lower_count = 0;
|
||||
uint64_t upper_count = 0;
|
||||
uint64_t digit_count = 0;
|
||||
uint64_t special_count = 0;
|
||||
passed = false;
|
||||
if (OB_FAIL(session.get_sys_variable(share::SYS_VAR_VALIDATE_PASSWORD_MIXED_CASE_COUNT, valid_mix_case_count))) {
|
||||
LOG_WARN("fail to get validate_password_mixed_case_count", K(ret));
|
||||
} else if (OB_FAIL(session.get_sys_variable(share::SYS_VAR_VALIDATE_PASSWORD_NUMBER_COUNT, valid_number_count))) {
|
||||
LOG_WARN("fail to get validate_password_number_count", K(ret));
|
||||
} else if (OB_FAIL(
|
||||
session.get_sys_variable(share::SYS_VAR_VALIDATE_PASSWORD_SPECIAL_CHAR_COUNT, valid_special_count))) {
|
||||
LOG_WARN("fail to get validate_password_special_char_count", K(ret));
|
||||
} else {
|
||||
auto handle_char_func = [&lower_count, &upper_count, &digit_count, &special_count](ObString, int wchar) -> int {
|
||||
int ret = OB_SUCCESS;
|
||||
if (islower(wchar)) {
|
||||
lower_count++;
|
||||
} else if (isupper(wchar)) {
|
||||
upper_count++;
|
||||
} else if (isdigit(wchar)) {
|
||||
digit_count++;
|
||||
} else {
|
||||
special_count++;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
OZ(ObCharsetUtils::foreach_char(password, ObCharset::get_system_collation(), handle_char_func));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
passed = lower_count >= valid_mix_case_count && upper_count >= valid_mix_case_count &&
|
||||
digit_count >= valid_number_count && special_count >= valid_special_count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprValidatePasswordStrength::validate_password_strong(
|
||||
const ObString &password, const ObBasicSessionInfo &session, bool &passed)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(password);
|
||||
UNUSED(session);
|
||||
// Check if the password matches the words in the dictionary file. The dictionary file is not
|
||||
// supported in OB yet, so this validation always passed
|
||||
passed = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
50
src/sql/engine/expr/ob_expr_validate_password_strength.h
Normal file
50
src/sql/engine/expr/ob_expr_validate_password_strength.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2021 Alibaba Inc. All Rights Reserved.
|
||||
// Author:
|
||||
// renqing <sean.yyj@antgroup.com>
|
||||
|
||||
#ifndef SRC_SQL_ENGINE_EXPR_OB_EXPR_VALIDATE_PASSWORD_STRENGTH_H_
|
||||
#define SRC_SQL_ENGINE_EXPR_OB_EXPR_VALIDATE_PASSWORD_STRENGTH_H_
|
||||
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace sql {
|
||||
|
||||
typedef int (*ObValidatePasswordFunc)(
|
||||
const common::ObString &password, const ObBasicSessionInfo &session, bool &passed);
|
||||
class ObExprValidatePasswordStrength : public ObFuncExprOperator {
|
||||
public:
|
||||
enum PasswordStrength {
|
||||
STRENGTH_WEAK = 0,
|
||||
STRENGTH_LESSWEAK,
|
||||
STRENGTH_LOW,
|
||||
STRENGTH_MEDIUM,
|
||||
STRENGTH_STRONG,
|
||||
STRENGTH_MAX,
|
||||
};
|
||||
explicit ObExprValidatePasswordStrength(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprValidatePasswordStrength();
|
||||
virtual int calc_result_type1(ObExprResType &type, ObExprResType &type1, common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int calc_result1(common::ObObj &result, const common::ObObj &obj1, common::ObExprCtx &expr_ctx) const;
|
||||
virtual int cg_expr(ObExprCGCtx &op_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override;
|
||||
static int eval_password_strength(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum);
|
||||
|
||||
private:
|
||||
static int calc_password_strength(const common::ObString &password, const ObBasicSessionInfo &session, int &strength);
|
||||
static int validate_password_lessweak(
|
||||
const common::ObString &password, const ObBasicSessionInfo &session, bool &passed);
|
||||
static int validate_password_low(const common::ObString &password, const ObBasicSessionInfo &session, bool &passed);
|
||||
static int validate_password_medium(
|
||||
const common::ObString &password, const ObBasicSessionInfo &session, bool &passed);
|
||||
static int validate_password_strong(
|
||||
const common::ObString &password, const ObBasicSessionInfo &session, bool &passed);
|
||||
static const int64_t VALID_PASSWORD_LENGTH_MIN = 4;
|
||||
static const int64_t PASSWORD_STRENGTH_MULTIPLIER = 25;
|
||||
static const ObValidatePasswordFunc validate_funcs_[STRENGTH_MAX];
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprValidatePasswordStrength);
|
||||
};
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
|
||||
#endif /* SRC_SQL_ENGINE_EXPR_OB_EXPR_VALIDATE_PASSWORD_STRENGTH_H_ */
|
||||
@ -428,6 +428,7 @@ typedef enum ObItemType {
|
||||
T_FUN_SYS_PI = 713,
|
||||
T_FUN_SYS_ANY_VALUE = 714,
|
||||
T_FUN_SYS_DEGREES = 715,
|
||||
T_FUN_SYS_VALIDATE_PASSWORD_STRENGTH = 716,
|
||||
T_FUN_SYS_BENCHMARK = 720,
|
||||
T_FUN_SYS_EXPORT_SET = 721,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user