Is there a way i can detect if the incoming connection is not SSL/TLS
(not encrypted) and then retrieve what has been read in already. i will
then use standard read/write to handle the unsecure connection? i know
that sounds like a bad idea, but i have requirements to do this...
thank you,
-=- adam grossman
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openss...@openssl.org
Automated List Manager majo...@openssl.org
> Is there a way i can detect if the incoming connection is not SSL/TLS
> (not encrypted) and then retrieve what has been read in already. i will
> then use standard read/write to handle the unsecure connection? i know
> that sounds like a bad idea, but i have requirements to do this...
If the client's first message is not an SSL HELLO message you could
treat the session as plain-text.
Application protocols that support both plain-text and SSL, tend to
have a "STARTTLS" verb, that explicitly initiates the TLS session,
that way you always start in plain-text.
If you protocol cannot support explicit STARTTLS, then you could
try to auto-detect TLS, which is a bit ugly, but not impossible,
provided plain-text messages can never look like an SSL HELLO.
--
Viktor.
thanks,
-=- adam grossman
On Fri, 2010-01-15 at 11:51 -0500, Victor Duchovni wrote:
> On Fri, Jan 15, 2010 at 10:57:35AM -0500, Adam Grossman wrote:
>
> > Is there a way i can detect if the incoming connection is not SSL/TLS
> > (not encrypted) and then retrieve what has been read in already. i will
> > then use standard read/write to handle the unsecure connection? i know
> > that sounds like a bad idea, but i have requirements to do this...
>
> If the client's first message is not an SSL HELLO message you could
> treat the session as plain-text.
>
> Application protocols that support both plain-text and SSL, tend to
> have a "STARTTLS" verb, that explicitly initiates the TLS session,
> that way you always start in plain-text.
>
> If you protocol cannot support explicit STARTTLS, then you could
> try to auto-detect TLS, which is a bit ugly, but not impossible,
> provided plain-text messages can never look like an SSL HELLO.
>
> A simpler question might be (hopefully), is after i call "SSL_accept",
> is there a way to retrieve all the raw data which was read in by
> SSL_accept?
Don't call SSL_accept() unless you know that the client's first
message is an SSL HELLO. Use bio-pairs to drive the SSL I/O
engine, capture the client's first input buffer directly, and
only start the SSL engine if it is an SSL HELLO.
--
Viktor.
i have been reading about BIO pairs, but i am still confused. here is
what i am doing:
internalBIO=BIO_new(BIO_s_bio());
BIO_set_write_buf_size(internalBIO, 1024);
sslbio=SSL_get_rbio(ssl);
BIO_make_bio_pair(sslbio,internalBIO);
now my plan was to read the first 128 bytes, look at it, get the info i
needed, they call SSL_accept. but how do i put those 128 bytes "back",
so SSL_accept will pick those up, then the rest of the stream? i try
reading from sslbio, then writing back to internalBIO, but that didn't
work... (and yes, i am a newbie when it comes to this)...
thanks for the help,
-=- adam grossman
> On Fri, 2010-01-15 at 17:06 -0500, Victor Duchovni wrote:
> > On Fri, Jan 15, 2010 at 04:11:04PM -0500, Adam Grossman wrote:
> >
> > > A simpler question might be (hopefully), is after i call "SSL_accept",
> > > is there a way to retrieve all the raw data which was read in by
> > > SSL_accept?
> >
> > Don't call SSL_accept() unless you know that the client's first
> > message is an SSL HELLO. Use bio-pairs to drive the SSL I/O
> > engine, capture the client's first input buffer directly, and
> > only start the SSL engine if it is an SSL HELLO.
> >
>
>
> i have been reading about BIO pairs, but i am still confused. here is
> what i am doing:
>
> internalBIO=BIO_new(BIO_s_bio());
> BIO_set_write_buf_size(internalBIO, 1024);
>
> sslbio=SSL_get_rbio(ssl);
>
> BIO_make_bio_pair(sslbio,internalBIO);
>
>
> now my plan was to read the first 128 bytes, look at it, get the info i
> needed, they call SSL_accept. but how do i put those 128 bytes "back",
> so SSL_accept will pick those up, then the rest of the stream?
You write octets you have read from the socket into the network side of
the biopair, and you must write octets that you read from the network
side of the biopair to the socket.
As in the man page for BIO_new_bio_pair:
application | TLS-engine
| |
+----------> SSL_operations()
| /\ ||
| || \/
| BIO-pair (internal_bio)
+----------< BIO-pair (network_bio)
| |
socket |
You need to copy all available bytes from the network BIO to the
network socket whenever an SSL operation returns SSL_ERROR_WANT_WRITE
OR SSL_ERROR_WANT_READ.
If (and only if) you have copied everything available on the network
bio to the network, and an SSL operation returns SSL_ERROR_WANT_READ,
you can read the network socket and copy anything you get to the
network bio.
--
Viktor.
One last questions, and i am done bugging you about this...
These are the steps i am taking:
SSL_set_fd(ssl_data->ssl_ssl, sock_fd);
sslbio=SSL_get_rbio(ssl_data->ssl_ssl);
internalBIO=BIO_new(BIO_s_bio());
BIO_set_write_buf_size(internalBIO, 1024);
BIO_make_bio_pair(sslbio,internalBIO);
size=read(sock_fd,buffer,128); // returns as read 128
size=BIO_write(sslbio,buffer,size); // returns as written 128
SSL_accept(ssl_data->ssl_ssl);
and then the accept always fails.
i thought this was straight forward, but i am very wrong (or very
thick...)
thank you so much for all the hand holding,
-=- adam
> These are the steps i am taking:
>
> SSL_set_fd(ssl_data->ssl_ssl, sock_fd);
No, you do not associate the network socket with the SSL engine,
your app copies data back and forth between the SSL engine network
bio and the socket. SSL knows nothing about the socket.
the network (bio).
> sslbio=SSL_get_rbio(ssl_data->ssl_ssl);
>
> internalBIO=BIO_new(BIO_s_bio());
> BIO_set_write_buf_size(internalBIO, 1024);
This buffer size will lead to Nagle delays, use a buffer at least as
large as the interface MTU. ALso this is not the *internal* BIO, it
the "network" bio. The "internal" bio is the "sslbio".
> BIO_make_bio_pair(sslbio,internalBIO);
I've always seen code that creates both bios as new, and uses
SSL_set_bio to assign the internal bio to the SSL connection.
> size=read(sock_fd,buffer,128); // returns as read 128
> size=BIO_write(sslbio,buffer,size); // returns as written 128
No, you don't write to the ssl bio, you write to the "network" bio
(which you called "internal").
--
Viktor.
> One last questions, and i am done bugging you about this...
>
> These are the steps i am taking:
>
> SSL_set_fd(ssl_data->ssl_ssl, sock_fd);
> sslbio=SSL_get_rbio(ssl_data->ssl_ssl);
>
> internalBIO=BIO_new(BIO_s_bio());
> BIO_set_write_buf_size(internalBIO, 1024);
>
> BIO_make_bio_pair(sslbio,internalBIO);
>
> size=read(sock_fd,buffer,128); // returns as read 128
> size=BIO_write(sslbio,buffer,size); // returns as written 128
>
> SSL_accept(ssl_data->ssl_ssl);
>
> and then the accept always fails.
>
>
> i thought this was straight forward, but i am very wrong (or very
> thick...)
You two are talking about two very different things. Victor Duchovni is talking about separating the SSL engine from the socket, so you can put anything you want between the two. You are talking about "peeking" into the SSL data stream so you can decide whether to implement SSL or not. He's telling you the supported way to do what you want and you are trying to hack it in.
What does the rest of your architecture look like? Is your application multi-threaded? Does it handle a larger number of SSL connections? Is it intended to be portable? Because if your answers are yes, yes, and yes, (or no, yes and yes) you are approaching this completely the wrong way and should follow Victor Duchovni's approach.
DS
thanks for the patience with me. i literally started 5 days ago learning
openssl while working on this project which has a very short timeline.
the application is not multithreaded, has to handle a lot of connections
and does not need to be portable. i was asked to take an existing server,
and have it do the SSL handling, instead of another backend process. it
is a very specific architecture for a very specific purpose.
The problem is that the clients have been hacked to add some information
within the first packet sent over. and i, unfortunately, can't change
that. so i need to be able to read in the raw first 128 bits, get some
info out of that, and the have the SSL connection go just as normal, never
needing to intervene again. off the top of my head (i do not access to
the code right now), it places a few bits of info where it claims the
first cipher is,but getting the cipher list does not show anything useful
(i think bits 40 and 41 for SSLv2 for instance)
everything i have written so far has worked perfectly, until i ran into
this snag.
thank you so, so, so much and if you any of you are in the philly area, i
owe you a beer :)
-=- adam
You have an ugly problem. There are two ways you can solve it:
1) Do it right using BIO pairs. This will require a lot of new coding.
2) Fake it. Call 'accept', get the socket, 'select' or whatever you do to
discover the socket is ready for action. Try to recv(MSG_PEEK) the first 16
bytes. If you get fewer than 16 bytes, you'll have to try again later
(that's the ugly part). When you finally do get 16 bytes peeked, process
them however you need. Then wrap the socket in an SSL connection and let it
read the first 16 bytes too.
>
> The problem is that the clients have been hacked to add some information
> within the first packet sent over. and i, unfortunately, can't change
> that. so i need to be able to read in the raw first 128 bits, get some
> info out of that, and the have the SSL connection go just as normal, never
> needing to intervene again. off the top of my head (i do not access to
> the code right now), it places a few bits of info where it claims the
> first cipher is,but getting the cipher list does not show anything useful
> (i think bits 40 and 41 for SSLv2 for instance)
>
> everything i have written so far has worked perfectly, until i ran into
> this snag.
>
> thank you so, so, so much and if you any of you are in the philly area, i
> owe you a beer :)
Not had time to read the full details yet but I wonder if it is possible to do
this another way. BIO pairs will certainly work well and you've then get a lot
of control over the whole process.
An alternative which *may* work would be to read the first x bytes in, decide
if that is SSL/TLS there manually by inspecting a few bytes.
If so write that first bit to a memory BIO attach the SSL connection to that
BIO for read and the socket for write. Once all the data has been read from
the memory BIO you should get a WANT_READ condition which indicates it is
empty. Then switch over the read side to the socket and you then proceed as
normal.
Steve.
--
Dr Stephen N. Henson. OpenSSL project core developer.
Commercial tech support now available see: http://www.openssl.org