1 /* 2 * Copyright (c) 2008, 2025, 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 boolean pinned = ContinuationSupport.pinIfSupported(); 110 return () -> { 111 try { 112 if (token != 0L) { 113 try { 114 if (stopImpersontating) 115 SetThreadToken(0L, 0L); 116 else if (needToRevert) 117 AdjustTokenPrivileges(token, pLuid, 0); 118 } catch (WindowsException x) { 119 // should not happen 120 throw new AssertionError(x); 121 } finally { 122 CloseHandle(token); 123 } 124 } 125 } finally { 126 LocalFree(pLuid); 127 if (pinned) Continuation.unpin(); 128 } 129 }; 130 } 131 132 /** 133 * Check the access right against the securityInfo in the current thread. 134 */ 135 static boolean checkAccessMask(long securityInfo, int accessMask, 136 int genericRead, int genericWrite, int genericExecute, int genericAll) 137 throws WindowsException 138 { 139 int privileges = TOKEN_QUERY; 140 long hToken = OpenThreadToken(GetCurrentThread(), privileges, false); 141 if (hToken == 0L && processTokenWithDuplicateAccess != 0L) 142 hToken = DuplicateTokenEx(processTokenWithDuplicateAccess, 143 privileges); 144 145 boolean hasRight = false; 146 if (hToken != 0L) { 147 try { 148 hasRight = AccessCheck(hToken, securityInfo, accessMask, 149 genericRead, genericWrite, genericExecute, genericAll); 150 } finally { 151 CloseHandle(hToken); 152 } 153 } 154 return hasRight; 155 } 156 157 }