Tomcat 7 ssl client authenitcation - java

I want to make a webapp accessible to some limited users only. So I select a SSL client authentication. I am newbie so not much knowledge about it I follow this tutorial to achive it. here is some quires in my mind. I am using basic self signed SSL.
1) Can we create a single client certificate for all clients which is provide by me? so whoever has a client certificate can access a app. sounds not a good way.
2) if not (1) then is there easy way to create a client certificate and register on tomcat user.xml. I dont want to force user to create a client certificate and send me so I register on server.
3) How to redirect to some other page if SSL certificate not match.?
4) can we use a private public key of one machine to another one?
5) there is multiple apps on my server but I want to authenticate only one app with SSL. Is is possible then how?
please also suggest me any good tutorials for this. Finally My requriment is to give access to limited users up to 50. and my clients can register his system in some user friendly way.

1) Can we create a single client certificate for all clients which is provide by me?
It doesn't make sense. The client certificate is supposed to uniquely identify the client. They should have one each.
so whoever has a client certificate can access a app. sounds not a good way.
It isn't.
2) if not (1) then is there easy way to create a client certificate and register on tomcat user.xml. I dont want to force user to create a client certificate and send me so I register on server.
It's the only secure way. If you create the certificate you have the private key so it isn't private so it can't do what it's supposed to do, legally. For example you can't prove that only the client could have executed any transaction, so you lose legal non-repudiability. You shoudn't be using users.xml for this, you should be using one of the other Tomcat security Realms, for example a database.
3) How to redirect to some other page if SSL certificate not match.?
If you're using Container Managed Authentication, which you should be, that's all defined in web.xml for the application.
4) can we use a private public key of one machine to another one?
It doesn't make sense, see above. A private key is supposed to be private and under the exclusive control of one entity.
I question whether using client certificates is even the right solution here. If you just want to restrict access to the server give each client a login.
5) there is multiple apps on my server but I want to authenticate only one app with SS

Related

Passing user authentication details from one server to the next

I've got users authenticating with client certificates in a JBoss server. All fine.
If I then use Apache HTTPClient to call onto another server it sends the client certificate of the user JBoss is configured with. I'd like to be able to pass the client certificate through so the second server authenticates the calling user too.
Is this possible (I'm assuming not as the server won't have the private key of the client certificate) and if so, how?
I'm pretty convinced from RFC5246 [1] that it's not possible.
If the client has sent
a certificate with signing ability, a digitally-signed
CertificateVerify message is sent to explicitly verify possession of
the private key in the certificate.
After all, what's the point of a private key if you make it public? I'll just get the server I'm connecting to to give my system user increased privileges.
1 https://www.rfc-editor.org/rfc/rfc5246
Not possible. The certificate is merely a public identifier of who the user is. The actual authentication is done using the client's private key. As a result, you would need to obtain both the certificate AND private key to accomplish this, which would eliminate all of the security around the use of certificates in the first place. Certificates are considered public, and can be distributed wherever needed to allow for identity verification, digital signature validation, encryption, etc. The private key must, by definition, remain private in order to ensure the security of the credential.
To accomplish your goal of propagating identity information, there are other tools you can use. If your JBoss server(s) are all part of the same security domain, you can use JavaEE Security to propagate the identity information. With some creative coding, you may also be able to use Kerberos to propagate the identity, although that is a non-trivial amount of effort.

Make sure http post comes from my applet and no one else?

I have an applet that communicates with php through http post requests and then my php script inserts data in a mysql database. So the problem is that i guess anyone can make a http post requests and add data to my mysql database if they now the "post" names and of course i dont want that.
So i would like to have som solution where my php can be sure that the http requests are really from my applet and no one else. I would be grateful for ideas on how to solve this. The data being sent contains no secrets so it dont need to be encrypted if it can be solved with no encryption that is.
Thanks in advance.
If you can't use encryption while communicating , so the answer is simply you can't make sure.
In fact, even with encryption, it is impossible to determine whether a request was made by your applet or by something else that is perfectly mimicing its behavior. You will need to build your application such that it can deal with this.
Encryption will help secure any methodology you will put into place in order to achieve what you want, but it will do nothing on its own.
What you want is to authenticate the post message. This is usually achieved by having your client (here, applet) sign (HMAC) the POST message using a key that only the applet AND the server knows. The challenge here is that you need to securely store the key on the client side.
If I were you I would check into authenticating the users and hosting the applet in a secured area of your site, making sure your applet is re-using the HTTP session of the authenticated user when performing POST requests. Add to this basic safeguards against standard attacks (ie Cross Site Request Forgery, Replay attack, etc). This setup would make sure your requests come from your site by authorized users.
You could have the applet register by generating an RSA key pair on the client and sending the public key to the server. The server then keeps track of the public key of each registered client.
On each POST the client signs some piece of data using the private key, and includes the signature and the public key (or a hash of the public key) to identify itself. The server verifies that the public key is registered, and verifies the signature.
There would be no way to mimic this short of stealing the private key from the client, or breaking RSA encryption. Well, I guess you could record and replay somebody else's POST. There is that problem to solve.
However, you could have a fake client follow the steps of registration and send a public key, and then that fake client would be free to POST along with all valid clients. So there is that problem to solve, too.

