客户端和服务器的通信使用SSL的C / C ++ - SSL协议不工作 [英] Client and Server communication using ssl c/c++ - SSL protocol don't works

查看:140
本文介绍了客户端和服务器的通信使用SSL的C / C ++ - SSL协议不工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用来自SSL客户端/服务器的例子:<一href=\"http://simplestcodings.blogspot.com.br/2010/08/secure-server-client-using-openssl-in-c.html\">http://simplestcodings.blogspot.com.br/2010/08/secure-server-client-using-openssl-in-c.html创建使用的SSLv3的安全连接。我提出了要求一些修改服务器端的证书,交际工作正常,并在双方了解。因此,我的问题是,当客户端连接到服务器时,协议通信的SSLv3不工作,我验证使用wirkeshark,并在协议字段只是表明TCP或IPA(RSL畸形报文)有人能帮助我吗?谢谢!

我创建了以下教程 https://help.ubuntu.com/community/OpenSSL 我的证书。

下面是我的客户code:

  // SSL-Client.c
#包括LT&;&stdio.h中GT;
#包括LT&;&errno.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&malloc.h所GT;
#包括LT&;&string.h中GT;
#包括LT&; SYS / socket.h中&GT;
#包括LT&;&resolv.h GT;
#包括LT&;&netdb.h中GT;
#包括LT&;的OpenSSL / ssl.h&GT;
#包括LT&;的OpenSSL / err.h&GT;#定义FAIL -1    //添加的服务器端如何使LoadCertificates。
无效LoadCertificates(SSL_CTX * CTX,字符* CERTFILE,字符* KeyFile时)
{
 / *从CERTFILE设置本地证书* /
    如果(SSL_CTX_use_certificate_file(CTX,CERTFILE,SSL_FILETYPE_PEM)下; = 0)
    {
        ERR_print_errors_fp(标准错误);
        中止();
    }
    / *从KeyFile中设置专用密钥(可以是相同CERTFILE)* /
    如果(SSL_CTX_use_PrivateKey_file(CTX,密钥文件,SSL_FILETYPE_PEM)LT; = 0)
    {
        ERR_print_errors_fp(标准错误);
        中止();
    }
    / *验证私钥* /
    如果(!SSL_CTX_check_private_key(CTX))
    {
        fprintf中(标准错误,私人密钥不匹配的公证书\\ n);
        中止();
    }
}INT OpenConnection的(为const char *主机名,INT口)
{诠释SD;
    结构hostent *主机;
    结构sockaddr_in的地址;    如果((主机=的gethostbyname(主机名))== NULL)
    {
        PERROR(主机名);
        中止();
    }
    SD =插座(PF_INET,SOCK_STREAM,0);
    bzero(安培;地址,的sizeof(地址));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(端口);
    addr.sin_addr.s_addr = *(*长)(主机 - &GT; h_addr);
    如果(连接(SD,(结构sockaddr *)及!地址,的sizeof(地址))= 0)
    {
        关闭(SD);
        PERROR(主机名);
        中止();
    }
    返回SD;
}SSL_CTX * InitCTX(无效)
{SSL_METHOD *方法;
    SSL_CTX * CTX;    OpenSSL_add_all_algorithms(); / *负载cryptos,等人* /
    SSL_load_error_strings(); / *带和注册错误信息* /
    方法= SSLv3_client_method(); / *创建新的客户方法实例* /
    CTX = SSL_CTX_new(法); / *创建新的上下文* /
    如果(CTX == NULL)
    {
        ERR_print_errors_fp(标准错误);
        中止();
    }
    返回CTX;
}无效ShowCerts(SSL * SSL)
{X509 *证书;
    字符*线;    证书= SSL_get_peer_certificate(SSL); / *获取服务器的证书* /
    如果(CERT!= NULL)
    {
        的printf(服务器证书:\\ n);
        行= X509_NAME_oneline(X509_get_subject_name(证书),0,0);
        的printf(主题:%S \\ n,行);
        免费(线); / *释放malloc分配的字符串* /
        行= X509_NAME_oneline(X509_get_issuer_name(证书),0,0);
        的printf(发行人:%S \\ n,行);
        免费(线); / *释放malloc分配的字符串* /
        X509_free(CERT); / *释放malloc分配证书复印件* /
    }
    其他
        的printf(没有证书\\ n);
}诠释的main()
{SSL_CTX * CTX;
    int服务器;
    SSL * SSL;
    焦炭BUF [1024];
    诠释字节;
    CHAR主机名[] =127.0.0.1;
    CHAR端口编号[] =5000;
    CHAR CERTFILE [] =/home/myCA/cacert.pem;
    CHAR KeyFile是[] =/home/myCA/private/cakey.pem;    SSL_library_init();    CTX = InitCTX();
    LoadCertificates(CTX,CERTFILE,密钥文件);
    服务器= OpenConnection的(主机名,与atoi号(端口));
    SSL = SSL_new(CTX); / *创建新的SSL连接状态* /
    SSL_set_fd(SSL,服务器); / *连接套接字描述符* /
    如果(所以SSL_connect(SSL)== FAIL)/ *进行连接* /
        ERR_print_errors_fp(标准错误);
    其他
    {字符*味精=你好?        的printf(已连接与%s的加密\\ n,SSL_get_cipher(SSL));
        ShowCerts(SSL); / *得到任何证书* /
        SSL_write(SSL,味精,strlen的(MSG)); / *加密和放大器;发信息 */
        字节= SSL_read(SSL,BUF,sizeof的(BUF)); / *得到答复和放大器;解密* /
        BUF [字节] = 0;
        的printf(收到:\\%s \\的\\ n,BUF);
        SSL_free(SSL); / *释放连接状态* /
    }
    关闭(服务器); / *关闭套接字* /
    SSL_CTX_free(CTX); / *版本中* /
    返回0;
}

