2 rayyt rayyt 于 2018.02.05 11:31 提问

openssl:用ssl_get_peer_certification函数得到证书为空 5C

我用阻塞模式的socket做ssl连接就能得到证书,但是用非阻塞的socket得到证书就为空。
下面是代码:
void ShowCerts(SSL * ssl) //show the certification
{
X509 * cert;
char * line;
cert = SSL_get_peer_certificate(ssl);
if (cert != NULL)
{
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("certification: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("publisher: %s\n", line);
free(line);
X509_free(cert);
}
else
{
printf("no certification!\n");
}
}

int main(int argc, char * *argv)
{
if (argc != 3)
{
printf("parameter error1!\n");
exit(0);
}
int sockfd, len;
struct sockaddr_in dest;
//initialize ssl
SSL_CTX * ctx;
SSL * ssl;
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv23_client_method());

if (ctx == NULL) 
{
    ERR_print_errors_fp(stdout);
    exit(1);
}
//create socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
{
    perror("Socket");
    exit(errno);
}
printf("socket created\n");

bzero( &dest, sizeof(dest));
dest.sin_family = AF_INET;

dest.sin_port = htons(atoi(argv[2]));

if (inet_aton(argv[1], (struct in_addr * ) &dest.sin_addr.s_addr) == 0) 
{
    perror(argv[1]);
    exit(errno);
}
printf("address created\n");
    int error=-1;
    len = sizeof(int);
    struct timeval tm;
    fd_set set;
    // set non-block socket
    unsigned long ul = 1;
    ioctl(sockfd,FIONBIO,&ul);
    // create tcp connection
    bool ret =false;
    if (connect(sockfd, (struct sockaddr * ) &dest, sizeof(dest)) == -1) 
    {
        tm.tv_sec =TIMEOUT;
        tm.tv_usec = 0;
        FD_ZERO(&set);
        FD_SET(sockfd,&set);
        if(select(sockfd+1,NULL,&set,NULL,&tm)>0) 
        {
            getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,(socklen_t *)&len);
            if(error==0)
            {
                ret = true;     //connect successfully
            }
            else
            {
                ret = false;    //connect timeout
            }
        }
        else
        {
            ret = false;
        }
    }
    else
    {
        ret = true;
    }
    if(!ret)
    {
        close(sockfd);
        SSL_CTX_free(ctx);
        printf("tcp connection timeout!\n");
        exit(0);

    }

    printf("server connected\n");
    ssl = SSL_new(ctx);
    //bind socket and ssl
    SSL_set_fd(ssl, sockfd);
    int flag;
    int result;
    int ssl_conn_ret=0;

    if(1!=ssl_conn_ret)
    {   
        //non block ssl connection
        ssl_conn_ret=SSL_connect(ssl);
        fd_set fds;
        FD_ZERO(&fds);
        FD_SET(sockfd, &fds);

        int ssl_get_error_value = SSL_get_error(ssl,ssl_conn_ret);
        printf("ssl_get_error_value is %d\n",ssl_get_error_value);
        switch (ssl_get_error_value)
        {
            case SSL_ERROR_WANT_READ:
                result=select(sockfd + 1, &fds, NULL, NULL, &tm);
                if(0==result)
                {
                    flag=0;
                }
                else if(-1==result)
                {
                    flag=0;
                }
                else
                {
                    flag=1;  //connect successfully
                }

                break;
            case SSL_ERROR_WANT_WRITE:
                result=select(sockfd + 1, NULL, &fds, NULL, &tm);
                if(0==result)
                {
                    flag=0;
                }
                else if(-1==result)
                {
                    flag=0; //conncet failed
                }
                else
                {
                    flag=1;
                }   
                break;
            default:
                flag=0;
                break;
        }
    }
    if(0==flag)
    {
        printf("connection error!\n");

    }
    if(1==ssl_conn_ret||1==flag)
    {
        ShowCerts(ssl);
    }


    ul = 0;
    ioctl(sockfd, FIONBIO, &ul);

    SSL_shutdown(ssl);
    SSL_free(ssl);
    close(sockfd);
    SSL_CTX_free(ctx);
return 0;

}

3个回答

oyljerry
oyljerry   Ds   Rxr 2018.02.05 13:56

非阻塞的时候,是不是连接等还没有建立好。获取的时间点有问题

InDepth
InDepth   2018.02.05 16:57

非阻塞情况下,SSL_do_handshake, 别用SSL_connect, 返回1表示握手成功,这时用SSL_get_peer_certificate就没问题了

InDepth
InDepth   2018.02.05 17:00

需要多次WHILE循环SSL_do_handshake的结果,直到返回1或小于0的值

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!