@@ -6,11 +6,6 @@ Filesystem `api_module` for grisp_keychain
66Implements the keychain API for direct filesystem based access to certificates and keys.
77""" .
88
9- % --- Includes ------------------------------------------------------------------
10-
11- -include_lib (" kernel/include/file.hrl" ).
12-
13-
149% --- Exports -------------------------------------------------------------------
1510
1611% API functions
@@ -29,158 +24,33 @@ Implements the keychain API for direct filesystem based access to certificates a
2924
3025tls_options (DomainName ) ->
3126 {CertsKeys , ClientTrustedCerts } =
32- case tls_use_client_certificate () of
27+ case grisp_keychain_utils : use_client_certificate () of
3328 false -> {[], []};
3429 true ->
3530 ClientCerts = client_certs (),
3631 ClientKey = client_key (),
37- TrustedCerts = client_trusted_certs (ClientCerts ),
32+ TrustedCerts = grisp_keychain_utils : client_trusted_certs (),
3833 {certs_keys_config (ClientCerts , ClientKey ), TrustedCerts }
3934 end ,
40- DomainNameStr = domain_name (DomainName ),
41- ServerNameIndication = server_name_indication (DomainNameStr ),
42- case tls_verify () of
43- verify_none ->
44- [{verify , verify_none },
45- {server_name_indication , ServerNameIndication },
46- {cacerts , ClientTrustedCerts }
47- | CertsKeys ];
48- verify_peer ->
49- ServerTrustedCerts = server_trusted_certs (DomainNameStr ),
50- [{verify , verify_peer },
51- {depth , 99 },
52- {cacerts , ClientTrustedCerts ++ ServerTrustedCerts },
53- {server_name_indication , ServerNameIndication },
54- {customize_hostname_check , [
55- {match_fun , public_key :pkix_verify_hostname_match_fun (https )}
56- ]}
57- | CertsKeys ]
58- end .
35+ grisp_keychain_utils :build_tls_options (DomainName , CertsKeys , ClientTrustedCerts ).
5936
6037read_cert (primary , der ) ->
6138 [PemBin |_ ] = client_certs (),
6239 PemBin .
6340
6441% --- Internal Functions --------------------------------------------------------
6542
66- locate_test_dir (BasePath ) ->
67- BuildTestDir = filename :join (BasePath , " test" ),
68- case filelib :is_dir (BuildTestDir ) of
69- true -> BuildTestDir ;
70- false ->
71- % no "test" directory, try to follow "src" link...
72- SrcDir = filename :join (BasePath , " src" ),
73- case file :read_link (SrcDir ) of
74- {error , einval } ->
75- throw ({test_directory_not_found , BasePath });
76- {ok , SrcTargetDir } ->
77- AbsSrcTargetDir = filename :absname (SrcTargetDir , BasePath ),
78- AbsSrcParentDir = filename :dirname (AbsSrcTargetDir ),
79- SrcTestDir = filename :join (AbsSrcParentDir , " test" ),
80- case filelib :is_dir (SrcTestDir ) of
81- true -> SrcTestDir ;
82- false ->
83- throw ({test_directory_not_found , AbsSrcParentDir })
84- end
85- end
86- end .
87-
88- resolve_path (undefined ) -> undefined ;
89- resolve_path (AbsPath ) when is_list (AbsPath ) -> AbsPath ;
90- resolve_path (AbsPath ) when is_binary (AbsPath ) ->
91- unicode :characters_to_list (AbsPath );
92- resolve_path ({Tag , AppName , RelPath })
93- when is_atom (Tag ), is_atom (AppName ), is_binary (RelPath ) ->
94- resolve_path ({Tag , AppName , unicode :characters_to_list (RelPath )});
95- resolve_path ({priv , AppName , RelPath })
96- when is_atom (AppName ), is_list (RelPath ) ->
97- case code :priv_dir (AppName ) of
98- {error , bad_name } -> throw ({bad_appname , AppName });
99- BasePath -> filename :join (BasePath , RelPath )
100- end ;
101- resolve_path ({test , AppName , RelPath })
102- when is_atom (AppName ), is_list (RelPath ) ->
103- % Only meaningfull for tests, as the test directory is copied into _build
104- case code :lib_dir (AppName ) of
105- {error , bad_name } -> throw ({bad_appname , AppName });
106- BasePath ->
107- TestDir = locate_test_dir (BasePath ),
108- filename :join (TestDir , RelPath )
109- end .
110-
111- get_config (Key ) ->
112- application :get_env (grisp_keychain , Key ).
113-
114- get_config_path (Key ) ->
115- case get_config (Key ) of
116- undefined -> undefined ;
117- {ok , PathSpec } -> {ok , resolve_path (PathSpec )}
118- end .
119-
120- get_config_path (Key , DefaultPathSpec ) ->
121- case get_config (Key ) of
122- undefined -> resolve_path (DefaultPathSpec );
123- {ok , PathSpec } -> resolve_path (PathSpec )
124- end .
125-
126- get_config_cb (Key , Default ) ->
127- case application :get_env (grisp_keychain , Key ) of
128- undefined -> Default ;
129- {ok , undefined } -> Default ;
130- {ok , {ModName , FunName }}
131- when is_atom (ModName ), is_atom (FunName ) ->
132- ModName :FunName ();
133- {ok , {ModName , FunName , FunArgs }}
134- when is_atom (ModName ), is_atom (FunName ) ->
135- erlang :apply (ModName , FunName , FunArgs )
136- end .
137-
138- tls_use_client_certificate () ->
139- case get_config (tls_use_client_certificate ) of
140- undefined -> true ;
141- {ok , Flag } when is_boolean (Flag ) -> Flag
142- end .
143-
144- tls_server_trusted_certs (DomainName ) ->
145- case get_config_path (tls_server_trusted_certs ) of
146- undefined -> [];
147- {ok , BasePath } ->
148- FilePath = filename :join (BasePath , DomainName ),
149- try load_cert_file (FilePath , [" .pem" , " .crt" ])
150- catch throw :_Reason -> []
151- end
152- end .
153-
154- tls_server_trusted_certs_cb () ->
155- get_config_cb (tls_server_trusted_certs_cb , []).
156-
157- tls_client_trusted_certs () ->
158- DefaultClientPath = {priv , grisp_keychain , " " },
159- BasePath = get_config_path (tls_client_trusted_certs , DefaultClientPath ),
160- try load_certs (BasePath )
161- catch throw :_Reason -> []
162- end .
163-
164- tls_client_trusted_certs_cb () ->
165- get_config_cb (tls_client_trusted_certs_cb , []).
166-
167- tls_verify () ->
168- case get_config (tls_verify ) of
169- undefined -> verify_peer ;
170- {ok , Value } when Value =:= verify_none ; Value =:= verify_peer -> Value
171- end .
172-
17343client_certs () ->
174- case get_config_path (client_certs ) of
44+ case grisp_keychain_utils : get_config_path (client_certs ) of
17545 undefined -> throw (no_client_certificates );
176- {ok , Path } -> load_certs (Path )
46+ {ok , Path } -> grisp_keychain_utils : load_certs (Path )
17747 end .
17848
17949
18050client_key () ->
181- case get_config_path (client_key ) of
51+ case grisp_keychain_utils : get_config_path (client_key ) of
18252 undefined -> throw (no_client_key );
183- {ok , Path } -> load_key (Path )
53+ {ok , Path } -> grisp_keychain_utils : load_key (Path )
18454 end .
18555
18656certs_keys_config (ClientCerts , ClientKey ) ->
@@ -189,85 +59,8 @@ certs_keys_config(ClientCerts, ClientKey) ->
18959 key => ClientKey
19060 }]}].
19161
192- domain_name (undefined ) -> undefined ;
193- domain_name (Name ) when is_atom (Name ) -> atom_to_list (Name );
194- domain_name (Name ) when is_list (Name ) -> Name ;
195- domain_name (Name ) when is_binary (Name ) -> unicode :characters_to_list (Name ).
196-
197- server_name_indication (undefined ) -> disabled ;
198- server_name_indication (DomainName ) -> DomainName .
199-
200- server_trusted_certs (undefined ) ->
201- tls_server_trusted_certs_cb ();
202- server_trusted_certs (DomainName ) ->
203- tls_server_trusted_certs (DomainName ) ++ tls_server_trusted_certs_cb ().
204-
205- client_trusted_certs (_ClientCerts ) ->
206- tls_client_trusted_certs () ++ tls_client_trusted_certs_cb ().
207-
20862load_key (FilePath ) ->
209- case file :read_file (FilePath ) of
210- {error , enoent } ->
211- throw ({file_not_found , FilePath });
212- {ok , PemData } ->
213- case public_key :pem_decode (PemData ) of
214- [] ->
215- throw ({invalid_key , FilePath });
216- [{Asn1Type , DerData , not_encrypted }] ->
217- {Asn1Type , DerData };
218- [{_Asn1Type , _DerData , _ }] ->
219- throw (encrypted_key_not_supported );
220- [_ |_ ] ->
221- throw (multiple_key_not_supported )
222- end
223- end .
63+ grisp_keychain_utils :load_key (FilePath ).
22464
22565load_certs (FilePath ) ->
226- case filelib :is_dir (FilePath ) of
227- true -> load_cert_dir (FilePath , [" .pem" , " .crt" ]);
228- false -> load_cert_file (FilePath , [" " , " .pem" , " .crt" ])
229- end .
230-
231- load_cert_dir (DirPath , Extentions ) ->
232- case file :list_dir (DirPath ) of
233- {error , Reason } -> throw (Reason );
234- {ok , Files } ->
235- lists :foldl (fun (Filename , Acc ) ->
236- FullPath = filename :join (DirPath , Filename ),
237- Ext = filename :extension (Filename ),
238- IsFile = filelib :is_file (FullPath ),
239- HasExt = lists :member (Ext , Extentions ),
240- case IsFile and HasExt of
241- false -> Acc ;
242- true -> load_cert_file (FullPath ) ++ Acc
243- end
244- end , [], Files )
245- end .
246-
247- load_cert_file (FilePath , []) ->
248- {ok , Cwd } = file :get_cwd (),
249- throw ({certificate_not_found , FilePath , Cwd });
250- load_cert_file (FilePath , [Ext | Rest ]) ->
251- FullPath = FilePath ++ Ext ,
252- case filelib :is_file (FullPath ) of
253- true -> load_cert_file (FullPath );
254- false -> load_cert_file (FilePath , Rest )
255- end .
256-
257- load_cert_file (FilePath ) ->
258- case file :read_file (FilePath ) of
259- {error , enoent } ->
260- throw ({certificate_not_found , FilePath });
261- {ok , PemData } ->
262- decode_certs (PemData )
263- end .
264-
265- decode_certs (PemData ) ->
266- decode_certs (public_key :pem_decode (PemData ), []).
267-
268- decode_certs ([], Acc ) ->
269- lists :reverse (Acc );
270- decode_certs ([{'Certificate' , D , not_encrypted } | Rest ], Acc ) ->
271- decode_certs (Rest , [D | Acc ]);
272- decode_certs ([Bad | _Rest ], _Acc ) ->
273- throw ({bad_certificate , Bad }).
66+ grisp_keychain_utils :load_certs (FilePath ).
0 commit comments