Skip to content

Commit

Permalink
Fix mixing loading from file or all files in a dir
Browse files Browse the repository at this point in the history
Previously it was either one or the other, so the latest commit
with Solaris fixes didn't work.
  • Loading branch information
dgud committed Oct 27, 2023
1 parent 852cf26 commit b200a72
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 17 deletions.
62 changes: 45 additions & 17 deletions lib/public_key/src/pubkey_os_cacerts.erl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
-module(pubkey_os_cacerts).

-include("public_key.hrl").
-include_lib("kernel/include/file.hrl").
-export([load/0, load/1, get/0, clear/0]).

-on_load(on_load/0).
Expand All @@ -46,15 +47,15 @@ get() ->
load() ->
case os:type() of
{unix, linux} ->
load_from_file(linux_paths());
load(linux_paths(), undefined);
{unix, openbsd} ->
load_from_file(bsd_paths());
load(bsd_paths(), undefined);
{unix, freebsd} ->
load_from_file(bsd_paths());
load(bsd_paths(), undefined);
{unix, netbsd} ->
load_from_file(bsd_paths());
load(bsd_paths(), undefined);
{unix, sunos} ->
load_from_files(sunos_paths());
load(sunos_paths(), undefined);
{win32, _} ->
load_win32();
{unix, darwin} ->
Expand All @@ -68,24 +69,53 @@ load() ->
%% Can be used when load/0 doesn't work for an unsupported os type.
-spec load([file:filename_all()]) -> ok | {error, Reason::term()}.
load(Paths) ->
load_from_file(Paths).

load(Paths, {error, enoent}).

%% cleanup persistent_key
-spec clear() -> boolean().
clear() ->
persistent_term:erase(?MODULE).

load([Path|Paths], Error) ->
case dir_or_file(Path) of
enoent ->
load(Paths, Error);
directory ->
case load_from_files(Path) of
ok -> ok;
Err -> load(Paths, Err)
end;
file ->
case load_from_file(Path) of
ok -> ok;
Err -> load(Paths, Err)
end
end;
load([], Error) ->
Error.

dir_or_file(Path) ->
case file:read_file_info(Path) of
{ok, #file_info{type = directory}} ->
directory;
{ok, #file_info{type = regular}} ->
file;
{ok, #file_info{}} ->
case filelib:is_dir(Path) of
true -> directory;
false -> file
end;
{error, _} -> enoent
end.

%% Implementation
load_from_file([Path|Paths]) when is_list(Path); is_binary(Path) ->
load_from_file(Path) when is_list(Path); is_binary(Path) ->
try
{ok, Binary} = file:read_file(Path),
ok = decode_result(Binary)
catch _:_Reason ->
load_from_file(Paths)
end;
load_from_file([]) ->
{error, enoent}.
{error, enoent}
end.

decode_result(Binary) ->
try
Expand All @@ -103,7 +133,6 @@ decode_result(Binary) ->
{error, Reason}
end.


load_from_files(Path) ->
MakeCert = fun(FileName, Acc) ->
try
Expand All @@ -118,7 +147,6 @@ load_from_files(Path) ->
Certs = filelib:fold_files(Path, ".*\.pem", false, MakeCert, []),
store(Certs).


load_win32() ->
Dec = fun({_Enc, Der}, Acc) ->
try
Expand Down Expand Up @@ -155,10 +183,10 @@ linux_paths() ->
].

bsd_paths() ->
["/usr/local/share/certs/ca-root-nss.crt",
"/etc/ssl/cert.pem",
["/etc/ssl/cert.pem",
"/etc/openssl/certs/cacert.pem", %% netbsd (if installed)
"/etc/openssl/certs/ca-certificates.crt"
"/etc/openssl/certs/ca-certificates.crt",
"/usr/local/share/certs/ca-root-nss.crt"
].

sunos_paths() ->
Expand Down
19 changes: 19 additions & 0 deletions lib/public_key/test/public_key_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1369,6 +1369,25 @@ cacerts_load() ->
cacerts_load(Config) ->
Datadir = proplists:get_value(data_dir, Config),
{error, enoent} = public_key:cacerts_load("/dummy.file"),

%% White box testing of paths loading
%% TestDirs
ok = pubkey_os_cacerts:load([filename:join(Datadir, "non_existing_dir"),
Datadir,
filename:join(Datadir, "cacerts.pem")
]),
true = 10 < length(public_key:cacerts_get()),
%% We currently pick the first found in input order
ok = pubkey_os_cacerts:load([filename:join(Datadir, "non_existing_file"),
filename:join(Datadir, "ldap_uri_cert.pem"),
filename:join(Datadir, "cacerts.pem")]),
1 = length(public_key:cacerts_get()),
ok = pubkey_os_cacerts:load([filename:join(Datadir, "non_existing_file"),
filename:join(Datadir, "cacerts.pem"),
filename:join(Datadir, "ldap_uri_cert.pem")]),
2 = length(public_key:cacerts_get()),

true = public_key:cacerts_clear(),
%% Load default OS certs
%% there is no default installed OS certs on netbsd
%% can be installed with 'pkgin install mozilla-rootcerts'
Expand Down

0 comments on commit b200a72

Please sign in to comment.