类 OpenSSL::X509::Store

X509 证书存储库保存用于验证对等证书的受信任 CA 证书。

创建有用证书存储库的最简单方法是

cert_store = OpenSSL::X509::Store.new
cert_store.set_default_paths

这将使用您系统的内置证书。

如果您的系统没有默认的证书集,您可以从 Mozilla CA 证书存储库中获取由 cURL 维护者提取的一组证书,网址为:curl.haxx.se/docs/caextract.html(您可能希望使用 firefox-db2pem.sh 脚本从本地安装中提取证书,以避免中间人攻击。)

从上面的链接下载或生成 cacert.pem 后,您可以从 pem 文件创建证书存储库,如下所示

cert_store = OpenSSL::X509::Store.new
cert_store.add_file 'cacert.pem'

证书存储库可以与 SSLSocket 一起使用,如下所示

ssl_context = OpenSSL::SSL::SSLContext.new
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
ssl_context.cert_store = cert_store

tcp_socket = TCPSocket.open 'example.com', 443

ssl_socket = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context

属性

chain[R]

由最后一次调用 verify 构造的证书链。

另请参阅 StoreContext#chain

error[R]

由最后一次调用 verify 设置的错误代码。

另请参阅 StoreContext#error

error_string[R]

由最后一次调用 verify 设置的错误代码的描述。

另请参阅 StoreContext#error_string

verify_callback[R]

用于额外证书验证的回调。它会为链中的每个证书调用,并且可以用来实现自定义证书验证条件。

回调会使用两个值调用,一个布尔值,指示 OpenSSL 的预验证是否成功,以及正在使用的 StoreContext

回调可以使用 StoreContext#error= 更改错误代码,如果需要。回调必须返回 true 或 false。

注意:回调中引发的任何异常都会被忽略。

另请参阅手册页 X509_STORE_CTX_set_verify_cb(3)。

公共类方法

X509::Store.new → store 点击切换源代码

创建一个新的 X509::Store

static VALUE
ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
{
    X509_STORE *store;

    GetX509Store(self, store);
    if (argc != 0)
        rb_warn("OpenSSL::X509::Store.new does not take any arguments");
#if !defined(HAVE_OPAQUE_OPENSSL)
    /* [Bug #405] [Bug #1678] [Bug #3000]; already fixed? */
    store->ex_data.sk = NULL;
#endif
    X509_STORE_set_verify_cb(store, x509store_verify_cb);
    ossl_x509store_set_vfy_cb(self, Qnil);

    /* last verification status */
    rb_iv_set(self, "@error", Qnil);
    rb_iv_set(self, "@error_string", Qnil);
    rb_iv_set(self, "@chain", Qnil);
    rb_iv_set(self, "@time", Qnil);

    return self;
}

公共实例方法

add_cert(cert) → self 点击切换源代码

OpenSSL::X509::Certificate cert 添加到证书存储库。

另请参阅手册页 X509_STORE_add_cert(3)。

static VALUE
ossl_x509store_add_cert(VALUE self, VALUE arg)
{
    X509_STORE *store;
    X509 *cert;

    cert = GetX509CertPtr(arg); /* NO NEED TO DUP */
    GetX509Store(self, store);
    if (X509_STORE_add_cert(store, cert) != 1)
        ossl_raise(eX509StoreError, "X509_STORE_add_cert");

    return self;
}
add_crl(crl) → self 点击切换源代码

OpenSSL::X509::CRL crl 添加到存储库。

另请参阅手册页 X509_STORE_add_crl(3)。

static VALUE
ossl_x509store_add_crl(VALUE self, VALUE arg)
{
    X509_STORE *store;
    X509_CRL *crl;

    crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */
    GetX509Store(self, store);
    if (X509_STORE_add_crl(store, crl) != 1)
        ossl_raise(eX509StoreError, "X509_STORE_add_crl");

    return self;
}
add_file(file) → self 点击切换源代码

file 中的证书添加到证书存储库。file 是文件的路径,该文件包含一个或多个以 PEM 格式连接在一起的证书。

另请参阅手册页 X509_LOOKUP_file(3)。

static VALUE
ossl_x509store_add_file(VALUE self, VALUE file)
{
    X509_STORE *store;
    X509_LOOKUP *lookup;
    const char *path;

    GetX509Store(self, store);
    path = StringValueCStr(file);
    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
    if (!lookup)
        ossl_raise(eX509StoreError, "X509_STORE_add_lookup");
    if (X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1)
        ossl_raise(eX509StoreError, "X509_LOOKUP_load_file");
#if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER)
    /*
     * X509_load_cert_crl_file() which is called from X509_LOOKUP_load_file()
     * did not check the return value of X509_STORE_add_{cert,crl}(), leaking
     * "cert already in hash table" errors on the error queue, if duplicate
     * certificates are found. This will be fixed by OpenSSL 1.1.1.
     */
    ossl_clear_error();
#endif

    return self;
}
add_path(path) → self 点击切换源代码

path 添加为存储库要查找的哈希目录。

另请参阅手册页 X509_LOOKUP_hash_dir(3)。

