OpenSSL generates TLS-alert: unsupported_protocol - c

I am trying to build an EAP-TLS client. I am using OpenSSL to build the TLS part of the data. Since EAP works on lower layers, I have used memory BIOs with OpenSSL to send information to Freeradius server using raw sockets. This is my code to generate client hello
ctx = SSL_CTX_new(TLSv1_client_method());
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
ssl = SSL_new(ctx);
rbio = BIO_new(BIO_s_mem());
wbio = BIO_new(BIO_s_mem());
SSL_set_bio(ssl, rbio, wbio);
SSL_set_connect_state(ssl);
SSL_do_handshake(ssl);
readbytes = BIO_read(wbio, buf, BUF_SIZ);
and this is what i tried to do to read the reply of the server into the same ssl:
BIO_write(rbio, temp, numbytes);
SSL_do_handshake(ssl);
readbytes = BIO_read(wbio, read, BUF_SIZ); // read is a buffer
however, when i try to send a packet using the data held in read, wireshark shows the packet as: Does anyone know why this is happening? Is this due to improper configuration of the RADIUS server? Or am I making a mistake in reading the data? According to what I read, SSL_do_handshake should be called till all the handshake steps are completed, so I dont think that there is a mistake there. Thanks a lot! Full packet sequence(use filter EAP) : http://www.filehosting.org/file/details/453553/eap-tls.pcapng

Related

What is a best way to send message from tcp server to raspberry pi?

I'm trying to use REST API server on my pi1 and TCP server on AWS EC2
I have two raspberry pis and as I wanted to use tcp server (in C) that I learned
(first one at home, second one at anywhere with wifi)
My goal is
if anyone (external) sends something on my pi's raspberry pi REST API server INSTANTLY
in an endpoint function, creates tcp client and also sending some JSON result to send somewhere
let mut stream =
TcpStream::connect("ec2-XXX-compute.amazonaws.com:8888")
.await
.expect("connect failed");
// Buffer the bytes
stream
.write_all(action.as_bytes())
.await
.expect("sending msg");
stream
.shutdown(Shutdown::Both)
.expect("shutdown call failed");
this client sends the message to EC2's TCP server and read with C language
if ((client_socket = accept(server_fd, (struct sockaddr *)&newAddr,
&addr_size)) < 0)
{
perror("accept");
exit(EXIT_FAILURE);
}
valread = read(client_socket, buffer, 10);
printf("From client: %s\n", buffer);
It works very well so far but what I want to do from here is to send the buffer data to
my another raspberry pi (pi2)
(pi 2's wifi keeps changing so it can only access internet, can't run server here)
What will be the best way to do this without delay or checking?
Sorry for the ugly picture but hope this helps your understanding
on PI 1, I'm running rest api/tcp server
and pi 2 can run tcp client server anywhere and connect to the pi 1
implemented with multiple clients without threading
Thanks all who watched this question!

SSL_get_peer_certificate(ssl) return NULL?

I am beginner. I have problem when use SSL.
I find a code c on internet. in server code, have a follow function:
void ShowCerts(SSL* ssl)
{ X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
if ( cert != NULL )
{
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
free(line);
X509_free(cert);
}
else
printf("No certificates.\n");
}
when I use command: openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem and run ./sslserver.o 443 and then i run ./client localhost 443. server error: "No certificates.". I think reason SSL_get_peer_certificate(ssl) return null but i don't know way to fix it. Can you help?
Full code: http://simplestcodings.blogspot.com/2010/08/secure-server-client-using-openssl-in-c.html
SSL_get_peer_certificates only returns a certificate on the server side if the client has send a certificate. But the code your refer to does not request a client certificate which means that the client will not send one. To request a client certificate the server would need to use SSL_CTX_set_verify and set the mode to at least SSL_VERIFY_PEER, i.e. at the minimum you need to do:
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
But this will only request an optional client certificate. It will not cause a validation of it. Note that the code example you use is broken in this regard anyway since it does not do any kind of certificate validation. This means it is open to trivial man in the middle attack, i.e. does not provide the security you expect when using SSL. Thus I recommend to not use this code as example on how to write secure SSL client and server.

Writing bytes directly to OpenSSL Connection, without TCP

