8214545: sun/management/jmxremote/bootstrap tests hang in revokeall.exe on Windows
Reviewed-by: dholmes, amenkov, bulasevich, dfuchs, erikj
--- a/make/test/JtregNativeJdk.gmk Wed May 22 09:26:48 2019 -0400
+++ b/make/test/JtregNativeJdk.gmk Wed May 22 09:06:24 2019 -0700
@@ -62,9 +62,11 @@
WIN_LIB_JLI := $(SUPPORT_OUTPUTDIR)/native/java.base/libjli/jli.lib
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJliLaunchTest := $(WIN_LIB_JLI)
BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := jvm.lib
+ BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib
else
BUILD_JDK_JTREG_LIBRARIES_LIBS_libstringPlatformChars := -ljava
BUILD_JDK_JTREG_LIBRARIES_LIBS_libDirectIO := -ljava
+ BUILD_JDK_JTREG_EXCLUDE += exerevokeall.c
ifeq ($(call isTargetOs, linux), true)
BUILD_JDK_JTREG_LIBRARIES_LIBS_libInheritedChannel := -ljava
else ifeq ($(call isTargetOs, solaris), true)
--- a/test/jdk/sun/management/jmxremote/bootstrap/GeneratePropertyPassword.sh Wed May 22 09:26:48 2019 -0400
+++ b/test/jdk/sun/management/jmxremote/bootstrap/GeneratePropertyPassword.sh Wed May 22 09:06:24 2019 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2019, 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
@@ -70,13 +70,11 @@
if [ "$OS" = "Windows_NT" ]; then
USER=`id -u -n`
CACLS="$SystemRoot/system32/cacls.exe"
- TEST_SRC=`cygpath ${TESTSRC}`
- REVOKEALL="$TEST_SRC/../../windows/revokeall.exe"
- if [ ! -f "$REVOKEALL" ] ; then
- echo "$REVOKEALL missing"
+ REVOKEALL="$TESTNATIVEPATH/revokeall.exe"
+ if [ ! -x "$REVOKEALL" ] ; then
+ echo "$REVOKEALL doesn't exist or is not executable"
exit 1
fi
- chmod ug+x $REVOKEALL
fi
;;
*)
--- a/test/jdk/sun/management/windows/README Wed May 22 09:26:48 2019 -0400
+++ b/test/jdk/sun/management/windows/README Wed May 22 09:06:24 2019 -0700
@@ -1,6 +1,29 @@
+/*
+ * Copyright (c) 2004, 2019, 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.
+ *
+ * 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.
+ */
-This directory contains the source and the binary version of a Windows
-utility to remove all non-owner Access Control Entries from a given file.
+
+This directory contains the source of a Windows utility to remove all
+non-owner Access Control Entries from a given file.
The tool is used by regression tests in the following directories :-
@@ -10,18 +33,3 @@
be "secured" (meaning that only the owner should have access to the
files).
-Both the source and the binary version are checked into SCCS. If
-you require to make changes to the tool then you need to Visual
-C++ to rebuild revokeall.exe after changing the source.
-
-To rebuild the tool you need to setup your environment (by
-calling the VC++ VCVARS32.BAT script), and then executing the
-following command :-
-
-cl /mt revokeall.c advapi32.lib
-
-This will generate revokeall.exe.
-
-Note that a 32-bit version of revokeall.exe is checked into SCCS
-- this 32-bit application is also used when running on 64-bit
-versions of Windows (AMD64 and IA64).
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/management/windows/exerevokeall.c Wed May 22 09:06:24 2019 -0700
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2004, 2019, 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.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <windows.h>
+#include <malloc.h>
+#include <string.h>
+
+/*
+ * Simple Windows utility to remove all non-owner access to a given file.
+ */
+
+
+/*
+ * Access mask to represent any file access
+ */
+#define ANY_ACCESS (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE)
+
+
+/*
+ * Print error message to stderr
+ */
+static void printLastError(const char* msg) {
+ int len;
+ char buf[128];
+ DWORD errval;
+
+ buf[0] = '\0';
+ len = sizeof(buf);
+
+ errval = GetLastError();
+ if (errval != 0) {
+ int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, errval,
+ 0, buf, len, NULL);
+ if (n > 3) {
+ /* Drop final '.', CR, LF */
+ if (buf[n - 1] == '\n') n--;
+ if (buf[n - 1] == '\r') n--;
+ if (buf[n - 1] == '.') n--;
+ buf[n] = '\0';
+ }
+ }
+
+ if (strlen(buf) > 0) {
+ fprintf(stderr, "revokeall %s: %s\n", msg, buf);
+ } else {
+ fprintf(stderr, "revokeall %s\n", msg);
+ }
+}
+
+
+
+/*
+ * Return a string that includes all the components of a given SID.
+ * See here for a description of the SID components :-
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/sid_components.asp
+ */
+static char *getTextualSid(SID* sid) {
+ SID_IDENTIFIER_AUTHORITY* sia;
+ DWORD i, count;
+ DWORD len;
+ char* name;
+
+ /*
+ * Get the identifier authority and the number of sub-authorities
+ */
+ sia = GetSidIdentifierAuthority(sid);
+ count = *GetSidSubAuthorityCount(sid);
+
+ /*
+ * Allocate buffer for the string - buffer is :-
+ * S-SID_REVISION- + identifierAuthority- + subauthorities- + NULL
+ */
+ len=(15 + 12 + (12 * count) + 1) * sizeof(char);
+ name = (char*)malloc(len);
+ if (name == NULL) {
+ return NULL;
+ }
+
+ // S-SID_REVISION
+ sprintf(name, "S-%lu-", SID_REVISION );
+
+ // Identifier authority
+ if ((sia->Value[0] != 0) || (sia->Value[1] != 0))
+ {
+ sprintf(name + strlen(name), "0x%02hx%02hx%02hx%02hx%02hx%02hx",
+ (USHORT)sia->Value[0],
+ (USHORT)sia->Value[1],
+ (USHORT)sia->Value[2],
+ (USHORT)sia->Value[3],
+ (USHORT)sia->Value[4],
+ (USHORT)sia->Value[5]);
+ }
+ else
+ {
+ sprintf(name + strlen(name), "%lu",
+ (ULONG)(sia->Value[5] ) +
+ (ULONG)(sia->Value[4] << 8) +
+ (ULONG)(sia->Value[3] << 16) +
+ (ULONG)(sia->Value[2] << 24) );
+ }
+
+ // finally, the sub-authorities
+ for (i=0 ; i<count; i++) {
+ sprintf(name + strlen(name), "-%lu",
+ *GetSidSubAuthority(sid, i) );
+ }
+
+ return name;
+}
+
+/*
+ * Returns a string to represent the given security identifier (SID).
+ * If the account is known to the local computer then the account
+ * domain is returned. The format will be \\name or domain\\name depending
+ * on if the computer belongs to a domain.
+ * If the account name is not known then the textual representation of
+ * SID is returned -- eg: S-1-5-21-2818032319-470147023-1036452850-13037.
+ */
+static char *getSIDString(SID* sid) {
+ char domain[255];
+ char name[255];
+ DWORD domainLen = sizeof(domain);
+ DWORD nameLen = sizeof(name);
+ SID_NAME_USE use;
+
+ if(!IsValidSid(sid)) {
+ return strdup("<Invalid SID>");
+ }
+
+ if (LookupAccountSid(NULL, sid, name, &nameLen, domain, &domainLen, &use)) {
+ size_t len = strlen(name) + strlen(domain) + 3;
+ char* s = (char*)malloc(len);
+ if (s != NULL) {
+ strcpy(s, domain);
+ strcat(s, "\\\\");
+ strcat(s, name);
+ }
+ return s;
+ } else {
+ return getTextualSid(sid);
+ }
+}
+
+
+
+/*
+ * Returns 1 if the specified file is on a file system that supports
+ * persistent ACLs (On NTFS file systems returns true, on FAT32 file systems
+ * returns false), otherwise 0. Returns -1 if error.
+ */
+static int isSecuritySupported(const char* path) {
+ char* root;
+ char* p;
+ BOOL res;
+ DWORD dwMaxComponentLength;
+ DWORD dwFlags;
+ char fsName[128];
+ DWORD fsNameLength;
+
+ /*
+ * Get root directory. For UNCs the slash after the share name is required.
+ */
+ root = strdup(path);
+ if (*root == '\\') {
+ /*
+ * \\server\share\file ==> \\server\share\
+ */
+ int slashskip = 3;
+ p = root;
+ while ((*p == '\\') && (slashskip > 0)) {
+ char* p2;
+ p++;
+ p2 = strchr(p, '\\');
+ if ((p2 == NULL) || (*p2 != '\\')) {
+ free(root);
+ fprintf(stderr, "Malformed UNC");
+ return -1;
+ }
+ p = p2;
+ slashskip--;
+ }
+ if (slashskip != 0) {
+ free(root);
+ fprintf(stderr, "Malformed UNC");
+ return -1;
+ }
+ p++;
+ *p = '\0';
+
+ } else {
+ p = strchr(root, '\\');
+
+ /*
+ * Relative path so use current directory
+ */
+ if (p == NULL) {
+ free(root);
+ root = malloc(255);
+ if (GetCurrentDirectory(255, root) == 0) {
+ printLastError("GetCurrentDirectory failed");
+ return -1;
+ }
+ p = strchr(root, '\\');
+ if (p == NULL) {
+ fprintf(stderr, "GetCurrentDirectory doesn't include drive letter!!!!\n");
+ return -1;
+ }
+ }
+ p++;
+ *p = '\0';
+ }
+
+ /*
+ * Get the volume information - this gives us the file system file and
+ * also tells us if the file system supports persistent ACLs.
+ */
+ fsNameLength = sizeof(fsName)-1;
+ res = GetVolumeInformation(root,
+ NULL, // address of name of the volume, can be NULL
+ 0, // length of volume name
+ NULL, // address of volume serial number, can be NULL
+ &dwMaxComponentLength,
+ &dwFlags,
+ fsName,
+ fsNameLength);
+ if (res == 0) {
+ printLastError("GetVolumeInformation failed");
+ free(root);
+ return -1;
+ }
+
+ free(root);
+ return (dwFlags & FS_PERSISTENT_ACLS) ? 1 : 0;
+}
+
+
+/*
+ * Returns the security descriptor for a file.
+ */
+static SECURITY_DESCRIPTOR* getFileSecurityDescriptor(const char* path) {
+ SECURITY_DESCRIPTOR* sd;
+ DWORD len = 0;
+ SECURITY_INFORMATION info =
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
+
+ GetFileSecurity(path, info , 0, 0, &len);
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ printLastError("GetFileSecurity failed");
+ return NULL;
+ }
+ sd = (SECURITY_DESCRIPTOR *)malloc(len);
+ if (sd == NULL) {
+ fprintf(stderr, "Out of memory");
+ } else {
+ if (!GetFileSecurity(path, info, sd, len, &len)) {
+ printLastError("GetFileSecurity failed");
+ free(sd);
+ return NULL;
+ }
+ }
+ return sd;
+}
+
+
+/*
+ * Revoke all access to the specific file
+ */
+static int revokeAll(const char* path) {
+ SECURITY_DESCRIPTOR* sd;
+ SID* owner;
+ ACL *acl;
+ BOOL defaulted, present;
+ ACL_SIZE_INFORMATION acl_size_info;
+ DWORD i, count;
+ char* str;
+
+ /*
+ * Get security descriptor for file; From security descriptor get the
+ * owner SID, and the DACL.
+ */
+ sd = getFileSecurityDescriptor(path);
+ if (sd == NULL) {
+ return -1; /* error already reported */
+ }
+ if (!GetSecurityDescriptorOwner(sd, &owner, &defaulted)) {
+ printLastError("GetSecurityDescriptorOwner failed");
+ return -1;
+ }
+ str = getSIDString(owner);
+ if (str != NULL) {
+ printf("owner: %s\n", str);
+ free(str);
+ }
+ if (!GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted)) {
+ printLastError("GetSecurityDescriptorDacl failed");
+ return -1;
+ }
+ if (!present) {
+ fprintf(stderr, "Security descriptor does not contain a DACL");
+ return -1;
+ }
+
+ /*
+ * If DACL is NULL there is no access to the file - we are done
+ */
+ if (acl == NULL) {
+ return 1;
+ }
+
+ /*
+ * Iterate over the ACEs. For each "allow" type check that the SID
+ * matches the owner - if not we remove the ACE from the ACL
+ */
+ if (!GetAclInformation(acl, (void *) &acl_size_info, sizeof(acl_size_info),
+ AclSizeInformation)) {
+ printLastError("GetAclInformation failed");
+ return -1;
+ }
+ count = acl_size_info.AceCount;
+ i = 0;
+ while (count > 0) {
+ void* ace;
+ ACCESS_ALLOWED_ACE *access;
+ SID* sid;
+ BOOL deleted;
+
+ if (!GetAce(acl, i, &ace)) {
+ printLastError("GetAce failed");
+ return -1;
+ }
+ if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) {
+ i++;
+ count--;
+ continue;
+ }
+ access = (ACCESS_ALLOWED_ACE *)ace;
+ sid = (SID *) &access->SidStart;
+
+
+ deleted = FALSE;
+ if (!EqualSid(owner, sid)) {
+ /*
+ * If the ACE allows any access then the file then we
+ * delete it.
+ */
+ if (access->Mask & ANY_ACCESS) {
+ str = getSIDString(sid);
+ if (str != NULL) {
+ printf("remove ALLOW %s\n", str);
+ free(str);
+ }
+ if (DeleteAce(acl, i) == 0) {
+ printLastError("DeleteAce failed");
+ return -1;
+ }
+ deleted = TRUE;
+ }
+ }
+
+ if (!deleted) {
+ str = getSIDString(sid);
+ if (str != NULL) {
+ printf("ALLOW %s (access mask=%x)\n", str, access->Mask);
+ free(str);
+ }
+
+ /* onto the next ACE */
+ i++;
+ }
+ count--;
+ }
+
+ /*
+ * No changes - only owner has access
+ */
+ if (i == acl_size_info.AceCount) {
+ printf("No changes.\n");
+ return 1;
+ }
+
+ /*
+ * Create security descriptor and set its DACL to the version
+ * that we just edited
+ */
+ if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) {
+ printLastError("InitializeSecurityDescriptor failed");
+ return -1;
+ }
+ if (!SetSecurityDescriptorDacl(sd, present, acl, defaulted)) {
+ printLastError("SetSecurityDescriptorDacl failed");
+ return -1;
+ }
+ if (!SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd)) {
+ printLastError("SetFileSecurity failed");
+ return -1;
+ }
+
+ printf("File updated.\n");
+
+ return 1;
+}
+
+/*
+ * Convert slashes in the pathname to backslashes if needed.
+ */
+static char* convert_path(const char* p) {
+ int i = 0;
+ char* path = strdup(p);
+ while (p[i] != '\0') {
+ if (p[i] == '/') {
+ path[i] = '\\';
+ }
+ i++;
+ }
+ return path;
+}
+
+/*
+ * Usage: revokeall file
+ */
+int main( int argc, char *argv[])
+{
+ int rc;
+ const char* path;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s file\n", argv[0]);
+ return -1;
+ }
+ path = convert_path(argv[1]);
+ printf("Revoking all non-owner access to %s\n", path);
+ rc = isSecuritySupported(path);
+ if (rc != 1) {
+ if (rc == 0) {
+ printf("File security not supported on this file system\n");
+ }
+ return rc;
+ } else {
+ return revokeAll(path);
+ }
+}
--- a/test/jdk/sun/management/windows/revokeall.c Wed May 22 09:26:48 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,462 +0,0 @@
-/*
- * Copyright (c) 2004, 2007, 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.
- *
- * 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.
- */
-
-#include <stdio.h>
-#include <windows.h>
-#include <malloc.h>
-#include <string.h>
-
-/*
- * Simple Windows utility to remove all non-owner access to a given
- * file - suitable for NT/2000/XP only.
- */
-
-
-/*
- * Access mask to represent any file access
- */
-#define ANY_ACCESS (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE)
-
-
-/*
- * Print error message to stderr
- */
-static void printLastError(const char* msg) {
- int len;
- char buf[128];
- DWORD errval;
-
- buf[0] = '\0';
- len = sizeof(buf);
-
- errval = GetLastError();
- if (errval != 0) {
- int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, errval,
- 0, buf, len, NULL);
- if (n > 3) {
- /* Drop final '.', CR, LF */
- if (buf[n - 1] == '\n') n--;
- if (buf[n - 1] == '\r') n--;
- if (buf[n - 1] == '.') n--;
- buf[n] = '\0';
- }
- }
-
- if (strlen(buf) > 0) {
- fprintf(stderr, "revokeall %s: %s\n", msg, buf);
- } else {
- fprintf(stderr, "revokeall %s\n", msg);
- }
-}
-
-
-
-/*
- * Return a string that includes all the components of a given SID.
- * See here for a description of the SID components :-
- * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/sid_components.asp
- */
-static char *getTextualSid(SID* sid) {
- SID_IDENTIFIER_AUTHORITY* sia;
- DWORD i, count;
- DWORD len;
- char* name;
-
- /*
- * Get the identifier authority and the number of sub-authorities
- */
- sia = GetSidIdentifierAuthority(sid);
- count = *GetSidSubAuthorityCount(sid);
-
- /*
- * Allocate buffer for the string - buffer is :-
- * S-SID_REVISION- + identifierAuthority- + subauthorities- + NULL
- */
- len=(15 + 12 + (12 * count) + 1) * sizeof(char);
- name = (char*)malloc(len);
- if (name == NULL) {
- return NULL;
- }
-
- // S-SID_REVISION
- sprintf(name, "S-%lu-", SID_REVISION );
-
- // Identifier authority
- if ((sia->Value[0] != 0) || (sia->Value[1] != 0))
- {
- sprintf(name + strlen(name), "0x%02hx%02hx%02hx%02hx%02hx%02hx",
- (USHORT)sia->Value[0],
- (USHORT)sia->Value[1],
- (USHORT)sia->Value[2],
- (USHORT)sia->Value[3],
- (USHORT)sia->Value[4],
- (USHORT)sia->Value[5]);
- }
- else
- {
- sprintf(name + strlen(name), "%lu",
- (ULONG)(sia->Value[5] ) +
- (ULONG)(sia->Value[4] << 8) +
- (ULONG)(sia->Value[3] << 16) +
- (ULONG)(sia->Value[2] << 24) );
- }
-
- // finally, the sub-authorities
- for (i=0 ; i<count; i++) {
- sprintf(name + strlen(name), "-%lu",
- *GetSidSubAuthority(sid, i) );
- }
-
- return name;
-}
-
-/*
- * Returns a string to represent the given security identifier (SID).
- * If the account is known to the local computer then the account
- * domain is returned. The format will be \\name or domain\\name depending
- * on if the computer belongs to a domain.
- * If the account name is not known then the textual representation of
- * SID is returned -- eg: S-1-5-21-2818032319-470147023-1036452850-13037.
- */
-static char *getSIDString(SID* sid) {
- char domain[255];
- char name[255];
- DWORD domainLen = sizeof(domain);
- DWORD nameLen = sizeof(name);
- SID_NAME_USE use;
-
- if(!IsValidSid(sid)) {
- return strdup("<Invalid SID>");
- }
-
- if (LookupAccountSid(NULL, sid, name, &nameLen, domain, &domainLen, &use)) {
- int len = strlen(name) + strlen(domain) + 3;
- char* s = (char*)malloc(len);
- if (s != NULL) {
- strcpy(s, domain);
- strcat(s, "\\\\");
- strcat(s, name);
- }
- return s;
- } else {
- return getTextualSid(sid);
- }
-}
-
-
-
-/*
- * Returns 1 if the specified file is on a file system that supports
- * persistent ACLs (On NTFS file systems returns true, on FAT32 file systems
- * returns false), otherwise 0. Returns -1 if error.
- */
-static int isSecuritySupported(const char* path) {
- char* root;
- char* p;
- BOOL res;
- DWORD dwMaxComponentLength;
- DWORD dwFlags;
- char fsName[128];
- DWORD fsNameLength;
-
- /*
- * Get root directory. For UNCs the slash after the share name is required.
- */
- root = strdup(path);
- if (*root == '\\') {
- /*
- * \\server\share\file ==> \\server\share\
- */
- int slashskip = 3;
- p = root;
- while ((*p == '\\') && (slashskip > 0)) {
- char* p2;
- p++;
- p2 = strchr(p, '\\');
- if ((p2 == NULL) || (*p2 != '\\')) {
- free(root);
- fprintf(stderr, "Malformed UNC");
- return -1;
- }
- p = p2;
- slashskip--;
- }
- if (slashskip != 0) {
- free(root);
- fprintf(stderr, "Malformed UNC");
- return -1;
- }
- p++;
- *p = '\0';
-
- } else {
- p = strchr(root, '\\');
-
- /*
- * Relative path so use current directory
- */
- if (p == NULL) {
- free(root);
- root = malloc(255);
- if (GetCurrentDirectory(255, root) == 0) {
- printLastError("GetCurrentDirectory failed");
- return -1;
- }
- p = strchr(root, '\\');
- if (p == NULL) {
- fprintf(stderr, "GetCurrentDirectory doesn't include drive letter!!!!\n");
- return -1;
- }
- }
- p++;
- *p = '\0';
- }
-
- /*
- * Get the volume information - this gives us the file system file and
- * also tells us if the file system supports persistent ACLs.
- */
- fsNameLength = sizeof(fsName)-1;
- res = GetVolumeInformation(root,
- NULL, // address of name of the volume, can be NULL
- 0, // length of volume name
- NULL, // address of volume serial number, can be NULL
- &dwMaxComponentLength,
- &dwFlags,
- fsName,
- fsNameLength);
- if (res == 0) {
- printLastError("GetVolumeInformation failed");
- free(root);
- return -1;
- }
-
- free(root);
- return (dwFlags & FS_PERSISTENT_ACLS) ? 1 : 0;
-}
-
-
-/*
- * Returns the security descriptor for a file.
- */
-static SECURITY_DESCRIPTOR* getFileSecurityDescriptor(const char* path) {
- SECURITY_DESCRIPTOR* sd;
- DWORD len = 0;
- SECURITY_INFORMATION info =
- OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
-
- GetFileSecurity(path, info , 0, 0, &len);
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- printLastError("GetFileSecurity failed");
- return NULL;
- }
- sd = (SECURITY_DESCRIPTOR *)malloc(len);
- if (sd == NULL) {
- fprintf(stderr, "Out of memory");
- } else {
- if (!GetFileSecurity(path, info, sd, len, &len)) {
- printLastError("GetFileSecurity failed");
- free(sd);
- return NULL;
- }
- }
- return sd;
-}
-
-
-/*
- * Revoke all access to the specific file
- */
-static int revokeAll(const char* path) {
- SECURITY_DESCRIPTOR* sd;
- SID* owner;
- ACL *acl;
- BOOL defaulted, present;
- ACL_SIZE_INFORMATION acl_size_info;
- DWORD i, count;
- char* str;
-
- /*
- * Get security descriptor for file; From security descriptor get the
- * owner SID, and the DACL.
- */
- sd = getFileSecurityDescriptor(path);
- if (sd == NULL) {
- return -1; /* error already reported */
- }
- if (!GetSecurityDescriptorOwner(sd, &owner, &defaulted)) {
- printLastError("GetSecurityDescriptorOwner failed");
- return -1;
- }
- str = getSIDString(owner);
- if (str != NULL) {
- printf("owner: %s\n", str);
- free(str);
- }
- if (!GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted)) {
- printLastError("GetSecurityDescriptorDacl failed");
- return -1;
- }
- if (!present) {
- fprintf(stderr, "Security descriptor does not contain a DACL");
- return -1;
- }
-
- /*
- * If DACL is NULL there is no access to the file - we are done
- */
- if (acl == NULL) {
- return 1;
- }
-
- /*
- * Iterate over the ACEs. For each "allow" type check that the SID
- * matches the owner - if not we remove the ACE from the ACL
- */
- if (!GetAclInformation(acl, (void *) &acl_size_info, sizeof(acl_size_info),
- AclSizeInformation)) {
- printLastError("GetAclInformation failed");
- return -1;
- }
- count = acl_size_info.AceCount;
- i = 0;
- while (count > 0) {
- void* ace;
- ACCESS_ALLOWED_ACE *access;
- SID* sid;
- BOOL deleted;
-
- if (!GetAce(acl, i, &ace)) {
- printLastError("GetAce failed");
- return -1;
- }
- if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) {
- continue;
- }
- access = (ACCESS_ALLOWED_ACE *)ace;
- sid = (SID *) &access->SidStart;
-
-
- deleted = FALSE;
- if (!EqualSid(owner, sid)) {
- /*
- * If the ACE allows any access then the file then we
- * delete it.
- */
- if (access->Mask & ANY_ACCESS) {
- str = getSIDString(sid);
- if (str != NULL) {
- printf("remove ALLOW %s\n", str);
- free(str);
- }
- if (DeleteAce(acl, i) == 0) {
- printLastError("DeleteAce failed");
- return -1;
- }
- deleted = TRUE;
- }
- }
-
- if (!deleted) {
- str = getSIDString(sid);
- if (str != NULL) {
- printf("ALLOW %s (access mask=%x)\n", str, access->Mask);
- free(str);
- }
-
- /* onto the next ACE */
- i++;
- }
- count--;
- }
-
- /*
- * No changes - only owner has access
- */
- if (i == acl_size_info.AceCount) {
- printf("No changes.\n");
- return 1;
- }
-
- /*
- * Create security descriptor and set its DACL to the version
- * that we just edited
- */
- if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) {
- printLastError("InitializeSecurityDescriptor failed");
- return -1;
- }
- if (!SetSecurityDescriptorDacl(sd, present, acl, defaulted)) {
- printLastError("SetSecurityDescriptorDacl failed");
- return -1;
- }
- if (!SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd)) {
- printLastError("SetFileSecurity failed");
- return -1;
- }
-
- printf("File updated.\n");
-
- return 1;
-}
-
-/*
- * Convert slashes in the pathname to backslashes if needed.
- */
-static char* convert_path(const char* p) {
- int i = 0;
- char* path = strdup(p);
- while (p[i] != '\0') {
- if (p[i] == '/') {
- path[i] = '\\';
- }
- i++;
- }
- return path;
-}
-
-/*
- * Usage: revokeall file
- */
-int main( int argc, char *argv[])
-{
- int rc;
- const char* path;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: %s file\n", argv[0]);
- return -1;
- }
- path = convert_path(argv[1]);
- printf("Revoking all non-owner access to %s\n", path);
- rc = isSecuritySupported(path);
- if (rc != 1) {
- if (rc == 0) {
- printf("File security not supported on this file system\n");
- }
- return rc;
- } else {
- return revokeAll(path);
- }
-}
Binary file test/jdk/sun/management/windows/revokeall.exe has changed