./ct_report/coverage/cert_utils.COVER.html

1 %%%=============================================================================
2 %%% @copyright (C) 1999-2018, Erlang Solutions Ltd
3 %%% @author Denys Gonchar <denys.gonchar@erlang-solutions.com>
4 %%% @doc a dedicated module to provide SSL certificate parsing functionality.
5 %%% @end
6 %%%=============================================================================
7 -module(cert_utils).
8 -copyright("2018, Erlang Solutions Ltd.").
9 -author('denys.gonchar@erlang-solutions.com').
10
11 -include("mongoose_logger.hrl").
12
13 -export([get_cert_domains/1,
14 get_common_name/1,
15 get_xmpp_addresses/1
16 ]).
17
18 -include_lib("public_key/include/public_key.hrl").
19 -include("XmppAddr.hrl").
20 -include("jlib.hrl").
21
22 -type certificate() :: #'Certificate'{}.
23
24 -spec get_common_name(certificate()) -> bitstring() | error.
25 get_common_name(Cert) ->
26 70 try
27 70 {rdnSequence, RDNSequence} = Cert#'Certificate'.tbsCertificate#'TBSCertificate'.subject,
28 70 [{ok, {_, CN}}] = ['OTP-PUB-KEY':decode('X520CommonName', V) ||
29 70 AtributesList <- RDNSequence,
30 79 #'AttributeTypeAndValue'{type = ?'id-at-commonName', value = V} <- AtributesList],
31 70 CN
32 catch
33 Class:Exception:StackTrace ->
34
:-(
log_exception(Cert, Class, Exception, StackTrace),
35
:-(
error
36 end.
37
38
39 -spec get_xmpp_addresses(certificate()) -> [bitstring()].
40 get_xmpp_addresses(Cert) ->
41 70 try
42 70 Extensions = Cert#'Certificate'.tbsCertificate#'TBSCertificate'.extensions,
43 70 [BinVal] = [convert_to_bin(V) ||
44 70 #'Extension'{extnID = ?'id-ce-subjectAltName', extnValue = V} <- Extensions],
45 70 {ok, SANs} = 'OTP-PUB-KEY':decode('SubjectAltName', BinVal),
46 70 XmppAddresses =
47 [begin
48 55 case 'XmppAddr':decode('XmppAddr', V) of
49 55 {ok, XmppAddr} -> XmppAddr;
50 Error ->
51
:-(
?LOG_DEBUG(#{what => get_xmpp_addresses_failed,
52 text => <<"'XmppAddr':decode/2 failed">>,
53
:-(
cert => Cert, reason => Error}),
54
:-(
ok
55 end
56 70 end || {otherName, #'AnotherName'{'type-id' = ?'id-on-xmppAddr', value = V}} <- SANs],
57 70 [Addr || Addr <- XmppAddresses, is_binary(Addr)]
58 catch
59 Class:Exception:StackTrace ->
60
:-(
log_exception(Cert, Class, Exception,StackTrace),
61
:-(
[]
62 end.
63
64
65 -spec get_dns_addresses(certificate()) -> [string()].
66 get_dns_addresses(Cert) ->
67 3 try
68 3 Extensions = Cert#'Certificate'.tbsCertificate#'TBSCertificate'.extensions,
69 3 [BinVal] = [convert_to_bin(V) ||
70 3 #'Extension'{extnID = ?'id-ce-subjectAltName', extnValue = V} <- Extensions],
71 3 {ok, SANs} = 'OTP-PUB-KEY':decode('SubjectAltName', BinVal),
72 3 [DNS || {dNSName, DNS} <- SANs]
73 catch
74 Class:Exception:StackTrace ->
75
:-(
log_exception(Cert, Class, Exception, StackTrace),
76
:-(
[]
77 end.
78
79
80 -spec get_cert_domains(certificate()) -> [bitstring()].
81 get_cert_domains(Cert) ->
82 3 CN = get_common_name(Cert),
83 3 Addresses = get_xmpp_addresses(Cert),
84 3 Domains = get_dns_addresses(Cert),
85 3 lists:append([get_lserver_from_addr(CN, false) |
86
:-(
[get_lserver_from_addr(Addr, true) || Addr <- Addresses, is_binary(Addr)] ++
87 18 [get_lserver_from_addr(DNS, false) || DNS <- Domains, is_list(DNS)]]).
88
89
90 convert_to_bin(Val) when is_list(Val) ->
91 18 list_to_binary(Val);
92 convert_to_bin(Val) ->
93 76 Val.
94
95 -spec get_lserver_from_addr(bitstring() | string(), boolean()) -> [bitstring()].
96 get_lserver_from_addr(V, UTF8) when is_binary(V); is_list(V) ->
97 21 Val = convert_to_bin(V),
98 21 case {jid:from_binary(Val), UTF8} of
99 {#jid{luser = <<"">>, lserver = LD, lresource = <<"">>}, true} ->
100
:-(
case mongoose_s2s_lib:domain_utf8_to_ascii(LD) of
101
:-(
false -> [];
102
:-(
PCLD -> [PCLD]
103 end;
104 6 {#jid{luser = <<"">>, lserver = LD, lresource = <<"">>}, _} -> [LD];
105 15 _ -> []
106 end;
107
:-(
get_lserver_from_addr(_, _) -> [].
108
109
110 log_exception(_Cert, Class, Exception, StackTrace) ->
111
:-(
?LOG_ERROR(#{what => <<"cert_parsing_failed">>,
112 text => <<"failed to parse certificate">>,
113
:-(
class => Class, reason => Exception, stacktrace => StackTrace}).
Line Hits Source