和服务器:

  // SSL-Server.c
#包括LT&;&errno.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&malloc.h所GT;
#包括LT&;&string.h中GT;
#包括LT&; ARPA / inet.h&GT;
#包括LT&; SYS / socket.h中&GT;
#包括LT&; SYS / types.h中&GT;
#包括LT&; netinet / in.h中&GT;
#包括LT&;&resolv.h GT;
#包括为OpenSSL / ssl.h
#包括为OpenSSL / err.h#定义FAIL -1INT OpenListener(INT端口)
{诠释SD;
    结构sockaddr_in的地址;    SD =插座(PF_INET,SOCK_STREAM,0);
    bzero(安培;地址,的sizeof(地址));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(端口);
    addr.sin_addr.s_addr = INADDR_ANY;
    如果(绑定(SD,(结构sockaddr *)及!地址,的sizeof(地址))= 0)
    {
        PERROR(不能绑定端口);
        中止();
    }
    如果(听(SD,10)!= 0)
    {
        PERROR(无法配置监听端口);
        中止();
    }
    返回SD;
}SSL_CTX * InitServerCTX(无效)
{SSL_METHOD *方法;
    SSL_CTX * CTX;    OpenSSL_add_all_algorithms(); / *负载和放大器;注册所有cryptos等。* /
    SSL_load_error_strings(); / *加载所有的错误信息* /
    方法= SSLv3_server_method(); / *创建新的服务器实例的方法* /
    CTX = SSL_CTX_new(法); / *从方法来创建新的上下文* /
    如果(CTX == NULL)
    {
        ERR_print_errors_fp(标准错误);
        中止();
    }
    返回CTX;
}无效LoadCertificates(SSL_CTX * CTX,字符* CERTFILE,字符* KeyFile时)
{
    //新线
    如果(SSL_CTX_load_verify_locations(CTX,CERTFILE,密钥文件)!= 1)
        ERR_print_errors_fp(标准错误);    如果(SSL_CTX_set_default_verify_paths(CTX)!= 1)
        ERR_print_errors_fp(标准错误);
    //结尾的新行    / *从CERTFILE设置本地证书* /
    如果(SSL_CTX_use_certificate_file(CTX,CERTFILE,SSL_FILETYPE_PEM)下; = 0)
    {
        ERR_print_errors_fp(标准错误);
        中止();
    }
    / *从KeyFile中设置专用密钥(可以是相同CERTFILE)* /
    如果(SSL_CTX_use_PrivateKey_file(CTX,密钥文件,SSL_FILETYPE_PEM)LT; = 0)
    {
        ERR_print_errors_fp(标准错误);
        中止();
    }
    / *验证私钥* /
    如果(!SSL_CTX_check_private_key(CTX))
    {
        fprintf中(标准错误,私人密钥不匹配的公证书\\ n);
        中止();
    }    //新行 - 强制客户端有一个证书
    SSL_CTX_set_verify(CTX,SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,NULL);
    SSL_CTX_set_verify_depth(CTX,4);
    //结尾的新行
}无效ShowCerts(SSL * SSL)
{X509 *证书;
    字符*线;    证书= SSL_get_peer_certificate(SSL); / *获取证书(如果可用)* /
    如果(CERT!= NULL)
    {
        的printf(服务器证书:\\ n);
        行= X509_NAME_oneline(X509_get_subject_name(证书),0,0);
        的printf(主题:%S \\ n,行);
        免费(线);
        行= X509_NAME_oneline(X509_get_issuer_name(证书),0,0);
        的printf(发行人:%S \\ n,行);
        免费(线);
        X509_free(CERT);
    }
    其他
        的printf(没有证书\\ n);
}无效的Servlet(SSL * SSL)/ *即成连接 - threadable * /
{字符BUF [1024];
    焦炭回复[1024];
    INT SD,字节;
    为const char * HTMLecho =&LT; HTML&GT;&LT;身体GT;&LT; pre&GT;%S&LT; / pre&GT;&LT; /身体GT;&LT; / HTML&GT; \\ n \\ n;    如果(SSL_accept(SSL)== FAIL)/ *做SSL协议接受* /
        ERR_print_errors_fp(标准错误);
    其他
    {
        ShowCerts(SSL); / *得到任何证书* /
        字节= SSL_read(SSL,BUF,sizeof的(BUF)); / * get请求* /
        如果(字节大于0)
        {
            BUF [字节] = 0;
            的printf(客户信息:\\%s \\的\\ n,BUF);
            sprintf的(回复,HTMLecho,BUF); / *结构答复* /
            SSL_write(SSL,回复,strlen的(回复)); / *发送应答* /
        }
        其他
            ERR_print_errors_fp(标准错误);
    }
    SD = SSL_get_fd(SSL); / *获取套接字连接* /
    SSL_free(SSL); / *释放SSL状态* /
    关闭(SD); / *关闭连接* /
}诠释的main()
{SSL_CTX * CTX;
    int服务器;
    CHAR端口编号[] =5000;        CHAR CERTFILE [] =/home/myCA/mycert.pem;
        CHAR KeyFile是[] =/home/myCA/mycert.pem;    SSL_library_init();    CTX = InitServerCTX(); / *初始化SSL * /
    LoadCertificates(CTX,CERTFILE,密钥文件); / *加载证书* /
    服务器= OpenListener(与atoi号(端口)); / *创建服务器套接字* /
    而(1)
    {结构sockaddr_in的地址;
        socklen_t的LEN = sizeof的(地址);
        SSL * SSL;        INT客户端=接受(服务器,(结构sockaddr *)及地址,和放大器; LEN); / *接受连接一样* /
        的printf(连接:%s的数:%d \\ n,INET_NTOA(addr.sin_addr),ntohs和(addr.sin_port));
        SSL = SSL_new(CTX); / *获得新的SSL状态,中* /
        SSL_set_fd(SSL,客户端); / *设置的连接插座SSL状态* /
        的servlet(SSL); / *服务连接* /
    }
    关闭(服务器); / *关闭服务器套接字* /
    SSL_CTX_free(CTX); / *版本中* /
}


