mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 19:11:46 +01:00
07d8be4544
Fixed some possible fatal wrong arguments to printf() style functions Initialized some not initialized variables Fixed bug in stored procedure and continue handlers (Fixes Bug#22150) include/mysql/plugin.h: Remove compiler warning mysql-test/mysql-test-run.pl: Ensure that --extern works on a clean tree (when 'var' directory doesn't exists) server-tools/instance-manager/commands.cc: Fixed possible use of unitialized variable server-tools/instance-manager/guardian.cc: Fixed wrong arguments to log_info() that could cause crashes server-tools/instance-manager/instance.cc: Fixed wrong arguments to log_info() and log_error() that could cause crashes server-tools/instance-manager/instance_options.cc: Fixed wrong arguments to log_error() that could cause crashes server-tools/instance-manager/mysql_connection.cc: Fixed wrong arguments to log_info() server-tools/instance-manager/parse.cc: Fixed possible use of unitialized variable server-tools/instance-manager/user_map.cc: Fixed wrong arguments to log_error() that could cause crashes sql/Makefile.am: Fix for bison 1.875 (It write an __attribute__() tag that was causing compiler failures) sql/ha_ndbcluster.cc: Fixed wrong snprintf() arguments Remoed not used variables sql/ha_ndbcluster_binlog.cc: Fixed compiler warning (unsigned/signed comparision) sql/handler.cc: Fixed wrong parameter to hton->binlog_func() sql/item_cmpfunc.cc: Removed compiler warnings sql/item_timefunc.cc: Removed compiler warnings sql/log.cc: fixed wrong argument to snprintf() sql/mysqld.cc: Removed compiler warnings Fixed wrong arguments to printf() sql/partition_info.cc: Removed compiler warnings sql/protocol.cc: reset is_fatal_error for stored procedures (Fix for Bug#22150) sql/sp_head.cc: More DBUG information Reset is_fatal_error in case of continue handler. (Fix for Bug#22150) sql/sql_base.cc: Removed compiler warnings sql/sql_class.h: More DBUG information sql/sql_insert.cc: Removed compiler warnings Initialize not initialized variable (fatal bug) sql/sql_parse.cc: Added DBUG_ASSERT to detect if stored procedure code returns with a wrong state Removed compiler warning sql/sql_plugin.cc: Fied wrong aruguments to printf() (Fatal bug) sql/sql_select.cc: Initailize not initialized variable. Remove compiler warnings Fixed wrong argument to printf() (Possible fatal error) sql/sql_view.cc: Removed compiler warnings sql/table.cc: Fixed wrong argument to printf() (Possible fatal)
396 lines
9.1 KiB
C++
396 lines
9.1 KiB
C++
/* Copyright (C) 2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
|
|
|
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; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include "user_map.h"
|
|
#include "exit_codes.h"
|
|
#include "log.h"
|
|
#include "portability.h"
|
|
|
|
User::User(const LEX_STRING *user_name_arg, const char *password)
|
|
{
|
|
user_length= strmake(user, user_name_arg->str, USERNAME_LENGTH + 1) - user;
|
|
|
|
set_password(password);
|
|
}
|
|
|
|
int User::init(const char *line)
|
|
{
|
|
const char *name_begin, *name_end, *password;
|
|
int password_length;
|
|
|
|
if (line[0] == '\'' || line[0] == '"')
|
|
{
|
|
name_begin= line + 1;
|
|
name_end= strchr(name_begin, line[0]);
|
|
if (name_end == 0 || name_end[1] != ':')
|
|
{
|
|
log_info("Error: invalid format (unmatched quote) of user line (%s).",
|
|
(const char *) line);
|
|
return 1;
|
|
}
|
|
password= name_end + 2;
|
|
}
|
|
else
|
|
{
|
|
name_begin= line;
|
|
name_end= strchr(name_begin, ':');
|
|
if (name_end == 0)
|
|
{
|
|
log_info("Error: invalid format (no delimiter) of user line (%s).",
|
|
(const char *) line);
|
|
return 1;
|
|
}
|
|
password= name_end + 1;
|
|
}
|
|
|
|
user_length= name_end - name_begin;
|
|
if (user_length > USERNAME_LENGTH)
|
|
{
|
|
log_info("Error: user name is too long (%d). Max length: %d. "
|
|
"User line: '%s'.",
|
|
(int) user_length,
|
|
(int) USERNAME_LENGTH,
|
|
(const char *) line);
|
|
return 1;
|
|
}
|
|
|
|
password_length= strlen(password);
|
|
if (password_length > SCRAMBLED_PASSWORD_CHAR_LENGTH)
|
|
{
|
|
log_info("Error: password is too long (%d). Max length: %d. User line: '%s'.",
|
|
(int) password_length,
|
|
(int) SCRAMBLED_PASSWORD_CHAR_LENGTH,
|
|
line);
|
|
return 1;
|
|
}
|
|
|
|
memcpy(user, name_begin, user_length);
|
|
user[user_length]= 0;
|
|
|
|
memcpy(scrambled_password, password, password_length);
|
|
scrambled_password[password_length]= 0;
|
|
|
|
get_salt_from_password(salt, password);
|
|
|
|
log_info("loaded user '%s'.", user);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
C_MODE_START
|
|
|
|
static byte* get_user_key(const byte* u, uint* len,
|
|
my_bool __attribute__((unused)) t)
|
|
{
|
|
const User *user= (const User *) u;
|
|
*len= user->user_length;
|
|
return (byte *) user->user;
|
|
}
|
|
|
|
static void delete_user(void *u)
|
|
{
|
|
User *user= (User *) u;
|
|
delete user;
|
|
}
|
|
|
|
C_MODE_END
|
|
|
|
|
|
void User_map::Iterator::reset()
|
|
{
|
|
cur_idx= 0;
|
|
}
|
|
|
|
|
|
User *User_map::Iterator::next()
|
|
{
|
|
if (cur_idx < user_map->hash.records)
|
|
return (User *) hash_element(&user_map->hash, cur_idx++);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
int User_map::init()
|
|
{
|
|
enum { START_HASH_SIZE= 16 };
|
|
if (hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
|
|
get_user_key, delete_user, 0))
|
|
return 1;
|
|
|
|
initialized= TRUE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
User_map::User_map()
|
|
:initialized(FALSE)
|
|
{
|
|
}
|
|
|
|
|
|
User_map::~User_map()
|
|
{
|
|
if (initialized)
|
|
hash_free(&hash);
|
|
}
|
|
|
|
|
|
/*
|
|
Load password database.
|
|
|
|
SYNOPSYS
|
|
load()
|
|
password_file_name [IN] password file path
|
|
err_msg [OUT] error message
|
|
|
|
DESCRIPTION
|
|
Load all users from the password file. Must be called once right after
|
|
construction. In case of failure, puts error message to the log file and
|
|
returns specific error code.
|
|
|
|
RETURN
|
|
0 on success
|
|
!0 on error
|
|
*/
|
|
|
|
int User_map::load(const char *password_file_name, const char **err_msg)
|
|
{
|
|
static const int ERR_MSG_BUF_SIZE = 255;
|
|
static char err_msg_buf[ERR_MSG_BUF_SIZE];
|
|
|
|
FILE *file;
|
|
char line[USERNAME_LENGTH + SCRAMBLED_PASSWORD_CHAR_LENGTH +
|
|
2 + /* for possible quotes */
|
|
1 + /* for ':' */
|
|
2 + /* for newline */
|
|
1]; /* for trailing zero */
|
|
User *user;
|
|
int rc= 1;
|
|
|
|
if (my_access(password_file_name, F_OK) != 0)
|
|
{
|
|
if (err_msg)
|
|
{
|
|
snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
|
|
"password file (%s) does not exist",
|
|
(const char *) password_file_name);
|
|
*err_msg= err_msg_buf;
|
|
}
|
|
|
|
return ERR_PASSWORD_FILE_DOES_NOT_EXIST;
|
|
}
|
|
|
|
if ((file= my_fopen(password_file_name, O_RDONLY | O_BINARY, MYF(0))) == 0)
|
|
{
|
|
if (err_msg)
|
|
{
|
|
snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
|
|
"can not open password file (%s): %s",
|
|
(const char *) password_file_name,
|
|
(const char *) strerror(errno));
|
|
*err_msg= err_msg_buf;
|
|
}
|
|
|
|
return ERR_IO_ERROR;
|
|
}
|
|
|
|
log_info("loading the password database...");
|
|
|
|
while (fgets(line, sizeof(line), file))
|
|
{
|
|
char *user_line= line;
|
|
|
|
/*
|
|
We need to skip EOL-symbols also from the beginning of the line, because
|
|
if the previous line was ended by \n\r sequence, we get \r in our line.
|
|
*/
|
|
|
|
while (user_line[0] == '\r' || user_line[0] == '\n')
|
|
++user_line;
|
|
|
|
/* Skip EOL-symbols in the end of the line. */
|
|
|
|
{
|
|
char *ptr;
|
|
|
|
if ((ptr= strchr(user_line, '\n')))
|
|
*ptr= 0;
|
|
|
|
if ((ptr= strchr(user_line, '\r')))
|
|
*ptr= 0;
|
|
}
|
|
|
|
/* skip comments and empty lines */
|
|
if (!user_line[0] || user_line[0] == '#')
|
|
continue;
|
|
|
|
if ((user= new User) == 0)
|
|
{
|
|
my_fclose(file, MYF(0));
|
|
|
|
if (err_msg)
|
|
{
|
|
snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
|
|
"out of memory while parsing password file (%s)",
|
|
(const char *) password_file_name);
|
|
*err_msg= err_msg_buf;
|
|
}
|
|
|
|
return ERR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if (user->init(user_line))
|
|
{
|
|
delete user;
|
|
my_fclose(file, MYF(0));
|
|
|
|
if (err_msg)
|
|
{
|
|
snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
|
|
"password file (%s) corrupted",
|
|
(const char *) password_file_name);
|
|
*err_msg= err_msg_buf;
|
|
}
|
|
|
|
return ERR_PASSWORD_FILE_CORRUPTED;
|
|
}
|
|
|
|
if (my_hash_insert(&hash, (byte *) user))
|
|
{
|
|
delete user;
|
|
my_fclose(file, MYF(0));
|
|
|
|
if (err_msg)
|
|
{
|
|
snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
|
|
"out of memory while parsing password file (%s)",
|
|
(const char *) password_file_name);
|
|
*err_msg= err_msg_buf;
|
|
}
|
|
|
|
return ERR_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
|
|
log_info("the password database loaded successfully.");
|
|
|
|
my_fclose(file, MYF(0));
|
|
|
|
if (err_msg)
|
|
*err_msg= NULL;
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
|
|
int User_map::save(const char *password_file_name, const char **err_msg)
|
|
{
|
|
static const int ERR_MSG_BUF_SIZE = 255;
|
|
static char err_msg_buf[ERR_MSG_BUF_SIZE];
|
|
|
|
FILE *file;
|
|
|
|
if ((file= my_fopen(password_file_name, O_WRONLY | O_TRUNC | O_BINARY,
|
|
MYF(0))) == 0)
|
|
{
|
|
if (err_msg)
|
|
{
|
|
snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
|
|
"can not open password file (%s) for writing: %s",
|
|
(const char *) password_file_name,
|
|
(const char *) strerror(errno));
|
|
*err_msg= err_msg_buf;
|
|
}
|
|
|
|
return ERR_IO_ERROR;
|
|
}
|
|
|
|
{
|
|
User_map::Iterator it(this);
|
|
User *user;
|
|
|
|
while ((user= it.next()))
|
|
{
|
|
if (fprintf(file, "%s:%s\n", (const char *) user->user,
|
|
(const char *) user->scrambled_password) < 0)
|
|
{
|
|
if (err_msg)
|
|
{
|
|
snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
|
|
"can not write to password file (%s): %s",
|
|
(const char *) password_file_name,
|
|
(const char *) strerror(errno));
|
|
*err_msg= err_msg_buf;
|
|
}
|
|
|
|
my_fclose(file, MYF(0));
|
|
|
|
return ERR_IO_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
my_fclose(file, MYF(0));
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
Check if user exists and password is correct
|
|
RETURN VALUE
|
|
0 - user found and password OK
|
|
1 - password mismatch
|
|
2 - user not found
|
|
*/
|
|
|
|
int User_map::authenticate(const LEX_STRING *user_name,
|
|
const char *scrambled_password,
|
|
const char *scramble) const
|
|
{
|
|
const User *user= find_user(user_name);
|
|
return user ? check_scramble(scrambled_password, scramble, user->salt) : 2;
|
|
}
|
|
|
|
|
|
User *User_map::find_user(const LEX_STRING *user_name)
|
|
{
|
|
return (User*) hash_search(&hash, (byte*) user_name->str, user_name->length);
|
|
}
|
|
|
|
const User *User_map::find_user(const LEX_STRING *user_name) const
|
|
{
|
|
return const_cast<User_map *> (this)->find_user(user_name);
|
|
}
|
|
|
|
|
|
bool User_map::add_user(User *user)
|
|
{
|
|
return my_hash_insert(&hash, (byte*) user) == 0 ? FALSE : TRUE;
|
|
}
|
|
|
|
|
|
bool User_map::remove_user(User *user)
|
|
{
|
|
return hash_delete(&hash, (byte*) user) == 0 ? FALSE : TRUE;
|
|
}
|