mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
A fix for Bug#8226 "Cannot connect via shared memory":
provide created shared memory objects with proper access rights to make them usable when client and server are running under different accounts. Post review fixes.
This commit is contained in:
parent
013c2ed3be
commit
ff8017f0d3
6 changed files with 275 additions and 23 deletions
|
@ -532,6 +532,11 @@ SOURCE=.\my_wincond.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\my_windac.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
|
||||
SOURCE=.\my_winsem.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -780,6 +780,14 @@ extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
|
|||
|
||||
#ifdef __WIN__
|
||||
extern my_bool have_tcpip; /* Is set if tcpip is used */
|
||||
|
||||
/* implemented in my_windac.c */
|
||||
|
||||
int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror,
|
||||
DWORD owner_rights, DWORD everybody_rights);
|
||||
|
||||
void my_security_attr_free(SECURITY_ATTRIBUTES *sa);
|
||||
|
||||
#endif
|
||||
#ifdef __NETWARE__
|
||||
void netware_reg_user(const char *ip, const char *user,
|
||||
|
|
|
@ -53,7 +53,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
|
|||
my_net.c my_semaphore.c my_port.c my_sleep.c \
|
||||
charset.c charset-def.c my_bitmap.c my_bit.c md5.c \
|
||||
my_gethostbyname.c rijndael.c my_aes.c sha1.c \
|
||||
my_handler.c my_netware.c
|
||||
my_handler.c my_netware.c my_windac.c
|
||||
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
|
||||
thr_mutex.c thr_rwlock.c
|
||||
libmysys_a_LIBADD = @THREAD_LOBJECTS@
|
||||
|
|
224
mysys/my_windac.c
Normal file
224
mysys/my_windac.c
Normal file
|
@ -0,0 +1,224 @@
|
|||
/* Copyright (C) 2000-2005 MySQL 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 */
|
||||
|
||||
#include "mysys_priv.h"
|
||||
#include "m_string.h"
|
||||
#ifdef __WIN__
|
||||
|
||||
/* Windows NT/2000 discretionary access control utility functions. */
|
||||
|
||||
/*
|
||||
Check if the operating system is built on NT technology.
|
||||
|
||||
RETURN
|
||||
0 Windows 95/98/Me
|
||||
1 otherwise
|
||||
*/
|
||||
|
||||
static my_bool is_nt()
|
||||
{
|
||||
return GetVersion() < 0x80000000;
|
||||
}
|
||||
|
||||
/*
|
||||
Auxilary structure to store pointers to the data which we need to keep
|
||||
around while SECURITY_ATTRIBUTES is in use.
|
||||
*/
|
||||
|
||||
typedef struct st_my_security_attr
|
||||
{
|
||||
PSID everyone_sid;
|
||||
PACL dacl;
|
||||
} My_security_attr;
|
||||
|
||||
|
||||
/*
|
||||
Allocate and initialize SECURITY_ATTRIBUTES setting up access
|
||||
rights for the owner and group `Everybody'.
|
||||
|
||||
SYNOPSIS
|
||||
my_security_attr_create()
|
||||
psa [OUT] pointer to store the pointer to SA in
|
||||
perror [OUT] pointer to store error message if there was an
|
||||
error
|
||||
owner_rights [IN] access rights for the owner
|
||||
everyone_rights [IN] access rights for group Everybody
|
||||
|
||||
DESCRIPTION
|
||||
Set up the security attributes to provide clients with sufficient
|
||||
access rights to a kernel object. We need this function
|
||||
because if we simply grant all access to everybody (by installing
|
||||
a NULL DACL) a mailicious user can attempt a denial of service
|
||||
attack by taking ownership over the kernel object. Upon successful
|
||||
return `psa' contains a pointer to SECUIRITY_ATTRIBUTES that can be used
|
||||
to create kernel objects with proper access rights.
|
||||
|
||||
RETURN
|
||||
0 success, psa is 0 or points to a valid SA structure,
|
||||
perror is left intact
|
||||
!0 error, SA is set to 0, error message is stored in perror
|
||||
*/
|
||||
|
||||
int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror,
|
||||
DWORD owner_rights, DWORD everyone_rights)
|
||||
{
|
||||
/* Top-level SID authority */
|
||||
SID_IDENTIFIER_AUTHORITY world_auth= SECURITY_WORLD_SID_AUTHORITY;
|
||||
PSID everyone_sid= 0;
|
||||
HANDLE htoken= 0;
|
||||
SECURITY_ATTRIBUTES *sa= 0;
|
||||
PACL dacl= 0;
|
||||
DWORD owner_token_length, dacl_length;
|
||||
SECURITY_DESCRIPTOR *sd;
|
||||
PTOKEN_USER owner_token;
|
||||
PSID owner_sid;
|
||||
My_security_attr *attr;
|
||||
|
||||
if (! is_nt())
|
||||
{
|
||||
*psa= 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Get SID of Everyone group. Easier to retrieve all SIDs each time
|
||||
this function is called than worry about thread safety.
|
||||
*/
|
||||
if (! AllocateAndInitializeSid(&world_auth, 1, SECURITY_WORLD_RID,
|
||||
0, 0, 0, 0, 0, 0, 0, &everyone_sid))
|
||||
{
|
||||
*perror= "Failed to retrieve the SID of Everyone group";
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
Get SID of the owner. Using GetSecurityInfo this task can be done
|
||||
in just one call instead of five, but GetSecurityInfo declared in
|
||||
aclapi.h, so I hesitate to use it.
|
||||
SIC: OpenThreadToken works only if there is an active impersonation
|
||||
token, hence OpenProcessToken is used.
|
||||
*/
|
||||
if (! OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken))
|
||||
{
|
||||
*perror= "Failed to retrieve thread access token";
|
||||
goto error;
|
||||
}
|
||||
GetTokenInformation(htoken, TokenUser, 0, 0, &owner_token_length);
|
||||
|
||||
if (! my_multi_malloc(MYF(MY_WME),
|
||||
&sa, ALIGN_SIZE(sizeof(SECURITY_ATTRIBUTES)) +
|
||||
sizeof(My_security_attr),
|
||||
&sd, sizeof(SECURITY_DESCRIPTOR),
|
||||
&owner_token, owner_token_length,
|
||||
0))
|
||||
{
|
||||
*perror= "Failed to allocate memory for SECURITY_ATTRIBUTES";
|
||||
goto error;
|
||||
}
|
||||
bzero(owner_token, owner_token_length);
|
||||
if (! GetTokenInformation(htoken, TokenUser, owner_token,
|
||||
owner_token_length, &owner_token_length))
|
||||
{
|
||||
*perror= "GetTokenInformation failed";
|
||||
goto error;
|
||||
}
|
||||
owner_sid= owner_token->User.Sid;
|
||||
|
||||
if (! IsValidSid(owner_sid))
|
||||
{
|
||||
*perror= "IsValidSid failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Calculate the amount of memory that must be allocated for the DACL */
|
||||
dacl_length= sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)) * 2 +
|
||||
GetLengthSid(everyone_sid) + GetLengthSid(owner_sid);
|
||||
|
||||
/* Create an ACL */
|
||||
if (! (dacl= (PACL) my_malloc(dacl_length, MYF(MY_ZEROFILL|MY_WME))))
|
||||
{
|
||||
*perror= "Failed to allocate memory for DACL";
|
||||
goto error;
|
||||
}
|
||||
if (! InitializeAcl(dacl, dacl_length, ACL_REVISION))
|
||||
{
|
||||
*perror= "Failed to initialize DACL";
|
||||
goto error;
|
||||
}
|
||||
if (! AddAccessAllowedAce(dacl, ACL_REVISION, everyone_rights, everyone_sid))
|
||||
{
|
||||
*perror= "Failed to set up DACL";
|
||||
goto error;
|
||||
}
|
||||
if (! AddAccessAllowedAce(dacl, ACL_REVISION, owner_rights, owner_sid))
|
||||
{
|
||||
*perror= "Failed to set up DACL";
|
||||
goto error;
|
||||
}
|
||||
if (! InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION))
|
||||
{
|
||||
*perror= "Could not initialize security descriptor";
|
||||
goto error;
|
||||
}
|
||||
if (! SetSecurityDescriptorDacl(sd, TRUE, dacl, FALSE))
|
||||
{
|
||||
*perror= "Failed to install DACL";
|
||||
goto error;
|
||||
}
|
||||
|
||||
sa->nLength= sizeof(*sa);
|
||||
sa->bInheritHandle= TRUE;
|
||||
sa->lpSecurityDescriptor= sd;
|
||||
/* Save pointers to everyone_sid and dacl to be able to clean them up */
|
||||
attr= (My_security_attr*) (((char*) sa) + ALIGN_SIZE(sizeof(*sa)));
|
||||
attr->everyone_sid= everyone_sid;
|
||||
attr->dacl= dacl;
|
||||
*psa= sa;
|
||||
|
||||
CloseHandle(htoken);
|
||||
return 0;
|
||||
error:
|
||||
if (everyone_sid)
|
||||
FreeSid(everyone_sid);
|
||||
if (htoken)
|
||||
CloseHandle(htoken);
|
||||
my_free((gptr) sa, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free((gptr) dacl, MYF(MY_ALLOW_ZERO_PTR));
|
||||
*psa= 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Cleanup security attributes freeing used memory.
|
||||
|
||||
SYNOPSIS
|
||||
my_security_attr_free()
|
||||
sa security attributes
|
||||
*/
|
||||
|
||||
void my_security_attr_free(SECURITY_ATTRIBUTES *sa)
|
||||
{
|
||||
if (sa)
|
||||
{
|
||||
My_security_attr *attr= (My_security_attr*)
|
||||
(((char*)sa) + ALIGN_SIZE(sizeof(*sa)));
|
||||
FreeSid(attr->everyone_sid);
|
||||
my_free((gptr) attr->dacl, MYF(0));
|
||||
my_free((gptr) sa, MYF(0));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __WIN__ */
|
|
@ -408,6 +408,7 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
|
|||
char *suffix_pos;
|
||||
DWORD error_allow = 0;
|
||||
DWORD error_code = 0;
|
||||
DWORD event_access_rights= SYNCHRONIZE | EVENT_MODIFY_STATE;
|
||||
char *shared_memory_base_name = mysql->options.shared_memory_base_name;
|
||||
|
||||
/*
|
||||
|
@ -419,13 +420,13 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
|
|||
*/
|
||||
suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS);
|
||||
strmov(suffix_pos, "CONNECT_REQUEST");
|
||||
if (!(event_connect_request= OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)))
|
||||
if (!(event_connect_request= OpenEvent(event_access_rights, FALSE, tmp)))
|
||||
{
|
||||
error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR;
|
||||
goto err;
|
||||
}
|
||||
strmov(suffix_pos, "CONNECT_ANSWER");
|
||||
if (!(event_connect_answer= OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)))
|
||||
if (!(event_connect_answer= OpenEvent(event_access_rights,FALSE,tmp)))
|
||||
{
|
||||
error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR;
|
||||
goto err;
|
||||
|
@ -487,35 +488,35 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
|
|||
}
|
||||
|
||||
strmov(suffix_pos, "SERVER_WROTE");
|
||||
if ((event_server_wrote = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
|
||||
if ((event_server_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
|
||||
{
|
||||
error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
strmov(suffix_pos, "SERVER_READ");
|
||||
if ((event_server_read = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
|
||||
if ((event_server_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
|
||||
{
|
||||
error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
strmov(suffix_pos, "CLIENT_WROTE");
|
||||
if ((event_client_wrote = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
|
||||
if ((event_client_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
|
||||
{
|
||||
error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
strmov(suffix_pos, "CLIENT_READ");
|
||||
if ((event_client_read = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
|
||||
if ((event_client_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
|
||||
{
|
||||
error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
strmov(suffix_pos, "CONNECTION_CLOSED");
|
||||
if ((event_conn_closed = OpenEvent(EVENT_ALL_ACCESS,FALSE,tmp)) == NULL)
|
||||
if ((event_conn_closed = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
|
||||
{
|
||||
error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
|
||||
goto err2;
|
||||
|
|
|
@ -3817,10 +3817,19 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
|
|||
char *suffix_pos;
|
||||
char connect_number_char[22], *p;
|
||||
const char *errmsg= 0;
|
||||
SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
|
||||
my_thread_init();
|
||||
DBUG_ENTER("handle_connections_shared_memorys");
|
||||
DBUG_PRINT("general",("Waiting for allocated shared memory."));
|
||||
|
||||
if (my_security_attr_create(&sa_event, &errmsg,
|
||||
GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE))
|
||||
goto error;
|
||||
|
||||
if (my_security_attr_create(&sa_mapping, &errmsg,
|
||||
GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
The name of event and file-mapping events create agree next rule:
|
||||
shared_memory_base_name+unique_part
|
||||
|
@ -3830,22 +3839,22 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
|
|||
*/
|
||||
suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
|
||||
strmov(suffix_pos, "CONNECT_REQUEST");
|
||||
if ((smem_event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
|
||||
if ((smem_event_connect_request= CreateEvent(sa_event,
|
||||
FALSE, FALSE, tmp)) == 0)
|
||||
{
|
||||
errmsg= "Could not create request event";
|
||||
goto error;
|
||||
}
|
||||
strmov(suffix_pos, "CONNECT_ANSWER");
|
||||
if ((event_connect_answer= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
|
||||
if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
|
||||
{
|
||||
errmsg="Could not create answer event";
|
||||
goto error;
|
||||
}
|
||||
strmov(suffix_pos, "CONNECT_DATA");
|
||||
if ((handle_connect_file_map= CreateFileMapping(INVALID_HANDLE_VALUE,0,
|
||||
PAGE_READWRITE,
|
||||
0,sizeof(connect_number),
|
||||
tmp)) == 0)
|
||||
if ((handle_connect_file_map=
|
||||
CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
|
||||
PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
|
||||
{
|
||||
errmsg= "Could not create file mapping";
|
||||
goto error;
|
||||
|
@ -3890,10 +3899,9 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
|
|||
suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
|
||||
"_",NullS);
|
||||
strmov(suffix_pos, "DATA");
|
||||
if ((handle_client_file_map= CreateFileMapping(INVALID_HANDLE_VALUE,0,
|
||||
PAGE_READWRITE,0,
|
||||
smem_buffer_length,
|
||||
tmp)) == 0)
|
||||
if ((handle_client_file_map=
|
||||
CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
|
||||
PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
|
||||
{
|
||||
errmsg= "Could not create file mapping";
|
||||
goto errorconn;
|
||||
|
@ -3906,31 +3914,33 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
|
|||
goto errorconn;
|
||||
}
|
||||
strmov(suffix_pos, "CLIENT_WROTE");
|
||||
if ((event_client_wrote= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
|
||||
if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
|
||||
{
|
||||
errmsg= "Could not create client write event";
|
||||
goto errorconn;
|
||||
}
|
||||
strmov(suffix_pos, "CLIENT_READ");
|
||||
if ((event_client_read= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
|
||||
if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
|
||||
{
|
||||
errmsg= "Could not create client read event";
|
||||
goto errorconn;
|
||||
}
|
||||
strmov(suffix_pos, "SERVER_READ");
|
||||
if ((event_server_read= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
|
||||
if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
|
||||
{
|
||||
errmsg= "Could not create server read event";
|
||||
goto errorconn;
|
||||
}
|
||||
strmov(suffix_pos, "SERVER_WROTE");
|
||||
if ((event_server_wrote= CreateEvent(0, FALSE, FALSE, tmp)) == 0)
|
||||
if ((event_server_wrote= CreateEvent(sa_event,
|
||||
FALSE, FALSE, tmp)) == 0)
|
||||
{
|
||||
errmsg= "Could not create server write event";
|
||||
goto errorconn;
|
||||
}
|
||||
strmov(suffix_pos, "CONNECTION_CLOSED");
|
||||
if ((event_conn_closed= CreateEvent(0, TRUE , FALSE, tmp)) == 0)
|
||||
if ((event_conn_closed= CreateEvent(sa_event,
|
||||
TRUE, FALSE, tmp)) == 0)
|
||||
{
|
||||
errmsg= "Could not create closed connection event";
|
||||
goto errorconn;
|
||||
|
@ -3980,6 +3990,8 @@ errorconn:
|
|||
NullS);
|
||||
sql_perror(buff);
|
||||
}
|
||||
my_security_attr_free(sa_event);
|
||||
my_security_attr_free(sa_mapping);
|
||||
if (handle_client_file_map)
|
||||
CloseHandle(handle_client_file_map);
|
||||
if (handle_client_map)
|
||||
|
@ -4005,6 +4017,8 @@ error:
|
|||
strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
|
||||
sql_perror(buff);
|
||||
}
|
||||
my_security_attr_free(sa_event);
|
||||
my_security_attr_free(sa_mapping);
|
||||
if (handle_connect_map) UnmapViewOfFile(handle_connect_map);
|
||||
if (handle_connect_file_map) CloseHandle(handle_connect_file_map);
|
||||
if (event_connect_answer) CloseHandle(event_connect_answer);
|
||||
|
|
Loading…
Add table
Reference in a new issue