move check_user/set_user from mysqld.cc to mysys

This commit is contained in:
Sergei Golubchik 2016-12-20 15:17:59 +01:00
parent 706fb790bc
commit c8e49f2f57
4 changed files with 98 additions and 74 deletions

View File

@ -602,8 +602,12 @@ extern void *my_memmem(const void *haystack, size_t haystacklen,
#ifdef _WIN32 #ifdef _WIN32
extern int my_access(const char *path, int amode); extern int my_access(const char *path, int amode);
#define my_check_user(A,B) (NULL)
#define my_set_user(A,B,C) (0)
#else #else
#define my_access access #define my_access access
struct passwd *my_check_user(const char *user, myf MyFlags);
int my_set_user(const char *user, struct passwd *user_info, myf MyFlags);
#endif #endif
extern int check_if_legal_filename(const char *path); extern int check_if_legal_filename(const char *path);

View File

@ -34,7 +34,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c
rijndael.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c rijndael.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c
thr_rwlock.c tree.c typelib.c base64.c my_memmem.c my_getpagesize.c thr_rwlock.c tree.c typelib.c base64.c my_memmem.c my_getpagesize.c
lf_alloc-pin.c lf_dynarray.c lf_hash.c lf_alloc-pin.c lf_dynarray.c lf_hash.c
safemalloc.c my_new.cc safemalloc.c my_new.cc
my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c
my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c
my_rdtsc.c my_context.c file_logger.c) my_rdtsc.c my_context.c file_logger.c)
@ -44,7 +44,7 @@ IF (WIN32)
ENDIF() ENDIF()
IF(UNIX) IF(UNIX)
SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_addr_resolve.c) SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_addr_resolve.c my_setuser.c)
ENDIF() ENDIF()
IF(HAVE_ALARM) IF(HAVE_ALARM)

81
mysys/my_setuser.c Normal file
View File

@ -0,0 +1,81 @@
#include <my_global.h>
#include <m_string.h>
#include <my_sys.h>
#include <my_pthread.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_GRP_H
#include <grp.h>
#endif
struct passwd *my_check_user(const char *user, myf MyFlags)
{
struct passwd *user_info;
uid_t user_id= geteuid();
DBUG_ENTER("my_check_user");
// Don't bother if we aren't superuser
if (user_id)
{
if (user)
{
/* Don't give a warning, if real user is same as given with --user */
user_info= getpwnam(user);
if (!user_info || user_id != user_info->pw_uid)
{
my_errno= EPERM;
if (MyFlags & MY_WME)
my_printf_error(my_errno, "One can only use the --user switch if "
"running as root", MYF(ME_JUST_WARNING|ME_NOREFRESH));
}
}
DBUG_RETURN(NULL);
}
if (!user)
{
if (MyFlags & MY_FAE)
{
my_errno= EINVAL;
my_printf_error(my_errno, "Please consult the Knowledge Base to find "
"out how to run mysqld as root!", MYF(ME_NOREFRESH));
}
DBUG_RETURN(NULL);
}
if (!strcmp(user,"root"))
DBUG_RETURN(NULL);
if (!(user_info= getpwnam(user)))
{
// Allow a numeric uid to be used
int err= 0;
user_id= my_strtoll10(user, NULL, &err);
if (err || !(user_info= getpwuid(user_id)))
{
my_errno= EINVAL;
my_printf_error(my_errno, "Can't change to run as user '%s'. Please "
"check that the user exists!", MYF(ME_NOREFRESH), user);
DBUG_RETURN(NULL);
}
}
DBUG_ASSERT(user_info);
DBUG_RETURN(user_info);
}
int my_set_user(const char *user, struct passwd *user_info, myf MyFlags)
{
DBUG_ENTER("my_set_user");
DBUG_ASSERT(user_info != 0);
#ifdef HAVE_INITGROUPS
initgroups(user, user_info->pw_gid);
#endif
if (setgid(user_info->pw_gid) == -1 || setuid(user_info->pw_uid) == -1)
{
my_errno= errno;
if (MyFlags & MY_WME)
my_error(my_errno, MYF(ME_NOREFRESH));
DBUG_RETURN(my_errno);
}
DBUG_RETURN(0);
}

View File