解决方案

您必须修改code(服务器端):
您code:

  INT的main()
{SSL_CTX * CTX;
    int服务器;
    **字符端口编号[] =5000; **        CHAR CERTFILE [] =/home/myCA/mycert.pem;
        CHAR KeyFile是[] =/home/myCA/mycert.pem;    SSL_library_init();    **端口编号=串[1]; **

而不是你应该使用这样的:

  INT主(INT ARGC,字符** argv的)
{SSL_CTX * CTX;
    int服务器;
    //字符端口编号[] =5000; ---&GT;你可以把它作为一个参数        CHAR CERTFILE [] =/home/myCA/mycert.pem;
        CHAR KeyFile是[] =/home/myCA/mycert.pem;    SSL_library_init();    //端口编号=串[1];
    端口编号=的argv [1]; // ---&GT;你可以在这里通过端口号,而不是把它放在code

我得到这个输出(客户端):

  TOC @ UnixServer:〜$ ./ssl_client
跟AES256-SHA加密
服务器证书:
主题:/C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/emailAddress=toc@toc.com
发行人:/C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/emailAddress=toc@toc.com
收稿日期:&LT; HTML&GT;&LT;身体GT;&LT; pre&GT;您好???&LT; / pre&GT;&LT; /身体GT;&LT; / HTML&GT;

和此输出(服务器):

 连接:127.0.0.1:59066
服务器证书:
主题:/C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/emailAddress=toc@toc.com
发行人:/C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/emailAddress=toc@toc.com
客户信息:你好?

当你使用像ssldump工具(http://www.rtfm.com/ssldump/)(在UNIX盒),你可以清楚地看到发生了什么:

  TOC @ UnixServer:〜$ sudo的ssldump -i LO端口5000
新的TCP连接1:本地主机(59071)LT; - &GT;本地主机(5000)
1 0.0012(0.0012),C&GT; S握手
      的ClientHello
        3.0版
        密码套件
        未知值0xc014
        未知值0xc00a
        SSL_DHE_RSA_WITH_AES_256_CBC_SHA
        SSL_DHE_DSS_WITH_AES_256_CBC_SHA
        未知值均为0x88
        未知值87H的
        未知值0xc00f
        未知值0xc005
        SSL_RSA_WITH_AES_256_CBC_SHA
        未知值的0x84
        未知值0xc012
        未知值0xc008
        SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
        SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
        未知值0xc00d
        未知值0xc003
        SSL_RSA_WITH_3DES_EDE_CBC_SHA
        未知值0xc013
        未知值0xc009
        SSL_DHE_RSA_WITH_AES_128_CBC_SHA
        SSL_DHE_DSS_WITH_AES_128_CBC_SHA
        未知值0x9A执行
        未知值0x99
        未知值×45
        未知值0x44进行
        未知值0xc00e
        未知值0xc004
        SSL_RSA_WITH_AES_128_CBC_SHA
        未知值0x96
        未知值×41
        未知值0xc011
        未知值0xc007
        未知值0xc00c
        未知0xC002的价值
        SSL_RSA_WITH_RC4_128_SHA
        SSL_RSA_WITH_RC4_128_MD5
        SSL_DHE_RSA_WITH_DES_CBC_SHA
        SSL_DHE_DSS_WITH_DES_CBC_SHA
        SSL_RSA_WITH_DES_CBC_SHA
        SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
        SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
        SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
        SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
        SSL_RSA_EXPORT_WITH_RC4_40_MD5
        未知数0xFF
        COM pression方法
                未知值
                  空值
1 2 0.0019(0.0006),S&以及c握手
      ServerHello
        3.0版
        SESSION_ID [32] =
          13 E2 5A F0 10 93 18 56 66 8 94 54 29 AB 8B 2D
          7B C6 9C 3B 7B EA C7 54 E6 86 7D 3A 56 8C 96 14
        密码套件SSL_RSA_WITH_AES_256_CBC_SHA
        COM pressionMethod未知值
1 3 0.0019(0.0000),S&以及c握手
      证书
1 4 0.0019(0.0000),S&以及c握手
      CertificateRequest
        certificate_types rsa_sign
        certificate_types dss_sign
      ServerHelloDone
1 5 0.0155(0.0136),C&GT; S握手
      证书
1 6 0.0155(0.0000),C&GT; S握手
      ClientKeyExchange
1 7 0.0155(0.0000),C&GT; S握手
      CertificateVerify
        签名[128] =
          AC 94 31 89 64 75 20 1006米4F 00 73 4E E8日51 B7
          F1 BB 16达63 B1 8D E9 15 9B AF F8 32 D7 84 F5
          B5 7D 4F 48 1C 2B 41 58 81 D3 A8 50 40 25 90 95
          44日9D BB C4 79 5C 64 A8 A9 28 16 F4 0E 7C 17
          B2 77比照B0 8C A9 90 50 34 76 A5 A2 57 39 37 8D
          12 D8 A5 8D F4​​ 08 3A 1E 83 7E 6C 0A 75 E9 85乳油
          3D 56 F2 2E 4A 7D 71 88 29 26 99 40 43 4E F3 29
          26 BF EB是15 36 22 72 F3 D9是4A E3 C9 0B CC
1 8 0.0155(0.0000),C&GT; S ChangeCipherSpec
1 9 0.0155(0.0000),C&GT; S握手
1 10 0.0245(0.0089),S&以及c ChangeCipherSpec
1月11日0.0245(0.0000),S&以及c握手
1月12日0.0250(0.0005),C&GT; S application_data
1月13日0.0250(0.0000),C&GT; S application_data
1月14日0.0258(0.0007),S&以及c application_data
1月15日0.0258(0.0000),S&以及c application_data
1 0.0261(0.0002),C&GT; S TCP FIN
1 0.0275(0.0013),S&以及c TCP FIN

问候。

I'm trying use an SSL client/server example from:http://simplestcodings.blogspot.com.br/2010/08/secure-server-client-using-openssl-in-c.html to create a secure connection using SSLv3. I made some changes for request the certificate on server-side, the comunication works fine and is understood in both sides. Thus, my problem is that when the client connects to server, the protocol communication SSLv3 is not working, I verified using the wirkeshark and in the protocol field just shows TCP, or IPA(RSL Malformed Packet) somebody can help me? Thanks!

I've created my certificates following the tutorial https://help.ubuntu.com/community/OpenSSL.

Here is my client code:

//SSL-Client.c
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define FAIL    -1

    //Added the LoadCertificates how in the server-side makes.    
void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
 /* 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) )
    {
        fprintf(stderr, "Private key does not match the public certificate\n");
        abort();
    }
}

int OpenConnection(const char *hostname, int port)
{   int sd;
    struct hostent *host;
    struct sockaddr_in addr;

    if ( (host = gethostbyname(hostname)) == NULL )
    {
        perror(hostname);
        abort();
    }
    sd = 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 = *(long*)(host->h_addr);
    if ( connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
    {
        close(sd);
        perror(hostname);
        abort();
    }
    return sd;
}

SSL_CTX* InitCTX(void)
{   SSL_METHOD *method;
    SSL_CTX *ctx;

    OpenSSL_add_all_algorithms();  /* Load cryptos, et.al. */
    SSL_load_error_strings();   /* Bring in and register error messages */
    method = SSLv3_client_method();  /* Create new client-method instance */
    ctx = SSL_CTX_new(method);   /* Create new context */
    if ( ctx == NULL )
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    return ctx;
}

void ShowCerts(SSL* ssl)
{   X509 *cert;
    char *line;

    cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
    if ( cert != NULL )
    {
        printf("Server certificates:\n");
        line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
        printf("Subject: %s\n", line);
        free(line);       /* free the malloc'ed string */
        line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
        printf("Issuer: %s\n", line);
        free(line);       /* free the malloc'ed string */
        X509_free(cert);     /* free the malloc'ed certificate copy */
    }
    else
        printf("No certificates.\n");
}

int main()
{   SSL_CTX *ctx;
    int server;
    SSL *ssl;
    char buf[1024];
    int bytes;
    char hostname[]="127.0.0.1";
    char portnum[]="5000";
    char CertFile[] = "/home/myCA/cacert.pem";
    char KeyFile[] = "/home/myCA/private/cakey.pem";

    SSL_library_init();

    ctx = InitCTX();
    LoadCertificates(ctx, CertFile, KeyFile);
    server = OpenConnection(hostname, atoi(portnum));
    ssl = SSL_new(ctx);      /* create new SSL connection state */
    SSL_set_fd(ssl, server);    /* attach the socket descriptor */
    if ( SSL_connect(ssl) == FAIL )   /* perform the connection */
        ERR_print_errors_fp(stderr);
    else
    {   char *msg = "Hello???";

        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
        ShowCerts(ssl);        /* get any certs */
        SSL_write(ssl, msg, strlen(msg));   /* encrypt & send message */
        bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
        buf[bytes] = 0;
        printf("Received: \"%s\"\n", buf);
        SSL_free(ssl);        /* release connection state */
    }
    close(server);         /* close socket */
    SSL_CTX_free(ctx);        /* release context */
    return 0;
}

And the server:

//SSL-Server.c
#include <errno.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
#include "openssl/ssl.h"
#include "openssl/err.h"

#define FAIL    -1

int OpenListener(int port)
{   int sd;
    struct sockaddr_in addr;

    sd = 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(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
    {
        perror("can't bind port");
        abort();
    }
    if ( listen(sd, 10) != 0 )
    {
        perror("Can't configure listening port");
        abort();
    }
    return sd;
}

SSL_CTX* InitServerCTX(void)
{   SSL_METHOD *method;
    SSL_CTX *ctx;

    OpenSSL_add_all_algorithms();  /* load & register all cryptos, etc. */
    SSL_load_error_strings();   /* load all error messages */
    method = SSLv3_server_method();  /* create new server-method instance */
    ctx = SSL_CTX_new(method);   /* create new context from method */
    if ( ctx == NULL )
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    return ctx;
}

void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
    //New lines 
    if (SSL_CTX_load_verify_locations(ctx, CertFile, KeyFile) != 1)
        ERR_print_errors_fp(stderr);

    if (SSL_CTX_set_default_verify_paths(ctx) != 1)
        ERR_print_errors_fp(stderr);
    //End new lines

    /* 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))
    {
        fprintf(stderr, "Private key does not match the public certificate\n");
        abort();
    }

    //New lines - Force the client-side have a certificate
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
    SSL_CTX_set_verify_depth(ctx, 4);
    //End new lines
}

void ShowCerts(SSL* ssl)
{   X509 *cert;
    char *line;

    cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
    if ( cert != NULL )
    {
        printf("Server certificates:\n");
        line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
        printf("Subject: %s\n", line);
        free(line);
        line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
        printf("Issuer: %s\n", line);
        free(line);
        X509_free(cert);
    }
    else
        printf("No certificates.\n");
}

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
    {
        ShowCerts(ssl);        /* get any certificates */
        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()
{   SSL_CTX *ctx;
    int server;
    char portnum[]="5000";

        char CertFile[] = "/home/myCA/mycert.pem";
        char KeyFile[] = "/home/myCA/mycert.pem";

    SSL_library_init();

    ctx = InitServerCTX();        /* initialize SSL */
    LoadCertificates(ctx, CertFile, KeyFile); /* load certs */
    server = OpenListener(atoi(portnum));    /* create server socket */
    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 */
}

解决方案

you must to modify your code (server side): your code:

int main()
{   SSL_CTX *ctx;
    int server;
    **char portnum[]="5000";**

        char CertFile[] = "/home/myCA/mycert.pem";
        char KeyFile[] = "/home/myCA/mycert.pem";

    SSL_library_init();

    **portnum = strings[1];**

instead you should use this:

int main(int argc, char **argv)
{   SSL_CTX *ctx;
    int server;
    //char portnum[]="5000"; ---> You can pass it as an argument

        char CertFile[] = "/home/myCA/mycert.pem";
        char KeyFile[] = "/home/myCA/mycert.pem";

    SSL_library_init();

    //portnum = strings[1]; 
    portnum = argv[1];  // ---> You can pass port number here, instead of put it in the code

I got this output (client):

toc@UnixServer:~$ ./ssl_client 
Connected with AES256-SHA encryption
Server certificates:
Subject: /C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/emailAddress=toc@toc.com
Issuer: /C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/emailAddress=toc@toc.com
Received: "<html><body><pre>Hello???</pre></body></html>

"

And this output (server):

Connection: 127.0.0.1:59066
Server certificates:
Subject: /C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/emailAddress=toc@toc.com
Issuer: /C=FR/ST=Some-State/L=PARIS/O=TOC/OU=TOC/CN=TOC/emailAddress=toc@toc.com
Client msg: "Hello???"

When you use a tool like ssldump (http://www.rtfm.com/ssldump/) (on unix box), you can see clearly what's going on:

toc@UnixServer:~$sudo ssldump -i lo port 5000
New TCP connection #1: localhost(59071) <-> localhost(5000)
1 1  0.0012 (0.0012)  C>S  Handshake
      ClientHello
        Version 3.0 
        cipher suites
        Unknown value 0xc014
        Unknown value 0xc00a
        SSL_DHE_RSA_WITH_AES_256_CBC_SHA
        SSL_DHE_DSS_WITH_AES_256_CBC_SHA
        Unknown value 0x88
        Unknown value 0x87
        Unknown value 0xc00f
        Unknown value 0xc005
        SSL_RSA_WITH_AES_256_CBC_SHA
        Unknown value 0x84
        Unknown value 0xc012
        Unknown value 0xc008
        SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
        SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
        Unknown value 0xc00d
        Unknown value 0xc003
        SSL_RSA_WITH_3DES_EDE_CBC_SHA
        Unknown value 0xc013
        Unknown value 0xc009
        SSL_DHE_RSA_WITH_AES_128_CBC_SHA
        SSL_DHE_DSS_WITH_AES_128_CBC_SHA
        Unknown value 0x9a
        Unknown value 0x99
        Unknown value 0x45
        Unknown value 0x44
        Unknown value 0xc00e
        Unknown value 0xc004
        SSL_RSA_WITH_AES_128_CBC_SHA
        Unknown value 0x96
        Unknown value 0x41
        Unknown value 0xc011
        Unknown value 0xc007
        Unknown value 0xc00c
        Unknown value 0xc002
        SSL_RSA_WITH_RC4_128_SHA
        SSL_RSA_WITH_RC4_128_MD5
        SSL_DHE_RSA_WITH_DES_CBC_SHA
        SSL_DHE_DSS_WITH_DES_CBC_SHA
        SSL_RSA_WITH_DES_CBC_SHA
        SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
        SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
        SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
        SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
        SSL_RSA_EXPORT_WITH_RC4_40_MD5
        Unknown value 0xff
        compression methods
                unknown value
                  NULL
1 2  0.0019 (0.0006)  S>C  Handshake
      ServerHello
        Version 3.0 
        session_id[32]=
          13 e2 5a f0 10 93 18 56 c8 66 54 94 29 ab 8b 2d 
          7b c6 9c 3b 7b ea c7 54 e6 86 7d 3a 56 8c 96 14 
        cipherSuite         SSL_RSA_WITH_AES_256_CBC_SHA
        compressionMethod                 unknown value
1 3  0.0019 (0.0000)  S>C  Handshake
      Certificate
1 4  0.0019 (0.0000)  S>C  Handshake
      CertificateRequest
        certificate_types                   rsa_sign
        certificate_types                   dss_sign
      ServerHelloDone
1 5  0.0155 (0.0136)  C>S  Handshake
      Certificate
1 6  0.0155 (0.0000)  C>S  Handshake
      ClientKeyExchange
1 7  0.0155 (0.0000)  C>S  Handshake
      CertificateVerify
        Signature[128]=
          ac 94 31 89 64 75 20 5f 4f 00 73 4e e8 de 51 b7 
          f1 bb 16 da 63 b1 8d e9 15 9b af f8 32 d7 84 f5 
          b5 7d 4f 48 1c 2b 41 58 81 d3 a8 50 40 25 90 95 
          44 de 9d bb c4 79 5c 64 a8 a9 28 f4 16 7c 0e 17 
          b2 77 cf b0 8c a9 90 50 34 a5 76 a2 57 39 8d 37 
          12 d8 a5 8d f4 08 3a 1e 83 7e 6c 0a e9 75 ec 85 
          3d 56 f2 2e 4a 7d 71 88 29 26 99 40 43 4e f3 29 
          26 bf eb 15 be 36 22 72 f3 d9 be 4a e3 c9 0b cc 
1 8  0.0155 (0.0000)  C>S  ChangeCipherSpec
1 9  0.0155 (0.0000)  C>S  Handshake
1 10 0.0245 (0.0089)  S>C  ChangeCipherSpec
1 11 0.0245 (0.0000)  S>C  Handshake
1 12 0.0250 (0.0005)  C>S  application_data
1 13 0.0250 (0.0000)  C>S  application_data
1 14 0.0258 (0.0007)  S>C  application_data
1 15 0.0258 (0.0000)  S>C  application_data
1    0.0261 (0.0002)  C>S  TCP FIN
1    0.0275 (0.0013)  S>C  TCP FIN

Regards.

这篇关于客户端和服务器的通信使用SSL的C / C ++ - SSL协议不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