MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_windac.c
1 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include "mysys_priv.h"
17 #include "m_string.h"
18 #ifdef __WIN__
19 
20 /* Windows NT/2000 discretionary access control utility functions. */
21 
22 /*
23  Check if the operating system is built on NT technology.
24 
25  RETURN
26  0 Windows 95/98/Me
27  1 otherwise
28 */
29 
30 static my_bool is_nt()
31 {
32  return GetVersion() < 0x80000000;
33 }
34 
35 /*
36  Auxilary structure to store pointers to the data which we need to keep
37  around while SECURITY_ATTRIBUTES is in use.
38 */
39 
40 typedef struct st_my_security_attr
41 {
42  PSID everyone_sid;
43  PACL dacl;
44 } My_security_attr;
45 
46 
47 /*
48  Allocate and initialize SECURITY_ATTRIBUTES setting up access
49  rights for the owner and group `Everybody'.
50 
51  SYNOPSIS
52  my_security_attr_create()
53  psa [OUT] pointer to store the pointer to SA in
54  perror [OUT] pointer to store error message if there was an
55  error
56  owner_rights [IN] access rights for the owner
57  everyone_rights [IN] access rights for group Everybody
58 
59  DESCRIPTION
60  Set up the security attributes to provide clients with sufficient
61  access rights to a kernel object. We need this function
62  because if we simply grant all access to everybody (by installing
63  a NULL DACL) a mailicious user can attempt a denial of service
64  attack by taking ownership over the kernel object. Upon successful
65  return `psa' contains a pointer to SECUIRITY_ATTRIBUTES that can be used
66  to create kernel objects with proper access rights.
67 
68  RETURN
69  0 success, psa is 0 or points to a valid SA structure,
70  perror is left intact
71  !0 error, SA is set to 0, error message is stored in perror
72 */
73 
74 int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror,
75  DWORD owner_rights, DWORD everyone_rights)
76 {
77  /* Top-level SID authority */
78  SID_IDENTIFIER_AUTHORITY world_auth= SECURITY_WORLD_SID_AUTHORITY;
79  PSID everyone_sid= 0;
80  HANDLE htoken= 0;
81  SECURITY_ATTRIBUTES *sa= 0;
82  PACL dacl= 0;
83  DWORD owner_token_length, dacl_length;
84  SECURITY_DESCRIPTOR *sd;
85  PTOKEN_USER owner_token;
86  PSID owner_sid;
87  My_security_attr *attr;
88 
89  if (! is_nt())
90  {
91  *psa= 0;
92  return 0;
93  }
94 
95  /*
96  Get SID of Everyone group. Easier to retrieve all SIDs each time
97  this function is called than worry about thread safety.
98  */
99  if (! AllocateAndInitializeSid(&world_auth, 1, SECURITY_WORLD_RID,
100  0, 0, 0, 0, 0, 0, 0, &everyone_sid))
101  {
102  *perror= "Failed to retrieve the SID of Everyone group";
103  goto error;
104  }
105 
106  /*
107  Get SID of the owner. Using GetSecurityInfo this task can be done
108  in just one call instead of five, but GetSecurityInfo declared in
109  aclapi.h, so I hesitate to use it.
110  SIC: OpenThreadToken works only if there is an active impersonation
111  token, hence OpenProcessToken is used.
112  */
113  if (! OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken))
114  {
115  *perror= "Failed to retrieve thread access token";
116  goto error;
117  }
118  GetTokenInformation(htoken, TokenUser, 0, 0, &owner_token_length);
119 
120  if (! my_multi_malloc(MYF(MY_WME),
121  &sa, ALIGN_SIZE(sizeof(SECURITY_ATTRIBUTES)) +
122  sizeof(My_security_attr),
123  &sd, sizeof(SECURITY_DESCRIPTOR),
124  &owner_token, owner_token_length,
125  0))
126  {
127  *perror= "Failed to allocate memory for SECURITY_ATTRIBUTES";
128  goto error;
129  }
130  memset(owner_token, 0, owner_token_length);
131  if (! GetTokenInformation(htoken, TokenUser, owner_token,
132  owner_token_length, &owner_token_length))
133  {
134  *perror= "GetTokenInformation failed";
135  goto error;
136  }
137  owner_sid= owner_token->User.Sid;
138 
139  if (! IsValidSid(owner_sid))
140  {
141  *perror= "IsValidSid failed";
142  goto error;
143  }
144 
145  /* Calculate the amount of memory that must be allocated for the DACL */
146  dacl_length= sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)) * 2 +
147  GetLengthSid(everyone_sid) + GetLengthSid(owner_sid);
148 
149  /* Create an ACL */
150  if (! (dacl= (PACL) my_malloc(dacl_length, MYF(MY_ZEROFILL|MY_WME))))
151  {
152  *perror= "Failed to allocate memory for DACL";
153  goto error;
154  }
155  if (! InitializeAcl(dacl, dacl_length, ACL_REVISION))
156  {
157  *perror= "Failed to initialize DACL";
158  goto error;
159  }
160  if (! AddAccessAllowedAce(dacl, ACL_REVISION, everyone_rights, everyone_sid))
161  {
162  *perror= "Failed to set up DACL";
163  goto error;
164  }
165  if (! AddAccessAllowedAce(dacl, ACL_REVISION, owner_rights, owner_sid))
166  {
167  *perror= "Failed to set up DACL";
168  goto error;
169  }
170  if (! InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION))
171  {
172  *perror= "Could not initialize security descriptor";
173  goto error;
174  }
175  if (! SetSecurityDescriptorDacl(sd, TRUE, dacl, FALSE))
176  {
177  *perror= "Failed to install DACL";
178  goto error;
179  }
180 
181  sa->nLength= sizeof(*sa);
182  sa->bInheritHandle= TRUE;
183  sa->lpSecurityDescriptor= sd;
184  /* Save pointers to everyone_sid and dacl to be able to clean them up */
185  attr= (My_security_attr*) (((char*) sa) + ALIGN_SIZE(sizeof(*sa)));
186  attr->everyone_sid= everyone_sid;
187  attr->dacl= dacl;
188  *psa= sa;
189 
190  CloseHandle(htoken);
191  return 0;
192 error:
193  if (everyone_sid)
194  FreeSid(everyone_sid);
195  if (htoken)
196  CloseHandle(htoken);
197  my_free(sa);
198  my_free(dacl);
199  *psa= 0;
200  return 1;
201 }
202 
203 /*
204  Cleanup security attributes freeing used memory.
205 
206  SYNOPSIS
207  my_security_attr_free()
208  sa security attributes
209 */
210 
211 void my_security_attr_free(SECURITY_ATTRIBUTES *sa)
212 {
213  if (sa)
214  {
215  My_security_attr *attr= (My_security_attr*)
216  (((char*)sa) + ALIGN_SIZE(sizeof(*sa)));
217  FreeSid(attr->everyone_sid);
218  my_free(attr->dacl);
219  my_free(sa);
220  }
221 }
222 
223 #endif /* __WIN__ */