6782021: It is not possible to read local computer certificates with the SunMSCAPI provider
Reviewed-by: weijun
This commit is contained in:
parent
d65fba412e
commit
5e5500cbd7
src
java.base/share/classes/sun/security/tools
jdk.crypto.mscapi/windows
test/jdk/sun/security/mscapi
@ -91,7 +91,11 @@ public class KeyStoreUtil {
|
||||
public static boolean isWindowsKeyStore(String storetype) {
|
||||
return storetype != null
|
||||
&& (storetype.equalsIgnoreCase("Windows-MY")
|
||||
|| storetype.equalsIgnoreCase("Windows-ROOT"));
|
||||
|| storetype.equalsIgnoreCase("Windows-ROOT")
|
||||
|| storetype.equalsIgnoreCase("Windows-MY-CURRENTUSER")
|
||||
|| storetype.equalsIgnoreCase("Windows-ROOT-CURRENTUSER")
|
||||
|| storetype.equalsIgnoreCase("Windows-MY-LOCALMACHINE")
|
||||
|| storetype.equalsIgnoreCase("Windows-ROOT-LOCALMACHINE"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,6 +106,14 @@ public class KeyStoreUtil {
|
||||
return "Windows-MY";
|
||||
} else if(storetype.equalsIgnoreCase("Windows-ROOT")) {
|
||||
return "Windows-ROOT";
|
||||
} else if(storetype.equalsIgnoreCase("Windows-MY-CURRENTUSER")) {
|
||||
return "Windows-MY-CURRENTUSER";
|
||||
} else if(storetype.equalsIgnoreCase("Windows-ROOT-CURRENTUSER")) {
|
||||
return "Windows-ROOT-CURRENTUSER";
|
||||
} else if(storetype.equalsIgnoreCase("Windows-MY-LOCALMACHINE")) {
|
||||
return "Windows-MY-LOCALMACHINE";
|
||||
} else if(storetype.equalsIgnoreCase("Windows-ROOT-LOCALMACHINE")) {
|
||||
return "Windows-ROOT-LOCALMACHINE";
|
||||
} else {
|
||||
return storetype.toUpperCase(Locale.ENGLISH);
|
||||
}
|
||||
|
@ -54,15 +54,30 @@ import sun.security.util.Debug;
|
||||
*/
|
||||
abstract class CKeyStore extends KeyStoreSpi {
|
||||
|
||||
private static final int LOCATION_CURRENTUSER = 0;
|
||||
private static final int LOCATION_LOCALMACHINE = 1;
|
||||
|
||||
public static final class MY extends CKeyStore {
|
||||
public MY() {
|
||||
super("MY");
|
||||
super("MY", LOCATION_CURRENTUSER);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ROOT extends CKeyStore {
|
||||
public ROOT() {
|
||||
super("ROOT");
|
||||
super("ROOT", LOCATION_CURRENTUSER);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class MYLocalMachine extends CKeyStore {
|
||||
public MYLocalMachine() {
|
||||
super("MY", LOCATION_LOCALMACHINE);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ROOTLocalMachine extends CKeyStore {
|
||||
public ROOTLocalMachine() {
|
||||
super("ROOT", LOCATION_LOCALMACHINE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,7 +235,12 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
*/
|
||||
private final String storeName;
|
||||
|
||||
CKeyStore(String storeName) {
|
||||
/*
|
||||
* The keystore location.
|
||||
*/
|
||||
private final int storeLocation;
|
||||
|
||||
CKeyStore(String storeName, int storeLocation) {
|
||||
// Get the compatibility mode
|
||||
@SuppressWarnings("removal")
|
||||
String prop = AccessController.doPrivileged(
|
||||
@ -233,6 +253,7 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
}
|
||||
|
||||
this.storeName = storeName;
|
||||
this.storeLocation = storeLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,7 +280,7 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
* @exception UnrecoverableKeyException if the key cannot be recovered.
|
||||
*/
|
||||
public java.security.Key engineGetKey(String alias, char[] password)
|
||||
throws NoSuchAlgorithmException, UnrecoverableKeyException {
|
||||
throws NoSuchAlgorithmException, UnrecoverableKeyException {
|
||||
if (alias == null) {
|
||||
return null;
|
||||
}
|
||||
@ -705,7 +726,7 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
try {
|
||||
|
||||
// Load keys and/or certificate chains
|
||||
loadKeysOrCertificateChains(getName());
|
||||
loadKeysOrCertificateChains(getName(), getLocation());
|
||||
|
||||
} catch (KeyStoreException e) {
|
||||
throw new IOException(e);
|
||||
@ -801,7 +822,7 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
* @param certCollection Collection of certificates.
|
||||
*/
|
||||
private void generateCertificate(byte[] data,
|
||||
Collection<Certificate> certCollection) {
|
||||
Collection<Certificate> certCollection) {
|
||||
try {
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(data);
|
||||
|
||||
@ -829,12 +850,20 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load keys and/or certificates from keystore into Collection.
|
||||
* Returns the location of the keystore.
|
||||
*/
|
||||
private int getLocation() {
|
||||
return storeLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads keys and/or certificates from keystore into Collection.
|
||||
*
|
||||
* @param name Name of keystore.
|
||||
* @param location Location of keystore.
|
||||
*/
|
||||
private native void loadKeysOrCertificateChains(String name)
|
||||
throws KeyStoreException;
|
||||
private native void loadKeysOrCertificateChains(String name,
|
||||
int location) throws KeyStoreException;
|
||||
|
||||
/**
|
||||
* Stores a DER-encoded certificate into the certificate store
|
||||
@ -844,8 +873,8 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
* @param encoding DER-encoded certificate.
|
||||
*/
|
||||
private native void storeCertificate(String name, String alias,
|
||||
byte[] encoding, int encodingLength, long hCryptProvider,
|
||||
long hCryptKey) throws CertificateException, KeyStoreException;
|
||||
byte[] encoding, int encodingLength, long hCryptProvider,
|
||||
long hCryptKey) throws CertificateException, KeyStoreException;
|
||||
|
||||
/**
|
||||
* Removes the certificate from the certificate store
|
||||
@ -855,7 +884,7 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
* @param encoding DER-encoded certificate.
|
||||
*/
|
||||
private native void removeCertificate(String name, String alias,
|
||||
byte[] encoding, int encodingLength)
|
||||
byte[] encoding, int encodingLength)
|
||||
throws CertificateException, KeyStoreException;
|
||||
|
||||
/**
|
||||
@ -864,7 +893,7 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
* @param keyContainerName The name of the key container.
|
||||
*/
|
||||
private native void destroyKeyContainer(String keyContainerName)
|
||||
throws KeyStoreException;
|
||||
throws KeyStoreException;
|
||||
|
||||
/**
|
||||
* Removes a CNG key.
|
||||
@ -877,16 +906,16 @@ abstract class CKeyStore extends KeyStoreSpi {
|
||||
* Generates a private-key BLOB from a key's components.
|
||||
*/
|
||||
private native byte[] generateRSAPrivateKeyBlob(
|
||||
int keyBitLength,
|
||||
byte[] modulus,
|
||||
byte[] publicExponent,
|
||||
byte[] privateExponent,
|
||||
byte[] primeP,
|
||||
byte[] primeQ,
|
||||
byte[] exponentP,
|
||||
byte[] exponentQ,
|
||||
byte[] crtCoefficient) throws InvalidKeyException;
|
||||
int keyBitLength,
|
||||
byte[] modulus,
|
||||
byte[] publicExponent,
|
||||
byte[] privateExponent,
|
||||
byte[] primeP,
|
||||
byte[] primeQ,
|
||||
byte[] exponentP,
|
||||
byte[] exponentQ,
|
||||
byte[] crtCoefficient) throws InvalidKeyException;
|
||||
|
||||
private native CPrivateKey storePrivateKey(String alg, byte[] keyBlob,
|
||||
String keyContainerName, int keySize) throws KeyStoreException;
|
||||
String keyContainerName, int keySize) throws KeyStoreException;
|
||||
}
|
||||
|
@ -91,10 +91,14 @@ public final class SunMSCAPI extends Provider {
|
||||
return new PRNG();
|
||||
}
|
||||
} else if (type.equals("KeyStore")) {
|
||||
if (algo.equals("Windows-MY")) {
|
||||
if (algo.equals("Windows-MY") || algo.equals("Windows-MY-CURRENTUSER")) {
|
||||
return new CKeyStore.MY();
|
||||
} else if (algo.equals("Windows-ROOT")) {
|
||||
} else if (algo.equals("Windows-ROOT") || algo.equals("Windows-ROOT-CURRENTUSER")) {
|
||||
return new CKeyStore.ROOT();
|
||||
} else if (algo.equals("Windows-MY-LOCALMACHINE")) {
|
||||
return new CKeyStore.MYLocalMachine();
|
||||
} else if (algo.equals("Windows-ROOT-LOCALMACHINE")) {
|
||||
return new CKeyStore.ROOTLocalMachine();
|
||||
}
|
||||
} else if (type.equals("Signature")) {
|
||||
if (algo.equals("NONEwithRSA")) {
|
||||
@ -165,8 +169,16 @@ public final class SunMSCAPI extends Provider {
|
||||
*/
|
||||
putService(new ProviderService(p, "KeyStore",
|
||||
"Windows-MY", "sun.security.mscapi.CKeyStore$MY"));
|
||||
putService(new ProviderService(p, "KeyStore",
|
||||
"Windows-MY-CURRENTUSER", "sun.security.mscapi.CKeyStore$MY"));
|
||||
putService(new ProviderService(p, "KeyStore",
|
||||
"Windows-ROOT", "sun.security.mscapi.CKeyStore$ROOT"));
|
||||
putService(new ProviderService(p, "KeyStore",
|
||||
"Windows-ROOT-CURRENTUSER", "sun.security.mscapi.CKeyStore$ROOT"));
|
||||
putService(new ProviderService(p, "KeyStore",
|
||||
"Windows-MY-LOCALMACHINE", "sun.security.mscapi.CKeyStore$MYLocalMachine"));
|
||||
putService(new ProviderService(p, "KeyStore",
|
||||
"Windows-ROOT-LOCALMACHINE", "sun.security.mscapi.CKeyStore$ROOTLocalMachine"));
|
||||
|
||||
/*
|
||||
* Signature engines
|
||||
|
@ -59,6 +59,9 @@
|
||||
#define SIGNATURE_EXCEPTION "java/security/SignatureException"
|
||||
#define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"
|
||||
|
||||
#define KEYSTORE_LOCATION_CURRENTUSER 0
|
||||
#define KEYSTORE_LOCATION_LOCALMACHINE 1
|
||||
|
||||
#define SS_CHECK(Status) \
|
||||
if (Status != ERROR_SUCCESS) { \
|
||||
ThrowException(env, SIGNATURE_EXCEPTION, Status); \
|
||||
@ -386,10 +389,10 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
|
||||
/*
|
||||
* Class: sun_security_mscapi_CKeyStore
|
||||
* Method: loadKeysOrCertificateChains
|
||||
* Signature: (Ljava/lang/String;)V
|
||||
* Signature: (Ljava/lang/String;I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateChains
|
||||
(JNIEnv *env, jobject obj, jstring jCertStoreName)
|
||||
(JNIEnv *env, jobject obj, jstring jCertStoreName, jint jCertStoreLocation)
|
||||
{
|
||||
/**
|
||||
* Certificate in cert store has enhanced key usage extension
|
||||
@ -407,7 +410,6 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
||||
char* pszNameString = NULL; // certificate's friendly name
|
||||
DWORD cchNameString = 0;
|
||||
|
||||
|
||||
__try
|
||||
{
|
||||
// Open a system certificate store.
|
||||
@ -415,8 +417,20 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
||||
== NULL) {
|
||||
__leave;
|
||||
}
|
||||
if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName))
|
||||
== NULL) {
|
||||
|
||||
if (jCertStoreLocation == KEYSTORE_LOCATION_CURRENTUSER) {
|
||||
hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName);
|
||||
}
|
||||
else if (jCertStoreLocation == KEYSTORE_LOCATION_LOCALMACHINE) {
|
||||
hCertStore = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, NULL,
|
||||
CERT_SYSTEM_STORE_LOCAL_MACHINE, pszCertStoreName);
|
||||
}
|
||||
else {
|
||||
PP("jCertStoreLocation is not a valid value");
|
||||
__leave;
|
||||
}
|
||||
|
||||
if (hCertStore == NULL) {
|
||||
|
||||
ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
|
||||
__leave;
|
||||
@ -469,7 +483,7 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateC
|
||||
PP("--------------------------");
|
||||
// Check if private key available - client authentication certificate
|
||||
// must have private key available.
|
||||
HCRYPTPROV hCryptProv = NULL;
|
||||
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv = NULL;
|
||||
DWORD dwKeySpec = 0;
|
||||
HCRYPTKEY hUserKey = NULL;
|
||||
BOOL bCallerFreeProv = FALSE;
|
||||
|
87
test/jdk/sun/security/mscapi/AllTypes.java
Normal file
87
test/jdk/sun/security/mscapi/AllTypes.java
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.SecurityTools;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6782021
|
||||
* @requires os.family == "windows"
|
||||
* @library /test/lib
|
||||
* @summary More keystore types
|
||||
*/
|
||||
public class AllTypes {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
var nm = test("windows-my");
|
||||
var nr = test("windows-root");
|
||||
var nmu = test("windows-my-currentuser");
|
||||
var nru = test("windows-root-currentuser");
|
||||
var hasAdminPrivileges = detectIfRunningWithAdminPrivileges();
|
||||
var nmm = adminTest("windows-my-localmachine", hasAdminPrivileges);
|
||||
var nrm = adminTest("windows-root-localmachine", hasAdminPrivileges);
|
||||
Asserts.assertEQ(nm, nmu);
|
||||
Asserts.assertEQ(nr, nru);
|
||||
}
|
||||
|
||||
private static boolean detectIfRunningWithAdminPrivileges() {
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec("reg query \"HKU\\S-1-5-19\"");
|
||||
p.waitFor();
|
||||
return (p.exitValue() == 0);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
System.out.println("Warning: unable to detect admin privileges, assuming none");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> adminTest(String type, boolean hasAdminPrivileges) throws Exception {
|
||||
if (hasAdminPrivileges) {
|
||||
return test(type);
|
||||
}
|
||||
System.out.println("Ignoring: " + type + " as it requires admin privileges");
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<String> test(String type) throws Exception {
|
||||
var stdType = "Windows-" + type.substring(8).toUpperCase(Locale.ROOT);
|
||||
SecurityTools.keytool("-storetype " + type + " -list")
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("Keystore provider: SunMSCAPI")
|
||||
.shouldContain("Keystore type: " + stdType);
|
||||
KeyStore ks = KeyStore.getInstance(type);
|
||||
ks.load(null, null);
|
||||
var content = Collections.list(ks.aliases());
|
||||
Collections.sort(content);
|
||||
return content;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user