我尝试了很多天在Linux服务器和Windows / Linux客户端之间实现TCP通信 通信工作但证书交换没有,服务器正在等待从未发送的客户端证书。
客户端和服务器作为使用OpenSSL 1.0.2n运行的展位 证书安装在Windows应用商店(.pfx)
上服务器代码:
void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile, char* CAFile)
{
// set the local certificate from CertFile
if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0)
{ ERR_print_errors_fp(stderr);abort(); }
// set the private key from KeyFile (may be the same as CertFile)
if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0)
{ ERR_print_errors_fp(stderr); abort(); }
// verify private key
if (!SSL_CTX_check_private_key(ctx))
{ printf(stderr, "Private key does not match the public certificate\n"); abort(); }
SSL_CTX_set_ecdh_auto(ctx, 1);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
SSL_CTX_set_verify_depth(ctx,4);
if (SSL_CTX_load_verify_locations(ctx, CAFile, NULL) != 1)
{ printf("SSL_CTX_load_verify_locations failed\n"); ERR_print_errors_fp(stderr); }
}
void Servlet(SSL* ssl) /* Serve the connection -- threadable */
{ char buf[1024];
char reply[1024];
int sd, bytes;
const char* HTMLecho="<html><body><pre>%s</pre></body></html>\n\n";
if ( SSL_accept(ssl) == FAIL ) /* do SSL-protocol accept */
ERR_print_errors_fp(stderr);
else
{
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
if ( bytes > 0 )
{
buf[bytes] = 0;
printf("Client msg: \"%s\"\n", buf);
sprintf(reply, HTMLecho, buf); /* construct reply */
SSL_write(ssl, reply, strlen(reply)); /* send reply */
}
else
ERR_print_errors_fp(stderr);
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
}
int main(int count, char *strings[])
{ SSL_CTX *ctx;
int server;
struct sockaddr_in addr;
char CertFile[] = "/opt/doamin.cer";char KeyFile[] = "/opt/doamin.key"; char CAFile[] = "doamin-ca.crt";
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(TLSv1_2_server_method());
SSL_CTX_set_options(ctx,SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_COMPRESSION);
LoadCertificates(ctx, CertFile, KeyFile,CAFile); /* load certs */
server = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if ( bind(server, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
{ perror("can't bind port"); abort(); }
if ( listen(server, 10) != 0 )
{ perror("Can't configure listening port");abort();}
while (1)
{ struct sockaddr_in addr;
socklen_t len = sizeof(addr);
SSL *ssl;
int client = accept(server, (struct sockaddr*)&addr, &len); /* accept connection as usual */
printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
ssl = SSL_new(ctx); /* get new SSL state with context */
SSL_set_fd(ssl, client); /* set connection socket to SSL state */
Servlet(ssl); /* service connection */
}
close(server); /* close server socket */
SSL_CTX_free(ctx); /* release context */
}
客户端(在Windows上)
int main()
{
SSL_load_error_strings();
ERR_load_crypto_strings();
ERR_load_SSL_strings();
OpenSSL_add_all_algorithms();
(void)SSL_library_init();
char *hostname = "dct.sub.domain.fr"; int port = 445;
SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_client_method()); /* Create new context */
if (ctx == NULL)
{ ERR_print_errors_fp(stderr);abort(); }
struct hostent *host = gethostbyname(hostname)
struct sockaddr_in addr;
char aszBuffer[256];
if (!host)
abort();
int server = socket(PF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long*)(host->h_addr);
if (connect(server, (struct sockaddr *)&addr, sizeof(addr)) != 0)
{ closesocket(server);perror(hostname);abort();}
// Load certificate from windows Store
X509_STORE* pSt = SSL_CTX_get_cert_store(ctx);
X509_LOOKUP* m_lookup = X509_STORE_add_lookup(pSt, X509_LOOKUP_file());
{
HCERTSTORE hStore;
PCCERT_CONTEXT pContext = NULL;
X509 *x509;
hStore = CertOpenSystemStore(NULL, L"ROOT");
if (!hStore)
return 1;
LPTSTR pszString;
LPTSTR pszName;
DWORD cbSize;
CERT_BLOB blobEncodedName;
while (pContext = CertEnumCertificatesInStore(hStore, pContext))
{
if (!(cbSize = CertGetNameString(pContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,0,NULL,NULL,0)))
MyHandleError(TEXT("CertGetName 1 failed."));
if (!(pszName = (LPTSTR)malloc(cbSize * sizeof(TCHAR))))
MyHandleError(TEXT("Memory allocation failed."));
if (CertGetNameString(pContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,0,NULL,pszName,cbSize))
{
_tprintf(TEXT("\nSubject -> %s.\n"), pszName);
//-------------------------------------------------------
// Free the memory allocated for the string.
free(pszName);
}
x509 = NULL;
x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded);
if (x509)
{
int i = X509_STORE_add_cert(pSt, x509);
if (i == 1)
printf("certificate added\n");
X509_free(x509);
}
}
CertFreeCertificateContext(pContext);
CertCloseStore(hStore, 0);
}
SSL_CTX_set_ecdh_auto(ctx, 1);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0);
SSL_CTX_set0_chain_cert_store(ctx, pSt);
SSL* pSsl = SSL_new(ctx);
X509_VERIFY_PARAM *param = SSL_get0_param(pSsl);
X509_VERIFY_PARAM_set_hostflags(param, 0);
if (!X509_VERIFY_PARAM_set1_host(param, hostname, strlen(hostname) ))
return 0;
SSL_set_mode(pSsl, SSL_MODE_AUTO_RETRY);
SSL_set_fd(pSsl, server);
if (SSL_connect(pSsl) == -1)
abort();
long l = SSL_get_verify_result(pSsl);
if ( l == X509_V_OK)
printf("SSL_get_verify_result Ok \n");
else
printf("SSL_get_verify_result %d \n",l);
for (int j = 0; j < 5; ++j)
SSL_write(pSsl, 4, "test");
}
客户端应用程序检查服务器但不发送其证书==&gt; 1074894052:错误:140890C7:SSL例程:ssl3_get_client_certificate:peer未返回证书:s3_srvr.c:3269:
客户结果:
OpenSSL: Loaded CA cert : subject='/C=FR/O=compagny/CN=AC compagny Root'
OpenSSL: Loaded CA cert : subject='/C=FR/ST=France/L=Paris/O=compagny/OU=TRA/CN=*.sub.domain.fr' : ( From certmgr : With Private key for this domain )
OpenSSL: Loaded CA cert : subject='/C=FR/O=compagny/CN=AC compagny'
[...]
SSL_get_verify_result OK
同样的事情附加'openssl s_client -connect dct.sub.domain.fr:445'
CONNECTED(000001A0)
depth=2 C = FR, O = company, OU = 0002 518888888, CN = AC company Root
verify error:num=19:self signed certificate in certificate chain
14220:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure: .\ssl\s3_pkt.c:1500:SSL alert number 40
14220:error:140790E5:SSL routines:ssl23_write:ssl handshake failure:.\ssl\s23_lib.c:177:
---
Certificate chain
0 s:/C=FR/ST=France/L=Paris/O=company/OU=TRA/CN=*.sub.domain.fr
i:/C=FR/O=company/OU=0002 999999999/CN=AC company
1 s:/C=FR/O=company/OU=0002 999999999/CN=AC company
i:/C=FR/O=company/OU=0002 518888888/CN=AC Ccompany
2 s:/C=FR/O=company/OU=0002 518888888/CN=AC company
i:/C=FR/O=company/OU=0002 518888888/CN=AC company
---
Server certificate
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
subject=/C=FR/ST=France/L=Paris/O=company/OU=TRA/CN=*.sub.domain.fr
issuer=/C=FR/O=company/OU=0002 999999999/CN=AC company
---
No client certificate CA names sent
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Shared Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 5325 bytes and written 138 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID:
Session-ID-ctx:
Master-Key: 8EB904862A6D7FB954F5A2AB701429D9D066852A0C7A40832EEC9AD3A56B66AE786D485BF8AFF8D37C4D27629A41D5F3
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1523868440
Timeout : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)
但适用于:'openssl.exe s_client -connect dct.sub.doamin.fr:445 -cert out.crt -key out.crt -CAfile out.crt'
CONNECTED(000001A0)
depth=2 C = FR, O = compagny, OU = 0002 999999999, CN = AC compagny Root
verify return:1
depth=1 C = FR, O = compagny, OU = 0002 998888888, CN = AC compagny
verify return:1
depth=0 C = FR, ST = France, L = Paris, O = compagny, OU = TRA, CN = *.sub.domain.fr
verify return:1
---
Certificate chain
0 s:/C=FR/ST=France/L=Paris/O=compagny/OU=TRA/CN=*.sub.domain.fr
i:/C=FR/O=compagny/OU=0002 998888888/CN=AC compagny
1 s:/C=FR/O=compagny/OU=0002 998888888/CN=AC compagny
i:/C=FR/O=compagny/OU=0002 999999999/CN=AC compagny Root
2 s:/C=FR/O=compagny/OU=0002 999999999/CN=AC compagny Root
i:/C=FR/O=compagny/OU=0002 999999999/CN=AC compagny Root
---
Server certificate
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
subject=/C=FR/ST=France/L=Paris/O=compagny/OU=TRA/CN=*.sub.doamin.fr
issuer=/C=FR/O=compagny/OU=0002 88888888/CN=AC compagny
---
No client certificate CA names sent
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Shared Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 7208 bytes and written 5569 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: FBF6E85A99787BFEA2088948841E03EFABD831D1D809CEB21DCB2C7CF3710997
Session-ID-ctx:
Master-Key: 16C1400E26554260B5921C305382BBFC098915CEBE54F5F9BB58D29715AFF94F7EDC5F88432887E4A8EA8487C8D9E939
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
[...]
Start Time: 1523882730
Timeout : 300 (sec)
Verify return code: 0 (ok)
任何帮助都是值得欣赏的,我尝试了很多东西,但现在我不知道在哪里继续,