ssl - 我如何知道在 SSL 上下文中加载的 CA 主题名称列表

标签 ssl openssl

我想从加载的 SSL_CTX() 中取回 ca 证书名称列表 openSSL 是否提供任何 API 来取回名称?

最佳答案

I want to get back the ca certificate name list from loaded SSL_CTX() Is there any APIs provided by openSSL to get back name?

有点。证书有颁发者和主题。当您说出“CA 名称”时,您是在询问颁发者。它通常在 SSL* 上;而不是 CTX*

您将执行如下操作。您将必须弄清楚如何获得要打印的证书。下面向您展示了如何使用对等方的证书来完成此操作。

/* Drops out of a handshake */
SSL* ssl = ...;

/* Get the certificate from the session object */
X509* cert = SSL_get_peer_certificate(ssl);

/* Get the issuer name */
X509_NAME* iname = cert ? X509_get_issuer_name(cert) : NULL;

/* Get the subject name */
X509_NAME* sname = cert ? X509_get_subject_name(cert) : NULL;

if (iname)
    print_cn_name("Issuer name", iname);

if (sname)
    print_cn_name("Subject name", sname);

X509_free(cert);

然后:

/* This prints the Common Name (CN), which is the "friendly" */
/*   name displayed to users in many tools                   */
void print_cn_name(const char* label, X509_NAME* const name)
{
    int idx = -1, success = 0;
    unsigned char *utf8 = NULL;

    do
    {
        if(!name) break; /* failed */

        idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
        if(!(idx > -1))  break; /* failed */

        X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx);
        if(!entry) break; /* failed */

        ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
        if(!data) break; /* failed */

        int length = ASN1_STRING_to_UTF8(&utf8, data);
        if(!utf8 || !(length > 0))  break; /* failed */

        fprintf(stdout, "%s: %s\n", label, utf8);
        success = 1;

    } while (0);

    if(utf8)
        OPENSSL_free(utf8);

    if(!success)
        fprintf(stdout, "  %s: <not available>\n", label);
}

如果您想要Subject Alternate Names (SAN) 作为服务器证书,那么您可以执行如下操作:

void print_san_name(const char* label, X509* const cert)
{
    int success = 0;
    GENERAL_NAMES* names = NULL;
    unsigned char* utf8 = NULL;

    do
    {
        if(!cert) break; /* failed */

        names = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0 );
        if(!names) break;

        int i = 0, count = sk_GENERAL_NAME_num(names);
        if(!count) break; /* failed */

        for( i = 0; i < count; ++i )
        {
            GENERAL_NAME* entry = sk_GENERAL_NAME_value(names, i);
            if(!entry) continue;

            if(GEN_DNS == entry->type)
            {
                int len1 = 0, len2 = -1;

                len1 = ASN1_STRING_to_UTF8(&utf8, entry->d.dNSName);
                if(utf8) {
                    len2 = (int)strlen((const char*)utf8);
                }

                if(len1 != len2) {
                    fprintf(stderr, "  Strlen and ASN1_STRING size do not match (embedded null?): %d vs %d\n", len2, len1);
                }

                /* If there's a problem with string lengths, then     */
                /* we skip the candidate and move on to the next.     */
                /* Another policy would be to fails since it probably */
                /* indicates the client is under attack.              */
                if(utf8 && len1 && len2 && (len1 == len2)) {
                    fprintf(stdout, "  %s: %s\n", label, utf8);
                    success = 1;
                }

                if(utf8) {
                    OPENSSL_free(utf8), utf8 = NULL;
                }
            }
            else
            {
                fprintf(stderr, "  Unknown GENERAL_NAME type: %d\n", entry->type);
            }
        }

    } while (0);

    if(names)
        GENERAL_NAMES_free(names);

    if(utf8)
        OPENSSL_free(utf8);

    if(!success)
        fprintf(stdout, "  %s: <not available>\n", label);    
}

以上摘自 OpenSSL 的 TLS client他们的维基上的例子。它还向您展示了如何在验证回调中打印链。

关于ssl - 我如何知道在 SSL 上下文中加载的 CA 主题名称列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38368710/

相关文章:

ruby-on-rails - 尝试抓取网站时出现 Ruby SSL 错误

node.js - Nodejs如何从https服务器获取TLS对象

android - 使用 SSL 的 Android 和 Python 之间的协议(protocol)错误

ruby-on-rails - 创建新 Rails 项目时出现 OpenSSL 错误

compiler-errors - 在Solaris Sparc 11下强制使用Sun Studio在./configure中进行编译(而不是cc)

powershell - 如何使用 powershell 脚本安装证书

ssl - CNAME 记录和 Heroku 域

android - android kitkat 版本中的 javax.net.ssl.SSLException : Connection closed by peer.

javascript - node.js 上的客户端 ssl 授权

encryption - OpenSSL,使用私钥解密