summaryrefslogtreecommitdiffstats
path: root/OpenSSL/X509
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSSL/X509')
-rw-r--r--OpenSSL/X509/Store.html146
-rw-r--r--OpenSSL/X509/StoreContext.html632
2 files changed, 741 insertions, 37 deletions
diff --git a/OpenSSL/X509/Store.html b/OpenSSL/X509/Store.html
index 6da89db2..0319a23f 100644
--- a/OpenSSL/X509/Store.html
+++ b/OpenSSL/X509/Store.html
@@ -119,11 +119,11 @@ certificates used to verify peer certificates.</p>
<p>This will use your system&#39;s built-in certificates.</p>
<p>If your system does not have a default set of certificates you can obtain a
-set from Mozilla here: <a
-href="http://curl.haxx.se/docs/caextract.html">curl.haxx.se/docs/caextract.html</a>
-(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.)</p>
+set extracted from Mozilla CA certificate store by cURL maintainers here:
+<a
+href="https://curl.haxx.se/docs/caextract.html">curl.haxx.se/docs/caextract.html</a>
+(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.)</p>
<p>After downloading or generating a cacert.pem from the above link you can
create a certificate store from the pem file like this:</p>
@@ -135,6 +135,7 @@ create a certificate store from the pem file like this:</p>
<p>The certificate store can be used with an SSLSocket like this:</p>
<pre class="ruby"><span class="ruby-identifier">ssl_context</span> = <span class="ruby-constant">OpenSSL</span><span class="ruby-operator">::</span><span class="ruby-constant">SSL</span><span class="ruby-operator">::</span><span class="ruby-constant">SSLContext</span>.<span class="ruby-identifier">new</span>
+<span class="ruby-identifier">ssl_context</span>.<span class="ruby-identifier">verify_mode</span> = <span class="ruby-constant">OpenSSL</span><span class="ruby-operator">::</span><span class="ruby-constant">SSL</span><span class="ruby-operator">::</span><span class="ruby-constant">VERIFY_PEER</span>
<span class="ruby-identifier">ssl_context</span>.<span class="ruby-identifier">cert_store</span> = <span class="ruby-identifier">cert_store</span>
<span class="ruby-identifier">tcp_socket</span> = <span class="ruby-constant">TCPSocket</span>.<span class="ruby-identifier">open</span> <span class="ruby-string">&#39;example.com&#39;</span>, <span class="ruby-value">443</span>
@@ -169,7 +170,8 @@ create a certificate store from the pem file like this:</p>
<div class="method-description">
-
+ <p>The certificate chain constructed by the last call of <a
+href="Store.html#method-i-verify">verify</a>.</p>
</div>
</div>
@@ -182,7 +184,8 @@ create a certificate store from the pem file like this:</p>
<div class="method-description">
-
+ <p>The error code set by the last call of <a
+href="Store.html#method-i-verify">verify</a>.</p>
</div>
</div>
@@ -195,7 +198,8 @@ create a certificate store from the pem file like this:</p>
<div class="method-description">
-
+ <p>The description for the error code set by the last call of <a
+href="Store.html#method-i-verify">verify</a>.</p>
</div>
</div>
@@ -208,7 +212,13 @@ create a certificate store from the pem file like this:</p>
<div class="method-description">
-
+ <p>The callback for additional certificate verification. It is invoked for
+each untrusted certificate in the chain.</p>
+
+<p>The callback is invoked with two values, a boolean that indicates if the
+pre-verification by <a href="../../OpenSSL.html">OpenSSL</a> has succeeded
+or not, and the <a href="StoreContext.html">StoreContext</a> in use. The
+callback must return either true or false.</p>
</div>
</div>
@@ -239,7 +249,7 @@ create a certificate store from the pem file like this:</p>
<div class="method-description">
-
+ <p>Creates a new <a href="Store.html">X509::Store</a>.</p>
@@ -334,18 +344,22 @@ ossl_x509store_add_cert(VALUE self, VALUE arg)
<div id="method-i-add_crl" class="method-detail ">
+
<div class="method-heading">
- <span class="method-name">add_crl</span><span
- class="method-args">(p1)</span>
+ <span class="method-callseq">
+ add_crl(crl) &rarr; self
+ </span>
<span class="method-click-advice">click to toggle source</span>
</div>
+
<div class="method-description">
-
+ <p>Adds the <a href="CRL.html">OpenSSL::X509::CRL</a> <code>crl</code> to the
+store.</p>
@@ -380,7 +394,7 @@ ossl_x509store_add_crl(VALUE self, VALUE arg)
<div class="method-heading">
<span class="method-callseq">
- add_file(file) &rarr; store
+ add_file(file) &rarr; self
</span>
<span class="method-click-advice">click to toggle source</span>
@@ -430,18 +444,21 @@ ossl_x509store_add_file(VALUE self, VALUE file)
<div id="method-i-add_path" class="method-detail ">
+
<div class="method-heading">
- <span class="method-name">add_path</span><span
- class="method-args">(p1)</span>
+ <span class="method-callseq">
+ add_path(path) &rarr; self
+ </span>
<span class="method-click-advice">click to toggle source</span>
</div>
+
<div class="method-description">
-
+ <p>Adds <code>path</code> as the hash dir to be looked up by the store.</p>
@@ -479,18 +496,23 @@ ossl_x509store_add_path(VALUE self, VALUE dir)
<div id="method-i-flags-3D" class="method-detail ">
+
<div class="method-heading">
- <span class="method-name">flags=</span><span
- class="method-args">(p1)</span>
+ <span class="method-callseq">
+ flags = flag
+ </span>
<span class="method-click-advice">click to toggle source</span>
</div>
+
<div class="method-description">
-
+ <p>Sets <code>flag</code> to the <a href="Store.html">Store</a>.
+<code>flag</code> consists of zero or more of the constants defined in with
+name V_FLAG_* or&#39;ed together.</p>
@@ -519,18 +541,43 @@ ossl_x509store_set_flags(VALUE self, VALUE flags)
<div id="method-i-purpose-3D" class="method-detail ">
+
<div class="method-heading">
- <span class="method-name">purpose=</span><span
- class="method-args">(p1)</span>
+ <span class="method-callseq">
+ purpose = purpose
+ </span>
<span class="method-click-advice">click to toggle source</span>
</div>
+
<div class="method-description">
-
+ <p>Sets the store&#39;s purpose to <code>purpose</code>. If specified, the
+verifications on the store will check every untrusted certificate&#39;s
+extensions are consistent with the purpose. The purpose is specified by
+constants:</p>
+<ul><li>
+<p>X509::PURPOSE_SSL_CLIENT</p>
+</li><li>
+<p>X509::PURPOSE_SSL_SERVER</p>
+</li><li>
+<p>X509::PURPOSE_NS_SSL_SERVER</p>
+</li><li>
+<p>X509::PURPOSE_SMIME_SIGN</p>
+</li><li>
+<p>X509::PURPOSE_SMIME_ENCRYPT</p>
+</li><li>
+<p>X509::PURPOSE_CRL_SIGN</p>
+</li><li>
+<p>X509::PURPOSE_ANY</p>
+</li><li>
+<p>X509::PURPOSE_OCSP_HELPER</p>
+</li><li>
+<p>X509::PURPOSE_TIMESTAMP_SIGN</p>
+</li></ul>
@@ -573,12 +620,14 @@ ossl_x509store_set_purpose(VALUE self, VALUE purpose)
<div class="method-description">
- <p>Adds the default certificates to the certificate store. These certificates
-are loaded from the default configuration directory which can usually be
-determined by:</p>
-
-<pre class="ruby"><span class="ruby-constant">File</span>.<span class="ruby-identifier">dirname</span> <span class="ruby-constant">OpenSSL</span><span class="ruby-operator">::</span><span class="ruby-constant">Config</span><span class="ruby-operator">::</span><span class="ruby-constant">DEFAULT_CONFIG_FILE</span>
-</pre>
+ <p>Configures <code>store</code> to look up CA certificates from the system
+default certificate store as needed basis. The location of the store can
+usually be determined by:</p>
+<ul><li>
+<p>OpenSSL::X509::DEFAULT_CERT_FILE</p>
+</li><li>
+<p>OpenSSL::X509::DEFAULT_CERT_DIR</p>
+</li></ul>
@@ -608,18 +657,21 @@ ossl_x509store_set_default_paths(VALUE self)
<div id="method-i-time-3D" class="method-detail ">
+
<div class="method-heading">
- <span class="method-name">time=</span><span
- class="method-args">(p1)</span>
+ <span class="method-callseq">
+ time = time
+ </span>
<span class="method-click-advice">click to toggle source</span>
</div>
+
<div class="method-description">
-
+ <p>Sets the time to be used in verifications.</p>
@@ -643,14 +695,17 @@ ossl_x509store_set_time(VALUE self, VALUE time)
<div id="method-i-trust-3D" class="method-detail ">
+
<div class="method-heading">
- <span class="method-name">trust=</span><span
- class="method-args">(p1)</span>
+ <span class="method-callseq">
+ trust = trust
+ </span>
<span class="method-click-advice">click to toggle source</span>
</div>
+
<div class="method-description">
@@ -683,18 +738,35 @@ ossl_x509store_set_trust(VALUE self, VALUE trust)
<div id="method-i-verify" class="method-detail ">
+
<div class="method-heading">
- <span class="method-name">verify</span><span
- class="method-args">(p1, p2 = v2)</span>
+ <span class="method-callseq">
+ verify(cert, chain = nil) &rarr; true | false
+ </span>
<span class="method-click-advice">click to toggle source</span>
</div>
+
<div class="method-description">
-
+ <p>Performs a certificate verification on the <a
+href="Certificate.html">OpenSSL::X509::Certificate</a> <code>cert</code>.</p>
+
+<p><code>chain</code> can be an array of <a
+href="Certificate.html">OpenSSL::X509::Certificate</a> that is used to
+construct the certificate chain.</p>
+
+<p>If a block is given, it overrides the callback set by <a
+href="Store.html#method-i-verify_callback-3D">verify_callback=</a>.</p>
+
+<p>After finishing the verification, the error information can be retrieved by
+<a href="Store.html#attribute-i-error">error</a>, <a
+href="Store.html#attribute-i-error_string">error_string</a>, and the
+resuting complete certificate chain can be retrieved by <a
+href="Store.html#attribute-i-chain">chain</a>.</p>
diff --git a/OpenSSL/X509/StoreContext.html b/OpenSSL/X509/StoreContext.html
index 65523cc6..29423ceb 100644
--- a/OpenSSL/X509/StoreContext.html
+++ b/OpenSSL/X509/StoreContext.html
@@ -70,8 +70,34 @@
<ul class="link-list" role="directory">
+ <li ><a href="#method-c-new">::new</a>
+
+ <li ><a href="#method-i-chain">#chain</a>
+
<li ><a href="#method-i-cleanup">#cleanup</a>
+ <li ><a href="#method-i-current_cert">#current_cert</a>
+
+ <li ><a href="#method-i-current_crl">#current_crl</a>
+
+ <li ><a href="#method-i-error">#error</a>
+
+ <li ><a href="#method-i-error-3D">#error=</a>
+
+ <li ><a href="#method-i-error_depth">#error_depth</a>
+
+ <li ><a href="#method-i-error_string">#error_string</a>
+
+ <li ><a href="#method-i-flags-3D">#flags=</a>
+
+ <li ><a href="#method-i-purpose-3D">#purpose=</a>
+
+ <li ><a href="#method-i-time-3D">#time=</a>
+
+ <li ><a href="#method-i-trust-3D">#trust=</a>
+
+ <li ><a href="#method-i-verify">#verify</a>
+
</ul>
</div>
@@ -85,6 +111,9 @@
<section class="description">
+<p>A <a href="StoreContext.html">StoreContext</a> is used while validating a
+single certificate and holds the status involved.</p>
+
</section>
@@ -100,12 +129,134 @@
+ <section id="public-class-5Buntitled-5D-method-details" class="method-section">
+ <header>
+ <h3>Public Class Methods</h3>
+ </header>
+
+
+ <div id="method-c-new" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ new(store, cert = nil, chain = nil)
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+
+
+
+
+
+ <div class="method-source-code" id="new-source">
+ <pre>static VALUE
+ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
+{
+ VALUE store, cert, chain, t;
+ X509_STORE_CTX *ctx;
+ X509_STORE *x509st;
+ X509 *x509 = NULL;
+ STACK_OF(X509) *x509s = NULL;
+
+ rb_scan_args(argc, argv, &quot;12&quot;, &amp;store, &amp;cert, &amp;chain);
+ GetX509StCtx(self, ctx);
+ SafeGetX509Store(store, x509st);
+ if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */
+ if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain);
+ if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(eX509StoreError, NULL);
+ }
+ if (!NIL_P(t = rb_iv_get(store, &quot;@time&quot;)))
+ ossl_x509stctx_set_time(self, t);
+ rb_iv_set(self, &quot;@verify_callback&quot;, rb_iv_get(store, &quot;@verify_callback&quot;));
+ rb_iv_set(self, &quot;@cert&quot;, cert);
+
+ return self;
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ </section>
+
<section id="public-instance-5Buntitled-5D-method-details" class="method-section">
<header>
<h3>Public Instance Methods</h3>
</header>
+ <div id="method-i-chain" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ chain &rarr; Array of X509::Certificate
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+
+
+
+
+
+ <div class="method-source-code" id="chain-source">
+ <pre>static VALUE
+ossl_x509stctx_get_chain(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+ STACK_OF(X509) *chain;
+ X509 *x509;
+ int i, num;
+ VALUE ary;
+
+ GetX509StCtx(self, ctx);
+ if((chain = X509_STORE_CTX_get0_chain(ctx)) == NULL){
+ return Qnil;
+ }
+ if((num = sk_X509_num(chain)) &lt; 0){
+ OSSL_Debug(&quot;certs in chain &lt; 0???&quot;);
+ return rb_ary_new();
+ }
+ ary = rb_ary_new2(num);
+ for(i = 0; i &lt; num; i++) {
+ x509 = sk_X509_value(chain, i);
+ rb_ary_push(ary, ossl_x509_new(x509));
+ }
+
+ return ary;
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
<div id="method-i-cleanup" class="method-detail ">
<div class="method-heading">
@@ -139,6 +290,487 @@
</div>
+ <div id="method-i-current_cert" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ current_cert &rarr; X509::Certificate
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+
+
+
+
+
+ <div class="method-source-code" id="current_cert-source">
+ <pre>static VALUE
+ossl_x509stctx_get_curr_cert(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+
+ return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-current_crl" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ current_crl &rarr; X509::CRL
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+
+
+
+
+
+ <div class="method-source-code" id="current_crl-source">
+ <pre>static VALUE
+ossl_x509stctx_get_curr_crl(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+ X509_CRL *crl;
+
+ GetX509StCtx(self, ctx);
+ crl = X509_STORE_CTX_get0_current_crl(ctx);
+ if (!crl)
+ return Qnil;
+
+ return ossl_x509crl_new(crl);
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-error" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ error &rarr; Integer
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+
+
+
+
+
+ <div class="method-source-code" id="error-source">
+ <pre>static VALUE
+ossl_x509stctx_get_err(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+
+ return INT2FIX(X509_STORE_CTX_get_error(ctx));
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-error-3D" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ error = error_code
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+
+
+
+
+
+ <div class="method-source-code" id="error-3D-source">
+ <pre>static VALUE
+ossl_x509stctx_set_error(VALUE self, VALUE err)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+ X509_STORE_CTX_set_error(ctx, NUM2INT(err));
+
+ return err;
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-error_depth" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ error_depth &rarr; Integer
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+
+
+
+
+
+ <div class="method-source-code" id="error_depth-source">
+ <pre>static VALUE
+ossl_x509stctx_get_err_depth(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+
+ return INT2FIX(X509_STORE_CTX_get_error_depth(ctx));
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-error_string" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ error_string &rarr; String
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+ <p>Returns the error string corresponding to the error code retrieved by <a
+href="StoreContext.html#method-i-error">error</a>.</p>
+
+
+
+
+ <div class="method-source-code" id="error_string-source">
+ <pre>static VALUE
+ossl_x509stctx_get_err_string(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+ long err;
+
+ GetX509StCtx(self, ctx);
+ err = X509_STORE_CTX_get_error(ctx);
+
+ return rb_str_new2(X509_verify_cert_error_string(err));
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-flags-3D" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ flags = flags
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+ <p>Sets the verification flags to the context. See <a
+href="Store.html#method-i-flags-3D">OpenSSL::X509::Store#flags=</a>.</p>
+
+
+
+
+ <div class="method-source-code" id="flags-3D-source">
+ <pre>static VALUE
+ossl_x509stctx_set_flags(VALUE self, VALUE flags)
+{
+ X509_STORE_CTX *store;
+ long f = NUM2LONG(flags);
+
+ GetX509StCtx(self, store);
+ X509_STORE_CTX_set_flags(store, f);
+
+ return flags;
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-purpose-3D" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ purpose = purpose
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+ <p>Sets the purpose of the context. See <a
+href="Store.html#method-i-purpose-3D">OpenSSL::X509::Store#purpose=</a>.</p>
+
+
+
+
+ <div class="method-source-code" id="purpose-3D-source">
+ <pre>static VALUE
+ossl_x509stctx_set_purpose(VALUE self, VALUE purpose)
+{
+ X509_STORE_CTX *store;
+ int p = NUM2INT(purpose);
+
+ GetX509StCtx(self, store);
+ X509_STORE_CTX_set_purpose(store, p);
+
+ return purpose;
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-time-3D" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ time = time
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+ <p>Sets the time used in the verification. If not set, the current time is
+used.</p>
+
+
+
+
+ <div class="method-source-code" id="time-3D-source">
+ <pre>static VALUE
+ossl_x509stctx_set_time(VALUE self, VALUE time)
+{
+ X509_STORE_CTX *store;
+ long t;
+
+ t = NUM2LONG(rb_Integer(time));
+ GetX509StCtx(self, store);
+ X509_STORE_CTX_set_time(store, 0, t);
+
+ return time;
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-trust-3D" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ trust = trust
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+
+
+
+
+
+ <div class="method-source-code" id="trust-3D-source">
+ <pre>static VALUE
+ossl_x509stctx_set_trust(VALUE self, VALUE trust)
+{
+ X509_STORE_CTX *store;
+ int t = NUM2INT(trust);
+
+ GetX509StCtx(self, store);
+ X509_STORE_CTX_set_trust(store, t);
+
+ return trust;
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
+ <div id="method-i-verify" class="method-detail ">
+
+
+ <div class="method-heading">
+ <span class="method-callseq">
+ verify &rarr; true | false
+ </span>
+
+ <span class="method-click-advice">click to toggle source</span>
+
+ </div>
+
+
+
+ <div class="method-description">
+
+
+
+
+
+
+ <div class="method-source-code" id="verify-source">
+ <pre>static VALUE
+ossl_x509stctx_verify(VALUE self)
+{
+ X509_STORE_CTX *ctx;
+
+ GetX509StCtx(self, ctx);
+ X509_STORE_CTX_set_ex_data(ctx, ossl_store_ctx_ex_verify_cb_idx,
+ (void *)rb_iv_get(self, &quot;@verify_callback&quot;));
+
+ switch (X509_verify_cert(ctx)) {
+ case 1:
+ return Qtrue;
+ case 0:
+ ossl_clear_error();
+ return Qfalse;
+ default:
+ ossl_raise(eX509CertError, NULL);
+ }
+}</pre>
+ </div>
+
+ </div>
+
+
+
+
+ </div>
+
+
</section>
</section>