static VALUE
ossl_x509store_add_path(VALUE self, VALUE dir)
{
    X509_STORE *store;
    X509_LOOKUP *lookup;
    const char *path;

    GetX509Store(self, store);
    path = StringValueCStr(dir);
    lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
    if (!lookup)
        ossl_raise(eX509StoreError, "X509_STORE_add_lookup");
    if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1)
        ossl_raise(eX509StoreError, "X509_LOOKUP_add_dir");

    return self;
}
flags = flags 点击切换源代码

设置 Store 执行的证书链验证使用的默认标志。

flagsOpenSSL::X509 中定义的名称为 V_FLAG_* 的一个或多个常量按位或运算组成。

OpenSSL::X509::StoreContext#flags= 可用于更改单个验证操作的标志。

另请参阅手册页 X509_VERIFY_PARAM_set_flags(3)。

static VALUE
ossl_x509store_set_flags(VALUE self, VALUE flags)
{
    X509_STORE *store;
    long f = NUM2LONG(flags);

    GetX509Store(self, store);
    X509_STORE_set_flags(store, f);

    return flags;
}
purpose = purpose 点击切换源代码

设置存储库的默认验证目的。如果指定,存储库上的验证将检查每个证书的扩展是否与目的相一致。目的由常量指定

  • X509::PURPOSE_SSL_CLIENT

  • X509::PURPOSE_SSL_SERVER

  • X509::PURPOSE_NS_SSL_SERVER

  • X509::PURPOSE_SMIME_SIGN

  • X509::PURPOSE_SMIME_ENCRYPT

  • X509::PURPOSE_CRL_SIGN

  • X509::PURPOSE_ANY

  • X509::PURPOSE_OCSP_HELPER

  • X509::PURPOSE_TIMESTAMP_SIGN

OpenSSL::X509::StoreContext#purpose= 可用于更改单个验证操作的值。

另请参阅手册页 X509_VERIFY_PARAM_set_purpose(3)。

static VALUE
ossl_x509store_set_purpose(VALUE self, VALUE purpose)
{
    X509_STORE *store;
    int p = NUM2INT(purpose);

    GetX509Store(self, store);
    X509_STORE_set_purpose(store, p);

    return purpose;
}
set_default_paths 点击切换源代码

配置 store 以根据需要从系统默认证书存储库中查找 CA 证书。存储库的位置通常可以通过以下方式确定

  • OpenSSL::X509::DEFAULT_CERT_FILE

  • OpenSSL::X509::DEFAULT_CERT_DIR

另请参阅手册页 X509_STORE_set_default_paths(3)。

static VALUE
ossl_x509store_set_default_paths(VALUE self)
{
    X509_STORE *store;

    GetX509Store(self, store);
    if (X509_STORE_set_default_paths(store) != 1)
        ossl_raise(eX509StoreError, "X509_STORE_set_default_paths");

    return Qnil;
}
time = time 点击切换源代码

设置用于存储库中证书验证的时间。默认情况下,如果未指定,则使用当前系统时间。

OpenSSL::X509::StoreContext#time= 可用于更改单个验证操作的值。

另请参阅手册页 X509_VERIFY_PARAM_set_time(3)。

static VALUE
ossl_x509store_set_time(VALUE self, VALUE time)
{
    rb_iv_set(self, "@time", time);
    return time;
}
trust = trust 点击切换源代码

设置存储库中证书验证使用的默认信任设置。

OpenSSL::X509::StoreContext#trust= 可用于更改单个验证操作的值。

另请参阅手册页 X509_VERIFY_PARAM_set_trust(3)。

static VALUE
ossl_x509store_set_trust(VALUE self, VALUE trust)
{
    X509_STORE *store;
    int t = NUM2INT(trust);

    GetX509Store(self, store);
    X509_STORE_set_trust(store, t);

    return trust;
}
verify(cert, chain = nil) → true | false 点击切换源代码

OpenSSL::X509::Certificate cert 执行证书验证。

chain 可以是 OpenSSL::X509::Certificate 的数组,用于构造证书链。

如果给出了一个块,它将覆盖由 verify_callback= 设置的回调。

完成验证后,可以通过 errorerror_string 获取错误信息,并且可以通过 chain 获取生成的完整证书链。

static VALUE
ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
{
    VALUE cert, chain;
    VALUE ctx, proc, result;

    rb_scan_args(argc, argv, "11", &cert, &chain);
    ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
    proc = rb_block_given_p() ?  rb_block_proc() :
           rb_iv_get(self, "@verify_callback");
    rb_iv_set(ctx, "@verify_callback", proc);
    result = rb_funcall(ctx, rb_intern("verify"), 0);

    rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx));
    rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx));
    rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx));

    return result;
}
verify_callback=(p1) 点击切换源代码

OpenSSL 验证的通用回调

static VALUE
ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
{
    X509_STORE *store;

    GetX509Store(self, store);
    rb_iv_set(self, "@verify_callback", cb);
    // We don't need to trigger a write barrier because `rb_iv_set` did it.
    X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb);

    return cb;
}