From 55d0840a0c02fea828fb6534d30204b7c76c2352 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 4 Sep 2019 16:20:57 -0700 Subject: [PATCH 01/49] add enclaveAttestationUrl property --- .../microsoft/sqlserver/jdbc/IOBuffer.java | 6 +++- .../sqlserver/jdbc/ISQLServerDataSource.java | 29 ++++++++++++++----- .../sqlserver/jdbc/SQLServerConnection.java | 23 +++++++++++---- .../sqlserver/jdbc/SQLServerDataSource.java | 18 ++++++++++-- .../sqlserver/jdbc/SQLServerDriver.java | 3 ++ .../sqlserver/jdbc/SQLServerResource.java | 1 + 6 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index c82b0e628..f89a6807d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -113,8 +113,12 @@ final class TDS { // AE constants // 0x03 is for x_eFeatureExtensionId_Rcs static final byte TDS_FEATURE_EXT_AE = 0x04; - static final byte MAX_SUPPORTED_TCE_VERSION = 0x01; // max version + static final byte COLUMNENCRYPTION_VERSION1 = 0x01; // column encryption without enclave + static final byte COLUMNENCRYPTION_VERSION2 = 0x02; // column encryption with enclave static final int CUSTOM_CIPHER_ALGORITHM_ID = 0; // max version + static final int AE_VERSION1 = 1; + static final int AE_VERSION_ENCLAVE = 2; + // 0x06 is for x_eFeatureExtensionId_LoginToken // 0x07 is for x_eFeatureExtensionId_ClientSideTelemetry // Data Classification constants diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java index b1c15c048..d644b690b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java @@ -844,6 +844,13 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource { */ void setKeyVaultProviderClientKey(String keyVaultProviderClientKey); + /** + * Returns the value for the connection property 'domain'. + * + * @return 'domain' property value + */ + String getDomain(); + /** * Sets the 'domain' connection property used for NTLM Authentication. * @@ -852,13 +859,6 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource { */ void setDomain(String domain); - /** - * Returns the value for the connection property 'domain'. - * - * @return 'domain' property value - */ - String getDomain(); - /** * Returns the current flag value for useFmtOnly. * @@ -873,4 +873,19 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource { * boolean value for 'useFmtOnly'. */ public void setUseFmtOnly(boolean useFmtOnly); + + /** + * Returns the enclave attestional url used with enclave based Always Encrypted. + * + * @return a String that contains the enclave attestation url. + */ + String getEnclaveAttestationUrl(); + + /** + * Sets the enclave attestional url to be used with enclave based Always Encrypted. + * + * @param url + * A String that contains the enclave attestation url. + */ + void setEnclaveAttestationUrl(String url); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 2cfe72ca0..c52d1b1e7 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -627,6 +627,8 @@ boolean isColumnEncryptionSettingEnabled() { return (columnEncryptionSetting.equalsIgnoreCase(ColumnEncryptionSetting.Enabled.toString())); } + String enclaveAttestationUrl = null; + String keyStoreAuthentication = null; String keyStoreSecret = null; String keyStoreLocation = null; @@ -1422,6 +1424,12 @@ Connection connectInternal(Properties propsIn, } columnEncryptionSetting = ColumnEncryptionSetting.valueOfString(sPropValue).toString(); + sPropKey = SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.toString(); + sPropValue = activeConnectionProperties.getProperty(sPropKey); + if (null != sPropValue) { + enclaveAttestationUrl = sPropValue; + } + sPropKey = SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); if (null != sPropValue) { @@ -3540,9 +3548,14 @@ int writeAEFeatureRequest(boolean write, /* if false just calculates the length int len = 6; // (1byte = featureID, 4bytes = featureData length, 1 bytes = Version) if (write) { - tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TCE - tdsWriter.writeInt(1); - tdsWriter.writeByte(TDS.MAX_SUPPORTED_TCE_VERSION); + tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TC + if (null == enclaveAttestationUrl || enclaveAttestationUrl.isEmpty()) { + tdsWriter.writeInt(TDS.AE_VERSION1); + tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION1); + } else { + tdsWriter.writeInt(TDS.AE_VERSION_ENCLAVE); + tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION2); + } } return len; } @@ -4553,8 +4566,8 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept throw new SQLServerException(SQLServerException.getErrString("R_InvalidAEVersionNumber"), null); } - byte supportedTceVersion = data[0]; - if (0 == supportedTceVersion || supportedTceVersion > TDS.MAX_SUPPORTED_TCE_VERSION) { + byte aeVersion = data[0]; + if (0 == aeVersion || aeVersion > TDS.COLUMNENCRYPTION_VERSION2) { throw new SQLServerException(SQLServerException.getErrString("R_InvalidAEVersionNumber"), null); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java index 64c523fd7..b40282fca 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java @@ -907,17 +907,29 @@ public void setKeyVaultProviderClientKey(String keyVaultProviderClientKey) { keyVaultProviderClientKey); } + @Override + public String getDomain() { + return getStringProperty(connectionProps, SQLServerDriverStringProperty.DOMAIN.toString(), + SQLServerDriverStringProperty.DOMAIN.getDefaultValue()); + } + @Override public void setDomain(String domain) { setStringProperty(connectionProps, SQLServerDriverStringProperty.DOMAIN.toString(), domain); } @Override - public String getDomain() { - return getStringProperty(connectionProps, SQLServerDriverStringProperty.DOMAIN.toString(), - SQLServerDriverStringProperty.DOMAIN.getDefaultValue()); + public String getEnclaveAttestationUrl() { + return getStringProperty(connectionProps, SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.toString(), + SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.getDefaultValue()); + } + + @Override + public void setEnclaveAttestationUrl(String url) { + setStringProperty(connectionProps, SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.toString(), url); } + /** * Sets a property string value. * diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index b3fd86735..b8e987c8b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -286,6 +286,7 @@ enum SQLServerDriverStringProperty { AUTHENTICATION("authentication", SqlAuthentication.NotSpecified.toString()), ACCESS_TOKEN("accessToken", ""), COLUMN_ENCRYPTION("columnEncryptionSetting", ColumnEncryptionSetting.Disabled.toString()), + ENCLAVE_ATTESTATIONURL("enclaveAttestationUrl", ""), KEY_STORE_AUTHENTICATION("keyStoreAuthentication", ""), KEY_STORE_SECRET("keyStoreSecret", ""), KEY_STORE_LOCATION("keyStoreLocation", ""), @@ -400,6 +401,8 @@ public final class SQLServerDriver implements java.sql.Driver { SQLServerDriverStringProperty.COLUMN_ENCRYPTION.getDefaultValue(), false, new String[] {ColumnEncryptionSetting.Disabled.toString(), ColumnEncryptionSetting.Enabled.toString()}), + new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.toString(), + SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.DATABASE_NAME.toString(), SQLServerDriverStringProperty.DATABASE_NAME.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.DISABLE_STATEMENT_POOLING.toString(), diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index cca3ff929..581ec7ddb 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -188,6 +188,7 @@ protected Object[][] getContents() { {"R_portNumberPropertyDescription", "The TCP port where an instance of SQL Server is listening."}, {"R_serverSpnPropertyDescription", "SQL Server SPN."}, {"R_columnEncryptionSettingPropertyDescription", "The column encryption setting."}, + {"R_enclaveAttestationUrlPropertyDescription", "The enclave attestation URL."}, {"R_serverNameAsACEPropertyDescription", "Translates the serverName from Unicode to ASCII Compatible Encoding (ACE), as defined by the ToASCII operation of RFC 3490."}, {"R_sendStringParametersAsUnicodePropertyDescription", From bd214ad2c0ed32d58696b877ac19324686c34192 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 5 Sep 2019 17:38:18 -0700 Subject: [PATCH 02/49] enclaveType --- .../microsoft/sqlserver/jdbc/SQLServerConnection.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index c52d1b1e7..8e4035d2d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -635,6 +635,8 @@ boolean isColumnEncryptionSettingEnabled() { private boolean serverSupportsColumnEncryption = false; + private String enclaveType = null; + boolean getServerSupportsColumnEncryption() { return serverSupportsColumnEncryption; } @@ -3548,12 +3550,11 @@ int writeAEFeatureRequest(boolean write, /* if false just calculates the length int len = 6; // (1byte = featureID, 4bytes = featureData length, 1 bytes = Version) if (write) { - tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TC + tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TC + tdsWriter.writeInt(1); if (null == enclaveAttestationUrl || enclaveAttestationUrl.isEmpty()) { - tdsWriter.writeInt(TDS.AE_VERSION1); tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION1); } else { - tdsWriter.writeInt(TDS.AE_VERSION_ENCLAVE); tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION2); } } @@ -4572,6 +4573,10 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept } serverSupportsColumnEncryption = true; + if (TDS.COLUMNENCRYPTION_VERSION2 == aeVersion) { + enclaveType = new String(data, 2, data.length-2); + } + break; } case TDS.TDS_FEATURE_EXT_DATACLASSIFICATION: { From 0557d1a6b8e955257fde4aefa6b2393a9040836e Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 5 Sep 2019 17:41:14 -0700 Subject: [PATCH 03/49] enclaveType (#1141) --- .../microsoft/sqlserver/jdbc/SQLServerConnection.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index c52d1b1e7..8e4035d2d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -635,6 +635,8 @@ boolean isColumnEncryptionSettingEnabled() { private boolean serverSupportsColumnEncryption = false; + private String enclaveType = null; + boolean getServerSupportsColumnEncryption() { return serverSupportsColumnEncryption; } @@ -3548,12 +3550,11 @@ int writeAEFeatureRequest(boolean write, /* if false just calculates the length int len = 6; // (1byte = featureID, 4bytes = featureData length, 1 bytes = Version) if (write) { - tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TC + tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TC + tdsWriter.writeInt(1); if (null == enclaveAttestationUrl || enclaveAttestationUrl.isEmpty()) { - tdsWriter.writeInt(TDS.AE_VERSION1); tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION1); } else { - tdsWriter.writeInt(TDS.AE_VERSION_ENCLAVE); tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION2); } } @@ -4572,6 +4573,10 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept } serverSupportsColumnEncryption = true; + if (TDS.COLUMNENCRYPTION_VERSION2 == aeVersion) { + enclaveType = new String(data, 2, data.length-2); + } + break; } case TDS.TDS_FEATURE_EXT_DATACLASSIFICATION: { From 5b0fee0522980f0d6fdb48642d74d183661f8719 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 6 Sep 2019 14:19:12 -0700 Subject: [PATCH 04/49] added some junit tests and attestationProtocol property --- .../sqlserver/jdbc/SQLServerConnection.java | 35 +++++++++++--- .../sqlserver/jdbc/SQLServerDataSource.java | 6 +-- .../sqlserver/jdbc/SQLServerDriver.java | 47 +++++++++++++++++-- .../sqlserver/jdbc/SQLServerResource.java | 8 +++- 4 files changed, 82 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 8e4035d2d..90ba867f1 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -628,7 +628,8 @@ boolean isColumnEncryptionSettingEnabled() { } String enclaveAttestationUrl = null; - + String enclaveAttestationProtocol = null; + String keyStoreAuthentication = null; String keyStoreSecret = null; String keyStoreLocation = null; @@ -636,7 +637,7 @@ boolean isColumnEncryptionSettingEnabled() { private boolean serverSupportsColumnEncryption = false; private String enclaveType = null; - + boolean getServerSupportsColumnEncryption() { return serverSupportsColumnEncryption; } @@ -1426,12 +1427,18 @@ Connection connectInternal(Properties propsIn, } columnEncryptionSetting = ColumnEncryptionSetting.valueOfString(sPropValue).toString(); - sPropKey = SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.toString(); + sPropKey = SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_URL.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); if (null != sPropValue) { enclaveAttestationUrl = sPropValue; } + sPropKey = SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_PROTOCOL.toString(); + sPropValue = activeConnectionProperties.getProperty(sPropKey); + if (null != sPropValue) { + enclaveAttestationProtocol = sPropValue; + } + sPropKey = SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); if (null != sPropValue) { @@ -3555,7 +3562,7 @@ int writeAEFeatureRequest(boolean write, /* if false just calculates the length if (null == enclaveAttestationUrl || enclaveAttestationUrl.isEmpty()) { tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION1); } else { - tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION2); + tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION2); } } return len; @@ -4573,10 +4580,24 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept } serverSupportsColumnEncryption = true; - if (TDS.COLUMNENCRYPTION_VERSION2 == aeVersion) { - enclaveType = new String(data, 2, data.length-2); + + if (null != enclaveAttestationUrl) { + if (aeVersion < TDS.COLUMNENCRYPTION_VERSION2) { + throw new SQLServerException(SQLServerException.getErrString("R_enclaveNotSupported"), null); + } else { + enclaveType = new String(data, 2, data.length - 2, UTF_16LE); + } + + if (null == enclaveType) { + throw new SQLServerException(SQLServerException.getErrString("R_enclaveTypeNotReturned"), null); + } + + if (!EnclaveType.isValidEnclaveType(enclaveType)) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_enclaveTypeInvalid")); + Object[] msgArgs = {enclaveType}; + throw new SQLServerException(null, form.format(msgArgs), null, 0, false); + } } - break; } case TDS.TDS_FEATURE_EXT_DATACLASSIFICATION: { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java index b40282fca..351904d3a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java @@ -920,13 +920,13 @@ public void setDomain(String domain) { @Override public String getEnclaveAttestationUrl() { - return getStringProperty(connectionProps, SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.toString(), - SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.getDefaultValue()); + return getStringProperty(connectionProps, SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_URL.toString(), + SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_URL.getDefaultValue()); } @Override public void setEnclaveAttestationUrl(String url) { - setStringProperty(connectionProps, SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.toString(), url); + setStringProperty(connectionProps, SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_URL.toString(), url); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index b8e987c8b..7d4974b83 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -112,6 +112,44 @@ static ColumnEncryptionSetting valueOfString(String value) throws SQLServerExcep } } +enum AttestationProtocol { + HGS("HGS"), + AAS("AAS"); + + private final String protocol; + + AttestationProtocol(String protocol) { + this.protocol = protocol; + } + + static boolean isValidAttestationProtocol(String protocol) { + for (AttestationProtocol p : AttestationProtocol.values()) { + if (protocol.equalsIgnoreCase(p.toString())) { + return true; + } + } + return false; + } +} + +enum EnclaveType { + VBS("VBS"); // only VBS type supported + + private final String type; + + EnclaveType(String type){ + this.type = type; + } + + static boolean isValidEnclaveType(String type) { + for (EnclaveType t : EnclaveType.values()) { + if (type.equalsIgnoreCase(t.toString())) { + return true; + } + } + return false; + } +} enum SSLProtocol { TLS("TLS"), @@ -286,7 +324,8 @@ enum SQLServerDriverStringProperty { AUTHENTICATION("authentication", SqlAuthentication.NotSpecified.toString()), ACCESS_TOKEN("accessToken", ""), COLUMN_ENCRYPTION("columnEncryptionSetting", ColumnEncryptionSetting.Disabled.toString()), - ENCLAVE_ATTESTATIONURL("enclaveAttestationUrl", ""), + ENCLAVE_ATTESTATION_URL("enclaveAttestationUrl", ""), + ENCLAVE_ATTESTATION_PROTOCOL("enclaveAttestationProtocol", ""), KEY_STORE_AUTHENTICATION("keyStoreAuthentication", ""), KEY_STORE_SECRET("keyStoreSecret", ""), KEY_STORE_LOCATION("keyStoreLocation", ""), @@ -401,8 +440,10 @@ public final class SQLServerDriver implements java.sql.Driver { SQLServerDriverStringProperty.COLUMN_ENCRYPTION.getDefaultValue(), false, new String[] {ColumnEncryptionSetting.Disabled.toString(), ColumnEncryptionSetting.Enabled.toString()}), - new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.toString(), - SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.getDefaultValue(), false, null), + new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_URL.toString(), + SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_URL.getDefaultValue(), false, null), + new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_PROTOCOL.toString(), + SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_PROTOCOL.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.DATABASE_NAME.toString(), SQLServerDriverStringProperty.DATABASE_NAME.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.DISABLE_STATEMENT_POOLING.toString(), diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 581ec7ddb..e123d2aed 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -189,6 +189,7 @@ protected Object[][] getContents() { {"R_serverSpnPropertyDescription", "SQL Server SPN."}, {"R_columnEncryptionSettingPropertyDescription", "The column encryption setting."}, {"R_enclaveAttestationUrlPropertyDescription", "The enclave attestation URL."}, + {"R_enclaveAttestationProtocolPropertyDescription", "The enclave attestation protocol."}, {"R_serverNameAsACEPropertyDescription", "Translates the serverName from Unicode to ASCII Compatible Encoding (ACE), as defined by the ToASCII operation of RFC 3490."}, {"R_sendStringParametersAsUnicodePropertyDescription", @@ -595,5 +596,10 @@ protected Object[][] getContents() { {"R_invalidUserSQL", "An error occurred when attempting to parse user SQL. Please verify SQL syntax."}, {"R_invalidInsertValuesQuery", "An error occurred when matching VALUES list to table columns. Please verify SQL syntax."}, - {"R_invalidValuesList", "An error occurred when reading VALUES list. Please verify SQL syntax."}}; + {"R_invalidValuesList", "An error occurred when reading VALUES list. Please verify SQL syntax."}, + {"R_enclaveNotSupported", "The SQL Server instance does not support enclave based computations."}, + {"R_enclaveTypeNotReturned", + "The SQL Server instance did not return an enclave type. Please make sure the enclave type is correct configured in the SQL Server instance."}, + {"R_enclaveTypeInvalid", "The enclave type {0} is invalid or not supported by the driver."}, + {"R_attestationUrlInvalid", "Unable to attest enclave specified by {0}."}}; }; From 6cb399425d4b4f2d5ed8e25ee9ec6dab75215655 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Thu, 12 Sep 2019 12:21:16 -0700 Subject: [PATCH 05/49] Add | Enclave STuff --- .../jdbc/ISQLServerEnclaveProvider.java | 21 +++++++++ .../sqlserver/jdbc/SQLServerConnection.java | 7 +++ .../sqlserver/jdbc/SQLServerStatement.java | 33 +++++++++++++- .../jdbc/SQLServerVSMEnclaveProvider.java | 45 +++++++++++++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java create mode 100644 src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java new file mode 100644 index 000000000..12a0038db --- /dev/null +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java @@ -0,0 +1,21 @@ +package com.microsoft.sqlserver.jdbc; + +import java.security.KeyPair; + +public interface ISQLServerEnclaveProvider { + BaseAttestationRequest getAttestationParamters(); + + void createEnclaveSession(); + + void invalidateEnclaveSession(); + + void getEnclaveSession(); +} + +abstract class BaseAttestationRequest { + KeyPair key; + + byte[] attestationParameters() { + return key.getPublic().getEncoded(); + } +} \ No newline at end of file diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index c52d1b1e7..02bf52344 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -5693,6 +5693,8 @@ public T unwrap(Class iface) throws SQLException { private List openStatements; private boolean originalUseFmtOnly; + int aeVersion = 2; + protected void beginRequestInternal() throws SQLException { loggerExternal.entering(getClassNameLogging(), "beginRequest", this); synchronized (this) { @@ -6382,6 +6384,11 @@ final synchronized void removeOpenStatement(ISQLServerStatement st) { openStatements.remove(st); } } + + ISQLServerEnclaveProvider enclaveProvider = null; + byte[] getAttestationPublicKey() { + return enclaveProvider.getAttestationParamters().attestationParameters(); + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index afd0a3e94..c57c20706 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -9,6 +9,8 @@ import static com.microsoft.sqlserver.jdbc.SQLServerConnection.parseAndCacheSQL; import java.sql.BatchUpdateException; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLTimeoutException; @@ -765,7 +767,12 @@ private final class StmtExecCmd extends TDSCommand { } final boolean doExecute() throws SQLServerException { - stmt.doExecuteStatement(this); + try { + stmt.doExecuteStatement(this); + } catch (SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } return false; } @@ -811,7 +818,7 @@ final void setMaxRowsAndMaxFieldSize() throws SQLServerException { } } - final void doExecuteStatement(StmtExecCmd execCmd) throws SQLServerException { + final void doExecuteStatement(StmtExecCmd execCmd) throws SQLException { resetForReexecute(); // Set this command as the current command @@ -837,6 +844,28 @@ final void doExecuteStatement(StmtExecCmd execCmd) throws SQLServerException { if (loggerExternal.isLoggable(Level.FINER) && Util.isActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } + + if (this.connection.aeVersion == 2) { + try (SQLServerCallableStatement c = (SQLServerCallableStatement) this.connection.prepareCall("exec sp_describe_parameter_encryption ?,?,?")) { + c.setNString(1, sql); + c.setNString(2, "''"); + c.setBytes(3, this.connection.getAttestationPublicKey()); + try (ResultSet rs = c.executeQueryInternal()) { + + } + } catch (SQLException e) { + if (e instanceof SQLServerException) { + throw (SQLServerException) e; + } else { + throw new SQLServerException(SQLServerException.getErrString("R_UnableRetrieveParameterMetadata"), null, + 0, e); + } + } + } + + + + if (isCursorable(executeMethod) && isSelect(sql)) { if (stmtlogger.isLoggable(java.util.logging.Level.FINE)) stmtlogger.fine(toString() + " Executing server side cursor " + sql); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java new file mode 100644 index 000000000..bd3874a8a --- /dev/null +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -0,0 +1,45 @@ +package com.microsoft.sqlserver.jdbc; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; + + +public class SQLServerVSMEnclaveProvider implements ISQLServerEnclaveProvider { + + @Override + public VSMAtttestationRequest getAttestationParamters() { + return new VSMAtttestationRequest(); + } + + @Override + public void createEnclaveSession() { + + } + + @Override + public void invalidateEnclaveSession() { + + } + + @Override + public void getEnclaveSession() { + + } + +} + + +class VSMAtttestationRequest extends BaseAttestationRequest { + public VSMAtttestationRequest() { + KeyPairGenerator kpg; + try { + kpg = KeyPairGenerator.getInstance("EC"); + kpg.initialize(384); + key = kpg.generateKeyPair(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} From 4bc018fbf943c72eee941052fe89e13103ea13b4 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Thu, 12 Sep 2019 12:51:09 -0700 Subject: [PATCH 06/49] asdf --- .../java/com/microsoft/sqlserver/jdbc/AE.java | 45 ++++++++++++++++++- .../sqlserver/jdbc/SQLServerConnection.java | 2 +- .../jdbc/SQLServerPreparedStatement.java | 18 +++++--- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java index 4ba6d0f69..2c1e49553 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java @@ -27,6 +27,21 @@ class EncryptionKeyInfo { algorithmName = algorithmNameVal; } + public EncryptionKeyInfo(byte[] encryptedKeyVal, int dbId, int keyId, int keyVersion, byte[] mdVersion, + String keyPathVal, String keyStoreNameVal, String algorithmNameVal, byte requestedByEnclave, + byte[] enclaveCmkSignature) { + encryptedKey = encryptedKeyVal; + databaseId = dbId; + cekId = keyId; + cekVersion = keyVersion; + cekMdVersion = mdVersion; + keyPath = keyPathVal; + keyStoreName = keyStoreNameVal; + algorithmName = algorithmNameVal; + this.requestedByEnclave = (requestedByEnclave == 0); + this.enclaveCmkSignature = enclaveCmkSignature; + } + byte[] encryptedKey; // the encrypted "column encryption key" int databaseId; int cekId; @@ -36,6 +51,8 @@ class EncryptionKeyInfo { String keyStoreName; String algorithmName; byte normalizationRuleVersion; + boolean requestedByEnclave; + byte[] enclaveCmkSignature; } @@ -114,6 +131,30 @@ void add(byte[] encryptedKey, int dbId, int keyId, int keyVersion, byte[] mdVers assert ((null != cekMdVersion) && (null != mdVersion) && (cekMdVersion.length == mdVersion.length)); } } + + public void add(byte[] encryptedKey, int dbId, int keyId, int keyVersion, byte[] mdVersion, String keyPath, + String keyStoreName, String algorithmName, byte requestedByEnclave, byte[] enclaveCMKSignature) { + + assert null != columnEncryptionKeyValues : "columnEncryptionKeyValues should already be initialized."; + + aeLogger.fine("Retrieving CEK values"); + + EncryptionKeyInfo encryptionKey = new EncryptionKeyInfo(encryptedKey, dbId, keyId, keyVersion, mdVersion, + keyPath, keyStoreName, algorithmName, requestedByEnclave, enclaveCMKSignature); + columnEncryptionKeyValues.add(encryptionKey); + + if (0 == databaseId) { + databaseId = dbId; + cekId = keyId; + cekVersion = keyVersion; + cekMdVersion = mdVersion; + } else { + assert (databaseId == dbId); + assert (cekId == keyId); + assert (cekVersion == keyVersion); + assert ((null != cekMdVersion) && (null != mdVersion) && (cekMdVersion.length == mdVersion.length)); + } + } } @@ -242,7 +283,9 @@ enum DescribeParameterEncryptionResultSet1 { EncryptedKey, ProviderName, KeyPath, - KeyEncryptionAlgorithm; + KeyEncryptionAlgorithm, + KeyRequestedByEnclave, + EnclaveCMKSignature; int value() { // Column indexing starts from 1; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 02bf52344..123cc93cc 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -6385,7 +6385,7 @@ final synchronized void removeOpenStatement(ISQLServerStatement st) { } } - ISQLServerEnclaveProvider enclaveProvider = null; + ISQLServerEnclaveProvider enclaveProvider = new SQLServerVSMEnclaveProvider(); byte[] getAttestationPublicKey() { return enclaveProvider.getAttestationParamters().attestationParameters(); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index dba2b644f..fdb58c24b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -556,8 +556,9 @@ final void doExecutePreparedStatement(PrepStmtExecCmd command) throws SQLServerE hasNewTypeDefinitions = buildPreparedStrings(inOutParam, false); } - if ((Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, connection)) && (0 < inOutParam.length) - && !isInternalEncryptionQuery) { + // if ((Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, connection)) && (0 < inOutParam.length) + // && !isInternalEncryptionQuery) { + if (!isInternalEncryptionQuery) { // retrieve parameter encryption metadata if they are not retrieved yet if (!encryptionMetadataIsRetrieved) { @@ -855,10 +856,15 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer "Calling stored procedure sp_describe_parameter_encryption to get parameter encryption information."); } - stmt = (SQLServerCallableStatement) connection.prepareCall("exec sp_describe_parameter_encryption ?,?"); + stmt = (SQLServerCallableStatement) connection.prepareCall("exec sp_describe_parameter_encryption ?,?,?"); stmt.isInternalEncryptionQuery = true; stmt.setNString(1, preparedSQL); - stmt.setNString(2, preparedTypeDefinitions); + if (preparedTypeDefinitions == null) { + stmt.setNString(2, "''"); + } else { + stmt.setNString(2, preparedTypeDefinitions); + } + stmt.setBytes(3, this.connection.getAttestationPublicKey()); rs = (SQLServerResultSet) stmt.executeQueryInternal(); } catch (SQLException e) { if (e instanceof SQLServerException) { @@ -893,7 +899,9 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer rs.getBytes(DescribeParameterEncryptionResultSet1.KeyMdVersion.value()), rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()), rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()), - rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value())); + rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value()), + rs.getByte(DescribeParameterEncryptionResultSet1.KeyRequestedByEnclave.value()), + rs.getBytes(DescribeParameterEncryptionResultSet1.EnclaveCMKSignature.value())); } if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { getStatementLogger().fine("Matadata of CEKs is retrieved."); From 0898459d0169d6051855852a676b87f45336ca04 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 12 Sep 2019 13:55:21 -0700 Subject: [PATCH 07/49] merged with Rene --- .../java/com/microsoft/sqlserver/jdbc/AE.java | 45 +++++++++++++++---- .../microsoft/sqlserver/jdbc/IOBuffer.java | 2 + ...ColumnEncryptionAzureKeyVaultProvider.java | 39 ++++++++++++++++ ...umnEncryptionCertificateStoreProvider.java | 36 +++++++++++++++ ...rColumnEncryptionJavaKeyStoreProvider.java | 7 +++ ...erverColumnEncryptionKeyStoreProvider.java | 16 +++++++ .../sqlserver/jdbc/SQLServerConnection.java | 23 +++++----- .../jdbc/SQLServerPreparedStatement.java | 23 +++++++--- .../sqlserver/jdbc/SQLServerResource.java | 2 +- .../jdbc/SQLServerSecurityUtility.java | 41 +++++++++++++++++ .../sqlserver/jdbc/SQLServerStatement.java | 4 +- 11 files changed, 211 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java index 2c1e49553..c541aac8c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java @@ -271,9 +271,11 @@ boolean IsAlgorithmInitialized() { } -// Fields in the first resultset of "sp_describe_parameter_encryption" -// We expect the server to return the fields in the resultset in the same order as mentioned below. -// If the server changes the below order, then transparent parameter encryption will break. +/** + * Fields in the first resultset of "sp_describe_parameter_encryption". We expect the server to return the fields in the + * resultset in the same order as mentioned below. If the server changes the below order, then transparent parameter + * encryption will break. + */ enum DescribeParameterEncryptionResultSet1 { KeyOrdinal, DbId, @@ -284,8 +286,8 @@ enum DescribeParameterEncryptionResultSet1 { ProviderName, KeyPath, KeyEncryptionAlgorithm, - KeyRequestedByEnclave, - EnclaveCMKSignature; + IsRequestedByEnclave, + KeySignature; int value() { // Column indexing starts from 1; @@ -294,9 +296,11 @@ int value() { } -// Fields in the second resultset of "sp_describe_parameter_encryption" -// We expect the server to return the fields in the resultset in the same order as mentioned below. -// If the server changes the below order, then transparent parameter encryption will break. +/** + * Fields in the second resultset of "sp_describe_parameter_encryption". We expect the server to return the fields in + * the resultset in the same order as mentioned below. If the server changes the below order, then transparent parameter + * encryption will break. + */ enum DescribeParameterEncryptionResultSet2 { ParameterOrdinal, ParameterName, @@ -309,5 +313,30 @@ int value() { // Column indexing starts from 1; return ordinal() + 1; } +} + + +/** + * Fields in the third resultset of "sp_describe_parameter_encryption". We expect the server to return the fields in the + * resultset in the same order as mentioned below. If the server changes the below order, then transparent parameter + * encryption will break. + */ +enum DescribeParameterEncryptionResultSet3 { + AttestationInfo; + + int value() { + // Column indexing starts from 1; + return ordinal() + 1; + } +} +enum ColumnEncryptionVersion { + AE_NotSupported, + AE_v1, + AE_v2; + + int value() { + // Column indexing starts from 1; + return ordinal() + 1; + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index f89a6807d..ff1dff5a9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -6288,6 +6288,7 @@ final SQLServerConnection getConnection() { private boolean useColumnEncryption = false; private boolean serverSupportsColumnEncryption = false; private boolean serverSupportsDataClassification = false; + private ColumnEncryptionVersion columnEncryptionVersion; private final byte valueBytes[] = new byte[256]; @@ -6312,6 +6313,7 @@ private static int nextReaderID() { useColumnEncryption = true; } serverSupportsColumnEncryption = con.getServerSupportsColumnEncryption(); + columnEncryptionVersion = con.getServerColumnEncryptionVersion(); serverSupportsDataClassification = con.getServerSupportsDataClassification(); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionAzureKeyVaultProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionAzureKeyVaultProvider.java index 1ad15e4f7..e803220d3 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionAzureKeyVaultProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionAzureKeyVaultProvider.java @@ -590,4 +590,43 @@ private int getAKVKeySize(String masterKeyPath) throws SQLServerException { return retrievedKey.key().n().length; } + + /* Check that the CEK is signed by an ENCLAVE_COMPUTATIONS CMK + * + * The (UTF-16LE) lowercase representations of the KSP name ("mssql_certificate_store"), key path, and the word + * "true" (74 00 72 00 75 00 65 00) are concatenated together and hashed with SHA256. The hash is signed using the + * private key of the CMK (the one referenced by the key path.) The resulting signature is the one stored in SQL + * Server and specified in the CMK metadata. + */ + public boolean verifyCMKMetadata(String keyPath, boolean isEnclaveEnabled, byte[] signature) throws SQLServerException { + KeyStoreProviderCommon.validateNonEmptyMasterKeyPath(keyPath); + + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new SQLServerException(SQLServerException.getErrString("R_NoSHA256Algorithm"), e); + } + + // compute hash + md.update(name.toLowerCase().getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); + md.update(keyPath.toLowerCase().getBytes()); + md.update("true".getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); + byte[] dataToSign = md.digest(); + if (null == dataToSign) { + throw new SQLServerException(SQLServerException.getErrString("R_HashNull"), null); + } + + // Sign the hash + byte[] signedHash = AzureKeyVaultSignHashedData(dataToSign, keyPath); + + // Validate the signature + if (!AzureKeyVaultVerifySignature(dataToSign, signedHash, keyPath)) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_CEKSignatureNotMatchCMK")); + Object[] msgArgs = {keyPath}; + throw new SQLServerException(this, form.format(msgArgs), null, 0, false); + } + + return true; + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java index 7733e6db2..e09f9618e 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java @@ -5,6 +5,9 @@ package com.microsoft.sqlserver.jdbc; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.MessageFormat; import java.util.Locale; @@ -81,4 +84,37 @@ public byte[] decryptColumnEncryptionKey(String masterKeyPath, String encryption "decryptColumnEncryptionKey", "Finished decrypting Column Encryption Key."); return plainCek; } + + /* + * The (UTF-16LE) lowercase representations of the KSP name ("mssql_certificate_store"), key path, and the word + * "true" (74 00 72 00 75 00 65 00) are concatenated together and hashed with SHA256. The hash is signed using the + * private key of the CMK (the one referenced by the key path.) The resulting signature is the one stored in SQL + * Server and specified in the CMK metadata. + */ + @Override + public boolean verifyCMKMetadata(String keyPath, boolean isEnclaveEnabled, + byte[] signature) throws SQLServerException { + // assume cert is already validated? + + // validate key path + if (null == keyPath || keyPath.trim().isEmpty() || keyPath.length() >= Integer.MAX_VALUE ) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_WindowsKeyPathInvalid")); + Object[] msgArgs = {keyPath}; + throw new SQLServerException(null, form.format(msgArgs), null, 0, false); + } + + byte[] kspNameBytes = name.toLowerCase().getBytes(java.nio.charset.StandardCharsets.UTF_16LE); + byte[] isEnclaveBytes = "true".getBytes(java.nio.charset.StandardCharsets.UTF_16LE); + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + throw new SQLServerException(SQLServerException.getErrString("R_NoSHA256Algorithm"), e); + } + byte[] hash = new byte[kspNameBytes.length+isEnclaveBytes.length+keyPath.length()]; + + + + return true; + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java index 41d012b65..2186b373a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java @@ -317,4 +317,11 @@ private byte[] getLittleEndianBytesFromShort(short value) { } + @Override + public boolean verifyCMKMetadata(String keyPath, boolean isEnclaveEnabled, + byte[] signature) throws SQLServerException { + // TODO Auto-generated method stub + return false; + } + } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionKeyStoreProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionKeyStoreProvider.java index 6fd8b845f..579b520d5 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionKeyStoreProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionKeyStoreProvider.java @@ -62,4 +62,20 @@ public abstract byte[] decryptColumnEncryptionKey(String masterKeyPath, String e public abstract byte[] encryptColumnEncryptionKey(String masterKeyPath, String encryptionAlgorithm, byte[] columnEncryptionKey) throws SQLServerException; + /** + * Verify the column master key metatadata + * + * @param keyPath + * column master key path + * @param isEnclaveEnabled + * indicates if key can be sent to a trusted enclave + * @param signature + * signature of the column master key metadata + * @return + * whether the column master key metadata can be verified based on the provided signature + * @throws SQLServerException + * when an error occurs while verifying the CMK + */ + public abstract boolean verifyCMKMetadata(String keyPath, boolean isEnclaveEnabled, byte[] signature) throws SQLServerException; + } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index b5457a5ea..6a368d2d8 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -633,13 +633,17 @@ boolean isColumnEncryptionSettingEnabled() { String keyStoreAuthentication = null; String keyStoreSecret = null; String keyStoreLocation = null; - - private boolean serverSupportsColumnEncryption = false; + + private ColumnEncryptionVersion serverColumnEncryptionVersion = ColumnEncryptionVersion.AE_NotSupported; private String enclaveType = null; boolean getServerSupportsColumnEncryption() { - return serverSupportsColumnEncryption; + return (serverColumnEncryptionVersion.value() > ColumnEncryptionVersion.AE_NotSupported.value()); + } + + ColumnEncryptionVersion getServerColumnEncryptionVersion() { + return serverColumnEncryptionVersion; } private boolean serverSupportsDataClassification = false; @@ -4574,17 +4578,18 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept throw new SQLServerException(SQLServerException.getErrString("R_InvalidAEVersionNumber"), null); } - byte aeVersion = data[0]; - if (0 == aeVersion || aeVersion > TDS.COLUMNENCRYPTION_VERSION2) { + byte supportedAeVersion = data[0]; + if (0 == supportedAeVersion || supportedAeVersion > TDS.COLUMNENCRYPTION_VERSION2) { throw new SQLServerException(SQLServerException.getErrString("R_InvalidAEVersionNumber"), null); } - serverSupportsColumnEncryption = true; - + serverColumnEncryptionVersion = ColumnEncryptionVersion.AE_v1; + if (null != enclaveAttestationUrl) { - if (aeVersion < TDS.COLUMNENCRYPTION_VERSION2) { + if (supportedAeVersion < TDS.COLUMNENCRYPTION_VERSION2) { throw new SQLServerException(SQLServerException.getErrString("R_enclaveNotSupported"), null); } else { + serverColumnEncryptionVersion = ColumnEncryptionVersion.AE_v2; enclaveType = new String(data, 2, data.length - 2, UTF_16LE); } @@ -5719,8 +5724,6 @@ public T unwrap(Class iface) throws SQLException { private List openStatements; private boolean originalUseFmtOnly; - int aeVersion = 2; - protected void beginRequestInternal() throws SQLException { loggerExternal.entering(getClassNameLogging(), "beginRequest", this); synchronized (this) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index fdb58c24b..93c7e2b71 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -556,10 +556,13 @@ final void doExecutePreparedStatement(PrepStmtExecCmd command) throws SQLServerE hasNewTypeDefinitions = buildPreparedStrings(inOutParam, false); } - // if ((Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, connection)) && (0 < inOutParam.length) - // && !isInternalEncryptionQuery) { + /*************************nooooooooooo + if ((Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, connection)) && (0 < inOutParam.length) + && !isInternalEncryptionQuery) { + **********/ if (!isInternalEncryptionQuery) { + // retrieve parameter encryption metadata if they are not retrieved yet if (!encryptionMetadataIsRetrieved) { getParameterEncryptionMetadata(inOutParam); @@ -883,6 +886,7 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer Map cekList = new HashMap<>(); CekTableEntry cekEntry = null; + boolean isRequestedByEnclave = false; try { while (rs.next()) { int currentOrdinal = rs.getInt(DescribeParameterEncryptionResultSet1.KeyOrdinal.value()); @@ -899,9 +903,18 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer rs.getBytes(DescribeParameterEncryptionResultSet1.KeyMdVersion.value()), rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()), rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()), - rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value()), - rs.getByte(DescribeParameterEncryptionResultSet1.KeyRequestedByEnclave.value()), - rs.getBytes(DescribeParameterEncryptionResultSet1.EnclaveCMKSignature.value())); + rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value())); + + // servers supporting enclave computations should always return a boolean indicating whether the key is + // required by enclave or not. + if (ColumnEncryptionVersion.AE_v2.value() <= connection.getServerColumnEncryptionVersion().value()) { + isRequestedByEnclave = rs + .getBoolean(DescribeParameterEncryptionResultSet1.IsRequestedByEnclave.value()); + } + + if (isRequestedByEnclave) { + + } } if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { getStatementLogger().fine("Matadata of CEKs is retrieved."); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index e123d2aed..adb7b3e14 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -597,7 +597,7 @@ protected Object[][] getContents() { {"R_invalidInsertValuesQuery", "An error occurred when matching VALUES list to table columns. Please verify SQL syntax."}, {"R_invalidValuesList", "An error occurred when reading VALUES list. Please verify SQL syntax."}, - {"R_enclaveNotSupported", "The SQL Server instance does not support enclave based computations."}, + {"R_enclaveNotSupported", "The SQL Server instance does not support enclave based computations."}, {"R_enclaveTypeNotReturned", "The SQL Server instance did not return an enclave type. Please make sure the enclave type is correct configured in the SQL Server instance."}, {"R_enclaveTypeInvalid", "The enclave type {0} is invalid or not supported by the driver."}, diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java index 45fa6c87b..89b8ec181 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java @@ -7,7 +7,9 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.text.MessageFormat; import java.util.Iterator; +import java.util.List; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; @@ -189,4 +191,43 @@ static byte[] decryptWithKey(byte[] cipherText, CryptoMetadata md, return plainText; } + + static void verifyCMKSignature(String keyStoreName, String keyPath, String serverName, boolean isEnclaveEnabled, byte[] CMKSignature) throws SQLServerException { + + // check trusted key paths + Boolean[] hasEntry = new Boolean[1]; + List trustedKeyPaths = SQLServerConnection.getColumnEncryptionTrustedMasterKeyPaths(serverName, + hasEntry); + if (hasEntry[0]) { + if ((null == trustedKeyPaths) || (0 == trustedKeyPaths.size()) + || (!trustedKeyPaths.contains(keyPath))) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_UntrustedKeyPath")); + Object[] msgArgs = {keyPath, serverName}; + throw new SQLServerException(form.format(msgArgs), null); + } + } + + SQLServerColumnEncryptionKeyStoreProvider provider = SQLServerConnection + .getGlobalSystemColumnEncryptionKeyStoreProvider(keyStoreName); + + // There is no global system provider of this name, check for the global custom providers. + if (null == provider) { + provider = SQLServerConnection + .getGlobalCustomColumnEncryptionKeyStoreProvider(keyStoreName); + } + + // No provider was found of this name. + if (null == provider) { + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_CustomKeyStoreProviderMapNull")); + Object[] msgArgs = {keyStoreName}; + throw new SQLServerException(form.format(msgArgs), null); + } + + if (true == isEnclaveEnabled) { + if (!provider.verifyCMKMetadata(keyPath, isEnclaveEnabled, CMKSignature)) { + throw new SQLServerException(SQLServerException.getErrString("R_InvalidSignatureComputed"), null); + } + } + } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index c57c20706..f6e821d6f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -9,8 +9,6 @@ import static com.microsoft.sqlserver.jdbc.SQLServerConnection.parseAndCacheSQL; import java.sql.BatchUpdateException; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLTimeoutException; @@ -845,7 +843,7 @@ final void doExecuteStatement(StmtExecCmd execCmd) throws SQLException { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } - if (this.connection.aeVersion == 2) { + if (this.connection.getServerColumnEncryptionVersion().value() >= ColumnEncryptionVersion.AE_v2.value()) { try (SQLServerCallableStatement c = (SQLServerCallableStatement) this.connection.prepareCall("exec sp_describe_parameter_encryption ?,?,?")) { c.setNString(1, sql); c.setNString(2, "''"); From ca3b4ed9e0a1bc17d2aa16514934c07a216e6429 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 13 Sep 2019 10:18:39 -0700 Subject: [PATCH 08/49] asd --- .../jdbc/SQLServerVSMEnclaveProvider.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index bd3874a8a..4b039a818 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -1,5 +1,9 @@ package com.microsoft.sqlserver.jdbc; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; @@ -31,6 +35,10 @@ public void getEnclaveSession() { class VSMAtttestationRequest extends BaseAttestationRequest { + + byte enclaveType[] = new byte[] {0x3, 0x0, 0x0, 0x0}; + byte enclaveChallenge[] = new byte[] {0x0, 0x0, 0x0, 0x0}; + public VSMAtttestationRequest() { KeyPairGenerator kpg; try { @@ -42,4 +50,14 @@ public VSMAtttestationRequest() { e.printStackTrace(); } } + + @Override + byte[] getBytes() throws IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + os.write(enclaveType); + os.write(enclaveChallenge); + os.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(key.getPublic().getEncoded().length).array()); + os.write(key.getPublic().getEncoded()); + return os.toByteArray(); + } } From 72e4daa2681d5076d8327e1346667d12387e3d7e Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 13 Sep 2019 10:24:32 -0700 Subject: [PATCH 09/49] asdf --- .../sqlserver/jdbc/ISQLServerEnclaveProvider.java | 13 ++++++++----- .../sqlserver/jdbc/SQLServerConnection.java | 15 ++++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java index 12a0038db..aa8896e63 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java @@ -1,7 +1,9 @@ package com.microsoft.sqlserver.jdbc; +import java.io.IOException; import java.security.KeyPair; + public interface ISQLServerEnclaveProvider { BaseAttestationRequest getAttestationParamters(); @@ -12,10 +14,11 @@ public interface ISQLServerEnclaveProvider { void getEnclaveSession(); } + abstract class BaseAttestationRequest { KeyPair key; - - byte[] attestationParameters() { - return key.getPublic().getEncoded(); - } -} \ No newline at end of file + + byte[] getBytes() throws IOException { + return null; + }; +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 123cc93cc..2c8ea7c61 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -3549,12 +3549,11 @@ int writeAEFeatureRequest(boolean write, /* if false just calculates the length if (write) { tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TC + tdsWriter.writeInt(1); //length of version if (null == enclaveAttestationUrl || enclaveAttestationUrl.isEmpty()) { - tdsWriter.writeInt(TDS.AE_VERSION1); tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION1); } else { - tdsWriter.writeInt(TDS.AE_VERSION_ENCLAVE); - tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION2); + tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION2); } } return len; @@ -6386,8 +6385,14 @@ final synchronized void removeOpenStatement(ISQLServerStatement st) { } ISQLServerEnclaveProvider enclaveProvider = new SQLServerVSMEnclaveProvider(); - byte[] getAttestationPublicKey() { - return enclaveProvider.getAttestationParamters().attestationParameters(); + public byte[] getAttestationParameters() { + byte[] b = null; + try { + b = enclaveProvider.getAttestationParamters().getBytes(); + } catch (IOException e) { + + } + return b; } } From bd5ddcae4c933b3d5256b905854ea1176bffc776 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Fri, 13 Sep 2019 12:33:49 -0700 Subject: [PATCH 10/49] fix server stuff --- .../microsoft/sqlserver/jdbc/IOBuffer.java | 2 -- .../jdbc/SQLServerPreparedStatement.java | 24 +++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index f89a6807d..5f7e6d942 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -116,8 +116,6 @@ final class TDS { static final byte COLUMNENCRYPTION_VERSION1 = 0x01; // column encryption without enclave static final byte COLUMNENCRYPTION_VERSION2 = 0x02; // column encryption with enclave static final int CUSTOM_CIPHER_ALGORITHM_ID = 0; // max version - static final int AE_VERSION1 = 1; - static final int AE_VERSION_ENCLAVE = 2; // 0x06 is for x_eFeatureExtensionId_LoginToken // 0x07 is for x_eFeatureExtensionId_ClientSideTelemetry diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index fdb58c24b..086fed448 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -556,8 +556,6 @@ final void doExecutePreparedStatement(PrepStmtExecCmd command) throws SQLServerE hasNewTypeDefinitions = buildPreparedStrings(inOutParam, false); } - // if ((Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, connection)) && (0 < inOutParam.length) - // && !isInternalEncryptionQuery) { if (!isInternalEncryptionQuery) { // retrieve parameter encryption metadata if they are not retrieved yet @@ -779,6 +777,10 @@ private void buildExecSQLParams(TDSWriter tdsWriter) throws SQLServerException { // No handle used. resetPrepStmtHandle(false); + if (this.connection.enclaveAttestationUrl != null) { + tdsWriter.writeBytes(new byte[] {0x0,0x0}); + } + // IN tdsWriter.writeRPCStringUnicode(preparedSQL); @@ -846,7 +848,7 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer * is defined as nvarchar(). Same for varchar datatypes, exact length is used. */ SQLServerResultSet rs = null; - SQLServerCallableStatement stmt = null; + SQLServerPreparedStatement stmt = null; assert connection != null : "Connection should not be null"; @@ -856,15 +858,15 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer "Calling stored procedure sp_describe_parameter_encryption to get parameter encryption information."); } - stmt = (SQLServerCallableStatement) connection.prepareCall("exec sp_describe_parameter_encryption ?,?,?"); + stmt = (SQLServerPreparedStatement) connection.prepareStatement("EXEC sp_describe_parameter_encryption ?,?,?"); stmt.isInternalEncryptionQuery = true; - stmt.setNString(1, preparedSQL); - if (preparedTypeDefinitions == null) { - stmt.setNString(2, "''"); + stmt.setNString(1,this.preparedSQL); + if (preparedTypeDefinitions != null && preparedTypeDefinitions.length() != 0) { + stmt.setNString(2,preparedTypeDefinitions); } else { - stmt.setNString(2, preparedTypeDefinitions); + stmt.setNString(2,""); } - stmt.setBytes(3, this.connection.getAttestationPublicKey()); + stmt.setBytes(3,this.connection.getAttestationParameters()); rs = (SQLServerResultSet) stmt.executeQueryInternal(); } catch (SQLException e) { if (e instanceof SQLServerException) { @@ -899,9 +901,7 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer rs.getBytes(DescribeParameterEncryptionResultSet1.KeyMdVersion.value()), rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()), rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()), - rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value()), - rs.getByte(DescribeParameterEncryptionResultSet1.KeyRequestedByEnclave.value()), - rs.getBytes(DescribeParameterEncryptionResultSet1.EnclaveCMKSignature.value())); + rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value())); } if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { getStatementLogger().fine("Matadata of CEKs is retrieved."); From 0816100851a9a5651fe42155f3be62343cd6001d Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Sun, 22 Sep 2019 21:12:53 -0700 Subject: [PATCH 11/49] save work --- ...mnEncryptionAzureKeyVaultProvider.java.swo | Bin 0 -> 16384 bytes .../java/com/microsoft/sqlserver/jdbc/AE.java | 41 ++++++------- .../sqlserver/jdbc/AuthenticationJNI.java | 4 ++ .../jdbc/KeyStoreProviderCommon.java | 2 +- ...ColumnEncryptionAzureKeyVaultProvider.java | 57 ++++++++---------- ...umnEncryptionCertificateStoreProvider.java | 35 ++--------- ...rColumnEncryptionJavaKeyStoreProvider.java | 48 +++++++++++++-- ...erverColumnEncryptionKeyStoreProvider.java | 15 +++-- .../sqlserver/jdbc/SQLServerConnection.java | 40 +++++++++--- .../jdbc/SQLServerPreparedStatement.java | 52 +++++++++++++--- .../jdbc/SQLServerSecurityUtility.java | 39 ++++++------ .../sqlserver/jdbc/SQLServerStatement.java | 19 ------ .../jdbc/SQLServerVSMEnclaveProvider.java | 5 +- 13 files changed, 204 insertions(+), 153 deletions(-) create mode 100644 src/main/java/com/microsoft/sqlserver/jdbc/.SQLServerColumnEncryptionAzureKeyVaultProvider.java.swo diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/.SQLServerColumnEncryptionAzureKeyVaultProvider.java.swo b/src/main/java/com/microsoft/sqlserver/jdbc/.SQLServerColumnEncryptionAzureKeyVaultProvider.java.swo new file mode 100644 index 0000000000000000000000000000000000000000..d251366df789bee56c98027fbe406a9233fd43a8 GIT binary patch literal 16384 zcmeHOUyLM08E-ie6j38QmAq>8_dSyY8-` zs(SZ^<6>f>5)+8wi3E%qh$aRVjelZ{_+Wf8F&cgL-30W>2Za-VUv*W_?B3maN8*cg zXMa62U0+pw^{c9{>ifF3H@|gah287l?cw^6=l%NcJCD`hy1_g2F3(fB3bG+39DH?2 z?)a&D?w&tbu9;@K88%a;9#0ylqh8ol5yP>x4B7Fp|wT=FG8-U{+WpOj)Jj=1!xz=O4^QY!}DX$;)x-F5g* zGfQu;-NtVE@a8*>fU3O}0~G@m0~G@m0~G@m0~G@m1Mg@C^yqr;i(udy%fch}6Yjsc z+~-^NI%%Ijx-b3THhs-Le|cZ}1)F}#K7V6h`kVXmuiJ`U{cqUx4V&-V`_lilul#@P zOaG@$Z`l0Hw!yA^`?&h37^oPi7^oPi7^oPi7^oPi7^oPi7^oPi82G4frweBj5$#Ebu7M0&WHVcBAM09{4Hn6!2AG z3#b9Fz2Eb`4?GTh3i!(np7$bf9(WSi1{Q%fumF4(`0e{V?^)m(;1=LJ@AbR}@apxR zcN|y*{(PP1{R#LT@Eq`U;0$mYXaIA-$AOp8(3gO9;1j^>*LvR1fFA-s0D3?GJPh0q zd>Xj$ZqIuY_#^NK;3eQi;7OndJPJGl90P6#ZUt@uZU(+_$ny>Zv%pUfZ+IH`GVlf9 zV*mwRi1(+JkjPwVPRM;qo{F6yA(b0F5h7%99P$cTi~5!CC&Nvy|gH`YUT z#Ghw4W1^@nqHh?CWQ-?1TjVGW%>l(|pi|C$23g4#qjM_g8sA5UK?(esj_Hk=JC{=Q z1`9NkIY>&;S7Mqn^V^(cp)AatWhoolc5PHFU{`kzrf6iq!izfYQuVhMF+L*G!shI( zXTF>-8q65@*SX9z&} zBC{=vgvxS8=oA{_C83f>G~6&uF!=3Pbzf2GMZ#t-?3)_Fc6pe$JG=P$ZmpeK$3< zNx1d-&GpXqQs?3At=8u92Ba8WleQLz-PmND81vADwd2g4b%TARxo5H(HSLrPlR&Af zwHL6rVDf-$n1H7Gvi5VH(RY@qc#s7!5&S6Yy06Zr(o}`YG`(0LWia-qWMD60?&HXq z+8&3ouS4o%*B63L1Xeasd&UTi(suGhH#eV?wnvH%D0u53>Q5NyBlRMdeBi`cOuSwFf-VLgzchToZ~< z*H>0+!)_WHV;!Z% z1B-icxYKkkEx4wdz$j{mBNpFulyI_ISm?2)t2m9507_$%gl@(#pcNfch6b4{&3^x7<0{KS^eG$imV{LSU7fh z58wTVkna@lEn#}Q$y+XJZ?m9@)w;@(QW5b)`OpPxaNHk*4XguKro|-h+K5Xt2;N@y zg*=NAY;q2uzvPfKrKRc$y3F(wG#X)3#~1QA!D;2mP@rSWey-yL%Tay#515*8fh)YxzXGv)b)o3yF;IK4|rVojJ`zSO~09#)Og!hQz`w zlSL-0x8jbzvxgQJ+HBFdAx0c~ew0sV;aOXZ#xfoZbv>M!%Fz~B^@`Dsy=cOWh=NHX z*MvvbF@YWfa`RwI(;(t7Ump4Y^YD#5_|fG5H}FB%_u%h;3-~7RIB*8&1GfVo1-=Vk ze;)WH{Q9o}UjnWLUWH%(E8qp-8Q>I92Yv%z{ujV2z;nQ7fa`#tTi-sx=Z(N2;2Pks z@bRAqo&`og4R{4Qeg&8ZJ_+0kTn}6Wkp6E`JF2TdZLF??3&WxO;wPkSlyn4`o+rm2vc^XEP^rh+WIz} zztZbj6?!Gm;jq23RGXR7E$*}WZD#lGcKd~MQf90pfDvp6`aNenbRHcK)NszZz%vxg zq!!YJ7~7VOd6+Gta!!|Ll5s1)*q9_q6eXgSd-R|hsU{vRLW4bOSmLIdfr?4qR60Z^ zYY0{>NAt#FP(`()|boi_7p;Q!CM*Sh*_B4 za-H=*>NWU+$6JT*IZ}Fq)P2)4^gLcAU~;hf<-A5nPYrWYH;vGHd%Q-X@dV!61X+lV zLyZkoS)1xsEyq)Z?8#dcN5h9aHG5%3?g>h^MVi8^a#6)qk#*9M9-QHWyy3S;<%-&XEK=ypxf$7$K#2iBL}InZi;| z1yxHk=~_97_*y@YqL*sK!y;~J{Ya?8QmYSKM!IIGm+72GdSFc z*CDE90%_(IA;WvHp+AFgBMDG+h2Gwj8k2|U@|#c@La7;rl3k_6Y-9C%?`HG!?B2uX zeh=M`(0v9$UUIWD3br9AjJmZzrz6s8f_F5OU6idDaO9yDL!9a+MUb9TNRt$C)sjpd z4t;|h`Wcqc%nUIz(FXhG&jfr*4}Gb7(!6V8^_uyw^X;jS-nMBNjc;O(_?R=gp*prJ zWbqoz1SCOobC$J-94|ig5K&MPp?Kj$Q!tA`(^+jVx3)Ul?X{JYn;Wf-6KktohR!hR wo7=?3+P7&GG>kc1^d-dLpa^VC1|%kuJT<~68KDgnIAG;1R##eduVCf<4= Integer.MAX_VALUE ) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_WindowsKeyPathInvalid")); - Object[] msgArgs = {keyPath}; - throw new SQLServerException(null, form.format(msgArgs), null, 0, false); - } - - byte[] kspNameBytes = name.toLowerCase().getBytes(java.nio.charset.StandardCharsets.UTF_16LE); - byte[] isEnclaveBytes = "true".getBytes(java.nio.charset.StandardCharsets.UTF_16LE); - MessageDigest md = null; try { - md = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - throw new SQLServerException(SQLServerException.getErrString("R_NoSHA256Algorithm"), e); + return AuthenticationJNI.VerifyColumnMasterKeyMetadata(masterKeyPath, allowEnclaveComputations, signature); + } catch (DLLException e) { + DLLException.buildException(e.GetErrCode(), e.GetParam1(), e.GetParam2(), e.GetParam3()); + return false; } - byte[] hash = new byte[kspNameBytes.length+isEnclaveBytes.length+keyPath.length()]; - - - - return true; } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java index 2186b373a..f5ffed36f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java @@ -16,6 +16,7 @@ import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Signature; @@ -303,7 +304,6 @@ private byte[] rsaSignHashedData(byte[] dataToSign, MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_EncryptionFailed")); Object[] msgArgs = {e.getMessage()}; throw new SQLServerException(this, form.format(msgArgs), null, 0, false); - } return signedHash; @@ -314,14 +314,52 @@ private byte[] getLittleEndianBytesFromShort(short value) { byteBuffer.order(ByteOrder.LITTLE_ENDIAN); byte[] byteValue = byteBuffer.putShort(value).array(); return byteValue; - } + /* + * Verify signature against certificate + */ + private boolean rsaVerifySignature(byte[] dataToVerify, byte[] signature, CertificateDetails certificateDetails) throws SQLServerException { + try { + Signature sig = Signature.getInstance("SHA256withRSA"); + sig.initSign((PrivateKey) certificateDetails.privateKey); + sig.update(dataToVerify); + byte[] signedHash = sig.sign(); + + sig.initVerify(certificateDetails.certificate.getPublicKey()); + sig.update(dataToVerify); + + return sig.verify(signedHash); + + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException e) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_VerifySignatureFailed")); + Object[] msgArgs = {e.getMessage()}; + throw new SQLServerException(this, form.format(msgArgs), null, 0, false); + } + } + @Override - public boolean verifyCMKMetadata(String keyPath, boolean isEnclaveEnabled, + public boolean verifyColumnMasterKeyMetadata(String masterKeyPath, boolean allowEnclaveComputations, byte[] signature) throws SQLServerException { - // TODO Auto-generated method stub - return false; + + if (!allowEnclaveComputations) + return false; + + KeyStoreProviderCommon.validateNonEmptyMasterKeyPath(masterKeyPath); + CertificateDetails certificateDetails = getCertificateDetails(masterKeyPath); + + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(name.toLowerCase().getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); + md.update(masterKeyPath.toLowerCase().getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); + // value of allowEnclaveComputations is true + md.update("true".getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); + return rsaVerifySignature(md.digest(), signature, certificateDetails); + + } catch (NoSuchAlgorithmException e) { + throw new SQLServerException(SQLServerException.getErrString("R_NoSHA256Algorithm"), e); + } } + } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionKeyStoreProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionKeyStoreProvider.java index 579b520d5..70415467c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionKeyStoreProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionKeyStoreProvider.java @@ -63,19 +63,18 @@ public abstract byte[] encryptColumnEncryptionKey(String masterKeyPath, String e byte[] columnEncryptionKey) throws SQLServerException; /** - * Verify the column master key metatadata + * Verify the signature is valid for the column master key * - * @param keyPath + * @param masterKeyPath * column master key path - * @param isEnclaveEnabled - * indicates if key can be sent to a trusted enclave + * @param allowEnclaveComputations + * indicates if whether the column master key supports enclave computations * @param signature * signature of the column master key metadata * @return - * whether the column master key metadata can be verified based on the provided signature + * whether the signature is valid for the column master key * @throws SQLServerException - * when an error occurs while verifying the CMK + * when an error occurs while verifying the signature */ - public abstract boolean verifyCMKMetadata(String keyPath, boolean isEnclaveEnabled, byte[] signature) throws SQLServerException; - + public abstract boolean verifyColumnMasterKeyMetadata (String masterKeyPath, boolean allowEnclaveComputations, byte[] signature) throws SQLServerException; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 2c8ea7c61..d0002cdf3 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -633,12 +633,18 @@ boolean isColumnEncryptionSettingEnabled() { String keyStoreSecret = null; String keyStoreLocation = null; - private boolean serverSupportsColumnEncryption = false; + private ColumnEncryptionVersion serverColumnEncryptionVersion = ColumnEncryptionVersion.AE_NotSupported; + + private String enclaveType = null; boolean getServerSupportsColumnEncryption() { - return serverSupportsColumnEncryption; + return (serverColumnEncryptionVersion.value() > ColumnEncryptionVersion.AE_NotSupported.value()); } + ColumnEncryptionVersion getServerColumnEncryptionVersion() { + return serverColumnEncryptionVersion; + } + private boolean serverSupportsDataClassification = false; boolean getServerSupportsDataClassification() { @@ -654,7 +660,7 @@ boolean getServerSupportsDataClassification() { } static Map globalCustomColumnEncryptionKeyStoreProviders = null; // This is a per-connection store provider. It can be JKS or AKV. - Map systemColumnEncryptionKeyStoreProvider = new HashMap<>(); + static Map systemColumnEncryptionKeyStoreProvider = new HashMap<>(); /** * Registers key store providers in the globalCustomColumnEncryptionKeyStoreProviders. @@ -1424,7 +1430,7 @@ Connection connectInternal(Properties propsIn, } columnEncryptionSetting = ColumnEncryptionSetting.valueOfString(sPropValue).toString(); - sPropKey = SQLServerDriverStringProperty.ENCLAVE_ATTESTATIONURL.toString(); + sPropKey = SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_URL.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); if (null != sPropValue) { enclaveAttestationUrl = sPropValue; @@ -4565,13 +4571,33 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept throw new SQLServerException(SQLServerException.getErrString("R_InvalidAEVersionNumber"), null); } - byte aeVersion = data[0]; - if (0 == aeVersion || aeVersion > TDS.COLUMNENCRYPTION_VERSION2) { + byte supportedAeVersion = data[0]; + if (0 == supportedAeVersion || supportedAeVersion > TDS.COLUMNENCRYPTION_VERSION2) { throw new SQLServerException(SQLServerException.getErrString("R_InvalidAEVersionNumber"), null); } - serverSupportsColumnEncryption = true; + serverColumnEncryptionVersion = ColumnEncryptionVersion.AE_v1; + + if (null != enclaveAttestationUrl) { + if (supportedAeVersion < TDS.COLUMNENCRYPTION_VERSION2) { + throw new SQLServerException(SQLServerException.getErrString("R_enclaveNotSupported"), null); + } else { + serverColumnEncryptionVersion = ColumnEncryptionVersion.AE_v2; + enclaveType = new String(data, 2, data.length - 2, UTF_16LE); + } + + if (null == enclaveType) { + throw new SQLServerException(SQLServerException.getErrString("R_enclaveTypeNotReturned"), null); + } + + if (!EnclaveType.isValidEnclaveType(enclaveType)) { + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_enclaveTypeInvalid")); + Object[] msgArgs = {enclaveType}; + throw new SQLServerException(null, form.format(msgArgs), null, 0, false); + } + } break; + } case TDS.TDS_FEATURE_EXT_DATACLASSIFICATION: { if (connectionlogger.isLoggable(Level.FINER)) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 93c7e2b71..803c5581e 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -29,6 +29,8 @@ import java.util.Vector; import java.util.logging.Level; +import org.apache.commons.codec.DecoderException; + import com.microsoft.sqlserver.jdbc.SQLServerConnection.CityHash128Key; import com.microsoft.sqlserver.jdbc.SQLServerConnection.PreparedStatementHandle; @@ -782,6 +784,10 @@ private void buildExecSQLParams(TDSWriter tdsWriter) throws SQLServerException { // No handle used. resetPrepStmtHandle(false); + if (this.connection.enclaveAttestationUrl != null) { + tdsWriter.writeBytes(new byte[] {0x0,0x0}); + } + // IN tdsWriter.writeRPCStringUnicode(preparedSQL); @@ -849,7 +855,7 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer * is defined as nvarchar(). Same for varchar datatypes, exact length is used. */ SQLServerResultSet rs = null; - SQLServerCallableStatement stmt = null; + SQLServerPreparedStatement stmt = null; assert connection != null : "Connection should not be null"; @@ -859,15 +865,33 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer "Calling stored procedure sp_describe_parameter_encryption to get parameter encryption information."); } - stmt = (SQLServerCallableStatement) connection.prepareCall("exec sp_describe_parameter_encryption ?,?,?"); + stmt = (SQLServerPreparedStatement) connection.prepareStatement("EXEC sp_describe_parameter_encryption ?,?,?"); stmt.isInternalEncryptionQuery = true; stmt.setNString(1, preparedSQL); if (preparedTypeDefinitions == null) { - stmt.setNString(2, "''"); + stmt.setNString(2, "''"); + } else { stmt.setNString(2, preparedTypeDefinitions); + // stmt.setNString(2, "@param char(11)"); + } + // byte[] param = this.connection.getAttestationParameters(); + byte[] param; + + param = org.apache.commons.codec.binary.Hex.decodeHex( + "03000000000000006800000045434B3330000000c48c7ce6df7b8da9c4433a6b02321814448f6830c37e308cb97df93ce9af0f5baf619d8705c4caf855d7592877aa0a40113a4ff6c84206508bfffd5ffd5309158697e491a2b9e0a29127ce27c34525a9b898ab63ce6342375f85cf31a84d6541"); + + final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); + char[] hexChars = new char[param.length * 2]; + for (int j = 0; j < param.length; j++) { + int v = param[j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; } - stmt.setBytes(3, this.connection.getAttestationPublicKey()); + String str = new String(hexChars); + + //stmt.setBytes(3, this.connection.getAttestationParameters()); + stmt.setBytes(3, param); rs = (SQLServerResultSet) stmt.executeQueryInternal(); } catch (SQLException e) { if (e instanceof SQLServerException) { @@ -876,8 +900,12 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer throw new SQLServerException(SQLServerException.getErrString("R_UnableRetrieveParameterMetadata"), null, 0, e); } + } catch (DecoderException e) { + // TODO Auto-generated catch block + e.printStackTrace(); } + if (null == rs) { // No results. Meaning no parameter. // Should never happen. @@ -896,14 +924,19 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer } else { cekEntry = cekList.get(currentOrdinal); } + + String keyStoreName = rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()); + String algo = rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value()); + String keyPath = rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()); + cekEntry.add(rs.getBytes(DescribeParameterEncryptionResultSet1.EncryptedKey.value()), rs.getInt(DescribeParameterEncryptionResultSet1.DbId.value()), rs.getInt(DescribeParameterEncryptionResultSet1.KeyId.value()), rs.getInt(DescribeParameterEncryptionResultSet1.KeyVersion.value()), rs.getBytes(DescribeParameterEncryptionResultSet1.KeyMdVersion.value()), - rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()), - rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()), - rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value())); + keyPath, + keyStoreName, + algo); // servers supporting enclave computations should always return a boolean indicating whether the key is // required by enclave or not. @@ -913,7 +946,10 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer } if (isRequestedByEnclave) { - + byte[] keySignature = rs.getBytes(DescribeParameterEncryptionResultSet1.EnclaveCMKSignature.value()); + String serverName = connection.getTrustedServerNameAE(); + SQLServerSecurityUtility.verifyColumnMasterKeyMetadata(connection, + keyStoreName, keyPath, serverName, isRequestedByEnclave, keySignature); } } if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java index 89b8ec181..530a64880 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java @@ -191,43 +191,46 @@ static byte[] decryptWithKey(byte[] cipherText, CryptoMetadata md, return plainText; } - - static void verifyCMKSignature(String keyStoreName, String keyPath, String serverName, boolean isEnclaveEnabled, byte[] CMKSignature) throws SQLServerException { - + + /* + * Verify the signature for the CMK + */ + static void verifyColumnMasterKeyMetadata(SQLServerConnection connection, String keyStoreName, String keyPath, + String serverName, boolean isEnclaveEnabled, byte[] CMKSignature) throws SQLServerException { + // check trusted key paths Boolean[] hasEntry = new Boolean[1]; List trustedKeyPaths = SQLServerConnection.getColumnEncryptionTrustedMasterKeyPaths(serverName, hasEntry); if (hasEntry[0]) { - if ((null == trustedKeyPaths) || (0 == trustedKeyPaths.size()) - || (!trustedKeyPaths.contains(keyPath))) { + if ((null == trustedKeyPaths) || (0 == trustedKeyPaths.size()) || (!trustedKeyPaths.contains(keyPath))) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_UntrustedKeyPath")); Object[] msgArgs = {keyPath, serverName}; throw new SQLServerException(form.format(msgArgs), null); } } - - SQLServerColumnEncryptionKeyStoreProvider provider = SQLServerConnection - .getGlobalSystemColumnEncryptionKeyStoreProvider(keyStoreName); - // There is no global system provider of this name, check for the global custom providers. + // Check for the connection provider first. + SQLServerColumnEncryptionKeyStoreProvider provider = connection + .getSystemColumnEncryptionKeyStoreProvider(keyStoreName); + + // There is no connection provider of this name, check for the global system providers. if (null == provider) { - provider = SQLServerConnection - .getGlobalCustomColumnEncryptionKeyStoreProvider(keyStoreName); + provider = SQLServerConnection.getGlobalCustomColumnEncryptionKeyStoreProvider(keyStoreName); } // No provider was found of this name. if (null == provider) { + String systemProviders = connection.getAllSystemColumnEncryptionKeyStoreProviders(); + String customProviders = SQLServerConnection.getAllGlobalCustomSystemColumnEncryptionKeyStoreProviders(); MessageFormat form = new MessageFormat( - SQLServerException.getErrString("R_CustomKeyStoreProviderMapNull")); - Object[] msgArgs = {keyStoreName}; + SQLServerException.getErrString("R_UnrecognizedKeyStoreProviderName")); + Object[] msgArgs = {keyStoreName, systemProviders, customProviders}; throw new SQLServerException(form.format(msgArgs), null); } - - if (true == isEnclaveEnabled) { - if (!provider.verifyCMKMetadata(keyPath, isEnclaveEnabled, CMKSignature)) { - throw new SQLServerException(SQLServerException.getErrString("R_InvalidSignatureComputed"), null); - } + + if (!provider.verifyColumnMasterKeyMetadata(keyPath, isEnclaveEnabled, CMKSignature)) { + throw new SQLServerException(SQLServerException.getErrString("R_VerifySignature"), null); } } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index f6e821d6f..482cfd672 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -843,25 +843,6 @@ final void doExecuteStatement(StmtExecCmd execCmd) throws SQLException { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } - if (this.connection.getServerColumnEncryptionVersion().value() >= ColumnEncryptionVersion.AE_v2.value()) { - try (SQLServerCallableStatement c = (SQLServerCallableStatement) this.connection.prepareCall("exec sp_describe_parameter_encryption ?,?,?")) { - c.setNString(1, sql); - c.setNString(2, "''"); - c.setBytes(3, this.connection.getAttestationPublicKey()); - try (ResultSet rs = c.executeQueryInternal()) { - - } - } catch (SQLException e) { - if (e instanceof SQLServerException) { - throw (SQLServerException) e; - } else { - throw new SQLServerException(SQLServerException.getErrString("R_UnableRetrieveParameterMetadata"), null, - 0, e); - } - } - } - - if (isCursorable(executeMethod) && isSelect(sql)) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index 4b039a818..fe5a1c26b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; @@ -55,6 +54,10 @@ public VSMAtttestationRequest() { byte[] getBytes() throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); os.write(enclaveType); + byte len[] = new byte[] {0x0, 0x0}; + + os.write(len); + os.write(enclaveChallenge); os.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(key.getPublic().getEncoded().length).array()); os.write(key.getPublic().getEncoded()); From 256aae7011d7442611f14129a2da42625a433d77 Mon Sep 17 00:00:00 2001 From: rene-ye Date: Mon, 23 Sep 2019 09:38:00 -0700 Subject: [PATCH 12/49] parse json --- .../java/com/microsoft/sqlserver/jdbc/AE.java | 96 ++++++++++++ .../jdbc/ISQLServerEnclaveProvider.java | 7 +- .../jdbc/SQLServerPreparedStatement.java | 59 +++++++- .../sqlserver/jdbc/SQLServerStatement.java | 143 ++++++++++++++---- .../jdbc/SQLServerVSMEnclaveProvider.java | 45 +++++- 5 files changed, 303 insertions(+), 47 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java index 2c1e49553..3bc9fc9b4 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java @@ -5,8 +5,25 @@ package com.microsoft.sqlserver.jdbc; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.io.Serializable; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; +import java.security.SignatureException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.sql.Blob; +import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; @@ -271,6 +288,85 @@ boolean IsAlgorithmInitialized() { } +class AttestationResponse { + int totalSize; + int identitySize; + int healthReportSize; + int enclaveReportSize; + + byte[] enclavePK; + byte[] healthReportCertificate; + byte[] enclaveReportPackage; + + int sessionInfoSize; + long sessionID; + int DHPKsize; + int DHPKSsize; + byte[] DHpublicKey; + byte[] publicKeySig; + + X509Certificate healthCert; + + AttestationResponse(byte[] b) { + ByteBuffer response = ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN); + this.totalSize = response.getInt(); + this.identitySize = response.getInt(); + this.healthReportSize = response.getInt(); + this.enclaveReportSize = response.getInt(); + + enclavePK = new byte[identitySize]; + healthReportCertificate = new byte[healthReportSize]; + enclaveReportPackage = new byte[enclaveReportSize]; + + response.get(enclavePK, 0, identitySize); + response.get(healthReportCertificate, 0, healthReportSize); + response.get(enclaveReportPackage, 0, enclaveReportSize); + + this.sessionInfoSize = response.getInt(); + this.sessionID = response.getLong(); + this.DHPKsize = response.getInt(); + this.DHPKSsize = response.getInt(); + + DHpublicKey = new byte[DHPKsize]; + publicKeySig = new byte[DHPKSsize]; + + response.get(DHpublicKey, 0, DHPKsize); + response.get(publicKeySig, 0, DHPKSsize); + + if (0 != response.remaining()) { + // throw exception + } + + try { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + healthCert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(healthReportCertificate)); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @SuppressWarnings("unchecked") + boolean validateCert(byte[] b) throws CertificateException { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Collection certs = (Collection) cf + .generateCertificates(new ByteArrayInputStream(b)); + for (X509Certificate cert : certs) { + try { + healthCert.verify(cert.getPublicKey()); + return true; + } catch (SignatureException se) { + // Doesn't match, invalid + } catch (NoSuchAlgorithmException | NoSuchProviderException | java.security.InvalidKeyException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return false; + } +} + + // Fields in the first resultset of "sp_describe_parameter_encryption" // We expect the server to return the fields in the resultset in the same order as mentioned below. // If the server changes the below order, then transparent parameter encryption will break. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java index aa8896e63..7d8c1716a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java @@ -2,6 +2,9 @@ import java.io.IOException; import java.security.KeyPair; +import java.security.PublicKey; + +import javax.crypto.KeyAgreement; public interface ISQLServerEnclaveProvider { @@ -16,7 +19,9 @@ public interface ISQLServerEnclaveProvider { abstract class BaseAttestationRequest { - KeyPair key; + protected PublicKey publickey; + KeyAgreement keyAgreement; + byte[] sharedsecret; byte[] getBytes() throws IOException { return null; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 086fed448..364a6eb01 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -8,9 +8,15 @@ import static com.microsoft.sqlserver.jdbc.SQLServerConnection.getCachedParsedSQL; import static com.microsoft.sqlserver.jdbc.SQLServerConnection.parseAndCacheSQL; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; +import java.net.MalformedURLException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; import java.sql.BatchUpdateException; import java.sql.NClob; import java.sql.ParameterMetaData; @@ -29,6 +35,8 @@ import java.util.Vector; import java.util.logging.Level; +import org.apache.commons.codec.DecoderException; + import com.microsoft.sqlserver.jdbc.SQLServerConnection.CityHash128Key; import com.microsoft.sqlserver.jdbc.SQLServerConnection.PreparedStatementHandle; @@ -778,9 +786,9 @@ private void buildExecSQLParams(TDSWriter tdsWriter) throws SQLServerException { resetPrepStmtHandle(false); if (this.connection.enclaveAttestationUrl != null) { - tdsWriter.writeBytes(new byte[] {0x0,0x0}); + tdsWriter.writeBytes(new byte[] {0x0, 0x0}); } - + // IN tdsWriter.writeRPCStringUnicode(preparedSQL); @@ -858,15 +866,16 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer "Calling stored procedure sp_describe_parameter_encryption to get parameter encryption information."); } - stmt = (SQLServerPreparedStatement) connection.prepareStatement("EXEC sp_describe_parameter_encryption ?,?,?"); + stmt = (SQLServerPreparedStatement) connection + .prepareStatement("EXEC sp_describe_parameter_encryption ?,?,?"); stmt.isInternalEncryptionQuery = true; - stmt.setNString(1,this.preparedSQL); + stmt.setNString(1, this.preparedSQL); if (preparedTypeDefinitions != null && preparedTypeDefinitions.length() != 0) { - stmt.setNString(2,preparedTypeDefinitions); + stmt.setNString(2, preparedTypeDefinitions); } else { - stmt.setNString(2,""); + stmt.setNString(2, ""); } - stmt.setBytes(3,this.connection.getAttestationParameters()); + stmt.setBytes(3, this.connection.getAttestationParameters()); rs = (SQLServerResultSet) stmt.executeQueryInternal(); } catch (SQLException e) { if (e instanceof SQLServerException) { @@ -901,7 +910,9 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer rs.getBytes(DescribeParameterEncryptionResultSet1.KeyMdVersion.value()), rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()), rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()), - rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value())); + rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value()), + rs.getByte(DescribeParameterEncryptionResultSet1.KeyRequestedByEnclave.value()), + rs.getBytes(DescribeParameterEncryptionResultSet1.EnclaveCMKSignature.value())); } if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { getStatementLogger().fine("Matadata of CEKs is retrieved."); @@ -979,6 +990,24 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } + // Process the third resultset. + if (!stmt.getMoreResults()) { + throw new SQLServerException(this, SQLServerException.getErrString("R_UnexpectedDescribeParamFormat"), null, + 0, false); + } + + try { + rs = (SQLServerResultSet) stmt.getResultSet(); + rs.next(); + byte[] attestationResponse = rs.getBytes(1); + AttestationResponse ar = new AttestationResponse(attestationResponse); + System.out.println(ar.sessionID); + byte[] attestationCerts = getAttestationCertificates(); + ar.validateCert(attestationCerts); + } catch (SQLException | CertificateException | IOException e) { + e.printStackTrace(); + } + // Null check for rs is done already. rs.close(); @@ -988,6 +1017,20 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer connection.resetCurrentCommand(); } + private byte[] getAttestationCertificates() throws IOException, CertificateException { + java.net.URL url = new java.net.URL( + connection.enclaveAttestationUrl + "/attestationservice.svc/v2.0/signingCertificates/"); + java.net.URLConnection con = url.openConnection(); + String s = new String(con.getInputStream().readAllBytes()); + // omit the square brackets that come with the JSON + String[] bytesString = s.substring(1, s.length() - 1).split(","); + byte[] certData = new byte[bytesString.length]; + for (int i = 0; i < certData.length; i++) { + certData[i] = (byte) (Integer.parseInt(bytesString[i])); + } + return certData; + } + /** * Manages re-using cached handles. */ diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java index c57c20706..4815da741 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerStatement.java @@ -9,8 +9,7 @@ import static com.microsoft.sqlserver.jdbc.SQLServerConnection.parseAndCacheSQL; import java.sql.BatchUpdateException; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; +import java.sql.Blob; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLTimeoutException; @@ -18,7 +17,9 @@ import java.sql.Statement; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.HashMap; import java.util.ListIterator; +import java.util.Map; import java.util.Stack; import java.util.StringTokenizer; import java.util.Vector; @@ -767,12 +768,7 @@ private final class StmtExecCmd extends TDSCommand { } final boolean doExecute() throws SQLServerException { - try { - stmt.doExecuteStatement(this); - } catch (SQLException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + stmt.doExecuteStatement(this); return false; } @@ -818,7 +814,7 @@ final void setMaxRowsAndMaxFieldSize() throws SQLServerException { } } - final void doExecuteStatement(StmtExecCmd execCmd) throws SQLException { + final void doExecuteStatement(StmtExecCmd execCmd) throws SQLServerException { resetForReexecute(); // Set this command as the current command @@ -839,33 +835,12 @@ final void doExecuteStatement(StmtExecCmd execCmd) throws SQLException { // well. // // Note: similar logic in SQLServerPreparedStatement.doExecutePreparedStatement - setMaxRowsAndMaxFieldSize(); + // setMaxRowsAndMaxFieldSize(); if (loggerExternal.isLoggable(Level.FINER) && Util.isActivityTraceOn()) { loggerExternal.finer(toString() + " ActivityId: " + ActivityCorrelator.getNext().toString()); } - - if (this.connection.aeVersion == 2) { - try (SQLServerCallableStatement c = (SQLServerCallableStatement) this.connection.prepareCall("exec sp_describe_parameter_encryption ?,?,?")) { - c.setNString(1, sql); - c.setNString(2, "''"); - c.setBytes(3, this.connection.getAttestationPublicKey()); - try (ResultSet rs = c.executeQueryInternal()) { - - } - } catch (SQLException e) { - if (e instanceof SQLServerException) { - throw (SQLServerException) e; - } else { - throw new SQLServerException(SQLServerException.getErrString("R_UnableRetrieveParameterMetadata"), null, - 0, e); - } - } - } - - - - + if (isCursorable(executeMethod) && isSelect(sql)) { if (stmtlogger.isLoggable(java.util.logging.Level.FINE)) stmtlogger.fine(toString() + " Executing server side cursor " + sql); @@ -878,6 +853,10 @@ final void doExecuteStatement(StmtExecCmd execCmd) throws SQLException { TDSWriter tdsWriter = execCmd.startRequest(TDS.PKT_QUERY); + if (this.connection.enclaveAttestationUrl != null) { + tdsWriter.writeBytes(new byte[] {0x0,0x0}); + } + tdsWriter.writeString(sql); // If this is an INSERT statement and generated keys were requested @@ -914,6 +893,106 @@ final void doExecuteStatement(StmtExecCmd execCmd) throws SQLException { } } + public static byte[] hexStringToByteArray(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16)); + } + return data; + } + + private void getParameterEncryptionMetadata(String userSQL) throws SQLServerException { + /* + * The parameter list is created from the data types provided by the user for the parameters. the data types do + * not need to be the same as in the table definition. Also, when string is sent to an int field, the parameter + * is defined as nvarchar(). Same for varchar datatypes, exact length is used. + */ + SQLServerResultSet rs = null; + SQLServerPreparedStatement stmt = null; + + assert connection != null : "Connection should not be null"; + + try { + if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { + getStatementLogger().fine( + "Calling stored procedure sp_describe_parameter_encryption to get parameter encryption information."); + } + stmt = (SQLServerPreparedStatement) connection.prepareStatement("exec sp_describe_parameter_encryption N'" + + userSQL + + "',N'',0x03000000000000006800000045434B3330000000c48c7ce6df7b8da9c4433a6b02321814448f6830c37e308cb97df93ce9af0f5baf619d8705c4caf855d7592877aa0a40113a4ff6c84206508bfffd5ffd5309158697e491a2b9e0a29127ce27c34525a9b898ab63ce6342375f85cf31a84d6541"); + stmt.isInternalEncryptionQuery = true; + // stmt.setNString(1,userSQL); + // stmt.setNString(2,""); + // stmt.setBytes(3, hexStringToByteArray("")); + // stmt.setBytes(3,this.connection.getAttestationParameters()); + rs = (SQLServerResultSet) stmt.executeQueryInternal(); + } catch (SQLException e) { + if (e instanceof SQLServerException) { + throw (SQLServerException) e; + } else { + throw new SQLServerException(SQLServerException.getErrString("R_UnableRetrieveParameterMetadata"), null, + 0, e); + } + } + + if (null == rs) { + // No results. Meaning no parameter. + // Should never happen. + return; + } + + Map cekList = new HashMap<>(); + CekTableEntry cekEntry = null; + try { + while (rs.next()) { + int currentOrdinal = rs.getInt(DescribeParameterEncryptionResultSet1.KeyOrdinal.value()); + if (!cekList.containsKey(currentOrdinal)) { + cekEntry = new CekTableEntry(currentOrdinal); + cekList.put(cekEntry.ordinal, cekEntry); + } else { + cekEntry = cekList.get(currentOrdinal); + } + cekEntry.add(rs.getBytes(DescribeParameterEncryptionResultSet1.EncryptedKey.value()), + rs.getInt(DescribeParameterEncryptionResultSet1.DbId.value()), + rs.getInt(DescribeParameterEncryptionResultSet1.KeyId.value()), + rs.getInt(DescribeParameterEncryptionResultSet1.KeyVersion.value()), + rs.getBytes(DescribeParameterEncryptionResultSet1.KeyMdVersion.value()), + rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()), + rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()), + rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value()), + rs.getByte(DescribeParameterEncryptionResultSet1.KeyRequestedByEnclave.value()), + rs.getBytes(DescribeParameterEncryptionResultSet1.EnclaveCMKSignature.value())); + } + if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { + getStatementLogger().fine("Matadata of CEKs is retrieved."); + } + } catch (SQLException e) { + if (e instanceof SQLServerException) { + throw (SQLServerException) e; + } else { + throw new SQLServerException(SQLServerException.getErrString("R_UnableRetrieveParameterMetadata"), null, + 0, e); + } + } + + // Process the second resultset. + if (!stmt.getMoreResults()) { + throw new SQLServerException(this, SQLServerException.getErrString("R_UnexpectedDescribeParamFormat"), null, + 0, false); + } + + // Parameter count in the result set. + + // Null check for rs is done already. + rs.close(); + + if (null != stmt) { + stmt.close(); + } + connection.resetCurrentCommand(); + } + private final class StmtBatchExecCmd extends TDSCommand { /** * Always update serialVersionUID when prompted. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index 4b039a818..7e071731b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -2,11 +2,23 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.InvalidParameterSpecException; +import java.util.concurrent.ThreadLocalRandom; + +import javax.crypto.KeyAgreement; +import javax.crypto.spec.DHParameterSpec; public class SQLServerVSMEnclaveProvider implements ISQLServerEnclaveProvider { @@ -44,20 +56,41 @@ public VSMAtttestationRequest() { try { kpg = KeyPairGenerator.getInstance("EC"); kpg.initialize(384); - key = kpg.generateKeyPair(); - } catch (NoSuchAlgorithmException e) { + KeyPair kp = kpg.generateKeyPair(); + publickey = kp.getPublic(); + keyAgreement = KeyAgreement.getInstance("ECDH"); + keyAgreement.init(kp.getPrivate()); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { // TODO Auto-generated catch block e.printStackTrace(); } } + private BigInteger randomBigInt() { + return new BigInteger(512, ThreadLocalRandom.current()); + } + + private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); + + public static String bytesToHex(byte[] bytes) { + char[] hexChars = new char[bytes.length * 2]; + for (int j = 0; j < bytes.length; j++) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + } + return new String(hexChars); + } + @Override byte[] getBytes() throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); - os.write(enclaveType); - os.write(enclaveChallenge); - os.write(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(key.getPublic().getEncoded().length).array()); - os.write(key.getPublic().getEncoded()); + os.writeBytes(enclaveType); + os.writeBytes(enclaveChallenge); + int keyLength = publickey.getEncoded().length; + os.writeBytes(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(keyLength).array()); + os.writeBytes(publickey.getEncoded()); + System.out.println(bytesToHex(os.toByteArray())); return os.toByteArray(); } } From d6198492067c76963ca49a92c51b20719dabd8aa Mon Sep 17 00:00:00 2001 From: rene-ye Date: Tue, 24 Sep 2019 08:42:48 -0700 Subject: [PATCH 13/49] Fix ECDH Key --- .../java/com/microsoft/sqlserver/jdbc/AE.java | 4 +- .../jdbc/ISQLServerEnclaveProvider.java | 10 ++--- .../jdbc/SQLServerVSMEnclaveProvider.java | 37 +++++++++++++------ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java index 3bc9fc9b4..0f84f2932 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java @@ -355,9 +355,9 @@ boolean validateCert(byte[] b) throws CertificateException { try { healthCert.verify(cert.getPublicKey()); return true; - } catch (SignatureException se) { + } catch (SignatureException e) { // Doesn't match, invalid - } catch (NoSuchAlgorithmException | NoSuchProviderException | java.security.InvalidKeyException e) { + } catch (java.security.GeneralSecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java index 7d8c1716a..434d40521 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java @@ -1,10 +1,8 @@ package com.microsoft.sqlserver.jdbc; import java.io.IOException; -import java.security.KeyPair; -import java.security.PublicKey; - -import javax.crypto.KeyAgreement; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; public interface ISQLServerEnclaveProvider { @@ -19,8 +17,8 @@ public interface ISQLServerEnclaveProvider { abstract class BaseAttestationRequest { - protected PublicKey publickey; - KeyAgreement keyAgreement; + protected ECPublicKey publicKey; + protected ECPrivateKey privateKey; byte[] sharedsecret; byte[] getBytes() throws IOException { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index 7e071731b..b83668216 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -11,10 +11,14 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; import java.security.spec.InvalidParameterSpecException; +import java.util.Arrays; import java.util.concurrent.ThreadLocalRandom; import javax.crypto.KeyAgreement; @@ -48,8 +52,12 @@ public void getEnclaveSession() { class VSMAtttestationRequest extends BaseAttestationRequest { + byte ECDH_MAGIC[] = {0x45, 0x43, 0x4b, 0x33, 0x30, 0x00, 0x00, 0x00}; byte enclaveType[] = new byte[] {0x3, 0x0, 0x0, 0x0}; byte enclaveChallenge[] = new byte[] {0x0, 0x0, 0x0, 0x0}; + int publicKeyLength; + byte[] x; + byte[] y; public VSMAtttestationRequest() { KeyPairGenerator kpg; @@ -57,19 +65,24 @@ public VSMAtttestationRequest() { kpg = KeyPairGenerator.getInstance("EC"); kpg.initialize(384); KeyPair kp = kpg.generateKeyPair(); - publickey = kp.getPublic(); - keyAgreement = KeyAgreement.getInstance("ECDH"); - keyAgreement.init(kp.getPrivate()); - } catch (NoSuchAlgorithmException | InvalidKeyException e) { + publicKey = (ECPublicKey)kp.getPublic(); + privateKey = (ECPrivateKey)kp.getPrivate(); + ECPoint w = publicKey.getW(); + x = w.getAffineX().abs().toByteArray(); + y = w.getAffineY().abs().toByteArray(); + if (x[0] == 0) { + x = Arrays.copyOfRange(x,1,x.length); + } + if (y[0] == 0) { + y = Arrays.copyOfRange(y,1,y.length); + } + publicKeyLength = ECDH_MAGIC.length + x.length + y.length; + } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } } - private BigInteger randomBigInt() { - return new BigInteger(512, ThreadLocalRandom.current()); - } - private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); public static String bytesToHex(byte[] bytes) { @@ -87,10 +100,10 @@ byte[] getBytes() throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); os.writeBytes(enclaveType); os.writeBytes(enclaveChallenge); - int keyLength = publickey.getEncoded().length; - os.writeBytes(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(keyLength).array()); - os.writeBytes(publickey.getEncoded()); - System.out.println(bytesToHex(os.toByteArray())); + os.writeBytes(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(publicKeyLength).array()); + os.writeBytes(ECDH_MAGIC); + os.writeBytes(x); + os.writeBytes(y); return os.toByteArray(); } } From 6333f79cbd02d7b94bdcd1bab388105db873aac4 Mon Sep 17 00:00:00 2001 From: "v-susanh@microsoft.com" Date: Tue, 24 Sep 2019 15:11:23 -0700 Subject: [PATCH 14/49] fixed akv verify --- ...LServerColumnEncryptionAzureKeyVaultProvider.java | 11 +++++++---- ...QLServerColumnEncryptionJavaKeyStoreProvider.java | 12 ++++++------ .../sqlserver/jdbc/SQLServerSecurityUtility.java | 5 +++++ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionAzureKeyVaultProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionAzureKeyVaultProvider.java index 7e87a8485..1ebd65118 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionAzureKeyVaultProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionAzureKeyVaultProvider.java @@ -603,19 +603,22 @@ public boolean verifyColumnMasterKeyMetadata(String masterKeyPath, boolean allow MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(name.toLowerCase().getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); md.update(masterKeyPath.toLowerCase().getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); - // value of allowEnclaveComputations is true + // value of allowEnclaveComputations is always true here md.update("true".getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); - + byte[] dataToSign = md.digest(); if (null == dataToSign) { throw new SQLServerException(SQLServerException.getErrString("R_HashNull"), null); } // Sign the hash - byte[] signedHash = AzureKeyVaultSignHashedData(dataToSign, masterKeyPath); + byte[] dataToVerify = AzureKeyVaultSignHashedData(dataToSign, masterKeyPath); + if (null == dataToVerify) { + throw new SQLServerException(SQLServerException.getErrString("R_SignedHashLengthError"), null); + } // Validate the signature - return AzureKeyVaultVerifySignature(signedHash, signature, masterKeyPath); + return AzureKeyVaultVerifySignature(dataToVerify, signature, masterKeyPath); } catch (NoSuchAlgorithmException e) { throw new SQLServerException(SQLServerException.getErrString("R_NoSHA256Algorithm"), e); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java index f5ffed36f..2ffc5125d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionJavaKeyStoreProvider.java @@ -319,7 +319,8 @@ private byte[] getLittleEndianBytesFromShort(short value) { /* * Verify signature against certificate */ - private boolean rsaVerifySignature(byte[] dataToVerify, byte[] signature, CertificateDetails certificateDetails) throws SQLServerException { + private boolean rsaVerifySignature(byte[] dataToVerify, byte[] signature, + CertificateDetails certificateDetails) throws SQLServerException { try { Signature sig = Signature.getInstance("SHA256withRSA"); sig.initSign((PrivateKey) certificateDetails.privateKey); @@ -337,14 +338,14 @@ private boolean rsaVerifySignature(byte[] dataToVerify, byte[] signature, Certif throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } } - + @Override public boolean verifyColumnMasterKeyMetadata(String masterKeyPath, boolean allowEnclaveComputations, byte[] signature) throws SQLServerException { - + if (!allowEnclaveComputations) return false; - + KeyStoreProviderCommon.validateNonEmptyMasterKeyPath(masterKeyPath); CertificateDetails certificateDetails = getCertificateDetails(masterKeyPath); @@ -352,7 +353,7 @@ public boolean verifyColumnMasterKeyMetadata(String masterKeyPath, boolean allow MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(name.toLowerCase().getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); md.update(masterKeyPath.toLowerCase().getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); - // value of allowEnclaveComputations is true + // value of allowEnclaveComputations is always true here md.update("true".getBytes(java.nio.charset.StandardCharsets.UTF_16LE)); return rsaVerifySignature(md.digest(), signature, certificateDetails); @@ -361,5 +362,4 @@ public boolean verifyColumnMasterKeyMetadata(String masterKeyPath, boolean allow } } - } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java index 530a64880..933e07b1e 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerSecurityUtility.java @@ -215,6 +215,11 @@ static void verifyColumnMasterKeyMetadata(SQLServerConnection connection, String .getSystemColumnEncryptionKeyStoreProvider(keyStoreName); // There is no connection provider of this name, check for the global system providers. + if (null == provider) { + provider = SQLServerConnection.getGlobalSystemColumnEncryptionKeyStoreProvider(keyStoreName); + } + + // There is no global system provider of this name, check for the global custom providers. if (null == provider) { provider = SQLServerConnection.getGlobalCustomColumnEncryptionKeyStoreProvider(keyStoreName); } From aa11348090e9e2e4f4c569e48182223a043dddeb Mon Sep 17 00:00:00 2001 From: rene-ye Date: Thu, 26 Sep 2019 14:02:07 -0700 Subject: [PATCH 15/49] Add | generate session key --- .../java/com/microsoft/sqlserver/jdbc/AE.java | 97 ------- .../jdbc/ISQLServerEnclaveProvider.java | 40 ++- .../sqlserver/jdbc/SQLServerConnection.java | 33 ++- .../jdbc/SQLServerPreparedStatement.java | 74 ++---- .../sqlserver/jdbc/SQLServerResource.java | 9 +- .../jdbc/SQLServerVSMEnclaveProvider.java | 247 ++++++++++++++---- 6 files changed, 278 insertions(+), 222 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java index 0f84f2932..0afb79d5b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/AE.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/AE.java @@ -5,25 +5,8 @@ package com.microsoft.sqlserver.jdbc; -import java.io.ByteArrayInputStream; -import java.io.InputStream; import java.io.Serializable; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.Provider; -import java.security.Security; -import java.security.SignatureException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.sql.Blob; -import java.sql.SQLException; import java.util.ArrayList; -import java.util.Collection; import java.util.List; @@ -287,86 +270,6 @@ boolean IsAlgorithmInitialized() { } } - -class AttestationResponse { - int totalSize; - int identitySize; - int healthReportSize; - int enclaveReportSize; - - byte[] enclavePK; - byte[] healthReportCertificate; - byte[] enclaveReportPackage; - - int sessionInfoSize; - long sessionID; - int DHPKsize; - int DHPKSsize; - byte[] DHpublicKey; - byte[] publicKeySig; - - X509Certificate healthCert; - - AttestationResponse(byte[] b) { - ByteBuffer response = ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN); - this.totalSize = response.getInt(); - this.identitySize = response.getInt(); - this.healthReportSize = response.getInt(); - this.enclaveReportSize = response.getInt(); - - enclavePK = new byte[identitySize]; - healthReportCertificate = new byte[healthReportSize]; - enclaveReportPackage = new byte[enclaveReportSize]; - - response.get(enclavePK, 0, identitySize); - response.get(healthReportCertificate, 0, healthReportSize); - response.get(enclaveReportPackage, 0, enclaveReportSize); - - this.sessionInfoSize = response.getInt(); - this.sessionID = response.getLong(); - this.DHPKsize = response.getInt(); - this.DHPKSsize = response.getInt(); - - DHpublicKey = new byte[DHPKsize]; - publicKeySig = new byte[DHPKSsize]; - - response.get(DHpublicKey, 0, DHPKsize); - response.get(publicKeySig, 0, DHPKSsize); - - if (0 != response.remaining()) { - // throw exception - } - - try { - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - healthCert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(healthReportCertificate)); - } catch (CertificateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - @SuppressWarnings("unchecked") - boolean validateCert(byte[] b) throws CertificateException { - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Collection certs = (Collection) cf - .generateCertificates(new ByteArrayInputStream(b)); - for (X509Certificate cert : certs) { - try { - healthCert.verify(cert.getPublicKey()); - return true; - } catch (SignatureException e) { - // Doesn't match, invalid - } catch (java.security.GeneralSecurityException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return false; - } -} - - // Fields in the first resultset of "sp_describe_parameter_encryption" // We expect the server to return the fields in the resultset in the same order as mentioned below. // If the server changes the below order, then transparent parameter encryption will break. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java index 434d40521..3350a8fae 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java @@ -1,27 +1,47 @@ package com.microsoft.sqlserver.jdbc; -import java.io.IOException; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; public interface ISQLServerEnclaveProvider { - BaseAttestationRequest getAttestationParamters(); + BaseAttestationRequest getAttestationParamters(boolean b, String s) throws NoSuchAlgorithmException; - void createEnclaveSession(); + void createEnclaveSession(byte[] b) throws SQLServerException; void invalidateEnclaveSession(); - void getEnclaveSession(); + EnclaveSession getEnclaveSession(); } abstract class BaseAttestationRequest { - protected ECPublicKey publicKey; - protected ECPrivateKey privateKey; - byte[] sharedsecret; + protected PrivateKey privateKey; - byte[] getBytes() throws IOException { + byte[] getBytes() { return null; }; } + + +class EnclaveSession { + private long sessionID; + private byte[] sessionSecret; + + // Don't allow default instantiation + @SuppressWarnings("unused") + private EnclaveSession() {}; + + public EnclaveSession(long l, byte[] b) { + sessionID = l; + sessionSecret = b; + } + + long getSessionID() { + return sessionID; + } + + byte[] getSessionSecret() { + return sessionSecret; + } +} diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 2c8ea7c61..36a81acdf 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -20,6 +20,7 @@ import java.net.SocketException; import java.net.URL; import java.net.UnknownHostException; +import java.security.NoSuchAlgorithmException; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -628,7 +629,7 @@ boolean isColumnEncryptionSettingEnabled() { } String enclaveAttestationUrl = null; - + String keyStoreAuthentication = null; String keyStoreSecret = null; String keyStoreLocation = null; @@ -3548,12 +3549,12 @@ int writeAEFeatureRequest(boolean write, /* if false just calculates the length int len = 6; // (1byte = featureID, 4bytes = featureData length, 1 bytes = Version) if (write) { - tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TC - tdsWriter.writeInt(1); //length of version + tdsWriter.writeByte(TDS.TDS_FEATURE_EXT_AE); // FEATUREEXT_TC + tdsWriter.writeInt(1); // length of version if (null == enclaveAttestationUrl || enclaveAttestationUrl.isEmpty()) { tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION1); } else { - tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION2); + tdsWriter.writeByte(TDS.COLUMNENCRYPTION_VERSION2); } } return len; @@ -4565,7 +4566,7 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept throw new SQLServerException(SQLServerException.getErrString("R_InvalidAEVersionNumber"), null); } - byte aeVersion = data[0]; + aeVersion = data[0]; if (0 == aeVersion || aeVersion > TDS.COLUMNENCRYPTION_VERSION2) { throw new SQLServerException(SQLServerException.getErrString("R_InvalidAEVersionNumber"), null); } @@ -5692,7 +5693,7 @@ public T unwrap(Class iface) throws SQLException { private List openStatements; private boolean originalUseFmtOnly; - int aeVersion = 2; + int aeVersion = 0; protected void beginRequestInternal() throws SQLException { loggerExternal.entering(getClassNameLogging(), "beginRequest", this); @@ -6384,15 +6385,23 @@ final synchronized void removeOpenStatement(ISQLServerStatement st) { } } + boolean isAEv2() { + return aeVersion == 2; + } + ISQLServerEnclaveProvider enclaveProvider = new SQLServerVSMEnclaveProvider(); - public byte[] getAttestationParameters() { - byte[] b = null; + + byte[] getAttestationParameters() throws SQLServerException { try { - b = enclaveProvider.getAttestationParamters().getBytes(); - } catch (IOException e) { - + return enclaveProvider.getAttestationParamters(false, this.enclaveAttestationUrl).getBytes(); + } catch (NoSuchAlgorithmException e) { + SQLServerException.makeFromDriverError(this, enclaveProvider, e.getLocalizedMessage(), "0", false); } - return b; + return null; + } + + public void validateAttestationResponse(byte[] b) throws SQLServerException { + enclaveProvider.createEnclaveSession(b); } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index 364a6eb01..c2ac708e9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -8,15 +8,9 @@ import static com.microsoft.sqlserver.jdbc.SQLServerConnection.getCachedParsedSQL; import static com.microsoft.sqlserver.jdbc.SQLServerConnection.parseAndCacheSQL; -import java.io.ByteArrayInputStream; -import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; -import java.net.MalformedURLException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; import java.sql.BatchUpdateException; import java.sql.NClob; import java.sql.ParameterMetaData; @@ -35,8 +29,6 @@ import java.util.Vector; import java.util.logging.Level; -import org.apache.commons.codec.DecoderException; - import com.microsoft.sqlserver.jdbc.SQLServerConnection.CityHash128Key; import com.microsoft.sqlserver.jdbc.SQLServerConnection.PreparedStatementHandle; @@ -903,16 +895,27 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer } else { cekEntry = cekList.get(currentOrdinal); } - cekEntry.add(rs.getBytes(DescribeParameterEncryptionResultSet1.EncryptedKey.value()), - rs.getInt(DescribeParameterEncryptionResultSet1.DbId.value()), - rs.getInt(DescribeParameterEncryptionResultSet1.KeyId.value()), - rs.getInt(DescribeParameterEncryptionResultSet1.KeyVersion.value()), - rs.getBytes(DescribeParameterEncryptionResultSet1.KeyMdVersion.value()), - rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()), - rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()), - rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value()), - rs.getByte(DescribeParameterEncryptionResultSet1.KeyRequestedByEnclave.value()), - rs.getBytes(DescribeParameterEncryptionResultSet1.EnclaveCMKSignature.value())); + if (this.connection.isAEv2()) { + cekEntry.add(rs.getBytes(DescribeParameterEncryptionResultSet1.EncryptedKey.value()), + rs.getInt(DescribeParameterEncryptionResultSet1.DbId.value()), + rs.getInt(DescribeParameterEncryptionResultSet1.KeyId.value()), + rs.getInt(DescribeParameterEncryptionResultSet1.KeyVersion.value()), + rs.getBytes(DescribeParameterEncryptionResultSet1.KeyMdVersion.value()), + rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()), + rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()), + rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value()), + rs.getByte(DescribeParameterEncryptionResultSet1.KeyRequestedByEnclave.value()), + rs.getBytes(DescribeParameterEncryptionResultSet1.EnclaveCMKSignature.value())); + } else { + cekEntry.add(rs.getBytes(DescribeParameterEncryptionResultSet1.EncryptedKey.value()), + rs.getInt(DescribeParameterEncryptionResultSet1.DbId.value()), + rs.getInt(DescribeParameterEncryptionResultSet1.KeyId.value()), + rs.getInt(DescribeParameterEncryptionResultSet1.KeyVersion.value()), + rs.getBytes(DescribeParameterEncryptionResultSet1.KeyMdVersion.value()), + rs.getString(DescribeParameterEncryptionResultSet1.KeyPath.value()), + rs.getString(DescribeParameterEncryptionResultSet1.ProviderName.value()), + rs.getString(DescribeParameterEncryptionResultSet1.KeyEncryptionAlgorithm.value())); + } } if (getStatementLogger().isLoggable(java.util.logging.Level.FINE)) { getStatementLogger().fine("Matadata of CEKs is retrieved."); @@ -927,7 +930,7 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer } // Process the second resultset. - if (!stmt.getMoreResults()) { + if (!stmt.getMoreResults() && !this.connection.isAEv2()) { throw new SQLServerException(this, SQLServerException.getErrString("R_UnexpectedDescribeParamFormat"), null, 0, false); } @@ -991,21 +994,12 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer } // Process the third resultset. - if (!stmt.getMoreResults()) { - throw new SQLServerException(this, SQLServerException.getErrString("R_UnexpectedDescribeParamFormat"), null, - 0, false); - } - - try { + if (this.connection.isAEv2() && stmt.getMoreResults()) { rs = (SQLServerResultSet) stmt.getResultSet(); - rs.next(); - byte[] attestationResponse = rs.getBytes(1); - AttestationResponse ar = new AttestationResponse(attestationResponse); - System.out.println(ar.sessionID); - byte[] attestationCerts = getAttestationCertificates(); - ar.validateCert(attestationCerts); - } catch (SQLException | CertificateException | IOException e) { - e.printStackTrace(); + while (rs.next()) { + // This validates and establishes the enclave session if valid + this.connection.validateAttestationResponse(rs.getBytes(1)); + } } // Null check for rs is done already. @@ -1017,20 +1011,6 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer connection.resetCurrentCommand(); } - private byte[] getAttestationCertificates() throws IOException, CertificateException { - java.net.URL url = new java.net.URL( - connection.enclaveAttestationUrl + "/attestationservice.svc/v2.0/signingCertificates/"); - java.net.URLConnection con = url.openConnection(); - String s = new String(con.getInputStream().readAllBytes()); - // omit the square brackets that come with the JSON - String[] bytesString = s.substring(1, s.length() - 1).split(","); - byte[] certData = new byte[bytesString.length]; - for (int i = 0; i < certData.length; i++) { - certData[i] = (byte) (Integer.parseInt(bytesString[i])); - } - return certData; - } - /** * Manages re-using cached handles. */ diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 581ec7ddb..f902cf114 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -595,5 +595,12 @@ protected Object[][] getContents() { {"R_invalidUserSQL", "An error occurred when attempting to parse user SQL. Please verify SQL syntax."}, {"R_invalidInsertValuesQuery", "An error occurred when matching VALUES list to table columns. Please verify SQL syntax."}, - {"R_invalidValuesList", "An error occurred when reading VALUES list. Please verify SQL syntax."}}; + {"R_invalidValuesList", "An error occurred when reading VALUES list. Please verify SQL syntax."}, + + {"R_EnclaveResponseLengthError", + "More bytes from the server was recieved than expected when parsing Enclave Attestation response."}, + {"R_MalformedECDHPublicKey", "The ECDH public key from the server must be 104 bits in length."}, + {"R_MalformedECDHHeader", "Unexpected values for ECDH public key header from the server."}, + + }; }; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index b83668216..dc265e6f4 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -1,109 +1,246 @@ package com.microsoft.sqlserver.jdbc; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.security.AlgorithmParameters; -import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; +import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SignatureException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; -import java.security.spec.AlgorithmParameterSpec; -import java.security.spec.ECGenParameterSpec; -import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; -import java.security.spec.InvalidParameterSpecException; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; import java.util.Arrays; -import java.util.concurrent.ThreadLocalRandom; +import java.util.Collection; import javax.crypto.KeyAgreement; -import javax.crypto.spec.DHParameterSpec; public class SQLServerVSMEnclaveProvider implements ISQLServerEnclaveProvider { + private VSMAttestationParameters vsmParams = null; + private String attestationURL = null; + EnclaveSession enclaveSession = null; + @Override - public VSMAtttestationRequest getAttestationParamters() { - return new VSMAtttestationRequest(); + public VSMAttestationParameters getAttestationParamters(boolean createNewParameters, + String url) throws NoSuchAlgorithmException { + if (null == vsmParams || createNewParameters) { + attestationURL = url; + vsmParams = new VSMAttestationParameters(); + } + return vsmParams; } @Override - public void createEnclaveSession() { - + public void createEnclaveSession(byte[] b) throws SQLServerException { + AttestationResponse ar = new AttestationResponse(b); + try { + byte[] attestationCerts = getAttestationCertificates(); + ar.validateCert(attestationCerts); + enclaveSession = new EnclaveSession(ar.getSessionID(), vsmParams.createSessionSecret(ar.DHpublicKey)); + } catch (IOException | InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException e) { + SQLServerException.makeFromDriverError(null, this, e.getLocalizedMessage(), "0", false); + } } @Override public void invalidateEnclaveSession() { - + enclaveSession = null; + vsmParams = null; + attestationURL = null; } @Override - public void getEnclaveSession() { - + public EnclaveSession getEnclaveSession() { + return enclaveSession; } + private byte[] getAttestationCertificates() throws IOException { + java.net.URL url = new java.net.URL(attestationURL + "/attestationservice.svc/v2.0/signingCertificates/"); + java.net.URLConnection con = url.openConnection(); + String s = new String(con.getInputStream().readAllBytes()); + // omit the square brackets that come with the JSON + String[] bytesString = s.substring(1, s.length() - 1).split(","); + byte[] certData = new byte[bytesString.length]; + for (int i = 0; i < certData.length; i++) { + certData[i] = (byte) (Integer.parseInt(bytesString[i])); + } + return certData; + } } -class VSMAtttestationRequest extends BaseAttestationRequest { +class VSMAttestationParameters extends BaseAttestationRequest { - byte ECDH_MAGIC[] = {0x45, 0x43, 0x4b, 0x33, 0x30, 0x00, 0x00, 0x00}; - byte enclaveType[] = new byte[] {0x3, 0x0, 0x0, 0x0}; - byte enclaveChallenge[] = new byte[] {0x0, 0x0, 0x0, 0x0}; - int publicKeyLength; + // Static byte[] for VSM ECDH + static byte ECDH_MAGIC[] = {0x45, 0x43, 0x4b, 0x33, 0x30, 0x00, 0x00, 0x00}; + // Type 3 is VSM, sent as Little Endian 0x30000000 + static byte ENCLAVE_TYPE[] = new byte[] {0x3, 0x0, 0x0, 0x0}; + // VSM doesn't have a challenge + static byte ENCLAVE_CHALLENGE[] = new byte[] {0x0, 0x0, 0x0, 0x0}; + static int ENCLAVE_LENGTH = 104; byte[] x; byte[] y; - public VSMAtttestationRequest() { + public VSMAttestationParameters() throws NoSuchAlgorithmException { KeyPairGenerator kpg; - try { - kpg = KeyPairGenerator.getInstance("EC"); - kpg.initialize(384); - KeyPair kp = kpg.generateKeyPair(); - publicKey = (ECPublicKey)kp.getPublic(); - privateKey = (ECPrivateKey)kp.getPrivate(); - ECPoint w = publicKey.getW(); - x = w.getAffineX().abs().toByteArray(); - y = w.getAffineY().abs().toByteArray(); - if (x[0] == 0) { - x = Arrays.copyOfRange(x,1,x.length); - } - if (y[0] == 0) { - y = Arrays.copyOfRange(y,1,y.length); - } - publicKeyLength = ECDH_MAGIC.length + x.length + y.length; - } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + kpg = KeyPairGenerator.getInstance("EC"); + kpg.initialize(384); + KeyPair kp = kpg.generateKeyPair(); + ECPublicKey publicKey = (ECPublicKey) kp.getPublic(); + privateKey = kp.getPrivate(); + ECPoint w = publicKey.getW(); + x = w.getAffineX().toByteArray(); + y = w.getAffineY().toByteArray(); + /* + * For some reason toByteArray doesn't have an Signum option like the constructor. Manually remove leading 00 + * byte if it exists. + */ + if (x[0] == 0 && x.length != 48) { + x = Arrays.copyOfRange(x, 1, x.length); } - } - - private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); - - public static String bytesToHex(byte[] bytes) { - char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = HEX_ARRAY[v >>> 4]; - hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + if (y[0] == 0 && y.length != 48) { + y = Arrays.copyOfRange(y, 1, y.length); } - return new String(hexChars); } @Override - byte[] getBytes() throws IOException { + byte[] getBytes() { ByteArrayOutputStream os = new ByteArrayOutputStream(); - os.writeBytes(enclaveType); - os.writeBytes(enclaveChallenge); - os.writeBytes(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(publicKeyLength).array()); + os.writeBytes(ENCLAVE_TYPE); + os.writeBytes(ENCLAVE_CHALLENGE); + os.writeBytes(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ENCLAVE_LENGTH).array()); os.writeBytes(ECDH_MAGIC); os.writeBytes(x); os.writeBytes(y); return os.toByteArray(); } + + byte[] createSessionSecret( + byte[] serverResponse) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SQLServerException { + if (serverResponse.length != 104) { + SQLServerException.makeFromDriverError(null, this, + SQLServerResource.getResource("R_MalformedECDHPublicKey"), "0", false); + } + ByteBuffer sr = ByteBuffer.wrap(serverResponse); + byte[] magic = new byte[8]; + sr.get(magic); + if (magic != ECDH_MAGIC) { + SQLServerException.makeFromDriverError(null, this, SQLServerResource.getResource("R_MalformedECDHHeader"), + "0", false); + } + byte[] x = new byte[48]; + byte[] y = new byte[48]; + sr.get(x); + sr.get(y); + /* + * Server returns X and Y coordinates, create a key using the point of the server and our key parameters. + * Public/Private key parameters are the same. + */ + ECPublicKeySpec keySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(1, x), new BigInteger(1, y)), + ((ECPrivateKey) privateKey).getParams()); + KeyAgreement ka = KeyAgreement.getInstance("ECDH"); + ka.init(privateKey); + // Generate a PublicKey from the above key specifications and do an agreement with our PrivateKey + ka.doPhase(KeyFactory.getInstance("EC").generatePublic(keySpec), true); + // Generate a Secret from the agreement and hash with SHA-256 to create Session Secret + return MessageDigest.getInstance("SHA-256").digest(ka.generateSecret()); + } +} + + +class AttestationResponse { + int totalSize; + int identitySize; + int healthReportSize; + int enclaveReportSize; + + byte[] enclavePK; + byte[] healthReportCertificate; + byte[] enclaveReportPackage; + + int sessionInfoSize; + long sessionID; + int DHPKsize; + int DHPKSsize; + byte[] DHpublicKey; + byte[] publicKeySig; + + X509Certificate healthCert; + + AttestationResponse(byte[] b) throws SQLServerException { + ByteBuffer response = ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN); + this.totalSize = response.getInt(); + this.identitySize = response.getInt(); + this.healthReportSize = response.getInt(); + this.enclaveReportSize = response.getInt(); + + enclavePK = new byte[identitySize]; + healthReportCertificate = new byte[healthReportSize]; + enclaveReportPackage = new byte[enclaveReportSize]; + + response.get(enclavePK, 0, identitySize); + response.get(healthReportCertificate, 0, healthReportSize); + response.get(enclaveReportPackage, 0, enclaveReportSize); + + this.sessionInfoSize = response.getInt(); + this.sessionID = response.getLong(); + this.DHPKsize = response.getInt(); + this.DHPKSsize = response.getInt(); + + DHpublicKey = new byte[DHPKsize]; + publicKeySig = new byte[DHPKSsize]; + + response.get(DHpublicKey, 0, DHPKsize); + response.get(publicKeySig, 0, DHPKSsize); + + if (0 != response.remaining()) { + SQLServerException.makeFromDriverError(null, this, + SQLServerResource.getResource("R_EnclaveResponseLengthError"), "0", false); + } + + try { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + healthCert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(healthReportCertificate)); + } catch (CertificateException ce) { + SQLServerException.makeFromDriverError(null, this, ce.getLocalizedMessage(), "0", false); + } + } + + @SuppressWarnings("unchecked") + boolean validateCert(byte[] b) throws SQLServerException { + try { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Collection certs = (Collection) cf + .generateCertificates(new ByteArrayInputStream(b)); + for (X509Certificate cert : certs) { + try { + healthCert.verify(cert.getPublicKey()); + return true; + } catch (SignatureException e) { + // Doesn't match, but continue looping through the rest of the certificates + } + } + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException | CertificateException e) { + SQLServerException.makeFromDriverError(null, this, e.getLocalizedMessage(), "0", false); + } + return false; + } + + long getSessionID() { + return sessionID; + } } From b86eef319b8b052a24553f0d4ee433e56d4c7437 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 16 Oct 2019 16:13:19 -0700 Subject: [PATCH 16/49] merged --- .../sqlserver/jdbc/SQLServerDriver.java | 38 ------------------- 1 file changed, 38 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index 7b67c7958..4e30fa3f9 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -112,44 +112,6 @@ static ColumnEncryptionSetting valueOfString(String value) throws SQLServerExcep } } -enum AttestationProtocol { - HGS("HGS"), - AAS("AAS"); - - private final String protocol; - - AttestationProtocol(String protocol) { - this.protocol = protocol; - } - - static boolean isValidAttestationProtocol(String protocol) { - for (AttestationProtocol p : AttestationProtocol.values()) { - if (protocol.equalsIgnoreCase(p.toString())) { - return true; - } - } - return false; - } -} - -enum EnclaveType { - VBS("VBS"); // only VBS type supported - - private final String type; - - EnclaveType(String type){ - this.type = type; - } - - static boolean isValidEnclaveType(String type) { - for (EnclaveType t : EnclaveType.values()) { - if (type.equalsIgnoreCase(t.toString())) { - return true; - } - } - return false; - } -} enum AttestationProtocol { HGS("HGS"); // only protocol supported currently From c4acfb85b900c7e73630948d03d257c9ac21b8fc Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 17 Oct 2019 12:31:10 -0700 Subject: [PATCH 17/49] updated to use reqExternalSetup tag --- .../jdbc/AlwaysEncrypted/AESetup.java | 173 ++---- .../jdbc/AlwaysEncrypted/EnclaveTest.java | 587 ++++++++++++++++++ .../JDBCEncryptionDecryptionTest.java | 400 +++--------- .../sqlserver/jdbc/TestResource.java | 7 +- 4 files changed, 727 insertions(+), 440 deletions(-) create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 634864ea9..af735c047 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -11,7 +11,6 @@ import java.io.FileReader; import java.io.IOException; import java.math.BigDecimal; -import java.sql.Connection; import java.sql.Date; import java.sql.JDBCType; import java.sql.SQLException; @@ -25,6 +24,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Tag; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; import org.opentest4j.TestAbortedException; @@ -35,10 +35,10 @@ import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionJavaKeyStoreProvider; import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionKeyStoreProvider; import com.microsoft.sqlserver.jdbc.SQLServerConnection; -import com.microsoft.sqlserver.jdbc.SQLServerException; import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement; import com.microsoft.sqlserver.jdbc.SQLServerStatement; import com.microsoft.sqlserver.jdbc.SQLServerStatementColumnEncryptionSetting; +import com.microsoft.sqlserver.jdbc.TestResource; import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.AbstractTest; @@ -55,33 +55,28 @@ * */ @RunWith(JUnitPlatform.class) +@Tag(Constants.reqExternalSetup) public class AESetup extends AbstractTest { - static String filePath = null; - static String thumbprint = null; - static String javaKeyPath = null; + static String cmkJks = Constants.CMK_NAME + "_JKS"; + static String cmkWin = Constants.CMK_NAME + "_WIN"; + static String cmkAkv = Constants.CMK_NAME + "_AKV"; + static String cekJks = Constants.CEK_NAME + "_JKS"; + static String cekWin = Constants.CEK_NAME + "_WIN"; + static String cekAkv = Constants.CEK_NAME + "_AKV"; + static String javaKeyAliases = null; - static String windowsKeyPath = null; - static String applicationClientID = null; - static String applicationKey = null; static String[] keyIDs = null; - static String cmkJks = null; - static String cmkWin = null; - static String cmkAkv = null; - static String cekJks = null; - static String cekWin = null; - static String cekAkv = null; - - static boolean kspRegistered = false; static SQLServerColumnEncryptionKeyStoreProvider jksProvider = null; static SQLServerColumnEncryptionAzureKeyVaultProvider akvProvider = null; static SQLServerStatementColumnEncryptionSetting stmtColEncSetting = null; static String AETestConnectionString; static Properties AEInfo; - static boolean isAEv2Supported = false; + static Map map = new HashMap(); - public static final String tableName = RandomUtil.getIdentifier("AETest_"); + static boolean isKspRegistered = false; + public static final String tableName = RandomUtil.getIdentifier("AETest_"); public static final String CHAR_TABLE_AE = RandomUtil.getIdentifier("JDBCEncryptedChar"); public static final String BINARY_TABLE_AE = RandomUtil.getIdentifier("JDBCEncryptedBinary"); public static final String DATE_TABLE_AE = RandomUtil.getIdentifier("JDBCEncryptedDate"); @@ -133,57 +128,22 @@ enum ColumnType { /* * List of all the randomized columns in the tests */ - static String[] randomizedColumns = { - "PlainBinary binary(20)", - "PlainVarbinary varbinary(50)", - "PlainVarbinaryMax varbinary(max)", - "PlainBinary512 binary(512)", - "PlainBinary8000 varbinary(8000)", - "PlainChar char(20)", - "PlainVarchar varchar(50)", - "PlainVarcharMax varchar(max)", - "PlainNchar nchar(30)", - "PlainNvarchar nvarchar(60)", - "PlainNvarcharMax nvarchar(max)", - "PlainUniqueidentifier uniqueidentifier", - "PlainVarchar8000 varchar(8000)", - "PlainNvarchar4000 nvarchar(4000)", - "PlainDate date", - "PlainDatetime2Default datetime2", - "PlainDatetimeoffsetDefault datetimeoffset", - "PlainTimeDefault time", - "PlainDatetime datetime", - "PlainSmalldatetime smalldatetime", - "PlainDatetime2 datetime2(0)", - "PlainDatetime2Default datetime2", - "PlainDatetimeoffsetDefault datetimeoffset", - "PlainTimeDefault time", - "PlainTime time(0)", - "PlainDatetimeoffset datetimeoffset(0)", - "PlainDatetime2 datetime2(2)", - "PlainTime time(2)", - "PlainDatetimeoffset datetimeoffset(2)", - "PlainBit bit", - "PlainTinyint tinyint", - "PlainSmallint smallint", - "PlainInt int", - "PlainBigint bigint", - "PlainFloatDefault float", - "PlainFloat float(30)", - "PlainReal real", - "PlainDecimalDefault decimal", - "PlainDecimal decimal(10,5)", - "PlainNumericDefault numeric", - "PlainNumeric numeric(8,2)", - "PlainSmallMoney smallmoney", - "PlainMoney money", - "PlainDecimal2 decimal(28,4)", - "PlainNumeric2 numeric(28,4)", - "PlainFloat float(30)", - "PlainDecimal decimal(30)", - "PlainNumeric numeric(30)" - }; - + static String[] randomizedColumns = {"PlainBinary binary(20)", "PlainVarbinary varbinary(50)", + "PlainVarbinaryMax varbinary(max)", "PlainBinary512 binary(512)", "PlainBinary8000 varbinary(8000)", + "PlainChar char(20)", "PlainVarchar varchar(50)", "PlainVarcharMax varchar(max)", "PlainNchar nchar(30)", + "PlainNvarchar nvarchar(60)", "PlainNvarcharMax nvarchar(max)", "PlainUniqueidentifier uniqueidentifier", + "PlainVarchar8000 varchar(8000)", "PlainNvarchar4000 nvarchar(4000)", "PlainDate date", + "PlainDatetime2Default datetime2", "PlainDatetimeoffsetDefault datetimeoffset", "PlainTimeDefault time", + "PlainDatetime datetime", "PlainSmalldatetime smalldatetime", "PlainDatetime2 datetime2(0)", + "PlainDatetime2Default datetime2", "PlainDatetimeoffsetDefault datetimeoffset", "PlainTimeDefault time", + "PlainTime time(0)", "PlainDatetimeoffset datetimeoffset(0)", "PlainDatetime2 datetime2(2)", + "PlainTime time(2)", "PlainDatetimeoffset datetimeoffset(2)", "PlainBit bit", "PlainTinyint tinyint", + "PlainSmallint smallint", "PlainInt int", "PlainBigint bigint", "PlainFloatDefault float", + "PlainFloat float(30)", "PlainReal real", "PlainDecimalDefault decimal", "PlainDecimal decimal(10,5)", + "PlainNumericDefault numeric", "PlainNumeric numeric(8,2)", "PlainSmallMoney smallmoney", + "PlainMoney money", "PlainDecimal2 decimal(28,4)", "PlainNumeric2 numeric(28,4)", "PlainFloat float(30)", + "PlainDecimal decimal(30)", "PlainNumeric numeric(30)"}; + /** * Create connection, statement and generate path of resource file * @@ -193,84 +153,49 @@ enum ColumnType { @BeforeAll public static void setUpConnection() throws TestAbortedException, Exception { AETestConnectionString = connectionString + ";sendTimeAsDateTime=false"; - String tmpConnectionString = AETestConnectionString; - String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); - if (null != enclaveAttestationUrl) { - tmpConnectionString = TestUtils.addOrOverrideProperty(tmpConnectionString, "enclaveAttestationUrl", - enclaveAttestationUrl); - } - String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); - if (null != enclaveAttestationProtocol) { - tmpConnectionString = TestUtils.addOrOverrideProperty(tmpConnectionString, "enclaveAttestationProtocol", - enclaveAttestationProtocol); - } + String applicationClientID = TestUtils.getConfiguredProperty("applicationClientID"); + String applicationKey = TestUtils.getConfiguredProperty("applicationKey"); + String keyID = TestUtils.getConfiguredProperty("keyID"); + String windowsKeyPath = TestUtils.getConfiguredProperty("windowsKeyPath"); + String javaKeyPath = TestUtils.getCurrentClassPath() + Constants.JKS_NAME; - // add enclave properties if AEv2 supported - try (Connection con = PrepUtil.getConnection(tmpConnectionString)) { - if (TestUtils.isAEv2(con)) { - isAEv2Supported = true; - AETestConnectionString = tmpConnectionString; - } - } catch (SQLServerException e) { - if (!e.getMessage().matches(TestUtils.formatErrorMsg("R_enclaveNotSupported"))) { - // ignore AEv2 not supported errors - fail(e.getMessage()); - } + if (null == applicationClientID || null == applicationKey || null == keyID || null == windowsKeyPath) { + fail(TestResource.getResource("R_reqExternalSetup")); } - cmkJks = Constants.CMK_NAME + "_JKS"; - cekJks = Constants.CEK_NAME + "_JKS"; - readFromFile(Constants.JAVA_KEY_STORE_FILENAME, "Alias name"); - javaKeyPath = TestUtils.getCurrentClassPath() + Constants.JKS_NAME; - applicationClientID = TestUtils.getConfiguredProperty("applicationClientID"); - applicationKey = TestUtils.getConfiguredProperty("applicationKey"); - String keyID = TestUtils.getConfiguredProperty("keyID"); - if (null != keyID) { - keyIDs = keyID.split(";"); - } + keyIDs = keyID.split(";"); - Map map = new HashMap(); if (null == jksProvider) { jksProvider = new SQLServerColumnEncryptionJavaKeyStoreProvider(javaKeyPath, Constants.JKS_SECRET.toCharArray()); map.put("My_KEYSTORE", jksProvider); } - if (null == akvProvider && null != applicationClientID && null != applicationKey) { + if (null == akvProvider) { akvProvider = new SQLServerColumnEncryptionAzureKeyVaultProvider(applicationClientID, applicationKey); map.put(Constants.AZURE_KEY_VAULT_NAME, akvProvider); } - if (!kspRegistered && (null != jksProvider || null != akvProvider)) { + if (!isKspRegistered) { SQLServerConnection.registerColumnEncryptionKeyStoreProviders(map); - kspRegistered = true; + isKspRegistered = true; } dropAll(); - // always test JKS createCMK(cmkJks, Constants.JAVA_KEY_STORE_NAME, javaKeyAliases, Constants.CMK_SIGNATURE); createCEK(cmkJks, cekJks, jksProvider); - if (null != akvProvider) { - cmkAkv = Constants.CMK_NAME + "_AKV"; - cekAkv = Constants.CEK_NAME + "_AKV"; + createCMK(cmkAkv, Constants.AZURE_KEY_VAULT_NAME, keyIDs[0], Constants.CMK_SIGNATURE_AKV); + createCEK(cmkAkv, cekAkv, akvProvider); - createCMK(cmkAkv, Constants.AZURE_KEY_VAULT_NAME, keyIDs[0], Constants.CMK_SIGNATURE_AKV); - createCEK(cmkAkv, cekAkv, akvProvider); - } + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "windowsKeyPath", + windowsKeyPath); - windowsKeyPath = TestUtils.getConfiguredProperty("windowsKeyPath"); - if (null != windowsKeyPath) { - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "windowsKeyPath", - windowsKeyPath); - cmkWin = Constants.CMK_NAME + "_WIN"; - cekWin = Constants.CEK_NAME + "_WIN"; - createCMK(cmkWin, Constants.WINDOWS_KEY_STORE_NAME, windowsKeyPath, Constants.CMK_SIGNATURE); - createCEK(cmkWin, cekWin, null); - } + createCMK(cmkWin, Constants.WINDOWS_KEY_STORE_NAME, windowsKeyPath, Constants.CMK_SIGNATURE); + createCEK(cmkWin, cekWin, null); stmtColEncSetting = SQLServerStatementColumnEncryptionSetting.Enabled; @@ -316,7 +241,7 @@ public static void dropAll() throws Exception { * @throws IOException */ private static void readFromFile(String inputFile, String lookupValue) throws IOException { - filePath = TestUtils.getCurrentClassPath(); + String filePath = TestUtils.getCurrentClassPath(); try { File f = new File(filePath + inputFile); try (BufferedReader buffer = new BufferedReader(new FileReader(f))) { @@ -547,7 +472,9 @@ private static void createCMK(String cmkName, String keyStoreName, String keyPat String sql = " if not exists (SELECT name from sys.column_master_keys where name='" + cmkName + "')" + " begin" + " CREATE COLUMN MASTER KEY " + cmkName + " WITH (KEY_STORE_PROVIDER_NAME = '" + keyStoreName + "', KEY_PATH = '" + keyPath + "'" - + (TestUtils.isAEv2(con) ? ",ENCLAVE_COMPUTATIONS (SIGNATURE = " + signature + ")) end" : ") end"); + // + (TestUtils.isAEv2(con) ? ",ENCLAVE_COMPUTATIONS (SIGNATURE = " + signature + ")) end" : ") + // end"); + + ",ENCLAVE_COMPUTATIONS (SIGNATURE = " + signature + ")) end"; stmt.execute(sql); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java new file mode 100644 index 000000000..6748aa5bc --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java @@ -0,0 +1,587 @@ +/* + * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made + * available under the terms of the MIT License. See the LICENSE file in the project root for more information. + */ +package com.microsoft.sqlserver.jdbc.AlwaysEncrypted; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.LinkedList; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; +import org.opentest4j.TestAbortedException; + +import com.microsoft.sqlserver.jdbc.RandomData; +import com.microsoft.sqlserver.jdbc.SQLServerConnection; +import com.microsoft.sqlserver.jdbc.SQLServerStatement; +import com.microsoft.sqlserver.jdbc.TestUtils; +import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; +import com.microsoft.sqlserver.testframework.Constants; +import com.microsoft.sqlserver.testframework.PrepUtil; + + +/** + * Tests Enclave Decryption and encryption of values + * + */ +@RunWith(JUnitPlatform.class) +@Tag(Constants.xSQLv15) +@Tag(Constants.xAzureSQLDW) +@Tag(Constants.xAzureSQLDB) +@Tag(Constants.reqExternalSetup) +public class EnclaveTest extends JDBCEncryptionDecryptionTest { + + private boolean nullable = false; + + @BeforeAll + public static void setupEnclave() throws TestAbortedException, Exception { + String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); + if (null != enclaveAttestationUrl) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", + enclaveAttestationUrl); + } + String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); + if (null != enclaveAttestationProtocol) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, + "enclaveAttestationProtocol", enclaveAttestationProtocol); + } + } + + /** + * Junit test case for char set string for string values + * + * @throws SQLException + */ + @Test + public void testCharSpecificSetter() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = createCharValues(nullable); + + testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, true); + testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, true); + testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, true); + } + } + + /** + * Junit test case for char set object for string values + * + * @throws SQLException + */ + @Test + public void testCharSetObject() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = createCharValues(nullable); + + testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, true); + testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, true); + testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, true); + } + } + + /** + * Junit test case for char set object for jdbc string values + * + * @throws SQLException + */ + @Test + public void testCharSetObjectWithJDBCTypes() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = createCharValues(nullable); + + testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); + testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); + testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); + } + } + + /** + * Junit test case for char set string for null values + * + * @throws SQLException + */ + public void testCharSpecificSetterNull() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = {null, null, null, null, null, null, null, null, null}; + + testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, true); + testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, true); + testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, true); + } + } + + /** + * Junit test case for char set object for null values + * + * @throws SQLException + */ + @Test + public void testCharSetObjectNull() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = {null, null, null, null, null, null, null, null, null}; + + testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, true); + testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, true); + testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, true); + } + } + + /** + * Junit test case for char set null for null values + * + * @throws SQLException + */ + @Test + public void testCharSetNull() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = {null, null, null, null, null, null, null, null, null}; + + testChars(stmt, cekJks, charTable, values, TestCase.NULL, true); + testChars(stmt, cekWin, charTable, values, TestCase.NULL, true); + testChars(stmt, cekAkv, charTable, values, TestCase.NULL, true); + } + } + + /** + * Junit test case for binary set binary for binary values + * + * @throws SQLException + */ + @Test + public void testBinarySpecificSetter() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createbinaryValues(false); + + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); + } + } + + /** + * Junit test case for binary set object for binary values + * + * @throws SQLException + */ + @Test + public void testBinarySetobject() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createbinaryValues(false); + + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT); + } + } + + /** + * Junit test case for binary set null for binary values + * + * @throws SQLException + */ + @Test + public void testBinarySetNull() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createbinaryValues(true); + + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NULL); + + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL); + } + } + + /** + * Junit test case for binary set binary for null values + * + * @throws SQLException + */ + @Test + public void testBinarySpecificSetterNull() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createbinaryValues(true); + + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); + } + } + + /** + * Junit test case for binary set object for null values + * + * @throws SQLException + */ + @Test + public void testBinarysetObjectNull() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createbinaryValues(true); + + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_NULL); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL); + } + } + + /** + * Junit test case for binary set object for jdbc type binary values + * + * @throws SQLException + */ + @Test + public void testBinarySetObjectWithJDBCTypes() throws SQLException { + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createbinaryValues(false); + + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + } + } + + /** + * Junit test case for date set date for date values + * + * @throws SQLException + */ + @Test + public void testDateSpecificSetter() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); + } + } + + /** + * Junit test case for date set object for date values + * + * @throws SQLException + */ + @Test + public void testDateSetObject() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT); + } + } + + /** + * Junit test case for date set object for java date values + * + * @throws SQLException + */ + @Test + public void testDateSetObjectWithJavaType() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); + } + } + + /** + * Junit test case for date set object for jdbc date values + * + * @throws SQLException + */ + @Test + public void testDateSetObjectWithJDBCType() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + } + } + + /** + * Junit test case for date set date for min/max date values + * + * @throws SQLException + */ + @Test + public void testDateSpecificSetterMinMaxValue() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + RandomData.returnMinMax = true; + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); + } + } + + /** + * Junit test case for date set date for null values + * + * @throws SQLException + */ + @Test + public void testDateSetNull() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + RandomData.returnNull = true; + nullable = true; + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.NULL); + testDates(stmt, cekWin, dateTable, values, TestCase.NULL); + testDates(stmt, cekAkv, dateTable, values, TestCase.NULL); + } + + nullable = false; + RandomData.returnNull = false; + } + + /** + * Junit test case for date set object for null values + * + * @throws SQLException + */ + @Test + public void testDateSetObjectNull() throws SQLException { + RandomData.returnNull = true; + nullable = true; + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_NULL); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL); + } + + nullable = false; + RandomData.returnNull = false; + } + + /** + * Junit test case for numeric set numeric for numeric values + * + * @throws SQLException + */ + @Test + public void testNumericSpecificSetter() throws TestAbortedException, Exception { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + } + } + + /** + * Junit test case for numeric set object for numeric values + * + * @throws SQLException + */ + @Test + public void testNumericSetObject() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT); + } + } + + /** + * Junit test case for numeric set object for jdbc type numeric values + * + * @throws SQLException + */ + @Test + public void testNumericSetObjectWithJDBCTypes() throws SQLException { + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); + } + } + + /** + * Junit test case for numeric set numeric for max numeric values + * + * @throws SQLException + */ + @Test + public void testNumericSpecificSetterMaxValue() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + + String[] values1 = {Boolean.TRUE.toString(), "255", "32767", "2147483647", "9223372036854775807", + "1.79E308", "1.123", "3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + String[] values2 = {Boolean.TRUE.toString(), "255", "32767", "2147483647", "9223372036854775807", + "1.79E308", "1.123", "3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + } + } + + /** + * Junit test case for numeric set numeric for min numeric values + * + * @throws SQLException + */ + @Test + public void testNumericSpecificSetterMinValue() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = {Boolean.FALSE.toString(), "0", "-32768", "-2147483648", "-9223372036854775808", + "-1.79E308", "1.123", "-3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "-214748.3648", "-922337203685477.5808", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + String[] values2 = {Boolean.FALSE.toString(), "0", "-32768", "-2147483648", "-9223372036854775808", + "-1.79E308", "1.123", "-3.4E38", "999999999999999999", "12345.12345", "999999999999999999", + "567812.78", "-214748.3648", "-922337203685477.5808", "999999999999999999999999.9999", + "999999999999999999999999.9999"}; + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + } + } + + /** + * Junit test case for numeric set numeric for null values + * + * @throws SQLException + */ + @Test + public void testNumericSpecificSetterNull() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + nullable = true; + RandomData.returnNull = true; + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); + } + + nullable = false; + RandomData.returnNull = false; + } + + /** + * Junit test case for numeric set object for null values + * + * @throws SQLException + */ + @Test + public void testNumericSpecificSetterSetObjectNull() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + nullable = true; + RandomData.returnNull = true; + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); + } + + nullable = false; + RandomData.returnNull = false; + } + + /** + * Junit test case for numeric set numeric for null normalization values + * + * @throws SQLException + */ + @Test + public void testNumericNormalization() throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values1 = {Boolean.TRUE.toString(), "1", "127", "100", "100", "1.123", "1.123", "1.123", + "123456789123456789", "12345.12345", "987654321123456789", "567812.78", "7812.7812", "7812.7812", + "999999999999999999999999.9999", "999999999999999999999999.9999"}; + String[] values2 = {Boolean.TRUE.toString(), "1", "127", "100", "100", "1.123", "1.123", "1.123", + "123456789123456789", "12345.12345", "987654321123456789", "567812.78", "7812.7812", "7812.7812", + "999999999999999999999999.9999", "999999999999999999999999.9999"}; + + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + } + } + + @Test + public void testAEFMTOnly() throws SQLException { + try (SQLServerConnection c = PrepUtil.getConnection(AETestConnectionString + ";useFmtOnly=true", AEInfo); + Statement s = c.createStatement()) { + dropTables(s); + createTable(NUMERIC_TABLE_AE, cekJks, numericTable); + String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; + try (PreparedStatement p = c.prepareStatement(sql)) { + ParameterMetaData pmd = p.getParameterMetaData(); + assertTrue(pmd.getParameterCount() == 48); + } + } + } +} diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index b2be22d5e..bb4385d20 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -40,6 +40,7 @@ @Tag(Constants.xSQLv12) @Tag(Constants.xAzureSQLDW) @Tag(Constants.xAzureSQLDB) +@Tag(Constants.reqExternalSetup) public class JDBCEncryptionDecryptionTest extends AESetup { private boolean nullable = false; @@ -59,30 +60,14 @@ enum TestCase { * @throws SQLException */ @Test - public void testCharSpecificSetter_aev1() throws SQLException { - testCharSpecificSetter(false); - } - - @Tag(Constants.xSQLv15) - @Test - public void testCharSpecificSetter_aev2() throws SQLException { - testCharSpecificSetter(isAEv2Supported); - } - - private void testCharSpecificSetter(boolean isTestEnclave) throws SQLException { + public void testCharSpecificSetter() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = createCharValues(nullable); - testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, isTestEnclave); - - if (null != cekWin) { - testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, isTestEnclave); - } - - if (null != cekAkv) { - testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, isTestEnclave); - } + testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, false); + testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, false); + testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, false); } } @@ -92,31 +77,14 @@ private void testCharSpecificSetter(boolean isTestEnclave) throws SQLException { * @throws SQLException */ @Test - public void testCharSetObject_aev1() throws SQLException { - testCharSetObject(false); - } - - @Tag(Constants.xSQLv15) - @Test - public void testCharSetObject_aev2() throws SQLException { - testCharSetObject(isAEv2Supported); - } - - private void testCharSetObject(boolean isTestEnclave) throws SQLException { + public void testCharSetObject() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = createCharValues(nullable); - testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, isTestEnclave); - - if (null != cekWin) { - testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, isTestEnclave); - } - - if (null != cekAkv) { - testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, isTestEnclave); - } - + testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, false); + testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, false); + testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, false); } } @@ -126,31 +94,14 @@ private void testCharSetObject(boolean isTestEnclave) throws SQLException { * @throws SQLException */ @Test - public void testCharSetObjectWithJDBCTypes_aev1() throws SQLException { - testCharSetObjectWithJDBCTypes(false); - } - - @Tag(Constants.xSQLv15) - @Test - public void testCharSetObjectWithJDBCTypes_aev2() throws SQLException { - testCharSetObjectWithJDBCTypes(isAEv2Supported); - } - - private void testCharSetObjectWithJDBCTypes(boolean isTestEnclave) throws SQLException { - + public void testCharSetObjectWithJDBCTypes() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = createCharValues(nullable); - testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, isTestEnclave); - - if (null != cekWin) { - testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, isTestEnclave); - } - - if (null != cekAkv) { - testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, isTestEnclave); - } + testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } @@ -161,29 +112,13 @@ private void testCharSetObjectWithJDBCTypes(boolean isTestEnclave) throws SQLExc */ @Test public void testCharSpecificSetterNull() throws SQLException { - testCharSpecificSetterNull(false); - } - - @Tag(Constants.xSQLv15) - @Test - public void testCharSpecificSetterNull_aev2() throws SQLException { - testCharSpecificSetterNull(isAEv2Supported); - } - - private void testCharSpecificSetterNull(boolean isTestEnclave) throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = {null, null, null, null, null, null, null, null, null}; - testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, isTestEnclave); - - if (null != cekWin) { - testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, isTestEnclave); - } - - if (null != cekAkv) { - testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, isTestEnclave); - } + testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, false); + testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, false); + testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, false); } } @@ -193,30 +128,14 @@ private void testCharSpecificSetterNull(boolean isTestEnclave) throws SQLExcepti * @throws SQLException */ @Test - public void testCharSetObjectNull_aev1() throws SQLException { - testCharSetObjectNull(false); - } - - @Tag(Constants.xSQLv15) - @Test - public void testCharSetObjectNull_aev2() throws SQLException { - testCharSetObjectNull(isAEv2Supported); - } - - private void testCharSetObjectNull(boolean isTestEnclave) throws SQLException { + public void testCharSetObjectNull() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = {null, null, null, null, null, null, null, null, null}; - testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, isTestEnclave); - - if (null != cekWin) { - testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, isTestEnclave); - } - - if (null != cekAkv) { - testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, isTestEnclave); - } + testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, false); + testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, false); + testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, false); } } @@ -226,30 +145,14 @@ private void testCharSetObjectNull(boolean isTestEnclave) throws SQLException { * @throws SQLException */ @Test - public void testCharSetNull_aev1() throws SQLException { - testCharSetNull(false); - } - - @Tag(Constants.xSQLv15) - @Test - public void testCharSetNull_aev2() throws SQLException { - testCharSetNull(isAEv2Supported); - } - - private void testCharSetNull(boolean isTestEnclave) throws SQLException { + public void testCharSetNull() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values = {null, null, null, null, null, null, null, null, null}; - testChars(stmt, cekJks, charTable, values, TestCase.NULL, isTestEnclave); - - if (null != cekWin) { - testChars(stmt, cekWin, charTable, values, TestCase.NULL, isTestEnclave); - } - - if (null != cekAkv) { - testChars(stmt, cekAkv, charTable, values, TestCase.NULL, isTestEnclave); - } + testChars(stmt, cekJks, charTable, values, TestCase.NULL, false); + testChars(stmt, cekWin, charTable, values, TestCase.NULL, false); + testChars(stmt, cekAkv, charTable, values, TestCase.NULL, false); } } @@ -265,14 +168,8 @@ public void testBinarySpecificSetter() throws SQLException { LinkedList values = createbinaryValues(false); testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL); - - if (null != cekWin) { - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); - } - - if (null != cekAkv) { - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); - } + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); } } @@ -288,14 +185,8 @@ public void testBinarySetobject() throws SQLException { LinkedList values = createbinaryValues(false); testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT); - - if (null != cekWin) { - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT); - } - - if (null != cekAkv) { - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT); - } + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT); } } @@ -311,14 +202,8 @@ public void testBinarySetNull() throws SQLException { LinkedList values = createbinaryValues(true); testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL); - - if (null != cekWin) { - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NULL); - } - - if (null != cekAkv) { - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL); - } + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NULL); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL); } } @@ -334,14 +219,8 @@ public void testBinarySpecificSetterNull() throws SQLException { LinkedList values = createbinaryValues(true); testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL); - - if (null != cekWin) { - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); - } - - if (null != cekAkv) { - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); - } + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); } } @@ -357,14 +236,8 @@ public void testBinarysetObjectNull() throws SQLException { LinkedList values = createbinaryValues(true); testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL); - - if (null != cekWin) { - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_NULL); - } - - if (null != cekAkv) { - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL); - } + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_NULL); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL); } } @@ -381,14 +254,8 @@ public void testBinarySetObjectWithJDBCTypes() throws SQLException { LinkedList values = createbinaryValues(false); testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - - if (null != cekWin) { - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - } - - if (null != cekAkv) { - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - } + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); } } @@ -404,14 +271,8 @@ public void testDateSpecificSetter() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL); - - if (null != cekWin) { - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); - } - - if (null != cekAkv) { - testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); - } + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); } } @@ -427,14 +288,8 @@ public void testDateSetObject() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT); - - if (null != cekWin) { - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT); - } - - if (null != cekAkv) { - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT); - } + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT); } } @@ -450,14 +305,8 @@ public void testDateSetObjectWithJavaType() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); - - if (null != cekWin) { - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); - } - - if (null != cekAkv) { - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); - } + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); } } @@ -473,14 +322,8 @@ public void testDateSetObjectWithJDBCType() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - - if (null != cekWin) { - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - } - - if (null != cekAkv) { - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - } + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); } } @@ -497,14 +340,8 @@ public void testDateSpecificSetterMinMaxValue() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL); - - if (null != cekWin) { - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); - } - - if (null != cekAkv) { - testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); - } + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); } } @@ -522,14 +359,8 @@ public void testDateSetNull() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.NULL); - - if (null != cekWin) { - testDates(stmt, cekWin, dateTable, values, TestCase.NULL); - } - - if (null != cekAkv) { - testDates(stmt, cekAkv, dateTable, values, TestCase.NULL); - } + testDates(stmt, cekWin, dateTable, values, TestCase.NULL); + testDates(stmt, cekAkv, dateTable, values, TestCase.NULL); } nullable = false; @@ -551,14 +382,8 @@ public void testDateSetObjectNull() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL); - - if (null != cekWin) { - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_NULL); - } - - if (null != cekAkv) { - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL); - } + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_NULL); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL); } nullable = false; @@ -580,14 +405,8 @@ public void testNumericSpecificSetter() throws TestAbortedException, Exception { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - - if (null != cekWin) { - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - } - - if (null != cekAkv) { - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); - } + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); } } @@ -605,14 +424,8 @@ public void testNumericSetObject() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT); - - if (null != cekWin) { - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT); - } - - if (null != cekAkv) { - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT); - } + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT); } } @@ -631,14 +444,8 @@ public void testNumericSetObjectWithJDBCTypes() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); - - if (null != cekWin) { - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); - } - - if (null != cekAkv) { - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); - } + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); } } @@ -662,14 +469,9 @@ public void testNumericSpecificSetterMaxValue() throws SQLException { "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - if (null != cekWin) { - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - } - - if (null != cekAkv) { - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); - } + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); } } @@ -692,14 +494,9 @@ public void testNumericSpecificSetterMinValue() throws SQLException { "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - if (null != cekWin) { - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - } - - if (null != cekAkv) { - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); - } + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); } } @@ -719,14 +516,8 @@ public void testNumericSpecificSetterNull() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL); - - if (null != cekWin) { - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); - } - - if (null != cekAkv) { - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); - } + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); } nullable = false; @@ -749,14 +540,8 @@ public void testNumericSpecificSetterSetObjectNull() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL); - - if (null != cekWin) { - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); - } - - if (null != cekAkv) { - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); - } + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); } nullable = false; @@ -780,14 +565,8 @@ public void testNumericNormalization() throws SQLException { "999999999999999999999999.9999", "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - - if (null != cekWin) { - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - } - - if (null != cekAkv) { - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); - } + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); } } @@ -807,7 +586,7 @@ public void testAEFMTOnly() throws SQLException { } } - private void testChar(SQLServerStatement stmt, String[] values) throws SQLException { + void testChar(SQLServerStatement stmt, String[] values) throws SQLException { String sql = "select * from " + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, @@ -823,7 +602,7 @@ private void testChar(SQLServerStatement stmt, String[] values) throws SQLExcept } - private void testBinary(SQLServerStatement stmt, LinkedList values) throws SQLException { + void testBinary(SQLServerStatement stmt, LinkedList values) throws SQLException { String sql = "select * from " + AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE.toString()); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); @@ -840,7 +619,7 @@ private void testBinary(SQLServerStatement stmt, LinkedList values) thro } } - private void testDate(SQLServerStatement stmt, LinkedList values1) throws SQLException { + void testDate(SQLServerStatement stmt, LinkedList values1) throws SQLException { String sql = "select * from " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); @@ -859,7 +638,7 @@ private void testDate(SQLServerStatement stmt, LinkedList values1) throw } } - private void testGetObject(ResultSet rs, int numberOfColumns, String[] values) throws SQLException { + void testGetObject(ResultSet rs, int numberOfColumns, String[] values) throws SQLException { int index = 0; for (int i = 1; i <= numberOfColumns; i = i + 3) { try { @@ -887,8 +666,7 @@ private void testGetObject(ResultSet rs, int numberOfColumns, String[] values) t } } - private void testGetObjectForTemporal(ResultSet rs, int numberOfColumns, - LinkedList values) throws SQLException { + void testGetObjectForTemporal(ResultSet rs, int numberOfColumns, LinkedList values) throws SQLException { int index = 0; for (int i = 1; i <= numberOfColumns; i = i + 3) { try { @@ -916,8 +694,7 @@ private void testGetObjectForTemporal(ResultSet rs, int numberOfColumns, } } - private void testGetObjectForBinary(ResultSet rs, int numberOfColumns, - LinkedList values) throws SQLException { + void testGetObjectForBinary(ResultSet rs, int numberOfColumns, LinkedList values) throws SQLException { int index = 0; for (int i = 1; i <= numberOfColumns; i = i + 3) { byte[] objectValue1 = (byte[]) rs.getObject(i); @@ -946,7 +723,7 @@ private void testGetObjectForBinary(ResultSet rs, int numberOfColumns, } } - private void testGetBigDecimal(ResultSet rs, int numberOfColumns, String[] values) throws SQLException { + void testGetBigDecimal(ResultSet rs, int numberOfColumns, String[] values) throws SQLException { int index = 0; for (int i = 1; i <= numberOfColumns; i = i + 3) { @@ -995,7 +772,7 @@ private void testGetBigDecimal(ResultSet rs, int numberOfColumns, String[] value } } - private void testGetString(ResultSet rs, int numberOfColumns, String[] values) throws SQLException { + void testGetString(ResultSet rs, int numberOfColumns, String[] values) throws SQLException { int index = 0; for (int i = 1; i <= numberOfColumns; i = i + 3) { @@ -1037,8 +814,7 @@ private void testGetString(ResultSet rs, int numberOfColumns, String[] values) t // not testing this for now. @SuppressWarnings("unused") - private void testGetStringForDate(ResultSet rs, int numberOfColumns, - LinkedList values) throws SQLException { + void testGetStringForDate(ResultSet rs, int numberOfColumns, LinkedList values) throws SQLException { int index = 0; for (int i = 1; i <= numberOfColumns; i = i + 3) { @@ -1090,7 +866,7 @@ private void testGetStringForDate(ResultSet rs, int numberOfColumns, } } - private void testGetBytes(ResultSet rs, int numberOfColumns, LinkedList values) throws SQLException { + void testGetBytes(ResultSet rs, int numberOfColumns, LinkedList values) throws SQLException { int index = 0; for (int i = 1; i <= numberOfColumns; i = i + 3) { byte[] b1 = rs.getBytes(i); @@ -1117,8 +893,7 @@ private void testGetBytes(ResultSet rs, int numberOfColumns, LinkedList } } - private void testGetStringForBinary(ResultSet rs, int numberOfColumns, - LinkedList values) throws SQLException { + void testGetStringForBinary(ResultSet rs, int numberOfColumns, LinkedList values) throws SQLException { int index = 0; for (int i = 1; i <= numberOfColumns; i = i + 3) { @@ -1151,7 +926,7 @@ private void testGetStringForBinary(ResultSet rs, int numberOfColumns, } } - private void testGetDate(ResultSet rs, int numberOfColumns, LinkedList values) throws SQLException { + void testGetDate(ResultSet rs, int numberOfColumns, LinkedList values) throws SQLException { for (int i = 1; i <= numberOfColumns; i = i + 3) { if (rs instanceof SQLServerResultSet) { @@ -1223,7 +998,7 @@ private void testGetDate(ResultSet rs, int numberOfColumns, LinkedList v } } - private void testNumeric(Statement stmt, String[] numericValues, boolean isNull) throws SQLException { + void testNumeric(Statement stmt, String[] numericValues, boolean isNull) throws SQLException { String sql = "select * from " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); @@ -1248,8 +1023,7 @@ private void testNumeric(Statement stmt, String[] numericValues, boolean isNull) } } - private void testWithSpecifiedtype(SQLServerResultSet rs, int numberOfColumns, - String[] values) throws SQLException { + void testWithSpecifiedtype(SQLServerResultSet rs, int numberOfColumns, String[] values) throws SQLException { String value1, value2, value3, expectedValue = null; int index = 0; @@ -1484,7 +1258,7 @@ private void testRichQuery(SQLServerStatement stmt, String tableName, String tab } - private void Compare(String expectedValue, String value1, String value2, String value3) { + void Compare(String expectedValue, String value1, String value2, String value3) { if (null != expectedValue) { if (expectedValue.equalsIgnoreCase("1.79E+308")) { @@ -1507,8 +1281,8 @@ private void Compare(String expectedValue, String value1, String value2, String + value3 + ".\n" + TestResource.getResource("R_expectedValue")); } - private void testChars(SQLServerStatement stmt, String cekName, String[][] table, String[] values, - TestCase testcase, boolean isTestEnclave) throws SQLException { + void testChars(SQLServerStatement stmt, String cekName, String[][] table, String[] values, TestCase testcase, + boolean isTestEnclave) throws SQLException { TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE), stmt); createTable(CHAR_TABLE_AE, cekName, table); @@ -1539,7 +1313,7 @@ private void testChars(SQLServerStatement stmt, String cekName, String[][] table } } - private void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, LinkedList values, + void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, LinkedList values, TestCase testcase) throws SQLException { TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE), stmt); createTable(BINARY_TABLE_AE, cekName, table); @@ -1566,7 +1340,7 @@ private void testBinaries(SQLServerStatement stmt, String cekName, String[][] ta testBinary(null, values); } - private void testDates(SQLServerStatement stmt, String cekName, String[][] table, LinkedList values, + void testDates(SQLServerStatement stmt, String cekName, String[][] table, LinkedList values, TestCase testcase) throws SQLException { TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE), stmt); createTable(DATE_TABLE_AE, cekName, table); @@ -1593,8 +1367,8 @@ private void testDates(SQLServerStatement stmt, String cekName, String[][] table testDate(null, values); } - private void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, String[] values1, - String[] values2, TestCase testcase) throws SQLException { + void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, String[] values1, String[] values2, + TestCase testcase) throws SQLException { TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE), stmt); createTable(NUMERIC_TABLE_AE, cekName, table); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java index ed421060f..fbd1fb06f 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java @@ -18,7 +18,7 @@ public final class TestResource extends ListResourceBundle { public static String getResource(String key) { return TestResource.getBundle(Constants.MSSQL_JDBC_PACKAGE + ".TestResource").getString(key); } - + public static String formatErrorMsg(String resource) { return (".*\\Q" + getResource(resource) + "\\E").replaceAll("\\{+[0-9]+\\}", "\\\\E.*\\\\Q"); } @@ -180,7 +180,6 @@ protected Object[][] getContents() { {"R_ConnectionStringNull", "Connection String should not be null"}, {"R_OperandTypeClash", "Operand type clash"}, {"R_NoPrivilege", "The EXECUTE permission was denied on the object {0}"}, - {"R_resultSetEmpty", "Result set is empty."}, - {"R_AlterAEv2Error", "Alter Column Encryption failed."}, - {"R_RichQueryError", "Rich query failed."}}; + {"R_resultSetEmpty", "Result set is empty."}, {"R_AlterAEv2Error", "Alter Column Encryption failed."}, + {"R_RichQueryError", "Rich query failed."}, {"R_reqExternalSetup", "External setup for test required."},}; } From 20aa27de0f66ebffebc8dc13553dc846f991d54e Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 21 Oct 2019 16:44:22 -0700 Subject: [PATCH 18/49] refactored tests to use reqExternalSetup and added tests for more datatypes --- .../jdbc/AlwaysEncrypted/AESetup.java | 29 +- .../CallableStatementTest.java | 2 +- .../jdbc/AlwaysEncrypted/EnclaveTest.java | 139 ++++--- .../JDBCEncryptionDecryptionTest.java | 372 ++++++++++++++---- 4 files changed, 373 insertions(+), 169 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index af735c047..6e48ca950 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -92,8 +92,9 @@ enum ColumnType { /* * tables used in the tests {columnName, columnType} */ - static String binaryTable[][] = {{"Binary", "binary(20)"}, {"Varbinary", "varbinary(50)"}, - {"VarbinaryMax", "varbinary(max)"}, {"Binary512", "binary(512)"}, {"Binary8000", "varbinary(8000)"},}; + static String binaryTable[][] = {{"Binary", "binary(20)", "BINARY"}, {"Varbinary", "varbinary(50)", "BINARY"}, + {"VarbinaryMax", "varbinary(max)", "BINARY"}, {"Binary512", "binary(512)", "BINARY"}, + {"Binary8000", "varbinary(8000)", "BINARY"}}; static String charTable[][] = {{"Char", "char(20) COLLATE Latin1_General_BIN2", "CHAR"}, {"Varchar", "varchar(50) COLLATE Latin1_General_BIN2", "CHAR"}, @@ -105,18 +106,20 @@ enum ColumnType { {"Varchar8000", "varchar(8000) COLLATE Latin1_General_BIN2", "CHAR"}, {"Nvarchar4000", "nvarchar(4000) COLLATE Latin1_General_BIN2", "NCHAR"},}; - static String dateTable[][] = {{"Date", "date"}, {"Datetime2Default", "datetime2"}, - {"DatetimeoffsetDefault", "datetimeoffset"}, {"TimeDefault", "time"}, {"Datetime", "datetime"}, - {"Smalldatetime", "smalldatetime"},}; + static String dateTable[][] = {{"Date", "date", "DATE"}, {"Datetime2Default", "datetime2", "TIMESTAMP"}, + {"DatetimeoffsetDefault", "datetimeoffset", "DATETIMEOFFSET"}, {"TimeDefault", "time", "TIME"}, + {"Datetime", "datetime", "DATETIME"}, {"Smalldatetime", "smalldatetime", "SMALLDATETIME"}}; - static String dateScaleTable[][] = {{"Datetime2", "datetime2(2)"}, {"Time", "time(2)"}, - {"Datetimeoffset", "datetimeoffset(2)"},}; + static String dateScaleTable[][] = {{"Datetime2", "datetime2(2)", "DATE"}, {"Time", "time(2)", "DATE"}, + {"Datetimeoffset", "datetimeoffset(2)", "DATE"}}; - static String numericTable[][] = {{"Bit", "bit"}, {"Tinyint", "tinyint"}, {"Smallint", "smallint"}, {"Int", "int"}, - {"Bigint", "bigint"}, {"FloatDefault", "float"}, {"Float", "float(30)"}, {"Real", "real"}, - {"DecimalDefault", "decimal"}, {"Decimal", "decimal(10,5)"}, {"NumericDefault", "numeric"}, - {"Numeric", "numeric(8,2)"}, {"SmallMoney", "smallmoney"}, {"Money", "money"}, - {"Decimal2", "decimal(28,4)"}, {"Numeric2", "numeric(28,4)"},}; + static String numericTable[][] = {{"Bit", "bit", "BIT"}, {"Tinyint", "tinyint", "TINYINT"}, + {"Smallint", "smallint", "SMALLINT"}, {"Int", "int", "INTEGER"}, {"Bigint", "bigint", "BIGINT"}, + {"FloatDefault", "float", "DOUBLE"}, {"Float", "float(30)", "DOUBLE"}, {"Real", "real", "FLOAT"}, + {"DecimalDefault", "decimal", "DECIMAL"}, {"Decimal", "decimal(10,5)", "DECIMAL"}, + {"NumericDefault", "numeric", "DECIMAL"}, {"Numeric", "numeric(8,2)", "DECIMAL"}, + {"SmallMoney", "smallmoney", "SMALLMONEY"}, {"Money", "money", "MONEY"}, + {"Decimal2", "decimal(28,4)", "DECIMAL"}, {"Numeric2", "numeric(28,4)", "DECIMAL"},}; // CREATE TABLE tableName (columns) NULL" static String createSql = "CREATE TABLE %s (%s)"; @@ -356,7 +359,7 @@ protected static void createScaleTable(String tableName, String table[][], Strin * * @param nullable */ - protected static LinkedList createbinaryValues(boolean nullable) { + protected static LinkedList createBinaryValues(boolean nullable) { boolean encrypted = true; RandomData.returnNull = nullable; diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java index 75ab29256..3f05121ae 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/CallableStatementTest.java @@ -106,7 +106,7 @@ public static void initCallableStatementTest() throws Exception { dropTables(); numericValues = createNumericValues(nullable); - byteValues = createbinaryValues(nullable); + byteValues = createBinaryValues(nullable); dateValues = createTemporalTypesCallableStatement(nullable); charValues = createCharValues(nullable); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java index 6748aa5bc..e4569c89e 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java @@ -165,11 +165,11 @@ public void testCharSetNull() throws SQLException { public void testBinarySpecificSetter() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(false); + LinkedList values = createBinaryValues(false); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, true); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, true); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, true); } } @@ -182,11 +182,11 @@ public void testBinarySpecificSetter() throws SQLException { public void testBinarySetobject() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(false); + LinkedList values = createBinaryValues(false); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT, true); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT, true); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT, true); } } @@ -199,12 +199,11 @@ public void testBinarySetobject() throws SQLException { public void testBinarySetNull() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(true); + LinkedList values = createBinaryValues(true); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NULL); - - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL, true); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NULL, true); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL, true); } } @@ -217,11 +216,11 @@ public void testBinarySetNull() throws SQLException { public void testBinarySpecificSetterNull() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(true); + LinkedList values = createBinaryValues(true); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, true); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, true); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, true); } } @@ -234,11 +233,11 @@ public void testBinarySpecificSetterNull() throws SQLException { public void testBinarysetObjectNull() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(true); + LinkedList values = createBinaryValues(true); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_NULL); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL, true); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_NULL, true); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL, true); } } @@ -252,11 +251,11 @@ public void testBinarySetObjectWithJDBCTypes() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(false); + LinkedList values = createBinaryValues(false); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); } } @@ -271,9 +270,9 @@ public void testDateSpecificSetter() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL); - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); - testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, true); + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, true); + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, true); } } @@ -288,9 +287,9 @@ public void testDateSetObject() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT); + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT, true); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT, true); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT, true); } } @@ -305,9 +304,9 @@ public void testDateSetObjectWithJavaType() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, true); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, true); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, true); } } @@ -322,9 +321,9 @@ public void testDateSetObjectWithJDBCType() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); } } @@ -340,9 +339,9 @@ public void testDateSpecificSetterMinMaxValue() throws SQLException { RandomData.returnMinMax = true; LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL); - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); - testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, true); + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, true); + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, true); } } @@ -359,9 +358,9 @@ public void testDateSetNull() throws SQLException { nullable = true; LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.NULL); - testDates(stmt, cekWin, dateTable, values, TestCase.NULL); - testDates(stmt, cekAkv, dateTable, values, TestCase.NULL); + testDates(stmt, cekJks, dateTable, values, TestCase.NULL, true); + testDates(stmt, cekWin, dateTable, values, TestCase.NULL, true); + testDates(stmt, cekAkv, dateTable, values, TestCase.NULL, true); } nullable = false; @@ -382,9 +381,9 @@ public void testDateSetObjectNull() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_NULL); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL); + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL, true); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_NULL, true); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL, true); } nullable = false; @@ -405,9 +404,9 @@ public void testNumericSpecificSetter() throws TestAbortedException, Exception { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, true); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, true); } } @@ -424,9 +423,9 @@ public void testNumericSetObject() throws SQLException { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT, true); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT, true); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT, true); } } @@ -444,9 +443,9 @@ public void testNumericSetObjectWithJDBCTypes() throws SQLException { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, true); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, true); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, true); } } @@ -469,9 +468,9 @@ public void testNumericSpecificSetterMaxValue() throws SQLException { "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", "999999999999999999999999.9999"}; - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, true); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, true); } } @@ -493,9 +492,9 @@ public void testNumericSpecificSetterMinValue() throws SQLException { "567812.78", "-214748.3648", "-922337203685477.5808", "999999999999999999999999.9999", "999999999999999999999999.9999"}; - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, true); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, true); } } @@ -514,9 +513,9 @@ public void testNumericSpecificSetterNull() throws SQLException { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, true); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL, true); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, true); } nullable = false; @@ -538,9 +537,9 @@ public void testNumericSpecificSetterSetObjectNull() throws SQLException { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, true); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL, true); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, true); } nullable = false; @@ -563,9 +562,9 @@ public void testNumericNormalization() throws SQLException { "123456789123456789", "12345.12345", "987654321123456789", "567812.78", "7812.7812", "7812.7812", "999999999999999999999999.9999", "999999999999999999999999.9999"}; - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, true); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, true); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index bb4385d20..79baebffd 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -7,11 +7,15 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import java.math.BigDecimal; +import java.sql.Date; import java.sql.ParameterMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; import java.util.LinkedList; import org.junit.jupiter.api.Tag; @@ -31,6 +35,8 @@ import com.microsoft.sqlserver.testframework.Constants; import com.microsoft.sqlserver.testframework.PrepUtil; +import microsoft.sql.DateTimeOffset; + /** * Tests Decryption and encryption of values @@ -165,11 +171,11 @@ public void testCharSetNull() throws SQLException { public void testBinarySpecificSetter() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(false); + LinkedList values = createBinaryValues(false); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, false); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, false); } } @@ -182,11 +188,11 @@ public void testBinarySpecificSetter() throws SQLException { public void testBinarySetobject() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(false); + LinkedList values = createBinaryValues(false); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT, false); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT, false); } } @@ -199,11 +205,11 @@ public void testBinarySetobject() throws SQLException { public void testBinarySetNull() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(true); + LinkedList values = createBinaryValues(true); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NULL); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL, false); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NULL, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL, false); } } @@ -216,11 +222,11 @@ public void testBinarySetNull() throws SQLException { public void testBinarySpecificSetterNull() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(true); + LinkedList values = createBinaryValues(true); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, false); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, false); } } @@ -233,11 +239,11 @@ public void testBinarySpecificSetterNull() throws SQLException { public void testBinarysetObjectNull() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(true); + LinkedList values = createBinaryValues(true); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_NULL); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL, false); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_NULL, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL, false); } } @@ -251,11 +257,11 @@ public void testBinarySetObjectWithJDBCTypes() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { - LinkedList values = createbinaryValues(false); + LinkedList values = createBinaryValues(false); - testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } @@ -270,9 +276,9 @@ public void testDateSpecificSetter() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL); - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); - testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, false); + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, false); + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, false); } } @@ -287,9 +293,9 @@ public void testDateSetObject() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT); + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT, false); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT, false); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT, false); } } @@ -304,9 +310,9 @@ public void testDateSetObjectWithJavaType() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES); + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); } } @@ -321,9 +327,9 @@ public void testDateSetObjectWithJDBCType() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES); + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } @@ -339,9 +345,9 @@ public void testDateSpecificSetterMinMaxValue() throws SQLException { RandomData.returnMinMax = true; LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL); - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL); - testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL); + testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, false); + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, false); + testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, false); } } @@ -358,9 +364,9 @@ public void testDateSetNull() throws SQLException { nullable = true; LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.NULL); - testDates(stmt, cekWin, dateTable, values, TestCase.NULL); - testDates(stmt, cekAkv, dateTable, values, TestCase.NULL); + testDates(stmt, cekJks, dateTable, values, TestCase.NULL, false); + testDates(stmt, cekWin, dateTable, values, TestCase.NULL, false); + testDates(stmt, cekAkv, dateTable, values, TestCase.NULL, false); } nullable = false; @@ -381,9 +387,9 @@ public void testDateSetObjectNull() throws SQLException { SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createTemporalTypes(nullable); - testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_NULL); - testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL); + testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL, false); + testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_NULL, false); + testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL, false); } nullable = false; @@ -404,9 +410,9 @@ public void testNumericSpecificSetter() throws TestAbortedException, Exception { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } @@ -423,9 +429,9 @@ public void testNumericSetObject() throws SQLException { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT, false); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT, false); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT, false); } } @@ -443,9 +449,9 @@ public void testNumericSetObjectWithJDBCTypes() throws SQLException { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } @@ -468,10 +474,10 @@ public void testNumericSpecificSetterMaxValue() throws SQLException { "567812.78", "214748.3647", "922337203685477.5807", "999999999999999999999999.9999", "999999999999999999999999.9999"}; - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } @@ -493,10 +499,10 @@ public void testNumericSpecificSetterMinValue() throws SQLException { "567812.78", "-214748.3648", "-922337203685477.5808", "999999999999999999999999.9999", "999999999999999999999999.9999"}; - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } @@ -515,9 +521,9 @@ public void testNumericSpecificSetterNull() throws SQLException { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, false); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL, false); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, false); } nullable = false; @@ -539,9 +545,9 @@ public void testNumericSpecificSetterSetObjectNull() throws SQLException { String[] values2 = new String[values1.length]; System.arraycopy(values1, 0, values2, 0, values1.length); - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, false); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL, false); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, false); } nullable = false; @@ -564,9 +570,9 @@ public void testNumericNormalization() throws SQLException { "123456789123456789", "12345.12345", "987654321123456789", "567812.78", "7812.7812", "7812.7812", "999999999999999999999999.9999", "999999999999999999999999.9999"}; - testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL); + testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); + testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } @@ -1182,8 +1188,8 @@ void testWithSpecifiedtype(SQLServerResultSet rs, int numberOfColumns, String[] * @param values * @throws SQLException */ - private void testAlterColumnEncryption(SQLServerStatement stmt, String tableName, String table[][], String cekName, - String[] values) throws SQLException { + private void testAlterColumnEncryption(SQLServerStatement stmt, String tableName, String table[][], + String cekName) throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { for (int i = 0; i < table.length; i++) { // alter deterministic to randomized @@ -1218,20 +1224,91 @@ private void testRichQuery(SQLServerStatement stmt, String tableName, String tab switch (table[i][2]) { case "CHAR": case "LONGVARCHAR": - pstmt.setString(1, values[i / 3]); + pstmt.setString(1, values[i + 1 / 3]); break; case "NCHAR": case "LONGNVARCHAR": - pstmt.setNString(1, values[i / 3]); + pstmt.setNString(1, values[i + 1 / 3]); break; case "GUID": pstmt.setUniqueIdentifier(1, null); pstmt.setUniqueIdentifier(1, Constants.UID); break; + case "BIT": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, java.sql.Types.BIT); + } else { + pstmt.setBoolean(1, + (values[i + 1 / 3].equalsIgnoreCase(Boolean.TRUE.toString())) ? true : false); + } + break; + case "TINYINT": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, java.sql.Types.TINYINT); + } else { + pstmt.setShort(1, Short.valueOf(values[i + 1 / 3])); + } + break; + case "SMALLINT": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, java.sql.Types.SMALLINT); + } else { + pstmt.setShort(1, Short.valueOf(values[i + 1 / 3])); + } + break; + case "INTEGER": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, java.sql.Types.INTEGER); + } else { + pstmt.setInt(1, Integer.valueOf(values[i + 1 / 3])); + } + break; + case "BIGINT": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, java.sql.Types.BIGINT); + } else { + pstmt.setLong(1, Long.valueOf(values[i + 1 / 3])); + } + break; + case "DOUBLE": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, java.sql.Types.DOUBLE); + } else { + pstmt.setDouble(1, Double.valueOf(values[i + 1 / 3])); + } + break; + case "FLOAT": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, java.sql.Types.DOUBLE); + } else { + pstmt.setFloat(1, Float.valueOf(values[i + 1 / 3])); + } + break; + case "DECIMAL": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, java.sql.Types.DECIMAL); + } else { + pstmt.setBigDecimal(1, new BigDecimal(values[i + 1 / 3])); + } + break; + case "SMALLMONEY": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, microsoft.sql.Types.SMALLMONEY); + } else { + pstmt.setSmallMoney(1, new BigDecimal(values[i + 1 / 3])); + } + break; + case "MONEY": + if (values[i + 1 / 3].equals("null")) { + pstmt.setObject(1, null, microsoft.sql.Types.MONEY); + } else { + pstmt.setMoney(1, new BigDecimal(values[i + 1 / 3])); + } + break; default: - System.out.println("die"); - + fail(TestResource.getResource("R_invalidObjectName") + ": " + table[i][2]); } + try (ResultSet rs = (pstmt.executeQuery())) { if (!TestUtils.isAEv2(con)) { fail(TestResource.getResource("R_expectedExceptionNotThrown")); @@ -1255,7 +1332,102 @@ private void testRichQuery(SQLServerStatement stmt, String tableName, String tab } } + } + + private void testRichQueryDate(SQLServerStatement stmt, String tableName, String table[][], + LinkedList values) throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { + for (int i = 0; i < table.length; i++) { + String sql = "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) + " WHERE " + + ColumnType.PLAIN.name() + table[i][0] + "= ?"; + try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, + stmtColEncSetting)) { + switch (table[i][2]) { + case "DATE": + pstmt.setDate(1, (Date) values.get(i + 1 / 3)); + break; + case "TIMESTAMP": + pstmt.setTimestamp(1, (Timestamp) values.get(i + 1 / 3)); + break; + case "DATETIMEOFFSET": + pstmt.setDateTimeOffset(1, (DateTimeOffset) values.get(i + 1 / 3)); + break; + case "TIME": + pstmt.setTime(1, (Time) values.get(i + 1 / 3)); + break; + case "DATETIME": + pstmt.setDateTime(1, (Timestamp) values.get(i + 1 / 3)); + break; + case "SMALLDATETIME": + pstmt.setSmallDateTime(1, (Timestamp) values.get(i + 1 / 3)); + break; + default: + fail(TestResource.getResource("R_invalidObjectName") + ": " + table[i][2]); + } + + try (ResultSet rs = (pstmt.executeQuery())) { + if (!TestUtils.isAEv2(con)) { + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } + + int numberOfColumns = rs.getMetaData().getColumnCount(); + while (rs.next()) { + testGetObjectForTemporal(rs, numberOfColumns, values); + testGetDate(rs, numberOfColumns, values); + } + } catch (SQLException e) { + if (!TestUtils.isAEv2(con)) { + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } else { + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + } + } + } catch (Exception e) { + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + } + } + } + } + + private void testRichQuery(SQLServerStatement stmt, String tableName, String table[][], + LinkedList values) throws SQLException { + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { + for (int i = 0; i < table.length; i++) { + String sql = "SELECT * FROM " + AbstractSQLGenerator.escapeIdentifier(tableName) + " WHERE " + + ColumnType.PLAIN.name() + table[i][0] + "= ?"; + try (SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, + stmtColEncSetting)) { + switch (table[i][2]) { + case "BINARY": + pstmt.setBytes(1, (byte[]) values.get(i + 1 / 3)); + break; + default: + fail(TestResource.getResource("R_invalidObjectName") + ": " + table[i][2]); + } + try (ResultSet rs = (pstmt.executeQuery())) { + if (!TestUtils.isAEv2(con)) { + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } + + int numberOfColumns = rs.getMetaData().getColumnCount(); + while (rs.next()) { + testGetStringForBinary(rs, numberOfColumns, values); + testGetBytes(rs, numberOfColumns, values); + testGetObjectForBinary(rs, numberOfColumns, values); + } + } catch (SQLException e) { + if (!TestUtils.isAEv2(con)) { + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } else { + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + } + } + } catch (Exception e) { + fail(TestResource.getResource("R_RichQueryError") + e.getMessage() + "Query: " + sql); + } + } + } } void Compare(String expectedValue, String value1, String value2, String value3) { @@ -1281,12 +1453,12 @@ void Compare(String expectedValue, String value1, String value2, String value3) + value3 + ".\n" + TestResource.getResource("R_expectedValue")); } - void testChars(SQLServerStatement stmt, String cekName, String[][] table, String[] values, TestCase testcase, + void testChars(SQLServerStatement stmt, String cekName, String[][] table, String[] values, TestCase testCase, boolean isTestEnclave) throws SQLException { TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE), stmt); createTable(CHAR_TABLE_AE, cekName, table); - switch (testcase) { + switch (testCase) { case NORMAL: populateCharNormalCase(values); break; @@ -1302,23 +1474,26 @@ void testChars(SQLServerStatement stmt, String cekName, String[][] table, String case NULL: populateCharNullCase(); break; + default: + fail(TestResource.getResource("R_switchFailed")); + break; } testChar(stmt, values); testChar(null, values); if (isTestEnclave && null != getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL)) { - testAlterColumnEncryption(stmt, CHAR_TABLE_AE, table, cekName, values); + testAlterColumnEncryption(stmt, CHAR_TABLE_AE, table, cekName); testRichQuery(stmt, CHAR_TABLE_AE, table, values); } } void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, LinkedList values, - TestCase testcase) throws SQLException { + TestCase testCase, boolean isTestEnclave) throws SQLException { TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(BINARY_TABLE_AE), stmt); createTable(BINARY_TABLE_AE, cekName, table); - switch (testcase) { + switch (testCase) { case NORMAL: populateBinaryNormalCase(values); break; @@ -1330,22 +1505,29 @@ void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, Lin case SETOBJECT_NULL: populateBinarySetObject(null); break; - case NULL: populateBinaryNullCase(); break; + default: + fail(TestResource.getResource("R_switchFailed")); + break; } testBinary(stmt, values); testBinary(null, values); + + if (isTestEnclave && null != getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL)) { + testAlterColumnEncryption(stmt, BINARY_TABLE_AE, table, cekName); + testRichQuery(stmt, BINARY_TABLE_AE, table, values); + } } void testDates(SQLServerStatement stmt, String cekName, String[][] table, LinkedList values, - TestCase testcase) throws SQLException { + TestCase testCase, boolean isTestEnclave) throws SQLException { TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE), stmt); createTable(DATE_TABLE_AE, cekName, table); - switch (testcase) { + switch (testCase) { case NORMAL: populateDateNormalCase(values); break; @@ -1358,22 +1540,33 @@ void testDates(SQLServerStatement stmt, String cekName, String[][] table, Linked case SETOBJECT_WITH_JAVATYPES: populateDateSetObject(values, "setwithJavaType"); break; + case SETOBJECT_NULL: + populateDateNullCase(); + break; case NULL: populateDateNullCase(); break; + default: + fail(TestResource.getResource("R_switchFailed")); + break; } testDate(stmt, values); testDate(null, values); + + if (isTestEnclave && null != getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL)) { + testAlterColumnEncryption(stmt, DATE_TABLE_AE, table, cekName); + testRichQueryDate(stmt, DATE_TABLE_AE, table, values); + } } void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, String[] values1, String[] values2, - TestCase testcase) throws SQLException { + TestCase testCase, boolean isTestEnclave) throws SQLException { TestUtils.dropTableIfExists(AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE), stmt); createTable(NUMERIC_TABLE_AE, cekName, table); boolean isNull = false; - switch (testcase) { + switch (testCase) { case NORMAL: populateNumeric(values1); break; @@ -1387,9 +1580,18 @@ void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, Str populateNumericNullCase(values1); isNull = true; break; + default: + fail(TestResource.getResource("R_switchFailed")); + break; } testNumeric(stmt, values1, isNull); testNumeric(null, values2, isNull); + + if (isTestEnclave && null != getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL)) { + testAlterColumnEncryption(stmt, NUMERIC_TABLE_AE, table, cekName); + testRichQuery(stmt, NUMERIC_TABLE_AE, table, values1); + testRichQuery(stmt, NUMERIC_TABLE_AE, table, values2); + } } } From 541da60c27d39f8afe283dfa18f069f10f9f62ea Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 22 Oct 2019 16:40:53 -0700 Subject: [PATCH 19/49] added properties to run AE tests --- azure-pipelines.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 3c025fa33..ab480777a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -34,11 +34,23 @@ jobs: displayName: 'Download PKCS12 truststore file' inputs: secureFile: 'pkcs12_truststore' + - task: DownloadSecureFile@1 + name: sqljdbc_auth + displayName: 'Download sqljdbc_auth.dll' + inputs: + secureFile: 'sqljdbc_auth' +steps: +- task: CopyFiles@2 + displayName: 'Copy sqljdbc_auth file to classpath' + inputs: + SourceFolder: '$(Agent.TempDirectory)' + TargetFolder: .\target\test-classes - task: Maven@3 displayName: 'Maven build jre13' inputs: mavenPomFile: 'pom.xml' - goals: 'clean -Dmssql_jdbc_test_connection_properties=jdbc:sqlserver://$(Target_SQL)$(server_domain);$(database);$(user);$(password); install -Pjre13 -DuserNTLM=$(userNTLM) -DpasswordNTLM=$(passwordNTLM) -DdomainNTLM=$(domainNTLM) -DexcludedGroups=$(Ex_Groups) -Dpkcs12_truststore_password=$(pkcs12_truststore_password) -Dpkcs12_truststore=$(pkcs12_truststore.secureFilePath)' + goals: 'clean -Dmssql_jdbc_test_connection_properties=jdbc:sqlserver://$(Target_SQL)$(server_domain);$(database);$(user);$(password); install -Pjre13 -DuserNTLM=$(userNTLM) -DpasswordNTLM=$(passwordNTLM) -DdomainNTLM=$(domainNTLM) -DexcludedGroups=$(Ex_Groups) -Dpkcs12_truststore_password=$(pkcs12_truststore_password) -Dpkcs12_truststore=$(pkcs12_truststore.secureFilePath) +-DapplicationClientID=$(applicationClientID) -DapplicationKey=$(applicationKey) -DkeyID=$(keyID) -DwindowsKeyPath=$(windowsKeyPath) -DenclaveAttestationUrl=$(enclaveAttestationUrl) -DenclaveAttestationProtocol=$(enclaveAttestationUrl)' testResultsFiles: '**/TEST-*.xml' testRunTitle: 'Maven build jre13' javaHomeOption: Path @@ -47,7 +59,9 @@ jobs: displayName: 'Maven build jre11' inputs: mavenPomFile: 'pom.xml' - goals: 'clean -Dmssql_jdbc_test_connection_properties=jdbc:sqlserver://$(Target_SQL)$(server_domain);$(database);$(user);$(password); install -Pjre11 -DuserNTLM=$(userNTLM) -DpasswordNTLM=$(passwordNTLM) -DdomainNTLM=$(domainNTLM) -DexcludedGroups=$(Ex_Groups) -Dpkcs12_truststore_password=$(pkcs12_truststore_password) -Dpkcs12_truststore=$(pkcs12_truststore.secureFilePath)' + goals: 'clean -Dmssql_jdbc_test_connection_properties=jdbc:sqlserver://$(Target_SQL)$(server_domain);$(database);$(user);$(password); install -Pjre11 -DuserNTLM=$(userNTLM) -DpasswordNTLM=$(passwordNTLM) -DdomainNTLM=$(domainNTLM) -DexcludedGroups=$(Ex_Groups) -Dpkcs12_truststore_password=$(pkcs12_truststore_password) -Dpkcs12_truststore=$(pkcs12_truststore.secureFilePath) +-DapplicationClientID=$(applicationClientID) -DapplicationKey=$(applicationKey) -DkeyID=$(keyID) -DwindowsKeyPath=$(windowsKeyPath) -DenclaveAttestationUrl=$(enclaveAttestationUrl) -DenclaveAttestationProtocol=$(enclaveAttestationUrl) +' testResultsFiles: '**/TEST-*.xml' testRunTitle: 'Maven build jre11' javaHomeOption: Path @@ -56,7 +70,8 @@ jobs: displayName: 'Maven build jre8' inputs: mavenPomFile: 'pom.xml' - goals: 'clean -Dmssql_jdbc_test_connection_properties=jdbc:sqlserver://$(Target_SQL)$(server_domain);$(database);$(user);$(password); install -Pjre8 -DuserNTLM=$(userNTLM) -DpasswordNTLM=$(passwordNTLM) -DdomainNTLM=$(domainNTLM) -DexcludedGroups=$(Ex_Groups) -Dpkcs12_truststore_password=$(pkcs12_truststore_password) -Dpkcs12_truststore=$(pkcs12_truststore.secureFilePath)' + goals: 'clean -Dmssql_jdbc_test_connection_properties=jdbc:sqlserver://$(Target_SQL)$(server_domain);$(database);$(user);$(password); install -Pjre8 -DuserNTLM=$(userNTLM) -DpasswordNTLM=$(passwordNTLM) -DdomainNTLM=$(domainNTLM) -DexcludedGroups=$(Ex_Groups) -Dpkcs12_truststore_password=$(pkcs12_truststore_password) -Dpkcs12_truststore=$(pkcs12_truststore.secureFilePath) +-DapplicationClientID=$(applicationClientID) -DapplicationKey=$(applicationKey) -DkeyID=$(keyID) -DwindowsKeyPath=$(windowsKeyPath) -DenclaveAttestationUrl=$(enclaveAttestationUrl) -DenclaveAttestationProtocol=$(enclaveAttestationUrl)' testResultsFiles: '**/TEST-*.xml' testRunTitle: 'Maven build jre8' javaHomeOption: Path From 74e23af1d48a0097f75667fb89f2b7ff362b0afd Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 22 Oct 2019 17:01:54 -0700 Subject: [PATCH 20/49] fixed typo --- azure-pipelines.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ab480777a..52abaa074 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -39,7 +39,6 @@ jobs: displayName: 'Download sqljdbc_auth.dll' inputs: secureFile: 'sqljdbc_auth' -steps: - task: CopyFiles@2 displayName: 'Copy sqljdbc_auth file to classpath' inputs: From 4e243b359f97ebf47d693701e5723c2ede2f6a4f Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 22 Oct 2019 17:07:29 -0700 Subject: [PATCH 21/49] fixed typo --- azure-pipelines.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 52abaa074..7b29246cb 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -39,11 +39,11 @@ jobs: displayName: 'Download sqljdbc_auth.dll' inputs: secureFile: 'sqljdbc_auth' -- task: CopyFiles@2 - displayName: 'Copy sqljdbc_auth file to classpath' - inputs: - SourceFolder: '$(Agent.TempDirectory)' - TargetFolder: .\target\test-classes + - task: CopyFiles@2 + displayName: 'Copy sqljdbc_auth file to classpath' + inputs: + SourceFolder: '$(Agent.TempDirectory)' + TargetFolder: .\target\test-classes - task: Maven@3 displayName: 'Maven build jre13' inputs: From aa9f25ebb8ee9ccfb8ad116d5631c89c506a93f3 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 22 Oct 2019 17:12:01 -0700 Subject: [PATCH 22/49] add dll --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7b29246cb..493ad7e93 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -38,7 +38,7 @@ jobs: name: sqljdbc_auth displayName: 'Download sqljdbc_auth.dll' inputs: - secureFile: 'sqljdbc_auth' + secureFile: 'sqljdbc_auth.dll' - task: CopyFiles@2 displayName: 'Copy sqljdbc_auth file to classpath' inputs: From 79363c7ce0c8b0ea82b4564626f19c4e1b6e27a3 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 23 Oct 2019 11:32:24 -0700 Subject: [PATCH 23/49] copy dll to default classpath --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 493ad7e93..6a95686f2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -43,7 +43,7 @@ jobs: displayName: 'Copy sqljdbc_auth file to classpath' inputs: SourceFolder: '$(Agent.TempDirectory)' - TargetFolder: .\target\test-classes + TargetFolder: c:\windows\system32 - task: Maven@3 displayName: 'Maven build jre13' inputs: From 41fa8bdd05dac993420d608342a2197af77b74a6 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 23 Oct 2019 13:49:54 -0700 Subject: [PATCH 24/49] fixed --- azure-pipelines.yml | 3 ++- .../com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6a95686f2..e8520ade7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -43,13 +43,14 @@ jobs: displayName: 'Copy sqljdbc_auth file to classpath' inputs: SourceFolder: '$(Agent.TempDirectory)' + Contents: sqljdbc_auth.dll TargetFolder: c:\windows\system32 - task: Maven@3 displayName: 'Maven build jre13' inputs: mavenPomFile: 'pom.xml' goals: 'clean -Dmssql_jdbc_test_connection_properties=jdbc:sqlserver://$(Target_SQL)$(server_domain);$(database);$(user);$(password); install -Pjre13 -DuserNTLM=$(userNTLM) -DpasswordNTLM=$(passwordNTLM) -DdomainNTLM=$(domainNTLM) -DexcludedGroups=$(Ex_Groups) -Dpkcs12_truststore_password=$(pkcs12_truststore_password) -Dpkcs12_truststore=$(pkcs12_truststore.secureFilePath) --DapplicationClientID=$(applicationClientID) -DapplicationKey=$(applicationKey) -DkeyID=$(keyID) -DwindowsKeyPath=$(windowsKeyPath) -DenclaveAttestationUrl=$(enclaveAttestationUrl) -DenclaveAttestationProtocol=$(enclaveAttestationUrl)' +-DapplicationClientID=$(applicationClientID) -DapplicationKey=$(applicationKey) -DkeyID=$(keyID) -DwindowsKeyPath=$(windowsKeyPath) -DenclaveAttestationUrl=$(enclaveAttestationUrl) -DenclaveAttestationProtocol=$(enclaveAttestationProtocol)' testResultsFiles: '**/TEST-*.xml' testRunTitle: 'Maven build jre13' javaHomeOption: Path diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 6e48ca950..182562171 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -166,6 +166,9 @@ public static void setUpConnection() throws TestAbortedException, Exception { fail(TestResource.getResource("R_reqExternalSetup")); } + // add to debug + System.out.println("java.library.path="+System.getProperty("java.library.path")); + readFromFile(Constants.JAVA_KEY_STORE_FILENAME, "Alias name"); keyIDs = keyID.split(";"); From 6019e95aee7eabe61f5ff19afb5a094132a7b476 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 23 Oct 2019 14:00:06 -0700 Subject: [PATCH 25/49] fix --- azure-pipelines.yml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e8520ade7..d36c2b744 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -16,6 +16,11 @@ jobs: Ex_Groups: 'xSQLv12' maxParallel: 2 steps: + - task: DownloadSecureFile@1 + name: sqljdbc_auth + displayName: 'Download sqljdbc_auth.dll' + inputs: + secureFile: 'sqljdbc_auth.dll' - powershell: | mkdir AE_Certificates cd AE_Certificates @@ -28,23 +33,13 @@ jobs: keytool -list -v -keystore clientcert.jks -storepass $(certPass) > JavaKeyStoreBase.txt Get-Content .\JavaKeyStoreBase.txt | Set-Content -Encoding utf8 JavaKeyStore.txt Remove-Item –path .\JavaKeyStoreBase.txt + Copy-Item -Path $(sqljdbc_auth.secureFilePath) -Destination "C:\Windows\System32" displayName: 'PowerShell Script' - task: DownloadSecureFile@1 name: pkcs12_truststore displayName: 'Download PKCS12 truststore file' inputs: secureFile: 'pkcs12_truststore' - - task: DownloadSecureFile@1 - name: sqljdbc_auth - displayName: 'Download sqljdbc_auth.dll' - inputs: - secureFile: 'sqljdbc_auth.dll' - - task: CopyFiles@2 - displayName: 'Copy sqljdbc_auth file to classpath' - inputs: - SourceFolder: '$(Agent.TempDirectory)' - Contents: sqljdbc_auth.dll - TargetFolder: c:\windows\system32 - task: Maven@3 displayName: 'Maven build jre13' inputs: From 8020b61a72059df1b8ae26b23128cba2e07a0a4f Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 23 Oct 2019 14:09:47 -0700 Subject: [PATCH 26/49] added debug --- azure-pipelines.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d36c2b744..222ddd38a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -33,7 +33,9 @@ jobs: keytool -list -v -keystore clientcert.jks -storepass $(certPass) > JavaKeyStoreBase.txt Get-Content .\JavaKeyStoreBase.txt | Set-Content -Encoding utf8 JavaKeyStore.txt Remove-Item –path .\JavaKeyStoreBase.txt + dir $(sqljdbc_auth.secureFilePath) Copy-Item -Path $(sqljdbc_auth.secureFilePath) -Destination "C:\Windows\System32" + dir C:\Windows\System32\sqljdbc_auth.dll displayName: 'PowerShell Script' - task: DownloadSecureFile@1 name: pkcs12_truststore From 91552dfafa32d5bb14f9f3324dc552e864397cc4 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 23 Oct 2019 15:09:01 -0700 Subject: [PATCH 27/49] changed to HGS server --- azure-pipelines.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 222ddd38a..db4b9ccf5 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: SQL-2019: - Target_SQL: 'SQL-2k19-01' + Target_SQL: 'HGS-2k19-01' Ex_Groups: 'xSQLv15' SQL-2012: Target_SQL: 'SQL-2K12-SP3-1' @@ -33,9 +33,7 @@ jobs: keytool -list -v -keystore clientcert.jks -storepass $(certPass) > JavaKeyStoreBase.txt Get-Content .\JavaKeyStoreBase.txt | Set-Content -Encoding utf8 JavaKeyStore.txt Remove-Item –path .\JavaKeyStoreBase.txt - dir $(sqljdbc_auth.secureFilePath) Copy-Item -Path $(sqljdbc_auth.secureFilePath) -Destination "C:\Windows\System32" - dir C:\Windows\System32\sqljdbc_auth.dll displayName: 'PowerShell Script' - task: DownloadSecureFile@1 name: pkcs12_truststore From 16dd417984f665c0571c4c1ed99d845cab1dff63 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 23 Oct 2019 16:04:01 -0700 Subject: [PATCH 28/49] removed debug line --- .../com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 182562171..6e48ca950 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -166,9 +166,6 @@ public static void setUpConnection() throws TestAbortedException, Exception { fail(TestResource.getResource("R_reqExternalSetup")); } - // add to debug - System.out.println("java.library.path="+System.getProperty("java.library.path")); - readFromFile(Constants.JAVA_KEY_STORE_FILENAME, "Alias name"); keyIDs = keyID.split(";"); From f6727580219d48c8816324e6b7d42e3bc672854f Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 23 Oct 2019 23:16:07 -0700 Subject: [PATCH 29/49] assumeTrue --- .../jdbc/AlwaysEncrypted/AESetup.java | 19 ++- .../jdbc/AlwaysEncrypted/EnclaveTest.java | 123 ++++++++++++------ .../JDBCEncryptionDecryptionTest.java | 101 +++++++++----- 3 files changed, 170 insertions(+), 73 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 6e48ca950..503ac07c1 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -186,6 +186,19 @@ public static void setUpConnection() throws TestAbortedException, Exception { isKspRegistered = true; } + String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); + if (null != enclaveAttestationUrl) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", + enclaveAttestationUrl); + } + String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); + if (null != enclaveAttestationProtocol) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, + "enclaveAttestationProtocol", enclaveAttestationProtocol); + } + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "windowsKeyPath", + windowsKeyPath); + dropAll(); createCMK(cmkJks, Constants.JAVA_KEY_STORE_NAME, javaKeyAliases, Constants.CMK_SIGNATURE); @@ -194,8 +207,6 @@ public static void setUpConnection() throws TestAbortedException, Exception { createCMK(cmkAkv, Constants.AZURE_KEY_VAULT_NAME, keyIDs[0], Constants.CMK_SIGNATURE_AKV); createCEK(cmkAkv, cekAkv, akvProvider); - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "windowsKeyPath", - windowsKeyPath); createCMK(cmkWin, Constants.WINDOWS_KEY_STORE_NAME, windowsKeyPath, Constants.CMK_SIGNATURE); createCEK(cmkWin, cekWin, null); @@ -475,9 +486,7 @@ private static void createCMK(String cmkName, String keyStoreName, String keyPat String sql = " if not exists (SELECT name from sys.column_master_keys where name='" + cmkName + "')" + " begin" + " CREATE COLUMN MASTER KEY " + cmkName + " WITH (KEY_STORE_PROVIDER_NAME = '" + keyStoreName + "', KEY_PATH = '" + keyPath + "'" - // + (TestUtils.isAEv2(con) ? ",ENCLAVE_COMPUTATIONS (SIGNATURE = " + signature + ")) end" : ") - // end"); - + ",ENCLAVE_COMPUTATIONS (SIGNATURE = " + signature + ")) end"; + + (TestUtils.isAEv2(con) ? ",ENCLAVE_COMPUTATIONS (SIGNATURE = " + signature + ")) end" : ") end"); stmt.execute(sql); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java index e4569c89e..c9a08308d 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java @@ -5,6 +5,7 @@ package com.microsoft.sqlserver.jdbc.AlwaysEncrypted; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import java.sql.ParameterMetaData; import java.sql.PreparedStatement; @@ -22,6 +23,7 @@ import com.microsoft.sqlserver.jdbc.RandomData; import com.microsoft.sqlserver.jdbc.SQLServerConnection; import com.microsoft.sqlserver.jdbc.SQLServerStatement; +import com.microsoft.sqlserver.jdbc.TestResource; import com.microsoft.sqlserver.jdbc.TestUtils; import com.microsoft.sqlserver.testframework.AbstractSQLGenerator; import com.microsoft.sqlserver.testframework.Constants; @@ -33,7 +35,7 @@ * */ @RunWith(JUnitPlatform.class) -@Tag(Constants.xSQLv15) +@Tag(Constants.xSQLv12) @Tag(Constants.xAzureSQLDW) @Tag(Constants.xAzureSQLDB) @Tag(Constants.reqExternalSetup) @@ -43,16 +45,17 @@ public class EnclaveTest extends JDBCEncryptionDecryptionTest { @BeforeAll public static void setupEnclave() throws TestAbortedException, Exception { - String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); - if (null != enclaveAttestationUrl) { - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", - enclaveAttestationUrl); - } - String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); - if (null != enclaveAttestationProtocol) { - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, - "enclaveAttestationProtocol", enclaveAttestationProtocol); + boolean isAEv2 = false; + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { + isAEv2 = TestUtils.isAEv2(con); + + } catch (SQLException e) { + isAEv2 = false; + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); } + + org.junit.Assume.assumeTrue(isAEv2); } /** @@ -67,10 +70,26 @@ public void testCharSpecificSetter() throws SQLException { String[] values = createCharValues(nullable); testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, true); - testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, true); testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, true); } } + + /** + * Junit test case for char set string for string values using windows certificate store + * + * @throws SQLException + */ + @Test + public void testCharSpecificSetterWindows() throws SQLException { + org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = createCharValues(nullable); + + testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, true); + } + } /** * Junit test case for char set object for string values @@ -84,7 +103,6 @@ public void testCharSetObject() throws SQLException { String[] values = createCharValues(nullable); testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, true); - testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, true); testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, true); } } @@ -101,7 +119,6 @@ public void testCharSetObjectWithJDBCTypes() throws SQLException { String[] values = createCharValues(nullable); testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); - testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); } } @@ -117,7 +134,6 @@ public void testCharSpecificSetterNull() throws SQLException { String[] values = {null, null, null, null, null, null, null, null, null}; testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, true); - testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, true); testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, true); } } @@ -134,7 +150,6 @@ public void testCharSetObjectNull() throws SQLException { String[] values = {null, null, null, null, null, null, null, null, null}; testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, true); - testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, true); testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, true); } } @@ -151,7 +166,6 @@ public void testCharSetNull() throws SQLException { String[] values = {null, null, null, null, null, null, null, null, null}; testChars(stmt, cekJks, charTable, values, TestCase.NULL, true); - testChars(stmt, cekWin, charTable, values, TestCase.NULL, true); testChars(stmt, cekAkv, charTable, values, TestCase.NULL, true); } } @@ -168,11 +182,27 @@ public void testBinarySpecificSetter() throws SQLException { LinkedList values = createBinaryValues(false); testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, true); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, true); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, true); } } + /** + * Junit test case for binary set binary for binary values using windows certificate store + * + * @throws SQLException + */ + @Test + public void testBinarySpecificSetterWindows() throws SQLException { + org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createBinaryValues(false); + + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, true); + } + } + /** * Junit test case for binary set object for binary values * @@ -185,7 +215,6 @@ public void testBinarySetobject() throws SQLException { LinkedList values = createBinaryValues(false); testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT, true); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT, true); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT, true); } } @@ -202,7 +231,6 @@ public void testBinarySetNull() throws SQLException { LinkedList values = createBinaryValues(true); testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL, true); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NULL, true); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL, true); } } @@ -219,7 +247,6 @@ public void testBinarySpecificSetterNull() throws SQLException { LinkedList values = createBinaryValues(true); testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, true); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, true); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, true); } } @@ -236,7 +263,6 @@ public void testBinarysetObjectNull() throws SQLException { LinkedList values = createBinaryValues(true); testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL, true); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_NULL, true); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL, true); } } @@ -248,13 +274,11 @@ public void testBinarysetObjectNull() throws SQLException { */ @Test public void testBinarySetObjectWithJDBCTypes() throws SQLException { - try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { LinkedList values = createBinaryValues(false); testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); } } @@ -271,11 +295,27 @@ public void testDateSpecificSetter() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, true); - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, true); testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, true); } } + /** + * Junit test case for date set date for date values using windows certificate store + * + * @throws SQLException + */ + @Test + public void testDateSpecificSetterWindows() throws SQLException { + org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, true); + } + } + /** * Junit test case for date set object for date values * @@ -288,7 +328,6 @@ public void testDateSetObject() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT, true); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT, true); testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT, true); } } @@ -305,7 +344,6 @@ public void testDateSetObjectWithJavaType() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, true); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, true); testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, true); } } @@ -322,7 +360,6 @@ public void testDateSetObjectWithJDBCType() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, true); } } @@ -340,7 +377,6 @@ public void testDateSpecificSetterMinMaxValue() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, true); - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, true); testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, true); } } @@ -359,7 +395,6 @@ public void testDateSetNull() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.NULL, true); - testDates(stmt, cekWin, dateTable, values, TestCase.NULL, true); testDates(stmt, cekAkv, dateTable, values, TestCase.NULL, true); } @@ -382,7 +417,6 @@ public void testDateSetObjectNull() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL, true); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_NULL, true); testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL, true); } @@ -405,11 +439,30 @@ public void testNumericSpecificSetter() throws TestAbortedException, Exception { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, true); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, true); } } + /** + * Junit test case for numeric set numeric for numeric values using windows certificate store + * + * @throws SQLException + */ + @Test + public void testNumericSpecificSetterWindows() throws TestAbortedException, Exception { + org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); + } + } + /** * Junit test case for numeric set object for numeric values * @@ -424,7 +477,6 @@ public void testNumericSetObject() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT, true); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT, true); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT, true); } } @@ -436,7 +488,6 @@ public void testNumericSetObject() throws SQLException { */ @Test public void testNumericSetObjectWithJDBCTypes() throws SQLException { - try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { String[] values1 = createNumericValues(nullable); @@ -444,7 +495,6 @@ public void testNumericSetObjectWithJDBCTypes() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, true); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, true); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, true); } } @@ -469,7 +519,6 @@ public void testNumericSpecificSetterMaxValue() throws SQLException { "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, true); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, true); } } @@ -493,7 +542,6 @@ public void testNumericSpecificSetterMinValue() throws SQLException { "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, true); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, true); } } @@ -514,7 +562,6 @@ public void testNumericSpecificSetterNull() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, true); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL, true); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, true); } @@ -538,7 +585,6 @@ public void testNumericSpecificSetterSetObjectNull() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, true); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL, true); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, true); } @@ -563,7 +609,6 @@ public void testNumericNormalization() throws SQLException { "999999999999999999999999.9999", "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, true); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, true); } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index 79baebffd..0bd5d7af7 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -72,11 +72,27 @@ public void testCharSpecificSetter() throws SQLException { String[] values = createCharValues(nullable); testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, false); - testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, false); testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, false); } } + /** + * Junit test case for char set string for string values using windows certificate store + * + * @throws SQLException + */ + @Test + public void testCharSpecificSetterWindows() throws SQLException { + org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = createCharValues(nullable); + + testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, false); + } + } + /** * Junit test case for char set object for string values * @@ -89,7 +105,6 @@ public void testCharSetObject() throws SQLException { String[] values = createCharValues(nullable); testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, false); - testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, false); testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, false); } } @@ -106,7 +121,6 @@ public void testCharSetObjectWithJDBCTypes() throws SQLException { String[] values = createCharValues(nullable); testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); - testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } @@ -123,7 +137,6 @@ public void testCharSpecificSetterNull() throws SQLException { String[] values = {null, null, null, null, null, null, null, null, null}; testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, false); - testChars(stmt, cekWin, charTable, values, TestCase.NORMAL, false); testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, false); } } @@ -140,7 +153,6 @@ public void testCharSetObjectNull() throws SQLException { String[] values = {null, null, null, null, null, null, null, null, null}; testChars(stmt, cekJks, charTable, values, TestCase.SETOBJECT, false); - testChars(stmt, cekWin, charTable, values, TestCase.SETOBJECT, false); testChars(stmt, cekAkv, charTable, values, TestCase.SETOBJECT, false); } } @@ -157,7 +169,6 @@ public void testCharSetNull() throws SQLException { String[] values = {null, null, null, null, null, null, null, null, null}; testChars(stmt, cekJks, charTable, values, TestCase.NULL, false); - testChars(stmt, cekWin, charTable, values, TestCase.NULL, false); testChars(stmt, cekAkv, charTable, values, TestCase.NULL, false); } } @@ -174,11 +185,27 @@ public void testBinarySpecificSetter() throws SQLException { LinkedList values = createBinaryValues(false); testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, false); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, false); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, false); } } + /** + * Junit test case for binary set binary for binary values using windows certificate store + * + * @throws SQLException + */ + @Test + public void testBinarySpecificSetterWindows() throws SQLException { + org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createBinaryValues(false); + + testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, false); + } + } + /** * Junit test case for binary set object for binary values * @@ -191,7 +218,6 @@ public void testBinarySetobject() throws SQLException { LinkedList values = createBinaryValues(false); testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT, false); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT, false); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT, false); } } @@ -208,7 +234,6 @@ public void testBinarySetNull() throws SQLException { LinkedList values = createBinaryValues(true); testBinaries(stmt, cekJks, binaryTable, values, TestCase.NULL, false); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NULL, false); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NULL, false); } } @@ -225,7 +250,6 @@ public void testBinarySpecificSetterNull() throws SQLException { LinkedList values = createBinaryValues(true); testBinaries(stmt, cekJks, binaryTable, values, TestCase.NORMAL, false); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.NORMAL, false); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.NORMAL, false); } } @@ -242,7 +266,6 @@ public void testBinarysetObjectNull() throws SQLException { LinkedList values = createBinaryValues(true); testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_NULL, false); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_NULL, false); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_NULL, false); } } @@ -260,7 +283,6 @@ public void testBinarySetObjectWithJDBCTypes() throws SQLException { LinkedList values = createBinaryValues(false); testBinaries(stmt, cekJks, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); - testBinaries(stmt, cekWin, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); testBinaries(stmt, cekAkv, binaryTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } @@ -277,11 +299,27 @@ public void testDateSpecificSetter() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, false); - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, false); testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, false); } } + /** + * Junit test case for date set date for date values using windows certificate store + * + * @throws SQLException + */ + @Test + public void testDateSpecificSetterWindows() throws SQLException { + org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + LinkedList values = createTemporalTypes(nullable); + + testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, false); + } + } + /** * Junit test case for date set object for date values * @@ -294,7 +332,6 @@ public void testDateSetObject() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT, false); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT, false); testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT, false); } } @@ -311,7 +348,6 @@ public void testDateSetObjectWithJavaType() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JAVATYPES, false); } } @@ -328,7 +364,6 @@ public void testDateSetObjectWithJDBCType() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } @@ -346,7 +381,6 @@ public void testDateSpecificSetterMinMaxValue() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.NORMAL, false); - testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, false); testDates(stmt, cekAkv, dateTable, values, TestCase.NORMAL, false); } } @@ -365,7 +399,6 @@ public void testDateSetNull() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.NULL, false); - testDates(stmt, cekWin, dateTable, values, TestCase.NULL, false); testDates(stmt, cekAkv, dateTable, values, TestCase.NULL, false); } @@ -388,7 +421,6 @@ public void testDateSetObjectNull() throws SQLException { LinkedList values = createTemporalTypes(nullable); testDates(stmt, cekJks, dateTable, values, TestCase.SETOBJECT_NULL, false); - testDates(stmt, cekWin, dateTable, values, TestCase.SETOBJECT_NULL, false); testDates(stmt, cekAkv, dateTable, values, TestCase.SETOBJECT_NULL, false); } @@ -411,11 +443,30 @@ public void testNumericSpecificSetter() throws TestAbortedException, Exception { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } + /** + * Junit test case for numeric set numeric for numeric values using windows certificate store + * + * @throws SQLException + */ + @Test + public void testNumericSpecificSetterWindows() throws TestAbortedException, Exception { + org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + + String[] values1 = createNumericValues(nullable); + String[] values2 = new String[values1.length]; + System.arraycopy(values1, 0, values2, 0, values1.length); + + testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); + } + } + /** * Junit test case for numeric set object for numeric values * @@ -430,7 +481,6 @@ public void testNumericSetObject() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT, false); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT, false); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT, false); } } @@ -450,7 +500,6 @@ public void testNumericSetObjectWithJDBCTypes() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.SETOBJECT_WITH_JDBCTYPES, false); } } @@ -475,8 +524,6 @@ public void testNumericSpecificSetterMaxValue() throws SQLException { "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } @@ -500,8 +547,6 @@ public void testNumericSpecificSetterMinValue() throws SQLException { "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } @@ -522,7 +567,6 @@ public void testNumericSpecificSetterNull() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, false); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL, false); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, false); } @@ -546,7 +590,6 @@ public void testNumericSpecificSetterSetObjectNull() throws SQLException { System.arraycopy(values1, 0, values2, 0, values1.length); testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NULL, false); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NULL, false); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NULL, false); } @@ -571,7 +614,6 @@ public void testNumericNormalization() throws SQLException { "999999999999999999999999.9999", "999999999999999999999999.9999"}; testNumerics(stmt, cekJks, numericTable, values1, values2, TestCase.NORMAL, false); - testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, false); testNumerics(stmt, cekAkv, numericTable, values1, values2, TestCase.NORMAL, false); } } @@ -594,6 +636,7 @@ public void testAEFMTOnly() throws SQLException { void testChar(SQLServerStatement stmt, String[] values) throws SQLException { String sql = "select * from " + AbstractSQLGenerator.escapeIdentifier(CHAR_TABLE_AE); + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { From d7644eb0a79bf301f1c26eaf976b3e176be81664 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 23 Oct 2019 23:17:43 -0700 Subject: [PATCH 30/49] removed reqExternalSetup for AE tests --- .../jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index 0bd5d7af7..80083cb4b 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -46,7 +46,6 @@ @Tag(Constants.xSQLv12) @Tag(Constants.xAzureSQLDW) @Tag(Constants.xAzureSQLDB) -@Tag(Constants.reqExternalSetup) public class JDBCEncryptionDecryptionTest extends AESetup { private boolean nullable = false; From 65f0fcdd14264fa54a09e3c7a6aaba31fba36148 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 24 Oct 2019 09:49:51 -0700 Subject: [PATCH 31/49] fixed typo for jre11 --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index db4b9ccf5..16a6c5394 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -55,7 +55,7 @@ jobs: inputs: mavenPomFile: 'pom.xml' goals: 'clean -Dmssql_jdbc_test_connection_properties=jdbc:sqlserver://$(Target_SQL)$(server_domain);$(database);$(user);$(password); install -Pjre11 -DuserNTLM=$(userNTLM) -DpasswordNTLM=$(passwordNTLM) -DdomainNTLM=$(domainNTLM) -DexcludedGroups=$(Ex_Groups) -Dpkcs12_truststore_password=$(pkcs12_truststore_password) -Dpkcs12_truststore=$(pkcs12_truststore.secureFilePath) --DapplicationClientID=$(applicationClientID) -DapplicationKey=$(applicationKey) -DkeyID=$(keyID) -DwindowsKeyPath=$(windowsKeyPath) -DenclaveAttestationUrl=$(enclaveAttestationUrl) -DenclaveAttestationProtocol=$(enclaveAttestationUrl) +-DapplicationClientID=$(applicationClientID) -DapplicationKey=$(applicationKey) -DkeyID=$(keyID) -DwindowsKeyPath=$(windowsKeyPath) -DenclaveAttestationUrl=$(enclaveAttestationUrl) -DenclaveAttestationProtocol=$(enclaveAttestationProtocol) ' testResultsFiles: '**/TEST-*.xml' testRunTitle: 'Maven build jre11' @@ -66,7 +66,7 @@ jobs: inputs: mavenPomFile: 'pom.xml' goals: 'clean -Dmssql_jdbc_test_connection_properties=jdbc:sqlserver://$(Target_SQL)$(server_domain);$(database);$(user);$(password); install -Pjre8 -DuserNTLM=$(userNTLM) -DpasswordNTLM=$(passwordNTLM) -DdomainNTLM=$(domainNTLM) -DexcludedGroups=$(Ex_Groups) -Dpkcs12_truststore_password=$(pkcs12_truststore_password) -Dpkcs12_truststore=$(pkcs12_truststore.secureFilePath) --DapplicationClientID=$(applicationClientID) -DapplicationKey=$(applicationKey) -DkeyID=$(keyID) -DwindowsKeyPath=$(windowsKeyPath) -DenclaveAttestationUrl=$(enclaveAttestationUrl) -DenclaveAttestationProtocol=$(enclaveAttestationUrl)' +-DapplicationClientID=$(applicationClientID) -DapplicationKey=$(applicationKey) -DkeyID=$(keyID) -DwindowsKeyPath=$(windowsKeyPath) -DenclaveAttestationUrl=$(enclaveAttestationUrl) -DenclaveAttestationProtocol=$(enclaveAttestationProtocol)' testResultsFiles: '**/TEST-*.xml' testRunTitle: 'Maven build jre8' javaHomeOption: Path From 30726b18a3f5e949bec4d432ad3dbebda14ce90a Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 24 Oct 2019 13:39:37 -0700 Subject: [PATCH 32/49] removed reqExternalSetup from reg AE tests --- .../sqlserver/jdbc/AlwaysEncrypted/AESetup.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 503ac07c1..819ac2985 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -24,7 +24,6 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Tag; import org.junit.platform.runner.JUnitPlatform; import org.junit.runner.RunWith; import org.opentest4j.TestAbortedException; @@ -49,13 +48,12 @@ /** - * Setup for Always Encrypted test This test will work on Appveyor and Travis-ci as java key store gets created from the - * .yml scripts. Users on their local machine should create the keystore manually and save the alias name in - * JavaKeyStore.txt file. For local test purposes, put this in the target/test-classes directory + * Setup for Always Encrypted test This test will work on Azure DevOps as java key store gets created from the .yml + * scripts. Users on their local machine should create the keystore manually and save the alias name in JavaKeyStore.txt + * file. For local test purposes, put this in the target/test-classes directory * */ @RunWith(JUnitPlatform.class) -@Tag(Constants.reqExternalSetup) public class AESetup extends AbstractTest { static String cmkJks = Constants.CMK_NAME + "_JKS"; @@ -207,7 +205,6 @@ public static void setUpConnection() throws TestAbortedException, Exception { createCMK(cmkAkv, Constants.AZURE_KEY_VAULT_NAME, keyIDs[0], Constants.CMK_SIGNATURE_AKV); createCEK(cmkAkv, cekAkv, akvProvider); - createCMK(cmkWin, Constants.WINDOWS_KEY_STORE_NAME, windowsKeyPath, Constants.CMK_SIGNATURE); createCEK(cmkWin, cekWin, null); From 7790d4f05ca85e2ab3902d01ab5c9c908d4049e8 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 24 Oct 2019 15:11:15 -0700 Subject: [PATCH 33/49] windows check --- .../microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java | 4 +++- .../AlwaysEncrypted/JDBCEncryptionDecryptionTest.java | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 819ac2985..0b33bda6f 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -73,6 +73,7 @@ public class AESetup extends AbstractTest { static Map map = new HashMap(); static boolean isKspRegistered = false; + static boolean isWindows = System.getProperty("os.name").startsWith("Windows"); public static final String tableName = RandomUtil.getIdentifier("AETest_"); public static final String CHAR_TABLE_AE = RandomUtil.getIdentifier("JDBCEncryptedChar"); @@ -160,7 +161,8 @@ public static void setUpConnection() throws TestAbortedException, Exception { String windowsKeyPath = TestUtils.getConfiguredProperty("windowsKeyPath"); String javaKeyPath = TestUtils.getCurrentClassPath() + Constants.JKS_NAME; - if (null == applicationClientID || null == applicationKey || null == keyID || null == windowsKeyPath) { + if (null == applicationClientID || null == applicationKey || null == keyID + || (isWindows && null == windowsKeyPath)) { fail(TestResource.getResource("R_reqExternalSetup")); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index 80083cb4b..c4d29a728 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -82,7 +82,7 @@ public void testCharSpecificSetter() throws SQLException { */ @Test public void testCharSpecificSetterWindows() throws SQLException { - org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + org.junit.Assume.assumeTrue(isWindows); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { @@ -195,7 +195,7 @@ public void testBinarySpecificSetter() throws SQLException { */ @Test public void testBinarySpecificSetterWindows() throws SQLException { - org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + org.junit.Assume.assumeTrue(isWindows); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { @@ -309,7 +309,7 @@ public void testDateSpecificSetter() throws SQLException { */ @Test public void testDateSpecificSetterWindows() throws SQLException { - org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + org.junit.Assume.assumeTrue(isWindows); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { @@ -453,7 +453,7 @@ public void testNumericSpecificSetter() throws TestAbortedException, Exception { */ @Test public void testNumericSpecificSetterWindows() throws TestAbortedException, Exception { - org.junit.Assume.assumeTrue(System.getProperty("os.name").startsWith("Windows")); + org.junit.Assume.assumeTrue(isWindows); try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { From b9ac82b1d0e8349223f784b4c273d86a2338afdd Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 24 Oct 2019 16:12:59 -0700 Subject: [PATCH 34/49] added comment to trigger build --- .../com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 0b33bda6f..8649adccc 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -73,6 +73,8 @@ public class AESetup extends AbstractTest { static Map map = new HashMap(); static boolean isKspRegistered = false; + + // test that only run on Windows will be skipped static boolean isWindows = System.getProperty("os.name").startsWith("Windows"); public static final String tableName = RandomUtil.getIdentifier("AETest_"); From a8ce69a02cf067fa2078dbe8c02b32aab26175c8 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 25 Oct 2019 18:12:28 -0700 Subject: [PATCH 35/49] added more tests and fixed some stuff --- .../microsoft/sqlserver/jdbc/IOBuffer.java | 2 +- .../sqlserver/jdbc/SQLServerConnection.java | 19 +- .../sqlserver/jdbc/SQLServerResource.java | 6 +- .../jdbc/SQLServerVSMEnclaveProvider.java | 2 +- .../com/microsoft/sqlserver/jdbc/AETest.java | 194 ++++++++++++++++++ .../jdbc/AlwaysEncrypted/AESetup.java | 16 +- .../jdbc/AlwaysEncrypted/EnclaveTest.java | 1 - .../sqlserver/jdbc/TestResource.java | 3 +- .../microsoft/sqlserver/jdbc/TestUtils.java | 15 ++ .../sqlserver/testframework/AbstractTest.java | 6 + .../sqlserver/testframework/Constants.java | 3 +- 11 files changed, 248 insertions(+), 19 deletions(-) create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/AETest.java diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index 2cd9404f8..cd82906a3 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -6197,7 +6197,7 @@ void writeRPCReaderUnicode(String sName, Reader re, long reLength, boolean bOut, void sendEnclavePackage(String sql, ArrayList enclaveCEKs) throws SQLServerException { if (null != con && con.isAEv2()) { if (null != sql && "" != sql && null != enclaveCEKs && 0 < enclaveCEKs.size() && con.enclaveEstablished()) { - byte[] b = con.generateEncalvePackage(sql, enclaveCEKs); + byte[] b = con.generateEnclavePackage(sql, enclaveCEKs); if (null != b && 0 != b.length) { this.writeShort((short) b.length); this.writeBytes(b); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 04366fa27..94bd9c08a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -1473,10 +1473,6 @@ Connection connectInternal(Properties propsIn, if (null != sPropValue) { enclaveAttestationProtocol = sPropValue; if (!AttestationProtocol.isValidAttestationProtocol(enclaveAttestationProtocol)) { - if (connectionlogger.isLoggable(Level.SEVERE)) { - connectionlogger.severe(toString() + " " - + SQLServerException.getErrString("R_enclaveInvalidAttestationProtocol")); - } throw new SQLServerException(SQLServerException.getErrString("R_enclaveInvalidAttestationProtocol"), null); } @@ -1487,11 +1483,14 @@ Connection connectInternal(Properties propsIn, && (null == enclaveAttestationProtocol || enclaveAttestationProtocol.isEmpty())) || (null != enclaveAttestationProtocol && !enclaveAttestationProtocol.isEmpty() && (null == enclaveAttestationUrl || enclaveAttestationUrl.isEmpty()))) { - if (connectionlogger.isLoggable(Level.SEVERE)) { - connectionlogger.severe( - toString() + " " + SQLServerException.getErrString("R_enclaveNoAttestationProtocol")); - } - throw new SQLServerException(SQLServerException.getErrString("R_enclaveNoAttestationProtocol"), null); + throw new SQLServerException(SQLServerException.getErrString("R_enclavePropertiesError"), null); + } + + // enclave requires columnEncryption + if ((null != enclaveAttestationUrl && !enclaveAttestationUrl.isEmpty() + && (null != enclaveAttestationProtocol || !enclaveAttestationProtocol.isEmpty()) + && (null == columnEncryptionSetting || !isColumnEncryptionSettingEnabled()))) { + throw new SQLServerException(SQLServerException.getErrString("R_enclaveAEdisabled"), null); } sPropKey = SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.toString(); @@ -6485,7 +6484,7 @@ boolean enclaveEstablished() { return (null != enclaveProvider.getEnclaveSession()); } - byte[] generateEncalvePackage(String userSQL, ArrayList enclaveCEKs) throws SQLServerException { + byte[] generateEnclavePackage(String userSQL, ArrayList enclaveCEKs) throws SQLServerException { return (enclaveCEKs.size() > 0) ? enclaveProvider.getEnclavePackage(userSQL, enclaveCEKs) : null; } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 093a7a83f..c89fb0885 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -598,8 +598,10 @@ protected Object[][] getContents() { "An error occurred when matching VALUES list to table columns. Please verify SQL syntax."}, {"R_invalidValuesList", "An error occurred when reading VALUES list. Please verify SQL syntax."}, {"R_enclaveNotSupported", "The SQL Server instance does not support enclave based computations."}, - {"R_enclaveNoAttestationProtocol", - "The \"enclaveAttestationProtocol\" connection property must be specified with \"enclaveAttestationUrl\"."}, + {"R_enclaveAEdisabled", + "The \"columnEncryptionSetting\" connection property must be enabled when specifying \"enclaveAttestationUrl\" and \"enclaveAttestationProtocol\" connection properties."}, + {"R_enclavePropertiesError", + "The \"enclaveAttestationUrl\" connection property must be specified with \"enclaveAttestationProtocol\"."}, {"R_enclaveInvalidAttestationProtocol", "The \"enclaveAttestationProtocol\" is invalid."}, {"R_enclaveTypeInvalid", "The enclave type {0} is invalid or not supported by the driver."}, {"R_attestationUrlInvalid", "Unable to attest enclave specified by {0}."}, diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index 9ad90e981..abdb84a23 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -362,7 +362,7 @@ byte[] getBytes() { } byte[] createSessionSecret(byte[] serverResponse) throws GeneralSecurityException, SQLServerException { - if (serverResponse.length != ENCLAVE_LENGTH) { + if (null == serverResponse || serverResponse.length != ENCLAVE_LENGTH) { SQLServerException.makeFromDriverError(null, this, SQLServerResource.getResource("R_MalformedECDHPublicKey"), "0", false); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java new file mode 100644 index 000000000..a5dddeedd --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java @@ -0,0 +1,194 @@ +package com.microsoft.sqlserver.jdbc; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.logging.LogManager; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +import com.microsoft.sqlserver.testframework.AbstractTest; +import com.microsoft.sqlserver.testframework.Constants; +import com.microsoft.sqlserver.testframework.PrepUtil; + + +/** + * A class for testing basic NTLMv2 functionality. + */ +@RunWith(JUnitPlatform.class) +@Tag(Constants.xSQLv12) +@Tag(Constants.xAzureSQLDW) +@Tag(Constants.xAzureSQLDB) +public class AETest extends AbstractTest { + + private static SQLServerDataSource dsLocal = null; + private static SQLServerDataSource dsXA = null; + private static SQLServerDataSource dsPool = null; + + private static String connectionStringAE; + + /** + * Setup environment for test. + * + * @throws Exception + * when an error occurs + */ + @BeforeAll + public static void setUp() throws Exception { + connectionStringAE = TestUtils.addOrOverrideProperty(connectionString, "columnEncryptionSetting", + ColumnEncryptionSetting.Enabled.toString()); + + String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); + connectionStringAE = TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationUrl", + (null != enclaveAttestationUrl) ? enclaveAttestationUrl : "http://blah"); + + String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); + connectionStringAE = TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationProtocol", + (null != enclaveAttestationProtocol) ? enclaveAttestationProtocol : AttestationProtocol.HGS.toString()); + + // reset logging to avoid severe logs due to negative testing + LogManager.getLogManager().reset(); + + dsLocal = new SQLServerDataSource(); + AbstractTest.updateDataSource(connectionStringAE, dsLocal); + + dsXA = new SQLServerXADataSource(); + AbstractTest.updateDataSource(connectionStringAE, dsXA); + + dsPool = new SQLServerConnectionPoolDataSource(); + AbstractTest.updateDataSource(connectionStringAE, dsPool); + + } + + /** + * Tests basic connection. + * + * @throws SQLException + * when an error occurs + */ + @Test + public void testBasicConnection() throws SQLException { + try (Connection con1 = dsLocal.getConnection(); Connection con2 = dsXA.getConnection(); + Connection con3 = dsPool.getConnection(); + Connection con4 = PrepUtil.getConnection(connectionStringAE)) { + if (TestUtils.isAEv2(con1)) { + verifyEnclaveEnabled(con1); + } + if (TestUtils.isAEv2(con2)) { + verifyEnclaveEnabled(con2); + } + if (TestUtils.isAEv2(con3)) { + verifyEnclaveEnabled(con3); + } + if (TestUtils.isAEv2(con4)) { + verifyEnclaveEnabled(con4); + } + } + } + + /** + * Tests invalid connection property combinations. + */ + @Test + public void testInvalidProperties() { + // enclaveAttestationUrl and enclaveAttestationProtocol without "columnEncryptionSetting" + testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringAE, "columnEncryptionSetting", + ColumnEncryptionSetting.Disabled.toString()), "R_enclaveAEdisabled"); + + // enclaveAttestationUrl without enclaveAttestationProtocol + testInvalidProperties(TestUtils.removeProperty(connectionStringAE, "enclaveAttestationProtocol"), + "R_enclavePropertiesError"); + + // enclaveAttestationProtocol without enclaveAttestationUrl + testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationUrl", ""), + "R_enclavePropertiesError"); + + // bad enclaveAttestationProtocol + testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationProtocol", ""), + "R_enclaveInvalidAttestationProtocol"); + + } + + /* + * Test getEnclavePackage with null enclaveSession + */ + @Test + public void testGetEnclavePackage() { + SQLServerVSMEnclaveProvider provider = new SQLServerVSMEnclaveProvider(); + try { + provider.getEnclavePackage(null, null); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException")); + } + + } + + /* + * Test invalidEnclaveSession + */ + @Test + public void testInvalidEnclaveSession() { + SQLServerVSMEnclaveProvider provider = new SQLServerVSMEnclaveProvider(); + provider.invalidateEnclaveSession(); + if (null != provider.getEnclaveSession()) { + fail(TestResource.getResource("R_invalidEnclaveSessionFailed")); + } + } + + /* + * Test VSM createSessionSecret with bad server response + */ + @Test + public void testCreateSessionSecret() throws SQLServerException { + VSMAttestationParameters param = new VSMAttestationParameters(); + + try { + param.createSessionSecret(null); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_MalformedECDHPublicKey"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + + try { + byte[] serverResponse = new byte[104]; // ENCLAVE_LENGTH is private + param.createSessionSecret(serverResponse); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_MalformedECDHHeader"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /* + * Test invalid properties + */ + private void testInvalidProperties(String connStr, String resourceKeyword) { + try (Connection con = PrepUtil.getConnection(connStr)) { + fail(TestResource.getResource("R_expectedFailPassed")); + } catch (SQLException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg(resourceKeyword)), e.getMessage()); + } + } + + /* + * Verify if Enclave is enabled + */ + private void verifyEnclaveEnabled(Connection con) throws SQLException { + try (Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery( + "SELECT [name], [value], [value_in_use] FROM sys.configurations WHERE [name] = 'column encryption enclave type';")) { + while (rs.next()) { + assertEquals("1", rs.getString(2)); + } + } + } +} diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 8649adccc..b915b9f4b 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -73,7 +73,7 @@ public class AESetup extends AbstractTest { static Map map = new HashMap(); static boolean isKspRegistered = false; - + // test that only run on Windows will be skipped static boolean isWindows = System.getProperty("os.name").startsWith("Windows"); @@ -156,13 +156,25 @@ enum ColumnType { */ @BeforeAll public static void setUpConnection() throws TestAbortedException, Exception { - AETestConnectionString = connectionString + ";sendTimeAsDateTime=false"; + AETestConnectionString = connectionString + ";sendTimeAsDateTime=false" + ";columnEncryptionSetting=enabled"; String applicationClientID = TestUtils.getConfiguredProperty("applicationClientID"); String applicationKey = TestUtils.getConfiguredProperty("applicationKey"); String keyID = TestUtils.getConfiguredProperty("keyID"); String windowsKeyPath = TestUtils.getConfiguredProperty("windowsKeyPath"); String javaKeyPath = TestUtils.getCurrentClassPath() + Constants.JKS_NAME; + /* + String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); + if (null != enclaveAttestationUrl) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", + enclaveAttestationUrl); + } + String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); + if (null != enclaveAttestationProtocol) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, + "enclaveAttestationProtocol", enclaveAttestationProtocol); + } +*/ if (null == applicationClientID || null == applicationKey || null == keyID || (isWindows && null == windowsKeyPath)) { fail(TestResource.getResource("R_reqExternalSetup")); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java index c9a08308d..cf89c9611 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java @@ -48,7 +48,6 @@ public static void setupEnclave() throws TestAbortedException, Exception { boolean isAEv2 = false; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { isAEv2 = TestUtils.isAEv2(con); - } catch (SQLException e) { isAEv2 = false; } catch (Exception e) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java index fbd1fb06f..de1a912ba 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestResource.java @@ -181,5 +181,6 @@ protected Object[][] getContents() { {"R_OperandTypeClash", "Operand type clash"}, {"R_NoPrivilege", "The EXECUTE permission was denied on the object {0}"}, {"R_resultSetEmpty", "Result set is empty."}, {"R_AlterAEv2Error", "Alter Column Encryption failed."}, - {"R_RichQueryError", "Rich query failed."}, {"R_reqExternalSetup", "External setup for test required."},}; + {"R_RichQueryError", "Rich query failed."}, {"R_reqExternalSetup", "External setup for test required."}, + {"R_invalidEnclaveSessionFailed", "invalidate enclave session failed."}}; } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java index dab9a33e6..208d9a1aa 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java @@ -843,6 +843,21 @@ public static String addOrOverrideProperty(String connectionString, String prope return connectionString + ";" + property + "=" + value + ";"; } + /** + * Remove the given connection property in the connection string + * + * @param connectionString + * original connection string + * @param property + * name of the property + * @return The updated connection string + */ + public static String removeProperty(String connectionString, String property) { + int start = connectionString.indexOf(property); + String propertyStr = connectionString.substring(start, connectionString.indexOf(";", start) + 1); + return connectionString.replace(propertyStr, ""); + } + /** * Creates a truststore and returns the path of it. * diff --git a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java index 8bb32524d..dcfbdaf48 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java @@ -204,6 +204,12 @@ protected static ISQLServerDataSource updateDataSource(String connectionString, case Constants.HOST_NAME_IN_CERTIFICATE: ds.setHostNameInCertificate(value); break; + case Constants.ENCLAVE_ATTESTATIONURL: + ds.setEnclaveAttestationUrl(value); + break; + case Constants.ENCLAVE_ATTESTATIONPROTOCOL: + ds.setEnclaveAttestationProtocol(value); + break; default: break; } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/Constants.java b/src/test/java/com/microsoft/sqlserver/testframework/Constants.java index beecd8fed..94e7a63fc 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/Constants.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/Constants.java @@ -135,7 +135,8 @@ private Constants() {} public static final String TRUST_STORE_SECRET_PROPERTY = "TRUSTSTOREPASSWORD"; public static final String TRUST_STORE = "TRUSTSTORE"; - public static final String ENCLAVE_ATTESTATIONURL = "enclaveAttestationUrl"; + public static final String ENCLAVE_ATTESTATIONURL = "ENCLAVEATTESTATIONURL"; + public static final String ENCLAVE_ATTESTATIONPROTOCOL = "ENCLAVEATTESTATIONPROTOCOL"; public enum LOB { CLOB, From d1cd647f708210bf27e449f14c4c58240c7b6c6d Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Fri, 25 Oct 2019 21:14:30 -0700 Subject: [PATCH 36/49] added aev2 check --- .../java/com/microsoft/sqlserver/jdbc/AETest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java index a5dddeedd..70a413c3a 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java @@ -28,6 +28,7 @@ @Tag(Constants.xSQLv12) @Tag(Constants.xAzureSQLDW) @Tag(Constants.xAzureSQLDB) +@Tag(Constants.reqExternalSetup) public class AETest extends AbstractTest { private static SQLServerDataSource dsLocal = null; @@ -55,6 +56,16 @@ public static void setUp() throws Exception { connectionStringAE = TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationProtocol", (null != enclaveAttestationProtocol) ? enclaveAttestationProtocol : AttestationProtocol.HGS.toString()); + boolean isAEv2 = false; + try (SQLServerConnection con = PrepUtil.getConnection(connectionStringAE)) { + isAEv2 = TestUtils.isAEv2(con); + } catch (SQLException e) { + isAEv2 = false; + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); + } + org.junit.Assume.assumeTrue(isAEv2); + // reset logging to avoid severe logs due to negative testing LogManager.getLogManager().reset(); From 560b02da45e80766e051c2e0f341b4df8ec87951 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 29 Oct 2019 11:13:28 -0700 Subject: [PATCH 37/49] update jacoco version and add code coverage --- pom.xml | 2 +- .../jdbc/SQLServerVSMEnclaveProvider.java | 2 ++ .../com/microsoft/sqlserver/jdbc/AETest.java | 7 ++++- .../JDBCEncryptionDecryptionTest.java | 28 ++++++++++++++++--- .../sqlserver/testframework/Constants.java | 4 +-- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index a6e58a706..2b0676edd 100644 --- a/pom.xml +++ b/pom.xml @@ -488,7 +488,7 @@ org.jacoco jacoco-maven-plugin - 0.8.3 + 0.8.5 pre-test diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index abdb84a23..8e7b76741 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -369,10 +369,12 @@ byte[] createSessionSecret(byte[] serverResponse) throws GeneralSecurityExceptio ByteBuffer sr = ByteBuffer.wrap(serverResponse); byte[] magic = new byte[8]; sr.get(magic); + if (!Arrays.equals(magic, ECDH_MAGIC)) { SQLServerException.makeFromDriverError(null, this, SQLServerResource.getResource("R_MalformedECDHHeader"), "0", false); } + byte[] x = new byte[48]; byte[] y = new byte[48]; sr.get(x); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java index 70a413c3a..cf718dc91 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java @@ -159,7 +159,7 @@ public void testInvalidEnclaveSession() { * Test VSM createSessionSecret with bad server response */ @Test - public void testCreateSessionSecret() throws SQLServerException { + public void testNullSessionSecret() throws SQLServerException { VSMAttestationParameters param = new VSMAttestationParameters(); try { @@ -169,6 +169,11 @@ public void testCreateSessionSecret() throws SQLServerException { } catch (Exception e) { fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } + } + + @Test + public void testBadSessionSecret() throws SQLServerException { + VSMAttestationParameters param = new VSMAttestationParameters(); try { byte[] serverResponse = new byte[104]; // ENCLAVE_LENGTH is private diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index c4d29a728..2a75721ab 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -1524,7 +1524,12 @@ void testChars(SQLServerStatement stmt, String cekName, String[][] table, String testChar(stmt, values); testChar(null, values); - if (isTestEnclave && null != getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL)) { + if (isTestEnclave) { + if (null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL) + || null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { + fail(TestResource.getResource("R_reqExternalSetup")); + } + testAlterColumnEncryption(stmt, CHAR_TABLE_AE, table, cekName); testRichQuery(stmt, CHAR_TABLE_AE, table, values); } @@ -1558,7 +1563,12 @@ void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, Lin testBinary(stmt, values); testBinary(null, values); - if (isTestEnclave && null != getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL)) { + if (isTestEnclave) { + if (null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL) + || null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { + fail(TestResource.getResource("R_reqExternalSetup")); + } + testAlterColumnEncryption(stmt, BINARY_TABLE_AE, table, cekName); testRichQuery(stmt, BINARY_TABLE_AE, table, values); } @@ -1596,7 +1606,12 @@ void testDates(SQLServerStatement stmt, String cekName, String[][] table, Linked testDate(stmt, values); testDate(null, values); - if (isTestEnclave && null != getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL)) { + if (isTestEnclave) { + if (null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL) + || null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { + fail(TestResource.getResource("R_reqExternalSetup")); + } + testAlterColumnEncryption(stmt, DATE_TABLE_AE, table, cekName); testRichQueryDate(stmt, DATE_TABLE_AE, table, values); } @@ -1630,7 +1645,12 @@ void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, Str testNumeric(stmt, values1, isNull); testNumeric(null, values2, isNull); - if (isTestEnclave && null != getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL)) { + if (isTestEnclave) { + if (null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL) + || null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { + fail(TestResource.getResource("R_reqExternalSetup")); + } + testAlterColumnEncryption(stmt, NUMERIC_TABLE_AE, table, cekName); testRichQuery(stmt, NUMERIC_TABLE_AE, table, values1); testRichQuery(stmt, NUMERIC_TABLE_AE, table, values2); diff --git a/src/test/java/com/microsoft/sqlserver/testframework/Constants.java b/src/test/java/com/microsoft/sqlserver/testframework/Constants.java index 94e7a63fc..98c3c5501 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/Constants.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/Constants.java @@ -135,8 +135,8 @@ private Constants() {} public static final String TRUST_STORE_SECRET_PROPERTY = "TRUSTSTOREPASSWORD"; public static final String TRUST_STORE = "TRUSTSTORE"; - public static final String ENCLAVE_ATTESTATIONURL = "ENCLAVEATTESTATIONURL"; - public static final String ENCLAVE_ATTESTATIONPROTOCOL = "ENCLAVEATTESTATIONPROTOCOL"; + public static final String ENCLAVE_ATTESTATIONURL = "enclaveAttestationUrl"; + public static final String ENCLAVE_ATTESTATIONPROTOCOL = "enclaveAttestationProtocol"; public enum LOB { CLOB, From 76031613c84dce8302199d679fb22bfad468fe54 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 30 Oct 2019 11:56:41 -0700 Subject: [PATCH 38/49] added more tests and fix executeBatch issue --- .../jdbc/SQLServerPreparedStatement.java | 4 +- .../sqlserver/jdbc/SQLServerResource.java | 2 +- .../jdbc/SQLServerVSMEnclaveProvider.java | 2 +- .../jdbc/AlwaysEncrypted/AESetup.java | 12 -- .../AlwaysEncrypted/PrecisionScaleTest.java | 140 +++++++++--------- .../RegressionAlwaysEncryptedTest.java | 4 +- 6 files changed, 73 insertions(+), 91 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java index c9d0f90e7..5f012f186 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerPreparedStatement.java @@ -938,7 +938,7 @@ private void getParameterEncryptionMetadata(Parameter[] params) throws SQLServer // cekEntry will be null if none of the parameters are encrypted. if ((null != cekEntry) && (cekList.size() < cekOrdinal)) { MessageFormat form = new MessageFormat( - SQLServerException.getErrString("R_InvalidEncryptionKeyOridnal")); + SQLServerException.getErrString("R_InvalidEncryptionKeyOrdinal")); Object[] msgArgs = {cekOrdinal, cekEntry.getSize()}; throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } @@ -2732,7 +2732,7 @@ final void doExecutePreparedStatementBatch(PrepStmtBatchExecCmd batchCommand) th boolean hasExistingTypeDefinitions = preparedTypeDefinitions != null; boolean hasNewTypeDefinitions = buildPreparedStrings(batchParam, false); - if (!isInternalEncryptionQuery && connection.isAEv2()) { + if ((0 == numBatchesExecuted) && !isInternalEncryptionQuery && connection.isAEv2()) { this.enclaveCEKs = connection.initEnclaveParameters(preparedSQL, preparedTypeDefinitions, batchParam, parameterNames); encryptionMetadataIsRetrieved = true; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index c89fb0885..5d6cb1f57 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -298,7 +298,7 @@ protected Object[][] getContents() { {"R_unsupportedEncoding", "The encoding {0} is not supported."}, {"R_UnexpectedDescribeParamFormat", "Internal error. The format of the resultset returned by sp_describe_parameter_encryption is invalid. One of the resultsets is missing."}, - {"R_InvalidEncryptionKeyOridnal", + {"R_InvalidEncryptionKeyOrdinal", "Internal error. The referenced column encryption key ordinal \"{0}\" is missing in the encryption metadata returned by sp_describe_parameter_encryption. Max ordinal is \"{1}\"."}, {"R_MissingParamEncryptionMetadata", "Internal error. Metadata for some parameters in statement or procedure \"{0}\" is missing in the resultset returned by sp_describe_parameter_encryption."}, diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index 8e7b76741..018f9660c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -251,7 +251,7 @@ private ArrayList describeParameterEncryption(SQLServerConnection connec // cekEntry will be null if none of the parameters are encrypted. if ((null != cekEntry) && (cekList.size() < cekOrdinal)) { MessageFormat form = new MessageFormat( - SQLServerException.getErrString("R_InvalidEncryptionKeyOridnal")); + SQLServerException.getErrString("R_InvalidEncryptionKeyOrdinal")); Object[] msgArgs = {cekOrdinal, cekEntry.getSize()}; throw new SQLServerException(this, form.format(msgArgs), null, 0, false); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index b915b9f4b..defcdbc89 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -163,18 +163,6 @@ public static void setUpConnection() throws TestAbortedException, Exception { String windowsKeyPath = TestUtils.getConfiguredProperty("windowsKeyPath"); String javaKeyPath = TestUtils.getCurrentClassPath() + Constants.JKS_NAME; - /* - String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); - if (null != enclaveAttestationUrl) { - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", - enclaveAttestationUrl); - } - String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); - if (null != enclaveAttestationProtocol) { - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, - "enclaveAttestationProtocol", enclaveAttestationProtocol); - } -*/ if (null == applicationClientID || null == applicationKey || null == keyID || (isWindows && null == windowsKeyPath)) { fail(TestResource.getResource("R_reqExternalSetup")); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java index 44bc5f841..11621d75c 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/PrecisionScaleTest.java @@ -84,8 +84,7 @@ public void testNumericPrecision8Scale2() throws Exception { createPrecisionTable(NUMERIC_TABLE_AE, numericPrecisionTable, cekJks, 30, 8, 2); - populateNumericNormalCase(numeric, 8, 2); - populateNumericSetObject(numeric, 8, 2); + populateNumeric(numeric, 8, 2); testNumeric(numeric); } @@ -104,8 +103,7 @@ public void testDateScale2() throws Exception { dateTimeOffsetExpectedValue + ".177 +00:01", GMTDateWithoutDate, GMTDateWithoutDate,}; createScaleTable(DATE_TABLE_AE, datePrecisionTable, cekJks, 2); - populateDateNormalCase(2); - populateDateSetObject(2); + populateDate(2); testDate(dateNormalCase, dateSetObject); } @@ -121,8 +119,7 @@ public void testNumericPrecision8Scale0() throws Exception { createPrecisionTable(NUMERIC_TABLE_AE, numericPrecisionTable, cekJks, 30, 8, 0); - populateNumericNormalCase(numeric2, 8, 0); - populateNumericSetObject(numeric2, 8, 0); + populateNumeric(numeric2, 8, 0); testNumeric(numeric2); } @@ -142,8 +139,7 @@ public void testDateScale0() throws Exception { createScaleTable(DATE_TABLE_AE, datePrecisionTable, cekJks, 0); - populateDateNormalCase(0); - populateDateSetObject(0); + populateDate(0); testDate(dateNormalCase2, dateSetObject2); } @@ -381,7 +377,7 @@ private void testGetDate(ResultSet rs, int numberOfColumns, String[] dates) thro } } - private void populateDateNormalCase(int scale) throws SQLException { + private void populateDate(int scale) throws SQLException { String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; @@ -389,6 +385,7 @@ private void populateDateNormalCase(int scale) throws SQLException { SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { + // add a normal row // datetime2 scale for (int i = 1; i <= 3; i++) { pstmt.setTimestamp(i, new Timestamp(date.getTime()), scale); @@ -420,7 +417,43 @@ private void populateDateNormalCase(int scale) throws SQLException { pstmt.setTime(i, new Time(date.getTime())); } - pstmt.execute(); + pstmt.addBatch(); + + // add a row using setObjecdt + // datetime2 scale + for (int i = 1; i <= 3; i++) { + pstmt.setObject(i, new Timestamp(date.getTime()), java.sql.Types.TIMESTAMP, scale); + } + + // datetime2 default + for (int i = 4; i <= 6; i++) { + pstmt.setObject(i, new Timestamp(date.getTime()), java.sql.Types.TIMESTAMP); + } + + // datetimeoffset scale + for (int i = 7; i <= 9; i++) { + pstmt.setObject(i, microsoft.sql.DateTimeOffset.valueOf(new Timestamp(date.getTime()), 1), + microsoft.sql.Types.DATETIMEOFFSET, scale); + } + + // datetimeoffset default + for (int i = 10; i <= 12; i++) { + pstmt.setObject(i, microsoft.sql.DateTimeOffset.valueOf(new Timestamp(date.getTime()), 1), + microsoft.sql.Types.DATETIMEOFFSET); + } + + // time scale + for (int i = 13; i <= 15; i++) { + pstmt.setObject(i, new Time(date.getTime()), java.sql.Types.TIME, scale); + } + + // time default + for (int i = 16; i <= 18; i++) { + pstmt.setObject(i, new Time(date.getTime()), java.sql.Types.TIME); + } + + pstmt.addBatch(); + pstmt.executeBatch(); } } @@ -462,18 +495,19 @@ private void populateDateNormalCaseNull(int scale) throws SQLException { pstmt.setTime(i, null); } - pstmt.execute(); + pstmt.addBatch(); + pstmt.executeBatch(); } } - private void populateNumericNormalCase(String[] numeric, int precision, int scale) throws SQLException { + private void populateNumeric(String[] numeric, int precision, int scale) throws SQLException { String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," + "?,?,?," + "?,?,?" + ")"; - try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, stmtColEncSetting)) { + // add a normal row // float(30) for (int i = 1; i <= 3; i++) { pstmt.setDouble(i, Double.valueOf(numeric[0])); @@ -488,23 +522,26 @@ private void populateNumericNormalCase(String[] numeric, int precision, int scal for (int i = 7; i <= 9; i++) { pstmt.setBigDecimal(i, new BigDecimal(numeric[2]), precision, scale); } + pstmt.addBatch(); + for (int i = 1; i <= 3; i++) { + pstmt.setDouble(i, Double.valueOf(numeric[0])); + } - pstmt.execute(); - } - } - - private void populateNumericSetObject(String[] numeric, int precision, int scale) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(NUMERIC_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?" + ")"; + // decimal(10,5) + for (int i = 4; i <= 6; i++) { + pstmt.setBigDecimal(i, new BigDecimal(numeric[1]), precision, scale); + } - try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); - SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, - stmtColEncSetting)) { + // numeric(8,2) + for (int i = 7; i <= 9; i++) { + pstmt.setBigDecimal(i, new BigDecimal(numeric[2]), precision, scale); + } + pstmt.addBatch(); + // add row using setObject // float(30) for (int i = 1; i <= 3; i++) { pstmt.setObject(i, Double.valueOf(numeric[0])); - } // decimal(10,5) @@ -516,8 +553,8 @@ private void populateNumericSetObject(String[] numeric, int precision, int scale for (int i = 7; i <= 9; i++) { pstmt.setObject(i, new BigDecimal(numeric[2]), java.sql.Types.NUMERIC, precision, scale); } - - pstmt.execute(); + pstmt.addBatch(); + pstmt.executeBatch(); } } @@ -532,7 +569,6 @@ private void populateNumericSetObjectNull(int precision, int scale) throws SQLEx // float(30) for (int i = 1; i <= 3; i++) { pstmt.setObject(i, null, java.sql.Types.DOUBLE); - } // decimal(10,5) @@ -545,51 +581,8 @@ private void populateNumericSetObjectNull(int precision, int scale) throws SQLEx pstmt.setObject(i, null, java.sql.Types.NUMERIC, precision, scale); } - pstmt.execute(); - } - } - - private void populateDateSetObject(int scale) throws SQLException { - String sql = "insert into " + AbstractSQLGenerator.escapeIdentifier(DATE_TABLE_AE) + " values( " + "?,?,?," - + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?," + "?,?,?" + ")"; - - try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); - SQLServerPreparedStatement pstmt = (SQLServerPreparedStatement) TestUtils.getPreparedStmt(con, sql, - stmtColEncSetting)) { - - // datetime2 scale - for (int i = 1; i <= 3; i++) { - pstmt.setObject(i, new Timestamp(date.getTime()), java.sql.Types.TIMESTAMP, scale); - } - - // datetime2 default - for (int i = 4; i <= 6; i++) { - pstmt.setObject(i, new Timestamp(date.getTime()), java.sql.Types.TIMESTAMP); - } - - // datetimeoffset scale - for (int i = 7; i <= 9; i++) { - pstmt.setObject(i, microsoft.sql.DateTimeOffset.valueOf(new Timestamp(date.getTime()), 1), - microsoft.sql.Types.DATETIMEOFFSET, scale); - } - - // datetimeoffset default - for (int i = 10; i <= 12; i++) { - pstmt.setObject(i, microsoft.sql.DateTimeOffset.valueOf(new Timestamp(date.getTime()), 1), - microsoft.sql.Types.DATETIMEOFFSET); - } - - // time scale - for (int i = 13; i <= 15; i++) { - pstmt.setObject(i, new Time(date.getTime()), java.sql.Types.TIME, scale); - } - - // time default - for (int i = 16; i <= 18; i++) { - pstmt.setObject(i, new Time(date.getTime()), java.sql.Types.TIME); - } - - pstmt.execute(); + pstmt.addBatch(); + pstmt.executeBatch(); } } @@ -631,7 +624,8 @@ private void populateDateSetObjectNull(int scale) throws SQLException { pstmt.setObject(i, null, java.sql.Types.TIME); } - pstmt.execute(); + pstmt.addBatch(); + pstmt.executeBatch(); } } } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/RegressionAlwaysEncryptedTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/RegressionAlwaysEncryptedTest.java index 8e8d1100c..1863c1802 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/RegressionAlwaysEncryptedTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/RegressionAlwaysEncryptedTest.java @@ -42,7 +42,7 @@ public class RegressionAlwaysEncryptedTest extends AESetup { @Test public void alwaysEncrypted1() throws SQLException { try (Connection connection = PrepUtil.getConnection( - connectionString + ";trustservercertificate=true;columnEncryptionSetting=enabled;", AEInfo); + AETestConnectionString + ";trustservercertificate=true;columnEncryptionSetting=enabled;", AEInfo); Statement stmt = connection.createStatement()) { dropTables(stmt); @@ -70,7 +70,7 @@ public void alwaysEncrypted1() throws SQLException { @Test public void alwaysEncrypted2() throws SQLException { try (Connection connection = PrepUtil.getConnection( - connectionString + ";trustservercertificate=true;columnEncryptionSetting=enabled;", AEInfo); + AETestConnectionString + ";trustservercertificate=true;columnEncryptionSetting=enabled;", AEInfo); Statement stmt = connection.createStatement()) { dropTables(stmt); From 12bceac5afe534420e8b51c25b535449b396ebd3 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 30 Oct 2019 17:04:47 -0700 Subject: [PATCH 39/49] more tests --- .../sqlserver/jdbc/SQLServerResource.java | 2 + .../jdbc/SQLServerVSMEnclaveProvider.java | 84 ++++---- .../com/microsoft/sqlserver/jdbc/AETest.java | 179 ++++++++++++++++++ .../jdbc/AlwaysEncrypted/AESetup.java | 15 +- 4 files changed, 241 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 5d6cb1f57..4cfed4243 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -613,6 +613,8 @@ protected Object[][] getContents() { "More bytes from the server were received than expected when parsing Enclave PK."}, {"R_MalformedECDHPublicKey", "The ECDH public key from the server must be 104 bits in length."}, {"R_MalformedECDHHeader", "Unexpected values for ECDH public key header from the server."}, + {"R_HealthCertError", + " Enclave Attestation failed, could not retrieve health report certificate provided in the enclave: {0}."}, {"R_InvalidHealthCert", " Enclave Attestation failed, the health report certificate provided in the enclave was not signed by the HGS."}, {"R_InvalidSignedStatement", diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index 018f9660c..0af89d269 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -433,61 +433,69 @@ class AttestationResponse { * DH Public Key - DHPKsize bytes * DH Public Key Signature - DHPKSsize bytes */ - ByteBuffer response = ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN); - this.totalSize = response.getInt(); - this.identitySize = response.getInt(); - this.healthReportSize = response.getInt(); - this.enclaveReportSize = response.getInt(); - - enclavePK = new byte[identitySize]; - healthReportCertificate = new byte[healthReportSize]; - enclaveReportPackage = new byte[enclaveReportSize]; - - response.get(enclavePK, 0, identitySize); - response.get(healthReportCertificate, 0, healthReportSize); - response.get(enclaveReportPackage, 0, enclaveReportSize); - - this.sessionInfoSize = response.getInt(); - response.get(sessionID, 0, 8); - this.DHPKsize = response.getInt(); - this.DHPKSsize = response.getInt(); - - DHpublicKey = new byte[DHPKsize]; - publicKeySig = new byte[DHPKSsize]; - - response.get(DHpublicKey, 0, DHPKsize); - response.get(publicKeySig, 0, DHPKSsize); + ByteBuffer response = (null != b) ? ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN) : null; + if (null != response) { + this.totalSize = response.getInt(); + this.identitySize = response.getInt(); + this.healthReportSize = response.getInt(); + this.enclaveReportSize = response.getInt(); + + enclavePK = new byte[identitySize]; + healthReportCertificate = new byte[healthReportSize]; + enclaveReportPackage = new byte[enclaveReportSize]; + + response.get(enclavePK, 0, identitySize); + response.get(healthReportCertificate, 0, healthReportSize); + response.get(enclaveReportPackage, 0, enclaveReportSize); + + this.sessionInfoSize = response.getInt(); + response.get(sessionID, 0, 8); + this.DHPKsize = response.getInt(); + this.DHPKSsize = response.getInt(); + + DHpublicKey = new byte[DHPKsize]; + publicKeySig = new byte[DHPKSsize]; + + response.get(DHpublicKey, 0, DHPKsize); + response.get(publicKeySig, 0, DHPKSsize); + } - if (0 != response.remaining()) { + if (null == response || 0 != response.remaining()) { SQLServerException.makeFromDriverError(null, this, SQLServerResource.getResource("R_EnclaveResponseLengthError"), "0", false); } + // Create a X.509 certificate from the bytes try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); healthCert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(healthReportCertificate)); } catch (CertificateException ce) { - SQLServerException.makeFromDriverError(null, this, ce.getLocalizedMessage(), "0", false); + MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_HealthCertError")); + Object[] msgArgs = {ce.getLocalizedMessage()}; + SQLServerException.makeFromDriverError(null, null, form.format(msgArgs), null, true); } } @SuppressWarnings("unchecked") void validateCert(byte[] b) throws SQLServerException { - try { - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Collection certs = (Collection) cf - .generateCertificates(new ByteArrayInputStream(b)); - for (X509Certificate cert : certs) { - try { - healthCert.verify(cert.getPublicKey()); - return; - } catch (SignatureException e) { - // Doesn't match, but continue looping through the rest of the certificates + if (null != b) { + try { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Collection certs = (Collection) cf + .generateCertificates(new ByteArrayInputStream(b)); + for (X509Certificate cert : certs) { + try { + healthCert.verify(cert.getPublicKey()); + return; + } catch (SignatureException e) { + // Doesn't match, but continue looping through the rest of the certificates + } } + } catch (GeneralSecurityException e) { + SQLServerException.makeFromDriverError(null, this, e.getLocalizedMessage(), "0", false); } - } catch (GeneralSecurityException e) { - SQLServerException.makeFromDriverError(null, this, e.getLocalizedMessage(), "0", false); } + SQLServerException.makeFromDriverError(null, this, SQLServerResource.getResource("R_InvalidHealthCert"), "0", false); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java index cf718dc91..2b10fb9c4 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import java.security.cert.CertificateException; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -37,6 +38,148 @@ public class AETest extends AbstractTest { private static String connectionStringAE; + private byte[] healthReportCertificate = {61, 11, 0, 0, 27, 2, 0, 0, -66, 3, 0, 0, 88, 5, 0, 0, 82, 83, 65, 49, 0, + 16, 0, 0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -57, 59, -80, 116, -86, -109, -4, -96, + -106, -85, 107, 22, 88, 29, 91, -50, 29, -44, -36, -109, -123, 57, 70, -41, 110, -85, 90, 49, -17, 100, -49, + 96, -34, 89, -76, -59, -82, 100, 118, -9, 44, 86, -112, 44, 13, 36, -43, 3, -69, -46, -6, -126, 26, -74, 75, + -89, 82, -111, 72, -1, 127, 78, -80, 102, -126, 51, -89, 12, 70, 107, 50, 126, -40, -6, 51, 13, 87, 5, 79, + -53, -66, 26, 126, -128, -82, 97, 103, 7, 62, 49, -66, -97, -115, 113, -88, -73, 127, 102, -21, -51, 79, 8, + 101, -76, 15, -29, 0, -83, -42, -12, 52, 106, -60, 62, -67, 5, -7, -91, -21, -60, 4, -52, -39, 59, -100, + 127, 5, -55, 93, 9, 89, 83, 14, 85, -9, -33, -5, 75, 42, -81, 123, -117, -73, -50, 15, 59, -35, -35, -74, + -113, 41, -74, -41, 51, -3, 88, 110, 44, 3, -31, -36, 94, 29, 82, 12, -119, -34, 72, -51, 59, -109, -92, 44, + 24, 75, 78, 84, 64, -86, -43, 11, 23, 70, 124, 33, -90, 60, -85, -63, -23, -70, 79, 62, 13, -121, -45, 53, + 107, -49, 104, -85, -80, 7, -84, 61, -93, 44, -87, -68, -101, -7, -43, -65, 90, -12, -12, 16, 104, 26, 5, + -103, -32, -84, -80, -26, 17, -29, 30, -46, 127, 44, -70, -87, 61, -35, 47, -62, 86, -23, 114, 0, -19, 38, + -25, 90, -6, -1, -121, -69, 51, 74, -95, 64, -67, 6, 49, 35, -125, -5, -40, -115, 1, -31, -51, 64, -102, + -51, 106, 111, 38, 124, -111, 25, -75, 7, -116, -111, -120, 82, 103, 112, 14, 32, -49, -87, 23, 31, -14, + -107, -64, -76, 9, -40, -37, 127, -99, 67, -114, 114, -3, -62, 7, -88, 103, -89, 124, 125, -14, -21, 59, 91, + 112, 13, 35, -80, -103, -79, 6, 41, -110, 8, -15, -58, 95, -101, 43, -8, 106, -50, -87, -32, 93, -30, -31, + -105, 69, -73, 57, -38, 75, 42, 120, -75, -49, 77, 76, -120, -14, -42, -44, -34, 8, -4, -98, -35, 46, -23, + 16, -83, -6, 115, -127, 117, 54, -25, 58, -106, 10, 85, 54, -105, 48, 62, -55, 70, 56, 115, -121, 31, -4, + 113, 21, -98, 53, 118, 31, -82, 122, -29, 41, 59, -112, -123, -114, -26, 54, -45, 106, 77, 79, 2, -63, -37, + 53, 42, -26, -24, -60, 88, -80, 22, 55, -37, -114, 99, -58, 113, 87, 26, -70, 105, -70, -78, -48, 26, 51, + 10, -37, -105, 66, 3, -69, 38, -56, 34, 77, -98, 56, 15, 0, 85, -63, -67, -102, -116, -49, -85, 22, -70, 68, + -31, 99, 23, -100, -33, -45, -49, -90, 104, -26, -5, -32, 100, 81, -117, -60, -7, -59, 84, -8, -101, 86, 88, + -100, 107, -65, -11, -5, 41, 96, -76, 24, 68, -105, -18, -99, -10, -15, 26, -43, 91, -86, 33, -17, -19, -6, + -89, 78, -123, 48, 47, -107, 36, -2, -33, 123, -124, 91, 123, -20, -88, 73, 48, -126, 3, -70, 48, -126, 2, + -94, -96, 3, 2, 1, 2, 2, 16, 66, 85, -66, 31, 39, 20, 120, -95, 75, 114, 74, -14, 59, 52, 99, -29, 48, 13, + 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 48, 47, 49, 45, 48, 43, 6, 3, 85, 4, 3, 12, 36, 77, 105, + 99, 114, 111, 115, 111, 102, 116, 32, 82, 101, 109, 111, 116, 101, 32, 65, 116, 116, 101, 115, 116, 97, 116, + 105, 111, 110, 32, 83, 101, 114, 118, 105, 99, 101, 48, 30, 23, 13, 49, 57, 49, 48, 51, 48, 49, 56, 50, 50, + 52, 55, 90, 23, 13, 49, 57, 49, 48, 51, 49, 48, 50, 50, 50, 52, 56, 90, 48, 75, 49, 73, 48, 71, 6, 3, 85, 4, + 3, 12, 64, 65, 49, 57, 67, 49, 56, 70, 51, 50, 53, 49, 56, 66, 56, 65, 57, 51, 70, 49, 57, 52, 57, 69, 66, + 57, 69, 56, 53, 48, 68, 56, 53, 66, 66, 53, 53, 65, 67, 69, 65, 49, 56, 67, 53, 54, 55, 49, 70, 55, 55, 65, + 69, 49, 54, 51, 54, 56, 52, 51, 55, 68, 65, 53, 56, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, + 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -50, -20, -124, 102, 67, -52, 79, + -43, 5, -104, 31, 99, -89, 53, -77, 61, 82, 64, -125, -30, 32, 102, 101, -87, 63, -75, -10, -100, -31, -125, + 15, -9, -40, 81, 8, 54, -43, 112, 91, -19, 126, 49, -57, 33, -51, -33, -82, 21, 22, 4, -68, 112, 83, -55, + -50, 60, -70, 1, -37, -60, 3, -75, 63, 124, -3, -112, 107, -120, -122, -97, 26, -28, 62, -101, -21, -66, 28, + -84, 23, 21, -126, 27, -9, 45, 43, 50, 1, -117, 28, -114, -99, -38, 38, -104, 7, -45, 85, -100, -44, -102, + 68, -6, -22, -45, -75, 84, -33, -11, -76, -9, 42, -1, 82, -21, -12, 18, -15, 118, -121, 124, 103, -85, 43, + 54, -106, 77, 102, 0, -107, -12, 103, 10, 118, -85, 23, 40, -61, -39, 76, 39, -124, 75, -121, -114, -65, + -119, -42, -75, 42, -110, -71, 94, 61, -125, 104, 105, -119, 74, -83, 57, -11, -38, -120, -94, -100, -58, + -85, 106, 124, 50, 30, 118, -102, 1, -123, -119, -81, 111, 6, 18, -114, 61, -35, 64, 99, -53, 16, -56, -8, + -18, -110, 96, -85, 125, 95, 60, 0, -58, -81, -30, 54, 39, 73, 100, -27, 14, 5, -45, 122, 120, -33, -48, + -62, -43, 98, 9, -5, -12, 4, -6, -57, -113, -28, 117, -26, 50, 76, 65, -107, 109, 49, -9, -22, 86, 103, 68, + -128, -87, -116, 25, -117, 114, 28, -9, 28, 70, -28, -36, 102, -27, 40, 120, 60, -113, -11, -73, 2, 3, 1, 0, + 1, -93, -127, -75, 48, -127, -78, 48, 14, 6, 3, 85, 29, 15, 1, 1, -1, 4, 4, 3, 2, 7, -128, 48, 29, 6, 9, 43, + 6, 1, 4, 1, -126, 55, 21, 10, 4, 16, 48, 14, 48, 12, 6, 10, 43, 6, 1, 4, 1, -126, 55, 48, 1, 2, 48, 25, 6, + 3, 85, 29, 14, 4, 18, 4, 16, 49, 110, 105, 97, 22, -114, 85, -99, 21, -32, -60, -109, 42, -59, 66, 11, 48, + 102, 6, 3, 85, 29, 35, 4, 95, 48, 93, -128, 20, 37, -118, -59, 87, -8, 105, 88, 79, -36, 20, -127, -8, -56, + -9, 97, -10, 105, -80, -109, -93, -95, 51, -92, 49, 48, 47, 49, 45, 48, 43, 6, 3, 85, 4, 3, 12, 36, 77, 105, + 99, 114, 111, 115, 111, 102, 116, 32, 82, 101, 109, 111, 116, 101, 32, 65, 116, 116, 101, 115, 116, 97, 116, + 105, 111, 110, 32, 83, 101, 114, 118, 105, 99, 101, -126, 16, 37, 113, -89, -86, -71, 42, -44, -83, 67, -30, + 8, -31, 97, 14, -40, -12, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 3, -126, 1, 1, 0, -85, + -56, -125, -91, 83, -96, -32, -69, -69, -40, -127, -93, 69, 24, -7, -121, 54, 30, 76, 20, 28, -95, 93, -76, + -109, -4, -97, -102, 126, 76, -68, -39, 6, -66, 70, -100, 67, -112, 25, -109, -2, -83, 40, 86, 69, -70, + -105, 40, 88, 109, -101, 64, 95, -60, -49, -25, -42, 61, -37, 18, -3, -64, -68, -123, 111, 7, 119, 107, 81, + 40, -103, 66, 42, 110, 81, 95, -38, 104, 109, -92, -90, 6, -120, -113, 53, -8, -116, -44, -90, -3, 103, 100, + 78, 90, 96, -121, 80, -105, 109, 28, -28, -63, 75, 14, -98, 83, -122, 78, -70, 83, 4, 11, -107, 115, 50, 78, + -37, -88, 62, -72, 4, 26, 6, 102, -65, -39, -48, 58, -72, 36, 125, 29, -27, -6, -42, 111, 57, -97, 102, 3, + -5, 112, 62, -13, -65, -4, 40, -103, 19, -75, 82, -83, -26, -12, 62, -41, -38, -70, -85, 22, 100, 34, 0, 90, + 68, -33, -107, 40, -63, -9, 38, 99, -89, 15, 118, 14, -33, -2, -18, -98, -105, 23, 31, 92, -46, -68, -61, + 103, 47, -121, 73, -8, -82, -28, 43, 0, 50, 78, 78, 68, 88, -91, 121, -29, 30, -25, 23, 88, 43, -72, -49, + -77, 92, -62, -8, 85, -86, -111, 99, -37, -46, -121, 34, 122, 118, 9, -27, 57, -56, 59, 44, 62, -115, -41, + -49, -73, -59, 122, 39, -69, 76, 122, 127, -21, 113, 43, -21, -109, 95, 98, 38, 33, 111, -34, -38, 71, 88, + 5, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 64, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 64, 4, 0, 0, 1, 0, 0, 0, 14, 60, -81, + -73, 81, 79, 109, 37, -78, -54, -47, -115, 69, -20, -28, -70, -75, 43, 5, -75, -42, 70, -27, 53, -124, -35, + 61, 45, -90, -38, 41, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 16, 32, 48, 64, 65, 49, 33, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -108, -76, 101, 116, -38, -69, -79, 113, -122, -19, -59, 38, 60, -76, -34, 123, -10, -39, -30, + -21, -122, -122, 34, 32, 90, -108, -45, -109, -44, -52, 101, -127, 4, 55, -54, -30, 83, 125, -117, -101, 7, + 118, -74, 27, 17, -26, -50, -45, -46, 50, -23, 48, -113, 96, -30, 26, -38, -78, -3, -111, -29, -38, -107, + -104, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 23, 18, 0, 1, 5, 32, 19, 0, 5, 20, 3, 18, 1, 34, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -112, 0, 0, 0, -108, + -76, 101, 116, -38, -69, -79, 113, -122, -19, -59, 38, 60, -76, -34, 123, -10, -39, -30, -21, -122, -122, + 34, 32, 90, -108, -45, -109, -44, -52, 101, -127, 4, 55, -54, -30, 83, 125, -117, -101, 7, 118, -74, 27, 17, + -26, -50, -45, -46, 50, -23, 48, -113, 96, -30, 26, -38, -78, -3, -111, -29, -38, -107, -104, -2, -2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 23, 18, 0, 1, 5, 32, 19, 0, 5, 20, 3, 18, 1, 34, 5, 0, 0, 0, 0, 97, + 0, 101, 0, 116, 0, 109, 0, 45, 0, 101, 0, 110, 0, 99, 0, 108, 0, 97, 0, 118, 0, 101, 0, 46, 0, 100, 0, 108, + 0, 108, 0, 0, 0, 0, 0, 1, 0, 0, 0, -120, 0, 0, 0, 90, -58, -49, 7, 59, -65, 81, -44, -97, -107, 97, -106, + 71, -70, 33, -5, 99, -7, -4, -117, -31, -91, -35, -56, -12, -105, -29, 80, 5, 72, 3, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 32, 39, -67, 104, 117, 89, 73, -73, -66, 6, 52, 80, -30, 22, -41, -19, 0, 0, 0, 0, 98, 0, 99, + 0, 114, 0, 121, 0, 112, 0, 116, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -104, + 0, 0, 0, -76, 15, 80, 111, -51, 57, 8, -54, -53, -109, -113, -106, 35, -72, -114, -12, -128, -17, 51, -64, + -124, -38, -55, 27, 1, 80, 69, 48, -96, -77, -128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -16, 60, -51, -89, + -24, 123, 70, -21, -86, -25, 31, 19, -43, -51, -34, 93, 0, 0, 0, 0, 117, 0, 99, 0, 114, 0, 116, 0, 98, 0, + 97, 0, 115, 0, 101, 0, 95, 0, 101, 0, 110, 0, 99, 0, 108, 0, 97, 0, 118, 0, 101, 0, 46, 0, 100, 0, 108, 0, + 108, 0, 0, 0, 0, 0, 1, 0, 0, 0, -120, 0, 0, 0, -41, 110, -101, -107, 45, -49, 11, 25, -47, 17, 90, 38, -28, + 105, -88, 110, 39, -35, -15, -94, -106, 14, -37, -70, -105, -14, 59, -88, 80, 30, -112, -91, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 114, -124, 65, 114, 103, -88, 78, -115, -65, 1, 40, 75, 7, 67, 43, 30, 0, 0, 0, 0, 118, + 0, 101, 0, 114, 0, 116, 0, 100, 0, 108, 0, 108, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, -112, 0, 0, 0, 20, -54, 74, 74, 43, -64, -12, 60, -101, -67, -58, -102, 71, -124, 113, -46, 92, -63, 11, + -104, 100, -6, -126, 9, 3, 16, -36, 57, 24, -22, 8, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 122, 0, 117, 0, 114, 0, 101, 0, 65, 0, 116, 0, 116, 0, + 101, 0, 115, 0, 116, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -104, 0, 0, 0, -54, 68, + -119, -29, 65, -104, -2, 53, -48, -27, -20, 25, 8, -72, -43, 124, -63, 9, 126, -58, -100, 14, -41, -75, 61, + -66, -28, 80, 67, 17, -109, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 19, -65, 62, 83, 100, 65, 48, -86, + -102, -64, -14, -31, -12, -58, 36, 0, 0, 0, 0, 98, 0, 99, 0, 114, 0, 121, 0, 112, 0, 116, 0, 80, 0, 114, 0, + 105, 0, 109, 0, 105, 0, 116, 0, 105, 0, 118, 0, 101, 0, 115, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, + -107, 11, 37, -57, 57, -18, -111, 70, 53, -83, -117, 111, -63, 65, -80, -4, -3, -36, 27, 35, 111, -91, 54, + -34, 103, 41, -5, -79, 8, -36, -124, 101, 103, 90, -115, -21, 40, 49, 33, 61, 85, -104, 67, 5, -26, -78, + -27, -78, -92, -70, 115, -77, -98, 39, -101, 58, 35, -21, -51, 83, -4, 80, 125, 39, -117, -75, 50, -71, 125, + -44, 28, 41, 25, 67, -4, 3, -120, -89, -124, -19, 94, -81, 31, 114, -91, 117, -9, 6, 85, 32, 16, -16, -28, + 59, 108, 67, -77, -126, 42, 25, 7, -46, 40, -32, 52, 51, -60, 120, 28, 1, 89, -1, 51, -96, 105, 93, -111, + -8, -25, 9, 55, -120, 37, -63, -6, -66, 11, -16, -34, -71, -18, 67, -74, 86, -98, -15, -56, -76, 86, 10, -6, + 13, -9, 24, -9, -94, -93, 127, -63, -69, 86, -73, -57, 91, -108, -11, 70, 77, -80, -39, 70, -14, -61, 39, + -45, -83, 46, 17, 126, -104, 10, -117, 46, -60, -122, 12, 20, -117, 30, 105, -80, -67, -48, -4, -57, -98, + 95, 102, -85, 36, 29, -61, -93, -91, 67, -61, 76, -54, -60, 77, 95, -79, -126, -66, 110, -32, -8, -45, -108, + 42, -101, 102, -99, 104, -33, 74, -43, -124, -47, 81, -58, 118, 112, -80, -9, 2, -40, 77, 40, 122, 16, 48, + 111, -98, 78, 80, -122, 99, -29, -125, -78, -104, -36, -94, -95, -115, -110, 31, -108, -46, 88, 79, -103, + -65, 90, -13, 120, 2, 0, 0, 19, 0, 0, 0, 75, 1, 0, 0, 104, 0, 0, 0, 0, 2, 0, 0, 69, 67, 75, 51, 48, 0, 0, 0, + 38, -81, -37, -121, 34, 74, 31, -103, -95, 62, 72, -29, 19, -105, -124, -112, 71, 6, 64, 98, -73, -85, -49, + -21, -63, -67, -69, 2, 56, 36, 116, -49, -24, -123, 24, 43, 69, -62, -126, -94, 80, 113, 114, 60, -44, -48, + -44, -83, -13, -104, -69, 57, -26, 41, 65, -15, 97, -65, 26, -41, 32, -125, -50, 52, -18, 15, -91, 98, -4, + -52, 88, -34, -61, -32, 126, -40, 63, 2, 113, -11, 92, 69, 3, -118, -52, 50, -30, 52, -105, -36, -95, -18, + 17, 99, 107, -105, 17, -104, -125, 34, 11, -44, 7, 79, 35, 24, -2, -27, -43, -21, 115, 52, 44, -45, -68, + -122, 100, -55, -79, 14, -79, 81, 49, 81, -3, -43, -89, -118, 116, 76, 13, -117, 16, -1, 46, -62, 40, 21, + 97, 63, 43, -65, 45, 101, 30, 2, 66, 15, -20, -53, -112, 23, 120, -12, -31, -79, -33, 89, -83, 95, -110, + -67, -58, -86, 118, 28, 84, 22, 79, -69, -41, -78, 88, 31, 73, 97, 71, -109, -127, -22, 14, 113, -65, 51, + 11, 34, -23, -61, 107, 114, -109, 58, 9, 104, 120, -36, -93, 70, 104, -79, -46, 13, -15, -62, -61, -62, -16, + 19, -79, 4, 121, -63, 61, -100, -66, 25, -23, 117, -119, -97, -84, 15, 99, -101, 59, -18, -81, -67, -99, + -20, -82, -41, 74, -19, -54, -86, -58, 121, -7, -8, -8, 11, 113, -52, -50, 14, -102, -77, -105, 126, -110, + 85, -97, 75, -24, -33, -63, 48, 79, 67, 84, 73, 54, 49, -104, 38, 13, -100, 76, 66, 86, 72, -120, 100, 33, + -5, -26, 107, 79, -48, -1, 71, 104, 22, 115, 66, -94, 73, 88, -48, 71, 44, 118, 15, -76, -98, -74, -78, 43, + 33, 120, -74, -87, 78, 31, 36, 96, -104, -98, -28, 121, -128, -8, -77, -16, -74, -94, -101, -57, 99, -78, + 70, 108, -26, 115, 21, -13, -41, 46, -93, -68, 29, 76, 68, 109, -63, 108, 27, -112, -20, -53, 92, 109, 121, + 33, 64, 69, 42, -72, -45, 35, 50, 60, -124, -99, -40, -7, -96, -57, -14, -71, -103, -44, 13, 69, -89, -17, + -46, -128, -5, -83, 80, -125, 13, -48, -126, 49, 62, 37, 113, -92, -30, 15, 47, 113, 124, 108, -89, -48, -4, + -84, -61, -11, -55, -97, -28, 36, 20, -106, 57, -16, 107, 51, 67, -95, -73, -76, -8, -118, 97, 127, -20, 67, + 103, 25, 3, -67, 41, 73, 122, 92, -9, 22, 69, -91, -107, 52, -23, -119, -56, 71, -76, 77, -51, 12, -72, 117, + -48, 108, -100, -77, -103, 114, 45, 100, 100, -11, 55, 124, -121, -102, -105, 22, 4, -33, 76, 68, 116, -96, + -80, 43, 5, -119, -113, 44, 66, -128, -104, 60, -78, -123, 56, -36, -99, -63, 71, 25, -15, 17, -8, -71, -8, + -37, 92, 70, 127, 33, 69, -34, 11, -9, 38, 127, -46, -10, 112, 126, -7, -77, 16, -32, -42, 118, -110, 98, + -112, 78, -95, 56, -45, -46, -108, -54, 116, 99, 107, 78, -92, -60, 72, -45, -40, 33, -93, -21, -90, -108, + -19, 89, -42, 29, -123, 35, -114, -95, -37, 2, -61, 12, 84, -100, -100, 112, -96, 80, 12, 90, 78, 36, 40, + -56, -90, -60, -77, -77, -56, 53, -93, -10, -22, -47, 15, 5, -90, -67, 111, -82, -94, 96, -68, -79, -3, -51, + -108, 41, 112, -89, 22, -92, 88, 37, 66, 20, 93, 111, 102, -69, -20, -47, -43, -24, 82, -41, 12, -58, 53, + 68, -76, -94, -116, 75, 14, 24, -43, 73, -78, -87, 21}; + /** * Setup environment for test. * @@ -185,6 +328,42 @@ public void testBadSessionSecret() throws SQLServerException { } } + @Test + public void testNullAttestationResponse() throws SQLServerException { + try { + AttestationResponse resp = new AttestationResponse(null); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_EnclaveResponseLengthError"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + @Test + public void testBadAttestationResponse() throws SQLServerException { + try { + byte[] responseBytes = new byte[36]; + AttestationResponse resp = new AttestationResponse(responseBytes); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_HealthCertError"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + @Test + public void testBadCertSignature() throws SQLServerException, CertificateException { + try { + AttestationResponse resp = new AttestationResponse(healthReportCertificate); + resp.validateCert(null); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidHealthCert"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + + } + /* * Test invalid properties */ diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index defcdbc89..80a951b04 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -227,7 +227,6 @@ public static void setUpConnection() throws TestAbortedException, Exception { * * @throws SQLException */ - @AfterAll public static void dropAll() throws Exception { try (Statement stmt = connection.createStatement()) { dropTables(stmt); @@ -247,6 +246,20 @@ public static void dropAll() throws Exception { } } + /** + * Dropping all CMKs and CEKs and any open resources. Technically, dropAll depends on the state of the class so it + * shouldn't be static, but the AfterAll annotation requires it to be static. + * + * @throws SQLException + */ + @AfterAll + public static void cleanUp() throws Exception { + dropAll(); + if (null != connection) { + connection.close(); + } + } + /** * Read the alias from file which is created during creating jks If the jks and alias name in JavaKeyStore.txt does * not exists, will not run! From b131be5805c64743bb3180b992e4ce3eee315d5e Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 31 Oct 2019 10:00:42 -0700 Subject: [PATCH 40/49] tag --- .../com/microsoft/sqlserver/jdbc/AETest.java | 84 ++++++++++++++++++- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java index 2b10fb9c4..c4239a22c 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java @@ -1,5 +1,6 @@ package com.microsoft.sqlserver.jdbc; +import static org.junit.Assert.assertFalse; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -37,6 +38,7 @@ public class AETest extends AbstractTest { private static SQLServerDataSource dsPool = null; private static String connectionStringAE; + private static boolean isAEv2 = false; private byte[] healthReportCertificate = {61, 11, 0, 0, 27, 2, 0, 0, -66, 3, 0, 0, 88, 5, 0, 0, 82, 83, 65, 49, 0, 16, 0, 0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -57, 59, -80, 116, -86, -109, -4, -96, @@ -199,7 +201,6 @@ public static void setUp() throws Exception { connectionStringAE = TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationProtocol", (null != enclaveAttestationProtocol) ? enclaveAttestationProtocol : AttestationProtocol.HGS.toString()); - boolean isAEv2 = false; try (SQLServerConnection con = PrepUtil.getConnection(connectionStringAE)) { isAEv2 = TestUtils.isAEv2(con); } catch (SQLException e) { @@ -207,7 +208,6 @@ public static void setUp() throws Exception { } catch (Exception e) { fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); } - org.junit.Assume.assumeTrue(isAEv2); // reset logging to avoid severe logs due to negative testing LogManager.getLogManager().reset(); @@ -220,7 +220,6 @@ public static void setUp() throws Exception { dsPool = new SQLServerConnectionPoolDataSource(); AbstractTest.updateDataSource(connectionStringAE, dsPool); - } /** @@ -231,6 +230,8 @@ public static void setUp() throws Exception { */ @Test public void testBasicConnection() throws SQLException { + org.junit.Assume.assumeTrue(isAEv2); + try (Connection con1 = dsLocal.getConnection(); Connection con2 = dsXA.getConnection(); Connection con3 = dsPool.getConnection(); Connection con4 = PrepUtil.getConnection(connectionStringAE)) { @@ -254,6 +255,8 @@ public void testBasicConnection() throws SQLException { */ @Test public void testInvalidProperties() { + org.junit.Assume.assumeTrue(isAEv2); + // enclaveAttestationUrl and enclaveAttestationProtocol without "columnEncryptionSetting" testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringAE, "columnEncryptionSetting", ColumnEncryptionSetting.Disabled.toString()), "R_enclaveAEdisabled"); @@ -269,7 +272,28 @@ public void testInvalidProperties() { // bad enclaveAttestationProtocol testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationProtocol", ""), "R_enclaveInvalidAttestationProtocol"); + } + + /* + * Test calling verifyColumnMasterKeyMetadata for non enclave computation + */ + @Test + public void testVerifyColumnMasterKeyMetadata() { + try { + SQLServerColumnEncryptionJavaKeyStoreProvider jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider("keystore", + null); + assertFalse(jksp.verifyColumnMasterKeyMetadata(null, false, null)); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + try { + SQLServerColumnEncryptionAzureKeyVaultProvider aksp = new SQLServerColumnEncryptionAzureKeyVaultProvider("", + ""); + assertFalse(aksp.verifyColumnMasterKeyMetadata(null, false, null)); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } } /* @@ -277,6 +301,8 @@ public void testInvalidProperties() { */ @Test public void testGetEnclavePackage() { + org.junit.Assume.assumeTrue(isAEv2); + SQLServerVSMEnclaveProvider provider = new SQLServerVSMEnclaveProvider(); try { provider.getEnclavePackage(null, null); @@ -291,6 +317,8 @@ public void testGetEnclavePackage() { */ @Test public void testInvalidEnclaveSession() { + org.junit.Assume.assumeTrue(isAEv2); + SQLServerVSMEnclaveProvider provider = new SQLServerVSMEnclaveProvider(); provider.invalidateEnclaveSession(); if (null != provider.getEnclaveSession()) { @@ -303,6 +331,8 @@ public void testInvalidEnclaveSession() { */ @Test public void testNullSessionSecret() throws SQLServerException { + org.junit.Assume.assumeTrue(isAEv2); + VSMAttestationParameters param = new VSMAttestationParameters(); try { @@ -314,8 +344,13 @@ public void testNullSessionSecret() throws SQLServerException { } } + /* + * Test bad session secret + */ @Test public void testBadSessionSecret() throws SQLServerException { + org.junit.Assume.assumeTrue(isAEv2); + VSMAttestationParameters param = new VSMAttestationParameters(); try { @@ -328,8 +363,13 @@ public void testBadSessionSecret() throws SQLServerException { } } + /* + * Test null Attestation response + */ @Test public void testNullAttestationResponse() throws SQLServerException { + org.junit.Assume.assumeTrue(isAEv2); + try { AttestationResponse resp = new AttestationResponse(null); } catch (SQLServerException e) { @@ -339,8 +379,13 @@ public void testNullAttestationResponse() throws SQLServerException { } } + /* + * Test bad Attestation response + */ @Test public void testBadAttestationResponse() throws SQLServerException { + org.junit.Assume.assumeTrue(isAEv2); + try { byte[] responseBytes = new byte[36]; AttestationResponse resp = new AttestationResponse(responseBytes); @@ -351,8 +396,13 @@ public void testBadAttestationResponse() throws SQLServerException { } } + /* + * Test bad certificate signature + */ @Test public void testBadCertSignature() throws SQLServerException, CertificateException { + org.junit.Assume.assumeTrue(isAEv2); + try { AttestationResponse resp = new AttestationResponse(healthReportCertificate); resp.validateCert(null); @@ -361,7 +411,23 @@ public void testBadCertSignature() throws SQLServerException, CertificateExcepti } catch (Exception e) { fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } + } + + /* + * Negative Test - AEv2 not supported + */ + @Tag(Constants.xSQLv15) + @Test + public void testAEv2NotSupported() { + org.junit.Assume.assumeFalse(isAEv2); + try (SQLServerConnection con = PrepUtil.getConnection(connectionStringAE)) { + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_enclaveNotSupported"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); + } } /* @@ -386,4 +452,16 @@ private void verifyEnclaveEnabled(Connection con) throws SQLException { } } } + + private void checkAEv2() { + boolean isAEv2 = false; + try (SQLServerConnection con = PrepUtil.getConnection(connectionStringAE)) { + isAEv2 = TestUtils.isAEv2(con); + } catch (SQLException e) { + isAEv2 = false; + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); + } + org.junit.Assume.assumeTrue(isAEv2); + } } From fb460c6da2a3d2c40c61c79a69fa3befeb2a0185 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 31 Oct 2019 15:52:21 -0700 Subject: [PATCH 41/49] more tests --- .../jdbc/SQLServerVSMEnclaveProvider.java | 4 +- .../com/microsoft/sqlserver/jdbc/AETest.java | 34 ++++++++++++-- .../jdbc/AlwaysEncrypted/AESetup.java | 35 +++------------ .../sqlserver/testframework/AbstractTest.java | 45 +++++++++++++++---- 4 files changed, 74 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index 0af89d269..873ff1d5e 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -118,7 +118,7 @@ public byte[] getEnclavePackage(String userSQL, ArrayList enclaveCEKs) t SQLServerEncryptionType.Randomized, (byte) 0x1); enclavePackage.writeBytes(algo.encryptData(keys.toByteArray())); return enclavePackage.toByteArray(); - } catch (GeneralSecurityException | SQLServerException e) { + } catch (GeneralSecurityException e) { SQLServerException.makeFromDriverError(null, this, e.getLocalizedMessage(), "0", false); } } @@ -495,7 +495,7 @@ void validateCert(byte[] b) throws SQLServerException { SQLServerException.makeFromDriverError(null, this, e.getLocalizedMessage(), "0", false); } } - + SQLServerException.makeFromDriverError(null, this, SQLServerResource.getResource("R_InvalidHealthCert"), "0", false); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java index c4239a22c..26744b9df 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java @@ -10,6 +10,9 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.logging.LogManager; import org.junit.jupiter.api.BeforeAll; @@ -278,10 +281,10 @@ public void testInvalidProperties() { * Test calling verifyColumnMasterKeyMetadata for non enclave computation */ @Test - public void testVerifyColumnMasterKeyMetadata() { + public void testVerifyCMKNoEnclave() { try { - SQLServerColumnEncryptionJavaKeyStoreProvider jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider("keystore", - null); + SQLServerColumnEncryptionJavaKeyStoreProvider jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider( + "keystore", null); assertFalse(jksp.verifyColumnMasterKeyMetadata(null, false, null)); } catch (SQLServerException e) { fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); @@ -296,6 +299,30 @@ public void testVerifyColumnMasterKeyMetadata() { } } + /* + * Test calling verifyColumnMasterKeyMetadata with untrusted key path + */ + @Test + public void testVerifyCMKUntrusted() { + try { + Map> trustedKeyPaths = SQLServerConnection.getColumnEncryptionTrustedMasterKeyPaths(); + List paths = new ArrayList(); + paths.add(javaKeyPath); + String serverName = connection.activeConnectionProperties + .getProperty(SQLServerDriverStringProperty.SERVER_NAME.toString()).toUpperCase(); + + trustedKeyPaths.put(serverName, paths); + SQLServerConnection.setColumnEncryptionTrustedMasterKeyPaths(trustedKeyPaths); + + SQLServerSecurityUtility.verifyColumnMasterKeyMetadata(connection, "My_KEYSTORE", "UnTrustedKeyPath", + serverName, true, null); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_UntrustedKeyPath"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException")); + } + } + /* * Test getEnclavePackage with null enclaveSession */ @@ -309,7 +336,6 @@ public void testGetEnclavePackage() { } catch (SQLServerException e) { fail(TestResource.getResource("R_unexpectedException")); } - } /* diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 80a951b04..cb3cd863a 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -63,17 +63,14 @@ public class AESetup extends AbstractTest { static String cekWin = Constants.CEK_NAME + "_WIN"; static String cekAkv = Constants.CEK_NAME + "_AKV"; - static String javaKeyAliases = null; - static String[] keyIDs = null; - static SQLServerColumnEncryptionKeyStoreProvider jksProvider = null; - static SQLServerColumnEncryptionAzureKeyVaultProvider akvProvider = null; + // static String javaKeyAliases = null; + // static SQLServerColumnEncryptionKeyStoreProvider jksProvider = null; + // static SQLServerColumnEncryptionAzureKeyVaultProvider akvProvider = null; static SQLServerStatementColumnEncryptionSetting stmtColEncSetting = null; static String AETestConnectionString; static Properties AEInfo; static Map map = new HashMap(); - static boolean isKspRegistered = false; - // test that only run on Windows will be skipped static boolean isWindows = System.getProperty("os.name").startsWith("Windows"); @@ -157,36 +154,14 @@ enum ColumnType { @BeforeAll public static void setUpConnection() throws TestAbortedException, Exception { AETestConnectionString = connectionString + ";sendTimeAsDateTime=false" + ";columnEncryptionSetting=enabled"; - String applicationClientID = TestUtils.getConfiguredProperty("applicationClientID"); - String applicationKey = TestUtils.getConfiguredProperty("applicationKey"); - String keyID = TestUtils.getConfiguredProperty("keyID"); - String windowsKeyPath = TestUtils.getConfiguredProperty("windowsKeyPath"); - String javaKeyPath = TestUtils.getCurrentClassPath() + Constants.JKS_NAME; - if (null == applicationClientID || null == applicationKey || null == keyID + if (null == applicationClientID || null == applicationKey || null == keyIDs || (isWindows && null == windowsKeyPath)) { fail(TestResource.getResource("R_reqExternalSetup")); - } - - readFromFile(Constants.JAVA_KEY_STORE_FILENAME, "Alias name"); - - keyIDs = keyID.split(";"); - if (null == jksProvider) { - jksProvider = new SQLServerColumnEncryptionJavaKeyStoreProvider(javaKeyPath, - Constants.JKS_SECRET.toCharArray()); - map.put("My_KEYSTORE", jksProvider); } - if (null == akvProvider) { - akvProvider = new SQLServerColumnEncryptionAzureKeyVaultProvider(applicationClientID, applicationKey); - map.put(Constants.AZURE_KEY_VAULT_NAME, akvProvider); - } - - if (!isKspRegistered) { - SQLServerConnection.registerColumnEncryptionKeyStoreProviders(map); - isKspRegistered = true; - } + readFromFile(Constants.JAVA_KEY_STORE_FILENAME, "Alias name"); String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); if (null != enclaveAttestationUrl) { diff --git a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java index dcfbdaf48..ee3332b33 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java @@ -11,6 +11,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.HashMap; +import java.util.Map; import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; import java.util.logging.Handler; @@ -24,6 +26,9 @@ import org.junit.jupiter.api.BeforeAll; import com.microsoft.sqlserver.jdbc.ISQLServerDataSource; +import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionAzureKeyVaultProvider; +import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionJavaKeyStoreProvider; +import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionKeyStoreProvider; import com.microsoft.sqlserver.jdbc.SQLServerConnection; import com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource; import com.microsoft.sqlserver.jdbc.SQLServerDataSource; @@ -44,13 +49,17 @@ */ public abstract class AbstractTest { - static String applicationClientID = null; - static String applicationKey = null; - static String[] keyIDs = null; + protected static String applicationClientID = null; + protected static String applicationKey = null; + protected static String[] keyIDs = null; - static String[] jksPaths = null; - static String[] javaKeyAliases = null; - static String windowsKeyPath = null; + protected static String javaKeyPath = null; + protected static String javaKeyAliases = null; + protected static SQLServerColumnEncryptionKeyStoreProvider jksProvider = null; + protected static SQLServerColumnEncryptionAzureKeyVaultProvider akvProvider = null; + static boolean isKspRegistered = false; + + protected static String windowsKeyPath = null; protected static SQLServerConnection connection = null; protected static ISQLServerDataSource ds = null; @@ -82,11 +91,31 @@ public static void setup() throws Exception { // Invoke fine logging... invokeLogging(); + connectionString = getConfiguredProperty(Constants.MSSQL_JDBC_TEST_CONNECTION_PROPERTIES); + connectionStringNTLM = connectionString; + applicationClientID = getConfiguredProperty("applicationClientID"); applicationKey = getConfiguredProperty("applicationKey"); + javaKeyPath = TestUtils.getCurrentClassPath() + Constants.JKS_NAME; keyIDs = getConfiguredProperty("keyID", "").split(Constants.SEMI_COLON); - connectionString = getConfiguredProperty(Constants.MSSQL_JDBC_TEST_CONNECTION_PROPERTIES); - connectionStringNTLM = connectionString; + windowsKeyPath = getConfiguredProperty("windowsKeyPath"); + + Map map = new HashMap(); + if (null == jksProvider) { + jksProvider = new SQLServerColumnEncryptionJavaKeyStoreProvider(javaKeyPath, + Constants.JKS_SECRET.toCharArray()); + map.put("My_KEYSTORE", jksProvider); + } + + if (null == akvProvider) { + akvProvider = new SQLServerColumnEncryptionAzureKeyVaultProvider(applicationClientID, applicationKey); + map.put(Constants.AZURE_KEY_VAULT_NAME, akvProvider); + } + + if (!isKspRegistered) { + SQLServerConnection.registerColumnEncryptionKeyStoreProviders(map); + isKspRegistered = true; + } // if these properties are defined then NTLM is desired, modify connection string accordingly String domain = System.getProperty("domainNTLM"); From ea1f5c1190c6e4452ba7fa0302c72a2ff87a958f Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 31 Oct 2019 17:20:13 -0700 Subject: [PATCH 42/49] fix --- src/test/java/com/microsoft/sqlserver/jdbc/AETest.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java index 26744b9df..cc61b4cb7 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java @@ -304,8 +304,9 @@ public void testVerifyCMKNoEnclave() { */ @Test public void testVerifyCMKUntrusted() { + Map> trustedKeyPaths = null; try { - Map> trustedKeyPaths = SQLServerConnection.getColumnEncryptionTrustedMasterKeyPaths(); + trustedKeyPaths = SQLServerConnection.getColumnEncryptionTrustedMasterKeyPaths(); List paths = new ArrayList(); paths.add(javaKeyPath); String serverName = connection.activeConnectionProperties @@ -320,6 +321,11 @@ public void testVerifyCMKUntrusted() { assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_UntrustedKeyPath"))); } catch (Exception e) { fail(TestResource.getResource("R_unexpectedException")); + } finally { + if (null != trustedKeyPaths) { + trustedKeyPaths.clear(); + SQLServerConnection.setColumnEncryptionTrustedMasterKeyPaths(trustedKeyPaths); + } } } From ef1b3646419d8fc999ff93d14a9a0cdc0809627e Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 7 Nov 2019 18:07:24 -0800 Subject: [PATCH 43/49] review updates and added more negative test --- pom.xml | 2 +- .../sqlserver/jdbc/SQLServerConnection.java | 14 +- .../sqlserver/jdbc/SQLServerResource.java | 4 +- .../com/microsoft/sqlserver/jdbc/AETest.java | 499 ------------------ .../jdbc/AlwaysEncrypted/AESetup.java | 2 - .../jdbc/AlwaysEncrypted/EnclaveTest.java | 211 ++++++-- .../sqlserver/jdbc/EnclavePackageTest.java | 447 ++++++++++++++++ 7 files changed, 629 insertions(+), 550 deletions(-) delete mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/AETest.java create mode 100644 src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java diff --git a/pom.xml b/pom.xml index 2b0676edd..69d1df490 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,7 @@ NTLM - - - - - - - For tests using NTLM Authentication mode (excluded by default) reqExternalSetup - For tests requiring external setup (excluded by default) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default testing enabled with SQL Server 2019 (SQLv14) --> + Default testing enabled with SQL Server 2019 (SQLv15) --> xSQLv15, NTLM, reqExternalSetup diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index 94bd9c08a..f41f2687f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -1478,21 +1478,17 @@ Connection connectInternal(Properties propsIn, } } - // both enclaveAttestationUrl must be enclaveAttestationProtocol specified + // enclave requires columnEncryption=enabled, enclaveAttestationUrl and enclaveAttestationProtocol if ((null != enclaveAttestationUrl && !enclaveAttestationUrl.isEmpty() && (null == enclaveAttestationProtocol || enclaveAttestationProtocol.isEmpty())) || (null != enclaveAttestationProtocol && !enclaveAttestationProtocol.isEmpty() - && (null == enclaveAttestationUrl || enclaveAttestationUrl.isEmpty()))) { + && (null == enclaveAttestationUrl || enclaveAttestationUrl.isEmpty())) + || (null != enclaveAttestationUrl && !enclaveAttestationUrl.isEmpty() + && (null != enclaveAttestationProtocol || !enclaveAttestationProtocol.isEmpty()) + && (null == columnEncryptionSetting || !isColumnEncryptionSettingEnabled()))) { throw new SQLServerException(SQLServerException.getErrString("R_enclavePropertiesError"), null); } - // enclave requires columnEncryption - if ((null != enclaveAttestationUrl && !enclaveAttestationUrl.isEmpty() - && (null != enclaveAttestationProtocol || !enclaveAttestationProtocol.isEmpty()) - && (null == columnEncryptionSetting || !isColumnEncryptionSettingEnabled()))) { - throw new SQLServerException(SQLServerException.getErrString("R_enclaveAEdisabled"), null); - } - sPropKey = SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.toString(); sPropValue = activeConnectionProperties.getProperty(sPropKey); if (null != sPropValue) { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index 4cfed4243..284af690b 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -598,10 +598,8 @@ protected Object[][] getContents() { "An error occurred when matching VALUES list to table columns. Please verify SQL syntax."}, {"R_invalidValuesList", "An error occurred when reading VALUES list. Please verify SQL syntax."}, {"R_enclaveNotSupported", "The SQL Server instance does not support enclave based computations."}, - {"R_enclaveAEdisabled", - "The \"columnEncryptionSetting\" connection property must be enabled when specifying \"enclaveAttestationUrl\" and \"enclaveAttestationProtocol\" connection properties."}, {"R_enclavePropertiesError", - "The \"enclaveAttestationUrl\" connection property must be specified with \"enclaveAttestationProtocol\"."}, + "The \"columnEncryptionSetting\" connection property must be enabled, along with valid \"enclaveAttestationUrl\" and \"enclaveAttestationProtocol\" connection properties when enabling Always Encrypted with secrure enclaves ."}, {"R_enclaveInvalidAttestationProtocol", "The \"enclaveAttestationProtocol\" is invalid."}, {"R_enclaveTypeInvalid", "The enclave type {0} is invalid or not supported by the driver."}, {"R_attestationUrlInvalid", "Unable to attest enclave specified by {0}."}, diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java deleted file mode 100644 index cc61b4cb7..000000000 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AETest.java +++ /dev/null @@ -1,499 +0,0 @@ -package com.microsoft.sqlserver.jdbc; - -import static org.junit.Assert.assertFalse; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.security.cert.CertificateException; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.logging.LogManager; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.platform.runner.JUnitPlatform; -import org.junit.runner.RunWith; - -import com.microsoft.sqlserver.testframework.AbstractTest; -import com.microsoft.sqlserver.testframework.Constants; -import com.microsoft.sqlserver.testframework.PrepUtil; - - -/** - * A class for testing basic NTLMv2 functionality. - */ -@RunWith(JUnitPlatform.class) -@Tag(Constants.xSQLv12) -@Tag(Constants.xAzureSQLDW) -@Tag(Constants.xAzureSQLDB) -@Tag(Constants.reqExternalSetup) -public class AETest extends AbstractTest { - - private static SQLServerDataSource dsLocal = null; - private static SQLServerDataSource dsXA = null; - private static SQLServerDataSource dsPool = null; - - private static String connectionStringAE; - private static boolean isAEv2 = false; - - private byte[] healthReportCertificate = {61, 11, 0, 0, 27, 2, 0, 0, -66, 3, 0, 0, 88, 5, 0, 0, 82, 83, 65, 49, 0, - 16, 0, 0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -57, 59, -80, 116, -86, -109, -4, -96, - -106, -85, 107, 22, 88, 29, 91, -50, 29, -44, -36, -109, -123, 57, 70, -41, 110, -85, 90, 49, -17, 100, -49, - 96, -34, 89, -76, -59, -82, 100, 118, -9, 44, 86, -112, 44, 13, 36, -43, 3, -69, -46, -6, -126, 26, -74, 75, - -89, 82, -111, 72, -1, 127, 78, -80, 102, -126, 51, -89, 12, 70, 107, 50, 126, -40, -6, 51, 13, 87, 5, 79, - -53, -66, 26, 126, -128, -82, 97, 103, 7, 62, 49, -66, -97, -115, 113, -88, -73, 127, 102, -21, -51, 79, 8, - 101, -76, 15, -29, 0, -83, -42, -12, 52, 106, -60, 62, -67, 5, -7, -91, -21, -60, 4, -52, -39, 59, -100, - 127, 5, -55, 93, 9, 89, 83, 14, 85, -9, -33, -5, 75, 42, -81, 123, -117, -73, -50, 15, 59, -35, -35, -74, - -113, 41, -74, -41, 51, -3, 88, 110, 44, 3, -31, -36, 94, 29, 82, 12, -119, -34, 72, -51, 59, -109, -92, 44, - 24, 75, 78, 84, 64, -86, -43, 11, 23, 70, 124, 33, -90, 60, -85, -63, -23, -70, 79, 62, 13, -121, -45, 53, - 107, -49, 104, -85, -80, 7, -84, 61, -93, 44, -87, -68, -101, -7, -43, -65, 90, -12, -12, 16, 104, 26, 5, - -103, -32, -84, -80, -26, 17, -29, 30, -46, 127, 44, -70, -87, 61, -35, 47, -62, 86, -23, 114, 0, -19, 38, - -25, 90, -6, -1, -121, -69, 51, 74, -95, 64, -67, 6, 49, 35, -125, -5, -40, -115, 1, -31, -51, 64, -102, - -51, 106, 111, 38, 124, -111, 25, -75, 7, -116, -111, -120, 82, 103, 112, 14, 32, -49, -87, 23, 31, -14, - -107, -64, -76, 9, -40, -37, 127, -99, 67, -114, 114, -3, -62, 7, -88, 103, -89, 124, 125, -14, -21, 59, 91, - 112, 13, 35, -80, -103, -79, 6, 41, -110, 8, -15, -58, 95, -101, 43, -8, 106, -50, -87, -32, 93, -30, -31, - -105, 69, -73, 57, -38, 75, 42, 120, -75, -49, 77, 76, -120, -14, -42, -44, -34, 8, -4, -98, -35, 46, -23, - 16, -83, -6, 115, -127, 117, 54, -25, 58, -106, 10, 85, 54, -105, 48, 62, -55, 70, 56, 115, -121, 31, -4, - 113, 21, -98, 53, 118, 31, -82, 122, -29, 41, 59, -112, -123, -114, -26, 54, -45, 106, 77, 79, 2, -63, -37, - 53, 42, -26, -24, -60, 88, -80, 22, 55, -37, -114, 99, -58, 113, 87, 26, -70, 105, -70, -78, -48, 26, 51, - 10, -37, -105, 66, 3, -69, 38, -56, 34, 77, -98, 56, 15, 0, 85, -63, -67, -102, -116, -49, -85, 22, -70, 68, - -31, 99, 23, -100, -33, -45, -49, -90, 104, -26, -5, -32, 100, 81, -117, -60, -7, -59, 84, -8, -101, 86, 88, - -100, 107, -65, -11, -5, 41, 96, -76, 24, 68, -105, -18, -99, -10, -15, 26, -43, 91, -86, 33, -17, -19, -6, - -89, 78, -123, 48, 47, -107, 36, -2, -33, 123, -124, 91, 123, -20, -88, 73, 48, -126, 3, -70, 48, -126, 2, - -94, -96, 3, 2, 1, 2, 2, 16, 66, 85, -66, 31, 39, 20, 120, -95, 75, 114, 74, -14, 59, 52, 99, -29, 48, 13, - 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 48, 47, 49, 45, 48, 43, 6, 3, 85, 4, 3, 12, 36, 77, 105, - 99, 114, 111, 115, 111, 102, 116, 32, 82, 101, 109, 111, 116, 101, 32, 65, 116, 116, 101, 115, 116, 97, 116, - 105, 111, 110, 32, 83, 101, 114, 118, 105, 99, 101, 48, 30, 23, 13, 49, 57, 49, 48, 51, 48, 49, 56, 50, 50, - 52, 55, 90, 23, 13, 49, 57, 49, 48, 51, 49, 48, 50, 50, 50, 52, 56, 90, 48, 75, 49, 73, 48, 71, 6, 3, 85, 4, - 3, 12, 64, 65, 49, 57, 67, 49, 56, 70, 51, 50, 53, 49, 56, 66, 56, 65, 57, 51, 70, 49, 57, 52, 57, 69, 66, - 57, 69, 56, 53, 48, 68, 56, 53, 66, 66, 53, 53, 65, 67, 69, 65, 49, 56, 67, 53, 54, 55, 49, 70, 55, 55, 65, - 69, 49, 54, 51, 54, 56, 52, 51, 55, 68, 65, 53, 56, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, - 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -50, -20, -124, 102, 67, -52, 79, - -43, 5, -104, 31, 99, -89, 53, -77, 61, 82, 64, -125, -30, 32, 102, 101, -87, 63, -75, -10, -100, -31, -125, - 15, -9, -40, 81, 8, 54, -43, 112, 91, -19, 126, 49, -57, 33, -51, -33, -82, 21, 22, 4, -68, 112, 83, -55, - -50, 60, -70, 1, -37, -60, 3, -75, 63, 124, -3, -112, 107, -120, -122, -97, 26, -28, 62, -101, -21, -66, 28, - -84, 23, 21, -126, 27, -9, 45, 43, 50, 1, -117, 28, -114, -99, -38, 38, -104, 7, -45, 85, -100, -44, -102, - 68, -6, -22, -45, -75, 84, -33, -11, -76, -9, 42, -1, 82, -21, -12, 18, -15, 118, -121, 124, 103, -85, 43, - 54, -106, 77, 102, 0, -107, -12, 103, 10, 118, -85, 23, 40, -61, -39, 76, 39, -124, 75, -121, -114, -65, - -119, -42, -75, 42, -110, -71, 94, 61, -125, 104, 105, -119, 74, -83, 57, -11, -38, -120, -94, -100, -58, - -85, 106, 124, 50, 30, 118, -102, 1, -123, -119, -81, 111, 6, 18, -114, 61, -35, 64, 99, -53, 16, -56, -8, - -18, -110, 96, -85, 125, 95, 60, 0, -58, -81, -30, 54, 39, 73, 100, -27, 14, 5, -45, 122, 120, -33, -48, - -62, -43, 98, 9, -5, -12, 4, -6, -57, -113, -28, 117, -26, 50, 76, 65, -107, 109, 49, -9, -22, 86, 103, 68, - -128, -87, -116, 25, -117, 114, 28, -9, 28, 70, -28, -36, 102, -27, 40, 120, 60, -113, -11, -73, 2, 3, 1, 0, - 1, -93, -127, -75, 48, -127, -78, 48, 14, 6, 3, 85, 29, 15, 1, 1, -1, 4, 4, 3, 2, 7, -128, 48, 29, 6, 9, 43, - 6, 1, 4, 1, -126, 55, 21, 10, 4, 16, 48, 14, 48, 12, 6, 10, 43, 6, 1, 4, 1, -126, 55, 48, 1, 2, 48, 25, 6, - 3, 85, 29, 14, 4, 18, 4, 16, 49, 110, 105, 97, 22, -114, 85, -99, 21, -32, -60, -109, 42, -59, 66, 11, 48, - 102, 6, 3, 85, 29, 35, 4, 95, 48, 93, -128, 20, 37, -118, -59, 87, -8, 105, 88, 79, -36, 20, -127, -8, -56, - -9, 97, -10, 105, -80, -109, -93, -95, 51, -92, 49, 48, 47, 49, 45, 48, 43, 6, 3, 85, 4, 3, 12, 36, 77, 105, - 99, 114, 111, 115, 111, 102, 116, 32, 82, 101, 109, 111, 116, 101, 32, 65, 116, 116, 101, 115, 116, 97, 116, - 105, 111, 110, 32, 83, 101, 114, 118, 105, 99, 101, -126, 16, 37, 113, -89, -86, -71, 42, -44, -83, 67, -30, - 8, -31, 97, 14, -40, -12, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 3, -126, 1, 1, 0, -85, - -56, -125, -91, 83, -96, -32, -69, -69, -40, -127, -93, 69, 24, -7, -121, 54, 30, 76, 20, 28, -95, 93, -76, - -109, -4, -97, -102, 126, 76, -68, -39, 6, -66, 70, -100, 67, -112, 25, -109, -2, -83, 40, 86, 69, -70, - -105, 40, 88, 109, -101, 64, 95, -60, -49, -25, -42, 61, -37, 18, -3, -64, -68, -123, 111, 7, 119, 107, 81, - 40, -103, 66, 42, 110, 81, 95, -38, 104, 109, -92, -90, 6, -120, -113, 53, -8, -116, -44, -90, -3, 103, 100, - 78, 90, 96, -121, 80, -105, 109, 28, -28, -63, 75, 14, -98, 83, -122, 78, -70, 83, 4, 11, -107, 115, 50, 78, - -37, -88, 62, -72, 4, 26, 6, 102, -65, -39, -48, 58, -72, 36, 125, 29, -27, -6, -42, 111, 57, -97, 102, 3, - -5, 112, 62, -13, -65, -4, 40, -103, 19, -75, 82, -83, -26, -12, 62, -41, -38, -70, -85, 22, 100, 34, 0, 90, - 68, -33, -107, 40, -63, -9, 38, 99, -89, 15, 118, 14, -33, -2, -18, -98, -105, 23, 31, 92, -46, -68, -61, - 103, 47, -121, 73, -8, -82, -28, 43, 0, 50, 78, 78, 68, 88, -91, 121, -29, 30, -25, 23, 88, 43, -72, -49, - -77, 92, -62, -8, 85, -86, -111, 99, -37, -46, -121, 34, 122, 118, 9, -27, 57, -56, 59, 44, 62, -115, -41, - -49, -73, -59, 122, 39, -69, 76, 122, 127, -21, 113, 43, -21, -109, 95, 98, 38, 33, 111, -34, -38, 71, 88, - 5, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 64, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 64, 4, 0, 0, 1, 0, 0, 0, 14, 60, -81, - -73, 81, 79, 109, 37, -78, -54, -47, -115, 69, -20, -28, -70, -75, 43, 5, -75, -42, 70, -27, 53, -124, -35, - 61, 45, -90, -38, 41, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 16, 32, 48, 64, 65, 49, 33, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -108, -76, 101, 116, -38, -69, -79, 113, -122, -19, -59, 38, 60, -76, -34, 123, -10, -39, -30, - -21, -122, -122, 34, 32, 90, -108, -45, -109, -44, -52, 101, -127, 4, 55, -54, -30, 83, 125, -117, -101, 7, - 118, -74, 27, 17, -26, -50, -45, -46, 50, -23, 48, -113, 96, -30, 26, -38, -78, -3, -111, -29, -38, -107, - -104, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 23, 18, 0, 1, 5, 32, 19, 0, 5, 20, 3, 18, 1, 34, - 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -112, 0, 0, 0, -108, - -76, 101, 116, -38, -69, -79, 113, -122, -19, -59, 38, 60, -76, -34, 123, -10, -39, -30, -21, -122, -122, - 34, 32, 90, -108, -45, -109, -44, -52, 101, -127, 4, 55, -54, -30, 83, 125, -117, -101, 7, 118, -74, 27, 17, - -26, -50, -45, -46, 50, -23, 48, -113, 96, -30, 26, -38, -78, -3, -111, -29, -38, -107, -104, -2, -2, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 23, 18, 0, 1, 5, 32, 19, 0, 5, 20, 3, 18, 1, 34, 5, 0, 0, 0, 0, 97, - 0, 101, 0, 116, 0, 109, 0, 45, 0, 101, 0, 110, 0, 99, 0, 108, 0, 97, 0, 118, 0, 101, 0, 46, 0, 100, 0, 108, - 0, 108, 0, 0, 0, 0, 0, 1, 0, 0, 0, -120, 0, 0, 0, 90, -58, -49, 7, 59, -65, 81, -44, -97, -107, 97, -106, - 71, -70, 33, -5, 99, -7, -4, -117, -31, -91, -35, -56, -12, -105, -29, 80, 5, 72, 3, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 32, 39, -67, 104, 117, 89, 73, -73, -66, 6, 52, 80, -30, 22, -41, -19, 0, 0, 0, 0, 98, 0, 99, - 0, 114, 0, 121, 0, 112, 0, 116, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -104, - 0, 0, 0, -76, 15, 80, 111, -51, 57, 8, -54, -53, -109, -113, -106, 35, -72, -114, -12, -128, -17, 51, -64, - -124, -38, -55, 27, 1, 80, 69, 48, -96, -77, -128, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -16, 60, -51, -89, - -24, 123, 70, -21, -86, -25, 31, 19, -43, -51, -34, 93, 0, 0, 0, 0, 117, 0, 99, 0, 114, 0, 116, 0, 98, 0, - 97, 0, 115, 0, 101, 0, 95, 0, 101, 0, 110, 0, 99, 0, 108, 0, 97, 0, 118, 0, 101, 0, 46, 0, 100, 0, 108, 0, - 108, 0, 0, 0, 0, 0, 1, 0, 0, 0, -120, 0, 0, 0, -41, 110, -101, -107, 45, -49, 11, 25, -47, 17, 90, 38, -28, - 105, -88, 110, 39, -35, -15, -94, -106, 14, -37, -70, -105, -14, 59, -88, 80, 30, -112, -91, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 114, -124, 65, 114, 103, -88, 78, -115, -65, 1, 40, 75, 7, 67, 43, 30, 0, 0, 0, 0, 118, - 0, 101, 0, 114, 0, 116, 0, 100, 0, 108, 0, 108, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, -112, 0, 0, 0, 20, -54, 74, 74, 43, -64, -12, 60, -101, -67, -58, -102, 71, -124, 113, -46, 92, -63, 11, - -104, 100, -6, -126, 9, 3, 16, -36, 57, 24, -22, 8, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 122, 0, 117, 0, 114, 0, 101, 0, 65, 0, 116, 0, 116, 0, - 101, 0, 115, 0, 116, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -104, 0, 0, 0, -54, 68, - -119, -29, 65, -104, -2, 53, -48, -27, -20, 25, 8, -72, -43, 124, -63, 9, 126, -58, -100, 14, -41, -75, 61, - -66, -28, 80, 67, 17, -109, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 19, -65, 62, 83, 100, 65, 48, -86, - -102, -64, -14, -31, -12, -58, 36, 0, 0, 0, 0, 98, 0, 99, 0, 114, 0, 121, 0, 112, 0, 116, 0, 80, 0, 114, 0, - 105, 0, 109, 0, 105, 0, 116, 0, 105, 0, 118, 0, 101, 0, 115, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, - -107, 11, 37, -57, 57, -18, -111, 70, 53, -83, -117, 111, -63, 65, -80, -4, -3, -36, 27, 35, 111, -91, 54, - -34, 103, 41, -5, -79, 8, -36, -124, 101, 103, 90, -115, -21, 40, 49, 33, 61, 85, -104, 67, 5, -26, -78, - -27, -78, -92, -70, 115, -77, -98, 39, -101, 58, 35, -21, -51, 83, -4, 80, 125, 39, -117, -75, 50, -71, 125, - -44, 28, 41, 25, 67, -4, 3, -120, -89, -124, -19, 94, -81, 31, 114, -91, 117, -9, 6, 85, 32, 16, -16, -28, - 59, 108, 67, -77, -126, 42, 25, 7, -46, 40, -32, 52, 51, -60, 120, 28, 1, 89, -1, 51, -96, 105, 93, -111, - -8, -25, 9, 55, -120, 37, -63, -6, -66, 11, -16, -34, -71, -18, 67, -74, 86, -98, -15, -56, -76, 86, 10, -6, - 13, -9, 24, -9, -94, -93, 127, -63, -69, 86, -73, -57, 91, -108, -11, 70, 77, -80, -39, 70, -14, -61, 39, - -45, -83, 46, 17, 126, -104, 10, -117, 46, -60, -122, 12, 20, -117, 30, 105, -80, -67, -48, -4, -57, -98, - 95, 102, -85, 36, 29, -61, -93, -91, 67, -61, 76, -54, -60, 77, 95, -79, -126, -66, 110, -32, -8, -45, -108, - 42, -101, 102, -99, 104, -33, 74, -43, -124, -47, 81, -58, 118, 112, -80, -9, 2, -40, 77, 40, 122, 16, 48, - 111, -98, 78, 80, -122, 99, -29, -125, -78, -104, -36, -94, -95, -115, -110, 31, -108, -46, 88, 79, -103, - -65, 90, -13, 120, 2, 0, 0, 19, 0, 0, 0, 75, 1, 0, 0, 104, 0, 0, 0, 0, 2, 0, 0, 69, 67, 75, 51, 48, 0, 0, 0, - 38, -81, -37, -121, 34, 74, 31, -103, -95, 62, 72, -29, 19, -105, -124, -112, 71, 6, 64, 98, -73, -85, -49, - -21, -63, -67, -69, 2, 56, 36, 116, -49, -24, -123, 24, 43, 69, -62, -126, -94, 80, 113, 114, 60, -44, -48, - -44, -83, -13, -104, -69, 57, -26, 41, 65, -15, 97, -65, 26, -41, 32, -125, -50, 52, -18, 15, -91, 98, -4, - -52, 88, -34, -61, -32, 126, -40, 63, 2, 113, -11, 92, 69, 3, -118, -52, 50, -30, 52, -105, -36, -95, -18, - 17, 99, 107, -105, 17, -104, -125, 34, 11, -44, 7, 79, 35, 24, -2, -27, -43, -21, 115, 52, 44, -45, -68, - -122, 100, -55, -79, 14, -79, 81, 49, 81, -3, -43, -89, -118, 116, 76, 13, -117, 16, -1, 46, -62, 40, 21, - 97, 63, 43, -65, 45, 101, 30, 2, 66, 15, -20, -53, -112, 23, 120, -12, -31, -79, -33, 89, -83, 95, -110, - -67, -58, -86, 118, 28, 84, 22, 79, -69, -41, -78, 88, 31, 73, 97, 71, -109, -127, -22, 14, 113, -65, 51, - 11, 34, -23, -61, 107, 114, -109, 58, 9, 104, 120, -36, -93, 70, 104, -79, -46, 13, -15, -62, -61, -62, -16, - 19, -79, 4, 121, -63, 61, -100, -66, 25, -23, 117, -119, -97, -84, 15, 99, -101, 59, -18, -81, -67, -99, - -20, -82, -41, 74, -19, -54, -86, -58, 121, -7, -8, -8, 11, 113, -52, -50, 14, -102, -77, -105, 126, -110, - 85, -97, 75, -24, -33, -63, 48, 79, 67, 84, 73, 54, 49, -104, 38, 13, -100, 76, 66, 86, 72, -120, 100, 33, - -5, -26, 107, 79, -48, -1, 71, 104, 22, 115, 66, -94, 73, 88, -48, 71, 44, 118, 15, -76, -98, -74, -78, 43, - 33, 120, -74, -87, 78, 31, 36, 96, -104, -98, -28, 121, -128, -8, -77, -16, -74, -94, -101, -57, 99, -78, - 70, 108, -26, 115, 21, -13, -41, 46, -93, -68, 29, 76, 68, 109, -63, 108, 27, -112, -20, -53, 92, 109, 121, - 33, 64, 69, 42, -72, -45, 35, 50, 60, -124, -99, -40, -7, -96, -57, -14, -71, -103, -44, 13, 69, -89, -17, - -46, -128, -5, -83, 80, -125, 13, -48, -126, 49, 62, 37, 113, -92, -30, 15, 47, 113, 124, 108, -89, -48, -4, - -84, -61, -11, -55, -97, -28, 36, 20, -106, 57, -16, 107, 51, 67, -95, -73, -76, -8, -118, 97, 127, -20, 67, - 103, 25, 3, -67, 41, 73, 122, 92, -9, 22, 69, -91, -107, 52, -23, -119, -56, 71, -76, 77, -51, 12, -72, 117, - -48, 108, -100, -77, -103, 114, 45, 100, 100, -11, 55, 124, -121, -102, -105, 22, 4, -33, 76, 68, 116, -96, - -80, 43, 5, -119, -113, 44, 66, -128, -104, 60, -78, -123, 56, -36, -99, -63, 71, 25, -15, 17, -8, -71, -8, - -37, 92, 70, 127, 33, 69, -34, 11, -9, 38, 127, -46, -10, 112, 126, -7, -77, 16, -32, -42, 118, -110, 98, - -112, 78, -95, 56, -45, -46, -108, -54, 116, 99, 107, 78, -92, -60, 72, -45, -40, 33, -93, -21, -90, -108, - -19, 89, -42, 29, -123, 35, -114, -95, -37, 2, -61, 12, 84, -100, -100, 112, -96, 80, 12, 90, 78, 36, 40, - -56, -90, -60, -77, -77, -56, 53, -93, -10, -22, -47, 15, 5, -90, -67, 111, -82, -94, 96, -68, -79, -3, -51, - -108, 41, 112, -89, 22, -92, 88, 37, 66, 20, 93, 111, 102, -69, -20, -47, -43, -24, 82, -41, 12, -58, 53, - 68, -76, -94, -116, 75, 14, 24, -43, 73, -78, -87, 21}; - - /** - * Setup environment for test. - * - * @throws Exception - * when an error occurs - */ - @BeforeAll - public static void setUp() throws Exception { - connectionStringAE = TestUtils.addOrOverrideProperty(connectionString, "columnEncryptionSetting", - ColumnEncryptionSetting.Enabled.toString()); - - String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); - connectionStringAE = TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationUrl", - (null != enclaveAttestationUrl) ? enclaveAttestationUrl : "http://blah"); - - String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); - connectionStringAE = TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationProtocol", - (null != enclaveAttestationProtocol) ? enclaveAttestationProtocol : AttestationProtocol.HGS.toString()); - - try (SQLServerConnection con = PrepUtil.getConnection(connectionStringAE)) { - isAEv2 = TestUtils.isAEv2(con); - } catch (SQLException e) { - isAEv2 = false; - } catch (Exception e) { - fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); - } - - // reset logging to avoid severe logs due to negative testing - LogManager.getLogManager().reset(); - - dsLocal = new SQLServerDataSource(); - AbstractTest.updateDataSource(connectionStringAE, dsLocal); - - dsXA = new SQLServerXADataSource(); - AbstractTest.updateDataSource(connectionStringAE, dsXA); - - dsPool = new SQLServerConnectionPoolDataSource(); - AbstractTest.updateDataSource(connectionStringAE, dsPool); - } - - /** - * Tests basic connection. - * - * @throws SQLException - * when an error occurs - */ - @Test - public void testBasicConnection() throws SQLException { - org.junit.Assume.assumeTrue(isAEv2); - - try (Connection con1 = dsLocal.getConnection(); Connection con2 = dsXA.getConnection(); - Connection con3 = dsPool.getConnection(); - Connection con4 = PrepUtil.getConnection(connectionStringAE)) { - if (TestUtils.isAEv2(con1)) { - verifyEnclaveEnabled(con1); - } - if (TestUtils.isAEv2(con2)) { - verifyEnclaveEnabled(con2); - } - if (TestUtils.isAEv2(con3)) { - verifyEnclaveEnabled(con3); - } - if (TestUtils.isAEv2(con4)) { - verifyEnclaveEnabled(con4); - } - } - } - - /** - * Tests invalid connection property combinations. - */ - @Test - public void testInvalidProperties() { - org.junit.Assume.assumeTrue(isAEv2); - - // enclaveAttestationUrl and enclaveAttestationProtocol without "columnEncryptionSetting" - testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringAE, "columnEncryptionSetting", - ColumnEncryptionSetting.Disabled.toString()), "R_enclaveAEdisabled"); - - // enclaveAttestationUrl without enclaveAttestationProtocol - testInvalidProperties(TestUtils.removeProperty(connectionStringAE, "enclaveAttestationProtocol"), - "R_enclavePropertiesError"); - - // enclaveAttestationProtocol without enclaveAttestationUrl - testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationUrl", ""), - "R_enclavePropertiesError"); - - // bad enclaveAttestationProtocol - testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringAE, "enclaveAttestationProtocol", ""), - "R_enclaveInvalidAttestationProtocol"); - } - - /* - * Test calling verifyColumnMasterKeyMetadata for non enclave computation - */ - @Test - public void testVerifyCMKNoEnclave() { - try { - SQLServerColumnEncryptionJavaKeyStoreProvider jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider( - "keystore", null); - assertFalse(jksp.verifyColumnMasterKeyMetadata(null, false, null)); - } catch (SQLServerException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - - try { - SQLServerColumnEncryptionAzureKeyVaultProvider aksp = new SQLServerColumnEncryptionAzureKeyVaultProvider("", - ""); - assertFalse(aksp.verifyColumnMasterKeyMetadata(null, false, null)); - } catch (SQLServerException e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /* - * Test calling verifyColumnMasterKeyMetadata with untrusted key path - */ - @Test - public void testVerifyCMKUntrusted() { - Map> trustedKeyPaths = null; - try { - trustedKeyPaths = SQLServerConnection.getColumnEncryptionTrustedMasterKeyPaths(); - List paths = new ArrayList(); - paths.add(javaKeyPath); - String serverName = connection.activeConnectionProperties - .getProperty(SQLServerDriverStringProperty.SERVER_NAME.toString()).toUpperCase(); - - trustedKeyPaths.put(serverName, paths); - SQLServerConnection.setColumnEncryptionTrustedMasterKeyPaths(trustedKeyPaths); - - SQLServerSecurityUtility.verifyColumnMasterKeyMetadata(connection, "My_KEYSTORE", "UnTrustedKeyPath", - serverName, true, null); - } catch (SQLServerException e) { - assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_UntrustedKeyPath"))); - } catch (Exception e) { - fail(TestResource.getResource("R_unexpectedException")); - } finally { - if (null != trustedKeyPaths) { - trustedKeyPaths.clear(); - SQLServerConnection.setColumnEncryptionTrustedMasterKeyPaths(trustedKeyPaths); - } - } - } - - /* - * Test getEnclavePackage with null enclaveSession - */ - @Test - public void testGetEnclavePackage() { - org.junit.Assume.assumeTrue(isAEv2); - - SQLServerVSMEnclaveProvider provider = new SQLServerVSMEnclaveProvider(); - try { - provider.getEnclavePackage(null, null); - } catch (SQLServerException e) { - fail(TestResource.getResource("R_unexpectedException")); - } - } - - /* - * Test invalidEnclaveSession - */ - @Test - public void testInvalidEnclaveSession() { - org.junit.Assume.assumeTrue(isAEv2); - - SQLServerVSMEnclaveProvider provider = new SQLServerVSMEnclaveProvider(); - provider.invalidateEnclaveSession(); - if (null != provider.getEnclaveSession()) { - fail(TestResource.getResource("R_invalidEnclaveSessionFailed")); - } - } - - /* - * Test VSM createSessionSecret with bad server response - */ - @Test - public void testNullSessionSecret() throws SQLServerException { - org.junit.Assume.assumeTrue(isAEv2); - - VSMAttestationParameters param = new VSMAttestationParameters(); - - try { - param.createSessionSecret(null); - } catch (SQLServerException e) { - assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_MalformedECDHPublicKey"))); - } catch (Exception e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /* - * Test bad session secret - */ - @Test - public void testBadSessionSecret() throws SQLServerException { - org.junit.Assume.assumeTrue(isAEv2); - - VSMAttestationParameters param = new VSMAttestationParameters(); - - try { - byte[] serverResponse = new byte[104]; // ENCLAVE_LENGTH is private - param.createSessionSecret(serverResponse); - } catch (SQLServerException e) { - assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_MalformedECDHHeader"))); - } catch (Exception e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /* - * Test null Attestation response - */ - @Test - public void testNullAttestationResponse() throws SQLServerException { - org.junit.Assume.assumeTrue(isAEv2); - - try { - AttestationResponse resp = new AttestationResponse(null); - } catch (SQLServerException e) { - assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_EnclaveResponseLengthError"))); - } catch (Exception e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /* - * Test bad Attestation response - */ - @Test - public void testBadAttestationResponse() throws SQLServerException { - org.junit.Assume.assumeTrue(isAEv2); - - try { - byte[] responseBytes = new byte[36]; - AttestationResponse resp = new AttestationResponse(responseBytes); - } catch (SQLServerException e) { - assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_HealthCertError"))); - } catch (Exception e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /* - * Test bad certificate signature - */ - @Test - public void testBadCertSignature() throws SQLServerException, CertificateException { - org.junit.Assume.assumeTrue(isAEv2); - - try { - AttestationResponse resp = new AttestationResponse(healthReportCertificate); - resp.validateCert(null); - } catch (SQLServerException e) { - assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidHealthCert"))); - } catch (Exception e) { - fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); - } - } - - /* - * Negative Test - AEv2 not supported - */ - @Tag(Constants.xSQLv15) - @Test - public void testAEv2NotSupported() { - org.junit.Assume.assumeFalse(isAEv2); - - try (SQLServerConnection con = PrepUtil.getConnection(connectionStringAE)) { - fail(TestResource.getResource("R_expectedExceptionNotThrown")); - } catch (SQLException e) { - assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_enclaveNotSupported"))); - } catch (Exception e) { - fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); - } - } - - /* - * Test invalid properties - */ - private void testInvalidProperties(String connStr, String resourceKeyword) { - try (Connection con = PrepUtil.getConnection(connStr)) { - fail(TestResource.getResource("R_expectedFailPassed")); - } catch (SQLException e) { - assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg(resourceKeyword)), e.getMessage()); - } - } - - /* - * Verify if Enclave is enabled - */ - private void verifyEnclaveEnabled(Connection con) throws SQLException { - try (Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery( - "SELECT [name], [value], [value_in_use] FROM sys.configurations WHERE [name] = 'column encryption enclave type';")) { - while (rs.next()) { - assertEquals("1", rs.getString(2)); - } - } - } - - private void checkAEv2() { - boolean isAEv2 = false; - try (SQLServerConnection con = PrepUtil.getConnection(connectionStringAE)) { - isAEv2 = TestUtils.isAEv2(con); - } catch (SQLException e) { - isAEv2 = false; - } catch (Exception e) { - fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); - } - org.junit.Assume.assumeTrue(isAEv2); - } -} diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index cb3cd863a..6e4009533 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -173,8 +173,6 @@ public static void setUpConnection() throws TestAbortedException, Exception { AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationProtocol", enclaveAttestationProtocol); } - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "windowsKeyPath", - windowsKeyPath); dropAll(); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java index cf89c9611..f8b3e2971 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import java.security.cert.CertificateException; import java.sql.ParameterMetaData; import java.sql.PreparedStatement; import java.sql.SQLException; @@ -20,8 +21,10 @@ import org.junit.runner.RunWith; import org.opentest4j.TestAbortedException; +import com.microsoft.sqlserver.jdbc.EnclavePackageTest; import com.microsoft.sqlserver.jdbc.RandomData; import com.microsoft.sqlserver.jdbc.SQLServerConnection; +import com.microsoft.sqlserver.jdbc.SQLServerException; import com.microsoft.sqlserver.jdbc.SQLServerStatement; import com.microsoft.sqlserver.jdbc.TestResource; import com.microsoft.sqlserver.jdbc.TestUtils; @@ -31,21 +34,22 @@ /** - * Tests Enclave Decryption and encryption of values + * Tests Enclave decryption and encryption of values * */ @RunWith(JUnitPlatform.class) @Tag(Constants.xSQLv12) +@Tag(Constants.xSQLv14) @Tag(Constants.xAzureSQLDW) @Tag(Constants.xAzureSQLDB) @Tag(Constants.reqExternalSetup) public class EnclaveTest extends JDBCEncryptionDecryptionTest { private boolean nullable = false; + private static boolean isAEv2 = false; @BeforeAll public static void setupEnclave() throws TestAbortedException, Exception { - boolean isAEv2 = false; try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { isAEv2 = TestUtils.isAEv2(con); } catch (SQLException e) { @@ -55,10 +59,139 @@ public static void setupEnclave() throws TestAbortedException, Exception { } org.junit.Assume.assumeTrue(isAEv2); + + EnclavePackageTest.setupEnclave(); } /** - * Junit test case for char set string for string values + * Tests basic connection. + * + * @throws SQLException + * when an error occurs + */ + @Test + public void testBasicConnection() throws SQLException { + org.junit.Assume.assumeTrue(isAEv2); + + EnclavePackageTest.testBasicConnection(); + } + + /** + * Tests invalid connection property combinations. + */ + @Test + public void testInvalidProperties() { + org.junit.Assume.assumeTrue(isAEv2); + + EnclavePackageTest.testInvalidProperties(); + } + + /* + * Test calling verifyColumnMasterKeyMetadata for non enclave computation + */ + @Test + public void testVerifyCMKNoEnclave() { + EnclavePackageTest.testVerifyCMKNoEnclave(); + } + + /* + * Test calling verifyColumnMasterKeyMetadata with untrusted key path + */ + @Test + public void testVerifyCMKUntrusted() { + EnclavePackageTest.testVerifyCMKUntrusted(); + } + + /* + * Test getEnclavePackage with null enclaveSession + */ + @Test + public void testGetEnclavePackage() { + EnclavePackageTest.testGetEnclavePackage(); + } + + /* + * Test invalidEnclaveSession + */ + @Test + public void testInvalidEnclaveSession() { + EnclavePackageTest.testInvalidEnclaveSession(); + } + + /* + * Test VSM createSessionSecret with bad server response + */ + @Test + public void testNullSessionSecret() throws SQLServerException { + EnclavePackageTest.testNullSessionSecret(); + } + + /* + * Test bad session secret + */ + @Test + public void testBadSessionSecret() throws SQLServerException { + EnclavePackageTest.testBadSessionSecret(); + } + + /* + * Test null Attestation response + */ + @Test + public void testNullAttestationResponse() throws SQLServerException { + EnclavePackageTest.testNullAttestationResponse(); + } + + /* + * Test bad Attestation response + */ + @Test + public void testBadAttestationResponse() throws SQLServerException { + EnclavePackageTest.testBadAttestationResponse(); + } + + /* + * Test bad certificate signature + */ + @Test + public void testBadCertSignature() throws SQLServerException, CertificateException { + EnclavePackageTest.testBadCertSignature(); + } + + /* + * Negative Test - AEv2 not supported + */ + @Test + public void testAEv2NotSupported() { + org.junit.Assume.assumeFalse(isAEv2); + + EnclavePackageTest.testAEv2NotSupported(); + } + + /* + * Negative Test = AEv2 not enabled + */ + @Test + public void testAEv2Disabled() throws SQLException { + org.junit.Assume.assumeTrue(isAEv2); + + // connection string w/o AEv2 + String testConnectionString = TestUtils.removeProperty(AETestConnectionString, "enclaveAttestationUrl"); + testConnectionString = TestUtils.removeProperty(testConnectionString, "enclaveAttestationProtocol"); + + try (SQLServerConnection con = PrepUtil.getConnection(testConnectionString); + SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { + String[] values = createCharValues(nullable); + testChars(stmt, cekJks, charTable, values, TestCase.NORMAL, true); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (Throwable e) { + // testChars called fail() + assertTrue(e.getMessage().contains(TestResource.getResource("R_AlterAEv2Error"))); + } + } + + /** + * Test case for char set string for string values * * @throws SQLException */ @@ -72,9 +205,9 @@ public void testCharSpecificSetter() throws SQLException { testChars(stmt, cekAkv, charTable, values, TestCase.NORMAL, true); } } - + /** - * Junit test case for char set string for string values using windows certificate store + * Test case for char set string for string values using windows certificate store * * @throws SQLException */ @@ -91,7 +224,7 @@ public void testCharSpecificSetterWindows() throws SQLException { } /** - * Junit test case for char set object for string values + * Test case for char set object for string values * * @throws SQLException */ @@ -107,7 +240,7 @@ public void testCharSetObject() throws SQLException { } /** - * Junit test case for char set object for jdbc string values + * Test case for char set object for jdbc string values * * @throws SQLException */ @@ -123,10 +256,11 @@ public void testCharSetObjectWithJDBCTypes() throws SQLException { } /** - * Junit test case for char set string for null values + * Test case for char set string for null values * * @throws SQLException */ + @Test public void testCharSpecificSetterNull() throws SQLException { try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo); SQLServerStatement stmt = (SQLServerStatement) con.createStatement()) { @@ -138,7 +272,7 @@ public void testCharSpecificSetterNull() throws SQLException { } /** - * Junit test case for char set object for null values + * Test case for char set object for null values * * @throws SQLException */ @@ -154,7 +288,7 @@ public void testCharSetObjectNull() throws SQLException { } /** - * Junit test case for char set null for null values + * Test case for char set null for null values * * @throws SQLException */ @@ -170,7 +304,7 @@ public void testCharSetNull() throws SQLException { } /** - * Junit test case for binary set binary for binary values + * Test case for binary set binary for binary values * * @throws SQLException */ @@ -186,7 +320,7 @@ public void testBinarySpecificSetter() throws SQLException { } /** - * Junit test case for binary set binary for binary values using windows certificate store + * Test case for binary set binary for binary values using windows certificate store * * @throws SQLException */ @@ -203,7 +337,7 @@ public void testBinarySpecificSetterWindows() throws SQLException { } /** - * Junit test case for binary set object for binary values + * Test case for binary set object for binary values * * @throws SQLException */ @@ -219,7 +353,7 @@ public void testBinarySetobject() throws SQLException { } /** - * Junit test case for binary set null for binary values + * Test case for binary set null for binary values * * @throws SQLException */ @@ -235,7 +369,7 @@ public void testBinarySetNull() throws SQLException { } /** - * Junit test case for binary set binary for null values + * Test case for binary set binary for null values * * @throws SQLException */ @@ -251,7 +385,7 @@ public void testBinarySpecificSetterNull() throws SQLException { } /** - * Junit test case for binary set object for null values + * Test case for binary set object for null values * * @throws SQLException */ @@ -267,7 +401,7 @@ public void testBinarysetObjectNull() throws SQLException { } /** - * Junit test case for binary set object for jdbc type binary values + * Test case for binary set object for jdbc type binary values * * @throws SQLException */ @@ -283,7 +417,7 @@ public void testBinarySetObjectWithJDBCTypes() throws SQLException { } /** - * Junit test case for date set date for date values + * Test case for date set date for date values * * @throws SQLException */ @@ -299,7 +433,7 @@ public void testDateSpecificSetter() throws SQLException { } /** - * Junit test case for date set date for date values using windows certificate store + * Test case for date set date for date values using windows certificate store * * @throws SQLException */ @@ -314,9 +448,9 @@ public void testDateSpecificSetterWindows() throws SQLException { testDates(stmt, cekWin, dateTable, values, TestCase.NORMAL, true); } } - + /** - * Junit test case for date set object for date values + * Test case for date set object for date values * * @throws SQLException */ @@ -332,7 +466,7 @@ public void testDateSetObject() throws SQLException { } /** - * Junit test case for date set object for java date values + * Test case for date set object for java date values * * @throws SQLException */ @@ -348,7 +482,7 @@ public void testDateSetObjectWithJavaType() throws SQLException { } /** - * Junit test case for date set object for jdbc date values + * Test case for date set object for jdbc date values * * @throws SQLException */ @@ -364,7 +498,7 @@ public void testDateSetObjectWithJDBCType() throws SQLException { } /** - * Junit test case for date set date for min/max date values + * Test case for date set date for min/max date values * * @throws SQLException */ @@ -381,7 +515,7 @@ public void testDateSpecificSetterMinMaxValue() throws SQLException { } /** - * Junit test case for date set date for null values + * Test case for date set date for null values * * @throws SQLException */ @@ -402,7 +536,7 @@ public void testDateSetNull() throws SQLException { } /** - * Junit test case for date set object for null values + * Test case for date set object for null values * * @throws SQLException */ @@ -424,7 +558,7 @@ public void testDateSetObjectNull() throws SQLException { } /** - * Junit test case for numeric set numeric for numeric values + * Test case for numeric set numeric for numeric values * * @throws SQLException */ @@ -443,7 +577,7 @@ public void testNumericSpecificSetter() throws TestAbortedException, Exception { } /** - * Junit test case for numeric set numeric for numeric values using windows certificate store + * Test case for numeric set numeric for numeric values using windows certificate store * * @throws SQLException */ @@ -461,9 +595,9 @@ public void testNumericSpecificSetterWindows() throws TestAbortedException, Exce testNumerics(stmt, cekWin, numericTable, values1, values2, TestCase.NORMAL, true); } } - + /** - * Junit test case for numeric set object for numeric values + * Test case for numeric set object for numeric values * * @throws SQLException */ @@ -481,7 +615,7 @@ public void testNumericSetObject() throws SQLException { } /** - * Junit test case for numeric set object for jdbc type numeric values + * Test case for numeric set object for jdbc type numeric values * * @throws SQLException */ @@ -499,7 +633,7 @@ public void testNumericSetObjectWithJDBCTypes() throws SQLException { } /** - * Junit test case for numeric set numeric for max numeric values + * Test case for numeric set numeric for max numeric values * * @throws SQLException */ @@ -523,7 +657,7 @@ public void testNumericSpecificSetterMaxValue() throws SQLException { } /** - * Junit test case for numeric set numeric for min numeric values + * Test case for numeric set numeric for min numeric values * * @throws SQLException */ @@ -546,7 +680,7 @@ public void testNumericSpecificSetterMinValue() throws SQLException { } /** - * Junit test case for numeric set numeric for null values + * Test case for numeric set numeric for null values * * @throws SQLException */ @@ -569,7 +703,7 @@ public void testNumericSpecificSetterNull() throws SQLException { } /** - * Junit test case for numeric set object for null values + * Test case for numeric set object for null values * * @throws SQLException */ @@ -592,7 +726,7 @@ public void testNumericSpecificSetterSetObjectNull() throws SQLException { } /** - * Junit test case for numeric set numeric for null normalization values + * Test case for numeric set numeric for null normalization values * * @throws SQLException */ @@ -612,6 +746,11 @@ public void testNumericNormalization() throws SQLException { } } + /** + * Test FMTOnly with Always Encrypted + * + * @throws SQLException + */ @Test public void testAEFMTOnly() throws SQLException { try (SQLServerConnection c = PrepUtil.getConnection(AETestConnectionString + ";useFmtOnly=true", AEInfo); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java new file mode 100644 index 000000000..8d4a21f51 --- /dev/null +++ b/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java @@ -0,0 +1,447 @@ +package com.microsoft.sqlserver.jdbc; + +import static org.junit.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.security.cert.CertificateException; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.logging.LogManager; + +import org.junit.jupiter.api.Tag; +import org.junit.platform.runner.JUnitPlatform; +import org.junit.runner.RunWith; + +import com.microsoft.sqlserver.testframework.AbstractTest; +import com.microsoft.sqlserver.testframework.Constants; +import com.microsoft.sqlserver.testframework.PrepUtil; + + +/** + * A class for testing basic NTLMv2 functionality. + */ +@RunWith(JUnitPlatform.class) +@Tag(Constants.xSQLv14) +@Tag(Constants.xAzureSQLDW) +@Tag(Constants.xAzureSQLDB) +@Tag(Constants.reqExternalSetup) +public class EnclavePackageTest extends AbstractTest { + + private static SQLServerDataSource dsLocal = null; + private static SQLServerDataSource dsXA = null; + private static SQLServerDataSource dsPool = null; + + private static String connectionStringEnclave; + + private static byte[] healthReportCertificate = {61, 11, 0, 0, 27, 2, 0, 0, -66, 3, 0, 0, 88, 5, 0, 0, 82, 83, 65, + 49, 0, 16, 0, 0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -57, 59, -80, 116, -86, -109, -4, + -96, -106, -85, 107, 22, 88, 29, 91, -50, 29, -44, -36, -109, -123, 57, 70, -41, 110, -85, 90, 49, -17, 100, + -49, 96, -34, 89, -76, -59, -82, 100, 118, -9, 44, 86, -112, 44, 13, 36, -43, 3, -69, -46, -6, -126, 26, + -74, 75, -89, 82, -111, 72, -1, 127, 78, -80, 102, -126, 51, -89, 12, 70, 107, 50, 126, -40, -6, 51, 13, 87, + 5, 79, -53, -66, 26, 126, -128, -82, 97, 103, 7, 62, 49, -66, -97, -115, 113, -88, -73, 127, 102, -21, -51, + 79, 8, 101, -76, 15, -29, 0, -83, -42, -12, 52, 106, -60, 62, -67, 5, -7, -91, -21, -60, 4, -52, -39, 59, + -100, 127, 5, -55, 93, 9, 89, 83, 14, 85, -9, -33, -5, 75, 42, -81, 123, -117, -73, -50, 15, 59, -35, -35, + -74, -113, 41, -74, -41, 51, -3, 88, 110, 44, 3, -31, -36, 94, 29, 82, 12, -119, -34, 72, -51, 59, -109, + -92, 44, 24, 75, 78, 84, 64, -86, -43, 11, 23, 70, 124, 33, -90, 60, -85, -63, -23, -70, 79, 62, 13, -121, + -45, 53, 107, -49, 104, -85, -80, 7, -84, 61, -93, 44, -87, -68, -101, -7, -43, -65, 90, -12, -12, 16, 104, + 26, 5, -103, -32, -84, -80, -26, 17, -29, 30, -46, 127, 44, -70, -87, 61, -35, 47, -62, 86, -23, 114, 0, + -19, 38, -25, 90, -6, -1, -121, -69, 51, 74, -95, 64, -67, 6, 49, 35, -125, -5, -40, -115, 1, -31, -51, 64, + -102, -51, 106, 111, 38, 124, -111, 25, -75, 7, -116, -111, -120, 82, 103, 112, 14, 32, -49, -87, 23, 31, + -14, -107, -64, -76, 9, -40, -37, 127, -99, 67, -114, 114, -3, -62, 7, -88, 103, -89, 124, 125, -14, -21, + 59, 91, 112, 13, 35, -80, -103, -79, 6, 41, -110, 8, -15, -58, 95, -101, 43, -8, 106, -50, -87, -32, 93, + -30, -31, -105, 69, -73, 57, -38, 75, 42, 120, -75, -49, 77, 76, -120, -14, -42, -44, -34, 8, -4, -98, -35, + 46, -23, 16, -83, -6, 115, -127, 117, 54, -25, 58, -106, 10, 85, 54, -105, 48, 62, -55, 70, 56, 115, -121, + 31, -4, 113, 21, -98, 53, 118, 31, -82, 122, -29, 41, 59, -112, -123, -114, -26, 54, -45, 106, 77, 79, 2, + -63, -37, 53, 42, -26, -24, -60, 88, -80, 22, 55, -37, -114, 99, -58, 113, 87, 26, -70, 105, -70, -78, -48, + 26, 51, 10, -37, -105, 66, 3, -69, 38, -56, 34, 77, -98, 56, 15, 0, 85, -63, -67, -102, -116, -49, -85, 22, + -70, 68, -31, 99, 23, -100, -33, -45, -49, -90, 104, -26, -5, -32, 100, 81, -117, -60, -7, -59, 84, -8, + -101, 86, 88, -100, 107, -65, -11, -5, 41, 96, -76, 24, 68, -105, -18, -99, -10, -15, 26, -43, 91, -86, 33, + -17, -19, -6, -89, 78, -123, 48, 47, -107, 36, -2, -33, 123, -124, 91, 123, -20, -88, 73, 48, -126, 3, -70, + 48, -126, 2, -94, -96, 3, 2, 1, 2, 2, 16, 66, 85, -66, 31, 39, 20, 120, -95, 75, 114, 74, -14, 59, 52, 99, + -29, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 11, 5, 0, 48, 47, 49, 45, 48, 43, 6, 3, 85, 4, 3, 12, + 36, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 82, 101, 109, 111, 116, 101, 32, 65, 116, 116, 101, 115, + 116, 97, 116, 105, 111, 110, 32, 83, 101, 114, 118, 105, 99, 101, 48, 30, 23, 13, 49, 57, 49, 48, 51, 48, + 49, 56, 50, 50, 52, 55, 90, 23, 13, 49, 57, 49, 48, 51, 49, 48, 50, 50, 50, 52, 56, 90, 48, 75, 49, 73, 48, + 71, 6, 3, 85, 4, 3, 12, 64, 65, 49, 57, 67, 49, 56, 70, 51, 50, 53, 49, 56, 66, 56, 65, 57, 51, 70, 49, 57, + 52, 57, 69, 66, 57, 69, 56, 53, 48, 68, 56, 53, 66, 66, 53, 53, 65, 67, 69, 65, 49, 56, 67, 53, 54, 55, 49, + 70, 55, 55, 65, 69, 49, 54, 51, 54, 56, 52, 51, 55, 68, 65, 53, 56, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122, + 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -50, -20, -124, 102, + 67, -52, 79, -43, 5, -104, 31, 99, -89, 53, -77, 61, 82, 64, -125, -30, 32, 102, 101, -87, 63, -75, -10, + -100, -31, -125, 15, -9, -40, 81, 8, 54, -43, 112, 91, -19, 126, 49, -57, 33, -51, -33, -82, 21, 22, 4, -68, + 112, 83, -55, -50, 60, -70, 1, -37, -60, 3, -75, 63, 124, -3, -112, 107, -120, -122, -97, 26, -28, 62, -101, + -21, -66, 28, -84, 23, 21, -126, 27, -9, 45, 43, 50, 1, -117, 28, -114, -99, -38, 38, -104, 7, -45, 85, + -100, -44, -102, 68, -6, -22, -45, -75, 84, -33, -11, -76, -9, 42, -1, 82, -21, -12, 18, -15, 118, -121, + 124, 103, -85, 43, 54, -106, 77, 102, 0, -107, -12, 103, 10, 118, -85, 23, 40, -61, -39, 76, 39, -124, 75, + -121, -114, -65, -119, -42, -75, 42, -110, -71, 94, 61, -125, 104, 105, -119, 74, -83, 57, -11, -38, -120, + -94, -100, -58, -85, 106, 124, 50, 30, 118, -102, 1, -123, -119, -81, 111, 6, 18, -114, 61, -35, 64, 99, + -53, 16, -56, -8, -18, -110, 96, -85, 125, 95, 60, 0, -58, -81, -30, 54, 39, 73, 100, -27, 14, 5, -45, 122, + 120, -33, -48, -62, -43, 98, 9, -5, -12, 4, -6, -57, -113, -28, 117, -26, 50, 76, 65, -107, 109, 49, -9, + -22, 86, 103, 68, -128, -87, -116, 25, -117, 114, 28, -9, 28, 70, -28, -36, 102, -27, 40, 120, 60, -113, + -11, -73, 2, 3, 1, 0, 1, -93, -127, -75, 48, -127, -78, 48, 14, 6, 3, 85, 29, 15, 1, 1, -1, 4, 4, 3, 2, 7, + -128, 48, 29, 6, 9, 43, 6, 1, 4, 1, -126, 55, 21, 10, 4, 16, 48, 14, 48, 12, 6, 10, 43, 6, 1, 4, 1, -126, + 55, 48, 1, 2, 48, 25, 6, 3, 85, 29, 14, 4, 18, 4, 16, 49, 110, 105, 97, 22, -114, 85, -99, 21, -32, -60, + -109, 42, -59, 66, 11, 48, 102, 6, 3, 85, 29, 35, 4, 95, 48, 93, -128, 20, 37, -118, -59, 87, -8, 105, 88, + 79, -36, 20, -127, -8, -56, -9, 97, -10, 105, -80, -109, -93, -95, 51, -92, 49, 48, 47, 49, 45, 48, 43, 6, + 3, 85, 4, 3, 12, 36, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 82, 101, 109, 111, 116, 101, 32, 65, + 116, 116, 101, 115, 116, 97, 116, 105, 111, 110, 32, 83, 101, 114, 118, 105, 99, 101, -126, 16, 37, 113, + -89, -86, -71, 42, -44, -83, 67, -30, 8, -31, 97, 14, -40, -12, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, + 1, 11, 5, 0, 3, -126, 1, 1, 0, -85, -56, -125, -91, 83, -96, -32, -69, -69, -40, -127, -93, 69, 24, -7, + -121, 54, 30, 76, 20, 28, -95, 93, -76, -109, -4, -97, -102, 126, 76, -68, -39, 6, -66, 70, -100, 67, -112, + 25, -109, -2, -83, 40, 86, 69, -70, -105, 40, 88, 109, -101, 64, 95, -60, -49, -25, -42, 61, -37, 18, -3, + -64, -68, -123, 111, 7, 119, 107, 81, 40, -103, 66, 42, 110, 81, 95, -38, 104, 109, -92, -90, 6, -120, -113, + 53, -8, -116, -44, -90, -3, 103, 100, 78, 90, 96, -121, 80, -105, 109, 28, -28, -63, 75, 14, -98, 83, -122, + 78, -70, 83, 4, 11, -107, 115, 50, 78, -37, -88, 62, -72, 4, 26, 6, 102, -65, -39, -48, 58, -72, 36, 125, + 29, -27, -6, -42, 111, 57, -97, 102, 3, -5, 112, 62, -13, -65, -4, 40, -103, 19, -75, 82, -83, -26, -12, 62, + -41, -38, -70, -85, 22, 100, 34, 0, 90, 68, -33, -107, 40, -63, -9, 38, 99, -89, 15, 118, 14, -33, -2, -18, + -98, -105, 23, 31, 92, -46, -68, -61, 103, 47, -121, 73, -8, -82, -28, 43, 0, 50, 78, 78, 68, 88, -91, 121, + -29, 30, -25, 23, 88, 43, -72, -49, -77, 92, -62, -8, 85, -86, -111, 99, -37, -46, -121, 34, 122, 118, 9, + -27, 57, -56, 59, 44, 62, -115, -41, -49, -73, -59, 122, 39, -69, 76, 122, 127, -21, 113, 43, -21, -109, 95, + 98, 38, 33, 111, -34, -38, 71, 88, 5, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 64, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 64, + 4, 0, 0, 1, 0, 0, 0, 14, 60, -81, -73, 81, 79, 109, 37, -78, -54, -47, -115, 69, -20, -28, -70, -75, 43, 5, + -75, -42, 70, -27, 53, -124, -35, 61, 45, -90, -38, 41, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 32, 48, 64, 65, 49, 33, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -108, -76, 101, 116, -38, -69, -79, 113, -122, -19, -59, 38, + 60, -76, -34, 123, -10, -39, -30, -21, -122, -122, 34, 32, 90, -108, -45, -109, -44, -52, 101, -127, 4, 55, + -54, -30, 83, 125, -117, -101, 7, 118, -74, 27, 17, -26, -50, -45, -46, 50, -23, 48, -113, 96, -30, 26, -38, + -78, -3, -111, -29, -38, -107, -104, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 23, 18, 0, 1, 5, + 32, 19, 0, 5, 20, 3, 18, 1, 34, 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, -112, 0, 0, 0, -108, -76, 101, 116, -38, -69, -79, 113, -122, -19, -59, 38, 60, -76, -34, 123, + -10, -39, -30, -21, -122, -122, 34, 32, 90, -108, -45, -109, -44, -52, 101, -127, 4, 55, -54, -30, 83, 125, + -117, -101, 7, 118, -74, 27, 17, -26, -50, -45, -46, 50, -23, 48, -113, 96, -30, 26, -38, -78, -3, -111, + -29, -38, -107, -104, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 23, 18, 0, 1, 5, 32, 19, 0, 5, + 20, 3, 18, 1, 34, 5, 0, 0, 0, 0, 97, 0, 101, 0, 116, 0, 109, 0, 45, 0, 101, 0, 110, 0, 99, 0, 108, 0, 97, 0, + 118, 0, 101, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, 1, 0, 0, 0, -120, 0, 0, 0, 90, -58, -49, 7, 59, + -65, 81, -44, -97, -107, 97, -106, 71, -70, 33, -5, 99, -7, -4, -117, -31, -91, -35, -56, -12, -105, -29, + 80, 5, 72, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 39, -67, 104, 117, 89, 73, -73, -66, 6, 52, 80, + -30, 22, -41, -19, 0, 0, 0, 0, 98, 0, 99, 0, 114, 0, 121, 0, 112, 0, 116, 0, 46, 0, 100, 0, 108, 0, 108, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -104, 0, 0, 0, -76, 15, 80, 111, -51, 57, 8, -54, -53, -109, -113, -106, + 35, -72, -114, -12, -128, -17, 51, -64, -124, -38, -55, 27, 1, 80, 69, 48, -96, -77, -128, 58, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -16, 60, -51, -89, -24, 123, 70, -21, -86, -25, 31, 19, -43, -51, -34, 93, 0, 0, 0, + 0, 117, 0, 99, 0, 114, 0, 116, 0, 98, 0, 97, 0, 115, 0, 101, 0, 95, 0, 101, 0, 110, 0, 99, 0, 108, 0, 97, 0, + 118, 0, 101, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, 1, 0, 0, 0, -120, 0, 0, 0, -41, 110, -101, -107, + 45, -49, 11, 25, -47, 17, 90, 38, -28, 105, -88, 110, 39, -35, -15, -94, -106, 14, -37, -70, -105, -14, 59, + -88, 80, 30, -112, -91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, -124, 65, 114, 103, -88, 78, -115, -65, 1, + 40, 75, 7, 67, 43, 30, 0, 0, 0, 0, 118, 0, 101, 0, 114, 0, 116, 0, 100, 0, 108, 0, 108, 0, 46, 0, 100, 0, + 108, 0, 108, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -112, 0, 0, 0, 20, -54, 74, 74, 43, -64, -12, 60, -101, -67, + -58, -102, 71, -124, 113, -46, 92, -63, 11, -104, 100, -6, -126, 9, 3, 16, -36, 57, 24, -22, 8, 122, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 122, 0, + 117, 0, 114, 0, 101, 0, 65, 0, 116, 0, 116, 0, 101, 0, 115, 0, 116, 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, -104, 0, 0, 0, -54, 68, -119, -29, 65, -104, -2, 53, -48, -27, -20, 25, 8, -72, -43, + 124, -63, 9, 126, -58, -100, 14, -41, -75, 61, -66, -28, 80, 67, 17, -109, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 77, 19, -65, 62, 83, 100, 65, 48, -86, -102, -64, -14, -31, -12, -58, 36, 0, 0, 0, 0, 98, 0, 99, 0, + 114, 0, 121, 0, 112, 0, 116, 0, 80, 0, 114, 0, 105, 0, 109, 0, 105, 0, 116, 0, 105, 0, 118, 0, 101, 0, 115, + 0, 46, 0, 100, 0, 108, 0, 108, 0, 0, 0, 0, 0, -107, 11, 37, -57, 57, -18, -111, 70, 53, -83, -117, 111, -63, + 65, -80, -4, -3, -36, 27, 35, 111, -91, 54, -34, 103, 41, -5, -79, 8, -36, -124, 101, 103, 90, -115, -21, + 40, 49, 33, 61, 85, -104, 67, 5, -26, -78, -27, -78, -92, -70, 115, -77, -98, 39, -101, 58, 35, -21, -51, + 83, -4, 80, 125, 39, -117, -75, 50, -71, 125, -44, 28, 41, 25, 67, -4, 3, -120, -89, -124, -19, 94, -81, 31, + 114, -91, 117, -9, 6, 85, 32, 16, -16, -28, 59, 108, 67, -77, -126, 42, 25, 7, -46, 40, -32, 52, 51, -60, + 120, 28, 1, 89, -1, 51, -96, 105, 93, -111, -8, -25, 9, 55, -120, 37, -63, -6, -66, 11, -16, -34, -71, -18, + 67, -74, 86, -98, -15, -56, -76, 86, 10, -6, 13, -9, 24, -9, -94, -93, 127, -63, -69, 86, -73, -57, 91, + -108, -11, 70, 77, -80, -39, 70, -14, -61, 39, -45, -83, 46, 17, 126, -104, 10, -117, 46, -60, -122, 12, 20, + -117, 30, 105, -80, -67, -48, -4, -57, -98, 95, 102, -85, 36, 29, -61, -93, -91, 67, -61, 76, -54, -60, 77, + 95, -79, -126, -66, 110, -32, -8, -45, -108, 42, -101, 102, -99, 104, -33, 74, -43, -124, -47, 81, -58, 118, + 112, -80, -9, 2, -40, 77, 40, 122, 16, 48, 111, -98, 78, 80, -122, 99, -29, -125, -78, -104, -36, -94, -95, + -115, -110, 31, -108, -46, 88, 79, -103, -65, 90, -13, 120, 2, 0, 0, 19, 0, 0, 0, 75, 1, 0, 0, 104, 0, 0, 0, + 0, 2, 0, 0, 69, 67, 75, 51, 48, 0, 0, 0, 38, -81, -37, -121, 34, 74, 31, -103, -95, 62, 72, -29, 19, -105, + -124, -112, 71, 6, 64, 98, -73, -85, -49, -21, -63, -67, -69, 2, 56, 36, 116, -49, -24, -123, 24, 43, 69, + -62, -126, -94, 80, 113, 114, 60, -44, -48, -44, -83, -13, -104, -69, 57, -26, 41, 65, -15, 97, -65, 26, + -41, 32, -125, -50, 52, -18, 15, -91, 98, -4, -52, 88, -34, -61, -32, 126, -40, 63, 2, 113, -11, 92, 69, 3, + -118, -52, 50, -30, 52, -105, -36, -95, -18, 17, 99, 107, -105, 17, -104, -125, 34, 11, -44, 7, 79, 35, 24, + -2, -27, -43, -21, 115, 52, 44, -45, -68, -122, 100, -55, -79, 14, -79, 81, 49, 81, -3, -43, -89, -118, 116, + 76, 13, -117, 16, -1, 46, -62, 40, 21, 97, 63, 43, -65, 45, 101, 30, 2, 66, 15, -20, -53, -112, 23, 120, + -12, -31, -79, -33, 89, -83, 95, -110, -67, -58, -86, 118, 28, 84, 22, 79, -69, -41, -78, 88, 31, 73, 97, + 71, -109, -127, -22, 14, 113, -65, 51, 11, 34, -23, -61, 107, 114, -109, 58, 9, 104, 120, -36, -93, 70, 104, + -79, -46, 13, -15, -62, -61, -62, -16, 19, -79, 4, 121, -63, 61, -100, -66, 25, -23, 117, -119, -97, -84, + 15, 99, -101, 59, -18, -81, -67, -99, -20, -82, -41, 74, -19, -54, -86, -58, 121, -7, -8, -8, 11, 113, -52, + -50, 14, -102, -77, -105, 126, -110, 85, -97, 75, -24, -33, -63, 48, 79, 67, 84, 73, 54, 49, -104, 38, 13, + -100, 76, 66, 86, 72, -120, 100, 33, -5, -26, 107, 79, -48, -1, 71, 104, 22, 115, 66, -94, 73, 88, -48, 71, + 44, 118, 15, -76, -98, -74, -78, 43, 33, 120, -74, -87, 78, 31, 36, 96, -104, -98, -28, 121, -128, -8, -77, + -16, -74, -94, -101, -57, 99, -78, 70, 108, -26, 115, 21, -13, -41, 46, -93, -68, 29, 76, 68, 109, -63, 108, + 27, -112, -20, -53, 92, 109, 121, 33, 64, 69, 42, -72, -45, 35, 50, 60, -124, -99, -40, -7, -96, -57, -14, + -71, -103, -44, 13, 69, -89, -17, -46, -128, -5, -83, 80, -125, 13, -48, -126, 49, 62, 37, 113, -92, -30, + 15, 47, 113, 124, 108, -89, -48, -4, -84, -61, -11, -55, -97, -28, 36, 20, -106, 57, -16, 107, 51, 67, -95, + -73, -76, -8, -118, 97, 127, -20, 67, 103, 25, 3, -67, 41, 73, 122, 92, -9, 22, 69, -91, -107, 52, -23, + -119, -56, 71, -76, 77, -51, 12, -72, 117, -48, 108, -100, -77, -103, 114, 45, 100, 100, -11, 55, 124, -121, + -102, -105, 22, 4, -33, 76, 68, 116, -96, -80, 43, 5, -119, -113, 44, 66, -128, -104, 60, -78, -123, 56, + -36, -99, -63, 71, 25, -15, 17, -8, -71, -8, -37, 92, 70, 127, 33, 69, -34, 11, -9, 38, 127, -46, -10, 112, + 126, -7, -77, 16, -32, -42, 118, -110, 98, -112, 78, -95, 56, -45, -46, -108, -54, 116, 99, 107, 78, -92, + -60, 72, -45, -40, 33, -93, -21, -90, -108, -19, 89, -42, 29, -123, 35, -114, -95, -37, 2, -61, 12, 84, + -100, -100, 112, -96, 80, 12, 90, 78, 36, 40, -56, -90, -60, -77, -77, -56, 53, -93, -10, -22, -47, 15, 5, + -90, -67, 111, -82, -94, 96, -68, -79, -3, -51, -108, 41, 112, -89, 22, -92, 88, 37, 66, 20, 93, 111, 102, + -69, -20, -47, -43, -24, 82, -41, 12, -58, 53, 68, -76, -94, -116, 75, 14, 24, -43, 73, -78, -87, 21}; + + /** + * Setup environment for test. + * + * @throws Exception + * when an error occurs + */ + public static void setupEnclave() throws Exception { + connectionStringEnclave = TestUtils.addOrOverrideProperty(connectionString, "columnEncryptionSetting", + ColumnEncryptionSetting.Enabled.toString()); + + String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); + connectionStringEnclave = TestUtils.addOrOverrideProperty(connectionStringEnclave, "enclaveAttestationUrl", + (null != enclaveAttestationUrl) ? enclaveAttestationUrl : "http://blah"); + + String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); + connectionStringEnclave = TestUtils.addOrOverrideProperty(connectionStringEnclave, "enclaveAttestationProtocol", + (null != enclaveAttestationProtocol) ? enclaveAttestationProtocol : AttestationProtocol.HGS.toString()); + + // reset logging to avoid severe logs due to negative testing + LogManager.getLogManager().reset(); + + dsLocal = new SQLServerDataSource(); + AbstractTest.updateDataSource(connectionStringEnclave, dsLocal); + + dsXA = new SQLServerXADataSource(); + AbstractTest.updateDataSource(connectionStringEnclave, dsXA); + + dsPool = new SQLServerConnectionPoolDataSource(); + AbstractTest.updateDataSource(connectionStringEnclave, dsPool); + } + + /** + * Tests basic connection. + * + * @throws SQLException + * when an error occurs + */ + public static void testBasicConnection() throws SQLException { + try (Connection con1 = dsLocal.getConnection(); Connection con2 = dsXA.getConnection(); + Connection con3 = dsPool.getConnection(); + Connection con4 = PrepUtil.getConnection(connectionStringEnclave)) { + if (TestUtils.isAEv2(con1)) { + verifyEnclaveEnabled(con1); + } + if (TestUtils.isAEv2(con2)) { + verifyEnclaveEnabled(con2); + } + if (TestUtils.isAEv2(con3)) { + verifyEnclaveEnabled(con3); + } + if (TestUtils.isAEv2(con4)) { + verifyEnclaveEnabled(con4); + } + } + } + + /** + * Tests invalid connection property combinations. + */ + public static void testInvalidProperties() { + // enclaveAttestationUrl and enclaveAttestationProtocol without "columnEncryptionSetting" + testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringEnclave, "columnEncryptionSetting", + ColumnEncryptionSetting.Disabled.toString()), "R_enclavePropertiesError"); + + // enclaveAttestationUrl without enclaveAttestationProtocol + testInvalidProperties(TestUtils.removeProperty(connectionStringEnclave, "enclaveAttestationProtocol"), + "R_enclavePropertiesError"); + + // enclaveAttestationProtocol without enclaveAttestationUrl + testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringEnclave, "enclaveAttestationUrl", ""), + "R_enclavePropertiesError"); + + // bad enclaveAttestationProtocol + testInvalidProperties( + TestUtils.addOrOverrideProperty(connectionStringEnclave, "enclaveAttestationProtocol", ""), + "R_enclaveInvalidAttestationProtocol"); + } + + /* + * Test calling verifyColumnMasterKeyMetadata for non enclave computation + */ + public static void testVerifyCMKNoEnclave() { + try { + SQLServerColumnEncryptionJavaKeyStoreProvider jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider( + "keystore", null); + assertFalse(jksp.verifyColumnMasterKeyMetadata(null, false, null)); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + + try { + SQLServerColumnEncryptionAzureKeyVaultProvider aksp = new SQLServerColumnEncryptionAzureKeyVaultProvider("", + ""); + assertFalse(aksp.verifyColumnMasterKeyMetadata(null, false, null)); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /* + * Test calling verifyColumnMasterKeyMetadata with untrusted key path + */ + public static void testVerifyCMKUntrusted() { + Map> trustedKeyPaths = null; + try { + trustedKeyPaths = SQLServerConnection.getColumnEncryptionTrustedMasterKeyPaths(); + List paths = new ArrayList(); + paths.add(javaKeyPath); + String serverName = connection.activeConnectionProperties + .getProperty(SQLServerDriverStringProperty.SERVER_NAME.toString()).toUpperCase(); + + trustedKeyPaths.put(serverName, paths); + SQLServerConnection.setColumnEncryptionTrustedMasterKeyPaths(trustedKeyPaths); + + SQLServerSecurityUtility.verifyColumnMasterKeyMetadata(connection, "My_KEYSTORE", "UnTrustedKeyPath", + serverName, true, null); + fail(TestResource.getResource("R_expectedFailPassed")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_UntrustedKeyPath"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException")); + } finally { + if (null != trustedKeyPaths) { + trustedKeyPaths.clear(); + SQLServerConnection.setColumnEncryptionTrustedMasterKeyPaths(trustedKeyPaths); + } + } + } + + /* + * Test getEnclavePackage with null enclaveSession + */ + public static void testGetEnclavePackage() { + SQLServerVSMEnclaveProvider provider = new SQLServerVSMEnclaveProvider(); + try { + byte[] b = provider.getEnclavePackage(null, null); + assertTrue(b == null); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException")); + } + } + + /* + * Test invalidEnclaveSession + */ + public static void testInvalidEnclaveSession() { + SQLServerVSMEnclaveProvider provider = new SQLServerVSMEnclaveProvider(); + provider.invalidateEnclaveSession(); + if (null != provider.getEnclaveSession()) { + fail(TestResource.getResource("R_invalidEnclaveSessionFailed")); + } + } + + /* + * Test VSM createSessionSecret with bad server response + */ + public static void testNullSessionSecret() throws SQLServerException { + VSMAttestationParameters param = new VSMAttestationParameters(); + + try { + param.createSessionSecret(null); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_MalformedECDHPublicKey"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /* + * Test bad session secret + */ + public static void testBadSessionSecret() throws SQLServerException { + VSMAttestationParameters param = new VSMAttestationParameters(); + + try { + byte[] serverResponse = new byte[104]; // ENCLAVE_LENGTH is private + param.createSessionSecret(serverResponse); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_MalformedECDHHeader"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /* + * Test null Attestation response + */ + @SuppressWarnings("unused") + public static void testNullAttestationResponse() throws SQLServerException { + try { + AttestationResponse resp = new AttestationResponse(null); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_EnclaveResponseLengthError"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /* + * Test bad Attestation response + */ + @SuppressWarnings("unused") + public static void testBadAttestationResponse() throws SQLServerException { + try { + byte[] responseBytes = new byte[36]; + AttestationResponse resp = new AttestationResponse(responseBytes); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_HealthCertError"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /* + * Test bad certificate signature + */ + public static void testBadCertSignature() throws SQLServerException, CertificateException { + try { + AttestationResponse resp = new AttestationResponse(healthReportCertificate); + resp.validateCert(null); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidHealthCert"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /* + * Negative Test - AEv2 not supported + */ + public static void testAEv2NotSupported() { + try (SQLServerConnection con = PrepUtil.getConnection(connectionStringEnclave)) { + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_enclaveNotSupported"))); + } catch (Exception e) { + fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); + } + } + + /* + * Test invalid properties + */ + private static void testInvalidProperties(String connStr, String resourceKeyword) { + try (Connection con = PrepUtil.getConnection(connStr)) { + fail(TestResource.getResource("R_expectedFailPassed")); + } catch (SQLException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg(resourceKeyword)), e.getMessage()); + } + } + + /* + * Verify if Enclave is enabled + */ + private static void verifyEnclaveEnabled(Connection con) throws SQLException { + try (Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery( + "SELECT [name], [value], [value_in_use] FROM sys.configurations WHERE [name] = 'column encryption enclave type';")) { + while (rs.next()) { + assertEquals("1", rs.getString(2)); + } + } + } +} From cb88339be7a191f5419f9dcbba11a8fc657f3df4 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 13 Nov 2019 12:17:09 -0800 Subject: [PATCH 44/49] merged --- azure-pipelines.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 16a6c5394..228df2086 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -16,11 +16,6 @@ jobs: Ex_Groups: 'xSQLv12' maxParallel: 2 steps: - - task: DownloadSecureFile@1 - name: sqljdbc_auth - displayName: 'Download sqljdbc_auth.dll' - inputs: - secureFile: 'sqljdbc_auth.dll' - powershell: | mkdir AE_Certificates cd AE_Certificates @@ -33,7 +28,6 @@ jobs: keytool -list -v -keystore clientcert.jks -storepass $(certPass) > JavaKeyStoreBase.txt Get-Content .\JavaKeyStoreBase.txt | Set-Content -Encoding utf8 JavaKeyStore.txt Remove-Item –path .\JavaKeyStoreBase.txt - Copy-Item -Path $(sqljdbc_auth.secureFilePath) -Destination "C:\Windows\System32" displayName: 'PowerShell Script' - task: DownloadSecureFile@1 name: pkcs12_truststore From 75e64752e3324e1a6e3b23d20862a917bec00ac6 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Sat, 16 Nov 2019 21:02:30 -0800 Subject: [PATCH 45/49] more AE tests --- .../jdbc/AlwaysEncrypted/AESetup.java | 11 - .../jdbc/AlwaysEncrypted/EnclaveTest.java | 11 + .../JDBCEncryptionDecryptionTest.java | 274 ++++++++++++++++++ .../sqlserver/jdbc/EnclavePackageTest.java | 28 ++ .../jdbc/SQLServerConnectionTest.java | 202 ++++++++++++- 5 files changed, 502 insertions(+), 24 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 6e4009533..67a4cb73c 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -163,17 +163,6 @@ public static void setUpConnection() throws TestAbortedException, Exception { readFromFile(Constants.JAVA_KEY_STORE_FILENAME, "Alias name"); - String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); - if (null != enclaveAttestationUrl) { - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", - enclaveAttestationUrl); - } - String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); - if (null != enclaveAttestationProtocol) { - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, - "enclaveAttestationProtocol", enclaveAttestationProtocol); - } - dropAll(); createCMK(cmkJks, Constants.JAVA_KEY_STORE_NAME, javaKeyAliases, Constants.CMK_SIGNATURE); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java index f8b3e2971..2747b5b10 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java @@ -50,6 +50,17 @@ public class EnclaveTest extends JDBCEncryptionDecryptionTest { @BeforeAll public static void setupEnclave() throws TestAbortedException, Exception { + String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); + if (null != enclaveAttestationUrl) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", + enclaveAttestationUrl); + } + String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); + if (null != enclaveAttestationProtocol) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, + "enclaveAttestationProtocol", enclaveAttestationProtocol); + } + try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { isAEv2 = TestUtils.isAEv2(con); } catch (SQLException e) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index 2a75721ab..e4a079555 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -17,6 +17,9 @@ import java.sql.Time; import java.sql.Timestamp; import java.util.LinkedList; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -24,8 +27,15 @@ import org.junit.runner.RunWith; import org.opentest4j.TestAbortedException; +import com.microsoft.aad.adal4j.AuthenticationContext; +import com.microsoft.aad.adal4j.AuthenticationResult; +import com.microsoft.aad.adal4j.ClientCredential; import com.microsoft.sqlserver.jdbc.RandomData; +import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionAzureKeyVaultProvider; +import com.microsoft.sqlserver.jdbc.SQLServerColumnEncryptionJavaKeyStoreProvider; import com.microsoft.sqlserver.jdbc.SQLServerConnection; +import com.microsoft.sqlserver.jdbc.SQLServerException; +import com.microsoft.sqlserver.jdbc.SQLServerKeyVaultAuthenticationCallback; import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement; import com.microsoft.sqlserver.jdbc.SQLServerResultSet; import com.microsoft.sqlserver.jdbc.SQLServerStatement; @@ -59,6 +69,247 @@ enum TestCase { NULL } + /* + * Test getting/setting JKS name + */ + @Test + public void testJksName() { + try { + SQLServerColumnEncryptionJavaKeyStoreProvider jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider( + javaKeyPath, new char[1]); + String keystoreName = "keystoreName"; + jksp.setName(keystoreName); + assertTrue(jksp.getName().equals(keystoreName)); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /* + * Test getting/setting AKV name + */ + @Test + public void testAkvName() { + try { + SQLServerColumnEncryptionAzureKeyVaultProvider akv = new SQLServerColumnEncryptionAzureKeyVaultProvider( + authenticationCallback); + String keystoreName = "keystoreName"; + akv.setName(keystoreName); + assertTrue(akv.getName().equals(keystoreName)); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + } + + /* + * Test bad Java Key Store + */ + @SuppressWarnings("unused") + @Test + public void testBadJks() { + try { + SQLServerColumnEncryptionJavaKeyStoreProvider jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider(null, + null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidConnectionSetting"))); + } + } + + /* + * Test bad Azure Key Vault + */ + @SuppressWarnings("unused") + @Test + public void testBadAkv() { + try { + SQLServerColumnEncryptionAzureKeyVaultProvider akv = new SQLServerColumnEncryptionAzureKeyVaultProvider( + null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_NullValue"))); + } + } + + /* + * Test bad encryptColumnEncryptionKey for JKS + */ + @Test + public void testJksBadEncryptColumnEncryptionKey() { + SQLServerColumnEncryptionJavaKeyStoreProvider jksp = null; + char[] secret = new char[1]; + try { + jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider(javaKeyPath, secret); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + + // null masterKeyPath + try { + jksp.encryptColumnEncryptionKey(null, null, null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidMasterKeyDetails"))); + } + + // empty cek + try { + byte[] emptyCek = new byte[0]; + jksp.encryptColumnEncryptionKey(javaKeyPath, Constants.CEK_ALGORITHM, emptyCek); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_EmptyColumnEncryptionKey"))); + } + } + + /* + * Test bad encryptColumnEncryptionKey for AKV + */ + @Test + public void testAkvBadEncryptColumnEncryptionKey() { + SQLServerColumnEncryptionAzureKeyVaultProvider akv = null; + try { + akv = new SQLServerColumnEncryptionAzureKeyVaultProvider(authenticationCallback); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + + // null encryptedColumnEncryptionKey + try { + akv.encryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_NullColumnEncryptionKey"))); + } + + // empty encryptedColumnEncryptionKey + try { + byte[] emptyCek = new byte[0]; + akv.encryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, emptyCek); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_EmptyCEK"))); + } + } + + /* + * Test decryptColumnEncryptionKey for JKS + */ + @Test + public void testJksDecryptColumnEncryptionKey() { + SQLServerColumnEncryptionJavaKeyStoreProvider jksp = null; + char[] secret = new char[1]; + try { + jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider("badkeypath", secret); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + + // null masterKeyPath + try { + jksp.decryptColumnEncryptionKey(null, null, null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidMasterKeyDetails"))); + } + + // bad keystore + try { + byte[] emptyCek = new byte[0]; + jksp.decryptColumnEncryptionKey("keypath", "algorithm", emptyCek); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_KeyStoreNotFound"))); + } + + try { + jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider(javaKeyPath, secret); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + + // bad cert + try { + byte[] badCek = new byte[1]; + jksp.decryptColumnEncryptionKey(javaKeyAliases, "RSA_OAEP", badCek); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_invalidKeyStoreFile"))); + } + } + + /* + * Test decryptColumnEncryptionKey for AKV + */ + @Test + public void testAkvDecryptColumnEncryptionKey() { + SQLServerColumnEncryptionAzureKeyVaultProvider akv = null; + try { + akv = new SQLServerColumnEncryptionAzureKeyVaultProvider(authenticationCallback); + } catch (SQLServerException e) { + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); + } + + // null akvpath + try { + akv.decryptColumnEncryptionKey(null, "", null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_AKVPathNull"))); + } + + // invalid akvpath + try { + akv.decryptColumnEncryptionKey("keypath", "", null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_AKVMasterKeyPathInvalid"))); + } + + // invalid akvpath url + try { + akv.decryptColumnEncryptionKey("http:///^[!#$&-;=?-[]_a-", "", null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_AKVURLInvalid"))); + } + + // null encryptedColumnEncryptionKey + try { + akv.decryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_NullEncryptedColumnEncryptionKey"))); + } + + // empty encryptedColumnEncryptionKey + try { + byte[] emptyCek = new byte[0]; + akv.decryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, emptyCek); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_EmptyEncryptedColumnEncryptionKey"))); + } + + // invalid algorithm + try { + byte[] badCek = new byte[1]; + akv.decryptColumnEncryptionKey(keyIDs[0], "invalidAlgo", badCek); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidKeyEncryptionAlgorithm"))); + } + + // bad encryptedColumnEncryptionKey + try { + byte[] badCek = new byte[1]; + akv.decryptColumnEncryptionKey(keyIDs[0], Constants.CEK_ALGORITHM, badCek); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidEcryptionAlgorithmVersion"))); + } + } + /** * Junit test case for char set string for string values * @@ -1656,4 +1907,27 @@ void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, Str testRichQuery(stmt, NUMERIC_TABLE_AE, table, values2); } } + + SQLServerKeyVaultAuthenticationCallback authenticationCallback = new SQLServerKeyVaultAuthenticationCallback() { + // @Override + ExecutorService service = Executors.newFixedThreadPool(2); + + public String getAccessToken(String authority, String resource, String scope) { + + AuthenticationResult result = null; + try { + AuthenticationContext context = new AuthenticationContext(authority, false, service); + ClientCredential cred = new ClientCredential(applicationClientID, applicationKey); + Future future = context.acquireToken(resource, cred, null); + result = future.get(); + return result.getAccessToken(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + // return null; + } + }; + } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java index 8d4a21f51..7b33a12ff 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java @@ -260,6 +260,34 @@ public static void testInvalidProperties() { "R_enclaveInvalidAttestationProtocol"); } + /* + * Test bad Java Key Store + */ + @SuppressWarnings("unused") + public static void testBadJks() { + try { + SQLServerColumnEncryptionJavaKeyStoreProvider jksp = new SQLServerColumnEncryptionJavaKeyStoreProvider(null, + null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_InvalidConnectionSetting"))); + } + } + + /* + * Test bad Azure Key Vault + */ + @SuppressWarnings("unused") + public static void testBadAkv() { + try { + SQLServerColumnEncryptionAzureKeyVaultProvider akv = new SQLServerColumnEncryptionAzureKeyVaultProvider( + null); + fail(TestResource.getResource("R_expectedExceptionNotThrown")); + } catch (SQLServerException e) { + assertTrue(e.getMessage().matches(TestUtils.formatErrorMsg("R_NullValue"))); + } + } + /* * Test calling verifyColumnMasterKeyMetadata for non enclave computation */ diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java index 2f5edccee..814764444 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java @@ -49,21 +49,197 @@ public class SQLServerConnectionTest extends AbstractTest { @Test public void testDataSource() { SQLServerDataSource ds = new SQLServerDataSource(); - ds.setUser("User"); - ds.setPassword("sUser"); - ds.setApplicationName("User"); - ds.setURL("jdbc:sqlserver://" + randomServer + ";packetSize=512"); + String stringPropValue = "stringPropValue"; + boolean booleanPropValue = true; + int intPropValue = 1; - String trustStore = "Store"; - String trustStorePassword = "pwd"; + ds.setInstanceName(stringPropValue); + assertEquals(stringPropValue, ds.getInstanceName(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setUser(stringPropValue); + assertEquals(stringPropValue, ds.getUser(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setPassword(stringPropValue); + assertEquals(stringPropValue, ds.getPassword(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setApplicationName(stringPropValue); + assertEquals(stringPropValue, ds.getApplicationName(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setDatabaseName(stringPropValue); + assertEquals(stringPropValue, ds.getDatabaseName(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setPortNumber(intPropValue); + assertEquals(intPropValue, ds.getPortNumber(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setURL(stringPropValue); + assertEquals(stringPropValue, ds.getURL(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setDescription(stringPropValue); + assertEquals(stringPropValue, ds.getDescription(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setPacketSize(intPropValue); + assertEquals(intPropValue, ds.getPacketSize(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setQueryTimeout(intPropValue); + assertEquals(intPropValue, ds.getQueryTimeout(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setCancelQueryTimeout(intPropValue); + assertEquals(intPropValue, ds.getCancelQueryTimeout(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setEnablePrepareOnFirstPreparedStatementCall(booleanPropValue); + assertEquals(booleanPropValue, ds.getEnablePrepareOnFirstPreparedStatementCall(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setEnablePrepareOnFirstPreparedStatementCall(booleanPropValue); + assertEquals(booleanPropValue, ds.getEnablePrepareOnFirstPreparedStatementCall(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setServerPreparedStatementDiscardThreshold(intPropValue); + assertEquals(intPropValue, ds.getServerPreparedStatementDiscardThreshold(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setStatementPoolingCacheSize(intPropValue); + assertEquals(intPropValue, ds.getStatementPoolingCacheSize(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setDisableStatementPooling(booleanPropValue); + assertEquals(booleanPropValue, ds.getDisableStatementPooling(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setSocketTimeout(intPropValue); + assertEquals(intPropValue, ds.getSocketTimeout(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setUseBulkCopyForBatchInsert(booleanPropValue); + assertEquals(booleanPropValue, ds.getUseBulkCopyForBatchInsert(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setJASSConfigurationName(stringPropValue); + assertEquals(stringPropValue, ds.getJASSConfigurationName(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setMSIClientId(stringPropValue); + assertEquals(stringPropValue, ds.getMSIClientId(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setAuthenticationScheme(stringPropValue); + // there is no corresponding getAuthenticationScheme + + ds.setAuthentication(stringPropValue); + assertEquals(stringPropValue, ds.getAuthentication(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setAccessToken(stringPropValue); + assertEquals(stringPropValue, ds.getAccessToken(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setLastUpdateCount(booleanPropValue); + assertEquals(booleanPropValue, ds.getLastUpdateCount(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setTransparentNetworkIPResolution(booleanPropValue); + assertEquals(booleanPropValue, ds.getTransparentNetworkIPResolution(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setTrustServerCertificate(booleanPropValue); + assertEquals(booleanPropValue, ds.getTrustServerCertificate(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setTrustStoreType(stringPropValue); + assertEquals(stringPropValue, ds.getTrustStoreType(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setTrustStore(stringPropValue); + assertEquals(stringPropValue, ds.getTrustStore(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setTrustStorePassword(stringPropValue); + assertEquals(stringPropValue, ds.getTrustStorePassword(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setEncrypt(booleanPropValue); + assertEquals(booleanPropValue, ds.getEncrypt(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setHostNameInCertificate(stringPropValue); + assertEquals(stringPropValue, ds.getHostNameInCertificate(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setLockTimeout(intPropValue); + assertEquals(intPropValue, ds.getLockTimeout(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setSelectMethod(stringPropValue); + assertEquals(stringPropValue, ds.getSelectMethod(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setResponseBuffering(stringPropValue); + assertEquals(stringPropValue, ds.getResponseBuffering(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setApplicationIntent(stringPropValue); + assertEquals(stringPropValue, ds.getApplicationIntent(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setSendTimeAsDatetime(booleanPropValue); + assertEquals(booleanPropValue, ds.getSendTimeAsDatetime(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setUseFmtOnly(booleanPropValue); + assertEquals(booleanPropValue, ds.getUseFmtOnly(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setSendStringParametersAsUnicode(booleanPropValue); + assertEquals(booleanPropValue, ds.getSendStringParametersAsUnicode(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setServerNameAsACE(booleanPropValue); + assertEquals(booleanPropValue, ds.getServerNameAsACE(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setServerName(stringPropValue); + assertEquals(stringPropValue, ds.getServerName(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setServerSpn(stringPropValue); + assertEquals(stringPropValue, ds.getServerSpn(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setFailoverPartner(stringPropValue); + assertEquals(stringPropValue, ds.getFailoverPartner(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setMultiSubnetFailover(booleanPropValue); + assertEquals(booleanPropValue, ds.getMultiSubnetFailover(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setWorkstationID(stringPropValue); + assertEquals(stringPropValue, ds.getWorkstationID(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setXopenStates(booleanPropValue); + assertEquals(booleanPropValue, ds.getXopenStates(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setFIPS(booleanPropValue); + assertEquals(booleanPropValue, ds.getFIPS(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setSSLProtocol(stringPropValue); + assertEquals(stringPropValue, ds.getSSLProtocol(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setTrustManagerClass(stringPropValue); + assertEquals(stringPropValue, ds.getTrustManagerClass(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setTrustManagerConstructorArg(stringPropValue); + assertEquals(stringPropValue, ds.getTrustManagerConstructorArg(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setHostNameInCertificate(stringPropValue); + assertEquals(stringPropValue, ds.getHostNameInCertificate(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setDomain(stringPropValue); + assertEquals(stringPropValue, ds.getDomain(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setColumnEncryptionSetting(stringPropValue); + assertEquals(stringPropValue, ds.getColumnEncryptionSetting(), + TestResource.getResource("R_valuesAreDifferent")); + + ds.setKeyStoreAuthentication(stringPropValue); + assertEquals(stringPropValue, ds.getKeyStoreAuthentication(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setKeyStoreSecret(stringPropValue); + // there is no corresponding getKeyStoreSecret + + ds.setKeyStoreLocation(stringPropValue); + assertEquals(stringPropValue, ds.getKeyStoreLocation(), TestResource.getResource("R_valuesAreDifferent")); + + ds.setEnclaveAttestationUrl(stringPropValue); + assertTrue(ds.getEnclaveAttestationUrl().equals(stringPropValue)); + + ds.setEnclaveAttestationProtocol(stringPropValue); + assertTrue(ds.getEnclaveAttestationProtocol().equals(stringPropValue)); + + ds.setKeyVaultProviderClientId(stringPropValue); + assertTrue(ds.getKeyVaultProviderClientId().equals(stringPropValue)); + + ds.setKeyVaultProviderClientKey(stringPropValue); + // there is no corresponding getKeyVaultProviderClientKey - ds.setTrustStore(trustStore); - ds.setEncrypt(true); - ds.setTrustStorePassword(trustStorePassword); - ds.setTrustServerCertificate(true); - assertEquals(trustStore, ds.getTrustStore(), TestResource.getResource("R_valuesAreDifferent")); - assertEquals(true, ds.getEncrypt(), TestResource.getResource("R_valuesAreDifferent")); - assertEquals(true, ds.getTrustServerCertificate(), TestResource.getResource("R_valuesAreDifferent")); } @Test From 21b394d9bea3f8cc99953d3f10a6cdd9d5039330 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 18 Nov 2019 14:53:56 -0800 Subject: [PATCH 46/49] removed reading env vars for properties --- .../sqlserver/jdbc/AlwaysEncrypted/AESetup.java | 11 +++++++++++ .../sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java | 11 ----------- .../java/com/microsoft/sqlserver/jdbc/TestUtils.java | 8 +------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index 67a4cb73c..6e4009533 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -163,6 +163,17 @@ public static void setUpConnection() throws TestAbortedException, Exception { readFromFile(Constants.JAVA_KEY_STORE_FILENAME, "Alias name"); + String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); + if (null != enclaveAttestationUrl) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", + enclaveAttestationUrl); + } + String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); + if (null != enclaveAttestationProtocol) { + AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, + "enclaveAttestationProtocol", enclaveAttestationProtocol); + } + dropAll(); createCMK(cmkJks, Constants.JAVA_KEY_STORE_NAME, javaKeyAliases, Constants.CMK_SIGNATURE); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java index 2747b5b10..f8b3e2971 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/EnclaveTest.java @@ -50,17 +50,6 @@ public class EnclaveTest extends JDBCEncryptionDecryptionTest { @BeforeAll public static void setupEnclave() throws TestAbortedException, Exception { - String enclaveAttestationUrl = TestUtils.getConfiguredProperty("enclaveAttestationUrl"); - if (null != enclaveAttestationUrl) { - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", - enclaveAttestationUrl); - } - String enclaveAttestationProtocol = TestUtils.getConfiguredProperty("enclaveAttestationProtocol"); - if (null != enclaveAttestationProtocol) { - AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, - "enclaveAttestationProtocol", enclaveAttestationProtocol); - } - try (SQLServerConnection con = PrepUtil.getConnection(AETestConnectionString, AEInfo)) { isAEv2 = TestUtils.isAEv2(con); } catch (SQLException e) { diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java index 208d9a1aa..e06bde535 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java @@ -126,13 +126,7 @@ public static boolean isAEv2(Connection con) { * @return Value */ public static String getConfiguredProperty(String key) { - String value = System.getProperty(key); - - if (value == null) { - value = System.getenv(key); - } - - return value; + return System.getProperty(key); } /** From 549c6ac0f2d2834afb047a9b099298e276ec593b Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Tue, 19 Nov 2019 13:37:38 -0800 Subject: [PATCH 47/49] more tests --- .../sqlserver/jdbc/SQLServerConnectionTest.java | 10 ++++++++++ .../jdbc/connection/NativeMSSQLDataSourceTest.java | 13 +++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java index 814764444..b09d959d6 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java @@ -239,7 +239,17 @@ public void testDataSource() { ds.setKeyVaultProviderClientKey(stringPropValue); // there is no corresponding getKeyVaultProviderClientKey + } + + @Test + public void testDSConnection() { + SQLServerDataSource ds = new SQLServerDataSource(); + updateDataSource(connectionString, ds); + // getPassword can only be accessed within package + try (Connection con = ds.getConnection(ds.getUser(), ds.getPassword())) {} catch (Exception e) { + fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage()); + } } @Test diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/connection/NativeMSSQLDataSourceTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/connection/NativeMSSQLDataSourceTest.java index fab794b2f..ec232b2d0 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/connection/NativeMSSQLDataSourceTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/connection/NativeMSSQLDataSourceTest.java @@ -46,10 +46,12 @@ public void testSerialization() throws IOException { try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ObjectOutput objectOutput = new ObjectOutputStream(outputStream)) { SQLServerDataSource ds = new SQLServerDataSource(); - ds.setLogWriter(new PrintWriter(new ByteArrayOutputStream())); - + PrintWriter out = new PrintWriter(new ByteArrayOutputStream()); + ds.setLogWriter(out); objectOutput.writeObject(ds); objectOutput.flush(); + + assertTrue(out == ds.getLogWriter()); } } @@ -109,6 +111,13 @@ public void testInterfaceWrapping() throws ClassNotFoundException, SQLException ids3.setApplicationName("AppName"); } + @Test + public void testDSReference() { + SQLServerDataSource ds = new SQLServerDataSource(); + assertTrue(ds.getReference().getClassName() + .equals("com.microsoft.sqlserver.jdbc.SQLServerDataSource")); + } + private SQLServerDataSource testSerial(SQLServerDataSource ds) throws IOException, ClassNotFoundException { try (java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); java.io.ObjectOutput objectOutput = new java.io.ObjectOutputStream(outputStream)) { From cdaa085849215df4e36d6a25bfdd621a5208c458 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Thu, 21 Nov 2019 21:59:25 -0800 Subject: [PATCH 48/49] added support for config.properties file --- .../microsoft/sqlserver/jdbc/TestUtils.java | 33 ------ .../sqlserver/testframework/AbstractTest.java | 101 ++++++++++++++++-- .../sqlserver/testframework/Constants.java | 2 + 3 files changed, 93 insertions(+), 43 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java index 2d0b138e2..2b5d6ab74 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/TestUtils.java @@ -119,39 +119,6 @@ public static boolean isAEv2(Connection con) { return ((SQLServerConnection) con).isAEv2(); } - - /** - * Read variable from property files if found null try to read from env. - * - * @param key - * @return Value - */ - public static String getConfiguredProperty(String key) { - String value = System.getProperty(key); - - if (value == null) { - value = System.getenv(key); - } - - return value; - } - - /** - * Convenient method for {@link #getConfiguredProperty(String)} - * - * @param key - * @return Value - */ - public static String getConfiguredProperty(String key, String defaultValue) { - String value = getConfiguredProperty(key); - - if (value == null) { - value = defaultValue; - } - - return value; - } - /** * * @param javatype diff --git a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java index a52f7fc55..1bbb879df 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java @@ -6,6 +6,9 @@ package com.microsoft.sqlserver.testframework; import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; import java.io.PrintStream; import java.sql.Connection; import java.sql.ResultSet; @@ -13,6 +16,7 @@ import java.sql.Statement; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; import java.util.logging.Handler; @@ -79,6 +83,7 @@ public abstract class AbstractTest { */ private static ByteArrayOutputStream logOutputStream = null; private static PrintStream logPrintStream = null; + private static Properties configProperties = null; /** * This will take care of all initialization before running the Test Suite. @@ -91,14 +96,22 @@ public static void setup() throws Exception { // Invoke fine logging... invokeLogging(); - connectionString = TestUtils.getConfiguredProperty(Constants.MSSQL_JDBC_TEST_CONNECTION_PROPERTIES); + // get Properties from config file + try (InputStream input = new FileInputStream(Constants.CONFIG_PROPERTIES_FILE)) { + configProperties = new Properties(); + configProperties.load(input); + } catch (FileNotFoundException | SecurityException e) { + // no config file used + } + + connectionString = getConfiguredPropertyOrEnv(Constants.MSSQL_JDBC_TEST_CONNECTION_PROPERTIES); connectionStringNTLM = connectionString; - applicationClientID = System.getProperty("applicationClientID"); - applicationKey = System.getProperty("applicationKey"); + applicationClientID = getConfiguredProperty("applicationClientID"); + applicationKey = getConfiguredProperty("applicationKey"); javaKeyPath = TestUtils.getCurrentClassPath() + Constants.JKS_NAME; - keyIDs = System.getProperty("keyID", "").split(Constants.SEMI_COLON); - windowsKeyPath = System.getProperty("windowsKeyPath"); + keyIDs = getConfiguredProperty("keyID", "").split(Constants.SEMI_COLON); + windowsKeyPath = getConfiguredProperty("windowsKeyPath"); Map map = new HashMap(); if (null == jksProvider) { @@ -118,9 +131,9 @@ public static void setup() throws Exception { } // if these properties are defined then NTLM is desired, modify connection string accordingly - String domain = System.getProperty("domainNTLM"); - String user = System.getProperty("userNTLM"); - String password = System.getProperty("passwordNTLM"); + String domain = getConfiguredProperty("domainNTLM"); + String user = getConfiguredProperty("userNTLM"); + String password = getConfiguredProperty("passwordNTLM"); if (null != domain) { connectionStringNTLM = TestUtils.addOrOverrideProperty(connectionStringNTLM, "domain", domain); @@ -309,14 +322,14 @@ public static void invokeLogging() { Handler handler = null; // enable logging to stream by default for tests - String enableLogging = TestUtils.getConfiguredProperty(Constants.MSSQL_JDBC_LOGGING, Boolean.TRUE.toString()); + String enableLogging = getConfiguredPropertyOrEnv(Constants.MSSQL_JDBC_LOGGING, Boolean.TRUE.toString()); // If logging is not enable then return. if (!Boolean.TRUE.toString().equalsIgnoreCase(enableLogging)) { return; } - String loggingHandler = TestUtils.getConfiguredProperty(Constants.MSSQL_JDBC_LOGGING_HANDLER, + String loggingHandler = getConfiguredPropertyOrEnv(Constants.MSSQL_JDBC_LOGGING_HANDLER, Constants.LOGGING_HANDLER_STREAM); try { @@ -390,4 +403,72 @@ private static void isSqlAzureOrAzureDW(Connection con) throws SQLException { determinedSqlAzureOrSqlServer = true; } } + + /** + * Read property from system or config properties file + * + * @param key + * @return property value + */ + private static String getConfiguredProperty(String key) { + String value = System.getProperty(key); + + if (null == value && null != configProperties) { + return configProperties.getProperty(key); + } + + return value; + } + + /** + * Read property from system or config properties file or read from env var + * + * @param key + * @return property value + */ + private static String getConfiguredPropertyOrEnv(String key) { + String value = getConfiguredProperty(key); + + if (null == value) { + return System.getenv(key); + } + + return value; + } + + /** + * Read property from system or config properties file if not set return default value + * + * @param key + * @return property value or default value + */ + private static String getConfiguredProperty(String key, String defaultValue) { + String value = getConfiguredProperty(key); + + if (null == value) { + return defaultValue; + } + + return value; + } + + /** + * Read property from system or config properties file or env var if not set return default value + * + * @param key + * @return property value or default value + */ + private static String getConfiguredPropertyOrEnv(String key, String defaultValue) { + String value = getConfiguredProperty(key); + + if (null == value) { + value = System.getenv(key); + } + + if (null == value) { + value = defaultValue; + } + + return value; + } } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/Constants.java b/src/test/java/com/microsoft/sqlserver/testframework/Constants.java index 98c3c5501..e6f16958e 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/Constants.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/Constants.java @@ -138,6 +138,8 @@ private Constants() {} public static final String ENCLAVE_ATTESTATIONURL = "enclaveAttestationUrl"; public static final String ENCLAVE_ATTESTATIONPROTOCOL = "enclaveAttestationProtocol"; + public static final String CONFIG_PROPERTIES_FILE = "config.properties"; + public enum LOB { CLOB, NCLOB, From 05c2fe367a14d4be2f1a1e357233da3ba5ab62d8 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Wed, 27 Nov 2019 11:47:57 -0800 Subject: [PATCH 49/49] review updates --- .../jdbc/AlwaysEncrypted/AESetup.java | 4 ++-- .../JDBCEncryptionDecryptionTest.java | 24 ++++++++----------- .../sqlserver/testframework/AbstractTest.java | 2 +- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java index c8b1a8ff9..6344ccf13 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/AESetup.java @@ -163,12 +163,12 @@ public static void setUpConnection() throws TestAbortedException, Exception { readFromFile(Constants.JAVA_KEY_STORE_FILENAME, "Alias name"); - String enclaveAttestationUrl = System.getProperty("enclaveAttestationUrl"); + String enclaveAttestationUrl = getConfiguredProperty("enclaveAttestationUrl"); if (null != enclaveAttestationUrl) { AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationUrl", enclaveAttestationUrl); } - String enclaveAttestationProtocol = System.getProperty("enclaveAttestationProtocol"); + String enclaveAttestationProtocol = getConfiguredProperty("enclaveAttestationProtocol"); if (null != enclaveAttestationProtocol) { AETestConnectionString = TestUtils.addOrOverrideProperty(AETestConnectionString, "enclaveAttestationProtocol", enclaveAttestationProtocol); diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java index 3aa0bd677..0e51d0adc 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/AlwaysEncrypted/JDBCEncryptionDecryptionTest.java @@ -1776,8 +1776,8 @@ void testChars(SQLServerStatement stmt, String cekName, String[][] table, String testChar(null, values); if (isTestEnclave) { - if (null == System.getProperty(Constants.ENCLAVE_ATTESTATIONURL) - || null == System.getProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { + if (null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL) + || null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { fail(TestResource.getResource("R_reqExternalSetup")); } @@ -1815,8 +1815,8 @@ void testBinaries(SQLServerStatement stmt, String cekName, String[][] table, Lin testBinary(null, values); if (isTestEnclave) { - if (null == System.getProperty(Constants.ENCLAVE_ATTESTATIONURL) - || null == System.getProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { + if (null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL) + || null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { fail(TestResource.getResource("R_reqExternalSetup")); } @@ -1858,8 +1858,8 @@ void testDates(SQLServerStatement stmt, String cekName, String[][] table, Linked testDate(null, values); if (isTestEnclave) { - if (null == System.getProperty(Constants.ENCLAVE_ATTESTATIONURL) - || null == System.getProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { + if (null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL) + || null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { fail(TestResource.getResource("R_reqExternalSetup")); } @@ -1897,8 +1897,8 @@ void testNumerics(SQLServerStatement stmt, String cekName, String[][] table, Str testNumeric(null, values2, isNull); if (isTestEnclave) { - if (null == System.getProperty(Constants.ENCLAVE_ATTESTATIONURL) - || null == System.getProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { + if (null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONURL) + || null == getConfiguredProperty(Constants.ENCLAVE_ATTESTATIONPROTOCOL)) { fail(TestResource.getResource("R_reqExternalSetup")); } @@ -1920,14 +1920,10 @@ public String getAccessToken(String authority, String resource, String scope) { ClientCredential cred = new ClientCredential(applicationClientID, applicationKey); Future future = context.acquireToken(resource, cred, null); result = future.get(); - return result.getAccessToken(); } catch (Exception e) { - e.printStackTrace(); - return null; + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); } - - // return null; + return result.getAccessToken(); } }; - } diff --git a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java index 1bbb879df..98c63a83e 100644 --- a/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java +++ b/src/test/java/com/microsoft/sqlserver/testframework/AbstractTest.java @@ -410,7 +410,7 @@ private static void isSqlAzureOrAzureDW(Connection con) throws SQLException { * @param key * @return property value */ - private static String getConfiguredProperty(String key) { + protected static String getConfiguredProperty(String key) { String value = System.getProperty(key); if (null == value && null != configProperties) {