SSL/TLS for FTP connections

I've built somekind of advanced ftp server, and i would now like to add SSL or TLS on the server.

Implementing implicit SSL is easy. I used some SSL sockets, and everything was working fine.

But if i want to use TLS or explicit SSL, i have a problem.

With an SSL socket, any attemps to read/write with the streams initiate an handshake.

But an explicit SSL connection is done that way:

-> Connecting to myftpserver.com port 21

-> Connected to myftpserver.com

Server: Welcome to this nice ftp

Server: Enjoy this nice server

-> AUTH SSL

Server: 234 AUTH SSL successful

-> Now negociating SSL session...

So, as u can see, some data(welcome msg, AUTH SSL command, etc) are exchanged BEFORE the SSL negociation.

I dont know how to do that since "any attemps to read/write with the streams initiate an handshake"

I hope someone will be able to help me :)

Dundee

[965 byte] By [Dundee31416] at [2007-9-30 21:01:08]
# 1

Sorry, I cannot help you but I need your help ^_^

I am implementing implicit SSL in a FTP client. Just as you said, I also used some SSL sockets, and everything seems working well. when I want to show some information about the SSL connection using SSLSocket's method( .getSession()) , the control socket runs well and the information is "Session-1, TLS_RSA_WITH_AES_128_CBC_SHA", but the data socket cannot work and shows "Session-1, SSL_NULL_WITH_NULL_NULL". I don't know what's wrong with it because the way to create the two sockets is similar. And if I don't call .getSession(), it can run well (but I think it's not SSLSession)

I don't know if there is something related to the FTP server. So I would like you to help me. Is there any difference when creating control socket and data socket at FTP server? Do you have any idea about my problem? Thanks a lot.

bluesweater at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 2
Well, a server using implicit SSL encrypts only the commands, not the data.The "main"socket will be using SSL, but when u open a data connection, it should be using plain socket.Check that first, and gimme news. Im not 100% sure if implicit SSL doesnt encrypts data.
Dundee31416 at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 3

Thanks a lot for your reply. Do you mean all the servers use plain socket for data connection if it's implicit SSL connection?Or just you use plain socket for data socket in your server? According to my results, it seems that data socket doesn't use SSL connection even if the socket is created as a SSLSocket. But when I use other FTP client like FTP Voyager, I can see the SSL connection for data socket. The server is server-U and it also uses implicit SSL connection. So that's the problem. I am very confused about it. Do you have any idea?

bluesweater at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 4

Have you tried to use SSLSocketFactory.createSocket( Socket, String, int, boolean) ?

I'm not sure if it can be used for that. What I was thinking is that is should be possible to start the communication using regular Socket then, start the SSL handshake.

That being said... I tried it without success.

I always get the following exception:

javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLProtocolException: Illegal client handshake msg

hferland at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 5

Ok, I found the way to connect client and server using "regular" - not encrypted - socket and then switching to SSL socket.

ClientServer

listen

connect -> accept

..... unencrypted communication using plan socket

write-> read(command to switch to SSL)

create SSLSocket over current socket

- SSLSocketFactory.createSocket(Socket.String,int,boolean)

- Don't use SSLServerSocketFactory since its not to get socket to liste

read<- write(command to tell the client the server is ready to talk SSL)

create SSLSocket over current socket (the same way as for the server sidee)

..... communication can start using the SSLSocket

I suggest to create a SSLContext (and initialize it as required) from which you can get the necessary SSLSocketFactory.

I don't know if this match what you were looking for. I hope this might help anyway.

Hugues

hferland at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 6

Thanks a lot for your so kindly help. I find out the problem today. That's because I call SSLSocket.getSession() just after creating the socket. Actually, the connection hasn't been established at that time. It's OK if I call the method after executing the command like LIST and so on. In fact, it's not a big problem. Right? I am very happy. And thanks again.

bluesweater at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 7

Here's what i've done:

SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();

SSLSocket cmdSocket = (SSLSocket)factory.createSocket(sock,"myftp.servemp3.com", 21, true);

Utils.send(out,"234 AUTH Successfull");

cmdSocket.startHandshake();

And i get the same HandshakeException that someone mentionned above.

What's wrong?

Can someone give me an exemple of "context"? I never worked with that.

Dundee31416 at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 8

Thanks for your help hugues.

But there's something i dont understand.

> Have you tried to use SSLSocketFactory.createSocket( Socket, String, int, boolean) ?

>

> I'm not sure if it can be used for that. What I was thinking is that is should be possible to start the

> communication using regular Socket then, start the SSL handshake.

>

> That being said... I tried it without success.

U said it wasnt working.

What's the difference between this idea and what you've done in this exemple?

> > ClientServer

> listen

> connect -> accept

> ..... unencrypted communication using plan socket

> write-> read(command to switch to SSL)

> create SSLSocket over current socket

> -

> SSLSocketFactory.createSocket(Socket.String,int,boolean

>

> - Don't use SSLServerSocketFactory since its not to

> get socket to liste

> read<- write(command to tell the client

> the server is ready to talk SSL)

> create SSLSocket over current socket (the same way as

> for the server sidee)

> ..... communication can start using the SSLSocket

>

Dundee

Dundee31416 at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 9
It is because I was not waiting for the server to be ready to receive SSL handshake. That is for the server to have created his SSLSocket.
hferland at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 10
P.S. Im my code i used(SSLSocket)factory.createSocket(sock,"myftp.servemp3.com", 21, true);only for testing purpose, cause i know that the port and address of the incoming connection would be that. I was too lazy to get the socket address :P
Dundee31416 at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 11
What's wrong with my code then?
Dundee31416 at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 12

> What's wrong with my code then?

You must make sure, before trying to send the first encrypted text, that both side are ready to negociate SSL.

I'm pretty sure your problem is about that.

Did you write both side (client and server) or only the client side?

Because if you are the author of the server side, you must also make sure the server will act as the server during the SSL negociation ( ((SSLSocket)s).setUseClientMode(false)).

So far, my understanding - based on my experimentation:

The client must ask to the server to start SSL communication, but MUST wait for the server to say it is ready before creating the SSL layer. This mean the client send - over the unencrypted communication - a command saying to the server: "i want to start to talk to you over SSL". Then the server answer "Ok, ,i'm ready". Then, and only then, the client create the SSL socket (over the already connected socket - as you seem to have done) and start the SSL negociation. By the way, it is not necessary to call SSLSocket.startNegotiate() explicitly, it will be called when sending the first block of data for the new SSL session.

I'm not sure if I made it clear. But I think the problem - the reason why you get the HandshakeException - is because the client try to negotiate SSL before the server is ready to accept SSL negotiation - maybe this should have been the only sentence of my answer ;-).

About the use of SSLContext; I feel that it only have value if you want to use your own customized X509TrustManager or X509KeyManager. For me, I found it very useful because my server certificate may not be valid as per the default validation algorithm. But basicly we can use the SSLContext the following way:

/* The creation of a KeyManager is a story in itself.

* The way I used it is to specify in my program the KeyStore to be used.

* I think it can be specified in other ways (-D java argument, for exemple).

* For now I not sure how useful it can be for the client side. (sorry)

*/

KeyManager[] myKeyManagers= ....

/* The TrustManager give you the opportunity to do your own validation

* of the server / client - depending on the situation - certificate.

* For now, I don't know how to use TrustManager and KeyManager

* together.

*/

TrustManager[] myTrustManager= new TrustManager[] {new MyX509TrustManager()};

/* The Key and Trust managers created above, can be used to initialize

* the SSL context below.

*/

SSLContext context= SSLContext.getInstance("SSL");

/* Initialize the context with your customized managers.

* Note that all parameters are optional - they can be "null".

* You only specify those you have customized.

*/

context.init( myKeyManager, myTrustManager, null);

/* Then later I can get my SSL socket factory, which will use my

* own customized key and trust manager and secure random.

*/

SSLServerSocketFactory sslSSF= context.getServerSocketFactory();

SSLSocketFactory sslSF= context.getSocketFactory();

I found an article in this forum about TrustManager.... seem very promising.

Hope this will help.

Hugues

hferland at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 13
The **** problem was that my SSLSocket was set to be in client mode. Didnt knew that.Thanks a lot Hugues, u got 10 Duke Dollars for your good answer :)
Dundee31416 at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 14

> The **** problem was that my SSLSocket was set to be in client mode. Didnt knew that.

This will always happen if you use SSLSocketFactory.createSocket( Socket, String, int, boolean). This always creates a socket in client mode. What else can it do? If the Socket you supplied came from an accept() it is up to you to put the resulting SSLSocket into server mode.

ejp at 2007-7-7 2:33:14 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 15

Has anybody of you now made it to a fully tls/ssl-encrypted ftp-connection?

Ive made it to encrypt the controlconnection, but whenever i try to create an additional encrypted socket for the data-connection the server doesnt accept it.

If you have any idea, what i have to do, e.g. take sth from the initial ssl-context of the controlconnection or sth like this, id be really glad.

Azrael

Azraelgoda at 2007-7-20 0:16:19 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 16
Hi !if you are still looking for a library look at http://www.sourceforge.net/projects/ftp4chethere are some guys which are implementing a java based ftp library (ssl already working).yourszyborg
zyborg_zyborga at 2007-7-20 0:16:19 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...