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: 190

Filed under:
|
|
|
|

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

Related posts about c++

Related posts about ssl