Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
0175-SSL-Make-the-handshake-fail-when-OCSP-stap...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0175-SSL-Make-the-handshake-fail-when-OCSP-staple-missing.patch of Package erlang
From 3b5043346f6db30bab1fa5370cdc4ee746816e60 Mon Sep 17 00:00:00 2001 From: Michal Palka <michal.palka@hiq.se> Date: Tue, 23 Mar 2021 16:00:48 +0100 Subject: [PATCH 1/3] SSL: Make the handshake fail when OCSP staple missing * Make the TLS handshake fail when OCSP staple is requested but missing. * Add test case for missing OCSP response. * Add test case for OCSP response with certificate status undetermined. --- lib/ssl/src/ssl_gen_statem.erl | 3 +- lib/ssl/src/ssl_handshake.erl | 12 ++++- lib/ssl/test/make_certs.erl | 20 +++++++- lib/ssl/test/openssl_ocsp_SUITE.erl | 71 ++++++++++++++++++++++++++++- lib/ssl/test/ssl_test_lib.erl | 16 ++++++- 5 files changed, 114 insertions(+), 8 deletions(-) diff --git a/lib/ssl/src/ssl_gen_statem.erl b/lib/ssl/src/ssl_gen_statem.erl index 6431b5bedd..c2dd4e5c7a 100644 --- a/lib/ssl/src/ssl_gen_statem.erl +++ b/lib/ssl/src/ssl_gen_statem.erl @@ -504,7 +504,8 @@ initial_hello({call, From}, {start, Timeout}, negotiated_version = RequestedVersion}, session = Session, handshake_env = HsEnv1#handshake_env{ - ocsp_stapling_state = OcspState0#{ocsp_nonce => OcspNonce}}, + ocsp_stapling_state = OcspState0#{ocsp_nonce => OcspNonce, + ocsp_stapling => OcspStaplingOpt}}, start_or_recv_from = From, key_share = KeyShare}, NextState = next_statem_state(Versions, Role), diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index de5490d232..aac4c28a5f 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -1971,10 +1971,18 @@ cert_status_check(_, #{ocsp_state := #{ocsp_stapling := true, valid; %% OCSP staple will now be checked by ssl_certifcate:verify_cert_extensions/2 in ssl_certifcate:validate cert_status_check(OtpCert, #{ocsp_state := #{ocsp_stapling := false}} = SslState, VerifyResult, CertPath, LogLevel) -> maybe_check_crl(OtpCert, SslState, VerifyResult, CertPath, LogLevel); -cert_status_check(OtpCert, #{ocsp_state := #{ocsp_stapling := best_effort, %%TODO should we support +cert_status_check(_OtpCert, #{ocsp_state := #{ocsp_stapling := true, + ocsp_expect := undetermined}}, + _VerifyResult, _CertPath, _LogLevel) -> + {bad_cert, {revocation_status_undetermined, not_stapled}}; +cert_status_check(OtpCert, #{ocsp_state := #{ocsp_stapling := best_effort, %% TODO support this ? ocsp_expect := undetermined}} = SslState, VerifyResult, CertPath, LogLevel) -> - maybe_check_crl(OtpCert, SslState, VerifyResult, CertPath, LogLevel). + maybe_check_crl(OtpCert, SslState, VerifyResult, CertPath, LogLevel); +cert_status_check(_OtpCert, #{ocsp_state := #{ocsp_stapling := true, + ocsp_expect := no_staple}}, + _VerifyResult, _CertPath, _LogLevel) -> + {bad_cert, {revocation_status_undetermined, not_stapled}}. maybe_check_crl(_, #{crl_check := false}, _, _, _) -> valid; diff --git a/lib/ssl/test/make_certs.erl b/lib/ssl/test/make_certs.erl index 8577397ac0..0efa776be2 100644 --- a/lib/ssl/test/make_certs.erl +++ b/lib/ssl/test/make_certs.erl @@ -88,7 +88,7 @@ all(DataDir, PrivDir, C = #config{}) -> create_rnd(DataDir, PrivDir), % For all requests rootCA(PrivDir, "erlangCA", C), intermediateCA(PrivDir, "otpCA", "erlangCA", C), - endusers(PrivDir, "otpCA", ["client", "server", "revoked", "a.server", "b.server"], C), + endusers(PrivDir, "otpCA", ["client", "server", "revoked", "undetermined", "a.server", "b.server"], C), endusers(PrivDir, "erlangCA", ["localhost"], C), %% Create keycert files SDir = filename:join([PrivDir, "server"]), @@ -107,6 +107,12 @@ all(DataDir, PrivDir, C = #config{}) -> RKC = filename:join([RDir, "keycert.pem"]), revoke(PrivDir, "otpCA", "revoked", C), append_files([RK, RC], RKC), + MDir = filename:join([PrivDir, "undetermined"]), + MC = filename:join([MDir, "cert.pem"]), + MK = filename:join([MDir, "key.pem"]), + MKC = filename:join([MDir, "keycert.pem"]), + remove_entry(PrivDir, "otpCA", "undetermined", C), + append_files([MK, MC], MKC), remove_rnd(PrivDir), {ok, C}. @@ -177,6 +183,18 @@ revoke(Root, CA, User, C) -> cmd(Cmd, Env), gencrl(Root, CA, C). +%% Remove the certificate's entry from the database. The OCSP responder +%% will consider the certificate unknown. +remove_entry(Root, CA, User, C) -> + Db = filename:join([Root, CA, "index.txt"]), + Cmd = ["grep", " -v" + " \"/CN=", User ,"/\" ", Db, + " > ", Db, "~new"], + cmd(Cmd, []), + Cmd2 = ["mv ", Db, "~new ", Db], + cmd(Cmd2, []), + gencrl(Root, CA, C). + gencrl(Root, CA, C) -> %% By default, the CRL is valid for a week from now. gencrl(Root, CA, C, 24*7). diff --git a/lib/ssl/test/openssl_ocsp_SUITE.erl b/lib/ssl/test/openssl_ocsp_SUITE.erl index d328a3cfbd..f4a68f7543 100644 --- a/lib/ssl/test/openssl_ocsp_SUITE.erl +++ b/lib/ssl/test/openssl_ocsp_SUITE.erl @@ -37,7 +37,9 @@ -export([ocsp_stapling_basic/0,ocsp_stapling_basic/1, ocsp_stapling_with_nonce/0, ocsp_stapling_with_nonce/1, ocsp_stapling_with_responder_cert/0,ocsp_stapling_with_responder_cert/1, - ocsp_stapling_revoked/0, ocsp_stapling_revoked/1 + ocsp_stapling_revoked/0, ocsp_stapling_revoked/1, + ocsp_stapling_undetermined/0, ocsp_stapling_undetermined/1, + ocsp_stapling_no_staple/0, ocsp_stapling_no_staple/1 ]). %% spawn export @@ -61,7 +63,9 @@ ocsp_tests() -> [ocsp_stapling_basic, ocsp_stapling_with_nonce, ocsp_stapling_with_responder_cert, - ocsp_stapling_revoked + ocsp_stapling_revoked, + ocsp_stapling_undetermined, + ocsp_stapling_no_staple ]. %%-------------------------------------------------------------------- @@ -254,6 +258,69 @@ ocsp_stapling_revoked(Config) ssl_test_lib:check_client_alert(Client, certificate_revoked). +%%-------------------------------------------------------------------- +ocsp_stapling_undetermined() -> + [{doc, "Verify OCSP stapling works with certificate with undetermined status."}]. +ocsp_stapling_undetermined(Config) + when is_list(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + CACertsFile = filename:join(PrivDir, "undetermined/cacerts.pem"), + + GroupName = proplists:get_value(group, Config), + ServerOpts = [{log_level, debug}, + {group, GroupName}], + {ClientNode, _ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server(openssl_ocsp_undetermined, + [{options, ServerOpts}], Config), + Port = ssl_test_lib:inet_port(Server), + + ClientOpts = [{log_level, debug}, + {verify, verify_peer}, + {server_name_indication, disable}, + {cacertfile, CACertsFile}, + {ocsp_stapling, true}, + {ocsp_nonce, true} + ] ++ dtls_client_opt(GroupName), + + Client = ssl_test_lib:start_client_error([{node, ClientNode},{port, Port}, + {host, Hostname}, {from, self()}, + {options, ClientOpts}]), + + ssl_test_lib:check_client_alert(Client, bad_certificate). + +%%-------------------------------------------------------------------- +ocsp_stapling_no_staple() -> + [{doc, "Verify OCSP stapling works with a missing OCSP response."}]. +ocsp_stapling_no_staple(Config) + when is_list(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + CACertsFile = filename:join(PrivDir, "a.server/cacerts.pem"), + + GroupName = proplists:get_value(group, Config), + ServerOpts = [{log_level, debug}, + {group, GroupName}], + {ClientNode, _ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + %% Start a server that will not include an OCSP response. + Server = ssl_test_lib:start_server(openssl, + [{options, ServerOpts}], Config), + Port = ssl_test_lib:inet_port(Server), + + ClientOpts = [{log_level, debug}, + {verify, verify_peer}, + {server_name_indication, disable}, + {cacertfile, CACertsFile}, + {ocsp_stapling, true}, + {ocsp_nonce, true} + ] ++ dtls_client_opt(GroupName), + + Client = ssl_test_lib:start_client_error([{node, ClientNode},{port, Port}, + {host, Hostname}, {from, self()}, + {options, ClientOpts}]), + + ssl_test_lib:check_client_alert(Client, bad_certificate). + %%-------------------------------------------------------------------- %% Intrernal functions ----------------------------------------------- %%-------------------------------------------------------------------- diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index c17883bd6f..ea2ad41c7a 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -228,6 +228,8 @@ start_server(openssl_ocsp, Options, Config) -> start_openssl_server(openssl_ocsp, Options, Config); start_server(openssl_ocsp_revoked, Options, Config) -> start_openssl_server(openssl_ocsp_revoked, Options, Config); +start_server(openssl_ocsp_undetermined, Options, Config) -> + start_openssl_server(openssl_ocsp_undetermined, Options, Config); start_server(Type, _Args, _Config) -> {error, unsupported_server_type, Type}. @@ -266,13 +268,22 @@ get_server_opts(openssl_ocsp_revoked, Config) -> Cert = filename:join(PrivDir, "revoked/cert.pem"), Key = filename:join(PrivDir, "revoked/key.pem"), CACerts = filename:join(PrivDir, "revoked/cacerts.pem"), + SOpts = [{reuseaddr, true}, + {cacertfile, CACerts}, + {certfile, Cert}, + {keyfile, Key}], + ssl_options(SOpts, Config); +get_server_opts(openssl_ocsp_undetermined, Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + Cert = filename:join(PrivDir, "undetermined/cert.pem"), + Key = filename:join(PrivDir, "undetermined/key.pem"), + CACerts = filename:join(PrivDir, "undetermined/cacerts.pem"), SOpts = [{reuseaddr, true}, {cacertfile, CACerts}, {certfile, Cert}, {keyfile, Key}], ssl_options(SOpts, Config). - get_client_opts(Config) -> DCOpts = proplists:get_value(client_ecdsa_opts, Config), COpts = proplists:get_value(client_opts, Config, DCOpts), @@ -724,7 +735,8 @@ init_openssl_server(openssl, _, Options) -> openssl_server_loop(Pid, SslPort, Args); init_openssl_server(Mode, ResponderPort, Options) when Mode == openssl_ocsp orelse - Mode == openssl_ocsp_revoked -> + Mode == openssl_ocsp_revoked orelse + Mode == openssl_ocsp_undetermined -> DefaultVersions = default_tls_version(Options), [Version | _] = proplists:get_value(versions, Options, DefaultVersions), Port = inet_port(node()), -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor