OpenSSL in C++ email client - server closes connection with TLSv1 Alert message
Posted
by
mice
on Stack Overflow
See other posts from Stack Overflow
or by mice
Published on 2012-03-24T11:23:37Z
Indexed on
2012/03/24
11:30 UTC
Read the original article
Hit count: 214
My app connects to a IMAP email server. One client configured his server to reject SSLv2 certificates, and now my app fails to connect to the server. All other email clients connect to this server successfully. My app uses openssl.
I debugged by creating minimal openssl client and attempt to connect to the server. Below is the code with connects to the mail server (using Windows sockets, but same problem is with unix sockets).
Server sends its initial IMAP greeting message, but after client sends 1st command, server closes connection. In Wireshark, I see that after sending command to server, it returns TLSv1 error message 21 (Encrypted Alert) and connection is gone.
I'm looking for proper setup of OpenSSL for this connection to succeed. Thanks
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <winsock2.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define CHK_NULL(x) if((x)==NULL) exit(1)
#define CHK_ERR(err,s) if((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
SSL *ssl;
char buf[4096];
void write(const char *s){
int err = SSL_write(ssl, s, strlen(s));
printf("> %s\n", s);
CHK_SSL(err);
}
void read(){
int n = SSL_read(ssl, buf, sizeof(buf) - 1);
CHK_SSL(n);
if(n==0){
printf("Finished\n");
exit(1);
}
buf[n] = 0;
printf("%s\n", buf);
}
void main(){
int err=0;
SSLeay_add_ssl_algorithms();
SSL_METHOD *meth = SSLv23_client_method();
SSL_load_error_strings();
SSL_CTX *ctx = SSL_CTX_new(meth);
CHK_NULL(ctx);
WSADATA data;
WSAStartup(0x202, &data);
int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
CHK_ERR(sd, "socket");
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr("195.137.27.14");
sa.sin_port = htons(993);
err = connect(sd,(struct sockaddr*) &sa, sizeof(sa));
CHK_ERR(err, "connect");
/* ----------------------------------------------- */
/* Now we have TCP connection. Start SSL negotiation. */
ssl = SSL_new(ctx); CHK_NULL(ssl);
SSL_set_fd(ssl, sd);
err = SSL_connect(ssl); CHK_SSL(err);
// Following two steps are optional and not required for data exchange to be successful.
/*
printf("SSL connection using %s\n", SSL_get_cipher(ssl));
X509 *server_cert = SSL_get_peer_certificate(ssl); CHK_NULL(server_cert);
printf("Server certificate:\n");
char *str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0);
CHK_NULL(str);
printf(" subject: %s\n", str);
OPENSSL_free(str);
str = X509_NAME_oneline(X509_get_issuer_name (server_cert),0,0);
CHK_NULL(str);
printf(" issuer: %s\n", str);
OPENSSL_free(str);
// We could do all sorts of certificate verification stuff here before deallocating the certificate.
X509_free(server_cert);
*/
printf("\n\n");
read(); // get initial IMAP greeting
write("1 CAPABILITY\r\n"); // send 1st command
read(); // get reply to cmd; server closes connection here
write("2 LOGIN a b\r\n");
read();
SSL_shutdown(ssl);
closesocket(sd);
SSL_free(ssl);
SSL_CTX_free(ctx);
}
© Stack Overflow or respective owner