Openssl Client不发送证书

时间:2018-04-17 09:38:36

标签: ssl openssl client-certificates

我尝试了很多天在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)

任何帮助都是值得欣赏的,我尝试了很多东西,但现在我不知道在哪里继续,

0 个答案:

没有答案