I'm implementing a RADIUS server with support for EAP(PEAP) authentication. The RADIUS relies on UDP and each packet will contain an EAP message with the authentication data. To simplify, each EAP (PEAP) message contains TLS packets so the client first will send an EAP packet containing TLS Client Handshake, which the server will process, and then return the TLS Server Handshake, and so on with the following packages.
I've been able to implement a simple TLS server over TCP, but what I need is write TLS bytes directly in the SSL connection.
SSLConn_init_thread();
SSL_load_error_strings();
ERR_load_crypto_strings();
SSL_library_init();
SSL_CTX *ctx;
...
ctx = SSL_CTX_new(SSLv23_server_method());
SSL_CTX_use_PrivateKey(...);
SSL_CTX_use_certificate(...);
ssl = SSL_new(ctx); // I want to read/write TLS packets directly with this object
I've looked into OpenSSL docs but it's not very well documented. In this guide says one can make the handshake "by hand" using the SSL_set_accept_state() with SSL_read and SSL_write, but I don't understand exactly how to do that.
Any advice with this or about handling OpenSSL connections without relying on TCP would be very appreciated.
I ended up reading the book Network Security with OpenSSL and found Memory BIOs were what i needed.
Network Security With OpenSSL
A memory BIO treats a memory segment the same as a file or socket, and can be created by using
BIO_s_mem to obtain a BIO_METHOD object suitable for use with BIO_new and BIO_set
BIO_s_mem()
BIO_s_mem() return the memory BIO method function.
A memory BIO is a source/sink BIO which uses memory for its I/O. Data written to a memory BIO is stored in a BUF_MEM structure which is extended as appropriate to accommodate the stored data.
Any data written to a memory BIO can be recalled by reading from it. Unless the memory BIO is read only any data read from it is deleted from the BIO.
Basically you can read/write encrypted data directly to the SSL connection using the memory BIOs:
// setup SSL_context...
ssl = SSL_new(ctx);
// Create read/write BIOs
rbio = BIO_new(BIO_s_mem());
wbio = BIO_new(BIO_s_mem());
SSL_set_bio(ssl, rbio, wbio);
if (/* Server */) {
SSL_set_accept_state(ssl);
} else {
SSL_set_connect_state(ssl);
}
To write/read from BIOs:
BIO_read(wbio, buffer, strlen(buffer));
BIO_write(wbio, buffer, strlen(buffer));
In ascii diagram terms, here's what the flow of bytes loops like. SSL_read/SSL_write are used to pass unencrypted bytes in-to/out-of the SSL object, and BIO_read/BIO_write are used to get corresponding encrypted bytes in-to/out-of the SSL object. It's the up to you to then transfer the encrypted bytes over a network connection.
Git hub example of non blocking sockets / SSL
(https://gist.github.com/darrenjs/4645f115d10aa4b5cebf57483ec82eca)
+------+ +-----+
|......|--> read(fd) --> BIO_write(rbio) -->|.....|--> SSL_read(ssl) --> IN
|......| |.....|
|.sock.| |.SSL.|
|......| |.....|
|......|<-- write(fd) <-- BIO_read(wbio) <--|.....|<-- SSL_write(ssl) <-- OUT
+------+ +-----+
| | | |
|<-------------------------------->| |<------------------->|
| encrypted bytes | | unencrypted bytes |

SMTPS: OpenSSL - SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol s23_clnt.c:787:

I'm using OpenSSL in order to encrypt some emails, that a piece of hardware sends. But, whenever I try to call SSL_connect(), I get :
SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
After sending "EHLO" and "STARTTLS" I call the following function:
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
void CreateTLSSession(int sockfd)
{
printf("///////////////creating TLS Session/////////////////////\n");
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL)
{
printf("failed to initialize context\n");
return;
}
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
ssl = SSL_new(ctx);
if (!SSL_set_fd(ssl, sockfd))
{
printf("failed to bind to socket fd\n");
return;
}
if (SSL_connect(ssl) < 1)
{
ERR_print_errors_fp(stdout);
fflush(stdout);
printf("SSL_connect failed\n");
return;
}
}
I've tried connecting to :
smtp.live.com : 587 --> SSL routines:SSL23_GET_SERVER_HELLO:unknown
protocol s23_clnt.c:787:
smtp.live.com : 25 --> SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol s23_clnt.c:787:
smtp.gmail.com : 587 --> SSL routines:SSL23_GET_SERVER_HELLO:unknown
protocol s23_clnt.c:787:
smtp.gmail.com : 465 --> no response from server at all!
smtp.gmail.com : 25 --> SSL routines:SSL23_GET_SERVER_HELLO:unknown
protocol s23_clnt.c:787:
I've tried different ports, since some similar questions on this SO suggested, that such error is usually related to using the wrong port for SSL.
Am I missing something here?
UPDATE:
All other methods (i.e. TLSv1_1_method(), SSLv3_method() ...) lead to SSL3_GET_RECORD:wrong version number
UPDATE:
I was able to observe the following on wireshark:
"EHLO"
"at your service"
"STARTTLS"
"Ready to starttls"
-->now I call the above function
unreadable request (encrypted)
unreadable reply (encrypted)
--> ERROR
SMTP servers on ports 587 and 25 are usually plain text and will switch to TLS only after the initial SMTP dialog and a STARTTLS command from the client. And trying SSL_connect on the plain text socket will fail.
Another way to solve this problem may be to run your C program under Scott Gifford's sslclient (see http://www.superscript.com/ucspi-ssl/sslclient.html). sslclient will spawn your program and open an tcp connection to the server, and pipe your program's stdout to the server, and pipe output from the server to your program's stdin. He has a patched version for TLS that will start the connection off in plain text, then once the two sides have agreed on STARTTLS, your program can signal to sslcient to enable SSL encryption on the connection by writing a command to a file descriptor for this purpose. The nice thing about doing it this way is that you can let sslclient to all the heavy lifting as far as setting up the sockets and ssl, etc., and you can focus on the core function of your program.
The underlying socked was non-blocking. The problem was solved, by using select and waiting till the TLS handshake completes.

How to get the cipher signature after SSL handshake?

I'm making a DTLS client-server program with openssl. The program works fine, but I can't find a way to get the cipher signature after SSL handshake.
By after SSL handshake, I mean in the client side, after:
if (SSL_connect(ssl) <= 0)
{
//error handling
}
In the server side, after:
do
{
ret = SSL_accept(ssl);
} while (ret == 0);
I can see the actual cipher signature is sha256WithRSAEncryption from the captured DTLS packets, but how to get this information from openssl?
Note that even though I'm using DTLS protocol, the code is almost the same as TLS/SSL.
Cipher algorithm used is stored in a certificate. So when you have a certificate (x509), the type of cipher algorithm can be extracted. Numeric version only:
X509_get_signature_type(client_cert)
To get human readable string, convert the return value of the previous function with this:
OBJ_nid2ln(X509_get_signature_type(client_cert))

Resources