Java JDBC unable to connect to a Oracle database with SSL - java

I have configured a Oracle 11g database server to work with SSL using a wallet and self signed certificate.
Tested it with local client (sqlplus) and it works without any issues.
Now I'm trying to connect the database using Java JDBC.
Currently I'm getting an error:
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to
find valid certification path to requested target
Here is my code:
public static void main(String[] args)
{
Connection connection = null;
String url = "jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=192.168.200.191)(PORT=1522))(CONNECT_DATA=(SERVICE_NAME=VDB)))";
Properties props = new Properties();
props.setProperty("user", "dbuser");
props.setProperty("password", "dbpass");
props.setProperty("oracle.net.ssl_cipher_suites","(SSL_RSA_WITH_3DES_EDE_CBC_SHA)");
/* Load the database driver */
try
{
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
connection = DriverManager.getConnection(url,props);
if (connection != null) {
System.out.println("You made it, take control your database now!");
} else {
System.out.println("Failed to make connection!");
}
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
I did some more research, and found that if the wallet is configured as 'auto_login', I can try the following:
Connection connection = null;
String url = "jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=192.168.200.191)(PORT=1522))(CONNECT_DATA=(SERVICE_NAME=VDB)))";
Properties props = new Properties();
props.setProperty("user", "dbuser");
props.setProperty("password", "dbpass");
props.setProperty("javax.net.ssl.trustStore", "C:\\oracle\\wallet\\cwallet.sso");
props.setProperty("javax.net.ssl.trustStoreType","SSO");
/* Load the database driver */
try
{
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
connection = DriverManager.getConnection(url,props);
if (connection != null) {
System.out.println("You made it, take control your database now!");
} else {
System.out.println("Failed to make connection!");
}
}
catch (SQLException ex) {
ex.printStackTrace();
}
In this case, I'm getting:
java.security.NoSuchAlgorithmException: SSO KeyStore not available
I've added 3 Jars: oraclepki.jar, osdt_cert.jar, osdt_core.jar
Attempted to run the last version of the code, getting exception:
java.lang.ClassNotFoundException: com.phaos.crypto.AuthenticationException
Perhaps I should specify the wallet location? as I did in the tnsnames.ora file? or specify the certificate CN?
Please advise, thanks.

Using services or resources that requires certificates within your application, require that you somehow trust the certificate issuer or certificate itself. In this case, I guess you will have to trust the certificate itself as it is self-signed and not issued by a well-known CA (already trusted by the trust-store bundled with the JRE you're using).
In order to do this, export the certificate that you use together with your database and locate a file called "cacerts". The file exists within your jdk-installation folder. Example:
/path/to/jdk/jre/lib/security/cacerts
The easiest thing to do, is just to import the certificate to this file (you can use some commands to do this, or if you're lazy like me - download KSE and click the Import-button: http://keystore-explorer.org/). You may also specify your own trust-store using properties mentioned here:
https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html
If you choose to use a custom trust-store, you have more control regarding the cacerts - as if you're choosing to update to a newer jdk installation, that installation will use the cacerts issued with the jdk :-).
Anyway. Hope it helped a bit.

The JVM tries to establish a chain of trust of the server's certificate towards any known trusted CAs. You can either obtain a certificate from a CA which is trusted by your Java's default TrustStore or you can provide your own CA certificate (the one you used to sign the self-signed certificate) to your JVM by generating your own TrustStore. You would then pass the TrustStore e.g. using the command line argument -Djavax.net.ssl.trustStore= when starting your application.
Keep in mind that passing a custom TrustStore requires you to either add all CAs which are contained in your JRE's default TrustStore or you live with the fact that no chains of trust can be established to any certificates not issued by your own CA.
A third option is adding your own CA certificate to your system's global TrustStore which leads to any Java application accepting certificates from your CA. This is a shortcut but might not be in your best interest if you require a strict separation of CAs.

I think below link may be helpful to you.
http://docs.oracle.com/cd/B19306_01/java.102/b14355/sslthin.htm#BABHFBJD

Found the solution, as I'm using SSO need to specify both keystore and truststore.
Connection connection = null;
String url = "jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=192.168.200.191)(PORT=1522))(CONNECT_DATA=(SERVICE_NAME=NNVSDB)))";
Properties props = new Properties();
props.setProperty("user", "dbuser");
props.setProperty("password", "dbpass");
//Single sign on
props.setProperty("javax.net.ssl.trustStore", "C:\\oracle\\wallet\\cwallet.sso");
props.setProperty("javax.net.ssl.trustStoreType","SSO");
props.setProperty("javax.net.ssl.keyStore","C:\\oracle\\wallet\\cwallet.sso");
props.setProperty("javax.net.ssl.keyStoreType","SSO");
props.setProperty("oracle.net.authentication_services","(TCPS)");
/* Load the database driver */
try
{
Security.addProvider(new oracle.security.pki.OraclePKIProvider());
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
connection = DriverManager.getConnection(url,props);
if (connection != null) {
System.out.println("You made it, take control your database now!");
} else {
System.out.println("Failed to make connection!");
}
}
catch (SQLException ex) {
ex.printStackTrace();
}

Related

Getting error while JDBC connection with mySql(mysql 5.7.22) through eclipse in ubuntu 18.04 [duplicate]

This question already has answers here:
java.sql.SQLException: Access denied for user 'root'#'localhost' (using password: YES)
(31 answers)
Closed 4 years ago.
please help to solve this error. the same code is working fine in windows. but i'm not understanding why its not running in Linux(Ubuntu 18.04) .
The Following code:
import java.sql.*;
public class HelloWorld {
public static void main(String[] args) {
Connection con = null;
Statement st = null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","root");
String sql = "insert into mytable values('amsing#gmail.com','amit1234')";
st = con.createStatement();
int x = st.executeUpdate(sql);
if(x==1) {
System.out.println("Record inserted");
}else {
System.out.println("Record not inserted");
}
}catch(Exception e) {
e.printStackTrace();
}finally {
try {
if(st!=null)st.close();
if(con!=null)con.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
Throws this exception while running the code:
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
Sat Jul 07 12:52:40 IST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
java.sql.SQLException: Access denied for user 'root'#'localhost'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:127)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:862)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:444)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:230)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:226)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
at com.amitsingh.HelloWorld.main(HelloWorld.java:10)
Perhaps the user root has no sufficient rights to connect from localhost.
You can check this to connect to the database form the command line / shell
Use the following command to connect:
mysql --host=localhost --user=root --password=root mydb
If the connection is not succesfull then the user credentionals should be updated.
For testing purposes you could give all rights to the user. This can be done after connected to mysql.
GRANT ALL PRIVILEGES ON mydb.* TO 'root'#'%' WITH GRANT OPTION;

IBM MQ fail with reason '2278' ('MQRC_CLIENT_CONN_ERROR')

I have been trying with no luck to get a java app to connect to IBM MQ v8 via CCDT file. I can connect fine when connecting using properties (hostname, port, etc) but with CCDT I consistently get WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2278' ('MQRC_CLIENT_CONN_ERROR').
I am using a vanilla install of MQ Developer 8.0 (version required, can't change) and the Jars from the installation. All I did was install MQ, then setup a QueueManager 'QM1', then create a queue 'Q1'.
My code:
package mqtest;
import com.ibm.mq.jms.*;
import java.io.File;
import java.net.URL;
public class Main {
public static void main(String[] args) {
try {
MQQueueConnectionFactory cf = new MQQueueConnectionFactory();
File file = new File("C:/ProgramData/IBM/MQ/qmgrs/QM1/#ipcc/AMQCLCHL.TAB");
URL clientChannelTableUrl = file.toURI().toURL();
cf.setQueueManager("QM1");
cf.setCCDTURL(clientChannelTableUrl);
MQQueueConnection mqQueueConnection = (MQQueueConnection) cf.createConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
}
dis qmgr
AMQ8408: Display Queue Manager details.
QMNAME(QM1) ACCTCONO(DISABLED)
ACCTINT(1800) ACCTMQI(OFF)
ACCTQ(OFF) ACTIVREC(MSG)
ACTVCONO(DISABLED) ACTVTRC(OFF)
ALTDATE(2018-05-23) ALTTIME(10.21.26)
AUTHOREV(DISABLED) CCSID(437)
CERTLABL(ibmwebspheremqqm1) CERTVPOL(ANY)
CHAD(DISABLED) CHADEV(DISABLED)
CHADEXIT( ) CHLEV(DISABLED)
CHLAUTH(ENABLED) CLWLDATA( )
CLWLEXIT( ) CLWLLEN(100)
CLWLMRUC(999999999) CLWLUSEQ(LOCAL)
CMDEV(DISABLED) CMDLEVEL(800)
COMMANDQ(SYSTEM.ADMIN.COMMAND.QUEUE) CONFIGEV(DISABLED)
CONNAUTH(SYSTEM.DEFAULT.AUTHINFO.IDPWOS)
CRDATE(2018-05-23) CRTIME(10.21.26)
CUSTOM( ) DEADQ( )
DEFCLXQ(SCTQ) DEFXMITQ( )
DESCR( ) DISTL(YES)
INHIBTEV(DISABLED) IPADDRV(IPV4)
LOCALEV(DISABLED) LOGGEREV(DISABLED)
MARKINT(5000) MAXHANDS(256)
MAXMSGL(4194304) MAXPROPL(NOLIMIT)
MAXPRTY(9) MAXUMSGS(10000)
MONACLS(QMGR) MONCHL(OFF)
MONQ(OFF) PARENT( )
PERFMEV(DISABLED) PLATFORM(WINDOWSNT)
PSMODE(ENABLED) PSCLUS(ENABLED)
PSNPMSG(DISCARD) PSNPRES(NORMAL)
PSRTYCNT(5) PSSYNCPT(IFPER)
QMID(QM1_2018-05-23_10.21.26) REMOTEEV(DISABLED)
REPOS( ) REPOSNL( )
REVDNS(ENABLED) ROUTEREC(MSG)
SCHINIT(QMGR) SCMDSERV(QMGR)
SPLCAP(ENABLED) SSLCRLNL( )
SSLCRYP( ) SSLEV(DISABLED)
SSLFIPS(NO)
SSLKEYR(C:\ProgramData\IBM\MQ\qmgrs\QM1\ssl\key)
SSLRKEYC(0) STATACLS(QMGR)
STATCHL(OFF) STATINT(1800)
The error log in C:\ProgramData\IBM\MQ\qmgrs\QM1\errors has no relevant (that I can see at least) data in it.
As far as I can tell from various SO, IBM, Google searches this should work. As far as I can tell it has something to do with Channel definition or settings, but I just don't know what.
And, honestly, I think I have spent enough brain cells on this that I am most likely overlooking something important but can't see the small simple detail I am overlooking. Any help as appreciated.
MQ Version: 9.0.0.4
Step 1: only one jar required: com.ibm.mq.allclient-9.0.4.0.jar
Step 2:
Do not set any variable in MQEnvironment
Step 3:
java.net.URL chanTab1 = new URL("file:///C:/MGR.TAB");
MQQueueManager _queueManager = new MQQueueManager("*", chanTab1);
int openOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING;
MQQueue queue = _queueManager.accessQueue( "QNAME", openOptions,null,null, null );
MQMessage sendmsg = new MQMessage();
* will allow you to connect all the QManager available in the .TAB file.
Step 4:
Install certificate in your jre C:\Program Files\Java\jdk1.7\jre\bin by command
keytool -import -alias example -keystore ..\lib\security\cacerts -file C:\test.cer
default password is changeit. Mostly nobody change this. :-)
or
if you deployed your code on websphere application server then no need to install certificate in server JRE. Insted install certificate on Websphere server
SSL certificate and key management > Key stores and certificates > NodeDefaultKeyStore > Signer certificates > Retrieve from port

JSch hostKey not recognised with Titan SFTP server

I have an issue with my hostkey verification via JSch. I am using jsch 0.1.53, for my application, and the server I am connecting to is SouthRiverTech's Titan SFTP server.
I have tried generating a keypair with Puttygen, the Titan inbuilt key generator, and also with JSch's inbuilt libraries. The settings I used was RSA, 2048 bits.
The keys created by JSch's inbuilt libraries didn't seem to work. The keys generated by Titan and Puttygen were able to be used with winSCP, but kept giving me a "Reject Hostkey" error with JSch, which should be an issue with the known_hosts file. From what I have found, the known_hosts file should be the same as a public key file, but do tell me if I am wrong. I have set Titan's SFTP version to version 3.
I have the same keys set for the user profile in Titan to find out where the error lies, but to no avail. So far I have yet to find any answers online regarding hostkey issue between JSch and Titan server. This has been giving me a huge headache.
Thank you in advance for any answers you might have. I will try my best to post any information I might have missed out.
EDIT
Further debugging came up with JSchException: UnknownHostKey, followed by the RSA key fingerprint which is used by the server. My client key fingerprint and the server key fingerprint are the same, so why is this happening?
EDIT
Here is my Java code:
knownHostsFile = "D:/Keys/test.pub";
privateKey = "D:/Keys/test";
Session session = null;
Channel channel = null;
for(int i = 0; i < 3; i++) {
try {
logger.debug("Starting Upload");
JSch ssh=new JSch();
logger.debug("setting hosts - public key");
ssh.setKnownHosts(knownHostsFile);
logger.debug("Known hosts set as "+knownHostsFile);
logger.debug("Setting identity - private key");
ssh.addIdentity(privateKey);
logger.debug("identity set");
try {
int hostSFTPPort = Integer.parseInt(sftpPort);
if (!hostUserName.equalsIgnoreCase("no")
&& !hostPassword.equalsIgnoreCase("no")
&& !hostAddress.equalsIgnoreCase("no")) {
session=ssh.getSession(hostUserName,hostAddress,hostSFTPPort);
session.setPassword(hostPassword);
}
} catch (NumberFormatException ef){
logger.debug(ef);
}
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "yes");
config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
session.setConfig(config);
logger.debug("Establishing connection...");
session.connect(120000);
logger.debug("Connection established.");
logger.debug("Creating SFTP Channel.");
channel=session.openChannel("sftp");
logger.debug("Channel assigned. Connecting channel...");
channel.connect(120000);
logger.debug("SFTP Channel created.");
ChannelSftp sftp = (ChannelSftp) channel;
logger.debug("connection:"+sftp.isConnected());
if(sftp.isConnected()) {
result=Constants.CONNECTION_ONLINE;
}
session.disconnect();
channel.disconnect();
break;
} catch (JSchException e) {
logger.debug(e);
logger.debug(session.getHost());
logger.debug(session.getHostKey());
logger.debug("Continuing next loop......");
throw new JSchException("Session.connect failed",e);
} catch (Exception ex) {
logger.debug(ex);
logger.debug("Continuing next loop......");
continue;
}
}
Here is a picture of the Server admin console
Here are the keys I'm having trouble with:
This one does not seem to work with winSCP, and was created in a Linux environment
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA4R+w9rGUsBNJGZxAdnbnA7FMfGGhx3YaLYZtKf9wzKm8NkZeYIuh1fJ6ViX6RmdO55QxQ3PmBIg8QdhQ8m6SizEt9OGeXU2AnEbX/sbj54oHmiFsv24eDFzr7nrDKnrcllByob3LqjeOy5zg27kJt860oh6BAJfimdqVtETSXR1JHfqUIqGxIqsvyKEotX8gjoGkgsW653f18dW5PJKSEvrq6k1SL0bfgSAA0rN4nUq3JzDvowg5ijkOl91/lj8+FEQ7SjWmguTSx5BoI/CTxatCwNZSdzNED/u5A8I3716JuY7MEiTciPdzspGAXS2mHOtsDPkT7z6jvKQ6hWWv/w== test1#10.70.149.178
This one works with winSCP, and was created in a Windows environment
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "test"
AAAAB3NzaC1yc2EAAAABJQAAAQEA9a1nnbl/DV2Zo7s1IUifeC5suRmdO2ikSb0ToteO9uvA
gg0zYKA1iH52ysC+4Ni86Ceal4oWGl1dXZRKOaWNH6175uDTI1aBfPBvOddBheTeSQAWOkaM
eL5PDDabLkaKZ1GrtbTeEFOD/Kj/dVREhT5/OcEdFmCbHK6+vr2klrtH2xOd/Qeb89BzDFaj
weNER3fFnHVqy5/Nugo3n7CsiBxuK8KOVN4WpDHzrVe/tjAfVZyH8l4XHlR7bWA5rlAGwt0Y
HILQ+lT1PRmi5PiDq7WuP7NF3QhWjG/D1u/5PC/DzxjTOxwwmXfYj2T2OkE/2/tHSdU4geYr
+1ivdASJ5w==
---- END SSH2 PUBLIC KEY ----
You are confusing an account key pair with a host key (pair).
The JSchException "reject HostKey: ..." indicates that the server's public key (aka host key) differs from the public key known by your code or cached in the known_hosts file.
The server's host key is typically not generated by PuTTYgen (though it might be possible) and definitely has nothing to do with WinSCP. In PuTTYgen you typically generate an account key pair (which you can then use e.g. in WinSCP).
For details, see my article Understanding SSH key pairs.
The account key pair and host key pair have nothing to do with each other. Whatever you use for the account key, it won't make JSch accept the server's host key. Just forget this idea. It's completely wrong.
You have to provide the correct host key in the known_hosts file (or other implementation of the JSch HostKeyRepository interface). You cannot use a .pub file for the known_hosts file. The known_hosts file has a set format like:
IP_address ssh-rsa public_key
You can also use KnownHosts.add to set the expected hostkey on runtime.

Smack XMPP: Can't login to openfire server: "SASLErrorException: SASLError using DIGEST-MD5: not-authorized"

I am trying to create a basic connection and login to an Openfire server that I have installed. I have the following user in my users database which I created through the Openfire web admin interface:
User: user
Password: 12345678
I can connect fine to the server as the connection returns true in my sout. The problem is when it tries to log in I get the following error:
org.jivesoftware.smack.sasl.SASLErrorException: SASLError using DIGEST-MD5: not-authorized
I have the following code:
private XMPPConnection connection;
public void connect(String serverIP) {
try {
System.setProperty("smack.debugEnabled", "true");
ConnectionConfiguration config = new ConnectionConfiguration(serverIP, 5223);
config.setDebuggerEnabled(true);
config.setSocketFactory(new DummySSLSocketFactory());
config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);
config.setCompressionEnabled(true);
connection = new XMPPTCPConnection(config);
connection.connect();
System.out.println("Connected: " + connection.isConnected());
connection.login("user", "12345678");
System.out.println("Logged in: " + connection.isAuthenticated());
} catch (SmackException | IOException | XMPPException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
connectionHandler test = new connectionHandler();
test.connect("localhost");
}
If anyone can correct what I am doing wrong I would be really grateful.
I have also tried the username as the email would be for example
user#localhost.com
or
user#localhost
I finally managed to find the answer to this. The problem (possibly not even a problem) was that the authentication methods weren't set in the server config and as default allowed all methods. The first one chosen in java seems to be DIGEST-MD5 which was what was causing the errors. To fix this I added:
<sasl>
<mechs> PLAIN </mechs>
</sasl>
before the last closing tag of the openfire.xml found in the config folder of the server. This can also be changed in the ofproperty database table for the column called sasl.mechs.
Hopefully this helps someone (possibly me) in the future.
P.S. this is unsecure if not using SSL (port 5223 by default)
SASLError using DIGEST-MD5: not-authorized
This is most likely caused because you did not configure the correct XMPP domain (/service name) in your ConnectionConfiguration. DIGEST-MD5 would not only fail if the username or password is wrong, but also if the wrong XMPP domain is used.

Difficulty connecting to database using SQLserver jdbc

I'm trying to connect to my database using sqljdbc4, I'm pretty new to this so i followed a couple of tutorial but it still doesn't seem to work, When i try to run the program i get this Exception:
com.microsoft.sqlserver.jdbc.SQLServerException: Login failed for user ''. ClientConnectionId:f181fd37-7e28-4392-ac86-02914c2090e1
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
And this is my code:
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection con = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=DBank;","","");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
You are not passing any authentication credentials. If you want to use integrated security (windows authentication), then you need to explicitly specify that in your connection URL and you need to load the native library required for this.
See Connecting with Integrated Authentication On Windows on Windows on MSDN.
This essentially comes down to including the folder containing the (32 bit or 64 bit) sqljdbc_auth.dll in the java.library.path system property (see link for details) and adding integratedSecurity=true to your connection string:
DriverManager.getConnection(
"jdbc:sqlserver://localhost:1433;databaseName=DBank;integratedSecurity=true");
You are passing empty username and password while connecting to the database in getConnection method:
DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=DBank;","","");
Try supplying the db username and password, for example:
DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=DBank;","myusername","mypassword");

Categories