diff options
author | rhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-08-29 05:47:09 +0000 |
---|---|---|
committer | rhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-08-29 05:47:09 +0000 |
commit | c9dc0164b8ad1cb23faf6120749bcc349a7bfd45 (patch) | |
tree | 831281099f54c0be80293785761a46688a0711f3 /ext/openssl/ossl_x509store.c | |
parent | 28bf4d545fb7674fcdc99c93ba7476d320551d11 (diff) |
import Ruby/OpenSSL 2.0.0.beta.1
* NEWS, {ext,test,sample}/openssl: Import Ruby/OpenSSL 2.0.0.beta.1.
ext/openssl is now converted into a default gem. The full commit
history since r55538 can be found at:
https://github.com/ruby/openssl/compare/08e1881f5663...v2.0.0.beta.1
[Feature #9612]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56027 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/openssl/ossl_x509store.c')
-rw-r--r-- | ext/openssl/ossl_x509store.c | 224 |
1 files changed, 189 insertions, 35 deletions
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c index 26426d1832..75f8238b01 100644 --- a/ext/openssl/ossl_x509store.c +++ b/ext/openssl/ossl_x509store.c @@ -106,6 +106,20 @@ DupX509StorePtr(VALUE obj) /* * Private functions */ +static int +x509store_verify_cb(int ok, X509_STORE_CTX *ctx) +{ + VALUE proc; + + proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx); + if (!proc) + proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx), ossl_store_ex_verify_cb_idx); + if (!proc) + return ok; + + return ossl_verify_cb_call(proc, ok, ctx); +} + static VALUE ossl_x509store_alloc(VALUE klass) { @@ -141,6 +155,7 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb) * call-seq: * X509::Store.new => store * + * Creates a new X509::Store. */ static VALUE ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) @@ -153,7 +168,7 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) /* [Bug #405] [Bug #1678] [Bug #3000]; already fixed? */ store->ex_data.sk = NULL; #endif - X509_STORE_set_verify_cb(store, ossl_verify_cb); + X509_STORE_set_verify_cb(store, x509store_verify_cb); ossl_x509store_set_vfy_cb(self, Qnil); /* last verification status */ @@ -165,6 +180,13 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* + * call-seq: + * store.flags = flag + * + * Sets +flag+ to the Store. +flag+ consists of zero or more of the constants + * defined in with name V_FLAG_* or'ed together. + */ static VALUE ossl_x509store_set_flags(VALUE self, VALUE flags) { @@ -177,6 +199,24 @@ ossl_x509store_set_flags(VALUE self, VALUE flags) return flags; } +/* + * call-seq: + * store.purpose = purpose + * + * Sets the store's purpose to +purpose+. If specified, the verifications on + * the store will check every untrusted certificate's extensions are consistent + * with the purpose. The purpose is specified by constants: + * + * * 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 + */ static VALUE ossl_x509store_set_purpose(VALUE self, VALUE purpose) { @@ -189,6 +229,10 @@ ossl_x509store_set_purpose(VALUE self, VALUE purpose) return purpose; } +/* + * call-seq: + * store.trust = trust + */ static VALUE ossl_x509store_set_trust(VALUE self, VALUE trust) { @@ -201,6 +245,12 @@ ossl_x509store_set_trust(VALUE self, VALUE trust) return trust; } +/* + * call-seq: + * store.time = time + * + * Sets the time to be used in verifications. + */ static VALUE ossl_x509store_set_time(VALUE self, VALUE time) { @@ -210,13 +260,11 @@ ossl_x509store_set_time(VALUE self, VALUE time) /* * call-seq: - * store.add_file(file) -> store - * + * store.add_file(file) -> self * * Adds the certificates in +file+ to the certificate store. The +file+ can * contain multiple PEM-encoded certificates. */ - static VALUE ossl_x509store_add_file(VALUE self, VALUE file) { @@ -238,6 +286,12 @@ ossl_x509store_add_file(VALUE self, VALUE file) return self; } +/* + * call-seq: + * store.add_path(path) -> self + * + * Adds +path+ as the hash dir to be looked up by the store. + */ static VALUE ossl_x509store_add_path(VALUE self, VALUE dir) { @@ -263,11 +317,12 @@ ossl_x509store_add_path(VALUE self, VALUE dir) * call-seq: * store.set_default_paths * - * Adds the default certificates to the certificate store. These certificates - * are loaded from the default configuration directory which can usually be + * Configures +store+ to look up CA certificates from the system default + * certificate store as needed basis. The location of the store can usually be * determined by: * - * File.dirname OpenSSL::Config::DEFAULT_CONFIG_FILE + * * OpenSSL::X509::DEFAULT_CERT_FILE + * * OpenSSL::X509::DEFAULT_CERT_DIR */ static VALUE ossl_x509store_set_default_paths(VALUE self) @@ -288,7 +343,6 @@ ossl_x509store_set_default_paths(VALUE self) * * Adds the OpenSSL::X509::Certificate +cert+ to the certificate store. */ - static VALUE ossl_x509store_add_cert(VALUE self, VALUE arg) { @@ -304,6 +358,12 @@ ossl_x509store_add_cert(VALUE self, VALUE arg) return self; } +/* + * call-seq: + * store.add_crl(crl) -> self + * + * Adds the OpenSSL::X509::CRL +crl+ to the store. + */ static VALUE ossl_x509store_add_crl(VALUE self, VALUE arg) { @@ -323,6 +383,21 @@ static VALUE ossl_x509stctx_get_err(VALUE); static VALUE ossl_x509stctx_get_err_string(VALUE); static VALUE ossl_x509stctx_get_chain(VALUE); +/* + * call-seq: + * store.verify(cert, chain = nil) -> true | false + * + * Performs a certificate verification on the OpenSSL::X509::Certificate +cert+. + * + * +chain+ can be an array of OpenSSL::X509::Certificate that is used to + * construct the certificate chain. + * + * If a block is given, it overrides the callback set by #verify_callback=. + * + * After finishing the verification, the error information can be retrieved by + * #error, #error_string, and the resuting complete certificate chain can be + * retrieved by #chain. + */ static VALUE ossl_x509store_verify(int argc, VALUE *argv, VALUE self) { @@ -412,6 +487,10 @@ static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE); static VALUE ossl_x509stctx_set_trust(VALUE, VALUE); static VALUE ossl_x509stctx_set_time(VALUE, VALUE); +/* + * call-seq: + * StoreContext.new(store, cert = nil, chain = nil) + */ static VALUE ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) { @@ -438,6 +517,10 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* + * call-seq: + * stctx.verify -> true | false + */ static VALUE ossl_x509stctx_verify(VALUE self) { @@ -458,6 +541,10 @@ ossl_x509stctx_verify(VALUE self) } } +/* + * call-seq: + * stctx.chain -> Array of X509::Certificate + */ static VALUE ossl_x509stctx_get_chain(VALUE self) { @@ -484,6 +571,10 @@ ossl_x509stctx_get_chain(VALUE self) return ary; } +/* + * call-seq: + * stctx.error -> Integer + */ static VALUE ossl_x509stctx_get_err(VALUE self) { @@ -491,9 +582,13 @@ ossl_x509stctx_get_err(VALUE self) GetX509StCtx(self, ctx); - return INT2FIX(X509_STORE_CTX_get_error(ctx)); + return INT2NUM(X509_STORE_CTX_get_error(ctx)); } +/* + * call-seq: + * stctx.error = error_code + */ static VALUE ossl_x509stctx_set_error(VALUE self, VALUE err) { @@ -505,6 +600,12 @@ ossl_x509stctx_set_error(VALUE self, VALUE err) return err; } +/* + * call-seq: + * stctx.error_string -> String + * + * Returns the error string corresponding to the error code retrieved by #error. + */ static VALUE ossl_x509stctx_get_err_string(VALUE self) { @@ -517,6 +618,10 @@ ossl_x509stctx_get_err_string(VALUE self) return rb_str_new2(X509_verify_cert_error_string(err)); } +/* + * call-seq: + * stctx.error_depth -> Integer + */ static VALUE ossl_x509stctx_get_err_depth(VALUE self) { @@ -524,9 +629,13 @@ ossl_x509stctx_get_err_depth(VALUE self) GetX509StCtx(self, ctx); - return INT2FIX(X509_STORE_CTX_get_error_depth(ctx)); + return INT2NUM(X509_STORE_CTX_get_error_depth(ctx)); } +/* + * call-seq: + * stctx.current_cert -> X509::Certificate + */ static VALUE ossl_x509stctx_get_curr_cert(VALUE self) { @@ -537,6 +646,10 @@ ossl_x509stctx_get_curr_cert(VALUE self) return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx)); } +/* + * call-seq: + * stctx.current_crl -> X509::CRL + */ static VALUE ossl_x509stctx_get_curr_crl(VALUE self) { @@ -551,6 +664,12 @@ ossl_x509stctx_get_curr_crl(VALUE self) return ossl_x509crl_new(crl); } +/* + * call-seq: + * stctx.flags = flags + * + * Sets the verification flags to the context. See Store#flags=. + */ static VALUE ossl_x509stctx_set_flags(VALUE self, VALUE flags) { @@ -563,6 +682,12 @@ ossl_x509stctx_set_flags(VALUE self, VALUE flags) return flags; } +/* + * call-seq: + * stctx.purpose = purpose + * + * Sets the purpose of the context. See Store#purpose=. + */ static VALUE ossl_x509stctx_set_purpose(VALUE self, VALUE purpose) { @@ -575,6 +700,10 @@ ossl_x509stctx_set_purpose(VALUE self, VALUE purpose) return purpose; } +/* + * call-seq: + * stctx.trust = trust + */ static VALUE ossl_x509stctx_set_trust(VALUE self, VALUE trust) { @@ -589,7 +718,9 @@ ossl_x509stctx_set_trust(VALUE self, VALUE trust) /* * call-seq: - * storectx.time = time => time + * stctx.time = time + * + * Sets the time used in the verification. If not set, the current time is used. */ static VALUE ossl_x509stctx_set_time(VALUE self, VALUE time) @@ -610,10 +741,9 @@ ossl_x509stctx_set_time(VALUE self, VALUE time) void Init_ossl_x509store(void) { - VALUE x509stctx; - #if 0 - mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ + mOSSL = rb_define_module("OpenSSL"); + eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); mX509 = rb_define_module_under(mOSSL, "X509"); #endif @@ -631,11 +761,11 @@ Init_ossl_x509store(void) * * This will use your system's built-in certificates. * - * If your system does not have a default set of certificates you can - * obtain a set from Mozilla here: http://curl.haxx.se/docs/caextract.html - * (Note that this set does not have an HTTPS download option so you may - * wish to use the firefox-db2pem.sh script to extract the certificates - * from a local install to avoid man-in-the-middle attacks.) + * If your system does not have a default set of certificates you can obtain + * a set extracted from Mozilla CA certificate store by cURL maintainers + * here: https://curl.haxx.se/docs/caextract.html (You may wish to use the + * firefox-db2pem.sh script to extract the certificates from a local install + * to avoid man-in-the-middle attacks.) * * After downloading or generating a cacert.pem from the above link you * can create a certificate store from the pem file like this: @@ -646,6 +776,7 @@ Init_ossl_x509store(void) * The certificate store can be used with an SSLSocket like this: * * 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 @@ -654,12 +785,30 @@ Init_ossl_x509store(void) */ cX509Store = rb_define_class_under(mX509, "Store", rb_cObject); + /* + * The callback for additional certificate verification. It is invoked for + * each untrusted certificate in the chain. + * + * The callback is invoked with two values, a boolean that indicates if the + * pre-verification by OpenSSL has succeeded or not, and the StoreContext in + * use. The callback must return either true or false. + */ rb_attr(cX509Store, rb_intern("verify_callback"), 1, 0, Qfalse); + /* + * The error code set by the last call of #verify. + */ rb_attr(cX509Store, rb_intern("error"), 1, 0, Qfalse); + /* + * The description for the error code set by the last call of #verify. + */ rb_attr(cX509Store, rb_intern("error_string"), 1, 0, Qfalse); + /* + * The certificate chain constructed by the last call of #verify. + */ rb_attr(cX509Store, rb_intern("chain"), 1, 0, Qfalse); rb_define_alloc_func(cX509Store, ossl_x509store_alloc); rb_define_method(cX509Store, "initialize", ossl_x509store_initialize, -1); + rb_undef_method(cX509Store, "initialize_copy"); rb_define_method(cX509Store, "verify_callback=", ossl_x509store_set_vfy_cb, 1); rb_define_method(cX509Store, "flags=", ossl_x509store_set_flags, 1); rb_define_method(cX509Store, "purpose=", ossl_x509store_set_purpose, 1); @@ -672,21 +821,26 @@ Init_ossl_x509store(void) rb_define_method(cX509Store, "add_crl", ossl_x509store_add_crl, 1); rb_define_method(cX509Store, "verify", ossl_x509store_verify, -1); - cX509StoreContext = rb_define_class_under(mX509,"StoreContext",rb_cObject); - x509stctx = cX509StoreContext; + /* + * Document-class: OpenSSL::X509::StoreContext + * + * A StoreContext is used while validating a single certificate and holds + * the status involved. + */ + cX509StoreContext = rb_define_class_under(mX509,"StoreContext", rb_cObject); rb_define_alloc_func(cX509StoreContext, ossl_x509stctx_alloc); - rb_define_method(x509stctx,"initialize", ossl_x509stctx_initialize, -1); - rb_define_method(x509stctx,"verify", ossl_x509stctx_verify, 0); - rb_define_method(x509stctx,"chain", ossl_x509stctx_get_chain,0); - rb_define_method(x509stctx,"error", ossl_x509stctx_get_err, 0); - rb_define_method(x509stctx,"error=", ossl_x509stctx_set_error, 1); - rb_define_method(x509stctx,"error_string",ossl_x509stctx_get_err_string,0); - rb_define_method(x509stctx,"error_depth", ossl_x509stctx_get_err_depth, 0); - rb_define_method(x509stctx,"current_cert",ossl_x509stctx_get_curr_cert, 0); - rb_define_method(x509stctx,"current_crl", ossl_x509stctx_get_curr_crl, 0); - rb_define_method(x509stctx,"flags=", ossl_x509stctx_set_flags, 1); - rb_define_method(x509stctx,"purpose=", ossl_x509stctx_set_purpose, 1); - rb_define_method(x509stctx,"trust=", ossl_x509stctx_set_trust, 1); - rb_define_method(x509stctx,"time=", ossl_x509stctx_set_time, 1); - + rb_define_method(cX509StoreContext, "initialize", ossl_x509stctx_initialize, -1); + rb_undef_method(cX509StoreContext, "initialize_copy"); + rb_define_method(cX509StoreContext, "verify", ossl_x509stctx_verify, 0); + rb_define_method(cX509StoreContext, "chain", ossl_x509stctx_get_chain,0); + rb_define_method(cX509StoreContext, "error", ossl_x509stctx_get_err, 0); + rb_define_method(cX509StoreContext, "error=", ossl_x509stctx_set_error, 1); + rb_define_method(cX509StoreContext, "error_string", ossl_x509stctx_get_err_string,0); + rb_define_method(cX509StoreContext, "error_depth", ossl_x509stctx_get_err_depth, 0); + rb_define_method(cX509StoreContext, "current_cert", ossl_x509stctx_get_curr_cert, 0); + rb_define_method(cX509StoreContext, "current_crl", ossl_x509stctx_get_curr_crl, 0); + rb_define_method(cX509StoreContext, "flags=", ossl_x509stctx_set_flags, 1); + rb_define_method(cX509StoreContext, "purpose=", ossl_x509stctx_set_purpose, 1); + rb_define_method(cX509StoreContext, "trust=", ossl_x509stctx_set_trust, 1); + rb_define_method(cX509StoreContext, "time=", ossl_x509stctx_set_time, 1); } |