diff options
Diffstat (limited to 'lib/ssl/src/ssl_certificate.erl')
-rw-r--r-- | lib/ssl/src/ssl_certificate.erl | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl index 674870dd15..0b4211e1c3 100644 --- a/lib/ssl/src/ssl_certificate.erl +++ b/lib/ssl/src/ssl_certificate.erl @@ -75,7 +75,7 @@ trusted_cert_and_paths(Chain, CertDbHandle, CertDbRef, PartialChainHandler) -> %% If the chain contains extraneous certificates there could be %% more than one possible path such chains might be used to phase out %% an old certificate. - Paths = paths(Chain, CertDbHandle, CertDbRef), + Paths = paths(Chain, CertDbHandle), lists:map(fun(Path) -> case handle_partial_chain(Path, PartialChainHandler, CertDbHandle, CertDbRef) of {unknown_ca, _} = Result -> @@ -86,8 +86,7 @@ trusted_cert_and_paths(Chain, CertDbHandle, CertDbRef, PartialChainHandler) -> Result -> Result end - end, Paths). - + end, Paths). %%-------------------------------------------------------------------- -spec certificate_chain(undefined | binary() | #'OTPCertificate'{} , db_handle(), certdb_ref() | {extracted, list()}) -> {error, no_cert} | {ok, der_cert() | undefined, [der_cert()]}. @@ -439,38 +438,38 @@ pre_1_3_hash(sha1) -> pre_1_3_hash(Hash) -> Hash. -paths(Chain, CertDbHandle, CertDbRef) -> - paths(Chain, Chain, CertDbHandle, CertDbRef, []). +paths(Chain, CertDbHandle) -> + paths(Chain, Chain, CertDbHandle, []). -paths([Root], _, _, _, Path) -> - [[Root | Path]]; -paths([Cert1, Cert2 | Rest], Chain, CertDbHandle, CertDbRef, Path) -> +paths([Root], _, _, Path) -> + [[Root | Path]]; +paths([Cert1, Cert2 | Rest], Chain, CertDbHandle, Path) -> case public_key:pkix_is_issuer(Cert1, Cert2) of true -> %% Chain orded so far - paths([Cert2 | Rest], Chain, CertDbHandle, CertDbRef, [Cert1 | Path]); + paths([Cert2 | Rest], Chain, CertDbHandle, [Cert1 | Path]); false -> %% Chain is unorded and/or contains extraneous certificates - unorded_or_extraneous(Chain, CertDbHandle, CertDbRef) + unorded_or_extraneous(Chain, CertDbHandle) end. - -unorded_or_extraneous([Peer | FalseChain], CertDbHandle, CertDbRef) -> - ChainCandidates = extraneous_chains(FalseChain), - lists:map(fun(Candidate) -> - path_candidate(Peer, Candidate, CertDbHandle, CertDbRef) - end, + +unorded_or_extraneous([Peer | UnorderedChain], CertDbHandle) -> + ChainCandidates = extraneous_chains(UnorderedChain), + lists:map(fun(Candidate) -> + path_candidate(Peer, Candidate, CertDbHandle) + end, ChainCandidates). -path_candidate(Peer, ChainCandidateCAs, CertDbHandle, _CertDbRef) -> +path_candidate(Peer, ChainCandidateCAs, CertDbHandle) -> {ok, ExtractedCerts} = ssl_pkix_db:extract_trusted_certs({der, ChainCandidateCAs}), - %% certificate_chain/4 will make sure the chain is ordered - case certificate_chain(Peer, CertDbHandle, ExtractedCerts, []) of + %% certificate_chain/4 will make sure the chain is ordered + case certificate_chain(Peer, CertDbHandle, ExtractedCerts, []) of {ok, undefined, Chain} -> lists:reverse(Chain); {ok, Root, Chain} -> [Root | lists:reverse(Chain)] - end. - + end. + handle_partial_chain([IssuerCert| Rest] = Path, PartialChainHandler, CertDbHandle, CertDbRef) -> case public_key:pkix_is_self_signed(IssuerCert) of true -> %% IssuerCert = ROOT (That is ROOT was included in chain) @@ -533,7 +532,12 @@ handle_incomplete_chain([PeerCert| _] = Chain0, PartialChainHandler, Default, Ce %% See if we have the certificates to rebuild it. case certificate_chain(PeerCert, CertDbHandle, CertDbRef) of {ok, _, [PeerCert | _] = Chain} when Chain =/= Chain0 -> %% Chain candidate found - handle_partial_chain(lists:reverse(Chain), PartialChainHandler, CertDbHandle, CertDbRef); + case lists:prefix(Chain0, Chain) of + true -> + handle_partial_chain(lists:reverse(Chain), PartialChainHandler, CertDbHandle, CertDbRef); + false -> + Default + end; _ -> Default end. @@ -546,8 +550,8 @@ extraneous_chains(Certs) -> Subjects = [{subject(Cert), Cert} || Cert <- Certs], Duplicates = find_duplicates(Subjects), %% Number of certs with duplicates (same subject) has been limited - %% to two and the maximum number of combinations is limited to 4. - build_candidates(Duplicates, 2, 4). + %% to 4 and the maximum number of combinations is limited to 16. + build_candidates(Duplicates, 4, 16). build_candidates(Map, Duplicates, Combinations) -> Subjects = maps:keys(Map), @@ -568,7 +572,7 @@ build_candidates([H|T], Map, Duplicates, Combinations, Max, Acc0) -> Acc = [[Cert|L] || Cert <- Certs, L <- Acc0], build_candidates(T, Map, Duplicates - 1, Combinations * Counter, Max, Acc) end; - {[Cert|_], _} -> + {[Cert|_Throw], _Counter} -> case Acc0 of [] -> Acc = [[Cert]], |