0

您好我正在尝试用 C++ 编写一个 SMTP 客户端。在“ehlo ...”和 STARTTLS 命令之后,连接似乎很好,当我尝试 SSL_write() 时出现此错误:

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

我在 SSL_write 之前尝试了 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 上进行测试

谢谢

4

1 回答 1

0

您可能需要考虑使用 Scott Gifford 的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 等,并且您可以专注于程序的核心功能。

于 2015-02-07T12:24:15.097 回答