Skip to content

Commit

Permalink
Merge pull request #391 from khalidq/encryption
Browse files Browse the repository at this point in the history
Added encryption, decryption and raw backup functions to Advapi32
  • Loading branch information
dblock committed Jan 27, 2015
2 parents b792455 + 70cf574 commit 2f2667c
Show file tree
Hide file tree
Showing 6 changed files with 665 additions and 0 deletions.
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)
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

0 comments on commit 2f2667c

Please sign in to comment.