jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java
changeset 2057 3acf8e5e2ca0
child 5506 202f599c92aa
equal deleted inserted replaced
2056:115e09b7a004 2057:3acf8e5e2ca0
       
     1 /*
       
     2  * Copyright 2008-2009 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.nio.fs;
       
    27 
       
    28 import java.nio.file.ProviderMismatchException;
       
    29 import java.nio.file.attribute.*;
       
    30 import java.util.*;
       
    31 import java.io.IOException;
       
    32 
       
    33 import static sun.nio.fs.WindowsNativeDispatcher.*;
       
    34 import static sun.nio.fs.WindowsConstants.*;
       
    35 
       
    36 /**
       
    37  * Windows implementation of AclFileAttributeView.
       
    38  */
       
    39 
       
    40 class WindowsAclFileAttributeView
       
    41     extends AbstractAclFileAttributeView
       
    42 {
       
    43     /**
       
    44      * typedef struct _SECURITY_DESCRIPTOR {
       
    45      *     BYTE  Revision;
       
    46      *     BYTE  Sbz1;
       
    47      *     SECURITY_DESCRIPTOR_CONTROL Control;
       
    48      *     PSID Owner;
       
    49      *     PSID Group;
       
    50      *     PACL Sacl;
       
    51      *     PACL Dacl;
       
    52      * } SECURITY_DESCRIPTOR;
       
    53      */
       
    54     private static final short SIZEOF_SECURITY_DESCRIPTOR   = 20;
       
    55 
       
    56     private final WindowsPath file;
       
    57     private final boolean followLinks;
       
    58 
       
    59     WindowsAclFileAttributeView(WindowsPath file, boolean followLinks) {
       
    60         this.file = file;
       
    61         this.followLinks = followLinks;
       
    62     }
       
    63 
       
    64     // permision check
       
    65     private void checkAccess(WindowsPath file,
       
    66                              boolean checkRead,
       
    67                              boolean checkWrite)
       
    68     {
       
    69         SecurityManager sm = System.getSecurityManager();
       
    70         if (sm != null) {
       
    71             if (checkRead)
       
    72                 sm.checkRead(file.getPathForPermissionCheck());
       
    73             if (checkWrite)
       
    74                 sm.checkWrite(file.getPathForPermissionCheck());
       
    75             sm.checkPermission(new RuntimePermission("accessUserInformation"));
       
    76         }
       
    77     }
       
    78 
       
    79     // invokes GetFileSecurity to get requested security information
       
    80     static NativeBuffer getFileSecurity(String path, int request)
       
    81         throws IOException
       
    82     {
       
    83         // invoke get to buffer size
       
    84         int size = 0;
       
    85         try {
       
    86             size = GetFileSecurity(path, request, 0L, 0);
       
    87         } catch (WindowsException x) {
       
    88             x.rethrowAsIOException(path);
       
    89         }
       
    90         assert size > 0;
       
    91 
       
    92         // allocate buffer and re-invoke to get security information
       
    93         NativeBuffer buffer = NativeBuffers.getNativeBuffer(size);
       
    94         try {
       
    95             for (;;) {
       
    96                 int newSize = GetFileSecurity(path, request, buffer.address(), size);
       
    97                 if (newSize <= size)
       
    98                     return buffer;
       
    99 
       
   100                 // buffer was insufficient
       
   101                 buffer.release();
       
   102                 buffer = NativeBuffers.getNativeBuffer(newSize);
       
   103                 size = newSize;
       
   104             }
       
   105         } catch (WindowsException x) {
       
   106             buffer.release();
       
   107             x.rethrowAsIOException(path);
       
   108             return null;
       
   109         }
       
   110     }
       
   111 
       
   112     @Override
       
   113     public UserPrincipal getOwner()
       
   114         throws IOException
       
   115     {
       
   116         checkAccess(file, true, false);
       
   117 
       
   118         // GetFileSecurity does not follow links so when following links we
       
   119         // need the final target
       
   120         String path = WindowsLinkSupport.getFinalPath(file, followLinks);
       
   121         NativeBuffer buffer = getFileSecurity(path, OWNER_SECURITY_INFORMATION);
       
   122         try {
       
   123             // get the address of the SID
       
   124             long sidAddress = GetSecurityDescriptorOwner(buffer.address());
       
   125             if (sidAddress == 0L)
       
   126                 throw new IOException("no owner");
       
   127             return WindowsUserPrincipals.fromSid(sidAddress);
       
   128         } catch (WindowsException x) {
       
   129             x.rethrowAsIOException(file);
       
   130             return null;
       
   131         } finally {
       
   132             buffer.release();
       
   133         }
       
   134     }
       
   135 
       
   136     @Override
       
   137     public List<AclEntry> getAcl()
       
   138         throws IOException
       
   139     {
       
   140         checkAccess(file, true, false);
       
   141 
       
   142         // GetFileSecurity does not follow links so when following links we
       
   143         // need the final target
       
   144         String path = WindowsLinkSupport.getFinalPath(file, followLinks);
       
   145 
       
   146         // ALLOW and DENY entries in DACL;
       
   147         // AUDIT entries in SACL (ignore for now as it requires privileges)
       
   148         NativeBuffer buffer = getFileSecurity(path, DACL_SECURITY_INFORMATION);
       
   149         try {
       
   150             return WindowsSecurityDescriptor.getAcl(buffer.address());
       
   151         } finally {
       
   152             buffer.release();
       
   153         }
       
   154     }
       
   155 
       
   156     @Override
       
   157     public void setOwner(UserPrincipal obj)
       
   158         throws IOException
       
   159     {
       
   160         if (obj == null)
       
   161             throw new NullPointerException("'owner' is null");
       
   162         if (!(obj instanceof WindowsUserPrincipals.User))
       
   163             throw new ProviderMismatchException();
       
   164         WindowsUserPrincipals.User owner = (WindowsUserPrincipals.User)obj;
       
   165 
       
   166         // permission check
       
   167         checkAccess(file, false, true);
       
   168 
       
   169         // SetFileSecurity does not follow links so when following links we
       
   170         // need the final target
       
   171         String path = WindowsLinkSupport.getFinalPath(file, followLinks);
       
   172 
       
   173         // ConvertStringSidToSid allocates memory for SID so must invoke
       
   174         // LocalFree to free it when we are done
       
   175         long pOwner = 0L;
       
   176         try {
       
   177             pOwner = ConvertStringSidToSid(owner.sidString());
       
   178         } catch (WindowsException x) {
       
   179             throw new IOException("Failed to get SID for " + owner.getName()
       
   180                 + ": " + x.errorString());
       
   181         }
       
   182 
       
   183         // Allocate buffer for security descriptor, initialize it, set
       
   184         // owner information and update the file.
       
   185         try {
       
   186             NativeBuffer buffer = NativeBuffers.getNativeBuffer(SIZEOF_SECURITY_DESCRIPTOR);
       
   187             try {
       
   188                 InitializeSecurityDescriptor(buffer.address());
       
   189                 SetSecurityDescriptorOwner(buffer.address(), pOwner);
       
   190                 // may need SeRestorePrivilege to set the owner
       
   191                 WindowsSecurity.Privilege priv =
       
   192                     WindowsSecurity.enablePrivilege("SeRestorePrivilege");
       
   193                 try {
       
   194                     SetFileSecurity(path,
       
   195                                     OWNER_SECURITY_INFORMATION,
       
   196                                     buffer.address());
       
   197                 } finally {
       
   198                     priv.drop();
       
   199                 }
       
   200             } catch (WindowsException x) {
       
   201                 x.rethrowAsIOException(file);
       
   202             } finally {
       
   203                 buffer.release();
       
   204             }
       
   205         } finally {
       
   206             LocalFree(pOwner);
       
   207         }
       
   208     }
       
   209 
       
   210     @Override
       
   211     public void setAcl(List<AclEntry> acl) throws IOException {
       
   212         checkAccess(file, false, true);
       
   213 
       
   214         // SetFileSecurity does not follow links so when following links we
       
   215         // need the final target
       
   216         String path = WindowsLinkSupport.getFinalPath(file, followLinks);
       
   217         WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.create(acl);
       
   218         try {
       
   219             SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd.address());
       
   220         } catch (WindowsException x) {
       
   221              x.rethrowAsIOException(file);
       
   222         } finally {
       
   223             sd.release();
       
   224         }
       
   225     }
       
   226 }