2015-02-07 16 views
0

您好我正在嘗試在C++中編寫SMTP客戶端。 後,「EHLO ...」和STARTTLS命令,該連接似乎是罰款當我嘗試SSL_write()我得到這個錯誤:SSL_write前無法在STARTTLS後寫入ssl(openssl)套接字

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

我試過SSL_do_handshake()和它的作品。

這是我的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

你可能要考慮使用斯科特吉福德的sslclient(見http://www.superscript.com/ucspi-ssl/sslclient.html)。 sslclient會產生你的程序,並打開一個到服務器的tcp連接,並將你的程序的標準輸出到服務器,並將輸出從服務器輸出到你的程序的標準輸入。他有一個用於TLS的分支版本,它將以純文本形式啓動連接,然後一旦雙方就STARTTLS達成一致,則您的程序可以通過向此文件描述符寫入命令來向sslcient發出信號以啓用SSL加密目的(見https://github.com/SuperScript/ucspi-ssl/pull/1)。這樣做,您可以使用sslclient完成所有繁重的工作,只要設置套接字和ssl等,您就可以專注於程序的核心功能。