New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow authenticating using Kerberos and a Principal/Password. #163

Merged
merged 3 commits into from Apr 12, 2017

Conversation

Projects
None yet
7 participants
@pierresouchay

pierresouchay commented Feb 28, 2017

This closes #66

This patch allow to authenticate using kerberos using the previous
methods (eg: keytab) or specifying user/password either in properties
or in connect method.

This allows to use GUIs for instance to connect using Kerberos without
having a sql user.

If fixes issue #66

@codecov-io

This comment has been minimized.

codecov-io commented Feb 28, 2017

Codecov Report

Merging #163 into dev will increase coverage by 0.08%.
The diff coverage is 0%.

Impacted file tree graph

@@             Coverage Diff              @@
##                dev     #163      +/-   ##
============================================
+ Coverage     33.35%   33.43%   +0.08%     
- Complexity     1486     1487       +1     
============================================
  Files            97       98       +1     
  Lines         23569    23422     -147     
  Branches       3909     3845      -64     
============================================
- Hits           7862     7832      -30     
+ Misses        14141    14030     -111     
+ Partials       1566     1560       -6
Flag Coverage Δ Complexity Δ
#JDBC41 33.36% <0%> (+0.07%) 1483 <0> (ø) ⬇️
#JDBC42 33.37% <0%> (+0.11%) 1486 <0> (+7) ⬆️
Impacted Files Coverage Δ Complexity Δ
...om/microsoft/sqlserver/jdbc/SQLServerResource.java 100% <ø> (ø) 4 <0> (ø) ⬇️
...ava/com/microsoft/sqlserver/jdbc/KerbCallback.java 0% <0%> (ø) 0 <0> (?)
...m/microsoft/sqlserver/jdbc/KerbAuthentication.java 0% <0%> (ø) 0 <0> (ø) ⬇️
.../com/microsoft/sqlserver/jdbc/SQLServerJdbc41.java 33.33% <0%> (-26.67%) 0% <0%> (ø)
.../com/microsoft/sqlserver/jdbc/SQLServerJdbc42.java 25% <0%> (-25%) 0% <0%> (ø)
.../microsoft/sqlserver/jdbc/SQLServerDataSource.java 44.28% <0%> (-0.47%) 61% <0%> (ø)
...oft/sqlserver/jdbc/SQLServerParameterMetaData.java 19.78% <0%> (-0.36%) 27% <0%> (ø)
...m/microsoft/sqlserver/jdbc/SQLServerStatement.java 57.95% <0%> (-0.3%) 128% <0%> (ø)
...va/com/microsoft/sqlserver/jdbc/SQLServerBlob.java 26.34% <0%> (-0.26%) 13% <0%> (ø)
.../microsoft/sqlserver/jdbc/SQLServerConnection.java 41.1% <0%> (-0.24%) 227% <0%> (ø)
... and 14 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f3d22ac...115c7e9. Read the comment docs.

@pierresouchay

This comment has been minimized.

pierresouchay commented Feb 28, 2017

A few notes:
connecting with a user does not requires the full realm as long as default_realm is properly set in /etc/krb5.conf file (for instance, if default_realm = AD.EXAMPLE.COM then, if the username has no "@" within, it will be assumed that its name is user@AD.EXAMPLE.COM

Using a fully qualified username (for instance user@AD.EXAMPLE.COM) works as well.

In the case where a keytab is used, the callback won't even be called.

The global Kerberos mechanism may be enchanced as the Driver always retry even when the password is not valid (thus the return added).

For Another Review: A possible improvement would be to stop trying when login() does fails (we don't need to wait for timeout in that case) with a proper error message.

This commit should solve issue #66

@pierresouchay

This comment has been minimized.

pierresouchay commented Feb 28, 2017

The second commit also fixes issues with authentication taking a very long time even when Kerberos authentication is completely broken (eg: wrong keytab or wrong password)

@Suraiya-Hameed

This comment has been minimized.

Contributor

Suraiya-Hameed commented Mar 30, 2017

@pierresouchay Can you open this PR in dev branch?

@pierresouchay pierresouchay changed the base branch from master to dev Mar 31, 2017

@pierresouchay

This comment has been minimized.

pierresouchay commented Mar 31, 2017

@v-suhame done

@Suraiya-Hameed Suraiya-Hameed added this to the 6.1.7 milestone Apr 3, 2017

pierresouchay added some commits Feb 28, 2017

Allow authenticating using Kerberos and a Principal/Password.
This patch allow to authenticate using kerberos using the previous
methods (eg: keytab) or specifying user/password either in properties
or in connect method.

This allows to use GUIs for instance to connect using Kerberos without
having a sql user.
When Kerberos credentials were wrong, authentication was looping for …
…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.
@pierresouchay

This comment has been minimized.

pierresouchay commented Apr 3, 2017

Updated the review to fix conflict due to #178

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);
}

