From 7f17532250eec3be7eab1e9a538eae49be905564 Mon Sep 17 00:00:00 2001 From: lilgreenbird Date: Mon, 14 Nov 2022 15:25:44 -0800 Subject: [PATCH] Resolved issues reported by SonarQube (#1962) --- .../sqlserver/jdbc/AuthenticationJNI.java | 5 +- .../com/microsoft/sqlserver/jdbc/Column.java | 27 +- .../com/microsoft/sqlserver/jdbc/DDC.java | 100 ++++--- .../sqlserver/jdbc/DLLException.java | 8 +- .../microsoft/sqlserver/jdbc/DataTypes.java | 8 +- .../microsoft/sqlserver/jdbc/IOBuffer.java | 114 ++++++-- .../jdbc/ISQLServerEnclaveProvider.java | 10 - .../sqlserver/jdbc/KerbAuthentication.java | 19 +- .../jdbc/SQLServerAASEnclaveProvider.java | 7 + ...umnEncryptionCertificateStoreProvider.java | 4 +- .../sqlserver/jdbc/SQLServerConnection.java | 267 +++++++++--------- .../sqlserver/jdbc/SQLServerDriver.java | 246 +++++++++------- .../jdbc/SQLServerNoneEnclaveProvider.java | 7 + .../sqlserver/jdbc/SQLServerResultSet.java | 2 + .../jdbc/SQLServerVSMEnclaveProvider.java | 7 + .../sqlserver/jdbc/SQLServerXAConnection.java | 2 +- .../sqlserver/jdbc/EnclavePackageTest.java | 4 +- .../jdbc/SQLServerConnectionTest.java | 12 +- 18 files changed, 508 insertions(+), 341 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/AuthenticationJNI.java b/src/main/java/com/microsoft/sqlserver/jdbc/AuthenticationJNI.java index 4c02eae69..9d5251866 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/AuthenticationJNI.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/AuthenticationJNI.java @@ -82,9 +82,8 @@ static boolean isDllLoaded() { static FedAuthDllInfo getAccessTokenForWindowsIntegrated(String stsURL, String servicePrincipalName, String clientConnectionId, String clientId, long expirationFileTime) throws DLLException { - FedAuthDllInfo dllInfo = ADALGetAccessTokenForWindowsIntegrated(stsURL, servicePrincipalName, - clientConnectionId, clientId, expirationFileTime, authLogger); - return dllInfo; + return ADALGetAccessTokenForWindowsIntegrated(stsURL, servicePrincipalName, clientConnectionId, clientId, + expirationFileTime, authLogger); } // InitDNSName should be called to initialize the DNSName before calling this function diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/Column.java b/src/main/java/com/microsoft/sqlserver/jdbc/Column.java index ca9134244..50958571d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/Column.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/Column.java @@ -185,8 +185,8 @@ final boolean isInitialized() { * * If the column has not yet been read from the response then this method reads it. */ - Object getValue(JDBCType jdbcType, InputStreamGetterArgs getterArgs, Calendar cal, - TDSReader tdsReader, SQLServerStatement statement) throws SQLServerException { + Object getValue(JDBCType jdbcType, InputStreamGetterArgs getterArgs, Calendar cal, TDSReader tdsReader, + SQLServerStatement statement) throws SQLServerException { Object value = getterDTV.getValue(jdbcType, typeInfo.getScale(), getterArgs, cal, typeInfo, cryptoMetadata, tdsReader, statement); setInternalVariant(getterDTV.getInternalVariant()); @@ -242,12 +242,11 @@ else if (jdbcType.isBinary()) { // if jdbcType is char or varchar, check if the column is actually char/varchar or nchar/nvarchar // in order to make updateString() work with encrypted Nchar typpes - if (null != cryptoMetadata && (JDBCType.CHAR == jdbcType || JDBCType.VARCHAR == jdbcType)) { - if (JDBCType.NVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType() - || JDBCType.NCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType() - || JDBCType.LONGNVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType()) { - jdbcType = cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType(); - } + if (null != cryptoMetadata && (JDBCType.CHAR == jdbcType || JDBCType.VARCHAR == jdbcType) + && (JDBCType.NVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType() + || JDBCType.NCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType() + || JDBCType.LONGNVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType())) { + jdbcType = cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType(); } if (Util.shouldHonorAEForParameters(stmtColumnEncriptionSetting, con)) { @@ -264,12 +263,12 @@ else if (jdbcType.isBinary()) { // for update encrypted nchar or nvarchar value on result set, must double the value length, // otherwise, the data is truncated. - if (null != cryptoMetadata) { - if (JDBCType.NCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType() - || JDBCType.NVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType() - || JDBCType.LONGNVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType()) { - this.valueLength = valueLength * 2; - } + if (null != cryptoMetadata + && (JDBCType.NCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType() + || JDBCType.NVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType().getJDBCType() + || JDBCType.LONGNVARCHAR == cryptoMetadata.getBaseTypeInfo().getSSType() + .getJDBCType())) { + this.valueLength = valueLength * 2; } } } else { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java b/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java index 248060841..8c88d4e76 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/DDC.java @@ -531,7 +531,7 @@ static final Object convertBytesToObject(byte[] bytesValue, JDBCType jdbcType, * @return the required object. */ static final Object convertStringToObject(String stringVal, Charset charset, JDBCType jdbcType, - StreamType streamType) throws UnsupportedEncodingException, IllegalArgumentException { + StreamType streamType) throws UnsupportedEncodingException { switch (jdbcType) { // Convert String to Numeric types. case DECIMAL: @@ -622,7 +622,7 @@ private static LocalDateTime parseStringIntoLDT(String s) { int hour; int minute; int second; - int a_nanos = 0; + int nanos = 0; int firstDash; int secondDash; int dividingSpace; @@ -652,18 +652,18 @@ private static LocalDateTime parseStringIntoLDT(String s) { // Convert the date boolean parsedDate = false; - if (firstDash > 0 && secondDash > 0 && secondDash < dividingSpace - 1) { - if (firstDash == YEAR_LENGTH && (secondDash - firstDash > 1 && secondDash - firstDash <= MONTH_LENGTH + 1) - && (dividingSpace - secondDash > 1 && dividingSpace - secondDash <= DAY_LENGTH + 1)) { - year = Integer.parseInt(s.substring(0, firstDash)); - month = Integer.parseInt(s.substring(firstDash + 1, secondDash)); - day = Integer.parseInt(s.substring(secondDash + 1, dividingSpace)); - - if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) { - parsedDate = true; - } + if (firstDash > 0 && secondDash > 0 && secondDash < dividingSpace - 1 && firstDash == YEAR_LENGTH + && (secondDash - firstDash > 1 && secondDash - firstDash <= MONTH_LENGTH + 1) + && (dividingSpace - secondDash > 1 && dividingSpace - secondDash <= DAY_LENGTH + 1)) { + year = Integer.parseInt(s.substring(0, firstDash)); + month = Integer.parseInt(s.substring(firstDash + 1, secondDash)); + day = Integer.parseInt(s.substring(secondDash + 1, dividingSpace)); + + if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) { + parsedDate = true; } } + if (!parsedDate) { throw new java.lang.IllegalArgumentException(formatError); } @@ -685,7 +685,7 @@ private static LocalDateTime parseStringIntoLDT(String s) { tmpNanos *= 10; nanoPrecision++; } - a_nanos = tmpNanos; + nanos = tmpNanos; } else if (period > 0) { throw new java.lang.IllegalArgumentException(formatError); } else { @@ -694,7 +694,7 @@ private static LocalDateTime parseStringIntoLDT(String s) { } else { throw new java.lang.IllegalArgumentException(formatError); } - return LocalDateTime.of(year, month, day, hour, minute, second, a_nanos); + return LocalDateTime.of(year, month, day, hour, minute, second, nanos); } static final Object convertStreamToObject(BaseInputStream stream, TypeInfo typeInfo, JDBCType jdbcType, @@ -779,7 +779,7 @@ static final Object convertStreamToObject(BaseInputStream stream, TypeInfo typeI // Slightly less fast path for MBCS data that converts directly/easily to ASCII if (getterArgs.isAdaptive) { - return AsciiFilteredUnicodeInputStream.MakeAsciiFilteredUnicodeInputStream(stream, + return AsciiFilteredUnicodeInputStream.makeAsciiFilteredUnicodeInputStream(stream, new BufferedReader(new InputStreamReader(stream, typeInfo.getCharset()))); } else { return new ByteArrayInputStream( @@ -808,10 +808,7 @@ static final Object convertStreamToObject(BaseInputStream stream, TypeInfo typeI // // Catch them and translate them to a SQLException so that we don't propagate an unexpected exception // type all the way up to the app, which may not catch it either... - catch (IllegalArgumentException e) { - MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_errorConvertingValue")); - throw new SQLServerException(form.format(new Object[] {typeInfo.getSSType(), jdbcType}), null, 0, e); - } catch (UnsupportedEncodingException e) { + catch (IllegalArgumentException | UnsupportedEncodingException e) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_errorConvertingValue")); throw new SQLServerException(form.format(new Object[] {typeInfo.getSSType(), jdbcType}), null, 0, e); } @@ -891,7 +888,7 @@ private static String fractionalSecondsString(long subSecondNanos, int scale) { * @return a Java object of the desired type. */ static final Object convertTemporalToObject(JDBCType jdbcType, SSType ssType, Calendar timeZoneCalendar, - int daysSinceBaseDate, long ticksSinceMidnight, int fractionalSecondsScale) { + int daysSinceBaseDate, long ticksSinceMidnight, int fractionalSecondsScale) throws SQLServerException { // In cases where a Calendar object (and therefore Timezone) is not passed to the method, // use the path below instead to optimize performance. @@ -1036,7 +1033,9 @@ static final Object convertTemporalToObject(JDBCType jdbcType, SSType ssType, Ca } default: - throw new AssertionError("Unexpected SSType: " + ssType); + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_unsupportedConversionFromTo")); + throw new SQLServerException(form.format(new Object[] {ssType.name(), jdbcType}), null, 0, null); } int localMillisOffset = timeZoneCalendar.get(Calendar.ZONE_OFFSET); @@ -1098,7 +1097,10 @@ static final Object convertTemporalToObject(JDBCType jdbcType, SSType ssType, Ca } default: - throw new AssertionError("Unexpected SSType: " + ssType); + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_unsupportedConversionFromTo")); + throw new SQLServerException(form.format(new Object[] {ssType.name(), jdbcType}), null, 0, + null); } } @@ -1192,17 +1194,22 @@ cal, fractionalSecondsString(subSecondNanos, fractionalSecondsScale), } default: - throw new AssertionError("Unexpected SSType: " + ssType); + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_unsupportedConversionFromTo")); + throw new SQLServerException(form.format(new Object[] {ssType.name(), jdbcType}), null, 0, + null); } } default: - throw new AssertionError("Unexpected JDBCType: " + jdbcType); + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_unsupportedConversionFromTo")); + throw new SQLServerException(form.format(new Object[] {ssType.name(), jdbcType}), null, 0, null); } } private static Object convertTemporalToObject(JDBCType jdbcType, SSType ssType, int daysSinceBaseDate, - long ticksSinceMidnight, int fractionalSecondsScale) { + long ticksSinceMidnight, int fractionalSecondsScale) throws SQLServerException { int subSecondNanos; // In cases where Timezone values don't need to be considered, use LocalDateTime go avoid @@ -1254,7 +1261,9 @@ private static Object convertTemporalToObject(JDBCType jdbcType, SSType ssType, } default: - throw new AssertionError("Unexpected SSType: " + ssType); + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_unsupportedConversionFromTo")); + throw new SQLServerException(form.format(new Object[] {ssType.name(), jdbcType}), null, 0, null); } switch (jdbcType.category) { @@ -1282,7 +1291,10 @@ private static Object convertTemporalToObject(JDBCType jdbcType, SSType ssType, } default: - throw new AssertionError("Unexpected SSType: " + ssType); + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_unsupportedConversionFromTo")); + throw new SQLServerException(form.format(new Object[] {ssType.name(), jdbcType}), null, 0, + null); } } @@ -1333,12 +1345,17 @@ private static Object convertTemporalToObject(JDBCType jdbcType, SSType ssType, } default: - throw new AssertionError("Unexpected SSType: " + ssType); + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_unsupportedConversionFromTo")); + throw new SQLServerException(form.format(new Object[] {ssType.name(), jdbcType}), null, 0, + null); } } default: - throw new AssertionError("Unexpected JDBCType: " + jdbcType); + MessageFormat form = new MessageFormat( + SQLServerException.getErrString("R_unsupportedConversionFromTo")); + throw new SQLServerException(form.format(new Object[] {ssType.name(), jdbcType}), null, 0, null); } } @@ -1471,24 +1488,28 @@ final class AsciiFilteredInputStream extends InputStream { ASCII_FILTER[i] = (byte) '?'; } - AsciiFilteredInputStream(BaseInputStream containedStream) throws SQLServerException { + AsciiFilteredInputStream(BaseInputStream containedStream) { if (BaseInputStream.logger.isLoggable(java.util.logging.Level.FINER)) BaseInputStream.logger.finer(containedStream.toString() + " wrapping in AsciiFilteredInputStream"); this.containedStream = containedStream; } + @Override public void close() throws IOException { containedStream.close(); } + @Override public long skip(long n) throws IOException { return containedStream.skip(n); } + @Override public int available() throws IOException { return containedStream.available(); } + @Override public int read() throws IOException { int value = containedStream.read(); if (value >= 0 && value <= 255) @@ -1496,6 +1517,7 @@ public int read() throws IOException { return value; } + @Override public int read(byte[] b) throws IOException { int bytesRead = containedStream.read(b); if (bytesRead > 0) { @@ -1506,6 +1528,7 @@ public int read(byte[] b) throws IOException { return bytesRead; } + @Override public int read(byte b[], int offset, int maxBytes) throws IOException { int bytesRead = containedStream.read(b, offset, maxBytes); if (bytesRead > 0) { @@ -1516,14 +1539,17 @@ public int read(byte b[], int offset, int maxBytes) throws IOException { return bytesRead; } + @Override public boolean markSupported() { return containedStream.markSupported(); } + @Override public void mark(int readLimit) { containedStream.mark(readLimit); } + @Override public void reset() throws IOException { containedStream.reset(); } @@ -1540,27 +1566,29 @@ final class AsciiFilteredUnicodeInputStream extends InputStream { private final Reader containedReader; private final Charset asciiCharSet; - static AsciiFilteredUnicodeInputStream MakeAsciiFilteredUnicodeInputStream(BaseInputStream strm, - Reader rd) throws SQLServerException { + static AsciiFilteredUnicodeInputStream makeAsciiFilteredUnicodeInputStream(BaseInputStream strm, Reader rd) { if (BaseInputStream.logger.isLoggable(java.util.logging.Level.FINER)) BaseInputStream.logger.finer(strm.toString() + " wrapping in AsciiFilteredInputStream"); return new AsciiFilteredUnicodeInputStream(rd); } // Note the Reader provided should support mark, reset - private AsciiFilteredUnicodeInputStream(Reader rd) throws SQLServerException { + private AsciiFilteredUnicodeInputStream(Reader rd) { containedReader = rd; asciiCharSet = US_ASCII; } + @Override public void close() throws IOException { containedReader.close(); } + @Override public long skip(long n) throws IOException { return containedReader.skip(n); } + @Override public int available() throws IOException { // from the JDBC spec // Note: A stream may return 0 when the method InputStream.available is called whether there is data available @@ -1571,15 +1599,18 @@ public int available() throws IOException { private final byte[] bSingleByte = new byte[1]; + @Override public int read() throws IOException { int bytesRead = read(bSingleByte); return (-1 == bytesRead) ? -1 : (bSingleByte[0] & 0xFF); } + @Override public int read(byte[] b) throws IOException { return read(b, 0, b.length); } + @Override public int read(byte b[], int offset, int maxBytes) throws IOException { char tempBufferToHoldCharDataForConversion[] = new char[maxBytes]; int charsRead = containedReader.read(tempBufferToHoldCharDataForConversion); @@ -1593,10 +1624,12 @@ public int read(byte b[], int offset, int maxBytes) throws IOException { return charsRead; } + @Override public boolean markSupported() { return containedReader.markSupported(); } + @Override public void mark(int readLimit) { try { containedReader.mark(readLimit); @@ -1607,6 +1640,7 @@ public void mark(int readLimit) { } } + @Override public void reset() throws IOException { containedReader.reset(); } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/DLLException.java b/src/main/java/com/microsoft/sqlserver/jdbc/DLLException.java index e4300f3bc..ee7cda940 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/DLLException.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/DLLException.java @@ -44,19 +44,19 @@ class DLLException extends Exception { this.param3 = param3; } - int GetCategory() { + int getCategory() { return this.category; } - int GetStatus() { + int getStatus() { return this.status; } - int GetState() { + int getState() { return this.state; } - int GetErrCode() { + int getErrCode() { return this.errCode; } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java b/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java index 80b91c1b6..487705dde 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/DataTypes.java @@ -166,6 +166,7 @@ private SSType(Category category, String name, JDBCType jdbcType) { this.jdbcType = jdbcType; } + @Override public String toString() { return name; } @@ -321,6 +322,7 @@ private StreamType(JDBCType jdbcType, String name) { this.name = name; } + @Override public String toString() { return name; } @@ -425,6 +427,7 @@ enum JavaType { INPUTSTREAM(InputStream.class, JDBCType.UNKNOWN) { // InputStreams are either ASCII or binary + @Override JDBCType getJDBCType(SSType ssType, JDBCType jdbcTypeFromApp) { JDBCType jdbcType; @@ -530,9 +533,8 @@ static JavaType of(Object obj) { for (JavaType javaType : VALUES) // if JVM version is prior to Java 8, the javaClass variable can be // null if the java type is introduced in Java 8 - if (null != javaType.javaClass) { - if (javaType.javaClass.isInstance(obj)) - return javaType; + if (null != javaType.javaClass && javaType.javaClass.isInstance(obj)) { + return javaType; } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java index b6782d6da..fdb063b13 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java @@ -862,6 +862,7 @@ private void ensureSSLPayload() throws IOException { } } + @Override public long skip(long n) throws IOException { if (logger.isLoggable(Level.FINEST)) logger.finest(logContext + " Skipping " + n + " bytes..."); @@ -886,6 +887,7 @@ public long skip(long n) throws IOException { private final byte oneByte[] = new byte[1]; + @Override public int read() throws IOException { int bytesRead; @@ -895,10 +897,12 @@ public int read() throws IOException { return 1 == bytesRead ? oneByte[0] : -1; } + @Override public int read(byte[] b) throws IOException { return readInternal(b, 0, b.length); } + @Override public int read(byte b[], int offset, int maxBytes) throws IOException { return readInternal(b, offset, maxBytes); } @@ -940,6 +944,7 @@ private class SSLHandshakeOutputStream extends OutputStream { this.logContext = tdsChannel.toString() + " (SSLHandshakeOutputStream):"; } + @Override public void flush() throws IOException { // It seems that the security provider implementation in some JVMs // (notably SunJSSE in the 6.0 JVM) likes to add spurious calls to @@ -968,15 +973,18 @@ void endMessage() throws SQLServerException { private final byte singleByte[] = new byte[1]; + @Override public void write(int b) throws IOException { singleByte[0] = (byte) (b & 0xFF); writeInternal(singleByte, 0, singleByte.length); } + @Override public void write(byte[] b) throws IOException { writeInternal(b, 0, b.length); } + @Override public void write(byte[] b, int off, int len) throws IOException { writeInternal(b, off, len); } @@ -1052,7 +1060,7 @@ public boolean poll() { } if (logger.isLoggable(Level.FINEST)) { - logger.finest(toString() + "poll() - read() returned " + b); + logger.finest(super.toString() + "poll() - read() returned " + b); } if (b == -1) // end-of-stream @@ -1088,13 +1096,14 @@ private int getOneFromCache() { return result; } + @Override public long skip(long n) throws IOException { lock.lock(); try { long bytesSkipped = 0; if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Skipping " + n + " bytes"); + logger.finest(super.toString() + " Skipping " + n + " bytes"); while (cachedLength > 0 && bytesSkipped < n) { bytesSkipped++; @@ -1106,7 +1115,7 @@ public long skip(long n) throws IOException { } if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Skipped " + n + " bytes"); + logger.finest(super.toString() + " Skipped " + n + " bytes"); return bytesSkipped; } finally { @@ -1114,17 +1123,19 @@ public long skip(long n) throws IOException { } } + @Override public int available() throws IOException { int bytesAvailable = filteredStream.available() + cachedLength; if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " " + bytesAvailable + " bytes available"); + logger.finest(super.toString() + " " + bytesAvailable + " bytes available"); return bytesAvailable; } private final byte oneByte[] = new byte[1]; + @Override public int read() throws IOException { int bytesRead; @@ -1134,10 +1145,12 @@ public int read() throws IOException { return 1 == bytesRead ? oneByte[0] : -1; } + @Override public int read(byte[] b) throws IOException { return readInternal(b, 0, b.length); } + @Override public int read(byte[] b, int offset, int maxBytes) throws IOException { return readInternal(b, offset, maxBytes); } @@ -1148,7 +1161,7 @@ private int readInternal(byte[] b, int offset, int maxBytes) throws IOException int bytesRead; if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Reading " + maxBytes + " bytes"); + logger.finest(super.toString() + " Reading " + maxBytes + " bytes"); // Optimize for nothing cached if (cachedLength == 0) { @@ -1156,7 +1169,7 @@ private int readInternal(byte[] b, int offset, int maxBytes) throws IOException bytesRead = filteredStream.read(b, offset, maxBytes); } catch (IOException e) { if (logger.isLoggable(Level.FINER)) - logger.finer(toString() + " Reading bytes threw exception:" + e.getMessage()); + logger.finer(super.toString() + " Reading bytes threw exception:" + e.getMessage()); throw e; } } else { @@ -1180,7 +1193,7 @@ private int readInternal(byte[] b, int offset, int maxBytes) throws IOException System.arraycopy(bytesFromStream, 0, b, bytesFromCache.length, bytesReadFromStream); } catch (IOException e) { if (logger.isLoggable(Level.FINER)) - logger.finer(toString() + " " + e.getMessage()); + logger.finer(super.toString() + " " + e.getMessage()); logger.finer(toString() + " Reading bytes threw exception:" + e.getMessage()); throw e; @@ -1188,7 +1201,7 @@ private int readInternal(byte[] b, int offset, int maxBytes) throws IOException } if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Read " + bytesRead + " bytes"); + logger.finest(super.toString() + " Read " + bytesRead + " bytes"); return bytesRead; } finally { @@ -1196,18 +1209,20 @@ private int readInternal(byte[] b, int offset, int maxBytes) throws IOException } } + @Override public boolean markSupported() { boolean markSupported = filteredStream.markSupported(); if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Returning markSupported: " + markSupported); + logger.finest(super.toString() + " Returning markSupported: " + markSupported); return markSupported; } + @Override public void mark(int readLimit) { if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Marking next " + readLimit + " bytes"); + logger.finest(super.toString() + " Marking next " + readLimit + " bytes"); lock.lock(); try { @@ -1217,9 +1232,10 @@ public void mark(int readLimit) { } } + @Override public void reset() throws IOException { if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Resetting to previous mark"); + logger.finest(super.toString() + " Resetting to previous mark"); lock.lock(); try { @@ -1230,9 +1246,10 @@ public void reset() throws IOException { } } + @Override public void close() throws IOException { if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Closing"); + logger.finest(super.toString() + " Closing"); filteredStream.close(); } @@ -1255,38 +1272,43 @@ final void setFilteredStream(OutputStream os) { filteredStream = os; } + @Override public void close() throws IOException { if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Closing"); + logger.finest(super.toString() + " Closing"); filteredStream.close(); } + @Override public void flush() throws IOException { if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Flushing"); + logger.finest(super.toString() + " Flushing"); filteredStream.flush(); } private final byte singleByte[] = new byte[1]; + @Override public void write(int b) throws IOException { singleByte[0] = (byte) (b & 0xFF); writeInternal(singleByte, 0, singleByte.length); } + @Override public void write(byte[] b) throws IOException { writeInternal(b, 0, b.length); } + @Override public void write(byte[] b, int off, int len) throws IOException { writeInternal(b, off, len); } private void writeInternal(byte[] b, int off, int len) throws IOException { if (logger.isLoggable(Level.FINEST)) - logger.finest(toString() + " Writing " + len + " bytes"); + logger.finest(super.toString() + " Writing " + len + " bytes"); filteredStream.write(b, off, len); } @@ -1328,6 +1350,7 @@ void setStreams(InputStream is, OutputStream os) { proxyOutputStream.setFilteredStream(os); } + @Override public InputStream getInputStream() throws IOException { if (logger.isLoggable(Level.FINEST)) logger.finest(logContext + " Getting input stream"); @@ -1335,6 +1358,7 @@ public InputStream getInputStream() throws IOException { return proxyInputStream; } + @Override public OutputStream getOutputStream() throws IOException { if (logger.isLoggable(Level.FINEST)) logger.finest(logContext + " Getting output stream"); @@ -1343,105 +1367,130 @@ public OutputStream getOutputStream() throws IOException { } // Allow methods that should just forward to the underlying TCP socket or return fixed values + @Override public InetAddress getInetAddress() { return tdsChannel.tcpSocket.getInetAddress(); } + @Override public boolean getKeepAlive() throws SocketException { return tdsChannel.tcpSocket.getKeepAlive(); } + @Override public InetAddress getLocalAddress() { return tdsChannel.tcpSocket.getLocalAddress(); } + @Override public int getLocalPort() { return tdsChannel.tcpSocket.getLocalPort(); } + @Override public SocketAddress getLocalSocketAddress() { return tdsChannel.tcpSocket.getLocalSocketAddress(); } + @Override public boolean getOOBInline() throws SocketException { return tdsChannel.tcpSocket.getOOBInline(); } + @Override public int getPort() { return tdsChannel.tcpSocket.getPort(); } + @Override public int getReceiveBufferSize() throws SocketException { return tdsChannel.tcpSocket.getReceiveBufferSize(); } + @Override public SocketAddress getRemoteSocketAddress() { return tdsChannel.tcpSocket.getRemoteSocketAddress(); } + @Override public boolean getReuseAddress() throws SocketException { return tdsChannel.tcpSocket.getReuseAddress(); } + @Override public int getSendBufferSize() throws SocketException { return tdsChannel.tcpSocket.getSendBufferSize(); } + @Override public int getSoLinger() throws SocketException { return tdsChannel.tcpSocket.getSoLinger(); } + @Override public int getSoTimeout() throws SocketException { return tdsChannel.tcpSocket.getSoTimeout(); } + @Override public boolean getTcpNoDelay() throws SocketException { return tdsChannel.tcpSocket.getTcpNoDelay(); } + @Override public int getTrafficClass() throws SocketException { return tdsChannel.tcpSocket.getTrafficClass(); } + @Override public boolean isBound() { return true; } + @Override public boolean isClosed() { return false; } + @Override public boolean isConnected() { return true; } + @Override public boolean isInputShutdown() { return false; } + @Override public boolean isOutputShutdown() { return false; } + @Override public String toString() { return tdsChannel.tcpSocket.toString(); } + @Override public SocketChannel getChannel() { return null; } // Disallow calls to methods that would change the underlying TCP socket + @Override public void bind(SocketAddress bindPoint) throws IOException { logger.finer(logContext + " Disallowed call to bind. Throwing IOException."); throw new IOException(); } + @Override public void connect(SocketAddress endpoint) throws IOException { logger.finer(logContext + " Disallowed call to connect (without timeout). Throwing IOException."); throw new IOException(); } + @Override public void connect(SocketAddress endpoint, int timeout) throws IOException { logger.finer(logContext + " Disallowed call to connect (with timeout). Throwing IOException."); throw new IOException(); @@ -1449,63 +1498,76 @@ public void connect(SocketAddress endpoint, int timeout) throws IOException { // Ignore calls to methods that would otherwise allow the SSL socket // to directly manipulate the underlying TCP socket + @Override public void close() throws IOException { if (logger.isLoggable(Level.FINER)) logger.finer(logContext + " Ignoring close"); } + @Override public void setReceiveBufferSize(int size) throws SocketException { if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Ignoring setReceiveBufferSize size:" + size); } + @Override public void setSendBufferSize(int size) throws SocketException { if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Ignoring setSendBufferSize size:" + size); } + @Override public void setReuseAddress(boolean on) throws SocketException { if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Ignoring setReuseAddress"); } + @Override public void setSoLinger(boolean on, int linger) throws SocketException { if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Ignoring setSoLinger"); } + @Override public void setSoTimeout(int timeout) throws SocketException { tdsChannel.tcpSocket.setSoTimeout(timeout); } + @Override public void setTcpNoDelay(boolean on) throws SocketException { tdsChannel.tcpSocket.setTcpNoDelay(on); } + @Override public void setTrafficClass(int tc) throws SocketException { if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Ignoring setTrafficClass"); } + @Override public void shutdownInput() throws IOException { if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Ignoring shutdownInput"); } + @Override public void shutdownOutput() throws IOException { if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Ignoring shutdownOutput"); } + @Override public void sendUrgentData(int data) throws IOException { if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Ignoring sendUrgentData"); } + @Override public void setKeepAlive(boolean on) throws SocketException { tdsChannel.tcpSocket.setKeepAlive(on); } + @Override public void setOOBInline(boolean on) throws SocketException { if (logger.isLoggable(Level.FINER)) logger.finer(toString() + " Ignoring setOOBInline"); @@ -2299,7 +2361,7 @@ enum Result { TimeUnit.SECONDS, new SynchronousQueue()); // When parallel connections are to be used, use minimum timeout slice of 1500 milliseconds. - private static final int minTimeoutForParallelConnections = 1500; + private static final int MIN_TIMEOUT_FOR_PARALLEL_CONNECTIONS = 1500; // lock used for synchronization while updating // data within a socketFinder object @@ -2335,7 +2397,7 @@ enum Result { private final String traceID; // maximum number of IP Addresses supported - private static final int ipAddressLimit = 64; + private static final int IP_ADDRESS_LIMIT = 64; // necessary for raising exceptions so that the connection pool can be notified private final SQLServerConnection conn; @@ -2379,8 +2441,8 @@ Socket findSocket(String hostName, int portNumber, int timeoutInMilliSeconds, bo // MSF is false. TNIR could be true or false. DBMirroring could be true or false. // For TNIR first attempt, we should do existing behavior including how host name is resolved. if (useTnir && isTnirFirstAttempt) { - return getSocketByIPPreference(hostName, portNumber, SQLServerConnection.TnirFirstAttemptTimeoutMs, - iPAddressPreference); + return getSocketByIPPreference(hostName, portNumber, + SQLServerConnection.TNIR_FIRST_ATTEMPT_TIMEOUT_MS, iPAddressPreference); } else if (!useTnir) { return getSocketByIPPreference(hostName, portNumber, timeoutInMilliSeconds, iPAddressPreference); } @@ -2392,7 +2454,7 @@ Socket findSocket(String hostName, int portNumber, int timeoutInMilliSeconds, bo // Ignore TNIR if host resolves to more than 64 IPs. Make sure we are using original timeout for this. inetAddrs = InetAddress.getAllByName(hostName); - if ((useTnir) && (inetAddrs.length > ipAddressLimit)) { + if ((useTnir) && (inetAddrs.length > IP_ADDRESS_LIMIT)) { useTnir = false; timeoutInMilliSeconds = timeoutInMilliSecondsForFullTimeout; } @@ -2413,10 +2475,10 @@ Socket findSocket(String hostName, int portNumber, int timeoutInMilliSeconds, bo logger.finer(loggingString.toString()); } - if (inetAddrs.length > ipAddressLimit) { + if (inetAddrs.length > IP_ADDRESS_LIMIT) { MessageFormat form = new MessageFormat( SQLServerException.getErrString("R_ipAddressLimitWithMultiSubnetFailover")); - Object[] msgArgs = {Integer.toString(ipAddressLimit)}; + Object[] msgArgs = {Integer.toString(IP_ADDRESS_LIMIT)}; String errorStr = form.format(msgArgs); // we do not want any retry to happen here. So, terminate the connection // as the config is unsupported. @@ -2427,7 +2489,7 @@ Socket findSocket(String hostName, int portNumber, int timeoutInMilliSeconds, bo // Single address so do not start any threads return getConnectedSocket(inetAddrs[0], portNumber, timeoutInMilliSeconds); } - timeoutInMilliSeconds = Math.max(timeoutInMilliSeconds, minTimeoutForParallelConnections); + timeoutInMilliSeconds = Math.max(timeoutInMilliSeconds, MIN_TIMEOUT_FOR_PARALLEL_CONNECTIONS); if (Util.isIBM()) { if (logger.isLoggable(Level.FINER)) { logger.finer(this.toString() + "Using Java NIO with timeout:" + timeoutInMilliSeconds); @@ -2726,7 +2788,7 @@ private Socket getSocketByIPPreference(String hostName, int portNumber, int time InetAddress addresses[] = InetAddress.getAllByName(hostName); IPAddressPreference pref = IPAddressPreference.valueOfString(iPAddressPreference); switch (pref) { - case IPv6First: + case IPV6_FIRST: // Try to connect to first choice of IP address type fillAddressList(addresses, true); addr = getInetAddressByIPPreference(hostName, portNumber); @@ -2738,7 +2800,7 @@ private Socket getSocketByIPPreference(String hostName, int portNumber, int time if (!addr.isUnresolved()) return getConnectedSocket(addr, timeoutInMilliSeconds); break; - case IPv4First: + case IPV4_FIRST: // Try to connect to first choice of IP address type fillAddressList(addresses, false); addr = getInetAddressByIPPreference(hostName, portNumber); @@ -2750,7 +2812,7 @@ private Socket getSocketByIPPreference(String hostName, int portNumber, int time if (!addr.isUnresolved()) return getConnectedSocket(addr, timeoutInMilliSeconds); break; - case UsePlatformDefault: + case USE_PLATFORM_DEFAULT: for (InetAddress address : addresses) { addr = new InetSocketAddress(address, portNumber); if (!addr.isUnresolved()) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java index cecf363a9..6d57abb1c 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerEnclaveProvider.java @@ -49,16 +49,6 @@ * */ interface ISQLServerEnclaveProvider { - /** - * sp_describe_parameter_encryption stored procedure with 2 params - */ - static final String SDPE1 = "EXEC sp_describe_parameter_encryption ?,?"; - - /** - * sp_describe_parameter_encryption stored procedure with 3 params - */ - static final String SDPE2 = "EXEC sp_describe_parameter_encryption ?,?,?"; - /** * Get the Enclave package * diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java b/src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java index 5c32b7583..2151a176d 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java @@ -26,7 +26,7 @@ /** - * KerbAuthentication for int auth. + * KerbAuthentication for integrated authentication. */ final class KerbAuthentication extends SSPIAuthentication { private static final java.util.logging.Logger authLogger = java.util.logging.Logger @@ -47,7 +47,12 @@ final class KerbAuthentication extends SSPIAuthentication { Configuration.setConfiguration(new JaasConfiguration(Configuration.getConfiguration())); } - private void intAuthInit() throws SQLServerException { + /** + * Initializes the Kerberos client security context + * + * @throws SQLServerException + */ + private void initAuthInit() throws SQLServerException { try { // If we need to support NTLM as well, we can use null // Kerberos OID @@ -107,12 +112,13 @@ private void intAuthInit() throws SQLServerException { authLogger.finer(toString() + " Getting client credentials"); } peerCredentials = getClientCredential(currentSubject, manager, kerberos); + if (authLogger.isLoggable(Level.FINER)) { authLogger.finer(toString() + " creating security context"); } - peerContext = manager.createContext(remotePeerName, kerberos, peerCredentials, GSSContext.DEFAULT_LIFETIME); + // The following flags should be inline with our native implementation. peerContext.requestCredDeleg(true); peerContext.requestMutualAuth(true); @@ -131,7 +137,6 @@ private void intAuthInit() throws SQLServerException { con.terminate(SQLServerException.DRIVER_ERROR_NONE, SQLServerException.getErrString("R_integratedAuthenticationFailed"), ge); } - } // We have to do a privileged action to create the credential of the user in the current context @@ -150,7 +155,7 @@ public GSSCredential run() throws GSSException { return (GSSCredential) credential; } - private byte[] intAuthHandShake(byte[] pin, boolean[] done) throws SQLServerException { + private byte[] initAuthHandShake(byte[] pin, boolean[] done) throws SQLServerException { try { if (authLogger.isLoggable(Level.FINER)) { authLogger.finer(toString() + " Sending token to server over secure context"); @@ -204,9 +209,9 @@ private byte[] intAuthHandShake(byte[] pin, boolean[] done) throws SQLServerExce byte[] generateClientContext(byte[] pin, boolean[] done) throws SQLServerException { if (null == peerContext) { - intAuthInit(); + initAuthInit(); } - return intAuthHandShake(pin, done); + return initAuthHandShake(pin, done); } void releaseClientContext() { diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerAASEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerAASEnclaveProvider.java index b0612b030..b12151caf 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerAASEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerAASEnclaveProvider.java @@ -124,6 +124,13 @@ private void validateAttestationResponse() throws SQLServerException { private ArrayList describeParameterEncryption(SQLServerConnection connection, SQLServerStatement statement, String userSql, String preparedTypeDefinitions, Parameter[] params, ArrayList parameterNames) throws SQLServerException { + + // sp_describe_parameter_encryption stored procedure with 2 params + final String SDPE1 = "EXEC sp_describe_parameter_encryption ?,?"; + + // sp_describe_parameter_encryption stored procedure with 3 params + final String SDPE2 = "EXEC sp_describe_parameter_encryption ?,?,?"; + ArrayList enclaveRequestedCEKs = new ArrayList<>(); try (PreparedStatement stmt = connection.prepareStatement(connection.enclaveEstablished() ? SDPE1 : SDPE2)) { // Check the cache for metadata for Always Encrypted versions 1 and 3, when there are parameters to check. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java index f4f6cd458..24bc18ddb 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerColumnEncryptionCertificateStoreProvider.java @@ -61,7 +61,7 @@ private byte[] decryptColumnEncryptionKeyWindows(String masterKeyPath, String en return AuthenticationJNI.DecryptColumnEncryptionKey(masterKeyPath, encryptionAlgorithm, encryptedColumnEncryptionKey); } catch (DLLException e) { - DLLException.buildException(e.GetErrCode(), e.GetParam1(), e.GetParam2(), e.GetParam3()); + DLLException.buildException(e.getErrCode(), e.GetParam1(), e.GetParam2(), e.GetParam3()); return null; } } @@ -88,7 +88,7 @@ public boolean verifyColumnMasterKeyMetadata(String masterKeyPath, boolean allow try { return AuthenticationJNI.VerifyColumnMasterKeyMetadata(masterKeyPath, allowEnclaveComputations, signature); } catch (DLLException e) { - DLLException.buildException(e.GetErrCode(), e.GetParam1(), e.GetParam2(), e.GetParam3()); + DLLException.buildException(e.getErrCode(), e.GetParam1(), e.GetParam2(), e.GetParam3()); return false; } } diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java index fe0314dea..039625f05 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerConnection.java @@ -135,9 +135,6 @@ public class SQLServerConnection implements ISQLServerConnection, java.io.Serial /** discardedPreparedStatementHandle count */ private AtomicInteger discardedPreparedStatementHandleCount = new AtomicInteger(0); - /** keystore provider */ - private SQLServerColumnEncryptionKeyStoreProvider keystoreProvider = null; - /** fedAuth required by user flag */ private boolean fedAuthRequiredByUser = false; @@ -242,7 +239,7 @@ public class SQLServerConnection implements ISQLServerConnection, java.io.Serial * @throws SQLServerException */ SharedTimer getSharedTimer() throws SQLServerException { - if (state == State.Closed) { + if (state == State.CLOSED) { SQLServerException.makeFromDriverError(null, null, SQLServerException.getErrString("R_connectionIsClosed"), SQLServerException.EXCEPTION_XOPEN_CONNECTION_FAILURE, false); } @@ -301,9 +298,9 @@ public boolean equals(Object obj) { if (!(obj instanceof CityHash128Key)) return false; - return (java.util.Arrays.equals(segments, ((CityHash128Key) obj).segments)// checks if hash is equal, - // short-circuitting; - && this.unhashedString.equals(((CityHash128Key) obj).unhashedString));// checks if string is equal + // checks if hash is equal, short-circuitting and if string is equal + return (java.util.Arrays.equals(segments, ((CityHash128Key) obj).segments) + && this.unhashedString.equals(((CityHash128Key) obj).unhashedString)); } public int hashCode() { @@ -417,8 +414,7 @@ class IdleNetworkTracker { /** Has it been more than maxIdleMillis since network activity has been marked */ private boolean isIdle() { - boolean ret = Instant.now().minusMillis(maxIdleMillis).isAfter(lastNetworkActivity); - return ret; + return Instant.now().minusMillis(maxIdleMillis).isAfter(lastNetworkActivity); } /** Mark network activity now */ @@ -520,29 +516,29 @@ class FederatedAuthenticationFeatureExtensionData implements Serializable { switch (authenticationString.toUpperCase(Locale.ENGLISH)) { case "ACTIVEDIRECTORYPASSWORD": - this.authentication = SqlAuthentication.ActiveDirectoryPassword; + this.authentication = SqlAuthentication.ACTIVE_DIRECTORY_PASSWORD; break; case "ACTIVEDIRECTORYINTEGRATED": - this.authentication = SqlAuthentication.ActiveDirectoryIntegrated; + this.authentication = SqlAuthentication.ACTIVE_DIRECTORY_INTEGRATED; break; case "ACTIVEDIRECTORYMANAGEDIDENTITY": - this.authentication = SqlAuthentication.ActiveDirectoryManagedIdentity; + this.authentication = SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY; break; case "DEFAULTAZURECREDENTIAL": - this.authentication = SqlAuthentication.DefaultAzureCredential; + this.authentication = SqlAuthentication.DEFAULT_AZURE_CREDENTIAL; break; case "ACTIVEDIRECTORYSERVICEPRINCIPAL": - this.authentication = SqlAuthentication.ActiveDirectoryServicePrincipal; + this.authentication = SqlAuthentication.ACTIVE_DIRECTORY_SERVICE_PRINCIPAL; break; case "ACTIVEDIRECTORYINTERACTIVE": - this.authentication = SqlAuthentication.ActiveDirectoryInteractive; + this.authentication = SqlAuthentication.ACTIVE_DIRECTORY_INTERACTIVE; break; default: // If authenticationString not specified, check if access token callback was set. // If access token callback is set, break. if (null != activeConnectionProperties .get(SQLServerDriverObjectProperty.ACCESS_TOKEN_CALLBACK.toString())) { - this.authentication = SqlAuthentication.NotSpecified; + this.authentication = SqlAuthentication.NOT_SPECIFIED; break; } assert (false); @@ -589,20 +585,21 @@ class ActiveDirectoryAuthentication { static final int GET_ACCESS_TOKEN_OTHER_ERROR = 3; } + final static int TNIR_FIRST_ATTEMPT_TIMEOUT_MS = 500; // fraction of timeout to use for fast failover connections + /** * Denotes the state of the SqlServerConnection. */ private enum State { - Initialized, // default value on calling SQLServerConnection constructor - Connected, // indicates that the TCP connection has completed - Opened, // indicates that the prelogin, login have completed, the database session established and the + INITIALIZED, // default value on calling SQLServerConnection constructor + CONNECTED, // indicates that the TCP connection has completed + OPENED, // indicates that the prelogin, login have completed, the database session established and the // connection is ready for use. - Closed // indicates that the connection has been closed. + CLOSED // indicates that the connection has been closed. } private final static float TIMEOUTSTEP = 0.08F; // fraction of timeout to use for fast failover connections private final static float TIMEOUTSTEP_TNIR = 0.125F; - final static int TnirFirstAttemptTimeoutMs = 500; // fraction of timeout to use for fast failover connections /** * Connection state variables. NB If new state is added then logical connections derived from a physical connection @@ -622,7 +619,7 @@ ServerPortPlaceHolder getRoutingInfo() { } /** Permission targets */ - private static final String callAbortPerm = "callAbort"; + private static final String CALL_ABORT_PERM = "callAbort"; private static final String SET_NETWORK_TIMEOUT_PERM = "setNetworkTimeout"; @@ -837,7 +834,7 @@ final String getTrustManagerConstructorArg() { String encryptOption = null; boolean isColumnEncryptionSettingEnabled() { - return (columnEncryptionSetting.equalsIgnoreCase(ColumnEncryptionSetting.Enabled.toString())); + return (columnEncryptionSetting.equalsIgnoreCase(ColumnEncryptionSetting.ENABLED.toString())); } boolean getSendTemporalDataTypesAsStringForBulkCopy() { @@ -865,9 +862,6 @@ boolean getSendTemporalDataTypesAsStringForBulkCopy() { /** server column encryption version */ private ColumnEncryptionVersion serverColumnEncryptionVersion = ColumnEncryptionVersion.AE_NOTSUPPORTED; - /** Enclave type */ - private String enclaveType = null; - boolean getServerSupportsColumnEncryption() { return (serverColumnEncryptionVersion.value() > ColumnEncryptionVersion.AE_NOTSUPPORTED.value()); } @@ -1085,6 +1079,8 @@ SQLServerColumnEncryptionKeyStoreProvider getSystemColumnEncryptionKeyStoreProvi SQLServerColumnEncryptionKeyStoreProvider getSystemOrGlobalColumnEncryptionKeyStoreProvider( String providerName) throws SQLServerException { + SQLServerColumnEncryptionKeyStoreProvider keystoreProvider = null; + lock.lock(); try { // check for global system providers @@ -1363,7 +1359,7 @@ public static void clearUserTokenCache() { private byte[] ntlmPasswordHash = null; /** integrated authentication scheme */ - private AuthenticationScheme intAuthScheme = AuthenticationScheme.nativeAuthentication; + private AuthenticationScheme intAuthScheme = AuthenticationScheme.NATIVE_AUTHENTICATION; /** impersonated user credential */ private GSSCredential impersonatedUserCred; @@ -1400,7 +1396,7 @@ final boolean rolledBackTransaction() { } /** connection state */ - private volatile State state = State.Initialized; + private volatile State state = State.INITIALIZED; private void setState(State state) { this.state = state; @@ -1411,7 +1407,7 @@ private void setState(State state) { * session is established and after the session is closed. */ final boolean isSessionUnAvailable() { - return !(state.equals(State.Opened)); + return !(state.equals(State.OPENED)); } final static int maxDecimalPrecision = 38; // @@max_precision for SQL 2000 and 2005 is 38. @@ -1588,7 +1584,7 @@ final int getRetryCount() { } final boolean attachConnId() { - return state.equals(State.Connected); + return state.equals(State.CONNECTED); } SQLServerPooledConnection getPooledConnectionParent() { @@ -1753,7 +1749,7 @@ Connection connect(Properties propsIn, SQLServerPooledConnection pooledConnectio } // Interactive auth may involve MFA which require longer timeout - if (SqlAuthentication.ActiveDirectoryInteractive.toString().equalsIgnoreCase(authenticationString)) { + if (SqlAuthentication.ACTIVE_DIRECTORY_INTERACTIVE.toString().equalsIgnoreCase(authenticationString)) { loginTimeoutSeconds *= 10; } @@ -1869,13 +1865,13 @@ private void registerKeyStoreProviderOnConnection(String keyStoreAuth, String ke } else { KeyStoreAuthentication keyStoreAuthentication = KeyStoreAuthentication.valueOfString(keyStoreAuth); switch (keyStoreAuthentication) { - case JavaKeyStorePassword: + case JAVA_KEYSTORE_PASSWORD: setKeyStoreSecretAndLocation(keyStoreSecret, keyStoreLocation); break; - case KeyVaultClientSecret: + case KEYVAULT_CLIENT_SECRET: this.setKeyVaultProvider(keyStorePrincipalId, keyStoreSecret); break; - case KeyVaultManagedIdentity: + case KEYVAULT_MANAGED_IDENTITY: setKeyVaultProvider(keyStorePrincipalId); break; default: @@ -2245,11 +2241,11 @@ Connection connectInternal(Properties propsIn, trustServerCertificate = isBooleanPropertyOn(sPropKey, sPropValue); // Set requestedEncryptionLevel according to the value of the encrypt connection property - if (encryptOption.compareToIgnoreCase(EncryptOption.False.toString()) == 0) { + if (encryptOption.compareToIgnoreCase(EncryptOption.FALSE.toString()) == 0) { requestedEncryptionLevel = TDS.ENCRYPT_OFF; - } else if (encryptOption.compareToIgnoreCase(EncryptOption.True.toString()) == 0) { + } else if (encryptOption.compareToIgnoreCase(EncryptOption.TRUE.toString()) == 0) { requestedEncryptionLevel = TDS.ENCRYPT_ON; - } else if (encryptOption.compareToIgnoreCase(EncryptOption.Strict.toString()) == 0) { + } else if (encryptOption.compareToIgnoreCase(EncryptOption.STRICT.toString()) == 0) { // this is necessary so we don't encrypt again requestedEncryptionLevel = TDS.ENCRYPT_NOT_SUP; @@ -2407,13 +2403,13 @@ Connection connectInternal(Properties propsIn, } } - if (intAuthScheme == AuthenticationScheme.javaKerberos) { + if (intAuthScheme == AuthenticationScheme.JAVA_KERBEROS) { sPropKey = SQLServerDriverObjectProperty.GSS_CREDENTIAL.toString(); if (activeConnectionProperties.containsKey(sPropKey)) { impersonatedUserCred = (GSSCredential) activeConnectionProperties.get(sPropKey); isUserCreatedCredential = true; } - } else if (intAuthScheme == AuthenticationScheme.ntlm) { + } else if (intAuthScheme == AuthenticationScheme.NTLM) { String sPropKeyDomain = SQLServerDriverStringProperty.DOMAIN.toString(); String sPropValueDomain = activeConnectionProperties.getProperty(sPropKeyDomain); if (null == sPropValueDomain) { @@ -2449,7 +2445,7 @@ Connection connectInternal(Properties propsIn, } authenticationString = SqlAuthentication.valueOfString(sPropValue).toString().trim(); - if (authenticationString.equalsIgnoreCase(SqlAuthentication.DefaultAzureCredential.toString()) + if (authenticationString.equalsIgnoreCase(SqlAuthentication.DEFAULT_AZURE_CREDENTIAL.toString()) && (!activeConnectionProperties.getProperty(SQLServerDriverStringProperty.PASSWORD.toString()) .isEmpty())) { MessageFormat form = new MessageFormat( @@ -2458,12 +2454,12 @@ Connection connectInternal(Properties propsIn, } if (integratedSecurity - && !authenticationString.equalsIgnoreCase(SqlAuthentication.NotSpecified.toString())) { + && !authenticationString.equalsIgnoreCase(SqlAuthentication.NOT_SPECIFIED.toString())) { throw new SQLServerException( SQLServerException.getErrString("R_SetAuthenticationWhenIntegratedSecurityTrue"), null); } - if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString()) + if (authenticationString.equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTEGRATED.toString()) && ((!activeConnectionProperties.getProperty(SQLServerDriverStringProperty.USER.toString()) .isEmpty()) || (!activeConnectionProperties @@ -2472,7 +2468,7 @@ Connection connectInternal(Properties propsIn, SQLServerException.getErrString("R_IntegratedAuthenticationWithUserPassword"), null); } - if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryPassword.toString()) + if (authenticationString.equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_PASSWORD.toString()) && ((activeConnectionProperties.getProperty(SQLServerDriverStringProperty.USER.toString()) .isEmpty()) || (activeConnectionProperties @@ -2481,7 +2477,8 @@ Connection connectInternal(Properties propsIn, null); } - if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryManagedIdentity.toString()) + if (authenticationString + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY.toString()) && (!activeConnectionProperties.getProperty(SQLServerDriverStringProperty.PASSWORD.toString()) .isEmpty())) { MessageFormat form = new MessageFormat( @@ -2490,7 +2487,7 @@ Connection connectInternal(Properties propsIn, } if (authenticationString - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryServicePrincipal.toString())) { + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_SERVICE_PRINCIPAL.toString())) { if ((activeConnectionProperties.getProperty(SQLServerDriverStringProperty.USER.toString()).isEmpty() || activeConnectionProperties.getProperty(SQLServerDriverStringProperty.PASSWORD.toString()) .isEmpty()) @@ -2519,7 +2516,7 @@ Connection connectInternal(Properties propsIn, } } - if (authenticationString.equalsIgnoreCase(SqlAuthentication.SqlPassword.toString()) + if (authenticationString.equalsIgnoreCase(SqlAuthentication.SQLPASSWORD.toString()) && ((activeConnectionProperties.getProperty(SQLServerDriverStringProperty.USER.toString()) .isEmpty()) || (activeConnectionProperties @@ -2543,7 +2540,7 @@ Connection connectInternal(Properties propsIn, SQLServerException.getErrString("R_SetAccesstokenWhenIntegratedSecurityTrue"), null); } - if ((!authenticationString.equalsIgnoreCase(SqlAuthentication.NotSpecified.toString())) + if ((!authenticationString.equalsIgnoreCase(SqlAuthentication.NOT_SPECIFIED.toString())) && (null != accessTokenInByte)) { throw new SQLServerException( SQLServerException.getErrString("R_SetBothAuthenticationAndAccessToken"), null); @@ -2558,7 +2555,7 @@ Connection connectInternal(Properties propsIn, } // Turn off TNIR for FedAuth if user did not set TNIR explicitly - if (!userSetTNIR && (!authenticationString.equalsIgnoreCase(SqlAuthentication.NotSpecified.toString()) + if (!userSetTNIR && (!authenticationString.equalsIgnoreCase(SqlAuthentication.NOT_SPECIFIED.toString()) || null != accessTokenInByte)) { transparentNetworkIPResolution = false; } @@ -2928,7 +2925,7 @@ else if (0 == requestedPacketSize) } } - state = State.Opened; + state = State.OPENED; if (connectionlogger.isLoggable(Level.FINER)) { connectionlogger.finer(toString() + " End of connect"); @@ -2936,10 +2933,8 @@ else if (0 == requestedPacketSize) } finally { // once we exit the connect function, the connection can be only in one of two // states, Opened or Closed(if an exception occurred) - if (!state.equals(State.Opened)) { - // if connection is not closed, close it - if (!state.equals(State.Closed)) - this.close(); + if (!state.equals(State.OPENED) && !state.equals(State.CLOSED)) { + this.close(); } activeConnectionProperties.remove(SQLServerDriverStringProperty.TRUST_STORE_PASSWORD.toString()); @@ -3029,7 +3024,7 @@ private void login(String primary, String primaryInstanceName, int primaryPortNu // back into the parser for the error cases. while (true) { clientConnectionId = null; - state = State.Initialized; + state = State.INITIALIZED; try { if (isDBMirroring && useFailoverHost) { @@ -3413,7 +3408,7 @@ private InetSocketAddress connectHelper(ServerPortPlaceHolder serverInfo, int ti serverInfo.getPortNumber(), (0 == timeOutFullInSeconds) ? 0 : timeOutSliceInMillis, useParallel, useTnir, isTnirFirstAttempt, timeOutsliceInMillisForFullTimeout, iPAddressPreference); - setState(State.Connected); + setState(State.CONNECTED); try { clientConnectionId = UUID.randomUUID(); @@ -3482,7 +3477,7 @@ private void executeReconnect(LogonCommand logonCommand) throws SQLServerExcepti */ void prelogin(String serverName, int portNumber) throws SQLServerException { // Build a TDS Pre-Login packet to send to the server. - if ((!authenticationString.equalsIgnoreCase(SqlAuthentication.NotSpecified.toString())) + if ((!authenticationString.equalsIgnoreCase(SqlAuthentication.NOT_SPECIFIED.toString())) || (null != accessTokenInByte) || null != activeConnectionProperties .get(SQLServerDriverObjectProperty.ACCESS_TOKEN_CALLBACK.toString())) { fedAuthRequiredByUser = true; @@ -3862,10 +3857,10 @@ void prelogin(String serverName, int portNumber) throws SQLServerException { // We must NOT use the response for the FEDAUTHREQUIRED PreLogin option, if the connection string // option - // was not using the new Authentication keyword or in other words, if Authentication=NotSpecified + // was not using the new Authentication keyword or in other words, if Authentication=NOT_SPECIFIED // Or AccessToken is not null, mean token based authentication is used. if (((null != authenticationString) - && (!authenticationString.equalsIgnoreCase(SqlAuthentication.NotSpecified.toString()))) + && (!authenticationString.equalsIgnoreCase(SqlAuthentication.NOT_SPECIFIED.toString()))) || (null != accessTokenInByte) || null != activeConnectionProperties .get(SQLServerDriverObjectProperty.ACCESS_TOKEN_CALLBACK.toString())) { fedAuthRequiredPreLoginResponse = (preloginResponse[optionOffset] == 1); @@ -3910,15 +3905,15 @@ final void terminate(int driverErrorCode, String message) throws SQLServerExcept } final void terminate(int driverErrorCode, String message, Throwable throwable) throws SQLServerException { - String state = this.state.equals(State.Opened) ? SQLServerException.EXCEPTION_XOPEN_CONNECTION_FAILURE - : SQLServerException.EXCEPTION_XOPEN_CONNECTION_CANT_ESTABLISH; + String st = this.state.equals(State.OPENED) ? SQLServerException.EXCEPTION_XOPEN_CONNECTION_FAILURE + : SQLServerException.EXCEPTION_XOPEN_CONNECTION_CANT_ESTABLISH; if (!xopenStates) - state = SQLServerException.mapFromXopen(state); + st = SQLServerException.mapFromXopen(st); SQLServerException ex = new SQLServerException(this, - SQLServerException.checkAndAppendClientConnId(message, this), state, // X/Open or SQL99 - // SQLState + SQLServerException.checkAndAppendClientConnId(message, this), st, // X/Open or SQL99 + // SQLState 0, // database error number (0 -> driver error) true); // include stack trace in log @@ -4381,11 +4376,11 @@ public void abort(Executor executor) throws SQLException { SecurityManager secMgr = System.getSecurityManager(); if (secMgr != null) { try { - SQLPermission perm = new SQLPermission(callAbortPerm); + SQLPermission perm = new SQLPermission(CALL_ABORT_PERM); secMgr.checkPermission(perm); } catch (SecurityException ex) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_permissionDenied")); - Object[] msgArgs = {callAbortPerm}; + Object[] msgArgs = {CALL_ABORT_PERM}; SQLServerException.makeFromDriverError(this, this, form.format(msgArgs), null, true); } } @@ -4398,7 +4393,7 @@ public void abort(Executor executor) throws SQLException { * Always report the connection as closed for any further use, no matter what happens when we try to clean * up the physical resources associated with the connection using executor. */ - setState(State.Closed); + setState(State.CLOSED); executor.execute(() -> clearConnectionResources()); } @@ -4414,7 +4409,7 @@ public void close() throws SQLServerException { * Always report the connection as closed for any further use, no matter what happens when we try to clean up * the physical resources associated with the connection. */ - setState(State.Closed); + setState(State.CLOSED); clearConnectionResources(); @@ -4455,7 +4450,7 @@ private void clearConnectionResources() { * will pool the connection */ final void poolCloseEventNotify() throws SQLServerException { - if (state.equals(State.Opened) && null != pooledConnectionParent) { + if (state.equals(State.OPENED) && null != pooledConnectionParent) { // autocommit = true => nothing to do when app closes connection // XA = true => the transaction manager is the only one who can invoke transactional APIs @@ -4792,22 +4787,22 @@ int writeFedAuthFeatureRequest(boolean write, /* if false just calculates the le case TDS.TDS_FEDAUTH_LIBRARY_ADAL: byte workflow = 0x00; switch (fedAuthFeatureExtensionData.authentication) { - case ActiveDirectoryPassword: + case ACTIVE_DIRECTORY_PASSWORD: workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYPASSWORD; break; - case ActiveDirectoryIntegrated: + case ACTIVE_DIRECTORY_INTEGRATED: workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYINTEGRATED; break; - case ActiveDirectoryManagedIdentity: + case ACTIVE_DIRECTORY_MANAGED_IDENTITY: workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYMANAGEDIDENTITY; break; - case DefaultAzureCredential: + case DEFAULT_AZURE_CREDENTIAL: workflow = TDS.ADALWORKFLOW_DEFAULTAZURECREDENTIAL; break; - case ActiveDirectoryInteractive: + case ACTIVE_DIRECTORY_INTERACTIVE: workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYINTERACTIVE; break; - case ActiveDirectoryServicePrincipal: + case ACTIVE_DIRECTORY_SERVICE_PRINCIPAL: workflow = TDS.ADALWORKFLOW_ACTIVEDIRECTORYSERVICEPRINCIPAL; break; default: @@ -4993,10 +4988,10 @@ private void logon(LogonCommand command) throws SQLServerException { SSPIAuthentication authentication = null; if (integratedSecurity) { - if (AuthenticationScheme.nativeAuthentication == intAuthScheme) { + if (AuthenticationScheme.NATIVE_AUTHENTICATION == intAuthScheme) { authentication = new AuthenticationJNI(this, currentConnectPlaceHolder.getServerName(), currentConnectPlaceHolder.getPortNumber()); - } else if (AuthenticationScheme.javaKerberos == intAuthScheme) { + } else if (AuthenticationScheme.JAVA_KERBEROS == intAuthScheme) { if (null != impersonatedUserCred) { authentication = new KerbAuthentication(this, currentConnectPlaceHolder.getServerName(), currentConnectPlaceHolder.getPortNumber(), impersonatedUserCred, isUserCreatedCredential); @@ -5023,15 +5018,15 @@ private void logon(LogonCommand command) throws SQLServerException { * Feature Extension in Login7, indicating the intent to use Active Directory Authentication Library for SQL * Server. */ - if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryPassword.toString()) - || ((authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString()) + if (authenticationString.equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_PASSWORD.toString()) + || ((authenticationString.equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTEGRATED.toString()) || authenticationString - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryManagedIdentity.toString()) - || authenticationString.equalsIgnoreCase(SqlAuthentication.DefaultAzureCredential.toString()) + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY.toString()) + || authenticationString.equalsIgnoreCase(SqlAuthentication.DEFAULT_AZURE_CREDENTIAL.toString()) || authenticationString - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryServicePrincipal.toString()) + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_SERVICE_PRINCIPAL.toString()) || authenticationString - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString())) + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTERACTIVE.toString())) && fedAuthRequiredPreLoginResponse) || null != activeConnectionProperties .get(SQLServerDriverObjectProperty.ACCESS_TOKEN_CALLBACK.toString())) { @@ -5540,6 +5535,40 @@ final boolean doExecute() throws SQLServerException { sendFedAuthToken(this, sqlFedAuthToken, tdsTokenHandler); return true; } + + /** + * Send the access token to the server. + */ + private void sendFedAuthToken(FedAuthTokenCommand fedAuthCommand, SqlAuthenticationToken fedAuthToken, + TDSTokenHandler tdsTokenHandler) throws SQLServerException { + assert null != fedAuthToken; + assert null != fedAuthToken.getAccessToken(); + + if (connectionlogger.isLoggable(Level.FINER)) { + connectionlogger.fine(super.toString() + " Sending federated authentication token."); + } + + TDSWriter tdsWriter = fedAuthCommand.startRequest(TDS.PKT_FEDAUTH_TOKEN_MESSAGE); + + byte[] accessToken = fedAuthToken.getAccessToken().getBytes(UTF_16LE); + + // Send total length (length of token plus 4 bytes for the token length field) + // If we were sending a nonce, this would include that length as well + tdsWriter.writeInt(accessToken.length + 4); + + // Send length of token + tdsWriter.writeInt(accessToken.length); + + // Send federated authentication access token. + tdsWriter.writeBytes(accessToken, 0, accessToken.length); + + TDSReader tdsReader; + tdsReader = fedAuthCommand.startResponse(); + + federatedAuthenticationRequested = true; + + TDSParser.parse(tdsReader, tdsTokenHandler); + } } /** @@ -5549,11 +5578,11 @@ final boolean doExecute() throws SQLServerException { void onFedAuthInfo(SqlFedAuthInfo fedAuthInfo, TDSTokenHandler tdsTokenHandler) throws SQLServerException { assert (null != activeConnectionProperties.getProperty(SQLServerDriverStringProperty.USER.toString()) && null != activeConnectionProperties.getProperty(SQLServerDriverStringProperty.PASSWORD.toString())) - || (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString()) + || (authenticationString.equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTEGRATED.toString()) || authenticationString - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryManagedIdentity.toString()) + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY.toString()) || authenticationString - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString()) + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTERACTIVE.toString()) && fedAuthRequiredPreLoginResponse); assert null != fedAuthInfo; @@ -5563,7 +5592,7 @@ void onFedAuthInfo(SqlFedAuthInfo fedAuthInfo, TDSTokenHandler tdsTokenHandler) SQLServerAccessTokenCallback callback = (SQLServerAccessTokenCallback) activeConnectionProperties .get(SQLServerDriverObjectProperty.ACCESS_TOKEN_CALLBACK.toString()); - if (authenticationString.equals(SqlAuthentication.NotSpecified.toString()) && null != callback) { + if (authenticationString.equals(SqlAuthentication.NOT_SPECIFIED.toString()) && null != callback) { fedAuthToken = callback.getAccessToken(fedAuthInfo.spn, fedAuthInfo.stsurl); } else { fedAuthToken = getFedAuthToken(fedAuthInfo); @@ -5579,8 +5608,6 @@ void onFedAuthInfo(SqlFedAuthInfo fedAuthInfo, TDSTokenHandler tdsTokenHandler) } private SqlAuthenticationToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throws SQLServerException { - SqlAuthenticationToken fedAuthToken = null; - // fedAuthInfo should not be null. assert null != fedAuthInfo; @@ -5590,13 +5617,13 @@ private SqlAuthenticationToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throw int sleepInterval = 100; if (!msalContextExists() - && !authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString())) { + && !authenticationString.equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTEGRATED.toString())) { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_MSALMissing")); throw new SQLServerException(form.format(new Object[] {authenticationString}), null, 0, null); } while (true) { - if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryPassword.toString())) { + if (authenticationString.equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_PASSWORD.toString())) { fedAuthToken = SQLServerMSAL4JUtils.getSqlFedAuthToken(fedAuthInfo, user, activeConnectionProperties.getProperty(SQLServerDriverStringProperty.PASSWORD.toString()), authenticationString); @@ -5604,7 +5631,7 @@ private SqlAuthenticationToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throw // Break out of the retry loop in successful case. break; } else if (authenticationString - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryManagedIdentity.toString())) { + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY.toString())) { String managedIdentityClientId = activeConnectionProperties .getProperty(SQLServerDriverStringProperty.USER.toString()); @@ -5621,7 +5648,7 @@ private SqlAuthenticationToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throw // Break out of the retry loop in successful case. break; } else if (authenticationString - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryServicePrincipal.toString())) { + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_SERVICE_PRINCIPAL.toString())) { // aadPrincipalID and aadPrincipalSecret is deprecated replaced by username and password if (aadPrincipalID != null && !aadPrincipalID.isEmpty() && aadPrincipalSecret != null @@ -5637,7 +5664,8 @@ private SqlAuthenticationToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throw // Break out of the retry loop in successful case. break; - } else if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString())) { + } else if (authenticationString + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTEGRATED.toString())) { // If operating system is windows and mssql-jdbc_auth is loaded then choose the DLL authentication. if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("windows") && AuthenticationJNI.isDllLoaded()) { @@ -5660,11 +5688,11 @@ private SqlAuthenticationToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throw } catch (DLLException adalException) { // the mssql-jdbc_auth DLL return -1 for errorCategory, if unable to load the adalsql DLL - int errorCategory = adalException.GetCategory(); + int errorCategory = adalException.getCategory(); if (-1 == errorCategory) { MessageFormat form = new MessageFormat( SQLServerException.getErrString("R_UnableLoadADALSqlDll")); - Object[] msgArgs = {Integer.toHexString(adalException.GetState())}; + Object[] msgArgs = {Integer.toHexString(adalException.getState())}; throw new SQLServerException(form.format(msgArgs), null); } @@ -5672,7 +5700,7 @@ private SqlAuthenticationToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throw if (ActiveDirectoryAuthentication.GET_ACCESS_TOKEN_TANSISENT_ERROR != errorCategory || timerHasExpired(timerExpire) || (sleepInterval >= millisecondsRemaining)) { - String errorStatus = Integer.toHexString(adalException.GetStatus()); + String errorStatus = Integer.toHexString(adalException.getStatus()); if (connectionlogger.isLoggable(Level.FINER)) { connectionlogger.fine( @@ -5682,8 +5710,8 @@ private SqlAuthenticationToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throw MessageFormat form = new MessageFormat( SQLServerException.getErrString("R_ADALAuthenticationMiddleErrorMessage")); - String errorCode = Integer.toHexString(adalException.GetStatus()).toUpperCase(); - Object[] msgArgs1 = {errorCode, adalException.GetState()}; + String errorCode = Integer.toHexString(adalException.getStatus()).toUpperCase(); + Object[] msgArgs1 = {errorCode, adalException.getState()}; SQLServerException middleException = new SQLServerException(form.format(msgArgs1), adalException); @@ -5722,14 +5750,15 @@ private SqlAuthenticationToken getFedAuthToken(SqlFedAuthInfo fedAuthInfo) throw } // Break out of the retry loop in successful case. break; - } else if (authenticationString.equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString())) { + } else if (authenticationString + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTERACTIVE.toString())) { // interactive flow fedAuthToken = SQLServerMSAL4JUtils.getSqlFedAuthTokenInteractive(fedAuthInfo, user, authenticationString); // Break out of the retry loop in successful case. break; - } else if (authenticationString.equalsIgnoreCase(SqlAuthentication.DefaultAzureCredential.toString())) { + } else if (authenticationString.equalsIgnoreCase(SqlAuthentication.DEFAULT_AZURE_CREDENTIAL.toString())) { String managedIdentityClientId = activeConnectionProperties .getProperty(SQLServerDriverStringProperty.USER.toString()); @@ -5758,40 +5787,6 @@ private boolean msalContextExists() { return true; } - /** - * Send the access token to the server. - */ - private void sendFedAuthToken(FedAuthTokenCommand fedAuthCommand, SqlAuthenticationToken fedAuthToken, - TDSTokenHandler tdsTokenHandler) throws SQLServerException { - assert null != fedAuthToken; - assert null != fedAuthToken.getAccessToken(); - - if (connectionlogger.isLoggable(Level.FINER)) { - connectionlogger.fine(toString() + " Sending federated authentication token."); - } - - TDSWriter tdsWriter = fedAuthCommand.startRequest(TDS.PKT_FEDAUTH_TOKEN_MESSAGE); - - byte[] accessToken = fedAuthToken.getAccessToken().getBytes(UTF_16LE); - - // Send total length (length of token plus 4 bytes for the token length field) - // If we were sending a nonce, this would include that length as well - tdsWriter.writeInt(accessToken.length + 4); - - // Send length of token - tdsWriter.writeInt(accessToken.length); - - // Send federated authentication access token. - tdsWriter.writeBytes(accessToken, 0, accessToken.length); - - TDSReader tdsReader; - tdsReader = fedAuthCommand.startResponse(); - - federatedAuthenticationRequested = true; - - TDSParser.parse(tdsReader, tdsTokenHandler); - } - final void processFeatureExtAck(TDSReader tdsReader) throws SQLServerException { tdsReader.readUnsignedByte(); // Reading FEATUREEXTACK_TOKEN 0xAE @@ -5881,6 +5876,8 @@ private void onFeatureExtAck(byte featureId, byte[] data) throws SQLServerExcept serverColumnEncryptionVersion = ColumnEncryptionVersion.AE_V1; + String enclaveType = null; + if (null != enclaveAttestationUrl || (enclaveAttestationProtocol != null && enclaveAttestationProtocol.equalsIgnoreCase(AttestationProtocol.NONE.toString()))) { if (aeVersion < TDS.COLUMNENCRYPTION_VERSION2) { @@ -6219,7 +6216,7 @@ final boolean complete(LogonCommand logonCommand, TDSReader tdsReader) throws SQ // TDS version 8 if strict mode // Denali --> TDS 7.4, Katmai (10.0) & later 7.3B, Prelogin disconnects anything older - if (encryptOption.compareToIgnoreCase(EncryptOption.Strict.toString()) == 0) { + if (encryptOption.compareToIgnoreCase(EncryptOption.STRICT.toString()) == 0) { tdsVersion = TDS.VER_TDS80; } else if (serverMajorVersion >= 11) { tdsVersion = TDS.VER_DENALI; diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index a0227bf14..faf11e934 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -61,41 +61,53 @@ DriverPropertyInfo build(Properties connProperties) { enum SqlAuthentication { - NotSpecified, - SqlPassword, - ActiveDirectoryPassword, - ActiveDirectoryIntegrated, - ActiveDirectoryManagedIdentity, - ActiveDirectoryServicePrincipal, - ActiveDirectoryInteractive, - DefaultAzureCredential; + NOT_SPECIFIED("NotSpecified"), + SQLPASSWORD("SqlPassword"), + ACTIVE_DIRECTORY_PASSWORD("ActiveDirectoryPassword"), + ACTIVE_DIRECTORY_INTEGRATED("ActiveDirectoryIntegrated"), + ACTIVE_DIRECTORY_MANAGED_IDENTITY("ActiveDirectoryManagedIdentity"), + ACTIVE_DIRECTORY_SERVICE_PRINCIPAL("ActiveDirectoryServicePrincipal"), + ACTIVE_DIRECTORY_INTERACTIVE("ActiveDirectoryInteractive"), + DEFAULT_AZURE_CREDENTIAL("DefaultAzureCredential"); + + private final String name; + + private SqlAuthentication(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } static SqlAuthentication valueOfString(String value) throws SQLServerException { SqlAuthentication method = null; - if (value.toLowerCase(Locale.US).equalsIgnoreCase(SqlAuthentication.NotSpecified.toString())) { - method = SqlAuthentication.NotSpecified; - } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(SqlAuthentication.SqlPassword.toString())) { - method = SqlAuthentication.SqlPassword; + if (value.toLowerCase(Locale.US).equalsIgnoreCase(SqlAuthentication.NOT_SPECIFIED.toString())) { + method = SqlAuthentication.NOT_SPECIFIED; + } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(SqlAuthentication.SQLPASSWORD.toString())) { + method = SqlAuthentication.SQLPASSWORD; } else if (value.toLowerCase(Locale.US) - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryPassword.toString())) { - method = SqlAuthentication.ActiveDirectoryPassword; + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_PASSWORD.toString())) { + method = SqlAuthentication.ACTIVE_DIRECTORY_PASSWORD; } else if (value.toLowerCase(Locale.US) - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryIntegrated.toString())) { - method = SqlAuthentication.ActiveDirectoryIntegrated; + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTEGRATED.toString())) { + method = SqlAuthentication.ACTIVE_DIRECTORY_INTEGRATED; } else if (value.toLowerCase(Locale.US) - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryManagedIdentity.toString()) + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY.toString()) || SQLServerDriver.getNormalizedPropertyValueName(value).toLowerCase(Locale.US) - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryManagedIdentity.toString())) { - method = SqlAuthentication.ActiveDirectoryManagedIdentity; + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY.toString())) { + method = SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY; } else if (value.toLowerCase(Locale.US) - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryServicePrincipal.toString())) { - method = SqlAuthentication.ActiveDirectoryServicePrincipal; + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_SERVICE_PRINCIPAL.toString())) { + method = SqlAuthentication.ACTIVE_DIRECTORY_SERVICE_PRINCIPAL; } else if (value.toLowerCase(Locale.US) - .equalsIgnoreCase(SqlAuthentication.ActiveDirectoryInteractive.toString())) { - method = SqlAuthentication.ActiveDirectoryInteractive; - } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(SqlAuthentication.DefaultAzureCredential.toString())) { - method = SqlAuthentication.DefaultAzureCredential; + .equalsIgnoreCase(SqlAuthentication.ACTIVE_DIRECTORY_INTERACTIVE.toString())) { + method = SqlAuthentication.ACTIVE_DIRECTORY_INTERACTIVE; + } else if (value.toLowerCase(Locale.US) + .equalsIgnoreCase(SqlAuthentication.DEFAULT_AZURE_CREDENTIAL.toString())) { + method = SqlAuthentication.DEFAULT_AZURE_CREDENTIAL; } else { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidConnectionSetting")); Object[] msgArgs = {"authentication", value}; @@ -107,16 +119,27 @@ static SqlAuthentication valueOfString(String value) throws SQLServerException { enum ColumnEncryptionSetting { - Enabled, - Disabled; + ENABLED("Enabled"), + DISABLED("Disabled"); + + private final String name; + + private ColumnEncryptionSetting(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } static ColumnEncryptionSetting valueOfString(String value) throws SQLServerException { ColumnEncryptionSetting method = null; - if (value.toLowerCase(Locale.US).equalsIgnoreCase(ColumnEncryptionSetting.Enabled.toString())) { - method = ColumnEncryptionSetting.Enabled; - } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(ColumnEncryptionSetting.Disabled.toString())) { - method = ColumnEncryptionSetting.Disabled; + if (value.toLowerCase(Locale.US).equalsIgnoreCase(ColumnEncryptionSetting.ENABLED.toString())) { + method = ColumnEncryptionSetting.ENABLED; + } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(ColumnEncryptionSetting.DISABLED.toString())) { + method = ColumnEncryptionSetting.DISABLED; } else { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidConnectionSetting")); Object[] msgArgs = {"columnEncryptionSetting", value}; @@ -128,25 +151,36 @@ static ColumnEncryptionSetting valueOfString(String value) throws SQLServerExcep enum EncryptOption { - False, - No, - Optional, - True, - Mandatory, - Strict; + FALSE("False"), + NO("No"), + OPTIONAL("Optional"), + TRUE("True"), + MANDATORY("Mandatory"), + STRICT("Strict"); + + private final String name; + + private EncryptOption(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } static EncryptOption valueOfString(String value) throws SQLServerException { EncryptOption option = null; String val = value.toLowerCase(Locale.US); - if (val.equalsIgnoreCase(EncryptOption.False.toString()) || val.equalsIgnoreCase(EncryptOption.No.toString()) - || val.equalsIgnoreCase(EncryptOption.Optional.toString())) { - option = EncryptOption.False; - } else if (val.equalsIgnoreCase(EncryptOption.True.toString()) - || val.equalsIgnoreCase(EncryptOption.Mandatory.toString())) { - option = EncryptOption.True; - } else if (val.equalsIgnoreCase(EncryptOption.Strict.toString())) { - option = EncryptOption.Strict; + if (val.equalsIgnoreCase(EncryptOption.FALSE.toString()) || val.equalsIgnoreCase(EncryptOption.NO.toString()) + || val.equalsIgnoreCase(EncryptOption.OPTIONAL.toString())) { + option = EncryptOption.FALSE; + } else if (val.equalsIgnoreCase(EncryptOption.TRUE.toString()) + || val.equalsIgnoreCase(EncryptOption.MANDATORY.toString())) { + option = EncryptOption.TRUE; + } else if (val.equalsIgnoreCase(EncryptOption.STRICT.toString())) { + option = EncryptOption.STRICT; } else { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidConnectionSetting")); Object[] msgArgs = {"EncryptOption", value}; @@ -265,9 +299,9 @@ static SSLProtocol valueOfString(String value) throws SQLServerException { enum IPAddressPreference { - IPv4First("IPv4First"), - IPv6First("IPv6First"), - UsePlatformDefault("UsePlatformDefault"); + IPV4_FIRST("IPv4First"), + IPV6_FIRST("IPv6First"), + USE_PLATFORM_DEFAULT("UsePlatformDefault"); private final String name; @@ -283,12 +317,12 @@ public String toString() { static IPAddressPreference valueOfString(String value) throws SQLServerException { IPAddressPreference iptype = null; - if (value.toLowerCase(Locale.US).equalsIgnoreCase(IPAddressPreference.IPv4First.toString())) { - iptype = IPAddressPreference.IPv4First; - } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(IPAddressPreference.IPv6First.toString())) { - iptype = IPAddressPreference.IPv6First; - } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(IPAddressPreference.UsePlatformDefault.toString())) { - iptype = IPAddressPreference.UsePlatformDefault; + if (value.toLowerCase(Locale.US).equalsIgnoreCase(IPAddressPreference.IPV4_FIRST.toString())) { + iptype = IPAddressPreference.IPV4_FIRST; + } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(IPAddressPreference.IPV6_FIRST.toString())) { + iptype = IPAddressPreference.IPV6_FIRST; + } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(IPAddressPreference.USE_PLATFORM_DEFAULT.toString())) { + iptype = IPAddressPreference.USE_PLATFORM_DEFAULT; } else { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidIPAddressPreference")); @@ -301,21 +335,32 @@ static IPAddressPreference valueOfString(String value) throws SQLServerException enum KeyStoreAuthentication { - JavaKeyStorePassword, - KeyVaultClientSecret, - KeyVaultManagedIdentity; + JAVA_KEYSTORE_PASSWORD("JavaKeyStorePassword"), + KEYVAULT_CLIENT_SECRET("KeyVaultClientSecret"), + KEYVAULT_MANAGED_IDENTITY("KeyVaultManagedIdentity"); + + private final String name; + + private KeyStoreAuthentication(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } static KeyStoreAuthentication valueOfString(String value) throws SQLServerException { KeyStoreAuthentication method = null; - if (value.toLowerCase(Locale.US).equalsIgnoreCase(KeyStoreAuthentication.JavaKeyStorePassword.toString())) { - method = KeyStoreAuthentication.JavaKeyStorePassword; + if (value.toLowerCase(Locale.US).equalsIgnoreCase(KeyStoreAuthentication.JAVA_KEYSTORE_PASSWORD.toString())) { + method = KeyStoreAuthentication.JAVA_KEYSTORE_PASSWORD; } else if (value.toLowerCase(Locale.US) - .equalsIgnoreCase(KeyStoreAuthentication.KeyVaultClientSecret.toString())) { - method = KeyStoreAuthentication.KeyVaultClientSecret; + .equalsIgnoreCase(KeyStoreAuthentication.KEYVAULT_CLIENT_SECRET.toString())) { + method = KeyStoreAuthentication.KEYVAULT_CLIENT_SECRET; } else if (value.toLowerCase(Locale.US) - .equalsIgnoreCase(KeyStoreAuthentication.KeyVaultManagedIdentity.toString())) { - method = KeyStoreAuthentication.KeyVaultManagedIdentity; + .equalsIgnoreCase(KeyStoreAuthentication.KEYVAULT_MANAGED_IDENTITY.toString())) { + method = KeyStoreAuthentication.KEYVAULT_MANAGED_IDENTITY; } else { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_InvalidConnectionSetting")); @@ -328,19 +373,30 @@ static KeyStoreAuthentication valueOfString(String value) throws SQLServerExcept enum AuthenticationScheme { - nativeAuthentication, - ntlm, - javaKerberos; + NATIVE_AUTHENTICATION("nativeAuthentication"), + NTLM("ntlm"), + JAVA_KERBEROS("javaKerberos"); + + private final String name; + + private AuthenticationScheme(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } static AuthenticationScheme valueOfString(String value) throws SQLServerException { AuthenticationScheme scheme; - if (value.toLowerCase(Locale.US).equalsIgnoreCase(AuthenticationScheme.javaKerberos.toString())) { - scheme = AuthenticationScheme.javaKerberos; + if (value.toLowerCase(Locale.US).equalsIgnoreCase(AuthenticationScheme.JAVA_KERBEROS.toString())) { + scheme = AuthenticationScheme.JAVA_KERBEROS; } else if (value.toLowerCase(Locale.US) - .equalsIgnoreCase(AuthenticationScheme.nativeAuthentication.toString())) { - scheme = AuthenticationScheme.nativeAuthentication; - } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(AuthenticationScheme.ntlm.toString())) { - scheme = AuthenticationScheme.ntlm; + .equalsIgnoreCase(AuthenticationScheme.NATIVE_AUTHENTICATION.toString())) { + scheme = AuthenticationScheme.NATIVE_AUTHENTICATION; + } else if (value.toLowerCase(Locale.US).equalsIgnoreCase(AuthenticationScheme.NTLM.toString())) { + scheme = AuthenticationScheme.NTLM; } else { MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_invalidAuthenticationScheme")); Object[] msgArgs = {value}; @@ -466,7 +522,7 @@ enum SQLServerDriverStringProperty { SELECT_METHOD("selectMethod", "direct"), DOMAIN("domain", ""), SERVER_NAME("serverName", ""), - IPADDRESS_PREFERENCE("iPAddressPreference", IPAddressPreference.IPv4First.toString()), + IPADDRESS_PREFERENCE("iPAddressPreference", IPAddressPreference.IPV4_FIRST.toString()), SERVER_SPN("serverSpn", ""), REALM("realm", ""), SOCKET_FACTORY_CLASS("socketFactoryClass", ""), @@ -478,10 +534,10 @@ enum SQLServerDriverStringProperty { TRUST_MANAGER_CONSTRUCTOR_ARG("trustManagerConstructorArg", ""), USER("user", ""), WORKSTATION_ID("workstationID", Util.WSIDNotAvailable), - AUTHENTICATION_SCHEME("authenticationScheme", AuthenticationScheme.nativeAuthentication.toString()), - AUTHENTICATION("authentication", SqlAuthentication.NotSpecified.toString()), + AUTHENTICATION_SCHEME("authenticationScheme", AuthenticationScheme.NATIVE_AUTHENTICATION.toString()), + AUTHENTICATION("authentication", SqlAuthentication.NOT_SPECIFIED.toString()), ACCESS_TOKEN("accessToken", ""), - COLUMN_ENCRYPTION("columnEncryptionSetting", ColumnEncryptionSetting.Disabled.toString()), + COLUMN_ENCRYPTION("columnEncryptionSetting", ColumnEncryptionSetting.DISABLED.toString()), ENCLAVE_ATTESTATION_URL("enclaveAttestationUrl", ""), ENCLAVE_ATTESTATION_PROTOCOL("enclaveAttestationProtocol", ""), KEY_STORE_AUTHENTICATION("keyStoreAuthentication", ""), @@ -498,7 +554,7 @@ enum SQLServerDriverStringProperty { AAD_SECURE_PRINCIPAL_ID("AADSecurePrincipalId", ""), AAD_SECURE_PRINCIPAL_SECRET("AADSecurePrincipalSecret", ""), MAX_RESULT_BUFFER("maxResultBuffer", "-1"), - ENCRYPT("encrypt", EncryptOption.True.toString()), + ENCRYPT("encrypt", EncryptOption.TRUE.toString()), SERVER_CERTIFICATE("serverCertificate", ""); private final String name; @@ -625,8 +681,8 @@ public final class SQLServerDriver implements java.sql.Driver { SQLServerDriverStringProperty.APPLICATION_NAME.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.COLUMN_ENCRYPTION.toString(), SQLServerDriverStringProperty.COLUMN_ENCRYPTION.getDefaultValue(), false, - new String[] {ColumnEncryptionSetting.Disabled.toString(), - ColumnEncryptionSetting.Enabled.toString()}), + new String[] {ColumnEncryptionSetting.DISABLED.toString(), + ColumnEncryptionSetting.ENABLED.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_URL.toString(), SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_URL.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.ENCLAVE_ATTESTATION_PROTOCOL.toString(), @@ -638,9 +694,9 @@ public final class SQLServerDriver implements java.sql.Driver { new String[] {"true"}), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.ENCRYPT.toString(), SQLServerDriverStringProperty.ENCRYPT.getDefaultValue(), false, - new String[] {EncryptOption.False.toString(), EncryptOption.No.toString(), - EncryptOption.Optional.toString(), EncryptOption.True.toString(), - EncryptOption.Mandatory.toString(), EncryptOption.Strict.toString()}), + new String[] {EncryptOption.FALSE.toString(), EncryptOption.NO.toString(), + EncryptOption.OPTIONAL.toString(), EncryptOption.TRUE.toString(), + EncryptOption.MANDATORY.toString(), EncryptOption.STRICT.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.SERVER_CERTIFICATE.toString(), SQLServerDriverStringProperty.SERVER_CERTIFICATE.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.PREPARE_METHOD.toString(), @@ -657,7 +713,7 @@ public final class SQLServerDriver implements java.sql.Driver { TRUE_FALSE), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.toString(), SQLServerDriverStringProperty.KEY_STORE_AUTHENTICATION.getDefaultValue(), false, - new String[] {KeyStoreAuthentication.JavaKeyStorePassword.toString()}), + new String[] {KeyStoreAuthentication.JAVA_KEYSTORE_PASSWORD.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.KEY_STORE_SECRET.toString(), SQLServerDriverStringProperty.KEY_STORE_SECRET.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.KEY_STORE_LOCATION.toString(), @@ -699,8 +755,8 @@ public final class SQLServerDriver implements java.sql.Driver { SQLServerDriverStringProperty.SERVER_NAME.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.IPADDRESS_PREFERENCE.toString(), SQLServerDriverStringProperty.IPADDRESS_PREFERENCE.getDefaultValue(), false, - new String[] {IPAddressPreference.IPv4First.toString(), IPAddressPreference.IPv6First.toString(), - IPAddressPreference.UsePlatformDefault.toString()}), + new String[] {IPAddressPreference.IPV4_FIRST.toString(), IPAddressPreference.IPV6_FIRST.toString(), + IPAddressPreference.USE_PLATFORM_DEFAULT.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.SERVER_SPN.toString(), SQLServerDriverStringProperty.SERVER_SPN.getDefaultValue(), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.REALM.toString(), @@ -739,17 +795,17 @@ public final class SQLServerDriver implements java.sql.Driver { Boolean.toString(SQLServerDriverBooleanProperty.XOPEN_STATES.getDefaultValue()), false, TRUE_FALSE), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.AUTHENTICATION_SCHEME.toString(), SQLServerDriverStringProperty.AUTHENTICATION_SCHEME.getDefaultValue(), false, - new String[] {AuthenticationScheme.javaKerberos.toString(), - AuthenticationScheme.nativeAuthentication.toString(), - AuthenticationScheme.ntlm.toString()}), + new String[] {AuthenticationScheme.JAVA_KERBEROS.toString(), + AuthenticationScheme.NATIVE_AUTHENTICATION.toString(), + AuthenticationScheme.NTLM.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.AUTHENTICATION.toString(), SQLServerDriverStringProperty.AUTHENTICATION.getDefaultValue(), false, - new String[] {SqlAuthentication.NotSpecified.toString(), SqlAuthentication.SqlPassword.toString(), - SqlAuthentication.ActiveDirectoryPassword.toString(), - SqlAuthentication.ActiveDirectoryIntegrated.toString(), - SqlAuthentication.ActiveDirectoryManagedIdentity.toString(), - SqlAuthentication.ActiveDirectoryServicePrincipal.toString(), - SqlAuthentication.ActiveDirectoryInteractive.toString()}), + new String[] {SqlAuthentication.NOT_SPECIFIED.toString(), SqlAuthentication.SQLPASSWORD.toString(), + SqlAuthentication.ACTIVE_DIRECTORY_PASSWORD.toString(), + SqlAuthentication.ACTIVE_DIRECTORY_INTEGRATED.toString(), + SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY.toString(), + SqlAuthentication.ACTIVE_DIRECTORY_SERVICE_PRINCIPAL.toString(), + SqlAuthentication.ACTIVE_DIRECTORY_INTERACTIVE.toString()}), new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(), Integer.toString(SQLServerDriverIntProperty.SOCKET_TIMEOUT.getDefaultValue()), false, null), new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.FIPS.toString(), @@ -833,7 +889,7 @@ public final class SQLServerDriver implements java.sql.Driver { {"port", SQLServerDriverIntProperty.PORT_NUMBER.toString()}}; private static final String driverPropertyValuesSynonyms[][] = { - {"ActiveDirectoryMSI", SqlAuthentication.ActiveDirectoryManagedIdentity.toString()}}; + {"ActiveDirectoryMSI", SqlAuthentication.ACTIVE_DIRECTORY_MANAGED_IDENTITY.toString()}}; static private final AtomicInteger baseID = new AtomicInteger(0); // Unique id generator for each instance (used for // logging diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNoneEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNoneEnclaveProvider.java index f3f02299c..4bdabb93f 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNoneEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerNoneEnclaveProvider.java @@ -96,6 +96,13 @@ public EnclaveSession getEnclaveSession() { private ArrayList describeParameterEncryption(SQLServerConnection connection, SQLServerStatement statement, String userSql, String preparedTypeDefinitions, Parameter[] params, ArrayList parameterNames) throws SQLServerException { + + // sp_describe_parameter_encryption stored procedure with 2 params + final String SDPE1 = "EXEC sp_describe_parameter_encryption ?,?"; + + // sp_describe_parameter_encryption stored procedure with 3 params + final String SDPE2 = "EXEC sp_describe_parameter_encryption ?,?,?"; + ArrayList enclaveRequestedCEKs = new ArrayList<>(); try (PreparedStatement stmt = connection.prepareStatement(connection.enclaveEstablished() ? SDPE1 : SDPE2)) { // Check the cache for metadata for Always Encrypted versions 1 and 3, when there are parameters to check. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java index 9c4a4fd96..fabe23081 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResultSet.java @@ -323,6 +323,7 @@ final int getServerCursorId() { this.stmt = stmt; } + @Override boolean onRetStatus(TDSReader tdsReader) throws SQLServerException { // With server-cursored result sets, the column metadata is // followed by a return status and cursor-related OUT parameters @@ -333,6 +334,7 @@ boolean onRetStatus(TDSReader tdsReader) throws SQLServerException { return true; } + @Override boolean onRetValue(TDSReader tdsReader) throws SQLServerException { // The first OUT parameter after the sp_cursor[prep]exec OUT parameters // is the start of the application OUT parameters. Leave parsing diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java index bf8c0609a..acc8f7fe6 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerVSMEnclaveProvider.java @@ -148,6 +148,13 @@ private byte[] getAttestationCertificates() throws IOException { private ArrayList describeParameterEncryption(SQLServerConnection connection, SQLServerStatement statement, String userSql, String preparedTypeDefinitions, Parameter[] params, ArrayList parameterNames) throws SQLServerException { + + // sp_describe_parameter_encryption stored procedure with 2 params + final String SDPE1 = "EXEC sp_describe_parameter_encryption ?,?"; + + // sp_describe_parameter_encryption stored procedure with 3 params + final String SDPE2 = "EXEC sp_describe_parameter_encryption ?,?,?"; + ArrayList enclaveRequestedCEKs = new ArrayList<>(); try (PreparedStatement stmt = connection.prepareStatement(connection.enclaveEstablished() ? SDPE1 : SDPE2)) { // Check the cache for metadata for Always Encrypted versions 1 and 3, when there are parameters to check. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java index a63a57cff..924ef9483 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerXAConnection.java @@ -57,7 +57,7 @@ public final class SQLServerXAConnection extends SQLServerPooledConnection imple // Add password property for NTLM as physical connection had previously removed. This will be removed again String auth = controlConnectionProperties .getProperty(SQLServerDriverStringProperty.AUTHENTICATION_SCHEME.toString()); - if (null != auth && AuthenticationScheme.ntlm == AuthenticationScheme.valueOfString(auth)) { + if (null != auth && AuthenticationScheme.NTLM == AuthenticationScheme.valueOfString(auth)) { controlConnectionProperties.setProperty(SQLServerDriverStringProperty.PASSWORD.toString(), pwd); } diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java index 7856e1b37..d2ed9d088 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/EnclavePackageTest.java @@ -203,7 +203,7 @@ public static void setupTests() throws Exception { */ public static void setAEConnectionString(String url, String protocol) throws Exception { connectionStringEnclave = TestUtils.addOrOverrideProperty(connectionString, "columnEncryptionSetting", - ColumnEncryptionSetting.Enabled.toString()); + ColumnEncryptionSetting.ENABLED.toString()); connectionStringEnclave = TestUtils.addOrOverrideProperty(connectionStringEnclave, "enclaveAttestationUrl", (null != url) ? url : "http://blah"); @@ -257,7 +257,7 @@ public static void testInvalidProperties(String serverName, String url, String p // enclaveAttestationUrl and enclaveAttestationProtocol without "columnEncryptionSetting" testInvalidProperties(TestUtils.addOrOverrideProperty(connectionStringEnclave, "columnEncryptionSetting", - ColumnEncryptionSetting.Disabled.toString()), "R_enclavePropertiesError"); + ColumnEncryptionSetting.DISABLED.toString()), "R_enclavePropertiesError"); // enclaveAttestationUrl without enclaveAttestationProtocol testInvalidProperties(TestUtils.removeProperty(connectionStringEnclave, "enclaveAttestationProtocol"), diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java index ab90ddc72..e65c90538 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java @@ -168,26 +168,26 @@ public void testDataSource() throws SQLServerException { assertEquals(stringPropValue, ds.getTrustStorePassword(), TestResource.getResource("R_valuesAreDifferent")); // verify encrypt=true options - ds.setEncrypt(EncryptOption.Mandatory.toString()); + ds.setEncrypt(EncryptOption.MANDATORY.toString()); assertEquals("True", EncryptOption.valueOfString(ds.getEncrypt()).toString(), TestResource.getResource("R_valuesAreDifferent")); - ds.setEncrypt(EncryptOption.True.toString()); + ds.setEncrypt(EncryptOption.TRUE.toString()); assertEquals("True", EncryptOption.valueOfString(ds.getEncrypt()).toString(), TestResource.getResource("R_valuesAreDifferent")); // verify encrypt=false options - ds.setEncrypt(EncryptOption.Optional.toString()); + ds.setEncrypt(EncryptOption.OPTIONAL.toString()); assertEquals("False", EncryptOption.valueOfString(ds.getEncrypt()).toString(), TestResource.getResource("R_valuesAreDifferent")); - ds.setEncrypt(EncryptOption.False.toString()); + ds.setEncrypt(EncryptOption.FALSE.toString()); assertEquals("False", EncryptOption.valueOfString(ds.getEncrypt()).toString(), TestResource.getResource("R_valuesAreDifferent")); - ds.setEncrypt(EncryptOption.No.toString()); + ds.setEncrypt(EncryptOption.NO.toString()); assertEquals("False", EncryptOption.valueOfString(ds.getEncrypt()).toString(), TestResource.getResource("R_valuesAreDifferent")); // verify enrypt=strict options - ds.setEncrypt(EncryptOption.Strict.toString()); + ds.setEncrypt(EncryptOption.STRICT.toString()); assertEquals("Strict", EncryptOption.valueOfString(ds.getEncrypt()).toString(), TestResource.getResource("R_valuesAreDifferent"));