|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* |
|
7 * Test for NTFS File Permissions being correctly changed to match the new |
|
8 * directory upon moving a file. (Bug 224692.) |
|
9 */ |
|
10 |
|
11 #include "../TestHarness.h" |
|
12 #include "nsEmbedString.h" |
|
13 #include "nsIFile.h" |
|
14 #include <windows.h> |
|
15 #include <aclapi.h> |
|
16 |
|
17 #define BUFFSIZE 512 |
|
18 |
|
19 |
|
20 |
|
21 nsresult TestPermissions() |
|
22 { |
|
23 |
|
24 nsresult rv; // Return value |
|
25 |
|
26 // File variables |
|
27 HANDLE tempFileHandle; |
|
28 nsCOMPtr<nsIFile> tempFile; |
|
29 nsCOMPtr<nsIFile> tempDirectory1; |
|
30 nsCOMPtr<nsIFile> tempDirectory2; |
|
31 WCHAR filePath[MAX_PATH]; |
|
32 WCHAR dir1Path[MAX_PATH]; |
|
33 WCHAR dir2Path[MAX_PATH]; |
|
34 |
|
35 // Security variables |
|
36 DWORD result; |
|
37 PSID everyoneSID = nullptr, adminSID = nullptr; |
|
38 PACL dirACL = nullptr, fileACL = nullptr; |
|
39 PSECURITY_DESCRIPTOR dirSD = nullptr, fileSD = nullptr; |
|
40 EXPLICIT_ACCESS ea[2]; |
|
41 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = |
|
42 SECURITY_WORLD_SID_AUTHORITY; |
|
43 SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; |
|
44 SECURITY_ATTRIBUTES sa; |
|
45 TRUSTEE everyoneTrustee; |
|
46 ACCESS_MASK everyoneRights; |
|
47 |
|
48 // Create a well-known SID for the Everyone group. |
|
49 if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, |
|
50 SECURITY_WORLD_RID, |
|
51 0, 0, 0, 0, 0, 0, 0, |
|
52 &everyoneSID)) |
|
53 { |
|
54 fail("NTFS Permissions: AllocateAndInitializeSid Error"); |
|
55 return NS_ERROR_FAILURE; |
|
56 } |
|
57 |
|
58 // Create a SID for the Administrators group. |
|
59 if(! AllocateAndInitializeSid(&SIDAuthNT, 2, |
|
60 SECURITY_BUILTIN_DOMAIN_RID, |
|
61 DOMAIN_ALIAS_RID_ADMINS, |
|
62 0, 0, 0, 0, 0, 0, |
|
63 &adminSID)) |
|
64 { |
|
65 fail("NTFS Permissions: AllocateAndInitializeSid Error"); |
|
66 return NS_ERROR_FAILURE; |
|
67 } |
|
68 |
|
69 // Initialize an EXPLICIT_ACCESS structure for an ACE. |
|
70 // The ACE will allow Everyone read access to the directory. |
|
71 ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS)); |
|
72 ea[0].grfAccessPermissions = GENERIC_READ; |
|
73 ea[0].grfAccessMode = SET_ACCESS; |
|
74 ea[0].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; |
|
75 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; |
|
76 ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; |
|
77 ea[0].Trustee.ptstrName = (LPTSTR) everyoneSID; |
|
78 |
|
79 // Initialize an EXPLICIT_ACCESS structure for an ACE. |
|
80 // The ACE will allow the Administrators group full access |
|
81 ea[1].grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL; |
|
82 ea[1].grfAccessMode = SET_ACCESS; |
|
83 ea[1].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; |
|
84 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; |
|
85 ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; |
|
86 ea[1].Trustee.ptstrName = (LPTSTR) adminSID; |
|
87 |
|
88 // Create a new ACL that contains the new ACEs. |
|
89 result = SetEntriesInAcl(2, ea, nullptr, &dirACL); |
|
90 if (ERROR_SUCCESS != result) |
|
91 { |
|
92 fail("NTFS Permissions: SetEntriesInAcl Error"); |
|
93 return NS_ERROR_FAILURE; |
|
94 } |
|
95 |
|
96 // Initialize a security descriptor. |
|
97 dirSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, |
|
98 SECURITY_DESCRIPTOR_MIN_LENGTH); |
|
99 if (nullptr == dirSD) |
|
100 { |
|
101 fail("NTFS Permissions: LocalAlloc Error"); |
|
102 return NS_ERROR_FAILURE; |
|
103 } |
|
104 |
|
105 if (!InitializeSecurityDescriptor(dirSD, |
|
106 SECURITY_DESCRIPTOR_REVISION)) |
|
107 { |
|
108 fail("NTFS Permissions: InitializeSecurityDescriptor Error"); |
|
109 return NS_ERROR_FAILURE; |
|
110 } |
|
111 |
|
112 // Add the ACL to the security descriptor. |
|
113 if (!SetSecurityDescriptorDacl(dirSD, true, dirACL, false)) |
|
114 { |
|
115 fail("NTFS Permissions: SetSecurityDescriptorDacl Error"); |
|
116 return NS_ERROR_FAILURE; |
|
117 } |
|
118 |
|
119 // Initialize a security attributes structure. |
|
120 sa.nLength = sizeof (SECURITY_ATTRIBUTES); |
|
121 sa.lpSecurityDescriptor = dirSD; |
|
122 sa.bInheritHandle = false; |
|
123 |
|
124 // Create and open first temporary directory |
|
125 if(!CreateDirectoryW(L".\\NTFSPERMTEMP1", &sa)) |
|
126 { |
|
127 fail("NTFS Permissions: Creating Temporary Directory"); |
|
128 return NS_ERROR_FAILURE; |
|
129 } |
|
130 |
|
131 GetFullPathNameW((LPCWSTR)L".\\NTFSPERMTEMP1", MAX_PATH, dir1Path, |
|
132 nullptr); |
|
133 |
|
134 rv = NS_NewLocalFile(nsEmbedString(dir1Path), false, |
|
135 getter_AddRefs(tempDirectory1)); |
|
136 if (NS_FAILED(rv)) |
|
137 { |
|
138 fail("NTFS Permissions: Opening Temporary Directory 1"); |
|
139 return rv; |
|
140 } |
|
141 |
|
142 |
|
143 // Create and open temporary file |
|
144 tempFileHandle = CreateFileW(L".\\NTFSPERMTEMP1\\NTFSPerm.tmp", |
|
145 GENERIC_READ | GENERIC_WRITE, |
|
146 0, |
|
147 nullptr, //default security |
|
148 CREATE_ALWAYS, |
|
149 FILE_ATTRIBUTE_NORMAL, |
|
150 nullptr); |
|
151 |
|
152 if(tempFileHandle == INVALID_HANDLE_VALUE) |
|
153 { |
|
154 fail("NTFS Permissions: Creating Temporary File"); |
|
155 return NS_ERROR_FAILURE; |
|
156 } |
|
157 |
|
158 CloseHandle(tempFileHandle); |
|
159 |
|
160 GetFullPathNameW((LPCWSTR)L".\\NTFSPERMTEMP1\\NTFSPerm.tmp", |
|
161 MAX_PATH, filePath, nullptr); |
|
162 |
|
163 rv = NS_NewLocalFile(nsEmbedString(filePath), false, |
|
164 getter_AddRefs(tempFile)); |
|
165 if (NS_FAILED(rv)) |
|
166 { |
|
167 fail("NTFS Permissions: Opening Temporary File"); |
|
168 return rv; |
|
169 } |
|
170 |
|
171 // Update Everyone Explict_Acess to full access. |
|
172 ea[0].grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL; |
|
173 |
|
174 // Update the ACL to contain the new ACEs. |
|
175 result = SetEntriesInAcl(2, ea, nullptr, &dirACL); |
|
176 if (ERROR_SUCCESS != result) |
|
177 { |
|
178 fail("NTFS Permissions: SetEntriesInAcl 2 Error"); |
|
179 return NS_ERROR_FAILURE; |
|
180 } |
|
181 |
|
182 // Add the new ACL to the security descriptor. |
|
183 if (!SetSecurityDescriptorDacl(dirSD, true, dirACL, false)) |
|
184 { |
|
185 fail("NTFS Permissions: SetSecurityDescriptorDacl 2 Error"); |
|
186 return NS_ERROR_FAILURE; |
|
187 } |
|
188 |
|
189 // Create and open second temporary directory |
|
190 if(!CreateDirectoryW(L".\\NTFSPERMTEMP2", &sa)) |
|
191 { |
|
192 fail("NTFS Permissions: Creating Temporary Directory 2"); |
|
193 return NS_ERROR_FAILURE; |
|
194 } |
|
195 |
|
196 GetFullPathNameW((LPCWSTR)L".\\NTFSPERMTEMP2", MAX_PATH, dir2Path, |
|
197 nullptr); |
|
198 |
|
199 rv = NS_NewLocalFile(nsEmbedString(dir2Path), false, |
|
200 getter_AddRefs(tempDirectory2)); |
|
201 if (NS_FAILED(rv)) |
|
202 { |
|
203 fail("NTFS Permissions: Opening Temporary Directory 2"); |
|
204 return rv; |
|
205 } |
|
206 |
|
207 // Move the file. |
|
208 rv = tempFile->MoveTo(tempDirectory2, EmptyString()); |
|
209 |
|
210 if (NS_FAILED(rv)) |
|
211 { |
|
212 fail("NTFS Permissions: Moving"); |
|
213 return rv; |
|
214 } |
|
215 |
|
216 // Access the ACL of the file |
|
217 result = GetNamedSecurityInfoW(L".\\NTFSPERMTEMP2\\NTFSPerm.tmp", |
|
218 SE_FILE_OBJECT, |
|
219 DACL_SECURITY_INFORMATION | |
|
220 UNPROTECTED_DACL_SECURITY_INFORMATION, |
|
221 nullptr, nullptr, &fileACL, nullptr, |
|
222 &fileSD); |
|
223 if (ERROR_SUCCESS != result) |
|
224 { |
|
225 fail("NTFS Permissions: GetNamedSecurityDescriptor Error"); |
|
226 return NS_ERROR_FAILURE; |
|
227 } |
|
228 |
|
229 // Build a trustee representing "Everyone" |
|
230 BuildTrusteeWithSid(&everyoneTrustee, everyoneSID); |
|
231 |
|
232 // Get Everyone's effective rights. |
|
233 result = GetEffectiveRightsFromAcl(fileACL, &everyoneTrustee, |
|
234 &everyoneRights); |
|
235 if (ERROR_SUCCESS != result) |
|
236 { |
|
237 fail("NTFS Permissions: GetEffectiveRightsFromAcl Error"); |
|
238 return NS_ERROR_FAILURE; |
|
239 } |
|
240 |
|
241 // Check for delete access, which we won't have unless permissions have |
|
242 // updated |
|
243 if((everyoneRights & DELETE) == (DELETE)) |
|
244 { |
|
245 passed("NTFS Permissions Test"); |
|
246 rv = NS_OK; |
|
247 } |
|
248 else |
|
249 { |
|
250 fail("NTFS Permissions: Access check."); |
|
251 rv = NS_ERROR_FAILURE; |
|
252 } |
|
253 |
|
254 // Cleanup |
|
255 if (everyoneSID) |
|
256 FreeSid(everyoneSID); |
|
257 if (adminSID) |
|
258 FreeSid(adminSID); |
|
259 if (dirACL) |
|
260 LocalFree(dirACL); |
|
261 if (dirSD) |
|
262 LocalFree(dirSD); |
|
263 if(fileACL) |
|
264 LocalFree(fileACL); |
|
265 |
|
266 tempDirectory1->Remove(true); |
|
267 tempDirectory2->Remove(true); |
|
268 |
|
269 return rv; |
|
270 } |
|
271 |
|
272 int main(int argc, char** argv) |
|
273 { |
|
274 ScopedXPCOM xpcom("NTFSPermissionsTests"); // name for tests being run |
|
275 if (xpcom.failed()) |
|
276 return 1; |
|
277 |
|
278 int rv = 0; |
|
279 |
|
280 if(NS_FAILED(TestPermissions())) |
|
281 rv = 1; |
|
282 |
|
283 return rv; |
|
284 |
|
285 } |
|
286 |