Reputation: 12970
Using this example, almost get my conection working
http://blogs.nologin.es/rickyepoderi/index.php?/archives/105-Oracle-Driver-and-Kerberos.html
but after enable kerberos cache and debug it's getting my principal name correctly and credentials succesful there's an error related with ticket.
ticket is generated with okinit (oracle kinit from oracle 12)
Exception in thread "main" java.sql.SQLRecoverableException: Error de E/S: The service in process is not supported. Failure unspecified at GSS-API level (Mechanism level: Generic error (description in e-text) (60) - ASN.1 unexpected field number) at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:743) at oracle.jdbc.driver.PhysicalConnection.connect(PhysicalConnection.java:666) at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32) at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:566) at java.sql.DriverManager.getConnection(DriverManager.java:571) at java.sql.DriverManager.getConnection(DriverManager.java:187) at JdbcThin.main(JdbcThin.java:39) Caused by: oracle.net.ns.NetException: The service in process is not supported. Failure unspecified at GSS-API level (Mechanism level: Generic error (description in e-text) (60) - ASN.1 unexpected field number) at oracle.net.ano.AuthenticationService.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:415) at oracle.net.ano.AuthenticationService.e(Unknown Source) at oracle.net.ano.Ano.negotiation(Unknown Source) at oracle.net.ns.NSProtocol.connect(NSProtocol.java:293) at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:1452) at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:496) ... 6 more Caused by: GSSException: Failure unspecified at GSS-API level (Mechanism level: Generic error (description in e-text) (60) - ASN.1 unexpected field number) at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:710) at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:248) at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:179) ... 14 more Caused by: KrbException: Generic error (description in e-text) (60) - ASN.1 unexpected field number at sun.security.krb5.KrbApRep.(KrbApRep.java:126) at sun.security.krb5.KrbApRep.(KrbApRep.java:102) at sun.security.krb5.KrbApRep.(KrbApRep.java:75) at sun.security.jgss.krb5.AcceptSecContextToken.(AcceptSecContextToken.java:89) at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:696) ... 16 more Caused by: KrbException: Identifier doesn't match expected value (906) at sun.security.krb5.internal.APRep.init(APRep.java:92) at sun.security.krb5.internal.APRep.(APRep.java:75) at sun.security.krb5.KrbApRep.(KrbApRep.java:116) ... 20 more
I'm using a java 7 but there's no problem in use another one. Is there a way to read ticket correctly with a jvm (see kinit from jdk do not create a correct ticket too)
Upvotes: 2
Views: 24214
Reputation: 5298
This is solution for Win10/Win2019 where Credential Guard is in place (the trick with AllowTgtSessionKey=1 does not work anymore).
Kerberos ticket has to be generated using SSPI API. Works since JDK 11.0.10.
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleConnectionBuilder;
import oracle.jdbc.pool.OracleDataSource;
import oracle.net.ano.AnoServices;
public class Test3 {
String username = System.getProperty("user.name");
String domain = System.getenv("USERDNSDOMAIN");
String url = "jdbc:oracle:thin:@//dbatdb1:1521/TEST_1";
public Test3() {
}
public void doit() throws Exception
{
// set env. variable to enable tracing in sspi_bridge.dll
// set SSPI_BRIDGE_TRACE=1
//System.setProperty("oracle.jdbc.Trace", "true");
//System.setProperty("sun.security.krb5.debug", "true");
//System.setProperty("sun.security.spnego.debug", "true");
//System.setProperty("sun.security.jgss.debug", "true");
//System.setProperty("java.security.debug", "true");
//System.setProperty("sun.security.nativegss.debug", "true");
//System.setProperty("java.security.krb5.conf", "D:/oracle/WINDOWS.X64_193000_client_home/network/admin/krb5.conf");
System.setProperty("sun.security.jgss.native", "true");
System.setProperty("sun.security.jgss.lib", "sspi_bridge.dll");
Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");
GSSManager manager = GSSManager.getInstance();
GSSName srcName = manager.createName(username + "@" + domain, GSSName.NT_USER_NAME);
GSSCredential cred = manager.createCredential(srcName
, GSSCredential.DEFAULT_LIFETIME
, krb5Oid, GSSCredential.INITIATE_ONLY);
Properties prop = new Properties();
prop.setProperty(AnoServices.AUTHENTICATION_PROPERTY_SERVICES, "(" + AnoServices.AUTHENTICATION_KERBEROS5 + ")");
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICES,"( " + AnoServices.AUTHENTICATION_KERBEROS5 + " )");
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_KRB5_MUTUAL, "true");
OracleDataSource ods = new OracleDataSource();
ods.setURL(url);
ods.setConnectionProperties(prop);
OracleConnectionBuilder builder = ods.createConnectionBuilder();
OracleConnection conn = builder.gssCredential(cred).build();
String auth = ((OracleConnection)conn).getAuthenticationAdaptorName();
System.out.println("Authentication adaptor="+auth);
String sql = "select user from dual";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next())
System.out.println("whoami: " + rs.getString(1));
conn.close();
}
public static void main(String[] args) {
Test3 test = new Test3();
try {
test.doit();
System.out.println("Done");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Upvotes: 0
Reputation: 3773
I'm sharing this piece of code which has been working for me. Have you set the location of the kerberos cache file?
OracleDriver driver = new OracleDriver();
Properties prop = new Properties();
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICES,
"("+AnoServices.AUTHENTICATION_KERBEROS5+")");
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_KRB5_MUTUAL,
"true");
/* If you get the following error [Unable to obtain Principal Name for
* authentication] although you know that you have the right TGT in your
* credential cache, then it's probably because the JVM can't locate your
* cache.
* For example, here my credential cache is
* C:\Documents and Settings\Jean de Lavarene\krb5cc
* because when I run klist I get the following:
* > ./klist
* Ticket cache: FILE:C:\Documents and Settings\Jean de Lavarene\krb5cc
* Default principal: [email protected]
*
* Valid starting Expires Service principal
* 06/21/16 13:23:02 06/21/16 23:23:02 krbtgt/[email protected]
* renew until 06/21/16 13:23:02
* This isn't the default location, so I need to provide the location. Note
* that the default location on windows is "C:\Documents and Settings\krb5cc_username".
*/
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_KRB5_CC_NAME,
"C:\\Documents and Settings\\Jean de Lavarene\\krb5cc");
Connection conn = driver.connect(url,prop);
String auth = ((OracleConnection)conn).getAuthenticationAdaptorName();
System.out.println("Authentication adaptor="+auth);
Upvotes: 1