forked from kangjianwei/LearningJDK
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWindowsSecurityDescriptor.java
452 lines (404 loc) · 15.8 KB
/
WindowsSecurityDescriptor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.nio.fs;
import java.nio.file.ProviderMismatchException;
import java.nio.file.attribute.*;
import java.util.*;
import java.io.IOException;
import jdk.internal.misc.Unsafe;
import static sun.nio.fs.WindowsNativeDispatcher.*;
import static sun.nio.fs.WindowsConstants.*;
/**
* A SecurityDescriptor for use when setting a file's ACL or creating a file with an initial ACL.
*/
// windows安全描述符
class WindowsSecurityDescriptor {
private static final Unsafe unsafe = Unsafe.getUnsafe();
/**
* typedef struct _ACL {
* BYTE AclRevision;
* BYTE Sbz1;
* WORD AclSize;
* WORD AceCount;
* WORD Sbz2;
* } ACL;
*
* typedef struct _ACE_HEADER {
* BYTE AceType;
* BYTE AceFlags;
* WORD AceSize;
* } ACE_HEADER;
*
* typedef struct _ACCESS_ALLOWED_ACE {
* ACE_HEADER Header;
* ACCESS_MASK Mask;
* DWORD SidStart;
* } ACCESS_ALLOWED_ACE;
*
* typedef struct _ACCESS_DENIED_ACE {
* ACE_HEADER Header;
* ACCESS_MASK Mask;
* DWORD SidStart;
* } ACCESS_DENIED_ACE;
*
* typedef struct _SECURITY_DESCRIPTOR {
* BYTE Revision;
* BYTE Sbz1;
* SECURITY_DESCRIPTOR_CONTROL Control;
* PSID Owner;
* PSID Group;
* PACL Sacl;
* PACL Dacl;
* } SECURITY_DESCRIPTOR;
*/
private static final short SIZEOF_ACL = 8;
private static final short SIZEOF_ACCESS_ALLOWED_ACE = 12;
private static final short SIZEOF_ACCESS_DENIED_ACE = 12;
private static final short SIZEOF_SECURITY_DESCRIPTOR = 20;
// AclEntry中各字段在底层对象中的偏移量
private static final short OFFSETOF_TYPE = 0;
private static final short OFFSETOF_FLAGS = 1;
private static final short OFFSETOF_ACCESS_MASK = 4;
private static final short OFFSETOF_SID = 8;
// null security descriptor
private static final WindowsSecurityDescriptor NULL_DESCRIPTOR = new WindowsSecurityDescriptor();
// native resources
private final List<Long> sidList; // 记录SID在系统底层的存储位置
private final NativeBuffer aclBuffer, sdBuffer; // 本地内存
/**
* Creates the "null" SecurityDescriptor
*/
private WindowsSecurityDescriptor() {
this.sidList = null;
this.aclBuffer = null;
this.sdBuffer = null;
}
/**
* Creates a SecurityDescriptor from the given ACL
*/
// 创建包括指定ACL在内的安全描述符
private WindowsSecurityDescriptor(List<AclEntry> acl) throws IOException {
boolean initialized = false;
// SECURITY: need to copy list in case size changes during processing
acl = new ArrayList<AclEntry>(acl);
// list of SIDs
sidList = new ArrayList<Long>(acl.size());
try {
// initial size of ACL
int size = SIZEOF_ACL;
/* get the SID for each entry */
// 遍历ACE
for(AclEntry entry : acl) {
// 获取该ACE对应的实体(文件)"所有者"
UserPrincipal user = entry.principal();
if(!(user instanceof WindowsUserPrincipals.User)) {
throw new ProviderMismatchException();
}
// 获取文件"所有者"的SID
String sidString = ((WindowsUserPrincipals.User) user).sidString();
try {
// 获取该SID在系统底层的存储位置
long pSid = ConvertStringSidToSid(sidString);
sidList.add(pSid);
// increase size to allow for entry
size += GetLengthSid(pSid) + Math.max(SIZEOF_ACCESS_ALLOWED_ACE, SIZEOF_ACCESS_DENIED_ACE);
} catch(WindowsException x) {
throw new IOException("Failed to get SID for " + user.getName() + ": " + x.errorString());
}
}
// allocate memory for the ACL
aclBuffer = NativeBuffers.getNativeBuffer(size);
sdBuffer = NativeBuffers.getNativeBuffer(SIZEOF_SECURITY_DESCRIPTOR);
InitializeAcl(aclBuffer.address(), size);
// Add entry ACE to the ACL
int i = 0;
while(i<acl.size()) {
AclEntry entry = acl.get(i);
long pSid = sidList.get(i);
try {
// 向本地内存中编码(写入)AclEntry信息
encode(entry, pSid, aclBuffer.address());
} catch(WindowsException x) {
throw new IOException("Failed to encode ACE: " + x.errorString());
}
i++;
}
// initialize security descriptor and set DACL
InitializeSecurityDescriptor(sdBuffer.address());
SetSecurityDescriptorDacl(sdBuffer.address(), aclBuffer.address());
initialized = true;
} catch(WindowsException x) {
throw new IOException(x.getMessage());
} finally {
// release resources if not completely initialized
if(!initialized) {
release();
}
}
}
/**
* Creates a security descriptor with a DACL representing the given ACL.
*/
// 返回创建的windows安全描述符,其中的ACL信息由参数acl给出
static WindowsSecurityDescriptor create(List<AclEntry> acl) throws IOException {
return new WindowsSecurityDescriptor(acl);
}
/**
* Processes the array of attributes looking for the attribute "acl:acl".
* Returns security descriptor representing the ACL or the "null" security descriptor if the attribute is not in the array.
*/
/*
* 通过指定的文件属性构造windows安全描述符,该方法仅在windows平台使用。
*
* 如果attrs不为null,则会从中找到最后一个name为"acl:acl"的属性,
* 并进一步获取其属性值(要求该属性值是一个ACL,即是一个List<AclEntry>类型的对象)。
*/
@SuppressWarnings("unchecked")
static WindowsSecurityDescriptor fromAttribute(FileAttribute<?>... attrs) throws IOException {
WindowsSecurityDescriptor sd = NULL_DESCRIPTOR;
for(FileAttribute<?> attr : attrs) {
// if more than one ACL specified then last one wins
if(sd != NULL_DESCRIPTOR) {
sd.release();
}
if(attr == null) {
throw new NullPointerException();
}
if(attr.name().equals("acl:acl")) {
List<AclEntry> acl = (List<AclEntry>) attr.value();
sd = new WindowsSecurityDescriptor(acl);
} else {
throw new UnsupportedOperationException("'" + attr.name() + "' not supported as initial attribute");
}
}
return sd;
}
/**
* Extracts DACL from security descriptor.
*/
// 从指定的安全描述符中获取DACL实体信息
static List<AclEntry> getAcl(long pSecurityDescriptor) throws IOException {
// get address of DACL
long aclAddress = GetSecurityDescriptorDacl(pSecurityDescriptor);
// get ACE count
int aceCount = 0;
if(aclAddress == 0L) {
// no ACEs
aceCount = 0;
} else {
AclInformation aclInfo = GetAclInformation(aclAddress);
aceCount = aclInfo.aceCount();
}
ArrayList<AclEntry> result = new ArrayList<>(aceCount);
// decode each of the ACEs to AclEntry objects
for(int i = 0; i<aceCount; i++) {
long aceAddress = GetAce(aclAddress, i);
// 从本地内存中解码(读取)AclEntry信息
AclEntry entry = decode(aceAddress);
if(entry != null) {
result.add(entry);
}
}
return result;
}
/**
* Releases memory associated with SecurityDescriptor
*/
// 释放本地内存
void release() {
if(sdBuffer != null) {
sdBuffer.release();
}
if(aclBuffer != null) {
aclBuffer.release();
}
if(sidList != null) {
// release memory for SIDs
for(Long sid : sidList) {
LocalFree(sid);
}
}
}
/**
* Returns address of SecurityDescriptor
*/
// 返回存储安全描述符的本地内存地址
long address() {
return (sdBuffer == null) ? 0L : sdBuffer.address();
}
/* decode Windows ACE to NFSv4 AclEntry */
// 从本地内存中解码(读取)AclEntry信息
private static AclEntry decode(long aceAddress) throws IOException {
// map type
byte aceType = unsafe.getByte(aceAddress + OFFSETOF_TYPE);
if(aceType != ACCESS_ALLOWED_ACE_TYPE && aceType != ACCESS_DENIED_ACE_TYPE) {
return null;
}
AclEntryType type;
if(aceType == ACCESS_ALLOWED_ACE_TYPE) {
type = AclEntryType.ALLOW;
} else {
type = AclEntryType.DENY;
}
// map flags
byte aceFlags = unsafe.getByte(aceAddress + OFFSETOF_FLAGS);
Set<AclEntryFlag> flags = EnumSet.noneOf(AclEntryFlag.class);
if((aceFlags & OBJECT_INHERIT_ACE) != 0) {
flags.add(AclEntryFlag.FILE_INHERIT);
}
if((aceFlags & CONTAINER_INHERIT_ACE) != 0) {
flags.add(AclEntryFlag.DIRECTORY_INHERIT);
}
if((aceFlags & NO_PROPAGATE_INHERIT_ACE) != 0) {
flags.add(AclEntryFlag.NO_PROPAGATE_INHERIT);
}
if((aceFlags & INHERIT_ONLY_ACE) != 0) {
flags.add(AclEntryFlag.INHERIT_ONLY);
}
// map access mask
int mask = unsafe.getInt(aceAddress + OFFSETOF_ACCESS_MASK);
Set<AclEntryPermission> perms = EnumSet.noneOf(AclEntryPermission.class);
if((mask & FILE_READ_DATA)>0) {
perms.add(AclEntryPermission.READ_DATA);
}
if((mask & FILE_WRITE_DATA)>0) {
perms.add(AclEntryPermission.WRITE_DATA);
}
if((mask & FILE_APPEND_DATA)>0) {
perms.add(AclEntryPermission.APPEND_DATA);
}
if((mask & FILE_READ_EA)>0) {
perms.add(AclEntryPermission.READ_NAMED_ATTRS);
}
if((mask & FILE_WRITE_EA)>0) {
perms.add(AclEntryPermission.WRITE_NAMED_ATTRS);
}
if((mask & FILE_EXECUTE)>0) {
perms.add(AclEntryPermission.EXECUTE);
}
if((mask & FILE_DELETE_CHILD)>0) {
perms.add(AclEntryPermission.DELETE_CHILD);
}
if((mask & FILE_READ_ATTRIBUTES)>0) {
perms.add(AclEntryPermission.READ_ATTRIBUTES);
}
if((mask & FILE_WRITE_ATTRIBUTES)>0) {
perms.add(AclEntryPermission.WRITE_ATTRIBUTES);
}
if((mask & DELETE)>0) {
perms.add(AclEntryPermission.DELETE);
}
if((mask & READ_CONTROL)>0) {
perms.add(AclEntryPermission.READ_ACL);
}
if((mask & WRITE_DAC)>0) {
perms.add(AclEntryPermission.WRITE_ACL);
}
if((mask & WRITE_OWNER)>0) {
perms.add(AclEntryPermission.WRITE_OWNER);
}
if((mask & SYNCHRONIZE)>0) {
perms.add(AclEntryPermission.SYNCHRONIZE);
}
// lookup SID to create UserPrincipal
long sidAddress = aceAddress + OFFSETOF_SID;
UserPrincipal user = WindowsUserPrincipals.fromSid(sidAddress);
return AclEntry.newBuilder().setType(type).setPrincipal(user).setFlags(flags).setPermissions(perms).build();
}
/* encode NFSv4 AclEntry as Windows ACE to given ACL */
// 向本地内存中编码(写入)AclEntry信息
private static void encode(AclEntry ace, long sidAddress, long aclAddress) throws WindowsException {
// ignore non-allow/deny entries for now
if(ace.type() != AclEntryType.ALLOW && ace.type() != AclEntryType.DENY) {
return;
}
boolean allow = (ace.type() == AclEntryType.ALLOW);
// map access mask
Set<AclEntryPermission> aceMask = ace.permissions();
int mask = 0;
if(aceMask.contains(AclEntryPermission.READ_DATA)) {
mask |= FILE_READ_DATA;
}
if(aceMask.contains(AclEntryPermission.WRITE_DATA)) {
mask |= FILE_WRITE_DATA;
}
if(aceMask.contains(AclEntryPermission.APPEND_DATA)) {
mask |= FILE_APPEND_DATA;
}
if(aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS)) {
mask |= FILE_READ_EA;
}
if(aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS)) {
mask |= FILE_WRITE_EA;
}
if(aceMask.contains(AclEntryPermission.EXECUTE)) {
mask |= FILE_EXECUTE;
}
if(aceMask.contains(AclEntryPermission.DELETE_CHILD)) {
mask |= FILE_DELETE_CHILD;
}
if(aceMask.contains(AclEntryPermission.READ_ATTRIBUTES)) {
mask |= FILE_READ_ATTRIBUTES;
}
if(aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES)) {
mask |= FILE_WRITE_ATTRIBUTES;
}
if(aceMask.contains(AclEntryPermission.DELETE)) {
mask |= DELETE;
}
if(aceMask.contains(AclEntryPermission.READ_ACL)) {
mask |= READ_CONTROL;
}
if(aceMask.contains(AclEntryPermission.WRITE_ACL)) {
mask |= WRITE_DAC;
}
if(aceMask.contains(AclEntryPermission.WRITE_OWNER)) {
mask |= WRITE_OWNER;
}
if(aceMask.contains(AclEntryPermission.SYNCHRONIZE)) {
mask |= SYNCHRONIZE;
}
// map flags
Set<AclEntryFlag> aceFlags = ace.flags();
byte flags = 0;
if(aceFlags.contains(AclEntryFlag.FILE_INHERIT)) {
flags |= OBJECT_INHERIT_ACE;
}
if(aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT)) {
flags |= CONTAINER_INHERIT_ACE;
}
if(aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT)) {
flags |= NO_PROPAGATE_INHERIT_ACE;
}
if(aceFlags.contains(AclEntryFlag.INHERIT_ONLY)) {
flags |= INHERIT_ONLY_ACE;
}
if(allow) {
AddAccessAllowedAceEx(aclAddress, flags, mask, sidAddress);
} else {
AddAccessDeniedAceEx(aclAddress, flags, mask, sidAddress);
}
}
}