Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/management/FileSystemImpl.c
32287 views
1
/*
2
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#include <windows.h>
27
#include <malloc.h>
28
#include <string.h>
29
30
#include "jni.h"
31
#include "jni_util.h"
32
#include "sun_management_FileSystemImpl.h"
33
34
/*
35
* Access mask to represent any file access
36
*/
37
#define ANY_ACCESS (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE)
38
39
/*
40
* Returns JNI_TRUE if the specified file is on a file system that supports
41
* persistent ACLs (On NTFS file systems returns true, on FAT32 file systems
42
* returns false).
43
*/
44
static jboolean isSecuritySupported(JNIEnv* env, const char* path) {
45
char* root;
46
char* p;
47
BOOL res;
48
DWORD dwMaxComponentLength;
49
DWORD dwFlags;
50
char fsName[128];
51
DWORD fsNameLength;
52
53
/*
54
* Get root directory. Assume that files are absolute paths. For UNCs
55
* the slash after the share name is required.
56
*/
57
root = strdup(path);
58
if (*root == '\\') {
59
/*
60
* \\server\share\file ==> \\server\share\
61
*/
62
int slashskip = 3;
63
p = root;
64
while ((*p == '\\') && (slashskip > 0)) {
65
char* p2;
66
p++;
67
p2 = strchr(p, '\\');
68
if ((p2 == NULL) || (*p2 != '\\')) {
69
free(root);
70
JNU_ThrowIOException(env, "Malformed UNC");
71
return JNI_FALSE;
72
}
73
p = p2;
74
slashskip--;
75
}
76
if (slashskip != 0) {
77
free(root);
78
JNU_ThrowIOException(env, "Malformed UNC");
79
return JNI_FALSE;
80
}
81
p++;
82
*p = '\0';
83
84
} else {
85
p = strchr(root, '\\');
86
if (p == NULL) {
87
free(root);
88
JNU_ThrowIOException(env, "Absolute filename not specified");
89
return JNI_FALSE;
90
}
91
p++;
92
*p = '\0';
93
}
94
95
96
/*
97
* Get the volume information - this gives us the file system file and
98
* also tells us if the file system supports persistent ACLs.
99
*/
100
fsNameLength = sizeof(fsName)-1;
101
res = GetVolumeInformation(root,
102
NULL, // address of name of the volume, can be NULL
103
0, // length of volume name
104
NULL, // address of volume serial number, can be NULL
105
&dwMaxComponentLength,
106
&dwFlags,
107
fsName,
108
fsNameLength);
109
if (res == 0) {
110
free(root);
111
JNU_ThrowIOExceptionWithLastError(env, "GetVolumeInformation failed");
112
return JNI_FALSE;
113
}
114
115
free(root);
116
return (dwFlags & FS_PERSISTENT_ACLS) ? JNI_TRUE : JNI_FALSE;
117
}
118
119
120
/*
121
* Returns the security descriptor for a file.
122
*/
123
static SECURITY_DESCRIPTOR* getFileSecurityDescriptor(JNIEnv* env, const char* path) {
124
SECURITY_DESCRIPTOR* sd;
125
DWORD len = 0;
126
SECURITY_INFORMATION info =
127
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
128
129
GetFileSecurityA(path, info , 0, 0, &len);
130
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
131
JNU_ThrowIOExceptionWithLastError(env, "GetFileSecurity failed");
132
return NULL;
133
}
134
sd = (SECURITY_DESCRIPTOR *)malloc(len);
135
if (sd == NULL) {
136
JNU_ThrowOutOfMemoryError(env, 0);
137
} else {
138
if (!(*GetFileSecurityA)(path, info, sd, len, &len)) {
139
JNU_ThrowIOExceptionWithLastError(env, "GetFileSecurity failed");
140
free(sd);
141
return NULL;
142
}
143
}
144
return sd;
145
}
146
147
/*
148
* Returns pointer to the SID identifying the owner of the specified
149
* file.
150
*/
151
static SID* getFileOwner(JNIEnv* env, SECURITY_DESCRIPTOR* sd) {
152
SID* owner;
153
BOOL defaulted;
154
155
if (!GetSecurityDescriptorOwner(sd, &owner, &defaulted)) {
156
JNU_ThrowIOExceptionWithLastError(env, "GetSecurityDescriptorOwner failed");
157
return NULL;
158
}
159
return owner;
160
}
161
162
/*
163
* Returns pointer discretionary access-control list (ACL) from the security
164
* descriptor of the specified file.
165
*/
166
static ACL* getFileDACL(JNIEnv* env, SECURITY_DESCRIPTOR* sd) {
167
ACL *acl;
168
int defaulted, present;
169
170
if (!GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted)) {
171
JNU_ThrowIOExceptionWithLastError(env, "GetSecurityDescriptorDacl failed");
172
return NULL;
173
}
174
if (!present) {
175
JNU_ThrowInternalError(env, "Security descriptor does not contain a DACL");
176
return NULL;
177
}
178
return acl;
179
}
180
181
/*
182
* Returns JNI_TRUE if the specified owner is the only SID will access
183
* to the file.
184
*/
185
static jboolean isAccessUserOnly(JNIEnv* env, SID* owner, ACL* acl) {
186
ACL_SIZE_INFORMATION acl_size_info;
187
DWORD i;
188
189
/*
190
* If there's no DACL then there's no access to the file
191
*/
192
if (acl == NULL) {
193
return JNI_TRUE;
194
}
195
196
/*
197
* Get the ACE count
198
*/
199
if (!GetAclInformation(acl, (void *) &acl_size_info, sizeof(acl_size_info),
200
AclSizeInformation)) {
201
JNU_ThrowIOExceptionWithLastError(env, "GetAclInformation failed");
202
return JNI_FALSE;
203
}
204
205
/*
206
* Iterate over the ACEs. For each "allow" type check that the SID
207
* matches the owner, and check that the access is read only.
208
*/
209
for (i = 0; i < acl_size_info.AceCount; i++) {
210
void* ace;
211
ACCESS_ALLOWED_ACE *access;
212
SID* sid;
213
214
if (!GetAce(acl, i, &ace)) {
215
JNU_ThrowIOExceptionWithLastError(env, "GetAce failed");
216
return -1;
217
}
218
if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) {
219
continue;
220
}
221
access = (ACCESS_ALLOWED_ACE *)ace;
222
sid = (SID *) &access->SidStart;
223
if (!EqualSid(owner, sid)) {
224
/*
225
* If the ACE allows any access then the file is not secure.
226
*/
227
if (access->Mask & ANY_ACCESS) {
228
return JNI_FALSE;
229
}
230
}
231
}
232
return JNI_TRUE;
233
}
234
235
236
/*
237
* Class: sun_management_FileSystemImpl
238
* Method: init0
239
* Signature: ()V
240
*/
241
JNIEXPORT void JNICALL Java_sun_management_FileSystemImpl_init0
242
(JNIEnv *env, jclass ignored)
243
{
244
/* nothing to do */
245
}
246
247
/*
248
* Class: sun_management_FileSystemImpl
249
* Method: isSecuritySupported0
250
* Signature: (Ljava/lang/String;)Z
251
*/
252
JNIEXPORT jboolean JNICALL Java_sun_management_FileSystemImpl_isSecuritySupported0
253
(JNIEnv *env, jclass ignored, jstring str)
254
{
255
jboolean res;
256
jboolean isCopy;
257
const char* path;
258
259
path = JNU_GetStringPlatformChars(env, str, &isCopy);
260
if (path != NULL) {
261
res = isSecuritySupported(env, path);
262
if (isCopy) {
263
JNU_ReleaseStringPlatformChars(env, str, path);
264
}
265
return res;
266
} else {
267
/* exception thrown - doesn't matter what we return */
268
return JNI_TRUE;
269
}
270
}
271
272
273
/*
274
* Class: sun_management_FileSystemImpl
275
* Method: isAccessUserOnly0
276
* Signature: (Ljava/lang/String;)Z
277
*/
278
JNIEXPORT jboolean JNICALL Java_sun_management_FileSystemImpl_isAccessUserOnly0
279
(JNIEnv *env, jclass ignored, jstring str)
280
{
281
jboolean res = JNI_FALSE;
282
jboolean isCopy;
283
const char* path;
284
285
path = JNU_GetStringPlatformChars(env, str, &isCopy);
286
if (path != NULL) {
287
/*
288
* From the security descriptor get the file owner and
289
* DACL. Then check if anybody but the owner has access
290
* to the file.
291
*/
292
SECURITY_DESCRIPTOR* sd = getFileSecurityDescriptor(env, path);
293
if (sd != NULL) {
294
SID *owner = getFileOwner(env, sd);
295
if (owner != NULL) {
296
ACL* acl = getFileDACL(env, sd);
297
if (acl != NULL) {
298
res = isAccessUserOnly(env, owner, acl);
299
} else {
300
/*
301
* If acl is NULL it means that an exception was thrown
302
* or there is "all acess" to the file.
303
*/
304
res = JNI_FALSE;
305
}
306
}
307
free(sd);
308
}
309
if (isCopy) {
310
JNU_ReleaseStringPlatformChars(env, str, path);
311
}
312
}
313
return res;
314
}
315
316