%% kerlberos %% %% Copyright 2021 Alex Wilson %% The University of Queensland %% All rights reserved. %% %% Redistribution and use in source and binary forms, with or without %% modification, are permitted provided that the following conditions %% are met: %% 1. Redistributions of source code must retain the above copyright %% notice, this list of conditions and the following disclaimer. %% 2. Redistributions in binary form must reproduce the above copyright %% notice, this list of conditions and the following disclaimer in the %% documentation and/or other materials provided with the distribution. %% %% THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR %% IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES %% OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. %% IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, %% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT %% NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, %% DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY %% THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT %% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF %% THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. %% %% @private -module(gss_bindings). -export([ encode_rfc2744/1, decode_rfc2744/1, encode/1 ]). -type gss_af() :: unspec | local | inet | x25 | inet6 | null. -spec gss_af_i2a(integer()) -> gss_af(). gss_af_i2a(0) -> unspec; gss_af_i2a(1) -> local; gss_af_i2a(2) -> inet; gss_af_i2a(21) -> x25; gss_af_i2a(24) -> inet6; gss_af_i2a(255) -> null; gss_af_i2a(Other) -> error({bad_address_family, Other}). -spec gss_af_a2i(gss_af()) -> integer(). gss_af_a2i(unspec) -> 0; gss_af_a2i(local) -> 1; gss_af_a2i(inet) -> 2; gss_af_a2i(x25) -> 21; gss_af_a2i(inet6) -> 24; gss_af_a2i(null) -> 255; gss_af_a2i(Other) -> error({bad_address_family, Other}). -type gss_address() :: {inet, inet:ip_address()} | {inet6, inet:ip_address()} | {local, string()} | {unspec, binary()} | {x25, binary()} | null. -spec decode_gss_addr(gss_af(), binary()) -> gss_address(). decode_gss_addr(unspec, Data) -> {unspec, Data}; decode_gss_addr(local, Data) -> {local, unicode:characters_to_list(Data, utf8)}; decode_gss_addr(x25, Data) -> {x25, Data}; decode_gss_addr(inet, <>) -> {inet, {A, B, C, D}}; decode_gss_addr(inet6, <>) -> {inet6, {A, B, C, D, E, F, G, H}}. -spec encode_gss_addr(gss_address()) -> binary(). encode_gss_addr({unspec, Data}) -> Data; encode_gss_addr({local, String}) -> unicode:characters_to_binary(String, utf8); encode_gss_addr({x25, Data}) -> Data; encode_gss_addr({inet, {A, B, C, D}}) -> <>; encode_gss_addr({inet, {A, B, C, D, E, F, G, H}}) -> <>. -type rfc2744() :: {rfc2744, Initiator :: gss_address(), Acceptor :: gss_address(), AppData :: binary()}. -spec encode_rfc2744(rfc2744()) -> binary(). encode_rfc2744({rfc2744, Initiator = {InitiatorAF, _}, Acceptor = {AcceptorAF, _}, AppData}) -> InitiatorData = encode_gss_addr(Initiator), AcceptorData = encode_gss_addr(Acceptor), <<(gss_af_a2i(InitiatorAF)):32/little, (byte_size(InitiatorData)):32/little, InitiatorData/binary, (gss_af_a2i(AcceptorAF)):32/little, (byte_size(AcceptorData)):32/little, AcceptorData/binary, (byte_size(AppData)):32/little, AppData/binary>>. -spec decode_rfc2744(binary()) -> rfc2744(). decode_rfc2744(<>) -> Initiator = decode_gss_addr(gss_af_i2a(InitiatorAF), InitiatorData), Acceptor = decode_gss_addr(gss_af_i2a(AcceptorAF), AcceptorData), {rfc2744, Initiator, Acceptor, AppData}. encode(B = {rfc2744, _I, _A, _AppData}) -> encode_rfc2744(B); encode(B) when is_binary(B) -> B; encode(Other) -> error({unsupported_binding, Other}).