openSSL:握手失败 - 服务器无法获取客户端证书

时间:2012-04-17 04:47:03

标签: c linux openssl vmware public-key-encryption

我正在尝试使用openSSL API编写客户端和服务器代码来进行SSL握手。

客户端代码包含:

 // Part of client code:
 SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
 SSL_CTX_load_verify_locations(ctx,"ca.pem",NULL);
 ...
 if (SSL_CTX_use_certificate_file(ctx, "cli.crt" , SSL_FILETYPE_PEM) <= 0) {
  exit(1);
  }

  if (SSL_CTX_use_PrivateKey_file(ctx, "cli.key", SSL_FILETYPE_PEM) <= 0) {
  exit(1);
  }
 ...
 sd = socket (AF_INET, SOCK_STREAM, 0);
 sa.sin_family      = AF_INET;
 sa.sin_addr.s_addr = inet_addr ("127.0.0.1"); 
 sa.sin_port        = htons (44444);
 ...
 ssl = SSL_new (ctx);              
 SSL_set_fd (ssl, sd);
 err = SSL_connect (ssl); 

服务器代码包含:

 // Part of server code:
 SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
 SSL_CTX_load_verify_locations(ctx,"ca.pem",NULL);
 ...
 if (SSL_CTX_use_certificate_file(ctx, "serv.crt", SSL_FILETYPE_PEM) <= 0) {
    exit(1);
 }
 if (SSL_CTX_use_PrivateKey_file(ctx, "serv.key", SSL_FILETYPE_PEM) <= 0) {
    exit(1);
  }
 ...
 listen_sd = socket (AF_INET, SOCK_STREAM, 0);  
 memset (&sa_serv, '\0', sizeof(sa_serv));
 sa_serv.sin_family      = AF_INET;
 sa_serv.sin_addr.s_addr = INADDR_ANY;
 sa_serv.sin_port        = htons (44444);

 err = bind(listen_sd, (struct sockaddr*) &sa_serv, sizeof (sa_serv));                           
 err = listen (listen_sd, 5);       
 client_len = sizeof(sa_cli);
 sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
 close (listen_sd);
 ....
 ssl = SSL_new (ctx);                           
 SSL_set_fd (ssl, sd);
 err = SSL_accept (ssl);   

我使用目标地址作为回送地址(127.0.0.1)运行代码,从上面显示的代码可以看出。在同一台机器上执行的客户端和服务器程序工作正常。

但是,当我在不同的机器(VMWare VMs - Ubuntu Linux)上运行客户端和服务器程序时,代码会失败。

 Client VM IP:192.168.181.188
 Server VM IP:192.168.181.180

使用服务器VM的IP(例如192.168.181.180)作为客户端代码中的地址,我在服务器上收到以下错误:

 140890B2: SSL3_GET_CLIENT_CERTIFICATE:no certificate returned: s3_srvr.c:2602:

我在Linux机器上创建了自己的CA,并与客户端和服务器VM共享CA公钥文件。客户端和服务器证书由此CA签名。

 CA : CA123
 Client CN: Client (signed by CA123)
 Server CN: Server (signed by CA123)

客户端能够验证服务器证书(我甚至可以获得服务器证书并检查CN确实是'服务器'),但是服务器无法获得客户端证书,因此握手失败。

有人可以建议解决这个问题吗?

非常感谢。

2 个答案:

答案 0 :(得分:0)

检查客户端证书的subject。有时,CN(公用名)字段应具有客户端主机的IP或主机名。

在您的情况下,客户证书可能具有以下主题:

Subject: C=xxx, ST=xxx, L=xxx, O=xxx, OU=xxx, CN=192.168.181.180

我不是100%肯定这个修复。但在破墙之前,试一试。

答案 1 :(得分:0)

好的......我不确定以下是一个完整的解决方案,它只是我当前项目的修复,我仍然不满意我的答案。

因此,通过阅读我的问题,你会发现我提到CA是在linux机器上制作的,客户端和服务器的证书是由CA签署的。该主机是另一个VMWare VM,称之为“VM3”。因此,我在“VM3”上为客户端和服务器使用“CA123”生成的证书在客户端VM(称为“VM1”)和服务器VM(称为“VM2”)上不起作用。出于好奇,我尝试在VM2上设置CA,并签署客户端和服务器证书,并将客户端证书复制到客户端VM。令我惊讶的是,它有效,但我不知道为什么。我无法回答我在VM3上创建了哪种依赖?

随意发布更准确,更完整的答案。