@ -121,10 +121,7 @@ extern "C" { // Because of SCO 3.2V4.2
#include <sysent.h> #include <sysent.h>
#endif #endif
#ifdef HAVE_PWD_H #ifdef HAVE_PWD_H
#include <pwd.h> // For getpwent #include <pwd.h> // For struct passwd
#endif
#ifdef HAVE_GRP_H
#include <grp.h>
#endif #endif
#include <my_net.h> #include <my_net.h>
@ -455,9 +452,7 @@ ulong opt_binlog_rows_event_max_size;
my_bool opt_master_verify_checksum= 0; my_bool opt_master_verify_checksum= 0;
my_bool opt_slave_sql_verify_checksum= 1; my_bool opt_slave_sql_verify_checksum= 1;
const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS}; const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
#ifdef HAVE_INITGROUPS
volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */ volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
#endif
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options; uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
uint mysqld_extra_port; uint mysqld_extra_port;
uint mysqld_port_timeout; uint mysqld_port_timeout;
@ -2001,59 +1996,18 @@ static void set_ports()
static struct passwd *check_user(const char *user) static struct passwd *check_user(const char *user)
{ {
#if !defined(__WIN__) myf flags= 0;
struct passwd *tmp_user_info; if (global_system_variables.log_warnings)
uid_t user_id= geteuid(); flags|= MY_WME;
if (!opt_bootstrap && !opt_help)
flags|= MY_FAE;
// Don't bother if we aren't superuser struct passwd *tmp_user_info= my_check_user(user, MYF(flags));
if (user_id)
{
if (user)
{
/* Don't give a warning, if real user is same as given with --user */
/* purecov: begin tested */
tmp_user_info= getpwnam(user);
if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
global_system_variables.log_warnings)
sql_print_warning(
"One can only use the --user switch if running as root\n");
/* purecov: end */
}
return NULL;
}
if (!user)
{
if (!opt_bootstrap && !opt_help)
{
sql_print_error("Fatal error: Please consult the Knowledge Base "
"to find out how to run mysqld as root!\n");
unireg_abort(1);
}
return NULL;
}
/* purecov: begin tested */
if (!strcmp(user,"root"))
return NULL; // Avoid problem with dynamic libraries
if (!(tmp_user_info= getpwnam(user))) if (!tmp_user_info && my_errno==EINVAL && (flags & MY_FAE))
{ unireg_abort(1);
// Allow a numeric uid to be used
const char *pos;
for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
if (*pos) // Not numeric id
goto err;
if (!(tmp_user_info= getpwuid(atoi(user))))
goto err;
}
return tmp_user_info; return tmp_user_info;
/* purecov: end */
err:
sql_print_error("Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
unireg_abort(1);
#endif
return NULL;
} }
static inline void allow_coredumps() static inline void allow_coredumps()
@ -2070,10 +2024,6 @@ static inline void allow_coredumps()
static void set_user(const char *user, struct passwd *user_info_arg) static void set_user(const char *user, struct passwd *user_info_arg)
{ {
/* purecov: begin tested */
#if !defined(__WIN__)
DBUG_ASSERT(user_info_arg != 0);
#ifdef HAVE_INITGROUPS
/* /*
We can get a SIGSEGV when calling initgroups() on some systems when NSS We can get a SIGSEGV when calling initgroups() on some systems when NSS
is configured to use LDAP and the server is statically linked. We set is configured to use LDAP and the server is statically linked. We set
@ -2081,22 +2031,11 @@ static void set_user(const char *user, struct passwd *user_info_arg)
output a specific message to help the user resolve this problem. output a specific message to help the user resolve this problem.
*/ */
calling_initgroups= 1; calling_initgroups= 1;
initgroups((char*) user, user_info_arg->pw_gid); int res= my_set_user(user, user_info_arg, MYF(MY_WME));
calling_initgroups= 0; calling_initgroups= 0;
#endif if (res)
if (setgid(user_info_arg->pw_gid) == -1)
{
sql_perror("setgid");
unireg_abort(1); unireg_abort(1);
}
if (setuid(user_info_arg->pw_uid) == -1)
{
sql_perror("setuid");
unireg_abort(1);
}
allow_coredumps(); allow_coredumps();
#endif
/* purecov: end */
} }