c - openssl 握手失败

标签 c linux ssl

我正在尝试编写简单的 C openssl 客户端和服务器。这是客户的代码:

int main() {
    int err;

    SSL_CTX * ctx = init_ctx("client-cert.pem", "client-private.pem", "certs/cacert.pem", "clientpass");
    if (!ctx) {
        fprintf(stderr, "couldn't init ctx\n");
        exit(1);
    }

    int sock = tcp_connect("localhost", 4443);

    /* Connect the SSL socket */
    SSL * ssl = SSL_new(ctx);
    BIO * sbio = BIO_new_socket(sock,BIO_NOCLOSE);
    SSL_set_bio(ssl,sbio,sbio);

    if((err = SSL_connect(ssl)) != 1) {
        switch(SSL_get_error(ssl, err)) {
            case SSL_ERROR_NONE:
            fprintf(stderr, "error SSL_ERROR_NONE\n");
            break;
            case SSL_ERROR_ZERO_RETURN:
            fprintf(stderr, "errorSSL_ERROR_ZERO_RETURN \n");
            break;
            case SSL_ERROR_WANT_READ:
            fprintf(stderr, "error SSL_ERROR_WANT_READ\n");
            break;
            case SSL_ERROR_WANT_WRITE:
            fprintf(stderr, "error SSL_ERROR_WANT_WRITE\n");
            break;
            case SSL_ERROR_WANT_CONNECT:
            fprintf(stderr, "error SSL_ERROR_WANT_CONNECT\n");
            break;
            case SSL_ERROR_WANT_X509_LOOKUP:
            fprintf(stderr, "error SSL_ERROR_WANT_X509_LOOKUP\n");
            break;
            case SSL_ERROR_SYSCALL:
            fprintf(stderr, "error SSL_ERROR_SYSCALL\n");
            break;
            case SSL_ERROR_SSL:
            fprintf(stderr, "error SSL_ERROR_SSL\n");
            break;
            default:
            fprintf(stderr, "error f****** s***!!!\n");
            break;
        }
        fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
        ERR_print_errors_fp(stderr);
        //exit(1);
    }

    check_cert(ssl, "host.com");
    fprintf(stderr, "%d bytes sent\n", send_request(ssl, "come with me, we'll go dreaming"));   

    /* shutdown ssl connection */
    err = SSL_shutdown(ssl);
    if (err < 0) {
        ERR_print_errors_fp(stderr);
        exit(1);
    }

    close(sock);
    SSL_free(ssl);
    SSL_CTX_free(ctx);

    return 0;
}

ssize_t send_request(SSL * ssl, const char * req) {
    fprintf(stderr, "sending request...\n");
    ssize_t size = SSL_write(ssl, req, strlen(req));

    if (size < 0) {
        ERR_print_errors_fp(stderr);
    }

    return size;
}

SSL_get_error(ssl, err) 返回 SSL_ERROR_SYSCALL 并且 send_request 返回以下错误:5269:error:140790E5:SSL 例程: SSL23_WRITE:ssl 握手失败:s23_lib.c:188:。使用密码保护私钥,我正在设置 pem_password_cb 回调:

SSL_CTX_set_default_passwd_cb(ctx, passwd_func);
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)password);

.使用 v23 方法...我不知道这次握手失败的原因...

我试过这样调试:openssl s_client -connect localhost:4443 -cert sberbank-cert.pem -key sberbank-private.pem -verify 1 -CAfile cacert.pem -prexit -msg,我有以下结果:

milo@milonote:~/src/tests/ssl$ openssl s_client -connect localhost:4443 -cert sberbank-cert.pem -key sberbank-private.pem -verify 1 -CAfile cacert.pem -prexit  -msg
verify depth is 1
CONNECTED(00000003)
>>> TLS 1.0 Handshake [length 005a], ClientHello
    01 00 00 56 03 01 4d ed fc 5e a7 d7 56 6a 70 40
    0c a6 19 d0 06 23 08 28 65 07 53 46 d1 87 c0 c2
    a2 27 d8 5b ad ac 00 00 28 00 39 00 38 00 35 00
    16 00 13 00 0a 00 33 00 32 00 2f 00 05 00 04 00
    15 00 12 00 09 00 14 00 11 00 08 00 06 00 03 00
    ff 02 01 00 00 04 00 23 00 00
5825:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:188:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 95 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

这里是tcp_connect的源码。我确信它不会失败,因为它返回 fd(不是 -1):

int tcp_connect(const char *host, int port) {
    struct hostent *hp;
    struct sockaddr_in addr;
    int sock;

    if(!(hp=gethostbyname(host)))
        return -1;

    memset(&addr,0,sizeof(addr));
    addr.sin_addr=*(struct in_addr*)
    hp->h_addr_list[0];
    addr.sin_family=AF_INET;
    addr.sin_port=htons(port);

    if((sock=socket(AF_INET,SOCK_STREAM, IPPROTO_TCP))<0)
       return -1;

    if(connect(sock,(struct sockaddr *)&addr, sizeof(addr))<0)
        return -1;

    return sock;
}

最佳答案

我已经解决了我的问题!它不是客户端,而是服务器端!服务器关闭 tcp 连接,同时收到 SSL_WANT_READ 错误而不是重复 SSL_accept。感谢参与!

关于c - openssl 握手失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6263060/

相关文章:

c - 在英特尔 x64 汇编中执行函数的最快(CPU 方式)方式?

linux - 文本文件内容自动化

c - 在 C/C++ 中执行 linux 程序并通过 stdin/stdout 与其通信的最简单方法

objective-c - 适用于 iPhone/iPad 的线性回归库或代码片段?

c - 如何将 y[7990272] 值数组写入文本文件,每行文本有 2448 个值

c - WebSphere 非托管队列 MQSUB 返回 2019 错误

html - 网站 "inactive"时的 Google Analytics

php - 在 OSX 上读取 p12 证书时写入权限错误 (OSStatus -61)

r - 无法在 Windows 上将 PostgreSQL(通过 SSL)与 RPostgresql 连接

使用 Openssl 和 Client Auth 连接到服务器的 Java 客户端