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) ...@@ -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/psi/psi_abi_v2.h
${CMAKE_SOURCE_DIR}/include/mysql/client_plugin.h ${CMAKE_SOURCE_DIR}/include/mysql/client_plugin.h
${CMAKE_SOURCE_DIR}/include/mysql/plugin_auth.h ${CMAKE_SOURCE_DIR}/include/mysql/plugin_auth.h
${CMAKE_SOURCE_DIR}/include/mysql/plugin_password_validation.h
) )
ADD_CUSTOM_TARGET(abi_check ALL ADD_CUSTOM_TARGET(abi_check ALL
......
...@@ -80,17 +80,19 @@ typedef struct st_mysql_xid MYSQL_XID; ...@@ -80,17 +80,19 @@ typedef struct st_mysql_xid MYSQL_XID;
/* /*
The allowable types of plugins The allowable types of plugins
*/ */
#define MYSQL_UDF_PLUGIN 0 /* User-defined function */ #define MYSQL_UDF_PLUGIN 0 /* not implemented */
#define MYSQL_STORAGE_ENGINE_PLUGIN 1 /* Storage Engine */ #define MYSQL_STORAGE_ENGINE_PLUGIN 1
#define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */ #define MYSQL_FTPARSER_PLUGIN 2 /* Full-text parser plugin */
#define MYSQL_DAEMON_PLUGIN 3 /* The daemon/raw plugin type */ #define MYSQL_DAEMON_PLUGIN 3
#define MYSQL_INFORMATION_SCHEMA_PLUGIN 4 /* The I_S plugin type */ #define MYSQL_INFORMATION_SCHEMA_PLUGIN 4
#define MYSQL_AUDIT_PLUGIN 5 /* The Audit plugin type */ #define MYSQL_AUDIT_PLUGIN 5
#define MYSQL_REPLICATION_PLUGIN 6 /* The replication plugin type */ #define MYSQL_REPLICATION_PLUGIN 6
#define MYSQL_AUTHENTICATION_PLUGIN 7 /* The authentication plugin type */ #define MYSQL_AUTHENTICATION_PLUGIN 7
#define MYSQL_VALIDATE_PASSWORD_PLUGIN 8 /* validate password plugin type */
#define MYSQL_MAX_PLUGIN_TYPE_NUM 9 /* The number of plugin types */ #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 */ /* We use the following strings to define licenses for plugins */
#define PLUGIN_LICENSE_PROPRIETARY 0 #define PLUGIN_LICENSE_PROPRIETARY 0
#define PLUGIN_LICENSE_GPL 1 #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 @@ ...@@ -35,6 +35,7 @@
#include <mysql/plugin_auth.h> #include <mysql/plugin_auth.h>
#include "lock.h" // MYSQL_LOCK_IGNORE_TIMEOUT #include "lock.h" // MYSQL_LOCK_IGNORE_TIMEOUT
#include <mysql/plugin_auth.h> #include <mysql/plugin_auth.h>
#include <mysql/plugin_password_validation.h>
#include "sql_plugin_compat.h" #include "sql_plugin_compat.h"
#define REPORT_TO_LOG 1 #define REPORT_TO_LOG 1
...@@ -82,7 +83,8 @@ const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]= ...@@ -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("INFORMATION SCHEMA") },
{ C_STRING_WITH_LEN("AUDIT") }, { C_STRING_WITH_LEN("AUDIT") },
{ C_STRING_WITH_LEN("REPLICATION") }, { 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); extern int initialize_schema_table(st_plugin_int *plugin);
...@@ -98,14 +100,14 @@ extern int finalize_audit_plugin(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]= plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{ {
0,ha_initialize_handlerton,0,0,initialize_schema_table, 0, ha_initialize_handlerton, 0, 0,initialize_schema_table,
initialize_audit_plugin, 0, 0 initialize_audit_plugin, 0, 0, 0
}; };
plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]= plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{ {
0,ha_finalize_handlerton,0,0,finalize_schema_table, 0, ha_finalize_handlerton, 0, 0, finalize_schema_table,
finalize_audit_plugin, 0, 0 finalize_audit_plugin, 0, 0, 0
}; };
#ifdef HAVE_DLOPEN #ifdef HAVE_DLOPEN
...@@ -137,7 +139,8 @@ static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= ...@@ -137,7 +139,8 @@ static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION, MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
MYSQL_AUDIT_INTERFACE_VERSION, MYSQL_AUDIT_INTERFACE_VERSION,
MYSQL_REPLICATION_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]= 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]= ...@@ -148,7 +151,8 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION, MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION,
MYSQL_AUDIT_INTERFACE_VERSION, MYSQL_AUDIT_INTERFACE_VERSION,
MYSQL_REPLICATION_INTERFACE_VERSION, MYSQL_REPLICATION_INTERFACE_VERSION,
MYSQL_AUTHENTICATION_INTERFACE_VERSION MYSQL_AUTHENTICATION_INTERFACE_VERSION,
MariaDB_PASSWORD_VALIDATION_INTERFACE_VERSION
}; };
static struct static struct
...@@ -1051,7 +1055,8 @@ static bool plugin_add(MEM_ROOT *tmp_root, ...@@ -1051,7 +1055,8 @@ static bool plugin_add(MEM_ROOT *tmp_root,
continue; // invalid plugin type continue; // invalid plugin type
if (plugin->type == MYSQL_UDF_PLUGIN || 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 continue; // unsupported plugin type
if (name->str && my_strnncoll(system_charset_info, 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