Warm tip: This article is reproduced from stackoverflow.com, please click
c++ linux openssl

Got error undefined reference to `SSL_new' when compile code using openssl

发布于 2020-07-28 03:43:40

I'm writing a ssl client code using TLSv1.2 to connect a server, but always getting errors that cannot find openssl APIs, searched internet but didn't find much info similar to my situation.

My code is as below:

#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>
#include <openssl/bio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#define FAIL    -1

SSL_CTX* init_ssl_ctx();
static int verify_cb(int ok, X509_STORE_CTX *store);

int main()
{
    int sockfd;
    struct sockaddr_in servaddr;
    int ret;
    struct sockaddr sockaddr;
    int port = 8443;
    //string ns_addr = "55.0.0.5";

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8443);
    inet_pton(AF_INET, "55.0.0.5", &servaddr.sin_addr);

    sockfd = socket(PF_INET, SOCK_STREAM, 1); //tcp
    if (sockfd < 0)
    {
        printf("sockfd fail with %d, %s\n", sockfd, strerror(errno));
        return 0;
    }

    int reuse_opt = 1;
    ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_opt, sizeof(reuse_opt));
    if (ret < 0)
    {
        printf("setsocketopt fail with %d, %s\n", ret, strerror(errno));
        close(sockfd);
        return 0;
    }

    int flags = fcntl(sockfd, F_GETFL, 0);
    if (flags < 0)
    {
        printf("fcntl fail with %d, %s\n", flags, strerror(errno));
        close(sockfd);
        return 0;
    }

    ret = bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    if (ret < 0)
    {
        printf("bind fail with %d, %s\n", ret, strerror(errno));
        close(sockfd);
        return 0;
    }

    ret = connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
    if (ret < 0)
    {
        printf("bind fail with %d, %s\n", ret, strerror(errno));
        close(sockfd);
        return 0;
    }

    SSL_CTX* ssl_ctx = init_ssl_ctx();
    if (ssl_ctx == NULL)
    {
        close(sockfd);
        return 0;
    }

    SSL *p_ssl = SSL_new(ssl_ctx);
    if (p_ssl == NULL)
    {
        printf("SSL_new fail\n");
        close(sockfd);
        return 0;
    }

    BIO *p_bio = BIO_new_socket(sockfd, BIO_NOCLOSE);
    if (p_bio == NULL)
    {
        printf("BIO_new_socket fail\n");
        close(sockfd);
        SSL_free(p_ssl);
        return 0;
    }

    SSL_set_bio(p_ssl, p_bio, p_bio);

    SSL_clear_options(p_ssl, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3);

    long vermasks = SSL_OP_NO_SSLv2;
    vermasks |= SSL_OP_NO_TLSv1_3;
    SSL_set_options(p_ssl, SSL_OP_ALL | vermasks);
    SSL_set_verify(p_ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, verify_cb);
    SSL_set_verify_depth(p_ssl, 4);

    ret = SSL_connect(p_ssl);
    int err = SSL_get_error(p_ssl, ret);

    printf("SSL_connect err = %d\n", err);

    return 0;
}

static int verify_cb(int ok, X509_STORE_CTX *store)
{
    printf("SSL_set_verify fail\n");
    return ok;
}

SSL_CTX* init_ssl_ctx()
{
    SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method());
    if (ssl_ctx == NULL)
    {
        printf("SSL_CTX_new fail\n");
        return NULL;
    }

    long vermasks = SSL_OP_NO_SSLv2;
    vermasks |= SSL_OP_NO_TLSv1_3;
    SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | vermasks);

    //Two standardized session resumption mechanisms that require two different data sharing designs:
    //Session IDs RFC 5246, and Session Tickets RFC 5077. Both will be disabled by calling openssl APIs as below.
    //For details, please check SBC-23917
    SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_OFF);
    SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
    SSL_CTX_set_num_tickets(ssl_ctx, 0);

    SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);

    //set ALPN as HTTP/2
    unsigned char protos[] = {
        2, 'h', '2'
    };
    unsigned int protos_len = sizeof(protos);

    if (SSL_CTX_set_alpn_protos(ssl_ctx, protos, protos_len) != 0)
    {
        printf("SSL_CTX_set_alpn_protos fail\n");
        SSL_CTX_free(ssl_ctx);
        return NULL;
    }

    if (SSL_CTX_set_cipher_list(ssl_ctx, "ALL:!DH:!EXP:!RC4:@STRENGTH") != 1)
    {
        printf("SSL_CTX_set_cipher_list fail\n");
        SSL_CTX_free(ssl_ctx);
        return NULL;
    }

    char* CAfile = "CaListApple.pem";
    if (SSL_CTX_load_verify_locations(ssl_ctx, CAfile, NULL) != 1)
    {
        printf("SSL_CTX_load_verify_locations fail\n");
        SSL_CTX_free(ssl_ctx);
        return NULL;
    }

    char *client_cert_file = "CertificateAppleV4D.pem";
    if (SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert_file) != 1)
    {
        printf("SSL_CTX_use_certificate_chain_file fail\n");
        SSL_CTX_free(ssl_ctx);
        return NULL;
    }

    if (SSL_CTX_use_PrivateKey_file(ssl_ctx, client_cert_file, SSL_FILETYPE_PEM) != 1)
    {
        printf("SSL_CTX_use_PrivateKey_file fail\n");
        SSL_CTX_free(ssl_ctx);
        return NULL;
    }

    if (SSL_CTX_check_private_key(ssl_ctx) != 1)
    {
        printf("SSL_CTX_check_private_key fail\n");
        SSL_CTX_free(ssl_ctx);
        return NULL;
    }

    return ssl_ctx;
}

OS is ubuntu 20.04 LTS:

Description:    Ubuntu 20.04 LTS

openssl version 1.1.1f:

OpenSSL 1.1.1f  31 Mar 2020
built on: Mon Apr 20 11:53:50 2020 UTC
platform: debian-amd64
options:  bn(64,64) rc4(8x,int) des(int) blowfish(ptr)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -fdebug-prefix-map=/build/openssl-P_ODHM/openssl-1.1.1f=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_TLS_SECURITY_LEVEL=2 -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
OPENSSLDIR: "/usr/lib/ssl"
ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1"
Seeding source: os-specific

$ dpkg -l | grep ssl
ii  libflac8:amd64                 1.3.3-1build1                     amd64        Free Lossless Audio Codec - runtime C library
ii  libssl-dev:amd64               1.1.1f-1ubuntu2                   amd64        Secure Sockets Layer toolkit - development files
ii  libssl1.1:amd64                1.1.1f-1ubuntu2                   amd64        Secure Sockets Layer toolkit - shared libraries
ii  libxmlsec1-openssl:amd64       1.2.28-2                          amd64        Openssl engine for the XML security library
ii  libzstd1:amd64                 1.4.4+dfsg-3                      amd64        fast lossless compression algorithm
ii  openssl                        1.1.1f-1ubuntu2                   amd64        Secure Sockets Layer toolkit - cryptographic utility
ii  python3-openssl                19.0.0-1build1                    all          Python 3 wrapper around the OpenSSL library

Tried several build commands:

g++ -lssl -lcrypto -o ssl_client ssl_client.cpp
g++ -lrt -lssl -lcrypto -o ssl_client ssl_client.cpp
g++ -L/lib/x86_64-linux-gnu -lrt -lssl -lcrypto -o ssl_client ssl_client.cpp
g++ -L/usr/lib/ssl -lrt -lssl -lcrypto -o ssl_client ssl_client.cpp
g++ -L/usr/lib/x86_64-linux-gnu -lrt -lssl -lcrypto -o ssl_client ssl_client.cpp

Always got error:

/usr/bin/ld: /tmp/ccA1Fl3A.o: in function `main':
ssl_client.cpp:(.text+0x25c): undefined reference to `SSL_new'
/usr/bin/ld: ssl_client.cpp:(.text+0x296): undefined reference to `BIO_new_socket'
/usr/bin/ld: ssl_client.cpp:(.text+0x2c3): undefined reference to `SSL_free'
/usr/bin/ld: ssl_client.cpp:(.text+0x2e4): undefined reference to `SSL_set_bio'
/usr/bin/ld: ssl_client.cpp:(.text+0x2f5): undefined reference to `SSL_clear_options'
/usr/bin/ld: ssl_client.cpp:(.text+0x320): undefined reference to `SSL_set_options'
/usr/bin/ld: ssl_client.cpp:(.text+0x338): undefined reference to `SSL_set_verify'
/usr/bin/ld: ssl_client.cpp:(.text+0x349): undefined reference to `SSL_set_verify_depth'
/usr/bin/ld: ssl_client.cpp:(.text+0x355): undefined reference to `SSL_connect'
/usr/bin/ld: ssl_client.cpp:(.text+0x369): undefined reference to `SSL_get_error'
/usr/bin/ld: /tmp/ccA1Fl3A.o: in function `init_ssl_ctx()':
ssl_client.cpp:(.text+0x3e1): undefined reference to `TLS_client_method'
/usr/bin/ld: ssl_client.cpp:(.text+0x3e9): undefined reference to `SSL_CTX_new'
/usr/bin/ld: ssl_client.cpp:(.text+0x435): undefined reference to `SSL_CTX_set_options'
/usr/bin/ld: ssl_client.cpp:(.text+0x450): undefined reference to `SSL_CTX_ctrl'
/usr/bin/ld: ssl_client.cpp:(.text+0x461): undefined reference to `SSL_CTX_set_options'
/usr/bin/ld: ssl_client.cpp:(.text+0x472): undefined reference to `SSL_CTX_set_num_tickets'
/usr/bin/ld: ssl_client.cpp:(.text+0x48d): undefined reference to `SSL_CTX_ctrl'
/usr/bin/ld: ssl_client.cpp:(.text+0x4b4): undefined reference to `SSL_CTX_set_alpn_protos'
/usr/bin/ld: ssl_client.cpp:(.text+0x4d5): undefined reference to `SSL_CTX_free'
/usr/bin/ld: ssl_client.cpp:(.text+0x4f2): undefined reference to `SSL_CTX_set_cipher_list'
/usr/bin/ld: ssl_client.cpp:(.text+0x514): undefined reference to `SSL_CTX_free'
/usr/bin/ld: ssl_client.cpp:(.text+0x541): undefined reference to `SSL_CTX_load_verify_locations'
/usr/bin/ld: ssl_client.cpp:(.text+0x563): undefined reference to `SSL_CTX_free'
/usr/bin/ld: ssl_client.cpp:(.text+0x58b): undefined reference to `SSL_CTX_use_certificate_chain_file'
/usr/bin/ld: ssl_client.cpp:(.text+0x5ad): undefined reference to `SSL_CTX_free'
/usr/bin/ld: ssl_client.cpp:(.text+0x5cc): undefined reference to `SSL_CTX_use_PrivateKey_file'
/usr/bin/ld: ssl_client.cpp:(.text+0x5ee): undefined reference to `SSL_CTX_free'
/usr/bin/ld: ssl_client.cpp:(.text+0x601): undefined reference to `SSL_CTX_check_private_key'
/usr/bin/ld: ssl_client.cpp:(.text+0x623): undefined reference to `SSL_CTX_free'
collect2: error: ld returned 1 exit status

Not sure what I missed? Appreciate your suggestions.

Questioner
HarryH
Viewed
4
S.M. 2020-05-07 11:37

-lssl -lcrypto must be last in the command

g++ -o ssl_client ssl_client.cpp -lssl -lcrypto