From e501709bec61bf8813cab741b0e39c211c73c89e Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 27 Sep 2010 13:59:29 +0200 Subject: Peer awarness Changed the verify fun so that it differentiate between the peer certificate and CA certificates by using valid_peer or valid as the second argument to the verify fun. It may not always be trivial or even possible to know when the peer certificate is reached otherwise. --- lib/public_key/include/public_key.hrl | 2 ++ lib/public_key/src/pubkey_cert.erl | 2 +- lib/public_key/src/public_key.appup.src | 4 ++-- lib/public_key/src/public_key.erl | 11 +++++++++-- lib/public_key/test/public_key_SUITE.erl | 2 ++ lib/ssl/doc/src/ssl.xml | 20 +++++++++++++------- lib/ssl/src/ssl.erl | 4 ++++ lib/ssl/src/ssl_certificate.erl | 2 ++ lib/ssl/test/ssl_basic_SUITE.erl | 6 +++++- 9 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl index a16eb10fe6..4950597fb5 100644 --- a/lib/public_key/include/public_key.hrl +++ b/lib/public_key/include/public_key.hrl @@ -34,6 +34,8 @@ (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> + {valid, UserState}; + (_, valid_peer, UserState) -> {valid, UserState} end, []}). diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl index e704c168f1..d8d999a944 100644 --- a/lib/public_key/src/pubkey_cert.erl +++ b/lib/public_key/src/pubkey_cert.erl @@ -291,7 +291,7 @@ is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate = %%-------------------------------------------------------------------- -spec verify_fun(#'OTPTBSCertificate'{}, {bad_cert, atom()} | {extension, #'Extension'{}}| - valid, term(), fun()) -> term(). + valid | valid_peer, term(), fun()) -> term(). %% %% Description: Gives the user application the opportunity handle path %% validation errors and unknown extensions and optional do other diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src index c9d15b8747..d18cfd3536 100644 --- a/lib/public_key/src/public_key.appup.src +++ b/lib/public_key/src/public_key.appup.src @@ -6,7 +6,7 @@ {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []}, {update, public_key, soft, soft_purge, soft_purge, []}, {update, pubkey_pem, soft, soft_purge, soft_purge, []}, - {update, pubkey_cert_records, soft, soft_purge, soft_purge, []} + {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}, {update, pubkey_cert, soft, soft_purge, soft_purge, []} ] }, @@ -36,7 +36,7 @@ {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []}, {update, public_key, soft, soft_purge, soft_purge, []}, {update, pubkey_pem, soft, soft_purge, soft_purge, []}, - {update, pubkey_cert_records, soft, soft_purge, soft_purge, []} + {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}, {update, pubkey_cert, soft, soft_purge, soft_purge, []} ] }, diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 9c7817fa8e..c449c430fb 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -557,9 +557,16 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer, %% We want the key_usage extension to be checked before we validate %% the signature. - UserState0 = pubkey_cert:validate_signature(OtpCert, DerCert, + UserState6 = pubkey_cert:validate_signature(OtpCert, DerCert, Key, KeyParams, UserState5, VerifyFun), - UserState = pubkey_cert:verify_fun(OtpCert, valid, UserState0, VerifyFun), + UserState = case Last of + false -> + pubkey_cert:verify_fun(OtpCert, valid, UserState6, VerifyFun); + true -> + pubkey_cert:verify_fun(OtpCert, valid_peer, + UserState6, VerifyFun) + end, + ValidationState = ValidationState1#path_validation_state{user_state = UserState}, diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl index ea6a925139..4d76ad7bd4 100644 --- a/lib/public_key/test/public_key_SUITE.erl +++ b/lib/public_key/test/public_key_SUITE.erl @@ -379,6 +379,8 @@ pkix_path_validation(Config) when is_list(Config) -> (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> + {valid, UserState}; + (_, valid_peer, UserState) -> {valid, UserState} end, []}, {ok, _} = diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index d5b7253ef3..9d31282a44 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -202,10 +202,10 @@

The verification fun should be defined as:

-fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} | +fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | {extension, #'Extension'{}}, InitialUserState :: term()) -> - {valid, UserState :: term()} | {fail, Reason :: term()} | - {unknown, UserState :: term()}. + {valid, UserState :: term()} | {valid_peer, UserState :: term()} | + {fail, Reason :: term()} | {unknown, UserState :: term()}.

The verify fun will be called during the X509-path @@ -213,10 +213,12 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} | application is encountered. Additionally it will be called when a certificate is considered valid by the path validation to allow access to each certificate in the path to the user - application. + application. Note that the it will differentiate between + the peer certificate and CA certificates by using valid_peer + or valid as the second argument to the verify fun. See public_key(3) - for definition of #'OtpCertificate'{} and #'Extension'{}.

+ for definition of #'OTPCertificate'{} and #'Extension'{}.

If the verify callback fun returns {fail, Reason}, the verification process is immediately stopped and an alert is @@ -237,7 +239,9 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} | (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> - {valid, UserState} + {valid, UserState}; + (_, valid_peer, UserState) -> + {valid, UserState} end, []} @@ -251,7 +255,9 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} | (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> - {valid, UserState} + {valid, UserState}; + (_, valid_peer, UserState) -> + {valid, UserState} end, []} diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 12dffb413c..7a3b24c783 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -537,6 +537,8 @@ handle_options(Opts0, _Role) -> (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> + {valid, UserState}; + (_, valid_peer, UserState) -> {valid, UserState} end, []}, @@ -635,6 +637,8 @@ validate_option(verify_fun, Fun) when is_function(Fun) -> (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> + {valid, UserState}; + (_, valid_peer, UserState) -> {valid, UserState} end, Fun}; validate_option(verify_fun, {Fun, _} = Value) when is_function(Fun) -> diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl index 206024315e..714c94270d 100644 --- a/lib/ssl/src/ssl_certificate.erl +++ b/lib/ssl/src/ssl_certificate.erl @@ -129,6 +129,8 @@ validate_extension(_, {bad_cert, _} = Reason, _) -> validate_extension(_, {extension, _}, Role) -> {unknown, Role}; validate_extension(_, valid, Role) -> + {valid, Role}; +validate_extension(_, valid_peer, Role) -> {valid, Role}. %%-------------------------------------------------------------------- diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index 3cb9337775..fade67f3ba 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -2857,11 +2857,13 @@ unknown_server_ca_fail(Config) when is_list(Config) -> {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - FunAndState = {fun(_,{bad_cert, _} = Reason, _) -> + FunAndState = {fun(_,{bad_cert, unknown_ca} = Reason, _) -> {fail, Reason}; (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> + {valid, [test_to_update_user_state | UserState]}; + (_, valid_peer, UserState) -> {valid, UserState} end, []}, @@ -2930,6 +2932,8 @@ unknown_server_ca_accept_verify_peer(Config) when is_list(Config) -> (_,{extension, _}, UserState) -> {unknown, UserState}; (_, valid, UserState) -> + {valid, UserState}; + (_, valid_peer, UserState) -> {valid, UserState} end, []}, -- cgit v1.2.3