Jim Q
Jim Q

Reputation: 3

BIO_do_connect causes segfault

Summary

When my code calls BIO_do_connect it jumps back to the start of the function that called it and then segfaults.

What Tried

Debugger, Valgrind, changing code

// 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;
}

Expected Result:

Actual Output:

./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)

Debugger Output and Backtrace:

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 ?? ()

Upvotes: 0

Views: 259

Answers (1)

Steve Friedl
Steve Friedl

Reputation: 4247

Your function connect() is hiding the standard neworking library function of the same name that OpenSSL is calling to make the actual TCP connection, but instead of getting the library one, it's calling yours.

Rename your function (say, to do_connect()) so it won't clash with the one from the library.

Upvotes: 1

Related Questions