1 /* 2 * Copyright (c) 2008, 2024, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.fs; 27 28 import jdk.internal.vm.Continuation; 29 import jdk.internal.vm.ContinuationSupport; 30 31 import static sun.nio.fs.WindowsNativeDispatcher.*; 32 import static sun.nio.fs.WindowsConstants.*; 33 34 /** 35 * Security related utility methods. 36 */ 37 38 class WindowsSecurity { 39 private WindowsSecurity() { } 40 41 // opens process token for given access 42 private static long openProcessToken(int access) { 43 try { 44 return OpenProcessToken(GetCurrentProcess(), access); 45 } catch (WindowsException x) { 46 return 0L; 47 } 48 } 49 50 /** 51 * Returns the access token for this process with TOKEN_DUPLICATE access 52 */ 53 static final long processTokenWithDuplicateAccess = 54 openProcessToken(TOKEN_DUPLICATE); 55 56 /** 57 * Returns the access token for this process with TOKEN_QUERY access 58 */ 59 static final long processTokenWithQueryAccess = 60 openProcessToken(TOKEN_QUERY); 61 62 /** 63 * Returned by enablePrivilege when code may require a given privilege. 64 * The drop method should be invoked after the operation completes so as 65 * to revert the privilege. 66 */ 67 static interface Privilege { 68 void drop(); 69 } 70 71 /** 72 * Attempts to enable the given privilege for this method. 73 */ 74 static Privilege enablePrivilege(String priv) { 75 final long pLuid; 76 try { 77 pLuid = LookupPrivilegeValue(priv); 78 } catch (WindowsException x) { 79 // indicates bug in caller 80 throw new AssertionError(x); 81 } 82 83 long hToken = 0L; 84 boolean impersontating = false; 85 boolean elevated = false; 86 try { 87 hToken = OpenThreadToken(GetCurrentThread(), 88 TOKEN_ADJUST_PRIVILEGES, false); 89 if (hToken == 0L && processTokenWithDuplicateAccess != 0L) { 90 hToken = DuplicateTokenEx(processTokenWithDuplicateAccess, 91 (TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE)); 92 SetThreadToken(0L, hToken); 93 impersontating = true; 94 } 95 96 if (hToken != 0L) { 97 AdjustTokenPrivileges(hToken, pLuid, SE_PRIVILEGE_ENABLED); 98 elevated = true; 99 } 100 } catch (WindowsException x) { 101 // nothing to do, privilege not enabled 102 } 103 104 final long token = hToken; 105 final boolean stopImpersontating = impersontating; 106 final boolean needToRevert = elevated; 107 108 // prevent yielding with privileges 109 if (ContinuationSupport.isSupported()) 110 Continuation.pin(); 111 112 return () -> { 113 try { 114 if (token != 0L) { 115 try { 116 if (stopImpersontating) 117 SetThreadToken(0L, 0L); 118 else if (needToRevert) 119 AdjustTokenPrivileges(token, pLuid, 0); 120 } catch (WindowsException x) { 121 // should not happen 122 throw new AssertionError(x); 123 } finally { 124 CloseHandle(token); 125 } 126 } 127 } finally { 128 LocalFree(pLuid); 129 if (ContinuationSupport.isSupported()) 130 Continuation.unpin(); 131 } 132 }; 133 } 134 135 /** 136 * Check the access right against the securityInfo in the current thread. 137 */ 138 static boolean checkAccessMask(long securityInfo, int accessMask, 139 int genericRead, int genericWrite, int genericExecute, int genericAll) 140 throws WindowsException 141 { 142 int privileges = TOKEN_QUERY; 143 long hToken = OpenThreadToken(GetCurrentThread(), privileges, false); 144 if (hToken == 0L && processTokenWithDuplicateAccess != 0L) 145 hToken = DuplicateTokenEx(processTokenWithDuplicateAccess, 146 privileges); 147 148 boolean hasRight = false; 149 if (hToken != 0L) { 150 try { 151 hasRight = AccessCheck(hToken, securityInfo, accessMask, 152 genericRead, genericWrite, genericExecute, genericAll); 153 } finally { 154 CloseHandle(hToken); 155 } 156 } 157 return hasRight; 158 } 159 160 }