Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added encryption, decryption and raw backup functions to Advapi32 #391

Merged
merged 3 commits into from
Jan 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Features
* [#365](https://github.com/twall/jna/pull/365): Added `com.sun.jna.platform.win32.Kernel32.GetComputerNameEx` support - [@lgoldstein](https://github.com/lgoldstein).
* [#368](https://github.com/twall/jna/pull/368): Added `com.sun.jna.platform.win32.Kernel32.VirtualQueryEx`, `com.sun.jna.platform.win32.WinNT.MEMORY_BASIC_INFORMATION` and `MEM_COMMIT`, `MEM_FREE`, `MEM_RESERVE`, `MEM_IMAGE`, `MEM_MAPPED`, `MEM_PRIVATE` constants to `com.sun.jna.platform.win32.WinNT` - [@apsk](https://github.com/apsk).
* Allow interoperation with JNI revision changes - [@twall](https://github.com/twall).
* [#391](https://github.com/twall/jna/pull/391): Added `EncryptFile`, `DecryptFile`, `FileEncryptionStatus`, `EncryptionDisable`, `OpenEncryptedFileRaw`, `ReadEncryptedFileRaw`, `WriteEncryptedFileRaw`, and `CloseEncryptedFileRaw` to `com.sun.jna.platform.win32.Advapi32` with related `Advapi32Util` helpers - [@khalidq](https://github.com/khalidq).

Bug Fixes
---------
Expand Down
152 changes: 152 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Advapi32.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import com.sun.jna.Structure;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinBase.SECURITY_ATTRIBUTES;
import com.sun.jna.platform.win32.WinBase.FE_EXPORT_FUNC;
import com.sun.jna.platform.win32.WinBase.FE_IMPORT_FUNC;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
import com.sun.jna.platform.win32.WinNT.PSID;
Expand All @@ -35,6 +37,7 @@
import static com.sun.jna.platform.win32.WinDef.BOOLByReference;
import static com.sun.jna.platform.win32.WinDef.DWORD;
import static com.sun.jna.platform.win32.WinDef.DWORDByReference;
import static com.sun.jna.platform.win32.WinDef.ULONG;
import static com.sun.jna.platform.win32.WinNT.GENERIC_MAPPING;
import static com.sun.jna.platform.win32.WinNT.PRIVILEGE_SET;

Expand Down Expand Up @@ -1558,4 +1561,153 @@ public boolean AccessCheck(Pointer pSecurityDescriptor,
PRIVILEGE_SET PrivilegeSet,
DWORDByReference PrivilegeSetLength,
DWORDByReference GrantedAccess, BOOLByReference AccessStatus);

/**
* Encrypts a file or directory. All data streams in a file are encrypted. All
* new files created in an encrypted directory are encrypted.
*
* @param lpFileName
* The name of the file or directory to be encrypted.
* @return If the function succeeds, the return value is nonzero. If the
* function fails, the return value is zero. To get extended error
* information, call GetLastError.
*/
public boolean EncryptFile(WString lpFileName);

/**
* Decrypts an encrypted file or directory.
*
* @param lpFileName
* The name of the file or directory to be decrypted.
* @param dwReserved
* Reserved; must be zero.
* @return If the function succeeds, the return value is nonzero. If the
* function fails, the return value is zero. To get extended error
* information, call GetLastError.
*/
public boolean DecryptFile(WString lpFileName, DWORD dwReserved);

/**
* Retrieves the encryption status of the specified file.
*
* @param lpFileName
* The name of the file.
* @param lpStatus
* A pointer to a variable that receives the encryption status of the
* file.
* @return If the function succeeds, the return value is nonzero. If the
* function fails, the return value is zero. To get extended error
* information, call GetLastError.
*/
public boolean FileEncryptionStatus(WString lpFileName, DWORDByReference lpStatus);

/**
* Disables or enables encryption of the specified directory and the files in
* it. It does not affect encryption of subdirectories below the indicated
* directory.
*
* @param DirPath
* The name of the directory for which to enable or disable
* encryption.
* @param Disable
* Indicates whether to disable encryption (TRUE) or enable it
* (FALSE).
* @return If the function succeeds, the return value is nonzero. If the
* function fails, the return value is zero. To get extended error
* information, call GetLastError.
*/
public boolean EncryptionDisable(WString DirPath, boolean Disable);

/**
* Opens an encrypted file in order to backup (export) or restore (import) the
* file. This is one of a group of Encrypted File System (EFS) functions that
* is intended to implement backup and restore functionality, while
* maintaining files in their encrypted state.
*
* @param lpFileName
* The name of the file to be opened. The string must consist of
* characters from the Windows character set.
* @param ulFlags
* The operation to be performed.
* @param pvContext
* The address of a context block that must be presented in subsequent
* calls to ReadEncryptedFileRaw, WriteEncryptedFileRaw, or
* CloseEncryptedFileRaw. Do not modify it.
* @return If the function succeeds, it returns ERROR_SUCCESS. If the function
* fails, it returns a nonzero error code defined in WinError.h. You can use
* FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a generic
* text description of the error.
*/
public int OpenEncryptedFileRaw(WString lpFileName, ULONG ulFlags,
PointerByReference pvContext);

/**
* Backs up (export) encrypted files. This is one of a group of Encrypted File
* System (EFS) functions that is intended to implement backup and restore
* functionality, while maintaining files in their encrypted state.
*
* @param pfExportCallback
* A pointer to the export callback function. The system calls the
* callback function multiple times, each time passing a block of the
* file's data to the callback function until the entire file has been
* read. For more information, see ExportCallback.
* @param pvCallbackContext
* A pointer to an application-defined and allocated context block.
* The system passes this pointer to the callback function as a
* parameter so that the callback function can have access to
* application-specific data. This can be a structure and can contain
* any data the application needs, such as the handle to the file that
* will contain the backup copy of the encrypted file.
* @param pvContext
* A pointer to a system-defined context block. The context block is
* returned by the OpenEncryptedFileRaw function. Do not modify it.
* @return If the function succeeds, the return value is ERROR_SUCCESS. If the
* function fails, it returns a nonzero error code defined in WinError.h. You
* can use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a
* generic text description of the error.
*/
public int ReadEncryptedFileRaw(FE_EXPORT_FUNC pfExportCallback,
Pointer pvCallbackContext, Pointer pvContext);

/**
* Restores (import) encrypted files. This is one of a group of Encrypted File
* System (EFS) functions that is intended to implement backup and restore
* functionality, while maintaining files in.
*
* @param pfImportCallback
* A pointer to the import callback function. The system calls the
* callback function multiple times, each time passing a buffer that
* will be filled by the callback function with a portion of backed-up
* file's data. When the callback function signals that the entire
* file has been processed, it tells the system that the restore
* operation is finished. For more information, see ImportCallback.
* @param pvCallbackContext
* A pointer to an application-defined and allocated context block.
* The system passes this pointer to the callback function as a
* parameter so that the callback function can have access to
* application-specific data. This can be a structure and can contain
* any data the application needs, such as the handle to the file that
* will contain the backup copy of the encrypted file.
* @param pvContext
* A pointer to a system-defined context block. The context block is
* returned by the OpenEncryptedFileRaw function. Do not modify it.
* @return If the function succeeds, the return value is ERROR_SUCCESS. If the
* function fails, it returns a nonzero error code defined in WinError.h. You
* can use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a
* generic text description of the error.
*/
public int WriteEncryptedFileRaw(FE_IMPORT_FUNC pfImportCallback,
Pointer pvCallbackContext, Pointer pvContext);

/**
* Closes an encrypted file after a backup or restore operation, and frees
* associated system resources. This is one of a group of Encrypted File
* System (EFS) functions that is intended to implement backup and restore
* functionality, while maintaining files in their encrypted state.
*
* @param pvContext
* A pointer to a system-defined context block. The
* OpenEncryptedFileRaw function returns the context block.
*/
public void CloseEncryptedFileRaw(Pointer pvContext);
}
158 changes: 158 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
*/
package com.sun.jna.platform.win32;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
Expand All @@ -37,6 +39,7 @@
import com.sun.jna.platform.win32.WinNT.SID_NAME_USE;
import com.sun.jna.platform.win32.WinReg.HKEY;
import com.sun.jna.platform.win32.WinReg.HKEYByReference;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.PointerByReference;
Expand Down Expand Up @@ -2185,4 +2188,159 @@ public static boolean accessCheck(File file, AccessCheckPermission permissionToC

return hasAccess;
}

/**
* Encrypts a file or directory.
*
* @param file
* The file or directory to encrypt.
*/
public static void encryptFile(File file) {
WString lpFileName = new WString(file.getAbsolutePath());
if (!Advapi32.INSTANCE.EncryptFile(lpFileName)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
}

/**
* Decrypts an encrypted file or directory.
*
* @param file
* The file or directory to decrypt.
*/
public static void decryptFile(File file) {
WString lpFileName = new WString(file.getAbsolutePath());
if (!Advapi32.INSTANCE.DecryptFile(lpFileName, new DWORD(0))) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
}

/**
* Checks the encryption status of a file.
*
* @param file
* The file to check the status for.
* @return The status of the file.
*/
public static int fileEncryptionStatus(File file) {
DWORDByReference status = new DWORDByReference();
WString lpFileName = new WString(file.getAbsolutePath());
if (!Advapi32.INSTANCE.FileEncryptionStatus(lpFileName, status)) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
return status.getValue().intValue();
}

/**
* Disables or enables encryption of the specified directory and the files in
* it.
*
* @param directory
* The directory for which to enable or disable encryption.
* @param disable
* TRUE to disable encryption. FALSE to enable it.
*/
public static void disableEncryption(File directory, boolean disable) {
WString dirPath = new WString(directory.getAbsolutePath());
if (!Advapi32.INSTANCE.EncryptionDisable(dirPath, disable)) {
throw new Win32Exception(Native.getLastError());
}
}

/**
* Backup an encrypted file or folder without decrypting it. A file named
* "bar/sample.text" will be backed-up to "destDir/sample.text". A directory
* named "bar" will be backed-up to "destDir/bar". This method is NOT
* recursive. If you have an encrypted directory with encrypted files, this
* method must be called once for the directory, and once for each encrypted
* file to be backed-up.
*
* @param src
* The encrypted file or directory to backup.
* @param destDir
* The directory where the backup will be saved.
*/
public static void backupEncryptedFile(File src, File destDir) {
if (!destDir.isDirectory()) {
throw new IllegalArgumentException("destDir must be a directory.");
}

ULONG readFlag = new ULONG(0); // Open the file for export (backup)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This are flags, such as CREATE_FOR_IMPORT, should be defined that way elsewhere (corresponding to the .h file).

ULONG writeFlag = new ULONG(CREATE_FOR_IMPORT); // Import (restore) file

if (src.isDirectory()) {
writeFlag.setValue(CREATE_FOR_IMPORT | CREATE_FOR_DIR);
}

// open encrypted file for export
WString srcFileName = new WString(src.getAbsolutePath());
PointerByReference pvContext = new PointerByReference();
if (Advapi32.INSTANCE.OpenEncryptedFileRaw(srcFileName, readFlag,
pvContext) != W32Errors.ERROR_SUCCESS) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}

// read encrypted file
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
FE_EXPORT_FUNC pfExportCallback = new FE_EXPORT_FUNC() {
@Override
public DWORD callback(ByteByReference pbData, Pointer pvCallbackContext,
ULONG ulLength) {
byte[] arr = pbData.getPointer().getByteArray(0, ulLength.intValue());
try {
outputStream.write(arr);
} catch (IOException e) {
throw new RuntimeException(e);
}
return new DWORD(W32Errors.ERROR_SUCCESS);
}
};

if (Advapi32.INSTANCE.ReadEncryptedFileRaw(pfExportCallback, null,
pvContext.getValue()) != W32Errors.ERROR_SUCCESS) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}

// close
try {
outputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
Advapi32.INSTANCE.CloseEncryptedFileRaw(pvContext.getValue());

// open file for import
WString destFileName = new WString(destDir.getAbsolutePath() + File.separator
+ src.getName());
pvContext = new PointerByReference();
if (Advapi32.INSTANCE.OpenEncryptedFileRaw(destFileName, writeFlag,
pvContext) != W32Errors.ERROR_SUCCESS) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}

// write encrypted file
final IntByReference elementsReadWrapper = new IntByReference(0);
FE_IMPORT_FUNC pfImportCallback = new FE_IMPORT_FUNC() {
@Override
public DWORD callback(ByteByReference pbData, Pointer pvCallbackContext,
ULONGByReference ulLength) {
int elementsRead = elementsReadWrapper.getValue();
int remainingElements = outputStream.size() - elementsRead;
int length = Math.min(remainingElements, ulLength.getValue().intValue());
pbData.getPointer().write(0, outputStream.toByteArray(), elementsRead,
length);
elementsReadWrapper.setValue(elementsRead + length);
ulLength.setValue(new ULONG(length));
return new DWORD(W32Errors.ERROR_SUCCESS);
}
};

if (Advapi32.INSTANCE.WriteEncryptedFileRaw(pfImportCallback, null,
pvContext.getValue()) != W32Errors.ERROR_SUCCESS) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}

// close
Advapi32.INSTANCE.CloseEncryptedFileRaw(pvContext.getValue());
}
}
Loading