Commit c98b2b39 authored by Sergei Golubchik's avatar Sergei Golubchik

password validation plugin type and a simple plugin

parent b5357f02
......@@ -43,6 +43,7 @@ IF(CMAKE_COMPILER_IS_GNUCC AND RUN_ABI_CHECK)
${CMAKE_SOURCE_DIR}/include/mysql/psi/psi_abi_v2.h
${CMAKE_SOURCE_DIR}/include/mysql/client_plugin.h
${CMAKE_SOURCE_DIR}/include/mysql/plugin_auth.h
${CMAKE_SOURCE_DIR}/include/mysql/plugin_password_validation.h
)
ADD_CUSTOM_TARGET(abi_check ALL
......
......@@ -80,17 +80,19 @@ typedef struct st_mysql_xid MYSQL_XID;
/*
The allowable types of plugins
*/
#define MYSQL_UDF_PLUGIN 0 /* User-defined function */
#define MYSQL_STORAGE_ENGINE_PLUGIN 1 /* Storage Engine */
#define MYSQL_UDF_PLUGIN 0 /* not implemented */
#define MYSQL_STORAGE_ENGINE_PLUGIN 1
#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */
#define MYSQL_DAEMON_PLUGIN 3 /* The daemon/raw plugin type */
#define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */
#define MYSQL_AUDIT_PLUGIN 5 /* The Audit plugin type */
#define MYSQL_REPLICATION_PLUGIN 6 /* The replication plugin type */
#define MYSQL_AUTHENTICATION_PLUGIN 7 /* The authentication plugin type */
#define MYSQL_VALIDATE_PASSWORD_PLUGIN 8 /* validate password plugin type */
#define MYSQL_DAEMON_PLUGIN 3
#define MYSQL_INFORMATION_SCHEMA_PLUGIN 4
#define MYSQL_AUDIT_PLUGIN 5
#define MYSQL_REPLICATION_PLUGIN 6
#define MYSQL_AUTHENTICATION_PLUGIN 7
#define MYSQL_MAX_PLUGIN_TYPE_NUM 9 /* The number of plugin types */
/* MariaDB plugin types */
#define MariaDB_PASSWORD_VALIDATION_PLUGIN 8
/* We use the following strings to define licenses for plugins */
#define PLUGIN_LICENSE_PROPRIETARY 0
#define PLUGIN_LICENSE_GPL 1
......
#ifndef MYSQL_PLUGIN_PASSWORD_VALIDATION_INCLUDED
/* Copyright (C) 2014 Sergei Golubchik and MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
Authentication Plugin API.
This file defines the API for server authentication plugins.
*/
#define MYSQL_PLUGIN_PASSWORD_VALIDATION_INCLUDED
#include <mysql/plugin.h>
#define MariaDB_PASSWORD_VALIDATION_INTERFACE_VERSION 0x0100
/**
Password validation plugin descriptor
*/
struct st_mysql_password_validation
{
int interface_version; /**< version plugin uses */
/**
Function provided by the plugin which should perform password validation
and return 0 if the password has passed the validation.
*/
int (*validate_password)(MYSQL_LEX_STRING *username,
MYSQL_LEX_STRING *password);
};
#endif
This diff is collapsed.
install soname "simple_password_check";
select * from information_schema.plugins where plugin_name='simple_password_check';
PLUGIN_NAME simple_password_check
PLUGIN_VERSION 1.0
PLUGIN_STATUS ACTIVE
PLUGIN_TYPE PASSWORD VALIDATION
PLUGIN_TYPE_VERSION 1.0
PLUGIN_LIBRARY simple_password_check.so
PLUGIN_LIBRARY_VERSION 1.10
PLUGIN_AUTHOR Sergei Golubchik
PLUGIN_DESCRIPTION Simple password strength checks
PLUGIN_LICENSE GPL
LOAD_OPTION ON
PLUGIN_MATURITY Alpha
PLUGIN_AUTH_VERSION 1.0
select * from information_schema.system_variables where variable_name like 'simple_password_check%' order by 1;
VARIABLE_NAME SIMPLE_PASSWORD_CHECK_DIGITS
SESSION_VALUE NULL
GLOBAL_VALUE 1
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Minimal required number of digits
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1000
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SIMPLE_PASSWORD_CHECK_LETTERS_SAME_CASE
SESSION_VALUE NULL
GLOBAL_VALUE 1
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Minimal required number of letters of the same letter case.This limit is applied separately to upper-case and lower-case letters
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1000
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SIMPLE_PASSWORD_CHECK_MINIMAL_LENGTH
SESSION_VALUE NULL
GLOBAL_VALUE 8
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 8
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Minimal required password length
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1000
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SIMPLE_PASSWORD_CHECK_OTHER_CHARACTERS
SESSION_VALUE NULL
GLOBAL_VALUE 1
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 1
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Minimal required number of other (not letters or digits) characters
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 1000
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
uninstall plugin simple_password_check;
--source include/not_embedded.inc
if (!$SIMPLE_PASSWORD_CHECK_SO) {
skip No SIMPLE_PASSWORD_CHECK plugin;
}
install soname "simple_password_check";
--vertical_results
--replace_result .dll .so
select * from information_schema.plugins where plugin_name='simple_password_check';
select * from information_schema.system_variables where variable_name like 'simple_password_check%' order by 1;
--horizontal_results
uninstall plugin simple_password_check;
MYSQL_ADD_PLUGIN(simple_password_check simple_password_check.c MODULE_ONLY)
/* Copyright (c) 2014, Sergei Golubchik and MariaDB
Copyright (c) 2012, 2013, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include <mysql/plugin_password_validation.h>
#include <ctype.h>
#include <string.h>
static unsigned min_length, min_digits, min_letters, min_others;
static int validate(MYSQL_LEX_STRING *username, MYSQL_LEX_STRING *password)
{
unsigned digits=0 , uppers=0 , lowers=0, others=0, length= password->length;
const char *ptr= password->str, *end= ptr + length;
if (strncmp(password->str, username->str, length) == 0)
return 1;
/* everything non-ascii is the "other" character and is good for the password */
for(; ptr < end; ptr++)
{
if (isdigit(*ptr))
digits++;
else if (isupper(*ptr))
uppers++;
else if (islower(*ptr))
lowers++;
else
others++;
}
/* remember TRUE means the password failed the validation */
return length < min_length ||
uppers < min_letters ||
lowers < min_letters ||
digits < min_digits ||
others < min_others;
}
static void fix_min_length(MYSQL_THD thd, struct st_mysql_sys_var *var,
void *var_ptr, const void *save)
{
*((unsigned int *)var_ptr)= *((unsigned int *)save);
if (min_length < min_digits + 2 * min_letters + min_others)
min_length= min_digits + 2 * min_letters + min_others;
}
static MYSQL_SYSVAR_UINT(minimal_length, min_length, PLUGIN_VAR_RQCMDARG,
"Minimal required password length", NULL, fix_min_length, 8, 0, 1000, 1);
static MYSQL_SYSVAR_UINT(digits, min_digits, PLUGIN_VAR_RQCMDARG,
"Minimal required number of digits", NULL, fix_min_length, 1, 0, 1000, 1);
static MYSQL_SYSVAR_UINT(letters_same_case, min_letters, PLUGIN_VAR_RQCMDARG,
"Minimal required number of letters of the same letter case."
"This limit is applied separately to upper-case and lower-case letters",
NULL, fix_min_length, 1, 0, 1000, 1);
static MYSQL_SYSVAR_UINT(other_characters, min_others, PLUGIN_VAR_RQCMDARG,
"Minimal required number of other (not letters or digits) characters",
NULL, fix_min_length, 1, 0, 1000, 1);
static struct st_mysql_sys_var* sysvars[]= {
MYSQL_SYSVAR(minimal_length),
MYSQL_SYSVAR(digits),
MYSQL_SYSVAR(letters_same_case),
MYSQL_SYSVAR(other_characters),
NULL
};
static struct st_mysql_password_validation info=
{
MariaDB_PASSWORD_VALIDATION_INTERFACE_VERSION,
validate
};
maria_declare_plugin(simple_password_check)
{
MariaDB_PASSWORD_VALIDATION_PLUGIN,
&info,
"simple_password_check",
"Sergei Golubchik",
"Simple password strength checks",
PLUGIN_LICENSE_GPL,
NULL,
NULL,
0x0100,
NULL,
sysvars,
"1.0",
MariaDB_PLUGIN_MATURITY_ALPHA,
}
maria_declare_plugin_end;
......@@ -35,6 +35,7 @@
#include <mysql/plugin_auth.h>
#include "lock.h" // MYSQL_LOCK_IGNORE_TIMEOUT
#include <mysql/plugin_auth.h>
#include <mysql/plugin_password_validation.h>
#include "sql_plugin_compat.h"
#define REPORT_TO_LOG 1
......@@ -82,7 +83,8 @@ const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{ C_STRING_WITH_LEN("INFORMATION SCHEMA") },
{ C_STRING_WITH_LEN("AUDIT") },
{ C_STRING_WITH_LEN("REPLICATION") },
{ C_STRING_WITH_LEN("AUTHENTICATION") }
{ C_STRING_WITH_LEN("AUTHENTICATION") },
{ C_STRING_WITH_LEN("PASSWORD VALIDATION") }
};
extern int initialize_schema_table(st_plugin_int *plugin);
......@@ -98,14 +100,14 @@ extern int finalize_audit_plugin(st_plugin_int *plugin);
*/
plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
0,ha_initialize_handlerton,0,0,initialize_schema_table,
initialize_audit_plugin, 0, 0
0, ha_initialize_handlerton, 0, 0,initialize_schema_table,
initialize_audit_plugin, 0, 0, 0
};
plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
0,ha_finalize_handlerton,0,0,finalize_schema_table,
finalize_audit_plugin, 0, 0
0, ha_finalize_handlerton, 0, 0, finalize_schema_table,
finalize_audit_plugin, 0, 0, 0
};
#ifdef HAVE_DLOPEN
......@@ -137,7 +139,8 @@ static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
MYSQL_AUDIT_INTERFACE_VERSION,
MYSQL_REPLICATION_INTERFACE_VERSION,
MIN_AUTHENTICATION_INTERFACE_VERSION
MIN_AUTHENTICATION_INTERFACE_VERSION,
MariaDB_PASSWORD_VALIDATION_INTERFACE_VERSION
};
static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
......@@ -148,7 +151,8 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
MYSQL_AUDIT_INTERFACE_VERSION,
MYSQL_REPLICATION_INTERFACE_VERSION,
MYSQL_AUTHENTICATION_INTERFACE_VERSION
MYSQL_AUTHENTICATION_INTERFACE_VERSION,
MariaDB_PASSWORD_VALIDATION_INTERFACE_VERSION
};
static struct
......@@ -1051,7 +1055,8 @@ static bool plugin_add(MEM_ROOT *tmp_root,
continue; // invalid plugin type
if (plugin->type == MYSQL_UDF_PLUGIN ||
(plugin->type == 8 && tmp.plugin_dl->mariaversion == 0))
(plugin->type == MariaDB_PASSWORD_VALIDATION_PLUGIN &&
tmp.plugin_dl->mariaversion == 0))
continue; // unsupported plugin type
if (name->str && my_strnncoll(system_charset_info,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment