SSL_add0_chain_cert和SSL_add1_chain_cert之间的用法区别?

Sup*_*iyi 5 ssl lua openssl nginx ssl-certificate

在OpenSSL 文档中,它说:

所有这些功能都以宏的形式实现.包含1的那些增加了所提供的证书或链的引用计数,因此必须在操作之后的某个时刻释放它.包含0的那些不会增加引用计数,并且在操作之后不得释放提供的证书或链.

但是,当我试图查看一些案例的例子时,我应该在困惑的地方使用哪一个.

第一个OpenSSL:

它使用SSL_add0_chain_cert自身的SSL_CTX_use_certificate_chain_file功能ssl_rsa.c.是来源:

static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file) {
    if (ctx)
        ret = SSL_CTX_use_certificate(ctx, x);
    else
        ret = SSL_use_certificate(ssl, x);
    ......
    while ((ca = PEM_read_bio_X509(in, NULL, passwd_callback,
                                   passwd_callback_userdata))
           != NULL) {
        if (ctx)
            r = SSL_CTX_add0_chain_cert(ctx, ca);
        else
            r = SSL_add0_chain_cert(ssl, ca);
    ......
}
Run Code Online (Sandbox Code Playgroud)

我看到的第二种用法是OpenResty Lua:

SSL_add0_chain_cert以一种方式设置certificate(ngx_http_lua_ffi_ssl_set_der_certificate),见这里:

int ngx_http_lua_ffi_ssl_set_der_certificate(ngx_http_request_t *r,
const char *data, size_t len, char **err) {
    ......
    if (SSL_use_certificate(ssl_conn, x509) == 0) {
        *err = "SSL_use_certificate() failed";
        goto failed;
    }
    ......
    while (!BIO_eof(bio)) {

        x509 = d2i_X509_bio(bio, NULL);
        if (x509 == NULL) {
            *err = "d2i_X509_bio() failed";
            goto failed;
        }

        if (SSL_add0_chain_cert(ssl_conn, x509) == 0) {
            *err = "SSL_add0_chain_cert() failed";
            goto failed;
        }
    }

    BIO_free(bio);

    *err = NULL;
    return NGX_OK;
failed:
    .......
}
Run Code Online (Sandbox Code Playgroud)

然而SSL_add1_chain_cert以另一种方式使用(ngx_http_lua_ffi_set_cert),请看这里:

int ngx_http_lua_ffi_set_cert(ngx_http_request_t *r,
    void *cdata, char **err) {
    ......
    if (SSL_use_certificate(ssl_conn, x509) == 0) {
        *err = "SSL_use_certificate() failed";
        goto failed;
    }

    x509 = NULL;

    /* read rest of the chain */

    for (i = 1; i < sk_X509_num(chain); i++) {

        x509 = sk_X509_value(chain, i);
        if (x509 == NULL) {
            *err = "sk_X509_value() failed";
            goto failed;
        }

        if (SSL_add1_chain_cert(ssl_conn, x509) == 0) {
            *err = "SSL_add1_chain_cert() failed";
            goto failed;
        }
    }

    *err = NULL;
    return NGX_OK; /* No free of x509 here */

failed:
......
}
Run Code Online (Sandbox Code Playgroud)

然而,在Lua中调用这两个时,我看不出有什么变化的明显区别,并且看起来不像证书X509,当设置成功时,在任何一种情况下都会被释放.根据我对OpenSSL文档的理解,我应该期望X509_free(x509)在调用SSL_add1_chain_certx509 后调用某个地方.这是正确的理解吗?

最后,在Openssl的 实现ssl_cert_add1_chain_cert(从什么归结SSL_add1_chain_cert宏)确实显示它只是一个包装ssl_cert_add0_chain_cert参考计数递增的证书,但应如何在呼叫过程中反映出来?

int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
{
    if (!ssl_cert_add0_chain_cert(s, ctx, x))
        return 0;
    X509_up_ref(x);
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

现在,Nginx只处理另一个功能SSL_CTX_add_extra_chain_cert,这会使这种选择的负担落后,因为它不处理每个SSL连接的切换证书.在我的情况下,我需要使用此功能修补Nginx,为每个连接切换证书(但不使用Lua).

所以我不确定我应该使用哪一个,SSL_add0_chain_cert或者SSL_add1_chain_cert?那里的解放实践是什么?