This comment has been minimized.

@Suraiya-Hameed

Suraiya-Hameed Apr 6, 2017

Contributor

To be consistent with the existing code, can you add this new exception error string in SQLServerResource.java?

}
private static String getAnyOf(Callback callback, Properties properties, String... names)
throws UnsupportedCallbackException {

This comment has been minimized.

@Suraiya-Hameed

Suraiya-Hameed Apr 6, 2017

Contributor

use the formatter on new code.

Reformat code in KerbCallback with formatter
Added translated message for Kerberos login authentication errors.
@pierresouchay

This comment has been minimized.

pierresouchay commented Apr 7, 2017

@v-suhame DONE in new patch

@Suraiya-Hameed

This comment has been minimized.

Contributor

Suraiya-Hameed commented Apr 11, 2017

@pierresouchay Can you also push changes for IBM jre?

@pierresouchay

This comment has been minimized.

pierresouchay commented Apr 12, 2017

@v-suhame As far as I know, there is no option on IBM JVM to disable callback according to https://www.ibm.com/support/knowledgecenter/en/SSYKE2_7.1.0/com.ibm.java.security.api.doc/jgss/com/ibm/security/auth/module/Krb5LoginModule.html

So I suspect it works on IBM JVM without changes

@Suraiya-Hameed

This comment has been minimized.

Contributor

Suraiya-Hameed commented Apr 12, 2017

Tested PR with IBM JVM, Kerberos auth with username and password doesn't work. It looks like driver should switch between useDefaultCcache to true while using ticket and false for principal/password.

@pierresouchay

This comment has been minimized.

pierresouchay commented Apr 12, 2017

It means probably refactoring the creation of configurations according to connection parameters (and not in a static way)

For another PR?

@Suraiya-Hameed

This comment has been minimized.

Contributor

Suraiya-Hameed commented Apr 12, 2017

Sounds good! I'll accept/merge this PR and leave the issue #66 open until it's fixed for IBM JVM.
Thanks @pierresouchay, and sorry it took so long to review and merge.

@Suraiya-Hameed Suraiya-Hameed merged commit 23676aa into Microsoft:dev Apr 12, 2017

2 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@pierresouchay

This comment has been minimized.

pierresouchay commented Apr 12, 2017

That's great !

IBM owners can still create their $HOME/.java.login.config file and specify the parameters of the config to make it work.

I did actually plan to use several names for instead of hardcoded default "SQLJDBCDriver" (and so remove the static initialization) -> that would be the right time to allow switching to a default configuration that enables login with username/password for IBM JVM

@pierresouchay pierresouchay deleted the pierresouchay:kerberos-with-user_password branch Apr 18, 2017

@bayramgns

This comment has been minimized.

bayramgns commented Oct 11, 2017

Hello,

Is there a road map to develop driver for also IBM JVM to be able to use connection username and password properties for the kerberos authentication?

We can provide kerberos authentication by using keytab and login config files; it' s OK. But it would be much better to authenticate by using connection username and password properties instead of keytab and login config files as it' s used for Oracle JVM.

@pierresouchay

This comment has been minimized.

pierresouchay commented Oct 11, 2017

I did not test it, but it should work, did you try it?

@pierresouchay

This comment has been minimized.

pierresouchay commented Oct 12, 2017

@bayramgns you might try by creating a .java.login.config in your $HOME directory and putting useDefaultCcache=false it seems. Which version of IBM's JVM are you using?

@bayramgns

This comment has been minimized.

bayramgns commented Oct 12, 2017

@pierresouchay it works well for Oracle JVM. When you use Oracle JVM, you don' t need to use any keytab and login conf file; you only need to set up kerberos conf file and set driver connection properties. But for IBM JVM, it does not seem like that.

I use IBMSDK 7.1 and mssql-jdbc-6.2.1.jre7.jar versions.

As this change, I thought I won' t need to set any login conf property file; because you don' t need it for Oracle JVM.However, although I set login conf file as it seems below, it still does not work;

SQLJDBCDriver {
com.ibm.security.auth.module.Krb5LoginModule required
useDefaultCcache=false;
};

But when I set the login conf file like the below, it works well;

SQLJDBCDriver {
com.ibm.security.auth.module.Krb5LoginModule required
useDefaultCcache=false
useKeytab="D:/GUNES/krb5.keytab"
credsType=both
principal="XXX@YYY";
};

@bayramgns

This comment has been minimized.

bayramgns commented Oct 19, 2017

@pierresouchay could you check the case?

@pierresouchay

This comment has been minimized.

pierresouchay commented Oct 19, 2017

@bayramgns What do you mean exactly?

What are you testing?

  1. You are logged using Kerberos (for instance, a Windows session) and would like to access to a MS SQL Db?
  2. You are not logged using Kerberos and want to use keytab "D:/GUNES/krb5.keytab" ?
  3. You are not logged and want to connect using Kerberos and a login/password ?

Assuming you are in the third case, and according to this page:

https://www.ibm.com/support/knowledgecenter/en/SSYKE2_7.1.0/com.ibm.java.security.component.71.doc/security-component/jgssDocs/jaas_login_user.html

Krb5LoginModule might prompt for a principal name, password or both. Or it might not prompt for any input whatsoever. Whether or not the login is interactive depends on the options specified in the JAAS configuration file. For example, the login proceeds non-interactively when the credential type is initiator and a Kerberos TGT is to be retrieved from a default credentials cache file. On the other hand,a user is prompt for useCcache where user can specify a different credentials cache file if useDefaultCcache is set to false. If no value is entered, , a user is prompted for a password (and, perhaps, a principal name) when a TGT is to be obtained from a Kerberos KDC. When the login is interactive, the application must specify com.ibm.security.auth.callback.Krb5CallbackHandler as the callback handler when creating the login context. The callback handler is responsible for prompting for input.

I would try the following:

SQLJDBCDriver {
com.ibm.security.auth.module.Krb5LoginModule required
useDefaultCcache=false
credsType=both
};

I don't have a Windows machine nor IBM JVM to test now, can you test this configuration and tell me whether it works?

Current default configurations are the following:
https://github.com/Microsoft/mssql-jdbc/blob/dev/src/main/java/com/microsoft/sqlserver/jdbc/JaasConfiguration.java#L26

@bayramgns

This comment has been minimized.

bayramgns commented Nov 2, 2017

@pierresouchay I have good news :) It worked by using IBM Java Version 8. I used to work with IBM Java 7 version before and it was getting KerberosException.

