Skip to content

Commit

Permalink
Update getUserName in impersonated security context in Azure SQL data…
Browse files Browse the repository at this point in the history
…base (#2193)
  • Loading branch information
lilgreenbird authored Aug 15, 2023
1 parent 81b0ea8 commit 844ddca
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1709,12 +1709,30 @@ public String getUserName() throws SQLServerException, SQLTimeoutException {
}
checkClosed();
String result = "";
try (SQLServerStatement s = (SQLServerStatement) connection.createStatement();
SQLServerResultSet rs = s.executeQueryInternal("select system_user")) {
// Select system_user will always return a row.
boolean next = rs.next();
assert next;
result = rs.getString(1);
try (SQLServerStatement s = (SQLServerStatement) connection.createStatement()) {
try (SQLServerResultSet rs = s.executeQueryInternal("SELECT SYSTEM_USER")) {
// Select system_user will always return a row.
boolean next = rs.next();
assert next;
result = rs.getString(1);
} catch (SQLServerException e) {
// execution using impersonated security context is disallowed for Azure SQL Server so return CURRENT_USER instead
if (e.getErrorCode() == SQLServerException.IMPERSONATION_CONTEXT_NOT_SUPPORTED) {
if (loggerExternal.isLoggable(Level.FINEST)) {
loggerExternal.finest(toString()
+ " Impersonation context is not supported in this version of SQL Server. Re-try getting CURRENT_USER");
}

try (SQLServerResultSet rs = s.executeQueryInternal("SELECT CURRENT_USER")) {
boolean next = rs.next();
assert next;
result = rs.getString(1);
}
} else {
// re-throw
throw e;
}
}
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ public final class SQLServerException extends java.sql.SQLException {
static final int LOGON_FAILED = 18456;
static final int PASSWORD_EXPIRED = 18488;
static final int USER_ACCOUNT_LOCKED = 18486;
static final java.util.logging.Logger exLogger = java.util.logging.Logger
.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerException");

// Built-in function '%.*ls' in impersonation context is not supported in this version of SQL Server.
static final int IMPERSONATION_CONTEXT_NOT_SUPPORTED = 40529;

// Facility for driver-specific error codes
static final int DRIVER_ERROR_NONE = 0;
Expand All @@ -84,6 +85,9 @@ public final class SQLServerException extends java.sql.SQLException {
static final int DATA_CLASSIFICATION_INVALID_LABEL_INDEX = 12;
static final int DATA_CLASSIFICATION_INVALID_INFORMATION_TYPE_INDEX = 13;

static final java.util.logging.Logger exLogger = java.util.logging.Logger
.getLogger("com.microsoft.sqlserver.jdbc.internals.SQLServerException");

/** driver error code */
private int driverErrorCode = DRIVER_ERROR_NONE;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
Expand All @@ -43,6 +44,7 @@
import com.microsoft.sqlserver.jdbc.RandomUtil;
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
import com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData;
import com.microsoft.sqlserver.jdbc.SQLServerException;
import com.microsoft.sqlserver.jdbc.StringUtils;
import com.microsoft.sqlserver.jdbc.TestResource;
import com.microsoft.sqlserver.jdbc.TestUtils;
Expand Down Expand Up @@ -155,8 +157,6 @@ public void testGetURL() throws SQLException {
* @throws SQLException
*/
@Test
@Tag(Constants.xAzureSQLDW)
@Tag(Constants.xAzureSQLDB)
public void testDBUserLogin() throws SQLException {
try (Connection conn = getConnection()) {
DatabaseMetaData databaseMetaData = conn.getMetaData();
Expand Down Expand Up @@ -187,6 +187,45 @@ public void testDBUserLogin() throws SQLException {
}
}

@Test
@Tag(Constants.xAzureSQLDW)
public void testImpersonateGetUserName() throws SQLException {
String newUser = "newUser" + UUID.randomUUID();

try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) {
String escapedNewUser = AbstractSQLGenerator.escapeIdentifier(newUser);
String password = "password" + UUID.randomUUID();

stmt.execute("IF EXISTS (select * from sys.sysusers where name = '" + escapedNewUser + "') DROP USER"
+ escapedNewUser);

// create new user and login
try {
stmt.execute("CREATE USER " + escapedNewUser + " WITH password='" + password + "'");
} catch (SQLServerException e) {
// handle failed cases when database is master
if (e.getMessage().contains("contained database")) {
stmt.execute("CREATE LOGIN " + escapedNewUser + " WITH password='" + password + "'");
stmt.execute("CREATE USER " + escapedNewUser);
}
}

DatabaseMetaData databaseMetaData = conn.getMetaData();
try (CallableStatement asOtherUser = conn.prepareCall("EXECUTE AS USER = '" + newUser + "'")) {
asOtherUser.execute();
assertTrue(newUser.equalsIgnoreCase(databaseMetaData.getUserName()),
TestResource.getResource("R_userNameNotMatch"));
} catch (Exception e) {
fail(TestResource.getResource("R_unexpectedErrorMessage") + e.getMessage());
} finally {
stmt.execute("IF EXISTS (select * from sys.sysusers where name = '" + escapedNewUser + "') DROP USER"
+ escapedNewUser);
stmt.execute("IF EXISTS (select * from sys.sysusers where name = '" + escapedNewUser + "') DROP LOGIN"
+ escapedNewUser);
}
}
}

/**
* Testing of {@link SQLServerDatabaseMetaData#getSchemas()}
*
Expand Down

0 comments on commit 844ddca

Please sign in to comment.