BIO_do_connect导致段错误

时间:2019-11-03 19:45:43

标签: c openssl

摘要

当我的代码调用BIO_do_connect时,它会跳回到调用它的函数的开头,然后进行段错误。

尝试过的

调试器,Valgrind,更改代码

// compiled with:
// gcc -g -O0 -Wall -Wextra -o sslex sslex_main.c -fstack-protector -lssl -lcrypto
#include <stdio.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>

// BIO handles communication including files and sockets.
static BIO* g_bio = NULL;
// holds SSL connection information
static SSL_CTX* g_sslContext = NULL;
char* g_trustedStore = "certs/trusted.pem";

void initialize() {
    SSL_load_error_strings();
    ERR_load_BIO_strings();
    OpenSSL_add_all_algorithms();
}

int connect(char* hostnamePort) {
    SSL* sslp = NULL;
    BIO* out = NULL;
    printf("Connect called\n");
    printf("Connecting... to %s\n", hostnamePort);

    g_sslContext = SSL_CTX_new(TLS_client_method());

    // load trusted certificate store
    if (! SSL_CTX_load_verify_locations(g_sslContext, g_trustedStore, NULL)) {
        fprintf(stderr, "Failure loading certificats from trusted store %s!\n", g_trustedStore);
        fprintf(stderr, "Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        return -1;
    }

    g_bio = BIO_new_ssl_connect(g_sslContext);
    if (g_bio == NULL) {
        fprintf(stderr, "Error cannot get BSD Input/Output\n");
        return -1;
    }
    // retrieve ssl pointer of the BIO
    BIO_get_ssl(g_bio, &sslp);
    if (sslp == NULL) {
        fprintf(stderr, "Could not locate SSL pointer\n");
        fprintf(stderr, "Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        return -1;
    }

    // if server wants a new handshake, handle that in the background
    SSL_set_mode(sslp, SSL_MODE_AUTO_RETRY);

    // attempt to connect
    BIO_set_conn_hostname(g_bio, hostnamePort);

    out = BIO_new_fp(stdout, BIO_NOCLOSE);
    printf("Connecting to: %s\n", BIO_get_conn_hostname(g_bio));

    // THIS LINE CAUSES STACK SMASH
    if (BIO_do_connect(g_bio) <= 0) { // BUGGY LINE
        fprintf(stderr, "Error cannot connect to %s\n", hostnamePort);
        fprintf(stderr, "Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        BIO_free_all(g_bio);
        SSL_CTX_free(g_sslContext);
        return -1;
    }
    return -1;
}

void close_connection() {
    BIO_free_all(g_bio);
    SSL_CTX_free(g_sslContext);
}

int main(int argc, char* argv[]) {
    char* hostnamePort = argv[1];
    initialize();
    if (connect(hostnamePort) != 0)
        return 0;
    printf("Done connecting. doing operation\n");
    close_connection();
    return 0;
}

预期结果:

  • “被叫连接”应该只显示一次。
  • 程序不应出现分段错误。

实际输出:

./sslex 192.168.11.141
Connect called
Connecting... to 192.168.11.141
Connecting to: 192.168.11.141
Connect called
Segmentation fault (core dumped)

调试器输出和回溯:

Starting program: sslex 192.168.11.141
warning: Probes-based dynamic linker interface failed.
Reverting to original interface.

Connect called
Connecting... to 192.168.11.141
Connecting to: 192.168.11.141

Breakpoint 3, connect (hostnamePort=0x7fffffffe9db "192.168.11.141") at sslex_main.c:57
57      if (BIO_do_connect(g_bio) <= 0) { // BUGGY LINE
(gdb) bt
#0  connect (hostnamePort=0x7fffffffe9db "192.168.11.141") at sslex_main.c:57
#1  0x000055555555503a in main (argc=2, argv=0x7fffffffe698) at sslex_main.c:75
(gdb) s
Connect called

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff733d646 in ?? ()
(gdb) bt
#0  0x00007ffff733d646 in ?? ()
#1  0x00007ffff72e94d3 in ?? ()
#2  0x0000000000000000 in ?? ()

1 个答案:

答案 0 :(得分:0)

您的函数connect()隐藏了标准的Neworking库函数,该函数的名称与OpenSSL建立实际的TCP连接所调用的名称相同,但是它并没有获得库的名称,而是在调用您的库。

重命名您的函数(例如,重命名为do_connect()),以免与库中的函数冲突。