Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/management/FileSystemImpl.c
32287 views
/*1* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <windows.h>26#include <malloc.h>27#include <string.h>2829#include "jni.h"30#include "jni_util.h"31#include "sun_management_FileSystemImpl.h"3233/*34* Access mask to represent any file access35*/36#define ANY_ACCESS (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE)3738/*39* Returns JNI_TRUE if the specified file is on a file system that supports40* persistent ACLs (On NTFS file systems returns true, on FAT32 file systems41* returns false).42*/43static jboolean isSecuritySupported(JNIEnv* env, const char* path) {44char* root;45char* p;46BOOL res;47DWORD dwMaxComponentLength;48DWORD dwFlags;49char fsName[128];50DWORD fsNameLength;5152/*53* Get root directory. Assume that files are absolute paths. For UNCs54* the slash after the share name is required.55*/56root = strdup(path);57if (*root == '\\') {58/*59* \\server\share\file ==> \\server\share\60*/61int slashskip = 3;62p = root;63while ((*p == '\\') && (slashskip > 0)) {64char* p2;65p++;66p2 = strchr(p, '\\');67if ((p2 == NULL) || (*p2 != '\\')) {68free(root);69JNU_ThrowIOException(env, "Malformed UNC");70return JNI_FALSE;71}72p = p2;73slashskip--;74}75if (slashskip != 0) {76free(root);77JNU_ThrowIOException(env, "Malformed UNC");78return JNI_FALSE;79}80p++;81*p = '\0';8283} else {84p = strchr(root, '\\');85if (p == NULL) {86free(root);87JNU_ThrowIOException(env, "Absolute filename not specified");88return JNI_FALSE;89}90p++;91*p = '\0';92}939495/*96* Get the volume information - this gives us the file system file and97* also tells us if the file system supports persistent ACLs.98*/99fsNameLength = sizeof(fsName)-1;100res = GetVolumeInformation(root,101NULL, // address of name of the volume, can be NULL1020, // length of volume name103NULL, // address of volume serial number, can be NULL104&dwMaxComponentLength,105&dwFlags,106fsName,107fsNameLength);108if (res == 0) {109free(root);110JNU_ThrowIOExceptionWithLastError(env, "GetVolumeInformation failed");111return JNI_FALSE;112}113114free(root);115return (dwFlags & FS_PERSISTENT_ACLS) ? JNI_TRUE : JNI_FALSE;116}117118119/*120* Returns the security descriptor for a file.121*/122static SECURITY_DESCRIPTOR* getFileSecurityDescriptor(JNIEnv* env, const char* path) {123SECURITY_DESCRIPTOR* sd;124DWORD len = 0;125SECURITY_INFORMATION info =126OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;127128GetFileSecurityA(path, info , 0, 0, &len);129if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {130JNU_ThrowIOExceptionWithLastError(env, "GetFileSecurity failed");131return NULL;132}133sd = (SECURITY_DESCRIPTOR *)malloc(len);134if (sd == NULL) {135JNU_ThrowOutOfMemoryError(env, 0);136} else {137if (!(*GetFileSecurityA)(path, info, sd, len, &len)) {138JNU_ThrowIOExceptionWithLastError(env, "GetFileSecurity failed");139free(sd);140return NULL;141}142}143return sd;144}145146/*147* Returns pointer to the SID identifying the owner of the specified148* file.149*/150static SID* getFileOwner(JNIEnv* env, SECURITY_DESCRIPTOR* sd) {151SID* owner;152BOOL defaulted;153154if (!GetSecurityDescriptorOwner(sd, &owner, &defaulted)) {155JNU_ThrowIOExceptionWithLastError(env, "GetSecurityDescriptorOwner failed");156return NULL;157}158return owner;159}160161/*162* Returns pointer discretionary access-control list (ACL) from the security163* descriptor of the specified file.164*/165static ACL* getFileDACL(JNIEnv* env, SECURITY_DESCRIPTOR* sd) {166ACL *acl;167int defaulted, present;168169if (!GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted)) {170JNU_ThrowIOExceptionWithLastError(env, "GetSecurityDescriptorDacl failed");171return NULL;172}173if (!present) {174JNU_ThrowInternalError(env, "Security descriptor does not contain a DACL");175return NULL;176}177return acl;178}179180/*181* Returns JNI_TRUE if the specified owner is the only SID will access182* to the file.183*/184static jboolean isAccessUserOnly(JNIEnv* env, SID* owner, ACL* acl) {185ACL_SIZE_INFORMATION acl_size_info;186DWORD i;187188/*189* If there's no DACL then there's no access to the file190*/191if (acl == NULL) {192return JNI_TRUE;193}194195/*196* Get the ACE count197*/198if (!GetAclInformation(acl, (void *) &acl_size_info, sizeof(acl_size_info),199AclSizeInformation)) {200JNU_ThrowIOExceptionWithLastError(env, "GetAclInformation failed");201return JNI_FALSE;202}203204/*205* Iterate over the ACEs. For each "allow" type check that the SID206* matches the owner, and check that the access is read only.207*/208for (i = 0; i < acl_size_info.AceCount; i++) {209void* ace;210ACCESS_ALLOWED_ACE *access;211SID* sid;212213if (!GetAce(acl, i, &ace)) {214JNU_ThrowIOExceptionWithLastError(env, "GetAce failed");215return -1;216}217if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) {218continue;219}220access = (ACCESS_ALLOWED_ACE *)ace;221sid = (SID *) &access->SidStart;222if (!EqualSid(owner, sid)) {223/*224* If the ACE allows any access then the file is not secure.225*/226if (access->Mask & ANY_ACCESS) {227return JNI_FALSE;228}229}230}231return JNI_TRUE;232}233234235/*236* Class: sun_management_FileSystemImpl237* Method: init0238* Signature: ()V239*/240JNIEXPORT void JNICALL Java_sun_management_FileSystemImpl_init0241(JNIEnv *env, jclass ignored)242{243/* nothing to do */244}245246/*247* Class: sun_management_FileSystemImpl248* Method: isSecuritySupported0249* Signature: (Ljava/lang/String;)Z250*/251JNIEXPORT jboolean JNICALL Java_sun_management_FileSystemImpl_isSecuritySupported0252(JNIEnv *env, jclass ignored, jstring str)253{254jboolean res;255jboolean isCopy;256const char* path;257258path = JNU_GetStringPlatformChars(env, str, &isCopy);259if (path != NULL) {260res = isSecuritySupported(env, path);261if (isCopy) {262JNU_ReleaseStringPlatformChars(env, str, path);263}264return res;265} else {266/* exception thrown - doesn't matter what we return */267return JNI_TRUE;268}269}270271272/*273* Class: sun_management_FileSystemImpl274* Method: isAccessUserOnly0275* Signature: (Ljava/lang/String;)Z276*/277JNIEXPORT jboolean JNICALL Java_sun_management_FileSystemImpl_isAccessUserOnly0278(JNIEnv *env, jclass ignored, jstring str)279{280jboolean res = JNI_FALSE;281jboolean isCopy;282const char* path;283284path = JNU_GetStringPlatformChars(env, str, &isCopy);285if (path != NULL) {286/*287* From the security descriptor get the file owner and288* DACL. Then check if anybody but the owner has access289* to the file.290*/291SECURITY_DESCRIPTOR* sd = getFileSecurityDescriptor(env, path);292if (sd != NULL) {293SID *owner = getFileOwner(env, sd);294if (owner != NULL) {295ACL* acl = getFileDACL(env, sd);296if (acl != NULL) {297res = isAccessUserOnly(env, owner, acl);298} else {299/*300* If acl is NULL it means that an exception was thrown301* or there is "all acess" to the file.302*/303res = JNI_FALSE;304}305}306free(sd);307}308if (isCopy) {309JNU_ReleaseStringPlatformChars(env, str, path);310}311}312return res;313}314315316