2015-02-07 17 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等,您就可以专注于程序的核心功能。