openssl SSL客户端例子

原创
2022/06/12 12:09
阅读数 464

以百度为目标服务端,获取证书链

openssl s_client -showcerts -connect www.baidu.com:443 </dev/null

CONNECTED(00000003)
depth=2 C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
verify return:1
depth=1 C = BE, O = GlobalSign nv-sa, CN = GlobalSign Organization Validation CA - SHA256 - G2
verify return:1
depth=0 C = CN, ST = beijing, L = beijing, OU = service operation department, O = "Beijing Baidu Netcom Science Technology Co., Ltd", CN = baidu.com
verify return:1

可以看到根证书是GlobalSign Root CA。

从本地证书库里获取CA根公钥证书,我的系统是centos 8 stream,本地证书库是/etc/ssl/certs/ca-bundle.crt

-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----

代码

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <openssl/ssl.h>

#define LOG(fmt, args...) printf("[%s:%d] " fmt "\n", __FILE__, __LINE__, ##args)

int getfd(const char *hostname)
{
    struct hostent *ent = gethostbyname(hostname);
    if (ent == NULL) {
        LOG("host ent is NULL");
        return -1;
    }
    char tmp[128];
    for (char **p = ent->h_addr_list; *p != NULL; p++) {
        LOG("add is %s", inet_ntop(ent->h_addrtype, *p, tmp, sizeof tmp));
    }
    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(443);
    addr.sin_addr = *((struct in_addr *)ent->h_addr_list[0]);
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        LOG("invalid fd %d", fd);
        return -1;
    }
    if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
        LOG("connect failed");
        return -1;
    }
    return fd;
}

int main()
{
    int ret;
    SSL_CTX *ctx = SSL_CTX_new(TLS_client_method());
    if (ctx == NULL) {
        LOG("ssl ctx is NULL");
        return -1;
    }
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); // 设置需要验证服务端证书
    if (SSL_CTX_load_verify_locations(ctx, "ca.pem", NULL) != 1) { // 加载www.baidu.com的ca文件
        LOG("ssl ctx load ca failed");
        return -1;
    }
    SSL *ssl = SSL_new(ctx);
    if (ssl == NULL) {
        LOG("ssl is NULL");
        return -1;
    }
    int fd = getfd("www.baidu.com");
    if (fd < 0) {
        LOG("invalid fd %d", fd);
        return -1;
    }
    if (SSL_set_fd(ssl, fd) != 1) {
        LOG("ssl set fd failed");
        return -1;
    }
    ret = SSL_connect(ssl);
    if (ret != 1) {
        LOG("ssl connect failed, %d", SSL_get_error(ssl, ret));
        return -1;
    }
    LOG("ssl connect success");
    const char *req = "GET / HTTP/1.1\r\nHost: www.baidu.com\r\n\r\n";
    ret = SSL_write(ssl, req, strlen(req));
    LOG("ssl write %d", ret);
    char out[64];
    ret = SSL_read(ssl, out, sizeof(out));
    LOG("ssl read %d", ret);
    out[ret] = 0;
    LOG("result: %s", out);
    close(fd);
    SSL_free(ssl);
    SSL_CTX_free(ctx);
    return 0;
}

编译

gcc -Wall -o a main.c -lssl

运行结果

[main.c:21] add is 14.215.177.38
[main.c:21] add is 14.215.177.39
[main.c:72] ssl connect success
[main.c:75] ssl write 39
[main.c:78] ssl read 64
[main.c:80] result: HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: no-cache

解析证书库里的所有证书

openssl crl2pkcs7 -nocrl -certfile /etc/ssl/certs/ca-bundle.crt| openssl pkcs7 -print_certs -text -noout

 

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部