1 /* Copyright (c) 2000-2005, 2007 MySQL AB
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.
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.
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 Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 #include "mysys_priv.h"
20 /* Windows NT/2000 discretionary access control utility functions. */
23 Check if the operating system is built on NT technology.
30 static my_bool
is_nt()
32 return GetVersion() < 0x80000000;
36 Auxilary structure to store pointers to the data which we need to keep
37 around while SECURITY_ATTRIBUTES is in use.
40 typedef struct st_my_security_attr
48 Allocate and initialize SECURITY_ATTRIBUTES setting up access
49 rights for the owner and group `Everybody'.
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
56 owner_rights [IN] access rights for the owner
57 everyone_rights [IN] access rights for group Everybody
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.
69 0 success, psa is 0 or points to a valid SA structure,
71 !0 error, SA is set to 0, error message is stored in perror
74 int my_security_attr_create(SECURITY_ATTRIBUTES
**psa
, const char **perror
,
75 DWORD owner_rights
, DWORD everyone_rights
)
77 /* Top-level SID authority */
78 SID_IDENTIFIER_AUTHORITY world_auth
= SECURITY_WORLD_SID_AUTHORITY
;
81 SECURITY_ATTRIBUTES
*sa
= 0;
83 DWORD owner_token_length
, dacl_length
;
84 SECURITY_DESCRIPTOR
*sd
;
85 PTOKEN_USER owner_token
;
87 My_security_attr
*attr
;
96 Get SID of Everyone group. Easier to retrieve all SIDs each time
97 this function is called than worry about thread safety.
99 if (! AllocateAndInitializeSid(&world_auth
, 1, SECURITY_WORLD_RID
,
100 0, 0, 0, 0, 0, 0, 0, &everyone_sid
))
102 *perror
= "Failed to retrieve the SID of Everyone group";
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.
113 if (! OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &htoken
))
115 *perror
= "Failed to retrieve thread access token";
118 GetTokenInformation(htoken
, TokenUser
, 0, 0, &owner_token_length
);
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
,
127 *perror
= "Failed to allocate memory for SECURITY_ATTRIBUTES";
130 bzero(owner_token
, owner_token_length
);
131 if (! GetTokenInformation(htoken
, TokenUser
, owner_token
,
132 owner_token_length
, &owner_token_length
))
134 *perror
= "GetTokenInformation failed";
137 owner_sid
= owner_token
->User
.Sid
;
139 if (! IsValidSid(owner_sid
))
141 *perror
= "IsValidSid failed";
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
);
150 if (! (dacl
= (PACL
) my_malloc(dacl_length
, MYF(MY_ZEROFILL
|MY_WME
))))
152 *perror
= "Failed to allocate memory for DACL";
155 if (! InitializeAcl(dacl
, dacl_length
, ACL_REVISION
))
157 *perror
= "Failed to initialize DACL";
160 if (! AddAccessAllowedAce(dacl
, ACL_REVISION
, everyone_rights
, everyone_sid
))
162 *perror
= "Failed to set up DACL";
165 if (! AddAccessAllowedAce(dacl
, ACL_REVISION
, owner_rights
, owner_sid
))
167 *perror
= "Failed to set up DACL";
170 if (! InitializeSecurityDescriptor(sd
, SECURITY_DESCRIPTOR_REVISION
))
172 *perror
= "Could not initialize security descriptor";
175 if (! SetSecurityDescriptorDacl(sd
, TRUE
, dacl
, FALSE
))
177 *perror
= "Failed to install DACL";
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
;
194 FreeSid(everyone_sid
);
197 my_free((uchar
*) sa
, MYF(MY_ALLOW_ZERO_PTR
));
198 my_free((uchar
*) dacl
, MYF(MY_ALLOW_ZERO_PTR
));
204 Cleanup security attributes freeing used memory.
207 my_security_attr_free()
208 sa security attributes
211 void my_security_attr_free(SECURITY_ATTRIBUTES
*sa
)
215 My_security_attr
*attr
= (My_security_attr
*)
216 (((char*)sa
) + ALIGN_SIZE(sizeof(*sa
)));
217 FreeSid(attr
->everyone_sid
);
218 my_free((uchar
*) attr
->dacl
, MYF(0));
219 my_free((uchar
*) sa
, MYF(0));