is it possible to make sure the client used is from a particular host?

I have a server application and a client application created with java that will communicate with the server application. But, since i haven't put emphasis on security in the server side it is really easy to hack the server application if a hacker creates his own client to connect with my server. I want to make sure the client application that is communicating with my server is the authentic client that i created. I upload client to a specific host like www.abcd.com. Now, can i make sure when a client that connects to my server came from that host. I am knowledgeable about signing it with trusted signer but i am looking for a cheap option.
No, this isn't possible. If it were, DRM would work, but everyone knows it's hopelessly broken.
To be truly secure, the client has to be a machine with a "trusted platform module," TPM, that supports something called remote attestation. This allows the server to verify the client is authentic and unaltered. But I've never heard of a real world application of this, and though TPMs are common, I'm not sure if the remote attestation feature is.
I want to make sure the client application that is communicating with my server is the authentic client that i created.
You have two options. One is a password or shared secret, and the other is client certificates. All three are supported in SSL/TLS. Look for TLS-SRP (password based authenticated key exchange), TLS_PSK (preshared key based on a block cipher), and the traditional SSLTLS ciphers with client side certificates.
You can even set up the tunnel with Server Authentication only, and then perform the client authentication at the application level. This is what usually happens in web apps. But this has some non-trivial defects because it does not provide mutual authentication and lacks channel binding. You are better off with TLS-SRP, TLS-PSK, or client certificates.
EDIT: I focused on SSL/TLS because you cited a hostname, but you can do it at other layers, too. For example, you can use shared secrets and certificates at the VPN level. #erickson provides one method using TPMs that could be used at the application level.
Now, can i make sure when a client that connects to my server came from that host.... host like www.abcd.com
This will work if DNS is configured and trustworthy. That is, you will have to extract the host's name, perform a reverse lookup, and then authenticate the IP address. I believe this is called network based authentication.
If an attacker controls DNS or is on the same LAN segment as the server, then I believe network based authentication has some non-trivial security defects.
In any case, HSMs and TPMs are not the answer. To understand why, see Peter Gutmann's Engineering Security, and the section on Unattended Key Storage. From his book:
TPMs don’t work because all that they can do is store the fixed key
that’s required to decrypt the other keys (TPMs are just repurposed
smart cards and don’t have the horsepower to perform anything more
than lightweight crypto themselves so you can’t offload the overall
encryption processing to them), and since for unattended operation
they have to release their secrets without a PIN being entered they’re
just providing plaintext key storage with one level of indirection.

How do I use our private key to make a web service call?

We're using Java 6, JBoss 7.1.1 and Spring 3.1.1.RELEASE. I'm trying to write an application that will request data from a WSDL on a corporate web site and then write that data back to a local database. Our corporate group has asked for the public key of a signed-by-authority client certificate (self-signed is fine for QA) of the machine that will be requesting the data, saying that they will use that to send SSL responses back to us and we should use our private key to send requests up to them.
I'm clueless about how to do this. Normally I would use JAX-WS to create client WSDL code and communicating with the web service, adding the server's public certificate to our trust store. But in this case, I have no idea how to tell the web service client to use the requesting machine's private key to encrypt data for the purposes of making a WSDL request.
Grateful for any example code or other reference material to pull this off. -
I have no idea how to tell the web service client to use the requesting machine's private key to encrypt data for the purposes of making a WSDL request.
That doesn't make sense. There is no such thing as encrypting with a private key. Anybody could decrypt it, the public key being, err, public. Let us hope that's not what they are asking for. It's far from clear but they are most probably asking for one of two things:
Use a client certificate when speaking SSL to them. All you have to do for this is use the keystore containing the private key and its certificate: JSSE will do the rest. OR
Digitally sign the request using your private key. There are APIs for this.
Get them to clarify which it is.

2-way SSL for web services on GAE (java)

