/*
 * Copyright (c) 2008, 2009, 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 static sun.nio.fs.WindowsNativeDispatcher.*;
import static sun.nio.fs.WindowsConstants.*;

Windows implementation of AclFileAttributeView.
/** * Windows implementation of AclFileAttributeView. */
class WindowsAclFileAttributeView extends AbstractAclFileAttributeView {
typedef struct _SECURITY_DESCRIPTOR { BYTE Revision; BYTE Sbz1; SECURITY_DESCRIPTOR_CONTROL Control; PSID Owner; PSID Group; PACL Sacl; PACL Dacl; } SECURITY_DESCRIPTOR;
/** * 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_SECURITY_DESCRIPTOR = 20; private final WindowsPath file; private final boolean followLinks; WindowsAclFileAttributeView(WindowsPath file, boolean followLinks) { this.file = file; this.followLinks = followLinks; } // permission check private void checkAccess(WindowsPath file, boolean checkRead, boolean checkWrite) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (checkRead) sm.checkRead(file.getPathForPermissionCheck()); if (checkWrite) sm.checkWrite(file.getPathForPermissionCheck()); sm.checkPermission(new RuntimePermission("accessUserInformation")); } } // invokes GetFileSecurity to get requested security information static NativeBuffer getFileSecurity(String path, int request) throws IOException { // invoke get to buffer size int size = 0; try { size = GetFileSecurity(path, request, 0L, 0); } catch (WindowsException x) { x.rethrowAsIOException(path); } assert size > 0; // allocate buffer and re-invoke to get security information NativeBuffer buffer = NativeBuffers.getNativeBuffer(size); try { for (;;) { int newSize = GetFileSecurity(path, request, buffer.address(), size); if (newSize <= size) return buffer; // buffer was insufficient buffer.release(); buffer = NativeBuffers.getNativeBuffer(newSize); size = newSize; } } catch (WindowsException x) { buffer.release(); x.rethrowAsIOException(path); return null; } } @Override public UserPrincipal getOwner() throws IOException { checkAccess(file, true, false); // GetFileSecurity does not follow links so when following links we // need the final target String path = WindowsLinkSupport.getFinalPath(file, followLinks); NativeBuffer buffer = getFileSecurity(path, OWNER_SECURITY_INFORMATION); try { // get the address of the SID long sidAddress = GetSecurityDescriptorOwner(buffer.address()); if (sidAddress == 0L) throw new IOException("no owner"); return WindowsUserPrincipals.fromSid(sidAddress); } catch (WindowsException x) { x.rethrowAsIOException(file); return null; } finally { buffer.release(); } } @Override public List<AclEntry> getAcl() throws IOException { checkAccess(file, true, false); // GetFileSecurity does not follow links so when following links we // need the final target String path = WindowsLinkSupport.getFinalPath(file, followLinks); // ALLOW and DENY entries in DACL; // AUDIT entries in SACL (ignore for now as it requires privileges) NativeBuffer buffer = getFileSecurity(path, DACL_SECURITY_INFORMATION); try { return WindowsSecurityDescriptor.getAcl(buffer.address()); } finally { buffer.release(); } } @Override public void setOwner(UserPrincipal obj) throws IOException { if (obj == null) throw new NullPointerException("'owner' is null"); if (!(obj instanceof WindowsUserPrincipals.User)) throw new ProviderMismatchException(); WindowsUserPrincipals.User owner = (WindowsUserPrincipals.User)obj; // permission check checkAccess(file, false, true); // SetFileSecurity does not follow links so when following links we // need the final target String path = WindowsLinkSupport.getFinalPath(file, followLinks); // ConvertStringSidToSid allocates memory for SID so must invoke // LocalFree to free it when we are done long pOwner = 0L; try { pOwner = ConvertStringSidToSid(owner.sidString()); } catch (WindowsException x) { throw new IOException("Failed to get SID for " + owner.getName() + ": " + x.errorString()); } // Allocate buffer for security descriptor, initialize it, set // owner information and update the file. try { NativeBuffer buffer = NativeBuffers.getNativeBuffer(SIZEOF_SECURITY_DESCRIPTOR); try { InitializeSecurityDescriptor(buffer.address()); SetSecurityDescriptorOwner(buffer.address(), pOwner); // may need SeRestorePrivilege to set the owner WindowsSecurity.Privilege priv = WindowsSecurity.enablePrivilege("SeRestorePrivilege"); try { SetFileSecurity(path, OWNER_SECURITY_INFORMATION, buffer.address()); } finally { priv.drop(); } } catch (WindowsException x) { x.rethrowAsIOException(file); } finally { buffer.release(); } } finally { LocalFree(pOwner); } } @Override public void setAcl(List<AclEntry> acl) throws IOException { checkAccess(file, false, true); // SetFileSecurity does not follow links so when following links we // need the final target String path = WindowsLinkSupport.getFinalPath(file, followLinks); WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.create(acl); try { SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd.address()); } catch (WindowsException x) { x.rethrowAsIOException(file); } finally { sd.release(); } } }