diff options
| author | Alexandru Scvortov <alexandru@rabbitmq.com> | 2010-09-07 13:09:17 +0100 |
|---|---|---|
| committer | Alexandru Scvortov <alexandru@rabbitmq.com> | 2010-09-07 13:09:17 +0100 |
| commit | 1250c50a0286a8aaf69bfb87f18ef14eaa81a720 (patch) | |
| tree | d0261892e2e474e82b3dee865dd1534f51c1a279 /src | |
| parent | 7edec1ac0319f8d8d0bb48260f5e5ee933d6ad7f (diff) | |
| download | rabbitmq-server-git-1250c50a0286a8aaf69bfb87f18ef14eaa81a720.tar.gz | |
moved ssl functions to a separate module + refactor
Diffstat (limited to 'src')
| -rw-r--r-- | src/rabbit_reader.erl | 105 | ||||
| -rw-r--r-- | src/rabbit_ssl.erl | 164 |
2 files changed, 168 insertions, 101 deletions
diff --git a/src/rabbit_reader.erl b/src/rabbit_reader.erl index bec0e1c116..8d2d6a6223 100644 --- a/src/rabbit_reader.erl +++ b/src/rabbit_reader.erl @@ -33,10 +33,6 @@ -include("rabbit_framing.hrl"). -include("rabbit.hrl"). --compile(export_all). - --include_lib("public_key/include/public_key.hrl"). - -export([start_link/3, info_keys/0, info/1, info/2, shutdown/2]). -export([system_continue/3, system_terminate/4, system_code_change/4]). @@ -70,7 +66,7 @@ send_pend, state, channels]). -define(CREATION_EVENT_KEYS, [pid, address, port, peer_address, peer_port, - ssl_cn, ssl_issuer, ssl_validity, + ssl_subject, ssl_issuer, ssl_validity, protocol, user, vhost, timeout, frame_max, client_properties]). @@ -823,11 +819,11 @@ i(peer_address, #v1{sock = Sock}) -> {ok, {A, _}} = rabbit_net:peername(Sock), A; i(ssl_issuer, #v1{sock = Sock}) -> - get_ssl_info(fun get_ssl_issuer/1, Sock); + get_ssl_info(fun rabbit_ssl:ssl_issuer/1, Sock); i(ssl_subject, #v1{sock = Sock}) -> - get_ssl_info(fun get_ssl_subject/1, Sock); + get_ssl_info(fun rabbit_ssl:ssl_subject/1, Sock); i(ssl_validity, #v1{sock = Sock}) -> - get_ssl_info(fun get_ssl_validity/1, Sock); + get_ssl_info(fun rabbit_ssl:ssl_validity/1, Sock); i(peer_port, #v1{sock = Sock}) -> {ok, {_, P}} = rabbit_net:peername(Sock), P; @@ -877,99 +873,6 @@ get_ssl_info(F, Sock) -> end end. -get_ssl_issuer(#'OTPCertificate' { - tbsCertificate = #'OTPTBSCertificate' { - issuer = Issuer }}) -> - format_ssl_subject(extract_ssl_values(Issuer)). - -get_ssl_subject(#'OTPCertificate' { - tbsCertificate = #'OTPTBSCertificate' { - subject = Subject }}) -> - format_ssl_subject(extract_ssl_values(Subject)). - -get_ssl_validity(#'OTPCertificate' { - tbsCertificate = #'OTPTBSCertificate' { - validity = Validity }}) -> - case extract_ssl_values(Validity) of - {'validity', Start, End} -> io_lib:format("~s to ~s", [Start, End]); - V -> V - end. - - -extract_ssl_values({rdnSequence, List}) -> - extract_ssl_values_list(List); -extract_ssl_values({'Validity', Start, End}) -> - {'validity', format_ssl_value(Start), format_ssl_value(End)}; -extract_ssl_values(V) -> - V. - -extract_ssl_values_list([[#'AttributeTypeAndValue'{type = T, value = V}] - | Rest]) -> - [format_ssl_type_and_value(T, V) | extract_ssl_values_list(Rest)]; -extract_ssl_values_list([V|Rest]) -> - [io_lib:format("~p", V) | extract_ssl_values_list(Rest)]; -extract_ssl_values_list([]) -> - []. - -format_ssl_subject([C]) -> - [escape_ssl_string(C, start)]; -format_ssl_subject([C|Cs]) -> - [escape_ssl_string(C, start), "," | format_ssl_subject(Cs)]; -format_ssl_subject([]) -> - []. - -escape_ssl_string([], _) -> - []; -escape_ssl_string([$ | S], start) -> - ["\\ " | escape_ssl_string(S, start)]; -escape_ssl_string([$# | S], start) -> - ["\\#" | escape_ssl_string(S, start)]; -escape_ssl_string(S, start) -> - escape_ssl_string(S, middle); -escape_ssl_string([$ | S], middle) -> - case lists:filter(fun(C) -> C =/= $ end, S) of - [] -> escape_ssl_string([$ | S], ending); - [_|_] -> [" " | escape_ssl_string(S, middle)] - end; -escape_ssl_string([C | S], middle) -> - case lists:member(C, ",+\"\\<>;") of - false -> [C | escape_ssl_string(S, middle)]; - true -> ["\\", C | escape_ssl_string(S, middle)] - end; -escape_ssl_string([$ | S], ending) -> - ["\\ " | escape_ssl_string(S, ending)]. - -%% A few common attribute type names, as described by RFC 2253 (2.3) -format_ssl_type_and_value(Type, Value) -> - FV = format_ssl_value(Value), - Fmts = [{?'id-at-commonName' , "CN"}, - {?'id-at-countryName' , "C"}, - {?'id-at-organizationName' , "O"}, - {?'id-at-organizationalUnitName' , "OU"}, - {?'street-address' , "STREET"}, - {?'id-domainComponent' , "DC"}, - {?'id-at-stateOrProvinceName' , "ST"}, - {?'id-at-localityName' , "L"}], - case proplists:lookup(Type, Fmts) of - {_, Fmt} -> - io_lib:format(Fmt ++ "=~s", [FV]); - none when is_tuple(Type) -> - TypeL = [io_lib:format("~w", [X]) || X <- tuple_to_list(Type)], - io_lib:format("~s:~s", [rabbit_misc:intersperse(".", TypeL), FV]); - none -> - io_lib:format("~p:~s", [Type, FV]) - end. - -format_ssl_value({printableString, S}) -> - S; -format_ssl_value({utf8String, Bin}) -> - Bin; -format_ssl_value({utcTime, [Y1, Y2, M1, M2, D1, D2, H1, H2, - Min1, Min2, S1, S2, $Z]}) -> - io_lib:format("20~c~c-~c~c-~c~c ~c~c:~c~c:~c~c", - [Y1, Y2, M1, M2, D1, D2, H1, H2, Min1, Min2, S1, S2]); -format_ssl_value(V) -> - V. %%-------------------------------------------------------------------------- diff --git a/src/rabbit_ssl.erl b/src/rabbit_ssl.erl new file mode 100644 index 0000000000..86c8e21e02 --- /dev/null +++ b/src/rabbit_ssl.erl @@ -0,0 +1,164 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License at +%% http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +%% License for the specific language governing rights and limitations +%% under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developers of the Original Code are LShift Ltd, +%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd. +%% +%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd, +%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd +%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial +%% Technologies LLC, and Rabbit Technologies Ltd. +%% +%% Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift +%% Ltd. Portions created by Cohesive Financial Technologies LLC are +%% Copyright (C) 2007-2010 Cohesive Financial Technologies +%% LLC. Portions created by Rabbit Technologies Ltd are Copyright +%% (C) 2007-2010 Rabbit Technologies Ltd. +%% +%% All Rights Reserved. +%% +%% Contributor(s): ______________________________________. +%% + +-module(rabbit_ssl). + +-include_lib("public_key/include/public_key.hrl"). + +-export([ssl_issuer/1, ssl_subject/1, ssl_validity/1]). + + +%%-------------------------------------------------------------------------- + +-ifdef(use_specs). + +-spec(ssl_issuer/1 :: (#'OTPCertificate'{}) -> string()). +-spec(ssl_subject/1 :: (#'OTPCertificate'{}) -> string()). +-spec(ssl_validity/1 :: (#'OTPCertificate'{}) -> string()). + +-endif. %% use_specs + + +%%-------------------------------------------------------------------------- +%% High-level functions used by reader +%%-------------------------------------------------------------------------- + +%% Return a string describing the certificate's issuer. +ssl_issuer(#'OTPCertificate' { + tbsCertificate = #'OTPTBSCertificate' { + issuer = Issuer }}) -> + format_ssl_subject(extract_ssl_values(Issuer)). + +%% Return a string describing the certificate's subject, as per RFC2253. +ssl_subject(#'OTPCertificate' { + tbsCertificate = #'OTPTBSCertificate' { + subject = Subject }}) -> + format_ssl_subject(extract_ssl_values(Subject)). + +%% Return a string describing the certificate's validity. +ssl_validity(#'OTPCertificate' { + tbsCertificate = #'OTPTBSCertificate' { + validity = Validity }}) -> + case extract_ssl_values(Validity) of + {'Validity', Start, End} -> + io_lib:format("~s to ~s", [format_ssl_value(Start), + format_ssl_value(End)]); + V -> + io_lib:format("~p", [V]) + end. + + +%%-------------------------------------------------------------------------- +%% Functions for extracting information from OTPCertificates +%%-------------------------------------------------------------------------- + +%% Convert OTPCertificate fields to something easier to use. +extract_ssl_values({rdnSequence, List}) -> + extract_ssl_values_list(List); +extract_ssl_values(V) -> + V. + +%% Convert an rdnSequeuence list to a proplist. +extract_ssl_values_list([[#'AttributeTypeAndValue'{type = T, value = V}] + | Rest]) -> + [{T, V} | extract_ssl_values_list(Rest)]; +extract_ssl_values_list([V|Rest]) -> + rabbit_log:info("Found unexpected element ~p in an rdnSequence~n", [V]), + extract_ssl_values_list(Rest); +extract_ssl_values_list([]) -> + []. + + +%%-------------------------------------------------------------------------- +%% Formatting functions +%%-------------------------------------------------------------------------- + +%% Convert a proplist to a RFC2253 subject string. +format_ssl_subject(RDNs) -> + rabbit_misc:intersperse( + ",", [escape_ssl_string(format_ssl_type_and_value(T, V), start) + || {T, V} <- RDNs]). + +%% Escape a string as per RFC2253. +escape_ssl_string([], _) -> + []; +escape_ssl_string([$ | S], start) -> + ["\\ " | escape_ssl_string(S, start)]; +escape_ssl_string([$# | S], start) -> + ["\\#" | escape_ssl_string(S, start)]; +escape_ssl_string(S, start) -> + escape_ssl_string(S, middle); +escape_ssl_string([$ | S], middle) -> + case lists:filter(fun(C) -> C =/= $ end, S) of + [] -> escape_ssl_string([$ | S], ending); + [_|_] -> [" " | escape_ssl_string(S, middle)] + end; +escape_ssl_string([C | S], middle) -> + case lists:member(C, ",+\"\\<>;") of + false -> [C | escape_ssl_string(S, middle)]; + true -> ["\\", C | escape_ssl_string(S, middle)] + end; +escape_ssl_string([$ | S], ending) -> + ["\\ " | escape_ssl_string(S, ending)]. + +%% Format a type-value pair as an RDN. If the type name is unknown, +%% use the dotted decimal representation. See RFC2253, section 2.3. +format_ssl_type_and_value(Type, Value) -> + FV = format_ssl_value(Value), + Fmts = [{?'id-at-commonName' , "CN"}, + {?'id-at-countryName' , "C"}, + {?'id-at-organizationName' , "O"}, + {?'id-at-organizationalUnitName' , "OU"}, + {?'street-address' , "STREET"}, + {?'id-domainComponent' , "DC"}, + {?'id-at-stateOrProvinceName' , "ST"}, + {?'id-at-localityName' , "L"}], + case proplists:lookup(Type, Fmts) of + {_, Fmt} -> + io_lib:format(Fmt ++ "=~s", [FV]); + none when is_tuple(Type) -> + TypeL = [io_lib:format("~w", [X]) || X <- tuple_to_list(Type)], + io_lib:format("~s:~s", [rabbit_misc:intersperse(".", TypeL), FV]); + none -> + io_lib:format("~p:~s", [Type, FV]) + end. + +%% Get the string representation of an OTPCertificate field. +format_ssl_value({printableString, S}) -> + S; +format_ssl_value({utf8String, Bin}) -> + binary:bin_to_list(Bin); +format_ssl_value({utcTime, [Y1, Y2, M1, M2, D1, D2, H1, H2, + Min1, Min2, S1, S2, $Z]}) -> + io_lib:format("20~c~c-~c~c-~c~c ~c~c:~c~c:~c~c", + [Y1, Y2, M1, M2, D1, D2, H1, H2, Min1, Min2, S1, S2]); +format_ssl_value(V) -> + io_lib:format("~p", [V]). |
