In case of POP3 it is possible to connect via telnet using sockets over port 110, But how to do it , if SPOP3 is implemented.
With normal telnet it can be done quite easily with
Socket pop3Socket = new Socket(host.com, 110);
FYI:
For connecting to SPOP3 we use in linux/unix
openssl s_client -connect servername.com:995
You'll need to use the SSLSocket class. An example can be found at: http://www.herongyang.com/JDK/SSL-Socket-Client-Example-SslSocketClient.html.
Basically, you'll do something like:
SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket c = (SSLSocket) f.createSocket("localhost", 8888);
If the endpoint has a self signed certificate then you have two options:
Add this self-signed cert to your local keystore. This URL gives a good overview: http://www.chrissearle.org/blog/technical/adding_self_signed_https_certificates_java_keystore
Create a TrustManager that does not validate the server's certificate: http://www.howardism.org/Technical/Java/SelfSignedCerts.html
Option 1 is more secure.
Related
I made my implementation of the HTTP protocol following the specification of the W3C in Java. But I can't handle https connections.
There is nothing special about HTTPs when it comes to HTTP protocol. All you need is to open server SSL socket and once the new connection comes, get the socket's input stream and you can use it (maybe after wrapping to buffered input stream) in the same way as for HTTP.
int port = 443;
ServerSocketFactory ssocketFactory = SSLServerSocketFactory.getDefault();
ServerSocket ssocket = ssocketFactory.createServerSocket(port);
Socket socket = ssocket.accept();
EDIT: You might be missing server keystore. Pls try to follow this tutorial: http://stilius.net/java/java_ssl.php i.e.
generate server keystore:
keytool -genkey -keystore mySrvKeystore -keyalg RSA
run your server with proper arguments like:
java -Djavax.net.ssl.keyStore=mySrvKeystore -Djavax.net.ssl.keyStorePassword=123456 EchoServer
I have this code to connect the server with a client using SSL, and now I want to add client-side authentication:
(I have a server keystore (JCEKS type) and a client keystore (JKS type), the server uses a truststore (cacerts) where I imported both certificates because I also want to use this truststore for client authentication)
Client code:
System.setProperty("javax.net.ssl.trustStore", cerServer);
System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
System.setProperty("javax.net.ssl.trustStorePassword", pwdCacerts);
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", port);
Server Code:
KeyStore ks = LoadKeyStore(new File(serverKeyStore), pwdKeyStore, "JCEKS");
KeyManagerFactory kmf;
kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, pwdKeyStore.toCharArray());
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(kmf.getKeyManagers(),null, null);
SSLServerSocketFactory ssf = sc.getServerSocketFactory();
sslserversocket = (SSLServerSocket) ssf.createServerSocket(port);
thanks in advance for any help.
edit:
I add this code in the server side:
System.setProperty("javax.net.ssl.trustStore", cacerts);
System.setProperty("javax.net.ssl.trustStoreType","JKS");
System.setProperty("javax.net.ssl.trustStorePassword", pwdCacerts);
but if I delete the client certificate in cacerts, the connection doesn't give me error and for that I think it's wrong that way
If you want your system to use client-certificate authentication, you'll need
the server to request (or require) a client certificate. This is done by setting setWantClientAuth(true) on the server socket (or setNeedClientAuth, respectively). You'll also need the server to advertise the CA it accepts, which is normally done by using a truststore on the server that contains the CA by which the client-certificate chain was issued (this seems to be what you've done by setting javax.net.ssl.trustStore* on the server).
the client to be configured with a keystore containing the client certificate (possible the chain if there are intermediate CAs) and its private key. This can be done by setting the javax.net.ssl.keyStore* (which may affect other connections) or by using a KeyManagerFactory in the same way as you've done it on the server side.
If you use setWantClientAuth(true), you might still not get an error, since the server will accept connections that don't have a client-certificate (the server would then check the SSLSession's peer certificates to see whether there was a cert or not). setNeedClientAuth(true) would break the connection when the client doesn't present a certificate.
I am getting this error: javax.net.ssl.SSLHandshakeException: no cipher suites in common
when trying to do an SSL socket communication between java server and android client.
I used this line to create the keyfile: keytool -genkey -keystore mySrvKeystore -keyalg RSA
server code:
System.setProperty("javax.net.ssl.keyStore","mySrvKeystore.key");
System.setProperty("javax.net.ssl.keyStorePassword","1234567");
private SSLServerSocketFactory sslserversocketfactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
private SSLServerSocket sslserversocket;
private SSLSocket sslsocket;
sslserversocket= (SSLServerSocket) sslserversocketfactory.createServerSocket(port);
sslsocket = (SSLSocket) sslserversocket.accept();
client code:
System.setProperty("javax.net.ssl.trustStore","mySrvKeystore.key");
System.setProperty("javax.net.ssl.trustStorePassword","1234567");
sslsocket = (SSLSocket) sslsocketfactory.createSocket(serverAddr, SERVERPORT);
private SSLSocketFactory sslsocketfactory = (SSLSocketFactory)
SSLSocketFactory.getDefault();
private SSLSocket sslsocket;
Any idea how to solve this issue ?
Is it possible that the connection is failing because the server's certificate is self-signed ?
Thanks.
You must be changing the enabled cipher suites in either your SSLServerSocket or your SSLSocket. Don't do that. If you must, make sure you set a subset that is supported by both peers.
EDIT In your client code, you have
System.setProperty("javax.net.ssl.trustStore","mySrvKeystore.key");
i.e. you are using the server keystore as the client truststore. Don't do that. The keystore contains the private key and it shouldn't reside anywhere except at the server. You need to export the server certificate from that keystore and import it into the client truststore as a trusted CA certificate.
Android uses slightly different approach to setup up a secure connection. Please take a look at this post:
Android Trusting SSL Certificates
For secure server sockets in order to send the server certificate, all I do is initialize SSLContext with a KeyManagerFactory.getKeyManagers() that has been initialized with my keystore.
But how can I do this in client side?
I.e. for client I do:
System.setProperty("javax.net.ssl.keyStore", "clientKeystore.keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "secret");
System.setProperty("javax.net.ssl.trustStore", "clientKeystore.keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "secret");
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket("localhost", 7890);
I use the same keystore as trust store. I assume that just for looking arround JSSE it is ok.
Problem is that I get in the server part (I have setNeedClientAuth in the serversocket to true).
Exception in thread "main" javax.net.ssl.SSLHandshakeException: null cert chain
So how am I supposed to configure the client side to send a certificate?Isn't the system properties a correct approach?
Because I do not see how the SSLContext can be used in client side.
Thank you!
You do not have to set a specific configuration on the client side to use a certificate for authentication. Maybe some intermediate CAs are missing in the keystore, and the client is not able to build a certificate path from the trust anchor sent by the server and therefore cannot determine if the certificate is suitable for authentication.
You can add the system property javax.net.debug to all to print the debug stream on the standard output. Maybe you can get more information on the error.
I have to write a Java Client to connect to an SSL server. The server uses openssl certificate, and is configured to do Client Auth.
I can't seem to locate any useful resources online that can help me (who doesn't know anything about openssl and much about SSL) to understand who to go about implementing my Client Side.
Help!
The twist here is that you are using client authentication, so you need a private key and a certificate to identify yourself. You provide this to JSSE by specifying KeyManagers when you initialize an SSLContext.
Customizable Setup
Following are the basic steps. The JSSE API was significantly improved in Java 6, but I'll stick with Java 5, in case you're stuck on that version.
KeyStore tks = KeyStore.getInstance(KeyStore.getDefaultType());
tks.load(...); /* Load the trust key store with root CAs. */
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(tks);
KeyStore iks = KeyStore.getInstance(KeyStore.getDefaultType());
iks.load(...); /* Load the identity key store with your key/cert. */
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(iks, password);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SocketFactory factory = ctx.getSocketFactory();
Socket socket = factory.createSocket(host, port);
System Configuration
An alternative "zero-config" scenario can be used when using the SunJSSE provider. I believe many other providers (like IBM) have followed the same pattern and will work as well. The mechanism uses system properties, and is described in detail by the JSSE Reference Guide.
For client authentication, the important properties are javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword. The values should be the path to the user's key store and the password for that key store's "key entries", respectively.
When using these properties, you can create a new SSLSocket that supports client authentication like this:
SocketFactory factory = SSLSocketFactory.getDefault();
Socket socket = factory.createSocket(host, port);
Since you are using the "default" SSLSocketFactory, which depends on the system-wide properties, all sockets created in the JVM will authenticate with the same certificate. If you need more control than that, you have to use the "Customizable Setup" above.
Java includes SSL support in the standard API. Have a look at these classes in the 1.5.0 javadoc:
SSLSocket if you're doing the comms logic yourself.
HttpsURLConnection if the server side speaks HTTP
You could use httpclient. Have a look at this SSL guide.