Skip to content

Commit

Permalink
When Kerberos credentials were wrong, authentication was looping for …
Browse files Browse the repository at this point in the history
…a long time.

This commit solves this by stopping directly authentication when login() fails.

It means that if keytab is wrong OR provided principal/password are wrong, the
driver immediatly return and does not retry in a endless loop.
  • Loading branch information
pierresouchay committed Feb 28, 2017
1 parent 12aba6b commit 26dd540
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 7 deletions.
20 changes: 17 additions & 3 deletions src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,19 +127,33 @@ private void intAuthInit() throws SQLServerException {
// Kerberos OID
Oid kerberos = new Oid("1.2.840.113554.1.2.2");
Subject currentSubject = null;
KerbCallback callback = new KerbCallback(con);
try {
AccessControlContext context = AccessController.getContext();
currentSubject = Subject.getSubject(context);
if (null == currentSubject) {
lc = new LoginContext(CONFIGNAME, new KerbCallback(con));
lc = new LoginContext(CONFIGNAME, callback);
lc.login();
// per documentation LoginContext will instantiate a new subject.
currentSubject = lc.getSubject();
}
}
catch (LoginException le) {
authLogger.fine("Failed to login due to " + le.getClass().getName() + ":" + le.getMessage());
con.terminate(SQLServerException.DRIVER_ERROR_NONE, SQLServerException.getErrString("R_integratedAuthenticationFailed"), le);
if (authLogger.isLoggable(Level.FINE)) {
authLogger.fine(toString() + "Failed to login using Kerberos due to " + le.getClass().getName() + ":" + le.getMessage());
}
try {
// Not very clean since it raises an Exception, but we are sure we are cleaning well everything
con.terminate(SQLServerException.DRIVER_ERROR_NONE, SQLServerException.getErrString("R_integratedAuthenticationFailed"), le);
} catch (SQLServerException alwaysTriggered) {
String message = String.format("%s due to %s (%s)", alwaysTriggered.getMessage(), le.getClass().getName(), le.getMessage());
if (callback.getUsernameRequested() != null) {
message = String.format("Login failed for Kerberos principal '%s'. %s", callback.getUsernameRequested(), message);
}
// By throwing Exception with LOGON_FAILED -> we avoid looping for connection
// In this case, authentication will never work anyway -> fail fast
throw new SQLServerException(message, alwaysTriggered.getSQLState(), SQLServerException.LOGON_FAILED, le);
}
return;
}

Expand Down
16 changes: 12 additions & 4 deletions src/main/java/com/microsoft/sqlserver/jdbc/KerbCallback.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
public class KerbCallback implements CallbackHandler {

private final SQLServerConnection con;
private String usernameRequested = null;

KerbCallback(SQLServerConnection con) {
this.con = con;
Expand All @@ -30,13 +31,22 @@ private static String getAnyOf(Callback callback, Properties properties, String.
"Cannot get any of properties: " + Arrays.toString(names) + " from con properties");
}

/**
* If a name was retrieved By Kerberos, return it.
* @return null if callback was not called or username was not provided
*/
public String getUsernameRequested(){
return usernameRequested;
}

@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
Callback callback = callbacks[i];
if (callback instanceof NameCallback) {
((NameCallback) callback).setName(getAnyOf(callback, con.activeConnectionProperties,
"user", SQLServerDriverStringProperty.USER.name()));
usernameRequested = getAnyOf(callback, con.activeConnectionProperties,
"user", SQLServerDriverStringProperty.USER.name());
((NameCallback) callback).setName(usernameRequested);
} else if (callback instanceof PasswordCallback) {
String password = getAnyOf(callback, con.activeConnectionProperties,
"password", SQLServerDriverStringProperty.PASSWORD.name());
Expand All @@ -47,7 +57,5 @@ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallback
throw new UnsupportedCallbackException(callback, "Unrecognized Callback type: " + callback.getClass());
}
}

}

}

0 comments on commit 26dd540

Please sign in to comment.