Skip to content

Commit

Permalink
Merge pull request #732 from Seven10Storage/master
Browse files Browse the repository at this point in the history
Added WinioctlUtil, Ntifs and modified Kernel32
  • Loading branch information
matthiasblaesing authored Dec 6, 2016
2 parents b6022ce + bfd9087 commit 7ab7ddc
Show file tree
Hide file tree
Showing 10 changed files with 2,081 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ Features
* [#689](https://github.com/java-native-access/jna/pull/689): Add `GetProcAddress(HMODULE, int)` to `com.sun.jna.platform.win32.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#723](https://github.com/java-native-access/jna/pull/723): Added `com.sun.jna.platform.win32.Wevtapi` and `com.sun.jna.platform.win32.Winevt` - [@sakamotodesu](https://github.com/sakamotodesu).
* [#720](https://github.com/java-native-access/jna/issues/720): Added `SetThreadExecutionState` to `com.sun.jna.platform.win32.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#732](https://github.com/java-native-access/jna/pull/732): Added `com.sun.jna.platform.win32.WinioctlUtil` for help in determining FSCTL_* codes - [@amarcionek](https://github.com/amarcionek).
* [#732](https://github.com/java-native-access/jna/pull/732): Added `com.sun.jna.platform.win32.Ntifs` with Reparse Point structures and defines - [@amarcionek](https://github.com/amarcionek).
* [#732](https://github.com/java-native-access/jna/pull/732): Added initialization of FILETIME from LARGE_INTEGER - [@amarcionek](https://github.com/amarcionek).
* [#732](https://github.com/java-native-access/jna/pull/732): Added `GetFileInformationByHandleEx` and `SetFileInformationByHandle` to `com.sun.jna.platform.win32.Kernel32` - [@amarcionek](https://github.com/amarcionek).

Bug Fixes
---------
Expand Down
206 changes: 206 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@
import static com.sun.jna.platform.win32.WinNT.SE_DACL_PROTECTED;
import static com.sun.jna.platform.win32.WinNT.SE_SACL_PROTECTED;
import static com.sun.jna.platform.win32.WinNT.STANDARD_RIGHTS_READ;
import static com.sun.jna.platform.win32.WinNT.TOKEN_ADJUST_PRIVILEGES;
import static com.sun.jna.platform.win32.WinNT.TOKEN_DUPLICATE;
import static com.sun.jna.platform.win32.WinNT.TOKEN_IMPERSONATE;
import static com.sun.jna.platform.win32.WinNT.TOKEN_QUERY;
import static com.sun.jna.platform.win32.WinNT.UNPROTECTED_DACL_SECURITY_INFORMATION;
import static com.sun.jna.platform.win32.WinNT.UNPROTECTED_SACL_SECURITY_INFORMATION;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
Expand Down Expand Up @@ -81,6 +83,7 @@
import com.sun.jna.platform.win32.WinNT.SECURITY_IMPERSONATION_LEVEL;
import com.sun.jna.platform.win32.WinNT.SID_AND_ATTRIBUTES;
import com.sun.jna.platform.win32.WinNT.SID_NAME_USE;
import com.sun.jna.platform.win32.WinNT.TOKEN_TYPE;
import com.sun.jna.platform.win32.WinReg.HKEY;
import com.sun.jna.platform.win32.WinReg.HKEYByReference;
import com.sun.jna.ptr.IntByReference;
Expand Down Expand Up @@ -2636,4 +2639,207 @@ public DWORD callback(Pointer pbData, Pointer pvCallbackContext,
// close
Advapi32.INSTANCE.CloseEncryptedFileRaw(pvContext.getValue());
}

/**
* Convenience class to enable certain Windows process privileges
*/
public static class Privilege implements Closeable {
/**
* If true, the thread is currently impersonating
*/
private boolean currentlyImpersonating = false;

/**
* If true, the privileges have been enabled
*/
private boolean privilegesEnabled = false;

/**
* LUID form of the privileges
*/
private final WinNT.LUID[] pLuids;

/**
* Construct and enable a set of privileges
* @param privileges the names of the privileges in the form of SE_* from Advapi32.java
* @throws IllegalArgumentException
*/
public Privilege(String... privileges) throws IllegalArgumentException, Win32Exception {
pLuids = new WinNT.LUID[privileges.length];
int i = 0;
for (String p : privileges) {
pLuids[i] = new WinNT.LUID();
if (!Advapi32.INSTANCE.LookupPrivilegeValue(null, p, pLuids[i])) {
throw new IllegalArgumentException("Failed to find privilege \"" + privileges[i] + "\" - " + Kernel32.INSTANCE.GetLastError());
}
i++;
}
}

/**
* Calls disable() to remove the privileges
* @see java.io.Closeable#close()
*/
@Override
public void close() {
this.disable();
}

/**
* Enables the given privileges. If required, it will duplicate the process token. No resources are left open when this completes. That is, it is
* NOT required to drop the privileges, although it is considered a best practice if you do not need it. This class is state full. It keeps track
* of whether it has enabled the privileges. Multiple calls to enable() without a drop() in between have no affect.
* @return pointer to self (Privilege) as a convenience for try with resources statements
* @throws Win32Exception
*/
public Privilege enable() throws Win32Exception {
// Ignore if already enabled.
if (privilegesEnabled)
return this;

// Get thread token
final HANDLEByReference phThreadToken = new HANDLEByReference();

try {
phThreadToken.setValue(getThreadToken());
WinNT.TOKEN_PRIVILEGES tp = new WinNT.TOKEN_PRIVILEGES(pLuids.length);
for (int i = 0; i < pLuids.length; i++) {
tp.Privileges[i] = new WinNT.LUID_AND_ATTRIBUTES(pLuids[i], new DWORD(WinNT.SE_PRIVILEGE_ENABLED));
}
if (!Advapi32.INSTANCE.AdjustTokenPrivileges(phThreadToken.getValue(), false, tp, 0, null, null)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
privilegesEnabled = true;
}
catch (Win32Exception ex) {
// If fails, clean up
if (currentlyImpersonating) {
Advapi32.INSTANCE.SetThreadToken(null, null);
currentlyImpersonating = false;
}
else {
if (privilegesEnabled) {
WinNT.TOKEN_PRIVILEGES tp = new WinNT.TOKEN_PRIVILEGES(pLuids.length);
for (int i = 0; i < pLuids.length; i++) {
tp.Privileges[i] = new WinNT.LUID_AND_ATTRIBUTES(pLuids[i], new DWORD(0));
}
Advapi32.INSTANCE.AdjustTokenPrivileges(phThreadToken.getValue(), false, tp, 0, null, null);
privilegesEnabled = false;
}
}
throw ex;
}
finally {
// Always close the thread token
if ((phThreadToken.getValue() != WinBase.INVALID_HANDLE_VALUE)
&& (phThreadToken.getValue() != null)) {
Kernel32.INSTANCE.CloseHandle(phThreadToken.getValue());
phThreadToken.setValue(null);
}
}
return this;
}

/**
* Disabled the prior enabled privilege
* @throws Win32Exception
*/
public void disable() throws Win32Exception {
// Get thread token
final HANDLEByReference phThreadToken = new HANDLEByReference();

try {
phThreadToken.setValue(getThreadToken());
if (currentlyImpersonating) {
Advapi32.INSTANCE.SetThreadToken(null, null);
}
else
{
if (privilegesEnabled) {
WinNT.TOKEN_PRIVILEGES tp = new WinNT.TOKEN_PRIVILEGES(pLuids.length);
for (int i = 0; i < pLuids.length; i++) {
tp.Privileges[i] = new WinNT.LUID_AND_ATTRIBUTES(pLuids[i], new DWORD(0));
}
Advapi32.INSTANCE.AdjustTokenPrivileges(phThreadToken.getValue(), false, tp, 0, null, null);
privilegesEnabled = false;
}
}
}
finally {
// Close the thread token
if ((phThreadToken.getValue() != WinBase.INVALID_HANDLE_VALUE)
&& (phThreadToken.getValue() != null)) {
Kernel32.INSTANCE.CloseHandle(phThreadToken.getValue());
phThreadToken.setValue(null);
}
}
}

/**
* Get a handle to the thread token. May duplicate the process token
* and set as the thread token if ther thread has no token.
* @return HANDLE to the thread token
* @throws Win32Exception
*/
private HANDLE getThreadToken() throws Win32Exception {
// we need to create a new token here for the duplicate
final HANDLEByReference phThreadToken = new HANDLEByReference();
final HANDLEByReference phProcessToken = new HANDLEByReference();

try {
// open thread token
if (!Advapi32.INSTANCE.OpenThreadToken(Kernel32.INSTANCE.GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES,
false,
phThreadToken)) {
// OpenThreadToken may fail with W32Errors.ERROR_NO_TOKEN if current thread is anonymous. Check for that condition here. If not, throw an error.
int lastError = Kernel32.INSTANCE.GetLastError();
if (W32Errors.ERROR_NO_TOKEN != lastError) {
throw new Win32Exception(lastError);
}

// Due to ERROR_NO_TOKEN, we need to open the process token to duplicate it, then set our thread token.
if (!Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(), TOKEN_DUPLICATE, phProcessToken)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}

// Process token opened, now duplicate
if (!Advapi32.INSTANCE.DuplicateTokenEx(phProcessToken.getValue(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_IMPERSONATE,
null,
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
TOKEN_TYPE.TokenImpersonation,
phThreadToken)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}

// And set thread token.
if (!Advapi32.INSTANCE.SetThreadToken(null, phThreadToken.getValue())) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
currentlyImpersonating = true;
}
}
catch (Win32Exception ex) {
// Close the thread token
if ((phThreadToken.getValue() != WinBase.INVALID_HANDLE_VALUE)
&& (phThreadToken.getValue() != null)) {
Kernel32.INSTANCE.CloseHandle(phThreadToken.getValue());
phThreadToken.setValue(null);
}
throw ex;
}
finally
{
// Always close the process token
if ((phProcessToken.getValue() != WinBase.INVALID_HANDLE_VALUE)
&& (phProcessToken.getValue() != null)) {
Kernel32.INSTANCE.CloseHandle(phProcessToken.getValue());
phProcessToken.setValue(null);
}
}

return phThreadToken.getValue();
}
}
}
Loading

0 comments on commit 7ab7ddc

Please sign in to comment.