Skip to content

Commit

Permalink
Merge pull request #606 from lgoldstein/validate-local-free
Browse files Browse the repository at this point in the history
Added Kerne32Util method to facilitate checking that calls to LocalFree/GlobalFree are successful
  • Loading branch information
lgoldstein committed Mar 5, 2016
2 parents bbc2291 + 8855dc9 commit 228177e
Show file tree
Hide file tree
Showing 8 changed files with 514 additions and 346 deletions.
7 changes: 4 additions & 3 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,21 @@ Features
* [#583](https://github.com/java-native-access/jna/pull/583): Added printer attributes and status - [@IvanRF](https://github.com/IvanRF).
* [#589](https://github.com/java-native-access/jna/pull/589): Use MethodResultContext in direct mapping (as done in interface mapping) - [@marco2357](https://github.com/marco2357).
* [#595](https://github.com/java-native-access/jna/pull/595): Allow calling COM methods/getters requiring hybrid calling (METHOD+PROPERTYGET) - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#582](https://github.com/java-native-access/jna/pull/582): Mavenize the build process - Phase 1: building the native code via Maven [@lgoldstein](https://github.com/lgoldstein)
* [#582](https://github.com/java-native-access/jna/pull/582): Mavenize the build process - Phase 1: building the native code via Maven [@lgoldstein](https://github.com/lgoldstein).
* [#606](https://github.com/java-native-access/jna/pull/606): Added Kerne32Util method to facilitate checking that calls to LocalFree/GlobalFree are successful [@lgoldstein](https://github.com/lgoldstein).

Bug Fixes
---------
* [#549](https://github.com/java-native-access/jna/pull/549): Fixed bug in types derived from XID - [@twall](https://github.com/twall).
* [#536](https://github.com/java-native-access/jna/pull/536): Fixed bug in determining the Library and options associated with types defined outside of a Library - [@twall](https://github.com/twall).
* [#531](https://github.com/java-native-access/jna/pull/531): Ensure direct-mapped callbacks use the right calling convention - [@twall](https://github.com/twall).
* [#566](https://github.com/java-native-access/jna/pull/566): Fix return type of Native#loadLibrary to match unconstrained generic [@lgoldstein](https://github.com/lgoldstein)
* [#566](https://github.com/java-native-access/jna/pull/566): Fix return type of Native#loadLibrary to match unconstrained generic [@lgoldstein](https://github.com/lgoldstein).
* [#584](https://github.com/java-native-access/jna/pull/584): Promote float varargs to double - [@marco2357](https://github.com/marco2357).
* [#588](https://github.com/java-native-access/jna/pull/588): Fix varargs calls on arm - [@twall](https://github.com/twall).
* [#593](https://github.com/java-native-access/jna/pull/593): Improve binding of TypeLib bindings - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#578](https://github.com/java-native-access/jna/pull/578): Fix COM CallbackHandlers, allow usage of VARIANTs directly in c.s.j.p.w.COM.util.ProxyObject and fix native memory leak in c.s.j.p.w.COM.util.ProxyObject - [@matthiasblaesing](https://github.com/matthiasblaesing)
* [#601](https://github.com/java-native-access/jna/pull/601): Remove COMThread and COM initialization from objects and require callers to initialize COM themselves. Asserts are added to guard correct usage. - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#602] https://github.com/java-native-access/jna/pull/602): Make sure SID related memory is properly released once no longer required [@lgoldstein](https://github.com/lgoldstein)
* [#602] https://github.com/java-native-access/jna/pull/602): Make sure SID related memory is properly released once no longer required [@lgoldstein](https://github.com/lgoldstein).

Release 4.2.1
=============
Expand Down
19 changes: 12 additions & 7 deletions contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ public static String convertSidToStringSid(PSID sid) {
try {
return ptr.getWideString(0);
} finally {
Kernel32.INSTANCE.LocalFree(ptr);
Kernel32Util.validateFreeLocalMemory(ptr);
}
}

Expand All @@ -323,7 +323,7 @@ public static byte[] convertStringSidToSid(String sidString) {
try {
return value.getBytes();
} finally {
Kernel32.INSTANCE.LocalFree(value.getPointer());
Kernel32Util.validateFreeLocalMemory(value.getPointer());
}
}

Expand All @@ -347,7 +347,7 @@ public static boolean isWellKnownSid(String sidString, int wellKnownSidType) {
try {
return Advapi32.INSTANCE.IsWellKnownSid(value, wellKnownSidType);
} finally {
Kernel32.INSTANCE.LocalFree(value.getPointer());
Kernel32Util.validateFreeLocalMemory(value.getPointer());
}
}

Expand Down Expand Up @@ -2207,10 +2207,15 @@ public static Memory getSecurityDescriptorForObject(final String absoluteObjectP
}

int nLength = Advapi32.INSTANCE.GetSecurityDescriptorLength(ppSecurityDescriptor.getValue());
final Memory memory = new Memory(nLength);
memory.write(0, ppSecurityDescriptor.getValue().getByteArray(0, nLength), 0, nLength);
Kernel32.INSTANCE.LocalFree(ppSecurityDescriptor.getValue());
return memory;
Memory memory = new Memory(nLength);
Pointer secValue = ppSecurityDescriptor.getValue();
try {
byte[] data = secValue.getByteArray(0, nLength);
memory.write(0, data, 0, nLength);
return memory;
} finally {
Kernel32Util.validateFreeLocalMemory(secValue);
}
}

/**
Expand Down
258 changes: 142 additions & 116 deletions contrib/platform/src/com/sun/jna/platform/win32/Crypt32Util.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/* Copyright (c) 2010 Daniel Doubrovkine, All Rights Reserved
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
*
* This library 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
* Lesser General Public License for more details.
* Lesser General Public License for more details.
*/
package com.sun.jna.platform.win32;

Expand All @@ -22,119 +22,145 @@
*/
public abstract class Crypt32Util {

/**
* Protect a blob of data.
* @param data
* Data to protect.
* @return
* Protected data.
*/
public static byte[] cryptProtectData(byte[] data) {
return cryptProtectData(data, 0);
}
/**
* Protect a blob of data.
* @param data
* Data to protect.
* @return
* Protected data.
*/
public static byte[] cryptProtectData(byte[] data) {
return cryptProtectData(data, 0);
}

/**
* Protect a blob of data with optional flags.
* @param data
* Data to protect.
* @param flags
* Optional flags, eg. CRYPTPROTECT_LOCAL_MACHINE | CRYPTPROTECT_UI_FORBIDDEN.
* @return
* Protected data.
*/
public static byte[] cryptProtectData(byte[] data, int flags) {
return cryptProtectData(data, null, flags, "", null);
}

/**
* Protect a blob of data.
* @param data
* Data to protect.
* @param entropy
* Optional entropy.
* @param flags
* Optional flags.
* @param description
* Optional description.
* @param prompt
* Prompt structure.
* @return
* Protected bytes.
*/
public static byte[] cryptProtectData(byte[] data, byte[] entropy, int flags,
String description, CRYPTPROTECT_PROMPTSTRUCT prompt) {
DATA_BLOB pDataIn = new DATA_BLOB(data);
DATA_BLOB pDataProtected = new DATA_BLOB();
DATA_BLOB pEntropy = (entropy == null) ? null : new DATA_BLOB(entropy);
try {
if (! Crypt32.INSTANCE.CryptProtectData(pDataIn, description,
pEntropy, null, prompt, flags, pDataProtected)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
return pDataProtected.getData();
} finally {
if (pDataProtected.pbData != null) {
Kernel32.INSTANCE.LocalFree(pDataProtected.pbData);
}
}
}

/**
* Unprotect a blob of data.
* @param data
* Data to unprotect.
* @return
* Unprotected blob of data.
*/
public static byte[] cryptUnprotectData(byte[] data) {
return cryptUnprotectData(data, 0);
}
/**
* Protect a blob of data with optional flags.
* @param data
* Data to protect.
* @param flags
* Optional flags, eg. CRYPTPROTECT_LOCAL_MACHINE | CRYPTPROTECT_UI_FORBIDDEN.
* @return
* Protected data.
*/
public static byte[] cryptProtectData(byte[] data, int flags) {
return cryptProtectData(data, null, flags, "", null);
}

/**
* Unprotect a blob of data.
* @param data
* Data to unprotect.
* @param flags
* Optional flags, eg. CRYPTPROTECT_UI_FORBIDDEN.
* @return
* Unprotected blob of data.
*/
public static byte[] cryptUnprotectData(byte[] data, int flags) {
return cryptUnprotectData(data, null, flags, null);
}

/**
* Unprotect a blob of data.
* @param data
* Data to unprotect.
* @param entropy
* Optional entropy.
* @param flags
* Optional flags.
* @param prompt
* Optional prompt structure.
* @return
* Unprotected blob of data.
*/
public static byte[] cryptUnprotectData(byte[] data, byte[] entropy, int flags,
CRYPTPROTECT_PROMPTSTRUCT prompt) {
DATA_BLOB pDataIn = new DATA_BLOB(data);
DATA_BLOB pDataUnprotected = new DATA_BLOB();
DATA_BLOB pEntropy = (entropy == null) ? null : new DATA_BLOB(entropy);
PointerByReference pDescription = new PointerByReference();
try {
if (! Crypt32.INSTANCE.CryptUnprotectData(pDataIn, pDescription,
pEntropy, null, prompt, flags, pDataUnprotected)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
return pDataUnprotected.getData();
} finally {
if (pDataUnprotected.pbData != null) {
Kernel32.INSTANCE.LocalFree(pDataUnprotected.pbData);
}
if (pDescription.getValue() != null) {
Kernel32.INSTANCE.LocalFree(pDescription.getValue());
}
}
}
/**
* Protect a blob of data.
* @param data
* Data to protect.
* @param entropy
* Optional entropy.
* @param flags
* Optional flags.
* @param description
* Optional description.
* @param prompt
* Prompt structure.
* @return
* Protected bytes.
*/
public static byte[] cryptProtectData(byte[] data, byte[] entropy, int flags,
String description, CRYPTPROTECT_PROMPTSTRUCT prompt) {
DATA_BLOB pDataIn = new DATA_BLOB(data);
DATA_BLOB pDataProtected = new DATA_BLOB();
DATA_BLOB pEntropy = (entropy == null) ? null : new DATA_BLOB(entropy);
try {
if (! Crypt32.INSTANCE.CryptProtectData(pDataIn, description,
pEntropy, null, prompt, flags, pDataProtected)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
return pDataProtected.getData();
} finally {
if (pDataProtected.pbData != null) {
Kernel32Util.validateFreeLocalMemory(pDataProtected.pbData);
}
}
}

/**
* Unprotect a blob of data.
* @param data
* Data to unprotect.
* @return
* Unprotected blob of data.
*/
public static byte[] cryptUnprotectData(byte[] data) {
return cryptUnprotectData(data, 0);
}

/**
* Unprotect a blob of data.
* @param data
* Data to unprotect.
* @param flags
* Optional flags, eg. CRYPTPROTECT_UI_FORBIDDEN.
* @return
* Unprotected blob of data.
*/
public static byte[] cryptUnprotectData(byte[] data, int flags) {
return cryptUnprotectData(data, null, flags, null);
}

/**
* Unprotect a blob of data.
* @param data
* Data to unprotect.
* @param entropy
* Optional entropy.
* @param flags
* Optional flags.
* @param prompt
* Optional prompt structure.
* @return
* Unprotected blob of data.
*/
public static byte[] cryptUnprotectData(byte[] data, byte[] entropy, int flags,
CRYPTPROTECT_PROMPTSTRUCT prompt) {
DATA_BLOB pDataIn = new DATA_BLOB(data);
DATA_BLOB pDataUnprotected = new DATA_BLOB();
DATA_BLOB pEntropy = (entropy == null) ? null : new DATA_BLOB(entropy);
PointerByReference pDescription = new PointerByReference();
Win32Exception err = null;
byte[] unProtectedData = null;
try {
if (! Crypt32.INSTANCE.CryptUnprotectData(pDataIn, pDescription,
pEntropy, null, prompt, flags, pDataUnprotected)) {
err = new Win32Exception(Kernel32.INSTANCE.GetLastError());
} else {
unProtectedData = pDataUnprotected.getData();
}
} finally {
if (pDataUnprotected.pbData != null) {
int rc = Kernel32Util.freeLocalMemory(pDataUnprotected.pbData);
if (rc != WinError.ERROR_SUCCESS) {
Win32Exception exc = new Win32Exception(rc);
if (err == null) {
err = exc;
} else {
err.addSuppressed(exc);
}
}
}

if (pDescription.getValue() != null) {
int rc = Kernel32Util.freeLocalMemory(pDescription.getValue());
if (rc != WinError.ERROR_SUCCESS) {
Win32Exception exc = new Win32Exception(rc);
if (err == null) {
err = exc;
} else {
err.addSuppressed(exc);
}
}
}
}

if (err != null) {
throw err;
}

return unProtectedData;
}
}
Loading

0 comments on commit 228177e

Please sign in to comment.