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

Add CertOpenStore to c.s.j.p.win32.Crypt32 #1418

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -11,6 +11,7 @@ Features
* [#1403](https://github.com/java-native-access/jna/pull/1403): Rebuild AIX binaries with libffi 3.4.2 (other architectures were part of 5.10) - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#1404](https://github.com/java-native-access/jna/issues/1404): Added Solaris Kstat2 library - [@dbwiddis](https://github.com/dbwiddis).
* [#1416](https://github.com/java-native-access/jna/pull/1416): Add `CFDictionaryGetCount` to `c.s.j.p.mac.CoreFoundation` - [@shalupov](https://github.com/shalupov)
* [#1418](https://github.com/java-native-access/jna/pull/1418): Add `CertOpenStore` to `c.s.j.p.win32.Crypt32` - [@shalupov](https://github.com/shalupov)

Bug Fixes
---------
Expand Down
81 changes: 77 additions & 4 deletions contrib/platform/src/com/sun/jna/platform/win32/Crypt32.java
Expand Up @@ -23,8 +23,7 @@
*/
package com.sun.jna.platform.win32;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.*;
import com.sun.jna.platform.win32.WinCrypt.CRYPTPROTECT_PROMPTSTRUCT;
import com.sun.jna.platform.win32.WinCrypt.DATA_BLOB;
import com.sun.jna.ptr.PointerByReference;
Expand Down Expand Up @@ -157,11 +156,83 @@ public boolean CryptUnprotectData(DATA_BLOB pDataIn, PointerByReference szDataDe
*/
boolean CertAddEncodedCertificateToSystemStore(String szCertStoreName, Pointer pbCertEncoded, int cbCertEncoded);

/**
* The {@code CertOpenStore} function opens a certificate store by using a specified store provider type
*
* @param lpszStoreProvider
* A pointer to a null-terminated ANSI string that contains the store provider type.
* @param dwEncodingType
* Specifies the <a href="https://docs.microsoft.com/en-us/windows/desktop/SecGloss/c-gly">certificate encoding type</a>
* and <a href="https://docs.microsoft.com/en-us/windows/desktop/SecGloss/m-gly">message encoding</a> type.
* Encoding is used only when the {@code dwSaveAs} parameter of the
* <a href="https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-certsavestore">CertSaveStore</a>
* function contains {@code CERT_STORE_SAVE_AS_PKCS7}.
* Otherwise, the {@code dwMsgAndCertEncodingType} parameter is not used.
* @param hCryptProv
* This parameter is not used and should be set to NULL.
* @param dwFlags
* These values consist of high-word and low-word values combined by using a bitwise-OR operation.
* See {@code CERT_STORE_*_FLAG} and {@code CERT_SYSTEM_STORE_*} constants.
* @param pvPara
* Additional information for this function. The contents of
* this parameter depends on the value of the {@code lpszStoreProvider} and other parameters.
* @return
* If the function succeeds, the function returns a handle to the certificate store.
* When you have finished using the store, release the handle by calling the
* {@link com.sun.jna.platform.win32.Crypt32#CertCloseStore(WinCrypt.HCERTSTORE, int)} function.
* If the function fails, it returns NULL. For extended error information,
* call {@link Native#getLastError()}.
*
* @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certopenstore">MSDN</a>
*/
WinCrypt.HCERTSTORE CertOpenStore(
CertStoreProviderName lpszStoreProvider,
int dwEncodingType,
WinCrypt.HCRYPTPROV_LEGACY hCryptProv,
int dwFlags,
Pointer pvPara);

/**
* The {@code CertOpenStore} function opens a certificate store by using a specified store provider type
*
* @param lpszStoreProvider
* A pointer to a null-terminated ANSI string that contains the store provider type.
* @param dwEncodingType
* Specifies the <a href="https://docs.microsoft.com/en-us/windows/desktop/SecGloss/c-gly">certificate encoding type</a>
* and <a href="https://docs.microsoft.com/en-us/windows/desktop/SecGloss/m-gly">message encoding</a> type.
* Encoding is used only when the {@code dwSaveAs} parameter of the
* <a href="https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-certsavestore">CertSaveStore</a>
* function contains {@code CERT_STORE_SAVE_AS_PKCS7}.
* Otherwise, the {@code dwMsgAndCertEncodingType} parameter is not used.
* @param hCryptProv
* This parameter is not used and should be set to NULL.
* @param dwFlags
* These values consist of high-word and low-word values combined by using a bitwise-OR operation.
* See {@code CERT_STORE_*_FLAG} and {@code CERT_SYSTEM_STORE_*} constants.
* @param pvPara
* Additional information for this function in {@link WTypes.LPWSTR} form. The contents of
* this parameter depends on the value of the {@code lpszStoreProvider} and other parameters.
* @return
* If the function succeeds, the function returns a handle to the certificate store.
* When you have finished using the store, release the handle by calling the
* {@link com.sun.jna.platform.win32.Crypt32#CertCloseStore(WinCrypt.HCERTSTORE, int)} function.
* If the function fails, it returns NULL. For extended error information,
* call {@link Native#getLastError()}.
*
* @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certopenstore">MSDN</a>
*/
WinCrypt.HCERTSTORE CertOpenStore(
CertStoreProviderName lpszStoreProvider,
int dwEncodingType,
WinCrypt.HCRYPTPROV_LEGACY hCryptProv,
int dwFlags,
WTypes.LPWSTR pvPara);

/**
* The CertOpenSystemStore function is a simplified function that opens the
* most common system certificate store. To open certificate stores with
* more complex requirements, such as file-based or memory-based stores, use
* CertOpenStore.
* {@link #CertOpenStore(CertStoreProviderName, int, HCRYPTPROV_LEGACY, int, Pointer)}.
*
* @param hprov This parameter is not used and should be set to NULL.
* @param szSubsystemProtocol A string that names a system store. If the
Expand All @@ -171,7 +242,9 @@ public boolean CryptUnprotectData(DATA_BLOB pDataIn, PointerByReference szDataDe
* stores. Some example system stores are listed in the following table.
* @return If the function succeeds, the function returns a handle to the
* certificate store. If the function fails, it returns NULL. For extended
* error information, call GetLastError.
* error information, call {@link Native#getLastError()}
*
* @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certopensystemstorew">MSDN</a>
*/
HCERTSTORE CertOpenSystemStore(Pointer hprov, String szSubsystemProtocol);

Expand Down
107 changes: 107 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/WinCrypt.java
Expand Up @@ -23,8 +23,10 @@
*/
package com.sun.jna.platform.win32;

import com.sun.jna.FromNativeContext;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.NativeMapped;
import com.sun.jna.Pointer;
import com.sun.jna.StringArray;
import com.sun.jna.Structure;
Expand Down Expand Up @@ -1194,6 +1196,49 @@ public CRYPTPROTECT_PROMPTSTRUCT(Pointer memory) {
}
}

/**
* Value wrapper for {@code lpszStoreProvider} of {@link Crypt32#CertOpenStore(CertStoreProviderName, int, HCRYPTPROV_LEGACY, int, Pointer)}
*/
class CertStoreProviderName implements NativeMapped {
private final Pointer pointer;

private CertStoreProviderName(Pointer fixedValue) {
this.pointer = fixedValue;
}

public CertStoreProviderName() {
pointer = Pointer.NULL;
}

public CertStoreProviderName(int fixedValue) {
this.pointer = Pointer.createConstant(fixedValue);
}

public CertStoreProviderName(String name) {
byte[] nameBytes = Native.toByteArray(name);
this.pointer = new Memory(nameBytes.length);
this.pointer.write(0, nameBytes, 0, nameBytes.length);
}

@Override
public Object fromNative(Object nativeValue, FromNativeContext fnc) {
if (nativeValue == null) {
return null;
}
return new CertStoreProviderName((Pointer) nativeValue);
}

@Override
public Object toNative() {
return pointer;
}

@Override
public Class<?> nativeType() {
return Pointer.class;
}
}

//
// CryptProtect PromptStruct dwPromtFlags
//
Expand Down Expand Up @@ -1617,6 +1662,68 @@ public CRYPTPROTECT_PROMPTSTRUCT(Pointer memory) {
*/
int PKCS12_INCLUDE_EXTENDED_PROPERTIES = 0x0010;

//
// Store providers for CertOpenStore
//

int CERT_STORE_PROV_MSG = 1;
int CERT_STORE_PROV_MEMORY = 2;
int CERT_STORE_PROV_FILE = 3;
int CERT_STORE_PROV_REG = 4;
int CERT_STORE_PROV_PKCS7 = 5;
int CERT_STORE_PROV_SERIALIZED = 6;
int CERT_STORE_PROV_FILENAME_A = 7; // ASCII
int CERT_STORE_PROV_FILENAME_W = 8; // Unicode
int CERT_STORE_PROV_FILENAME = CERT_STORE_PROV_FILENAME_W;
int CERT_STORE_PROV_SYSTEM_A = 9; // pvPara is ASCII (1 byte/char)
int CERT_STORE_PROV_SYSTEM_W = 10; // pvPara is Unicode (2 bytes/char)
int CERT_STORE_PROV_SYSTEM = CERT_STORE_PROV_SYSTEM_W;
int CERT_STORE_PROV_COLLECTION = 11;
int CERT_STORE_PROV_SYSTEM_REGISTRY_A = 12;
int CERT_STORE_PROV_SYSTEM_REGISTRY_W = 13;
int CERT_STORE_PROV_SYSTEM_REGISTRY = CERT_STORE_PROV_SYSTEM_REGISTRY_W;
int CERT_STORE_PROV_PHYSICAL_W = 14;
int CERT_STORE_PROV_PHYSICAL = CERT_STORE_PROV_PHYSICAL_W;
int CERT_STORE_PROV_SMART_CARD_W = 15;
int CERT_STORE_PROV_SMART_CARD = CERT_STORE_PROV_SMART_CARD_W;
int CERT_STORE_PROV_LDAP_W = 16;
int CERT_STORE_PROV_LDAP = CERT_STORE_PROV_LDAP_W;

//
// Store characteristics for CertOpenStore
//

int CERT_STORE_NO_CRYPT_RELEASE_FLAG = 0x00000001;
int CERT_STORE_SET_LOCALIZED_NAME_FLAG = 0x00000002;
int CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004;
int CERT_STORE_DELETE_FLAG = 0x00000010;
int CERT_STORE_UNSAFE_PHYSICAL_FLAG = 0x00000020;
int CERT_STORE_SHARE_STORE_FLAG = 0x00000040;
int CERT_STORE_SHARE_CONTEXT_FLAG = 0x00000080;
int CERT_STORE_MANIFOLD_FLAG = 0x00000100;
int CERT_STORE_ENUM_ARCHIVED_FLAG = 0x00000200;
int CERT_STORE_UPDATE_KEYID_FLAG = 0x00000400;
int CERT_STORE_BACKUP_RESTORE_FLAG = 0x00000800;
int CERT_STORE_MAXIMUM_ALLOWED_FLAG = 0x00001000;
int CERT_STORE_CREATE_NEW_FLAG = 0x00002000;
int CERT_STORE_OPEN_EXISTING_FLAG = 0x00004000;
int CERT_STORE_READONLY_FLAG = 0x00008000;

//
// Store locations for CertOpenStore
//

int CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000;
int CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000;
int CERT_SYSTEM_STORE_CURRENT_SERVICE = 0x00040000;
int CERT_SYSTEM_STORE_SERVICES = 0x00050000;
int CERT_SYSTEM_STORE_USERS = 0x00060000;
int CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY = 0x00070000;
int CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY = 0x00080000;
int CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE = 0x00090000;
int CERT_SYSTEM_STORE_UNPROTECTED_FLAG = 0x40000000;
int CERT_SYSTEM_STORE_RELOCATE_FLAG = 0x80000000;

/**
* Checks for nonfreed certificate, CRL, and CTL contexts. A returned error
* code indicates that one or more store elements is still in use. This flag
Expand Down
28 changes: 25 additions & 3 deletions contrib/platform/test/com/sun/jna/platform/win32/Crypt32Test.java
Expand Up @@ -423,10 +423,32 @@ public void testCertVerifyCertificateChainPolicy() {
assertTrue("The status would be true since a valid certificate chain was not passed in.", status);
}

public void testCertEnumCertificatesInStore() {
String SYSTEM_STORE_NAME = "ROOT";
WinCrypt.HCERTSTORE hCertStore = Crypt32.INSTANCE.CertOpenSystemStore(null, SYSTEM_STORE_NAME);
public void testCertOpenSystemStore() {
WinCrypt.HCERTSTORE hCertStore = Crypt32.INSTANCE.CertOpenSystemStore(null, "ROOT");
enumerateRootCertificates(hCertStore);
}

public void testCertOpenStoreWithPointerPara() {
WinCrypt.HCERTSTORE hCertStore = Crypt32.INSTANCE.CertOpenStore(
new WinCrypt.CertStoreProviderName(WinCrypt.CERT_STORE_PROV_SYSTEM_REGISTRY_W),
0,
null,
WinCrypt.CERT_SYSTEM_STORE_LOCAL_MACHINE | WinCrypt.CERT_STORE_OPEN_EXISTING_FLAG | WinCrypt.CERT_STORE_READONLY_FLAG,
new WTypes.LPWSTR("ROOT"));
enumerateRootCertificates(hCertStore);
}

public void testCertOpenStoreWithStringPara() {
WinCrypt.HCERTSTORE hCertStore = Crypt32.INSTANCE.CertOpenStore(
new WinCrypt.CertStoreProviderName(WinCrypt.CERT_STORE_PROV_SYSTEM_REGISTRY_W),
0,
null,
WinCrypt.CERT_SYSTEM_STORE_LOCAL_MACHINE | WinCrypt.CERT_STORE_OPEN_EXISTING_FLAG | WinCrypt.CERT_STORE_READONLY_FLAG,
new WTypes.LPWSTR("ROOT").getPointer());
shalupov marked this conversation as resolved.
Show resolved Hide resolved
enumerateRootCertificates(hCertStore);
}

private void enumerateRootCertificates(HCERTSTORE hCertStore) {
int readCertificates = 0;
int readExtensions = 0;

Expand Down