Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/management/windows/revokeall.c
38841 views
/*1* Copyright (c) 2004, 2007, 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.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include <stdio.h>24#include <windows.h>25#include <malloc.h>26#include <string.h>2728/*29* Simple Windows utility to remove all non-owner access to a given30* file - suitable for NT/2000/XP only.31*/323334/*35* Access mask to represent any file access36*/37#define ANY_ACCESS (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE)383940/*41* Print error message to stderr42*/43static void printLastError(const char* msg) {44int len;45char buf[128];46DWORD errval;4748buf[0] = '\0';49len = sizeof(buf);5051errval = GetLastError();52if (errval != 0) {53int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,54NULL, errval,550, buf, len, NULL);56if (n > 3) {57/* Drop final '.', CR, LF */58if (buf[n - 1] == '\n') n--;59if (buf[n - 1] == '\r') n--;60if (buf[n - 1] == '.') n--;61buf[n] = '\0';62}63}6465if (strlen(buf) > 0) {66fprintf(stderr, "revokeall %s: %s\n", msg, buf);67} else {68fprintf(stderr, "revokeall %s\n", msg);69}70}71727374/*75* Return a string that includes all the components of a given SID.76* See here for a description of the SID components :-77* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/sid_components.asp78*/79static char *getTextualSid(SID* sid) {80SID_IDENTIFIER_AUTHORITY* sia;81DWORD i, count;82DWORD len;83char* name;8485/*86* Get the identifier authority and the number of sub-authorities87*/88sia = GetSidIdentifierAuthority(sid);89count = *GetSidSubAuthorityCount(sid);9091/*92* Allocate buffer for the string - buffer is :-93* S-SID_REVISION- + identifierAuthority- + subauthorities- + NULL94*/95len=(15 + 12 + (12 * count) + 1) * sizeof(char);96name = (char*)malloc(len);97if (name == NULL) {98return NULL;99}100101// S-SID_REVISION102sprintf(name, "S-%lu-", SID_REVISION );103104// Identifier authority105if ((sia->Value[0] != 0) || (sia->Value[1] != 0))106{107sprintf(name + strlen(name), "0x%02hx%02hx%02hx%02hx%02hx%02hx",108(USHORT)sia->Value[0],109(USHORT)sia->Value[1],110(USHORT)sia->Value[2],111(USHORT)sia->Value[3],112(USHORT)sia->Value[4],113(USHORT)sia->Value[5]);114}115else116{117sprintf(name + strlen(name), "%lu",118(ULONG)(sia->Value[5] ) +119(ULONG)(sia->Value[4] << 8) +120(ULONG)(sia->Value[3] << 16) +121(ULONG)(sia->Value[2] << 24) );122}123124// finally, the sub-authorities125for (i=0 ; i<count; i++) {126sprintf(name + strlen(name), "-%lu",127*GetSidSubAuthority(sid, i) );128}129130return name;131}132133/*134* Returns a string to represent the given security identifier (SID).135* If the account is known to the local computer then the account136* domain is returned. The format will be \\name or domain\\name depending137* on if the computer belongs to a domain.138* If the account name is not known then the textual representation of139* SID is returned -- eg: S-1-5-21-2818032319-470147023-1036452850-13037.140*/141static char *getSIDString(SID* sid) {142char domain[255];143char name[255];144DWORD domainLen = sizeof(domain);145DWORD nameLen = sizeof(name);146SID_NAME_USE use;147148if(!IsValidSid(sid)) {149return strdup("<Invalid SID>");150}151152if (LookupAccountSid(NULL, sid, name, &nameLen, domain, &domainLen, &use)) {153int len = strlen(name) + strlen(domain) + 3;154char* s = (char*)malloc(len);155if (s != NULL) {156strcpy(s, domain);157strcat(s, "\\\\");158strcat(s, name);159}160return s;161} else {162return getTextualSid(sid);163}164}165166167168/*169* Returns 1 if the specified file is on a file system that supports170* persistent ACLs (On NTFS file systems returns true, on FAT32 file systems171* returns false), otherwise 0. Returns -1 if error.172*/173static int isSecuritySupported(const char* path) {174char* root;175char* p;176BOOL res;177DWORD dwMaxComponentLength;178DWORD dwFlags;179char fsName[128];180DWORD fsNameLength;181182/*183* Get root directory. For UNCs the slash after the share name is required.184*/185root = strdup(path);186if (*root == '\\') {187/*188* \\server\share\file ==> \\server\share\189*/190int slashskip = 3;191p = root;192while ((*p == '\\') && (slashskip > 0)) {193char* p2;194p++;195p2 = strchr(p, '\\');196if ((p2 == NULL) || (*p2 != '\\')) {197free(root);198fprintf(stderr, "Malformed UNC");199return -1;200}201p = p2;202slashskip--;203}204if (slashskip != 0) {205free(root);206fprintf(stderr, "Malformed UNC");207return -1;208}209p++;210*p = '\0';211212} else {213p = strchr(root, '\\');214215/*216* Relative path so use current directory217*/218if (p == NULL) {219free(root);220root = malloc(255);221if (GetCurrentDirectory(255, root) == 0) {222printLastError("GetCurrentDirectory failed");223return -1;224}225p = strchr(root, '\\');226if (p == NULL) {227fprintf(stderr, "GetCurrentDirectory doesn't include drive letter!!!!\n");228return -1;229}230}231p++;232*p = '\0';233}234235/*236* Get the volume information - this gives us the file system file and237* also tells us if the file system supports persistent ACLs.238*/239fsNameLength = sizeof(fsName)-1;240res = GetVolumeInformation(root,241NULL, // address of name of the volume, can be NULL2420, // length of volume name243NULL, // address of volume serial number, can be NULL244&dwMaxComponentLength,245&dwFlags,246fsName,247fsNameLength);248if (res == 0) {249printLastError("GetVolumeInformation failed");250free(root);251return -1;252}253254free(root);255return (dwFlags & FS_PERSISTENT_ACLS) ? 1 : 0;256}257258259/*260* Returns the security descriptor for a file.261*/262static SECURITY_DESCRIPTOR* getFileSecurityDescriptor(const char* path) {263SECURITY_DESCRIPTOR* sd;264DWORD len = 0;265SECURITY_INFORMATION info =266OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;267268GetFileSecurity(path, info , 0, 0, &len);269if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {270printLastError("GetFileSecurity failed");271return NULL;272}273sd = (SECURITY_DESCRIPTOR *)malloc(len);274if (sd == NULL) {275fprintf(stderr, "Out of memory");276} else {277if (!GetFileSecurity(path, info, sd, len, &len)) {278printLastError("GetFileSecurity failed");279free(sd);280return NULL;281}282}283return sd;284}285286287/*288* Revoke all access to the specific file289*/290static int revokeAll(const char* path) {291SECURITY_DESCRIPTOR* sd;292SID* owner;293ACL *acl;294BOOL defaulted, present;295ACL_SIZE_INFORMATION acl_size_info;296DWORD i, count;297char* str;298299/*300* Get security descriptor for file; From security descriptor get the301* owner SID, and the DACL.302*/303sd = getFileSecurityDescriptor(path);304if (sd == NULL) {305return -1; /* error already reported */306}307if (!GetSecurityDescriptorOwner(sd, &owner, &defaulted)) {308printLastError("GetSecurityDescriptorOwner failed");309return -1;310}311str = getSIDString(owner);312if (str != NULL) {313printf("owner: %s\n", str);314free(str);315}316if (!GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted)) {317printLastError("GetSecurityDescriptorDacl failed");318return -1;319}320if (!present) {321fprintf(stderr, "Security descriptor does not contain a DACL");322return -1;323}324325/*326* If DACL is NULL there is no access to the file - we are done327*/328if (acl == NULL) {329return 1;330}331332/*333* Iterate over the ACEs. For each "allow" type check that the SID334* matches the owner - if not we remove the ACE from the ACL335*/336if (!GetAclInformation(acl, (void *) &acl_size_info, sizeof(acl_size_info),337AclSizeInformation)) {338printLastError("GetAclInformation failed");339return -1;340}341count = acl_size_info.AceCount;342i = 0;343while (count > 0) {344void* ace;345ACCESS_ALLOWED_ACE *access;346SID* sid;347BOOL deleted;348349if (!GetAce(acl, i, &ace)) {350printLastError("GetAce failed");351return -1;352}353if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) {354continue;355}356access = (ACCESS_ALLOWED_ACE *)ace;357sid = (SID *) &access->SidStart;358359360deleted = FALSE;361if (!EqualSid(owner, sid)) {362/*363* If the ACE allows any access then the file then we364* delete it.365*/366if (access->Mask & ANY_ACCESS) {367str = getSIDString(sid);368if (str != NULL) {369printf("remove ALLOW %s\n", str);370free(str);371}372if (DeleteAce(acl, i) == 0) {373printLastError("DeleteAce failed");374return -1;375}376deleted = TRUE;377}378}379380if (!deleted) {381str = getSIDString(sid);382if (str != NULL) {383printf("ALLOW %s (access mask=%x)\n", str, access->Mask);384free(str);385}386387/* onto the next ACE */388i++;389}390count--;391}392393/*394* No changes - only owner has access395*/396if (i == acl_size_info.AceCount) {397printf("No changes.\n");398return 1;399}400401/*402* Create security descriptor and set its DACL to the version403* that we just edited404*/405if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) {406printLastError("InitializeSecurityDescriptor failed");407return -1;408}409if (!SetSecurityDescriptorDacl(sd, present, acl, defaulted)) {410printLastError("SetSecurityDescriptorDacl failed");411return -1;412}413if (!SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd)) {414printLastError("SetFileSecurity failed");415return -1;416}417418printf("File updated.\n");419420return 1;421}422423/*424* Convert slashes in the pathname to backslashes if needed.425*/426static char* convert_path(const char* p) {427int i = 0;428char* path = strdup(p);429while (p[i] != '\0') {430if (p[i] == '/') {431path[i] = '\\';432}433i++;434}435return path;436}437438/*439* Usage: revokeall file440*/441int main( int argc, char *argv[])442{443int rc;444const char* path;445446if (argc != 2) {447fprintf(stderr, "Usage: %s file\n", argv[0]);448return -1;449}450path = convert_path(argv[1]);451printf("Revoking all non-owner access to %s\n", path);452rc = isSecuritySupported(path);453if (rc != 1) {454if (rc == 0) {455printf("File security not supported on this file system\n");456}457return rc;458} else {459return revokeAll(path);460}461}462463464