We need to implement two-way SSL on Google App Engine, where we send out web service requests using JAX-WS to a server requring 2-way SSL authentication.
How can we set up 2-way SSL for our outgoing web service requests?
We know that javax.net.ssl* is forbidden in the App Engine environment.
Here's an example of our code:
#WebService(name="ListenerSoap", targetNamespace = "http://example.com/Listener.Wsdl")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface ListenerSoap {
#WebMethod(operationName = "Ping", action="http://example.com/Listener.Wsdl#Ping")
public void ping();
}
#WebServiceClient(name="Listener", targetNamespace="http://example.com/Listener.Wsdl", wsdlLocation = "https://example.com/Listener.asmx?WSDL")
public class Listener extends Service
{
public ListenerSoap getListenerSoap() {
return super.getPort(new QName("http://example.com/Listener.Wsdl",
"ListenerSoap"), ListenerSoap.class);
}
}
And an example of above code in use:
ListenerSoap soap = new Listener().getListenerSoap();
soap.ping();
I figure we can store the keystores or any certs needed in the DataStore as binary objects (though how to upload them is still a lil' vague to me).
How can we go about setting the necessary values needed for this web service to authenticate using 2-way SSL?
Thanks for any help
Update:
Through research I've seen this is how it can be done on a traditional server (one with filesystem access):
ListenerSoap soap = new Listener().getListenerSoap();
((BindingProvider) soap).getRequestContext().put("javax.net.ssl.keyStore", "client_cert.p12"
However, in this approach, client_cert.p12 is expected to be on the filesystem.
Additionally, SSLSocketFactory, SSLContext, KeyManager, and KeyManagerFactory all aren't allowed on GAE.
Update:
As of GAE SDK version 1.7.7. this should now be possible:
Similarly, Java developers can now use the javax.net.ssl package to make outbound SSL connections.
GAE 1.7.7 SDK Release Notes
From my restricted knowledge about SSL authorization, it seems you may be missing something of vital importance here; the certificates. Two-way SSL requires the client and server certificates to be in your keystore, which can be either a self-signed certificate( a pkcs12 or pem file, which you can easily generate with a few commands through shell) or a proprietary certificate issued by an authorized company like Thawte or Verisign.
Although I am not sure if that is the problem you are facing, but its good to check it out.
(Also, I am a newbie so please don't downvote my answer, just trying to suggest possible options.)
ListenerSoap soap = new Listener().getListenerSoap();
Hope it improves
Thanks
I know you might not want to hear this, but using SSL is expensive and problematic for two way communication. Depending on how much control you have over the server/client ends, I prefer a simple bi-directional pipe like web sockets and a data packet protocol that can simply implement AES. It really depends on the problem you are trying to solve.
It sounds like there is confusion over simple connection over SSL (https://...) and what is known as "mutual authentication" or "public key infrastructure (PKI)". You can actually do both or one independent of another. With the latter (what I think the original question is referring to), when you make a request to the server, the server will respond to you asking for a certificate which you must present to authenticate yourself.
To answer the specific question above (loading a keystore from binary data), I don't think that is really possible, since it's the Java runtime that picks up on your keystore. The only think you could do is load the bits from your datastore and temporarily write it to disk. Optionally delete it when the application exists. This I have done before and works fairly well. If you do this, I'd recommend using a location likely to be writable (such as System.getProperty("java.io.tmpdir"));), then after writing the file to disk, set the JVM properties (e.g. System.getProperties().put( "javax.net.ssl.keyStore","...");)
You will need App Engine's Socket API for this. This API is in trusted tester mode, so it's not available for everyone.
You can ask for an access gere : https://docs.google.com/spreadsheet/viewform?formkey=dF9QR3pnQ2pNa0dqalViSTZoenVkcHc6MQ#gid=0
2-way SSL (from app hosted in GAE to outside world) is not supported as far as I know. I tried a sample app few months ago and was frustrated to find GAE does n't even support this basic feature.. and the documentations are n't clear either. You won't be able to present client cert when you contact a web-service.. there is no place to store it, the keystore cannot be accessed.
For what i know about two way SSL, you will have no link with Java EE code: two way SSL is a transport layer security: when your client application will try to create a secured HTTP connection (HTTPS) with the serve, the server will ask for a certificate and will approve or not this certificate. If the client certificate is approved, then a secured connection will be established on parties and they are allow to exchange some messages through this tunnel. But this process is done on the transport layer. Your code (on application layer) will never be informed of this process.
In order to established two way SSL, the setup is done on the application server setup for the SSL port.

Categories