2015-02-07 3 views
0

Привет Я пытаюсь написать SMTP-клиент на C++. После того, как «EHLO ...» и команды STARTTLS, соединение, кажется, хорошо, я получаю эту ошибку, когда я пытаюсь SSL_write():не удалось выполнить запись в ssl (openssl) после STARTTLS

32096:error:140790E5:SSL routines:SSL23_write::ssl handshake failure 

Я попытался SSL_do_handshake() перед SSL_write и она работает.

Вот мой код для части SSL.

typedef struct { 
    int socket; 
    SSL *sslHandle; 
    SSL_CTX *sslContext; 
} SSLConnection; 

SSLConnection* wrapSslSocket(SOCKET hSocket) 
{ 
    SSLConnection *c; 
    c = (SSLConnection *)malloc (sizeof (SSLConnection)); 
    c->sslHandle = NULL; 
    c->sslContext = NULL; 
    c->socket = hSocket; 
    if (c->socket) 
    { 
     // Register the error strings for libcrypto & libssl 
     SSL_load_error_strings(); 
     // Register the available ciphers and digests 
     SSL_library_init(); 

     c->sslContext = SSL_CTX_new (SSLv23_client_method()); //I tried SSLv23, SSLv3, SSLv2, TLSv1.2 TLSv1.1, TLSv1.0 
     if (c->sslContext == NULL) 
      ERR_print_errors_fp (stderr); 

     // Create an SSL struct for the connection 
     c->sslHandle = SSL_new (c->sslContext); 
     if (c->sslHandle == NULL) 
      ERR_print_errors_fp (stderr); 

     // Connect the SSL struct to our connection 
     if (!SSL_set_fd (c->sslHandle, c->socket)) 
      ERR_print_errors_fp (stderr); 

     if (!SSL_set_mode(c->sslHandle, SSL_MODE_AUTO_RETRY)) 
      ERR_print_errors_fp (stderr); 

     // Initiate SSL handshake 
     if (SSL_connect (c->sslHandle) != 1) 
      ERR_print_errors_fp (stderr); 
    } 
    return c; 
} 



// Read all available text from the connection 
int sslRead (SSLConnection *c) 
{ 
    const int readSize = 1024; 
    char buffer[1024]; 
    int cb; 
    int cbBuffer = 0; 

if (c) 
{ 
    while (1) 
    {  
     cb = SSL_read(c->sslHandle, buffer + cbBuffer, sizeof(buffer) - 1 - cbBuffer); 
     if(cb <= 0) 
     { 
      ERR_print_errors_fp (stderr); 
      return -1; 
     } 
     cbBuffer += cb; 
     if(memcmp(buffer + cbBuffer - 2, "\r\n", 2) == 0) 
     { 
      buffer[cbBuffer] = '\0'; 
      break; 
     } 
    } 
} 
    printf("ssl send : %s \n",buffer); 
    char status[3]; 
    memcpy(status,buffer, 3*sizeof(char)); 
    status[3] = '\0'; 
    return atoi(status); 
} 

// Write text to the connection 
int sslWrite (SSLConnection *c, char *text) 
{ 
    if (c) 
    { 
     int v = SSL_do_handshake(c->sslHandle); 
     ERR_print_errors_fp (stderr); 
     return SSL_write (c->sslHandle, text, strlen (text)); 
    } 
} 

Я тестирую на smtp.gmail.com порт 587

Благодарности

ответ

0

Вы можете рассмотреть возможность использования Scott Гиффорд sslclient (см http://www.superscript.com/ucspi-ssl/sslclient.html). sslclient вызовет вашу программу и откроет соединение tcp с сервером, а также выведет на сервер стандартный вывод stdout вашей программы и выведет на сервер вывод с сервера на stdin вашей программы. У него есть разветвленная версия для TLS, которая запустит соединение в виде простого текста, а затем, когда обе стороны согласятся с STARTTLS, ваша программа может сигнализировать sslcient, чтобы включить SSL-шифрование в соединении, написав команду файловому дескриптору для этого цели (см. https://github.com/SuperScript/ucspi-ssl/pull/1). Таким образом, вы можете использовать sslclient для выполнения всего тяжелого подъема до установки сокетов и ssl и т. Д., И вы можете сосредоточиться на основной функции вашей программы.