My purpose is connect to an MS SQL DB by authenticating with Kerberos protocol.I don' t want to use keytab file for username and password. I just want to set username and password connection properties instead of using keytab file.

When using IBM Java 7, you have to create a keytab file and also provide "useKeytab" and "principal" properties in "SQLJDBCDriver .conf" file; otherwise it does not work.

But when using IBM Java 8, it works by setting connection username/password properties(no need to create keytab file) and using a "SQLJDBCDriver .conf" file as you mentioned above (no need to provide useKeytab and principal properties).

Anyway, I have no problem any more :) Thanks for help :)

@pierresouchay

This comment has been minimized.

pierresouchay commented Nov 2, 2017

@bayramgns Ok, that's good news, can you try without the config file as well (I mean simply delete the file)?

If it does not work, we might try setting those properties in the conf, so people you not even have to create the jaas config file.

@bayramgns

This comment has been minimized.

bayramgns commented Nov 2, 2017

@pierresouchay , it does not work without the jaas config file. I' ve removed the auth login config jvm parameter and tried; but got "com.ibm.security.krb5.KrbException, status code: 31" exception.

I guess the default value of "useDefaultCcache (true)" in JaasConfiguration class causes the error.

Sounds great if you develop for setting these properties in the conf and no need to have jaas config file any more :)

@kmohanarangam

This comment has been minimized.

kmohanarangam commented Mar 1, 2018

@pierresouchay @bayramgns 'But when using IBM Java 8, it works by setting connection username/password properties" - I tried the same. However, the driver picks up the logged in user instead of the userName and password provided in the connection string. Is your "run as" user and the username on the connection string one and the same?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment